/* emlynlearns.com shared theme tokens (1 Oct 2026, revised the same evening after Carmen's first look:
 * "a better palette, more consistent; no purple").
 * Load order on every page:  <script src="/js/theme.js?v=20261001a"></script>  then  <link rel="stylesheet" href="/css/theme.css?v=20261001a">
 * theme.js sets  <html data-theme="light|dark" data-theme-choice="light|dark|auto">  before any stylesheet, so there is no flash.
 * UI KIT v1 (the k- classes at the bottom of this file): one set of buttons, cards, chips, top bar, daily card, progress bar, rules sheet, result box, toast.
 * Guide for builders: css/THEME-GUIDE.md.  Test: node tools/test-theme.js.  Demo: /theme-demo.html.
 *
 * LIGHT is the cream family of Clock Shop, Castle Defence and the Professor.  DARK is the navy family of Newton's Workshop.
 * ONE primary action colour for the whole site: Anglesey sea blue (--primary).  Buttons that DO something use it.
 * SIX shared accents, and every app picks its accent from these six: blue (= primary), green, amber, coral, teal, slate.
 * Each accent has three tokens:  --name (a fill: bars, borders, icons, shapes)   --name-text (words on bg, card or -soft)
 * --name-soft (a quiet box or chip background that takes --name-text or --text).  No purple, no violet, no pink.  No gradients.
 * Only --primary carries words on top (--on-primary).  Dark text (--ink-dark) goes on --gold and --amber fills.
 *
 * Contrast (WCAG; 15 px body text needs 4.5 or more), computed by tools/test-theme.js:
 *   LIGHT  text on bg 12.47  text on card 14.28  text on card-raised 13.72  text on panel-soft 11.95
 *          text-dim on bg 5.24  text-dim on card 6.00  text-dim on card-raised 5.77  text-dim on panel-soft 5.02
 *          on-primary on primary 5.18   -text on card: blue 6.16  green 5.36  amber 5.92  coral 5.65  teal 6.03  slate 7.03  gold 5.81
 *          -text on its -soft: blue 5.18  green 4.59  amber 5.08  coral 4.60  teal 5.01  slate 5.87
 *   DARK   text on bg 14.55  text on card 12.36  text on card-raised 10.70  text on panel-soft 9.59
 *          text-dim on bg 7.97  text-dim on card 6.77  text-dim on card-raised 5.86  text-dim on panel-soft 5.26
 *          on-primary on primary 7.20   -text on card: blue 7.39  green 8.38  amber 9.99  coral 7.66  teal 8.49  slate 8.10  gold 8.67
 *          -text on its -soft: blue 6.01  green 7.21  amber 7.71  coral 6.78  teal 6.88  slate 6.53
 *   Fills: --ink-text on --ink 14.3 both themes; --ink-dark on --gold 8.7 and on --amber 6.07 (light) / 7.65 (dark).
 */

:root {
  color-scheme: light;

  /* surfaces */
  --bg: #f4efe6;            /* page background (cream) */
  --card: #ffffff;          /* a card or panel on the page */
  --card-raised: #fffaf0;   /* a card that sits on another card, or a sticky top bar */
  --panel-soft: #f3ead8;    /* soft inset panel: progress-bar track, picture placeholder, table stripe */
  --border: #d9cdb4;        /* quiet border between cream surfaces */
  --ink: #2d2a26;           /* strong outline (dark on light, light on dark) */
  --ink-text: #ffffff;      /* text that sits on an --ink fill */
  --ink-dark: #2d2a26;      /* always dark: text on --gold / --amber fills and on painted pictures */
  --shadow: 0 2px 8px rgba(45, 42, 38, 0.10);
  --shadow-big: 0 6px 20px rgba(45, 42, 38, 0.14);
  --scrim: rgba(45, 42, 38, 0.55);   /* behind a dialog */

  /* text */
  --text: #2d2a26;
  --text-dim: #6b6254;

  /* the one primary action colour (Anglesey sea blue) */
  --primary: #2a72a6;       /* filled buttons, the chosen tab, the switch's filled segment */
  --on-primary: #ffffff;    /* words on a --primary fill */
  --primary-text: #25659a;  /* blue words on bg, card or --primary-soft */
  --primary-soft: #e1edf6;  /* a quiet blue box, chip or selected row */
  --focus: #2a72a6;         /* focus ring = primary */

  /* the six shared accents (an app picks ONE as its accent; blue is the primary) */
  --blue: #2a72a6;        --blue-text: #25659a;   --blue-soft: #e1edf6;
  --green: #2e8b57;       --green-text: #1f7a40;  --green-soft: #dff2e6;
  --amber: #e39a2a;       --amber-text: #8a5a08;  --amber-soft: #fdecc8;
  --coral: #d9603c;       --coral-text: #b2431f;  --coral-soft: #fbe3da;
  --teal: #13897e;        --teal-text: #0d6f66;   --teal-soft: #d7efeb;
  --slate: #5b6b82;       --slate-text: #4a5a70;  --slate-soft: #e6ebf2;

  /* reward gold (the materials colour, not a chrome accent): a fill with --ink-dark on it, or gold words */
  --gold: #f2c531;        --gold-text: #8a5c06;

  /* compatibility names from the first cut (1 Oct, afternoon): same colours, keep working, prefer the names above */
  --success: var(--green);  --success-text: var(--green-text);  --success-bg: var(--green-soft);
  --info: var(--blue);      --info-text: var(--blue-text);      --info-bg: var(--blue-soft);
  --amber-bg: var(--amber-soft);
  --accent-blue: var(--blue);  --accent-green: var(--green);
  --accent-red: var(--coral);  --red-text: var(--coral-text);
  --accent-purple: var(--primary);  --purple-text: var(--primary-text);   /* purple is gone: these now mean primary */
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --bg: #1a1d2b;
  --card: #252a3d;
  --card-raised: #2e344a;
  --panel-soft: #343b55;
  --border: #3d4966;
  --ink: #f1efe8;
  --ink-text: #1a1d2b;
  --ink-dark: #2d2a26;
  --shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
  --shadow-big: 0 6px 20px rgba(0, 0, 0, 0.45);
  --scrim: rgba(8, 10, 18, 0.70);

  --text: #f1efe8;
  --text-dim: #aab3c9;

  --primary: #6fb0e6;
  --on-primary: #1a1d2b;
  --primary-text: #8fc0ec;
  --primary-soft: #243a57;
  --focus: #8fc0ec;

  --blue: #6fb0e6;        --blue-text: #8fc0ec;   --blue-soft: #243a57;
  --green: #4fcf84;       --green-text: #6fdc9a;  --green-soft: #1f3b2a;
  --amber: #f2b24e;       --amber-text: #ffd27a;  --amber-soft: #4a3a1c;
  --coral: #f28a6a;       --coral-text: #ffa98e;  --coral-soft: #4d2a21;
  --teal: #4fc8bb;        --teal-text: #7ad8ce;   --teal-soft: #1c3f3b;
  --slate: #9fb0c6;       --slate-text: #b7c5d6;  --slate-soft: #2f3a4d;

  --gold: #f2c531;        --gold-text: #f2c531;

  --success: var(--green);  --success-text: var(--green-text);  --success-bg: var(--green-soft);
  --info: var(--blue);      --info-text: var(--blue-text);      --info-bg: var(--blue-soft);
  --amber-bg: var(--amber-soft);
  --accent-blue: var(--blue);  --accent-green: var(--green);
  --accent-red: var(--coral);  --red-text: var(--coral-text);
  --accent-purple: var(--primary);  --purple-text: var(--primary-text);
}

/* ── the theme switch: one segmented control, three 44 px buttons, the current one filled with --primary ──
 * Rendered by Theme.mount(); sits inline in a header row as the last item.  .compact shows icons only. */
.theme-switch {
  display: inline-flex;
  align-items: stretch;
  flex: 0 0 auto;
  margin: 0;
  padding: 0;
  border: 2px solid var(--border);
  border-radius: 12px;
  background: var(--card);
  overflow: hidden;
  vertical-align: middle;
}
.theme-switch button {
  min-height: 44px;
  min-width: 44px;
  margin: 0;
  padding: 0 12px;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-weight: 700;
  font-size: 15px;   /* the smallest text anywhere on the site is 15 px (Carmen's rule); these labels were 14 px until 18 Oct 2026 */
  line-height: 1;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.theme-switch button + button { border-left: 2px solid var(--border); }
.theme-switch button[aria-pressed="true"] { background: var(--primary); color: var(--on-primary); }
.theme-switch button[aria-pressed="true"] + button { border-left-color: var(--primary); }
.theme-switch button:focus-visible { outline: 0; box-shadow: inset 0 0 0 3px var(--ink); }
.theme-switch .ts-ico { font-size: 18px; line-height: 1; }
.theme-switch.compact button { padding: 0 10px; }
.theme-switch.compact .ts-lbl { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
/* a phone (under 480 px, audit 2 Oct 2026 P1-9): ONE button instead of three, so the page name in the bar has room.
 * It shows the current choice (☀️ 🌙 📱); each tap moves on: Light, Dark, iPad.  Its aria-label says what is on and what a tap does. */
.theme-switch .ts-cycle { display: none; border-left: 0; min-width: 44px; padding: 0 8px; }
@media (max-width: 479.98px) {
  .theme-switch > button[data-choice] { display: none; }
  .theme-switch > .ts-cycle { display: inline-flex; }
  .k-bar .theme-switch.compact > .ts-cycle { min-width: 44px; padding: 0 8px; }
}


/* ════════════════════════════════════════════════════════════════════════════════════════════════
 * UI KIT v1 (1 Oct 2026): the one set of components every app adopts by adding classes.  Standard = qa/2026-10-01/audit-ui.md section A.
 * Every colour is a token above, so Dark is right for free.  No gradients.  Every tappable thing has a pressed state
 * (80 ms, translateY(2px), brightness .92) and a visible focus ring (--focus).  Recipes and the old-selector map: THEME-GUIDE.md "UI KIT v1".
 *   buttons   .k-back  .k-primary  .k-quiet  .k-rules  .k-tap
 *   cards     .k-grid (.k-grid-4)  .k-card  .k-card-pic  .k-card-label  (.k-card-sub  .k-card-tick)  .k-card.is-on
 *   chips     .k-chips  .k-chip  .is-on  .is-done
 *   top bar   .k-bar  (.k-bar-title  .k-bar-actions)
 *   daily     .k-daily (.k-daily-pic .k-daily-main .k-daily-title .k-daily-line .k-daily-go .k-daily-pay)  .k-why (.k-why-btn: js/theme.js)
 *   progress  .k-progress (> span)  .k-progress-row  .k-progress-label
 *   sheet     .k-sheet (dialog)  .k-sheet-x  .k-sheet-back
 *   result    .k-result  .is-ok  .is-near  (.k-result-pic .k-result-text .k-result-pay)
 *   others    .k-pay  .k-paychip (.k-paychip-line .k-paychip-why)  .k-empty  .k-toast (.is-ok .is-near .is-info)  .k-h1 .k-h2 .k-h3  .k-prose  .k-dim
 * ════════════════════════════════════════════════════════════════════════════════════════════════ */

/* shared reset for everything tappable in the kit */
.k-back, .k-primary, .k-quiet, .k-rules, .k-tap, .k-card, .k-chip, .k-why > summary, .k-paychip > summary, .k-sheet-x {
  box-sizing: border-box;
  margin: 0;
  font-family: inherit;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  -webkit-appearance: none;
  appearance: none;
  transition: transform 80ms, filter 80ms;
}
/* pressed state */
.k-back:active, .k-primary:active, .k-quiet:active, .k-rules:active, .k-tap:active, .k-card:active, .k-chip:active, .k-why > summary:active, .k-paychip > summary:active, .k-sheet-x:active {
  transform: translateY(2px);
  filter: brightness(.92);
}
/* focus ring (--focus is the primary blue in Light, a pale blue in Dark) */
.k-back:focus-visible, .k-primary:focus-visible, .k-quiet:focus-visible, .k-rules:focus-visible, .k-tap:focus-visible, .k-card:focus-visible,
.k-chip:focus-visible, .k-why > summary:focus-visible, .k-paychip > summary:focus-visible, .k-sheet-x:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}
/* disabled: no press, quieter */
.k-back[disabled], .k-primary[disabled], .k-quiet[disabled], .k-rules[disabled], .k-card[disabled], .k-chip[disabled],
.k-primary.is-disabled, .k-quiet.is-disabled, .k-card.is-disabled, .k-chip.is-disabled {
  opacity: .5;
  cursor: default;
  pointer-events: none;
}

/* .k-tap: any small control that must be at least 44 by 44 */
.k-tap { min-width: 44px; min-height: 44px; display: inline-flex; align-items: center; justify-content: center; }

/* .k-back: back / home button.  Its words ("🏠 Home") are the page's business. */
.k-back {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 44px; padding: 0 14px;
  border: 2px solid var(--border); border-radius: 12px;
  background: var(--card); color: var(--text);
  font-size: 15px; font-weight: 700; white-space: nowrap;
}

/* .k-primary: THE main action of a screen (one per screen).  Arrow "➜" at the end when it moves to another screen. */
.k-primary {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 52px; padding: 0 20px;
  border: 0; border-radius: 14px;
  background: var(--primary); color: var(--on-primary);
  font-size: 17px; font-weight: 800;
}
.k-bar .k-primary { min-height: 44px; }   /* 44 is the minimum when it sits in a bar */

/* .k-quiet: a secondary button (same dress as the back button) */
.k-quiet {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 44px; padding: 0 16px;
  border: 2px solid var(--border); border-radius: 12px;
  background: var(--card); color: var(--text);
  font-size: 15px; font-weight: 700;
}

/* .k-rules: the 📖 icon button (opens a .k-sheet) */
.k-rules {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  width: 44px; height: 44px; min-width: 44px; padding: 0;
  border: 2px solid var(--border); border-radius: 12px;
  background: var(--card); color: var(--text);
  font-size: 20px; font-weight: 700;
}

/* ── picture cards ── */
.k-grid {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 12px;
  max-width: 1000px; margin: 0 auto; padding: 0; list-style: none;
}
/* phone: 2 per row */
.k-grid > .k-card { flex: 0 0 auto; width: min(240px, calc((100% - 12px) / 2 - 1px)); }
/* portrait: 3 per row */
@media (min-width: 600px) {
  .k-grid > .k-card { width: min(240px, calc((100% - 24px) / 3 - 1px)); }
}
/* 1024: 5 per row (4 in .k-grid-4) */
@media (min-width: 900px) {
  .k-grid > .k-card { width: min(240px, calc((100% - 48px) / 5 - 1px)); }
  .k-grid.k-grid-4 > .k-card { width: min(240px, calc((100% - 36px) / 4 - 1px)); }
}

.k-card {
  position: relative;
  display: flex; flex-direction: column; align-items: stretch; text-align: center;
  min-height: 190px; padding: 8px;
  border: 3px solid var(--border); border-radius: 18px;
  background: var(--card); color: var(--text);
  box-shadow: var(--shadow);
  font-size: 17px; font-weight: 800;
}
.k-card.is-on { border-color: var(--primary); background: var(--primary-soft); }
/* the picture: 120 px tall, letterboxed, never cropped */
.k-card-pic {
  display: flex; align-items: center; justify-content: center;
  height: 120px; overflow: hidden; border-radius: 12px;
  background: var(--panel-soft); font-size: 56px; line-height: 1;
}
.k-card-pic > img, .k-card-pic > svg, .k-card-pic > canvas { display: block; width: 100%; height: 100%; object-fit: contain; }
.k-card-label { display: block; padding: 10px 6px 2px; font-size: 17px; font-weight: 800; line-height: 1.25; color: var(--text); }
.k-card-sub { display: block; padding: 0 6px 6px; font-size: 15px; font-weight: 400; line-height: 1.3; color: var(--text-dim); }
.k-card-tick {
  position: absolute; top: 12px; right: 12px;
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 28px; height: 28px; padding: 0 8px; border-radius: 14px;
  background: var(--green-soft); color: var(--green-text); font-size: 15px; font-weight: 800;
}

/* ── chips (levels, options, tabs) ── */
.k-chips { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.k-chip {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 44px; padding: 0 16px;
  border: 2px solid var(--border); border-radius: 999px;
  background: var(--card); color: var(--text);
  font-size: 15px; font-weight: 700; white-space: nowrap;
}
.k-chip.is-on { border-color: var(--primary); background: var(--primary); color: var(--on-primary); }
.k-chip.is-done { border-color: var(--green-soft); background: var(--green-soft); color: var(--green-text); }

/* ── top bar: one row, 64 px, sticky.  Slots: .k-back, .k-bar-title, .k-bar-actions (🔊 📖 then the compact theme switch LAST). No subtitle. ── */
.k-bar {
  position: sticky; top: 0; z-index: 50;
  box-sizing: border-box; display: flex; flex-wrap: nowrap; align-items: center; gap: 8px;
  height: 64px; padding: 0 16px;
  background: var(--card-raised); color: var(--text);
  border-bottom: 2px solid var(--border);
}
.k-bar-title {
  flex: 1 1 auto; min-width: 0; margin: 0;
  font-size: 20px; font-weight: 800; line-height: 1.2; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.k-bar-actions { flex: 0 0 auto; display: flex; flex-wrap: nowrap; align-items: center; gap: 8px; margin-left: auto; }
.k-bar > .k-back, .k-bar > .k-rules, .k-bar > .k-quiet, .k-bar > .theme-switch { flex: 0 0 auto; }
@media (max-width: 480px) {
  .k-bar { padding: 0 10px; gap: 6px; }
  .k-bar-actions { gap: 6px; }
  .k-hide-s { display: none; }    /* optional: wrap " Home" in <span class="k-hide-s"> so the bar fits a phone */
}
/* a small phone (375): the bar now also holds the playlist pill and the 💡 (js/feedback.js, 2 Oct 2026), so its buttons give up width: icon buttons 40 wide
   (44 tall), gaps 6 px, the switch's three segments 36 wide (finding 2: Castle's bar was 6 px too wide before the two new buttons) */
@media (max-width: 399px) {
  .k-bar { padding: 0 8px; gap: 6px; }
  .k-bar > .k-back { min-width: 40px; padding: 0 8px; }
  .k-bar-actions { gap: 6px; }
  .k-bar-actions > .k-quiet, .k-bar-actions > .k-tap, .k-bar-actions > .k-rules { min-width: 40px; }
  .k-bar-actions > .k-rules { width: 40px; }
  .k-bar-actions > .k-quiet { padding: 0 8px; }
  .k-bar-actions > .k-tap { padding: 0 4px; }
  .k-bar .theme-switch.compact button { min-width: 36px; padding: 0 4px; }
}

/* ── daily card ("Today's forge"): picture slot, H2, ONE line, pay chip, Start ➜; the bullets live in <details class="k-why"> ── */
.k-daily {
  box-sizing: border-box; display: grid; grid-template-columns: 64px minmax(0, 1fr) auto; gap: 10px 14px; align-items: center;
  padding: 14px 16px;
  border: 3px solid var(--border); border-radius: 18px;
  background: var(--card); color: var(--text); box-shadow: var(--shadow);
}
.k-daily-pic {
  display: flex; align-items: center; justify-content: center;
  width: 64px; height: 64px; overflow: hidden; border-radius: 14px;
  background: var(--panel-soft); font-size: 36px; line-height: 1;
}
.k-daily-pic > img, .k-daily-pic > svg { display: block; width: 100%; height: 100%; object-fit: contain; }
.k-daily-main { min-width: 0; }
.k-daily-title { margin: 0; font-size: 22px; font-weight: 800; line-height: 1.2; color: var(--text); }
/* the line wraps onto 2 lines, never "…" (audit 2 Oct 2026, batch 1 finding 6: the raiders and the coins are the useful part) */
.k-daily-line { margin: 2px 0 0; font-size: 16px; line-height: 1.3; color: var(--text-dim); white-space: normal; overflow: hidden; overflow-wrap: break-word; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; }
.k-daily-go { display: flex; align-items: center; gap: 12px; }
.k-daily-pay {
  display: inline-flex; align-items: center; min-height: 32px; padding: 0 12px; border-radius: 999px;
  background: var(--gold); color: var(--ink-dark); font-size: 15px; font-weight: 800; white-space: nowrap;
}
.k-why { grid-column: 1 / -1; }
.k-why > summary {
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 14px;
  border: 2px solid var(--border); border-radius: 12px; background: var(--card); color: var(--text);
  font-size: 15px; font-weight: 700; list-style: none;
}
.k-why > summary::-webkit-details-marker { display: none; }
.k-why[open] > summary { background: var(--panel-soft); }
.k-why > ul, .k-why > ol { max-width: 60ch; margin: 10px 0 2px; padding-left: 1.3em; font-size: 16px; line-height: 1.5; color: var(--text); }
.k-why > ul > li, .k-why > ol > li { margin: 4px 0; }
/* "? Why" IN the row (Professor and every app, 2 Oct 2026; batch 1 finding 7): js/theme.js puts a .k-why-btn at the start of
 * .k-daily-go and marks the card .k-why-inrow; the <details> keeps the bullets and opens under the row, its own summary hidden.
 * So a closed card is one row: picture, title and line, then ? Why, the pay chip and Start. */
.k-why-btn { white-space: nowrap; }
.k-daily.k-why-inrow > .k-why > summary { display: none; }
.k-daily.k-why-inrow > .k-why:not([open]) { display: none; }
.k-daily.k-why-inrow > .k-why[open] > ul, .k-daily.k-why-inrow > .k-why[open] > ol { margin-top: 0; }
@media (max-width: 599px) {
  .k-daily { grid-template-columns: 64px minmax(0, 1fr); }
  .k-daily-go { grid-column: 1 / -1; justify-content: space-between; }
  .k-daily-go.k-why-long { flex-wrap: wrap; }   /* a long "? Why" label (Pencil Press: "How Today's page works") takes its own line on a phone, so Start is never pushed off */
  .k-daily-go .k-primary { flex: 1 1 auto; }
  .k-daily-line { -webkit-line-clamp: 3; line-clamp: 3; }   /* a phone's narrow column: 3 lines, so the raiders and the coins still fit */
}

/* ── progress bar: 12 px, rounded 6, green fill, a "3 of 8" label beside it ── */
.k-progress { display: block; box-sizing: border-box; width: 100%; height: 12px; border-radius: 6px; background: var(--panel-soft); overflow: hidden; }
.k-progress > span, .k-progress > i, .k-progress-fill { display: block; height: 100%; width: 0; border-radius: 6px; background: var(--green); transition: width 200ms; }
.k-progress-row { display: flex; align-items: center; gap: 12px; }
.k-progress-row > .k-progress { flex: 1 1 auto; }
.k-progress-label { flex: 0 0 auto; font-size: 15px; font-weight: 700; color: var(--text-dim); white-space: nowrap; }

/* ── rules sheet: the 📖 button opens a <dialog class="k-sheet">; one numbered rule per line; one "Got it" .k-primary ── */
.k-sheet {
  box-sizing: border-box; width: min(560px, calc(100vw - 32px)); max-height: 86vh; overflow: auto;
  margin: auto; padding: 20px 22px;
  border: 3px solid var(--border); border-radius: 22px;
  background: var(--card); color: var(--text); box-shadow: var(--shadow-big);
  font-size: 16px; line-height: 1.5;
}
.k-sheet::backdrop { background: var(--scrim, rgba(8, 10, 18, .6)); }
.k-sheet h2, .k-sheet .k-h2 { margin: 0 44px 10px 0; }
.k-sheet ol, .k-sheet ul { max-width: 60ch; margin: 0 0 16px; padding-left: 1.4em; }
.k-sheet li { margin: 6px 0; }
.k-sheet-x { position: absolute; top: 12px; right: 12px; display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; padding: 0; border: 2px solid var(--border); border-radius: 12px; background: var(--card); color: var(--text); font-size: 18px; font-weight: 700; }
.k-sheet-actions { display: flex; justify-content: flex-end; margin: 0; }
/* the same sheet on a plain div (when <dialog> is not an option): wrap it in .k-sheet-back */
.k-sheet-back { position: fixed; inset: 0; z-index: 99000; display: flex; align-items: center; justify-content: center; padding: 16px; background: var(--scrim); overflow: auto; }
.k-sheet-back[hidden] { display: none; }
.k-sheet-back > .k-sheet { position: relative; display: block; }
dialog.k-sheet:not([open]) { display: none; }

/* ── result box (right answer / nearly): mascot 64 px, one sentence, the pay line, Next ➜ ── */
.k-result {
  box-sizing: border-box; display: grid; grid-template-columns: 64px minmax(0, 1fr); gap: 4px 14px; align-items: center;
  padding: 14px 16px;
  border: 3px solid var(--border); border-radius: 18px;
  background: var(--card); color: var(--text);
  animation: k-in 100ms ease-out;
}
.k-result.is-ok { border-color: var(--green); }
.k-result.is-near { border-color: var(--amber); }
.k-result-pic {
  grid-row: 1 / span 2; display: flex; align-items: center; justify-content: center;
  width: 64px; height: 64px; overflow: hidden; border-radius: 14px; background: var(--panel-soft); font-size: 36px; line-height: 1;
}
.k-result-pic > img, .k-result-pic > svg { display: block; width: 100%; height: 100%; object-fit: contain; }
.k-result-text { margin: 0; font-size: 17px; font-weight: 700; line-height: 1.35; color: var(--text); }
.k-result-pay { margin: 0; font-size: 17px; font-weight: 700; color: var(--gold-text); }
.k-result > .k-primary { grid-column: 1 / -1; margin-top: 8px; justify-self: end; }
.k-result.is-ok .k-result-pic { animation: k-burst 600ms ease-out 1; }   /* the win burst: once, 600 ms, never infinite */
@keyframes k-in { from { opacity: 0; transform: translateY(4px); } }
@keyframes k-burst { 0% { transform: scale(1); } 35% { transform: scale(1.25) rotate(-6deg); } 70% { transform: scale(.95) rotate(3deg); } 100% { transform: scale(1); } }

/* ── the pay line at the top of an app: "Pays 1 copper a level, 1 sand with the Pencil" ── */
.k-pay {
  box-sizing: border-box; display: flex; align-items: center; gap: 8px; max-width: 100%;
  margin: 0; padding: 8px 14px; border: 2px solid var(--border); border-radius: 12px;
  background: var(--card); color: var(--gold-text); font-size: 16px; font-weight: 700; line-height: 1.3;
}
/* ── the pay CHIP (visual audit 2 Oct 2026, part 2, "the pay box on every tab"): the full .k-pay box stays on an app's start
 * tab; every other tab shows ONE line that opens the same box, so the task is on the first screen and the pay is never hidden.
 *   <details class="k-paychip"><summary><span class="k-paychip-line">🔵 Pays lapis</span><span class="k-paychip-why">? Why</span></summary>
 *     <div class="k-pay">…the start tab's full box…</div></details> ── */
.k-paychip { display: block; max-width: 100%; margin: 0; }
.k-paychip > summary {
  display: inline-flex; align-items: center; gap: 10px; max-width: 100%; min-height: 44px; padding: 0 6px 0 14px;
  border: 2px solid var(--border); border-radius: 999px; background: var(--card); color: var(--gold-text);
  font-size: 15px; font-weight: 800; list-style: none;
}
.k-paychip > summary::-webkit-details-marker { display: none; }
.k-paychip-line { min-width: 0; }
.k-paychip-why {
  display: inline-flex; align-items: center; flex: 0 0 auto; min-height: 32px; padding: 0 10px; border-radius: 999px;
  background: var(--panel-soft); color: var(--text); font-size: 15px; font-weight: 700; white-space: nowrap;
}
.k-paychip[open] > summary { background: var(--panel-soft); }
.k-paychip > .k-pay { margin-top: 8px; }

/* ── empty state: a picture, one sentence, one .k-primary ── */
.k-empty {
  box-sizing: border-box; display: flex; flex-direction: column; align-items: center; gap: 14px; text-align: center;
  padding: 28px 16px; border: 3px dashed var(--border); border-radius: 18px;
  background: var(--card); color: var(--text);
}
.k-empty-pic { display: flex; align-items: center; justify-content: center; height: 96px; font-size: 64px; line-height: 1; }
.k-empty-pic > img, .k-empty-pic > svg { display: block; height: 100%; width: auto; max-width: 160px; object-fit: contain; }
.k-empty-text { max-width: 40ch; margin: 0; font-size: 17px; line-height: 1.4; color: var(--text); }

/* ── toast: bottom centre, 2.5 s (Feedback.toast(text, kind) in js/feedback.js builds this) ── */
.k-toast {
  position: fixed; left: 50%; bottom: calc(max(12px, env(safe-area-inset-bottom)) + 76px); transform: translateX(-50%); z-index: 99992;
  box-sizing: border-box; display: flex; align-items: center; gap: 10px; max-width: min(92vw, 520px);
  padding: 12px 18px; border: 2px solid var(--ink); border-radius: 18px;
  background: var(--ink); color: var(--ink-text);
  box-shadow: var(--shadow-big); font-size: 16px; font-weight: 700; line-height: 1.3; pointer-events: none;
}
.k-toast::before { content: ""; flex: 0 0 auto; width: 12px; height: 12px; border-radius: 50%; background: var(--primary); }
.k-toast.is-ok::before { background: var(--green); }
.k-toast.is-near::before { background: var(--amber); }
.k-toast.is-info::before { background: var(--primary); }

/* ── type scale and text ── */
.k-h1 { margin: 0 0 8px; font-size: 28px; font-weight: 900; line-height: 1.2; color: var(--text); }
.k-h2 { margin: 0 0 6px; font-size: 22px; font-weight: 800; line-height: 1.25; color: var(--text); }
.k-h3 { margin: 0 0 4px; font-size: 17px; font-weight: 800; line-height: 1.3; color: var(--text); }
.k-prose { max-width: 60ch; font-size: 16px; line-height: 1.5; color: var(--text); }
.k-prose p, .k-prose ul, .k-prose ol { max-width: 60ch; }
.k-dim { color: var(--text-dim); }

@media (prefers-reduced-motion: reduce) {
  .k-back, .k-primary, .k-quiet, .k-rules, .k-tap, .k-card, .k-chip, .k-why > summary, .k-paychip > summary, .k-sheet-x, .k-progress > span, .k-progress > i, .k-progress-fill { transition: none; }
  .k-result, .k-result.is-ok .k-result-pic { animation: none; }
}
@media print { .k-toast { display: none; } }

/* ── QUIET PAY (Carmen, 4 Oct 2026; the PAY FOR GROWN-UPS rule in _worker.js): abuelo, the tutor and any login not on PAY_SHOWN earn
 * exactly as Emlyn does (it is all kept on the server), but see nothing about pay. js/feedback.js puts el-quiet-pay on <html> for them
 * (from /api/me quietPay). These are the shared things that state pay; a page that shows pay its own way can mark it with .el-pay.
 * Feedback.toast also drops pay toasts for them (.fb-toast.is-pay is here too, for a toast made before the class arrived). ── */
html.el-quiet-pay .k-pay, html.el-quiet-pay .k-paychip, html.el-quiet-pay .k-daily-pay, html.el-quiet-pay .k-result-pay,
html.el-quiet-pay .el-pay, html.el-quiet-pay .fb-toast.is-pay, html.el-quiet-pay .rw-toast, html.el-quiet-pay .rw-box,
html.el-quiet-pay #matPill, html.el-quiet-pay [data-bank-tick] { display: none !important; }
/* 4 Oct 2026 (build ES-CODE): the games' own material toasts (.ore-toast: every one of them says "+N material for your builds") */
html.el-quiet-pay .ore-toast { display: none !important; }

/* the Pencil pad (pencil/js/ink.js) stacks two canvases in its host; every game that loads ink.js needs these (11 Oct 2026, found on Two Lighthouses) */
.ink-host { position: relative; }
.ink-host canvas { position: absolute; left: 0; top: 0; }
.ink-top { z-index: 2; touch-action: none; }
.ink-bg { z-index: 1; pointer-events: none; }
