/* ============================================================
   Social Bingo — Component library
   Mirrors design-system.md §10. Changes here MUST be mirrored there.
   ============================================================ */

/* ---------- 10.1 Wordmark ---------- */
/* The lockup is the mark plus the name. The gold gradient lives on the TEXT,
   not on the lockup: `background-clip:text` on the parent would clip the fill
   to the glyphs of everything inside it, and the mark is an SVG that has to
   keep its own colours. */
.wordmark{
  display:flex; align-items:center; gap:8px; text-decoration:none;
  white-space:nowrap; line-height:1;
}
.wordmark .logo-mark{ width:30px; height:30px; flex-shrink:0; display:block; }
.wordmark-text{
  font-family:var(--font-display); font-weight:700; font-size:22px;
  background:linear-gradient(180deg, var(--gold) 0%, #ffe9a8 45%, var(--gold-deep) 100%);
  -webkit-background-clip:text; background-clip:text; color:transparent;
}
/* The domain is part of the name but not the loud part of it. */
.wordmark-tld{ opacity:0.7; }

/* A drift you notice only if you look at it. A logo that bounces is a
   distraction, so this is three pixels over nearly four seconds. */
@keyframes logoDrift{
  0%, 100%{ transform:translateY(0); }
  50%     { transform:translateY(-3px); }
}
.logo-mark.is-floating{ animation:logoDrift 3.8s ease-in-out infinite; }

@media (prefers-reduced-motion:reduce){
  .logo-mark.is-floating{ animation:none; }
}

/* The lockup is wider than the magenta dot it replaced — about 30px more —
   which was enough to push the header past its own width on a phone. The mark
   comes down with the type, and the points pill steps out: it is a readout,
   not an action, and it is still on My hall and in the game bar. */
@media (max-width:520px){
  .wordmark .logo-mark{ width:26px; height:26px; }
  .wordmark{ gap:6px; }
  .site-header .nav-cta .points-pill{ display:none; }
}

/* Admin can drop the lockup to the mark alone on a phone. The name is hidden
   from sight, never removed — a link still needs its text, and the mark on its
   own would leave the accessible name to an aria-label nobody can read. */
@media (max-width:620px){
  .wordmark.is-mark-only .wordmark-text{
    position:absolute; width:1px; height:1px; padding:0; margin:-1px;
    overflow:hidden; clip-path:inset(50%); white-space:nowrap; border:0;
  }
  .wordmark.is-mark-only .logo-mark{ width:34px; height:34px; }
}

/* ---------- 10.1b Create-a-room panel ----------
   Lives here rather than in the lobby's own <style> block, because it now
   appears on the home page, the hall, the lobby and how-it-works. A layout
   class defined inside one page cannot be reused by the next (R-UI-21). */
.create-panel{
  display:flex; align-items:center; justify-content:space-between; gap:var(--sp-6);
  flex-wrap:wrap; margin-top:var(--sp-10);
  background:var(--paper); color:var(--ink);
  border-radius:var(--radius-lg); padding:28px 32px;
  box-shadow:var(--shadow-md), var(--inset-hilite);
}
.create-panel h2{ font-size:24px; margin:0 0 6px; }
.create-panel p{ font-size:14px; color:rgba(36,10,61,0.7); max-width:46ch; margin:0; }

@media (max-width:620px){
  /* On a phone this is the offer, not a footnote. A wrapped flex row left the
     button stranded at the bottom-left under a paragraph, at the same size as
     any other link on the page — so it stacks, centres, and the button takes
     the full width where a thumb expects it. */
  .create-panel{
    flex-direction:column; align-items:stretch; text-align:center;
    gap:var(--sp-4); padding:24px 20px; margin-top:var(--sp-8);
  }
  .create-panel h2{ font-size:21px; }
  .create-panel p{ max-width:none; }
  .create-panel .btn{ width:100%; }
}

/* ---------- 10.1c Room leaderboard ----------
   A room's own table, in a side panel. Small by design: it answers "who is
   winning in here", not "where do I rank on the site". */
.mini-board{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:2px; }
.mini-board li{
  display:flex; align-items:center; gap:var(--sp-3);
  padding:8px 6px; border-radius:var(--radius-sm);
}
.mini-board li:nth-child(odd){ background:var(--surface); }
.mini-board .pos{
  flex:0 0 20px; text-align:center; font-family:var(--font-display);
  font-weight:700; font-size:13px; color:var(--text-dim);
}
.mini-board li:nth-child(1) .pos{ color:var(--gold); }
.mini-board .avatar{ width:26px; height:26px; font-size:13px; flex:0 0 auto; margin:0; }
.mini-board .who{
  flex:1; min-width:0; font-size:13.5px; font-weight:700;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.mini-board .pts{
  flex:0 0 auto; font-family:var(--font-display); font-size:14px; color:var(--gold);
  font-variant-numeric:tabular-nums;
}

/* ---------- 10.1d Room presets ----------
   The choice a player makes instead of filling in a settings form. Real radios
   with their paint replaced, so the keyboard and the label target still work. */
.preset-grid{
  display:grid; gap:var(--sp-3);
  grid-template-columns:repeat(auto-fit, minmax(190px, 1fr));
  margin-top:var(--sp-2);
}
.preset-card{
  display:flex; align-items:flex-start; gap:var(--sp-3);
  padding:var(--sp-4); cursor:pointer;
  background:var(--surface); border:1px solid var(--border);
  border-radius:var(--radius-md);
  transition:border-color var(--dur-fast) ease, background var(--dur-fast) ease;
}
.preset-card:hover{ background:var(--surface-hover); border-color:var(--border-strong); }
.preset-card input[type="radio"]{
  appearance:none; -webkit-appearance:none;
  flex:0 0 auto; margin:2px 0 0; width:18px; height:18px; border-radius:50%;
  border:2px solid var(--border-strong); background:transparent; cursor:pointer;
}
.preset-card input[type="radio"]:checked{
  border-color:var(--gold);
  box-shadow:inset 0 0 0 4px var(--gold);
}
.preset-card input[type="radio"]:focus-visible{ outline:2px solid var(--gold); outline-offset:3px; }
.preset-card:has(input:checked){ border-color:var(--gold); background:rgba(255,203,61,0.08); }
.preset-card > span{ display:flex; flex-direction:column; gap:3px; min-width:0; }
.preset-card b{ font-size:15px; }
.preset-card .blurb{ font-size:13px; color:var(--text-muted); line-height:1.45; }
.preset-card .spec{ font-size:12px; color:var(--gold); font-weight:700; }

/* ---------- 10.2 Live pill ---------- */
.live-pill{
  font-family:var(--font-body); font-weight:800; font-size:var(--fs-xs); letter-spacing:0.6px;
  background:var(--surface-hover); border:1px solid var(--border-strong);
  padding:6px 10px; border-radius:var(--radius-pill);
  display:inline-flex; align-items:center; gap:6px; color:var(--cream);
}
.pulse{
  width:7px; height:7px; border-radius:50%; background:var(--teal);
  box-shadow:0 0 6px var(--teal); animation:pulse 1.4s ease-in-out infinite; flex-shrink:0;
}
@keyframes pulse{ 0%,100%{transform:scale(1);opacity:1;} 50%{transform:scale(1.5);opacity:0.5;} }

/* ---------- 10.3 Buttons ---------- */
.btn{
  font-family:var(--font-display); font-weight:600; font-size:15px;
  border:none; border-radius:var(--radius-md); cursor:pointer;
  padding:13px 26px; text-decoration:none; white-space:nowrap;
  display:inline-flex; align-items:center; justify-content:center; gap:var(--sp-2);
  min-height:46px;
  transition:transform 0.08s ease, box-shadow 0.08s ease, background var(--dur-fast);
}
.btn-gold{
  color:var(--ink);
  background:linear-gradient(180deg, #fff1b8, var(--gold) 60%, var(--gold-deep));
  box-shadow:0 8px 0 var(--gold-shadow), 0 12px 20px rgba(0,0,0,0.35);
}
.btn-gold:active{ transform:translateY(6px); box-shadow:0 2px 0 var(--gold-shadow), 0 4px 10px rgba(0,0,0,0.3); }
.btn-outline{ color:var(--cream); background:transparent; border:1.5px solid rgba(255,243,224,0.4); }
.btn-outline:hover{ border-color:var(--cream); }
.btn-ghost{ color:var(--text-muted); background:transparent; }
.btn-ghost:hover{ color:var(--cream); background:var(--surface); }
.btn-magenta{
  color:#fff; background:linear-gradient(180deg, #ff5ba3, var(--magenta) 60%, #c9146a);
  box-shadow:0 6px 0 #96094e, 0 10px 18px rgba(0,0,0,0.35);
}
.btn-magenta:active{ transform:translateY(4px); box-shadow:0 2px 0 #96094e; }
.btn[disabled],.btn.is-disabled{ opacity:0.45; cursor:not-allowed; pointer-events:none; box-shadow:0 8px 0 #4a4a4a; }
.btn-sm{ padding:9px 18px; font-size:13px; min-height:38px; }
.btn-lg{ padding:16px 32px; font-size:17px; min-height:54px; }
.btn-block{ width:100%; }

/* ---------- Button groups ----------
   There was no rule for two buttons next to each other, so every screen
   invented its own inline flex and gap — and a stacked pair ended up flush
   against each other with no gap at all. These are the only two shapes the
   site actually uses.

   VERTICAL gaps between buttons are one step larger than the scale value
   they read as: the 3D press shadow (box-shadow 0 8px 0) hangs 8px below
   every button and is visually part of it, so a 12px gap reads as 4px and a
   wrapped row of gold buttons looks like a pile-up. --sp-5 minus the shadow
   reads as --sp-3, which is the intended rhythm. */
.btn-block + .btn-block{ margin-top:var(--sp-5); }

/* Side by side, wrapping to stacked when there is no room. */
.btn-row{ display:flex; row-gap:var(--sp-5); column-gap:var(--sp-3); flex-wrap:wrap; align-items:center; }

/* Deliberately stacked, full width — a primary action and its way out. */
.btn-stack{ display:flex; flex-direction:column; gap:var(--sp-5); }
.btn-stack .btn{ width:100%; }
.btn-stack .btn + .btn{ margin-top:0; }   /* the gap owns the spacing here */
.btn.is-loading{ pointer-events:none; position:relative; color:transparent; }
.btn.is-loading::after{
  content:""; position:absolute; width:18px; height:18px; border-radius:50%;
  border:2.5px solid rgba(0,0,0,0.25); border-top-color:currentColor;
  animation:spin 0.7s linear infinite;
}
.btn-outline.is-loading::after,.btn-ghost.is-loading::after{ border-color:rgba(255,255,255,0.25); border-top-color:var(--cream); }
@keyframes spin{ to{ transform:rotate(360deg); } }

/* Google sign-in button (brand-locked, exempt from palette) */
.btn-google{
  background:#fff; color:#1f1f1f; border:1px solid #dadce0;
  font-family:var(--font-body); font-weight:700;
}
.btn-google:hover{ background:#f7f8f8; }
.btn-google svg{ width:18px; height:18px; }

/* ---------- 10.4 Caller ball ---------- */
.ball{
  position:relative; width:78px; height:78px; border-radius:50%; flex-shrink:0;
  display:flex; align-items:center; justify-content:center;
  font-family:var(--font-display); font-weight:700; font-size:24px; color:var(--ink);
  /* The artwork is a variable so a room theme can replace it in ONE place.
     `.ball` is shared by the caller, the card dock, the error page and the
     coming-soon mark, and a theme that overrode `background` directly had to
     be repeated for each — or, worse, hit only the one it was written for.
     Admin's uploaded art sets the same variable (see play.blade.php), so an
     upload and a built-in theme can never half-apply over each other. */
  background:var(--ball-art, radial-gradient(circle at 32% 28%, #fff, #ffe9a8 40%, var(--gold) 75%));
  box-shadow:var(--ball-shadow,
    0 0 0 4px rgba(255,255,255,0.12), 0 8px 22px rgba(0,0,0,0.45), inset 0 -6px 10px rgba(0,0,0,0.18));
  transition:background 0.25s ease;
}
.ball small{
  position:absolute; top:8px; font-size:var(--fs-xs); font-weight:800; letter-spacing:1px;
  color:rgba(36,10,61,0.55);
}
.ball.pop{ animation:ballPop 0.5s var(--ease-pop); }
@keyframes ballPop{
  0%{transform:scale(0.6) rotate(-8deg);}
  55%{transform:scale(1.18) rotate(4deg);}
  100%{transform:scale(1) rotate(0);}
}
.ball-sm{ width:56px; height:56px; font-size:18px; }

/* ---------- 10.5 Bingo card ---------- */
.card-wrap{
  background:var(--paper); border-radius:var(--radius-lg); padding:14px;
  box-shadow:var(--shadow-md), var(--inset-hilite);
  position:relative; overflow:hidden;
}
/* Holding a real card for a round that has not started yet. The card stays
   visible and readable underneath — the point is that you HAVE one, which an
   empty grid captioned "waiting" completely failed to communicate. */
.card-wrap.is-waiting .letters,
.card-wrap.is-waiting .grid{ opacity:0.35; filter:saturate(0.5); transition:opacity 0.3s ease; }

.card-waiting{
  position:absolute; inset:0; z-index:2;
  display:grid; place-items:center;
  background:linear-gradient(180deg, rgba(24,10,38,0.55), rgba(24,10,38,0.78));
  /* No backdrop-filter and no radius of its own, on purpose. A blur inside a
     rounded overlay samples past the corner and is clipped with aliasing —
     visibly jittered edges. The parent's overflow:hidden already rounds this,
     and the card underneath is already dimmed; the 1px blur bought nothing
     but the artifact. */
}
.card-waiting[hidden]{ display:none; }
.card-waiting-inner{ text-align:center; padding:12px 18px; }
.cw-label{
  font-family:var(--font-display); font-size:14px; color:#fff;
  text-transform:uppercase; letter-spacing:0.06em; margin-bottom:6px; opacity:0.85;
}
.cw-clock{
  font-family:var(--font-display); font-size:42px; line-height:1;
  color:var(--gold); font-variant-numeric:tabular-nums; margin-bottom:4px;
}
.cw-sub{ font-size:12px; color:rgba(255,255,255,0.75); }

@media (max-width:620px){ .cw-clock{ font-size:34px; } }

@media (prefers-reduced-motion:reduce){
  .card-wrap.is-waiting .letters,
  .card-wrap.is-waiting .grid{ transition:none; }
}

.letters{ display:grid; grid-template-columns:repeat(5,1fr); gap:var(--sp-2); margin-bottom:8px; }
.letters div{
  text-align:center; font-family:var(--font-display); font-weight:700; font-size:20px;
  color:#fff; border-radius:10px; padding:6px 0; letter-spacing:1px;
}
.letters .b{background:var(--col-b, var(--b));} .letters .i{background:var(--col-i, var(--i)); color:var(--ink);}
.letters .n{background:var(--col-n, var(--n)); color:var(--ink);} .letters .g{background:var(--col-g, var(--g));}
.letters .o{background:var(--col-o, var(--o));}

.grid{ display:grid; grid-template-columns:repeat(5,1fr); gap:var(--sp-2); }
.cell{
  aspect-ratio:1/1; border-radius:10px; background:#fff; border:2px solid rgba(36,10,61,0.08);
  display:flex; align-items:center; justify-content:center;
  font-family:var(--font-display); font-weight:600; font-size:16px; color:var(--ink);
  position:relative; cursor:pointer; user-select:none; padding:0;
  transition:transform var(--dur-fast) ease, border-color var(--dur-base) ease;
}
.cell:active{ transform:scale(0.94); }
.cell.free{ background:linear-gradient(160deg,#fff9ec,#ffe6a8); font-size:20px; color:var(--gold-deep); border-color:var(--gold); }
.cell.called:not(.dabbed){ border-color:var(--dab-edge, var(--magenta-soft)); }
.cell.dabbed{ color:var(--on-dab, #fff); }
/* The dab is the room's colour, not the brand's.
   It was hard-coded magenta, so a Halloween room marked its numbers in pink —
   the one mark a player looks at most often was the one thing that never
   matched the room it was in. The default is unchanged, so a theme that says
   nothing still dabs in magenta exactly as before. */
.cell.dabbed::after{
  content:""; position:absolute; inset:0; border-radius:10px;
  background:var(--dab, radial-gradient(circle at 40% 35%, var(--magenta), #b6106a 80%));
  animation:dab var(--dur-slow) var(--ease-pop); z-index:0;
}
.cell.dabbed span{ position:relative; z-index:1; }
@keyframes dab{
  0%{ transform:scale(0) rotate(-25deg); opacity:0; }
  60%{ transform:scale(1.25) rotate(8deg); opacity:1; }
  100%{ transform:scale(1) rotate(0deg); opacity:1; }
}

/* Mini (decorative) card variant — homepage hero */
.card-wrap.is-mini{ width:280px; padding:16px; box-shadow:var(--shadow-lg), var(--inset-hilite); transform:rotate(-4deg); }
.card-wrap.is-mini .letters{ gap:6px; margin-bottom:6px; }
.card-wrap.is-mini .letters div{ font-size:14px; border-radius:7px; padding:4px 0; }
.card-wrap.is-mini .grid{ gap:6px; }
.card-wrap.is-mini .cell{ border-radius:7px; font-size:12px; border-width:1.5px; cursor:default; }
.card-wrap.is-mini .cell.dabbed::after{ border-radius:7px; }
.card-wrap.is-mini .cell.free{ font-size:16px; }

/* ---------- 10.6 History chips ---------- */
.history{
  display:flex; gap:6px; overflow-x:auto;
  /* Vertical room so a matched chip's ring isn't clipped by the scroll box */
  padding:5px 0;
}
.chip{
  width:26px; height:26px; border-radius:50%; font-size:var(--fs-xs); font-weight:800; flex-shrink:0;
  display:flex; align-items:center; justify-content:center; color:var(--ink); background:var(--cream); opacity:0.9;
  font-family:var(--font-display);
}
.chip.b{background:var(--col-b, var(--b));color:#fff;} .chip.i{background:var(--col-i, var(--i));}
.chip.n{background:var(--col-n, var(--n));} .chip.g{background:var(--col-g, var(--g));color:#fff;} .chip.o{background:var(--col-o, var(--o));}

/* ---------- 10.7 Social strip ---------- */
.panel{
  background:var(--surface); border:1px solid var(--border);
  border-radius:var(--radius-lg); padding:var(--sp-4);
}
.panel-label{
  font-size:var(--fs-xs); font-weight:800; letter-spacing:1px; text-transform:uppercase;
  color:var(--magenta-soft); margin-bottom:var(--sp-3);
}
.avatars{ display:flex; align-items:center; }
.avatar{
  width:32px; height:32px; border-radius:50%; display:flex; align-items:center; justify-content:center;
  font-size:15px; border:2px solid var(--bg-1); margin-left:-8px; position:relative; flex-shrink:0;
}
.avatar:first-child{ margin-left:0; }
.avatar.more{ background:var(--surface-strong); color:var(--cream); font-size:10px; font-weight:800; }
.avatar-lg{ width:48px; height:48px; font-size:24px; }
.avatar-xl{ width:88px; height:88px; font-size:42px; border-width:3px; }

.feed{ display:flex; flex-direction:column; gap:6px; min-height:44px; }
.feed-item{ font-size:var(--fs-sm); color:rgba(255,243,224,0.85); animation:feedIn 0.3s ease; }
.feed-item b{ color:var(--gold); }
@keyframes feedIn{ from{opacity:0; transform:translateY(4px);} to{opacity:1; transform:translateY(0);} }

/* ---------- 10.8 Toggle switch ---------- */
.switch{
  width:44px; height:24px; border-radius:var(--radius-pill); background:var(--surface-strong);
  border:1px solid var(--border-strong); position:relative; cursor:pointer; flex-shrink:0; padding:0;
}
.switch::after{
  content:""; position:absolute; top:2px; left:2px; width:18px; height:18px; border-radius:50%;
  background:var(--cream); transition:transform var(--dur-base) ease, background var(--dur-base) ease;
}
.switch[aria-checked="true"]{ background:var(--teal); }
.switch[aria-checked="true"]::after{ transform:translateX(20px); background:#04372f; }

/* ---------- 10.9 Win overlay + confetti ---------- */
.win-overlay{
  position:fixed; inset:0; display:none; align-items:center; justify-content:center;
  background:rgba(21,8,38,0.7); backdrop-filter:blur(3px); z-index:var(--z-overlay);
}
.win-overlay.show{ display:flex; }
.win-banner{
  font-family:var(--font-display); font-weight:700; font-size:44px; text-align:center;
  background:linear-gradient(180deg, #fff, var(--gold) 60%, var(--gold-deep));
  -webkit-background-clip:text; background-clip:text; color:transparent;
  filter:drop-shadow(0 4px 18px rgba(255,203,61,0.5));
  animation:winPop 0.5s var(--ease-pop);
}
.win-sub{ text-align:center; font-size:14px; color:var(--cream); margin-top:var(--sp-2); font-weight:700; }
@keyframes winPop{ 0%{transform:scale(0.5) rotate(-6deg); opacity:0;} 100%{transform:scale(1) rotate(0); opacity:1;} }
.confetti{ position:fixed; top:-20px; width:9px; height:14px; z-index:var(--z-confetti); animation:fall linear forwards; border-radius:2px; }
@keyframes fall{ to{ transform:translateY(105vh) rotate(540deg); opacity:0.9; } }

/* ---------- 10.10 Room card ---------- */
.room-card{
  background:var(--surface); border:1px solid var(--border);
  border-radius:var(--radius-lg); padding:18px; position:relative; overflow:hidden;
  text-decoration:none; display:block; min-width:0;
  transition:transform var(--dur-base) ease, background var(--dur-base) ease, border-color var(--dur-base) ease;
}
a.room-card:hover{ transform:translateY(-3px); background:var(--surface-hover); border-color:var(--border-strong); }
.room-card .accent-bar{ position:absolute; top:0; left:0; right:0; height:4px; }

/* ---- The badge: a word admin wants shouted ----
 *
 * Both colours come from the room, as custom properties set on the card. The
 * model has already refused anything that is not #rrggbb, so nothing but a
 * colour reaches the style attribute.
 *
 * The card also takes a stroke in the badge's colour, so the tag and the card
 * read as one object. It is on an inset box-shadow rather than `border`,
 * because a border would change the card's size and shunt every other card in
 * the grid by a pixel — only the badged ones, which looks like a bug.
 */
.room-card.has-badge{
  box-shadow:inset 0 0 0 2px var(--badge-bg), 0 0 18px -6px var(--badge-bg);
}
.room-card .room-badge{
  display:inline-block; margin-bottom:10px; padding:4px 10px;
  border-radius:var(--radius-pill);
  background:var(--badge-bg); color:var(--badge-fg);
  font-size:10.5px; font-weight:800; letter-spacing:0.09em; text-transform:uppercase;
  /* Admin writes this, so it has to survive a long word without breaking the
     card: it wraps rather than pushing the card wide. */
  max-width:100%; overflow-wrap:anywhere; line-height:1.3;
}
.tag{
  display:inline-flex; align-items:center; gap:6px; font-size:10px; font-weight:800;
  letter-spacing:0.6px; text-transform:uppercase; background:var(--surface-hover);
  border:1px solid var(--border-strong); padding:5px 9px; border-radius:var(--radius-pill); margin-bottom:14px;
}
.tag .pulse{ width:6px; height:6px; }
.tag-soon{ color:var(--gold); border-color:rgba(255,203,61,0.35); }
.tag-private{ color:var(--g); border-color:rgba(139,107,255,0.4); }
.room-card h3{ margin:0 0 6px; }
/* The name, with the room's own mark beside it.
   align-items:baseline so the emoji sits on the name's baseline rather than
   centring against a line box that is taller than the glyph — centring left
   it floating slightly high next to a capital. min-width:0 on the name so a
   long room name still ellipsises instead of pushing the mark out. */
.room-card .room-title{
  display:flex; align-items:baseline; gap:8px; min-width:0;
}
.room-card .room-mark{ font-size:1.05em; line-height:1; flex:0 0 auto; }
.room-card .room-title > span:last-child{
  min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
/* What a win is worth. Gold, because that is what points are everywhere else
   on the site, and a chip rather than a line of text so it reads as a fact
   about the room rather than part of its description. */
.room-card .prize-chip{
  display:inline-flex; align-items:center; gap:6px; margin:0 0 10px;
  padding:4px 10px; border-radius:var(--radius-pill);
  background:rgba(255,203,61,0.12); border:1px solid rgba(255,203,61,0.34);
  color:var(--gold); font-size:12px; font-weight:800; line-height:1.2;
}
.room-card .prize-chip .icon{ width:13px; height:13px; flex:0 0 auto; }
.room-card p{ font-size:var(--fs-sm); color:var(--text-muted); margin:0 0 var(--sp-4); line-height:1.5; }
.room-card .meta{ display:flex; justify-content:space-between; align-items:center; font-size:12px; }
.room-card .price{ font-weight:800; color:var(--gold); }
.room-card .players{ color:var(--text-muted); }

/* ---------- 10.11 Feature card ---------- */
.feature-card{
  background:var(--surface); border:1px solid var(--border);
  border-radius:var(--radius-lg); padding:26px;
}
.feature-icon{
  width:48px; height:48px; border-radius:14px; display:flex; align-items:center; justify-content:center;
  font-size:22px; margin-bottom:var(--sp-4);
}
.feature-card h3{ margin:0 0 var(--sp-2); }
.feature-card p{ font-size:14px; line-height:1.6; color:var(--text-muted); margin:0; }

/* ---------- 10.12 Step item ---------- */
.step{ position:relative; padding-left:52px; }
.step .num{
  position:absolute; left:0; top:0; width:38px; height:38px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  font-family:var(--font-display); font-weight:700; font-size:16px; color:var(--ink);
  background:radial-gradient(circle at 32% 28%, #fff, #ffe9a8 40%, var(--gold) 75%);
  box-shadow:var(--shadow-sm);
}
.step h3{ font-size:17px; margin:0 0 6px; }
.step p{ font-size:14px; color:var(--text-muted); line-height:1.55; margin:0; }

/* ---------- 10.13 Proof stat band ---------- */
.proof-band{
  background:var(--paper); border-radius:var(--radius-lg);
  padding:36px 32px; display:flex; align-items:center; justify-content:space-between;
  gap:var(--sp-6); flex-wrap:wrap; color:var(--ink);
}
.proof-band .stat{ text-align:center; flex:1 1 120px; }
.proof-band .stat b{ display:block; font-family:var(--font-display); font-size:32px; font-weight:700; }
.proof-band .stat span{ font-size:12px; font-weight:700; color:rgba(36,10,61,0.6); text-transform:uppercase; letter-spacing:0.5px; }

/* ---------- Grids ---------- */
/* Room cards, wherever they appear.
   There were three answers to this: `.grid-4`, a page-local `.rooms-grid`
   defined in a @push block on the lobby, and `.room-grid` on the hall — which
   was never defined anywhere, so those cards fell out of grid entirely and
   stacked full-width. One class, defined once, beside the other grid helpers
   it belongs with. */
.room-grid{
  display:grid; grid-template-columns:repeat(3,1fr); gap:var(--sp-4);
}
@media (max-width:980px){ .room-grid{ grid-template-columns:repeat(2,1fr); } }
@media (max-width:620px){ .room-grid{ grid-template-columns:1fr; } }

.grid-4{ display:grid; grid-template-columns:repeat(4,1fr); gap:var(--sp-4); }
.grid-3{ display:grid; grid-template-columns:repeat(3,1fr); gap:var(--sp-5); }
@media (max-width:900px){ .grid-4{ grid-template-columns:repeat(2,1fr); } }
@media (max-width:820px){ .grid-3{ grid-template-columns:1fr; } }
@media (max-width:520px){ .grid-4{ grid-template-columns:1fr; } }

/* ---------- Room card — extended (lobby variant) ---------- */
.room-card .card-head{ display:flex; align-items:center; gap:var(--sp-2); flex-wrap:wrap; margin-bottom:var(--sp-3); }
.room-card .card-head .tag{ margin-bottom:0; }
.pattern-chip{
  display:inline-flex; align-items:center; gap:5px;
  font-size:10px; font-weight:800; letter-spacing:0.5px; text-transform:uppercase;
  /* The label is 10px uppercase; an icon at 1em of that is a speck. Sized off
     the chip rather than given a pixel value so it still tracks the type. */
  color:var(--text-muted); background:rgba(0,0,0,0.22); border:1px solid var(--border);
  padding:5px 9px; border-radius:var(--radius-pill);
}
.pattern-chip .icon{ width:1.4em; height:1.4em; }
.room-card .card-foot{
  display:flex; align-items:center; justify-content:space-between; gap:var(--sp-2);
  flex-wrap:wrap; border-top:1px solid var(--border);
  padding-top:var(--sp-3); margin-top:var(--sp-4);
}
.room-card .card-foot .avatars .avatar{ width:26px; height:26px; font-size:12px; margin-left:-7px; border-width:2px; }
.room-card .who{ display:flex; align-items:center; gap:var(--sp-2); min-width:0; }
.room-card .who > span:last-child{ font-size:12px; color:var(--text-muted); font-weight:700; }
.room-card .who .avatars{ flex-shrink:0; }
.room-card.is-full{ opacity:0.6; }
.room-card.is-full:hover{ transform:none; }

/* Featured room — spans two columns on desktop */
.room-card.is-featured{ grid-column:span 2; padding:24px; background:rgba(255,255,255,0.07); }
.room-card.is-featured h3{ font-size:26px; }
.room-card.is-featured p{ font-size:15px; max-width:46ch; }
@media (max-width:520px){ .room-card.is-featured{ grid-column:span 1; } }

/* ---------- Lobby toolbar ---------- */
.lobby-toolbar{
  display:flex; align-items:center; justify-content:space-between; gap:var(--sp-4);
  flex-wrap:wrap; margin-bottom:var(--sp-6);
  position:sticky; top:0; z-index:10;
  padding:var(--sp-3) 0;
  transition:background var(--dur-base) ease, box-shadow var(--dur-base) ease;
}
@media (max-width:700px){
  .lobby-toolbar{ align-items:flex-start; gap:var(--sp-2); }
  .lobby-toolbar .chips{
    flex-wrap:nowrap; overflow-x:auto; scrollbar-width:none;
    margin:0 calc(var(--sp-6) * -1); padding:2px var(--sp-6); width:100vw; max-width:100vw;
  }
  .lobby-toolbar .chips::-webkit-scrollbar{ display:none; }
  .lobby-toolbar .filter-chip{ flex-shrink:0; }
}
.lobby-toolbar.is-stuck{
  background:linear-gradient(180deg, rgba(21,8,38,0.96) 65%, rgba(21,8,38,0));
  backdrop-filter:blur(8px);
  box-shadow:0 10px 20px -14px rgba(0,0,0,0.8);
}

/* ---------- Chat (room detail preview + game screen) ---------- */
.chat-list{ display:flex; flex-direction:column; gap:var(--sp-3); }
.chat-msg{ display:flex; gap:var(--sp-2); align-items:flex-start; }
.chat-msg .avatar{ margin-left:0; width:28px; height:28px; font-size:13px; }
.chat-msg .body{ min-width:0; }
.chat-msg .who{
  display:flex; align-items:center; gap:5px; flex-wrap:wrap;
  font-size:12px; font-weight:800; color:var(--gold); margin-bottom:1px;
  /* A long name has no space in it to wrap at, so without this it runs off
     the side of a narrow screen and takes the report button with it. */
  min-width:0; overflow-wrap:anywhere;
}
.chat-msg .who time{ color:var(--text-dim); font-weight:700; font-size:11px; }
.chat-msg .text{ font-size:14px; line-height:1.45; color:rgba(255,243,224,0.9); overflow-wrap:anywhere; }
.chat-msg.is-system .text{ color:var(--text-muted); font-style:italic; }
.chat-msg.is-win .text{ color:var(--teal); font-weight:700; font-style:normal; }

/* ---------- Player wall tile ---------- */
.player-wall{ display:grid; grid-template-columns:repeat(auto-fill,minmax(84px,1fr)); gap:var(--sp-3); }
.player-tile{ text-align:center; min-width:0; }
.player-tile .avatar{ margin:0 auto 6px; }
.player-tile .name{
  font-size:12px; font-weight:800; color:var(--text-muted);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.player-tile .bot-badge{ margin-top:3px; }

/* ---------- Definition list (room facts, settings) ---------- */
.info-list{ margin:0; }
.info-list div{
  display:flex; align-items:baseline; justify-content:space-between; gap:var(--sp-4);
  padding:11px 0; border-bottom:1px solid var(--border);
}
.info-list div:last-child{ border-bottom:none; }
.info-list dt{ font-size:12px; font-weight:800; letter-spacing:0.5px; text-transform:uppercase; color:var(--text-dim); }
.info-list dd{ margin:0; font-size:14px; font-weight:700; text-align:right; }

/* ---------- Auth screen shell ---------- */
/* justify-content:center would clip the top of a card taller than the viewport;
   auto margins centre it when there's room and scroll cleanly when there isn't. */
.auth-shell{
  min-height:100dvh; display:flex; flex-direction:column; align-items:center;
  justify-content:flex-start; padding:var(--sp-6) var(--sp-4);
}
.auth-shell > *{ margin-block:auto; }
.auth-shell > * + *{ margin-block-start:0; }
.auth-card{
  width:100%; max-width:420px;
  background:linear-gradient(180deg, rgba(255,255,255,0.07), rgba(255,255,255,0.03));
  border:1px solid var(--border-strong); border-radius:var(--radius-lg);
  padding:var(--sp-8); box-shadow:var(--shadow-lg);
}
.auth-card h1{ font-size:28px; margin:0 0 var(--sp-2); }
.auth-card .auth-sub{ font-size:14px; color:var(--text-muted); margin-bottom:var(--sp-6); line-height:1.55; }
/* "No account yet?" — the same box signs you up, so this reads as an invitation
   rather than small print. Sits above the terms line, which is the quiet one. */
.auth-alt{
  margin-top:var(--sp-5); text-align:center; font-size:13.5px;
  color:var(--text-muted); line-height:1.6;
}
.auth-alt .linkish{ font-size:13.5px; font-weight:800; color:var(--gold); }

.auth-foot{ margin-top:var(--sp-4); text-align:center; font-size:12px; color:var(--text-dim); line-height:1.6; }
.auth-foot a{ color:var(--text-muted); }
.divider{ display:flex; align-items:center; gap:var(--sp-3); margin:var(--sp-5) 0; color:var(--text-dim); font-size:11px; font-weight:800; letter-spacing:1px; }
.divider::before,.divider::after{ content:""; flex:1; height:1px; background:var(--border); }
.step-dots{ display:flex; gap:6px; justify-content:center; margin-bottom:var(--sp-6); }
.step-dots span{ width:7px; height:7px; border-radius:50%; background:var(--surface-strong); }
.step-dots span.is-on{ background:var(--gold); box-shadow:0 0 8px rgba(255,203,61,0.6); }

/* ---------- Leaderboard ---------- */
.podium{ display:grid; grid-template-columns:1fr 1.15fr 1fr; gap:var(--sp-3); align-items:end; margin-bottom:var(--sp-6); }
.podium-step{
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg);
  padding:var(--sp-4) var(--sp-3); text-align:center; position:relative; overflow:hidden;
}
.podium-step .medal{ font-size:24px; line-height:1; margin-bottom:6px; }
.podium-step .avatar{ margin:0 auto 8px; }
.podium-step .name{ font-family:var(--font-display); font-weight:600; font-size:15px; }
.podium-step .pts{ font-size:12px; font-weight:800; color:var(--gold); margin-top:2px; }
.podium-step .sub{ font-size:11px; color:var(--text-dim); font-weight:700; margin-top:2px; }
.podium-step.is-1{
  background:linear-gradient(180deg, rgba(255,203,61,0.20), rgba(255,255,255,0.05));
  border-color:rgba(255,203,61,0.45); padding-top:var(--sp-6); padding-bottom:var(--sp-6);
}
.podium-step.is-1 .name{ font-size:18px; }
@media (max-width:520px){
  .podium{ grid-template-columns:1fr; }
  .podium-step.is-1{ order:-1; }
}

.lb-list{ background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg); overflow:hidden; }
.lb-row{ display:flex; align-items:center; gap:var(--sp-3); padding:13px var(--sp-4); border-bottom:1px solid var(--border); }
.lb-row:last-child{ border-bottom:none; }
.lb-rank{
  width:30px; flex-shrink:0; text-align:center;
  font-family:var(--font-display); font-weight:700; font-size:15px; color:var(--text-dim);
}
.lb-row .avatar{ margin-left:0; flex-shrink:0; }
.lb-name{ flex:1; min-width:0; font-weight:800; font-size:14px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.lb-name .meta{ display:block; font-size:11px; font-weight:700; color:var(--text-dim); }
.lb-pts{ font-family:var(--font-display); font-weight:700; font-size:16px; color:var(--gold); flex-shrink:0; }
.lb-move{ width:34px; text-align:right; font-size:11px; font-weight:800; flex-shrink:0; }
.lb-move.up{ color:var(--teal); } .lb-move.down{ color:var(--danger); } .lb-move.same{ color:var(--text-dim); }
.lb-row.is-you{
  background:linear-gradient(90deg, rgba(255,203,61,0.16), rgba(255,203,61,0.04));
  border-left:3px solid var(--gold);
}
.lb-row.is-you .lb-name::after{ content:" · you"; color:var(--gold); font-weight:800; }

/* ---------- Article card ---------- */
.article-card{
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg);
  overflow:hidden; text-decoration:none; display:flex; flex-direction:column; min-width:0;
  transition:transform var(--dur-base) ease, background var(--dur-base) ease;
}
a.article-card:hover{ transform:translateY(-3px); background:var(--surface-hover); }
.article-card .thumb{
  aspect-ratio:16/9; display:flex; align-items:center; justify-content:center; font-size:44px;
  border-bottom:1px solid var(--border);
}
.article-card .inner{ padding:18px; display:flex; flex-direction:column; gap:var(--sp-2); flex:1; }
.article-card h3{ font-size:18px; line-height:1.3; }
.article-card p{ font-size:13px; color:var(--text-muted); line-height:1.55; flex:1; }
.article-card .byline{ display:flex; align-items:center; gap:7px; font-size:11px; color:var(--text-dim); font-weight:700; }
.article-card .byline .avatar{ width:22px; height:22px; font-size:11px; margin-left:0; border-width:1.5px; }
.cat-chip{
  align-self:flex-start; font-size:10px; font-weight:800; letter-spacing:0.6px; text-transform:uppercase;
  padding:4px 9px; border-radius:var(--radius-pill); background:var(--surface-strong); color:var(--magenta-soft);
}
.ai-note{
  display:inline-flex; align-self:flex-start; align-items:center; gap:5px; font-size:10px; font-weight:800;
  letter-spacing:0.4px; color:var(--text-dim); border:1px solid var(--border);
  padding:3px 8px; border-radius:var(--radius-pill);
}

/* ---------- Long-form document layout (legal, help, articles) ---------- */
.doc-layout{ display:grid; grid-template-columns:240px 1fr; gap:var(--sp-10); align-items:start; padding-bottom:var(--sp-16); }
@media (max-width:900px){ .doc-layout{ grid-template-columns:1fr; gap:var(--sp-6); } }

.doc-toc{ position:sticky; top:var(--sp-6); }
@media (max-width:900px){
  .doc-toc{ position:static; background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg); padding:var(--sp-4); }
}
.doc-toc .panel-label{ margin-bottom:var(--sp-3); }
.doc-toc ol{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:2px; counter-reset:toc; }
.doc-toc a{
  display:block; padding:7px 10px; border-radius:var(--radius-sm); text-decoration:none;
  font-size:13px; font-weight:700; color:var(--text-muted); border-left:2px solid transparent;
}
.doc-toc a:hover{ color:var(--cream); background:var(--surface); }
.doc-toc a.is-active{ color:var(--gold); border-left-color:var(--gold); background:var(--surface); }

.doc-body{ max-width:72ch; }
.doc-body h2{
  font-size:26px; margin:var(--sp-10) 0 var(--sp-4); scroll-margin-top:var(--sp-6);
  padding-top:var(--sp-4); border-top:1px solid var(--border);
}
.doc-body h2:first-child{ margin-top:0; border-top:none; padding-top:0; }
.doc-body h3{ font-size:18px; margin:var(--sp-6) 0 var(--sp-2); }
.doc-body p{ margin-bottom:var(--sp-4); color:var(--text-muted); font-size:15px; line-height:1.7; }
.doc-body ul,.doc-body ol{ margin:0 0 var(--sp-4); padding-left:var(--sp-5); color:var(--text-muted); font-size:15px; line-height:1.7; }
.doc-body li{ margin-bottom:var(--sp-2); }
.doc-body li::marker{ color:var(--magenta-soft); }
.doc-body strong{ color:var(--cream); }
.doc-body a{ color:var(--gold); }
.doc-body table{ width:100%; border-collapse:collapse; margin-bottom:var(--sp-4); font-size:14px; }
.doc-body th,.doc-body td{ text-align:left; padding:10px 12px; border-bottom:1px solid var(--border); color:var(--text-muted); }
.doc-body th{ color:var(--cream); font-weight:800; font-size:12px; text-transform:uppercase; letter-spacing:0.5px; }
.doc-body blockquote{
  margin:0 0 var(--sp-4); padding:var(--sp-3) 0 var(--sp-3) var(--sp-4);
  border-left:3px solid var(--gold); color:var(--text-muted); font-size:15px; line-height:1.7;
}

.doc-head{ padding:var(--sp-6) 0 var(--sp-6); }
.doc-head h1{ font-size:40px; margin:0 0 var(--sp-3); }
@media (max-width:620px){ .doc-head h1{ font-size:28px; } }
.doc-meta{ display:flex; gap:var(--sp-2); flex-wrap:wrap; align-items:center; font-size:12px; color:var(--text-dim); font-weight:700; }

/* Draft banner — anything not yet reviewed by a human who's qualified to */
.draft-banner{
  display:flex; gap:var(--sp-3); align-items:flex-start;
  background:rgba(255,92,92,0.10); border:1px solid rgba(255,92,92,0.35);
  border-radius:var(--radius-md); padding:var(--sp-4); margin-bottom:var(--sp-6);
  font-size:13px; line-height:1.6; color:var(--text-muted);
}
.draft-banner b{ color:var(--cream); }
.draft-banner .ico{ font-size:18px; line-height:1; flex-shrink:0; }

/* Help search */
.help-search{ position:relative; max-width:520px; margin-bottom:var(--sp-8); }
.help-search .input{ padding-left:44px; height:54px; font-size:16px; }
.help-search .ico{ position:absolute; left:15px; top:15px; font-size:19px; opacity:0.6; pointer-events:none; }

.help-cats{ display:grid; grid-template-columns:repeat(4,1fr); gap:var(--sp-3); margin-bottom:var(--sp-10); }
@media (max-width:820px){ .help-cats{ grid-template-columns:repeat(2,1fr); } }
.help-cat{
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg);
  padding:var(--sp-5) var(--sp-4); text-align:center; text-decoration:none; display:block;
  transition:background var(--dur-base), transform var(--dur-base);
}
.help-cat:hover{ background:var(--surface-hover); transform:translateY(-2px); }
.help-cat .ico{ font-size:26px; display:block; margin-bottom:var(--sp-2); }
.help-cat .t{ display:block; font-family:var(--font-display); font-weight:600; font-size:15px; }
.help-cat .n{ display:block; font-size:11px; color:var(--text-dim); font-weight:700; margin-top:3px; }

/* ---------- Card dock ----------
   When the bingo card scrolls out of view on a phone, the draws follow you.
   Shows the current call, recent draws and how close you are, with a chevron
   that brings the card back. Hidden on desktop, where the card stays visible. */
.card-dock{
  position:fixed; left:0; right:0; bottom:0; z-index:calc(var(--z-nav) + 5);
  display:flex; align-items:center; gap:var(--sp-3);
  padding:10px var(--sp-4) calc(10px + env(safe-area-inset-bottom));
  background:rgba(21,8,38,0.94); backdrop-filter:blur(14px);
  border-top:1px solid var(--border-strong);
  box-shadow:0 -10px 30px rgba(0,0,0,0.45);
  transform:translateY(200%); opacity:0; visibility:hidden;
  transition:transform var(--dur-slow) var(--ease-pop), opacity var(--dur-base) ease;
  pointer-events:none;
}
.card-dock.is-up{ transform:translateY(0); opacity:1; visibility:visible; pointer-events:auto; }
.card-dock .ball{
  width:46px; height:46px; font-size:15px; flex-shrink:0;
  box-shadow:0 0 0 3px rgba(255,255,255,0.10), 0 4px 12px rgba(0,0,0,0.4);
}
.card-dock .ball small{ top:4px; font-size:8px; }
.card-dock .dock-body{ flex:1; min-width:0; }
.card-dock .dock-label{
  font-size:9px; font-weight:800; letter-spacing:0.8px; text-transform:uppercase;
  color:var(--magenta-soft); margin-bottom:4px;
}
.card-dock .history .chip{ width:22px; height:22px; font-size:9px; }
.card-dock .dock-status{ font-size:11px; font-weight:800; color:var(--text-muted); margin-top:4px; }
.card-dock .dock-status.is-close{ color:var(--gold); }
.card-dock .reopen{
  width:44px; height:44px; flex-shrink:0; border-radius:50%; cursor:pointer;
  display:flex; align-items:center; justify-content:center;
  background:linear-gradient(180deg, #fff1b8, var(--gold) 60%, var(--gold-deep));
  color:var(--ink); border:none; font-size:19px; line-height:1;
  box-shadow:0 4px 0 var(--gold-shadow), 0 6px 14px rgba(0,0,0,0.4);
}
.card-dock .reopen:active{ transform:translateY(3px); box-shadow:0 1px 0 var(--gold-shadow); }
/* Sits above the mobile app nav when one is present */
body.has-bottom-nav .card-dock{ bottom:68px; }
@media (min-width:1081px){ .card-dock{ display:none; } }

/* ---------- Invite / share ---------- */
.share-link{
  display:flex; align-items:center; gap:var(--sp-2);
  background:rgba(0,0,0,0.3); border:1.5px solid var(--border-strong);
  border-radius:var(--radius-md); padding:6px 6px 6px 14px;
}
.share-link input{
  flex:1; min-width:0; background:none; border:none; color:var(--cream);
  font-family:var(--font-body); font-weight:700; font-size:14px; padding:8px 0;
}
.share-link input:focus{ outline:none; }
.share-grid{ display:grid; grid-template-columns:repeat(3,1fr); gap:var(--sp-2); margin-top:var(--sp-3); }
.share-btn{
  display:flex; flex-direction:column; align-items:center; gap:5px; cursor:pointer;
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-md);
  padding:12px 8px; color:var(--cream); font-family:var(--font-body); font-weight:800; font-size:11px;
  transition:background var(--dur-fast), transform var(--dur-fast);
}
.share-btn:hover{ background:var(--surface-hover); transform:translateY(-2px); }
.share-btn .ico{ font-size:20px; line-height:1; }

.qr-box{
  width:168px; height:168px; margin:0 auto; padding:12px; border-radius:var(--radius-md);
  background:#fff; display:flex; align-items:center; justify-content:center;
}
.qr-box svg{ width:100%; height:100%; display:block; }
.qr-note{ text-align:center; font-size:11px; color:var(--text-dim); margin-top:var(--sp-2); line-height:1.5; }

/* Link unfurl preview — what people see when the link is pasted */
.unfurl{
  display:flex; gap:var(--sp-3); align-items:stretch; overflow:hidden;
  background:rgba(0,0,0,0.28); border:1px solid var(--border); border-radius:var(--radius-md);
}
.unfurl .thumb{
  width:96px; flex-shrink:0; display:flex; align-items:center; justify-content:center; font-size:34px;
  background:linear-gradient(150deg, var(--magenta), var(--g));
}
.unfurl .meta{ padding:12px 14px; min-width:0; }
.unfurl .site{ font-size:10px; font-weight:800; letter-spacing:0.6px; text-transform:uppercase; color:var(--text-dim); }
.unfurl .t{ font-family:var(--font-display); font-weight:600; font-size:15px; margin:2px 0 3px; }
.unfurl .d{ font-size:12px; color:var(--text-muted); line-height:1.45; }

/* ---------- Invite landing ---------- */
.invite-hero{ text-align:center; padding:var(--sp-12) 0 var(--sp-8); }
.invite-hero .from{
  display:inline-flex; align-items:center; gap:var(--sp-2); margin-bottom:var(--sp-5);
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-pill);
  padding:8px 16px 8px 8px; font-size:13px; font-weight:800;
}
.invite-hero .from .avatar{ margin-left:0; width:30px; height:30px; font-size:15px; }
.invite-hero h1{ font-size:40px; margin:0 auto var(--sp-4); max-width:16ch; }
@media (max-width:620px){ .invite-hero h1{ font-size:28px; } }
.invite-hero .lede{ margin:0 auto var(--sp-6); }
.invite-card{ max-width:420px; margin:0 auto; }
.trust-row{
  display:flex; gap:var(--sp-5); justify-content:center; flex-wrap:wrap;
  margin-top:var(--sp-6); font-size:12px; font-weight:700; color:var(--text-muted);
}
/* inline-block, not inline-flex: a single text node has no flex gap and the
   whitespace between emoji and label collapses. */
.trust-row span{ display:inline-block; }

/* ---------- Settings ---------- */
.settings-layout{ display:grid; grid-template-columns:220px minmax(0,1fr); gap:var(--sp-8); align-items:start; padding-bottom:var(--sp-16); }
@media (max-width:860px){ .settings-layout{ grid-template-columns:1fr; gap:var(--sp-5); } }

.settings-nav{ position:sticky; top:var(--sp-6); }
@media (max-width:860px){
  .settings-nav{ position:static; display:flex; gap:var(--sp-2); overflow-x:auto; scrollbar-width:none;
    margin:0 calc(var(--sp-6) * -1); padding:2px var(--sp-6); }
  .settings-nav::-webkit-scrollbar{ display:none; }
  .settings-nav a{ flex-shrink:0; white-space:nowrap; }
}
.settings-nav a{
  display:block; padding:9px 12px; border-radius:var(--radius-sm); text-decoration:none;
  font-size:13px; font-weight:800; color:var(--text-muted); border-left:2px solid transparent;
}
.settings-nav a:hover{ color:var(--cream); background:var(--surface); }
.settings-nav a.is-active{ color:var(--gold); border-left-color:var(--gold); background:var(--surface); }
@media (max-width:860px){
  .settings-nav a{ border-left:none; border:1px solid var(--border); border-radius:var(--radius-pill); }
  .settings-nav a.is-active{ border-color:var(--gold); }
}

.set-group{ margin-bottom:var(--sp-8); scroll-margin-top:var(--sp-6); }
.set-group > h2{ font-size:20px; margin-bottom:var(--sp-2); }
.set-group > .intro{ font-size:14px; color:var(--text-muted); line-height:1.6; margin-bottom:var(--sp-4); max-width:60ch; }

.set-row{
  display:flex; align-items:flex-start; justify-content:space-between; gap:var(--sp-4);
  padding:var(--sp-4) 0; border-bottom:1px solid var(--border);
}
.set-row:last-child{ border-bottom:none; }
.set-row .label{ min-width:0; }
.set-row .label .t{ font-size:14px; font-weight:800; margin-bottom:3px; }
.set-row .label .d{ font-size:13px; color:var(--text-muted); line-height:1.55; max-width:52ch; }
.set-row .control{ flex-shrink:0; display:flex; align-items:center; gap:var(--sp-2); }
.set-row .control .select{ width:auto; min-width:150px; padding:9px 34px 9px 12px; min-height:40px; font-size:14px; }
@media (max-width:560px){
  .set-row{ flex-direction:column; gap:var(--sp-3); }
  .set-row .control{ width:100%; }
  .set-row .control .select{ width:100%; }
}

.danger-zone{
  background:rgba(255,92,92,0.07); border:1px solid rgba(255,92,92,0.35);
  border-radius:var(--radius-lg); padding:var(--sp-6);
}
.danger-zone h2{ font-size:18px; margin-bottom:var(--sp-2); color:var(--danger); }
.btn-danger{
  color:#fff; background:transparent; border:1.5px solid rgba(255,92,92,0.6);
}
.btn-danger:hover{ background:rgba(255,92,92,0.15); border-color:var(--danger); }

.break-active{
  display:flex; align-items:center; gap:var(--sp-3);
  background:rgba(35,230,197,0.1); border:1px solid rgba(35,230,197,0.4);
  border-radius:var(--radius-md); padding:var(--sp-4); margin-top:var(--sp-3); font-size:13px; line-height:1.55;
}
.saved-flag{
  display:inline-flex; align-items:center; gap:5px; font-size:11px; font-weight:800;
  color:var(--teal); opacity:0; transition:opacity var(--dur-base);
}
.saved-flag.show{ opacity:1; }

/* ---------- Stat tiles ---------- */
.stat-grid{ display:grid; grid-template-columns:repeat(4,1fr); gap:var(--sp-3); }
@media (max-width:760px){ .stat-grid{ grid-template-columns:repeat(2,1fr); } }
.stat-tile{
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg);
  padding:var(--sp-5) var(--sp-4); text-align:center;
}
.stat-tile b{ display:block; font-family:var(--font-display); font-weight:700; font-size:28px; line-height:1; }
.stat-tile span{
  display:block; font-size:10px; font-weight:800; letter-spacing:0.6px; text-transform:uppercase;
  color:var(--text-dim); margin-top:6px;
}
.stat-tile.is-gold b{ color:var(--gold); }
.stat-tile.is-teal b{ color:var(--teal); }
.stat-tile.is-magenta b{ color:var(--magenta-soft); }

/* ---------- Streak ---------- */
.streak{
  display:flex; align-items:center; gap:var(--sp-4); flex-wrap:wrap;
  background:linear-gradient(120deg, rgba(255,203,61,0.16), rgba(255,47,135,0.10));
  border:1px solid rgba(255,203,61,0.35); border-radius:var(--radius-lg); padding:var(--sp-5);
}
.streak .flame{ font-size:36px; line-height:1; }
.streak .body{ flex:1; min-width:180px; }
.streak .body h3{ font-size:19px; margin-bottom:3px; }
.streak .body p{ font-size:13px; color:var(--text-muted); }
.streak-days{ display:flex; gap:6px; margin-top:10px; }
.streak-days i{
  width:26px; height:26px; border-radius:8px; display:flex; align-items:center; justify-content:center;
  background:var(--surface-strong); font-style:normal; font-size:10px; font-weight:800; color:var(--text-dim);
}
.streak-days i.on{ background:var(--gold); color:var(--ink); }
.streak-days i.today{ box-shadow:0 0 0 2px var(--cream); }

/* ---------- Ledger / activity timeline ---------- */
.ledger{ border:1px solid var(--border); border-radius:var(--radius-lg); overflow:hidden; }
.ledger-row{
  display:flex; align-items:center; gap:var(--sp-3); padding:13px var(--sp-4);
  border-bottom:1px solid var(--border);
}
.ledger-row:last-child{ border-bottom:none; }
.ledger-row .ico{
  width:34px; height:34px; border-radius:10px; flex-shrink:0;
  display:flex; align-items:center; justify-content:center; font-size:16px; background:var(--surface-strong);
}
.ledger-row .what{ flex:1; min-width:0; }
.ledger-row .what .t{ font-size:14px; font-weight:800; }
.ledger-row .what .m{ font-size:12px; color:var(--text-dim); font-weight:700; }
.ledger-row .amt{ font-family:var(--font-display); font-weight:700; font-size:16px; flex-shrink:0; }
.ledger-row .amt.plus{ color:var(--teal); }
.ledger-row .amt.minus{ color:var(--danger); }
.ledger-row .rankedness{ flex-shrink:0; }

/* ---------- Badges ---------- */
.badge-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(132px,1fr)); gap:var(--sp-3); }
.badge-tile{
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg);
  padding:var(--sp-4) var(--sp-3); text-align:center;
}
.badge-tile .em{ font-size:32px; line-height:1; margin-bottom:8px; }
.badge-tile .n{ font-family:var(--font-display); font-weight:600; font-size:14px; }
.badge-tile .d{ font-size:11px; color:var(--text-dim); line-height:1.45; margin-top:3px; }
.badge-tile.is-locked{ opacity:0.42; }
.badge-tile.is-locked .em{ filter:grayscale(1); }
.badge-progress{ height:4px; border-radius:99px; background:var(--surface-strong); margin-top:8px; overflow:hidden; }
.badge-progress i{ display:block; height:100%; background:var(--gold); }

/* ---------- Dashboard hero ---------- */
.hall-hero{
  display:flex; align-items:center; gap:var(--sp-4); flex-wrap:wrap;
  padding:var(--sp-8) 0 var(--sp-6);
}
.hall-hero .avatar{ margin-left:0; }
.hall-hero h1{ font-size:32px; margin:0; }
.hall-hero .sub{ font-size:14px; color:var(--text-muted); margin-top:2px; }
@media (max-width:620px){ .hall-hero h1{ font-size:24px; } }

.section-title{ display:flex; align-items:baseline; justify-content:space-between; gap:var(--sp-3); margin-bottom:var(--sp-4); flex-wrap:wrap; }
.section-title h2{ font-size:20px; }
.section-title a{ font-size:13px; font-weight:800; color:var(--gold); text-decoration:none; }

/* ---------- Friends list ---------- */
.friend-row{ display:flex; align-items:center; gap:var(--sp-3); padding:12px 0; border-bottom:1px solid var(--border); }
.friend-row:last-child{ border-bottom:none; }
.friend-row .avatar{ margin-left:0; position:relative; }
.friend-row .who{ flex:1; min-width:0; }
.friend-row .who .n{ font-size:14px; font-weight:800; }
.friend-row .who .s{ font-size:12px; color:var(--text-dim); font-weight:700; }
.friend-row .who .s.online{ color:var(--teal); }
.dot-online{
  position:absolute; right:-1px; bottom:-1px; width:11px; height:11px; border-radius:50%;
  background:var(--teal); border:2px solid var(--bg-1);
}

/* ---------- Season band (leaderboards) ---------- */
.season-band{
  display:flex; align-items:center; justify-content:space-between; gap:var(--sp-4); flex-wrap:wrap;
  background:linear-gradient(135deg, rgba(255,203,61,0.14), rgba(255,47,135,0.10));
  border:1px solid rgba(255,203,61,0.3); border-radius:var(--radius-lg);
  padding:var(--sp-4); margin-bottom:var(--sp-5);
}
.season-band b{ display:block; font-family:var(--font-display); font-size:16px; }
.season-band span{ font-size:12.5px; color:var(--text-muted); }

/* ---------- Your rank, pinned (leaderboards) ----------
   The number most people came to look at. Sticks to the bottom so it survives
   scrolling past your own row, and clears the mobile bottom nav. */
.your-rank{
  position:sticky; bottom:var(--sp-4); z-index:20;
  display:flex; align-items:center; gap:var(--sp-3); margin-top:var(--sp-6);
  background:var(--surface-strong); border:1px solid var(--magenta); border-radius:var(--radius-lg);
  padding:13px var(--sp-4); box-shadow:0 10px 30px rgba(0,0,0,0.45);
}
body.has-bottom-nav .your-rank{ bottom:calc(var(--sp-4) + 72px); }

/* ---------- Points pill (header) ----------
   The player's total, one tap from the ledger. Next to the avatar rather than
   inside the Play now button — a CTA should say one thing, and a number in it
   competes with the verb. */
.points-pill{
  display:inline-flex; align-items:center; gap:6px; text-decoration:none;
  padding:7px 12px; border-radius:var(--radius-pill); white-space:nowrap;
  background:rgba(255,203,61,0.12); border:1px solid rgba(255,203,61,0.35);
  font-size:13px; font-weight:800; color:var(--gold);
}
.points-pill:hover{ background:rgba(255,203,61,0.2); }
.points-pill .dot{ width:7px; height:7px; border-radius:50%; background:var(--gold); flex-shrink:0; }
.points-pill b{ font-family:var(--font-display); }

/* ---------- User menu (header) ---------- */
.user-menu{ position:relative; }
.user-trigger{
  display:inline-flex; align-items:center; gap:2px; cursor:pointer;
  background:none; border:none; padding:2px; border-radius:var(--radius-pill);
}
.user-trigger .avatar{ margin-left:0; }
.user-trigger .chev{ color:var(--text-muted); font-size:11px; transition:transform var(--dur-fast); }
.user-trigger[aria-expanded="true"] .chev{ transform:rotate(180deg); }
.user-trigger:hover .chev{ color:var(--cream); }

.user-dropdown{
  position:absolute; top:calc(100% + 10px); right:0; z-index:60; min-width:216px;
  /* Opaque — this floats over cards and chat, and a translucent panel over a
     bingo grid is unreadable. */
  background:linear-gradient(180deg, var(--surface-float-hi), var(--surface-float));
  border:1px solid rgba(255,255,255,0.14);
  border-radius:var(--radius-lg); padding:6px;
  box-shadow:0 18px 44px rgba(0,0,0,0.6), 0 0 0 1px rgba(0,0,0,0.3);
}
.user-dropdown[hidden]{ display:none; }
.user-dropdown .who{ padding:10px 12px 12px; border-bottom:1px solid var(--border); margin-bottom:6px; }
.user-dropdown .who b{ display:block; font-family:var(--font-display); font-size:15px; }
.user-dropdown .who span{ font-size:12px; font-weight:700; color:var(--gold); }
.user-dropdown a,
.user-dropdown button{
  display:flex; align-items:center; gap:9px; width:100%; text-align:left; cursor:pointer;
  padding:10px 12px; border:none; background:none; border-radius:var(--radius-md);
  font-family:var(--font-body); font-size:14px; font-weight:700; color:var(--cream); text-decoration:none;
}
.user-dropdown a:hover,
.user-dropdown button:hover{ background:rgba(255,255,255,0.07); }
.user-dropdown a.is-admin{ color:var(--gold); }
/* A count of things waiting on you, pushed to the right of its label. */
.user-dropdown .menu-count{
  margin-left:auto; min-width:19px; height:19px; padding:0 6px; border-radius:999px;
  display:inline-flex; align-items:center; justify-content:center;
  background:var(--danger, #ff5a6e); color:#fff; font-size:11px; font-weight:800; line-height:1;
}
.user-dropdown .sep{ height:1px; background:var(--border); margin:6px 8px; }
.user-dropdown form{ margin:0; }

@media (max-width:520px){
  .points-pill{ padding:7px 10px; }
}

/* The caller has stopped. Not an error the player caused, so it is a warning
   rather than a failure — but it must not look like business as usual. */
.status-banner.is-stalled{
  background:rgba(255,203,61,0.14); border-color:rgba(255,203,61,0.45); color:var(--gold);
}

/* Staff shortcut on the hall.
   It was an editorial-note with three inline colour overrides, which made a
   convenience read like a warning — the same box the site uses for "not
   saved" and "something went wrong". This is a link that looks like a link:
   the whole row is the target, and it says where it goes. */
.staff-note{
  display:flex; align-items:center; gap:var(--sp-4);
  padding:var(--sp-4) var(--sp-5); margin-bottom:var(--sp-6);
  border:1px solid var(--border); border-radius:var(--radius-lg);
  background:var(--surface); text-decoration:none; color:var(--text);
  transition:background var(--dur-base) ease, border-color var(--dur-base) ease;
}
.staff-note:hover{ background:var(--surface-hover); border-color:var(--border-strong); }
.staff-note .ico{
  display:grid; place-items:center; flex:0 0 auto;
  width:38px; height:38px; border-radius:var(--radius-md); font-size:18px;
  background:rgba(255,203,61,0.12); border:1px solid rgba(255,203,61,0.3);
}
.staff-note .body{ display:flex; flex-direction:column; gap:2px; min-width:0; }
.staff-note .body b{ font-size:15px; }
.staff-note .sub{ font-size:13px; color:var(--text-muted); }
.staff-note .go{ margin-left:auto; color:var(--gold); font-weight:800; flex:0 0 auto; }
@media (max-width:520px){
  .staff-note{ padding:var(--sp-3) var(--sp-4); gap:var(--sp-3); }
  .staff-note .sub{ display:none; }
}
