/* ============================================
   FONTS
   Self-hosted latin-subset woff2. Licensed OFL — see fonts/OFL-*.txt
   ============================================ */
@font-face {
  font-family: 'Barlow Semi Condensed';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/BarlowSemiCondensed-SemiBold.woff2') format('woff2');
}

@font-face {
  font-family: 'Barlow Semi Condensed';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/BarlowSemiCondensed-Bold.woff2') format('woff2');
}

/* One variable file covers 400/500/600 */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('fonts/Inter-Variable.woff2') format('woff2');
}

/* ============================================
   BRAND TOKENS
   ============================================ */
:root {
  /* Foundation — type, nav, dark bands */
  --color-graphite: #3A4754;
  --color-graphite-90: #2F3B47;

  /* Background */
  --color-surface-alt: #F4F6F8;
  --color-white: #FFFFFF;

  /* Action — CTAs, links, accents on light surfaces */
  --color-cobalt: #0046C8;
  --color-cobalt-hover: #003BAB;
  --color-cobalt-light: #93BAF4;           /* cobalt accents on dark surfaces only */

  /* Supporting */
  --color-muted: #626D79;                  /* At its contrast floor on the tinted cards — do not
                                              lighten. Hardcoded again in both schematic SVGs;
                                              change all three together. */
  --color-border: #DDE3E8;
  --color-text-on-dark: #FFFFFF;
  --color-text-on-dark-muted: #B9C3CC;

  /* Typography */
  --font-display: 'Barlow Semi Condensed', sans-serif;
  --font-body: 'Inter', sans-serif;

  --text-hero: clamp(2.25rem, 5vw + 1rem, 4rem);
  --text-h2: clamp(1.75rem, 3vw + 0.5rem, 2.75rem);
  --text-h3: clamp(1.4rem, 2.5vw + 0.5rem, 1.75rem);
  --text-body: 1rem;
  --text-body-lg: 1.125rem;
  --text-small: 0.875rem;
  --text-xs: 0.75rem;

  --leading-tight: 1.15;
  --leading-snug: 1.3;
  --leading-normal: 1.6;

  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;

  /* Spacing */
  --space-xs: 0.25rem;
  --space-sm: 0.5rem;
  --space-md: 1rem;
  --space-lg: 1.5rem;
  --space-xl: 2rem;
  --space-2xl: 3rem;
  --space-3xl: 4rem;
  --space-section: clamp(4rem, 8vw, 8rem);

  /* Shadows */
  --shadow-sm: 0 1px 2px rgba(23, 32, 41, 0.08);
  --shadow-md: 0 4px 12px rgba(23, 32, 41, 0.08);
  --shadow-lg: 0 8px 24px rgba(23, 32, 41, 0.12);

  /* Max Widths */
  --max-width-content: 1200px;
  --max-width-narrow: 800px;

  /* The fixed header's height. Anything that has to clear the header derives from this —
     hero and page-intro padding, and the scroll-padding that anchor jumps and keyboard
     focus land on. Overridden once in the tablet block. */
  --header-height: 64px;
}

/* ============================================
   RESET & BASE
   ============================================ */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

body {
  font-family: var(--font-body);
  font-size: var(--text-body);
  font-weight: var(--weight-regular);
  line-height: var(--leading-normal);
  color: var(--color-graphite);
  background-color: var(--color-surface-alt);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Two independent owners, one lock. The modal cannot reuse .menu-open: opening it from the
   mobile menu runs closeMenu(), which would strip the class and unlock the page underneath a
   modal that is still open. Separate classes let either one hold the lock on its own. */
body.menu-open,
body.modal-open {
  overflow: hidden;
}

img {
  max-width: 100%;
  height: auto;
  display: block;
}

/* Links are undecorated by default and opt into an underline where one is wanted
   (.prose a, .footer-link:hover, .mobile-nav-link:hover). */
a {
  color: var(--color-graphite);
  text-decoration: none;
}

/* Nav lists (header and mobile menu). <ol> is untouched, so the privacy prose keeps its markers. */
ul {
  list-style: none;
}

button {
  font-family: inherit;
  cursor: pointer;
  border: none;
  background: none;
}

/* One offset for every scroll-into-view, on the scroller rather than per target: anchor
   jumps land flush under the fixed header, and tabbing to a control above the viewport
   scrolls it clear of the bar rather than behind it. Exactly the header height, not more:
   any surplus shows as a strip of the previous section above an anchor target. Keep
   scroll-margin-top off the sections — it ADDS to this and every jump lands double-offset.
   The bottom inset clears the sticky mobile CTA bar; the tablet block zeroes it. */
html {
  scroll-padding-top: var(--header-height);
  scroll-padding-bottom: 64px;
}

/* ============================================
   UTILITY
   ============================================ */
.container {
  max-width: var(--max-width-content);
  margin: 0 auto;
  padding-left: var(--space-lg);
  padding-right: var(--space-lg);
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

/* The inline SVG symbol sprite at the top of index.html. A class, not a style
   attribute, because the CSP in .htaccess allows stylesheet CSS only
   (style-src 'self') — an inline attribute would be ignored in production. */
.icon-sprite {
  display: none;
}

/* Skip link */
.skip-link {
  position: absolute;
  top: -100%;
  left: var(--space-md);
  background: var(--color-graphite);
  border: 1px solid rgba(255, 255, 255, 0.4);
  color: var(--color-white);
  padding: var(--space-sm) var(--space-md);
  font-size: var(--text-small);
  font-weight: var(--weight-medium);
  z-index: 10000;
  transition: top 0.2s;
}

.skip-link:focus {
  top: var(--space-sm);
}

/* ============================================
   FOCUS STATES
   ============================================ */
:focus-visible {
  outline: 2px solid var(--color-cobalt);
  outline-offset: 2px;
}

/* On dark graphite surfaces, cobalt-light carries the accent (design-system rule) */
.site-header :focus-visible,
.hero :focus-visible,
.contact :focus-visible,
.site-footer :focus-visible {
  outline-color: var(--color-cobalt-light);
}

/* ============================================
   BUTTONS
   ============================================ */
.btn {
  display: inline-block;
  font-weight: var(--weight-semibold);
  text-align: center;
  transition: background-color 0.2s ease;
}

.btn-primary {
  background-color: var(--color-cobalt);
  color: var(--color-white);
  font-size: var(--text-small);
  padding: var(--space-sm) var(--space-lg);
}

.btn-primary:hover {
  background-color: var(--color-cobalt-hover);
}

/* Secondary tier for light surfaces (MH Series spec sheets). */
.btn-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  background-color: var(--color-graphite);
  color: var(--color-white);
  font-size: var(--text-small);
  /* Taller than base .btn-primary, which lands under the 44px touch-target minimum. */
  padding: var(--space-md) var(--space-lg);
  border: 1px solid var(--color-graphite);
  box-shadow: var(--shadow-sm);
  transition: background-color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}

.btn-secondary:hover {
  background-color: var(--color-cobalt);
  border-color: var(--color-cobalt);
  box-shadow: var(--shadow-md);
}

.btn-secondary .btn-icon {
  flex-shrink: 0;
}

/* ============================================
   HEADER
   ============================================ */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: var(--header-height);
  background-color: var(--color-graphite);
  z-index: 1000;
  transition: box-shadow 0.2s ease;
}

.site-header.scrolled {
  box-shadow: var(--shadow-sm);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 100%;
}

.header-logo img {
  height: 28px;
  width: auto;
}

.main-nav {
  display: none;
}

.nav-list {
  display: flex;
  gap: var(--space-xl);
}

.nav-link {
  font-size: var(--text-small);
  font-weight: var(--weight-medium);
  color: rgba(255, 255, 255, 0.8);
  padding: var(--space-xs) 0;
  position: relative;
  transition: color 0.2s ease;
}

/* A drawn bar rather than a text underline: hover and active share one mark, and it
   scales from the element's own box so nothing reflows. main.js sets .active. */
.nav-link::after {
  content: '';
  position: absolute;
  bottom: -2px;
  left: 0;
  right: 0;
  height: 2px;
  background-color: var(--color-cobalt-light);
  transform: scaleX(0);
  transition: transform 0.2s ease;
}

.nav-link:hover,
.nav-link.active {
  color: var(--color-white);
}

.nav-link:hover::after,
.nav-link.active::after {
  transform: scaleX(1);
}

.header-cta {
  display: none;
}

/* Hamburger */
.hamburger {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  padding: 10px;
}

.hamburger-line {
  display: block;
  width: 24px;
  height: 2px;
  background-color: var(--color-white);
  border-radius: 1px;
}

/* Forced colors (Windows High Contrast) strips author backgrounds, and these are the two
   meaning-carrying marks drawn with one: without this block the hamburger renders as a
   blank button and the active-section bar never shows. System colours are exempt from the
   strip — they resolve to the user's own palette — so each mark takes the ink of the role
   it belongs to: ButtonText for the icon, LinkText for the link marker. */
@media (forced-colors: active) {
  .hamburger-line {
    background-color: ButtonText;
  }

  .nav-link::after {
    background-color: LinkText;
  }
}

/* Mobile menu. Flex with auto margins on the inner block, not align-items:center: a centred
   flex child overflows symmetrically, which puts the top of a too-tall menu above the scroll
   origin where no amount of scrolling can reach it (landscape phones, 200% zoom). margin:auto
   centres while it fits and degrades to a top-aligned scroll when it does not. */
.mobile-menu {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: var(--color-white);
  z-index: 2000;
  display: flex;
  overflow-y: auto;
  opacity: 0;
  visibility: hidden;
  /* Opacity does the fading; visibility only gates rendering. On close, the 0.3s delay
     holds the menu visible until the fade finishes. On open, the .open rule drops the
     delay so the flip is immediate: openMenu() focuses the close button in the same tick,
     and an element that is still visibility:hidden at that instant — which a transitioned
     visibility computes at t=0 — turns that focus() into a silent no-op. */
  transition: opacity 0.3s ease, visibility 0s 0.3s;
}

.mobile-menu.open {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.3s ease, visibility 0s;
}

.mobile-menu-inner {
  text-align: center;
  width: 100%;
  padding: var(--space-xl);
  margin: auto; /* see .mobile-menu — centring that stays scrollable on overflow */
}

.mobile-menu-close {
  /* fixed, not absolute: .mobile-menu scrolls, and an absolute child would ride the
     content out of view — the one exit stays pinned to the viewport corner. (opacity on
     .mobile-menu creates a stacking context, not a fixed-position containing block, so
     this genuinely anchors to the viewport.) */
  position: fixed;
  top: var(--space-md);
  right: var(--space-md);
  width: 44px;
  height: 44px;
  font-size: 2rem;
  color: var(--color-graphite);
  display: flex;
  align-items: center;
  justify-content: center;
}

.mobile-nav-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-xl);
  margin-bottom: var(--space-2xl);
}

.mobile-nav-link {
  font-size: var(--text-h3);
  font-weight: var(--weight-semibold);
  color: var(--color-graphite);
}

.mobile-nav-link:hover {
  text-decoration: underline;
}

.mobile-menu-cta {
  width: 100%;
  padding: var(--space-md) var(--space-xl);
  font-size: var(--text-body);
}

/* Mobile bottom CTA. main.js adds .visible once the hero CTA scrolls away; the tablet
   block switches it back off, because from 768px up the header carries its own CTA and
   two sticky "Request a conversation" controls would be on screen at once. */
.mobile-bottom-cta {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: var(--color-white);
  box-shadow: 0 -4px 12px rgba(23, 32, 41, 0.08);
  padding: var(--space-sm) var(--space-lg);
  z-index: 900;
  display: none;
  height: 64px;
  align-items: center;
}

.mobile-bottom-cta.visible {
  display: flex;
}

.mobile-bottom-cta-btn {
  width: 100%;
  padding: var(--space-sm) var(--space-md);
  font-size: var(--text-body);
}

/* ============================================
   HERO
   ============================================ */
.hero {
  position: relative;
  overflow: hidden;
  background-color: var(--color-graphite);
  padding-top: calc(var(--header-height) + var(--space-2xl) + var(--space-xl));
  padding-bottom: var(--space-section);
}

/* Full-bleed hydrogen-release artwork. Authored at 1440x720 with its mass in
   the lower right, so it is anchored there and cropped from the left. */
.hero-visual {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: right bottom;
  opacity: 0.6;
  pointer-events: none;
  user-select: none;
}

/* Scrim holding type contrast over the lattice. Runs top-down on mobile where
   the copy is stacked over the whole band, left-right on desktop where it is
   confined to the left column. The stops are tuned against the brightest marks
   in the artwork — brightening the art or thinning either scrim means
   re-measuring the text contrast. */
.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    rgba(58, 71, 84, 0.95) 0%,
    rgba(58, 71, 84, 0.78) 40%,
    rgba(58, 71, 84, 0.25) 100%
  );
}

.hero-inner {
  position: relative;
  z-index: 1;
}

.hero-headline {
  font-family: var(--font-display);
  font-size: var(--text-hero);
  font-weight: var(--weight-bold);
  line-height: 1.05;
  color: var(--color-text-on-dark);
  margin-bottom: var(--space-xl);
}

.hero-subhead {
  font-family: var(--font-body);
  font-size: var(--text-body-lg);
  font-weight: var(--weight-regular);
  color: var(--color-text-on-dark-muted);
  max-width: 600px;
  margin-bottom: var(--space-xl);
}

.hero-cta {
  font-size: var(--text-body);
  padding: var(--space-md) var(--space-xl);
  margin-bottom: var(--space-md);
}

/* ============================================
   SOLUTIONS
   ============================================ */
.solutions {
  background-color: var(--color-white);
  padding: var(--space-section) 0;
}

.section-eyebrow {
  font-family: var(--font-body);
  font-size: var(--text-small);
  font-weight: var(--weight-semibold);
  color: var(--color-cobalt);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  margin-bottom: var(--space-sm);
}

.section-heading {
  font-family: var(--font-display);
  font-size: var(--text-h2);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  color: var(--color-graphite);
  margin-bottom: var(--space-xl);
}

/* Six cards, so 1 / 2 / 3 columns by breakpoint. Grid rather than flex: row heights
   equalise across the whole grid, which flex only manages per line. */
.solutions-grid {
  display: grid;
  gap: var(--space-lg);
}

.solution-card {
  background-color: var(--color-surface-alt);
  border-top: 3px solid var(--color-graphite);
  padding: var(--space-xl);
}

.solution-icon {
  margin-bottom: var(--space-md);
  color: var(--color-graphite);
}

.solution-title {
  font-family: var(--font-display);
  font-size: var(--text-h3);
  font-weight: var(--weight-bold);
  line-height: var(--leading-snug);
  color: var(--color-graphite);
  margin-bottom: var(--space-md);
}

.solution-problem {
  font-size: var(--text-body);
  font-weight: var(--weight-regular);
  color: var(--color-muted);
  line-height: var(--leading-normal);
}

/* ============================================
   TECHNOLOGY
   ============================================ */
/* Tinted band so the white Solutions and Specs sections do not run together as one
   unbroken stretch. Safe for the schematics because both are transparent and carry no
   white or near-white marks — recheck that if either SVG is redrawn. */
.technology {
  background-color: var(--color-surface-alt);
  padding: var(--space-section) 0;
}

.technology-text {
  font-size: var(--text-body-lg);
  font-weight: var(--weight-regular);
  color: var(--color-graphite);
  line-height: var(--leading-normal);
  margin-bottom: var(--space-md);
}

/* Both schematic files carry empty artboard above and below the drawing. Left alone that stacks on top of the section's padding and
   Technology reads as if it had half again as much bottom padding as Solutions or Specs.
   --artboard-pad is that dead space at the size each variant actually renders, and
   the negative margins below pull the wrapper in to hug the drawing itself. Nothing is
   clipped: the empty artboard simply overlaps padding that was blank anyway. flow-root stops
   those negative margins collapsing out of the wrapper, which would move the section instead
   of the image. Re-measure if either SVG is re-exported. */
.process-diagram {
  --artboard-pad: 15px;
  display: flow-root;
  margin-top: var(--space-xl);
  /* Full-bleed on small phones, which buys the labels a couple of points of size. The
     SVG carries ~80 units of internal left margin inside its 400-unit viewBox, so going
     edge-to-edge still reads as inset. Past ~448px the 400px cap takes over and centres it. */
  margin-left: calc(-1 * var(--space-lg));
  margin-right: calc(-1 * var(--space-lg));
}

.process-diagram-svg {
  width: 100%;
  height: auto;
  display: block;
  margin-block: calc(-1 * var(--artboard-pad));
}

/* Holds the vertical schematic at its authored 400px — without this it
   stretches to a 2000px-tall column on tablets. */
.process-diagram-svg--vertical {
  max-width: 400px;
  margin-inline: auto; /* not `margin: 0 auto` — that would reset the block margins above */
}

/* A percentage, not px, because the wide file renders at anything from 960 to 1136px once
   the container stops being maxed out. Vertical margin percentages resolve against the
   containing block's WIDTH, and this image is width:100% of that block, so 40 dead units in
   a 1300-unit artboard is exactly 40/1300 at every size. The vertical variant keeps a px
   value: it is capped at 400px, so its width and its container's part company. */
.process-diagram-svg--wide {
  --artboard-pad: 3.077%;
  display: none;
}

/* ============================================
   SPECS
   ============================================ */
.specs {
  background-color: var(--color-white);
  padding: var(--space-section) 0;
}

.specs-framing {
  font-family: var(--font-body);
  font-size: var(--text-body-lg);
  font-weight: var(--weight-regular);
  color: var(--color-graphite);
  line-height: var(--leading-normal);
}

/* Stacked until 1024px — see the two-column rules in the desktop block. */
.specs-intro {
  margin-bottom: var(--space-xl);
}

/* Knocked-out shot on white — no plate or frame, the unit floats. The cap is 364 rather
   than 300 because the unit sits inset inside a square canvas and fills only part of it;
   364 lands the unit itself near its intended 300px. Re-derive the cap if the file is
   ever re-exported at a different inset. */
.product-photo {
  width: 100%;
  max-width: 364px;
  margin: var(--space-xl) auto 0;
}

/* Spec sheet downloads: stacked full-width on mobile so the labels never truncate,
   inline from 768px up. */
.spec-downloads {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

/* ============================================
   CONTACT
   ============================================ */
.contact {
  background-color: var(--color-graphite);
  padding: var(--space-section) 0;
}

.contact-headline {
  font-family: var(--font-display);
  font-size: var(--text-h2);
  font-weight: var(--weight-bold);
  color: var(--color-white);
  text-align: center;
  line-height: var(--leading-tight);
  margin-bottom: var(--space-md);
  max-width: 640px;
  margin-left: auto;
  margin-right: auto;
}

.contact-subhead {
  font-family: var(--font-body);
  font-size: var(--text-body-lg);
  font-weight: var(--weight-regular);
  color: var(--color-text-on-dark-muted);
  text-align: center;
  max-width: 640px;
  margin-left: auto;
  margin-right: auto;
}

/* Sized like .hero-cta rather than base .btn-primary, which lands under the 44px touch
   minimum. block + fit-content because .container is not a centring context — the headline
   and subhead above centre themselves with text-align. */
.contact-cta {
  display: block;
  width: fit-content;
  margin: var(--space-xl) auto 0;
  font-size: var(--text-body);
  padding: var(--space-md) var(--space-xl);
}

/* ============================================
   CONTACT FORM MODAL
   ============================================ */
/* Microsoft Forms in a <dialog>. showModal() is load-bearing: the panel's only content is a
   cross-origin frame we cannot script a focus trap around, so the top layer's inerting of the
   rest of the page does that job. Cross-origin caveats live in main.js. */
.form-modal {
  /* UA resets. The default dialog is a 2px groove box with 1em of padding and a
     calc(100% - 6px - 2em) size cap, all three of which fight a full-bleed panel. */
  margin: 0;
  padding: 0;
  border: 0;
  max-width: none;
  max-height: none;

  inset: 0;
  width: 100%;
  /* dvh because a 100vh panel on iOS Safari is taller than the visible area while the URL bar
     is showing, which pushes the bottom of the form — including Microsoft's Submit button —
     under browser chrome. The vh line is the fallback for engines that do not parse dvh. */
  height: 100vh;
  height: 100dvh;

  background-color: var(--color-white);
  color: var(--color-graphite);
  overflow: hidden; /* the frame scrolls; the panel never does — one scroll context was the point */
}

/* dialog is display:none until opened, so any display value must be scoped to [open] or the panel
   would be permanently visible. */
.form-modal[open] {
  display: flex;
  flex-direction: column;
}

/* This is the shadow ink (23, 32, 41) at modal strength, written
   literally on purpose — do not "tidy" it into a var(). */
.form-modal::backdrop {
  background-color: rgba(23, 32, 41, 0.6);
}

/* A white strip above the frame instead of an × floated over it: Microsoft paints a navy title
   band across the top of the response page and a graphite glyph on navy is close to invisible.
   The strip also guarantees one always-visible exit, which matters because Escape dies the moment
   focus enters the frame. */
.form-modal-bar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 52px;
  /* Asymmetric on purpose: the 44px close button is mostly transparent padding around a small
     glyph, so matching the left inset numerically would leave the × looking further from the
     edge than the logo. */
  padding-left: var(--space-md);
  padding-right: var(--space-xs);
  background-color: var(--color-white);
  border-bottom: 1px solid var(--color-border);
}

/* Same 24px as .footer-brand img — the compact lockup. Explicit height with width:auto because
   the base img reset sets height:auto, which would otherwise let the intrinsic 70px through. */
.form-modal-logo {
  height: 24px;
  width: auto;
}

/* Glyph, 44px target and optical size lifted from .mobile-menu-close; laid out in flow rather
   than absolutely positioned. */
.form-modal-close {
  width: 44px;
  height: 44px;
  font-size: 2rem;
  line-height: 1;
  color: var(--color-graphite);
  display: flex;
  align-items: center;
  justify-content: center;
}

.form-modal-frame {
  display: block;
  flex: 1;
  width: 100%;
  min-height: 0; /* flex items are min-height:auto by default; without this the frame refuses to
                    shrink past its intrinsic 150px and overflows short viewports */
  border: 0;
}

@keyframes form-modal-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.form-modal[open],
.form-modal[open]::backdrop {
  animation: form-modal-in 0.2s ease;
}

/* Feature-scoped on purpose: motion overrides live with the feature they modify, not in the
   width-breakpoint blocks at the bottom. */
@media (prefers-reduced-motion: reduce) {
  .form-modal[open],
  .form-modal[open]::backdrop {
    animation: none;
  }
}

/* ============================================
   FOOTER
   ============================================ */
.site-footer {
  background-color: var(--color-graphite);
  border-top: 1px solid var(--color-graphite-90);
  padding: var(--space-2xl) 0;
}

.footer-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
  text-align: center;
}

.footer-brand img {
  height: 24px;
  width: auto;
}

.footer-company {
  font-size: var(--text-small);
  font-weight: var(--weight-medium);
  color: var(--color-text-on-dark-muted);
}

.footer-address {
  font-size: var(--text-small);
  font-weight: var(--weight-regular);
  color: var(--color-text-on-dark-muted);
}

.footer-links {
  display: flex;
  gap: var(--space-lg);
}

.footer-link {
  font-size: var(--text-small);
  font-weight: var(--weight-regular);
  color: var(--color-text-on-dark-muted);
}

.footer-link:hover {
  color: var(--color-white);
  text-decoration: underline;
}

.footer-copyright {
  font-size: var(--text-xs);
  font-weight: var(--weight-regular);
  color: var(--color-text-on-dark-muted);
}

/* ============================================
   STATIC PAGE (Privacy, Terms, etc.)
   ============================================ */
.page-intro {
  background-color: var(--color-white);
  padding-top: calc(var(--header-height) + var(--space-2xl) + var(--space-xl));
  padding-bottom: var(--space-2xl);
  border-bottom: 1px solid var(--color-border);
}

.page-headline {
  font-family: var(--font-display);
  font-size: var(--text-h2);
  font-weight: var(--weight-bold);
  line-height: var(--leading-tight);
  color: var(--color-graphite);
  margin-bottom: var(--space-sm);
}

.page-updated {
  font-family: var(--font-body);
  font-size: var(--text-small);
  font-weight: var(--weight-regular);
  color: var(--color-muted);
}

.page-body {
  background-color: var(--color-white);
  padding-top: var(--space-2xl);
  padding-bottom: var(--space-section);
}

.prose {
  max-width: var(--max-width-narrow);
  color: var(--color-graphite);
  font-family: var(--font-body);
  font-size: var(--text-body);
  line-height: var(--leading-normal);
}

.prose h2 {
  font-family: var(--font-display);
  font-size: var(--text-h3);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  color: var(--color-graphite);
  margin-top: var(--space-2xl);
  margin-bottom: var(--space-md);
}

.prose p,
.prose ol {
  margin-bottom: var(--space-md);
}

.prose ol {
  padding-left: var(--space-xl);
}

.prose li {
  margin-bottom: var(--space-xs);
}

.prose a {
  text-decoration: underline;
}

.prose a:hover {
  color: var(--color-cobalt);
}

/* ============================================
   TABLET (768px)
   ============================================ */
@media (min-width: 768px) {
  /* Taller header here. Everything derived from it — .site-header, the hero and page-intro
     padding, and the scroll-padding — follows from this one line. */
  :root {
    --header-height: 72px;
  }

  /* No sticky bottom CTA bar from 768px up, so no bottom inset to reserve. */
  html {
    scroll-padding-bottom: 0;
  }

  .container {
    padding-left: var(--space-xl);
    padding-right: var(--space-xl);
  }

  /* Header: show nav + CTA, hide hamburger */
  .header-logo img {
    height: 32px;
  }

  .main-nav {
    display: block;
  }

  .header-cta {
    display: inline-block;
  }

  .hamburger {
    display: none;
  }

  /* The header CTA above now covers this job — see the base rule. */
  .mobile-bottom-cta.visible {
    display: none;
  }

  .process-diagram {
    margin-left: 0;
    margin-right: 0;
  }

  .solutions-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  /* Spec sheet buttons sit inline once there is room for all three */
  .spec-downloads {
    flex-direction: row;
    flex-wrap: wrap;
  }

  /* The panel stops being full-bleed and becomes a centred sheet. inset:0 comes from the base
     rule, so margin:auto with a fixed width and height centres it in the top layer. 560px keeps
     it a form column rather than a slab, and stops Microsoft's navy banner dominating.
     Narrowing is paid for inside the frame — Microsoft's layout is fluid, so the form grows
     taller and scrolls a little more within the fixed height. That scrollbar is the intended
     behaviour, not a symptom to design around. */
  .form-modal {
    width: 560px;
    height: 88vh;
    height: 88dvh;
    margin: auto;
    box-shadow: var(--shadow-lg);
  }
}

/* ============================================
   DESKTOP (1024px)
   ============================================ */
@media (min-width: 1024px) {
  .hero {
    padding-top: calc(var(--header-height) + var(--space-3xl) + var(--space-xl));
    min-height: 620px;
  }

  /* Copy moves into a left column, so the scrim turns horizontal and the artwork
     comes up to full strength on the open right side. The 0.88 stop holds to 58% —
     the full reach of .hero-text below — so the subhead stays readable even with a
     molecule drifting behind it; the falloff lives in the text-free right fifth. */
  .hero-visual {
    opacity: 1;
  }

  .hero::after {
    background: linear-gradient(
      to right,
      rgba(58, 71, 84, 0.96) 0%,
      rgba(58, 71, 84, 0.88) 58%,
      rgba(58, 71, 84, 0.30) 80%,
      rgba(58, 71, 84, 0.05) 100%
    );
  }

  .hero-text {
    max-width: 58%;
  }

  .solutions-grid {
    grid-template-columns: repeat(3, 1fr);
  }

  /* Two columns only from 1024px, not 768px: at 768 the copy column is narrow enough that
     the heading runs several lines beside a portrait photo. The photo takes the smaller
     share; 0.7fr rather than 0.65 so the column still clears the 364px cap once the
     container maxes out, instead of shrinking the unit below its design size. */
  .specs-intro {
    display: grid;
    grid-template-columns: minmax(0, 1.3fr) minmax(0, 0.7fr);
    gap: var(--space-2xl);
    align-items: center;
  }

  /* Holds the copy to a readable measure instead of letting it run the full column width.
     Only bites above ~1200px; at 1024 the column is already narrower than the cap. */
  .specs-copy {
    max-width: 640px;
  }

  .product-photo {
    margin: 0 auto;
  }

  /* The schematic swaps to the wide drawing here. The crossover is legibility, not width:
     below this the wide artboard scales down far enough that its labels render smaller than
     the vertical variant's flat 11px, so the vertical one is genuinely the more readable of
     the two. Moving this breakpoint means re-checking the type sizes inside both SVGs. */
  .process-diagram-svg--vertical {
    display: none;
  }

  .process-diagram-svg--wide {
    display: block;
  }
}

/* No 1440px block on purpose: .container already caps at --max-width-content, so a wider
   breakpoint has nothing left to do. Restating a max-width up here only risks narrowing
   the hero at exactly the sizes where it should be widest. */
