/* Spell Flash. A child-facing product: the games' interaction bar (44px, legible
   at 320px) over the apps' data bar (docs/new-game-preflight.md §7a). */
:root {
  /* R-C40: colours that were written out in rules, as tokens (theme-derive.py) */
  --kBg1: #0d1611;
  --kBg2: #16181c;
  --kBg3: #2e3339;
  --kBg4: #3c4650;
  --kBg5: #8ab4f8;
  --kBg6: #434a52;
  --kBg7: #2a1616;
  --kBg8: #e8eaed;
  --kBg9: rgba(138, 180, 248, .16);
  --kInk1: #5d7566;
  --kInk2: #e8eaed;
  --kInk3: #16181c;
  --kInk4: #06210f;
  --kInk5: #2a1c06;
  --kLine1: #6b2b2b;
  --kLine2: #8ab4f8;
  --kLine3: #3c4650;

  --bg: #132018; --card: #1b2c21; --ink: #eef5ee; --dim: #a9c0af;
  --accent: #5fd08a; --accentInk: #06210f;
  --line: #2e4534; --good: #5fd08a; --slow: #f0a94c; --bad: #ef6f6f; --key: #2a3f31;
}

/* R-C40: the light look. This product's own is dark; the other is chosen with the switch beside Home. */
:root[data-theme="light"] {
  --kBg1: #f1f9f4;
  --kBg2: #eff1f4;
  --kBg3: #cbcfd3;
  --kBg4: #b3bac1;
  --kBg5: #3a4f73;
  --kBg6: #b0b4ba;
  --kBg7: #f8e6e5;
  --kBg8: #242527;
  --kBg9: rgba(58, 79, 115, .16);
  --kInk1: #485f50;
  --kInk2: #010101;
  --kInk3: #bec1c7;
  --kInk4: #122d1a;
  --kInk5: #352610;
  --kLine1: #ddaeac;
  --kLine2: #3a4f73;
  --kLine3: #b3bac1;

  --bg: #effaf3;
  --card: #dfebe2;
  --ink: #1d201d;
  --dim: #445047;
  --line: #bfcfc2;
  --good: #2aa360;
  --accent: #2aa360;
  --accentInk: #122d1a;
  --slow: #c58016;
  --bad: #e46666;
  --key: #c6d5ca;
}

* { box-sizing: border-box; }
html, body {
  margin: 0; height: 100%; background: var(--bg); color: var(--ink);
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  -webkit-text-size-adjust: 100%;
  /* R-C15: the page itself never scrolls or rubber-bands; the overlays do */
  overflow: hidden; overscroll-behavior: none;
}
body { display: flex; flex-direction: column; overflow-x: hidden; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
/* HIDDEN MEANS HIDDEN. The browser's own `[hidden]` rule loses to ANY author
   rule naming an id, so `#stage { display: flex }` kept the card laid out
   behind every overlay: on a short screen its tail showed under them. */
[hidden] { display: none !important; }

#hdr {
  flex: none; display: flex; align-items: center; gap: 8px;
  padding: calc(6px + env(safe-area-inset-top)) 10px 6px;
}
.iconbtn {
  min-width: 44px; min-height: 44px; border-radius: 14px; border: 2px solid var(--line);
  background: var(--card); color: var(--ink); font-size: 20px; cursor: pointer;
}
/* the two readouts share what is left of the header row and never wrap it */
#statusLbl { margin-left: auto; font-weight: 800; font-size: 14px; color: var(--dim); white-space: nowrap; }
#tallyLbl { font-weight: 800; font-size: 14px; color: var(--dim); white-space: nowrap; }
#answer::placeholder { color: var(--kInk1); font-weight: 600; font-size: 20px; }

#main { flex: 1; position: relative; display: flex; flex-direction: column; padding: 8px 12px; min-height: 0; }

/* ---------- the card ---------- */
#stage { flex: 1; min-height: 0; display: flex; flex-direction: column; align-items: center; gap: 10px; padding-top: 6px; }
#modeTag { font-size: 14px; font-weight: 800; color: var(--dim); letter-spacing: .04em; }
#sentence { font-size: 19px; font-weight: 700; text-align: center; min-height: 52px; line-height: 1.35; }
#voiceRow { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }
/* what he has spelled so far. Not an input: the device keyboard suggested the
   word above itself on an iPad, which answers the question (R9a). */
#answer {
  width: 100%; max-width: 460px; min-height: 60px; font-size: 30px; font-weight: 800; text-align: center;
  border-radius: 16px; border: 3px solid var(--line); background: var(--kBg1); color: var(--ink);
  padding: 10px 12px; letter-spacing: .06em; display: flex; align-items: center; justify-content: center;
}
#caret { display: inline-block; width: 3px; height: 30px; margin-left: 2px; background: var(--good); }
@media (prefers-reduced-motion: no-preference) { #caret { animation: blink 1.1s steps(2) infinite; } }
@keyframes blink { 50% { opacity: 0; } }

/* ---------- the keyboard (docs/in-app-keyboard.md) ---------- */
/* Byte-identical to crossword's and word-sleuth's, on purpose: one keyboard,
   one set of habits. Only the two lines below place it in this card. */
/* The card above the keys takes 336px and the keyboard's own padding and gaps
   30px (measured at 320x568, where a 62px key put the bottom row 46px off the
   screen). A key is as tall as its size asks, down to what the screen has
   left, and never under the 44px floor. */
#kb { width: 100%; max-width: 460px; margin-top: auto; --kbmaxh: max(44px, calc((100dvh - 366px) / 4)); }
#kb {
  flex: 0 0 auto;
  display: flex; flex-direction: column; gap: 6px;
  padding: 6px 4px calc(6px + env(safe-area-inset-bottom));
  background: var(--kBg2);
  /* EVERY LETTER IS THE SAME WIDTH, as on the phone: one tenth of the row,
     whatever that row holds. Sizing keys with `flex: 1 1 0` instead makes the
     nine-key row wider than the ten-key row, and the hand learns a keyboard
     whose letters move. A short row keeps its width and CENTRES. */
  --kbgap: 5px;
  --kbkey: calc((100% - 9 * var(--kbgap)) / 10);
}
/* R-K11. FOUR LETTER SIZES, one choice for the device (`kb.size`). A key is
   one tenth of the row whatever is chosen; the letter and the key's height
   grow. S is the size this keyboard had before there was a choice. */
[data-kbsize="0"] { --kbfont: 16px; --kbh: 48px; }
[data-kbsize="1"] { --kbfont: 19px; --kbh: 50px; }
[data-kbsize="2"] { --kbfont: 22px; --kbh: 56px; }
[data-kbsize="3"] { --kbfont: 25px; --kbh: 62px; }
.kbrow { display: flex; gap: var(--kbgap); justify-content: center; }
.key {
  /* --kbmaxh is the product's: how tall a key may be before the keyboard
     leaves the screen it sits on. Unset, the size is the size. */
  flex: 0 0 var(--kbkey); min-width: 0; height: min(var(--kbh, 50px), var(--kbmaxh, 999px)); padding: 0;
  background: var(--kBg3); color: var(--kInk2); border: 0; border-radius: 8px;
  font-size: var(--kbfont, 20px); font-weight: 600; font-family: inherit; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
/* The function keys — shift, backspace, ?123, return — are one and a half
   letters wide and the lighter slate the phone gives them, so the letters read
   as one block and these do not. */
.key.wide, .key.enter { flex: 0 0 calc(var(--kbkey) * 1.5 + var(--kbgap) * 0.5); background: var(--kBg4); }
/* The space bar takes what is left of the row. Where there is no space bar its
   slot is kept, so the keys either side stay put — but it is drawn as nothing,
   because a child presses anything that looks like a key. */
.key.space { flex: 1 1 auto; }
.kbgap { flex: 1 1 auto; }
.key.go { background: var(--kBg4); }
.key.on { background: var(--kBg5); color: var(--kInk3); }
.key:active { background: var(--kBg6); }
#verdict { min-height: 40px; font-size: 24px; font-weight: 900; text-align: center; }
#verdict.good { color: var(--good); }
#verdict.slow { color: var(--slow); }
#verdict.bad { color: var(--bad); }
#verdict.showWord { color: var(--ink); letter-spacing: .12em; }
#fixRow { text-align: center; }
#fixShow { font-size: 30px; font-weight: 900; letter-spacing: .18em; }
#fixShow b { color: var(--good); }
#fixHint { font-size: 14px; color: var(--dim); margin-top: 4px; }

/* ---------- buttons ---------- */
.bigbtn, .softbtn, .chip, .listItem {
  font-family: inherit; cursor: pointer; border-radius: 16px; border: 3px solid var(--line);
  background: var(--card); color: var(--ink); font-weight: 800;
}
.bigbtn { min-height: 56px; font-size: 18px; padding: 10px 16px; width: 100%; max-width: 460px; }
.bigbtn.primary { background: var(--accent); color: var(--accentInk); border-color: var(--accent); }
.bigbtn:disabled { opacity: .45; }
.softbtn { min-height: 44px; font-size: 15px; padding: 8px 14px; }
.chip { min-height: 44px; font-size: 15px; padding: 6px 14px; border-radius: 999px; }
.chip.on { background: var(--good); color: var(--kInk4); border-color: var(--good); }
.chip.ghost { background: transparent; color: var(--dim); }
/* a destructive button, armed: the next tap does it. It must not resize:
   #btnDeleteList has its own full-width row and one line that never wraps. */
.arm { border-color: var(--bad); color: var(--bad); background: var(--kBg7); }
/* Done is the way out and looks it; deleting is small, red and set apart, so
   the two are never mistaken for each other. */
#btnDeleteList {
  width: auto; max-width: 460px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  border-color: var(--kLine1); color: var(--bad); background: transparent; font-size: 13px; padding: 6px 12px;
  margin-top: 14px; opacity: .85;
}
#editList .menuBtns { flex-direction: column-reverse; align-items: center; gap: 4px; }

/* ---------- overlays ---------- */
.overlay {
  position: absolute; inset: 0; display: none; flex-direction: column; align-items: center; gap: 10px;
  padding: 10px 12px calc(12px + env(safe-area-inset-bottom)); overflow-y: auto; background: var(--bg);
}
.overlay.show { display: flex; }
.overlay h1, .overlay h2 { margin: 6px 0; font-size: 24px; text-align: center; }
.overlay h3 { margin: 4px 0; font-size: 17px; }
.menuBtns { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; width: 100%; max-width: 460px; }
.menuBtns .softbtn { flex: 1 1 auto; }
.note { color: var(--dim); font-size: 14px; text-align: center; margin: 4px 0; max-width: 460px; }
.best { color: var(--dim); font-size: 14px; text-align: center; }
#spellerRow, #listRow { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; align-items: center;
  font-size: 15px; color: var(--dim); text-align: center; }
.field { width: 100%; max-width: 460px; }
.fieldName { display: block; font-size: 14px; color: var(--dim); margin: 6px 0 4px; }
.pickRow, .listPick { display: flex; flex-wrap: wrap; gap: 8px; }
.row { display: flex; gap: 8px; align-items: center; justify-content: center; width: 100%; max-width: 460px; }

input[type=text], textarea {
  width: 100%; max-width: 460px; font-family: inherit; font-size: 16px; padding: 10px 12px; min-height: 44px;
  border-radius: 14px; border: 3px solid var(--line); background: var(--kBg1); color: var(--ink);
}
textarea { min-height: 120px; }

/* ---------- lists ---------- */
.star { flex: 0 0 auto; font-size: 20px; }
.listItem { flex: 1 1 auto; max-width: 400px; text-align: left; padding: 12px 14px; display: flex;
  justify-content: space-between; align-items: center; gap: 10px; min-height: 56px; }
.listItem span { color: var(--dim); font-size: 13px; font-weight: 700; }
.wordRow { display: flex; gap: 8px; align-items: center; width: 100%; max-width: 460px; margin: 4px 0; }
.wordRow .w { flex: 0 0 34%; font-weight: 800; }
.wordRow .sentIn { flex: 1 1 auto; min-height: 44px; font-size: 14px; }
.wordRow.needs .sentIn { border-color: var(--slow); }
#clashNote { color: var(--slow); font-size: 14px; text-align: center; max-width: 460px; }

/* ---------- progress ---------- */
.progList { width: 100%; max-width: 460px; border: 2px solid var(--line); border-radius: 16px; padding: 10px; margin-bottom: 8px; }
.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.wchip { padding: 6px 10px; border-radius: 999px; font-size: 14px; font-weight: 800; border: 2px solid var(--line); }
.wchip.unseen { color: var(--dim); }
.wchip.learning { color: var(--kInk5); background: var(--slow); border-color: var(--slow); }
.wchip.known { color: var(--kInk4); background: var(--good); border-color: var(--good); }
.tally { display: flex; gap: 12px; justify-content: center; font-weight: 800; flex-wrap: wrap; }
.tally .good { color: var(--good); } .tally .slow { color: var(--slow); } .tally .bad { color: var(--bad); }
.rules { max-width: 460px; line-height: 1.45; font-size: 15px; }
.rules li { margin-bottom: 8px; }

#footer { flex: none; text-align: center; padding: 2px 0 6px; }

@media (prefers-reduced-motion: reduce) { * { animation: none !important; transition: none !important; } }

/* ---- settings: reading speed (R8a), voice (R38), keyboard letters ---- */
#speedTrack {
  position: relative; height: 48px; margin: 8px 22px 2px;
  touch-action: none;
}
#speedTrack::before {
  content: ''; position: absolute; left: 0; right: 0; top: 21px; height: 6px;
  border-radius: 3px; background: var(--kBg4);
}
#speedFill { position: absolute; top: 21px; height: 6px; border-radius: 3px; background: var(--kBg5); }
.speedHandle {
  position: absolute; top: 2px; width: 44px; height: 44px; margin-left: -22px;
  border: 0; border-radius: 50%; background: var(--kBg8); color: var(--kInk3);
  font-size: 20px; cursor: grab; touch-action: none; padding: 0;
  display: flex; align-items: center; justify-content: center;
}
.speedHandle:focus-visible { outline: 3px solid var(--kLine2); outline-offset: 2px; }
#speedNow { text-align: center; }
#voicePick {
  display: flex; flex-direction: column; gap: 6px;
  max-height: 240px; overflow-y: auto; -webkit-overflow-scrolling: touch;
}
.voiceRow {
  min-height: 46px; padding: 8px 12px; border: 1px solid var(--kLine3); border-radius: 12px;
  background: transparent; color: inherit; font: inherit; text-align: left; cursor: pointer;
}
.voiceRow.on { border-color: var(--kLine2); background: var(--kBg9); }
.chip.kbSize { min-width: 56px; min-height: 46px; font-size: var(--kbfont, 19px); font-weight: 600; }
