/* ═══════════════════════════════════════════════════════════════════════════
   Lateral homepage v3 — Apple-grammar card page with Liquid Glass
   ───────────────────────────────────────────────────────────────────────────
   Design language (matching the iOS app):
   - System font stack: SF on Apple devices, Inter elsewhere. Same as the app.
   - Semibold 600 display. Centered marketing copy. Short lines.
   - Sections are ART-DIRECTED light or dark, like product photography —
     they do not flip with the site theme.
   - Liquid Glass: translucent, blurred, hairline-bordered surfaces — the
     floating nav pill, chips, and CTAs mirror the app's glass toolbars.

   Fail-safe tiers carry over from v2 and remain load-bearing:
   T0 complete page · T1 .rv reveals armed by home.js (.rv-armed) ·
   T2 @supports-gated CSS scroll garnish · T3 rAF scenes whose T0 = final frame.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  --sf: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text",
        "Helvetica Neue", Inter, system-ui, sans-serif;
  /* The scene tokens. Every band on this page is painted from these, so an
     art-directed dark section is a short override (see the band below) rather
     than a second copy of the stylesheet. */
  --ink-card-dark: #1d1d1f;   /* the black tile in the apple.com-style grid */
  --scene-ink: #ffffff;
  --scene-tint: #f5f5f7;      /* the alternating band */
  --scene-txt: #1d1d1f;
  --scene-dim: #6e6e73;
  --scene-line: #d2d2d7;
  --scene-fill: rgba(0, 0, 0, .05);      /* a resting surface on paper */
  --scene-fill-2: rgba(0, 0, 0, .09);    /* the same, one step up */
  --amber: #F5A524;
  /* Accent hues are declared TWICE — the pale versions read on near-black and
     are invisible on paper, so each has a darkened light-mode twin. */
  --red: #d92d2d;
  --blue: #0071e3;
  --green: #17864f;
  --violet: #6b46d6;
  --wrapW: 1180px;
  /* --glass-bg / --glass-brd are NOT redeclared here. chrome.css owns them and
     loads first, so a copy in this file silently wins on the homepage only —
     which is exactly how the pill stayed dark while the page went light. */
}

/* ── The art-directed dark band ───────────────────────────────────────────
   Apple runs a full-bleed black section inside a white page when the subject is
   the product lit against nothing. Two sections here earn it: the Three.js
   hazard-engine terrain (which IS a night scene — its fog colour is baked into
   the material) and the Dynamic Island, which is a black pill and has no
   light-mode form. They inherit the same token names, so nothing below needs a
   second rule. */
.engine-track, .isl-track, .on-dark, .card.dark {
  color-scheme: dark;
  color: #f5f5f7;
  --scene-ink: #04060a;
  --scene-tint: #080c10;
  --scene-txt: #f5f5f7;
  --scene-dim: rgba(235, 235, 240, .62);
  --scene-line: rgba(235, 235, 240, .12);
  --scene-fill: rgba(235, 235, 240, .10);
  --scene-fill-2: rgba(235, 235, 240, .16);
  /* the accent tokens are NOT set here: theme.css already flips them for every
     dark context, and a copy in this block hardcoded one hue onto every dark
     surface — which is how the Plan tile ended up wearing the hazard orange. */
  --red: #ff5c5c;
  --blue: #6bb7ff;
  --green: #34D399;
  --violet: #d9b8ff;
}

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body.home {
  font-family: var(--sf);
  background: var(--scene-ink);
  color: var(--scene-txt);
  font-size: 17px; line-height: 1.47;
  -webkit-font-smoothing: antialiased;
}

/* ── Liquid Glass primitives, the nav pill and the footer now live in
      assets/chrome.css, which every page loads. They were duplicated here and
      the two copies had drifted: this file collapsed the nav at 720px while
      chrome.css does it at 860px, so the homepage silently disagreed with the
      rest of the site about when the menu button appears. ─────────────────── */

/* ── Type scale ──────────────────────────────────────────────────────────── */
.h-super {
  font-size: clamp(48px, 7.4vw, 96px); font-weight: 700;
  letter-spacing: -.015em; line-height: 1.03; color: var(--scene-txt);
}
/* ── The wordmark ─────────────────────────────────────────────────────────
   The supplied neon rendering, used as the file it is. A previous pass drew it
   in CSS with -webkit-text-stroke and a stack of glows; it was close and it was
   not the same drawing, so the artwork wins.

   The <h1> is kept and the alt text carries the name — the page still has a
   heading and something to be found by — and the glyphs are sized off the
   IMAGE width, which is wider than the letters: the file carries about 5% of
   transparent glow margin on each side and roughly 13% top and bottom. That
   padding is the light, so it must not be cropped; it just means the picture
   always looks a size larger than the word inside it. */
.hero-pin .wordmark { line-height: 0; margin-bottom: clamp(14px, 2.2vh, 26px); }
.hero-pin .wordmark img {
  display: block; width: min(86%, 620px); height: auto; margin: 0 auto;
}

.h1 {
  font-size: clamp(38px, 5.4vw, 72px); font-weight: 600;
  letter-spacing: -.015em; line-height: 1.05;
}
.h2 {
  font-size: clamp(28px, 3.6vw, 48px); font-weight: 600;
  letter-spacing: -.012em; line-height: 1.08; margin-bottom: 14px;
}
.h3 { font-size: clamp(19px, 2vw, 24px); font-weight: 600; line-height: 1.19; }
.sub {
  font-size: clamp(17px, 1.9vw, 21px); line-height: 1.42; font-weight: 400;
  max-width: 640px; margin: 0 auto;
}
.eyebrow {
  font-size: 13px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
  color: var(--accent-text); margin-bottom: 14px;
}

/* ── Card grammar (the apple.com homepage grid) ──────────────────────────── */
.cards { display: grid; gap: 14px; padding: 14px; max-width: 1440px; margin: 0 auto; }
/* Cards size to their content. The old 560px floor was set for cards that
   carry device art; on the text-only ones it left ~400px of dead space. */
.card {
  position: relative; border-radius: 28px; overflow: clip;
  display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: clamp(38px, 5.5vh, 62px) 28px clamp(38px, 5.5vh, 62px);
  min-height: 0;
}
.card .sub { max-width: 34rem; }
/* only the cards that actually hold artwork keep a floor and a flush bottom */
.card.has-art { min-height: 520px; padding-bottom: 0; }
/* a little depth at the base so a text card still reads as an object */
.card.dark::after {
  content: ''; position: absolute; left: 50%; bottom: -46%; width: 120%; height: 62%;
  transform: translateX(-50%); pointer-events: none;
  background: radial-gradient(closest-side, rgba(245, 165, 36, .10), transparent 72%);
}
/* The grid checkerboards black and grey tiles on a white page — the
   apple.com/#store grammar. .dark is a real black tile, not a token flip: it
   carries dark device art and must sit BEHIND that art, not match the page. */
.card.dark { background: var(--ink-card-dark); color: #f5f5f7; }
.card.light { background: var(--scene-tint); color: var(--scene-txt); }
.card.light .sub { color: #6e6e73; }
.card.dark .sub { color: rgba(235, 235, 240, .68); }
.card .kicker {
  font-size: 14px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  margin-bottom: 10px;
}
.card.dark .kicker { color: var(--accent-text); }
/* the tile wears its product's hue; .tint-* on the card does the rest */
.card.light .kicker { color: var(--accent-text); }
.card .name { margin-bottom: 8px; }
/* ── Product names as neon artwork ────────────────────────────────────────
   Sized by HEIGHT, not width: the five words are wildly different lengths, and
   matching their widths would set "Plan" three times the size of "Jobs &
   Marketplace". Height is what makes the cap heights agree across the grid.

   --name-h is the height for a 922px-tall source. The files are all cut at ONE
   type scale but on different canvases — taller where a descender needs the
   room, which is why "Jobs & Marketplace" is 1036px against Plan's 922 — so
   each is scaled by its own source height over 922 and the type comes out the
   same size in all five. Change --name-h alone to resize the whole set.

   The clamp is what keeps the longest of them inside the narrowest card:
   "Jobs & Marketplace" is 6.9:1, so at the 30px floor it draws 231px wide,
   which still fits a phone's card. */
.cards { --name-h: clamp(30px, 4.2vw, 66px); }
/* the Plan card is full width and its name was already set larger (.h1) */
.card.has-art { --name-h: clamp(40px, 5.6vw, 92px); }
.card .name-art { line-height: 0; margin-bottom: 14px; }
.card .name-art img { display: block; width: auto; }
.card .name-art img[src*="name-plan"]     { height: calc(var(--name-h) * 922 / 922); }
.card .name-art img[src*="name-fleet"]    { height: calc(var(--name-h) * 922 / 922); }
.card .name-art img[src*="name-schedule"] { height: calc(var(--name-h) * 930 / 922); }
.card .name-art img[src*="name-weather"]  { height: calc(var(--name-h) * 912 / 922); }
.card .name-art img[src*="name-jobs"]     { height: calc(var(--name-h) * 1036 / 922); }
.card .ctas { display: flex; gap: 12px; margin: 22px 0 8px; flex-wrap: wrap; justify-content: center; }
.row-2 { grid-template-columns: 1fr 1fr; }
@media (max-width: 900px) { .row-2 { grid-template-columns: 1fr; } .card.has-art { min-height: 440px; } }

.pill-btn {
  display: inline-block; border-radius: 999px; padding: 11px 22px;
  font-size: 15px; font-weight: 500; text-decoration: none; line-height: 1.2;
  transition: transform .2s, background .2s;
}
.pill-btn:hover { transform: scale(1.03); }
.pill-btn.solid { background: var(--accent); color: var(--accent-ink); font-weight: 600; }
/* ── A button that IS artwork ──────────────────────────────────────────────
   It brings its own pill and its own glow, so the styled background, border
   and padding all have to come off or the picture sits inside a second
   button. Sized by HEIGHT, to line up with the text buttons beside it: the
   glow is transparent margin, which makes the file both wider and taller than
   the control it draws — the pill is about 80% of the file's height, so 52px
   here renders a ~42px pill, matching .pill-btn.line next to it. */
.pill-btn.art { background: none; border: 0; padding: 0; line-height: 0; }
.pill-btn.art img { display: block; height: 52px; width: auto; }
@media (max-width: 560px) { .pill-btn.art img { height: 48px; } }
/* The outline is on .line itself, not only on the card variants — the hero
   uses this button too, and outside a card it was rendering as a bare link. */
.pill-btn.line { border: 1px solid rgba(0, 0, 0, .24); color: var(--scene-txt); }
.card.light .pill-btn.line { border: 1px solid rgba(0, 0, 0, .24); color: var(--scene-txt); }
.card.dark .pill-btn.line { border: 1px solid rgba(255, 255, 255, .3); color: #f5f5f7; }
.status-tag {
  display: inline-block; font-size: 11.5px; font-weight: 600; letter-spacing: .07em;
  text-transform: uppercase; border-radius: 999px; padding: 4px 11px; margin-bottom: 12px;
}
/* the tag wears the tile's hue — .tint-* on the card supplies it */
.card.dark .status-tag  { background: var(--accent-soft); color: var(--accent-text); }
.card.light .status-tag { background: var(--accent-soft); color: var(--accent-text); }

/* ── Hero: the headline is pinned, the picture scrolls up over it ─────────
   apple.com/pages' hero, and the mechanism is worth stating because it looks
   like more than it is: the headline is sticky, the picture below it is in
   normal flow with a higher z-index, and scrolling carries the picture up
   until it covers the words.

   The one thing holding it together is that .hero-art is OPAQUE and painted in
   the page's own colour. The block therefore has no visible boundary of its
   own, and the headline reads as being swallowed rather than wiped by a moving
   rectangle. Give .hero-art a transparent background and the words show
   through the gaps between the devices; give it a tinted one and a coloured
   band slides up the page.

   There is no JS here at all, which is the other half of the point: the first
   frame is the finished one, with no loading state, no WebGL path and no
   still to keep in sync with a live scene. */
.hero { position: relative; background: var(--scene-ink); }
.hero-pin {
  position: sticky; top: 0; z-index: 0;
  height: 100vh; height: 100svh;
  display: flex; flex-direction: column; align-items: center;
  justify-content: flex-start; text-align: center;
  padding: clamp(96px, 17svh, 190px) 22px 0;
}
.hero-pin .h-super { margin-bottom: 12px; }
.hero-pin .sub { color: var(--scene-dim); max-width: 620px; margin: 0 auto; }
.hero-pin .sub b { color: var(--scene-txt); font-weight: 600; }

/* Pulled back up over the pinned block, then padded down so the picture starts
   just below the headline and its top edge is already visible above the fold —
   the devices have to be promised before they arrive, or the first screen is
   a headline over nothing. z-index is what lets it pass in front. */
.hero-scroll {
  position: relative; z-index: 1;
  margin-top: -100vh; margin-top: -100svh;
  padding-top: 56vh; padding-top: 56svh;
}
/* ── The hero composition: three devices, face on, side by side ───────────
   Apple's arrangement on that page is FLAT. Every device is square to the
   camera and they overlap only left-to-right and in stacking order — nothing
   is rotated or tilted. That is not a style choice: at this size a perspective
   arrangement looks livelier and you cannot read a word on any of the three
   screens, which is the whole reason for showing them.

   It is DOM rather than a rendered picture, built from the site's own device
   frames, so a new screenshot is a src swap and the frames stay crisp at any
   pixel density.

   `.hero-art` must stay OPAQUE and full-bleed: this is the block that covers
   the headline as it scrolls up, and anything transparent lets the words show
   through it. */
.hero-art {
  background: var(--scene-ink);
  width: 100vw; margin-left: calc(50% - 50vw);
  padding-top: clamp(8px, 1.6vh, 22px);
}
.hero-devices {
  width: min(94%, 1220px); margin: 0 auto;
  display: flex; align-items: flex-end; justify-content: center;
  container-type: inline-size;
}

/* Sizes are in cqw — percent of the ROW's width — because the device frames
   derive every radius, bezel and inset from their own width variable, and a
   plain percentage there would resolve against the wrong box and wreck the
   corner radii. The px values are the fallback for engines without container
   queries; they are a fixed size rather than a correct one, which is the right
   trade for a browser that old. */
.hero-devices .phone   { --w: 150px;  width: var(--w); margin: 0; z-index: 3; }
.hero-devices .macbook { --mw: 660px; width: var(--mw); margin: 0; z-index: 1; }
.hero-devices .tablet  { --tw: 300px; width: var(--tw); margin: 0; z-index: 2; }
@supports (width: 1cqw) {
  /* ⚠️ The MacBook's BOX is wider than anything you can see of it: .mac-screen
     is 78% of .macbook and centred, so there is ~11% of empty box on each side
     before the lid starts. Overlaps sized against the box therefore left a
     visible gap. These numbers overlap the lid, and the tablets sit over the
     base — which is full width — exactly as they do on Apple's. */
  .hero-devices .phone   { --w: 14cqw; margin-right: -8.6cqw; }
  .hero-devices .macbook { --mw: 69cqw; margin-bottom: 1.4cqw; }
  /* The iPad is PORTRAIT (Apple's is landscape), so it has to be narrower than
     the arrangement wants: at Apple's relative width a portrait tablet stands
     taller than the MacBook and takes over the composition. */
  .hero-devices .tablet  { --tw: 22cqw; margin-left: -10cqw; }
  /* the MacBook's own radii and base are fixed px in the card grid, where the
     Mac is always about one size; here it ranges from a phone to a monitor */
  .hero-devices .mac-screen { border-radius: 1.3cqw 1.3cqw 0 0; }
  .hero-devices .mac-display { border-radius: 1.0cqw 1.0cqw 0 0; }
  .hero-devices .mac-base { height: 1.5cqw; border-radius: 0 0 1.05cqw 1.05cqw; }
  /* The lid is 16:10.4 in the card grid, where the screen holds a wireframe
     that can be any shape. Here it holds a 16:10 capture, and `cover` was
     quietly shaving the right-hand side of the planner off. */
  .hero-devices .mac-screen { aspect-ratio: 16 / 10.18; }
  .hero-devices .mac-base::before { height: 34%; border-radius: 0 0 .5cqw .5cqw; }
}
/* the Mac's screen carries a real capture here, not the wireframe */
.hero-devices .mac-display img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
}
/* On paper the frames' dark-mode drop shadows read as soot. */
.hero-devices .phone-frame {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .09), 0 1px 2px rgba(0, 0, 0, .35),
              0 18px 40px rgba(0, 0, 0, .20);
}
.hero-devices .mac-screen {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .08), 0 14px 40px rgba(0, 0, 0, .16);
}
.hero-devices .mac-base { box-shadow: 0 8px 22px rgba(0, 0, 0, .18); }

/* ── CSS iPad ─────────────────────────────────────────────────────────────
   Same construction as the iPhone, and the numbers are the whole difference
   between the two: an iPhone's display corner is ~15% of its width and an
   iPad's is ~5.5%, with a far wider bezel and no island. Get those wrong and
   it reads as a big phone. */
.tablet {
  --tw: 300px;
  width: var(--tw); aspect-ratio: 1000 / 1451;
  position: relative; margin: 0 auto; flex: none;
}
.tablet-frame {
  position: absolute; inset: 0;
  border-radius: calc(var(--tw) * .055);
  padding: calc(var(--tw) * .028);
  background: linear-gradient(145deg, #3a3d44, #17181c 45%, #060708);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .09), 0 1px 2px rgba(0, 0, 0, .35),
              0 18px 44px rgba(0, 0, 0, .20);
}
.tablet-screen {
  position: relative; width: 100%; height: 100%; overflow: hidden;
  border-radius: calc(var(--tw) * .055 - var(--tw) * .028);
  background: #000; box-shadow: inset 0 0 0 2px #000;
}
.tablet-screen img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.hero-below { padding: clamp(24px, 4.5vh, 52px) 22px clamp(36px, 7vh, 84px); text-align: center; }
.hero-ctas { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }
.hero-note { margin-top: 16px; font-size: 14px; color: var(--scene-dim); }

@media (max-width: 760px) {
  .hero-pin { padding-top: clamp(80px, 13svh, 140px); }
  .hero-scroll { padding-top: 48vh; padding-top: 48svh; overflow-x: clip; }
  /* Nearly edge to edge: at this width every pixel counts, and the row can go
     wider than it does on a laptop because there is nothing beside it. */
  .hero-devices { width: 98%; }
}

@media (prefers-reduced-motion: reduce) {
  /* Nothing animates, but pinning is still motion of a kind: the headline
     holds while the page moves under it. Released, the hero is an ordinary
     stack — headline, picture, buttons — which is the same content in the
     same order. */
  .hero-pin { position: static; height: auto; padding-bottom: clamp(20px, 4svh, 44px); }
  .hero-scroll { margin-top: 0; padding-top: 0; }
}

/* ── CSS iPhone ──────────────────────────────────────────────────────────── */
.phone {
  --w: clamp(230px, 24vw, 320px);
  width: var(--w); aspect-ratio: 860 / 1868;
  position: relative; margin: 0 auto; flex: none;
}
.phone-frame {
  position: absolute; inset: 0;
  border-radius: calc(var(--w) * .155);
  padding: calc(var(--w) * .026);
  background: linear-gradient(145deg, #3a3d44, #17181c 45%, #060708);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .09), 0 1px 2px rgba(0, 0, 0, .6),
              0 24px 70px rgba(0, 0, 0, .55);
}
.phone-screen {
  position: relative; width: 100%; height: 100%; overflow: hidden;
  border-radius: calc(var(--w) * .155 - var(--w) * .026);
  background: #000;
  box-shadow: inset 0 0 0 2px #000, inset 0 0 18px rgba(0, 0, 0, .5);
}
.phone-screen img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.phone-island {
  position: absolute; z-index: 3; top: calc(var(--w) * .048); left: 50%;
  transform: translateX(-50%);
  width: calc(var(--w) * .29); height: calc(var(--w) * .085);
  border-radius: 999px; background: #000;
}
.phone-glow {
  position: absolute; inset: -14%; z-index: -1; border-radius: 30%;
  background-image: url(/assets/glow-dark.webp);
  background-size: 100% 100%; filter: blur(38px) saturate(1.3);
  opacity: .5; pointer-events: none;
}

/* ── CSS MacBook (Lateral Web card — blank screen until it ships) ───────────── */
.macbook { --mw: min(680px, 88%); width: var(--mw); margin: 28px auto 0; position: relative; }
.mac-screen {
  /* 16:10.4 while the screen held a wireframe, which could be any shape. It
     holds a 16:10 capture of the real planner now, and the extra 0.4 was
     letterboxing it. */
  width: 78%; margin: 0 auto; aspect-ratio: 16 / 10;
  border-radius: 18px 18px 0 0; padding: 1.1%;
  background: linear-gradient(160deg, #2a2c31, #101114 55%, #060708);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .08), 0 18px 60px rgba(0, 0, 0, .35);
}
.mac-display {
  width: 100%; height: 100%; border-radius: 12px 12px 0 0; overflow: hidden;
  background: #000; position: relative;
  display: grid; place-items: center;
}
/* The screen carried a wireframe of the planning view while Lateral Plan
   had nothing to photograph. The beta is live, so it carries a capture of
   the real planner now, and the wireframe rules went with it. */
.mac-display { background: #06070a; }
/* The .mac-display is a grid with place-items:center, which the wireframe SVG
   filled by declaring its own 100%×100%. An <img> does not, so without this it
   renders at its intrinsic 1760 px and you see the top-left corner of it. */
.mac-display img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
}
.mac-base {
  width: 100%; height: 13px; margin-top: -1px;
  border-radius: 0 0 14px 14px;
  background: linear-gradient(180deg, #3a3d43, #1a1c20 55%, #0b0c0f);
  box-shadow: 0 10px 30px rgba(0, 0, 0, .4);
  position: relative;
}
.mac-base::before {
  content: ""; position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  width: 15%; height: 5px; border-radius: 0 0 8px 8px; background: #0a0b0d;
}

/* ── Highlights rail (CSS scroll-snap) ───────────────────────────────────── */
.rail-wrap { background: var(--scene-tint); padding: clamp(48px, 8vh, 90px) 0 8px; }
.rail-head { text-align: center; margin-bottom: 26px; padding: 0 22px; }
.rail {
  display: grid; grid-auto-flow: column; grid-auto-columns: min(78vw, 380px);
  gap: 14px; overflow-x: auto; padding: 4px max(calc((100vw - 1180px) / 2), 20px) 22px;
  scroll-snap-type: x mandatory; scrollbar-width: none;
}
.rail::-webkit-scrollbar { display: none; }
.rail .hcard {
  scroll-snap-align: center; border-radius: 22px; padding: 26px 26px 30px;
  background: var(--scene-ink); border: 1px solid var(--scene-line);
  min-height: 190px; text-align: left;
}
.rail .hcard h3 { margin-bottom: 8px; color: var(--scene-txt); }
.rail .hcard h3 i { font-style: normal; margin-right: 8px; }
.rail .hcard p { font-size: 15px; color: var(--scene-dim); line-height: 1.5; }

/* ── Stat row (colored numerals, no boxes — apple nits-row style) ────────── */
.statrow {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 26px;
  max-width: 1020px; margin: 0 auto; padding: clamp(40px, 7vh, 80px) 22px 24px;
  text-align: center;
}
@media (max-width: 820px) { .statrow { grid-template-columns: repeat(2, 1fr); gap: 32px 18px; } }
.statrow b {
  display: block; font-size: clamp(28px, 3.4vw, 44px); font-weight: 600;
  letter-spacing: -.015em; font-variant-numeric: tabular-nums; line-height: 1.1;
}
.statrow .c1 b { color: var(--accent-text); } .statrow .c2 b { color: var(--blue); }
.statrow .c3 b { color: var(--green); } .statrow .c4 b { color: var(--violet); }
.statrow span { display: block; font-size: 14px; color: var(--scene-dim); margin-top: 6px; }
.statnote {
  text-align: center; font-size: 13px; color: var(--scene-dim);
  max-width: 640px; margin: 0 auto; padding: 0 22px 44px;
}

/* ── Hazard Engine (Three.js scene) ──────────────────────────────────────── */
.engine-track { position: relative; height: 450vh; height: 450svh; background: var(--scene-ink); }
.engine-stage {
  position: sticky; top: 0; height: 100vh; height: 100svh; overflow: clip;
  display: flex; flex-direction: column; justify-content: center;
  background: var(--scene-ink);
}
.engine-head {
  position: absolute; top: clamp(72px, 11svh, 132px); left: 0; right: 0; z-index: 3;
  text-align: center; padding: 0 22px;
}
.engine-head .h2 { color: var(--scene-txt); }
.engine-head .sub { color: var(--scene-dim); }
/* The scene renders edge to edge the whole time; a clip-path opens from a card
   to the full viewport as you scroll in. Clipping rather than resizing keeps
   the canvas at full resolution and never re-allocates the WebGL buffer. */
.engine-canvas-wrap {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, #070b12, #04060a);
  clip-path: inset(var(--ct, 0px) var(--cx, 0px) var(--cb, 0px) var(--cx, 0px)
                   round var(--crad, 0px));
}
/* keeps the captions and pills legible once they sit on top of the scene */
.engine-scrim {
  position: absolute; left: 0; right: 0; bottom: 0; height: 42svh; z-index: 2;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(4, 6, 10, 0), rgba(4, 6, 10, .82) 62%,
                              rgba(4, 6, 10, .94));
}
#hazardCanvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.engine-fallback { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.engine-captions {
  position: absolute; left: 0; right: 0; bottom: clamp(84px, 13svh, 150px);
  height: 58px; z-index: 3;
}
.engine-cap {
  position: absolute; left: 0; right: 0; text-align: center; padding: 0 22px;
  font-size: clamp(15px, 1.8vw, 19px); font-weight: 500; color: var(--scene-txt);
  opacity: 0;                                    /* scene furniture: JS-driven */
}
.engine-cap b { color: var(--accent-text); }
.engine-cap .r { color: var(--red); }
.engine-cap .g { color: #30d158; }        /* matches the scene's all-clear green */
.engine-cap:last-child { opacity: 1; }           /* T0 = final caption */
.engine-pills {
  display: flex; gap: 10px; justify-content: center; flex-wrap: wrap;
  padding: 0 22px; position: absolute; left: 0; right: 0;
  bottom: clamp(28px, 5svh, 60px); z-index: 3;
}
/* the pills wrap to three rows on a phone — give the caption room above them */
@media (max-width: 700px) {
  .engine-captions { bottom: 208px; height: 84px; }
  .engine-pills { bottom: 26px; gap: 8px; }
  .engine-scrim { height: 58svh; }
  .engine-head { top: clamp(84px, 13svh, 150px); }
}
.engine-pills .pill {
  border-radius: 999px; padding: 8px 16px; font-size: 13.5px; font-weight: 500;
  color: var(--scene-txt);
}

/* ── Shared scene plumbing ───────────────────────────────────────────────── */
.scene-track { position: relative; }
.scene-stage {
  position: sticky; top: 0; height: 100vh; height: 100svh; overflow: clip;
  display: flex; flex-direction: column; justify-content: center;
}
.scene-progress {
  position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: var(--scene-line);
}
.scene-progress i {
  display: block; height: 100%; background: var(--accent);
  transform: scaleX(0); transform-origin: 0 50%;
}

/* ── Day / night scene ───────────────────────────────────────────────────── */
.split-track { height: 280vh; height: 280svh; background: var(--scene-ink); }
/* the stage centres its contents, so without this the heading lands directly
   under the floating nav pill on a short window */
.split-stage { background: var(--scene-ink); padding-top: clamp(78px, 11svh, 132px); }
.split-head { text-align: center; padding: 0 22px; margin-bottom: clamp(14px, 3vh, 30px); }
.split-head .h2 { color: var(--scene-txt); }
/* An explicit, capped two-column grid: the old flex row let the caption drift
   to the far right edge on a wide monitor instead of staying beside the phone. */
.split-scene {
  display: grid; grid-template-columns: auto minmax(0, 340px);
  align-items: center; justify-content: center;
  gap: clamp(26px, 4vw, 72px);
  max-width: 1080px; margin: 0 auto; padding: 0 22px;
}
.split-scene .phone { --w: clamp(170px, min(24vw, calc((100svh - 300px) * .46)), 300px); }
.shot-light { opacity: 1; }
.split-scene .phone-glow { background-image: url(/assets/glow-light.webp); }
.capslot { position: relative; width: min(340px, 38vw); min-height: 200px; text-align: left; }
@media (max-width: 760px) {
  .split-scene { grid-template-columns: minmax(0, 1fr); justify-items: center; gap: 22px; }
  .capslot { width: min(420px, 88vw); min-height: 150px; }
}
.split-cap { position: absolute; inset: 0; }
.split-cap .tag {
  display: inline-block; font-size: 11px; font-weight: 600; letter-spacing: .12em;
  text-transform: uppercase; padding: 4px 10px; border-radius: 999px; margin-bottom: 12px;
}
.cap-dark .tag { background: rgba(80, 100, 220, .12); color: #3b4fc4; }
.cap-light .tag { background: var(--accent-soft); color: var(--accent-text); }
.split-cap h3 { color: var(--scene-txt); margin-bottom: 8px; }
.split-cap p { font-size: 15px; line-height: 1.55; color: var(--scene-dim); }
.split-alert {
  display: inline-flex; align-items: center; gap: 8px; margin-top: 14px;
  font-size: 12.5px; font-weight: 600; letter-spacing: .1em;
  color: var(--red); border: 1px solid rgba(217, 45, 45, .32); border-radius: 10px;
  padding: 7px 12px; background: rgba(217, 45, 45, .06);
}
.split-alert i { width: 7px; height: 7px; border-radius: 50%; background: var(--red);
  box-shadow: 0 0 8px var(--red); }
.cap-dark { opacity: 0; visibility: hidden; }
.cap-light { opacity: 1; }
.dawn {
  position: absolute; top: 0; bottom: 0; width: 14%; left: 100%;
  pointer-events: none; opacity: 0; z-index: 2;
  background: linear-gradient(90deg, transparent,
              rgba(255, 214, 140, .38) 45%, rgba(255, 240, 210, .55) 50%,
              rgba(255, 214, 140, .38) 55%, transparent);
  filter: blur(2px);
  transform: translateX(-50%);
}

/* ── Data explainer strip (chips + honest meter, dark) ───────────────────── */
.data-strip { background: var(--scene-ink); padding: 40px 0 64px; }
.srcrow { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center;
  max-width: var(--wrapW); margin: 0 auto; padding: 0 22px; }
.chip {
  font-size: 13.5px; color: var(--scene-dim); border: 1px solid var(--scene-line);
  border-radius: 999px; padding: 8px 15px;
}
.chip b { color: var(--accent-text); }
.honest {
  display: grid; grid-template-columns: 1.2fr 1fr; gap: clamp(20px, 4vw, 54px);
  align-items: center; margin: 30px auto 0; padding: 26px 30px;
  max-width: 940px; width: calc(100% - 44px);
  border: 1px solid var(--scene-line); border-radius: 20px; background: var(--scene-tint);
  text-align: left;
}
@media (max-width: 760px) { .honest { grid-template-columns: 1fr; } }
.honest h3 { color: var(--scene-txt); margin-bottom: 8px; }
.honest p { font-size: 15px; color: var(--scene-dim); }
.honest p b { color: var(--scene-txt); }
.meter .mtop { display: flex; justify-content: space-between; font-size: 13.5px;
  color: var(--scene-dim); margin-bottom: 8px; }
.meter .mtop b { color: var(--accent-text); font-size: 17px; }
.meter .bar { height: 10px; border-radius: 999px; background: var(--scene-fill-2); overflow: hidden; }
.meter .bar i { display: block; height: 100%; width: 41.7%; border-radius: 999px;
  background: linear-gradient(90deg, var(--accent-text), var(--accent)); }
.meter .msub { font-size: 12.5px; color: var(--scene-dim); margin-top: 8px;
  font-variant-numeric: tabular-nums; }

.aud { display: flex; gap: 9px; flex-wrap: wrap; padding: 0 0 22px; }
.aud span {
  font-size: 13.5px; font-weight: 500; color: var(--scene-dim);
  border: 1px solid var(--scene-line); border-radius: 999px; padding: 7px 14px;
}
@media (max-width: 560px) { .gallery { grid-template-columns: 1fr; } }
.g-tall { grid-row: span 2; }

/* ═══ T1 reveals — armed only by home.js (.rv-armed); cards/images only ═══ */
.rv-armed .rv { opacity: 0; translate: 0 18px;
  transition: opacity .65s cubic-bezier(.16, 1, .3, 1), translate .65s cubic-bezier(.16, 1, .3, 1);
  transition-delay: calc(var(--i, 0) * 70ms); }
.rv-armed .rv.in { opacity: 1; translate: 0 0; }
@media (prefers-reduced-motion: reduce) {
  .rv-armed .rv { opacity: 1; translate: none; transition: none; }
}


/* ═══ "Take a closer look." — feature explorer ════════════════════════════
   Pills on the left, the matching screen on the right. Replaces the old
   carousel: one screen at a time, chosen, instead of six scrolling past.
   T0 (no JS) = first feature open with its shot showing — a finished state. */
.closer { background: var(--scene-tint); padding: clamp(52px, 9vh, 100px) 0 clamp(20px, 4vh, 40px); }
.closer-inner { max-width: 1180px; margin: 0 auto; padding: 0 24px; }
.closer-inner .h2 { color: var(--scene-txt); margin-bottom: 22px; }
.closer-card {
  display: grid; grid-template-columns: minmax(280px, 38%) 1fr; gap: clamp(20px, 4vw, 56px);
  align-items: center; background: var(--scene-ink);
  border-radius: 30px; padding: clamp(26px, 4.4vw, 56px);
  border: 1px solid var(--scene-line);
}
.closer-list { display: flex; flex-direction: column; gap: 10px; align-items: flex-start; }
/* The capsule lives on the BUTTON, not the item: sizing the item to max-content
   made every pill the width of its longest hidden paragraph, so they all came
   out identical instead of hugging their labels. */
.cl-item { width: 100%; border-radius: 22px; transition: background .3s ease; }
.cl-item.on { background: var(--scene-fill); }
.cl-pill {
  display: flex; align-items: center; gap: 11px;
  width: max-content; max-width: 100%;
  background: var(--scene-fill); border: 0; border-radius: 22px;
  cursor: pointer; padding: 12px 18px;
  color: var(--scene-txt); font-family: var(--sf);
  font-size: clamp(15px, 1.6vw, 17px); font-weight: 600; text-align: left;
  transition: background .3s ease;
}
.cl-pill:hover { background: var(--scene-fill-2); }
.cl-item.on .cl-pill { width: 100%; background: transparent; }
.cl-ico {
  position: relative; flex: none; width: 21px; height: 21px; border-radius: 50%;
  border: 1px solid rgba(0, 0, 0, .28);
}
.cl-ico::before, .cl-ico::after { content: ''; position: absolute; background: currentColor; }
.cl-ico::before { left: 5px; right: 5px; top: 9.5px; height: 1.6px; border-radius: 2px; }
.cl-ico::after {
  top: 5px; bottom: 5px; left: 9.5px; width: 1.6px; border-radius: 2px;
  transition: transform .32s cubic-bezier(.3, 0, .2, 1);
}
.cl-item.on .cl-ico { border-color: var(--accent-text); color: var(--accent-text); }
.cl-item.on .cl-ico::after { transform: scaleY(0); }   /* plus becomes minus */
/* 0fr→1fr animates to the panel's natural height without hardcoding one */
.cl-panel {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows .44s cubic-bezier(.3, 0, .2, 1);
}
.cl-panel > div { overflow: hidden; }
.cl-item.on .cl-panel { grid-template-rows: 1fr; }
.cl-panel p {
  margin: 0; padding: 0 18px 4px 50px; color: var(--scene-dim);
  font-size: clamp(14px, 1.45vw, 15.5px); line-height: 1.5;
}
.cl-more {
  display: inline-block; margin: 10px 0 14px 50px; font-size: 14px; font-weight: 600;
  color: var(--accent-text); text-decoration: none;
}
.cl-more:hover { text-decoration: underline; }

.closer-media { position: relative; height: clamp(400px, 70svh, 720px); }
.cl-shot {
  position: absolute; inset: 0; margin: auto; height: 100%; width: auto;
  max-width: 100%; object-fit: contain; border-radius: 22px;
  opacity: 0; transform: scale(.965);
  transition: opacity .45s ease, transform .6s cubic-bezier(.3, 0, .2, 1);
  box-shadow: 0 30px 70px rgba(0, 0, 0, .20);
}
.cl-shot.on { opacity: 1; transform: scale(1); }

/* desktop keeps the copy inline in the accordion */
.cl-mobile-copy { display: none; }

/* ── Mobile: the screenshot and the picker have to be on screen together ────
   Stacking the accordion under the image meant selecting a feature scrolled
   the image out of view. Image on top, copy in the middle, pills as a
   horizontal rail along the bottom — the way Apple handles this on a phone. */
@media (max-width: 860px) {
  .closer-inner { padding: 0 16px; }
  .closer-card {
    grid-template-columns: 1fr; gap: 14px;
    padding: 20px 0 16px; align-items: stretch;
  }
  .closer-media { order: 1; height: clamp(260px, 40svh, 400px); margin: 0 12px; }
  .cl-mobile-copy {
    order: 2; display: block; margin: 0 20px; min-height: 4.6em;
    font-size: 14.5px; line-height: 1.5; color: var(--scene-dim); text-align: left;
  }
  .cl-mobile-copy p { margin: 0; }
  .cl-mobile-copy a {
    display: inline-block; margin-top: 8px; color: var(--accent-text);
    font-weight: 600; font-size: 14px; text-decoration: none;
  }
  .closer-list {
    order: 3; flex-direction: row; flex-wrap: nowrap; align-items: center;
    gap: 10px; overflow-x: auto; scrollbar-width: none;
    scroll-snap-type: x proximity; padding: 2px 20px 4px;
    -webkit-overflow-scrolling: touch;
  }
  .closer-list::-webkit-scrollbar { display: none; }
  .cl-item { flex: 0 0 auto; width: auto; background: none; scroll-snap-align: center; }
  .cl-item.on { background: none; }
  .cl-pill, .cl-item.on .cl-pill {
    width: max-content; white-space: nowrap; padding: 11px 16px;
    background: var(--scene-fill);
  }
  .cl-item.on .cl-pill { background: var(--scene-fill-2); }
  .cl-panel { display: none; }          /* the copy lives in .cl-mobile-copy */
}
@media (prefers-reduced-motion: reduce) {
  .cl-panel, .cl-shot, .cl-ico::after { transition: none; }
}

/* the engine scene names the thing that powers it */
.r2-badge { display: inline-flex; align-items: center; gap: 8px; }
.r2-badge img { border-radius: 5px; display: block; }
.r2-badge b { color: var(--accent); font-weight: 600; }

/* ── Engine sign-off: the R2 mark takes the screen, then scrolls away ─────── */
.engine-signoff {
  position: absolute; inset: 0; z-index: 6;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(16px, 2.6vh, 30px); padding: 0 22px; text-align: center;
  /* lighter in the middle so the aircraft you just flew stays visible behind
     the mark it is nested in; opaque at the edges to kill the terrain */
  background: radial-gradient(56% 56% at 50% 40%, rgba(4, 6, 10, .66), rgba(4, 6, 10, .97));
}
.so-chip {
  width: clamp(150px, 29svh, 300px); height: auto; display: block;
  transform-origin: 50% 55%; overflow: visible;
}
.so-chip text { font-family: var(--sf); }
/* T0 = fully powered up, the finished frame. JS winds it back to dark. */
.so-chip .c-leg, .so-chip .c-trace, .so-chip .c-die,
.so-chip .c-pin1, .so-chip .c-txt { opacity: 1; }
.so-chip .c-body { stroke-dasharray: 1; stroke-dashoffset: 0; }
.so-chip .c-trace { stroke-dasharray: 1; stroke-dashoffset: 0; }
.so-line {
  font-size: clamp(16px, 2.1vw, 23px); font-weight: 500; color: var(--scene-dim);
  letter-spacing: -.01em;
}
.so-line b { color: var(--scene-txt); font-weight: 600; }
.so-more {
  border-radius: 999px; padding: 9px 18px; font-size: 14px; font-weight: 600;
  color: var(--accent); text-decoration: none; margin-top: 4px;
}
/* ── "The chip is running" ────────────────────────────────────────────────
   Once the mark has finished assembling, current runs continuously from the
   outside in: down every leg, along the corner traces, into the die, with a
   highlight lapping the package. Dormant until .running so it never competes
   with the assembly animation. */
.so-chip .c-flow path { opacity: 0; }
.engine-signoff.running .so-chip .c-cur {
  opacity: 1; stroke: #FFD8A2;
  /* pathLength=12 on every path, so one dash-cycle spans each one exactly,
     whatever its real length — legs and traces animate off the same keyframe */
  stroke-dasharray: 3 9;
  animation: r2Cur 1.45s linear infinite;
  animation-delay: calc(var(--i) * -0.085s);   /* negative: already in flight */
}
@keyframes r2Cur { from { stroke-dashoffset: 12; } to { stroke-dashoffset: 0; } }

.engine-signoff.running .so-chip .c-ring {
  opacity: .95; stroke: #FFE3B8;
  stroke-dasharray: .1 .9;
  animation: r2Ring 2.6s linear infinite;
}
@keyframes r2Ring { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }

/* the die answers each arrival with a pulse */
.engine-signoff.running .so-chip .c-die {
  animation: r2Die 1.45s ease-in-out infinite;
}
@keyframes r2Die {
  0%, 62%, 100% { stroke: #FF8A3D; }
  80%           { stroke: #FFE3B8; }
}

@media (prefers-reduced-motion: reduce) {
  .so-chip { transform: none !important; }
  .engine-signoff.running .so-chip .c-cur,
  .engine-signoff.running .so-chip .c-ring,
  .engine-signoff.running .so-chip .c-die { animation: none; }
  .engine-signoff.running .so-chip .c-cur { opacity: 0; }
}

/* keep-scrolling cue: a trace running out of the chip, with a pulse down it */
.so-scroll {
  position: relative; display: block; width: 1.5px;
  height: clamp(46px, 7.5svh, 82px); margin-top: clamp(6px, 1.4vh, 16px);
  border-radius: 2px; overflow: hidden;
  background: linear-gradient(rgba(245, 165, 36, .5), rgba(245, 165, 36, .04));
}
.so-scroll i {
  position: absolute; left: 0; width: 100%; height: 34%; border-radius: 2px;
  background: linear-gradient(rgba(255, 196, 107, 0), #FFC46B, rgba(255, 196, 107, 0));
  animation: soFlow 2.1s cubic-bezier(.45, 0, .55, 1) infinite;
}
@keyframes soFlow {
  0%   { top: -40%; opacity: 0; }
  18%  { opacity: 1; }
  72%  { opacity: 1; }
  100% { top: 106%; opacity: 0; }
}
@media (prefers-reduced-motion: reduce) { .so-scroll i { display: none; } }

/* ═══ How the warning reaches you — the Island, and the sound off it ═══════
   Apple's MacBook audio section: product held still, concentric waves pushed
   out of it by scroll, copy in two columns above. T0 = the alert state with
   the waves out, i.e. the finished frame. */
.isl-track { height: 165vh; height: 165svh; background: var(--scene-ink); }
.isl-stage {
  background: var(--scene-ink); justify-content: center;
  padding-top: clamp(108px, 15svh, 168px);   /* clears the floating nav pill */
}
.isl-heads {
  display: grid; grid-template-columns: 1fr 1fr; gap: clamp(24px, 5vw, 72px);
  max-width: 1080px; margin: 0 auto clamp(20px, 5vh, 56px); padding: 0 24px;
}
.isl-col {
  font-size: clamp(15px, 1.75vw, 19px); line-height: 1.45; color: var(--scene-dim);
}
.isl-col b { color: var(--scene-txt); font-weight: 600; }
/* clipped, so the waves stay in their own field and never cross the copy */
.isl-scene {
  position: relative; display: grid; place-items: center; overflow: hidden;
  height: clamp(260px, 40svh, 430px); width: 100%;
}
.isl-pillwrap {
  position: relative; z-index: 2; width: min(520px, 78vw); aspect-ratio: 720 / 268;
}
.isl-pill {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain;
  border-radius: 22px;
}
.isl-quiet { opacity: 0; }        /* T0 = the alert, the frame that matters */
.isl-alert { opacity: 1; }
/* the waves: pill-shaped, pushed outward from the widget */
.isl-rings { position: absolute; inset: 0; display: grid; place-items: center; z-index: 1; }
/* Base narrower than the widget so a wave starts inside it and grows out. It
   also has to stay narrower than the viewport at full scale, or the rounded
   ends land off-screen and the "ring" reads as two straight lines. */
.isl-rings i {
  position: absolute; width: min(300px, 46vw); aspect-ratio: 720 / 268;
  border: 1.5px solid rgba(245, 165, 36, .5); border-radius: 999px;
  opacity: 0; transform: scale(1);
}
@media (max-width: 760px) {
  .isl-heads { grid-template-columns: 1fr; gap: 14px; }
  .isl-track { height: 150vh; height: 150svh; }
}

/* a video pane sits in the same frame as the stills */
/* The video panes are dark app footage; a matching dark plate behind them
   stops a white flash in the frame before the first decoded frame lands. */
.closer-media video.cl-shot { background: #0b0d12; }
