/* =====================================================================
 * PurePep "Play for a Cause" — app styles (re-skinned onto the PurePep
 * design system). Mobile-first, high-contrast, large tap targets.
 *
 * ENFORCEMENT CONTRACT (see ../PLAYBOOK.md §1):
 *   Every brand value below is a var(--token) from pp-tokens.css — no literal
 *   brand hex / off-scale px / off-guideline font. Load pp-tokens.css BEFORE
 *   this file (see each surface's <head>).
 *
 * The only local variables are functional, non-brand ergonomics (tap size).
 * ===================================================================== */
:root{
  --tap: 48px;                 /* min touch target — a11y, not a brand value */
}

*{ box-sizing:border-box } html,body{ margin:0 }

/* The whole app hides things with the `hidden` attribute, and `hidden` is only
 * a default of display:none — any rule that sets `display` on the same element
 * silently beats it and the element stays on screen. That is exactly how the
 * nickname field kept showing to players who already had one: `.nick` sets
 * display:flex. Make `hidden` actually mean hidden, once, for everything. */
[hidden]{ display:none !important }

/* body typography/colour comes from pp-tokens.css (PP Mori Light, ink-900 on white). */
body{ -webkit-text-size-adjust:100%; line-height:var(--lh-normal); min-height:100vh }
b{ font-weight:var(--fw-semibold) }
.muted{ color:var(--fg-muted); font-weight:var(--fw-regular) }

button{ font:inherit; cursor:pointer; min-height:var(--tap); border-radius:var(--r-lg); border:0 }
input{ font:inherit; min-height:var(--tap); padding:var(--sp-3) var(--sp-4);
  border:1.5px solid var(--border-strong); border-radius:var(--r-lg); width:100%;
  background:var(--ink-000); color:var(--fg); }
input:focus, button:focus-visible{ outline:2px solid var(--border-accent); outline-offset:2px;
  box-shadow:var(--shadow-focus) }

/* =====================================================================
 *  BRAND HEADER — the PurePep gradient "logo bar" (slim app variant)
 *  Canonical gradient: Orange 3 (left) → Orange 1 (right). White foreground.
 * ===================================================================== */
.topbar{ display:flex; align-items:center; justify-content:space-between; gap:var(--sp-2);
  padding:var(--sp-3) var(--sp-4); background:var(--pp-gradient-bar); color:var(--fg-inverse) }
.logo{ font-family:var(--font-sans); font-weight:var(--fw-medium); font-size:var(--fs-18);
  letter-spacing:var(--tracking-snug); display:flex; align-items:center; gap:var(--sp-2) }
/* GPT wordmark is ~4.5:1, so height drives it; keep it short enough that the
   room name still fits beside it on a 360px phone */
.topbar-logo{ height:26px; width:auto; display:block; flex:0 0 auto }
/* the wordmark is a link on the player app only. NOT on the booth screen: that
   runs unattended, and a stray tap must not navigate it away from the counters */
.topbar-logo-link{ display:block; line-height:0; border-radius:var(--r-sm) }
.topbar-logo-link:focus-visible{ outline:2px solid var(--fg-inverse); outline-offset:3px }

/* =====================================================================
 *  MINI FOOTER — the locked campaign lockup
 *  "Driving Peptide Synthesis Forward. Together." over #forpeptidescientists.
 *  Quiet: it signs the page, it does not compete with the CTA above it.
 * ===================================================================== */
.pp-footer{ max-width:560px; margin:0 auto; padding:var(--sp-6) var(--sp-4) var(--sp-8);
  text-align:center }
.pp-footer-line{ margin:0; font-size:var(--fs-14); font-weight:var(--fw-medium);
  color:var(--fg-muted); letter-spacing:var(--tracking-snug); line-height:var(--lh-snug) }
.pp-footer-tag{ margin:var(--sp-1) 0 0; font-size:var(--fs-13); font-weight:var(--fw-medium);
  letter-spacing:var(--tracking-wide);
  background:var(--pp-gradient-bar); -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent; color:transparent }
.pill{ background:rgba(255,255,255,.22); padding:var(--sp-1) var(--sp-3); border-radius:var(--r-pill);
  font-size:var(--fs-12); font-weight:var(--fw-medium); letter-spacing:var(--tracking-caps);
  text-transform:uppercase }
.booth{ font-weight:var(--fw-medium); font-size:var(--fs-16) }
.wrap{ max-width:560px; margin:0 auto; padding:var(--sp-4) }

/* =====================================================================
 *  BUTTONS
 * ===================================================================== */
.primary{ background:var(--pp-orange-1); color:var(--fg-inverse); font-weight:var(--fw-medium);
  padding:var(--sp-3) var(--sp-5); width:100%; transition:background var(--dur-fast) var(--ease-out) }
.primary:hover{ background:var(--pp-orange-600) }
.primary:disabled{ background:var(--ink-300); color:var(--ink-050); cursor:not-allowed }
.secondary{ background:var(--pp-orange-100); color:var(--pp-orange-700); font-weight:var(--fw-medium);
  padding:var(--sp-3) var(--sp-5); width:100% }
.secondary:hover{ background:var(--pp-orange-050) }
.ghost{ background:transparent; color:var(--pp-orange-700); font-weight:var(--fw-medium);
  border:1.5px solid var(--border-strong) }
.ghost:hover{ border-color:var(--border-accent) }
.ghost.sm{ min-height:36px; padding:var(--sp-1) var(--sp-3); font-size:var(--fs-14) }
.big{ font-size:var(--fs-18); padding:var(--sp-4) }
.actions{ display:flex; gap:var(--sp-3); margin-top:var(--sp-4) } .actions button{ flex:1 }

/* =====================================================================
 *  PLAYER — HOME
 * ===================================================================== */
/* =====================================================================
 *  "PLAY FOR A CAUSE" LOCKUP
 *  Small "Play for a" over large "CAUSE." filled with the brand gradient —
 *  mirrors the "Driving Peptide Synthesis Forward. / TOGETHER." lockup.
 *  Headline weight is Medium, not Bold: the style guide reserves Bold for CTA
 *  accents (colors_and_type.css). Peptide Pursuit / Play to Donate are retired.
 * ===================================================================== */
.pfc-lockup{ display:flex; flex-direction:column; line-height:var(--lh-tight) }
.pfc-sm{ font-size:var(--fs-14); font-weight:var(--fw-medium); color:var(--fg-muted);
  letter-spacing:var(--tracking-snug) }
.pfc-lg{ font-size:var(--fs-36); font-weight:var(--fw-medium);
  letter-spacing:var(--tracking-tight);
  background:var(--pp-gradient-bar); -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent; color:transparent }
/* on the orange gradient bar the gradient fill would vanish — go solid white */
.pfc-lockup--onbar .pfc-sm{ color:rgba(255,255,255,.85) }
.pfc-lockup--onbar .pfc-lg{ background:none; -webkit-text-fill-color:var(--fg-inverse);
  color:var(--fg-inverse) }

.hook{ font-size:var(--fs-18); line-height:var(--lh-normal); margin:var(--sp-3) 0 var(--sp-4);
  font-weight:var(--fw-light) }
.progress-note{ color:var(--pp-orange-700); font-weight:var(--fw-medium); margin:var(--sp-1) 0 var(--sp-4) }
.grid{ display:grid; grid-template-columns:1fr 1fr; gap:var(--sp-3) }
.card{ background:var(--ink-000); border:1.5px solid var(--border); border-radius:var(--r-xl);
  padding:var(--sp-4) var(--sp-3); text-align:left; box-shadow:var(--shadow-2);
  display:flex; flex-direction:column; gap:var(--sp-1); min-height:160px;
  transition:border-color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out) }
.card:hover{ border-color:var(--border-accent); transform:translateY(-2px) }
.card-emoji{ font-size:var(--fs-30) }
.card-title{ font-family:var(--font-sans); font-weight:var(--fw-medium); font-size:var(--fs-18) }
.card-blurb{ font-size:var(--fs-14); color:var(--fg-muted); flex:1; font-weight:var(--fw-light) }
.card-badge{ font-size:var(--fs-12); font-weight:var(--fw-medium); color:var(--pp-orange-700);
  background:var(--pp-orange-100); align-self:flex-start; padding:var(--sp-1) var(--sp-2);
  border-radius:var(--r-pill) }
.how{ margin-top:var(--sp-5); background:var(--ink-000); border:1px solid var(--border);
  border-radius:var(--r-lg); padding:var(--sp-3) var(--sp-4) }
.how summary{ font-weight:var(--fw-medium); cursor:pointer }
.how ol{ margin:var(--sp-3) 0 var(--sp-1); padding-left:var(--sp-5) } .how li{ margin:var(--sp-1) 0 }
.how + .how{ margin-top:var(--sp-3) }
.restore-lead{ margin:var(--sp-3) 0 var(--sp-2); font-size:var(--fs-14) }
.restore-row{ display:flex; gap:var(--sp-2); align-items:stretch }
.restore-row input{ flex:1 1 auto; min-width:0; text-transform:uppercase;
  font-weight:var(--fw-medium); letter-spacing:var(--tracking-wide) }
.restore-row .secondary{ width:auto; flex:0 0 auto; padding-left:var(--sp-5); padding-right:var(--sp-5) }
/* build marker: deliberately quiet, but readable on a phone without dev tools */
.build-tag{ margin:var(--sp-4) 0 0; text-align:center; font-size:var(--fs-12);
  color:var(--fg-subtle); letter-spacing:var(--tracking-wide) }
.staff .build-tag{ margin:0; text-align:right; color:rgba(255,255,255,.7) }
/* visually hidden but read by screen readers */
.sr-only{ position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden;
  clip:rect(0 0 0 0); white-space:nowrap; border:0 }

/* =====================================================================
 *  PLAYER — GAME HOST
 * ===================================================================== */
.game-head{ display:flex; align-items:center; justify-content:space-between; margin-bottom:var(--sp-3) }
.game-head h2{ margin:0; font-size:var(--fs-24) }
.game-host{ background:var(--ink-000); border:1.5px solid var(--border); border-radius:var(--r-xl);
  padding:var(--sp-4); min-height:340px; box-shadow:var(--shadow-2) }
.g-hud{ display:flex; justify-content:space-between; font-weight:var(--fw-medium); font-size:var(--fs-24);
  margin-bottom:var(--sp-2) }
.g-score{ color:var(--pp-orange-1); font-weight:var(--fw-bold) }
.g-time{ color:var(--pp-orange-3); font-weight:var(--fw-bold) }
.g-prog{ color:var(--fg-muted); font-size:var(--fs-16) }
.g-prompt{ text-align:center; margin:var(--sp-3) 0 var(--sp-4) }
.g-promptlabel{ display:block; font-size:var(--fs-12); color:var(--fg-muted); text-transform:uppercase;
  letter-spacing:var(--tracking-caps); font-weight:var(--fw-medium) }
.g-prompttext{ font-size:var(--fs-24); font-weight:var(--fw-medium); margin-top:var(--sp-1) }
.g-prompttext--sm{ font-size:var(--fs-18); font-weight:var(--fw-regular); line-height:var(--lh-snug) }
.g-prog--center{ text-align:center; margin-bottom:var(--sp-2) }
.g-options{ display:grid; grid-template-columns:1fr 1fr; gap:var(--sp-3) }
.g-options--wide{ grid-template-columns:1fr }
.g-opt{ position:relative; background:var(--bg-muted); border:1.5px solid var(--border); font-weight:var(--fw-medium);
  font-size:var(--fs-20); padding:var(--sp-4); color:var(--fg);
  transition:border-color var(--dur-fast) var(--ease-out) }
.g-opt:hover:not(:disabled){ border-color:var(--border-accent) }
.g-opt:disabled{ cursor:default; opacity:1 }
/* full-width option with a second explanatory line (the yield game) */
.g-opt--wide{ display:flex; flex-direction:column; align-items:flex-start; gap:2px; text-align:left;
  font-size:var(--fs-18); padding:var(--sp-3) var(--sp-4) }
.g-opt-label{ font-weight:var(--fw-medium) }
.g-opt-detail{ font-size:var(--fs-13); color:var(--fg-muted); font-weight:var(--fw-regular) }
.g-opt--wide.g-bad .g-opt-detail, .g-opt--wide.g-ok .g-opt-detail{ color:inherit; opacity:.75 }
/* verdicts are never colour-alone — every marked option carries a glyph too */
.g-ok{ background:var(--ok-bg) !important; border-color:var(--ok) !important; color:var(--ok) !important }
.g-bad{ background:var(--err-bg) !important; border-color:var(--err) !important; color:var(--err) !important }
/* the call that would have cost nothing, revealed only after a costly one */
.g-best{ border-color:var(--ok) !important; border-style:dashed !important; color:var(--ok) !important }
.g-mark{ position:absolute; top:var(--sp-2); right:var(--sp-3); font-size:var(--fs-14);
  font-weight:var(--fw-bold); letter-spacing:0 }
.g-best .g-mark{ font-size:var(--fs-12); text-transform:uppercase; letter-spacing:var(--tracking-caps) }

/* ---- the teaching reveal: what makes this educational, and what a rep
 *      in The Forum can pick the conversation up from afterwards ---- */
.g-why{ margin-top:var(--sp-4); padding:var(--sp-3) var(--sp-4); border-radius:var(--r-lg);
  border-left:4px solid var(--ok); background:var(--ok-bg) }
.g-why--bad{ border-left-color:var(--err); background:var(--err-bg) }
.g-why-head{ display:flex; align-items:center; gap:var(--sp-2); font-weight:var(--fw-medium);
  font-size:var(--fs-14); text-transform:uppercase; letter-spacing:var(--tracking-caps); color:var(--ok) }
.g-why--bad .g-why-head{ color:var(--err) }
.g-why-glyph{ font-size:var(--fs-18) }
.g-why-text{ margin:var(--sp-2) 0 0; font-size:var(--fs-16); line-height:var(--lh-normal);
  font-weight:var(--fw-light); color:var(--fg) }
.g-next{ margin-top:var(--sp-3); width:100%; background:var(--pp-orange-1); color:var(--fg-inverse);
  font-weight:var(--fw-medium); font-size:var(--fs-18); padding:var(--sp-3) var(--sp-5) }
.g-next:hover{ background:var(--pp-orange-600) }

/* ---- build game: the chain, and the residue tray ---- */
.g-ends{ display:flex; justify-content:space-between; font-size:var(--fs-12); color:var(--fg-muted);
  text-transform:uppercase; letter-spacing:var(--tracking-caps); font-weight:var(--fw-medium) }
/* The chain must never wrap — a wrapped chain destroys the whole point of the
 * game, which is reading it end-to-end and filling from the C-terminus.
 * Slots share the row equally and shrink for longer peptides instead. */
.g-seq{ display:flex; gap:var(--sp-1); justify-content:center; margin:var(--sp-5) 0 var(--sp-4);
  flex-wrap:nowrap }
.g-res{ flex:1 1 0; min-width:0; max-width:44px; height:44px;
  display:flex; align-items:center; justify-content:center;
  font-weight:var(--fw-bold); font-size:var(--fs-20); background:var(--bg-muted);
  border:2px dashed var(--border-strong); border-radius:var(--r-md); color:var(--fg-subtle) }
.g-res.g-filled{ background:var(--pp-orange-1); color:var(--fg-inverse); border-style:solid;
  border-color:var(--pp-orange-1) }
/* the next slot is marked by an arrow as well as colour */
.g-res--next{ border-color:var(--pp-orange-1); border-style:solid; position:relative; color:var(--pp-orange-1) }
.g-res--next::after{ content:"▾"; position:absolute; top:-16px; left:50%; transform:translateX(-50%);
  font-size:var(--fs-14); color:var(--pp-orange-1) }
.g-tray{ display:flex; flex-wrap:wrap; gap:var(--sp-2); justify-content:center }
.g-tile{ min-width:60px; min-height:var(--tap); display:flex; flex-direction:column; align-items:center;
  justify-content:center; gap:0; padding:var(--sp-2); background:var(--ink-000);
  border:1.5px solid var(--border-strong); border-radius:var(--r-lg); color:var(--fg) }
.g-tile:hover:not(:disabled){ border-color:var(--border-accent) }
.g-tile-1{ font-size:var(--fs-20); font-weight:var(--fw-bold); line-height:1 }
.g-tile-3{ font-size:var(--fs-12); color:var(--fg-muted); font-weight:var(--fw-regular) }
.g-tile--used{ opacity:.28; border-style:dashed; cursor:default }
/* Scrabble-style point value on each residue tile */
.g-tile{ position:relative }
.g-tile-pts{ position:absolute; top:2px; right:5px; font-size:var(--fs-12);
  font-weight:var(--fw-bold); color:var(--pp-orange-700); line-height:1 }
/* running commentary under the chain: what the last placement just bought you */
.g-note{ min-height:2.6em; margin:var(--sp-2) 0 var(--sp-3); font-size:var(--fs-14);
  line-height:var(--lh-normal); color:var(--fg); text-align:center;
  background:var(--bg-wash); border-radius:var(--r-md); padding:var(--sp-2) var(--sp-3) }
.g-final-seq{ font-family:var(--font-mono); font-size:var(--fs-30); font-weight:var(--fw-bold);
  letter-spacing:var(--tracking-wide); color:var(--fg); margin:var(--sp-1) 0 }
.g-shake{ animation:pp-shake 260ms var(--ease-out) }
@keyframes pp-shake{ 0%,100%{transform:translateX(0)} 25%{transform:translateX(-5px)} 75%{transform:translateX(5px)} }
.g-hint{ min-height:1.4em; margin:var(--sp-2) 0 0; font-size:var(--fs-14); color:var(--err);
  text-align:center; font-weight:var(--fw-medium) }

/* ---- yield game: the compounding crude-purity meter ---- */
.g-brief{ background:var(--bg-muted); border-radius:var(--r-lg); padding:var(--sp-3) var(--sp-4);
  margin-bottom:var(--sp-4) }
.g-brief-text{ margin:var(--sp-1) 0 0; font-size:var(--fs-14); line-height:var(--lh-normal);
  font-weight:var(--fw-light) }
.g-purity{ text-align:center }
.g-purity-lab{ font-size:var(--fs-12); color:var(--fg-muted); text-transform:uppercase;
  letter-spacing:var(--tracking-caps); font-weight:var(--fw-medium) }
.g-purity-val{ font-size:var(--fs-48); font-weight:var(--fw-medium); color:var(--ok);
  line-height:var(--lh-tight); letter-spacing:var(--tracking-tight) }
.g-purity--low .g-purity-val{ color:var(--err) }
/* The draft game maximises this number, so the purity meter's green/red health
   semantics would read backwards. Brand orange is neutral: it is a tally. */
.g-purity--draft .g-purity-val{ color:var(--pp-orange-1) }
.g-purity-track{ height:12px; background:var(--ink-200); border-radius:var(--r-pill); overflow:hidden;
  margin-top:var(--sp-2) }
.g-purity-fill{ height:100%; width:100%; background:var(--ok); border-radius:var(--r-pill);
  transition:width var(--dur-slow) var(--ease-out), background var(--dur-slow) var(--ease-out) }
.g-purity--low .g-purity-fill{ background:var(--err) }
.g-final{ text-align:center; padding:var(--sp-4) 0 }
.g-final-lab{ font-size:var(--fs-14); color:var(--fg-muted) }
.g-final-val{ font-size:var(--fs-36); font-weight:var(--fw-medium); color:var(--pp-orange-1);
  letter-spacing:var(--tracking-tight); margin:var(--sp-1) 0 var(--sp-3) }
.g-final-text{ font-size:var(--fs-16); font-weight:var(--fw-light); line-height:var(--lh-normal); margin:0 }

/* =====================================================================
 *  PLAYER — SCORE
 * ===================================================================== */
.score-card{ background:var(--ink-000); border-radius:var(--r-xl); box-shadow:var(--shadow-3);
  padding:var(--sp-6); text-align:center; border:1.5px solid var(--border) }
.score-label{ color:var(--fg-muted); font-weight:var(--fw-medium) }
.score-big{ font-size:var(--fs-64); font-weight:var(--fw-medium); color:var(--pp-orange-1);
  line-height:var(--lh-tight); letter-spacing:var(--tracking-tight) }
.nick{ background:var(--ink-000); border:1.5px solid var(--border-accent); border-radius:var(--r-xl);
  padding:var(--sp-4); margin-top:var(--sp-4); display:flex; flex-direction:column; gap:var(--sp-3) }
.nick label{ font-weight:var(--fw-medium) }
/* Forum tie-in: a quiet pointer, not a second CTA competing with "Unlock" */
.tiein{ margin:var(--sp-4) 0 0; padding:var(--sp-3) var(--sp-4);
  background:var(--bg-wash); border-left:3px solid var(--pp-orange-1);
  border-radius:var(--r-md); font-size:var(--fs-16); line-height:var(--lh-normal);
  font-weight:var(--fw-regular); color:var(--fg) }
.tiein[hidden]{ display:none }
.summary{ font-size:var(--fs-18); margin:var(--sp-4) 0; font-weight:var(--fw-light) }
.board{ background:var(--ink-000); border:1px solid var(--border); border-radius:var(--r-lg);
  padding:var(--sp-3) var(--sp-4); margin-top:var(--sp-1) }
.board-title{ font-weight:var(--fw-medium); margin-bottom:var(--sp-1) }
.board-row{ display:flex; justify-content:space-between; padding:var(--sp-1) 0;
  border-top:1px solid var(--border) }

/* =====================================================================
 *  PLAYER — CLAIM (the brand moment: halftone + orange code)
 * ===================================================================== */
.claim-h{ text-align:center }
.claim-amount{ text-align:center; font-size:var(--fs-18); font-weight:var(--fw-light) }
.codecard{ position:relative; overflow:hidden; background:var(--ink-000);
  border:2px solid var(--pp-orange-1); border-radius:var(--r-xl);
  padding:var(--sp-8) var(--sp-4); text-align:center; box-shadow:var(--shadow-3); margin:var(--sp-4) 0 }
/* halftone as a subtle top-right whisper only — never behind the code/hint text,
   so the claim code keeps strong contrast (staff must read it at a glance). */
.codecard::before{ content:""; position:absolute; top:0; right:0; width:52%; height:52%; z-index:0;
  background:url('../assets/halftone-orange.png') no-repeat top right / cover; opacity:.16;
  pointer-events:none }
.codecard > *{ position:relative; z-index:1 }
.code-label{ text-transform:uppercase; letter-spacing:var(--tracking-caps); font-size:var(--fs-13);
  color:var(--pp-orange-700); font-weight:var(--fw-medium) }
.code{ font-size:var(--fs-48); font-weight:var(--fw-bold); letter-spacing:var(--tracking-wide);
  color:var(--pp-orange-700); margin:var(--sp-2) 0 }   /* deeper orange for ~5.4:1 on white — critical read */
.code-hint{ font-size:var(--fs-14); color:var(--fg-muted) }

/* =====================================================================
 *  BOOTH SCREEN — distance-readable; dark charcoal + orange, halftone motif
 * ===================================================================== */
/* This is an unattended full-screen display: it must FIT, never scroll and never
 * clip. Fixed-height flex column — the leaderboard absorbs whatever is left. */
.booth-screen{ background:var(--ink-900); color:var(--fg-inverse); height:100vh; overflow:hidden;
  position:relative; display:flex; flex-direction:column }
.booth-top{ flex:0 0 auto }
.hero{ flex:0 0 auto }
.booth-bottom{ flex:1 1 auto; min-height:0 }
.board-col{ min-height:0; display:flex; flex-direction:column; overflow:hidden }
.lb{ flex:1 1 auto; min-height:0; overflow:hidden }
/* brand halftone stays a whisper: at full strength it sits straight behind the
 * leaderboard and drops white-on-orange body text well under the ~7:1 this
 * screen needs to be read across the room */
.booth-screen::before{ content:""; position:absolute; inset:auto 0 0 0; height:45vh; z-index:0;
  background:url('../assets/halftone-orange.png') no-repeat bottom center / cover; opacity:.26;
  pointer-events:none }
.booth-screen > *{ position:relative; z-index:1 }
.booth-top{ display:flex; justify-content:space-between; align-items:center;
  padding:var(--sp-5) var(--sp-10); font-size:var(--fs-24); font-weight:var(--fw-medium);
  background:var(--pp-gradient-bar); color:var(--fg-inverse) }
.booth-brand-wrap{ display:flex; align-items:center; gap:var(--sp-4) }
.booth-logo{ height:var(--sp-10); width:auto; display:block }
.booth-tag{ background:rgba(255,255,255,.18); padding:var(--sp-2) var(--sp-5); border-radius:var(--r-pill);
  font-size:var(--fs-18) }
/* the lockup sits on the gradient bar and is read across the room — scale it
 * with the display and align it right, where the pill used to be */
.booth-top .pfc-lockup{ align-items:flex-end; text-align:right }
.booth-top .pfc-sm{ font-size:clamp(.8rem, 1.4vh, 1.125rem) }
.booth-top .pfc-lg{ font-size:clamp(1.5rem, 3.4vh, 2.5rem) }
.hero{ text-align:center; padding:var(--sp-6) var(--sp-4) var(--sp-4) }
.hero-label{ font-size:var(--fs-30); color:var(--pp-orange-2); font-weight:var(--fw-medium);
  letter-spacing:var(--tracking-snug) }
.cap{ max-width:760px; margin:var(--sp-4) auto 0 }
.cap-track{ height:18px; background:rgba(255,255,255,.16); border-radius:var(--r-pill); overflow:hidden }
.cap-fill{ height:100%; width:0; background:var(--pp-gradient-bar);
  transition:width var(--dur-slow) var(--ease-out) }
.cap-label{ font-size:var(--fs-24); margin-top:var(--sp-2); font-weight:var(--fw-medium) }
.impact-row{ display:flex; gap:var(--sp-6); justify-content:center; padding:var(--sp-6) var(--sp-8);
  flex-wrap:wrap }
.impact-card{ background:rgba(0,0,0,.42); border:3px solid; border-radius:var(--r-xl);
  padding:var(--sp-5) var(--sp-8); text-align:center; min-width:220px }
.impact-emoji{ font-size:var(--fs-36) }
.impact-num{ font-size:var(--fs-48); font-weight:var(--fw-medium); line-height:var(--lh-tight) }
.impact-unit{ font-size:var(--fs-20); font-weight:var(--fw-medium); opacity:.92 }
.impact-name{ font-size:var(--fs-16); opacity:.7; margin-top:var(--sp-1) }

/* ---- HERO VARIANT: the three outcomes carry the screen ----
 * These replaced a single giant € total, so they have to hold the same
 * distance-read job (~8 m). Numbers scale with the viewport and the cards
 * share one row; the emoji and cause name stay small so the COUNT dominates. */
.impact-row--hero{ padding:var(--sp-4) var(--sp-4) 0; gap:clamp(12px, 2vw, 32px); flex-wrap:nowrap;
  align-items:stretch }
.impact-row--hero .impact-card{ flex:1 1 0; min-width:0;
  padding:var(--sp-4) var(--sp-3); display:flex; flex-direction:column; justify-content:center }
.impact-row--hero .impact-emoji{ font-size:clamp(1.75rem, 3.2vw, 3rem); line-height:1 }
/* sized against BOTH axes — a 16:9 booth screen is height-constrained, and a
 * number that only respects vw pushes the leaderboard off the bottom */
.impact-row--hero .impact-num{ font-size:clamp(2.5rem, min(9vw, 15vh), 7rem); font-weight:var(--fw-medium);
  letter-spacing:var(--tracking-tight); text-shadow:0 6px 40px rgba(237,109,30,.45);
  font-variant-numeric:tabular-nums; line-height:var(--lh-tight) }
.impact-row--hero .impact-unit{ font-size:clamp(1rem, 1.9vw, 1.75rem); opacity:1 }
.impact-row--hero .impact-name{ font-size:clamp(.8rem, 1.2vw, 1.125rem); opacity:.65 }
/* narrow or portrait screens: let the three stack rather than crush the numbers */
@media (max-width:900px){
  .impact-row--hero{ flex-wrap:wrap }
  .impact-row--hero .impact-card{ flex:1 1 240px }
  .impact-row--hero .impact-num{ font-size:clamp(2.5rem, 12vw, 5rem) }
}
/* stretch, not flex-start: flex-start lets each column size to its own content
 * and spill off the bottom of a fixed-height screen */
.booth-bottom{ display:flex; gap:var(--sp-8); padding:0 var(--sp-10) var(--sp-8); align-items:stretch }
.board-col{ flex:2 }
/* min-height:0 or the QR's intrinsic size stops the column ever shrinking */
.stats-col{ flex:1; min-height:0; display:flex; flex-direction:column; gap:var(--sp-4);
  justify-content:space-between }   /* QR to the top, counters level with the board's foot */
.board-h{ font-size:var(--fs-30); font-weight:var(--fw-medium); margin-bottom:var(--sp-3) }
/* rows scale with viewport height so the whole board fits an unattended
 * screen; booth.js additionally hides any row that still would not fit */
.lb-row{ display:grid; grid-template-columns:50px 1fr auto; align-items:center;
  font-size:clamp(1rem, 2.4vh, 1.5rem);
  font-weight:var(--fw-medium); padding:clamp(4px, 0.9vh, 12px) var(--sp-3);
  background:rgba(0,0,0,.42); border-radius:var(--r-lg); margin-bottom:var(--sp-1) }
.lb-top{ background:rgba(237,109,30,.5) }
.lb-rank{ font-weight:var(--fw-bold); opacity:.8 } .lb-score{ font-weight:var(--fw-bold) }
.board-empty{ font-size:var(--fs-20); opacity:.8 }
.stat{ background:rgba(0,0,0,.42); border-radius:var(--r-xl); padding:var(--sp-4); text-align:center }
.stat-num{ font-size:var(--fs-36); font-weight:var(--fw-medium); line-height:var(--lh-tight) }
.stat-lbl{ font-size:var(--fs-18); opacity:.8 }
/* participation as one slim line under the board — it earns a mention, not a
 * pair of boxes, and the space it frees goes to the QR */
.stat-line{ flex:0 0 auto; display:flex; gap:var(--sp-2); align-items:baseline;
  padding:var(--sp-2) var(--sp-3) 0; opacity:.75;
  font-size:clamp(.8rem, 1.9vh, 1.25rem) }
.stat-line b{ font-weight:var(--fw-bold) }

/* ---- QR TO PLAY ----
 * The join-here call to action, parked beside the leaderboard because that is
 * what people walk over to read. White card: a QR needs a light quiet zone to
 * scan reliably, and it doubles as the brightest thing on a dark screen. */
.qr-card[hidden]{ display:none }   /* display:flex below would otherwise beat [hidden] */
.qr-card{ flex:1 1 auto; min-height:0; background:var(--ink-000); border-radius:var(--r-xl);
  padding:var(--sp-4); display:flex; flex-direction:column; align-items:center;
  justify-content:center; gap:var(--sp-2); text-align:center }
/* Sized in vh rather than by flex: the code is square with a 3000px intrinsic
 * width, and inside a flex column it either sets the column height (blowing
 * past 100vh) or collapses to zero. An explicit viewport-relative size scales
 * with the display and stays predictable. */
.qr-img{ width:clamp(110px, 20vh, 260px); height:auto; aspect-ratio:1 / 1;
  object-fit:contain; display:block }
.qr-cta{ flex:0 0 auto; color:var(--ink-900); font-weight:var(--fw-medium);
  font-size:clamp(1rem, 2.6vh, 1.75rem); line-height:var(--lh-tight) }
.qr-url{ flex:0 0 auto; color:var(--ink-600); font-weight:var(--fw-regular);
  font-size:clamp(.75rem, 1.7vh, 1.125rem); word-break:break-all }

/* =====================================================================
 *  STAFF CONSOLE
 * ===================================================================== */
.staff .admin{ display:flex; gap:var(--sp-4); align-items:center; font-size:var(--fs-14);
  color:var(--fg-inverse) }
.lookup-row{ display:flex; gap:var(--sp-3); margin:var(--sp-4) 0 }
.lookup-row input{ text-transform:uppercase; font-weight:var(--fw-medium); font-size:var(--fs-20) }
.lookup-row .primary{ width:auto; padding-left:var(--sp-6); padding-right:var(--sp-6) }
.msg{ min-height:1.2em; color:var(--pp-orange-700); font-weight:var(--fw-medium) }
.review-player{ font-size:var(--fs-24) }
.review-amount{ font-size:var(--fs-18); color:var(--pp-orange-700); font-weight:var(--fw-medium) }
.tiles-label{ font-weight:var(--fw-medium); margin:var(--sp-4) 0 var(--sp-2) }
.tiles{ display:grid; grid-template-columns:1fr 1fr 1fr; gap:var(--sp-3); margin-bottom:var(--sp-5) }
.tile{ background:var(--ink-000); border:2px solid var(--border); border-radius:var(--r-xl);
  padding:var(--sp-4) var(--sp-3); text-align:center;
  transition:border-color var(--dur-fast) var(--ease-out) }
.tile-emoji{ font-size:var(--fs-30) }
.tile-name{ font-weight:var(--fw-medium); font-size:var(--fs-16); margin-top:var(--sp-1) }
.tile-tag{ font-size:var(--fs-13); color:var(--fg-muted) }
/* --tc is the chosen charity's own brand colour, injected by claim.js (data, not brand) */
.tile.sel{ border-color:var(--tc, var(--pp-orange-1)); background:var(--bg-wash);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--tc, var(--pp-orange-1)) 22%, transparent) }
.done-impact{ font-size:var(--fs-20) }
/* ---- contact hand-off: QR to the Microsoft Form, scanned on the attendee's
 *      own phone. Nothing is typed on this shared console. ---- */
/* Staff hold the console up and the attendee scans off the screen, so the code
 * has to be big enough to read at arm's length across a table, and on white. */
.handoff{ display:flex; gap:var(--sp-5); align-items:center; margin:var(--sp-3) 0 var(--sp-4) }
.handoff-qr{ flex:0 0 auto; width:clamp(140px, 32vw, 200px); height:auto; aspect-ratio:1 / 1;
  background:var(--ink-000); border:1.5px solid var(--border); border-radius:var(--r-lg);
  padding:var(--sp-2); display:block }
.handoff-body{ flex:1 1 auto; min-width:0 }
.handoff-lead{ margin:0 0 var(--sp-2); font-size:var(--fs-18); font-weight:var(--fw-medium) }
.handoff-url{ margin:0 0 var(--sp-2); font-size:var(--fs-14); word-break:break-all;
  color:var(--fg-muted) }
.handoff-note{ margin:0; font-size:var(--fs-14) }
@media (max-width:520px){ .handoff{ flex-direction:column; align-items:flex-start } }
.contact{ background:var(--ink-000); border:1.5px solid var(--border); border-radius:var(--r-xl);
  padding:var(--sp-4); margin-top:var(--sp-4) }
.contact-h{ font-weight:var(--fw-medium); margin-bottom:var(--sp-3) }
.form-grid{ display:grid; grid-template-columns:1fr 1fr; gap:var(--sp-3) }
.field{ display:flex; flex-direction:column; gap:var(--sp-1) }
.field .label{ margin:0 }
.consent{ font-size:var(--fs-13); margin-top:var(--sp-3) }
#done-headline{ color:var(--pp-orange-1) }

/* =====================================================================
 *  UI POLISH PASS — warmth, depth, delight (tokens only)
 * ===================================================================== */

/* Soft brand wash behind the player/staff surfaces (booth stays dark) */
body.player, body.staff{
  background: radial-gradient(130% 55% at 50% -8%, var(--bg-wash) 0%, rgba(253,242,232,0) 60%), var(--bg); }

/* Sticky header with a touch of depth */
.topbar{ position:sticky; top:0; z-index:20; box-shadow:0 2px 12px rgba(32,32,32,.12) }

/* Hook reads as a warm lead */
.hook{ font-size:var(--fs-20); line-height:var(--lh-normal); color:var(--fg); margin:var(--sp-3) 0 var(--sp-5) }
.hook b{ color:var(--pp-orange-700); font-weight:var(--fw-semibold) }

/* Game cards — emoji on a floating tile, warm gradient, lift + glow on hover */
.card{ background:linear-gradient(180deg, var(--ink-000) 0%, var(--pp-orange-050) 150%); border-color:var(--ink-150) }
.card:hover, .card:focus-visible{ border-color:var(--pp-orange-1); transform:translateY(-3px);
  box-shadow:0 12px 30px rgba(237,109,30,.20) }
.card-emoji{ width:54px; height:54px; display:inline-flex; align-items:center; justify-content:center;
  background:var(--ink-000); border-radius:var(--r-lg); box-shadow:var(--shadow-1); margin-bottom:var(--sp-1) }
.card-title{ font-size:var(--fs-20) }
/* game-card chips: timing badge + difficulty flag (text-labelled, not colour-only) */
.card-chips{ display:flex; flex-wrap:wrap; gap:var(--sp-2); align-items:center }
.card-diff{ font-size:var(--fs-12); font-weight:var(--fw-medium); padding:var(--sp-1) var(--sp-2);
  border-radius:var(--r-pill); letter-spacing:var(--tracking-wide) }
.card-diff--easy{ background:var(--ok-bg); color:var(--ok) }
.card-diff--medium{ background:var(--warn-bg); color:var(--warn) }
.card-diff--hard{ background:var(--err-bg); color:var(--err) }
.card-diff--played{ background:var(--ink-150); color:var(--fg-muted) }

/* played games — greyed + non-interactive (each game plays once) */
.card--played{ opacity:.6; filter:grayscale(.35); background:var(--bg-muted) }
.card--played:hover{ transform:none; border-color:var(--border); box-shadow:var(--shadow-2) }
.card--played .card-emoji{ box-shadow:none }

/* home donation / resume bar — persistent entry to pick / show code / status */
.home-donation{ margin:var(--sp-2) 0 var(--sp-5) }
.home-donation .primary{ width:100% }
.home-donation-note{ background:var(--ok-bg); color:var(--ok); padding:var(--sp-3) var(--sp-4);
  border-radius:var(--r-lg); font-weight:var(--fw-medium); text-align:center }

/* Primary buttons — depth + lift; the two "unlock / continue" CTAs get the brand gradient */
.primary{ box-shadow:0 6px 16px rgba(237,109,30,.30) }
.primary:hover{ transform:translateY(-1px) } .primary:active{ transform:translateY(0) }
#to-claim, #pick-continue{ background:var(--pp-gradient-bar) }
#to-claim:hover, #pick-continue:hover{ filter:brightness(1.05) }
#to-claim:disabled, #pick-continue:disabled{ background:var(--ink-300); box-shadow:none; filter:none }

/* Score screen — celebratory gradient numeral on a soft halftone card */
.score-card{ position:relative; overflow:hidden;
  background:linear-gradient(180deg, var(--ink-000), var(--pp-orange-050)) }
.score-card::before{ content:""; position:absolute; inset:auto -8% -28% auto; width:58%; height:80%; z-index:0;
  background:url('../assets/halftone-orange.png') no-repeat right bottom / contain; opacity:.14; pointer-events:none }
.score-card > *{ position:relative; z-index:1 }
.score-big{ background:var(--pp-gradient-bar); -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent; color:transparent }

/* Pick screen — single-column list of horizontal, tappable cause rows with a check */
#pick-tiles.tiles{ grid-template-columns:1fr; gap:var(--sp-3) }
#pick-tiles .tile{ display:flex; align-items:center; gap:var(--sp-4); text-align:left; padding:var(--sp-4) var(--sp-5) }
#pick-tiles .tile-emoji{ flex:0 0 auto; width:52px; height:52px; border-radius:var(--r-circle); margin:0;
  display:inline-flex; align-items:center; justify-content:center; font-size:var(--fs-30);
  background:color-mix(in srgb, var(--tc, var(--pp-orange-1)) 15%, white) }
/* the outcome leads on each cause tile — it is what the player is choosing
 * between. Text stacks in its own column beside the emoji. */
#pick-tiles .tile-body{ flex:1 1 auto; min-width:0; display:flex; flex-direction:column; gap:2px }
#pick-tiles .tile-impact{ font-size:var(--fs-20); font-weight:var(--fw-medium); color:var(--fg);
  line-height:var(--lh-snug) }
#pick-tiles .tile-name{ font-size:var(--fs-14); color:var(--fg-muted); font-weight:var(--fw-regular);
  line-height:var(--lh-snug) }
#pick-tiles .tile.sel{ position:relative; padding-right:var(--sp-12) }
#pick-tiles .tile.sel::after{ content:"✓"; position:absolute; top:50%; right:var(--sp-4); transform:translateY(-50%);
  width:26px; height:26px; border-radius:var(--r-circle); background:var(--tc, var(--pp-orange-1)); color:#fff;
  display:flex; align-items:center; justify-content:center; font-weight:var(--fw-bold); font-size:var(--fs-14) }

/* Claim code — a touch more presence */
.code{ letter-spacing:var(--tracking-caps) }

/* Gentle entrance on each player/staff screen (disabled under reduced-motion below) */
.wrap > section:not([hidden]){ animation:pp-screen-in var(--dur-slow) var(--ease-out) }
@keyframes pp-screen-in{ from{ opacity:0; transform:translateY(10px) } to{ opacity:1; transform:none } }

@media (max-width:420px){ .form-grid{ grid-template-columns:1fr } .tiles{ grid-template-columns:1fr } }
@media (prefers-reduced-motion:reduce){ *{ transition:none !important; animation:none !important } }
