/* =============================================================================
 * onboarding.css — Design-system primitives for the v3.5.0 onboarding revamp.
 *
 * Source of truth: ../../onboarding-storyboard.html (`:root` + component styles).
 * Slice 0 (epic #81). Everything downstream (slices 1–4) imports THIS file —
 * do not fork these styles per page.
 *
 * Framework-free: plain CSS, paired with js/onboarding-components.js.
 * ========================================================================== */

/* --- Tokens — match the mockup `:root` exactly ---------------------------- */
:root{
  --ink:#1A202C; --muted:#4A5568; --muted2:#718096; --line:#E2E8F0; --line2:#CBD5E0; --bg:#F8F9FA;
  --brand:#0250CB; --brand-d:#023A94; --brand-dd:#01349A; --tint:#E0EAF9; --accent:#0288D1;
  /* The mockup inlines the wordmark as base64; we reference the decoded asset. */
  --logo:url("../images/hooz-wordmark.png");
}

/* --- Phone chrome (preview / mockup context only) ------------------------- */
.phone{width:298px;height:606px;background:#0B1220;border-radius:40px;padding:11px;
  box-shadow:0 18px 40px -14px rgba(2,80,203,.32), inset 0 0 0 2px #1F2937;}
.screen{position:relative;height:100%;background:#fff;border-radius:30px;overflow:hidden;display:flex;flex-direction:column;}
.statusbar{height:30px;flex:0 0 auto;display:flex;align-items:center;justify-content:space-between;
  padding:0 18px;font-size:12px;font-weight:600;color:#1A202C;}
.statusbar .r{display:flex;gap:5px;align-items:center;font-size:11px;}
.notch{position:absolute;top:8px;left:50%;transform:translateX(-50%);width:108px;height:20px;background:#0B1220;border-radius:0 0 14px 14px;z-index:5;}

/* --- Screen scaffold: app bar / body / cta ------------------------------- */
.ui{flex:1;display:flex;flex-direction:column;min-height:0;}

/* 1. Centered HOOZ logo app bar — back chevron left, wordmark centered, step right. */
.brand-logo{background:var(--logo) center/contain no-repeat;display:inline-block;}
.ui-top{flex:0 0 auto;display:flex;align-items:center;gap:8px;padding:9px 16px 4px;min-height:34px;position:relative;}
.ui-top .back{width:26px;height:26px;border-radius:8px;border:1px solid var(--line);display:flex;align-items:center;justify-content:center;color:var(--muted);font-size:15px;cursor:pointer;}
.ui-top .brand-logo{height:17px;width:56px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);}
.ui-top .step{margin-left:auto;font-size:11px;color:var(--muted);font-weight:600;}
.ui-body{flex:1;overflow:auto;padding:8px 18px 6px;}
.ui-cta{flex:0 0 auto;padding:12px 16px 18px;}

/* 5. Step header — heading + sub. */
h2.t{font-size:21px;margin:6px 0 4px;letter-spacing:-.02em;line-height:1.15;}
p.sub{font-size:13px;color:var(--muted);margin:0 0 14px;line-height:1.45;}

/* 5. Field inputs. */
.field{border:1.5px solid var(--line);border-radius:13px;padding:13px 14px;font-size:15px;color:var(--ink);margin-bottom:10px;background:var(--bg);}
.field .lbl{font-size:11px;color:var(--muted2);font-weight:600;margin-bottom:3px;}
.field .val{font-size:16px;font-weight:600;}

/* 2. Pill buttons — primary / ghost / soft. */
.btn{display:block;width:100%;text-align:center;border:0;border-radius:13px;padding:14px;font-size:15px;font-weight:700;cursor:pointer;}
.btn-primary{background:var(--brand);color:#fff;box-shadow:0 8px 18px -8px var(--brand);}
.btn-ghost{background:transparent;color:var(--brand);font-weight:600;padding:11px;}
.btn-soft{background:var(--tint);color:var(--brand-d);}
.ctahint{text-align:center;font-size:11px;color:var(--muted);margin-top:8px;}

/* 5. Chips. */
.chips{display:flex;flex-wrap:wrap;gap:9px;margin:4px 0 8px;}
.chip{border:1.5px solid var(--line);border-radius:12px;padding:10px 13px;font-size:13.5px;font-weight:600;background:var(--bg);display:flex;align-items:center;gap:6px;cursor:pointer;}
.chip.sel{border-color:var(--brand);background:var(--tint);color:var(--brand-d);}

/* 5b. Tag pickers (positions / about-you / vouch) — shared by the manager and
 * player flows. Chips form a tidy two-up grid (rows align, unlike wrap) with
 * centered text and a leading ✓ on selection; the group label sits flush left
 * in the design system's small-caps hint style. */
.pos-chips .chips{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin:0 0 4px;}
.pos-chips .chip{user-select:none;justify-content:center;text-align:center;padding:12px 10px;
  transition:border-color .12s ease, background .12s ease, transform .06s ease;}
.pos-chips .chip:active{transform:scale(.97);}
.pos-chips .chip.sel{box-shadow:0 6px 16px -10px rgba(2,80,203,.55);}
.pos-chips .chip.sel::before{content:"✓";font-weight:800;}
/* Vouch candidates carry longer labels (name · team) — one per row reads better. */
.vouch-chips .chips{grid-template-columns:1fr;}
.chip-lbl{display:block;text-align:left;font-size:11px;color:var(--muted2);font-weight:600;letter-spacing:.04em;margin:16px 2px 8px;}
.chip-lbl:first-child{margin-top:0;}
.chip-lbl span{font-weight:500;text-transform:none;letter-spacing:0;}

/* 5c. Sub-network opt-in — the pulsing "your network" graph (sub-network
 * storyboard). Edges draw outward from YOU to teammates on other teams. */
.netwrap{display:flex;justify-content:center;padding:2px 0;}
@keyframes subnetPulse{0%,100%{transform:scale(1)}50%{transform:scale(1.14)}}
@keyframes subnetEdge{0%{stroke-dashoffset:60;opacity:.25}55%{stroke-dashoffset:0;opacity:1}100%{stroke-dashoffset:0;opacity:.5}}
.netwrap .edge{stroke:var(--accent);stroke-width:2;stroke-dasharray:60;animation:subnetEdge 2.6s ease-in-out infinite;}
.netwrap .edge.e2{animation-delay:.5s}.netwrap .edge.e3{animation-delay:1s}
.netwrap .edge.e4{animation-delay:1.5s}.netwrap .edge.e5{animation-delay:2s}
.netwrap .nodep{animation:subnetPulse 2.6s ease-in-out infinite;transform-origin:center;transform-box:fill-box;}
.netwrap .n2{animation-delay:.5s}.netwrap .n3{animation-delay:1s}
.netwrap .n4{animation-delay:1.5s}.netwrap .n5{animation-delay:2s}
@media (prefers-reduced-motion:reduce){.netwrap .edge,.netwrap .nodep,.netwrap svg circle{animation:none;}}

/* 3. Rounded card. */
.card{border:1px solid var(--line);border-radius:14px;padding:13px;background:#fff;margin-bottom:11px;}
.card.tint{background:var(--tint);border-color:rgba(2,80,203,.22);}
.card .ct{font-size:13.5px;font-weight:700;margin-bottom:3px;display:flex;gap:7px;align-items:center;}
.card .cs{font-size:12px;color:var(--muted);line-height:1.45;}

/* 4. Animated text-thread demo — staggered fade-in, ~6.5s loop. -----------
 * Reusable: js/onboarding-components.js builds the bubble markup AND emits the
 * per-instance stagger keyframes (one keyframe per bubble) so it generalises to
 * any number of bubbles while preserving the mockup's 3-bubble feel. The base
 * `.b1/.b2/.b3` classes below remain for static/3-bubble use. */
.demo{display:flex;flex-direction:column;background:#EEF2F7;border-radius:16px;padding:10px 11px 11px;margin:8px 0 12px;}
.demo .dh{display:flex;align-items:center;gap:7px;font-size:11px;font-weight:700;color:var(--muted);padding:2px 2px 9px;border-bottom:1px solid var(--line);margin-bottom:10px;}
.demo .dh .b{width:18px;height:18px;border-radius:50%;background:var(--tint);display:flex;align-items:center;justify-content:center;font-size:10px;}
.bub{max-width:84%;padding:8px 11px;border-radius:15px;font-size:12.5px;line-height:1.35;margin-bottom:9px;opacity:0;}
.bub.inq{background:#fff;color:#1A202C;border-top-left-radius:5px;align-self:flex-start;box-shadow:0 1px 1px rgba(0,0,0,.05);}
.bub.out{background:var(--brand);color:#fff;border-top-right-radius:5px;align-self:flex-end;}
.b1,.b2,.b3{animation-duration:6.5s;animation-timing-function:ease-in-out;animation-iteration-count:infinite;}
.b1{animation-name:bb1;} .b2{animation-name:bb2;} .b3{animation-name:bb3;}
@keyframes bb1{0%,5%{opacity:0;transform:translateY(9px)}11%,90%{opacity:1;transform:none}97%,100%{opacity:0}}
@keyframes bb2{0%,33%{opacity:0;transform:translateY(9px)}40%,90%{opacity:1;transform:none}97%,100%{opacity:0}}
@keyframes bb3{0%,60%{opacity:0;transform:translateY(9px)}67%,90%{opacity:1;transform:none}97%,100%{opacity:0}}
.demo .cap{font-size:11px;color:var(--muted);text-align:center;margin-top:1px;}

/* --- 6. "Ditch the group chat" hero ---------------------------------------
 * A realistic iMessage-style group thread spiraling into chaos, then a sweep
 * ("Hooz silences the chaos") resolving to Hooz calm. Copied verbatim from the
 * mockup; markup comes from js/onboarding-components.js `groupChatDemo(role)`
 * (role: 'manager' loops every 12s; 'player' plays once and holds the join
 * beat via `.gcx.once`). Used by the Welcome screens of slices 1 and 4. */
.gcx{position:relative;height:228px;width:100%;border-radius:20px;overflow:hidden;}
.gcx .layer{position:absolute;inset:0;display:flex;flex-direction:column;}
/* The card chrome lives on the chaos layer (not the container) so it fades
 * away WITH the group-chat phase — the sweep pill and calm resolution sit
 * directly on the page background, no box around them. */
.chaos{border-radius:20px;background:#fff;border:1px solid var(--line);
  box-shadow:0 12px 26px -16px rgba(2,80,203,.4);overflow:hidden;
  animation:chaosCycle 12s ease-in-out infinite;}

/* iOS-style chat header (frosted bar, avatar cluster, buzzing unread badge) */
.gc-head{flex:0 0 auto;display:flex;align-items:center;gap:8px;padding:7px 11px 7px;
  background:rgba(248,248,248,.94);-webkit-backdrop-filter:saturate(180%) blur(8px);backdrop-filter:saturate(180%) blur(8px);
  border-bottom:1px solid var(--line);position:relative;z-index:2;}
.gc-head .chev{color:#0A84FF;font-size:18px;font-weight:600;line-height:1;margin:-1px -2px 0 -2px;}
.gc-stack{position:relative;width:31px;height:26px;flex:0 0 auto;}
.gc-stack i{position:absolute;width:21px;height:21px;border-radius:50%;border:1.5px solid #fff;
  display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:700;color:#fff;}
.gc-stack i:nth-child(1){left:0;top:3px;background:linear-gradient(135deg,#FFB07A,#F4511E);}
.gc-stack i:nth-child(2){left:10px;top:0;background:linear-gradient(135deg,#5BC6F7,#0277BD);}
.gc-stack i:nth-child(3){left:5px;top:9px;background:linear-gradient(135deg,#8FD89A,#388E3C);z-index:2;}
.gc-meta{flex:1;min-width:0;line-height:1.12;}
.gc-meta b{font-size:12.5px;font-weight:700;color:#1A202C;display:block;}
.gc-meta small{font-size:9.5px;color:#8E8E93;}
.gc-head .badge{background:#FF3B30;color:#fff;border-radius:99px;font-size:9.5px;font-weight:800;
  padding:2px 7px;animation:buzz 2.2s ease-in-out infinite;transform-origin:center;box-shadow:0 1px 5px rgba(255,59,48,.55);}

.cfeed{flex:1;min-height:0;overflow:hidden;position:relative;padding:8px 9px 5px;background:#fff;
  container-type:size;
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 14px,#000 100%);mask-image:linear-gradient(180deg,transparent 0,#000 14px,#000 100%);}
.cwrap{display:flex;flex-direction:column;gap:3px;animation:feedScroll 12s cubic-bezier(.4,.05,.45,1) infinite;}
/* Scroll end: last message lands at the bottom of the window. The fixed -378px
 * is the mockup value tuned for the 228px hero; the @supports version is
 * content-relative (-100% of the feed + the window height via cqh) so the
 * hero can be any height — e.g. it flexes to fill the welcome screen. */
@keyframes feedScroll{0%,3%{transform:translateY(6px)}27%,100%{transform:translateY(-378px)}}
@supports (container-type: size){
  @keyframes feedScroll{0%,3%{transform:translateY(6px)}27%,100%{transform:translateY(calc(-100% + 100cqh))}}
}

/* a message row: [avatar] [name + bubble] — incoming left, your replies right */
.cm{display:flex;align-items:flex-end;gap:6px;max-width:92%;}
.cm.in{align-self:flex-start;}
.cm.out{align-self:flex-end;flex-direction:row-reverse;max-width:84%;}
.cm .cav{flex:0 0 auto;width:20px;height:20px;border-radius:50%;display:flex;align-items:center;
  justify-content:center;font-size:8.5px;font-weight:700;color:#fff;margin-bottom:1px;}
.cm.cont .cav{visibility:hidden;}
.cstack{display:flex;flex-direction:column;gap:2px;min-width:0;}
.cname{font-size:9.5px;color:#8E8E93;font-weight:600;margin:1px 0 0 11px;}
.cbub{position:relative;font-size:11.5px;line-height:1.3;padding:6px 11px;border-radius:16px;width:fit-content;max-width:100%;word-wrap:break-word;}
.cm.in .cbub{background:#E9E9EB;color:#000;border-bottom-left-radius:5px;}
.cm.out .cbub{background:linear-gradient(180deg,#2BA2FF,#0A84FF);color:#fff;border-bottom-right-radius:5px;margin-left:auto;box-shadow:0 1px 5px rgba(10,132,255,.4);}
.cm.in .cbub.nag{background:#FFE7AE;color:#8A5300;font-weight:600;}
.cm.in .cbub.red{background:#FFDCD8;color:#C0271E;font-weight:600;}

/* tapback reaction bubble that pops onto a message corner */
.tb{position:absolute;top:-9px;width:18px;height:18px;border-radius:50%;background:#fff;border:1px solid #ECECEC;
  display:flex;align-items:center;justify-content:center;font-size:9.5px;box-shadow:0 1px 3px rgba(0,0,0,.16);
  transform:scale(0);animation:pop .4s ease-out forwards;}
.cm.in .tb{right:-6px;}
.cm.out .tb{left:-6px;}
@keyframes pop{0%{transform:scale(0)}70%{transform:scale(1.25)}100%{transform:scale(1)}}

/* typing indicator bubble */
.typing{display:flex;gap:3px;align-items:center;padding:8px 11px;background:#E9E9EB;border-radius:16px;border-bottom-left-radius:5px;width:fit-content;}
.typing i{width:6px;height:6px;border-radius:50%;background:#9A9AA0;animation:typedot 1.2s infinite;}
.typing i:nth-child(2){animation-delay:.18s;}.typing i:nth-child(3){animation-delay:.36s;}
@keyframes typedot{0%,60%,100%{opacity:.32;transform:translateY(0)}30%{opacity:1;transform:translateY(-2px)}}

@keyframes chaosCycle{0%,28%{opacity:1;transform:none}34%,100%{opacity:0;transform:translateY(-14px)}}
/* manager loop: the chat is DISMISSED (shrinks away) and the fan-out panel
 * takes over — no sweep pill beat. */
.gcx.mgr .chaos{animation-name:mgrChaosOut;}
@keyframes mgrChaosOut{0%,30%{opacity:1;transform:none}37%,100%{opacity:0;transform:translateY(-10px) scale(.97)}}

/* the wipe line that sweeps the noise away */
.sweep{position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);text-align:center;opacity:0;z-index:3;animation:sweepCycle 12s infinite;}
.sweep span{display:inline-block;background:var(--brand);color:#fff;font-size:11.5px;font-weight:700;padding:7px 15px;border-radius:99px;box-shadow:0 8px 18px -6px rgba(2,80,203,.6);}
.sweep .sw2{padding:9px 16px;line-height:1.3;}
.sweep .sw2 b{display:block;font-size:12px;font-weight:800;}
.sweep .sw2 i{display:block;font-style:normal;font-size:10.5px;font-weight:600;opacity:.9;margin-top:2px;}
@keyframes sweepCycle{0%,31%{opacity:0;transform:translateY(-50%) scale(.9)}36%,46%{opacity:1;transform:translateY(-50%) scale(1)}51%,100%{opacity:0;transform:translateY(-50%) scale(1)}}

/* Hooz "calm" resolution — transparent, blends with the page background */
.calm{align-items:center;justify-content:center;text-align:center;padding:14px 16px;
  opacity:0;animation:calmCycle 12s ease-in-out infinite;}
@keyframes calmCycle{0%,46%{opacity:0;transform:scale(.96)}52%,95%{opacity:1;transform:none}99%,100%{opacity:0}}

/* Manager fan-out panel — the mechanism made visible: Hooz texts every
 * member 1-on-1, replies pop in per person (four waves), then the tally and
 * punchline land. Card chrome matches .chaos so before/after read as the
 * same phone. */
.fan{background:#fff;border-radius:20px;border:1px solid var(--line);box-shadow:0 12px 26px -16px rgba(2,80,203,.4);
  padding:13px 15px 12px;opacity:0;animation:fanCycle 12s ease-in-out infinite;}
@keyframes fanCycle{0%,33%{opacity:0;transform:scale(.975)}40%,95%{opacity:1;transform:none}99%,100%{opacity:0}}
.fan-head{display:flex;gap:9px;align-items:flex-start;flex:0 0 auto;}
.fan-head .sms-av{width:28px;height:28px;font-size:12px;}
.fan-ht{text-align:left;}
.fan-ht b{display:block;font-size:12.5px;font-weight:800;color:var(--ink);}
.fan-ht small{display:block;font-size:10.5px;color:var(--muted);margin-top:2px;}
.fan-rows{flex:1;min-height:0;display:flex;flex-direction:column;justify-content:space-evenly;margin-top:7px;}
.frow{display:flex;align-items:center;gap:8px;padding:2px 0;}
.frow .fav{flex:0 0 auto;width:20px;height:20px;border-radius:50%;color:#fff;font-size:8.5px;font-weight:700;
  display:flex;align-items:center;justify-content:center;}
.frow .fname{flex:1;font-size:11.5px;font-weight:600;color:var(--ink);text-align:left;}
.fchip{font-size:10px;font-weight:800;border-radius:99px;padding:3px 10px;opacity:0;transform:scale(.4);}
.fchip.in{background:#E7F6EC;color:#1D7A46;}
.fchip.out{background:#F1F3F6;color:#7A8494;}
.fchip.w1{animation:chipW1 12s ease-out infinite;}
.fchip.w2{animation:chipW2 12s ease-out infinite;}
.fchip.w3{animation:chipW3 12s ease-out infinite;}
.fchip.w4{animation:chipW4 12s ease-out infinite;}
@keyframes chipW1{0%,46%{opacity:0;transform:scale(.4)}50%{opacity:1;transform:scale(1.12)}53%,100%{opacity:1;transform:scale(1)}}
@keyframes chipW2{0%,54%{opacity:0;transform:scale(.4)}58%{opacity:1;transform:scale(1.12)}61%,100%{opacity:1;transform:scale(1)}}
@keyframes chipW3{0%,62%{opacity:0;transform:scale(.4)}66%{opacity:1;transform:scale(1.12)}69%,100%{opacity:1;transform:scale(1)}}
@keyframes chipW4{0%,70%{opacity:0;transform:scale(.4)}74%{opacity:1;transform:scale(1.12)}77%,100%{opacity:1;transform:scale(1)}}
.fan-tally{flex:0 0 auto;display:flex;align-items:center;justify-content:center;gap:7px;font-size:11.5px;color:var(--ink);
  font-weight:600;margin-top:8px;padding-top:9px;border-top:1px solid var(--line);opacity:0;animation:fanTally 12s ease-out infinite;}
.fan-tally .dot{width:8px;height:8px;border-radius:50%;background:#22A35B;box-shadow:0 0 0 3px rgba(34,163,91,.18);}
@keyframes fanTally{0%,79%{opacity:0;transform:translateY(6px)}84%,100%{opacity:1;transform:none}}
.fan-punch{flex:0 0 auto;text-align:center;font-size:11px;color:#22A35B;font-weight:800;margin-top:6px;
  opacity:0;animation:fanPunch 12s ease-out infinite;}
@keyframes fanPunch{0%,86%{opacity:0;transform:translateY(5px)}91%,100%{opacity:1;transform:none}}
/* player calm holds visible at the end (the sequence plays once and stops on the join beat) */
@keyframes calmHold{0%,46%{opacity:0;transform:scale(.96)}52%,100%{opacity:1;transform:none}}

/* calm as a real 1:1 SMS thread from Hooz, staged in — the manager gets the
 * finished-headcount text, the player gets the IN/OUT + join beat. Card
 * chrome matches .chaos so before and after read as the same phone. */
.calm.sms{align-items:stretch;justify-content:flex-start;text-align:left;padding:0;background:#fff;
  border-radius:20px;border:1px solid var(--line);box-shadow:0 12px 26px -16px rgba(2,80,203,.4);overflow:hidden;}
.sms-head{flex:0 0 auto;display:flex;align-items:center;gap:7px;padding:7px 11px;
  background:rgba(248,248,248,.94);-webkit-backdrop-filter:saturate(180%) blur(8px);backdrop-filter:saturate(180%) blur(8px);border-bottom:1px solid var(--line);}
.sms-head .chev{color:#0A84FF;font-size:18px;font-weight:600;margin:-1px 0;}
.sms-av{flex:0 0 auto;width:25px;height:25px;border-radius:50%;background:linear-gradient(135deg,#2BA2FF,var(--brand));color:#fff;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:800;}
.sms-id{line-height:1.12;}
.sms-id b{font-size:12.5px;color:#1A202C;display:block;font-weight:700;}
.sms-id small{font-size:9.5px;color:#8E8E93;}
.sms-thread{flex:1;min-height:0;display:flex;flex-direction:column;justify-content:flex-end;gap:5px;padding:10px 11px 11px;position:relative;}
.smsg{max-width:85%;font-size:11.5px;line-height:1.34;padding:7px 11px;border-radius:17px;width:fit-content;opacity:0;}
.smsg.in{align-self:flex-start;background:#E9E9EB;color:#000;border-bottom-left-radius:5px;}
.smsg.out{align-self:flex-end;background:linear-gradient(180deg,#2BA2FF,#0A84FF);color:#fff;border-bottom-right-radius:5px;box-shadow:0 1px 5px rgba(10,132,255,.4);}
.smsg.in b{font-weight:800;}
.sms-time{align-self:center;font-size:9.5px;color:#8E8E93;font-weight:600;margin-bottom:3px;opacity:0;}
.sms-delivered{align-self:flex-end;font-size:9px;color:#8E8E93;font-weight:600;margin:0 2px 2px 0;opacity:0;}
.sms-confirm{align-self:center;font-size:10.5px;color:#22A35B;font-weight:700;opacity:0;margin-top:2px;}
.s1{animation:smsIn1 12s ease-out infinite;}
.s2{animation:smsIn2 12s ease-out infinite;}
.s3{animation:smsIn3 12s ease-out infinite;}
@keyframes smsIn1{0%,53%{opacity:0;transform:translateY(8px)}58%,100%{opacity:1;transform:none}}
@keyframes smsIn2{0%,67%{opacity:0;transform:translateY(8px)}72%,100%{opacity:1;transform:none}}
@keyframes smsIn3{0%,80%{opacity:0;transform:translateY(5px)}84%,100%{opacity:1;transform:none}}
/* the join-the-team beat overlays the settled thread */
.sms-join{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;
  background:linear-gradient(180deg,rgba(243,248,255,.92),rgba(255,255,255,.98));-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);opacity:0;animation:smsJoin 12s ease-out infinite;}
.sms-join .jteam{width:46px;height:46px;border-radius:14px;background:var(--tint);display:flex;align-items:center;justify-content:center;font-size:24px;margin-bottom:7px;box-shadow:0 8px 18px -8px rgba(2,80,203,.55);}
.sms-join b{font-size:17px;font-weight:800;color:var(--ink);}
.sms-join .jsub{font-size:11.5px;color:var(--muted);margin-top:1px;}
@keyframes smsJoin{0%,90%{opacity:0;transform:scale(.93)}96%,100%{opacity:1;transform:scale(1)}}

/* player sequence plays ONCE and holds the final "join the team" beat (no loop back) */
.gcx.once .chaos,.gcx.once .cwrap,.gcx.once .sweep,.gcx.once .calm,
.gcx.once .s1,.gcx.once .s2,.gcx.once .s3,.gcx.once .sms-join{
  animation-iteration-count:1;animation-fill-mode:forwards;animation-duration:16s;}
.gcx.once .calm{animation-name:calmHold;}

@keyframes buzz{0%,84%,100%{transform:rotate(0)}88%{transform:rotate(-11deg)}92%{transform:rotate(11deg)}96%{transform:rotate(-6deg)}}

/* =============================================================================
 * Shared interactive flow pieces (slices 1–4) — the live onboarding pages
 * (onboarding-manager.html, onboarding-player.html) both build on these.
 * Moved out of onboarding-manager.html so the player flow REUSES, not
 * re-forks, the phone / verify / consent / celebration components.
 * ========================================================================== */

*{box-sizing:border-box;}
html,body{margin:0;height:100%;}
body{background:var(--bg);color:var(--ink);
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  display:flex;align-items:center;justify-content:center;padding:0;}

/* Web frame: full-screen on phones, a centered rounded card on larger screens.
 * Fixed height (dvh tracks mobile browser chrome) so the body scrolls
 * INTERNALLY and the CTA stays pinned — the frame must never grow with
 * content or the primary button falls below the fold. */
.frame{width:100%;max-width:440px;height:100vh;height:100dvh;background:#fff;display:flex;flex-direction:column;}
@media(min-width:520px){
  body{padding:24px;}
  .frame{min-height:0;height:min(760px,calc(100vh - 48px));border-radius:24px;
    box-shadow:0 24px 60px -24px rgba(2,80,203,.28),0 0 0 1px var(--line);overflow:hidden;}
}
/* The Onboarding.screen() scaffold fills the frame. */
.frame .ui{flex:1;min-height:0;}
.frame .ui-body{padding-left:22px;padding-right:22px;}
.frame .ui-cta{padding-left:20px;padding-right:20px;padding-bottom:calc(34px + env(safe-area-inset-bottom));}

/* Vertically-centered screen body (phone / verify / consent / …).
 * margin:auto centers when the content is shorter than the screen but
 * degrades to a normal top-aligned scroll when it's taller — unlike
 * justify-content:center, which clips the top off overflowing content. */
.center-body{margin:auto 0;display:flex;flex-direction:column;text-align:center;padding:8px 0 14px;}
/* Form elements keep left-aligned text inside centered bodies. */
.center-body .ifield,.center-body .card{text-align:left;}
.center-body h2.t{font-size:26px;margin:0 0 8px;}
.center-body .sub{font-size:14.5px;margin:0 0 26px;}
.center-body .finehint{font-size:11.5px;color:var(--muted2);margin:14px 0 0;}
.center-body .finehint a{color:var(--brand);font-weight:600;text-decoration:none;}

/* Agreement checkboxes (SMS consent, terms, 18+). */
.agree{display:flex;align-items:flex-start;gap:10px;text-align:left;margin:14px 0 0;
  padding:12px 14px;border:1.5px solid var(--line);border-radius:13px;background:var(--bg);cursor:pointer;}
.agree input{width:18px;height:18px;margin:1px 0 0;accent-color:var(--brand);flex:0 0 auto;cursor:pointer;}
.agree span{font-size:12.5px;color:var(--muted);line-height:1.45;}
.agree a{color:var(--brand);font-weight:600;text-decoration:none;}
.agree:has(input:checked){border-color:var(--brand);background:var(--tint);}

/* First/last name side by side. */
.name-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px;}
.name-grid .ifield{margin-bottom:0;text-align:left;}

/* Large phone input with a fixed +1 country code. */
.phone-row{display:flex;align-items:center;gap:10px;border:1.5px solid var(--line);border-radius:16px;
  background:var(--bg);padding:16px;}
.phone-row:focus-within{border-color:var(--brand);background:#fff;}
.phone-row select.cc{flex:0 0 auto;border:0;outline:0;background:transparent;font-family:inherit;
  font-size:18px;font-weight:700;color:var(--muted);padding:0;appearance:none;-webkit-appearance:none;
  cursor:pointer;text-align:right;}
.phone-row .ccwrap{flex:0 0 auto;display:flex;align-items:center;gap:3px;border-right:1.5px solid var(--line);padding-right:10px;}
.phone-row .ccwrap::after{content:"▾";font-size:11px;color:var(--muted2);}
.phone-row input{flex:1;min-width:0;border:0;outline:0;background:transparent;font-family:inherit;
  font-size:21px;font-weight:700;letter-spacing:.3px;color:var(--ink);}
.phone-row input::placeholder{color:var(--line2);font-weight:500;}

/* Editable field (the design-system .field is display-only). */
.ifield{border:1.5px solid var(--line);border-radius:13px;padding:9px 14px;margin-bottom:10px;background:var(--bg);}
.ifield:focus-within{border-color:var(--brand);background:#fff;}
.ifield .lbl{font-size:11px;color:var(--muted2);font-weight:600;margin-bottom:2px;}
.ifield input{width:100%;border:0;outline:0;background:transparent;font-size:16px;font-weight:600;color:var(--ink);padding:0;font-family:inherit;}
.ifield input::placeholder{color:var(--line2);font-weight:500;}

/* Code-entry boxes (verify). */
.codeboxes{display:flex;gap:8px;justify-content:space-between;margin:6px 0 12px;}
.codeboxes input{flex:1;width:0;height:54px;border:1.5px solid var(--line);border-radius:12px;
  text-align:center;font-size:22px;font-weight:700;background:var(--bg);color:var(--brand-d);font-family:inherit;outline:0;}
.codeboxes input:focus{border-color:var(--brand);background:#fff;}

/* Full-bleed landing screens (no app bar) — logo on top, hero filling the
 * middle, tagline, CTAs pinned to the bottom. */
.hero-logo{height:46px;width:156px;background:var(--logo) center/contain no-repeat;margin:18px auto 0;flex:0 0 auto;}
.ui-body-flex{display:flex;flex-direction:column;}
.welcome-body{flex:1;display:flex;flex-direction:column;align-items:center;text-align:center;
  justify-content:space-evenly;gap:14px;}
/* The hero flexes to take most of the screen; the feed-scroll keyframe is
 * content-relative (cqh) so any height works. Cap it so the chaos scroll
 * keeps visible motion (the thread is ~600px tall). */
.welcome-body .gcx{height:auto;flex:1 1 0;min-height:260px;max-height:500px;}
.welcome-body .tagline{font-size:15.5px;color:var(--muted);line-height:1.5;max-width:300px;margin:0;}

/* Invite / celebration hero (icon tile + heading + team chip). */
.invite-hero{display:flex;flex-direction:column;align-items:center;text-align:center;padding:0 6px;}
.invite-ic{position:relative;width:104px;height:104px;border-radius:30px;background:linear-gradient(160deg,#E7EFFC,#fff);
  border:1px solid var(--line);display:flex;align-items:center;justify-content:center;font-size:50px;box-shadow:0 16px 34px -16px rgba(2,80,203,.45);}
.invite-ic .badge-share{position:absolute;right:-7px;bottom:-7px;width:36px;height:36px;border-radius:50%;background:var(--brand);
  color:#fff;display:flex;align-items:center;justify-content:center;font-size:17px;border:2.5px solid #fff;box-shadow:0 6px 14px -4px rgba(2,80,203,.6);}
.invite-hero h2{font-size:23px;margin:22px 0 0;}
.invite-hero .sub{text-align:center;max-width:248px;margin-top:9px;}
.team-chip{display:inline-flex;align-items:center;gap:7px;background:var(--tint);color:var(--brand-d);font-weight:700;font-size:13px;padding:6px 14px 6px 7px;border-radius:99px;margin-top:18px;}
.team-chip .av{width:23px;height:23px;border-radius:50%;background:var(--brand);color:#fff;display:flex;align-items:center;justify-content:center;font-size:10.5px;font-weight:800;}

/* Done-screen celebration — confetti rain + badge pop + staggered entrance.
 * Pure CSS; pieces are clipped by the .confetti box (inset:0 against the
 * positioned .ui-body) so they never stretch the scroll area, and
 * pointer-events:none keeps everything tappable underneath. */
.frame .ui-body{position:relative;}
.confetti{position:absolute;inset:0;overflow:hidden;pointer-events:none;z-index:1;}
/* One celebratory burst (~2s), then out of the way — pieces fall once and
 * return to their base opacity:0, leaving the copy and CTAs easy to read. */
.confetti i{position:absolute;top:-16px;border-radius:2px;opacity:0;
  animation:confetti-fall var(--dur,1.8s) linear var(--delay,0s) 1;}
@keyframes confetti-fall{
  0%{transform:translate3d(0,0,0) rotateZ(0) rotateY(0);opacity:0;}
  6%{opacity:.95;}
  80%{opacity:.95;}
  100%{transform:translate3d(var(--drift,20px),640px,0) rotateZ(var(--spin,540deg)) rotateY(720deg);opacity:0;}
}
.done-pop{animation:pop-in .6s cubic-bezier(.2,1.4,.4,1) both;}
@keyframes pop-in{0%{transform:scale(0);}60%{transform:scale(1.12);}100%{transform:scale(1);}}
.done-pop .tada{display:inline-block;animation:tada 3.2s ease 1.1s infinite;}
@keyframes tada{ /* quick wobble, then rest for most of the loop */
  0%,30%,100%{transform:rotate(0) scale(1);}
  6%{transform:rotate(-10deg) scale(1.06);}
  12%{transform:rotate(9deg) scale(1.1);}
  18%{transform:rotate(-6deg) scale(1.06);}
  24%{transform:rotate(4deg) scale(1.02);}
}
.done-ring{position:absolute;inset:-10px;border-radius:36px;border:2.5px solid var(--brand);
  opacity:0;animation:ring-pulse 2.2s ease-out .5s infinite;pointer-events:none;}
@keyframes ring-pulse{0%{transform:scale(.82);opacity:.55;}70%{transform:scale(1.3);opacity:0;}100%{transform:scale(1.3);opacity:0;}}
.rise{animation:rise .55s ease both;}
@keyframes rise{from{transform:translateY(16px);opacity:0;}to{transform:translateY(0);opacity:1;}}
@media (prefers-reduced-motion:reduce){
  .confetti{display:none;}
  .done-pop,.done-pop .tada,.done-ring,.rise{animation:none;}
}

/* Side-by-side official store badges (Onboarding.storeBadges()). */
.store-row{display:flex;gap:10px;justify-content:center;align-items:center;margin-bottom:4px;}
.store-row a{display:block;}
.store-row img{height:44px;width:auto;display:block;}

/* Toast / inline error. */
.note{font-size:12.5px;margin:8px 0 0;min-height:16px;}
.note.err{color:#C53030;}
.note.ok{color:#2F855A;}
.btn[disabled]{opacity:.5;pointer-events:none;}
.spin{display:inline-block;width:15px;height:15px;border:2px solid rgba(255,255,255,.5);border-top-color:#fff;
  border-radius:50%;animation:spin .7s linear infinite;vertical-align:-2px;margin-right:7px;}
@keyframes spin{to{transform:rotate(360deg);}}
