:root{
  --zb-blue:#0079BD; --zb-blue-dark:#005f95; --zb-blue-soft:#E6F2F9;
  /* THE primary-button treatment (BRIEF-021). Single source: .btn below and app.js's DARKBTN
     both resolve to this, so Spin, the award screen, onboarding and every CTA cannot drift. */
  --btn-grad:linear-gradient(100deg,#04070D 0%,#0A1421 26%,#123156 55%,#1E63A8 82%,#2E86D6 100%);
  --bg:#F5F7FA; --card:#FFFFFF; --ink:#1A1A1A; --muted:#6B7280; --line:#ECEFF3;
  --good:#1E9E5A; --bad:#D64545; --gold:#E8B923;
  --radius:16px; --radius-sm:10px;
  --shadow:0 1px 2px rgba(16,24,40,.04),0 4px 16px rgba(16,24,40,.06);
  --shadow-lg:0 8px 30px rgba(16,24,40,.12);
  --font:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{margin:0;padding:0}
body{font-family:var(--font);background:#e9edf2;color:var(--ink);-webkit-font-smoothing:antialiased}
#app{max-width:460px;margin:0 auto;min-height:100vh;background:var(--bg);position:relative;box-shadow:var(--shadow-lg);overflow:hidden}
.appbar{position:sticky;top:0;z-index:20;display:flex;align-items:center;gap:12px;padding:15px 18px;background:rgba(255,255,255,.92);backdrop-filter:saturate(180%) blur(20px);border-bottom:1px solid var(--line)}
.appbar .brand{font-weight:800;font-size:19px;letter-spacing:-.02em}
.appbar .brand span{color:var(--zb-blue)}
.appbar .spacer{flex:1}
.pts{background:var(--zb-blue);color:#fff;font-weight:800;font-size:13px;padding:5px 12px;border-radius:999px}
.bell{position:relative;background:none;border:none;cursor:pointer;color:var(--ink);padding:2px;display:flex}
.bell .badge{position:absolute;top:-4px;right:-5px}
.badge{background:var(--bad);color:#fff;border-radius:999px;font-size:10px;font-weight:800;padding:0 5px;min-width:16px;height:16px;display:inline-flex;align-items:center;justify-content:center}
/* Bottom padding reserves the fixed .tabbar (64px) plus the iOS home-bar inset, so no
   screen's last element can sit underneath the nav. */
.screen{padding:18px 18px calc(96px + env(safe-area-inset-bottom,0px));animation:fade .25s ease}
@keyframes fade{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
@keyframes popIn{from{opacity:0;transform:scale(.9) translateY(10px)}to{opacity:1;transform:none}}
@keyframes ringSpin{from{transform:rotate(0)}to{transform:rotate(360deg)}}
@keyframes reelDrift{from{transform:translate3d(0,0,0)}to{transform:translate3d(-50%,0,0)}}
@keyframes sheen{0%{transform:translateX(-140%) skewX(-16deg);opacity:0}8%{opacity:1}26%{transform:translateX(240%) skewX(-16deg);opacity:1}34%{opacity:0}100%{transform:translateX(240%) skewX(-16deg);opacity:0}}
@keyframes btnGlow{0%,100%{box-shadow:0 6px 20px rgba(3,8,18,.45),0 0 0 rgba(56,160,235,0)}50%{box-shadow:0 8px 28px rgba(3,8,18,.5),0 0 30px rgba(56,160,235,.4)}}
/* Talking points (a meetup partner's icebreakers) — given more presence than a plain card,
   since it is the thing that gets a conversation started. Static, so the tinted background is
   safe (no backdrop-filter on anything animated). */
.card.talk{background:linear-gradient(160deg,#F2F8FC 0%,#E9F3FA 100%);border-color:#CFE4F1}
.card.talk .q{margin:10px 0 0}
.card.talk .q .t{color:var(--zb-blue);font-weight:650}
.card.talk .ans{margin-top:5px;white-space:pre-wrap;color:var(--ink)}
.card.talk .lead{display:flex;align-items:center;gap:10px}
.card.talk .lead .nicon{flex:none}
/* the +10 icebreaker chip on the award screen sits under the 30-point chip */
.zb-chip-bonus{margin-top:10px;animation:zbAwardPop .6s .52s cubic-bezier(.2,1.3,.4,1) both}
.zb-chip-bonus .n{font-size:19px}
.zb-chip-bonus .t{font-size:15px}
/* Language cue on a colleague's card (BRIEF-023) — a compact pill, not an emoji flag, so it
   renders identically on every platform and matches the tierpill treatment. */
.langpill{display:inline-block;white-space:nowrap;font-size:10px;font-weight:800;letter-spacing:.6px;color:var(--zb-blue);background:var(--zb-blue-soft);border:1px solid #CFE4F1;padding:2px 6px;border-radius:6px;vertical-align:middle}
/* SVG flag badge (BRIEF-023A): rounded, hairline border, sits on the text baseline. */
.langflag{display:inline-flex;align-items:center;vertical-align:middle;width:20px;height:13px;border-radius:3px;overflow:hidden;box-shadow:0 0 0 1px rgba(16,24,40,.18)}
.langflag svg{display:block}
/* ---- Go-live countdown (BRIEF-019, ported from the Claude Design handoff) ----
   NOTE on backdrop-filter: the handoff puts it on the frosted card, which also has a riseIn
   entry animation — exactly the combination CLAUDE.md forbids (Android Chrome flicker, already
   bitten). The card background is rgba(255,255,255,.94), so the blur contributes almost
   nothing; it is dropped on the animated card and kept only on static elements. */
@keyframes zbDriftR{from{transform:translateX(-104%)}to{transform:translateX(392px)}}
@keyframes zbDriftL{from{transform:translateX(392px)}to{transform:translateX(-104%)}}
@keyframes zbTickBeat{0%,100%{opacity:.35}50%{opacity:1}}
.zb-cd{position:relative;min-height:100vh;min-height:100dvh;display:flex;flex-direction:column;overflow:hidden}
.zb-cd .behind{position:absolute;inset:0;z-index:0;filter:blur(18px);opacity:.9;pointer-events:none;transform:scale(1.04)}
.zb-cd .scrim{position:absolute;inset:0;z-index:1;pointer-events:none;background:linear-gradient(180deg,rgba(12,34,58,.5) 0%,rgba(12,34,58,.66) 60%,rgba(8,24,42,.78) 100%)}
.zb-cd .band{position:relative;z-index:2;flex:none;pointer-events:none}
.zb-cd .band.top{padding:calc(6px + env(safe-area-inset-top,0px)) 0 0}
.zb-cd .band.bot{padding:0 0 calc(12px + env(safe-area-inset-bottom,0px))}
.zb-cd .lane{position:relative;height:48px;overflow:hidden;margin-bottom:6px}
.zb-cd .stage{position:relative;z-index:2;flex:1;display:flex;flex-direction:column;justify-content:center;padding:6px 20px}
.zb-pill{position:absolute;left:0;top:0;display:inline-flex;align-items:center;gap:11px;padding:4px 22px 4px 4px;border-radius:999px;box-shadow:0 6px 18px rgba(6,20,38,.16)}
.zb-pill .av{width:40px;height:40px;border-radius:999px;border:3px solid #fff;box-shadow:0 3px 10px rgba(6,20,38,.22);object-fit:cover;display:flex;align-items:center;justify-content:center;color:#fff;font-size:14px;font-weight:700;letter-spacing:.4px;flex:none;overflow:hidden}
.zb-pill .nm{font-size:16.5px;font-weight:700;letter-spacing:-.3px;color:#fff;white-space:nowrap}
.zb-cd-card{border-radius:28px;padding:22px 22px 18px;text-align:center;background:rgba(255,255,255,.94);border:1px solid rgba(255,255,255,.7);box-shadow:0 24px 60px rgba(4,14,28,.34),0 2px 8px rgba(4,14,28,.16);animation:riseIn .55s ease-out both}
.zb-cd-card .logo{height:23px;width:auto;margin:0 auto 16px;display:block}
.zb-clock{position:relative;width:104px;height:104px;margin:0 auto;display:flex;align-items:center;justify-content:center;animation:zbAwardPop .6s .08s cubic-bezier(.2,1.3,.4,1) both}
.zb-clock .ring{position:absolute;inset:0;border:2px solid rgba(0,121,189,.34);border-radius:999px;animation:zbRingPulse 2.8s ease-out infinite}
.zb-clock .ring-dashed{position:absolute;inset:11px;border:2px dashed rgba(0,121,189,.26);border-radius:999px;animation:ringSpin 26s linear infinite}
.zb-clock .disc{width:72px;height:72px;border-radius:999px;display:flex;align-items:center;justify-content:center;color:#fff;background:linear-gradient(160deg,#3E6EA8 0%,#2F5F9E 45%,#20416F 100%);box-shadow:0 12px 28px rgba(32,65,111,.34)}
.zb-cd-eyebrow{display:inline-flex;align-items:center;gap:7px;margin-top:14px;padding:6px 13px 6px 9px;border-radius:999px;background:var(--zb-blue-soft);color:var(--zb-blue);font-size:11px;font-weight:700;letter-spacing:1.3px;animation:riseIn .5s .16s both}
.zb-cd-eyebrow .dot{width:7px;height:7px;border-radius:999px;background:var(--zb-blue);animation:zbTickBeat 1.6s ease-in-out infinite}
.zb-cd-card h1{margin:10px 0 0;font-size:27px;font-weight:700;line-height:1.14;letter-spacing:-.7px;color:#1A1A1A;animation:riseIn .5s .22s both}
.zb-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin-top:16px;animation:riseIn .5s .3s both}
.zb-tile{padding:11px 4px 9px;border-radius:16px;background:#F5F7FA;border:1px solid #E7ECF2}
.zb-tile .v{font-size:29px;font-weight:700;letter-spacing:-1.2px;color:#20416F;font-variant-numeric:tabular-nums}
.zb-tile .l{font-size:10px;font-weight:700;letter-spacing:.9px;color:#8A94A3;text-transform:uppercase;margin-top:7px}
.zb-tile.sec{background:var(--zb-blue-soft);border-color:#CFE4F1}
.zb-tile.sec .v{color:var(--zb-blue)}
.zb-tile.sec .l{color:#5E93B6}
.zb-cd-sub{margin-top:14px;font-size:14px;line-height:1.55;color:var(--muted);animation:riseIn .5s .38s both}
.zb-cd-sub b{color:#1A1A1A;font-weight:650}
.zb-cd-foot{display:flex;flex-direction:column;align-items:center;gap:9px;margin-top:12px;animation:riseIn .5s .5s both}
.zb-how{display:inline-flex;align-items:center;gap:9px;padding:11px 20px 11px 17px;min-height:44px;border-radius:999px;background:rgba(255,255,255,.16);border:1px solid rgba(255,255,255,.3);color:#fff;font-family:inherit;font-size:14px;font-weight:650;letter-spacing:-.1px;cursor:pointer}
.zb-how:hover{background:rgba(255,255,255,.26)}
.zb-tz{font-size:12.5px;font-weight:600;color:rgba(255,255,255,.66);text-align:center}
/* Reduced motion: entry, rings and the heartbeat stop and the pills hold still — but the
   countdown keeps ticking, because it is information rather than decoration. */
@media (prefers-reduced-motion: reduce){
  .zb-cd *,.zb-pill,.zb-clock,.zb-clock .ring,.zb-clock .ring-dashed,.zb-cd-card{animation:none !important}
}
/* ---- Points Awarded screen (BRIEF-017, ported from the Claude Design handoff) ----
   btnGlow above is already byte-identical to the handoff's, so it is reused. popIn/riseIn are
   NOT: ours are gentler and shared by other screens, so the award screen gets its own. */
@keyframes zbAwardPop{0%{opacity:0;transform:scale(.6) rotate(-8deg)}60%{opacity:1;transform:scale(1.08) rotate(2deg)}100%{opacity:1;transform:scale(1) rotate(0)}}
@keyframes zbAwardRise{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:translateY(0)}}
@keyframes zbRingPulse{0%{transform:scale(.85);opacity:.55}70%,100%{transform:scale(1.5);opacity:0}}
@keyframes zbChipFloat{0%,100%{transform:translateY(0)}50%{transform:translateY(-5px)}}
.zb-award{position:relative;min-height:100vh;min-height:100dvh;display:flex;flex-direction:column;background:var(--bg);overflow:hidden}
.zb-award .glow{position:absolute;top:-140px;left:50%;transform:translateX(-50%);width:520px;height:520px;pointer-events:none;background:radial-gradient(circle,rgba(0,121,189,.16) 0%,rgba(0,121,189,0) 68%)}
.zb-award canvas{position:absolute;inset:0;width:100%;height:100%;z-index:30;pointer-events:none}
.zb-award .body{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px 22px 0;text-align:center;position:relative;z-index:2}
.zb-award .foot{padding:22px 16px 26px;display:flex;flex-direction:column;gap:6px;position:relative;z-index:2;animation:zbAwardRise .5s .62s both}
.zb-medal{position:relative;width:150px;height:150px;display:flex;align-items:center;justify-content:center;animation:zbAwardPop .62s cubic-bezier(.2,1.3,.4,1) both}
.zb-medal .ring{position:absolute;inset:0;border:2px solid rgba(0,121,189,.35);border-radius:999px;animation:zbRingPulse 2.6s ease-out infinite}
.zb-medal .ring-dashed{position:absolute;inset:14px;border:2px dashed rgba(0,121,189,.22);border-radius:999px}
.zb-medal .disc{width:104px;height:104px;border-radius:999px;display:flex;align-items:center;justify-content:center;color:#fff;background:linear-gradient(160deg,#3E6EA8 0%,#2F5F9E 45%,#20416F 100%);box-shadow:0 14px 34px rgba(32,65,111,.34)}
.zb-award .eyebrow{margin-top:26px;font-size:11.5px;font-weight:700;letter-spacing:1.6px;color:var(--zb-blue);animation:zbAwardRise .5s .12s both}
.zb-award h1{margin:12px 0 0;font-size:31px;font-weight:700;line-height:1.14;letter-spacing:-.8px;color:#1A1A1A;animation:zbAwardRise .5s .2s both}
.zb-award .sub{margin-top:13px;font-size:14.5px;line-height:1.55;color:var(--muted);max-width:320px;animation:zbAwardRise .5s .28s both}
.zb-chip-award{display:inline-flex;align-items:center;gap:11px;margin-top:26px;padding:13px 22px 13px 15px;border-radius:999px;background:#fff;border:1px solid #DCE7F0;box-shadow:0 4px 18px rgba(16,24,40,.1),0 0 0 6px rgba(0,121,189,.06);animation:zbAwardPop .6s .42s cubic-bezier(.2,1.3,.4,1) both,zbChipFloat 3.4s 1.1s ease-in-out infinite}
.zb-chip-award .puck{width:34px;height:34px;border-radius:999px;background:var(--zb-blue-soft);color:var(--zb-blue);display:flex;align-items:center;justify-content:center;flex:none}
.zb-chip-award .n{font-size:22px;font-weight:700;color:var(--zb-blue);letter-spacing:-.3px}
.zb-chip-award .t{font-size:16px;font-weight:600;color:#1A1A1A;letter-spacing:-.3px}
.zb-award .balance{margin-top:16px;font-size:12.5px;font-weight:600;color:#8A94A3;animation:zbAwardRise .5s .55s both}
.zb-primary-btn{position:relative;overflow:hidden;width:100%;border:0;cursor:pointer;display:flex;align-items:center;justify-content:center;gap:10px;padding:19px;border-radius:999px;color:#fff;font-family:inherit;font-size:17px;font-weight:600;letter-spacing:-.2px;background:var(--btn-grad);animation:btnGlow 4.6s ease-in-out infinite}
.zb-primary-btn:active{transform:scale(.985)}
.zb-ghost-btn{width:100%;background:none;border:0;cursor:pointer;padding:14px;font-family:inherit;font-size:14.5px;font-weight:600;color:var(--muted)}
.zb-ghost-btn:hover{color:var(--zb-blue)}
/* Honour reduced motion: keep the final layout, drop the looping motion (confetti is skipped in JS). */
@media (prefers-reduced-motion: reduce){
  .zb-award *,.zb-medal,.zb-medal .ring,.zb-chip-award,.zb-primary-btn{animation:none !important}
}
@keyframes dashDraw{from{stroke-dashoffset:230}to{stroke-dashoffset:0}}
@keyframes dashFlow{from{stroke-dashoffset:0}to{stroke-dashoffset:-24}}
@keyframes sparkPulse{0%,100%{transform:scale(1);box-shadow:0 6px 18px rgba(0,121,189,.26),0 0 0 rgba(0,121,189,.30)}50%{transform:scale(1.09);box-shadow:0 8px 22px rgba(0,121,189,.3),0 0 0 14px rgba(0,121,189,0)}}
@keyframes a2up{0%,100%{transform:translateY(0)}50%{transform:translateY(-4px)}}
@keyframes riseIn{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
.a2hs{position:fixed;left:50%;transform:translateX(-50%);bottom:14px;width:calc(100% - 24px);max-width:436px;background:#fff;border:1px solid var(--line);border-radius:16px;box-shadow:var(--shadow-lg);display:flex;align-items:center;gap:12px;padding:12px 12px 12px 14px;z-index:200;animation:fade .3s ease}
.a2hs .a2hs-ic img{width:46px;height:46px;border-radius:12px;display:block}
.a2hs .a2hs-txt{flex:1;min-width:0}
.a2hs .a2hs-txt b{font-size:14px}
.a2hs .a2hs-sub{font-size:12.5px;color:var(--muted);margin-top:3px;line-height:1.45}
.a2hs .a2hs-sub svg{vertical-align:-4px;margin:0 1px}
.a2hs .a2hs-x{background:none;border:none;color:var(--muted);cursor:pointer;padding:4px;align-self:flex-start}
.a2hs .a2hs-arrow{position:absolute;left:50%;bottom:-9px;transform:translateX(-50%);color:#fff;filter:drop-shadow(0 2px 2px rgba(16,24,40,.12));animation:a2up 1.8s ease-in-out infinite}
h2{font-size:22px;font-weight:800;letter-spacing:-.02em;margin:4px 0 2px}
.sub{color:var(--muted);font-size:14px;margin:0 0 16px}
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);padding:16px;margin-bottom:14px}
.row{display:flex;align-items:center;gap:12px}
.between{justify-content:space-between}
.chip{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;padding:4px 10px;border-radius:999px;background:var(--zb-blue-soft);color:var(--zb-blue)}
.chip.grey{background:#F1F3F6;color:var(--muted)}
.chip.good{background:#E7F6EE;color:var(--good)}
.chip.gold{background:#FBF3D7;color:#9a7b10}
/* Sized to match the Welcome screen's "Create account" CTA (19px vertical, 17px/600, pill),
   so every full-width primary in the app has the same weight. .btn.sm below stays compact. */
.btn{appearance:none;border:none;cursor:pointer;font-family:inherit;font-size:17px;font-weight:600;letter-spacing:-.2px;padding:19px;border-radius:999px;background:var(--btn-grad);color:#fff;width:100%;min-height:44px;transition:transform .06s,filter .15s,opacity .15s;display:inline-flex;align-items:center;justify-content:center;gap:10px;animation:btnGlow 4.6s ease-in-out infinite}
.btn:active{transform:scale(.98)}
.btn:hover{filter:brightness(1.08)}
.btn:disabled{opacity:.4;cursor:not-allowed;animation:none;box-shadow:none;filter:none}
.btn.secondary{background:var(--zb-blue-soft);color:var(--zb-blue);animation:none;box-shadow:none;border-radius:12px}
.btn.secondary:hover{background:#d6e9f4;filter:none}
.btn.ghost{background:transparent;color:var(--muted);animation:none;box-shadow:none;border-radius:12px}
.btn.alt{background:#fff;color:var(--zb-blue);border:1px solid #DCE7F0;box-shadow:var(--shadow);animation:none;border-radius:999px}
.btn.alt:hover{background:#F5FAFD;filter:none}
.btn.ghost:hover{background:#f1f3f6;filter:none}
.btn.danger{background:transparent;color:var(--bad);border:1px solid #f3d0d0;animation:none;box-shadow:none;border-radius:12px}
.btn.danger:hover{background:#fdecec;filter:none}
/* Small primaries keep the shared gradient but not the pulsing glow: two compact buttons can
   sit side by side (admin Save + Add), and pulsing both would compete. The glow stays for the
   one full-width CTA per screen. */
.btn.sm{width:auto;padding:9px 13px;font-size:14px;font-weight:700;letter-spacing:0;gap:8px;border-radius:10px;min-height:auto;animation:none;box-shadow:none}
.avatar{border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-weight:800;color:#fff;flex:0 0 auto;width:44px;height:44px;font-size:15px;overflow:hidden}
.avatar.lg{width:120px;height:120px;font-size:40px;box-shadow:var(--shadow-lg)}
.avatar.sm{width:34px;height:34px;font-size:12px}
.input,textarea.input{width:100%;font-family:inherit;font-size:15px;padding:11px 12px;border:1px solid var(--line);border-radius:10px;background:#fff;color:var(--ink);outline:none}
.input:focus{border-color:var(--zb-blue);box-shadow:0 0 0 3px var(--zb-blue-soft)}
textarea.input{resize:vertical}
/* No backdrop-filter here: the bar is also transform:translateX(-50%) for centring, and that
   combination causes repaint flicker on Android Chrome (CLAUDE.md guardrail, BRIEF-022). The
   background is solid instead of .96 + blur, so it reads the same and can never let scrolled
   content bleed through. */
.tabbar{position:fixed;left:50%;transform:translateX(-50%);bottom:0;width:100%;max-width:460px;display:flex;background:var(--card);border-top:1px solid var(--line);z-index:30;padding-bottom:env(safe-area-inset-bottom,0px)}
.tabbar button{flex:1;border:none;background:none;padding:9px 0 12px;font-family:inherit;font-size:10.5px;font-weight:600;color:var(--muted);cursor:pointer;display:flex;flex-direction:column;align-items:center;gap:3px}
.tabbar button.active{color:var(--zb-blue)}
/* BRIEF-036 — an icon must never be its own tap target.
   The heart is a small .iconbtn whose inline SVG covers nearly the whole control. Older
   WebKit let a tap on that child SVG fire the parent button; the newest WebKit does not
   deliver it reliably, so the heart read as dead on an iPhone 18 Pro while working on a 13.
   Making icons transparent to pointers means the tap always lands on the button itself.

   Verified safe before applying: `class="ic"` has exactly one producer (icon(), app.js:36),
   no <svg> anywhere carries an inline handler, and no addEventListener binds to an svg or
   .ic — every handler is on a parent button or anchor. So nothing relies on an icon being
   the click target. */
.ic{display:inline-block;vertical-align:middle;pointer-events:none}
/* spinnerIcon() emits a bare <svg> with no .ic class, and one of them sits inside the
   bottom Spin tab — the most-tapped control in the app — so .ic alone would have left it
   exposed to exactly the same failure. This covers every icon inside a control, whichever
   function drew it. */
.btn svg,.iconbtn svg,.tabbar button svg{pointer-events:none}
.btn.white{background:#fff;color:var(--zb-blue);animation:none;box-shadow:none;border-radius:12px} .btn.white:hover{background:#eef5fb;filter:none}
.prize{background:linear-gradient(135deg,#0079BD,#005f95);color:#fff;border:none}
.prizerow{display:flex;gap:9px;margin-top:14px}
.prizecard{flex:1;background:rgba(255,255,255,.14);border-radius:12px;padding:12px 6px;text-align:center}
.prizecard .pk{font-size:10px;font-weight:800;opacity:.85;letter-spacing:.04em}
.prizecard .pv{font-size:13px;font-weight:800;margin-top:4px}
.mailbox{display:flex;align-items:center;gap:12px;cursor:pointer}
select.input{appearance:none;-webkit-appearance:none;background:#fff url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236B7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>") no-repeat right 12px center}
/* onboarding: content top, buttons low (thumb reach) */
.ob{min-height:calc(100vh - 130px);display:flex;flex-direction:column}
.ob-cta{margin-top:auto;padding-top:20px}
/* meetup detail blue header */
.meet-hero{background:linear-gradient(160deg,#0079BD,#005f95);border-radius:18px;padding:18px;color:#fff;box-shadow:var(--shadow-lg);margin-bottom:16px}
.meet-hero .muted{color:rgba(255,255,255,.8)}
/* full-height chat */
/* The composer used to slide under the fixed nav because the CARD was sized off the
   viewport (height:calc(100vh - ...)): any error in the estimate of the chrome above it,
   or a mobile-browser viewport quirk, pushed its bottom edge past the nav.
   So: the card stays in NORMAL FLOW (no viewport height) and only the scrolling message
   list is sized. .screen's bottom padding (nav + home-bar inset) is then a hard floor the
   card cannot cross, whatever the viewport does — worst case the page scrolls a little. */
.threadcard{display:flex;flex-direction:column}
.threadcard>.row{flex:0 0 auto}
.threadcard .thread{flex:0 0 auto;max-height:none;overflow:auto;
  height:calc(100vh - 380px);
  height:calc(100dvh - 380px - env(safe-area-inset-bottom,0px));
  min-height:200px}
/* notifications as spaced cards */
.ncard{display:flex;gap:12px;align-items:center;background:#fff;border:1px solid var(--line);border-radius:14px;padding:13px 14px;margin-bottom:10px;box-shadow:var(--shadow);cursor:pointer}
.ncard.unread{background:var(--zb-blue-soft);border-color:#cfe6f5}
.muted{color:var(--muted)} .center{text-align:center} .small{font-size:12px}
.q{margin:12px 0}.q .t{font-size:15px;font-weight:600;margin-bottom:6px}
/* inline-block + nowrap so the pill can wrap to the next line as a unit but never split
   "key" / "idea" across two lines mid-pill */
.tierpill{display:inline-block;white-space:nowrap;font-size:10px;font-weight:800;color:var(--zb-blue);background:var(--zb-blue-soft);padding:2px 7px;border-radius:999px;margin-left:6px;vertical-align:middle}
.wall-photo{aspect-ratio:1;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:800;font-size:15px;text-align:center;padding:8px;line-height:1.25;border-radius:12px}
.msg{max-width:80%;padding:9px 12px;border-radius:14px;font-size:14px;margin-bottom:7px;line-height:1.35}
.msg.them{background:#F1F3F6;border-bottom-left-radius:4px;align-self:flex-start}
.msg.me{background:var(--zb-blue);color:#fff;border-bottom-right-radius:4px;align-self:flex-end;margin-left:auto}
.thread{display:flex;flex-direction:column;max-height:230px;overflow:auto;padding:2px}
.rankrow{display:flex;align-items:center;gap:11px;padding:10px 0;border-top:1px solid var(--line)}
.rankrow:first-child{border-top:none}
.rankrow .n{width:20px;font-weight:800;color:var(--muted);text-align:center}
.rankrow .nm{flex:1;font-weight:600;font-size:15px}
.rankrow .p{font-weight:800;font-size:13px;color:#fff;background:var(--zb-blue);padding:3px 10px;border-radius:999px}
.rankrow.me{background:var(--zb-blue-soft);margin:0 -8px;padding:10px 8px;border-radius:10px;border:none}
.toast{position:fixed;left:50%;bottom:84px;transform:translateX(-50%);background:var(--ink);color:#fff;padding:10px 16px;border-radius:999px;font-size:13px;font-weight:600;z-index:50;opacity:0;transition:opacity .2s,transform .2s;pointer-events:none;white-space:nowrap;max-width:92%}
.toast.show{opacity:1;transform:translateX(-50%) translateY(-4px)}
.note{background:#FFF9E6;border:1px solid #F2E4B0;color:#7a5c00;font-size:12px;padding:9px 11px;border-radius:10px;margin-bottom:12px}
.hr{height:1px;background:var(--line);margin:14px 0}
.notif{display:flex;gap:12px;padding:12px 0;border-top:1px solid var(--line);cursor:pointer}
.notif:first-child{border-top:none}
.notif.unread{background:var(--zb-blue-soft);margin:0 -8px;padding:12px 8px;border-radius:10px;border:none}
.nicon{width:36px;height:36px;border-radius:50%;background:var(--zb-blue-soft);color:var(--zb-blue);display:flex;align-items:center;justify-content:center;flex:0 0 auto}
.comment{font-size:13px;margin:6px 0;line-height:1.35}
.comment b{font-weight:700}
.ment{color:var(--zb-blue);font-weight:700}
.stat{flex:1;text-align:center;padding:10px 6px}
.stat .v{font-size:22px;font-weight:800;color:var(--zb-blue)}
.stat .l{font-size:11px;color:var(--muted)}
.iconbtn{background:none;border:none;cursor:pointer;color:var(--muted);display:inline-flex;align-items:center;gap:5px;font-family:inherit;font-size:13px;font-weight:700;padding:6px 4px}
.iconbtn.liked{color:var(--bad)}
.steps{display:flex;gap:6px;justify-content:center;margin-bottom:18px}
.steps i{width:8px;height:8px;border-radius:50%;background:var(--line)}
.steps i.on{background:var(--zb-blue)}

/* ---- BRIEF-025: mentions, picker, and the deep-link highlight ---- */
.ment{color:var(--zb-blue);font-weight:700}
.mentbox{margin-top:6px;border:1px solid #ECEFF3;border-radius:14px;background:#fff;
  box-shadow:var(--shadow);overflow:hidden;max-height:232px;overflow-y:auto}
.mentopt{display:flex;align-items:center;gap:10px;width:100%;padding:9px 12px;border:0;
  background:none;font-family:inherit;font-size:14px;color:var(--ink);text-align:left;cursor:pointer}
.mentopt+.mentopt{border-top:1px solid #F2F4F7}
.mentopt:hover,.mentopt:focus{background:#F5F7FA}
/* The deep-linked post. No backdrop-filter and no transform — this sits on the animated
   wall list, which is exactly the combination that flickers on Android Chrome. */
.card.focus{box-shadow:0 0 0 2px var(--zb-blue),var(--shadow);transition:box-shadow .5s ease}

/* ---- BRIEF-026: busy buttons ---- */
.btn[aria-busy="true"]{opacity:.82;cursor:default}
.btn-spin{display:inline-flex;animation:btnSpin .9s linear infinite;transform-origin:50% 50%}
@keyframes btnSpin{to{transform:rotate(360deg)}}

/* ---- BRIEF-027: builder credit + prize-ineligibility chip ---- */
.ttf{margin-top:10px;font-size:11px;line-height:1.5;text-align:center;letter-spacing:.01em}
.ttf a{text-decoration:none;font-weight:600}
.ttf a:hover{text-decoration:underline}
/* Sits under the name in a leaderboard row, so it never shifts the rank or the score. */
.noteligible{display:block;font-size:10.5px;font-weight:600;color:var(--muted);margin-top:1px}

/* ---- BRIEF-029: shareable demo badge ----
   Sits clear of the tab bar and the home indicator, and is pointer-events:none so it can
   never swallow a tap on the UI it is labelling. It is transform-centred, so per the
   Android-flicker guardrail it carries no backdrop-filter — the background is solid. */
.demobadge{position:fixed;left:50%;transform:translateX(-50%);
  bottom:calc(72px + env(safe-area-inset-bottom,0px));
  z-index:40;pointer-events:none;
  max-width:calc(100% - 32px);
  padding:6px 13px;border-radius:999px;
  background:rgba(26,26,26,.88);color:#fff;
  font-size:11.5px;font-weight:600;letter-spacing:.01em;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;
  box-shadow:0 4px 14px rgba(6,14,26,.22)}
/* Onboarding and the countdown hide the tab bar, so the badge drops to the bottom edge. */
.demobadge.nobar{bottom:calc(16px + env(safe-area-inset-bottom,0px))}

/* ---- BRIEF-030 B: talking-point generator ----
   The button borrows the Spin/primary treatment (--btn-grad via .btn) and only adds the
   spacing that makes it read as its own moment between two cards. */
.tp-btn{width:100%;justify-content:center;margin:2px 0 12px}
/* The reveal. popIn is the same curve the match card and award chips use, so this lands
   on-brand; re-setting #tpOut's innerHTML restarts it on every re-roll.
   No backdrop-filter — this animates, which is the combination that flickers on Android. */
/* The reveal rides .meet-hero for the blue gradient, so there is exactly one definition
   of that treatment; this only adds the reveal animation and the label/question type. */
.tp-card{margin:0 0 10px;animation:popIn .34s cubic-bezier(.2,.9,.3,1.2) both}
.tp-tag{display:inline-flex;align-items:center;gap:6px;
  font-size:10.5px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
  color:rgba(255,255,255,.88)}
.tp-q{margin-top:8px;font-size:17px;line-height:1.45;font-weight:650;color:#fff}
