/* V775: the two gaps he marked on the screenshot -- above the title and under the
   mode pills. Tightened by 4px and 4px, which is where the 8px the trace line now
   reserves comes from: the fix costs the page NO extra height. */
.ws-wrap{ max-width:560px; margin:0 auto; padding:2px 16px calc(40px + env(safe-area-inset-bottom)); text-align:center; color:var(--text,#eaf5ee); font-family:'Fredoka','Segoe UI',system-ui,-apple-system,sans-serif; }
.ws-h1{ font-size:30px; font-weight:700; margin:2px 0 2px; display:flex; align-items:center; justify-content:center; gap:10px; }
.ws-logo{ width:40px; height:40px; }
.ws-sub{ color:var(--muted2,#9fb6a8); font-size:13px; margin-bottom:14px; font-weight:400; }
.ws-loading{ padding:40px 0; color:var(--muted2,#9fb6a8); }
.ws-seg{ display:inline-flex; gap:7px; margin-bottom:12px; }
.ws-seg button{ background:var(--btn,#14503c); color:var(--text,#eaf5ee); border:1px solid var(--line2,#2c4636); border-radius:999px; padding:8px 18px; font-size:14px; font-weight:600; font-family:inherit; cursor:pointer; }
.ws-seg button.active{ background:var(--accent,#ffcf5c); color:var(--accent-fg,#3d2c05); border-color:var(--accent,#ffcf5c); }
.ws-hud{ display:flex; justify-content:center; gap:10px; margin-bottom:8px; }
.ws-stat{ background:var(--card, var(--panel, #0e2a20)); border:1px solid var(--line2,#2c4636); border-radius:12px; padding:7px 16px; min-width:74px; }
.ws-stat span{ display:block; font-size:11px; color:var(--muted2,#9fb6a8); text-transform:uppercase; letter-spacing:.05em; }
.ws-stat b{ font-size:22px; font-weight:700; }
.ws-stat b.warn{ color:#ff8a6a; }
/* V775 --- THE BOARD STOPS MOVING WHEN YOU TOUCH A LETTER.
   His report: "when we start selecting alphabets- the grid goes don by a little bit:
   it shuld not move." MEASURED, not guessed: exactly 8px, at every width. This line
   had TWO heights -- `min-height:30px` here at 22px/700 for the word being built, and
   `min-height:22px` at 14px/600 on `.ws-trace.ph` for the "Swipe letters to build a
   word" prompt -- and the swipe takes `.ph` off on the first tile. So the prompt's box
   was 22px, the word's box was 30px, and the 25 tiles under it dropped 8px mid-swipe,
   which is the worst possible moment for the thing your finger is on to move.
   ONE FIXED HEIGHT, flex-centred, so the box is the same whichever state it is in and
   whatever font-size that state uses. `height`, not `min-height`: a minimum is not a
   promise. See .ws-trace.ph below, which now sets only type, never geometry. */
.ws-trace{ height:32px; display:flex; align-items:center; justify-content:center;
  font-size:22px; font-weight:700; line-height:1.2; letter-spacing:.16em;
  margin:4px 0 8px; color:var(--accent,#ffcf5c);
  /* A swipe can cross all 25 tiles and there is no cap on the path (see
     wordsweeper.js), so a 25-letter trace is reachable. At 22px it is ~410px, which
     WRAPPED on a phone -- a second 8px shift on top of the first, and the fix for it
     is not a taller box (that moves the board too) but a smaller type: paintPath()
     adds .l2 / .l3 by length. nowrap + hidden so a pathological path can never make
     the page scroll sideways (PROJECT_GUIDE section 5, layer 8). */
  white-space:nowrap; overflow:hidden; }
/* the two step-downs, by how many letters are on the line */
.ws-trace.l2{ font-size:17px; letter-spacing:.10em; }
.ws-trace.l3{ font-size:13px; letter-spacing:.04em; }
.ws-board{ display:grid; grid-template-columns:repeat(5,1fr); gap:8px; max-width:360px; margin:0 auto 12px; touch-action:none; }
.ws-tile{ aspect-ratio:1/1; display:flex; align-items:center; justify-content:center; font-size:26px; font-weight:700; border-radius:12px; background:var(--btn,#14503c); border:1px solid var(--line2,#2c4636); color:var(--text,#eaf5ee); user-select:none; cursor:pointer; transition:background .1s,transform .1s; }
.ws-tile.on{ background:var(--accent,#ffcf5c); color:var(--accent-fg,#3d2c05); transform:scale(1.06); border-color:var(--accent,#ffcf5c); }
.ws-tile.good{ background:#2f9e63; color:#fff; }
.ws-tile.bad{ background:#c24a4a; color:#fff; }
.ws-tile.dup{ background:#b8860b; color:#fff; }
.ws-actions{ margin:8px 0; }
.ws-btn{ background:var(--btn,#14503c); color:var(--text,#eaf5ee); border:1px solid var(--line2,#2c4636); border-radius:12px; padding:12px 30px; font-size:16px; font-weight:700; font-family:inherit; cursor:pointer; }
.ws-btn.pri{ background:var(--accent,#ffcf5c); color:var(--accent-fg,#3d2c05); border-color:var(--accent,#ffcf5c); }
.ws-btn[disabled]{ opacity:.6; cursor:default; }
.ws-found-wrap{ margin-top:10px; text-align:left; }
.ws-found-h{ font-size:12px; color:var(--muted2,#9fb6a8); text-transform:uppercase; letter-spacing:.06em; margin-bottom:6px; text-align:center; }
.ws-found{ display:flex; flex-wrap:wrap; gap:6px; justify-content:center; }
.ws-chip{ background:var(--card, var(--panel, #0e2a20)); border:1px solid var(--line2,#2c4636); border-radius:999px; padding:3px 10px; font-size:13px; font-weight:600; }
.ws-chip i{ font-style:normal; font-size:11px; color:var(--accent,#ffcf5c); margin-left:5px; }
.ws-final{ margin:14px 0 6px; font-size:16px; }
.ws-lb{ max-width:420px; margin:6px auto 0; }
.ws-final{ margin:14px 0 4px; font-size:16px; font-weight:600; }
.ws-lbwrap{ max-width:420px; margin:12px auto 0; }
.ws-lb h3{ font-size:15px; font-weight:700; margin:6px 0 8px; }
.ws-lb .sk-lb{ width:100%; border-collapse:collapse; font-size:14px; }
.ws-lb .sk-lb td{ padding:6px 8px; border-bottom:1px solid var(--line2,#2c4636); text-align:left; }
.ws-lb .sk-lb td:first-child{ width:34px; text-align:center; color:var(--muted2,#9fb6a8); }
.ws-lb .sk-lb td:last-child{ text-align:right; font-weight:700; white-space:nowrap; }
.ws-lb .sk-lb tr.me td{ color:var(--accent,#ffcf5c); font-weight:700; }
.ws-lb .sk-empty{ color:var(--muted2,#9fb6a8); font-size:13px; }
.ws-lb .sk-me-line{ margin-top:6px; font-size:13px; color:var(--accent,#ffcf5c); font-weight:600; }
.ws-lb .flag{ border-radius:2px; vertical-align:-1px; }
#sk-toast{ position:fixed; left:50%; bottom:26px; transform:translateX(-50%) translateY(20px);
  background:var(--panel,#0e2a20); color:var(--text,#eaf5ee); border:1px solid var(--line2,#2c4636);
  border-radius:10px; padding:10px 16px; font-size:14px; font-weight:600; opacity:0; pointer-events:none;
  transition:all .25s; z-index:60; max-width:90vw; text-align:center; }
#sk-toast.show{ opacity:1; transform:translateX(-50%) translateY(0); }
.ws-topline{display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:6px;}
.ws-help{width:30px;height:30px;border-radius:50%;background:var(--btn,#14503c);color:var(--accent,#ffcf5c);border:1px solid var(--line2,#2c4636);font-weight:700;font-size:16px;cursor:pointer;flex:0 0 auto;}
.ws-help:hover{filter:brightness(1.15);}
.ws-btn.ghost{background:transparent;border:1px solid var(--line2,#2c4636);color:var(--text,#eaf5ee);font-weight:600;}
.ws-durwrap{display:flex;flex-direction:column;gap:6px;align-items:center;min-width:180px;}
.ws-durwrap label{font-size:13px;color:var(--muted2,#9fb6a8);}
.ws-durwrap label b{color:var(--accent,#ffcf5c);font-size:15px;}
.ws-durwrap input[type=range]{width:180px;accent-color:var(--accent,#ffcf5c);}
.ws-ansrow{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;margin:2px 0 10px;}
.ws-ansrow .ws-btn{font-size:13px;padding:8px 14px;}
.ws-chip.rare{border-color:var(--accent,#ffcf5c);}
.ws-chip.rare i{color:var(--accent,#ffcf5c);}
.ws-foundlist{display:flex;flex-wrap:wrap;gap:6px;justify-content:center;margin-top:8px;}
.ws-fw{background:var(--card, var(--panel, #0e2a20));border:1px solid var(--line2,#2c4636);border-radius:8px;padding:3px 9px;font-size:13px;font-weight:600;}
.ws-mini{font-size:12px;color:var(--muted2,#9fb6a8);}
.ws-ov{position:fixed;inset:0;background:rgba(0,0,0,.6);display:flex;align-items:center;justify-content:center;padding:18px;z-index:10000;}
.ws-ov-card{background:var(--panel,#0f3d2d);border:1px solid var(--line2,#2c4636);border-radius:16px;max-width:520px;width:100%;max-height:82vh;overflow:auto;box-shadow:0 10px 40px rgba(0,0,0,.5);}
.ws-ov-h{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;border-bottom:1px solid var(--line2,#2c4636);font-size:17px;position:sticky;top:0;background:var(--panel,#0f3d2d);}
/* V670: this was 15x22px -- `border:0` and no padding -- and it is the only
   control inside a position:fixed inset:0 z-index:10000 overlay, so it is the only
   way out that looks like one. (A backdrop tap also closes it, which is why this was
   a bad target rather than a trap.) 44px is the floor everything else on the page
   holds to. */
.ws-ov-x{background:transparent;border:0;color:var(--muted2,#9fb6a8);font-size:18px;
  cursor:pointer;min-width:44px;min-height:44px;display:inline-flex;
  align-items:center;justify-content:center;}
.ws-ov-body{padding:14px 16px;text-align:left;}
.ws-rules{margin:0;padding-left:18px;line-height:1.6;font-size:14px;}
.ws-rules li{margin-bottom:8px;}

/* --- v291: Stop button, timer picker, tutorial demo, compact trace --- */
.ws-actions{ display:flex; gap:10px; justify-content:center; flex-wrap:wrap; }
.ws-btn.stop{ background:transparent; border:1px solid #e5673f; color:#ff8a6a; }
.ws-btn.stop:hover{ background:rgba(229,103,63,.12); }
/* placeholder trace is small & muted; a live swiped word stays big/gold */
/* V775: TYPE ONLY. The `min-height:22px` that used to be here is what made the board
   jump -- the prompt reserved 22px and the word wanted 30. Geometry lives in
   .ws-trace, once, for both states. */
.ws-trace.ph{ font-size:14px; font-weight:600; letter-spacing:normal; color:var(--muted2,#9fb6a8); opacity:.9; }
/* clickable TIME box (Free play, before start) */
.ws-stat.pick{ cursor:pointer; border-color:var(--accent,#ffcf5c); }
.ws-stat.pick:hover{ filter:brightness(1.08); }
.ws-stat.pick span{ color:var(--accent,#ffcf5c); }
/* second round pill button (demo) sits next to the ? */
.ws-help.ws-demo{ font-size:15px; }
/* timer stepper popup */
.ws-timer-pop{ text-align:center; }
.ws-stepper{ display:flex; align-items:center; justify-content:center; gap:16px; margin:14px 0 16px; }
.ws-step{ width:52px; height:52px; border-radius:14px; font-size:26px; font-weight:800; line-height:1;
  background:var(--btn,#14503c); color:var(--accent,#ffcf5c); border:1px solid var(--line2,#2c4636); cursor:pointer; font-family:inherit; }
.ws-step:hover{ filter:brightness(1.15); }
.ws-stepval{ min-width:74px; }
.ws-stepval b{ display:block; font-size:34px; font-weight:800; color:var(--text,#eaf5ee); }
.ws-stepval span{ font-size:12px; color:var(--muted2,#9fb6a8); text-transform:uppercase; letter-spacing:.05em; }
/* tutorial demo grid */
.ws-demo-wrap{ text-align:center; }
.ws-demo-grid{ display:grid; grid-template-columns:repeat(3,58px); gap:8px; justify-content:center; margin:6px auto 4px; }
.ws-dtile{ width:58px; height:58px; border-radius:12px; display:flex; align-items:center; justify-content:center;
  font-size:24px; font-weight:800; background:var(--card, var(--panel, #0e2a20)); border:1px solid var(--line2,#2c4636); color:var(--text,#eaf5ee);
  transition:background .18s, transform .18s, box-shadow .18s; }
.ws-dtile.on{ background:var(--accent,#ffcf5c); color:var(--accent-fg,#3d2c05); border-color:var(--accent,#ffcf5c); }
.ws-dtile.head{ transform:scale(1.08); box-shadow:0 0 0 3px rgba(255,207,92,.35); }
.ws-demo-cap{ font-size:14px; font-weight:700; color:var(--accent,#ffcf5c); min-height:20px; margin-top:8px; }
.ws-mini{ font-size:12px; color:var(--muted2,#9fb6a8); }
/* v291: leaderboard attempts (Tries) column */
.ws-lb .sk-lb tr.sk-lb-head td{ font-size:10px; text-transform:uppercase; letter-spacing:.04em; color:var(--muted2,#9fb6a8); font-weight:700; }
.ws-lb .sk-lb td.sk-tries{ text-align:right; width:52px; color:var(--muted2,#9fb6a8); font-weight:600; white-space:nowrap; }
.ws-lb .sk-lb td:nth-child(3){ text-align:right; font-weight:700; }
.ws-me-line, .ws-lb .sk-me-line{ font-size:12px; color:var(--muted2,#9fb6a8); margin-top:6px; }
/* v294: timer presets (1-60 min) */
.ws-presets{ display:flex; flex-wrap:wrap; gap:6px; justify-content:center; margin-top:4px; }
.ws-preset{ min-width:40px; padding:7px 10px; border-radius:9px; font-size:13px; font-weight:700; font-family:inherit;
  background:var(--btn,#14503c); color:var(--text,#eaf5ee); border:1px solid var(--line2,#2c4636); cursor:pointer; }
.ws-preset.active{ background:var(--accent,#ffcf5c); color:var(--accent-fg,#3d2c05); border-color:var(--accent,#ffcf5c); }
.ws-preset:hover{ filter:brightness(1.1); }

/* v614 -------------------------------------------------------------------- */
/* The target line. Says what the board holds, so a small number reads as
   progress instead of failure. Hidden until a round starts, because the board
   on screen before that is a decoy. */
.ws-target{margin:6px 0 2px;text-align:center;font-size:13px;color:var(--muted,#9aa4b2);letter-spacing:.2px}
.ws-target b{color:var(--fg, var(--text, #e8edf4));font-weight:700}
/* V775: HIDDEN, NOT REMOVED. `display:none` meant the board also moved when the
   round STARTED -- the "Everyday words: 0 of 73" line appeared and pushed the grid
   down by its own height. Same complaint, one moment earlier, so it gets the same
   answer: the line always occupies its space and is merely invisible before the
   round. (A class, not the `hidden` attribute, so test_v616's rule about `display`
   beating `[hidden]` is not in play here.) */
.ws-target.hide{visibility:hidden}

/* The hint button. Secondary weight is carried by border and font-weight, never
   opacity -- opacity:.75 measured 3.81:1 and that is not a contrast ratio. */
.ws-btn.hint{border-color:#d8a43a;color:#f0c869;font-weight:600}
.ws-btn.hint:disabled{border-color:#4a4f57;color:#8b929b;font-weight:500;cursor:default}

/* The two lit tiles. Gold ring, distinct from .on (the live swipe path) and from
   .good/.bad/.dup flashes -- a colour that already means something else would
   remove information rather than add it. */
.ws-tile.hintlit{box-shadow:inset 0 0 0 3px #d8a43a;animation:ws-hintpulse 1.1s ease-in-out 3}
@keyframes ws-hintpulse{0%,100%{box-shadow:inset 0 0 0 3px #d8a43a}50%{box-shadow:inset 0 0 0 3px rgba(216,164,58,.35)}}

.ws-final.warn{color:#f0c869}
