/* ═════════════════════════════════════════════════════════════════════════════
   THE OPENING FLOW — landing → configure → queue — and the moving star field.

   ⭐ THIS FILE AND newlobby.js ARE THE WHOLE CHANGE. app.js, style.css, tilt.css and
   tilt.js are untouched, so the board, the rail, the hand tray, the log and every other
   in-game behaviour are the same code they were. The only thing that reaches past the
   opening screens is `#cof-bg`, the star field, which is a deliberate addition.

   HOW IT WORKS. The original lobby markup stays in the DOM and stays wired to app.js; it
   is only hidden. Every control here drives the REAL control by calling `.click()` on it,
   which fires handlers regardless of visibility. One implementation of "start a game",
   and it is app.js's. Delete these two files and the old lobby is back.

   WHAT IT TAKES FROM WHERE  [user, 2026-08-25]
     · the LOOK  — from mockups/archive/2026-08-25-config-page-comp.html: the hero deck
       cards, their double chamfered frames, the faction medallions, the flat ground.
     · the FLOW  — from mockups/archive/2026-08-25-opening-flow.html: landing first, one
       question per screen, Advanced Options collapsed, one Play Now, and a queue that
       finds a human or falls back to a random AI deck.

   ⚠️ EVERY CLASS IS PREFIXED `cfg-` and every rule inside the screens is qualified with
   an id. `.deck` alone appears 19 times in style.css as a mat zone, and style.css also
   styles bare `button`, `h1`, `input` and `select` plus `.lobby h1` — a `.cfg-*` class is
   (0,1,0) and loses to `.lobby h1` (0,1,1). CLAUDE.md §6.1 #5 records what a reused class
   name costs here.
   ⚠️ EVERY TOKEN IS SCOPED, never `:root`. The client's --cyan/--panel/--edge drive the
   board; redefining them globally would restyle the game from a file that claims not to.
   ══════════════════════════════════════════════════════════════════════════ */

@property --cfg-glow { syntax:'<color>'; inherits:true; initial-value:#6fe6f1; }

/* ── the star field ─────────────────────────────────────────────────────────
   `z-index:-1` on a direct child of <body> paints ABOVE the canvas (which carries
   body's own background) and BELOW every piece of in-flow content — so it needs no
   z-index anywhere else and can never get in front of the board.
   ⚠️ Never give <body> a transform/filter/perspective: that would re-anchor this
   fixed element to it and break it (CLAUDE.md §6.1). */
#cof-bg{position:fixed; inset:0; z-index:-1; overflow:hidden; background:#05070f; pointer-events:none}
#cof-bg video{position:absolute; inset:0; width:100%; height:100%; object-fit:cover; opacity:.72}
#cof-bg::after{
  content:''; position:absolute; inset:0;
  background:
    radial-gradient(26% 14% at 95% 0%, rgba(224,85,47,.16) 0%, transparent 72%),
    radial-gradient(30% 16% at 12% 0%, rgba(24,58,96,.20) 0%, transparent 72%),
    /* ⭐ TURNED WAY DOWN [user, 2026-08-25]. This wash used to run .18 -> .55 -> .72 down
       the page and the video sat at .34 behind it, which is why the field read as a hint.
       It is now .06 -> .16 -> .22 with the video at .72. */
    linear-gradient(180deg, rgba(5,7,15,.06) 0%, rgba(5,7,15,.16) 40%, rgba(5,7,15,.22) 100%);
}
/* ⭐ THE STAR FIELD IS THE BOARD'S BACKGROUND TOO [user, 2026-08-25].
   It was already reaching the board — nothing in the table paints an opaque ground:
   `#table`, `.scene3d`, `#board3d` and `.mat-wrap` are all transparent, `.surface3d` is a
   translucent gradient and `.mat` is `rgba(10,18,34,.72)`. It was simply too faint to see:
   measured 0.009 mean frame-to-frame change inside the board area against 0.030 in the
   page margin, i.e. present and invisible.
   ⚠️ .90 IS CHOSEN, NOT ASSUMED, and it is the second time this was set by rendering
   candidates rather than by taste. Four levels were compared on a real board; .60 still
   read as texture and this is where the field reads as the room the board sits in.
   ⚠️ THE READABILITY COST WAS MEASURED, NOT WAVED THROUGH. The faintest text on these
   screens is `--dm` (#8095ab). Against the typical background it holds 6.6:1 at every
   level tested — stars cover under 1% of the frame, so the usual case does not move. The
   worst case is a bright star landing directly behind a glyph, and that goes 4.0:1 -> 3.9:1
   between the old setting and this one. Going brighter still (video 1.0, almost no wash)
   took it to 3.6:1 for very little extra, which is why this is not that. */
body.in-game #cof-bg video{opacity:.90}
body.in-game #cof-bg::after{
  background:
    radial-gradient(120% 85% at 50% 45%, rgba(5,7,15,.02) 0%, rgba(5,7,15,.16) 100%),
    linear-gradient(180deg, rgba(5,7,15,.05) 0%, rgba(5,7,15,.05) 100%);
}

#cof-bg-pause{
  position:fixed; right:.6rem; bottom:.6rem; z-index:35;
  width:1.8rem; height:1.8rem; border-radius:50%; cursor:pointer;
  display:grid; place-items:center; font-size:.6rem; line-height:1;
  color:#7d93ab; border:1px solid rgba(8,245,255,.22); background:rgba(4,8,16,.55);
  opacity:.35; transition:opacity .18s, color .18s;
}
#cof-bg-pause:hover,#cof-bg-pause:focus-visible{opacity:1; color:#dbe8f5}

/* ── the original lobby: hidden, alive ──────────────────────────────────────
   `display:none`, and that is safe precisely because `.click()` still reaches a
   display:none button. The elements keep their handlers, their state and their IDs.

   ⭐⭐ KEYED ON `html.cof-skin`, NOT ON A BODY CLASS SET BY newlobby.js — THAT IS THE
   WHOLE POINT. These rules used to wait for the skin to mount, and the skin waits for
   app.js's `/api/starters` round trip, so the ORIGINAL lobby painted and sat there for
   about half a second on every load: measured visible from t=104ms to t=652ms, with the
   skin arriving at t=717ms. `cof-skin` is set by a three-line inline script in
   index.html's <head>, which runs before the body is parsed — and this stylesheet is a
   <link> in <head> too, so it is applied before first paint. The old lobby never renders.
   ⚠️ That inline script also arms a failsafe which REMOVES the class if the skin never
   mounts, so a broken newlobby.js still leaves a usable page rather than a blank one. */
/*
 * ⚠️ THIS LIST LEAKS BY DEFAULT, AND IT HAS. [reported 2026-09-03]
 * `.spectate-cta` was added to #lobby when spectator mode landed and nobody added it here, so the
 * old "Spectate a game" button rendered in the top-left corner of the configure screen for weeks —
 * beside, and then redundant with, the new gold pill. A NEW CHILD OF #lobby IS VISIBLE UNLESS
 * SOMEONE REMEMBERS THIS BLOCK, which is the wrong default and is why the leak went unnoticed.
 * `tools/check-lobby-leak.ts` now fails on any unexpected visible child, so the next one is caught
 * by a test rather than by a person noticing a stray button.
 *
 * ⚠️ display:none, NEVER removed: `#cfg-spectate` delegates its click to `#btn-spectate`, which is
 * inside `.spectate-cta`. A `.click()` still reaches a display:none button — that is the whole
 * mechanism this skin is built on — but a REMOVED one takes the feature with it.
 */
html.cof-skin #lobby > .activity,
html.cof-skin #lobby > .spectate-cta,
html.cof-skin #lobby > h1,
html.cof-skin #lobby > .sub,
html.cof-skin #lobby > .lobby-actions,
html.cof-skin #lobby > .note{display:none !important}
html.cof-skin #waitboard{display:none}
/* The queue is skinned onto `#waiting` for the same reason the configure screen is
   skinned onto `#lobby`: app.js already owns when each is shown. Its original children
   are hidden, not removed — `#big-code` and `#btn-back` are still driven from here. */
html.cof-skin #waiting > h1,
html.cof-skin #waiting > .sub,
html.cof-skin #waiting > .bigcode,
html.cof-skin #waiting > .waiting,
html.cof-skin #waiting > .activity,
html.cof-skin #waiting > .startrow{display:none !important}
html.cof-skin #waiting{max-width:none; margin:0; padding:0; text-align:left}

/* ⚠️ `.lobby` IS A 640px CENTRED COLUMN with `text-align:center` and 1.5rem of padding.
   Left in place it squeezed the layout into a third of the width and wrapped every label.
   Released only while the skin is mounted. */
html.cof-skin #lobby{max-width:none; margin:0; padding:0 clamp(1rem,2.3vw,2rem) 3rem;
  text-align:left}

/* The client's own top bar draws the SAME wordmark these screens do, so both showed at
   once. Hidden on the opening screens only; it is already absent in a game, so this is a
   no-op there and cannot reach the board. The build stamp is unaffected — app.js writes
   it into `#topmeta` as well, which is the ⓘ pin. */
html.cof-skin body:not(.in-game) .topbar{display:none}

/* ⭐⭐ THE OPENING SCREENS MUST BE ABLE TO SCROLL, AND BY DEFAULT THEY COULD NOT.
   `tilt.css` sets `body.tilt3d{overflow:hidden}` — correct for the board, which must
   never scroll — and tilt.js adds `tilt3d` ON LOAD at desktop widths, lobby included.
   When <html> is `overflow:visible` the viewport takes its overflow from BODY, so that
   one rule silently disabled wheel and touch scrolling everywhere, while `scrollTo()`
   still worked and `scrollHeight > clientHeight` still reported true — which is why the
   "▾ MORE BELOW" cue appeared, bouncing, over a page that would not move.
   ⚠️ A LATENT BUG THIS DESIGN ONLY EXPOSED: the old lobby fitted one screen on a
   desktop, so nothing ever ran past the fold to reveal it.
   Scoped to the opening screens — `.in-game` mirrors app.js's own `#lobby.hidden`, so
   the board keeps `overflow:hidden` exactly as before. */
html.cof-skin body.tilt3d:not(.in-game){overflow:auto}

/* ══════════════════════════════════════════════════════════ the screens ═══
   Landing → configure → queue. All three live inside #lobby, so all three inherit
   app.js's own hide when a seat is taken — there is no "close it when the game
   starts" code to forget. The same structural trick the changelog panel relies on. */
#cof-landing,#cof-cfg,#cof-queue{
  display:none;
  --cy:#6fe6f1; --cy-dim:#3ba9c4; --gd:#f5c451;
  --ed:rgba(111,230,241,.18); --ed2:rgba(140,170,200,.14);
  --tx:#dbe8f5; --dm:#8095ab; --vi:#a855f7; --em:#e0552f;
  /* The comp's four faction colours. Two match the site-wide theme module; Church of
     Zero and Astrixids do not, because cyan is reserved for selection here and a
     faction that IS cyan would look permanently pre-selected. */
  --f-spawn:#c041e4; --f-nova7:#e7ca04; --f-zero:#7d46a4; --f-astrixids:#64d341;
  font-family:'Azeret Mono',ui-monospace,monospace; color:var(--tx);
}
#cof-landing *,#cof-cfg *,#cof-queue *{box-sizing:border-box}
#cof-cfg.on{display:block}
/* The queue's visibility belongs to app.js — it lives inside `#waiting`, which app.js
   shows and hides — so it is permanently `.on` and simply inherits that. */
#cof-queue.on{display:flex}
#cof-landing.on,#cof-queue.on{
  display:flex; flex-direction:column;
  /* `safe` centring: a plain `center` pushes overflow out of BOTH ends and the top of a
     scroll container cannot be reached, so a tall screen loses its own header. */
  align-items:safe center; justify-content:safe center;
  /* Leave room for `.lobby-foot` (Update History) so the landing is not one button
     taller than the viewport for no reason. It still scrolls if it needs to — that is
     what the body.tilt3d override above is for. */
  min-height:calc(100dvh - 8rem); padding:1.5rem 1rem; text-align:center;
}

/* Reset the client's global element rules inside these screens only. style.css gives
   every bare <button> Orbitron, 700 weight, .8rem/1.5rem padding and a border; <h1>,
   <input> and <select> are styled too. Every rule below is id-qualified, so it outranks
   this reset. ⚠️ `text-align:center`, NOT `inherit` — a button centres its label by
   default, and inheriting picks up the screen's `text-align:left`. */
#cof-landing button,#cof-cfg button,#cof-queue button{
  font:inherit; font-weight:inherit; letter-spacing:inherit; padding:0; border:0;
  border-radius:0; background:none; color:inherit; transition:none; text-align:center}
#cof-landing button:hover,#cof-cfg button:hover,#cof-queue button:hover{background:none; box-shadow:none}
#cof-landing button:active,#cof-cfg button:active,#cof-queue button:active{transform:none}
#cof-landing h1,#cof-cfg h1,#cof-cfg h2,#cof-queue h2,
#cof-landing p,#cof-cfg p,#cof-queue p{margin:0; text-shadow:none}
#cof-cfg input,#cof-cfg select{font:inherit}

/* ── the big button, shared by the landing and the bottom of the configure screen ──
   TWO animations at DIFFERENT periods on ONE element: an 18s walk through the five
   faction colours and a 2.6s breath, both reading the same registered custom property.
   One keyframe set would force a single period and turn the pulse into a slow throb. */
#cof-landing .cfg-big,#cof-cfg .cfg-big{
  position:relative; cursor:pointer; display:block; padding:0; border:0; background:none;
  font:inherit; animation:cfg-hue 18s linear infinite; -webkit-tap-highlight-color:transparent}
#cof-landing .cfg-face,#cof-cfg .cfg-face{
  display:block; padding:clamp(.9rem,2.2vw,1.15rem) clamp(2.4rem,8vw,4rem);
  font-family:Orbitron,sans-serif; font-weight:900; text-align:center;
  font-size:clamp(1rem,2.6vw,1.35rem); letter-spacing:.24em; text-indent:.24em;
  text-transform:uppercase;
  color:#fff; border-radius:999px; border:2px solid var(--cfg-glow);
  background:linear-gradient(180deg,color-mix(in srgb,var(--cfg-glow) 22%,transparent),rgba(4,8,16,.72));
  text-shadow:0 0 16px color-mix(in srgb,var(--cfg-glow) 80%,transparent);
  animation:cfg-pulse 2.6s ease-in-out infinite; transition:transform .12s ease}
#cof-landing .cfg-big:hover .cfg-face,#cof-cfg .cfg-big:hover .cfg-face{transform:scale(1.02)}
#cof-landing .cfg-big:focus-visible .cfg-face,#cof-cfg .cfg-big:focus-visible .cfg-face{
  outline:3px solid #fff; outline-offset:5px}
#cof-cfg .cfg-big[disabled]{cursor:not-allowed; animation:none}
#cof-cfg .cfg-big[disabled] .cfg-face{animation:none; color:#6b7c90; border-color:#33465c;
  background:rgba(8,14,24,.6); box-shadow:none; text-shadow:none}
@keyframes cfg-hue{
  0%{--cfg-glow:#12d6df} 20%{--cfg-glow:#e7ca04} 40%{--cfg-glow:#c041e4}
  60%{--cfg-glow:#2fb383} 80%{--cfg-glow:#4154e4} 100%{--cfg-glow:#12d6df}}
@keyframes cfg-pulse{
  0%,100%{box-shadow:0 0 18px color-mix(in srgb,var(--cfg-glow) 45%,transparent),
                     0 0 52px color-mix(in srgb,var(--cfg-glow) 24%,transparent)}
  50%    {box-shadow:0 0 34px color-mix(in srgb,var(--cfg-glow) 78%,transparent),
                     0 0 104px color-mix(in srgb,var(--cfg-glow) 48%,transparent)}}

/* ── 1. landing ─────────────────────────────────────────────────────────── */
#cof-landing .cfg-logo{width:min(58vw,520px); height:auto; display:block;
  filter:drop-shadow(0 0 34px rgba(8,245,255,.20)) drop-shadow(0 6px 26px rgba(0,0,0,.75));
  animation:cfg-in 1.1s cubic-bezier(.2,.7,.2,1) both}
#cof-landing .cfg-tag{font-family:Orbitron,sans-serif; letter-spacing:.34em;
  text-transform:uppercase; font-size:clamp(.6rem,1.6vw,.78rem); color:var(--dm);
  margin:.2rem 0 clamp(1.6rem,5vh,2.8rem);
  animation:cfg-in 1.1s .25s cubic-bezier(.2,.7,.2,1) both}
@keyframes cfg-in{from{opacity:0; transform:scale(.94)} to{opacity:1; transform:none}}
#cof-landing .cfg-foot2{margin-top:clamp(1.4rem,5vh,2.4rem); color:var(--dm);
  font-size:.72rem; letter-spacing:.16em; text-transform:uppercase;
  display:flex; gap:1.4rem; flex-wrap:wrap; justify-content:center}
#cof-landing .cfg-foot2 b{color:var(--tx); font-weight:600}

/* ── 2. configure ───────────────────────────────────────────────────────────
   ONE COLUMN, top to bottom, in the order the flow asks for:
     sign in · [your cof.gg decks, only when signed in] · the four starters ·
     custom deck · Advanced Options (collapsed) · one Play Now.
   The comp put Match Setup in a right-hand rail; there is no rail in this flow. */
#cof-cfg .cfg-wrap{max-width:940px; margin:0 auto}

#cof-cfg .cfg-top{display:flex; align-items:center; justify-content:space-between;
  gap:1rem; padding:.95rem 0 .9rem; flex-wrap:wrap}
#cof-cfg .cfg-mark{font-family:Orbitron,sans-serif; font-weight:700; color:#fff;
  white-space:nowrap; font-size:clamp(.85rem,1.55vw,1.2rem); letter-spacing:.13em}
#cof-cfg .cfg-mark i{font-style:normal; color:var(--cy)}
#cof-cfg .cfg-right{display:flex; align-items:center; gap:clamp(.6rem,1.6vw,1.1rem);
  font-size:.72rem; letter-spacing:.14em; text-transform:uppercase; color:var(--dm)}
#cof-cfg .cfg-on{display:inline-flex; align-items:center; gap:.5rem; color:var(--tx)}
#cof-cfg .cfg-on::before{content:''; width:.5rem; height:.5rem; border-radius:50%;
  background:var(--cy); box-shadow:0 0 8px var(--cy)}
#cof-cfg .cfg-rule{height:2.5px; margin-bottom:clamp(1.2rem,4vh,2.2rem);
  background:linear-gradient(90deg,var(--cy) 0%,rgba(111,230,241,.45) 42%,
             rgba(224,85,47,.55) 78%,var(--em) 100%);
  clip-path:polygon(0 0,calc(100% - 46px) 0,100% 100%,0 100%); opacity:.85}

/* sign in — the first thing on the screen */
#cof-cfg .cfg-signin{display:inline-flex; align-items:center; gap:.6rem; cursor:pointer;
  font-size:.74rem; letter-spacing:.1em; padding:.5rem 1rem; border-radius:999px;
  color:var(--tx); border:1px solid var(--ed); background:rgba(6,12,22,.72);
  transition:border-color .15s, box-shadow .15s}
#cof-cfg .cfg-signin:hover{border-color:var(--cy); box-shadow:0 0 18px rgba(111,230,241,.25)}
#cof-cfg .cfg-signin .cfg-dot{width:.5rem; height:.5rem; border-radius:50%; background:var(--dm)}
body.cof-signedin #cof-cfg .cfg-signin .cfg-dot{background:#4ee38a; box-shadow:0 0 10px #4ee38a}

/* ⚠️ THE `flex-direction: column` THAT USED TO BE HERE IS WHAT STACKED THE PROVIDER BUTTONS on a
   phone. The layout now lives in the PROVIDER BUTTONS block at the end of this file; only the
   plate they sit on is described here, so there is one place that decides the arrangement. */
#cof-cfg .cfg-providers{margin-top:.5rem;
  padding:.6rem; border-radius:8px; border:1px solid var(--ed); background:rgba(6,12,22,.92)}
#cof-cfg .cfg-h1{font-family:Orbitron,sans-serif; font-weight:900; color:#fff;
  font-size:clamp(1.55rem,2.7vw,2.4rem); letter-spacing:.041em; line-height:1.06;
  text-transform:uppercase; text-shadow:0 3px 10px rgba(0,0,0,.6);
  /* It is the only thing between the rule and the decks now, so it owns the gap the
     removed subheading used to provide. */
  margin:0 0 clamp(1.4rem,3.5vh,2.1rem)}
#cof-cfg .cfg-seclabel{display:flex; align-items:center; gap:.85rem; margin:0 0 1rem;
  font-weight:600; font-size:.74rem; letter-spacing:.24em; text-transform:uppercase;
  color:var(--cy)}
#cof-cfg .cfg-seclabel::after{content:''; flex:1; height:1px; background:var(--ed2)}

/* the player's own cof.gg decks — a dropdown, ABOVE the starters, only when signed in */
/*
 * ⭐ THE REJOIN OFFER. [R-REJOIN, 2026-08-29 · narrowed and given a second action R-REJOIN-3]
 *
 * ⚠️ DELIBERATELY NARROWER THAN EVERYTHING ELSE ON THIS SCREEN, and centred. Full-width made it
 * read as another section of the form — one more thing to work through on the way to the decks —
 * when it is an interruption: a short question with two answers. Sizing it away from the page
 * rhythm is what makes it read as a notice rather than as furniture.
 */
#cof-cfg .cfg-rejoin{
  /* 33rem, not 30: measured, the two buttons need 436px + the gap and a 30rem banner gave the
     row 441px — six pixels short, so it wrapped and stacked concede above rejoin. Still about
     half the panel's width, which is the point of narrowing it. */
  max-width:33rem; margin:0 auto 1.6rem; padding:1rem 1.15rem; border-radius:.6rem;
  border:1px solid var(--gd,#f5c451); background:rgba(245,196,81,.08);
  box-shadow:0 0 22px rgba(245,196,81,.14); text-align:center}
#cof-cfg .cfg-rejoin[hidden]{display:none}
#cof-cfg .cfg-rejoin-lead{margin:0 0 .9rem; color:var(--tx); font-size:.9rem; line-height:1.45}

/* Concede left, rejoin right. Wraps on a narrow phone rather than squeezing both. */
#cof-cfg .cfg-rejoin-row{
  display:flex; gap:.6rem; align-items:stretch; justify-content:center; flex-wrap:wrap}
#cof-cfg .cfg-rejoin-row .cfg-big{width:auto; animation:none; flex:0 1 auto}
#cof-cfg .cfg-rejoin .cfg-big[hidden]{display:none}

/*
 * The primary. Pinned GOLD rather than riding the shared `cfg-hue` cycle: this banner is gold,
 * and a control that changes colour on its own cannot show a colour CHANGE on hover.
 */
#cof-cfg .cfg-rejoin .cfg-face{
  --cfg-glow:#f5c451; animation:none;
  /* Sized so BOTH buttons fit one row inside the narrowed banner - they are meant to sit side
     by side, and at the first attempt they wrapped and stacked concede ABOVE rejoin. */
  padding:.7rem 1.1rem; font-size:clamp(.72rem,1.7vw,.85rem); letter-spacing:.16em;
  text-indent:.16em; white-space:nowrap;
  transition:background .14s ease, color .14s ease, border-color .14s ease,
             box-shadow .14s ease, transform .12s ease}
/* Hover GLOWS AROUND THE EDGES, as asked — the ring grows and brightens rather than the fill
   inverting, so the button still reads as gold-on-dark at every moment. */
#cof-cfg .cfg-rejoin .cfg-big:hover .cfg-face,
#cof-cfg .cfg-rejoin .cfg-big:focus-visible .cfg-face{
  border-color:#ffe9a8;
  background:linear-gradient(180deg,rgba(245,196,81,.34),rgba(4,8,16,.72));
  box-shadow:0 0 10px rgba(245,196,81,.85), 0 0 26px rgba(245,196,81,.55),
             0 0 48px rgba(245,196,81,.28);
  transform:scale(1.02)}
#cof-cfg .cfg-rejoin .cfg-big:active .cfg-face{transform:scale(.99)}
#cof-cfg .cfg-rejoin .cfg-big[disabled] .cfg-face{
  background:rgba(8,14,24,.6); color:#6b7c90; border-color:#33465c; box-shadow:none}

/*
 * ⭐ THE QUIET ONE. [R-REJOIN-3] Concede ends the match for good, so it is drawn to be found
 * rather than noticed: no fill, a grey hairline border, dimmed text, and no glow at any point.
 * It must never compete with the button beside it — a mis-click here costs a whole game.
 */
#cof-cfg .cfg-quiet{
  cursor:pointer; display:block; padding:0; border:0; background:none; font:inherit;
  -webkit-tap-highlight-color:transparent}
#cof-cfg .cfg-quiet-face{
  display:block; padding:.7rem 1rem; border-radius:999px; white-space:nowrap;
  font-family:Orbitron,sans-serif; font-weight:700; text-transform:uppercase;
  font-size:clamp(.7rem,1.6vw,.82rem); letter-spacing:.16em; text-indent:.16em;
  color:#7f8fa3; border:1px solid #3a4a5e; background:rgba(255,255,255,.02);
  transition:color .14s ease, border-color .14s ease, background .14s ease}
/* Hover brings it only as far as legible — still quieter than the primary's resting state. */
#cof-cfg .cfg-quiet:hover .cfg-quiet-face,
#cof-cfg .cfg-quiet:focus-visible .cfg-quiet-face{
  color:#c3d0de; border-color:#5b6f86; background:rgba(255,255,255,.05)}
/* Armed = the second press ends the game. The ONLY moment it is allowed to look dangerous. */
#cof-cfg .cfg-quiet.armed .cfg-quiet-face{
  color:#ffb4b4; border-color:#8c3b3b; background:rgba(140,59,59,.16)}
#cof-cfg .cfg-quiet[disabled]{cursor:default}
#cof-cfg .cfg-quiet[disabled] .cfg-quiet-face{color:#5c6a7a; border-color:#2c3947}

#cof-cfg .cfg-acct{display:none; margin-bottom:1.5rem}
/*
 * ⭐ SHOWN WHENEVER THE PLAYER IS SIGNED IN, not only when decks came back. [user request
 * 2026-08-27] `cof-signedin` is set by the DECK COUNT, so an account with no decks used to
 * fall through and show nothing at all — no picker, and not the signed-OUT note either, since
 * that hides the moment you sign in. The block appears either way now; syncAccount() swaps the
 * empty <select> for the message below.
 */
body.cof-signedin #cof-cfg .cfg-acct,
body.cof-authed   #cof-cfg .cfg-acct{display:block}
/*
 * ⚠️ MATCH THE SPECIFICITY THE PICKER USES. `.cfg-acct select` is (1,1,1) via `#cof-cfg`; a bare
 * `.cfg-nodecks` rule would be outranked by anything similar that arrives later. Same convention
 * as `.cfg-ggnote` below, and for the same reason recorded there.
 */
#cof-cfg .cfg-nodecks{margin:0; padding:.8rem .9rem; border:1px dashed var(--ed2);
  border-radius:.5rem; color:var(--dim,#93a7bd); font-size:.9rem; line-height:1.5}
#cof-cfg .cfg-nodecks[hidden]{display:none}
#cof-cfg .cfg-nodecks a{color:var(--cy,#08F5FF); text-decoration:underline}
#cof-cfg .cfg-nodecks a:hover{text-decoration:none}
/*
 * The stale-link notice. Warmer than `.cfg-nodecks` on purpose: that one is a neutral "nothing
 * here yet", this one is "your decks exist and we cannot reach them", which is an action, not a
 * state. Same `#cof-cfg` id scoping as everything above, for the reason recorded there.
 */
#cof-cfg .cfg-stalelink{margin:0; padding:.8rem .9rem; border:1px solid var(--warn,#f0b429);
  border-radius:.5rem; color:var(--tx,#e6eef8); font-size:.9rem; line-height:1.5}
#cof-cfg .cfg-stalelink[hidden]{display:none}
#cof-cfg .cfg-reconnect{display:block; margin:.6rem 0 0; padding:.5rem .9rem; cursor:pointer;
  border:1px solid var(--cy,#08F5FF); border-radius:.4rem; background:transparent;
  color:var(--cy,#08F5FF); font:inherit; font-size:.85rem}
#cof-cfg .cfg-reconnect:hover{background:rgba(8,245,255,.12)}
/* `hidden` on a <select> is not honoured by every engine on its own — pin it. */
#cof-cfg .cfg-acct select[hidden]{display:none}
#cof-cfg .cfg-acct select{width:100%; color:var(--tx); cursor:pointer; padding:.8rem .9rem;
  border-radius:7px; border:1px solid var(--ed); background:rgba(4,8,16,.92)}
#cof-cfg .cfg-acct select:focus-visible{outline:2px solid var(--cy); outline-offset:2px}
#cof-cfg .cfg-orline{display:flex; align-items:center; gap:.8rem; margin:1rem 0 0;
  color:var(--dm); font-size:.66rem; letter-spacing:.2em; text-transform:uppercase}
#cof-cfg .cfg-orline::before,#cof-cfg .cfg-orline::after{content:''; flex:1; height:1px;
  background:var(--ed2)}

/* ── the four hero cards — kept exactly as the comp draws them ──────────── */
#cof-cfg .cfg-decks{display:grid; grid-template-columns:repeat(4,1fr); gap:23px}
#cof-cfg .cfg-cardwrap{position:relative; transition:filter .2s ease}
#cof-cfg .cfg-cardwrap:hover{filter:drop-shadow(0 0 12px color-mix(in srgb,var(--fa) 40%,transparent))}
#cof-cfg .cfg-cardwrap.on{filter:drop-shadow(0 0 10px rgba(111,230,241,.75))
                                 drop-shadow(0 0 28px rgba(111,230,241,.35))}
#cof-cfg .cfg-card{
  --fa:var(--cy);
  position:relative; display:block; width:100%; aspect-ratio:203/333;
  padding:0; cursor:pointer; overflow:hidden; border:0; background:#080b14;
  color:inherit; -webkit-tap-highlight-color:transparent;
  clip-path:polygon(10px 0,calc(100% - 10px) 0,100% 10px,100% calc(100% - 10px),
                    calc(100% - 10px) 100%,10px 100%,0 calc(100% - 10px),0 10px)}
/* Shorter on a wide screen: this flow puts Advanced Options and a Play Now below the
   cards, where the comp had a rail beside them, so the column has to fit a screen. */
@media (min-width:1040px){ #cof-cfg .cfg-card{aspect-ratio:203/286} }
#cof-cfg .cfg-art{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  clip-path:inset(6px round 2px);
  -webkit-mask-image:radial-gradient(118% 96% at 50% 42%,#000 55%,rgba(0,0,0,.72) 100%);
          mask-image:radial-gradient(118% 96% at 50% 42%,#000 55%,rgba(0,0,0,.72) 100%);
  filter:saturate(.92) brightness(.68); transition:filter .25s ease, transform .5s ease}
#cof-cfg .cfg-card:hover .cfg-art{filter:saturate(1) brightness(.84); transform:scale(1.03)}
#cof-cfg .cfg-card.on .cfg-art{filter:saturate(1) brightness(.9)}
/* Two concentric chamfered outlines — the card's whole character, and the thing a single
   border misses. Both need their own clip-path: clipping the parent does not chamfer a
   child's border. */
#cof-cfg .cfg-card::after{content:''; position:absolute; inset:0; pointer-events:none;
  z-index:4; border:2px solid var(--fa); transition:border-color .2s ease;
  clip-path:polygon(10px 0,calc(100% - 10px) 0,100% 10px,100% calc(100% - 10px),
                    calc(100% - 10px) 100%,10px 100%,0 calc(100% - 10px),0 10px)}
#cof-cfg .cfg-card::before{content:''; position:absolute; inset:5px; pointer-events:none;
  z-index:4; border:1px solid color-mix(in srgb,var(--fa) 42%,transparent);
  transition:border-color .2s ease;
  clip-path:polygon(8px 0,calc(100% - 8px) 0,100% 8px,100% calc(100% - 8px),
                    calc(100% - 8px) 100%,8px 100%,0 calc(100% - 8px),0 8px)}
#cof-cfg .cfg-card.on::after{border-color:var(--cy)}
#cof-cfg .cfg-card.on::before{border-color:color-mix(in srgb,var(--cy) 50%,transparent)}
#cof-cfg .cfg-card:focus-visible{outline:2px solid #fff; outline-offset:3px}
#cof-cfg .cfg-plate{position:absolute; left:6px; right:6px; bottom:6px; z-index:2;
  text-align:center; padding:2.2rem .3rem .9rem; pointer-events:none;
  background:linear-gradient(180deg,transparent 0%,rgba(3,6,12,.55) 28%,
             rgba(3,6,12,.90) 58%,rgba(3,6,12,.99) 100%)}
#cof-cfg .cfg-nm{display:block; font-family:Orbitron,sans-serif; font-weight:400;
  color:#fff; font-size:clamp(.6rem,.92vw,.82rem); letter-spacing:.045em; line-height:1.3;
  text-transform:uppercase}
#cof-cfg .cfg-state{display:block; margin-top:.3rem; font-family:Orbitron,sans-serif;
  font-size:clamp(.55rem,.9vw,.72rem); letter-spacing:.2em; text-transform:uppercase;
  color:var(--cy); opacity:0; transition:opacity .18s ease}
#cof-cfg .cfg-card.on .cfg-state{opacity:1}
/* The medallion artwork is ALREADY a white disc with the emblem knocked out of it — it
   needs no plate and no ring behind it. ⚠️ And no percentage padding on this box: it is
   position:absolute, so a percentage resolves against the CARD's width, not its own. */
#cof-cfg .cfg-emblem{position:absolute; left:16px; top:17px; z-index:5; width:28%;
  aspect-ratio:1; display:grid; place-items:center}
#cof-cfg .cfg-emblem img{width:74%; height:74%; object-fit:contain;
  filter:drop-shadow(0 2px 6px rgba(0,0,0,.65))}
#cof-cfg .cfg-tick{position:absolute; right:13px; top:15px; z-index:5; width:29px;
  aspect-ratio:1; display:grid; place-items:center; color:#fff; font-size:.82rem;
  font-weight:700; background:var(--cy); opacity:0; transform:scale(.6);
  transition:opacity .18s ease, transform .18s ease;
  clip-path:polygon(30% 0,70% 0,100% 30%,100% 70%,70% 100%,30% 100%,0 70%,0 30%)}
#cof-cfg .cfg-card.on .cfg-tick{opacity:1; transform:none}

/* ⭐ The custom-deck paste row used to sit here. It is gone: a custom deck is reached by
   signing in and choosing from your own cof.gg decks, which is the `.cfg-acct` dropdown
   above the starters. [user, 2026-08-25] */

/* ── advanced options, collapsed ─────────────────────────────────────────── */
#cof-cfg .cfg-adv{border:1px solid var(--ed); border-radius:9px;
  background:rgba(6,12,22,.6); margin-top:1.3rem}
#cof-cfg .cfg-adv > summary{cursor:pointer; list-style:none; padding:.85rem 1.1rem;
  font-weight:600; font-size:.74rem; letter-spacing:.18em; text-transform:uppercase;
  color:var(--dm); display:flex; align-items:center; gap:.6rem}
#cof-cfg .cfg-adv > summary::-webkit-details-marker{display:none}
#cof-cfg .cfg-adv > summary::before{content:'▸'; display:inline-block;
  transition:transform .2s ease}
#cof-cfg .cfg-adv[open] > summary::before{transform:rotate(90deg)}
#cof-cfg .cfg-adv > summary:hover{color:var(--tx)}
#cof-cfg .cfg-advbody{padding:.2rem 1.1rem 1.1rem; display:flex; flex-direction:column;
  gap:.9rem}
#cof-cfg .cfg-advrow{display:flex; align-items:center; gap:.8rem; flex-wrap:wrap}
#cof-cfg .cfg-advrow label{color:var(--tx); font-size:.82rem}
#cof-cfg .cfg-advrow input[type=checkbox]{width:1.1rem; height:1.1rem; accent-color:var(--cy);
  cursor:pointer}
#cof-cfg .cfg-advrow select,#cof-cfg .cfg-code{color:var(--tx); padding:.45rem .6rem;
  border-radius:6px; border:1px solid var(--ed2); background:rgba(4,8,16,.92)}
#cof-cfg .cfg-code{letter-spacing:.2em; text-transform:uppercase; width:7rem}
#cof-cfg .cfg-note{color:var(--dm); font-size:.72rem; line-height:1.5; margin:0}
#cof-cfg .cfg-advsep{height:1px; background:var(--ed2)}
#cof-cfg .cfg-advhead{font-weight:600; font-size:.66rem; letter-spacing:.2em;
  text-transform:uppercase; color:var(--dm); margin:0}
#cof-cfg .cfg-ghost{font-size:.78rem; cursor:pointer; color:var(--tx); padding:.45rem .9rem;
  border-radius:6px; border:1px solid var(--ed2); background:rgba(4,8,16,.7)}
#cof-cfg .cfg-ghost:hover{border-color:var(--cy)}

/* ── one Play Now, at the bottom ─────────────────────────────────────────── */
#cof-cfg .cfg-startrow{display:flex; flex-direction:column; align-items:center; gap:.7rem;
  margin-top:1.6rem}
#cof-cfg .cfg-why{color:var(--dm); font-size:.76rem; min-height:1.2em; text-align:center}
#cof-cfg .cfg-msg{color:var(--dm); font-size:.74rem; text-align:center; min-height:1.2em}
#cof-cfg .cfg-msg.err{color:#ff8a8a}
#cof-cfg .cfg-foot{text-align:center; color:var(--dm); margin-top:1.4rem; font-size:.72rem;
  letter-spacing:.16em; text-transform:uppercase}
#cof-cfg .cfg-foot b{color:var(--tx); margin-right:.4rem}

/* ── 3. queue ───────────────────────────────────────────────────────────── */
#cof-queue .cfg-ring{position:relative; width:min(58vw,230px); aspect-ratio:1}
#cof-queue .cfg-ring svg{width:100%; height:100%; transform:rotate(-90deg); overflow:visible}
#cof-queue .cfg-track{fill:none; stroke:rgba(125,147,171,.18); stroke-width:3}
#cof-queue .cfg-bar{fill:none; stroke:var(--cy); stroke-width:3; stroke-linecap:round;
  filter:drop-shadow(0 0 8px var(--cy)); transition:stroke-dashoffset .95s linear}
#cof-queue .cfg-mid{position:absolute; inset:0; display:grid; place-content:center; gap:.2rem}
#cof-queue .cfg-cd{font-family:Orbitron,sans-serif; font-weight:700; color:#fff;
  font-size:clamp(1.8rem,7vw,2.8rem); font-variant-numeric:tabular-nums}
#cof-queue .cfg-cdl{font-size:.6rem; letter-spacing:.24em; text-transform:uppercase;
  color:var(--dm)}
#cof-queue h2{font-family:Orbitron,sans-serif; font-size:clamp(1rem,3.4vw,1.35rem);
  color:#fff; margin:1.4rem 0 .6rem; letter-spacing:.08em}
#cof-queue .cfg-qsub{color:var(--dm); font-size:.84rem; margin:0 0 1.2rem; max-width:38ch}
#cof-queue .cfg-qsub b{color:var(--tx); font-weight:600}
#cof-queue .cfg-found{color:#4ee38a; text-shadow:0 0 16px rgba(78,227,138,.6)}
#cof-queue .cfg-aiw{color:#f5c451; text-shadow:0 0 16px rgba(245,196,81,.5)}
#cof-queue .cfg-dots{display:inline-flex; gap:.3rem; margin-left:.35rem; vertical-align:middle}
#cof-queue .cfg-dots i{width:.32rem; height:.32rem; border-radius:50%; background:var(--dm);
  animation:cfg-dot 1.4s ease-in-out infinite}
#cof-queue .cfg-dots i:nth-child(2){animation-delay:.18s}
#cof-queue .cfg-dots i:nth-child(3){animation-delay:.36s}
@keyframes cfg-dot{0%,100%{opacity:.25} 50%{opacity:1; background:#6fe6f1}}
#cof-queue .cfg-cancel{font-size:.78rem; cursor:pointer; color:var(--tx); padding:.5rem 1.1rem;
  border-radius:6px; border:1px solid var(--ed); background:rgba(4,8,16,.7)}
#cof-queue .cfg-cancel:hover{border-color:var(--cy)}

/* ══════════════════════════════════════════════════════════════ mobile ═══ */
@media (max-width:1039px){
  #cof-cfg .cfg-decks{grid-template-columns:1fr 1fr}
  #cof-cfg .cfg-card{aspect-ratio:1/1.08}
  #cof-cfg .cfg-rule{margin-bottom:1.05rem}
  #cof-cfg .cfg-seclabel{margin-bottom:.7rem}
  #cof-cfg .cfg-h1{font-size:1.5rem}
  #cof-cfg .cfg-emblem{left:11px; top:11px; width:26%}
  #cof-cfg .cfg-tick{right:9px; top:10px; width:24px}
  #cof-cfg .cfg-nm{font-size:.62rem}
}
@media (max-width:430px){
  #cof-cfg .cfg-mark{font-size:.78rem; letter-spacing:.1em}
  #cof-cfg .cfg-right{gap:.5rem; font-size:.64rem}
}

/* ⚠️ The star field is NOT listed here. Hiding it under this query is what turned the
   landing mockup into a still on 2026-08-25; there is an explicit pause control instead. */
@media (prefers-reduced-motion:reduce){
  #cof-cfg .cfg-art,#cof-cfg .cfg-card::after,#cof-cfg .cfg-cardwrap{transition:none}
  #cof-cfg .cfg-card:hover .cfg-art{transform:none}
  #cof-landing .cfg-logo,#cof-landing .cfg-tag{animation:none}
  #cof-landing .cfg-big,#cof-cfg .cfg-big,
  #cof-landing .cfg-face,#cof-cfg .cfg-face{animation:none}
  #cof-landing .cfg-face,#cof-cfg .cfg-face{border-color:var(--cy);
    box-shadow:0 0 20px rgba(111,230,241,.45)}
  #cof-queue .cfg-dots i{animation:none; background:var(--cy)}
  #cof-queue .cfg-bar{transition:none}
}

/* ===== PRIVATE GAME — waiting for one specific person ======================
 * [user spec 2026-08-25] No ring and no countdown: this table waits for a named opponent and
 * has no AI fallback, so a timer would promise something that is not going to happen.
 * `.cfg-private-mode` is set on `#cof-queue` by startPrivate() and cleared by startQueue(),
 * so the same element serves both and neither can leak into the other.
 * ------------------------------------------------------------------------- */
#cof-queue .cfg-codewrap{display:none}
#cof-queue.cfg-private-mode .cfg-ring{display:none}
#cof-queue.cfg-private-mode .cfg-codewrap{display:block; margin:0 0 1.4rem}

#cof-queue .cfg-codelabel{
  margin:0 0 .5rem; font-size:.62rem; letter-spacing:.18em; text-transform:uppercase;
  color:#7d93ab;
}
/* A real <button>: it is clicked, so it must be reachable by keyboard and announce itself. */
#cof-queue .cfg-bigcode{
  display:block; width:100%; max-width:min(92vw,420px); margin:0 auto;
  font-family:Orbitron,sans-serif; font-size:clamp(2.4rem,9vw,4rem); font-weight:700;
  letter-spacing:.24em; text-indent:.24em;      /* letter-spacing pads the right; recentre it */
  color:#eaf6ff; background:rgba(8,245,255,.06);
  border:1px solid rgba(8,245,255,.45); border-radius:8px;
  padding:.5rem .6rem; cursor:pointer;
  text-shadow:0 0 18px rgba(8,245,255,.55);
  transition:background .18s ease, border-color .18s ease, transform .12s ease;
}
#cof-queue .cfg-bigcode:hover:not(:disabled),
#cof-queue .cfg-bigcode:focus-visible{background:rgba(8,245,255,.13); border-color:#08F5FF}
#cof-queue .cfg-bigcode:active:not(:disabled){transform:scale(.985)}
#cof-queue .cfg-bigcode:disabled{opacity:.45; cursor:default}
#cof-queue .cfg-copied{
  min-height:1.1em;                              /* reserve it, so the layout cannot jump */
  margin:.5rem 0 0; font-size:.66rem; letter-spacing:.08em; color:#35E08A;
}

@media (prefers-reduced-motion: reduce){
  #cof-queue .cfg-bigcode{transition:none}
  #cof-queue .cfg-bigcode:active:not(:disabled){transform:none}
}

/* ===== PROVIDER BUTTONS ====================================================
 * ⭐ [user report 2026-08-26, tested on mobile] "The Discord and Google login buttons look very
 * rough. They are also stacked on top of each other, but they should be displayed side by side."
 *
 * They were plain `.cfg-ghost` text buttons in a plain div, so they inherited the block layout
 * and read as two unrelated links at the moment a player is deciding whether to trust us with a
 * login. Now a two-up grid carrying each provider's own mark and brand colour.
 *
 * ⚠️ `1fr 1fr` AND NOT `auto-fit`/`minmax` — with two providers, `auto-fit` collapses to one
 * column on a narrow phone, which is exactly the stacking that was reported. Side by side is the
 * requirement, so the columns are stated. The label hides below 340px rather than the buttons
 * wrapping: two recognisable logos side by side still say what they are.
 * ------------------------------------------------------------------------- */
/*
 * ⚠️ IT IS A DROP-DOWN NOW, NOT AN INLINE BLOCK. [reported with a screenshot 2026-09-03]
 *
 * `insertAdjacentElement('afterend')` puts this box next to `#cfg-signin`, and that button is now
 * inside `.cfg-acctwrap` — an `inline-flex` wrapper sized to the pill. So `width:100%` meant "as
 * wide as the pill", the grid spilled past it, and on a phone the whole PAGE went wider than the
 * device: Chrome zoomed out to cope and the Google button was sliced in half at the right edge.
 * Measured: a 465px layout viewport on a 393px screen.
 *
 * Anchored to the pill like the account menu, so it can never widen the page again whatever it
 * contains, and right-aligned so it cannot run off the edge it hangs from.
 */
#cof-cfg .cfg-providers{
  position:absolute; top:calc(100% + 8px); right:0; z-index:95;
  display:grid; grid-template-columns:1fr 1fr; gap:.6rem;
  width:min(320px, calc(100vw - 24px));
  margin:0; padding:.7rem;
  background:rgba(6,12,22,.98); border:1px solid var(--ed); border-radius:8px;
  box-shadow:0 14px 40px rgba(0,0,0,.65);
  text-transform:none; letter-spacing:normal;
}
/*
 * ⭐ STACKED ON A PHONE. [user request 2026-09-03]
 *
 * ⚠️ THIS REVERSES AN EARLIER REQUIREMENT, DELIBERATELY. The note below this block records that
 * side-by-side was asked for *because* stacking had been reported — so do not "fix" this back
 * without asking. What changed is that the panel is now a bounded drop-down: two columns inside
 * 320px leave each button about 145px, which is what clipped "Google". One column per row gives
 * both a full-width tap target and cannot overflow at any width.
 */
@media (max-width:760px){
  #cof-cfg .cfg-providers{grid-template-columns:1fr}
}
/* The reason, above both buttons — it is why the choice is worth making. */
#cof-cfg .cfg-whysignin{
  grid-column:1 / -1; margin:0 0 .15rem;
  font-size:.72rem; line-height:1.45; color:var(--tx);
}
#cof-cfg .cfg-prov{
  display:flex; align-items:center; justify-content:center; gap:.55rem;
  min-height:48px;                        /* a real tap target on a phone */
  padding:.7rem .8rem;
  font-family:Orbitron,sans-serif; font-size:.72rem; font-weight:700; letter-spacing:.06em;
  border-radius:8px; border:1px solid transparent; cursor:pointer;
  transition:transform .12s ease, box-shadow .18s ease, filter .18s ease;
}
#cof-cfg .cfg-prov:active{transform:scale(.98)}
#cof-cfg .cfg-provmark{display:flex; align-items:center; justify-content:center; flex:0 0 auto}
#cof-cfg .cfg-provmark svg{width:20px; height:20px; display:block}
#cof-cfg .cfg-provlabel{white-space:nowrap}

/* Discord: blurple plate, white mark — the mark is monochrome by design. */
#cof-cfg .cfg-prov-discord{background:#5865F2; color:#fff; border-color:#5865F2}
#cof-cfg .cfg-prov-discord:hover,
#cof-cfg .cfg-prov-discord:focus-visible{filter:brightness(1.12); box-shadow:0 0 18px rgba(88,101,242,.55)}

/* ⚠️ Google's mark MUST stay four-colour and must not be tinted — the brand guidelines require
   it, so this button gets a white plate and dark text rather than matching the page. */
#cof-cfg .cfg-prov-google{background:#fff; color:#1f1f1f; border-color:#dadce0}
#cof-cfg .cfg-prov-google:hover,
#cof-cfg .cfg-prov-google:focus-visible{background:#f5f6f7; box-shadow:0 0 18px rgba(255,255,255,.32)}

#cof-cfg .cfg-prov:focus-visible{outline:2px solid var(--cy); outline-offset:2px}

@media (max-width: 340px){
  #cof-cfg .cfg-provlabel{display:none}     /* logos alone still read; wrapping does not */
  #cof-cfg .cfg-prov{padding:.7rem .4rem}
}
@media (prefers-reduced-motion: reduce){
  #cof-cfg .cfg-prov{transition:none}
  #cof-cfg .cfg-prov:active{transform:none}
}

/* Sign out — sits beside the status pill, quieter than it so the pill still reads first.
   Only ever visible while signed in; syncSignInRow() owns the `hidden` attribute. */
#cof-cfg .cfg-signout{display:inline-flex; align-items:center; cursor:pointer;
  font-size:.68rem; letter-spacing:.1em; text-transform:uppercase;
  padding:.45rem .9rem; margin-left:.5rem; border-radius:999px;
  color:var(--dm); border:1px solid var(--ed); background:transparent;
  transition:color .15s, border-color .15s, box-shadow .15s}
#cof-cfg .cfg-signout:hover{color:var(--tx); border-color:var(--em);
  box-shadow:0 0 16px rgba(224,85,47,.22)}
#cof-cfg .cfg-signout:focus-visible{outline:2px solid var(--cy); outline-offset:2px}
#cof-cfg .cfg-signout[hidden]{display:none}
#cof-cfg .cfg-signout:disabled{opacity:.5; cursor:default}

/*
 * ⚠️ SIGNED IN, THE PILL IS A MENU AND MUST LOOK LIKE ONE. [card 3546]
 * These two rules used to make it a dead status chip — `cursor: default`, no hover — which was
 * right when it did nothing and is wrong now that it opens the player's record. Left as they were
 * it would still work and simply look unclickable, which is the sort of thing nobody reports and
 * everybody quietly stops using.
 */
body.cof-authed #cof-cfg .cfg-signin{cursor:pointer; opacity:1}
body.cof-authed #cof-cfg .cfg-signin:hover{border-color:var(--cy);
  box-shadow:0 0 18px rgba(111,230,241,.25)}
body.cof-authed #cof-cfg .cfg-signin .cfg-dot{background:#4ee38a; box-shadow:0 0 10px #4ee38a}

/* The watchdog gave up on the loop — keep the poster, which is what it is for. */
#cof-bg.cof-bg-still video{display:none}
#cof-bg.cof-bg-still{
  background-image:url('/video/starry-loop.jpg');
  background-size:cover; background-position:center;
}

/* Spectate chip beside the ONLINE pill. Hidden unless a game is actually in progress. */
/*
 * ⭐ SPECTATE — a GOLD pill, inline with the account menu. [user request 2026-09-03]
 * Gold rather than cyan so it reads as the one call to action on a line of status, and inline so
 * it costs no vertical space. (It was briefly centred on its own row; that row is gone.)
 */
#cof-cfg .cfg-spec {
  font: inherit; font-family: Orbitron, sans-serif;
  font-size: .6rem; letter-spacing: .14em;
  display: inline-flex; align-items: center; gap: .45rem;
  background: rgba(245,196,81,.10); color: var(--gd);
  border: 1px solid var(--gd); border-radius: 999px;
  padding: .42rem .9rem; cursor: pointer;
  transition: background .14s ease, color .14s ease;
}
#cof-cfg .cfg-spec::before { content: '\1F441'; }
#cof-cfg .cfg-spec:hover, #cof-cfg .cfg-spec:focus-visible { background: var(--gd); color: #140d02; }
#cof-cfg .cfg-spec b { font-weight: 700; }

/* ══ the account menu ═══════════════════════════════════════════════════════════════════════ */
#cof-cfg .cfg-acctwrap { position: relative; display: inline-flex; }
#cof-cfg .cfg-caret { color: var(--dm); font-size: .6rem; }
#cof-cfg .cfg-acctmenu {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 90;
  width: 290px; max-width: 92vw; max-height: 70vh; overflow-y: auto;
  background: rgba(6,12,20,.98); border: 1px solid var(--ed); border-radius: 8px;
  padding: .6rem; box-shadow: 0 14px 40px rgba(0,0,0,.65);
  text-transform: none; letter-spacing: normal;
}
#cof-cfg .cfg-acctmenu.hidden { display: none; }
#cof-cfg .cfg-amhead {
  font-family: Orbitron, sans-serif; font-size: .52rem; letter-spacing: .16em;
  text-transform: uppercase; color: var(--dm); padding: .1rem .2rem .45rem;
}
#cof-cfg .cfg-amrow {
  display: flex; justify-content: space-between; align-items: baseline; gap: .6rem;
  padding: .3rem .35rem; border-radius: 4px; font-size: .68rem;
}
#cof-cfg .cfg-amrow:nth-child(odd) { background: rgba(255,255,255,.03); }
#cof-cfg .cfg-amk { color: var(--dm); }
/* ⚠️ `min-width: 0` + wrapping: a deck or player name is a string somebody else chose, and
   without these a long one widens the menu instead of wrapping inside it. */
#cof-cfg .cfg-amv { color: var(--tx); font-weight: 700; text-align: right; min-width: 0;
                    overflow-wrap: anywhere; }
#cof-cfg .cfg-amv.gold { color: var(--gd); }
#cof-cfg .cfg-amv.warn { color: var(--em); font-weight: 400; }
#cof-cfg .cfg-amrule { height: 1px; background: rgba(255,255,255,.08); margin: .5rem 0; }
#cof-cfg .cfg-amlabel { font-size: .62rem; color: var(--dm); padding: .1rem .35rem .3rem; }
#cof-cfg .cfg-amnote { font-size: .62rem; color: var(--dm); margin: 0; padding: .1rem .35rem; }
#cof-cfg .cfg-amgame {
  display: flex; gap: .5rem; align-items: center;
  padding: .22rem .35rem; font-size: .64rem; border-radius: 4px;
}
#cof-cfg .cfg-amgame:nth-child(even) { background: rgba(255,255,255,.03); }
#cof-cfg .cfg-amres { width: 1.1rem; font-weight: 700; flex: 0 0 auto; }
#cof-cfg .cfg-amres.win { color: #4ee38a; }
#cof-cfg .cfg-amres.loss { color: var(--dm); }
/* Quitting is the thing the ladder punishes, so it is the thing the list makes visible. */
#cof-cfg .cfg-amres.concede, #cof-cfg .cfg-amres.abandon { color: var(--em); }
#cof-cfg .cfg-amopp { flex: 1; min-width: 0; color: var(--tx);
                      overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#cof-cfg .cfg-amcq { color: var(--dm); flex: 0 0 auto; }
/* Last in the menu and visually separated — it ends the session, so a mis-tap must not reach it. */
#cof-cfg .cfg-acctmenu .cfg-signout {
  display: block; width: 100%; margin-top: .5rem; padding: .42rem;
  font-family: Orbitron, sans-serif; font-size: .55rem; letter-spacing: .14em;
  text-transform: uppercase; cursor: pointer;
  color: var(--em); background: transparent;
  border: 1px solid rgba(224,85,47,.5); border-radius: 6px;
}
.cfg-spec.hidden { display: none; }
.cfg-spec b { font-weight: 700; }

/* Where custom decks come from, for players who are not signed in. [2026-08-26] */
/*
 * ⚠️ SCOPED `#cof-cfg .cfg-*` LIKE EVERY OTHER RULE IN THIS FILE. The first version was a bare
 * class (0,1,0) and worked only because nothing else claimed the selector — the moment a
 * `#cof-cfg .cfg-ggnote` rule (1,1,0) appeared it would have silently won. Match the convention.
 *
 * ⭐ SPACING [user, 2026-08-26]: the note sat in the heading's gap with only .6rem beneath it, so
 * it crowded the starter-deck art below. It now pulls UP into that gap — the heading's own
 * margin-bottom is a generous clamp(1.4rem, 3.5vh, 2.1rem) and the note belongs with the heading,
 * not floating in the middle — and takes a full 1.5rem underneath, which is the same rhythm
 * `.cfg-acct` uses above the decks when signed in.
 */
#cof-cfg .cfg-ggnote {
  margin: -0.9rem 0 1.5rem; font-size: .72rem; color: var(--dm, #7d93ab); text-align: center;
}
#cof-cfg .cfg-ggnote[hidden] { display: none; }
#cof-cfg .cfg-ggnote a { color: var(--cy, #08F5FF); text-decoration: underline; }
#cof-cfg .cfg-ggnote a:hover { text-decoration: none; }

/* ── INTERNAL STAFF MENU ────────────────────────────────────────────────────────────────────
   ⚠️ EVERY RULE IS ID-QUALIFIED WITH #cof-cfg, like everything else in this file. style.css
   styles a bare `button` at (0,1,1); a lone `.cfg-admin` is (0,1,0) and would silently lose.
   ⚠️ Tokens are the SCOPED ones (--cy/--ed/--tx/--dm). Never redefine them at :root here — this
   file must not restyle the board. */
#cof-cfg .cfg-admin{display:inline-flex; align-items:center; cursor:pointer;
  font-size:.7rem; letter-spacing:.12em; padding:.5rem .95rem; border-radius:999px;
  color:var(--vi); border:1px solid rgba(168,85,247,.32); background:rgba(18,8,30,.72);
  transition:border-color .15s, box-shadow .15s}
#cof-cfg .cfg-admin:hover{border-color:var(--vi); box-shadow:0 0 18px rgba(168,85,247,.3)}
#cof-cfg .cfg-admin.hidden{display:none}

/* The dropdown. Anchored to the header row, which is `position:relative` for this reason. */
#cof-cfg .cfg-top{position:relative}
#cof-cfg .cfg-adminpanel{position:absolute; right:0; top:calc(100% + .5rem); z-index:60;
  width:min(30rem, calc(100vw - 2rem)); max-height:min(30rem, 70vh); overflow-y:auto;
  padding:1rem 1.1rem; border-radius:.7rem; text-align:left;
  color:var(--tx); border:1px solid rgba(168,85,247,.3); background:rgba(8,6,16,.97);
  box-shadow:0 18px 48px rgba(0,0,0,.6)}
#cof-cfg .cfg-adminpanel.hidden{display:none}
#cof-cfg .cfg-adminpanel h4{margin:0 0 .5rem; font-size:.72rem; letter-spacing:.14em;
  color:var(--vi); text-transform:uppercase}
#cof-cfg .cfg-adminpanel dl{display:grid; grid-template-columns:auto 1fr; gap:.28rem .9rem;
  margin:0 0 .9rem; font-size:.74rem}
#cof-cfg .cfg-adminpanel dt{color:var(--dm); white-space:nowrap}
#cof-cfg .cfg-adminpanel dd{margin:0; color:var(--tx); font-variant-numeric:tabular-nums;
  overflow-wrap:anywhere}
#cof-cfg .cfg-adminpanel .cfg-admwarn{margin:.2rem 0 0; font-size:.68rem; color:var(--dm);
  line-height:1.5}
#cof-cfg .cfg-adminpanel .cfg-admbad{color:var(--em)}

/* ── THE PANEL'S CONTROLS: buttons must look like buttons ────────────────────────────────────
   [user report 2026-09-07: "the buttons to apply things inside of the internal menu need to
   actually look like buttons. they just look like text right now."]

   ⚠️ THIS IS A CONSEQUENCE OF THE RESET AT THE TOP OF THIS FILE, not an oversight in isolation.
   `#cof-landing button,#cof-cfg button,#cof-queue button` deliberately strips every bare button
   back to plain text — no border, no background, no padding — so each screen can style its own.
   Every screen that came later did. The staff panel was added after that and never got a rule
   back, so both Apply buttons rendered as a centred word and read as a heading rather than a
   control. Anything else added to this panel inherits the same problem, which is why these rules
   are written against the CONTAINER and the element, not against one button's class.

   ⚠️ SPECIFICITY, since the reset is not a trivial thing to beat: the reset's base rule is
   (1,0,1) and its :hover/:active variants are (1,1,1). Qualifying with `.cfg-adminpanel` puts
   these at (1,1,1) and (1,2,1) respectively — so the hover and active rules BOTH need the class
   or they tie and lose to source order. */
#cof-cfg .cfg-adminpanel button{
  display:inline-flex; align-items:center; justify-content:center;
  padding:.42rem 1.05rem; border-radius:.4rem; cursor:pointer;
  font-size:.7rem; letter-spacing:.1em; text-transform:uppercase;
  color:var(--tx); border:1px solid rgba(168,85,247,.45);
  background:linear-gradient(180deg, rgba(168,85,247,.24), rgba(168,85,247,.10));
  transition:border-color .15s, box-shadow .15s, background .15s}
#cof-cfg .cfg-adminpanel button:hover{
  border-color:var(--vi); box-shadow:0 0 16px rgba(168,85,247,.3);
  background:linear-gradient(180deg, rgba(168,85,247,.36), rgba(168,85,247,.16))}
#cof-cfg .cfg-adminpanel button:active{transform:translateY(1px)}
#cof-cfg .cfg-adminpanel button:disabled{opacity:.45; cursor:default; box-shadow:none}

/* The rows. Label left, control right, and the control may not grow past the panel — a long
   option label in the game-speed select ran off the right edge and was clipped mid-word. */
#cof-cfg .cfg-adminpanel .aia-row{
  display:flex; align-items:center; justify-content:space-between; gap:.9rem;
  margin:0 0 .4rem; font-size:.74rem; color:var(--tx)}
#cof-cfg .cfg-adminpanel .aia-row > span{color:var(--dm); flex:0 1 auto}
#cof-cfg .cfg-adminpanel .aia-row label{display:inline-flex; align-items:center; gap:.5rem;
  cursor:pointer}
/* ⚠️ `.aia-reasons` is borrowed from the AI-assist panel in style.css, where it is
   `display:flex; flex-direction:column` — so a button in it STRETCHES to full width by
   default. Align it to the end so it sits under the controls column it applies to. */
#cof-cfg .cfg-adminpanel .aia-reasons > button{margin-top:.6rem; align-self:flex-end}

/* ⚠️ `color-scheme:dark` is what makes the NATIVE parts render dark — the select's dropdown list
   and the number input's spinners are drawn by the browser, not by us, and they were coming back
   white-on-white inside a near-black panel. It cannot be done with `background` alone. */
#cof-cfg .cfg-adminpanel{color-scheme:dark}
#cof-cfg .cfg-adminpanel select,
#cof-cfg .cfg-adminpanel input[type="number"]{
  font:inherit; font-size:.72rem; padding:.3rem .5rem; border-radius:.35rem;
  color:var(--tx); background:rgba(18,8,30,.92);
  border:1px solid rgba(168,85,247,.32); min-width:0}
#cof-cfg .cfg-adminpanel select{flex:0 1 auto; max-width:62%}
#cof-cfg .cfg-adminpanel input[type="number"]{flex:0 0 auto; width:5rem; text-align:right}
#cof-cfg .cfg-adminpanel select:focus,
#cof-cfg .cfg-adminpanel input:focus{outline:1px solid var(--vi); outline-offset:1px}
#cof-cfg .cfg-adminpanel input[type="checkbox"]{
  width:1rem; height:1rem; accent-color:var(--vi); cursor:pointer}

/* ── Scenario Builder, in the internal panel ─────────────────────────────────── [card 3561]
   ⚠️ EVERY RULE IS ID-QUALIFIED WITH #cof-cfg, like the rest of this file. style.css styles bare
   `button` and `select` at (0,0,1) and `.lobby h1` at (0,1,1), so a plain `.cfg-scnrow select`
   would be (0,1,1) and lose the coin toss on several properties. The id makes it (1,1,1). */
#cof-cfg .cfg-scnform{display:grid; gap:.5rem; margin:.5rem 0 0}
/* ⚠️ THE LABEL SITS ABOVE THE SELECT, NOT BESIDE IT. Two columns left the control ~195px wide,
   and a deck name is long — "The Perfect Spawn — Starter" wants 300px and "Dummy — fills every
   Location, no abilities" wants 360px, so both were CLIPPED rather than overflowing, which no
   overflow check can see. Caught by check-exhibition-panel.ts's P10b, which measures what each
   dropdown's own content asks for. Stacking gives the select the panel's full width. */
#cof-cfg .cfg-scnrow{display:grid; grid-template-columns:1fr; align-items:start;
  gap:.15rem; font-size:.72rem; color:var(--dm)}
/* ⚠️ OPTS OUT OF `.cfg-adminpanel select{max-width:62%}` ABOVE. That cap is right for a
   label-beside-control row, where the select shares the line; these rows put the label ABOVE, so
   the select owns the full width and a 62% cap just clips a long deck name. */
#cof-cfg .cfg-scnrow select{width:100%; max-width:100%; min-width:0;
  padding:.34rem .5rem; font-size:.72rem;
  color:var(--tx); background:rgba(0,0,0,.5); border:1px solid rgba(168,85,247,.32);
  border-radius:.35rem}
#cof-cfg .cfg-adminpanel #scn-start{margin:.15rem 0 0; padding:.42rem .8rem; width:100%;
  font-size:.72rem; letter-spacing:.08em; text-transform:uppercase; cursor:pointer;
  color:#f6e7ff; background:rgba(168,85,247,.22); border:1px solid rgba(168,85,247,.5);
  border-radius:.4rem}
#cof-cfg .cfg-adminpanel #scn-start:hover:not(:disabled){background:rgba(168,85,247,.34)}
#cof-cfg .cfg-adminpanel #scn-start:disabled{opacity:.55; cursor:default}
/* (The rows stack at every width now — see the note above.) */

/* ── Override Random AI Player, in the internal panel ─────────────────────── [card 3573]
   ⚠️ Id-qualified with #cof-cfg like every other rule in this file: style.css styles a bare
   `select` at (0,0,1) and `.lobby h1` at (0,1,1), so an unqualified class rule loses. */
#cof-cfg .cfg-aipick { margin: .35rem 0 0 1.5rem; }
#cof-cfg .cfg-aipick.hidden { display: none; }
#cof-cfg .cfg-aipick select {
  /* Same opt-out as the scenario rows: this select owns its line, so the 62% cap would clip a
     long character or faction label. */
  width: 100%; max-width: 100%; padding: .34rem .5rem; font-size: .72rem;
  color: var(--tx); background: rgba(0, 0, 0, .5);
  border: 1px solid rgba(168, 85, 247, .32); border-radius: .35rem;
}

/* ── the config strip must never push a control off screen ──────────────── [card 3592]
 *
 * ⚠️ `.cfg-right` had no `flex-wrap`, so its children — WATCH, the account pill and Internal —
 * overflowed horizontally on a narrow screen and the Internal button ended up past the right edge.
 * Shortening the pill's label bought room but did not fix the cause: a long enough username would
 * push it off again.
 */
#cof-cfg .cfg-right{flex-wrap:wrap; justify-content:flex-end; row-gap:.45rem; min-width:0}
/* ⚠️ AND THE PILL MUST BE ABLE TO SHRINK. A flex item defaults to `min-width:auto`, which refuses
   to go below its content — so one long name would still force the row wider than the screen.
   Capped and ellipsised instead: the name stays readable and the row stays inside the viewport. */
#cof-cfg .cfg-signin{min-width:0; max-width:min(52vw, 15rem)}
#cof-cfg #cfg-who{overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0}
