:root{
  /* TrickMate: black, minimal, neon. The accent variable is still called --gold for
     the sake of the hundred rules that reference it; the value is the brand
     cyan. Board squares are cool slate so the board still reads as a board. */
  --ground:#09090B;--felt:#111114;--panel:#16161A;--edge:#2A2A31;
  --ink:#ECF6F8;--muted:#8B94A0;--gold:#22E7FF;--gold-soft:rgba(34,231,255,.13);
  --light:#CDD7DE;--dark:#3F4C58;--sel:#22E7FF;--dot:rgba(34,231,255,.55);
  --danger:#FF2E6A;--good:#39FF9E;
  --safe-b:env(safe-area-inset-bottom,0px);
}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{overscroll-behavior-y:none}
/* [hidden] is only a UA-stylesheet display:none, so any competing display
   declaration silently outranks it and the element stays on screen. */
[hidden]{display:none!important}
.signed{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:12px}
body{margin:0;background:var(--ground);color:var(--ink);
  font:16px/1.5 "Karla",ui-sans-serif,system-ui,-apple-system,sans-serif;-webkit-font-smoothing:antialiased}
.mono{font-family:"JetBrains Mono",ui-monospace,monospace}
h1,h2,h3{font-family:"Cormorant Garamond",Georgia,serif;margin:0;font-weight:600}
.wrap{max-width:1180px;margin:0 auto;padding:14px 14px calc(18px + var(--safe-b))}
a{color:var(--gold)}

header{display:flex;justify-content:space-between;align-items:center;gap:10px;margin-bottom:12px}
h1{font-size:26px;letter-spacing:.01em;line-height:1}
h1 .sub{font-family:"JetBrains Mono",monospace;font-size:9.5px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--gold);display:block;margin-top:3px}
.hdr-right{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--muted)}

button{font:600 14px "Karla",sans-serif;padding:11px 15px;border-radius:5px;border:1px solid var(--edge);
  background:var(--panel);color:var(--ink);cursor:pointer;min-height:44px}
button:hover:not(:disabled){border-color:var(--gold);color:var(--gold)}
button.primary{background:var(--gold);border-color:var(--gold);color:#04141A}
button.primary:hover:not(:disabled){filter:brightness(1.08);color:#04141A}
button:disabled{opacity:.4;cursor:default}
button.slim{min-height:38px;padding:8px 12px;font-size:13px}
.row{display:flex;gap:8px;margin-top:10px}

/* ---------- lobby ---------- */
.lobby{max-width:520px;margin:2vh auto;background:var(--panel);border:1px solid var(--edge);border-radius:8px;padding:20px}
.lobby h2{font-size:24px;margin-bottom:4px}
.lobby p{color:var(--muted);margin:0 0 14px;font-size:14.5px}
input[type=text]{flex:1;min-width:0;font:700 20px/1 "JetBrains Mono",monospace;letter-spacing:.28em;
  text-transform:uppercase;padding:12px;background:var(--felt);border:1px solid var(--edge);
  border-radius:5px;color:var(--ink);min-height:48px}
.code{font-family:"JetBrains Mono",monospace;font-size:34px;letter-spacing:.32em;color:var(--gold);text-align:center;padding:12px 0}

/* your games list */
.games{display:flex;flex-direction:column;gap:8px;margin:6px 0 4px}
.gitem{display:flex;align-items:center;gap:10px;width:100%;min-width:0;text-align:left;padding:11px 13px;
  border:1px solid var(--edge);border-radius:6px;background:var(--felt);cursor:pointer;min-height:56px}
.gitem:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.gitem .nudge{flex:0 0 auto;font:700 10px "JetBrains Mono",monospace;letter-spacing:.1em;
  text-transform:uppercase;padding:7px 11px;border-radius:4px;cursor:pointer;
  border:1px solid var(--gold);background:transparent;color:var(--gold);min-height:34px}
.gitem .nudge:hover:not(:disabled){background:var(--gold);color:var(--ground)}
.gitem .nudge:disabled{opacity:.6;cursor:default}
/* Forfeiting is destructive, so it is quiet until armed, then unmistakably red. */
.gitem .concede{flex:0 0 auto;font:700 9.5px "JetBrains Mono",monospace;letter-spacing:.1em;
  text-transform:uppercase;padding:6px 9px;border-radius:4px;cursor:pointer;
  border:1px solid var(--edge);background:transparent;color:var(--muted);min-height:32px}
.gitem .concede:hover:not(:disabled){border-color:var(--danger);color:var(--danger)}
.gitem .concede.armed{border-color:var(--danger);background:var(--danger);color:#fff}
.gitem .concede:disabled{opacity:.6;cursor:default}
.h2h-row .challenge{font:700 9.5px "JetBrains Mono",monospace;
  letter-spacing:.1em;text-transform:uppercase;padding:6px 10px;border-radius:4px;cursor:pointer;
  border:1px solid var(--gold);background:transparent;color:var(--gold);min-height:32px}
.h2h-row .challenge:hover:not(:disabled){background:var(--gold);color:var(--ground)}
.h2h-row .challenge:disabled{opacity:.6;cursor:default}
.invite-preview{color:var(--muted);font-size:13px;line-height:1.4;margin:10px 0 12px;
  padding:10px 11px;border:1px dashed var(--edge);border-radius:6px;word-break:break-word}
.gitem:hover{border-color:var(--gold)}
.gitem.turn{border-color:var(--gold);background:var(--gold-soft)}
.gitem .gc{font:700 15px "JetBrains Mono",monospace;letter-spacing:.14em;color:var(--gold);flex:0 0 auto}
.gitem .gm{flex:1;min-width:0;font-size:13px;color:var(--muted);line-height:1.3}
.gitem .gm b{color:var(--ink);font-weight:600}
.gitem .gx{flex:0 0 auto;font:700 9.5px "JetBrains Mono",monospace;letter-spacing:.1em;
  text-transform:uppercase;padding:4px 7px;border-radius:3px;border:1px solid var(--edge);color:var(--muted)}
.gitem.turn .gx{border-color:var(--gold);color:var(--gold)}
.empty{color:var(--muted);font-size:14px;padding:6px 0}

/* ---------- table ---------- */
.table{display:grid;grid-template-columns:minmax(0,1fr) 330px;gap:20px;align-items:start}
.boardwrap{background:linear-gradient(160deg,#15151B,#0D0D11);border:1px solid var(--edge);
  border-radius:10px;padding:14px;box-shadow:0 10px 30px rgba(0,0,0,.42)}

/* The frame: a dark bevel with a thin gold inlay, so the board sits IN
   something rather than floating on the page. */
.boardframe{position:relative;padding:9px;border-radius:7px;
  background:linear-gradient(150deg,#3B322A,#241E19 45%,#3B322A);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.10), 0 2px 10px rgba(0,0,0,.5)}
.boardframe::after{content:"";position:absolute;inset:6px;border-radius:3px;
  border:1px solid rgba(201,162,39,.38);pointer-events:none;z-index:4}

.board{display:grid;grid-template-columns:repeat(8,1fr);aspect-ratio:1;width:100%;
  border-radius:2px;overflow:hidden;touch-action:manipulation;position:relative;
  box-shadow:inset 0 0 22px rgba(0,0,0,.55)}
.sqr{position:relative;display:flex;align-items:center;justify-content:center;
  font-size:min(9.4vw,44px);line-height:1;cursor:pointer;user-select:none;
  transition:box-shadow .12s}
/* Two woods rather than two flat fills; the gradient gives each square a
   direction so the grid does not read as a checkerboard sticker. */
.sqr.l{background:linear-gradient(145deg,#DCE5EA,#C4D0D8)}
.sqr.d{background:linear-gradient(145deg,#4A5A67,#36434E)}
.sqr.l::before,.sqr.d::before{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(115deg,rgba(255,255,255,.10),rgba(0,0,0,.07) 55%,rgba(0,0,0,.13));
  mix-blend-mode:overlay}

/* Pieces: solid glyphs for BOTH sides, coloured and outlined, so they render
   identically everywhere instead of relying on hollow "white" glyphs. */
.pcwrap{position:relative;z-index:2;width:86%;height:86%;display:block;pointer-events:none;
  filter:drop-shadow(0 2px 2px rgba(0,0,0,.42))}
.pcwrap svg{width:100%;height:100%;display:block}
/* Same silhouette for both sides; only fill and outline differ, as on a real
   board. Explicit fill/stroke means no font can substitute or recolour them. */
.sqr .pc{stroke-width:1.6}
.sqr .pc.w{fill:#FBF6EC;stroke:#2A2018}
.sqr .pc.b{fill:#221B14;stroke:#0B0806}
.sqr .pc .cut{stroke:inherit;fill:none;stroke-width:2.2}
.sqr .pc.w .cut{stroke:#2A2018}
.sqr .pc.b .cut{stroke:#C3D2DA}
.sqr .pc .eye{fill:#FBF6EC;stroke:none}
.sqr .pc.w .eye{fill:#2A2018}

/* The last move: a faded ghost of the piece on the square it LEFT, and a ring
   on the square it ARRIVED at. The old marker tinted both squares the same
   faint colour, which said two squares were involved without saying which way
   the piece went — and read as discoloration rather than as a mark. The ghost
   stays put rather than fading on a timer: in a correspondence game you may
   not look for hours, and a marker that has gone by then is worth nothing. */
.sqr.arrived{box-shadow:inset 0 0 0 3px var(--gold)}
.sqr .ghost{position:absolute;inset:0;display:flex;align-items:center;
  justify-content:center;opacity:.22;pointer-events:none}
.sqr .ghost svg{width:86%;height:86%}
.sqr.sel{box-shadow:inset 0 0 0 3px var(--sel), inset 0 0 20px rgba(201,162,39,.30)}
.sqr.tgt::after{content:"";position:absolute;width:26%;height:26%;border-radius:50%;
  background:radial-gradient(circle,rgba(201,162,39,.95),rgba(201,162,39,.45));
  box-shadow:0 0 8px rgba(201,162,39,.5);z-index:3}
.sqr.tgt.occupied::after{width:86%;height:86%;background:transparent;
  border:3px solid rgba(201,162,39,.85);box-shadow:0 0 10px rgba(201,162,39,.4) inset}
.sqr.chk{box-shadow:inset 0 0 0 3px var(--danger), inset 0 0 22px rgba(217,83,79,.45)}
.coord{position:absolute;font:700 8px "JetBrains Mono",monospace;pointer-events:none;z-index:3}
.sqr.l .coord{color:rgba(90,70,45,.62)}
.sqr.d .coord{color:rgba(245,235,215,.55)}
.coord.f{right:3px;bottom:1px}.coord.r{left:3px;top:1px}

.status{display:flex;justify-content:space-between;align-items:center;gap:8px;margin-bottom:9px;font-size:13.5px}
.turnchip{font:700 10px "JetBrains Mono",monospace;letter-spacing:.14em;text-transform:uppercase;
  padding:5px 9px;border-radius:4px;border:1px solid var(--edge);color:var(--muted)}
.turnchip.on{border-color:var(--gold);color:var(--gold);background:var(--gold-soft)}

.side{display:flex;flex-direction:column;gap:12px;min-width:0}
.card-panel{min-width:0}
.card-panel{background:var(--panel);border:1px solid var(--edge);border-radius:8px;padding:13px}
.lab{font:700 10px "JetBrains Mono",monospace;letter-spacing:.15em;text-transform:uppercase;color:var(--muted);margin-bottom:8px}
.hand{display:flex;flex-direction:column;gap:7px}
.gcard{position:relative;display:grid;grid-template-columns:38px 1fr;gap:10px;align-items:start;
  text-align:left;padding:10px 11px 10px 10px;border-radius:8px;
  border:1px solid var(--edge);cursor:pointer;width:100%;overflow:hidden;
  background:
    radial-gradient(120% 90% at 0% 0%, rgba(255,255,255,.07), transparent 60%),
    linear-gradient(160deg,#1A1A22,#101015);
  transition:transform .12s, border-color .12s, box-shadow .12s}
/* A colour bar down the spine identifies the card at a glance in the hand. */
.gcard::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;
  background:var(--cc,var(--gold));opacity:.9}
.gcard:hover:not(:disabled){border-color:var(--gold);transform:translateY(-2px);
  box-shadow:0 6px 18px rgba(0,0,0,.42)}
.gcard.sel{border-color:var(--gold);box-shadow:0 0 0 1px var(--gold),0 6px 20px rgba(0,0,0,.5);
  background:radial-gradient(120% 90% at 0% 0%, rgba(201,162,39,.16), transparent 60%),
             linear-gradient(160deg,#1B2A31,#111A20)}
.gcard .art{width:38px;height:38px;color:var(--cc,var(--gold));opacity:.95;flex:0 0 auto}
.gcard .art svg{width:100%;height:100%;display:block}
.gcard .body{min-width:0}
.gcard .nm{font:700 13px "Karla",sans-serif;color:var(--cc,var(--ink));letter-spacing:.01em}
.gcard .tx{font-size:11.8px;color:var(--muted);margin-top:2px;line-height:1.34}
.gcard .codes{display:flex;flex-wrap:wrap;gap:3px;margin-top:6px}
.gcard .code-chip{font:700 8.5px "JetBrains Mono",monospace;letter-spacing:.06em;
  padding:2px 5px;border-radius:3px;border:1px solid var(--edge);color:var(--muted);background:rgba(0,0,0,.25)}
.gcard .count{position:absolute;top:8px;right:9px;font:700 10px "JetBrains Mono",monospace;
  color:var(--muted);background:rgba(0,0,0,.35);border:1px solid var(--edge);
  border-radius:10px;padding:1px 6px}
.gcard:disabled{opacity:.4;cursor:default}
.gcard:disabled:hover{transform:none;box-shadow:none;border-color:var(--edge)}
.prompt{background:var(--gold-soft);border:1px solid var(--gold);border-radius:5px;padding:10px 12px;font-size:13.5px}
.grave{display:flex;flex-wrap:wrap;gap:8px;line-height:1}
/* The piece sits on a LIGHT tile, the same colour as the board's light
   squares. Drawn at #221B14 on the near-black felt panel, a black piece was
   all but invisible — which is what made the graveyard hard to read. */
/* A Trick marked for the bin while choosing a mulligan. */
.gcard.binned{border-color:var(--danger)}
.binned-tag{font-size:10.5px;font-weight:700;color:var(--danger);
  text-transform:uppercase;letter-spacing:.5px;align-self:center;padding-left:6px}
.mull-hint{font-size:13.5px;line-height:1.45;color:var(--ink);margin:8px 0 4px}
.gside{margin-top:8px}
.gwho{font-size:12px;font-weight:700;color:var(--muted);margin-bottom:4px}
.gchip{display:inline-flex;flex-direction:column;align-items:center;width:54px}
.gtile{display:flex;align-items:center;justify-content:center;
  width:42px;height:42px;border-radius:8px;background:var(--light)}
.gname{font-size:10.5px;color:var(--muted);margin-top:3px;white-space:nowrap}
.gnone{font-size:12.5px;color:var(--muted);font-style:italic}
.gpick{display:inline-block;width:auto;padding:4px 6px;margin:3px 3px 0 0;
  background:var(--felt);border:1px solid var(--edge);border-radius:6px;cursor:pointer}
.gpick .gname{color:var(--ink)}
/* A piece that cannot be brought back: shown, but plainly not on offer. */
.gpick.barred{opacity:.35;cursor:not-allowed}
.log{font-family:"JetBrains Mono",monospace;font-size:11px;color:var(--muted);
  display:flex;flex-direction:column;gap:2px;max-height:130px;overflow-y:auto}
.err{color:var(--danger);font-size:13px;min-height:18px;margin-top:6px}
.result{background:var(--panel);border:2px solid var(--gold);border-radius:8px;padding:16px;text-align:center}
.result h2{font-size:28px;color:var(--gold)}

/* ---------- phone ---------- */
/* ---------- phones -------------------------------------------------------
   The board is the page on a phone. Everything here is about giving it the
   screen, keeping the one thing you need to know (whose move) in sight while
   you scroll, and not letting iOS zoom the page when you tap a field. */
@media (max-width:860px){
  .wrap{padding:10px 10px calc(14px + var(--safe-b))}
  header{margin-bottom:8px}
  h1{font-size:21px}
  .table{grid-template-columns:minmax(0,1fr);gap:12px}
  .boardwrap{padding:0;border:0;background:transparent;box-shadow:none}
  .boardframe{padding:6px;border-radius:6px}
  .boardframe::after{inset:4px}
  .sqr{font-size:min(10.5vw,46px)}

  /* The hand becomes a horizontal strip so the board keeps the screen. */
  .side{gap:10px}
  #handpanel .hand{flex-direction:row;overflow-x:auto;gap:8px;padding-bottom:4px;
    min-width:0;scroll-snap-type:x proximity;-webkit-overflow-scrolling:touch;
    /* Stops Chrome on Android turning a swipe past the last card into a
       browser back-navigation. */
    overscroll-behavior-x:contain}
  #handpanel .gcard{flex:0 0 44vw;max-width:210px;scroll-snap-align:start;min-height:74px}
  #handpanel .gcard .tx{font-size:11.5px}

  /* Secondary detail is available but never in the way. */
  details.more{background:var(--panel);border:1px solid var(--edge);border-radius:8px;padding:0}
  details.more>summary{list-style:none;cursor:pointer;padding:12px 13px;
    font:700 10px "JetBrains Mono",monospace;letter-spacing:.15em;text-transform:uppercase;color:var(--muted)}
  details.more>summary::-webkit-details-marker{display:none}
  details.more>summary::after{content:" ▾";color:var(--gold)}
  details.more[open]>summary::after{content:" ▴"}
  details.more .inner{padding:0 13px 13px}
}
@media (min-width:861px){
  details.more{background:var(--panel);border:1px solid var(--edge);border-radius:8px;padding:13px}
  details.more>summary{list-style:none;font:700 10px "JetBrains Mono",monospace;
    letter-spacing:.15em;text-transform:uppercase;color:var(--muted);margin-bottom:8px;cursor:pointer}
  details.more>summary::-webkit-details-marker{display:none}
}

/* Pending-decision sheet: always visible, above everything, safe-area aware. */
.sheet{position:fixed;left:0;right:0;bottom:0;z-index:60;background:var(--panel);
  border-top:2px solid var(--gold);box-shadow:0 -8px 28px rgba(0,0,0,.5);
  padding:12px 12px calc(12px + var(--safe-b));animation:rise .16s ease-out}
@keyframes rise{from{transform:translateY(100%)}to{transform:translateY(0)}}
@media(prefers-reduced-motion:reduce){.sheet{animation:none}}
.sheet-in{max-width:640px;margin:0 auto}
.sheet .prompt{background:transparent;border:0;padding:0 0 4px;font-size:15px}
.sheet .row{margin-top:8px}

/* ---- card effect replay ---- */
.board{position:relative}
.fx{position:absolute;pointer-events:none;z-index:5;display:flex;align-items:center;justify-content:center}
.fx .ghost{line-height:0;animation:ghost .95s ease-out forwards}
.pcmini{display:inline-block;vertical-align:middle;line-height:0}
.pcmini svg{width:100%;height:100%;display:block}
.pcmini .pc{stroke-width:1.8}
.pcmini .pc.w{fill:#FBF6EC;stroke:#2A2018}
.pcmini .pc.b{fill:#221B14;stroke:#0B0806}
.pcmini .pc .cut{fill:none;stroke-width:2.2}
.pcmini .pc.w .cut{stroke:#2A2018}
.pcmini .pc.b .cut{stroke:#C3D2DA}
.pcmini .pc .eye{stroke:none;fill:#FBF6EC}
.pcmini .pc.w .eye{fill:#2A2018}
.grave{align-items:center}
@keyframes ghost{
  0%{opacity:1;transform:scale(1) rotate(0)}
  35%{opacity:1;transform:scale(1.25) rotate(-8deg)}
  100%{opacity:0;transform:scale(.35) rotate(22deg) translateY(14px)}
}
.fx .burst{position:absolute;inset:6%;border-radius:50%;
  background:radial-gradient(circle,rgba(255,214,120,.95) 0%,rgba(240,120,30,.75) 42%,rgba(200,40,20,0) 72%);
  animation:burst .8s ease-out forwards}
@keyframes burst{0%{transform:scale(.15);opacity:0}18%{opacity:1}100%{transform:scale(1.9);opacity:0}}
.fx .ring{position:absolute;inset:2%;border-radius:50%;border:3px solid var(--gold);
  animation:ring .9s ease-out forwards}
@keyframes ring{0%{transform:scale(.2);opacity:.95}100%{transform:scale(1.7);opacity:0}}
.fx .spark{position:absolute;inset:0;animation:spark .85s ease-out forwards}
@keyframes spark{0%{opacity:0;transform:scale(.4)}20%{opacity:1}100%{opacity:0;transform:scale(1.5)}}
.sqr.shake{animation:shake .5s ease-in-out}
@keyframes shake{0%,100%{transform:translate(0)}20%{transform:translate(-2px,1px)}
  40%{transform:translate(2px,-1px)}60%{transform:translate(-1px,-1px)}80%{transform:translate(1px,1px)}}

/* the announcement banner */
.toast{position:fixed;left:50%;transform:translateX(-50%);bottom:calc(16px + var(--safe-b));
  z-index:70;max-width:min(560px,calc(100vw - 24px));background:var(--panel);
  border:2px solid var(--gold);border-radius:8px;padding:12px 15px;
  box-shadow:0 10px 34px rgba(0,0,0,.55);animation:pop .2s ease-out}
@keyframes pop{from{opacity:0;transform:translateX(-50%) translateY(12px)}to{opacity:1;transform:translateX(-50%) translateY(0)}}
.toast .tt{font:700 13px "Karla",sans-serif;color:var(--gold);display:flex;align-items:center;gap:7px}
.toast .tb{font-size:14px;margin-top:3px;line-height:1.4}
.toast .pieces{font-size:20px;letter-spacing:2px;margin-top:4px}
.toast .dismiss{margin-top:9px;width:100%}
@media(prefers-reduced-motion:reduce){
  .fx .ghost,.fx .burst,.fx .ring,.fx .spark,.sqr.shake,.toast{animation:none}
  .fx{display:none}
}

/* rankings + head-to-head */
.rank-row{display:grid;grid-template-columns:34px 1fr auto auto;gap:10px;align-items:center;
  padding:9px 11px;border:1px solid var(--edge);border-radius:6px;background:var(--felt);margin-bottom:6px}
.rank-row.me{border-color:var(--gold);background:var(--gold-soft)}
.rank-row .rk{font:700 13px "JetBrains Mono",monospace;color:var(--muted)}
.rank-row.me .rk,.rank-row.me .nm2{color:var(--gold)}
.rank-row .nm2{font-weight:600;font-size:14px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rank-row .wl{font:600 12px "JetBrains Mono",monospace;color:var(--muted);white-space:nowrap}
.rank-row .rt{font:700 14px "JetBrains Mono",monospace;color:var(--ink);white-space:nowrap}
.h2h-row{display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:10px;align-items:center;
  padding:10px 11px;border:1px solid var(--edge);border-radius:6px;background:var(--felt);margin-bottom:6px}
.h2h-row .who{font-weight:600;font-size:14px;min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.h2h-row .rec{font:700 15px "JetBrains Mono",monospace}
.h2h-row .rec .w{color:var(--good)}.h2h-row .rec .l{color:var(--danger)}.h2h-row .rec .d{color:var(--muted)}
.you-card{border:1px solid var(--gold);background:var(--gold-soft);border-radius:6px;padding:12px;margin-bottom:10px}
.you-card .big{font:700 26px "Familjen Grotesk",sans-serif;color:var(--gold);line-height:1}
.you-card .sub2{font-size:13px;color:var(--muted);margin-top:3px}

.signin{border:1px solid var(--gold);background:var(--gold-soft);border-radius:8px;padding:14px;margin-bottom:14px}
.signin input{background:var(--felt);border:1px solid var(--edge);border-radius:5px;
  padding:12px;color:var(--ink);min-height:48px}
.signin input:focus{outline:2px solid var(--gold);outline-offset:1px}

/* A move that exists only because of a Trick in force. An empowered rook's
   L-shaped hop looked identical to its ordinary moves, so nobody could tell
   what the card had bought. */
.sqr.tgt.granted::after { background: var(--gold); box-shadow: 0 0 8px var(--gold); }
.sqr.tgt.granted.occupied::after { border-color: var(--gold); box-shadow: 0 0 8px var(--gold); }

/* A card's restrictions, in words. They used to be letter chips with a hover
   title, which a phone never shows — so nobody learned what CTQ meant until a
   move was refused. */
.gcard .rule { display:block; margin-top:4px; font-size:11.5px; line-height:1.45;
               color: var(--danger); }


/* ---- the end of a game -------------------------------------------------- */
/* Fireworks for a win, a veil and a toppled King for a loss. CSS keyframes,
   so there is nothing to load and nothing to go wrong offline. */
.finale{position:fixed;inset:0;pointer-events:none;z-index:60;overflow:hidden}
.finale .spark{position:absolute;width:5px;height:5px;border-radius:50%;
  opacity:0;animation:spark 1.3s ease-out forwards}
@keyframes spark{
  0%{opacity:0;transform:translate(0,0) scale(1.3)}
  8%{opacity:1}
  55%{opacity:.85;transform:translate(var(--dx),var(--dy)) scale(1)}
  100%{opacity:0;transform:translate(var(--dx),var(--drop)) scale(.5)}
}
.finale .veil{position:absolute;inset:0;background:#05070A;opacity:0;
  animation:veil 2.6s ease-in-out forwards}
.finale .veil.draw{background:var(--edge);animation:pulse 1.5s ease-in-out forwards}
@keyframes veil{0%{opacity:0}55%{opacity:.62}100%{opacity:.45}}
@keyframes pulse{0%{opacity:0}40%{opacity:.35}100%{opacity:0}}
.finale .fallen{position:absolute;left:50%;top:34%;width:30vmin;height:30vmin;
  margin-left:-15vmin;opacity:0;animation:topple 2.6s ease-in-out forwards}
.finale .fallen svg{width:100%;height:100%}
@keyframes topple{
  0%{opacity:0;transform:rotate(0) translateY(0)}
  15%{opacity:1}
  45%{opacity:1;transform:rotate(84deg) translateY(6px)}
  80%{opacity:.9}
  100%{opacity:0;transform:rotate(90deg) translateY(46px)}
}
/* Anyone who has asked for less motion gets the result text and nothing else. */
@media (prefers-reduced-motion: reduce){
  .finale{display:none}
}


/* ---- chat --------------------------------------------------------------- */
.chatbox summary .unread { display:inline-flex; align-items:center; justify-content:center;
  min-width:19px; height:19px; padding:0 5px; margin-left:7px; border-radius:10px;
  background:var(--danger); color:#fff; font-size:11.5px; font-weight:800;
  font-variant-numeric:tabular-nums; }
.chatlist { display:flex; flex-direction:column; gap:6px; max-height:260px; overflow-y:auto;
  margin-bottom:10px; }
.chatlist .none { color:var(--muted); font-size:13.5px }
.bub { max-width:86%; border:1px solid var(--edge); border-radius:10px; padding:7px 10px; }
.bub.mine { align-self:flex-end; background:var(--gold-soft) }
.bub.theirs { align-self:flex-start; background:var(--panel) }
.bub .who { display:block; color:var(--muted); font-size:10.5px; font-weight:700;
  text-transform:uppercase; letter-spacing:.5px; margin-bottom:2px }
.bub .msg { display:block; color:var(--ink); font-size:14.5px; line-height:1.4;
  overflow-wrap:anywhere; }
.chatrow { display:flex; gap:8px; align-items:center }
.gitem .unreadmark { color:var(--gold); font-weight:800 }
.chatrow input { flex:1; min-width:0; padding:10px 11px; border:1px solid var(--edge);
  border-radius:6px; background:var(--felt); color:var(--ink);
  font:15px "Karla",sans-serif; letter-spacing:0; text-transform:none }


/* ---------- phone pass ---------------------------------------------------- */
@media (max-width:860px){
  /* 1. iOS zooms the whole page when you focus a field under 16px. The chat
     box was 15px, so tapping it shoved the board off-screen. */
  input, textarea, select { font-size:16px }
  .chatrow input { font-size:16px }

  /* 2. The board keeps the screen, but never more of it than there is. On a
     short phone, and in landscape, an aspect-ratio:1 board taller than the
     viewport pushed everything below it out of reach. */
  .boardframe { max-width:min(100%, calc(100dvh - 232px)); margin-inline:auto }

  /* 3. Whose move it is stays in sight while you scroll down to your hand.
     Without this you lose the one piece of state that decides what to do. */
  .boardwrap .status { position:sticky; top:0; z-index:30; display:flex;
    align-items:center; gap:9px; flex-wrap:wrap;
    margin:-4px -4px 8px; padding:8px 4px;
    background:var(--ground);
    background:color-mix(in srgb, var(--ground) 92%, transparent);
    backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px) }

  /* 4. The masthead is decoration; the game is not. */
  h1 { font-size:19px }
  h1 .sub { display:none }
  header { gap:8px }
  .hdr-right { font-size:11.5px; gap:6px; min-width:0 }
  #roomline { overflow:hidden; text-overflow:ellipsis; white-space:nowrap }

  /* 5. A games row used to squeeze the opponent's name to nothing to fit its
     pills. Let the pills drop to a second line instead. */
  .gitem { flex-wrap:wrap; row-gap:8px }
  /* .gm is the name-and-status column; give it the whole first line so the
     pills wrap under it rather than squeezing it to nothing. */
  .gitem .gm { flex:1 1 55%; min-width:0 }

  /* 6. Chat sized against the viewport rather than a fixed 260px, so the
     keyboard does not leave a single visible line of conversation. */
  .chatlist { max-height:min(42dvh, 320px) }
  .chatrow button { min-height:44px }

  .lobby { margin:0 auto; padding:16px }
}

/* Landscape on a phone: almost no height, so shrink the board hard and let the
   sticky status bar go, rather than leaving a board nobody can see past. */
@media (orientation:landscape) and (max-height:520px){
  .boardframe { max-width:min(100%, calc(100dvh - 96px)) }
  .boardwrap .status { position:static; backdrop-filter:none }
  h1 { font-size:17px }
}
