
/* ==========================================================================
   ZeroRank — landing page
   Figma: LL-Website (new) · frame 9086:1122 "Frame 7" · 1920 × 10344
   --------------------------------------------------------------------------
   One self-contained file. No build step, no dependencies.

   SIX SECTIONS ARE MOUNT POINTS, not rebuilds — the animated sections already
   signed off in this project drop straight in. Search for `data-mount` and
   paste that file's style + section + script blocks inside the div:

     data-mount="hero-beams"    ← raycast-beams.html  /  glass-band-top.html
     data-mount="bento"         ← the 5-card bento grid   (node 9472:19350)
     data-mount="workflow"      ← workflow-hero.html      (node 9449:11705)
     data-mount="growth"        ← visibility-revenue-section.html (9377:5976)
     data-mount="mcp"           ← mcp-agents-section.html (node 9377:6861)
     data-mount="wall-of-love"  ← wall-of-love.html       (node 9457:11813)

   Each slot is already sized to the Figma box and shows a dashed label while
   it's empty; the label disappears on its own the moment content is pasted in
   (`:empty` selector), so there is nothing to delete afterwards.
   ========================================================================== */

:root{
  /* ── colour ───────────────────────────────────────────────────────────── */
  --zr-blue      : #1463F5;   /* primary action                              */
  --zr-blue-lit  : #0091FF;   /* radar, glows, data accents                  */
  --zr-orange    : #FD9A46;   /* "opportunity" state                         */
  --zr-ink       : #1F2328;   /* heading gradient, top stop                  */
  --zr-ink-soft  : #6E7C8E;   /* heading gradient, bottom stop               */
  --zr-body      : #525252;
  --zr-muted     : #737373;
  --zr-line      : #E5E5E5;
  --zr-line-soft : #F2F2F2;
  --zr-dark      : #232323;   /* nav pill, footer                            */
  --zr-paper     : #FFFFFF;

  --zr-head-grad : linear-gradient(180deg, var(--zr-ink) 0%, var(--zr-ink-soft) 100%);
  --zr-accent-grad: linear-gradient(95.14deg, #EB2699 55.3%, #000D72 72.53%, #0A72F4 92.67%);

  /* ── type ─────────────────────────────────────────────────────────────── */
  --zr-font: "Geist", ui-sans-serif, -apple-system, "Segoe UI", Inter, Roboto, sans-serif;

  --zr-h1  : clamp(32px, 4.3vw, 58px);
  --zr-h2  : clamp(30px, 3.7vw, 56px);
  --zr-h3  : clamp(22px, 2.4vw, 38px);
  --zr-h4  : clamp(20px, 1.9vw, 29px);
  --zr-lead: clamp(14px, 1.02vw, 16px);

  /* ── layout ───────────────────────────────────────────────────────────── */
  --zr-max  : 1200px;         /* the design's content column                 */
  --zr-gut  : 24px;           /* bento gap, card gap                         */
  --zr-pad  : clamp(16px, 3vw, 40px);
  --zr-r-lg : 30px;           /* hero + big section cards                    */
  --zr-r-md : 24px;
  --zr-r-sm : 8px;

  /* ── motion ───────────────────────────────────────────────────────────── */
  --zr-ease : cubic-bezier(.22,.61,.36,1);
  --zr-slow : .9s;
}

*,*::before,*::after{ box-sizing:border-box; }

html{ -webkit-text-size-adjust:100%; scroll-behavior:smooth; }

body{
  margin:0;
  background:var(--zr-paper);
  color:var(--zr-body);
  font-family:var(--zr-font);
  font-size:16px;
  line-height:1.5;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  overflow-x:hidden;
}

img,svg{ display:block; max-width:100%; }
a{ color:inherit; text-decoration:none; }
button{ font:inherit; color:inherit; background:none; border:0; cursor:pointer; }

:where(a,button,input,summary,[tabindex]):focus-visible{
  outline:2px solid var(--zr-blue);
  outline-offset:3px;
  border-radius:4px;
}
/* The url input sets outline:0 so there is no ring *inside* the rounded box;
   the ring therefore has to live on the wrapper, or the field is a keyboard
   dead end. :focus-within rather than :has() so it works everywhere. */
.zr-field__input:focus-within{
  border-color:var(--zr-blue);
  outline:2px solid var(--zr-blue);
  outline-offset:2px;
}

/* ==========================================================================
   shared primitives
   ========================================================================== */

/* visually hidden, still read aloud */
.zr-sr{
  position:absolute; width:1px; height:1px;
  overflow:hidden; clip:rect(0 0 0 0); clip-path:inset(50%);
  white-space:nowrap;
}

.zr-wrap{
  width:100%;
  max-width:var(--zr-max);
  margin-inline:auto;
  padding-inline:var(--zr-pad);
}

/* section rhythm. Figma gaps between sections average ~120px at 1920. */
.zr-section{ padding-block:clamp(56px, 7vw, 120px); position:relative; }

/* Headings are a gradient fill in the design, not a flat colour. The
   -webkit- prefixes are load-bearing: without them Safari renders the text
   fully transparent rather than falling back to the ink colour. */
.zr-h1,.zr-h2,.zr-h3,.zr-h4{
  margin:0;
  font-weight:500;
  line-height:1.2;
  background:var(--zr-head-grad);
  -webkit-background-clip:text;
  background-clip:text;
  color:transparent;
  -webkit-text-fill-color:transparent;
}
.zr-h1{ font-size:var(--zr-h1); letter-spacing:-.028em; }
.zr-h2{ font-size:var(--zr-h2); letter-spacing:-.026em; }
.zr-h3{ font-size:var(--zr-h3); letter-spacing:-.022em; }
.zr-h4{ font-size:var(--zr-h4); letter-spacing:-.018em; }

.zr-lead{
  margin:0;
  font-size:var(--zr-lead);
  line-height:1.45;
  color:var(--zr-body);
}

/* The hero's tri-colour span, drifting like an aurora. The stop list repeats
   the Figma hues so the ramp tiles seamlessly — first and last stop match,
   which is what lets a linear 0%→200% loop run without a visible seam. */
.zr-grad-accent{
  background:linear-gradient(95.14deg,
    #EB2699  0%,  #000D72 12%, #0A72F4 24%, #4FC3F7 33%,
    #EB2699 50%,  #000D72 62%, #0A72F4 74%, #4FC3F7 83%,
    #EB2699 100%);
  background-size:200% 100%;
  -webkit-background-clip:text;
  background-clip:text;
  color:transparent;
  -webkit-text-fill-color:transparent;
  animation:zr-aurora 11s linear infinite;
}
@keyframes zr-aurora{
  from{ background-position:0% 50%; }
  to  { background-position:200% 50%; }
}

/* ── buttons ──────────────────────────────────────────────────────────────
   The design's primary button is a flat blue with an *inset* white highlight
   at the top — that inner glow is what stops it reading as a plain rectangle,
   so it survives at every size. */
/* ══ BUTTON ════════════════════════════════════════════════════════════════
   One component. A surface is chosen by setting four custom properties, so a
   new variant is four lines and never a new set of state rules.

     --btn-face   resting fill          --btn-face-hi  fill on hover
     --btn-ink    label colour          --btn-sheen    the inset top highlight

   States are carried by INSET shadow only:
     rest    a soft sheen across the top of the face, so it reads as lit
     hover   the sheen strengthens and a hairline is pressed round the inside
     active  a hard dark inset top-down, and the label drops 1px — the face
             reads as pushed into the page rather than floating above it

   Nothing casts a drop shadow, on any state. A growing outer shadow on a
   control that also moves reads as two effects competing, and the page
   already has plenty of lift.
   ─────────────────────────────────────────────────────────────────────── */
.zr-btn{
  --btn-face   : var(--zr-blue);
  --btn-face-hi: #0F53D6;
  --btn-ink    : #fff;
  --btn-sheen  : rgba(255,255,255,.35);
  --btn-sheen-hi: rgba(255,255,255,.48);
  --btn-press  : rgba(3,22,60,.45);

  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  height:48px; padding-inline:24px;
  border:0; border-radius:var(--zr-r-sm);
  background:var(--btn-face);
  color:var(--btn-ink);
  font-family:inherit; font-weight:500; font-size:16px; line-height:20px;
  white-space:nowrap; cursor:pointer;
  box-shadow:inset 0 3px 14px var(--btn-sheen);
  transition:background .16s var(--zr-ease-out-quad),
             box-shadow  .16s var(--zr-ease-out-quad),
             translate   .09s var(--zr-ease-out-quad);
}
.zr-btn:hover{
  background:var(--btn-face-hi);
  box-shadow:inset 0 3px 14px var(--btn-sheen-hi),
             inset 0 0 0 1px rgba(0,0,0,.07);
}
.zr-btn:active{
  translate:0 1px;
  box-shadow:inset 0 4px 9px var(--btn-press),
             inset 0 1px 2px var(--btn-press);
}
.zr-btn:focus-visible{ outline:2px solid var(--zr-blue); outline-offset:2px; }

/* transparent on a light ground — the nav's Log in */
.zr-btn--ghost{
  --btn-face   : transparent;
  --btn-face-hi: rgba(15,23,42,.05);
  --btn-ink    : #000;
  --btn-sheen  : transparent;
  --btn-sheen-hi: transparent;
  --btn-press  : rgba(15,23,42,.20);
}
/* a filled but quiet surface, for secondary actions next to a blue one */
.zr-btn--soft{
  --btn-face   : #F1F4F9;
  --btn-face-hi: #E7ECF4;
  --btn-ink    : var(--zr-ink);
  --btn-sheen  : rgba(255,255,255,.7);
  --btn-sheen-hi: rgba(255,255,255,.9);
  --btn-press  : rgba(15,23,42,.22);
}
/* white face on a coloured or photographic ground */
.zr-btn--light{
  --btn-face   : #fff;
  --btn-face-hi: #F4F6FA;
  --btn-ink    : var(--zr-ink);
  --btn-sheen  : rgba(255,255,255,.9);
  --btn-sheen-hi: rgba(255,255,255,1);
  --btn-press  : rgba(15,23,42,.24);
}

@media (prefers-reduced-motion:reduce){
  .zr-btn{ transition:background .16s linear, box-shadow .16s linear; }
  .zr-btn:active{ translate:0 0; }
}

/* ── hero rating row — node 96:638 ─────────────────────────────────────
   Two review scores, each a 24px brand mark against a line of copy. The
   marks ride as background images rather than <img> so the box measures
   exactly 24 square whatever the art's own ratio is — the star is drawn
   23.973 x 22.395 and centres itself inside the square, which is what the
   node does. G2 is the project's own vector (assets/src-g2.svg): the node
   exports that mark as a 150px raster, and the vector is the same glyph
   drawn sharp at any size. The star is assets/rating-star.svg, straight
   off the node. #535361 is the node's own body colour — a shade cooler
   than --zr-body, so it is spelt out rather than borrowed.
   --------------------------------------------------------------------- */
.zr-rating{
  display:flex; flex-wrap:wrap; align-items:center; justify-content:center;
  gap:32px;
  font-size:14px; line-height:22px; color:#535361;
}
.zr-rating__item{ display:flex; align-items:center; gap:10px; }
.zr-rating__mark{
  flex:none; width:24px; height:24px;
  background-repeat:no-repeat; background-position:50%; background-size:contain;
}
.zr-rating__mark--g2  { background-image:url("data:image/svg+xml,%3Csvg%20fill%3D%22%23FF492C%22%20role%3D%22img%22%20viewBox%3D%220%200%2024%2024%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Ctitle%3EG2%3C%2Ftitle%3E%3Cpath%20d%3D%22M12%200a12%2012%200%201%200%200%2024%2012%2012%200%200%200%200-24Zm.122%205.143c.45%200%20.9.044%201.342.132l-1.342%202.806C9.962%208.08%208.203%209.84%208.203%2012s1.76%203.92%203.92%203.92c.937%200%201.844-.338%202.553-.951l1.483%202.572A6.856%206.856%200%200%201%205.266%2012a6.856%206.856%200%200%201%206.856-6.856Zm3.498.49a1.262%201.262%200%200%201%20.026%200c.427%200%20.792.113%201.101.34.31.229.466.546.466.946%200%20.639-.36%201.03-1.035%201.376l-.377.191c-.403.204-.602.385-.657.706h2.05v.85h-3.101v-.144c0-.526.103-.96.314-1.306.211-.345.576-.65%201.102-.917l.242-.117c.427-.216.538-.401.538-.625%200-.266-.228-.458-.6-.458-.44%200-.773.228-1.004.694l-.592-.595c.13-.279.338-.502.619-.675a1.7%201.7%200%200%201%20.908-.266Zm-2.094%205.388h3.394l1.697%202.937-1.697%202.94-1.697-2.94H11.83l1.696-2.937Z%22%2F%3E%3C%2Fsvg%3E"); }
.zr-rating__mark--star{ background-image:url("data:image/svg+xml,%3Csvg%20preserveAspectRatio%3D%22none%22%20overflow%3D%22visible%22%20style%3D%22display%3A%20block%3B%22%20width%3D%2223.9726%22%20height%3D%2222.3951%22%20viewBox%3D%220%200%2023.9726%2022.3951%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%20%3Cg%20id%3D%22Group%202%22%3E%20%3Cpath%20id%3D%22Vector%22%20d%3D%22M23.9726%208.55915H14.8185L11.991%200L9.1534%208.55986L0%208.55057L7.41354%2013.8452L4.57742%2022.3951L11.991%2017.109L19.3959%2022.3951L16.5684%2013.8452L23.9726%208.55915Z%22%20fill%3D%22%2304DA8D%22%2F%3E%20%3Cpath%20id%3D%22Vector_2%22%20d%3D%22M17.2041%2015.7817L16.5676%2013.8459L11.9909%2017.1097L17.2041%2015.7817Z%22%20fill%3D%22%23126849%22%2F%3E%20%3C%2Fg%3E%20%3C%2Fsvg%3E"); }

/* The row is 338px as drawn. That clears a 375px viewport by 5px and a
   360px one not at all, so the gap gives way before the row is allowed
   to break the two scores onto separate lines. */
@media (max-width:400px){
  .zr-rating{ gap:20px; }
}

/* ==========================================================================
   scroll reveal — one observer drives the whole page
   ========================================================================== */
/* Easing lifted from linear.app's own stylesheet — --ease-out-quad is what
   they run every interaction on (0.1–0.16s, deliberately quick), --ease-out-quart
   the longer curve for things entering the page. */
:root{
  --zr-ease-out-quad   : cubic-bezier(.25,.46,.45,.94);
  --zr-ease-out-quart  : cubic-bezier(.165,.84,.44,1);
  --zr-ease-inout-quart: cubic-bezier(.77,0,.175,1);
}
/* Linear's entrance is a rise that resolves out of a blur rather than a plain
   fade — the blur is what makes it read as settling into place instead of
   switching on. Long curve, heavy tail, staggered by --d. */
[data-reveal]{
  opacity:0;
  translate:0 20px;
  filter:blur(7px);
  transition:opacity .9s var(--zr-ease-out-quart) var(--d,0ms),
             translate .9s var(--zr-ease-out-quart) var(--d,0ms),
             filter .72s var(--zr-ease-out-quart) var(--d,0ms);
}
[data-reveal].is-in{ opacity:1; translate:0 0; filter:blur(0); }

/* Above the fold there is nothing to wait for — the hero is on screen from
   the first paint, so it runs a shorter curve and a tighter stagger than the
   sections that earn their entrance by being scrolled to. Long enough to
   read as settling rather than switching on — the last element in lands just
   under a second. The three durations are opacity, translate, filter. */
[data-reveal="load"]{
  /* Above the fold there is nothing to wait for, so this variant does not wait
     for anything: the hidden state lives ONLY in the keyframes below and this
     rule resolves to the FINISHED state. opacity:1 here is not redundant — it
     is what overrides the opacity:0 on [data-reveal] above (same specificity,
     later in the sheet), and it is what any renderer that never runs the
     animation falls back to. tests/parity.spec.ts injects
     `*,*::before,*::after{animation:none!important;transition:none!important}`
     before every screenshot, so moving opacity:0 back up into this rule would
     photograph a blank hero in every parity capture (26 routes x 4 widths). */
  opacity:1;
  translate:0 0;
  filter:blur(0);
  /* Nothing toggles these three on a "load" element any more (.is-in now sets
     what the base rule already says), so this pair has nothing left to fire
     on. It stays because it is the measured curve these elements settle on if
     any later state does change them, and because the animation below is timed
     off exactly these numbers. */
  transition-duration:.72s, .72s, .58s;
  transition-delay:calc(var(--d, 0ms) * .75);
  /* Same .72s, same curve, same --d * .75 stagger as the transition it
     replaces. `backwards` and not `both`: backwards fill is what holds an
     element hidden through its own stagger, the way opacity:0 used to, while
     forwards fill would pin the finished keyframe over the author rules for
     good — computed filter would stay blur(0px) and translate 0px instead of
     the `none` that the prefers-reduced-motion block just below and the
     scripting:none block at the end of this sheet reset them to, and the
     no-JS specs read those two values as "still held back". Ending on the
     base rule's own values means there is nothing to pin.
     The stagger is now the floor on LCP — .zr-shot carries --d:360ms
     (util.css, .zr-x11), so the LCP candidate starts painting 270ms in rather
     than one render-blocking script fetch in. */
  animation:zr-reveal-load .72s var(--zr-ease-out-quart) calc(var(--d, 0ms) * .75) backwards;
}
/* 7px of blur across a 1120px panel is a real paint cost, and it was
   outlasting the transition — the hero settled ~250ms after the curve
   said it should. 4px still reads as settling into place and clears in
   time.
   58/72 = 80.56% is where the blur has to clear to keep the .58s it had: a
   keyframe list is per-property, so cutting the timeline there for filter
   leaves opacity and translate interpolating across the full .72s on one
   curve, which is what the three separate transition-durations did. */
@keyframes zr-reveal-load{
  from  { opacity:0; translate:0 16px; filter:blur(5px); }
  80.56%{ filter:blur(0); }
  to    { opacity:1; translate:0 0; filter:blur(0); }
}

@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto; }
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
  }
  [data-reveal]{ opacity:1; translate:none; filter:none; }
}
/* ==========================================================================
   1 — NAV                                            node 9086:1212 · 960×64
   A floating dark pill, not a full-bleed bar. It stays pinned so the CTA is
   always one click away on a 10,000px page.
   ========================================================================== */
.zr-nav{
  /* 40 is where it sits at rest; 20 is where it parks once you scroll, so the
     pill tucks up toward the edge instead of hanging in the middle of it. */
  position:sticky; top:20px; z-index:60;
  width:min(960px, calc(100% - 2 * var(--zr-pad)));
  margin:40px auto 0;
  height:64px;
  display:flex; align-items:center; justify-content:space-between;
  padding:12px 12px 12px 24px;
  /* node 9585:15722 — a white pill on a 1px #efefef hairline, not the dark bar
     the first port used. 22px radius, and the shadow is a 2px lift, not a drop. */
  border-radius:22px;
  background:#fff;
  border:1px solid #EFEFEF;
  box-shadow:0 2px 2px rgba(0,0,0,.07);
  color:var(--zr-ink);
  transition:
    box-shadow    .4s var(--zr-ease),
    background    .4s var(--zr-ease),
    width         .34s var(--zr-ease-out-quart),
    border-radius .34s var(--zr-ease-out-quart);
}
/* ── the pill draws in once you leave the top ────────────────────────────
   Width and corner only — the height stays 64px throughout, so nothing in
   the flow below it moves and the logo, links and buttons keep their size. */
.zr-nav.is-stuck{
  width:min(860px, calc(100% - 2 * var(--zr-pad)));
  border-radius:18px;
  background:rgba(255,255,255,.86);
  backdrop-filter:blur(16px) saturate(1.6);
  -webkit-backdrop-filter:blur(16px) saturate(1.6);
  box-shadow:0 10px 34px rgba(16,49,110,.14);
}

@media (prefers-reduced-motion:reduce){
  .zr-nav{ transition:none; }
}

/* One lockup now — mark and wordmark are the same SVG, so there is no gap to
   tune and no live text to keep in sync with it. currentColor does the rest:
   near-black on the white pill, the footer's own ink on #232323. */
/* max-content, or the anchor stretches: flex:0 0 auto only bites in the nav,
   where it is a flex item. In the footer it sits in a grid cell as a block
   and was spanning the full 922px column — a link that wide, with nothing
   drawn across most of it, is a trap for anyone aiming at something else. */
.zr-nav__logo{ display:flex; align-items:center; flex:0 0 auto; width:max-content; color:#18181B; }
.zr-logo__art{ height:20px; width:auto; display:block; }
.zr-foot .zr-nav__logo{ color:#fff; }

/* ── logo context menu ────────────────────────────────────────────────────
   Right-click the nav lockup and you get the two things anyone right-clicks
   a logo for, the way Framer does it, instead of the browser's own menu —
   which on an inline <svg><use> would have offered nothing useful anyway. */
.zr-logo-menu{
  position:fixed; z-index:200; min-width:196px;
  padding:6px;
  background:#fff; border:1px solid #E8E8EA; border-radius:12px;
  box-shadow:0 12px 34px rgba(16,49,110,.16), 0 2px 6px rgba(16,49,110,.08);
  opacity:0; visibility:hidden; translate:0 -4px;
  transition:opacity .13s var(--zr-ease-out-quad),
             translate .13s var(--zr-ease-out-quad),
             visibility .13s;
}
.zr-logo-menu.is-open{ opacity:1; visibility:visible; translate:0 0; }
.zr-logo-menu button{
  display:flex; align-items:center; gap:9px; width:100%;
  padding:9px 10px; border:0; border-radius:8px;
  background:none; cursor:pointer; text-align:left;
  font:500 13.5px/18px var(--zr-font); color:#27272A;
  transition:background .13s var(--zr-ease-out-quad);
}
.zr-logo-menu button:hover,
.zr-logo-menu button:focus-visible{ background:#F4F5F7; outline:none; }
.zr-logo-menu button svg{ width:15px; height:15px; flex:0 0 auto; color:#8A8A92; }
.zr-logo-menu button.is-done{ color:#0F9D58; }
.zr-logo-menu button.is-done svg{ color:#0F9D58; }
@media (prefers-reduced-motion:reduce){
  .zr-logo-menu{ transition:none; translate:0 0; }
}

.zr-nav__links{
  display:flex; align-items:center; gap:2px;
  position:absolute; left:50%; translate:-50% 0;
}
.zr-nav__link{
  display:inline-flex; align-items:center;
  padding:8px 12px; border-radius:9px;
  /* node 9585:15722 — #3f3f3f on the white pill, not the white the dark bar used */
  font-size:14px; font-weight:500; line-height:20px; color:#3F3F3F;
  transition:color .16s var(--zr-ease-out-quad),
             background .16s var(--zr-ease-out-quad);
}
/* A grey pill picks the label up, the way peec.ai does it. The padding is
   what draws it, so the links carry it at rest and the row keeps its width:
   12px of padding each side came out of the 12px gap between them. Nothing
   moves or changes weight — that would shove the three links beside it
   sideways every time the pointer crossed one. A trigger holds the pill for
   as long as its panel is up. */
.zr-nav__link:hover,
.zr-nav__link:focus-visible,
.zr-nav__link[aria-expanded="true"]{ color:var(--zr-ink); background:#F1F2F4; }

.zr-nav__cta{ display:flex; align-items:center; gap:12px; flex:0 0 auto; }
.zr-nav__cta .zr-btn{ height:40px; border-radius:20px; font-size:14px; }
.zr-nav__cta .zr-btn--ghost{ padding-inline:12px; }

.zr-nav__burger{ display:none; width:40px; height:40px; border-radius:20px; align-items:center; justify-content:center; }
.zr-nav__burger span{ display:block; width:18px; height:1.5px; background:#3F3F3F; position:relative; transition:.3s var(--zr-ease); }
.zr-nav__burger span::before,
.zr-nav__burger span::after{ content:""; position:absolute; left:0; width:18px; height:1.5px; background:#3F3F3F; transition:.3s var(--zr-ease); }
.zr-nav__burger span::before{ top:-6px; }
.zr-nav__burger span::after{ top:6px; }
.zr-nav.is-open .zr-nav__burger span{ background:transparent; }
.zr-nav.is-open .zr-nav__burger span::before{ top:0; rotate:45deg; }
.zr-nav.is-open .zr-nav__burger span::after{ top:0; rotate:-45deg; }

/* ── nav dropdown ───────────────────────────────────────── node 9242:8479
   Panel is #232323 / r30 / 10px pad holding four 207.5×263 cards at r20 with
   a 10px gap — 880px total. Anchored to the nav rather than to the trigger,
   because 880px centred on "Product" would hang off the left edge. */
.zr-nav__item{ position:relative; display:flex; align-items:center; }

.zr-nav__panel{
  position:absolute; z-index:70;
  top:calc(100% + 6px); left:50%;
  width:880px; max-width:calc(100vw - 24px);
  translate:-50% 0;
  padding:10px;
  border-radius:30px;
  background:var(--zr-dark);
  box-shadow:0 24px 60px -12px rgba(0,0,0,.45);
  opacity:0; visibility:hidden;
  scale:.985;
  transform-origin:top center;
  transition:opacity .22s var(--zr-ease), scale .22s var(--zr-ease), visibility .22s;
}
.zr-nav__panel.is-open{ opacity:1; visibility:visible; scale:1; }

/* the hover bridge — without it the 12px gap closes the menu mid-travel */
.zr-nav__panel::before{
  content:""; position:absolute; left:0; right:0; top:-14px; height:14px;
}


/* ── the Platform menu ────────────────────────────────────────────────────
   A light sheet rather than the dark card row: a labelled list of the six
   platform areas on the left, each with its own icon so they are told apart
   at a glance, and a featured panel on the right. */
.zr-nav__panel--menu{
  padding:16px;
  border-radius:18px;
  background:#fff;
  border:1px solid #ECECEC;
  box-shadow:0 26px 60px -18px rgba(16,49,110,.24);
}
/* Three panels, three widths — each sized to its own deck rather than all
   three inheriting the widest. */
.zr-nav__panel--menu{ width:720px; }
.zr-nav__panel--sol{ width:400px; }
.zr-nav__panel--res{ width:740px; }

.zr-menu{ display:flex; flex-direction:column; }
.zr-menu__label{
  font-size:12px; font-weight:500; color:#9A9AA0; letter-spacing:.01em;
  padding:0 4px 8px;
}

/* the endpoint pill's two glyphs, shared with the copy button */
.zr-menu__url-t{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.zr-menu__copy, .zr-menu__tick{ width:13px; height:13px; flex:0 0 auto; color:#9AA1AC; }
.zr-menu__tick{ display:none; color:#0F9D58; }

/* ── menu rows ────────────────────────────────────────────────────────────
   One row design across all three panels. The tile deck it replaced put the
   icon on its own line above the title, which bought a 38px chip and cost
   two rows of height per three items; at nine entries that was a wall.
   Chip geometry is still the Figma set's — a white tile on a hairline, the
   dual-tone glyph in product blue, and the label does the work.
   --------------------------------------------------------------------- */
.zr-rows{ display:grid; gap:2px; }
.zr-rows--2{ grid-template-columns:repeat(2, minmax(0,1fr)); gap:2px 18px; }

.zr-grow{
  display:flex; align-items:center; gap:11px;
  padding:9px; border-radius:11px;
  text-decoration:none; min-width:0;
  transition:background .16s var(--zr-ease-out-quad);
}
/* No lift and no shadow — the fill is the whole of it. */
.zr-grow:hover{ background:#F5F7FB; }
.zr-grow:focus-visible{ background:#F5F7FB; outline:2px solid var(--zr-blue); outline-offset:-2px; }
.zr-grow__ico{
  display:grid; place-items:center; flex:0 0 auto;
  width:32px; height:32px; border-radius:9px;
  background:#fff; border:1px solid #E4EAF7; color:var(--zr-blue);
  transition:border-color .16s var(--zr-ease-out-quad);
}
.zr-grow:hover .zr-grow__ico{ border-color:#C9D6F2; }
.zr-grow__ico svg{ width:18px; height:18px; display:block; }
.zr-grow__t{ display:flex; flex-direction:column; gap:1px; min-width:0; }
.zr-grow__t b{ font-size:13.5px; font-weight:600; letter-spacing:-.01em; color:#0F1720; line-height:1.3; }
.zr-grow__t s{
  text-decoration:none; font-size:12px; color:#8A8A92; line-height:1.3;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}

.zr-groups{ display:grid; grid-template-columns:repeat(2, minmax(0,1fr)); gap:10px 22px; align-items:start; }
.zr-group{ display:flex; flex-direction:column; gap:2px; min-width:0; }

/* ═══ nav menu CSS · generated from tools/platform-pages/nav.css ═══ */
/* ── Platform: six rows, no feature cards ─────────────────────────────────
   The only thing a row carries beyond the chip and the two lines is the
   badge, and it rides the row's own flex line rather than the text block. */
.zr-grow__new{
  margin-left:auto; align-self:center; flex:0 0 auto;
  padding:2px 7px; border-radius:6px;
  background:#E8F0FE; color:#1D4ED8;
  font-size:10.5px; font-weight:600; letter-spacing:.02em; line-height:1.55;
}

/* ── Reference: three link columns and the app ────────────────────────────
   The link columns stay fluid so the longest description sets the measure;
   the app column is fixed, because a phone that changes width with the
   viewport looks like a bug rather than a device. */
/* ── Platform: six rows and a sign-up column ──────────────────────────────
   Same card as the Reference app column — same silk, same corner treatment —
   with the product screenshot in place of the phone. */
.zr-nav__panel--plat{ width:986px; }
.zr-plat{ display:grid; grid-template-columns:minmax(0,1fr) 252px; gap:18px; align-items:stretch; }
.zr-plat__rows{ display:flex; flex-direction:column; min-width:0; }

/* The whole card is the link now — no button, no supporting line, so the
   headline gets the room the other two were taking and the screenshot can
   sit further into the corner. */
.zr-app--start{
  justify-content:flex-start; gap:8px; text-decoration:none;
  transition:box-shadow .18s var(--zr-ease-out-quad);
}
.zr-app--start:focus-visible{ outline:2px solid var(--zr-blue); outline-offset:2px; }
.zr-app--start .zr-app__h{ max-width:13ch; font-size:14.5px; line-height:1.3; }
.zr-app--start:hover .zr-app__h{ color:var(--zr-blue); }
.zr-app__shot{
  position:absolute; z-index:-1; right:-44px; bottom:-24px;
  width:182px; overflow:hidden; border-radius:11px;
  rotate:-6deg; transform-origin:100% 100%;
  box-shadow:-7px -5px 24px rgba(16,40,90,.22);
  transition:translate .22s var(--zr-ease-out-quad);
}
.zr-app--start:hover .zr-app__shot{ translate:-5px -4px; }
.zr-app__shot img{ display:block; width:100%; height:auto; }

.zr-nav__panel--res{ width:884px; }
.zr-groups--app{
  grid-template-columns:repeat(2, minmax(0,1fr)) 252px;
  gap:10px 18px; align-items:stretch;
}
/* The descriptions are now short enough to hold one line each at this column
   width, so the rows are a single height without reserving a second line for
   them. The clamp stays as the backstop: if an edit runs long that row wraps
   and grows rather than being cut mid-word. */
.zr-groups--app .zr-grow__t s{
  white-space:normal; overflow:hidden;
  display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2;
}

/* The app column takes its height from the two link columns beside it, so the
   phone is taken out of flow and tucked into the bottom-right corner — at
   148px upright it was setting the height of the whole panel. */
.zr-app{
  position:relative; isolation:isolate; overflow:hidden;
  display:flex; flex-direction:column; align-items:flex-start; gap:7px;
  padding:14px;
  /* was a 1.5px stroke that only appeared on hover — it is the card's own
     edge, so it holds at 1px whether or not the pointer is on it. inset, so
     it sits inside the 14px radius and costs no layout */
  box-shadow:inset 0 0 0 1px #BFD3F6;
  border-radius:14px;
  background:#EAF0FA center/cover no-repeat;
  background-image:url("/assets/menu-app-bg.webp");
}
.zr-app__label{ padding:0; color:#5B79A8; }
.zr-app__h{
  font-size:14px; font-weight:600; letter-spacing:-.015em; line-height:1.28;
  color:#0F1720; max-width:11ch;
}
.zr-app__stores{ display:flex; flex-direction:column; gap:6px; margin-top:2px; }
.zr-store{
  display:flex; align-items:center; gap:6px;
  padding:5px 8px; border-radius:9px;
  background:#101722; color:#fff; text-decoration:none;
  transition:background .16s var(--zr-ease-out-quad);
}
.zr-store:hover{ background:#2A3444; }
.zr-store svg{ width:14px; height:14px; flex:0 0 auto; }
.zr-store > span{ display:flex; flex-direction:column; line-height:1.14; white-space:nowrap; }
.zr-store s{ text-decoration:none; font-size:7.5px; letter-spacing:.04em; text-transform:uppercase; opacity:.68; }
.zr-store b{ font-size:10.5px; font-weight:600; letter-spacing:-.01em; }

.zr-app__phone{
  position:absolute; z-index:-1; right:-16px; bottom:-18px;
  width:104px; height:150px; overflow:hidden;
  rotate:-9deg; transform-origin:100% 100%;
  border:3px solid #101722; border-bottom:0;
  border-radius:14px 14px 0 0;
  background:#101722;
  box-shadow:-6px -4px 22px rgba(16,40,90,.22);
}
.zr-app__phone img{ display:block; width:100%; height:auto; border-radius:11px 11px 0 0; }

/* Panels are not drawn below 900px at all, but the 884px panel plus the 24px
   gutter does not fit the band just above it — drop the app column there and
   let the two link columns have the width. */
@media (max-width:1020px){
  .zr-nav__panel--plat{ width:720px; }
  .zr-plat{ grid-template-columns:minmax(0,1fr); }
  .zr-app--start{ display:none; }
}
@media (max-width:940px){
  .zr-nav__panel--res{ width:600px; }
  .zr-groups--app{ grid-template-columns:repeat(2, minmax(0,1fr)); }
  .zr-app{ display:none; }
}

/* The phone sheet's sub-lists are built into the nav markup on every page, so
   they need hiding above the breakpoint that uses them — without this they
   render as loose inline text across the desktop nav. */
.zr-nav__sub{ display:none; }

/* ── the phone sheet ──────────────────────────────────────────────────────
   Below 900px the panels are not drawn, so each trigger becomes a section
   header with its own list underneath. The caret is the only affordance the
   row needs — .zr-nav__link is already justify-content:space-between here,
   which is what that rule was waiting for. */
@media (max-width:900px){
  .zr-nav__item{ display:block; }
  .zr-nav__item > .zr-nav__link{ width:100%; }
  .zr-nav__item > .zr-nav__link::after{
    content:''; flex:0 0 auto; width:7px; height:7px; margin-right:2px;
    border-right:1.6px solid #9AA1AC; border-bottom:1.6px solid #9AA1AC;
    rotate:45deg; translate:0 -2px;
    transition:rotate .24s var(--zr-ease-out-quad), translate .24s var(--zr-ease-out-quad);
  }
  .zr-nav__item.is-sub > .zr-nav__link{ background:#F1F2F4; color:var(--zr-ink); }
  .zr-nav__item.is-sub > .zr-nav__link::after{ rotate:225deg; translate:0 2px; }

  /* grid-template-rows 0fr → 1fr animates a list of unknown height without
     measuring it in script */
  .zr-nav__sub{
    display:grid; grid-template-rows:0fr; grid-template-columns:minmax(0,1fr);
    transition:grid-template-rows .26s var(--zr-ease-out-quad);
  }
  .zr-nav__sub > *{ min-height:0; overflow:hidden; }
  .zr-nav__item.is-sub > .zr-nav__sub{ grid-template-rows:1fr; }
  .zr-nav__sublink{
    display:block; padding:10px 14px 10px 26px;
    border-radius:9px; text-decoration:none;
    font-size:13.5px; font-weight:500; line-height:18px; color:#5B6577;
  }
  .zr-nav__sublink:hover,
  .zr-nav__sublink:focus-visible{ background:#F5F7FB; color:var(--zr-ink); outline:none; }
  /* the sheet can outgrow a short phone once three sections are open */
  .zr-nav__links{ max-height:calc(100svh - 110px); overflow-y:auto; overscroll-behavior:contain; }
}
/* ═══ end nav menu CSS ═══ */

@media (max-width:900px){
  .zr-nav__panel--menu{ display:none; }
}


@media (max-width:900px){
  .zr-nav__panel--menu{ display:none; }
}


@media (max-width:900px){
  /* the panel is a desktop affordance; the burger sheet already lists these */
  .zr-nav__panel{ display:none; }
}

/* ==========================================================================
   2 — HERO                                          node 9086:1123 · 1880×1040
   ========================================================================== */
.zr-hero{
  --zr-hero-cut:clamp(90px, 16vw, 240px);   /* how far the shot hangs below */
  margin-bottom:0;
  position:relative;
  z-index:5;
  margin:20px;
  isolation:isolate;
  /* pull the sticky nav on top of the hero card, as in the design */
  margin-top:-104px; padding-top:104px;
}
/* The card is a layer, not the section box. That is what lets the dashboard
   overhang it — in the node the shot runs to y=1300 while the card ends at
   1060, and clipping the section would cut it off. */
.zr-hero__card{
  position:absolute; z-index:0;
  /* The card used to stop short of the section bottom (inset ... var(--zr-hero-cut))
     and cap at 1040px. That left the footage ending in a rounded rectangle, which
     read as two coloured slabs either side of the dashboard. It now runs the full
     section and is masked out at the bottom instead — one continuous wash that
     dissolves into the page, no edge anywhere. */
  inset:0;
  border-radius:var(--zr-r-lg) var(--zr-r-lg) 0 0;
  /* No border. The ring sat outside the scrim's box, so the footage showed
     through it unwashed and painted a blue hairline along the top and sides —
     the one thing a background that is supposed to dissolve must not have. */
  border:0;
  overflow:clip;
  -webkit-mask-image:linear-gradient(180deg,#000 0%,#000 46%,rgba(0,0,0,.55) 72%,transparent 96%);
          mask-image:linear-gradient(180deg,#000 0%,#000 46%,rgba(0,0,0,.55) 72%,transparent 96%);
  /* Base fill straight off the node, so the section reads correctly even
     before raycast-beams.html is mounted. The beams paint white light only —
     this gradient is what they sit on. */
  background:linear-gradient(180deg,
    #fff 52.8%,
    rgba(128,176,255,.75) 89.8%,
    rgba(0,145,255,.5) 100%);
}
.zr-hero__beams{ border-radius:inherit; }
.zr-hero__inner{
  position:relative; z-index:2;
  display:flex; flex-direction:column; align-items:center;
  padding:clamp(64px, 9vw, 170px) var(--zr-pad) 0;
}

/* — copy block — node 9086:1159 · 769 wide — */
.zr-hero__copy{
  display:flex; flex-direction:column; align-items:center; gap:18px;
  width:min(769px, 100%); text-align:center;
}
/* The two lines were nearly touching at the clamped size — the node's 1.2 is
   drawn at 56px on a 1920 frame and does not survive being scaled down. */
.zr-hero__title{ margin:0; line-height:1.3; }
/* "AI search <tile> visibility" travels as one unit, so the line breaks after
   "your" the way the node does instead of stranding "visibility" on its own. */
.zr-hero__h1b{ white-space:nowrap; }
@media (max-width:680px){
  .zr-hero__h1b{ white-space:normal; }
}

/* the sub-line with three engine pills baked into the sentence */
.zr-hero__sub{
  display:flex; flex-wrap:wrap; align-items:center; justify-content:center;
  gap:4px 6px;
  /* the three pills plus their connectors must not break across lines, so
     the row gets its own width rather than the 577px copy measure */
  width:min(760px, 100%);
  font-size:var(--zr-lead); line-height:24px; color:var(--zr-body);
}
.zr-hero__sub p{ margin:0; }
/* everything from "tracks how" to the last pill is one run */
.zr-hero__row{
  display:flex; flex-wrap:nowrap; align-items:center; justify-content:center;
  gap:4px 6px; width:100%;
}
@media (max-width:820px){ .zr-hero__row{ flex-wrap:wrap; } }
.zr-engine{
  display:inline-flex; align-items:center; gap:5px;
  padding:6px 9px;
  border:1px solid var(--_c); border-radius:6px;
  background:#fff;
  font-size:14px; line-height:17px; color:#000;
  box-shadow:inset 0 -3px 0 0 var(--_c);
  rotate:var(--_r,0deg);
  /* the pills settle into their tilt on load rather than starting there */
  animation:zr-engine-set .8s var(--zr-ease) backwards;
  animation-delay:var(--_d,0s);
}
.zr-engine svg,.zr-engine img{ width:18px; height:18px; color:var(--_c); }
.zr-engine b{ font-weight:inherit; }
/* the swap: fade down, exchange mark + label + accent, fade back */
.zr-engine{
  transition:border-color .45s var(--zr-ease), box-shadow .45s var(--zr-ease),
             rotate .55s var(--zr-ease);
}
/* Names run from "Grok" to "Perplexity", so without a floor the whole
   sentence re-wraps every three seconds. Pin the width to the longest. */
.zr-engine{ min-width:100px; justify-content:center; }
.zr-engine__in{
  display:inline-flex; align-items:center; gap:5px;
  transition:opacity .22s var(--zr-ease), translate .22s var(--zr-ease);
}
.zr-engine.is-swapping .zr-engine__in{ opacity:0; translate:0 -5px; }
@keyframes zr-engine-set{
  from{ rotate:0deg; translate:0 6px; opacity:0; }
}
.zr-engine--gpt   { --_c:#74AA9C; --_r:-1.98deg; --_d:.15s; }
.zr-engine--claude{ --_c:#F89575; --_r:4.15deg;  --_d:.28s; }
.zr-engine--google{ --_c:#DF6069; --_r:1.58deg;  --_d:.41s; }

/* — the headline's model tile — node 9585:15758 ————————————————————————
   The Figma draws a white rounded square tilted 9.31°, a 1.971px #d9d9d9
   border and a hard inset edge along the bottom, holding the engine's mark in
   full colour. Everything is in em against the 56px headline it sits in, so it
   tracks the clamped type at every width instead of needing its own steps. */
.zr-mark{
  display:inline-grid; place-items:center;
  width:1.196em; height:1.196em;
  margin-inline:.1em;
  /* Sat .2em low, which read as slumped against the baseline rather than set
     into the line. At 0 the tile's centre lands within half a pixel of the
     cap-height centre of the sentence around it — measured against Geist's
     own .71em cap. Being em-based it holds at every clamped headline size:
     it lifts ~8.8px at 44px and ~11.6px at the 58px ceiling. */
  vertical-align:0;
  rotate:9.31deg;
  border:.035em solid #D9D9D9;
  border-radius:.211em;
  background:#fff;
  box-shadow:inset 0 -.07em 0 0 #D9D9D9;
  color:var(--_c,#74AA9C);
}
.zr-mark__in{
  display:grid; place-items:center;
  width:.727em; height:.727em;
  transition:opacity .26s var(--zr-ease), translate .26s var(--zr-ease),
             rotate .26s var(--zr-ease);
}
.zr-mark.is-swapping .zr-mark__in{ opacity:0; translate:0 -.2em; rotate:-14deg; }
.zr-mark__in > *{ width:100%; height:100%; display:block; }
/* Gemini ships as the Figma export because its mark is four-colour; the other
   seven are single-colour brands, so the sprite carries them and --_c paints. */
.zr-mark[data-kind="img"] .zr-mark__svg{ display:none; }
.zr-mark:not([data-kind="img"]) .zr-mark__img{ display:none; }

.zr-hero__lede{ max-width:35em; }

/* — the analyse field — node 9086:1206 · 497×64 — */
.zr-field{
  width:min(497px, 100%);
  padding:8px;
  border-radius:13px;
  background:radial-gradient(ellipse 62% 100% at 50% 50%,
              rgba(128,199,255,.08), rgba(128,199,255,.064));
}
.zr-field__row{ display:flex; gap:12px; }
.zr-field__input{
  flex:1 1 0; min-width:0;
  display:flex; align-items:center; gap:10px;
  height:48px; padding:4px 12px;
  border:1px solid var(--zr-line); border-radius:var(--zr-r-sm);
  background:#fff;
  box-shadow:0 1px 2px rgba(0,0,0,.1);
}
.zr-field__input svg{ width:16px; height:16px; flex:0 0 auto; color:var(--zr-muted); }
.zr-field__input input{
  flex:1 1 0; min-width:0;
  border:0; outline:0; background:none;
  font:400 16px/24px var(--zr-font); color:#111;
}
.zr-field__input input::placeholder{ color:rgba(115,115,115,.4); }

/* — the product shot — node 9087:1277 · 1120×683 — */
.zr-shot{
  position:relative; z-index:6;
  width:min(1120px, 100%);
  margin:clamp(52px, 6vw, 96px) auto 0;
  border-radius:var(--zr-r-md);
  background:rgba(255,255,255,.6);
  border:1px solid rgba(255,255,255,.7);
  backdrop-filter:blur(12px);
  -webkit-backdrop-filter:blur(12px);
  box-shadow:0 40px 90px -30px rgba(16,49,110,.35);
  overflow:hidden;
}
/* Three tracks: the toolbar groups size to their contents and the address
   field takes everything between them. */
.zr-shot__bar{ display:grid; align-items:center; grid-template-columns:auto minmax(0,1fr) auto; gap:20px; padding:10px 28px; }
.zr-shot__dots{ display:flex; gap:5px; }
.zr-shot__dots i{ width:12px; height:12px; border-radius:50%; background:#D9D9D9; }
.zr-shot__dots i:nth-child(1){ background:#FF5F57; }
.zr-shot__dots i:nth-child(2){ background:#FEBC2E; }
.zr-shot__dots i:nth-child(3){ background:#28C840; }
/* ── the chrome, as macOS Safari draws it ─────────────────────────────────
   Traffic lights, sidebar toggle and back/forward on the left; the address
   field taking the whole middle; one share control on the right. Only the
   address field and the share control are links — everything else is a span,
   decoration with no hover and no target. */
.zr-shot__lead,
.zr-shot__trail{ display:flex; align-items:center; gap:2px; min-width:0; }
.zr-shot__lead{ grid-column:1; justify-self:start; gap:14px; }
.zr-shot__trail{ grid-column:3; justify-self:end; }

.zr-shot__tools{ display:flex; align-items:center; gap:2px; }
.zr-shot__tool{
  display:grid; place-items:center;
  width:26px; height:24px; border-radius:6px;
  color:#5B5B5E; text-decoration:none;
  transition:background .2s var(--zr-ease), color .2s var(--zr-ease);
}
.zr-shot__tool svg{ width:16px; height:16px; }
a.zr-shot__tool:hover{ background:rgba(0,0,0,.07); color:var(--zr-ink); }
/* forward is dimmed in Safari when there is nowhere to go forward to */
.zr-shot__tool--off{ opacity:.32; }

.zr-shot__url{
  grid-column:2; width:100%;
  display:flex; align-items:center; justify-content:center; gap:6px;
  padding:6px 14px; border-radius:8px;
  background:rgba(0,0,0,.055);
  font-size:13px; line-height:15px; letter-spacing:-.01em;
  color:#4B4B4D; text-decoration:none; white-space:nowrap;
  transition:background .25s var(--zr-ease), color .25s var(--zr-ease);
}
.zr-shot__url:hover{ background:rgba(0,0,0,.09); color:var(--zr-ink); }
.zr-shot__url svg{ width:11px; height:11px; flex:0 0 auto; opacity:.5; }

/* ── the pointer inside the mock ──────────────────────────────────────────
   The panel is a picture of an app, so the OS arrow over it reads as a real
   window. This is the product's own cursor instead — outlined rather than
   filled, and squatter and broader than a system arrow. Hotspot on the tip. */
.zr-shot{
  cursor:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='26' height='26' viewBox='0 0 30 26'%3E%3Cpath d='M4.4 2.6 25.6 10.8c1.05.4 1.05 1.9 0 2.32l-8.5 3.4a1.5 1.5 0 0 0-.84.84l-3.4 8.5c-.42 1.05-1.92 1.05-2.32 0L2.34 4.66A1.5 1.5 0 0 1 4.4 2.6Z' fill='%23fff' stroke='%232F6FED' stroke-width='2.3' stroke-linejoin='round'/%3E%3C/svg%3E") 4 3, default;
}
.zr-shot__frame{
  margin:0 10px 10px;
  border-radius:16px;
  border:1px solid rgba(0,0,0,.06);
  background:#F7F9FC;
  aspect-ratio:1091 / 620;
  overflow:hidden;
}
.zr-shot__frame img{ width:100%; height:100%; object-fit:cover; object-position:top center; }

/* the frame holds a real screenshot when you have one — drop a URL into
   #zr-dashboard's src. Until then the pale panel stands in, which is what
   the Figma placeholder shows too. */
.zr-shot__frame img{ width:100%; height:100%; object-fit:cover; object-position:top center; }
.zr-shot__frame img:not([src]),
.zr-shot__frame img[src=""]{ display:none; }

/* ==========================================================================
   3 — LOGO MARQUEE                                        node 9253:9233
   Two 840px lists in the design. One track duplicated is the same thing and
   loops seamlessly at any width.
   ========================================================================== */
/* The marquee slides up under the dashboard and runs behind it — the hero
   and the shot are raised above, so logos vanish under the card instead of
   colliding with its shadow. */
.zr-logos{
  position:relative; z-index:1;
  margin-top:calc(-1 * clamp(56px, 7.4vw, 108px));
  padding-block:0 clamp(40px,5vw,72px);
  overflow:hidden;
}
.zr-logos__mask{
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 12%,#000 88%,transparent);
          mask-image:linear-gradient(90deg,transparent,#000 12%,#000 88%,transparent);
}
.zr-logos__track{
  display:flex; width:max-content;
  animation:zr-marquee 38s linear infinite;
}
.zr-logos:hover .zr-logos__track{ animation-play-state:paused; }
.zr-logos__set{ display:flex; align-items:center; }
/* Real brand marks, pulled from each vendor's own site, then flattened to
   currentColor — two of the six ship white-on-dark wordmarks that would be
   invisible here, and six palettes in one row never hold together anyway. The
   marquee's own colour drives them all. Each SVG's ids are namespaced at build
   time because the script clones this whole set to make the loop seamless. */
.zr-logos__item{
  display:grid; place-items:center;
  width:168px; height:34px;
  color:#8A9099;
  opacity:.75;
  transition:opacity .3s var(--zr-ease), color .3s var(--zr-ease);
}
.zr-logos__item:hover{ opacity:1; color:var(--zr-ink); }
.zr-logos__item svg{ max-height:26px; max-width:146px; height:auto; width:auto; }
/* the odd one out: an icon plus type, sized to sit level with the wordmarks */
.zr-logos__item--mark{
  display:flex; align-items:center; justify-content:center; gap:8px;
  font-size:19px; font-weight:600; letter-spacing:-.02em; color:#5F6672;
}
.zr-logos__item--mark svg{ max-height:22px; max-width:22px; }
@keyframes zr-marquee{ to{ translate:-50% 0; } }

/* ==========================================================================
   4 — PULL QUOTE                                          node 9087:1276
   ========================================================================== */
.zr-quote{ padding-block:clamp(48px,6vw,96px); }
/* same two stacked washes as the LanderLab card — magenta over blue, both
   running bottom→top (node 9125:3161) */
.zr-quote__card{
  display:flex; flex-direction:column; align-items:center;
  max-width:var(--zr-max); margin-inline:auto;
  padding:clamp(40px,6vw,80px) clamp(24px,10vw,120px);
  border-radius:30px;
  background:
    linear-gradient(0deg, rgba(255,255,255,0) 0%, rgba(250,36,206,.16) 100%),
    linear-gradient(0deg, rgba(241,241,241,0) 0%, rgba(0,145,255,.10) 100%);
  border:0;
  /* the card centres on the page; the copy inside ranges left within a
     centred measure, so the quote and the byline share one left edge */
  text-align:left;
}
.zr-quote__text{
  margin:0 auto 29px;
  max-width:826px;
  width:100%;
  font-size:clamp(19px,2.2vw,32px); line-height:1.5; font-weight:400;
  letter-spacing:-.012em;
  color:var(--zr-ink);
}
/* the opening sentence carries the colour in the node — #0091ff */
.zr-quote__lead{ color:#0091FF; }
.zr-quote__foot{
  display:flex; flex-wrap:wrap; gap:24px; align-items:center;
  justify-content:space-between;
  max-width:826px; width:100%; margin-inline:auto;
}
.zr-quote__who{ display:flex; align-items:center; gap:12px; }
.zr-quote__av{
  width:64px; height:64px; border-radius:10px; flex:0 0 auto;
  /* the gradient stands in only while the portrait decodes */
  background:linear-gradient(140deg,#DCE6F7,#B9CDEE);
  object-fit:cover;
}
.zr-quote__name{ font-size:20px; font-weight:400; color:#000; line-height:1.3; }
.zr-quote__role{ font-size:16px; color:#939393; line-height:1.3; }
/* the customer's own lockup, sized as the node has it: 28 mark, 18.67 wordmark */
.zr-quote__brand{ display:flex; align-items:center; gap:7px; flex:0 0 auto; }
.zr-quote__brand-mark{ display:block; height:28px; }
.zr-quote__brand-mark svg{ height:28px; width:auto; display:block; }
.zr-quote__brand-word{ display:block; height:18.67px; }
.zr-quote__brand-word svg{ height:18.67px; width:auto; display:block; }

/* ==========================================================================
   6 — CTA BAND                                       node 9090:1692 · 1200×164
   ========================================================================== */
.zr-band{ padding-block:clamp(32px,4vw,56px); }
.zr-band__inner{
  max-width:var(--zr-max); margin-inline:auto;
  display:flex; flex-wrap:wrap; gap:24px;
  align-items:center; justify-content:space-between;
  padding:44px;
  border-radius:var(--zr-r-md);
  background:linear-gradient(100deg,#F6F9FE,#EDF3FD);
  border:1px solid var(--zr-line-soft);
}
.zr-band__copy{ max-width:649px; }
.zr-band__copy .zr-h3{ margin-bottom:14px; }
.zr-band__video{
  /* a <button> now, not a link — it opens the lightbox rather than going
     anywhere, so the UA's border, padding and font have to go */
  appearance:none; -webkit-appearance:none;
  border:0; padding:0; margin:0; font:inherit; color:inherit; cursor:pointer;
  position:relative; flex:0 0 auto;
  width:154px; aspect-ratio:154 / 93;
  border-radius:12px; overflow:hidden;
  background:linear-gradient(140deg,#1B2A44,#0B1730);
  display:grid; place-items:center;
  box-shadow:0 10px 26px rgba(11,23,48,.28);
  transition:transform .3s var(--zr-ease);
}
.zr-band__video:hover{ transform:scale(1.04); }
.zr-band__video:focus-visible{ outline:2px solid var(--zr-blue); outline-offset:3px; }
.zr-band__play{
  width:28px; height:28px; border-radius:50%;
  background:rgba(255,255,255,.92);
  display:grid; place-items:center;
}
.zr-band__play::after{
  content:""; margin-left:2px;
  border-left:10px solid #16233A;
  border-top:6px solid transparent; border-bottom:6px solid transparent;
}
.zr-band__len{
  position:absolute; right:8px; bottom:7px;
  padding:2px 6px; border-radius:5px;
  font-size:10px; line-height:14px; font-weight:500;
  color:#fff; background:rgba(6,14,32,.72);
  -webkit-backdrop-filter:blur(4px); backdrop-filter:blur(4px);
}

/* ==========================================================================
   7 — BENTO                       nodes 9127:1130 · 2126 · 2097 · 2158 · 2375
   The 5-card grid keeps the Figma column rhythm exactly: 384·384·384 with a
   24px gutter = 1200, and rows 402 / 384 / 402.
   ========================================================================== */
.zr-eyebrow{
  max-width:548px; margin:0 auto clamp(40px,5vw,72px);
  text-align:center;
  display:flex; flex-direction:column; align-items:center; gap:16px;
}
.zr-eyebrow .zr-lead{ max-width:434px; }

.zr-bento__slot{
  max-width:var(--zr-max); margin-inline:auto;
  min-height:min(1237px, 96vw);
  border-radius:var(--zr-r-lg);
}

/* ==========================================================================
   10 — CASE STUDIES                        nodes 9225:1176 · 9225:7337 · 9125:3161
   Solid colour cards, not the light ones I had: #0091FF, #4C2FD6, #8400FF,
   r30, 30px pad. The comp drew two — 685fr / 491fr on its 1200px split — but
   there are three published clients and each card is now the link to that
   client's story, so the row is even and the type steps down to fit a third
   of the width instead of a half.
   ========================================================================== */
.zr-cases{ padding-block:clamp(48px,6vw,96px) clamp(24px,3vw,40px); }
.zr-cases__grid{
  max-width:var(--zr-max); margin-inline:auto;
  display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:var(--zr-gut);
}
.zr-case{
  display:flex; flex-direction:column; justify-content:space-between; gap:32px;
  min-height:312px;
  padding:30px;
  border-radius:30px;
  color:#fff;
  background:var(--zr-blue-lit);
  transition:filter .3s var(--zr-ease);
}
.zr-case--indigo{ background:#4C2FD6; }
.zr-case--violet{ background:#8400FF; }
/* was a 3px lift on a 44px shadow — the card brightens in place instead */
.zr-case:hover{ filter:brightness(1.07); }

.zr-case__top{ display:flex; flex-direction:column; align-items:flex-start; gap:14px; }
.zr-case__num{
  font-size:clamp(44px,4.6vw,64px); font-weight:500;
  line-height:1.25; letter-spacing:-.01em;
  font-variant-numeric:tabular-nums; white-space:nowrap;
  color:#fff;
}
.zr-case__lab{
  font-size:clamp(18px,1.7vw,23px); line-height:1.3; font-weight:400;
  max-width:none;
}

.zr-case__foot{ display:flex; flex-wrap:nowrap; gap:12px; align-items:center; justify-content:space-between; }
/* the widest lockup is AdPlexity's, and at 28px it is 193px against a 297px
   foot — wide enough to push "Read more" onto a second line on that card
   alone. It shrinks to the room that is left instead. */
.zr-case__brand{ display:flex; align-items:center; gap:10px; height:28px; min-width:0; color:#fff; }
.zr-case__brand svg{ height:28px; width:auto; max-width:100%; }
.zr-case__more{ flex:0 0 auto; }
.zr-case__more{
  display:inline-flex; align-items:center; gap:6px;
  font-family:'Inter', var(--zr-font);
  font-size:16px; font-weight:500; line-height:24px; color:#fff;
}
.zr-case__more svg{ width:24px; height:24px; transition:translate .25s var(--zr-ease); }
.zr-case:hover .zr-case__more svg{ translate:4px 0; }

/* ── the LanderLab pull-quote ─────────────────────────── node 9125:3161
   Two stacked washes, both running bottom→top: magenta over blue. */
.zr-testimonial{
  display:flex; flex-direction:column; align-items:center;
  max-width:var(--zr-max); margin-inline:auto;
  padding:clamp(40px,6vw,80px) clamp(24px,10vw,120px);
  border-radius:30px;
  background:
    linear-gradient(0deg, rgba(255,255,255,0) 0%, rgba(250,36,206,.16) 100%),
    linear-gradient(0deg, rgba(241,241,241,0) 0%, rgba(0,145,255,.10) 100%);
}
.zr-testimonial{ text-align:left; }
.zr-testimonial__q{
  margin:0 auto 29px;
  max-width:920px;
  width:100%;
  font-size:clamp(20px,2.3vw,32px); line-height:1.28; font-weight:400;
  color:#000;
}
.zr-testimonial__q em{ font-style:normal; color:var(--zr-blue-lit); }
.zr-testimonial__who{
  display:flex; align-items:center; justify-content:flex-start; gap:12px;
  max-width:920px; width:100%; margin-inline:auto;
}
.zr-testimonial__av{
  width:64px; height:64px; border-radius:10px; flex:0 0 auto;
  object-fit:cover;
  background:linear-gradient(140deg,#DCE6F7,#B9CDEE);
}
.zr-testimonial__name{ font-size:20px; color:#000; line-height:1.4; }
.zr-testimonial__role{ font-size:16px; color:#939393; line-height:1.4; }

@media (max-width:820px){
  .zr-cases__grid{ grid-template-columns:1fr; }
  .zr-case{ min-height:0; gap:26px; }
  .zr-case__lab{ max-width:none; }
}

/* ==========================================================================
   13 — FAQ                                          node 9148:1641 · 1200×494
   ========================================================================== */
.zr-faq{ padding-block:clamp(56px,7vw,110px); }
.zr-faq__head{ max-width:764px; margin:0 auto clamp(40px,5vw,72px); text-align:center; display:flex; flex-direction:column; align-items:center; gap:16px; }
.zr-faq__grid{
  max-width:var(--zr-max); margin-inline:auto;
  display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:16px 24px;
  align-items:start;
}
.zr-faq__col{ display:flex; flex-direction:column; gap:16px; }
.zr-faq__item{
  border:1px solid var(--zr-line-soft); border-radius:12px;
  background:#fff;
  overflow:hidden;
  transition:border-color .3s var(--zr-ease), background .3s var(--zr-ease);
}
.zr-faq__item[open]{ border-color:rgba(20,99,245,.28); background:#FBFCFF; }
/* an open item is a click target end to end, not just its summary row */
.zr-faq__item[open] .zr-faq__wrap{ cursor:pointer; }
/* the questions wrap to one or two lines; pinning the row height keeps the two
   columns stepping together instead of drifting apart down the page */
.zr-faq__q{ min-height:64px; }
.zr-faq__q{
  display:flex; align-items:center; justify-content:space-between; gap:16px;
  padding:16px 24px;
  font-size:16px; line-height:24px; color:var(--zr-ink);
  list-style:none; cursor:pointer;
}
.zr-faq__q::-webkit-details-marker{ display:none; }
.zr-faq__sign{ position:relative; width:24px; height:24px; flex:0 0 auto; }
.zr-faq__sign::before,
.zr-faq__sign::after{
  content:""; position:absolute; left:50%; top:50%;
  background:var(--zr-muted);
  transition:rotate .3s var(--zr-ease), opacity .3s var(--zr-ease);
}
.zr-faq__sign::before{ width:13px; height:1.5px; translate:-50% -50%; }
.zr-faq__sign::after { width:1.5px; height:13px; translate:-50% -50%; }
.zr-faq__item[open] .zr-faq__sign::after{ rotate:90deg; opacity:0; }
.zr-faq__a{
  padding:0 24px 20px;
  font-size:14px; line-height:20px; color:var(--zr-body);
}
/* grid-template-rows animates cleanly where height:auto cannot */
.zr-faq__wrap{ display:grid; grid-template-rows:0fr; transition:grid-template-rows .35s var(--zr-ease); }
.zr-faq__item[open] .zr-faq__wrap{ grid-template-rows:1fr; }
.zr-faq__wrap > div{ overflow:hidden; }

/* <details> drops `open` the instant you click, which takes the answer with
   it — so the item opened smoothly and shut like a trapdoor. The script now
   holds `open` for the length of the collapse and marks the item .is-closing;
   these three rules run the open state backwards while it does. Same
   specificity as the [open] rules above, so they win by coming after. */
.zr-faq__item.is-closing .zr-faq__wrap{ grid-template-rows:0fr; }
.zr-faq__item.is-closing{ border-color:var(--zr-line-soft); background:#fff; }
.zr-faq__item.is-closing .zr-faq__sign::after{ rotate:0deg; opacity:1; }

/* ==========================================================================
   14 — FOOTER + FINAL CTA                            node 9225:1165 · 1860×931
   ========================================================================== */
/* ══ FOOTER — node 9585:15598 ══════════════════════════════════════════════
   Self-contained and page-agnostic: every link is absolute, so this block can
   be lifted into any ZeroRank page as-is. It needs four things from the host
   page — the sprite symbols #i-mark, #i-check, #i-shield, #i-pulse, #i-globe;
   the .zr-btn component; the --zr-* custom properties; and the reveal
   observer if you want the CTA to animate in (drop data-reveal if not).

   Two surfaces stacked, exactly as the node has them: a near-black #232323
   panel carrying the CTA, then a #303030 → #2c0000 wash for the link deck,
   the whole thing on one 30px radius. The light streak is the node's rotated
   rectangle, kept as a gradient rather than an export so it costs nothing.
   ─────────────────────────────────────────────────────────────────────── */
.zr-foot{
  position:relative;
  margin:20px;
  border-radius:var(--zr-r-lg);
  overflow:clip;
  background:#232323;
  color:#E7ECF3;
  isolation:isolate;
}
/* the streak across the top-right of the CTA panel */
.zr-foot::before{
  content:""; position:absolute; z-index:0; pointer-events:none;
  width:152px; height:1116px;
  right:14%; top:-262px;
  rotate:-53.59deg;
  background:linear-gradient(90deg,
    rgba(255,255,255,0) 0%, rgba(255,255,255,.055) 42%,
    rgba(255,255,255,.085) 50%, rgba(255,255,255,.055) 58%,
    rgba(255,255,255,0) 100%);
  filter:blur(26px);
}
.zr-foot > *{ position:relative; z-index:1; }

.zr-foot__cta{
  padding:clamp(56px,7vw,88px) var(--zr-pad);
  text-align:center;
  display:flex; flex-direction:column; align-items:center; gap:18px;
}
.zr-foot__cta .zr-h2{
  max-width:564px;
  background:linear-gradient(180deg,#FFFFFF,#EAEAEA);
  -webkit-background-clip:text; background-clip:text;
  letter-spacing:-.036em;
}
.zr-foot__ticks{ display:flex; flex-wrap:wrap; gap:32px; justify-content:center; }
.zr-foot__tick{ display:inline-flex; align-items:center; gap:12px; font-size:16px; line-height:24px; color:#fff; }
.zr-foot__tick svg{ width:24px; height:24px; color:rgba(255,255,255,.85); }

/* ── the link deck ──────────────────────────────────────────────────────── */
.zr-foot__main{
  padding:clamp(48px,5.6vw,72px) var(--zr-pad) clamp(36px,4vw,52px);
  background:linear-gradient(180deg,#303030 0%,#2C0000 100%);
  border-top:1px solid rgba(255,255,255,.07);
}
.zr-foot__grid{
  max-width:1240px; margin-inline:auto;
  display:grid; grid-template-columns:minmax(280px,360px) 1fr;
  gap:clamp(40px,6vw,120px);
}
.zr-foot__blurb{
  margin:24px 0 0; max-width:388px;
  font-size:18px; line-height:28px; font-weight:500; color:#DEDEDE;
}
.zr-foot__badges{ display:flex; flex-wrap:wrap; align-items:center; gap:22px; margin-top:24px; }
.zr-foot__badge{ display:inline-flex; align-items:center; gap:10px; font-size:16px; line-height:20px; color:#fff; white-space:nowrap; }
.zr-foot__badge svg{ width:18px; height:18px; color:rgba(255,255,255,.85); }
/* the node divides the two badges with a 16px hairline. It is its own element
   rather than a ::before, so it can be dropped when the pair wraps — a rule
   hanging off the start of a line reads as a mistake. */
.zr-foot__rule{ width:1px; height:16px; background:rgba(255,255,255,.28); flex:none; }
@media (max-width:1100px){
  .zr-foot__rule{ display:none; }
}
.zr-foot__cols{ display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:32px; }
.zr-foot__h{ margin:0 0 24px; font-size:20px; font-weight:500; line-height:28px; color:#fff; }
.zr-foot__list{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:16px; }
.zr-foot__list a{
  font-size:16px; line-height:24px; color:rgba(255,255,255,.8);
  transition:color .16s var(--zr-ease-out-quad);
}
.zr-foot__list a:hover{ color:#fff; }

.zr-foot__bar{
  max-width:1240px; margin:clamp(36px,4vw,56px) auto 0;
  padding-top:24px;
  display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:16px;
  font-size:15px; line-height:28px; color:rgba(222,222,222,.4);
  border-top:1px solid rgba(255,255,255,.08);
}
.zr-foot__legal{ display:flex; flex-wrap:wrap; gap:24px; }
.zr-foot__legal a{ color:rgba(222,222,222,.4); transition:color .16s var(--zr-ease-out-quad); }
.zr-foot__legal a:hover{ color:rgba(255,255,255,.85); }

@media (max-width:1100px){
  .zr-foot__grid{ grid-template-columns:1fr; }
  .zr-foot__cols{ grid-template-columns:repeat(4,minmax(0,1fr)); }
}
@media (max-width:720px){
  .zr-foot__cols{ grid-template-columns:1fr 1fr; gap:36px 20px; }
  .zr-foot__bar{ justify-content:flex-start; }
}

/* ==========================================================================
   RESPONSIVE
   The design is a 1200px column inside a 1920 frame. Everything above is
   fluid, so these are structural changes only — no type snapping.
   ========================================================================== */

@media (max-width:1100px){
  .zr-flow__card{ grid-template-columns:1fr; }
  .zr-flow__copy .zr-lead{ max-width:none; }
  .zr-cases__grid{ grid-template-columns:1fr; }
}

@media (max-width:900px){
  .zr-nav{ top:32px; margin-top:32px; padding-right:8px; }
  .zr-nav__links{
    position:absolute; left:0; right:0; top:calc(100% + 10px);
    translate:none;
    flex-direction:column; align-items:stretch; gap:2px;
    padding:10px;
    border-radius:20px;
    background:rgba(255,255,255,.97);
    border:1px solid #EFEFEF;
    backdrop-filter:blur(14px);
    -webkit-backdrop-filter:blur(14px);
    box-shadow:0 20px 40px rgba(16,49,110,.16);
    opacity:0; visibility:hidden; translate:0 -8px;
    transition:opacity .3s var(--zr-ease), translate .3s var(--zr-ease), visibility .3s;
  }
  .zr-nav.is-open .zr-nav__links{ opacity:1; visibility:visible; translate:0 0; }
  .zr-nav__link{ padding:12px 14px; justify-content:space-between; }
  .zr-nav__burger{ display:flex; }
  .zr-nav__cta .zr-btn--ghost{ display:none; }

  .zr-hero{ margin:12px; margin-top:-92px; padding-top:92px; }
  .zr-hero__card{ border-radius:var(--zr-r-md); }
  .zr-growth__stats{ grid-template-columns:1fr; gap:24px; }
  .zr-faq__grid{ grid-template-columns:1fr; }
  .zr-foot__grid{ grid-template-columns:1fr; gap:48px; }
  .zr-band__inner{ padding:28px; }
}

@media (max-width:680px){
  :root{ --zr-gut:14px; }
  .zr-hero__inner{ padding-top:64px; }
  .zr-hero__sub{ gap:6px; }
  .zr-engine{ rotate:0deg; animation:none; }
  .zr-field__row{ flex-direction:column; }
  .zr-field__row .zr-btn{ width:100%; }
  .zr-shot__url{ padding:5px 10px; font-size:12px; }
  .zr-shot__tools, .zr-shot__trail{ display:none; }
  .zr-quote__foot{ flex-direction:column; align-items:flex-start; }
  .zr-case__top{ flex-direction:column; align-items:flex-start; gap:12px; }
  .zr-foot__cols{ grid-template-columns:1fr 1fr; gap:28px 20px; }
  .zr-foot{ margin:12px; }
  /* the radar is 1.8:1 — on a phone it reads better cropped than shrunk */
  .zr-radar__stage{ width:150%; margin-left:-25%; }
  .zr-love__head{ margin-top:-40px; }
}


/* ==========================================================================
   HERO — ONE VIEWPORT, 20px ALL ROUND                          (desktop only)
   --------------------------------------------------------------------------
   Nav sits 20 from the top and is 64 tall, so it ends at 84. Pulling the hero
   up by exactly 64 puts its top edge at 20, and a height of 100svh − 40 puts
   its bottom edge at 100svh − 20. The 20px side margins were already there.

   svh not vh — on mobile Safari `vh` is the *largest* viewport, so the hero
   would run under the toolbar.

   The dashboard is the point of the hero, so it gets a GUARANTEED share of
   the height (min-height 44%) and the copy above it scales with the viewport
   to make room. Previously the copy was fixed and the dashboard absorbed
   whatever was left — which on a 720-tall laptop left it 227px and looking
   like a stub.
   ========================================================================== */
@media (min-width:1025px){
  :root{
    /* type now answers to viewport HEIGHT as well as width, so a short
       laptop shrinks the headline instead of crushing the dashboard */
    --zr-h1  : clamp(30px, min(4.3vw, 6.3vh), 56px);
    --zr-lead: clamp(13px, min(1.02vw, 1.85vh), 16px);
  }

  .zr-hero{
    margin-top:-84px;
    padding-top:84px;
    display:flex; flex-direction:column;
  }
  /* Card top edge at 20, bottom at 100svh − 20 — one viewport, inset 20 all
     round, exactly as before. What changed is that the SECTION is now free
     to run past it so the dashboard can be shown in full. */
  .zr-hero__card{
    inset:0;
    height:auto;
    min-height:560px;
  }

  .zr-hero__inner{
    flex:1 1 auto; min-height:0;
    display:flex; flex-direction:column;
    /* The nav ends at 84 and the rating row began ~52 under it — too tight a
       shelf for a floating pill to sit on. Roughly 1.7x that now; it costs
       the dashboard nothing, since the shot is free to overhang. */
    padding-top:clamp(30px, 5.4vh, 88px);
  }

  .zr-hero__copy{ flex:0 0 auto; gap:clamp(9px, 1.5vh, 18px); }
  .zr-field{ padding:6px; }
  .zr-field__input, .zr-field .zr-btn{ height:44px; }

  /* The dashboard is shown WHOLE at its own 1200x700 ratio — nothing
     cropped. It no longer fits inside the card, so it overhangs onto the
     page below, which is what the Figma does too (card ends 1060, the shot
     runs on to 1300). The card itself still measures exactly one viewport
     less the 20px inset; the section around it grows to fit the shot. */
  .zr-shot{
    flex:0 0 auto;
    display:flex; flex-direction:column;
    /* 24px put the dashboard almost against the field. It reads as its own
       object with air above it. */
    margin-top:clamp(20px, 3.4vh, 48px);
  }
  .zr-shot__bar{ padding:8px 20px; flex:0 0 auto; }
  .zr-shot__frame{
    flex:0 0 auto;
    aspect-ratio:1200 / 700;   /* exactly the dashboard, so no crop */
    margin:0 8px 8px;
  }

  /* The marquee runs under the dashboard here too, so the logos sit on the
     tail of the video wash rather than on bare page white below it. The pull-up
     is what tucks the section under the panel; the matching top padding is what
     keeps the logos themselves clear of it — without it the row lands squarely
     behind the dashboard and you see nothing. */
  .zr-logos{
    margin-top:calc(-1 * clamp(40px, 5vw, 84px));
    padding-block:clamp(52px, 6.4vw, 98px) clamp(30px,3.6vw,52px);
  }
}

/* ── store buttons: coming soon (ADR-21) ───────────────────────────────
   The apps are not in the stores yet: the pills are plain text, dimmed, and
   do not react to hover. */
.zr-store--soon{ opacity:.55; cursor:default; }
.zr-store--soon:hover{ background:#101722; }

/* ── no scripting: nothing ever adds .is-in, so no [data-reveal] block may wait for it (ADR-22).
   Still load-bearing for the SCROLL variant, which has no other way in: the observer is the only thing that
   adds .is-in to it. The "load" variant reveals itself with a keyframe now and would not need this rule, but
   that animation is switched off under scripting:none at the end of this sheet, so here too this rule is the
   whole story: without a script the page is visible on the first frame, not a second of fade later.
   Descendants that other sheets gate on the parent's .is-in (.zr-bento .zr-dk in ui.css, .zr-feats li in
   prompts.css, the .vg-row family in vig.css) are not covered: the legacy pages keep blank interiors there. ── */
@media (scripting:none){
  [data-reveal]{ opacity:1; translate:none; filter:none; }
}

/* ── where the hero's own animation must not run at all ──
   · prefers-reduced-motion: the *,*::before,*::after rule up in the reveal section shortens every
     animation-duration to .001ms but says nothing about animation-delay, so the backwards fill would still
     hold the hero invisible for the whole stagger — up to 270ms, .zr-shot's --d of 360ms × .75 — and then
     snap it in, which is the flash that block exists to prevent.
   · scripting:none (ADR-22): nothing there is waiting on a script, so the animation buys nothing, and it
     would leave the load elements mid-fade for about a second after load — the state the four no-JS specs
     (wall, university, ambassador, zindex) read as "still held back" when they assert every [data-reveal]
     is at opacity 1 with filter and translate `none` the moment the page fires load.
   Dropping the animation leaves the base rule, which is already the finished, visible state. */
@media (prefers-reduced-motion:reduce), (scripting:none){
  [data-reveal="load"]{ animation:none; }
}
