/* ============================================================
   Once de Letras — the board.
   Tokens and geometry are lifted from reference/prototype.html; the values
   are tuned for both themes, so change them there first, not here.
   ============================================================ */

/* ---------- Fonts: self-hosted, latin + latin-ext, swap ------------------
   unicode-range means a Spanish-only page downloads the latin files alone;
   latin-ext arrives the first time an answer like Łódź or Şahin appears. */
@font-face{font-family:'Archivo';font-style:normal;font-weight:500 700;font-display:swap;
  src:url(../fonts/archivo-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Archivo';font-style:normal;font-weight:500 700;font-display:swap;
  src:url(../fonts/archivo-latin-ext.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:'Karla';font-style:normal;font-weight:400 600;font-display:swap;
  src:url(../fonts/karla-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Karla';font-style:normal;font-weight:400 600;font-display:swap;
  src:url(../fonts/karla-latin-ext.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:500;font-display:swap;
  src:url(../fonts/plexmono-500-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:500;font-display:swap;
  src:url(../fonts/plexmono-500-latin-ext.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:600;font-display:swap;
  src:url(../fonts/plexmono-600-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:600;font-display:swap;
  src:url(../fonts/plexmono-600-latin-ext.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}

/* ---------- Tokens ------------------------------------------------------- */
:root{
  --bg:#EBEDE7; --surface:#FFFFFF; --surface-2:#F3F5F1;
  --ink:#131A14; --muted:#5A6659; --line:#CBD3C7;
  --ok:#1C7A45; --bad:#AE3A2C; --pass:#B9820D;
  --accent:#1C7A45;
  --turf-a:#1F6B41; --turf-b:#1B5F3A; --turf-ln:rgba(255,255,255,.34);
  --slot:rgba(9,28,18,.52); --slot-ln:rgba(255,255,255,.5); --slot-tx:#F2F6F1;
  --shadow:0 1px 0 rgba(19,26,20,.06);

  /* Fixed in both themes: these sit on turf or on a state colour, never on --bg.
     Values are the prototype's; only their names are new. */
  --now-bg:#F2F6F1; --now-tx:#0E1A12; --now-ring:rgba(242,246,241,.22);
  --on-state:#fff;
  --ok-ln:#EAF7EF; --bad-ln:#FBE6E2; --pass-ln:#FAEFD6;
  --pass-tx:#2A1D02;               /* dark on amber on purpose: light text fails contrast */
  --label-tx:#F2F6F1; --label-shadow:rgba(0,0,0,.65);
  --bench-ring:rgba(28,122,69,.25);

  --font-display:'Archivo',system-ui,-apple-system,sans-serif;
  --font-body:'Karla',system-ui,-apple-system,sans-serif;
  --font-mono:'IBM Plex Mono',ui-monospace,monospace;
  color-scheme:light;
}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --bg:#0E120F; --surface:#1A211B; --surface-2:#141A15;
    --ink:#E7EDE5; --muted:#95A291; --line:#2F3B30;
    --ok:#4FBC80; --bad:#E4796A; --pass:#E0AC42;
    --accent:#4FBC80;
    --turf-a:#173F2A; --turf-b:#133523; --turf-ln:rgba(255,255,255,.22);
    --slot:rgba(4,14,9,.62); --slot-ln:rgba(255,255,255,.38); --slot-tx:#E7EDE5;
    --shadow:none;
    color-scheme:dark;
  }
}
:root[data-theme="dark"]{
  --bg:#0E120F; --surface:#1A211B; --surface-2:#141A15;
  --ink:#E7EDE5; --muted:#95A291; --line:#2F3B30;
  --ok:#4FBC80; --bad:#E4796A; --pass:#E0AC42;
  --accent:#4FBC80;
  --turf-a:#173F2A; --turf-b:#133523; --turf-ln:rgba(255,255,255,.22);
  --slot:rgba(4,14,9,.62); --slot-ln:rgba(255,255,255,.38); --slot-tx:#E7EDE5;
  --shadow:none;
  color-scheme:dark;
}

/* ---------- Base --------------------------------------------------------- */
*{box-sizing:border-box}
html{background:var(--bg)}
body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--font-body);
  font-size:16px;line-height:1.55;-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%}
[hidden]{display:none !important}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}
a:focus-visible,button:focus-visible,input:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* ---------- Layout ------------------------------------------------------
   One column, phone first. The DOM puts the clue panel BEFORE the pitch so
   the input comes before the 15 disc buttons in tab order; `order` puts it
   back under the pitch visually, as in the prototype.

   The column is exactly one viewport tall and the pitch is its only
   flexible item: when everything else needs the room, the pitch shrinks
   (down to --pitch-min) so the clue panel stays on screen with it. */
.wrap{
  --gutter:16px;
  --pitch-min:200px;
  --pitch-max:calc((min(100vw, 540px) - 2 * var(--gutter)) * 3.7 / 3);
  max-width:540px;margin:0 auto;padding:12px var(--gutter) 20px;
  display:flex;flex-direction:column;gap:12px;
  height:100vh;height:100svh;
}
.wrap > *{flex-shrink:0}
.masthead{order:1}
.levels{order:2}
.hud{order:3}
.pitch-box{order:4}
.bench-block{order:5}
.panel{order:6}
.foot{order:7}

/* ---------- Masthead ----------------------------------------------------- */
.masthead{display:flex;flex-direction:column;gap:2px}
.eyebrow{font-size:11.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);font-weight:600;margin:0}
h1{font-family:var(--font-display);font-weight:700;font-size:24px;line-height:1.1;margin:0;letter-spacing:-.02em}

/* ---------- Level switch: links, because switching is a fresh load ------- */
.levels{display:flex;gap:6px;background:var(--surface-2);border:1px solid var(--line);border-radius:999px;padding:4px}
.lvl{flex:1;text-align:center;text-decoration:none;color:var(--muted);font-size:13.5px;font-weight:600;
  padding:6px 8px;border-radius:999px;white-space:nowrap}
.lvl[aria-current="page"]{background:var(--surface);color:var(--ink);box-shadow:var(--shadow)}
.lvl:hover{color:var(--ink)}
.lvl-desc{order:2;margin:-6px 0 0;text-align:center;font-size:12.5px;color:var(--muted)}
/* Only needed to choose a level; during play the line goes back to the pitch. */
[data-phase="playing"] .lvl-desc{display:none}

/* ---------- HUD ---------------------------------------------------------- */
.hud{display:flex;justify-content:space-between;align-items:baseline;gap:12px;padding:0 2px}
.clock{font-family:var(--font-mono);font-weight:600;font-size:28px;line-height:1;font-variant-numeric:tabular-nums}
.clock.low{color:var(--bad)}
.tally{font-size:13px;color:var(--muted);font-variant-numeric:tabular-nums;margin:0}
.tally b{font-weight:600;color:var(--ink)}

/* ---------- Pitch --------------------------------------------------------
   .pitch-box is the flexible item; the pitch inside keeps 3:3.7 and takes
   whichever of the box's width or height runs out first. Browsers without
   container units ignore the min() and fall back to full width. */
.pitch-box{flex:0 1 var(--pitch-max);min-height:var(--pitch-min);container-type:size}
.pitch{position:relative;width:100%;width:min(100cqw, 100cqh * 3 / 3.7);margin:0 auto;
  aspect-ratio:3/3.7;border-radius:14px;overflow:hidden;container-type:inline-size;
  background:repeating-linear-gradient(180deg,var(--turf-a) 0 9%,var(--turf-b) 9% 18%)}
.pitch svg.lines{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
.lines path,.lines circle,.lines line{fill:none;stroke:var(--turf-ln);stroke-width:1.6}

/* ---------- Slots: every disc is a real <button> ------------------------- */
.slot{position:absolute;transform:translate(-50%,-50%);width:17%;display:flex;flex-direction:column;
  align-items:center;gap:3px;padding:0;margin:0;border:0;background:none;color:inherit;
  font:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}
.slot:focus-visible{outline:none}
.slot:focus-visible .disc{outline:2px solid var(--accent);outline-offset:3px}
.disc{width:100%;aspect-ratio:1/1;border-radius:50%;background:var(--slot);border:1.5px solid var(--slot-ln);
  display:flex;align-items:center;justify-content:center;
  font-family:var(--font-display);font-weight:700;color:var(--slot-tx);
  font-size:clamp(14px,4.4vw,20px)}
/* Same bounds, measured against the pitch rather than the window, so the
   letters shrink with the pitch when a short viewport squeezes it. */
@supports (width:1cqw){.pitch .disc{font-size:clamp(14px,6.6cqw,20px)}}
/* Breaks between words only, two lines at most: "Olympique de Marsella"
   must not become "Olympi / que de / Marsell / a" on a narrow pitch. */
.nm{font-size:clamp(8.5px,2.5vw,11px);font-weight:600;color:var(--label-tx);text-align:center;line-height:1.15;
  text-shadow:0 1px 2px var(--label-shadow);width:max-content;max-width:170%;
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow:hidden}
.nm[hidden]{display:none}
/* On a phone the pitch is 160–200 px wide during play and names collide
   ("República Centroafricana"; at 400 px "Friburgo" still runs into the next
   disc). The feedback line already says each answer as it lands; the names
   come back on the pitch at the final whistle. */
@media (max-width:480px){[data-phase="playing"] .pitch .nm{display:none}}
/* The fixed 4-3-3 puts back-line labels close to the goalkeeper. Stack so
   the current disc is never covered, and answers sit above pending discs. */
.slot.ok,.slot.bad,.slot.pass{z-index:1}
.slot.now{z-index:2}
.slot.now .disc{background:var(--now-bg);color:var(--now-tx);border-color:var(--now-bg);box-shadow:0 0 0 4px var(--now-ring)}
/* sent: answered, verdict in flight. Neutral, from existing tokens only. */
.slot.sent .disc{background:var(--muted);border-color:var(--muted);color:var(--bg)}
.slot.ok .disc{background:var(--ok);border-color:var(--ok-ln);color:var(--on-state)}
.slot.bad .disc{background:var(--bad);border-color:var(--bad-ln);color:var(--on-state)}
.slot.pass .disc{background:var(--pass);border-color:var(--pass-ln);color:var(--pass-tx)}
/* A second channel besides colour: ✓ ✕ » … in a corner badge, so the
   states survive greyscale and red/green colour blindness. "missed" is a
   slot never answered by the final whistle. */
.disc{position:relative}
.slot.ok .disc::after,.slot.bad .disc::after,.slot.pass .disc::after,.slot.sent .disc::after{
  position:absolute;top:-5px;right:-5px;width:15px;height:15px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  font:700 10px/1 var(--font-body);background:var(--surface);color:var(--ink);box-shadow:0 0 0 1.5px var(--ink)}
/* A little bigger once the disc has room for it. */
@supports (width:1cqw){.pitch .slot .disc::after{width:clamp(15px,5.4cqw,19px);height:clamp(15px,5.4cqw,19px);
  font-size:clamp(10px,3.6cqw,12.5px)}}
.slot.ok .disc::after{content:"✓"}
.slot.bad .disc::after{content:"✕"}
.slot.pass .disc::after{content:"»"}   /* not ↺: in Karla it reads as a "G" */
.slot.sent .disc::after{content:"…"}
.slot.missed .disc::after{content:"–"}
/* Tap target: the drawn disc can be 28 px on a small phone; an invisible
   ring makes the tappable area 44 px without drawing it any bigger. */
.slot .disc::before{content:"";position:absolute;inset:-8px;border-radius:50%}

/* ---------- Bench: absent on fácil, not empty ---------------------------- */
.bench-block{display:flex;flex-direction:column;gap:6px}
.bench-lbl{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);font-weight:600;margin:0 0 0 2px}
/* Capped so the substitutes never outsize the starting eleven. */
.bench{display:grid;grid-template-columns:repeat(4,minmax(0,46px));justify-content:center;gap:14px;
  background:var(--surface-2);border:1px solid var(--line);border-radius:12px;padding:7px 9px}
.bench .slot{position:static;transform:none;width:auto}
.bench .disc{background:var(--surface);border:1.5px solid var(--line);color:var(--muted);font-size:clamp(12px,3.4vw,16px)}
.bench .nm{color:var(--ink);text-shadow:none;font-size:clamp(8.5px,2.4vw,11px)}
.bench .slot.now .disc{background:var(--ink);color:var(--bg);border-color:var(--ink);box-shadow:0 0 0 3px var(--bench-ring)}
.bench .slot.sent .disc{background:var(--muted);border-color:var(--muted);color:var(--bg)}
.bench .slot.ok .disc{background:var(--ok);border-color:var(--ok);color:var(--on-state)}
.bench .slot.bad .disc{background:var(--bad);border-color:var(--bad);color:var(--on-state)}
.bench .slot.pass .disc{background:var(--pass);border-color:var(--pass);color:var(--pass-tx)}

/* ---------- Clue panel --------------------------------------------------- */
.card{background:var(--surface);border:1px solid var(--line);border-radius:14px;padding:12px 14px;
  box-shadow:var(--shadow);display:flex;flex-direction:column;gap:8px}
#play,.ready{display:flex;flex-direction:column;gap:8px}
.prompt-head{display:flex;gap:12px;align-items:flex-start}
.prompt-head .clue-block{flex:1;min-width:0}
.letter-tile{flex:none;width:46px;height:46px;border-radius:11px;background:var(--ink);color:var(--bg);
  display:flex;align-items:center;justify-content:center;
  font-family:var(--font-display);font-weight:800;font-size:28px;line-height:1}
.prompt-lbl{font-family:var(--font-display);font-size:14px;letter-spacing:.06em;text-transform:uppercase;
  font-weight:700;color:var(--accent);margin:0}
.panel-clock{flex:none;font-family:var(--font-mono);font-weight:600;font-size:16px;line-height:1.3;
  font-variant-numeric:tabular-nums;color:var(--muted)}
.panel-clock.low{color:var(--bad)}
.clue{font-size:17px;line-height:1.4;margin:0;text-wrap:balance}
.clue-block{display:flex;flex-direction:column;gap:4px}
.opts{display:flex;flex-direction:column;gap:8px}
button.opt{width:100%;text-align:left;background:var(--surface-2);border:1px solid var(--line);color:var(--ink);
  font-family:var(--font-body);font-size:16px;font-weight:500;padding:11px 14px;border-radius:10px;cursor:pointer}
button.opt:hover{border-color:var(--ink)}
.row{display:flex;gap:8px;flex-wrap:wrap;margin:0}
/* 16px or iOS Safari zooms on focus and the player loses the board. */
input[type=text]{flex:1 1 140px;min-width:0;background:var(--surface-2);border:1px solid var(--line);border-radius:10px;
  padding:11px 14px;font-family:var(--font-body);font-size:16px;color:var(--ink)}
input[type=text]::placeholder{color:var(--muted)}
.btn{background:var(--ink);color:var(--bg);border:1px solid var(--ink);font-family:var(--font-body);font-size:15px;
  font-weight:600;padding:11px 16px;border-radius:10px;cursor:pointer}
.btn.ghost{background:transparent;color:var(--ink);border-color:var(--line)}
.btn.ghost:hover{border-color:var(--ink)}
.btn:disabled,button.opt:disabled{opacity:.5;cursor:not-allowed}
.btn.ghost:disabled:hover{border-color:var(--line)}
.err{color:var(--bad);font-size:13.5px;margin:0}
.err:empty{display:none}
.hintline{font-family:var(--font-mono);font-size:17px;letter-spacing:.18em;color:var(--accent);margin:0}
.catline{font-size:15px;font-weight:600;color:var(--accent);margin:0}
/* Comodines: three equal buttons on one line, so the row never wraps on a
   360 px phone; 44 px tall to tap one-handed. */
.lifelines{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:6px}
.btn.ll{font-size:13.5px;padding:6px 4px;min-height:44px;white-space:nowrap}
.flash{font-size:14.5px;margin:0;font-weight:500}
/* While playing, the feedback line keeps its space so the panel does not
   jump when "¡Correcto!" appears; before the start an empty line takes none. */
#feedback{min-height:1.55em}
#ready-flash:empty{display:none}
.slot.sent{z-index:1}
.status-wrap{display:flex;flex-direction:column;gap:10px}
.flash.ok{color:var(--ok)} .flash.bad{color:var(--bad)}
.foot{font-size:12.5px;color:var(--muted);margin:0}
/* On a phone-height screen every line is taken from the pitch; the footer is the first to go. */
@media (max-height:820px){.foot{display:none}}

/* ---------- Challenge and end screen ------------------------------------- */
.challenge{margin:0;padding:10px 12px;background:var(--surface-2);border:1px solid var(--line);
  border-left:3px solid var(--accent);border-radius:10px;font-size:15px}
.result{display:flex;flex-direction:column;gap:10px}
.result-title{font-family:var(--font-display);font-weight:700;font-size:22px;line-height:1.15;margin:0}
.result-title:focus{outline:none}
.result-title:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.result-summary{margin:0;color:var(--muted);font-size:14.5px}
.stat-row{display:flex;gap:18px;flex-wrap:wrap}
.stat span{display:block;font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);font-weight:600}
.stat b{font-family:var(--font-display);font-size:24px;font-weight:700;font-variant-numeric:tabular-nums}
/* The share grid as the player will see it: formation rows, never wrapped. */
.grid-res{margin:0;font-family:"Apple Color Emoji","Segoe UI Emoji","Noto Color Emoji",sans-serif;
  font-size:20px;line-height:1.3;white-space:pre}
.missed-title{font-family:var(--font-display);font-size:13px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted);font-weight:600;margin:4px 0 0}
.missed{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:6px;font-size:15px}
/* Each missed answer with its clue: the part of the end screen that
   teaches something, and the reason to come back tomorrow. */
.missed{gap:8px}
.missed li{display:flex;align-items:baseline;gap:10px;padding:8px 10px;background:var(--surface-2);
  border:1px solid var(--line);border-radius:10px}
.missed em{font-style:normal;font-family:var(--font-display);font-weight:700;min-width:1.4em;text-align:center}
.missed li.bad em{color:var(--bad)}
.missed li.miss em{color:var(--pass)}
.missed .what{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.missed .ans{font-weight:700}
.missed .ans.wait{font-weight:500;color:var(--muted);font-style:italic}
.missed .mclue{font-size:13.5px;line-height:1.35;color:var(--muted)}
.missed .tag{font-size:12px;color:var(--muted);white-space:nowrap}
.share-status{margin:0;font-size:13.5px;color:var(--ok)}
.share-status:empty{display:none}
.share-manual{width:100%;font:14px/1.4 var(--font-mono);color:var(--ink);background:var(--surface-2);
  border:1px solid var(--line);border-radius:10px;padding:10px}
.other-levels{margin:0;font-size:14px;color:var(--muted)}
.other-levels a{color:var(--accent);font-weight:600}

/* Loading and error states live in the panel; the board stays out of the way. */
.status{margin:0;font-size:16px}
.status-title{font-family:var(--font-display);font-weight:700;font-size:18px;margin:0}

@media (prefers-reduced-motion:no-preference){
  .disc{transition:background .18s ease,color .18s ease,border-color .18s ease}
}
