/* ============================================================
   PHAROS — restyle (Pharos Style Guide system)
   Dark, precise hardware product page. Inter only.
   Accent rust #8C4A2A used ONLY on the primary button fill
   and the small bar above each spec number. Nothing else.
   ============================================================ */

:root{
  --bg:#0A0A0A;
  --panel:#121212;               /* the one raised surface grey */
  --headline:#F2F2F2;
  --body:#CCCCCC;
  --label:#888888;
  --border:#333333;              /* decorative dividers and card edges */
  --border-strong:#636363;       /* anything whose border IS the control: inputs, outlined
                                    buttons. 3.30:1 on the page ground and 3.12:1 on the
                                    panel grey, so it clears WCAG 1.4.11 on both surfaces */
  --accent:#8C4A2A;              /* rust — button fill + spec bar only */
  --accent-up:#9A5330;           /* hover state of the same rust, not a second accent */
  --accent-down:#7A4023;         /* pressed state */
  --danger:#C0564A;
  --btn-text-on-accent:#F2F2F2;
  --btn-text-on-plain:#0A0A0A;
  /* FLUID SCALING, 22 Jul 2026 (FLUID-SCALING-BRIEF.md). Nothing here is a fixed
     pixel width any more: the layout derives from the viewport and grows with it.

     Two widths, on purpose. --maxw is the SPINE and it carries text, so it is fluid
     but capped: past about 1720px a heading stops being scannable. --maxw-wide is
     the BAND and it carries boxed surfaces (card grids, framed media), which stay
     legible much wider, so it runs to 96vw with a far higher ceiling. That split is
     what closes the empty margin on a 2560 or 3440 screen without stretching a
     sentence across a metre of glass. */
  --maxw:min(92vw, 1720px);      /* the spine: heads, paragraphs, forms, unboxed surfaces */
  --maxw-wide:var(--maxw);       /* below 1280 the band IS the spine, so mobile never moves */
  --body-maxw:65ch;              /* the one true fixed rule: reading never scales past comfort */
  --gap-section:clamp(60px, 9vw, 160px);
  --gap-block:clamp(40px, 4.5vw, 72px);
  --side:clamp(20px, 3vw, 64px);
  --font:'Inter',system-ui,sans-serif;
  --ease:cubic-bezier(.22,1,.36,1);
  --ease-out:cubic-bezier(.16,1,.3,1); /* interaction curve */
  --t-fast:180ms;                /* hover, focus, tint */
  --t-med:240ms;                 /* larger surface moves */
}
/* The two :root breakpoint tiers that used to step --side and --gap-section are gone:
   the clamps above do it continuously, so the layout no longer jumps at 1040 and 720.
   The nav breakpoint survives further down, because the nav genuinely is a switch
   (links become a burger) rather than a scale. It was 1040 until 31 Jul 2026, when
   the two pillar links forced it to 1140; the reasoning is at that rule. */

*{ box-sizing:border-box; margin:0; padding:0 }
/* Base type scales with the viewport, and every font-size on the page is rem, so the
   whole composition grows on a big screen instead of sitting small in the middle.
   Floor is 16px, not the brief's 15px: 15 would shrink mobile text below both today's
   size and the browser default, a regression on the commonest device. */
html{ font-size:clamp(16px, 0.42vw + 12px, 19px); scroll-behavior:smooth }
html.lenis, html.lenis body{ height:auto }
.lenis.lenis-smooth{ scroll-behavior:auto !important }
body{
  background:var(--bg); color:var(--body);
  font:400 1rem/1.55 var(--font);
  /* kerning is never optional */
  font-kerning:normal; font-feature-settings:"kern" 1; text-rendering:optimizeLegibility;
  -webkit-font-smoothing:antialiased; overflow-x:hidden;
}
/* one letterspacing value for every all caps label on the site: 10%, inside the
   5 to 12% the eye needs on caps, and in em so it scales with the type */
:root{ --caps-track:.1em }
img,video{ max-width:100%; height:auto; display:block }
a{ color:inherit; text-decoration:none }
.wrap{ max-width:var(--maxw); margin:0 auto; padding:0 var(--side) }
/* Founder direction: fill the screen. Card grids and framed media opt into a wider
   band; section heads, paragraphs and every unboxed surface stay on the 1200px spine
   so the left edge never moves. The nav keeps the band too, but it is chrome, not
   content: it is a full-width bar that grows its own background and border on scroll.
   The band only opens above 1280px, where 96vw has cleared the spine, so every
   layout below that width is byte for byte what it was. */
@media (min-width:1280px){
  /* 96vw with a high ceiling. The old value was min(96vw,1560px), which on a 2560 or
     3440 screen capped out well before the glass ran out and left the void the brief
     is about. Boxed surfaces read fine this wide because density grows with them. */
  :root{ --maxw-wide:min(96vw, 3400px) }
}
/* One utility does the widening, applied to the surfaces the brief names rather
   than to .wrap, so no section markup has to be split and the head keeps the
   spine. The margin is measured off the two tokens, never off the viewport, so
   it cannot be thrown out by a scrollbar; below 1280 the two tokens are equal
   and the margin computes to exactly 0.

   THE RULE, and it is about boxes, not about content type:
   only a surface with its OWN VISIBLE EDGE may leave the spine. A bordered card
   grid or a framed video reads as a deliberate wider object. A surface with no
   border and no background has nothing to explain the different edge, so next to
   a heading on the spine it simply looks misaligned.

   In the band, every one of these has a visible edge:
     .svc, .founders   border + background
     .media            border
     .thermal-static   its figures are bordered
     .usecases         bordered, sized by --maxw-wide in its own rule
   NOT in the band, and why:
     .specs, .foot-cols   no border, no background. Widened once, and the spec
                          numbers ended up hanging 180px left of the H2 above them
                          and the paragraph below them. Unboxed follows the text.
     .appsplit, .paths, .who-head, #ctaForm, .trust-para   text bearing.
     .watcher-panel    its photograph is a 660px source already upscaled at 1080px. */
.svc, .founders, .media, .thermal-static{
  margin-left:calc((var(--maxw) - var(--maxw-wide)) / 2);
  margin-right:calc((var(--maxw) - var(--maxw-wide)) / 2);
}

/* transform, not top: never animate a layout property. Off black, never #000. */
.skip-link{ position:fixed; top:16px; left:16px; z-index:100; background:var(--headline); color:var(--bg);
  padding:10px 16px; transform:translateY(-200%); transition:transform var(--t-fast) var(--ease-out) }
.skip-link:focus{ transform:none }
:focus-visible{ outline:2px solid var(--headline); outline-offset:3px }
/* the nav is fixed, so anchored sections must clear it when jumped to */
[id]{ scroll-margin-top:96px }
/* kill the 300ms tap delay and the grey flash on touch */
a,button,summary,label,input,select,textarea{ touch-action:manipulation }
html{ -webkit-tap-highlight-color:transparent }
.fn-ref{ position:relative; color:var(--body); text-decoration:none; transition:color var(--t-fast) var(--ease-out) }
.fn-ref:hover{ color:var(--headline) }
/* the superscript glyph is only about 5px wide. The hit area is grown with a
   pseudo element rather than padding, so the target is comfortable without the
   footnote marker disturbing the line it sits in. */
.fn-ref::after{ content:""; position:absolute; inset:-11px -10px }
/* main only takes focus programmatically from the skip link; never ring it */
main:focus{ outline:none }
::selection{ background:var(--headline); color:var(--bg) }

/* ---------- type ---------- */
.eyebrow{ font-size:0.8125rem; letter-spacing:var(--caps-track); text-transform:uppercase; font-weight:500; color:var(--label); margin-bottom:24px }
/* headings: never hyphenated, balanced across lines, space above beats space below */
.h2,.h3,.hero-h1,.statement-line,.path-h,.markplate-word{ hyphens:none; text-wrap:balance }
.h2{ font-size:clamp(1.875rem,5vw,2.5rem); font-weight:700; line-height:1.15; letter-spacing:-.01em; color:var(--headline); max-width:20ch }
.h3{ font-size:clamp(1.25rem,2.4vw,1.625rem); font-weight:700; line-height:1.2; color:var(--headline) }
.lede{ font-size:clamp(1.0625rem,1.4vw,1.1875rem); font-weight:400; line-height:1.5; color:var(--body); max-width:var(--body-maxw); margin-top:24px; text-wrap:pretty }

/* ---------- sections ---------- */
.sec{ padding:var(--gap-section) 0; position:relative }
.sec--tight{ padding:calc(var(--gap-section) * .5) 0 }

/* ---------- dock lid loader (kept, part of hero) ---------- */
.lid{ position:fixed; inset:0; z-index:90; pointer-events:none }
.lid-panel{ position:absolute; left:0; right:0; height:50.5%; background:var(--bg) }
.lid-panel--top{ top:0; transform-origin:top }
.lid-panel--bottom{ bottom:0; transform-origin:bottom }
.lid-seam{ position:absolute; left:0; right:0; top:50%; height:2px; transform:translateY(-50%); background:var(--accent); opacity:0 }
.lid.is-done{ display:none }

/* ---------- nav ---------- */
.nav{
  position:fixed; top:0; left:0; right:0; z-index:50; height:80px;
  display:flex; align-items:center; justify-content:space-between;
  /* clear the notch in landscape without moving the bar on every other device, and
     hold the bar to the wide band instead of letting it run to the screen edge */
  padding-left:max(var(--side), (100% - var(--maxw-wide)) / 2, env(safe-area-inset-left));
  padding-right:max(var(--side), (100% - var(--maxw-wide)) / 2, env(safe-area-inset-right));
  border-bottom:1px solid transparent;
  transition:height var(--t-med) var(--ease-out), background var(--t-med) var(--ease-out), border-color var(--t-med) var(--ease-out), box-shadow var(--t-med) var(--ease-out);
}
.nav.is-scrolled{ height:64px; background:rgba(10,10,10,.9); backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px); border-color:var(--border); box-shadow:0 8px 32px rgba(0,0,0,.35) }
.nav-brand{ display:flex; align-items:center; gap:12px; color:var(--headline); transition:opacity var(--t-fast) var(--ease-out) }
.nav-brand:hover{ opacity:.85 }
.nav-mark{ width:24px; height:24px; color:var(--headline) }
.nav-word{ font-size:1.0625rem; font-weight:600; letter-spacing:-.02em; color:var(--headline) }
.nav-dot{ color:#F0A544 } /* Beacon — the lamp in the wordmark (pharos.) */
.nav-links{ display:flex; align-items:center; gap:32px; font-size:0.875rem; font-weight:500; color:var(--body) }
.nav-links a{ transition:color var(--t-fast) var(--ease-out) }
.nav-links a:hover{ color:var(--headline) }
.nav-cta{ border:1px solid var(--border-strong); padding:10px 20px; color:var(--headline); border-radius:2px; transition:border-color var(--t-fast) var(--ease-out), background var(--t-fast) var(--ease-out), transform var(--t-fast) var(--ease-out) }
.nav-cta:hover{ border-color:var(--label); background:rgba(255,255,255,.04) }
.nav-cta:active{ transform:translateY(1px) }
.nav-burger{ display:none; background:none; border:0; width:44px; height:44px; cursor:pointer; position:relative }
.nav-burger span{ position:absolute; left:8px; right:8px; height:1.5px; background:var(--headline); transition:transform 200ms var(--ease-out), opacity var(--t-fast) var(--ease-out) }
.nav-burger:hover span{ opacity:.75 }
.nav-burger span:nth-child(1){ top:17px } .nav-burger span:nth-child(2){ top:26px }
.nav-burger.is-open span:nth-child(1){ transform:translateY(4.5px) rotate(45deg) }
.nav-burger.is-open span:nth-child(2){ transform:translateY(-4.5px) rotate(-45deg) }
.mnav{ position:fixed; inset:0; z-index:45; overscroll-behavior:contain; background:rgba(10,10,10,.98); display:flex; flex-direction:column; justify-content:center; gap:24px; padding:0 var(--side);
  opacity:0; visibility:hidden; pointer-events:none;
  transition:opacity var(--t-med) var(--ease-out), visibility 0s var(--t-med) }
.mnav.is-open{ opacity:1; visibility:visible; pointer-events:auto; transition:opacity var(--t-med) var(--ease-out), visibility 0s }
.mnav.is-open a{ animation:menuIn 260ms var(--ease-out) both }
.mnav.is-open a:nth-child(1){ animation-delay:40ms }
.mnav.is-open a:nth-child(2){ animation-delay:90ms }
.mnav.is-open a:nth-child(3){ animation-delay:140ms }
.mnav.is-open a:nth-child(4){ animation-delay:190ms }
.mnav.is-open a:nth-child(5){ animation-delay:240ms }
.mnav.is-open a:nth-child(6){ animation-delay:290ms }
@keyframes menuFade{ from{ opacity:0 } to{ opacity:1 } }
@keyframes menuIn{ from{ opacity:0; transform:translateY(16px) } to{ opacity:1; transform:none } }
.mnav a{ font-size:clamp(1.875rem,8vw,2.75rem); font-weight:700; line-height:1.1; color:var(--headline); transition:opacity var(--t-fast) var(--ease-out) }
.mnav a:hover{ opacity:.72 }
/* Seven links plus the CTA need room; below this the menu button carries them.
   RAISED 1040 -> 1140 on 31 Jul 2026, two pillar build. The Overwatch and Data
   links added 168px to a row that had only 118px of slack, so at the old
   breakpoint six of the eight links wrapped onto two lines inside an 80px bar.
   Measured natural widths at the breakpoint: 743px before this build, 926px with
   the short labels, 1028px with the full pillar names. Short labels need a 1112px
   window, so 1140 leaves headroom. IF THE NAV LABELS EVER BECOME THE FULL PILLAR
   NAMES ("Pharos Overwatch", "Pharos Data"), THIS MUST GO TO 1220. */
@media (max-width:1140px){ .nav-links{ display:none } .nav-burger{ display:block } }

/* ---------- hero (scrub kept) ---------- */
.hero{ position:relative; height:100vh; height:100dvh; min-height:640px }
.hero-stage{ position:absolute; inset:0; overflow:hidden }
.hero-canvas,.hero-poster{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover }
/* origin 50% 20%: jib-down reveal keeps its top-pinned feel, but the punched-in
   resting scale doesn't push the dock low in frame. No brightness filter — the
   poster is frame 0 of the graded film and must match the canvas exactly. */
.hero-poster{ transform-origin:50% 20%; z-index:1; transform:scale(1.45) }
.hero-canvas{ opacity:0; z-index:2; transform-origin:50% 20% }
.hero-canvas.is-live{ opacity:1 }
/* hero video test: plain background loop in the same slot as the old poster/canvas stack */
.hero-video{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; z-index:1 }
.hero-clouds{ position:absolute; inset:0; width:100%; height:100%; z-index:3; pointer-events:none }
@media (prefers-reduced-motion: reduce){ .hero-clouds{ display:none } }
/* bottom 40% fades to the page background; headline sits inside the fade */
.hero-stage::after{ content:''; position:absolute; inset:0; z-index:3; pointer-events:none;
  background:linear-gradient(180deg, rgba(10,10,10,.35) 0%, rgba(10,10,10,0) 30%, rgba(10,10,10,0) 38%, rgba(10,10,10,.55) 70%, rgba(10,10,10,.97) 100%) }
.hero-content{
  position:absolute; inset:0; z-index:4; display:flex; flex-direction:column;
  justify-content:flex-end; padding:0 var(--side) 12vh; max-width:var(--maxw); margin:0 auto; left:0; right:0;
  transform:scale(calc(1 - var(--hero-progress,0)*.05));
  opacity:calc(1 - var(--hero-progress,0)*1.15);
}
.hero-eyebrow{ margin-bottom:16px; color:var(--body); text-shadow:0 1px 8px rgba(0,0,0,.6) }
.hero-h1{ font-weight:700; letter-spacing:-.02em; line-height:1.05; color:var(--headline) }
.h-line{ display:block; font-size:clamp(2.125rem,7.5vw,4.5rem) }
.h-line--sub{ font-size:clamp(1.125rem,3vw,2rem); font-weight:500; color:var(--body); margin-top:12px; text-shadow:0 1px 8px rgba(0,0,0,.6) }
/* The hero opens as a clean frame: no text until the visitor scrolls. With no JS
   the copy is simply there, so crawlers and no script visitors lose nothing. */
.js .hero-content{ opacity:0; visibility:hidden; transition:opacity .5s var(--ease-out), visibility 0s .5s }
.js .hero-content.is-revealed{ opacity:1; visibility:visible; transition:opacity .5s var(--ease-out), visibility 0s }
.js .hero-content.is-revealed .h-line{ animation:hwipe .6s var(--ease-out) both; animation-delay:.05s }
.js .hero-content.is-revealed .h-line--sub{ animation-delay:.17s }
.js .hero-content.is-revealed .hero-eyebrow{ animation:heroRise .5s var(--ease-out) both }
.js .hero-content.is-revealed .hero-body{ animation:heroRise .5s var(--ease-out) both; animation-delay:.3s }
@keyframes heroRise{ from{ opacity:0; transform:translateY(10px) } to{ opacity:1; transform:none } }
@media (prefers-reduced-motion: reduce){
  .js .hero-content{ opacity:1; visibility:visible; transition:none }
  .js .hero-content .h-line, .js .hero-content .hero-eyebrow, .js .hero-content .hero-body{ animation:none }
}
.qa-still .hero-content{ opacity:1 !important; visibility:visible !important }
@keyframes hwipe{
  from{ clip-path:inset(0 0 100% 0); transform:translateY(.25em) }
  to{ clip-path:inset(-2% 0 -8% 0); transform:none }
}
.hero-body{ margin-top:24px; max-width:var(--body-maxw); font-size:1rem; line-height:1.5; color:var(--body) }

/* ---------- spec presentation ---------- */
.specs{ display:grid; grid-template-columns:repeat(4,1fr); gap:60px; margin-top:var(--gap-block); list-style:none }
.specs--3{ grid-template-columns:repeat(3,1fr) }
#specs .specs{ margin-top:0 }
.spec{ display:flex; flex-direction:column }
.spec-bar{ width:36px; height:2px; background:var(--accent); margin-bottom:15px }
.spec-n{ font-size:clamp(2.5rem,5vw,3.5rem); font-weight:800; line-height:1; color:var(--headline); letter-spacing:-.01em; font-variant-numeric:tabular-nums }
.spec-u{ font-size:.4em; font-weight:500; color:var(--label); margin-left:.1em }
.spec-l{ font-size:0.75rem; letter-spacing:var(--caps-track); text-transform:uppercase; font-weight:500; color:var(--label); margin-top:8px; max-width:22ch }
@media (max-width:820px){ .specs,.specs--3{ grid-template-columns:1fr 1fr; gap:40px } }
@media (max-width:480px){ .specs,.specs--3{ grid-template-columns:1fr } }

.tb-k{ display:block; font-size:0.8125rem; letter-spacing:var(--caps-track); text-transform:uppercase; font-weight:700; color:var(--headline); margin-bottom:10px }
.tb-v{ display:block; font-size:0.875rem; line-height:1.5; color:var(--body) }
@media (max-width:820px){ .trust-band{ grid-template-columns:1fr 1fr } }
@media (max-width:480px){ .trust-band{ grid-template-columns:1fr } }

/* ---------- real footage bands ---------- */
/* full bleed already, so no void here — but on an ultrawide a 16:9 clip stretched to
   3440 would be 1935px tall. Cap the height and let cover crop. */
.filmband{ position:relative; border-top:1px solid var(--border); border-bottom:1px solid var(--border); background:var(--bg);
  max-height:min(78vh, 900px); overflow:hidden }
/* fill the capped box and crop from the centre, so the subject stays in frame
   instead of the bottom of the shot being sliced off */
.filmband video{ display:block; width:100%; height:100%; object-fit:cover; object-position:center }
/* full bleed captions align to the content column, not the viewport edge */
.filmband-cap{ position:absolute; left:max(var(--side), calc((100% - var(--maxw)) / 2 + var(--side))); bottom:16px;
  color:var(--label); font-size:0.75rem; letter-spacing:var(--caps-track); text-transform:uppercase; text-shadow:0 1px 6px rgba(0,0,0,.9) }
figcaption.filmband-cap{ position:absolute }
/* captions inside framed media use a fixed comfortable inset instead */
.media .filmband-cap, .thermal-static .filmband-cap, .usecase-media .filmband-cap{ left:24px; right:24px; z-index:2 }
/* A thermal frame is nearly white. A grey caption with a soft shadow vanishes on
   it, so framed media get a scrim under the caption and the caption goes bright. */
.media figure, .thermal-static figure, .usecase-media{ position:relative }
.media figure::after, .thermal-static figure::after, .usecase-media::after{
  content:''; position:absolute; left:0; right:0; bottom:0; height:96px; pointer-events:none; z-index:1;
  background:linear-gradient(180deg, rgba(10,10,10,0), rgba(10,10,10,.82)) }
.media .filmband-cap, .thermal-static .filmband-cap, .usecase-media .filmband-cap{ color:var(--headline) }

/* ---------- media frames ---------- */
/* 16:9 at band width would be 1777px tall on a 3440 screen, so the height is capped
   and object-fit:cover crops instead. Above about 1600px wide the frame reads as a
   cinematic strip rather than a 16:9 box, which is the intended trade: it keeps the
   media on the SAME edge as the card grids beside it (the rule from 21 Jul) instead
   of shrinking back to the spine and reintroducing two edges in one section. */
.media{ position:relative; margin-top:var(--gap-block); overflow:hidden; border:1px solid var(--border);
  aspect-ratio:16/9; max-height:min(78vh, 900px) }
.media video,.media img{ width:100%; height:100%; object-fit:cover; display:block }
.media--wide{ aspect-ratio:21/9 }
.media--apple{ will-change:clip-path, transform }
@media (prefers-reduced-motion: reduce){ .media--apple{ clip-path:none !important; transform:none !important } }
.sec-head{ display:grid; grid-template-columns:1.3fr 1fr; gap:clamp(24px,4vw,64px); align-items:end }
.sec-head .lede{ margin-top:0 }
@media (max-width:900px){ .sec-head{ grid-template-columns:1fr } .sec-head .lede{ margin-top:20px } }

/* ---------- service strip ---------- */
.svc{ list-style:none; display:grid; grid-template-columns:repeat(4,1fr); gap:1px; background:var(--border); border:1px solid var(--border) }
/* §2.2 container queries. A service cell is ~300px when the grid is six across on an
   ultrawide and ~560px when it is three across at 1920, so its internals size off the
   CELL (cqi = 1% of the container's inline size), not the viewport. Note a container
   query cannot style its own container, which is why the adaptation is in cqi units on
   the children rather than an @container block changing this padding. */
.svc li{ container-type:inline-size; background:var(--bg); padding:clamp(20px, 2.2vw, 32px) }
.svc b{ display:block; font-weight:600; font-size:0.75rem; letter-spacing:var(--caps-track); text-transform:uppercase; color:var(--label); margin-bottom:clamp(10px, 3cqi, 18px) }
.svc span{ display:block; font-size:clamp(0.9375rem, 3.4cqi, 1.0625rem); line-height:1.5; color:var(--body); max-width:var(--body-maxw) }
.svc--solo{ margin-top:var(--gap-block) }   /* every .svc on the site is standalone */
@media (max-width:900px){ .svc{ grid-template-columns:1fr 1fr } }
@media (max-width:560px){ .svc{ grid-template-columns:1fr } }

/* the commercial offer strip carries panel weight; secondary grids stay on canvas */
#service .svc li{ background:var(--panel); box-shadow:inset 0 1px 0 rgba(255,255,255,.03) }
#service .svc b{ color:var(--headline) }

/* ---------- the amber sweep (Act I centre of gravity) ---------- */
/* the one long motion on the page: an amber line sweeps the top edge of the
   block it is put on, once, when that block first comes into view */
/* the single amber sweep motion signature, spent here and nowhere else */
.sweep{ position:relative }
.sweep::after{ content:''; position:absolute; top:-1px; left:0; height:2px; width:18%; background:var(--accent); opacity:0; pointer-events:none }
.is-swept .sweep::after{ animation:sweep 1.5s var(--ease-out) 1 forwards }
@keyframes sweep{ 0%{ opacity:0; transform:translateX(-40%) } 15%{ opacity:1 } 100%{ opacity:0; transform:translateX(480%) } }
@media (prefers-reduced-motion: reduce){ .is-swept .sweep::after{ animation:none; opacity:0 } }

/* ---------- watcher panel (the operations room) ---------- */
.watcher-panel{ margin-top:var(--gap-block); border:1px solid var(--border); background:linear-gradient(180deg,var(--panel),var(--bg));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.04);
  padding:clamp(28px,5vw,56px); display:flex; flex-direction:column; align-items:center; gap:18px }
.watcher-panel svg{ width:min(420px,86%); height:auto; color:var(--label) }
/* the photograph IS the panel: no padding, no inner border, no caption */
.watcher-panel--photo{ padding:0; display:block; overflow:hidden; background:var(--panel) }
.watcher-panel--photo img{ width:100%; height:auto; display:block;
  /* the source is 660px wide, so it upscales here. Crisp edges beat a soft blur
     when a browser has to invent pixels. */
  image-rendering:auto }

/* ---------- the client app (#app) ----------
   The phone is a CSS frame around the real screen captures, not a photo render:
   it stays crisp at any DPI, the dark bezel dissolves into the page ground, and
   the three WebP screens cost about 180KB on a page already heavy with video.
   The heading stays on the left gutter with every other h2 on the site; only the
   body of the section splits, so nothing breaks the page's alignment spine. */
/* the phone column is the width of the phone, not a percentage: a 216px device in a
   45% column floats in its own empty half and breaks the left edge the h2 sets */
.appsplit{ display:grid; grid-template-columns:min(216px,62vw) 1fr; gap:clamp(40px,7vw,96px);
  align-items:center; margin-top:var(--gap-block) }
@media (max-width:900px){ .appsplit{ grid-template-columns:1fr; gap:40px } }

.appstage{ display:flex; flex-direction:column; align-items:center }
/* dark titanium, one thin edge highlight, no glow — the bezel should recede */
.appphone{ position:relative; width:min(216px,62vw); padding:10px; border-radius:54px;
  background:linear-gradient(155deg,#2E2E2E,#141414 42%,#242424);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.10), 0 28px 60px -34px rgba(0,0,0,.9) }
.appphone-screen{ position:relative; aspect-ratio:1179/2556; border-radius:45px; overflow:hidden;
  background:#0A0F1A }
.appphone-screen img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  opacity:0; transition:opacity var(--t-med) var(--ease-out) }
/* screen one carries .is-on in the markup, so with no JS, or if the script never
   runs, the phone still shows the live view instead of a stack of three */
.appphone-screen img.is-on{ opacity:1 }
/* the captures already carry the status bar; the island is what makes it a phone */
.appphone-island{ position:absolute; top:2.2%; left:50%; width:31%; height:4.3%;
  transform:translateX(-50%); border-radius:999px; background:#000; pointer-events:none }

.appcaps{ margin-top:20px; display:grid; justify-items:center; text-align:center }
.appcap{ font-size:0.84375rem; line-height:1.5; color:var(--label); max-width:32ch; margin:0 auto }
/* no JS: the three captions read as a short list under the one visible screen.
   With JS they stack in one grid cell and crossfade, so nothing shifts. */
.js .appcap{ grid-area:1/1; opacity:0; transition:opacity var(--t-med) var(--ease-out) }
.js .appcap.is-on{ opacity:1 }

.appdots{ display:none }
.js .appdots{ display:flex; gap:8px; margin-top:12px; justify-content:center }
.appdot{ width:44px; height:44px; padding:0; background:none; border:0; cursor:pointer;
  display:grid; place-items:center; touch-action:manipulation }
.appdot::before{ content:""; width:8px; height:8px; border-radius:50%; background:var(--border-strong);
  transition:background var(--t-fast) var(--ease-out), transform var(--t-fast) var(--ease-out) }
.appdot:hover::before{ background:var(--body) }
/* the hit area is 44px, the dot is 8px: ring the dot, not the empty square */
.appdot:focus-visible{ outline:none }
.appdot:focus-visible::before{ outline:2px solid var(--headline); outline-offset:4px }
.appdot[aria-pressed="true"]::before{ background:var(--headline); transform:scale(1.25) }
.appnote{ margin-top:14px; font-size:0.8125rem; line-height:1.5; color:var(--label); text-align:center }

.appbens{ display:grid; gap:28px }
.appben{ display:grid; grid-template-columns:auto 1fr; gap:18px; align-items:baseline }
/* the numeral is the only tie between a benefit and the screen it describes —
   it brightens with the active screen. No amber: the screens carry that. */
.appben-n{ font-size:0.75rem; font-weight:600; letter-spacing:var(--caps-track); color:var(--label);
  font-variant-numeric:tabular-nums; transition:color var(--t-fast) var(--ease-out) }
.appben.is-on .appben-n{ color:var(--headline) }
.appben b{ display:block; font-size:1.0625rem; font-weight:700; line-height:1.3; color:var(--headline) }
.appben p{ margin-top:8px; font-size:0.9375rem; line-height:1.5; color:var(--body); max-width:46ch; text-wrap:pretty }
.appquiet{ padding-top:24px; border-top:1px solid var(--border);   /* the grid gap is the space above */
  font-size:0.9375rem; line-height:1.5; color:var(--label) }
@media (max-width:520px){ .appben{ grid-template-columns:1fr; gap:6px } }

/* ---------- act III sub movements ---------- */
.sub-movement{ margin-top:72px }
.sub-block .lede{ margin-top:20px }
/* .svc-note carries a 60ch cap. In a centred .statement that cap has to be centred
   too, or the box hangs at the left edge and its centred text lands ~436px left of
   the page centre at 1440. The side padding keeps it off the screen edge on mobile. */
.statement .svc-note{ margin:16px auto 0; padding:0 var(--side) }

/* ---------- founders ---------- */
/* ---------- who we are: text left, the mark at size on the right ---------- */
.who-head{ display:grid; grid-template-columns:1.35fr 1fr; gap:clamp(32px,5vw,72px); align-items:start }
@media (max-width:900px){ .who-head{ grid-template-columns:1fr } }
.markplate{ border:1px solid var(--border); background:linear-gradient(180deg,var(--panel),var(--bg));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.04); padding:clamp(28px,4vw,44px);
  display:flex; flex-direction:column; align-items:center; text-align:center }
.markplate-mark{ width:min(150px,52%); height:auto; display:block }
.markplate-word{ margin-top:24px; font-size:1.625rem; font-weight:600; letter-spacing:-.02em; color:var(--headline) }
.markplate-dot{ color:#F0A544 }   /* the full stop is the lamp, the one place amber belongs here */
.markplate-cap{ margin-top:16px; font-size:0.84375rem; line-height:1.5; color:var(--label); max-width:34ch }
/* the only motion the brand guide allows on the mark: the lamp breathing, 4s */
.mark-lamp{ animation:lampPulse 4s ease-in-out infinite }
@keyframes lampPulse{ 0%,100%{ opacity:1 } 50%{ opacity:.6 } }
@media (prefers-reduced-motion: reduce){ .mark-lamp{ animation:none } }
.qa-still .mark-lamp{ animation:none !important }

.founders{ display:grid; grid-template-columns:1fr 1fr; gap:1px; background:var(--border); border:1px solid var(--border); margin-top:var(--gap-block) }
.founder{ background:var(--bg); padding:32px 28px; display:flex; gap:22px; align-items:flex-start }
/* real portraits now: 4:5, the crop they were delivered in. They are already
   black and white on a dark grade, so they sit on the page without a filter. */
.founder-photo{ width:116px; aspect-ratio:4/5; height:auto; flex:none; border:1px solid var(--border); background:var(--panel);
  display:flex; align-items:center; justify-content:center; font-weight:700; font-size:1.625rem; color:var(--label); object-fit:cover }
@media (max-width:520px){ .founder-photo{ width:88px } }
.founder b{ display:block; font-size:1.0625rem; font-weight:700; line-height:1.3; color:var(--headline) }
.founder em{ display:block; font-style:normal; font-size:0.75rem; letter-spacing:var(--caps-track); text-transform:uppercase; color:var(--label); margin:6px 0 12px }
.founder p{ font-size:0.9375rem; line-height:1.5; color:var(--body); max-width:var(--body-maxw) }
@media (max-width:760px){ .founders{ grid-template-columns:1fr } }

/* ---------- resilience (3 col svc variant + note) ---------- */
.svc--3{ grid-template-columns:repeat(3,1fr) }
/* these carry whole sentences, and caps are for labels under a line long, never
   for running prose. Sentence case, normal tracking, readable size. */
.svc-note{ margin-top:24px; font-size:0.9375rem; line-height:1.5; letter-spacing:0; font-weight:400;
  color:var(--label); max-width:60ch; text-wrap:pretty }
@media (max-width:900px){ .svc--3{ grid-template-columns:1fr } }

/* ---------- added services grid (six items, three per row) ---------- */
#added-services .svc{ grid-template-columns:repeat(3,1fr) }
/* DENSITY, not stretch. Six-beat grids go one row across once the band is wide enough
   that six cells still read: at 2100px each cell is about 315px, which holds a label
   and two sentences comfortably. Targeted by section on purpose — .svc--3 is shared
   with three-item and four-item grids, and 6 columns would leave those half empty. */
@media (min-width:2100px){
  #service .svc--3,
  #added-services .svc{ grid-template-columns:repeat(6,1fr) }
}
@media (max-width:900px){ #added-services .svc{ grid-template-columns:1fr } } /* correctness: ID selector above defeats the .svc breakpoints, restore mobile stack */

/* ---------- added services, click to open ----------
   Native details and summary: it works with no JS, it is keyboard operable and
   screen readers announce the state, and the page stays quiet until asked. */
#added-services .svc > li{ padding:0 }
.svc-d{ height:100% }
.svc-d summary{ list-style:none; cursor:pointer; display:block; padding:24px; position:relative;
  transition:background var(--t-fast) var(--ease-out) }
.svc-d summary::-webkit-details-marker{ display:none }
.svc-d summary:hover{ background:rgba(255,255,255,.03) }
.svc-d summary:focus-visible{ outline:2px solid var(--label); outline-offset:-2px }
.svc-d summary b{ display:block; font-weight:600; font-size:0.75rem; letter-spacing:var(--caps-track); text-transform:uppercase;
  color:var(--label); margin-bottom:12px; padding-right:28px }
.svc-d summary span{ display:block; font-size:0.9375rem; line-height:1.5; color:var(--body) }
/* the marker: a plus that becomes a minus, the only thing that moves */
.svc-mark{ position:absolute; top:24px; right:24px; width:12px; height:12px; flex:none }
.svc-mark::before, .svc-mark::after{ content:''; position:absolute; background:var(--label);
  transition:transform var(--t-med) var(--ease-out), opacity var(--t-fast) var(--ease-out) }
.svc-mark::before{ top:5px; left:0; width:12px; height:1.5px }
.svc-mark::after{ left:5px; top:0; width:1.5px; height:12px }
.svc-d[open] .svc-mark::after{ transform:rotate(90deg); opacity:0 }
.svc-d[open] summary b{ color:var(--headline) }
.svc-detail{ padding:0 24px 24px; animation:svcOpen var(--t-med) var(--ease-out) both }
@keyframes svcOpen{ from{ opacity:0; transform:translateY(-6px) } to{ opacity:1; transform:none } }
.svc-detail ul{ list-style:none; margin:0 0 16px }
/* reset the .svc li cell styling that would otherwise cascade into these */
.svc-detail ul li{ background:none; position:relative; padding:0 0 0 16px; margin-bottom:8px;
  font-size:0.9375rem; line-height:1.5; color:var(--body) }
.svc-detail ul li::before{ content:''; position:absolute; left:0; top:9px; width:5px; height:1.5px; background:var(--label) }
/* a sentence, not a label: sentence case and readable, the way the guide asks */
.svc-deliverable{ font-size:0.875rem; color:var(--label); border-top:1px solid var(--border);
  padding-top:14px; line-height:1.6; max-width:var(--body-maxw) }
@media (prefers-reduced-motion: reduce){ .svc-detail{ animation:none } .svc-mark::before, .svc-mark::after{ transition:none } }

/* ---------- statement sections ---------- */
.statement{ padding:var(--gap-section) 0; text-align:center }
.statement-line{ max-width:calc(22ch + 2*var(--side)); margin:0 auto; font-size:clamp(1.625rem,3.6vw,2.5rem); font-weight:700; line-height:1.2; letter-spacing:-.01em; color:var(--headline);
  padding:0 var(--side) }

/* ---------- thermal before/after (static) ---------- */
.thermal-static{ display:grid; grid-template-columns:1fr 1fr; gap:24px; margin-top:var(--gap-block) }
.thermal-static figure{ position:relative; overflow:hidden; border:1px solid var(--border); aspect-ratio:16/9 }
.thermal-static img{ width:100%; height:100%; object-fit:cover }
@media (max-width:720px){ .thermal-static{ grid-template-columns:1fr } }

/* ---------- trust paragraph (the one long block) ---------- */
.sec--trust .eyebrow{ font-size:clamp(1.25rem,2.4vw,1.625rem); font-weight:700; letter-spacing:0; text-transform:none; color:var(--headline); margin-bottom:20px }
/* a px measure cap does not survive fluid type: as the base font grows the line gets
   SHORTER, not longer. In ch the character count holds steady at any base size. */
.trust-para{ max-width:58ch; font-size:1.0625rem; line-height:1.55; color:var(--body) }
.trust-para a{ color:var(--body); text-decoration:underline; text-underline-offset:3px; text-decoration-color:var(--label);
  transition:color var(--t-fast) var(--ease-out), text-decoration-color var(--t-fast) var(--ease-out) }
.trust-para a:hover{ color:var(--headline); text-decoration-color:currentColor }

/* ---------- use cases ---------- */
.usecases{ width:calc(100% - 2*var(--side)); max-width:calc(var(--maxw-wide) - 2*var(--side)); margin:var(--gap-block) auto 0;
  display:flex; flex-direction:column; gap:1px; background:var(--border); border:1px solid var(--border) }
.usecase{ display:grid; grid-template-columns:1.2fr 1fr; background:var(--bg); align-items:center }
/* the brief widens the use case MEDIA, so the extra band goes to the frame, not to
   a copy column that is capped at 40ch and would just gain trailing space */
@media (min-width:1280px){ .usecase{ grid-template-columns:1.5fr 1fr } }
.usecase-media{ position:relative; overflow:hidden; aspect-ratio:16/9 }
.usecase-media img,.usecase-media video{ width:100%; height:100%; object-fit:cover }
.usecase-copy{ padding:clamp(28px,4vw,48px) }
.usecase-copy p{ color:var(--body); margin-top:14px; max-width:40ch }
@media (max-width:760px){ .usecase{ grid-template-columns:1fr } }
/* §2.3 the three use cases go one row across once each card still has room for its
   media/copy split: at 2200px each card is about 1050px, so media ~630 and copy ~420.
   Three columns, never two — two would leave an orphan cell in a hairline grid. */
@media (min-width:2200px){ .usecases{ flex-direction:row } .usecases > .usecase{ flex:1 1 0; min-width:0 } }

/* ---------- detection overlay, drawn over the footage ----------
   Matches the boxes already baked into the wildlife clip, so the two tiles read
   as one system. Nothing here touches the video file. */
.ardet{ position:absolute; inset:0; z-index:2; pointer-events:none;
  font:600 clamp(8px,1.15vw,11px)/1 var(--font); letter-spacing:.06em }
.ardet-drift{ position:absolute; inset:0;
  /* the aircraft is flying forward, so the whole scene creeps down and out */
  animation:ardetDrift 8.68s linear infinite }
@keyframes ardetDrift{
  from{ transform:translate(0,0) scale(1) }
  to{ transform:translate(1.6%,7%) scale(1.09) }
}
.ardet-box{ position:absolute; left:var(--x); top:var(--y); width:var(--w); height:var(--h);
  border:1.5px solid #F0A544; opacity:0;
  animation:ardetBox 8.68s var(--ease-out) var(--in) infinite }
@keyframes ardetBox{
  0%{ opacity:0; transform:scale(.94) }
  4%{ opacity:1; transform:none }
  46%{ opacity:1 }
  54%{ opacity:0 }
  100%{ opacity:0 }
}
.ardet-box i{ position:absolute; left:-1.5px; bottom:100%; display:block; white-space:nowrap;
  background:#F0A544; color:#141414; font-style:normal; padding:3px 6px 3px 5px }
.ardet-chip{ position:absolute; top:10px; right:10px; display:flex; align-items:center; gap:6px;
  background:rgba(10,10,10,.72); color:#F2F2F2; padding:5px 9px; border-radius:3px;
  font:600 clamp(9px,1.2vw,12px)/1 var(--font); letter-spacing:.04em }
.ardet-dot{ width:6px; height:6px; border-radius:50%; background:#F0A544; display:block }
/* the caption sits above the overlay */
.usecase-media .filmband-cap{ z-index:3 }
@media (prefers-reduced-motion: reduce){
  .ardet-drift{ animation:none }
  .ardet-box{ animation:none; opacity:1 }
}
.qa-still .ardet-drift{ animation:none }
.qa-still .ardet-box{ animation:none; opacity:1 }




/* ---------- contact ---------- */
.contact-quick{ display:flex; flex-wrap:wrap; gap:8px 32px; margin-top:48px }
.quick-link{ font-size:0.9375rem; color:var(--body); text-decoration:underline; text-decoration-thickness:1px; text-underline-offset:2px; text-decoration-color:var(--label);
  padding:11px 0; transition:color var(--t-fast) var(--ease-out), text-decoration-color var(--t-fast) var(--ease-out) }
.quick-link:hover{ color:var(--headline); text-decoration-color:currentColor }
@media (max-width:560px){ .contact-quick{ flex-direction:column; gap:2px } .quick-link{ padding:13px 0 } }
#ctaForm{ margin-top:48px; max-width:720px }
.f-grid{ display:grid; grid-template-columns:1fr 1fr; gap:32px }
.f-wide{ grid-column:1/-1 }
label{ display:flex; flex-direction:column; gap:8px; font-size:0.75rem; letter-spacing:var(--caps-track); text-transform:uppercase; color:var(--label); font-weight:500; transition:color var(--t-fast) var(--ease-out) }
input,select,textarea{
  background:transparent; border:0; border-bottom:1px solid var(--border-strong);
  color:var(--headline); font:400 1rem var(--font); padding:10px 0;
  caret-color:var(--headline);
  transition:border-color var(--t-fast) var(--ease-out); border-radius:0;
}
select{ appearance:none; -webkit-appearance:none; padding-right:28px;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' fill='none' stroke='%23888888' stroke-width='1.5'/></svg>");
  background-repeat:no-repeat; background-position:right 4px center }
input:hover,select:hover,textarea:hover{ border-color:var(--label) }
input:focus,select:focus,textarea:focus{ outline:none; border-color:var(--headline) }
input:focus-visible,select:focus-visible,textarea:focus-visible{ outline:2px solid var(--headline); outline-offset:3px }
label:focus-within{ color:var(--body) }
input.is-invalid{ border-color:var(--danger) }
select option{ background:var(--panel) }

/* buttons */
.btn{ display:inline-block; cursor:pointer; font:700 .875rem var(--font); letter-spacing:.5px; border-radius:2px;
  transition:background var(--t-fast) var(--ease-out), transform var(--t-fast) var(--ease-out), box-shadow var(--t-fast) var(--ease-out), opacity var(--t-fast) var(--ease-out) }
.btn--primary{ background:var(--accent); color:var(--btn-text-on-accent); border:0; padding:16px 30px; box-shadow:0 1px 0 rgba(255,255,255,.06) inset }
.btn--primary:hover{ background:var(--accent-up) }
.btn--primary:active{ background:var(--accent-down); transform:translateY(1px); box-shadow:none }
.btn--primary:disabled{ opacity:.45; cursor:default; background:var(--accent); transform:none }
/* the second path: same weight of decision, quieter surface, so the rust stays
   on one action per screen */
.btn--line{ background:none; color:var(--headline); border:1px solid var(--border-strong); padding:15px 29px;
  transition:border-color var(--t-fast) var(--ease-out), background var(--t-fast) var(--ease-out), transform var(--t-fast) var(--ease-out) }
.btn--line:hover{ border-color:var(--label); background:rgba(255,255,255,.04) }
.btn--line:active{ transform:translateY(1px) }

/* ---------- two ways to start (contact) ---------- */
.paths{ display:grid; grid-template-columns:1fr 1fr; gap:1px; background:var(--border);
  border:1px solid var(--border); margin-top:var(--gap-block) }
.path{ background:var(--panel); padding:clamp(24px,3vw,36px); display:flex; flex-direction:column; align-items:flex-start;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.03) }
.path-n{ font-size:0.75rem; letter-spacing:var(--caps-track); text-transform:uppercase; font-weight:600; color:var(--label); margin-bottom:14px }
.path-h{ font-size:clamp(1.1875rem,2vw,1.4375rem); font-weight:700; line-height:1.2; color:var(--headline); letter-spacing:-.01em }
.path-b{ margin-top:12px; font-size:0.9375rem; line-height:1.5; color:var(--body); max-width:var(--body-maxw) }
.path .btn{ margin-top:24px }
@media (max-width:760px){ .paths{ grid-template-columns:1fr } }
#ctaForm .btn{ margin-top:48px }
.f-note{ margin-top:16px; font-size:0.84375rem; line-height:1.5; color:var(--label); max-width:var(--body-maxw) }
.f-note a{ color:var(--body); text-decoration:underline; text-underline-offset:3px; text-decoration-color:var(--border) }
.f-note a:hover{ text-decoration-color:currentColor }
.f-ack{ margin-top:24px; color:var(--body) }
/* a red border alone is colour-only error signalling, so every invalid field also
   gets a sentence. Same red as .f-err, which already clears AA on the page ground. */
.f-fielderr{ display:block; margin-top:6px; font-size:0.84375rem; line-height:1.4; color:#d98177 }
.f-err{ margin-top:24px; color:#d98177 }
.f-err a{ text-decoration:underline }
@media (max-width:640px){ .f-grid{ grid-template-columns:1fr } }

/* ---------- sticky CTA ---------- */
.sticky-cta{ padding-bottom:env(safe-area-inset-bottom);
  position:fixed; left:0; right:0; bottom:0; z-index:55; height:64px;
  display:flex; align-items:center; justify-content:center;
  background:rgba(10,10,10,.95); backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px);
  border-top:1px solid var(--border); box-shadow:0 -12px 32px rgba(0,0,0,.4);
  transform:translateY(100%); transition:transform var(--t-med) var(--ease-out); pointer-events:none;
}
.sticky-cta.is-on{ transform:none; pointer-events:auto }
.sticky-cta .btn{ padding:12px 24px }

/* ---------- footer ---------- */
.footer{ border-top:1px solid var(--border); padding:72px 0 96px; color:var(--label) }
.foot-cols{ display:grid; grid-template-columns:repeat(3,1fr); gap:32px; margin-bottom:48px }
.foot-col{ display:flex; flex-direction:column; gap:12px; font-size:0.875rem; color:var(--label) }
.foot-col a{ transition:color var(--t-fast) var(--ease-out) }
.foot-col a:hover{ color:var(--headline) }
.foot-brand{ font-size:1.0625rem; font-weight:700; color:var(--headline) }
.foot-tag{ color:var(--body) }
.fn{ font-size:0.8125rem; max-width:62ch;   /* 68ch measured 91 real characters in Inter; ch is the width of "0", which is wider than the average glyph */ margin-top:10px; line-height:1.5; color:var(--label) }
@media (max-width:640px){ .foot-cols{ grid-template-columns:1fr } }

/* ---------- the spine hairlines are GONE (22 Jul 2026) ----------
   They were added on 21 Jul to give the big empty margin some structure, back when
   content stopped at 1200px and a 3440 screen was 58% black. The fluid refactor
   removed the thing they existed to solve: the band now runs to 96vw and only the
   gutter is left, so there is no void to give structure to.

   Worse, they had become actively wrong. The lines were drawn at --maxw, the SPINE,
   which is now narrower than the band the grids use. On a 3440 screen they ran
   vertically THROUGH the content instead of marking its edge — two arbitrary rules
   sitting inside the layout. Do not bring them back without re-deciding which of the
   two widths they are supposed to mark. */
/* NO GUTTER EYEBROWS. They were tried above 1800px and removed: the treatment only
   works if the outer gutter is empty, and the wide band fills it. At 1900 the eyebrow
   sat at x208 while its own H2 sat at x397, and it ran horizontally into the spec
   strip beside it. An eyebrow belongs directly above the heading it labels, on the
   same left edge, at every width. Do not reintroduce this without first checking it
   against --maxw-wide at 1800, 1920 and 2560. */
/* The >1800px body bump that used to live here is gone. The html clamp at the top of
   this file now scales the whole composition continuously, and a second size rule
   firing at one breakpoint would fight it. */

/* ---------- reveal system (guide default: fade + scale 95→100) ---------- */
.js [data-reveal]{ opacity:0; transform:translateY(14px); transition:opacity .38s var(--ease-out), transform .38s var(--ease-out) }
.js [data-reveal].is-in{ opacity:1; transform:none }

/* ---------- group stagger: cells settle in sequence once their grid is in ---------- */
.js .specs[data-reveal] .spec, .js .svc[data-reveal] > li, .js .founders[data-reveal] .founder{
  opacity:0; transform:translateY(10px);
  transition:opacity .32s var(--ease-out), transform .32s var(--ease-out) }
.js [data-reveal].is-in > li, .js [data-reveal].is-in .spec, .js [data-reveal].is-in .founder{ opacity:1; transform:none }
.js [data-reveal].is-in > *:nth-child(1){ transition-delay:0ms }
.js [data-reveal].is-in > *:nth-child(2){ transition-delay:60ms }
.js [data-reveal].is-in > *:nth-child(3){ transition-delay:120ms }
.js [data-reveal].is-in > *:nth-child(4){ transition-delay:180ms }
.js [data-reveal].is-in > *:nth-child(5){ transition-delay:240ms }
.js [data-reveal].is-in > *:nth-child(n+6){ transition-delay:300ms }

/* ---------- QA still mode ---------- */
.qa-still .lid{ display:none !important }
.qa-still [data-reveal]{ opacity:1 !important; transform:none !important; transition:none !important }
.qa-still [data-reveal] li, .qa-still [data-reveal] .spec, .qa-still [data-reveal] .founder{ opacity:1 !important; transform:none !important; transition:none !important }
.qa-still .hero-h1 .h-line{ animation:none !important; clip-path:none !important }

/* ---------- reduced motion parity ---------- */
@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior:auto }
  *,*::before,*::after{ animation:none !important; transition:none !important }
  .js [data-reveal],[data-reveal]{ opacity:1; transform:none }
  .js [data-reveal] li, .js [data-reveal] .spec, .js [data-reveal] .founder{ opacity:1; transform:none }
  .hero-canvas{ display:none }
  .hero-content{ transform:none; opacity:1 }
  .lid{ display:none }
}
