/* ===================================================================
   RevRep — single source of truth. Tokens defined ONCE here; every
   component (including the signature .choice / .setup / .does /
   .section--cinema modules) reads from these. Fonts are loaded via
   <link rel="preload" + stylesheet> in each HTML <head> so they
   stream in parallel with this stylesheet.
   =================================================================== */

:root{
  /* Fonts — display (wordmark + headings) uses General Sans via Fontshare; body uses Inter
     via Google Fonts. The seal r² stays Georgia per brand sheet. */
  --font-body:    'Inter', system-ui, -apple-system, Segoe UI, sans-serif;
  --font-display: 'General Sans', 'Inter', system-ui, sans-serif;
  --font-seal:    'Georgia', 'Gelasio', 'Times New Roman', serif;

  /* Ink + neutrals (Ink #1A1A17 per brand sheet) */
  --ink:#1A1A17;
  --ink-soft:#3d4651;       /* primary secondary text — body copy */
  --muted:#5b6470;          /* tertiary text — captions, sub-labels */
  --stone:#C9A66B;          /* Kiwi tan — warm accent + .ai suffix */
  --cream:#FAF7F0;          /* Cream — background & base, on-green text */
  --bg:#ffffff;
  --bg-soft:#FAF7F0;        /* soft sections now sit on brand Cream */
  --bg-softer:#f1ecde;
  --line:rgba(26,26,23,.10);
  --line-strong:rgba(26,26,23,.16);

  /* Brand — Revenue Green #83C702 is the provisional primary. The token NAMES kept as
     --brand-green* because they're consumed in 50+ places; treat them as "brand primary".
     Per brand sheet: "the primary color can be swapped everywhere in seconds." */
  --brand-green:#3E9142;
  --brand-green-dark:#356F3A;
  --brand-green-deep:#356F3A;
  --brand-green-ink:#1a2e10;
  --brand-green-bright:#5FBE66;
  --brand-green-soft:rgba(62,145,66,.12);

  /* Dark/hero surface */
  --hero-bg:#0a0e11;
  --hero-ink:#f4f6f5;
  --hero-muted:rgba(244,246,245,.66);
  --hero-line:rgba(244,246,245,.12);
  --glass:rgba(13,19,21,.62);

  /* Layout */
  --maxw:1200px;
  --radius:14px;
  --radius-lg:20px;

  /* Motion — ONE easing, ONE duration scale, ONE reveal distance */
  --motion-ease:    cubic-bezier(.2, .7, .2, 1);
  --motion-fast:    .22s;
  --motion-base:    .36s;
  --motion-slow:    .55s;
  --motion-rise:    14px;
  --motion-stagger: 90ms;
}

*{ box-sizing:border-box; margin:0; padding:0; }
html{ scroll-behavior:smooth; }
body{ font-family:var(--font-body); color:var(--ink); background:var(--bg); line-height:1.6; -webkit-font-smoothing:antialiased; }
/* Defensive: inline <style>/<script> blocks inside <body> sit between sections in this
   project; UA stylesheets set them display:none but be explicit so no anonymous block
   from a whitespace text node ever creates a line-height-sized gap between dark sections. */
body > style, body > script { display: none !important; }
/* When two .section--dark blocks (or .whyus + .section--dark) sit next to each other, force
   the lower one to start exactly where the upper one ends so the white body bg can never
   bleed through a sub-pixel gap. */
.section--dark + .section--dark,
.whyus + .section--dark,
.whyus + style + script + .section--dark,
.whyus + style + .section--dark,
.whyus + script + .section--dark { margin-top: -4px; }
img{ max-width:100%; display:block; }
a{ color:inherit; text-decoration:none; }
/* Keyboard focus — visible ring for tab users, invisible to mouse/touch (:focus-visible). */
:where(a, button, input, select, textarea, [tabindex]):focus-visible{
  outline:2px solid var(--brand-green); outline-offset:2px; border-radius:4px;
}

.wrap{ max-width:var(--maxw); margin:0 auto; padding:0 2rem; }
h1,h2,h3{ font-family:var(--font-display); font-weight:600; letter-spacing:-.02em; line-height:1.05; }
.eyebrow{ display:inline-flex; align-items:center; gap:.55rem; font-size:.76rem; letter-spacing:.06em; text-transform:uppercase; font-weight:500; color:var(--brand-green-deep); }
.eyebrow--light{ color:var(--hero-ink); background:var(--brand-green-soft); border:1px solid rgba(95,190,102,.35); padding:.4rem .85rem; border-radius:999px; }
.eyebrow--on-dark{ color:var(--brand-green-bright); }
.eyebrow .dot{ width:7px; height:7px; border-radius:50%; background:var(--brand-green-bright); box-shadow:0 0 0 0 rgba(95,190,102,.6); animation:pulse 1.9s infinite; }

/* ---------- buttons ---------- */
.btn{ display:inline-flex; align-items:center; gap:.5rem; font-family:var(--font-body); font-weight:500; font-size:1rem; padding:.82rem 1.45rem; border-radius:12px; cursor:pointer; border:1px solid transparent; transition:transform .14s ease, background .2s ease, border-color .2s ease; }
.btn:active{ transform:scale(.98); }
.btn--primary{ background:var(--brand-green); color:#fff; transition:background .15s ease, transform .05s ease; }
.btn--primary:hover{ background:var(--brand-green-dark); }
.btn--primary:active{ transform:translateY(1px); }
.btn--ghost{ background:transparent; border-color:var(--line-strong); color:var(--ink); }
.btn--ghost:hover{ background:var(--bg-soft); }
.btn--ghost-light{ background:transparent; border-color:var(--hero-line); color:var(--hero-ink); }
.btn--ghost-light:hover{ background:rgba(244,246,245,.07); }
.btn--lg{ padding:1rem 1.7rem; font-size:1.05rem; }

/* ---------- nav ---------- */
.nav{ position:sticky; top:0; z-index:50; background:rgba(255,255,255,.86); backdrop-filter:blur(10px); border-bottom:1px solid var(--line); }
/* Full-width balanced header: logo pinned to the LEFT gutter, nav spread across the
   MIDDLE (flex:1 + centered), "Schedule a demo" pinned to the RIGHT gutter. Equal 56px
   side gutters, capped at 1600px on ultrawide, ~88px tall. */
.nav__row{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:0;
  width:100%;
  height:88px;
  max-width:1600px;
  margin:0 auto;
  padding:0 56px;
}
/* ---------- brand lockup (r² seal + revrep.ai wordmark) ----------
   Per brand sheet: the r² seal carries the green; "revrep" wordmark is in Ink (Fraunces
   Medium); the ".ai" suffix is always Stone. On dark surfaces, swap wordmark color to Cream
   via the `.brand--reversed` modifier (the footer uses it automatically). */
.brand{ display:inline-flex; align-items:center; gap:1.1rem; font-family:var(--font-display); font-weight:500; font-size:2.6rem; letter-spacing:-.005em; line-height:1; color:var(--ink); }
/* Inline-block + matching line-height vertically centers the text; `r` and the <sup> sit
   on the same baseline naturally because they're inline. */
.brand__seal{ display:inline-block; width:128px; height:128px; line-height:128px; text-align:center;
  border-radius:50%; background:var(--brand-green); color:var(--cream);
  font-family:var(--font-seal); font-weight:500; font-size:5.5rem;
  flex:none; padding-right:4px; }
.brand__seal sup{ font-size:.58em; font-weight:400; vertical-align:super; line-height:0; margin-left:1px; }
.brand__wordmark{ font-family:var(--font-display); font-weight:500; }
.brand__ai{ color:var(--stone); font-weight:500; }
/* Reversed lockup — used on dark surfaces (footer, dark sections). Seal stays green; wordmark
   flips to Cream while .ai stays Stone for consistency with the printed brand sheet. */
.brand--reversed, .footer .brand{ color:var(--cream); }
.brand--reversed .brand__seal, .footer .brand .brand__seal{ background:var(--brand-green); color:var(--cream); }
/* Nav sits in the middle zone: grow to fill the space between logo and CTA, and center
   its own links with a generous 48px gap so they spread across the width. */
.nav__links{ flex:1; display:flex; align-items:center; justify-content:center; gap:48px; }
.nav__links a{ white-space:nowrap; }
/* Nav-scoped brand shrink so the r² lockup balances the three zones inside the 88px row
   (the full-size 128px seal is kept for the footer / dark surfaces). */
.nav .brand{ font-size:2.1rem; gap:0.8rem; }
.nav .brand__seal{ width:62px; height:62px; line-height:62px; font-size:3rem; padding-right:2px; }
.nav__links a{ font-weight:500; color:var(--ink-soft); transition:color .2s; }
.nav__links a:hover{ color:var(--ink); }
.nav__cta{ display:flex; align-items:center; gap:1.25rem; }
/* Nav CTA scaled up to balance the larger logo (desktop; mobile shrinks it back below). */
.nav__cta .btn--primary{ padding:14px 28px; font-size:1.08rem; }
.nav__toggle{ display:none; background:none; border:0; cursor:pointer; }

/* ---------- Nav mobile (<900px) — logo left, button right, links → hamburger ----------
   Links collapse into the hamburger; seal / wordmark / CTA compressed to fit. */
@media (max-width: 900px){
  .nav__row{
    /* Mobile: shrink, hide links, kill the desktop cap so the row hugs viewport edges. */
    height: 88px;
    max-width: none;
    padding: 0 1.25rem;
    gap: 0;
  }
  .nav__row .nav__links{ display:none; }
  /* Hamburger-opened dropdown panel (JS toggles .open on .nav__links). */
  .nav .nav__links.open{
    display:flex; flex-direction:column; align-items:flex-start; gap:1.1rem;
    position:absolute; top:88px; left:0; right:0;
    background:rgba(255,255,255,.98); backdrop-filter:blur(10px);
    border-bottom:1px solid var(--line); padding:1.25rem 1.5rem; z-index:60;
  }
  .brand{ font-size: 1.4rem; gap: 0.6rem; }
  .brand__seal{
    width: 56px; height: 56px; line-height: 56px;
    font-size: 2.1rem; padding-right: 2px;
  }
  .nav__cta{ gap: 0.6rem; }
  .nav__cta .btn{ padding: 0.6rem 1rem; font-size: 0.92rem; }
  .nav__toggle{
    display: grid; place-items: center;
    min-width: 44px; min-height: 44px;
    color: var(--ink);
  }
}

/* ---------- hero ---------- */
.hero{ position:relative; background:var(--hero-bg); color:var(--hero-ink); overflow:hidden;
  background-image:radial-gradient(120% 90% at 80% 0%, #16242a 0%, #0a0e11 60%); }
/* Shifted toward center (32%) so she sits out from under the call card, face center-ish.
   Tunable 25–40% — nudge in preview. object-fit:cover keeps it full-bleed, no letterboxing. */
/* Full-bleed photo. The image aspect (1800×1356 ≈ 1.33) is close to the hero box, so
   object-position can't pan her horizontally — instead translateX shifts the whole image
   to frame her in the open area right of the headline. The scrim below carries a
   viewport-pinned dark gradient on the right so the call card always floats over dark,
   independent of where the photo is shifted. Reset on mobile (below). */
.hero__media{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; object-position:50% center; opacity:.95;
  transform:translateX(-60px); }
/* Scrim: heavy darkening on the LEFT (over her wall / where the headline sits), lighter on
   the RIGHT so her face stays visible. Adds a subtle radial fade so her face has a clean
   highlight zone above the call card. */
.hero__scrim{ position:absolute; inset:0; background:
  /* Viewport-pinned dark strip on the RIGHT so the call card floats over solid hero-bg no
     matter where the photo is shifted. Solid for the rightmost ~380px (the card), fading
     to clear by 520px so her shoulder blends in rather than hard-cutting. */
  linear-gradient(270deg, var(--hero-bg) 0, var(--hero-bg) 380px, rgba(10,14,17,0) 520px),
  radial-gradient(60% 50% at 78% 38%, rgba(7,10,12,0) 0%, rgba(7,10,12,.18) 65%, rgba(7,10,12,.45) 100%),
  linear-gradient(95deg, rgba(7,10,12,.96) 0%, rgba(7,10,12,.82) 32%, rgba(7,10,12,.45) 60%, rgba(7,10,12,.55) 100%); }
/* Grid uses `stretch` so per-item align-self can pin .hero__copy top and .call bottom.
   This keeps her face (around upper-right of photo) visible ABOVE the call card. */
.hero__inner{ position:relative; z-index:2; display:grid; grid-template-columns:1.05fr .95fr; gap:3.5rem; align-items:stretch; padding:5.5rem 0 4.5rem; min-height:min(92vh, 880px); }
.hero__copy{ align-self:start; }
.hero__copy{ max-width:560px; }
.hero__eyebrow{ margin-bottom:1.5rem; }
.hero h1{ font-size:clamp(2.4rem,4.7vw,3.85rem); margin:0 0 1.35rem; }
.hero__sub{ font-size:1.15rem; color:var(--hero-muted); margin:0 0 2.1rem; max-width:31rem; }
.hero__cta{ display:flex; gap:.9rem; flex-wrap:wrap; margin-bottom:2.2rem; }
.hero__promises{ display:flex; gap:1.6rem; flex-wrap:wrap; }
.hero__promise{ display:flex; align-items:center; gap:.5rem; font-size:.92rem; color:var(--hero-muted); }
.hero__promise svg{ color:var(--brand-green-bright); flex:none; }

/* ---------- call card ---------- */
/* align-self:end pushes card to bottom of its grid cell — sits over desk/shoulder, leaving
   her face clear above. Slightly narrower than before so the card doesn't dominate the right. */
/* Narrower + bottom-anchored. Fixed body height (below) keeps total card size predictable so
   it never grows tall enough to cover her face as new messages arrive. */
.call{ background:rgba(8,14,16,.78); backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px); border:1px solid var(--hero-line); border-radius:var(--radius-lg); overflow:hidden; box-shadow:0 34px 90px -24px rgba(0,0,0,.65); width:100%; max-width:340px; justify-self:end; align-self:end; color:var(--hero-ink); transform:translateZ(0); }

/* Home hero — call card is absolutely positioned relative to .hero (full-bleed) so it
   can reach the true viewport edge. It's no longer constrained by .wrap's max-width,
   and the headline copy keeps the default 1200 wrap. See .hero .call rule below. */

/* Home hero card is wider + taller than the default — there's room for it now that the
   card is pushed far to the right, and the longer message bubbles need the space to
   avoid being clipped. Scoped to .hero so the cinema-outbound card stays compact. */
/* Home hero card — direct child of .hero (full-bleed), absolutely positioned per the
   user's exact spec: top:40px, right:40px from the true viewport edge. Width 360px,
   z-index above the scrim. Markup was moved OUT of .wrap / .hero__inner so right:40px
   lands on the true page edge, not the centered max-width boundary. */
.hero .call{
  position: absolute;
  top: clamp(120px, 24vh, 240px);  /* near her head; height-tolerant so it doesn't drift on short/tall windows */
  right: 20px;
  left: auto;
  bottom: auto;
  margin: 0;
  z-index: 5;
  max-width: 360px;
  border-radius: 16px;
  justify-self: auto;
  align-self: auto;
}

/* Below 1280px there isn't room for the card to float beside her without covering her face
   (the photo is full-bleed and she sits center-right). So from 1280px down, drop the absolute
   positioning and stack the card in normal flow below the copy — no overlap at any width.
   The floating-over-photo layout is reserved for ≥1281px, which is verified to have clearance. */
@media (max-width: 1280px){
  /* Single-column stacked hero: copy on top, her photo shown clearly, call card below. */
  .hero__inner{ grid-template-columns:1fr; gap:2.25rem; padding:3.5rem 0 4rem; align-items:start; min-height:0; }
  .hero .call{
    position: static;
    top: auto;
    right: auto;
    left: auto;
    margin: 20px auto 0;
    max-width: min(440px, 100% - 3rem);
  }
  /* Top-weighted scrim: dark behind the eyebrow/headline/copy at the top, clearing toward the
     bottom so her face reads clearly (per design choice). Overrides the desktop right-pinned scrim. */
  .hero__scrim{ background:linear-gradient(180deg,
    rgba(7,10,12,.92) 0%, rgba(7,10,12,.86) 30%, rgba(7,10,12,.5) 62%, rgba(7,10,12,.3) 100%); }
  /* Full-bleed photo, framed so her face sits in the visible lower band (tuned in verification). */
  .hero__media{ right:0 !important; left:0 !important; width:100% !important; object-position:50% 32%;
    transform:none !important; -webkit-mask-image:none !important; mask-image:none !important; }
}
.hero .call__body{ height:200px; padding:1.05rem 1.2rem; }
.call__head{ display:flex; align-items:center; gap:.75rem; padding:1rem 1.15rem; border-bottom:1px solid var(--hero-line); }
.call__avatar{ display:grid; place-items:center; width:40px; height:40px; border-radius:50%; background:var(--brand-green-soft); color:var(--brand-green-bright); flex:none; }
.call__who{ flex:1; min-width:0; }
.call__name{ display:block; font-size:.92rem; font-weight:500; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.call__status{ display:block; font-size:.78rem; color:var(--hero-muted); transition:color .3s; }
.call__status.is-done{ color:var(--brand-green-bright); }
.call__wave{ display:flex; align-items:center; gap:3px; height:22px; transition:opacity .4s; }
.call__wave i{ width:3px; height:18px; border-radius:2px; background:var(--brand-green-bright); transform-origin:center; animation:bar .9s ease-in-out infinite; }
.call__wave i:nth-child(2){ animation-delay:.15s } .call__wave i:nth-child(3){ animation-delay:.3s }
.call__wave i:nth-child(4){ animation-delay:.45s } .call__wave i:nth-child(5){ animation-delay:.6s }

/* Fixed height + overflow:hidden — the card NEVER grows as new bubbles arrive. Instead,
   the JS trims the oldest message off the top when it would overflow (see app.js). The
   mask-image fades the top so disappearing messages look elegant, not abrupt.
   Height kept tight (200px) so the card stays short and never reaches the receptionist's face. */
.call__body{ padding:.95rem 1.05rem; height:200px; overflow:hidden; display:flex; flex-direction:column; gap:.4rem; -webkit-mask-image:linear-gradient(180deg, transparent 0, #000 24px, #000 100%); mask-image:linear-gradient(180deg, transparent 0, #000 24px, #000 100%); }
.msg{ animation:rise .35s ease both; max-width:82%; margin-top:.45rem; }
.msg__label{ display:block; font-size:.66rem; letter-spacing:.05em; text-transform:uppercase; color:rgba(244,246,245,.42); margin-bottom:.28rem; }
.msg__b{ padding:.62rem .85rem; border-radius:14px; font-size:.92rem; line-height:1.45; }
.msg--ai{ align-self:flex-start; }
.msg--ai .msg__b{ background:var(--brand-green-soft); color:#d3ebdc; border:1px solid rgba(95,190,102,.28); border-bottom-left-radius:5px; }
.msg--caller{ align-self:flex-end; }
.msg--caller .msg__label{ text-align:right; }
.msg--caller .msg__b{ background:rgba(244,246,245,.08); border:1px solid var(--hero-line); border-bottom-right-radius:5px; }
.tag{ align-self:flex-start; font-size:.7rem; color:var(--brand-green-bright); background:rgba(95,190,102,.10); border:1px solid rgba(95,190,102,.22); padding:.18rem .55rem; border-radius:7px; margin-top:.15rem; animation:rise .3s ease both; }
.tag--right{ align-self:flex-end; }
.typing{ align-self:flex-start; display:inline-flex; gap:5px; padding:.7rem .85rem; background:var(--brand-green-soft); border:1px solid rgba(95,190,102,.2); border-radius:14px; border-bottom-left-radius:5px; width:auto; }
.typing i{ width:6px; height:6px; border-radius:50%; background:var(--brand-green-bright); animation:dot 1.2s infinite; }
.typing i:nth-child(2){ animation-delay:.2s } .typing i:nth-child(3){ animation-delay:.4s }
/* Old messages fade out when trimmed off the top so the card height stays fixed. */
.msg.is-leaving, .tag.is-leaving, .typing.is-leaving{ opacity:0; transform:translateY(-6px); transition:opacity .18s ease, transform .18s ease; }

.call__foot{ padding:.85rem 1.15rem; border-top:1px solid var(--hero-line); }
.chips{ display:flex; flex-wrap:wrap; gap:.45rem; }
.chip{ display:inline-flex; align-items:center; gap:.3rem; font-size:.73rem; padding:.32rem .62rem; border-radius:8px; border:1px solid var(--hero-line); color:var(--hero-muted); opacity:.42; transition:all .35s; }
.chip.is-lit{ opacity:1; background:var(--brand-green-soft); border-color:rgba(95,190,102,.4); color:#b0ddc4; }
.call__replay{ margin-top:.85rem; display:none; align-items:center; gap:.35rem; font-family:var(--font-body); font-size:.82rem; color:var(--hero-muted); background:none; border:1px solid var(--hero-line); border-radius:9px; padding:.4rem .8rem; cursor:pointer; }
.call__replay:hover{ color:var(--hero-ink); }

/* Industry switcher pills — sit between the call header and body; picking one swaps the
   demo script (see app.js DEMOS) so each visitor hears a call from their own trade. */
.call__inds{ display:flex; flex-wrap:wrap; gap:.4rem; padding:.65rem 1.15rem 0; }
.call__ind{ font-family:var(--font-body); font-size:.72rem; font-weight:500; letter-spacing:.02em; color:var(--hero-muted);
  background:rgba(244,246,245,.05); border:1px solid var(--hero-line); border-radius:999px; padding:.3rem .7rem; cursor:pointer;
  transition:color var(--motion-fast) var(--motion-ease), background var(--motion-fast) var(--motion-ease), border-color var(--motion-fast) var(--motion-ease); }
.call__ind:hover{ color:var(--hero-ink); border-color:rgba(244,246,245,.3); }
.call__ind.is-on{ color:var(--brand-green-ink); background:var(--brand-green-bright); border-color:var(--brand-green-bright); }

/* ---------- sections ---------- */
.section{ padding:5.5rem 0; }
.section--soft{ background:var(--bg-soft); }
.section--dark{ background:var(--hero-bg); color:var(--hero-ink); }
.section__head{ max-width:46rem; margin-bottom:3rem; }
.section__head.center{ margin-left:auto; margin-right:auto; text-align:center; }
.section h2{ font-size:clamp(1.85rem,3.3vw,2.6rem); margin:.9rem 0 0; }
.section--dark h2{ color:var(--hero-ink); }
.lead{ font-size:1.12rem; color:var(--ink-soft); margin-top:1.1rem; }
.section--dark .lead{ color:var(--hero-muted); }

.prose{ max-width:46rem; font-size:1.12rem; color:var(--ink-soft); }
.prose p{ margin-bottom:1.1rem; }

/* tiles / grids */
.grid{ display:grid; gap:1.1rem; }
.grid--2{ grid-template-columns:repeat(2,1fr); }
.grid--3{ grid-template-columns:repeat(3,1fr); }
.tile{ background:var(--bg); border:1px solid var(--line); border-radius:var(--radius); padding:1.6rem; }
.section--soft .tile{ background:var(--bg); }
.tile__ic{ display:grid; place-items:center; width:42px; height:42px; border-radius:11px; background:var(--brand-green-soft); color:var(--brand-green-deep); margin-bottom:1rem; }
.tile h3{ font-size:1.15rem; margin-bottom:.5rem; }
.tile p{ color:var(--ink-soft); font-size:1rem; }
.tile--dark{ background:rgba(244,246,245,.04); border-color:var(--hero-line); }
.tile--dark p{ color:var(--hero-muted); }
.tile--num{ position:relative; }
.tile__num{ font-family:var(--font-display); font-weight:700; font-size:1.1rem; color:var(--brand-green-deep); }

.reasons{ display:grid; gap:1.4rem; }
.reason{ display:grid; grid-template-columns:auto 1fr; gap:1.1rem; align-items:start; padding-bottom:1.4rem; border-bottom:1px solid var(--line); }
.reason:last-child{ border-bottom:0; }
.reason__ic{ display:grid; place-items:center; width:40px; height:40px; border-radius:11px; background:var(--brand-green-soft); color:var(--brand-green-deep); }
.reason h3{ font-size:1.2rem; margin-bottom:.4rem; }
.reason p{ color:var(--ink-soft); }

/* value table */
.value{ border:1px solid var(--line); border-radius:var(--radius-lg); overflow:hidden; max-width:48rem; }
.value__row{ display:flex; justify-content:space-between; gap:1.5rem; padding:1.1rem 1.5rem; border-bottom:1px solid var(--line); align-items:baseline; }
.value__row:last-child{ border-bottom:0; }
.value__row span:first-child{ color:var(--ink); }
.value__cost{ font-weight:500; color:var(--brand-green-deep); white-space:nowrap; font-variant-numeric:tabular-nums; }
.value__total{ background:var(--bg-soft); }
.value__total span:first-child{ font-weight:500; }

/* parts (what we run) */
.part{ display:grid; grid-template-columns:auto 1fr; gap:1.4rem; padding:2rem 0; border-bottom:1px solid var(--line); align-items:start; }
.part:last-of-type{ border-bottom:0; }
.part__n{ display:grid; place-items:center; width:46px; height:46px; border-radius:50%; background:var(--brand-green); color:var(--brand-green-ink); font-family:var(--font-display); font-weight:700; }
.part h3{ font-size:1.4rem; margin-bottom:.5rem; }
.part .kicker{ color:var(--brand-green-deep); font-weight:500; }
.part p{ color:var(--ink-soft); margin-top:.6rem; }

/* industries strip */
.strip{ display:flex; flex-wrap:wrap; gap:.6rem; margin-top:1.6rem; }
.strip span{ font-size:.92rem; padding:.45rem .9rem; border:1px solid var(--line); border-radius:999px; color:var(--ink-soft); }

/* faq */
.faq{ max-width:48rem; }
.faq__item{ border-bottom:1px solid var(--line); padding:1.5rem 0; }
.faq__q{ font-family:var(--font-display); font-weight:600; font-size:1.2rem; margin-bottom:.55rem; }
.faq__a{ color:var(--ink-soft); }

/* form */
.form{ max-width:34rem; }
.field{ margin-bottom:1.1rem; }
.field label{ display:block; font-size:.9rem; font-weight:500; margin-bottom:.4rem; }
.field input, .field select, .field textarea{ width:100%; font-family:inherit; font-size:1rem; padding:.8rem .9rem; border:1px solid var(--line-strong); border-radius:11px; background:var(--bg); color:var(--ink); }
.field input:focus, .field select:focus, .field textarea:focus{ outline:none; border-color:var(--brand-green); box-shadow:0 0 0 3px var(--brand-green-soft); }
.field textarea{ min-height:96px; resize:vertical; }
.form__note{ font-size:.9rem; color:var(--ink-soft); margin-top:.5rem; }
.form__ok{ display:none; background:var(--brand-green-soft); border:1px solid rgba(62,145,66,.3); color:var(--brand-green-deep); padding:1rem 1.2rem; border-radius:12px; font-weight:500; }

/* cta band */
.band{ text-align:center; }
.band h2{ font-size:clamp(2rem,3.6vw,2.8rem); }
.band p{ color:var(--hero-muted); max-width:38rem; margin:1.1rem auto 2rem; font-size:1.12rem; }

/* footer */
.footer{ background:var(--hero-bg); color:var(--hero-muted); padding:4rem 0 2.5rem; }
.footer__top{ display:flex; justify-content:space-between; gap:2rem; flex-wrap:wrap; padding-bottom:2.5rem; border-bottom:1px solid var(--hero-line); }
.footer__pos{ font-family:var(--font-display); font-weight:500; font-size:1.4rem; color:var(--hero-ink); max-width:30rem; line-height:1.2; }
.footer__links{ display:flex; gap:2rem; flex-wrap:wrap; }
.footer__links a{ color:var(--hero-muted); }
.footer__links a:hover{ color:var(--hero-ink); }
.footer__bottom{ display:flex; justify-content:space-between; gap:1rem; flex-wrap:wrap; padding-top:1.6rem; font-size:.88rem; }
.footer .brand{ color:var(--hero-ink); margin-bottom:.6rem; }
/* Legacy footer brand-mark rules removed — the new .brand component (r² seal lockup
   defined above) handles its own reversed variant via .footer .brand. */

/* animations */
@keyframes pulse{ 0%{ box-shadow:0 0 0 0 rgba(95,190,102,.55) } 70%{ box-shadow:0 0 0 9px rgba(95,190,102,0) } 100%{ box-shadow:0 0 0 0 rgba(95,190,102,0) } }
@keyframes bar{ 0%,100%{ transform:scaleY(.3) } 50%{ transform:scaleY(1) } }
@keyframes dot{ 0%,80%,100%{ opacity:.25 } 40%{ opacity:1 } }
@keyframes rise{ from{ opacity:0; transform:translateY(8px) } to{ opacity:1; transform:translateY(0) } }

/* responsive */
@media (max-width:960px){
  /* Hero stacking now lives in the max-width:1280px block above. Keep only the general
     responsive rules here. */
  .grid--3{ grid-template-columns:1fr 1fr; }
  .footer__top{ flex-direction:column; }
}
@media (max-width:680px){
  .wrap{ padding:0 1.25rem; }
  .nav__links{ display:none; }
  .grid--2, .grid--3{ grid-template-columns:1fr; }
  .part{ grid-template-columns:1fr; }
  .reason{ grid-template-columns:1fr; }
  .value__row{ flex-direction:column; gap:.2rem; }
  .value__cost{ align-self:flex-start; }
}

/* ---------- Scroll reveal (vanilla, no framework) ---------- */
/* Elements get .reveal added by app.js; .in flips when they enter the viewport. */
.reveal { opacity: 0; transform: translate3d(0,10px,0); transition: opacity .32s cubic-bezier(.2,.8,.2,1), transform .32s cubic-bezier(.2,.8,.2,1); }
.reveal.in { opacity: 1; transform: none; }
.reveal[data-d="1"] { transition-delay: 40ms; }
.reveal[data-d="2"] { transition-delay: 80ms; }
.reveal[data-d="3"] { transition-delay: 120ms; }
.reveal[data-d="4"] { transition-delay: 160ms; }
.reveal[data-d="5"] { transition-delay: 200ms; }
@media (prefers-reduced-motion: reduce) { .reveal { opacity: 1; transform: none; transition: none; } }

/* ---------- Cinematic photo-bg section (Outreach on what-we-run) ----------
   Mirrors the Home hero treatment so inbound + outbound feel like one system.
   - photo layer behind, scrim above, content + call card on top
   - call card narrow + bottom-anchored so the subject's face stays clear
   - Ken Burns drift + cursor parallax (transform/opacity only; killed under reduced-motion) */
.section--cinema{ position:relative; overflow:hidden; padding:0; background:var(--hero-bg); color:var(--hero-ink); isolation:isolate; }
.section--cinema .wrap{ padding-top:5rem; padding-bottom:5rem; }
/* Shorter than the home hero — keeps the call card at a comfortable mid-low position
   (not glued to the bottom of the viewport). Bumped to 720px so the wider/taller card
   below has room without crowding the copy. */
.section--cinema .hero__inner{ min-height:min(80vh, 720px); align-items:stretch; }
.section--cinema .hero__copy{ align-self:center; }
/* Match the home hero's wider+taller card so the SDR demo gets the same breathing room
   for longer message bubbles. margin-bottom lifts it off the section floor. */
.section--cinema .call{ align-self:end; max-width:400px; margin-bottom:1.5rem; }
.section--cinema .call__body{ height:280px; padding:1.05rem 1.2rem; }
/* Lead paragraph: brighter than the global --hero-muted so it stays readable over the
   monitor area where the scrim is intentionally lighter. */
.section--cinema .lead{ color:rgba(244,246,245,.92); }

/* Photo layer — slightly larger than its container so Ken Burns has room to drift
   without ever exposing an edge. translate3d transforms are GPU-friendly. */
.cinema__media{ position:absolute; inset:0; overflow:hidden; z-index:0; will-change:transform; }
.cinema__img{ position:absolute; inset:-6%; width:112%; height:112%; object-fit:cover; object-position:center; opacity:.95;
  animation:kenburns 28s ease-in-out infinite alternate; will-change:transform; }
@keyframes kenburns{
  from{ transform:translate3d(0,0,0) scale(1.00); }
  to  { transform:translate3d(-1.2%, -.8%, 0) scale(1.05); }
}

/* Scrim — LIGHTER than the Home hero so the monitor stays faintly visible behind the copy
   (reinforces the "he's working a dashboard" read). Heavier on the left where the headline
   sits, soft on the right where his face is. */
/* Darker on the left third where the headline + lead sit; still lighter than the home hero
   so the monitor stays faintly visible behind the copy (reinforces "he's working a dashboard"). */
.cinema-outbound .cinema__scrim{ position:absolute; inset:0; z-index:1; background:
  radial-gradient(55% 45% at 82% 36%, rgba(7,10,12,0) 0%, rgba(7,10,12,.15) 60%, rgba(7,10,12,.42) 100%),
  linear-gradient(95deg, rgba(7,10,12,.94) 0%, rgba(7,10,12,.82) 32%, rgba(7,10,12,.42) 60%, rgba(7,10,12,.50) 100%); }

/* Cursor-parallax targets — JS sets --px/--py in [-1, 1]. Photo and card drift on opposite
   axes for depth. Tiny amplitudes — this should be felt, not seen. */
.section--cinema[data-parallax] .cinema__media{ transform:translate3d(calc(var(--px,0) * 10px), calc(var(--py,0) * 6px), 0); transition:transform .35s cubic-bezier(.2,.8,.2,1); }
.section--cinema[data-parallax] .call{ transform:translate3d(calc(var(--px,0) * -6px), calc(var(--py,0) * -4px), 0); transition:transform .35s cubic-bezier(.2,.8,.2,1); }

/* In-view fade-up for the cinema section's copy + card (scoped — uses the global .reveal
   machinery but adds a tiny stagger). */
.section--cinema .hero__copy.reveal{ transition-delay:60ms; }
.section--cinema .call.reveal{ transition-delay:160ms; }

/* Mobile: drop the parallax (touch has no useful pointer); keep Ken Burns subtle. */
@media (max-width:960px){
  .section--cinema .wrap{ padding-top:4rem; padding-bottom:4rem; }
  .section--cinema .hero__inner{ min-height:0; }
  .section--cinema[data-parallax] .cinema__media,
  .section--cinema[data-parallax] .call{ transform:none; }
  .cinema-outbound .cinema__scrim{ background:linear-gradient(180deg, rgba(7,10,12,.86), rgba(7,10,12,.82)); }
}

/* Reduced motion — kill Ken Burns, kill parallax, instant reveal. */
@media (prefers-reduced-motion: reduce){
  .cinema__img{ animation:none; }
  .section--cinema[data-parallax] .cinema__media,
  .section--cinema[data-parallax] .call{ transform:none; transition:none; }
}

/* ---------- Consent block v2 — two-tier (RevRep /demo form) ----------
   Tier 1 = the .rr2__tier1 paragraph above submit (submission alone = baseline consent
            for a human callback).
   Tier 2 = the .rr2__row single unchecked checkbox (PEWC unlocks the AI lane).
   Tokens inherited from :root. */
.rr2{ margin:1rem 0 1.25rem; display:flex; flex-direction:column; gap:.7rem; font-family:var(--font-body); }
.rr2__tier1{ font-size:.8rem; line-height:1.45; color:var(--muted); margin:0; }
.rr2__row{ display:flex; align-items:flex-start; gap:.55rem; font-size:.8rem; line-height:1.45; color:var(--muted); }
.rr2__row input[type=checkbox]{ margin-top:.18rem; width:1rem; height:1rem; flex:none; accent-color:var(--brand-green); cursor:pointer; }
.rr2 a{ color:var(--brand-green-deep); text-decoration:underline; }
.rr2 strong{ color:var(--ink); font-weight:600; }

/* ====================================================================
   MOBILE COHESION PASS — site-wide rhythm for ≤760px (iPhone 390/430).
   ONE set of tokens, applied across every page + every section. Uses
   !important to beat per-section inline <style> blocks (which load
   after this stylesheet in document order). When a new section is
   added later, name it under the patterns below and it picks up the
   shared rhythm automatically.
   ==================================================================== */

:root{
  --section-py-mobile: 3.5rem;
  --wrap-px-mobile:    1.25rem;
}

/* Overflow safeguard — real causes are fixed below; this keeps a stray
   absolutely-positioned element from creating sideways scroll. */
html, body{ overflow-x: hidden; max-width: 100vw; }

/* iOS safe-area insets on the sticky nav so notch / Dynamic Island
   don't crop the brand or CTA on the side. The top inset is applied
   inside the @media block below so the nav still hugs the top on
   non-notch displays. */
.nav{ padding-left: env(safe-area-inset-left, 0); padding-right: env(safe-area-inset-right, 0); }

@media (max-width: 760px){

  /* ---------- 1. Section padding + wrap side padding — every section ---------- */
  .does, .choice, .choicecmp, .gap, .diff, .who, .whyus, .setup, .need, .integ,
  .svc, .ba, .prod, .parts, .oneview, .faqx, .about, .section{
    padding-top: var(--section-py-mobile) !important;
    padding-bottom: var(--section-py-mobile) !important;
  }
  .wrap, .does__wrap, .choice__wrap, .choicecmp__wrap, .gap__wrap, .diff__wrap, .who__wrap,
  .whyus__wrap, .setup__wrap, .need__wrap, .integ__wrap, .svc__wrap, .ba__wrap, .prod__wrap,
  .parts__wrap, .oneview__wrap, .faqx__wrap, .about__wrap, .ohero__wrap{
    padding-left: var(--wrap-px-mobile) !important;
    padding-right: var(--wrap-px-mobile) !important;
  }

  /* ---------- 2. Heroes — kill the iOS 100vh gap ----------
     Replace 100vh (which on iOS over-reserves height for the disappearing
     address bar) with dvh OR drop min-height entirely on mobile and let
     content sit at natural top. Eyebrow + H1 land just under the nav. */
  .hero{ min-height: 0 !important; }
  .hero__inner{
    min-height: 0 !important;
    padding: 1.5rem 0 var(--section-py-mobile) !important;
    align-items: start !important;
    gap: 1.5rem !important;
  }
  .hero h1{ font-size: clamp(2rem, 8vw, 2.6rem) !important; }
  .hero__sub{ font-size: 1rem !important; }
  /* Phone-specific hero photo framing + scrim. The tall/narrow phone box crops differently
     than tablet/desktop, so override the 1280px stacked values: keep her in frame (higher
     object-position X) and use a gentler gradient so her face reads below the copy. */
  .hero__media{ object-position: 66% center !important; }
  .hero__scrim{ background:linear-gradient(180deg,
    rgba(7,10,12,.9) 0%, rgba(7,10,12,.82) 42%, rgba(7,10,12,.58) 100%) !important; }
  /* Card stacks below copy in normal flow (static reset lives in the 1280px block above). */

  .ohero{ min-height: 0 !important; }
  .ohero__wrap{ padding-top: 1.75rem !important; padding-bottom: var(--section-py-mobile) !important; }
  .ohero__h1{ font-size: clamp(1.9rem, 7vw, 2.4rem) !important; }

  .section--cinema{ min-height: 0 !important; }
  .section--cinema .wrap{ padding-top: 1.5rem !important; padding-bottom: var(--section-py-mobile) !important; }
  .section--cinema .hero__inner{ padding: 0 !important; min-height: 0 !important; }

  /* ---------- 3. Nav — shrink, compress, hide expanded links ---------- */
  .nav__row{ height: auto !important; min-height: 64px; padding-top: env(safe-area-inset-top, 0); }
  .nav__links{ display: none !important; }
  .brand{ font-size: 1.3rem !important; gap: 0.55rem !important; }
  .brand__seal{
    width: 48px !important; height: 48px !important; line-height: 48px !important;
    font-size: 1.85rem !important; padding-right: 2px !important;
  }
  .nav__cta{ gap: 0.5rem !important; }
  .nav__cta .btn{ padding: 0.55rem 0.9rem !important; font-size: 0.9rem !important; }
  .nav__toggle{
    display: grid !important; place-items: center;
    min-width: 44px; min-height: 44px;
    color: var(--ink);
  }

  /* ---------- 4. Multi-column grids → single column ---------- */
  .choicecmp__cmp, .ba__cmp{ grid-template-columns: 1fr !important; gap: 1.25rem !important; }
  .choicecmp__vs, .ba__vs{ padding: 0.25rem 0; }
  .choicecmp__vs span, .ba__vs span{ transform: rotate(90deg); }
  .does__grid, .diff__grid, .who__grid, .whyus__grid, .gap__grid{ grid-template-columns: 1fr !important; }
  .prod__item{ grid-template-columns: 1fr !important; gap: 1rem !important; padding: 1.5rem 1.25rem !important; }
  .svc__wrap, .oneview__wrap{ grid-template-columns: 1fr !important; gap: 1.5rem !important; }

  /* Parts diagram (legacy /parts__grid 2-col): collapse */
  .parts__grid{ grid-template-columns: 1fr !important; gap: 2rem !important; }

  /* ---------- 5. Fixed-pixel visuals scaled to fit ≤390px viewport ---------- */
  /* Conductor circle on Home — narrow ring + node distances so nothing escapes */
  .choicecmp__stage{ min-height: 320px; }
  .choicecmp__ring{ width: 170px !important; height: 170px !important; }
  .choicecmp__hub{ width: 86px !important; height: 86px !important; }
  .choicecmp__hub span{ font-size: 12px !important; }
  .choicecmp__hub em{ font-size: 9px !important; }
  .choicecmp__orbit i{ transform: translate(-50%, -50%) translateY(-85px) !important; }
  .choicecmp__node{ width: 96px !important; padding: 0.4rem !important; }
  .choicecmp__node span{ font-size: 11px !important; }
  .choicecmp__node--n{ transform: translate(-50%,-50%) translateY(-118px) !important; }
  .choicecmp__node--e{ transform: translate(-50%,-50%) translateX(112px) !important; }
  .choicecmp__node--s{ transform: translate(-50%,-50%) translateY(118px) !important; }
  .choicecmp__node--w{ transform: translate(-50%,-50%) translateX(-112px) !important; }

  /* Before/After stage on What We Run — only 2 horizontal nodes, narrow them */
  .ba__stage{ min-height: 230px; }
  .ba__ring{ width: 170px !important; height: 170px !important; }
  .ba__hub{ width: 80px !important; height: 80px !important; }
  .ba__hub span{ font-size: 11px !important; }
  .ba__orbit i{ transform: translate(-50%,-50%) translateY(-85px) !important; }
  .ba__node{ width: 88px !important; padding: 0.4rem !important; }
  .ba__node--l{ transform: translate(-50%,-50%) translateX(-85px) !important; }
  .ba__node--r{ transform: translate(-50%,-50%) translateX(85px) !important; }

  /* Integrations: kill the absolute-positioned SVG stage on mobile — the
     .integ__mobile pill list already exists as the responsive fallback. */
  .integ__stage{ display: none !important; }
  .integ__mobile{ display: block !important; }

  /* OneView dashboard inner panels — narrow gutters */
  .oneview__panel, .ba__panel, .choicecmp__panel{ padding: 1.25rem !important; }
  .does__tile, .diff__row, .who__tile, .whyus__card{ padding: 1.25rem !important; }

  /* ---------- 6. Tap targets — 44px iOS minimum ---------- */
  .btn, .btn--lg{ min-height: 44px; }
  .nav__links a{ min-height: 44px; display: inline-flex; align-items: center; }
  .faqx__q, .choice__replay, .setup__replay, .call__replay, .choicecmp__replay, .ba__replay{ min-height: 44px; }
  /* Consent checkbox labels get a 44px tap row; the visible boxes themselves
     stay small for the design but the touch area on the whole label is iOS-safe. */
  .rr2__row, .rrc2__row{ min-height: 44px; align-items: center; }
  .rr2__row input[type=checkbox], .rrc2__row input[type=checkbox]{ width: 22px; height: 22px; }
  .field input, .field select, .field textarea{ min-height: 44px; font-size: 16px; /* iOS no-zoom */ }

  /* ---------- 7. Type rhythm — H1/H2 don't wrap to 4 lines at 390px ---------- */
  h1{ font-size: clamp(1.9rem, 7vw, 2.4rem) !important; }
  h2{ font-size: clamp(1.55rem, 6vw, 2rem) !important; }
  h3{ font-size: clamp(1.1rem, 4.5vw, 1.3rem) !important; }

  /* Form occupies full width — prevents the side gutter that left it cramped */
  .form{ max-width: 100% !important; }
}

/* Even tighter at sub-400px (iPhone 12/13 mini, older devices) */
@media (max-width: 400px){
  :root{ --wrap-px-mobile: 1rem; --section-py-mobile: 3rem; }
  /* Smallest screens: tighten the CTA + drop its arrow so logo, button, and the
     hamburger all fit on one row without clipping (overflow-x is hidden). */
  .nav__row{ padding: 0 1rem !important; }
  .nav__cta{ gap: 0.35rem !important; }
  .nav__cta .btn{ padding: 0.5rem 0.8rem !important; font-size: 0.82rem !important; }
  .nav__cta .btn span[aria-hidden]{ display: none !important; }
  .choicecmp__node{ width: 86px !important; }
  .choicecmp__node--e{ transform: translate(-50%,-50%) translateX(102px) !important; }
  .choicecmp__node--w{ transform: translate(-50%,-50%) translateX(-102px) !important; }
  .ba__node{ width: 80px !important; }
  .ba__node--l{ transform: translate(-50%,-50%) translateX(-78px) !important; }
  .ba__node--r{ transform: translate(-50%,-50%) translateX(78px) !important; }
  .brand__seal{ width: 44px !important; height: 44px !important; line-height: 44px !important; font-size: 1.65rem !important; }
}

/* ====================================================================
   VERTICAL RHYTHM NORMALIZATION (desktop)
   Every signature module was authored standalone with its own padding
   (5.5–7rem). That creates uneven gaps between sections — two 7rem
   sections = 224px of vertical white. Normalize all of them to ONE
   value so the page reads as a single rhythm. !important needed
   because per-module inline <style> blocks load after this file
   in document order.
   ==================================================================== */
:root{
  --section-py-desktop:       4rem;
  --section-py-first-desktop: 2.5rem; /* first section under sticky nav — tighter top */
}
.choice, .choicecmp, .does, .gap, .diff, .who, .whyus, .setup, .need, .integ,
.svc, .ba, .prod, .parts, .oneview, .faqx, .about,
.section:not(.section--dark):not(.section--cinema){
  padding-top: var(--section-py-desktop) !important;
  padding-bottom: var(--section-py-desktop) !important;
}
/* When the first content section sits directly after the sticky nav header (no hero
   image between them — e.g., the Demo, About, FAQ, How It Works, What We Run pages),
   tighten the gap so the page doesn't open with 250px of dead white. The selector
   targets a section that's the first child of <body> after the <header class="nav">. */
.nav + section,
.nav + .section,
.nav + .choice, .nav + .choicecmp, .nav + .does, .nav + .gap, .nav + .diff,
.nav + .who, .nav + .whyus, .nav + .setup, .nav + .need, .nav + .integ,
.nav + .svc, .nav + .ba, .nav + .prod, .nav + .parts, .nav + .oneview,
.nav + .faqx, .nav + .about{
  padding-top: var(--section-py-first-desktop) !important;
}
/* Dark sections that act as page headers (e.g., the How It Works / What We Run
   top bands) keep their own tighter inline padding — they're already 4.5rem. */
