/* ============================================================================
   Hermoso — marketing design system · v16 "Night Premiere"
   CINEMATIC DARK. A film-studio register: warm near-black canvas, enormous
   Fraunces display type, electric coral used like neon signage, full-bleed
   video, grain + glow atmosphere. The bloom mark is treated like a studio
   ident. Every behavioral class/id from site.v17.js is preserved (.reveal,
   .nav-toggle, .mobile-menu, .qa, .cinema-strip/.strip-track, .cookie-consent,
   video[data-auto|data-hover]) so the shared JS keeps working untouched.
   ========================================================================== */

/* Self-hosted faces — identical to site.v15.css, which every other page on the
   site already uses. The homepage used to pull Newsreader + Hanken from
   fonts.googleapis.com, which our own CSP (`style-src 'self'`, `font-src 'self'`)
   blocks, so it rendered in Times/Helvetica. Paths are relative to THIS
   stylesheet (/assets/), so they resolve for the root page and every /<lang>/
   homepage alike. Display serif is Fraunces site-wide. */
@font-face{
  font-family:'Fraunces'; font-style:normal; font-weight:400 600; font-display:swap;
  src:url('fonts/fraunces-latin.woff2') format('woff2');
}
@font-face{
  font-family:'Fraunces'; font-style:italic; font-weight:400 500; font-display:swap;
  src:url('fonts/fraunces-italic-latin.woff2') format('woff2');
}
@font-face{
  font-family:'Hanken Grotesk'; font-style:normal; font-weight:400 700; font-display:swap;
  src:url('fonts/hanken-latin.woff2') format('woff2');
}
@font-face{
  font-family:'Fraunces Fallback';
  src:local('Georgia');
  ascent-override:97.8%; descent-override:25.5%; line-gap-override:0%; size-adjust:107%;
}

:root{
  /* v17 "GALLERY" (2026-08-04, ref = Apple España): the page is a FRAME, the ads are the picture.
     Near-white canvas alternating white / #f5f4f1 in bands, ink headlines, enormous negative space,
     BORDERLESS components at 28px radii and ZERO shadow — hierarchy comes from the band alternation,
     not from boxes. THE LOAD-BEARING RULE: colour appears in the product imagery itself (the channel
     marks, the reel, the format loops) and NEVER as UI decoration; coral is reserved exclusively for
     interactive moments — buttons, links, focus. That is also Dave's own standing note in
     [[cta-green-not-coral]]: "coral belongs to the logo and shouldn't be sprinkled through the UI."
     Every v16/v17 selector is kept so the shared site.v17.js stays untouched.
     (Superseded: v17 "Daylight Editorial", warm paper + bordered cards + soft shadows.) */
  --bg:        #ffffff;   /* paper — the default band */
  --bg-2:      #f5f4f1;   /* canvas — the alternating band (our warm twin of Apple's #f5f5f7) */
  --surface:   #ffffff;   /* card — borderless, so it reads only against a canvas band */
  --surface-2: #f5f4f1;   /* card hover / inset */
  --surface-3: #eceae5;   /* chips */

  /* hairlines — ink at low alpha. Used between SECTIONS as a rare exception, never around cards. */
  --line:      rgba(24,21,15,.10);
  --line-2:    rgba(24,21,15,.16);
  --hair:      rgba(24,21,15,.06);

  /* near-black editorial ink (our warm twin of Apple's #1d1d1f) */
  /* MEASURED, never eyeballed ([[cta-green-not-coral]]). Ratios are against the worst background each token
     actually lands on: paper #ffffff / canvas #f5f4f1 / chip #eceae5.
       --text  17.7 / 16.1 / 14.7    --muted 7.8 / 7.1 / 6.5    --faint 5.5 / 5.0 / 4.5   — all AA at any size. */
  --text:   #1a1814;
  --muted:  #55524b;
  --faint:  #6e6960;   /* was #8a847a (3.5:1) then #79746b (3.9:1 on a chip) — both failed AA on small text */

  /* CORAL — now the ONLY colour on the page, and only on interactive moments. The ladder was re-measured on
     2026-08-04 and the fill moved DOWN a step because white ink on the old #D5503F measured 4.16:1 and on the
     old hover #E36A5A 3.24:1 — both under AA for a 15px button label, and both had shipped for months.
     #B23A2C is also exactly the app's settled light-mode `--cta` ([[cta-green-not-coral]]), so the site and
     the product now agree on the colour instead of drifting apart.
       white on --coral-solid 5.94:1 · on --coral-hot 4.88:1 · on --coral-deep 7.15:1
       --coral as link text 5.37:1 on paper, 4.88:1 on canvas                          — all AA. */
  --coral:       #C13A2E;   /* accent text / links */
  --coral-solid: #B23A2C;   /* primary fill */
  --coral-deep:  #9E3226;   /* pressed */
  --coral-hot:   #C9422F;   /* hover (fill AND text) */
  --plum:        #8a5772;
  --gold:        #b98a3e;
  --cream:       #ffffff;   /* ink on coral fills */

  --glow:   rgba(213,80,63,.10);   /* near-invisible now — no neon on light */
  --glow-2: rgba(138,87,114,.06);

  --display: 'Fraunces', 'Fraunces Fallback', Georgia, 'Times New Roman', serif;
  --body:    'Hanken Grotesk', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --mono:    ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace;

  --r-sm: 12px;
  --r:    18px;
  --r-lg: 28px;   /* the gallery radius — cards, media, product frames */
  --r-xl: 28px;
  --pill: 999px;

  /* ZERO shadow. The tokens survive because ~30 rules name them; they now resolve to nothing, so a
     rule we miss cannot quietly re-introduce elevation. Depth is band alternation + radius, only. */
  --el-1: none;
  --el-2: none;
  --el-glow: none;

  --maxw: 1200px;
  --t: 240ms cubic-bezier(.2,.7,.2,1);
  --t-slow: 700ms cubic-bezier(.19,1,.22,1);
  --ease-hero: cubic-bezier(.19,1,.22,1);
}

*,*::before,*::after{ box-sizing:border-box; margin:0; padding:0; }
html{ -webkit-text-size-adjust:100%; scroll-padding-top:92px; background:var(--bg); }
body{
  background:var(--bg);
  color:var(--text);
  font-family:var(--body);
  font-size:17px;
  line-height:1.62;
  letter-spacing:-.004em;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  overflow-x:hidden;
}
img,svg,video{ display:block; max-width:100%; }
a{ color:inherit; text-decoration:none; }
button{ font:inherit; color:inherit; cursor:pointer; background:none; border:none; }
:focus-visible{ outline:2px solid var(--coral); outline-offset:3px; border-radius:6px; }
::selection{ background:rgba(213,80,63,.16); color:var(--text); }
.skip{ position:absolute; left:-9999px; top:0; z-index:300; background:var(--coral-solid); color:var(--cream); padding:10px 16px; border-radius:0 0 10px 0; font-weight:600; }
.skip:focus{ left:0; }

/* ── atmosphere: projector grain + ember glow, fixed behind everything ────── */
body::before{ /* film grain */
  content:""; position:fixed; inset:0; z-index:0; pointer-events:none; opacity:.055; mix-blend-mode:screen;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
}
body::after{ /* light: the ember pool is gone — just a barely-there warm paper vignette at the very bottom */
  content:""; position:fixed; inset:0; z-index:0; pointer-events:none;
  background: radial-gradient(60% 42% at 50% 110%, rgba(213,80,63,.045), transparent 66%);
  opacity:.7;
}
.page{ position:relative; z-index:1; }
.wrap{ max-width:var(--maxw); margin:0 auto; padding:0 clamp(18px,4vw,40px); }

/* ── type ─────────────────────────────────────────────────────────────────── */
h1,h2,h3,.tt{ font-family:var(--display); font-weight:500; letter-spacing:-.015em; line-height:1.04; text-wrap:balance; }
h1{ font-size:clamp(2.9rem, 8.2vw, 7.2rem); font-optical-sizing:auto; }
h2,.tt{ font-size:clamp(1.9rem, 4.2vw, 3.4rem); line-height:1.08; }
h2 i,.tt i,h1 em{ font-style:italic; font-weight:400; color:var(--coral); }
h1 em.key{ font-style:italic; font-weight:400;
  background:linear-gradient(100deg, var(--coral-hot), var(--coral) 55%, var(--gold));
  -webkit-background-clip:text; background-clip:text; color:transparent;
}
p{ color:var(--muted); max-width:58ch; }
.lead{ font-size:clamp(1.05rem, 1.6vw, 1.3rem); line-height:1.55; color:var(--muted); }
.mono{ font-family:var(--mono); font-size:.72rem; letter-spacing:.22em; text-transform:uppercase; color:var(--faint); display:inline-flex; align-items:center; gap:10px; }
.mono .dot{ width:6px; height:6px; border-radius:50%; background:var(--coral); box-shadow:0 0 12px 2px var(--glow); flex:none; animation:pulse 2.6s ease-in-out infinite; }
@keyframes pulse{ 0%,100%{ opacity:1 } 50%{ opacity:.35 } }
.eyebrow{ font-family:var(--mono); font-size:.72rem; letter-spacing:.22em; text-transform:uppercase; color:var(--coral); }
.eyebrow.center{ display:block; text-align:center; }

/* ── buttons ─────────────────────────────────────────────────────────────── */
.btn{ display:inline-flex; align-items:center; justify-content:center; gap:9px;
  padding:12px 22px; border-radius:var(--pill); font-weight:600; font-size:.95rem;
  line-height:1; white-space:nowrap; transition:transform var(--t), background var(--t), box-shadow var(--t), border-color var(--t); }
.btn-lg{ padding:16px 30px; font-size:1.05rem; }
.btn-primary{ background:var(--coral-solid); color:var(--cream);
  box-shadow:0 6px 18px -8px rgba(213,80,63,.42); }
.btn-primary:hover{ background:var(--coral-hot); transform:translateY(-1px);
  box-shadow:0 10px 26px -8px rgba(213,80,63,.46); }
.btn-primary:active{ background:var(--coral-deep); transform:none; }
.btn-ghost{ border:1px solid var(--line-2); color:var(--text); background:#ffffff; }
.btn-ghost:hover{ border-color:rgba(213,80,63,.5); color:var(--coral-hot); transform:translateY(-1px); }
.btn .arr{ transition:transform var(--t); }
.btn:hover .arr{ transform:translateX(3px); }
.btn:focus-visible{ outline:2px solid var(--coral-hot); outline-offset:3px; }

/* ── nav — dark glass over the stage ─────────────────────────────────────── */
.nav{ position:sticky; top:0; z-index:100; transition:background var(--t), border-color var(--t); border-bottom:1px solid transparent; }
.nav.scrolled{ background:rgba(250,249,247,.82); -webkit-backdrop-filter:blur(14px) saturate(1.2); backdrop-filter:blur(14px) saturate(1.2); border-bottom-color:var(--line); }
.nav-in{ display:flex; align-items:center; gap:28px; height:72px; }
.brand{ display:inline-flex; align-items:center; gap:10px; font-family:var(--display); font-size:1.35rem; letter-spacing:-.02em; }
.brand b{ font-weight:500; }
.bloom{ width:26px; height:26px; filter:drop-shadow(0 0 10px var(--glow)); }
.nav-links{ display:flex; gap:26px; margin-left:auto; }
.nav-links a{ font-size:.92rem; color:var(--muted); transition:color var(--t); position:relative; }
.nav-links a:hover{ color:var(--text); }
.nav-links a::after{ content:""; position:absolute; left:0; right:100%; bottom:-6px; height:1px; background:var(--coral); transition:right var(--t); }
.nav-links a:hover::after{ right:0; }
.nav-cta{ display:flex; gap:10px; }
.nav-cta .btn{ padding:10px 18px; font-size:.88rem; }

.nav-toggle{ display:none; width:44px; height:44px; position:relative; margin-left:auto; }
.nav-toggle span, .nav-toggle::before, .nav-toggle::after{
  content:""; position:absolute; left:11px; right:11px; height:2px; border-radius:2px; background:var(--text);
  transition:transform var(--t), opacity var(--t), top var(--t); }
.nav-toggle::before{ top:15px; } .nav-toggle span{ top:21px; display:block; } .nav-toggle::after{ top:27px; }
.nav-toggle.open::before{ top:21px; transform:rotate(45deg); }
.nav-toggle.open span{ opacity:0; }
.nav-toggle.open::after{ top:21px; transform:rotate(-45deg); }

.mobile-menu{ display:none; }
body.menu-open{ overflow:hidden; }

/* ── HERO — the premiere stage ───────────────────────────────────────────── */
.hero{ position:relative; min-height:min(100svh, 1040px); display:flex; flex-direction:column; justify-content:center;
  padding:clamp(84px,10vh,150px) 0 clamp(40px,6vh,80px); overflow:clip; }

/* full-bleed montage behind the headline (slot; poster carries it until the
   montage asset exists). Scrimmed hard so type always wins. */
.hero-stage{ position:absolute; inset:0; z-index:-2; }
.hero-stage video, .hero-stage img{ width:100%; height:100%; object-fit:cover; opacity:.14; } /* light: montage recedes to a faint texture behind the type */
.hero-stage::after{ content:""; position:absolute; inset:0; /* light scrims fade the montage into the paper so the type always wins */
  background:
    radial-gradient(90% 70% at 50% 42%, transparent 34%, rgba(250,249,247,.92) 82%),
    linear-gradient(180deg, rgba(250,249,247,.72), rgba(250,249,247,.36) 34%, rgba(250,249,247,.97) 88%);
}
.hero-stage::before{ content:""; position:absolute; inset:0; z-index:1;
  background:radial-gradient(42% 34% at 50% 4%, rgba(24,21,15,.03), transparent 70%); }

/* studio-ident bloom: rises + glows once, like a production card */
.ident{ display:flex; flex-direction:column; align-items:center; gap:18px; text-align:center; }
.ident .bloom{ width:52px; height:52px; }
.ident-line{ font-family:var(--mono); font-size:.7rem; letter-spacing:.34em; text-transform:uppercase; color:var(--faint); }
.ident-line b{ color:var(--muted); font-weight:500; }

.hero .wrap{ display:flex; flex-direction:column; align-items:center; text-align:center; gap:26px; }
/* Overflow guard for the centered flex column. MUST stay above the per-element measures below: it has the
   same specificity as `.hero .lead`, so when it sat further down the file it overrode every measure in the
   hero and the copy ran the full width of the column, straight under the floating cards. */
.hero .wrap > *{ max-width:100%; }
.hero h1{ max-width:14ch; }
.hero .lead{ max-width:560px; margin:0 auto; }
.hero-cta{ display:flex; gap:14px; flex-wrap:wrap; justify-content:center; }
.hero-note{ font-size:.85rem; color:var(--faint); }

/* floating finished-ad cards — the proof, in the frame with the promise */
.hero-float{ position:absolute; z-index:2; width:clamp(130px, 15vw, 216px); aspect-ratio:9/16;
  border-radius:var(--r-lg); overflow:hidden; border:1px solid var(--line-2);
  box-shadow:var(--el-2), 0 0 60px -18px var(--glow); background:var(--surface); }
.hero-float video, .hero-float img{ width:100%; height:100%; object-fit:cover; }
/* The floats flank the hero — they must never sit ON the copy. Measured at 1428px they covered 154-316px and
   1115-1274px of the lead paragraph: "Hermoso is" and "the campaigns" were unreadable behind a phone mockup.
   Two changes keep them clear at every width: the copy gets a real measure (below), and the cards drop to the
   CTA band, which is narrow, instead of straddling the full-width paragraph. */
.hf-l{ left:clamp(8px,4vw,72px); top:34%; transform:rotate(-5deg); animation:float-l 9s ease-in-out infinite; }
.hf-r{ right:clamp(8px,4vw,72px); top:36%; transform:rotate(4.5deg); animation:float-r 11s ease-in-out infinite; }
@keyframes float-l{ 0%,100%{ transform:rotate(-5deg) translateY(0) } 50%{ transform:rotate(-5deg) translateY(-14px) } }
@keyframes float-r{ 0%,100%{ transform:rotate(4.5deg) translateY(0) } 50%{ transform:rotate(4.5deg) translateY(-18px) } }
.rc-brand{ position:absolute; left:10px; bottom:10px; z-index:2; font-family:var(--mono); font-size:.62rem; letter-spacing:.14em;
  text-transform:uppercase; color:var(--text); background:rgba(255,255,255,.74); -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
  padding:5px 9px; border-radius:7px; }

/* entrance choreography (guarded below for reduced-motion) */
.rise{ opacity:0; transform:translateY(26px); animation:rise 1s var(--ease-hero) forwards; }
.rise.d1{ animation-delay:.12s } .rise.d2{ animation-delay:.26s } .rise.d3{ animation-delay:.42s } .rise.d4{ animation-delay:.58s }
@keyframes rise{ to{ opacity:1; transform:none } }
.ident .bloom{ opacity:0; transform:scale(.6) rotate(-30deg); animation:ident 1.3s var(--ease-hero) forwards; }
@keyframes ident{ 60%{ filter:drop-shadow(0 0 26px var(--glow)); } to{ opacity:1; transform:none; filter:drop-shadow(0 0 12px var(--glow)); } }

/* model ticker — a marquee of the engine room, CSS-only */
.ticker{ position:relative; margin-top:clamp(34px,6vh,64px); border-top:1px solid var(--hair); border-bottom:1px solid var(--hair);
  overflow:hidden; -webkit-mask-image:linear-gradient(90deg,transparent,#000 12%,#000 88%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 12%,#000 88%,transparent); }
.ticker-track{ display:flex; width:max-content; animation:tick 46s linear infinite; }
.ticker:hover .ticker-track{ animation-play-state:paused; }
.ticker-set{ display:flex; align-items:center; gap:44px; padding:14px 22px; flex:none; }
.ticker-set span{ font-family:var(--mono); font-size:.7rem; letter-spacing:.24em; text-transform:uppercase; color:var(--faint); white-space:nowrap; }
.ticker-set span b{ color:var(--coral); font-weight:500; }
@keyframes tick{ to{ transform:translateX(-50%) } }

/* ── sections ────────────────────────────────────────────────────────────── */
.section{ padding:clamp(72px,10vw,140px) 0; scroll-margin-top:84px; }
.section.tight{ padding:clamp(56px,7vw,96px) 0; }
.sec-head{ max-width:760px; }
.sec-head.center{ margin:0 auto; text-align:center; }
.sec-head.center p{ margin:18px auto 0; }
.sec-head p{ margin-top:18px; }

/* slate — film-slate section marker */
.slate{ display:flex; align-items:baseline; gap:16px; font-family:var(--mono); font-size:.72rem; letter-spacing:.22em; text-transform:uppercase; color:var(--faint); }
.slate::before{ content:""; width:34px; height:1px; background:var(--coral); align-self:center; box-shadow:0 0 10px var(--glow); }

/* scroll reveals (driven by site.v17.js → .reveal.in) */
.reveal{ opacity:0; transform:translateY(30px); transition:opacity .9s var(--ease-hero), transform .9s var(--ease-hero); }
.reveal.in{ opacity:1; transform:none; }
.reveal.d1{ transition-delay:.1s } .reveal.d2{ transition-delay:.2s } .reveal.d3{ transition-delay:.3s }

/* ── CINEMA STRIP — the AI-ad era reel ───────────────────────────────────── */
.cinema{ padding:clamp(72px,9vw,120px) 0; background:var(--bg-2); border-top:1px solid var(--hair); border-bottom:1px solid var(--hair);
  overflow:clip; scroll-margin-top:84px; }
.cinema .tt{ margin-top:14px; max-width:20ch; }
.cinema-strip{ display:flex; gap:18px; margin-top:44px; padding:6px clamp(18px,4vw,40px) 26px; overflow-x:auto; scrollbar-width:none; cursor:grab;
  overscroll-behavior-x:contain; -webkit-overflow-scrolling:touch;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 3%,#000 97%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 3%,#000 97%,transparent); }
.cinema-strip::-webkit-scrollbar{ display:none; }
.cinema-strip.dragging{ cursor:grabbing; }
.cinema-strip.dragging .reel-card{ pointer-events:none; }
/* auto-marquee (ported from v15: site.v17.js wraps the cards in a doubled .strip-track;
   falls back to the manual scroll above without JS / under reduced-motion) */
.cinema-strip.marquee{ display:block; overflow:hidden; }
.strip-track{ display:flex; gap:18px; width:max-content; animation:stripDrift 80s linear infinite; }
.strip-set{ display:flex; gap:18px; flex:none; }
.cinema-strip.marquee:hover .strip-track{ animation-play-state:paused; }
@keyframes stripDrift{ to{ transform:translateX(-50%); } }
.reel-card{ position:relative; flex:none; height:clamp(200px,26vw,300px); border-radius:var(--r); overflow:hidden;
  background:var(--surface); border:1px solid var(--line); box-shadow:var(--el-1); transition:transform var(--t), border-color var(--t), box-shadow var(--t); }
.reel-card:hover{ transform:translateY(-5px); border-color:rgba(213,80,63,.4); box-shadow:var(--el-glow); }
.reel-card video, .reel-card img{ height:100%; width:auto; object-fit:cover; }
.reel-card.w{ aspect-ratio:16/9; } .reel-card.s{ aspect-ratio:1; } .reel-card.v{ aspect-ratio:9/16; }
.reel-card video{ width:100%; }

/* ── THREE MOVES — Spy / Studio / Ship ───────────────────────────────────── */
.move{ display:grid; grid-template-columns:minmax(0,5fr) minmax(0,6fr); gap:clamp(30px,6vw,84px); align-items:center;
  padding:clamp(44px,6vw,84px) 0; position:relative; }
.move + .move{ border-top:1px solid var(--hair); }
.move.flip .move-txt{ order:2; } .move.flip .move-media{ order:1; }
/* removed the giant faint outlined move numbers — redundant with the "ACT 0N" eyebrow + extra fanciness (Dave 2026-07-23) */
.move-idx{ display:none; }
.move-txt{ position:relative; z-index:1; }
.move-txt h2{ margin:14px 0 16px; }
.move-link{ display:inline-flex; align-items:center; gap:8px; margin-top:20px; font-weight:600; color:var(--coral); }
.move-link .arr{ transition:transform var(--t); }
.move-link:hover .arr{ transform:translateX(4px); }
.move-link:hover{ color:var(--coral-hot); }

.ui-frame{ border-radius:var(--r-lg); overflow:hidden; background:var(--surface); border:1px solid var(--line-2); box-shadow:var(--el-2); }
.ui-bar{ display:flex; gap:6px; padding:11px 14px; border-bottom:1px solid var(--line); background:var(--surface-2); }
.ui-bar i{ width:9px; height:9px; border-radius:50%; background:var(--surface-3); }
.ui-bar i:first-child{ background:rgba(213,80,63,.7); }
.ui-frame img, .ui-frame video{ width:100%; height:auto; }
.move-media{ position:relative; }
.move-media:hover .ui-frame{ border-color:rgba(213,80,63,.35); box-shadow:var(--el-glow); }
.media-cap{ margin-top:14px; text-align:center; display:block; }

/* ── LIVE agent demo (hooks consumed by site.v17.js) ─────────────────────── */
.agentdemo{ display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:26px; align-items:stretch; }
.ad-log{ background:var(--surface); border:1px solid var(--line); border-radius:var(--r-lg); padding:22px;
  font-family:var(--mono); font-size:.8rem; line-height:1.9; color:var(--muted); min-height:300px; box-shadow:var(--el-1); }
.ad-log b, .ad-log .hl{ color:var(--coral); font-weight:500; }
.ad-out{ display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:14px; align-content:center; }
.ad-out .th{ border-radius:var(--r); overflow:hidden; aspect-ratio:9/16; border:1px solid var(--line-2); box-shadow:var(--el-1);
  transition:transform var(--t), box-shadow var(--t); background:var(--surface); }
.ad-out .th:hover{ transform:translateY(-4px) scale(1.02); box-shadow:var(--el-glow); }
.ad-out .th img{ width:100%; height:100%; object-fit:cover; }

/* ── FORMATS ─────────────────────────────────────────────────────────────── */
.formats{ background:var(--bg-2); border-top:1px solid var(--hair); border-bottom:1px solid var(--hair); }
.fmt-group{ margin-top:clamp(44px,6vw,72px); }
.fmt-grouphead{ display:flex; flex-wrap:wrap; align-items:baseline; gap:14px 22px; margin-bottom:22px; }
.fmt-sub{ color:var(--muted); font-size:.95rem; }
.fmt-more-head{ color:var(--muted); font-size:.95rem; margin-bottom:18px; }
.fmt-more-head b{ color:var(--text); }
.fmt-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(200px,1fr)); gap:16px; }
/* format tiles as hung pieces: the media is the framed print, the caption a
   museum plaque on the wall beneath it (grafted from the gallery system) */
.fmt-card{ min-width:0; }
.fmt-media{ aspect-ratio:9/16; position:relative; overflow:hidden; border-radius:var(--r);
  background:var(--surface-2); border:1px solid var(--line); box-shadow:var(--el-1);
  transition:transform var(--t), border-color var(--t), box-shadow var(--t); }
.fmt-card:hover .fmt-media{ transform:translateY(-4px); border-color:rgba(213,80,63,.4); box-shadow:var(--el-glow); }
.fmt-media video, .fmt-media img{ width:100%; height:100%; object-fit:cover; }
.fmt-media img.gone{ opacity:0; transition:opacity .4s; }
.fmt-cap{ display:flex; flex-direction:column; gap:3px; padding:10px 4px 0; }
.fmt-name{ font-family:var(--mono); font-weight:500; font-size:10px; letter-spacing:.14em; text-transform:uppercase; color:var(--muted); }
.fmt-desc{ color:var(--faint); font-size:.78rem; line-height:1.45; }
.fmt-stack{ display:flex; flex-direction:column; gap:16px; }
.fmt-mini{ position:relative; flex:1; display:flex; flex-direction:column; justify-content:center; gap:3px; padding:16px;
  border-radius:var(--r); background:var(--surface); border:1px solid var(--line); transition:border-color var(--t), transform var(--t); }
.fmt-mini:hover{ border-color:rgba(213,80,63,.35); transform:translateY(-2px); }
.fmt-mini-name{ font-weight:600; font-size:.9rem; }
.fmt-mini-desc{ color:var(--faint); font-size:.78rem; line-height:1.4; }
.fmt-mini-tag{ position:absolute; top:10px; right:12px; font-family:var(--mono); font-size:.58rem; letter-spacing:.16em;
  text-transform:uppercase; color:var(--coral); }
.fmt-mini.is-new{ border-color:rgba(213,80,63,.28); }
.fmt-mini--cta{ align-items:flex-start; color:var(--coral); font-weight:600; background:rgba(213,80,63,.06); border-color:rgba(213,80,63,.35); }
.fmt-mini--cta:hover{ background:rgba(213,80,63,.12); color:var(--coral-hot); }
.fmt-grid-lead{ grid-template-columns:repeat(auto-fill,minmax(180px,1fr)); }
.fmt-cta{ display:flex; justify-content:center; margin-top:clamp(40px,5vw,60px); }

/* ── models row ──────────────────────────────────────────────────────────── */
.models-row{ display:flex; flex-wrap:wrap; justify-content:center; gap:12px 18px; }
.models-row span{ font-family:var(--mono); font-size:.72rem; letter-spacing:.2em; text-transform:uppercase; color:var(--faint);
  border:1px solid var(--line); border-radius:var(--pill); padding:9px 16px; transition:color var(--t), border-color var(--t); }
.models-row span:hover{ color:var(--coral); border-color:rgba(213,80,63,.4); }

/* ── pull-quote ──────────────────────────────────────────────────────────── */
.pullq{ font-family:var(--display); font-size:clamp(1.7rem,4vw,3.1rem); line-height:1.22; letter-spacing:-.01em;
  color:var(--text); max-width:26ch; margin:0 auto; text-align:center; text-wrap:balance; }
.pullq i{ font-style:italic; font-weight:400; color:var(--coral); }
.pullq-link{ text-align:center; margin-top:26px; }
/* Four priced tiers read as four bundles. This is the correction, on the measure, at --muted so it is a claim
   rather than small print. */
.price-solo{ max-width:74ch; margin:30px auto 0; text-align:center; font-size:.94rem; line-height:1.65; color:var(--muted); }

/* ── pricing teaser ──────────────────────────────────────────────────────── */
.teaser{ display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:16px; }
.tease{ position:relative; display:flex; flex-direction:column; gap:6px; padding:26px 22px; border-radius:var(--r-lg);
  background:var(--surface); border:1px solid var(--line); transition:transform var(--t), border-color var(--t), box-shadow var(--t); }
.tease:hover{ transform:translateY(-5px); border-color:rgba(213,80,63,.4); box-shadow:var(--el-glow); }
.tease.feat{ background:linear-gradient(180deg, rgba(213,80,63,.10), rgba(213,80,63,.02) 55%), var(--surface);
  border-color:rgba(213,80,63,.5); box-shadow:var(--el-glow); }
.t-tag{ position:absolute; top:-11px; left:20px; font-family:var(--mono); font-size:.6rem; letter-spacing:.18em; text-transform:uppercase;
  background:var(--coral-solid); color:var(--cream); padding:4px 10px; border-radius:var(--pill); }
.t-name{ font-family:var(--mono); font-size:.72rem; letter-spacing:.2em; text-transform:uppercase; color:var(--faint); }
.t-amt{ font-family:var(--display); font-size:2.3rem; line-height:1.1; margin-top:2px; }
.t-amt small{ font-size:.95rem; color:var(--faint); font-family:var(--body); }
.t-credits{ color:var(--coral); font-weight:600; font-size:.95rem; }
.t-ads{ color:var(--muted); font-size:.85rem; }
.t-ads b{ color:var(--text); }
.tease p{ font-size:.85rem; margin-top:8px; }
.t-go{ margin-top:auto; padding-top:18px; font-weight:600; color:var(--coral); display:flex; align-items:center; gap:8px; }
.tease:hover .t-go{ color:var(--coral-hot); }

/* ── FAQ ─────────────────────────────────────────────────────────────────── */
.faq{ max-width:760px; margin:36px auto 0; }
.qa{ border-bottom:1px solid var(--line); }
.qa-q{ width:100%; display:flex; justify-content:space-between; align-items:center; gap:20px; text-align:left;
  padding:20px 4px; font-weight:600; font-size:1.02rem; color:var(--text); transition:color var(--t); }
.qa-q:hover{ color:var(--coral-hot); }
.qa .pm{ position:relative; flex:none; width:18px; height:18px; }
.qa .pm::before,.qa .pm::after{ content:""; position:absolute; inset:8px 0; background:var(--coral); border-radius:2px; transition:transform var(--t); }
.qa .pm::after{ transform:rotate(90deg); }
.qa.open .pm::after{ transform:rotate(0); }
.qa-a{ max-height:0; overflow:hidden; transition:max-height .4s var(--ease-hero); }
.qa-a-in{ padding:0 4px 22px; color:var(--muted); max-width:64ch; }

/* ── closing CTA — end credits ───────────────────────────────────────────── */
.closer{ position:relative; text-align:center; padding:clamp(96px,14vw,190px) 0; overflow:clip; }
.closer .scrim{ position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(64% 58% at 50% 112%, var(--glow), transparent 66%); }
.closer h2{ font-size:clamp(2.6rem,6.5vw,5.4rem); position:relative; }
.closer h2 em.key{ font-style:italic; font-weight:400;
  background:linear-gradient(100deg, var(--coral-hot), var(--coral) 55%, var(--gold));
  -webkit-background-clip:text; background-clip:text; color:transparent; }
.closer .hero-cta{ margin-top:34px; position:relative; }
.closer .hero-note{ margin-top:18px; position:relative; }

/* ── footer ──────────────────────────────────────────────────────────────── */
.footer{ border-top:1px solid var(--line); background:var(--bg-2); padding:clamp(48px,7vw,80px) 0 34px; }
.foot-grid{ display:grid; grid-template-columns:2fr repeat(5,minmax(0,1fr)); gap:34px 26px; }
.foot-brand p{ margin-top:14px; font-size:.9rem; max-width:26ch; }
.foot-col h3{ font-family:var(--mono); font-weight:500; font-size:.68rem; letter-spacing:.2em; text-transform:uppercase; color:var(--faint); margin-bottom:14px; }
.foot-col a{ display:block; font-size:.88rem; color:var(--muted); padding:4px 0; transition:color var(--t); }
.foot-col a:hover{ color:var(--coral-hot); }
.foot-bottom{ display:flex; flex-wrap:wrap; align-items:center; gap:16px 26px; margin-top:48px; padding-top:24px; border-top:1px solid var(--hair); }
.foot-bottom .meta{ color:var(--faint); font-size:.82rem; }
.social{ display:flex; gap:14px; margin-left:auto; }
.social a{ color:var(--faint); transition:color var(--t); display:flex; padding:6px; }
.social a:hover{ color:var(--coral); }
#cookieSettingsLink{ font-size:.82rem; color:var(--faint); }
#cookieSettingsLink:hover{ color:var(--coral-hot); }

/* language picker */
.langpick{ position:relative; }
.langpick summary{ list-style:none; cursor:pointer; display:inline-flex; align-items:center; gap:8px; font-size:.82rem; color:var(--faint);
  border:1px solid var(--line); border-radius:var(--pill); padding:7px 14px; transition:color var(--t), border-color var(--t); }
.langpick summary::-webkit-details-marker{ display:none; }
.langpick summary:hover{ color:var(--text); border-color:var(--line-2); }
.langpick .globe{ width:15px; height:15px; }
.langmenu{ position:absolute; bottom:calc(100% + 10px); left:0; z-index:60; display:grid; grid-template-columns:repeat(2,minmax(150px,1fr));
  gap:2px; max-height:320px; overflow:auto; background:var(--surface); border:1px solid var(--line-2); border-radius:var(--r);
  padding:8px; box-shadow:var(--el-2); }
.langmenu a{ display:flex; justify-content:space-between; gap:12px; font-size:.82rem; color:var(--muted); padding:7px 10px; border-radius:8px; }
.langmenu a:hover{ background:var(--surface-2); color:var(--text); }
.langmenu a.on{ color:var(--coral); }
.langmenu .lc{ color:var(--faint); font-family:var(--mono); font-size:.66rem; }

/* ── cookie consent (markup injected by site.v17.js) ─────────────────────── */
.cookie-consent{ position:fixed; z-index:200; left:18px; right:18px; bottom:18px; margin:0 auto; max-width:520px;
  display:flex; flex-wrap:wrap; align-items:center; gap:12px 18px; padding:16px 20px;
  background:rgba(255,255,255,.95); -webkit-backdrop-filter:blur(14px); backdrop-filter:blur(14px);
  border:1px solid var(--line-2); border-radius:var(--r-lg); box-shadow:var(--el-2);
  opacity:0; transform:translateY(14px); transition:opacity .35s var(--ease-hero), transform .35s var(--ease-hero); }
.cookie-consent.show{ opacity:1; transform:none; }
.cc-msg{ font-size:.85rem; color:var(--muted); flex:1 1 260px; }
.cc-msg a{ color:var(--coral); }
.cc-btns{ display:flex; gap:10px; margin-left:auto; }
.cc-btn{ border-radius:var(--pill); padding:8px 16px; font-size:.85rem; font-weight:600; border:1px solid var(--line-2); color:var(--muted); transition:all var(--t); }
.cc-btn:hover{ color:var(--text); border-color:var(--line-2); }
.cc-accept{ background:var(--coral-solid); border-color:transparent; color:var(--cream); }
.cc-accept:hover{ background:#f0603f; color:var(--cream); }

/* ── poster shield (ported from v15 — site.v17.js injects an <img.pshield> after
   every video[data-hover|data-auto] and fades it once playback truly starts) ── */
img.pshield{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; z-index:1;
  opacity:1; transition:opacity .32s ease; pointer-events:none; background:var(--surface-3); }
img.pshield.gone{ opacity:0; }

/* ── museum captions (grafted from the gallery system, dark-adapted):
   a hung piece = the framed media + a mono plaque beneath it ─────────────── */
.piece{ flex:none; width:min-content; min-width:0; }
.plaque{ display:flex; flex-wrap:wrap; justify-content:space-between; gap:2px 10px; padding:9px 2px 0;
  font-family:var(--mono); font-size:10px; letter-spacing:.14em; text-transform:uppercase; color:var(--faint); }
.plaque b{ font-weight:500; color:var(--muted); }
.plaque .ai{ color:var(--coral); white-space:nowrap; }

/* ── stat strip (grafted from the kinetic system, dark-adapted; count-up is the
   existing .stat .n module inside site.v17.js — no extra JS) ─────────────── */
.statstrip{ padding:clamp(44px,6vw,80px) 0; }
.stats{ display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:clamp(18px,3vw,40px); }
.stat b{ display:block; font-family:var(--display); font-weight:500; font-size:clamp(2.3rem,4.4vw,3.6rem);
  line-height:1; letter-spacing:-.02em; color:var(--text); font-variant-numeric:tabular-nums; }
.stat:nth-child(2) b{ color:var(--coral); }
.stat span{ display:block; margin-top:10px; font-size:.82rem; line-height:1.5; color:var(--muted); }

/* ══ AGENT-FIRST BLOCK (2026-07-30) ════════════════════════════════════════
   The MCP is the product, so the homepage leads with an install line and a
   real prompt. Four new pieces, all built from the existing tokens (paper +
   hairline + rationed coral): .copyline (a one-click copy chip, wired to the
   [data-copy] handler in site.v17.js), .install (the three install routes),
   .promptcard (a real thing you can type) and .toolfams (what your agent gets).
   ========================================================================= */

/* The repositioned headline is 36 characters, not 24 — at the old 14ch/8.2vw it took three
   lines and pushed the install chip and CTAs below the fold. Two lines, slightly smaller. */
.hero h1{ max-width:min(26ch, 100%); font-size:clamp(2.3rem, 5.3vw, 4.8rem); }
.hero .lead{ max-width:min(640px, 100%); }
.hero .hero-note{ max-width:min(640px, 100%); margin-left:auto; margin-right:auto; }
.hero{ padding-top:clamp(64px,7vh,110px); }
/* .hero .wrap is a CENTERED FLEX COLUMN, so a child sizes to its own content and a bare
   max-width (26ch, 640px) can exceed the column on a phone — the page then scrolls
   sideways, or gets silently clipped by body{overflow-x:hidden}. min(…, 100%) pins it. */
.hero .wrap{ gap:22px; }

/* one-click copy chip — a <button> so it's keyboard-reachable and announces itself */
.copyline{ display:inline-flex; align-items:center; gap:12px; max-width:100%;
  padding:11px 12px 11px 16px; border-radius:var(--pill);
  background:var(--surface); border:1px solid var(--line-2); box-shadow:var(--el-1);
  font-family:var(--mono); font-size:.82rem; line-height:1.2; color:var(--text); text-align:left;
  transition:border-color var(--t), box-shadow var(--t), transform var(--t); }
.copyline:hover{ border-color:rgba(213,80,63,.45); box-shadow:var(--el-glow); transform:translateY(-1px); }
.copyline:active{ transform:none; }
.copyline code{ font-family:inherit; font-size:inherit; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; }
.copyline-pre{ color:var(--coral); flex:none; font-weight:600; }
.copyline-x{ flex:none; font-family:var(--body); font-size:.72rem; font-weight:600; letter-spacing:.08em; text-transform:uppercase;
  color:var(--muted); background:var(--surface-3); border-radius:var(--pill); padding:5px 11px; transition:background var(--t), color var(--t); }
.copyline:hover .copyline-x{ background:var(--coral-solid); color:var(--cream); }
.copyline.copied .copyline-x{ background:#1f7a4d; color:#fff; }
.hero .copyline{ margin:0 auto; }

/* the three install routes */
.install{ max-width:760px; margin:44px auto 0; padding:26px clamp(18px,3vw,30px);
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r-lg); box-shadow:var(--el-1); }
.install-row{ display:grid; grid-template-columns:minmax(0,1fr); gap:8px; }
.install-row + .install-row{ margin-top:18px; padding-top:18px; border-top:1px solid var(--hair); }
.install-lbl{ font-family:var(--mono); font-size:.68rem; letter-spacing:.2em; text-transform:uppercase; color:var(--faint); }
.install-row .copyline{ width:100%; }
.install-foot{ margin-top:22px; padding-top:18px; border-top:1px solid var(--hair);
  font-size:.86rem; line-height:1.6; color:var(--muted); max-width:none; }
.install-foot code{ font-family:var(--mono); font-size:.8em; background:var(--surface-3); border-radius:6px; padding:2px 6px; }

/* "here's a real thing you can type" */
.promptcard{ max-width:820px; margin:34px auto 0; padding:clamp(24px,3.4vw,38px);
  background:var(--bg-2); border:1px solid var(--line); border-radius:var(--r-lg); text-align:left; }
.promptcard .mono{ margin-bottom:16px; }
.promptline{ font-family:var(--display); font-size:clamp(1.15rem,2.1vw,1.55rem); line-height:1.4; color:var(--text);
  max-width:none; border-left:2px solid var(--coral); padding-left:clamp(16px,2vw,24px); }
.promptnote{ margin-top:20px; font-size:.9rem; line-height:1.65; color:var(--muted); max-width:none; }
.promptnote code, .toolfam code, .act-tool code{ font-family:var(--mono); font-size:.82em; color:var(--coral);
  background:rgba(213,80,63,.07); border-radius:6px; padding:2px 6px; white-space:nowrap; }

/* what your agent gets — six families */
.toolfams{ display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:18px; margin-top:44px; text-align:left; }
.toolfam{ padding:26px 24px; background:var(--surface); border:1px solid var(--line); border-radius:var(--r);
  box-shadow:var(--el-1); transition:border-color var(--t), box-shadow var(--t), transform var(--t); }
.toolfam:hover{ border-color:rgba(213,80,63,.35); box-shadow:var(--el-glow); transform:translateY(-2px); }
.toolfam h3{ font-family:var(--display); font-size:1.22rem; font-weight:500; letter-spacing:-.01em; }
.toolfam p{ margin-top:10px; font-size:.92rem; line-height:1.6; max-width:none; }
.toolfam > code{ display:block; margin-top:16px; padding-top:14px; border-top:1px solid var(--hair);
  font-family:var(--mono); font-size:.72rem; line-height:1.9; letter-spacing:.01em; color:var(--faint);
  background:none; white-space:normal; word-break:break-word; }

.mcp-safety{ max-width:760px; margin:36px auto 0; text-align:center; font-size:.92rem; line-height:1.7; color:var(--muted); }

/* the per-act tool line under each of the three moves */
.act-tool{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin-top:16px; max-width:none; }
.act-tool span{ font-family:var(--mono); font-size:.66rem; letter-spacing:.2em; text-transform:uppercase; color:var(--faint); margin-right:2px; }

/* ── responsive ──────────────────────────────────────────────────────────── */
@media (max-width:1060px){
  .foot-grid{ grid-template-columns:repeat(3,minmax(0,1fr)); }
  .foot-brand{ grid-column:1 / -1; }
  .teaser{ grid-template-columns:repeat(2,minmax(0,1fr)); }
}
@media (max-width:1120px){ .hero-float{ display:none; } } /* no room outside the 760px measure for a card */
@media (max-width:900px){
  .move{ grid-template-columns:1fr; gap:26px; }
  .move.flip .move-txt{ order:1; } .move.flip .move-media{ order:2; }
  .move-idx{ display:none; }
  .agentdemo{ grid-template-columns:1fr; }
  .hero-float{ display:none; }
}
@media (max-width:860px){
  .nav-links, .nav-cta{ display:none; }
  .nav-toggle{ display:block; }
  .nav{ background:rgba(250,249,247,.86); -webkit-backdrop-filter:blur(14px); backdrop-filter:blur(14px); }
  .mobile-menu{ display:flex; flex-direction:column; gap:4px; position:fixed; inset:72px 0 0; z-index:99;
    background:rgba(250,249,247,.98); padding:26px clamp(18px,5vw,32px); transform:translateY(-8px); opacity:0; pointer-events:none;
    transition:opacity var(--t), transform var(--t); overflow:auto; }
  .mobile-menu.open{ opacity:1; transform:none; pointer-events:auto; }
  .mobile-menu a{ font-family:var(--display); font-size:1.7rem; padding:12px 0; border-bottom:1px solid var(--hair); }
  .mobile-menu .m-actions{ display:flex; gap:12px; margin-top:22px; border:0; }
  .mobile-menu .m-actions a{ font-family:var(--body); font-size:1rem; border:0; flex:1; }
}
@media (max-width:640px){
  body{ font-size:16px; }
  .hero{ min-height:88svh; }
  .stats{ grid-template-columns:repeat(2,minmax(0,1fr)); gap:28px 18px; }
  .teaser{ grid-template-columns:1fr; }
  .fmt-grid, .fmt-grid-lead{ grid-template-columns:repeat(2,minmax(0,1fr)); }
  .fmt-stack{ grid-column:span 1; }
  .ad-out{ grid-template-columns:repeat(3,minmax(0,1fr)); }
  .foot-grid{ grid-template-columns:repeat(2,minmax(0,1fr)); }
  .reel-card{ height:180px; }
  .social{ margin-left:0; }
}

/* ── reduced motion: kill choreography, keep everything visible ──────────── */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{ animation-duration:.01ms !important; animation-iteration-count:1 !important; transition-duration:.01ms !important; }
  .rise, .ident .bloom{ opacity:1; transform:none; animation:none; }
  .reveal{ opacity:1; transform:none; }
  .ticker-track{ animation:none; }
  .strip-track{ animation:none; }
  .hero-float{ animation:none; }
  html{ scroll-behavior:auto; }
}
/* MOBILE MENU REPAIR (2026-07-17, Dave's iPhone screenshot: the open menu had no opaque panel — only the first
   link floated over the hero). Full-screen near-black panel UNDER the sticky nav (z 99 < nav 100) so the logo +
   close toggle stay tappable; body scroll locks while open. Appended last so these win the earlier partial rules. */
/* ░░ `visibility` IS LOAD-BEARING, NOT DECORATION (2026-08-05). This panel is `display:flex` at EVERY width —
   the earlier rule that hid it under 860px was overridden by this block — and a closed panel was hidden only by
   `opacity:0; pointer-events:none`. Neither of those takes an element out of the TAB ORDER. Measured on the live
   homepage at 1440px: tab stops 11-16 landed on the eight invisible menu links, so a keyboard user on a DESKTOP
   browser tabbed off the "Sign up" button into six links they could not see, on all 446 pages. `visibility:hidden`
   removes them; the 0s-delayed transition on the closed state keeps the fade-out visible before it applies, and the
   open state resets that delay so the panel appears immediately. */
.mobile-menu{display:flex;flex-direction:column;position:fixed;inset:0;z-index:99;background:#faf9f7;padding:96px 26px 40px;opacity:0;pointer-events:none;visibility:hidden;transform:translateY(-8px);transition:opacity .25s ease,transform .25s ease,visibility 0s linear .25s;overflow-y:auto}
.mobile-menu.open{opacity:1;transform:none;pointer-events:auto;visibility:visible;transition:opacity .25s ease,transform .25s ease,visibility 0s}
body.menu-open{overflow:hidden}
@media (prefers-reduced-motion: reduce){.mobile-menu{transition:none;transform:none}}
/* The menu panel is a CHILD of .nav — inside that stacking context it painted over its sibling toggle (second tap
   couldn't close). Lift the toggle + brand above the panel; they stay visible/tappable while the menu is open. */
.nav .nav-toggle,.nav .brand{position:relative;z-index:120}

/* ── AGENT-FIRST BLOCK: responsive. Appended LAST so these win the earlier rules
      (same discipline as the mobile-menu repair above). ──────────────────── */
@media (max-width:900px){
  .toolfams{ grid-template-columns:repeat(2,minmax(0,1fr)); }
}
@media (max-width:640px){
  .toolfams{ grid-template-columns:1fr; gap:14px; }
  .install{ padding:20px 16px; }
  /* on a phone the command must wrap instead of truncating into a useless ellipsis */
  .copyline{ flex-wrap:wrap; border-radius:var(--r); padding:12px 14px; gap:8px; font-size:.76rem; }
  .copyline code{ white-space:normal; word-break:break-all; flex:1 1 100%; order:2; }
  .copyline-pre{ order:1; }
  .copyline-x{ order:3; margin-left:auto; }
  .promptline{ border-left-width:2px; padding-left:14px; }
}

/* ░░ CONNECTOR WALL (2026-07-31 – 2026-08-04) — DELETED. It was a tight logo grid under the hero whose job was
   to prove breadth before a line of copy was read. The flow device ("One brief → everywhere", in the GALLERY
   layer below) does that job better because it shows the SHAPE of the platform and not just the logo count,
   and it carries the wall's two honest limits and its export destinations forward verbatim in .flow-note.
   Removed rather than left orphaned: `grep -rl connwall site --include='*.html'` returns 0 pages. */


/* Hero agent rotator — the headline named only Claude, and the product is not Claude-only.
   The word carries its OWN clipped gradient: an inline-block child does not reliably show a
   parent's background-clip:text.

   ░░ THE SLOT IS SIZED TO THE LONGEST WORD AND NEVER CHANGES AGAIN. This was the site's ENTIRE
   mobile CLS: 0.204 at 402px, against Google's 0.1 "Good" bound, and every layout-shift entry
   named this <h1>. The wrapper used to animate its WIDTH to each word in turn — which on a phone
   moves the line-break: "OpenClaw" pushes the headline from two lines to three, and the lead, the
   install chip, both CTAs and the footnote all drop 40px. Two of those re-wraps were 0.079 and
   0.082 on their own. On a CENTRED headline it is worse than a re-wrap, because a width change
   re-centres the whole line even when the wrap point survives.

   THE SIZER IS ::after, NOT A HIDDEN SPAN AND NOT JAVASCRIPT.
     · Not a span: a second copy of the word in the DOM makes the h1 read
       "…marketing in ClaudeOpenClaw." to every text extractor, LLM crawler and og-description
       scraper, and this site is SEO/AEO work first.
     · Not JS: the script is at the end of <body>, so a width reserved from JS lands AFTER first
       paint and is itself one shift. `content` is applied at first style resolution — zero shift,
       and it still works with JS off.
     · `visibility:hidden` keeps the box (so it sizes the slot) while removing it from the
       accessibility tree, so the pseudo-element is never announced.
   The word is a PROPER NOUN, identical in all 32 locales (lib/i18n-protect.mjs protects exactly
   these), so one declaration in the shared stylesheet is correct for every homepage — there is no
   per-locale value to derive. tools/site-hero-slot-check.mjs asserts this string is still the
   longest entry in every page's data-rot list, so adding a longer client name fails the suite
   instead of silently restoring the shift.

   ░░ THE COST IS A WIDER SPACE BEFORE THE WORD, AND IT WAS PAID DELIBERATELY. "OpenClaw" is 174px
   at 402px and "Cline" is 86px, so a reserved slot leaves up to 88px (2.3em) of air on a phone and
   168px on a 1440 desktop. THREE CHEAPER-LOOKING ALTERNATIVES WERE BUILT AND MEASURED FIRST, AND
   ALL THREE FAILED ON DATA, NOT ON TASTE:
     · `min-height` clamping the h1 to a fixed line count (0.030 CLS, no gap at all — but the
       required clamp is per-locale AND per-width: measured over all 32 homepages × 18 widths, the
       tallest configuration ranges from 5 lines at 320px to 2 at 1440px, and the SHORTEST locale
       at the same width is 2 and 1. One number is wrong for someone at every breakpoint, and 576
       numbers is not a stylesheet.
     · Forcing the accent phrase onto its own line (`em.key::before{content:"\A"}`): cut the
       re-wrapping locales from 14 to 6 but never to 0, because the accent LINE then wraps instead.
     · Making `.rotw` a block so its width cannot matter: needs every word after the rotator moved
       inside it, and the h1 tails are not punctuation in 7 locales — zh's headline is `在` + the
       word + eleven more characters, so the block would strand a one-character first line.
   Only the reserved slot is automatically correct for 32 sentence structures at every width with
   no per-locale rule, which is why it wins despite being the least pretty of the four.

   `text-align:end` places that air BEFORE the word rather than around it. That is the whole reason
   this is `end` and not `center`: the tail — "." in 24 locales, "で動かす。" in Japanese, " 里运营
   你的整个营销。" in Chinese — stays welded to the word. A centred word leaves the full stop
   floating half the slack away, which does not read as spacing, it reads as a typo. `end` is the
   LOGICAL property, so Arabic/Hebrew/Persian/Urdu get it on the correct side (verified in ar). */
.hero h1 em.key .rotw{ display:inline-block; position:relative; white-space:nowrap;
  text-align:end; }
.hero h1 em.key .rotw::after{ content:"OpenClaw"; visibility:hidden; }
/* The visible word rides ON the sizer. Absolute, so the sizer alone establishes the inline-block's
   baseline and the swap cannot touch layout. */
.hero h1 em.key .rotw-in{ position:absolute; left:0; right:0; top:0; display:block;
  background:linear-gradient(100deg, var(--coral-hot), var(--coral) 55%, var(--gold));
  -webkit-background-clip:text; background-clip:text; color:transparent;
  transition:opacity .24s ease, transform .24s ease; }
.hero h1 em.key .rotw-in.out{ opacity:0; transform:translateY(-.16em); }
@media (prefers-reduced-motion:reduce){
  .hero h1 em.key .rotw, .hero h1 em.key .rotw-in{ transition:none; }
}


/* ════════════════════════════════════════════════════════════════════════════════════════════════════════════
   ░░ GALLERY LAYER (2026-08-04) — the page becomes a FRAME so the ads can be the picture.
   Reference: Apple (España). Adopted verbatim: near-white canvas alternating #ffffff / #f5f5f7-equivalent in
   BANDS, ink text, oversized headlines, 100–120px section gaps, borderless components at a 28px radius, ZERO
   shadow, and — the load-bearing rule — COLOUR APPEARS IN THE PRODUCT IMAGERY ITSELF, NEVER AS UI DECORATION,
   with a single accent reserved exclusively for interactive moments.
   Adapted, not copied: our typefaces stay (Fraunces / Hanken Grotesk), and the accent stays CORAL — Apple's
   blue is deliberately NOT introduced. [[cta-green-not-coral]] settled the CTA as coral and recorded Dave's
   standing note that "coral belongs to the logo and shouldn't be sprinkled through the UI"; this layer is that
   audit for the marketing site.
   Appended LAST, the same discipline the mobile-menu and agent-first repairs above use, so it wins on source
   order without a specificity fight and without touching a single behavioural hook in site.v17.js.
   ═══════════════════════════════════════════════════════════════════════════════════════════════════════════ */

/* ── 1 · the canvas: no atmosphere. Grain and the ember vignette were UI decoration painted over every band,
      and they are exactly what stops a near-white page reading as a gallery wall. ──────────────────────────── */
body::before, body::after{ display:none !important; content:none !important; }

/* …and the skip link stops being hidden with a PHYSICAL offset. `left:-9999px` works in LTR because
   body{overflow-x:hidden} clips the left side, but on the four RTL homepages (ar / he / ur / fa) that offset
   lands 9999px past the inline-START edge, on the side the clip does not cover: measured on /ar/,
   documentElement.scrollWidth was 11179 against a 1180 viewport — the whole page scrolled sideways. Pre-dates
   this redesign; found by measuring rather than by looking, because the leaked area is empty. Clip-based
   hiding has no geometry to leak in either direction. */
.skip{ left:auto; top:0; inset-inline-start:0; width:1px; height:1px; overflow:hidden; clip-path:inset(50%); white-space:nowrap; }
.skip:focus{ left:auto; inset-inline-start:0; width:auto; height:auto; overflow:visible; clip-path:none; }

/* ── 2 · BANDS. Hierarchy comes from alternating background, not from dividers or boxes. nth-child is used
      deliberately over hand-applied classes: the 31 localized homepages have a DIFFERENT section count from
      the English one, so a structural rule alternates correctly on all 32 without per-locale reasoning. ───── */
main > section{ background:var(--bg); position:relative; }
main > section:nth-child(even){ background:var(--bg-2); }
.hero{ background:var(--bg); }
/* dividers deleted — two adjacent bands are never the same colour, so a hairline between them is noise */
.cinema, .formats{ border-top:0; border-bottom:0; }
.footer{ background:var(--bg); border-top:1px solid var(--hair); }
.closer .scrim{ display:none; }

/* ── 3 · AIR. Apple's section rhythm is 100–120px; ours was 72–140 with a tight variant that collapsed to 56. */
.section{ padding:clamp(84px,11vw,132px) 0; }
.section.tight{ padding:clamp(72px,9vw,112px) 0; }
.statstrip{ padding:clamp(64px,8vw,104px) 0; }
.cinema{ padding:clamp(84px,10vw,124px) 0; }
.closer{ padding:clamp(104px,15vw,190px) 0; }

/* ── 4 · TYPE. Oversized headlines on near-white, tighter tracking, one measure for prose. ─────────────────── */
h2,.tt{ font-size:clamp(2.05rem, 4.6vw, 3.9rem); letter-spacing:-.022em; }
.hero h1{ font-size:clamp(2.4rem, 5.6vw, 5.1rem); letter-spacing:-.028em; }
/* …but a headline living in a HALF-WIDTH column cannot take the full-bleed size: the three acts sit in a 5fr
   column of a 5fr/6fr grid, where 3.9rem broke "See what's already winning" onto four lines beside a stationary
   screenshot. Oversized type needs the whole page under it. */
.move h2{ font-size:clamp(1.9rem, 3vw, 2.9rem); }
.sec-head{ max-width:820px; }
.lead{ font-size:clamp(1.06rem, 1.55vw, 1.28rem); }

/* ── 5 · COLOUR IS NOT DECORATION. Every one of these was coral doing a non-interactive job. The accent now
      survives only on: .btn-primary, links, .move-link, .t-go, :focus-visible and the copyline's hover
      affordance. Nothing else. ────────────────────────────────────────────────────────────────────────────── */
h2 i,.tt i,h1 em{ color:var(--text); }                         /* italic emphasis is a WEIGHT change, not a hue */
h1 em.key,
.hero h1 em.key .rotw-in,
.closer h2 em.key{ background:none; -webkit-background-clip:border-box; background-clip:border-box; color:var(--text); }
.eyebrow{ color:var(--faint); }
.mono .dot{ background:var(--faint); box-shadow:none; animation:none; opacity:.55; }
/* A section eyebrow is a SENTENCE, not a row. As an inline-flex it centred the dot against the whole block, so
   a two-line eyebrow on a phone ("ONE LOGIN · EVERY CHANNEL YOU MARKET ON" wraps at 402px) left the dot
   stranded out to the left of the gap between the lines. Inline flow puts it at the head of the first line and
   lets the text centre normally. Scoped to .sec-head so the flex eyebrows elsewhere (.fmt-grouphead) stand. */
.sec-head .mono{ display:inline; }
.sec-head .mono .dot{ display:inline-block; vertical-align:middle; margin-inline-end:9px; }
.slate::before{ background:var(--line-2); box-shadow:none; }
.stat:nth-child(2) b{ color:var(--text); }
.pullq i{ color:var(--text); }
.plaque .ai{ color:var(--faint); }
.t-credits{ color:var(--text); }
.fmt-mini-tag{ color:var(--faint); }
.qa .pm::before,.qa .pm::after{ background:var(--text); }
.promptline{ border-left-color:var(--line-2); }
.promptnote code, .toolfam code, .act-tool code, .install-foot code{ color:var(--muted); background:var(--surface-3); }
.toolfam > code{ background:none; }   /* the block-level tool list is a hairline-ruled footer, not an inner box */
.models-row span:hover{ color:var(--text); border-color:var(--line-2); }
.fmt-mini.is-new{ border-color:transparent; }
.fmt-mini--cta{ color:var(--coral); }                          /* a link — the accent is correct here */
.ticker-set span b{ color:var(--text); }                       /* a marquee is not an interaction */
.ad-log b, .ad-log .hl{ color:var(--text); }
.copyline-pre{ color:var(--faint); }                           /* the "$" glyph is punctuation, not an accent */
.langmenu a.on{ color:var(--text); font-weight:600; }          /* current locale = weight, not hue */
/* The frames themselves lose their outline + lift: an ad in a gallery hangs on the wall, it does not float. */
.hero-float, .reel-card{ border:0; box-shadow:none; }
.hero-float{ border-radius:var(--r-lg); }
.reel-card:hover{ border-color:transparent; box-shadow:none; }

/* ── 6 · BORDERLESS + FLAT. A card is a rounded plane of a different band value, never a boxed outline. ────── */
.toolfam, .tease, .fmt-mini, .install, .promptcard, .ad-log, .ui-frame, .copyline, .langmenu{
  border-color:transparent; box-shadow:none;
}
.toolfam, .tease, .install, .promptcard, .ad-log, .ui-frame{ border-radius:var(--r-lg); }
.fmt-media, .reel-card, .fmt-mini{ border-radius:var(--r); }
/* On a WHITE band a white card is invisible, so a card takes the OTHER band value and flips inside a canvas
   band. `main > section:nth-child(even)` IS the canvas band, so one pair of rules covers every section. */
.toolfam, .tease, .install, .promptcard, .ad-log, .fmt-mini{ background:var(--bg-2); }
main > section:nth-child(even) :is(.toolfam,.tease,.install,.promptcard,.ad-log,.fmt-mini){
  background:var(--surface);
}
.toolfam:hover, .tease:hover, .fmt-mini:hover{ border-color:transparent; box-shadow:none; }
.toolfam:hover, .fmt-mini:hover{ background:var(--surface-3); transform:none; }
main > section:nth-child(even) :is(.toolfam,.fmt-mini):hover{ background:var(--surface-2); }
/* the "See them all" tile keeps the ordinary card background: coral on the darker --surface-3 chip measures
   4.46:1 and misses AA for a 14px link, while on either band value it is 5.37 / 4.88. */
.tease{ transition:transform var(--t), background var(--t); }
.tease:hover{ transform:translateY(-3px); }
/* THE FEATURED PLAN WAS WHITE ON WHITE — the whole "Pro / Most popular" card rendered blank, MEASURED at
   1.00:1 on ea38afc0 before this line changed. `.tease.feat` is (0,2,0) and the band rule two blocks up is
   `main > section:nth-child(even) :is(…)` = (0,2,2), so on a canvas band the band rule won the background while
   the white text below still applied. The band selector is repeated here rather than reaching for !important,
   so the ink fill wins on BOTH bands and #pricing can move sections without going invisible again. */
.tease.feat, .tease.feat:hover,
main > section:nth-child(even) .tease.feat,
main > section:nth-child(even) .tease.feat:hover{ background:var(--text); }
.tease.feat .t-amt, .tease.feat .t-go, .tease.feat .t-tag{ color:#ffffff; }
.tease.feat p, .tease.feat .t-name, .tease.feat .t-ads, .tease.feat .t-credits, .tease.feat .t-amt small{ color:rgba(255,255,255,.78); }
.tease.feat .t-ads b{ color:#ffffff; }
.tease.feat .t-tag{ background:#ffffff; color:var(--text); }
.ui-frame{ border:0; }
.ui-bar{ background:var(--surface-3); border-bottom-color:transparent; }
.ui-bar i:first-child{ background:var(--line-2); }              /* a window dot is chrome, not an accent */
.btn-ghost{ border-color:var(--line-2); background:transparent; }
.btn-ghost:hover{ border-color:var(--text); color:var(--text); }
.btn-primary, .btn-primary:hover{ box-shadow:none; }
.copyline{ background:var(--surface-3); }
main > section:nth-child(even) .copyline{ background:var(--surface); }
.copyline:hover{ border-color:transparent; box-shadow:none; }
.cookie-consent, .langmenu{ border:1px solid var(--line-2); }   /* floating panels keep one hairline to read */

/* ════════════════════════════════════════════════════════════════════════════════════════════════════════════
   ░░ THE FLOW DEVICE — "One brief → everywhere"
   The positioning problem this solves: the breadth was already on the page, but only in PROSE. A scanner could
   not tell in five seconds that we do everything a scheduler does PLUS seven ad platforms PLUS the creative
   itself. This is the product's real dataflow, drawn once.
   HOW IT IS BUILT, and why: every word is real HTML (translatable, selectable, in the a11y tree); only the
   connector geometry is inline SVG, marked aria-hidden. The SVG carries `vector-effect="non-scaling-stroke"`
   so a stretched connector keeps a crisp line, and `pathLength="100"` so the travelling highlight is
   deterministic without measuring a path in JS. The BASE paths are always solid at full opacity: motion is a
   SECOND path layered on top, so the diagram is complete and correct as a static image — no-JS, print, social
   card and prefers-reduced-motion all show the finished drawing rather than a half-revealed one.
   ═══════════════════════════════════════════════════════════════════════════════════════════════════════════ */
.flowsec{ padding:clamp(84px,11vw,132px) 0; scroll-margin-top:84px; }
.flowgraph{ margin-top:clamp(40px,5vw,64px); }
/* The fan is much taller than a three-line stage card, and the three ways of resolving that are not equal:
     · stretch each card to the row      → copy stranded at the top of three tall empty planes
     · centre each card in the row       → ragged top edges (they differ by ~10px), which reads as a bug
     · centre the SPINE AS A GROUP       → equal-height cards, straight edges, group centred on the fan  ← this
   So the spine is its own nested 3-column grid spanning columns 1–3, `align-self:center`, with the cards
   stretching to each other inside it. That also puts the group's mid-line on the row's mid-line, which is
   exactly where the braid's stem is drawn. */
/* TWO ROWS, and the reason is geometric rather than decorative. The inlet ("or start here") sits in row 1 over the
   rails; EVERYTHING ELSE stays in row 2, so the spine is still centred on the FAN and every constant the braid
   hard-codes still holds — stem at viewBox y=100 of 200, tips at 25% / 75%. Put the inlet in the same row and the
   spine's mid-line moves, which silently breaks the stem it took a rewrite to get straight. */
.flow-row{
  /* The braid column went 52 → 72px WITH the inlet, and the 20px buys two things at once: the junction moves to
     x=30, clear of the inlet card's own 28px corner radius so its drop leaves a STRAIGHT edge, and the branch
     curves get 38px of run instead of 32px. The braid viewBox is 1:1 in x (preserveAspectRatio="none" over an
     equal pixel width), so every number in its `d` is a real pixel and moved with it. */
  display:grid; grid-template-columns:repeat(3,minmax(0,1fr)) 72px minmax(0,2fr);
  grid-template-rows:auto minmax(0,1fr);
  gap:clamp(10px,1.2vw,16px) clamp(10px,1.4vw,20px); align-items:stretch;
}

/* the spine: three numbered stages, borderless, sitting straight on the band */
.flow-spine{ grid-area:2 / 1 / 3 / 4; align-self:center; list-style:none; margin:0; padding:0;
  display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:0 clamp(10px,1.4vw,20px); }
.fstep{ position:relative; display:flex; flex-direction:column; gap:8px; min-width:0;
  padding:clamp(18px,2vw,26px) clamp(16px,1.6vw,22px); border-radius:var(--r-lg); background:var(--bg-2); }
main > section:nth-child(even) .fstep{ background:var(--surface); }
.fstep-n{ font-family:var(--mono); font-size:.66rem; letter-spacing:.22em; color:var(--faint); }
.fstep h3{ font-family:var(--display); font-size:clamp(1.05rem,1.5vw,1.3rem); font-weight:500; line-height:1.16; letter-spacing:-.015em; }
.fstep p{ font-size:.86rem; line-height:1.55; color:var(--muted); max-width:none; }
/* the connector between two spine stages — a fixed-size inline SVG dropped into the gutter.
   LOGICAL, not physical: `inset-inline-end` puts it in the flow direction, so the four RTL homepages
   (ar / he / ur / fa) get the connector on the correct side without a second rule. The arrowheads still
   have to be mirrored, which is the [dir=rtl] block below — a grid auto-mirrors, a drawn glyph does not. */
.flow-link{ position:absolute; z-index:2; top:50%; inset-inline-end:calc(clamp(10px,1.4vw,20px) * -1);
  width:clamp(10px,1.4vw,20px); height:14px; transform:translateY(-50%); overflow:visible; pointer-events:none; }
[dir="rtl"] .flow-link, [dir="rtl"] .flow-braidwrap, [dir="rtl"] .flow-tip{ transform:scaleX(-1); }
[dir="rtl"] .flow-link{ transform:translateY(-50%) scaleX(-1); }

/* The fan: one stem splitting into the two rails. THREE elements, not one — the lines must stretch to an
   unknown fan height (`preserveAspectRatio="none"`), and while `vector-effect:non-scaling-stroke` holds the
   line WEIGHT constant it cannot hold a SHAPE's proportions: at the ~1.85× vertical stretch this renders at,
   an arrowhead drawn inside the stretched viewBox came out visibly elongated. So the tips are separate,
   fixed-size, and pinned by CSS at the rails' centres, where nothing distorts them. */
.flow-braidwrap{ grid-area:2 / 4 / 3 / 5; position:relative; align-self:stretch; display:block; pointer-events:none; }
.flow-braid{ position:absolute; inset:0; width:100%; height:100%; overflow:visible; }
.flow-braidtip{ position:absolute; inset-inline-end:2px; width:8px; height:11px; transform:translateY(-50%); overflow:visible; }
.flow-braidtip.t1{ top:25%; } .flow-braidtip.t2{ top:75%; }
/* RTL: TWO MIRRORS MAKE A RIGHT. `.flow-braidtip` is a CHILD of `.flow-braidwrap`, which the rule above already
   flips — so the tip must not flip itself, and it must LAY OUT at the logical start, because the parent's flip is
   what paints it against the rails. With both of its own mirrors in place the arrowheads sat on the far side of
   the junction pointing away from the rails: MEASURED on /ar/ at 1300px, tips at x 560–568 with the rails ending
   at 480. (Defect predates this change; the arrowheads are simply next to the device it edits.) */
[dir="rtl"] .flow-braidtip{ inset-inline-end:auto; inset-inline-start:2px; transform:translateY(-50%); }

/* ── THE SECOND WAY IN ────────────────────────────────────────────────────────────────────────────────────────
   The device drew ONE entry, and a single-entry flow reads as a PIPELINE: everything right of 02 looks
   downstream of our generation. That is false and it excludes real buyers — a brand that already makes its own
   creative and wants the scheduler, an agency that wants the seven ad platforms. So there is a second entry, and
   it is a node in the diagram rather than a sentence under it.
   WHERE IT JOINS, and why that exact point: the SPLIT, not a rail. A file you bring reaches BOTH rails exactly as
   a render does, so joining one rail would draw a narrower truth than we ship.
   HOW IT KEEPS THE GEOMETRY THE SPINE DEPENDS ON: it is in its own grid ROW, so the spine is still centred on the
   FAN and the braid's hard-coded constants (stem at viewBox y=100 of 200, tips at 25% / 75%) are untouched. The
   first draft instead shared the spine's cell, bottom-pinned into its slack, and fed the junction with a curve
   that rose 250px over the 16px the braid column then had — built, looked at, and thrown away: it read as a
   bracket, not a flow. A drop straight down onto the junction is the merge this column can actually draw.
   Spans the BRAID column as well as the fan, so "30px from my left edge" is the junction's own x — which is what
   lets the inlet's drop and the braid's vertical share one line without either measuring the other. */
.flow-entry{ grid-area:1 / 4 / 2 / 6; position:relative;
  display:flex; align-items:baseline; gap:6px clamp(12px,1.4vw,18px); min-width:0;
  padding:clamp(13px,1.4vw,17px) clamp(16px,1.8vw,22px); border-radius:var(--r-lg); background:var(--bg-2); }
main > section:nth-child(even) .flow-entry{ background:var(--surface); }
.flow-entry .fstep-n{ flex:none; text-transform:uppercase; }
.flow-entry-say{ min-width:0; display:flex; flex-wrap:wrap; align-items:baseline; gap:2px 10px; }
.flow-entry h3{ font-family:var(--display); font-size:clamp(1rem,1.35vw,1.16rem); font-weight:500;
  line-height:1.2; letter-spacing:-.015em; }
.flow-entry p{ font-size:.84rem; line-height:1.5; color:var(--muted); max-width:none; }
/* The inlet's drop, across the row gap, continuing into the braid's own vertical at the same x. No arrowhead —
   the head belongs at the destination, and the destination is the junction the braid draws. */
.flow-entrylink{ position:absolute; z-index:2; left:30px; bottom:calc(clamp(10px,1.2vw,16px) * -1);
  width:8px; height:calc(clamp(10px,1.2vw,16px) + 3px); margin-inline-start:-4px; overflow:visible; pointer-events:none; }
[dir="rtl"] .flow-entrylink{ left:auto; right:30px; }
.flow-entry > .flow-link{ display:none; }   /* stacked-only; see the ≤900px block */

/* the two rails */
.flow-fan{ grid-area:2 / 5 / 3 / 6; display:grid; grid-template-rows:1fr 1fr; gap:clamp(10px,1.2vw,16px); min-width:0; }
.rail{ display:flex; flex-direction:column; gap:12px; min-width:0;
  padding:clamp(16px,1.8vw,22px); border-radius:var(--r-lg); background:var(--bg-2); }
main > section:nth-child(even) .rail{ background:var(--surface); }
.rail-head{ display:flex; flex-wrap:wrap; align-items:baseline; gap:4px 10px; }
.rail-kind{ font-family:var(--mono); font-size:.68rem; letter-spacing:.2em; text-transform:uppercase; color:var(--text); font-weight:600; }
.rail-what{ font-size:.78rem; color:var(--faint); line-height:1.4; }
.rail-list{ list-style:none; margin:0; padding:0; display:grid; gap:6px; grid-template-columns:repeat(auto-fill,minmax(104px,1fr)); }
.rail-list .ch{ display:flex; align-items:center; gap:7px; min-width:0; padding:7px 9px; border-radius:10px; background:var(--surface); }
main > section:nth-child(even) .rail-list .ch{ background:var(--bg-2); }
.rail-list .ch svg{ width:16px; height:16px; flex:none; }
/* the label WRAPS rather than truncating: "Microsoft Advertising" is the platform's real name and an ellipsis
   in a breadth device defeats the whole point of the device. */
.rail-list .ch span{ font-size:.72rem; line-height:1.22; color:var(--muted); font-weight:500;
  min-width:0; overflow-wrap:anywhere; }

/* the return arm — results coming back as analytics */
.flow-return{ display:flex; align-items:center; gap:clamp(10px,1.6vw,18px);
  margin-top:clamp(14px,1.8vw,22px); padding:0 2px; max-width:none; }
.flow-tip{ flex:none; width:12px; height:14px; overflow:visible; }
/* MEASURED at 402px: `flex:none` on the label made it take its 368px max-content width and push the row to
   476px — a real 73px horizontal overflow, invisible only because body{overflow-x:hidden} was swallowing it.
   The label shrinks and wraps instead; the line keeps a small basis so it never disappears entirely. */
.flow-back{ flex:1 1 40px; height:14px; min-width:40px; overflow:visible; }
.flow-return span{ flex:1 1 auto; min-width:0; font-size:.82rem; line-height:1.45; color:var(--muted); }
/* A DIAGRAM CANNOT CARRY A NEGATIVE. The graph can show a second way in; it cannot say "you do not have to use
   the studio", and flexibility is a selling point rather than a disclaimer — so this is a claim in the head, at
   --muted on the reading measure, not a footnote at --faint like .flow-note. */
.flow-say{ max-width:70ch; margin:14px auto 0; font-size:1rem; line-height:1.62; color:var(--muted); }
.flow-say b, .flow-say strong{ color:var(--text); font-weight:600; }
.flow-note{ max-width:78ch; margin:clamp(22px,2.6vw,32px) auto 0; text-align:center; font-size:.9rem; line-height:1.65; color:var(--faint); }
.flow-note a{ color:var(--coral); border-bottom:1px solid rgba(193,58,46,.32); }
.flow-note a:hover{ border-bottom-color:var(--coral); }

/* Strokes — one ink hue, never the accent: the diagram is structure, not a highlight.
   NOT --line-2. A hairline meant for a card edge measures 1.40:1 against its background, and these arrows are
   a "graphical object required to understand the content" under WCAG 1.4.11, which wants 3:1. At .5 alpha the
   stroke measures 3.44:1 on paper and 3.35:1 on canvas. A diagram nobody can see is not a subtle diagram. */
.flowgraph{ --flow-line: rgba(24,21,15,.5); }
.flowgraph .fl-base{ fill:none; stroke:var(--flow-line); stroke-width:1.4; vector-effect:non-scaling-stroke; }
.flowgraph .fl-head{ fill:var(--flow-line); stroke:none; }
/* MOTION IS ADDITIVE. This path is layered over a base path that is already solid, so removing it (reduced
   motion, no-JS, print) leaves the finished diagram rather than an empty one. */
.flowgraph .fl-spark{ fill:none; stroke:var(--text); stroke-width:1.6; vector-effect:non-scaling-stroke;
  stroke-linecap:round; stroke-dasharray:9 91; stroke-dashoffset:100; opacity:.42;
  animation:flowspark 3.4s linear infinite; }
.flowgraph .fl-spark.d1{ animation-delay:.35s } .flowgraph .fl-spark.d2{ animation-delay:.7s }
.flowgraph .fl-spark.d3{ animation-delay:1.05s } .flowgraph .fl-spark.d4{ animation-delay:1.2s }
.flowgraph .fl-spark.rev{ animation-name:flowsparkrev; animation-duration:4.8s; }
@keyframes flowspark{ from{ stroke-dashoffset:100 } to{ stroke-dashoffset:0 } }
@keyframes flowsparkrev{ from{ stroke-dashoffset:0 } to{ stroke-dashoffset:100 } }

/* ── the flow device on a phone: the rails STACK and stay legible; they never shrink to fit ───────────────── */
@media (max-width:900px){
  /* Everything stacks in DOM order, so the explicit grid areas are released — the entry then sits where it reads:
     after the three stages, before the rails it feeds. */
  .flow-row{ grid-template-columns:minmax(0,1fr); gap:14px; }
  .flow-spine{ grid-area:auto; grid-column:1; grid-template-columns:minmax(0,1fr); gap:14px; }
  .flow-entry{ grid-area:auto; flex-direction:column; align-items:flex-start; gap:8px; }
  .flow-entrylink{ display:none; }
  .flow-entry > .flow-link{ display:block; }
  .flow-braidwrap{ display:none; }
  /* the horizontal connector becomes a vertical one between stacked cards */
  .flow-link{ top:auto; right:auto; bottom:-14px; left:50%; width:14px; height:14px; transform:translateX(-50%) rotate(90deg); }
  .flow-fan{ grid-area:auto; grid-template-rows:auto auto; }
}
@media (max-width:640px){
  /* the return label takes its own line under the arrow rather than fighting it for width */
  .flow-return{ flex-wrap:wrap; }
  .flow-return span{ flex:1 1 100%; }
}
@media (max-width:520px){
  .rail-list{ grid-template-columns:repeat(auto-fill,minmax(90px,1fr)); }
  .rail-list .ch span{ font-size:.68rem; }
  .flow-return span{ font-size:.78rem; }
}

/* ════════════════════════════════════════════════════════════════════════════════════════════════════════════
   ░░ THE PLATFORM PANELS — scheduling, ads management, measurement and AGENCY get their own HEADINGS.
   All four were true on the page already and all four were buried inside one 90-word paragraph in Act 03.
   "agency" appeared ZERO times on the site while we ship unlimited brand workspaces and team seats on every
   plan — that is the positioning miss this panel closes.
   ═══════════════════════════════════════════════════════════════════════════════════════════════════════════ */
.pgrid{ display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:clamp(14px,2vw,22px); margin-top:clamp(38px,4.6vw,58px); }
.pcard{ display:flex; flex-direction:column; gap:10px; padding:clamp(24px,2.6vw,34px); border-radius:var(--r-lg); background:var(--bg-2); }
main > section:nth-child(even) .pcard{ background:var(--surface); }
.pcard h3{ font-family:var(--display); font-size:clamp(1.24rem,2vw,1.62rem); font-weight:500; letter-spacing:-.018em; line-height:1.14; }
.pcard p{ font-size:.94rem; line-height:1.62; max-width:none; }
/* "On its own" — the standalone claim, repeated on all four cards so the PATTERN is what a scanner reads. Set
   apart by a mono lead-in and space, never by a rule or a second fill: this restyle is deliberately borderless
   and shadowless, and this is the same claim four times, not a card inside a card. --muted, not --faint: a
   defining claim is not a footnote, and --faint measured 3.5:1 and fails AA at this size. */
.pcard-solo{ margin-top:6px; font-size:.88rem; line-height:1.6; color:var(--muted); }
.pcard-solo b{ font-family:var(--mono); font-size:.66rem; font-weight:600; letter-spacing:.18em;
  text-transform:uppercase; color:var(--text); margin-inline-end:8px; white-space:nowrap; }
.pcard code{ margin-top:auto; padding-top:14px; font-family:var(--mono); font-size:.7rem; line-height:1.9;
  letter-spacing:.01em; color:var(--faint); background:none; word-break:break-word; }
@media (max-width:760px){ .pgrid{ grid-template-columns:minmax(0,1fr); } }

/* ── reduced motion: the diagram is already finished, so the spark simply stops existing ───────────────────── */
@media (prefers-reduced-motion: reduce){
  .flowgraph .fl-spark{ display:none; }
  .tease:hover{ transform:none; }
}

/* ════════════════════════════════════════════════════════════════════════════════════════════════════════════
   ░░ WATCH IT WORK (2026-08-05) — the second screen is now a RENDERED VIDEO, not a CSS panel.

   WHAT WAS HERE, AND WHY IT WENT. A ~165-line pure-CSS device staged a brief, five ticking tool names and four
   finished-ad stills on a 20s loop. It was good and it was honest, and it told exactly two of the five things
   this product does. site/assets/hero/hero-*.webm tells all five — the brief AND the agent surface, the ad
   research nobody else's hero can show, the render actually playing, the eight-channel schedule, and the paid
   campaign read back from Meta — in 55 seconds. Two devices in the same slot doing the same job is the bloat
   Dave was reacting to when he asked for this, so the panel is deleted rather than parked beneath it. Its
   inputs are NOT deleted: /assets/console/*.jpg are now frames inside the video's own act 4.

   IT IS BUILT FROM SOURCE. tools/hero-video/ + `npm run hero:video`. A screen-recorded hero goes stale the day
   the UI moves and only a human with a screen recorder can refresh it; this one is a text file and a command.

   THE TWO CUTS ARE TWO ELEMENTS, not two <source media> attributes on one, and that is load-bearing three
   times over: each cut keeps its OWN poster (a 15:8 poster letterboxed into a 2:3 box is a visible pop when
   the video takes over), each keeps its own aspect-ratio so the box is the right shape BEFORE a byte arrives
   (CLS 0), and the hidden one never loads — site.v17.js's `video[data-auto]` observer plays on intersection,
   and an element inside `display:none` never intersects, so with preload="none" it costs zero bytes. The
   poster-shield <img> the same script injects lands INSIDE the hidden wrapper, so it hides with it.

   H.264 ONLY. VP9/webm was built, shipped first (Postiz serves webm) and then MEASURED: at 402 in real,
   headful Chrome it died on PIPELINE_ERROR_DECODE 3 loads in 12, against 12/12 for the mp4 and 12/12 for the
   h264 clip this site already ships. The mp4s are also the SMALLER files here. See tools/hero-video/README.md.

   NO NEW JAVASCRIPT. `data-auto` already gives us: play/pause on intersection, muted+playsinline+loop forced,
   prefers-reduced-motion AND save-data respected (neither ever calls play(), so preload="none" downloads
   nothing and the poster attribute is what renders), and the poster shield that kills the blank-frame flash.
   ═══════════════════════════════════════════════════════════════════════════════════════════════════════════ */
.wiw{ padding:clamp(84px,11vw,132px) 0; scroll-margin-top:84px; }

.wiwv{ margin:clamp(34px,4.4vw,58px) auto 0; max-width:1180px; }
.wiwv-cut{ position:relative; border-radius:var(--r-lg); overflow:hidden; background:var(--bg-2);
  border:1px solid var(--line); line-height:0; }
.wiwv-cut video{ display:block; width:100%; height:auto; }
/* THE SHAPE IS DECLARED, NEVER INFERRED. Without an aspect-ratio the box is 0px tall until metadata arrives
   and then jumps to ~600px — the single largest layout shift this page could have, on the block a visitor
   scrolls to first. Each cut declares its own, matching what tools/build-hero-video.mjs renders. */
.wiwv-w video, .wiwv-w img.pshield{ aspect-ratio:15/8; object-fit:cover; }
.wiwv-t video, .wiwv-t img.pshield{ aspect-ratio:2/3;  object-fit:cover; }

.wiwv-t{ display:none; }
@media (max-width:700px){
  .wiwv-w{ display:none; }
  .wiwv-t{ display:block; }
  .wiwv{ margin-top:clamp(24px,5vw,34px); }
}
