/* ============================================================
   getnessi.ai v2 — film → home → setup → ceremony → handoff

   Sources, in order of authority:
     new_design/…/uploads/GETNESSI-SITE-SPEC.md   copy and sequence
     new_design/…/Nessi Site v2.dc.html           visual reference
     new_design/…/HANDOFF-v2.md                   the send CTA, the typewriter

   The styleguide.md shipped alongside those is the v1 document (cyan,
   IBM Plex Mono, twelve-card storm) and does NOT describe this design.
   v2 is Newsreader for headlines, Schibsted Grotesk for UI, no monospace
   anywhere, teal #7FDFDB for Nessi, coral #FD8360/#E2603A for the user's
   own action. iMessage blue appears exactly once — the handoff preview
   bubble depicts real software, so it carries real software's colour.

   Token names --cream/--body/--cyan etc. are inherited from v1 on
   purpose: /privacy links this sheet for tokens (see legal.v1.css) and
   keeps working unrenamed.
   ============================================================ */

:root{
  /* Base */
  --ink:#07090C;
  --raised:#0D1218;
  --field-focus:#101720;
  --panel:#0D1218;
  --surface:#10161D;
  --line:#151B22;
  --line-2:#1B222B;
  --line-3:#1B222B;
  --line-4:#253039;
  --line-hover:#2B3742;
  --line-skip:#212932;

  /* Text */
  --cream:#F4EFE7;
  --body:#D8D3CA;
  --body-2:#ADB5BF;
  --body-3:#F4EFE7;
  --lede:#ADB5BF;
  --muted:#8B949F;
  --faint:#6C7681;
  --ghost:#4F5966;

  /* Accent. Teal is Nessi; coral is the user acting. */
  --cyan:#7FDFDB;
  --cyan-deep:#2DD3CD;
  --cyan-light:#A8F5F1;
  --teal:#7FDFDB;
  --teal-deep:#2DD3CD;
  --on-cyan:#07171A;
  --coral:#FD8360;
  --coral-deep:#E2603A;
  --coral-text:#26100A;
  --send-dark:#2A1109;
  /* Semantic error red — not a brand accent. Used only for validation
     states (the phone field's error line and border); never decorative,
     the same carve-out shape as iMessage blue: errors are a state, and
     states get their conventional colour. Chosen for ≥4.5:1 on --ink. */
  --bad:#FF5F56;

  --grad-cta:linear-gradient(120deg,#FD8360,#E2603A);

  --font-sans:'Schibsted Grotesk',system-ui,-apple-system,sans-serif;
  --serif:'Newsreader',Georgia,serif;

  --col:430px;

  /* Entrances overshoot; consumption accelerates away. */
  --enter:cubic-bezier(.16,1,.3,1);
  --converge:cubic-bezier(.55,0,.35,1);
  --pop:cubic-bezier(.2,1.2,.3,1);
}

*{box-sizing:border-box}
html,body{margin:0;padding:0;background:var(--ink);-webkit-text-size-adjust:100%;overscroll-behavior-y:none}
button,a,input{-webkit-tap-highlight-color:transparent;touch-action:manipulation}
button{font-family:inherit}
input{font-family:inherit}
a{color:var(--teal);text-decoration:none}
a:hover{color:var(--cyan-light)}

body{
  font-family:var(--font-sans);
  color:var(--cream);
  -webkit-font-smoothing:antialiased;
}

.stage{display:flex;justify-content:center;min-height:100dvh}

/* The 430px column on a wider field. Light falls from above. */
.frame{
  position:relative;
  width:100%;max-width:var(--col);min-height:100dvh;
  overflow:hidden;
  background:radial-gradient(125% 72% at 50% -8%,#0E141A 0%,#07090C 60%);
}

.view{
  position:absolute;inset:0;
  opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .45s var(--enter),visibility 0s linear .45s;
}
.view.on{opacity:1;visibility:visible;pointer-events:auto;transition:opacity .45s var(--enter)}

:where(a,button,input):focus-visible{
  outline:2px solid var(--teal);
  outline-offset:3px;
  border-radius:6px;
}

/* ── keyframes (transcribed from Nessi Site v2.dc.html) ── */

@keyframes nsChipIn{from{opacity:0;transform:translate(var(--fx),var(--fy)) scale(.94)}to{opacity:1;transform:translate(0,0) rotate(var(--r))}}
@keyframes nsDrift{0%{transform:translate(0,0)}50%{transform:translate(-5px,-8px)}100%{transform:translate(0,0)}}
@keyframes nsDim{to{opacity:.42;filter:blur(2px) saturate(.65)}}
@keyframes nsConverge{0%{opacity:1;transform:translate(0,0) scale(1)}60%{opacity:.7}100%{opacity:0;transform:translate(var(--cx),var(--cy)) scale(.05);filter:blur(3px)}}
@keyframes nsBeat{0%{opacity:0;transform:translateY(12px)}16%{opacity:1;transform:translateY(0)}82%{opacity:1;transform:translateY(0)}100%{opacity:0;transform:translateY(-7px)}}
@keyframes nsUp{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:translateY(0)}}
@keyframes nsFade{from{opacity:0}to{opacity:1}}
@keyframes nsOut{to{opacity:0}}
@keyframes nsOrbIn{0%{opacity:0;transform:scale(.3)}100%{opacity:1;transform:scale(1)}}
@keyframes nsBreathe{0%,100%{transform:scale(1)}50%{transform:scale(1.045)}}
@keyframes nsSpin{to{transform:rotate(360deg)}}
@keyframes nsRing{0%{opacity:.38;transform:scale(.85)}100%{opacity:0;transform:scale(1.8)}}
@keyframes nsCheck{from{stroke-dashoffset:18}to{stroke-dashoffset:0}}
@keyframes nsPop{0%{opacity:0;transform:scale(.4)}60%{opacity:1;transform:scale(1.08)}100%{opacity:1;transform:scale(1)}}
@keyframes nsDot{0%,100%{box-shadow:0 0 0 0 rgba(127,223,219,.4)}50%{box-shadow:0 0 0 7px rgba(127,223,219,0)}}
@keyframes nsCaret{0%,46%{opacity:1}50%,96%{opacity:0}100%{opacity:1}}
@keyframes nsSweep{0%{transform:translateX(-130%)}55%,100%{transform:translateX(130%)}}
@keyframes nsHalo{0%{opacity:.5;transform:scale(.99)}100%{opacity:0;transform:scale(1.055)}}
@keyframes nsLift{0%,100%{transform:translateY(0);box-shadow:0 12px 30px rgba(226,96,58,.28)}50%{transform:translateY(-3px);box-shadow:0 20px 44px rgba(226,96,58,.4)}}
@keyframes nsNudge{0%,62%,100%{transform:translate(0,0)}74%{transform:translate(3px,-3px)}86%{transform:translate(1px,-1px)}}

/* ── the shared Skip ──────────────────────────────────── */

.skip{
  position:absolute;right:16px;top:calc(16px + env(safe-area-inset-top));
  padding:11px 18px;border-radius:999px;border:1px solid var(--line-skip);
  background:rgba(7,9,12,.72);backdrop-filter:blur(8px);color:var(--muted);
  font-family:inherit;font-size:12px;font-weight:500;letter-spacing:.08em;
  text-transform:uppercase;cursor:pointer;z-index:2;
}
.skip:hover{color:var(--cream);border-color:#37424E}

/* ═══════════════ A. FILM ═══════════════
   14.3s, auto-advances to Home. Skip is visible from 0.8s and
   always lands on Home. The chips are injected by app.js — geometry
   per chip goes in through the CSSOM (see the CSP note in _headers). */

#vFilm{overflow:hidden}
#vFilm.on{animation:nsOut .7s ease 18.44s both}
#vFilm.on .skip{animation:nsFade .8s ease .8s both}

.chips{position:absolute;inset:0}
#vFilm.on .chips{animation:nsDim 1s ease 2.25s both,nsDrift 18s ease-in-out 2s infinite}

.chip{position:absolute;left:var(--l);top:var(--t)}
#vFilm.on .chip{animation:nsChipIn .55s var(--enter) var(--d1) both}
.chip-cv{}
#vFilm.on .chip-cv{animation:nsConverge .95s var(--converge) var(--d2) both}

.chip-card{
  width:252px;padding:12px 14px;border-radius:17px;
  background:rgba(20,26,33,.94);border:1px solid var(--line-2);
  box-shadow:0 18px 44px rgba(0,0,0,.55);
  display:flex;gap:11px;align-items:flex-start;
}
.chip-tx{min-width:0}
.chip-l{font-size:10px;font-weight:600;letter-spacing:.13em;text-transform:uppercase;color:var(--faint)}
.chip-m{margin-top:4px;font-size:14px;line-height:1.35;color:var(--body)}

/* App tiles: original glyphs in each app's signature colour, not logos.
   Real software's colours, the one sanctioned exception to the palette. */
.tile{flex-shrink:0;width:34px;height:34px;border-radius:9px;box-shadow:0 3px 8px rgba(0,0,0,.35)}
.tile svg{display:block}
.t-mail{background:linear-gradient(160deg,#4DA3FF,#1471E8);display:flex;align-items:center;justify-content:center}
.t-mail svg{width:19px;height:19px}
.t-msg{background:linear-gradient(160deg,#5BE370,#21B93F);display:flex;align-items:center;justify-content:center}
.t-msg svg{width:19px;height:19px}
.t-cal{background:#FFF;overflow:hidden}
.t-cal .cb{height:11px;background:#FF3B30}
.t-cal .cd{height:23px;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:600;color:#16150F}
.t-rem{background:#FFF;display:flex;flex-direction:column;justify-content:center;gap:4px;padding:0 7px}
.t-rem .rl{display:flex;align-items:center;gap:4px}
.t-rem .rl i{width:5px;height:5px;border-radius:50%;flex-shrink:0}
.t-rem .rl b{flex:1;height:2px;border-radius:2px;background:#D6D0C6}
.t-rem .rl1 i{background:#FF3B30}
.t-rem .rl2 i{background:#FF9500}
.t-rem .rl3 i{background:#007AFF}
.t-notes{background:#FFF;overflow:hidden}
.t-notes .cb{height:10px;background:#FFD60A}
.t-notes .nl{padding:6px 7px;display:flex;flex-direction:column;gap:3px}
.t-notes .nl i{height:2px;background:#D6D0C6;border-radius:2px}
.t-notes .nl i.sh{width:60%}

/* The two film beats. Stacked in one grid cell so the block stays centred
   while only one is ever alive. */
.fbeats{
  position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);
  padding:0 34px;text-align:center;display:grid;
}
.fbeat{
  grid-area:1/1;
  font-family:var(--serif);font-size:clamp(25px,7.2vw,31px);
  line-height:1.24;font-weight:500;letter-spacing:-.01em;text-wrap:pretty;
  /* Weight 500 (up from the reference's 400) plus this soft dark halo: the
     beats sit ON TOP of the dimmed, blurred chip field and the regular
     weight was hard to read through it. The halo lifts the type off the
     background noise without turning the storm down. Brightness has no
     headroom left — cream is the palette's ceiling and pure white is
     banned by the design system. If 500 isn't enough, 600 is already
     loaded; if the halo feels wrong, it is this one declaration. */
  text-shadow:0 2px 16px rgba(7,9,12,.85);
}
#vFilm.on .f1{animation:nsBeat 4.43s ease 2.65s both}
#vFilm.on .f2{animation:nsBeat 4.43s ease 7.23s both}
.fbeat .coral{color:var(--coral)}
.fbeat .soft{color:var(--muted)}

/* The orb and the resolve line, one centred column. */
.forb{
  position:absolute;inset:0;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:40px;padding:0 34px;
  pointer-events:none;
}
.orb{position:relative;flex-shrink:0;width:128px;height:128px}
#vFilm.on .orb{animation:nsOrbIn 1.1s cubic-bezier(.2,.9,.25,1) 12.11s both}
.orb-b{position:absolute;inset:0}
#vFilm.on .orb-b{animation:nsBreathe 5s ease-in-out 13.26s infinite}
.o-glow{position:absolute;inset:-32px;border-radius:50%;background:radial-gradient(circle,rgba(45,211,205,.2) 0%,rgba(45,211,205,0) 68%)}
.o-ring{position:absolute;inset:0;border-radius:50%;background:conic-gradient(from 0deg,rgba(45,211,205,0),rgba(45,211,205,.85),rgba(45,211,205,0));opacity:.4;animation:nsSpin 14s linear infinite}
.o-core{position:absolute;inset:5px;border-radius:50%;background:radial-gradient(circle at 38% 32%,#101C22 0%,#07090C 74%);border:1px solid rgba(45,211,205,.24)}
.o-inner{position:absolute;inset:26px;border-radius:50%;background:radial-gradient(circle at 40% 36%,rgba(168,245,241,.42) 0%,rgba(45,211,205,.16) 52%,rgba(45,211,205,0) 80%);filter:blur(8px)}
.o-icon{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}
.o-icon img{width:58px;height:auto;display:block}
.o-pulse{position:absolute;inset:0;border-radius:50%;border:1px solid rgba(45,211,205,.4)}
#vFilm.on .o-pulse{animation:nsRing 4.5s ease-out 13.46s infinite}

.fresolve{width:100%;max-width:330px;text-align:center}
#vFilm.on .fresolve{animation:nsUp .9s var(--enter) 13.61s both}
.fr-t{font-family:var(--serif);font-size:clamp(24px,7vw,29px);line-height:1.26;letter-spacing:-.01em;text-wrap:pretty}
.fr-sub{margin-top:16px;font-size:16px;line-height:1.5;color:var(--muted);text-wrap:pretty}
#vFilm.on .fr-sub{animation:nsFade .9s ease 15.34s both}

/* ═══════════════ B. HOME ═══════════════ */

#vHome.on,#vSetup.on,#vCer.on,#vFin.on{overflow-y:auto}

.home{
  position:relative;min-height:100dvh;
  padding:calc(22px + env(safe-area-inset-top)) 24px calc(40px + env(safe-area-inset-bottom));
}

.h-logo{display:flex;align-items:center;gap:10px}
#vHome.on .h-logo{animation:nsUp .7s var(--enter) both}
.h-logo img{display:block}
.h-logo .ic{width:28px;height:auto}
.h-logo .wd{height:18px;width:auto}

.h-h1{
  margin:52px 0 0;font-family:var(--serif);
  font-size:clamp(38px,11.6vw,48px);line-height:1.04;font-weight:400;
  letter-spacing:-.02em;text-wrap:pretty;
}
#vHome.on .h-h1{animation:nsUp .8s var(--enter) .1s both}
.h-h1 .soft{color:var(--muted)}

.h-sub{margin:22px 0 0;font-size:17px;line-height:1.55;color:var(--body-2);max-width:22em;text-wrap:pretty}
.h-guide{margin:20px 0 0;font-size:17px;line-height:1.55;color:var(--cream);max-width:22em;text-wrap:pretty}
.h-guide .soft{color:var(--body-2)}
#vHome.on .h-sub{animation:nsUp .8s var(--enter) .2s both}
#vHome.on .h-guide{animation:nsUp .8s var(--enter) .28s both}

.h-plan{margin:40px 0 0;padding:0;list-style:none;display:flex;flex-direction:column;gap:20px}
#vHome.on .h-plan{animation:nsUp .8s var(--enter) .36s both}
.h-plan li{display:flex;gap:16px;align-items:flex-start}
.h-plan .n{
  flex-shrink:0;width:26px;height:26px;border-radius:50%;
  border:1px solid var(--line-4);display:flex;align-items:center;justify-content:center;
  font-size:13px;font-weight:600;color:var(--teal);
}
.h-plan .t{font-size:16px;line-height:1.5;color:var(--body);text-wrap:pretty}

.cta{
  width:100%;min-height:58px;padding:18px 22px;border:0;border-radius:16px;
  background:var(--grad-cta);color:var(--coral-text);
  font-family:inherit;font-size:17px;font-weight:600;letter-spacing:-.01em;
  cursor:pointer;box-shadow:0 14px 36px rgba(226,96,58,.26);
}
.cta:hover{filter:brightness(1.07)}
#vHome.on .h-cta{margin:40px 0 0;animation:nsUp .8s var(--enter) .44s both}

.h-alt{margin:18px 0 0;text-align:center;font-size:14px;color:var(--faint)}
#vHome.on .h-alt{animation:nsFade .8s ease .6s both}

/* Desktop bridge note. Shown by media query alone — no JS. */
.h-note{
  display:none;margin:22px 0 0;padding:14px 16px;border-radius:12px;
  border:1px solid var(--line-2);text-align:center;
  font-size:13.5px;line-height:1.5;color:var(--muted);
}
@media (min-width:900px){.h-note{display:block}}

/* The lock-screen proof. Pure CSS/HTML — a mock until a real screenshot
   exists, per the handoff. */
.h-proof{margin:64px 0 0;padding-top:40px;border-top:1px solid var(--line)}
#vHome.on .h-proof{animation:nsFade 1s ease .8s both}

.phone{
  position:relative;margin:0 auto;width:250px;height:420px;
  border-radius:38px;padding:9px;background:#14181D;
  box-shadow:0 32px 70px rgba(0,0,0,.6);
}
.phone-in{
  position:relative;height:100%;border-radius:30px;overflow:hidden;
  background:linear-gradient(170deg,#1B2A33 0%,#0B1116 55%,#0A0D11 100%);
  display:flex;flex-direction:column;align-items:center;padding:26px 12px 18px;
}
.notch{position:absolute;left:50%;top:10px;transform:translateX(-50%);width:74px;height:20px;border-radius:999px;background:#07090C}
.p-date{margin-top:30px;font-size:13px;color:rgba(244,239,231,.72);letter-spacing:.02em}
.p-time{margin-top:2px;font-size:62px;font-weight:500;letter-spacing:-.03em;line-height:1.05;color:var(--cream)}
.glass{
  margin-top:26px;width:100%;padding:12px 13px;border-radius:17px;
  background:rgba(28,34,42,.78);backdrop-filter:blur(12px);
  border:1px solid rgba(255,255,255,.07);
  display:flex;gap:10px;align-items:flex-start;text-align:left;
}
.glass .tile{width:30px;height:30px;border-radius:8px;padding:0 6px;gap:4px}
.glass .t-rem .rl i{width:4px;height:4px}
.glass .t-rem .rl b{height:2px}
.g-t{min-width:0;flex:1}
.g-hd{display:flex;justify-content:space-between;gap:8px;font-size:11.5px;font-weight:600;letter-spacing:.04em;color:rgba(244,239,231,.62)}
.g-hd .now{font-weight:400}
.g-tt{margin-top:3px;font-size:14px;font-weight:500;line-height:1.3;color:var(--cream)}
.g-ts{margin-top:1px;font-size:13px;line-height:1.35;color:rgba(244,239,231,.7)}
.p-bar{flex:1}
.p-home{width:96px;height:4px;border-radius:999px;background:rgba(244,239,231,.4);margin-top:auto}

.h-win{
  margin:30px auto 0;max-width:22em;text-align:center;
  font-family:var(--serif);font-size:21px;line-height:1.35;color:var(--cream);
  text-wrap:pretty;
}
.h-fail{margin:14px auto 0;max-width:22em;text-align:center;font-size:15px;line-height:1.45;color:var(--faint);text-wrap:pretty}

/* The one outbound link. The opt-out switch lives on /privacy; the page
   must not strand it. */
.foot{margin-top:48px;padding-top:18px;border-top:1px solid var(--line);font-size:13px;color:var(--faint)}
.foot a{color:var(--muted)}
.foot a:hover{color:var(--cream)}

/* ═══════════════ C. SETUP ═══════════════
   Nothing is validated and nothing is required except the job choice,
   which arrives pre-selected. The submit is a local stage change for
   now — the workspace endpoint lands in a later pass (see app.js). */

.setup{
  position:relative;min-height:100dvh;
  padding:calc(24px + env(safe-area-inset-top)) 24px calc(40px + env(safe-area-inset-bottom));
  display:flex;flex-direction:column;
}
.s-back{
  align-self:flex-start;margin-bottom:34px;padding:8px 0;border:0;
  background:transparent;color:var(--faint);font-family:inherit;font-size:14px;
  cursor:pointer;
}
.s-back:hover{color:var(--cream)}

.s-lab{display:block;font-size:17px;font-weight:500;color:var(--cream)}
.s-in{
  margin-top:12px;width:100%;min-height:54px;padding:15px 18px;
  border-radius:14px;border:1px solid var(--line-4);background:var(--raised);
  color:var(--cream);font-size:16px;outline:none;
}
.s-in:focus{border-color:var(--teal);background:var(--field-focus)}
.s-help{margin:10px 0 0;font-size:13.5px;line-height:1.5;color:var(--faint)}

.s-name{}
.s-jobs{margin-top:34px}
.s-phone{margin-top:34px}
#vSetup.on .s-name{animation:nsUp .7s var(--enter) both}
#vSetup.on .s-jobs{animation:nsUp .7s var(--enter) .08s both}
#vSetup.on .s-phone{animation:nsUp .7s var(--enter) .16s both}

.joblist{margin-top:12px;display:flex;flex-direction:column;gap:10px}
.job{
  position:relative;width:100%;min-height:54px;padding:15px 18px;
  border:1px solid #1D252E;border-radius:14px;background:var(--raised);
  color:var(--body);font-family:inherit;font-size:16px;text-align:left;
  cursor:pointer;display:flex;align-items:center;justify-content:space-between;gap:12px;
}
.job:hover{border-color:var(--line-hover)}
.job .ck{
  flex-shrink:0;width:20px;height:20px;border-radius:50%;background:var(--teal);
  display:flex;align-items:center;justify-content:center;opacity:0;
}
.job.on .ck{opacity:1}
.job .ring{position:absolute;inset:-1px;border-radius:14px;border:1.5px solid var(--teal);pointer-events:none;opacity:0}
.job.on .ring{opacity:1}

.s-spacer{flex:1;min-height:40px}
.s-cta{margin-top:34px}
#vSetup.on .s-cta{animation:nsUp .7s var(--enter) .24s both}

/* The country selector. A REAL <select> — on iOS that is the native
   wheel picker, keyboard type-ahead and free accessibility — laid over
   the whole drawn row at opacity 0 (opacity does not affect
   hit-testing, so it is still what a tap lands on; font-size stays at
   16px for iOS's focus-zoom threshold). The drawn row exists because a
   native select renders its selected option's own text, which truncates
   the dial code first — and the dial code is the whole reason the
   control exists. Only the name truncates; flag, dial and chevron are
   shrink-0. The drawn row is aria-hidden — it duplicates what the
   select already announces. Ported from nessi-ui's CountrySelect. */
.s-selrow{
  position:relative;margin-top:12px;display:flex;align-items:center;gap:10px;
  min-height:54px;padding:15px 18px;border-radius:14px;
  border:1px solid var(--line-4);background:var(--raised);
}
.s-selrow:focus-within{border-color:var(--teal);background:var(--field-focus)}
.cs-flag{flex-shrink:0;font-size:20px;line-height:1}
.cs-name{
  min-width:0;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  color:var(--body);font-size:16px;
}
.cs-dial{flex-shrink:0;color:var(--body);font-size:16px}
.cs-chev{flex-shrink:0;width:16px;height:16px;color:var(--muted)}
#country{
  position:absolute;inset:0;width:100%;height:100%;
  opacity:0;appearance:none;-webkit-appearance:none;border:0;padding:0 18px;
  background:transparent;font-family:inherit;font-size:16px;cursor:pointer;
}
#country:disabled{cursor:not-allowed}
/* The visibly-disabled state for a typed + (the ignoring must be
   visible, never silent). */
.s-selrow.dis .cs-flag,.s-selrow.dis .cs-name,.s-selrow.dis .cs-dial{opacity:.55}

/* The phone field's validation states. Phone is required: an invalid
   entry shows one short line in the semantic red (never the brand
   coral — an error must not read as marketing) and does not advance. */
.s-in[aria-invalid="true"]{border-color:var(--bad)}
.s-in[aria-invalid="true"]:focus{border-color:var(--bad)}
.s-err{margin:10px 0 0;font-size:13.5px;line-height:1.5;color:var(--bad)}

/* ═══════════════ D1. CEREMONY ═══════════════
   Five quiet checklist lines, ~7.4s, then the end card and the
   handoff. No terminal, no agent id — the spec bans both. */

.cer{
  position:relative;min-height:100dvh;
  padding:calc(24px + env(safe-area-inset-top)) 28px calc(40px + env(safe-area-inset-bottom));
  display:flex;flex-direction:column;justify-content:center;
}
.c-orb{position:relative;align-self:center;width:76px;height:76px;margin-bottom:44px}
#vCer.on .c-orb{animation:nsFade .8s ease both}
.c-orb-b{position:absolute;inset:0;animation:nsBreathe 5s ease-in-out infinite}
.c-glow{position:absolute;inset:-20px;border-radius:50%;background:radial-gradient(circle,rgba(45,211,205,.16) 0%,rgba(45,211,205,0) 70%)}
.c-ring{position:absolute;inset:0;border-radius:50%;border:1px solid rgba(45,211,205,.22)}
.c-icon{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}
.c-icon img{width:36px;height:auto;display:block}

.c-list{display:flex;flex-direction:column;gap:22px;max-width:21em;width:100%;align-self:center}
.c-row{display:flex;gap:14px;align-items:center;font-size:16px;line-height:1.45;color:var(--body)}
.c-ck{position:relative;flex-shrink:0;width:21px;height:21px}
.c-hole{position:absolute;inset:0;border-radius:50%;border:1px solid var(--line-4)}
.c-ck svg{position:absolute;inset:0;opacity:0}
#vCer.on .c-row.r1{animation:nsFade .6s ease .2s both}
#vCer.on .c-row.r2{animation:nsFade .6s ease 1.1s both}
#vCer.on .c-row.r3{animation:nsFade .6s ease 2s both}
#vCer.on .c-row.r4{animation:nsFade .6s ease 2.9s both}
#vCer.on .c-row.r5{animation:nsFade .6s ease 3.8s both}
#vCer.on .c-row.r1 .c-ck svg{animation:nsPop .5s var(--pop) 1s both}
#vCer.on .c-row.r2 .c-ck svg{animation:nsPop .5s var(--pop) 1.9s both}
#vCer.on .c-row.r3 .c-ck svg{animation:nsPop .5s var(--pop) 2.8s both}
#vCer.on .c-row.r4 .c-ck svg{animation:nsPop .5s var(--pop) 3.7s both}
#vCer.on .c-row.r5 .c-ck svg{animation:nsPop .5s var(--pop) 4.6s both}
#vCer.on .c-row.r1 .c-ck path{animation:nsCheck .45s ease 1.1s both}
#vCer.on .c-row.r2 .c-ck path{animation:nsCheck .45s ease 2s both}
#vCer.on .c-row.r3 .c-ck path{animation:nsCheck .45s ease 2.9s both}
#vCer.on .c-row.r4 .c-ck path{animation:nsCheck .45s ease 3.8s both}
#vCer.on .c-row.r5 .c-ck path{animation:nsCheck .45s ease 4.7s both}

.c-end{margin-top:44px;max-width:21em;width:100%;align-self:center}
#vCer.on .c-end{animation:nsUp .8s var(--enter) 5.2s both}
.c-end-t{font-family:var(--serif);font-size:26px;line-height:1.3;letter-spacing:-.01em}
.c-end-s{margin-top:10px;font-size:15.5px;line-height:1.5;color:var(--muted);text-wrap:pretty}
.c-meta{margin-top:22px;font-size:13px;letter-spacing:.04em;color:var(--ghost)}

/* ═══════════════ D2. HANDOFF ═══════════════ */

.fin{
  position:relative;min-height:100dvh;
  padding:calc(30px + env(safe-area-inset-top)) 24px calc(40px + env(safe-area-inset-bottom));
  display:flex;flex-direction:column;
}
.live{display:flex;align-items:center;gap:9px}
#vFin.on .live{animation:nsFade .7s ease both}
.live-dot{width:7px;height:7px;border-radius:50%;background:var(--teal);animation:nsDot 2.6s ease-in-out infinite}
.live-lbl{font-size:12px;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--faint)}

.finh{
  margin:20px 0 0;font-family:var(--serif);
  font-size:clamp(28px,8.4vw,34px);line-height:1.15;font-weight:400;
  letter-spacing:-.015em;text-wrap:pretty;
}
#vFin.on .finh{animation:nsUp .8s var(--enter) .1s both}
.finh .soft{color:var(--muted)}

.fprev{margin-top:32px;border-radius:20px;border:1px solid var(--line-2);background:#0B1015;overflow:hidden}
#vFin.on .fprev{animation:nsUp .8s var(--enter) .2s both}
.fprev-to{padding:14px 16px;border-bottom:1px solid var(--line);display:flex;gap:8px;align-items:baseline}
.fprev-to .k{font-size:13.5px;color:var(--faint)}
.fprev-to .v{font-size:15px;font-weight:500;color:var(--cream)}
.fprev-body{padding:18px 16px 20px;display:flex;justify-content:flex-end}
.bubble{
  max-width:88%;padding:12px 16px;border-radius:20px 20px 6px 20px;
  background:linear-gradient(150deg,#2E9BFF,#1478E8);
  font-size:15.5px;line-height:1.45;color:#FFF;text-wrap:pretty;
}
.caret{
  display:inline-block;width:2px;height:1.05em;margin-left:1px;
  vertical-align:-.18em;background:#FFF;border-radius:1px;
  animation:nsCaret 1.05s steps(1,end) infinite;
}
.caret.off{display:none}

.f-spacer{flex:1;min-height:32px}

.send-wrap{position:relative}
#vFin.on .send-wrap{animation:nsUp .8s var(--enter) .3s both}
.halo{
  position:absolute;inset:0;border-radius:999px;
  border:1.5px solid rgba(253,131,96,.65);pointer-events:none;
  animation:nsHalo 2.6s ease-out .6s infinite;
}
.halo.h2a{border-color:rgba(253,131,96,.45);animation-delay:1.9s}
.send-a{
  position:relative;display:flex;align-items:center;justify-content:space-between;
  gap:14px;min-height:66px;padding:12px 12px 12px 24px;border-radius:999px;
  background:linear-gradient(112deg,#FFA07C 0%,#FD8360 42%,#E2603A 100%);
  color:var(--send-dark);font-size:17px;font-weight:600;letter-spacing:-.01em;
  overflow:hidden;animation:nsLift 3.4s ease-in-out 1s infinite;
}
.send-a:hover{filter:brightness(1.06);color:var(--send-dark)}
.sweep{
  position:absolute;top:0;bottom:0;left:0;width:46%;
  background:linear-gradient(100deg,rgba(255,255,255,0) 0%,rgba(255,255,255,.42) 50%,rgba(255,255,255,0) 100%);
  pointer-events:none;animation:nsSweep 3.4s cubic-bezier(.5,0,.5,1) 1s infinite;
}
.send-l{position:relative;text-align:left;line-height:1.25}
.send-ic{
  position:relative;flex-shrink:0;width:42px;height:42px;border-radius:50%;
  background:var(--send-dark);display:flex;align-items:center;justify-content:center;
}
.send-ic svg{width:19px;height:19px;animation:nsNudge 3.4s ease-in-out 1s infinite}

.fine{margin:16px 0 0;text-align:center;font-size:13.5px;line-height:1.5;color:var(--faint)}
#vFin.on .fine{animation:nsFade .8s ease .5s both}

/* Desktop only: sms: is inert on most desktops, so hand them a way
   across to the phone with the message already written. Rendered by
   app.js (qr.v6.js — never a third-party QR service), and .ready is
   only set on a successful render. */
.qrwrap{
  display:none;margin-top:26px;padding:22px;border-radius:18px;
  border:1px solid var(--line-2);align-items:center;gap:18px;
}
.qrwrap.ready{display:flex}
.qr{flex-shrink:0;width:104px;height:104px;border-radius:10px;background:#F4EFE7;display:flex;align-items:center;justify-content:center}
.qr svg{width:96px;height:96px;display:block}
.qrcap{font-size:14px;line-height:1.55;color:var(--muted);text-wrap:pretty}

/* ── reduced motion ─────────────────────────────────────
   Not the prototype's global collapse. The film is skipped outright
   in app.js; the plain entrances on home/setup/handoff resolve
   instantly; the ambient loops stop. The ceremony keeps its stagger —
   five quiet fades are the narrative, and collapsing them onto one
   frame removes the story rather than the motion. The typewriter
   keeps running: it is content, not decoration. */

@media (prefers-reduced-motion: reduce){
  #vHome.on *,#vSetup.on *,#vFin.on *{
    animation-duration:.01ms !important;
    animation-delay:0s !important;
  }
  .chips,.o-ring,.o-pulse,#vFilm.on .orb-b,.c-orb-b,.live-dot,.halo,.sweep,.send-a,.send-ic svg{
    animation:none !important;
  }
  .caret{animation:none !important}
}
