/* Sage Stage — a fully local classroom screen */
:root {
  --ink: #22303c;
  --ink-soft: #5b6b7b;
  --accent: #0f766e;
  --accent-soft: #ccfbf1;
  --panel: rgba(255, 255, 255, 0.92);
  --panel-border: rgba(34, 48, 60, 0.08);
  --shadow: 0 10px 30px rgba(15, 30, 45, 0.18);
  --radius: 16px;
  --danger: #dc2626;

  /* --panel stays translucent on purpose: the brand pill, the icon buttons and
     the dock all pair it with backdrop-filter and have to keep looking frosted.
     --panel-solid is for the things that sit still and should just be paper —
     modals, menus, popovers, dashboard cards. */
  --panel-solid: #fff;

  /* page and card surfaces. --surface-page is the flat ground a scrolling page
     sits on; --surface-muted is the same tone used as a well inside a card;
     --surface-tool is a half-step lighter, for small tool strips. --surface-page
     and --surface-muted share a value today — two names so they can part later. */
  --surface-page: #f1f5f5;
  --surface-muted: #f1f5f5;
  --surface-tool: #f7fafa;
  /* --surface-accent is the same tone as --accent-soft. --accent-soft means
     "this control is on"; --surface-accent means "this panel is tinted". Keep
     them apart in use even though they look the same. */
  --surface-accent: #ccfbf1;
  --surface-info: #e8f1ff;
  --info-ink: #3e6ea8; /* the ink that reads on --surface-info — 4.6:1 */

  /* lines and edges. --hairline and --track are opaque, so only use them on a
     surface you already know. Where the thing underneath could be a photo or a
     teacher-picked colour, keep the rgba(34, 48, 60, x) hairlines instead. */
  --hairline: #e9eff1;
  --track: #dce4e7;
  --border-dashed: #bac9ce;

  /* --ink-faint is for placeholder text and quiet hints. The handoff's #8b9ba5
     was 2.9:1 on white — below even the 3:1 non-text floor — so it is darkened
     here to clear 4.5:1 on white (5.0) and on --surface-page (4.6). */
  --ink-faint: #657178;
  /* --danger for fills and icons, --danger-ink for small red words: #dc2626 is
     4.8:1 on white and only 4.0:1 on #fee2e2, --danger-ink is 6.5:1 and 5.3:1. */
  --danger-ink: #a13b4b;

  /* flat card tints — decorative backgrounds only. None of these ever means a
     state, a warning or a selection; the accent and danger colours do that. */
  --tint-orange: #ffe9d6;
  --tint-blue: #e8f1ff;
  --tint-teal: #ccfbf1;
  --tint-yellow: #fff3c9;
  --tint-violet: #eee6fb;
  /* nudged from the handoff's #ffe1e6 so --ink-soft clears 4.5:1 on it (4.57) */
  --tint-pink: #ffe4e9;

  /* elevation ladder for the chrome. The maths manipulatives further down keep
     their own hand-tuned shadows — there the shadow is the object, not the UI. */
  --shadow-1: 0 6px 18px rgba(15, 30, 45, 0.06);
  --shadow-2: 0 4px 16px rgba(15, 30, 45, 0.08);
  --shadow-3: 0 8px 24px rgba(15, 30, 45, 0.07);
  --shadow-accent: 0 8px 20px rgba(15, 118, 110, 0.32);
  --shadow-dock: 0 16px 40px rgba(15, 30, 45, 0.16);
  --shadow-window: 0 24px 60px rgba(15, 30, 45, 0.22);

  /* corner ladder. --radius keeps its 16px so nothing already using it moves. */
  --radius-pill: 999px;
  --radius-sm: 14px;
  --radius-md: 20px;
  --radius-lg: 26px;
  --radius-xl: 28px;
  --radius-2xl: 32px;

  /* two faces, both already vendored in vendor/fonts. --font-ui is the stack the
     app has always run on, written down as a token so a display face can differ
     from it. Note print-pdf.html does not load fonts.css, so anything using these
     falls back to the system end of the stack in that harness. */
  --font-ui: "Quicksand", ui-rounded, "SF Pro Rounded", -apple-system, "Segoe UI", system-ui, sans-serif;
  --font-display: "Lexend", "Quicksand", sans-serif;

  font-size: 16px;
}

/* ---------- Reading fonts ---------- */
/* One attribute on <html> (set from state.readingFont at boot) rewrites the two
   face tokens; every chrome rule follows. Content fonts the teacher chose
   inside widgets keep their own stacks — this never restyles their work.
   Atkinson and OpenDyslexic ship 400/700 only, so 600/800 weights snap down —
   acceptable: both faces are designed to differentiate letters, not weights. */
html[data-reading-font='hyper'] {
  --font-ui: "Atkinson Hyperlegible", system-ui, sans-serif;
  --font-display: "Atkinson Hyperlegible", system-ui, sans-serif;
}
html[data-reading-font='dys'] {
  --font-ui: "OpenDyslexic", system-ui, sans-serif;
  --font-display: "OpenDyslexic", system-ui, sans-serif;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

/* ---------- Icons ---------- */
.ic { display: inline-flex; flex-shrink: 0; }
.ic svg { width: 1em; height: 1em; display: block; }
.icon-btn .ic svg { width: 19px; height: 19px; }
#screenNav .ic svg { width: 16px; height: 16px; }

html, body {
  height: 100%;
  overflow: hidden;
  font-family: var(--font-ui);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
}

button { font: inherit; color: inherit; cursor: pointer; border: none; background: none; }
input, select, textarea { font: inherit; color: inherit; }

#stage {
  position: fixed;
  inset: 0;
  background: linear-gradient(160deg, #134e4a, #0f766e 45%, #67e8f9);
  background-size: cover;
  background-position: center;
  overflow: hidden;
}

/* ---------- Top bar ---------- */
#topbar {
  position: fixed;
  top: 14px;
  left: 16px;
  right: 16px;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  pointer-events: none;
  z-index: 4000;
}
#topbar > * { pointer-events: auto; }

.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  padding: 8px 14px;
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow);
  backdrop-filter: blur(12px);
  font-weight: 700;
  letter-spacing: 0.2px;
  font-family: var(--font-display);
}
.brand .logo { font-size: 18px; }
#brandName { font-family: var(--font-display); font-weight: 600; }
.brand .tag {
  font-size: 14px;
  font-family: var(--font-ui);
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: var(--radius-pill);
  padding: 2px 8px;
}

.top-actions { display: flex; gap: 8px; }
/* teacher-awarded class stars: one tap, one star, without leaving the lesson */
.star-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 40px;
  padding: 0 14px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow);
  backdrop-filter: blur(12px);
  font-size: 15px;
  font-weight: 800;
  transition: transform 0.12s ease;
}
.star-pill:hover { transform: translateY(-1px); }
.star-pill .ic svg { width: 18px; height: 18px; }
.icon-btn {
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 12px;
  box-shadow: var(--shadow);
  backdrop-filter: blur(12px);
  font-size: 17px;
  transition: transform 0.12s ease;
}
.icon-btn:hover { transform: translateY(-1px); }

/* ---------- Bottom toolbar ---------- */
#toolbar {
  position: fixed;
  left: 50%;
  bottom: 14px;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 4px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow);
  backdrop-filter: blur(14px);
  padding: 8px 10px;
  z-index: 4000;
  /* 498 = both sides clearing the screen-nav pill (≈241px incl. margins) while
     centered — the old 220 let the dock slide 130px underneath the nav at 1024 */
  max-width: calc(100vw - 498px);
  overflow-x: auto;
  scrollbar-width: none;
}
#toolbar::-webkit-scrollbar { display: none; }
/* fitDock() measures, these dress. Stage 2: labels go, 34px glyphs stay in
   ≥44px targets, every tool remains visible (names live in title/aria-label).
   Stage 3: centering can't clear the nav pill, so the dock hugs the left. */
#toolbar.compact .tool .label { display: none; }
#toolbar.compact .tool { min-width: 44px; padding: 6px 5px; }
#toolbar.compact { gap: 2px; padding: 8px 6px; } /* tighten the chrome, never the 44px targets */
#toolbar.dock-left {
  /* fitDock sets --dock-left to CENTRE the bar in the span the nav pill leaves
     free. A fixed left:16px here made stage 3 a cliff: a dock 13px over the
     centred budget leapt to the window edge and left a dead gap in front of
     the nav (Glenn, 2026-08-01, in the Tauri window — 1280 default width is
     exactly the marginal case). */
  left: var(--dock-left, 16px);
  transform: none;
  /* 269 = 16px left margin + the nav pill's ~241px zone + 12px breathing room */
  max-width: calc(100vw - 269px);
}

.tool {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  min-width: 64px;
  padding: 6px 4px;
  border-radius: 12px;
  transition: background 0.12s ease;
  flex-shrink: 0;
}
.tool:hover { background: rgba(15, 118, 110, 0.1); }
.tool .glyph {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  color: var(--ink);
  background: var(--surface-muted);
  background: color-mix(in srgb, var(--acc, #c7d2fe) 26%, #fff);
  border-radius: 10px;
}
.glyph .ic svg { width: 21px; height: 21px; }
.tool .label {
  font-size: 14px; /* the screen floor — when there isn't room at 14, fitDock drops to icons, not to smaller type */
  font-weight: 600;
  color: var(--ink-soft);
  white-space: nowrap;
}

#screenNav {
  position: fixed;
  right: 16px;
  bottom: 14px;
  display: flex;
  align-items: center;
  gap: 2px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  backdrop-filter: blur(14px);
  padding: 6px 8px;
  z-index: 4000;
  font-weight: 600;
}
#screenNav button { padding: 4px 8px; border-radius: 8px; }
#deckBtn { display: flex; align-items: center; gap: 5px; }
#screenNav button:hover { background: rgba(15, 118, 110, 0.1); }
#screenLabel { font-size: 14px; padding: 0 4px; color: var(--ink-soft); }

/* ---------- Widgets ---------- */
.widget {
  position: absolute;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  /* the Soft Daylight tool-window frame: big soft corners, deep lift. The
     frosted --panel stays — opaque white over a teacher's backdrop would cost
     the stage its depth. */
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-window);
  backdrop-filter: blur(12px);
  display: flex;
  flex-direction: column;
  min-width: 150px;
  min-height: 100px;
  overflow: visible;
  color: var(--ink);
}
.widget.theme-clear {
  border-color: transparent;
  box-shadow: none;
  backdrop-filter: none;
}
.widget.theme-clear .widget-header { opacity: 0; transition: opacity 0.15s ease; }
.widget.theme-clear:hover .widget-header,
.widget.theme-clear.show-settings .widget-header { opacity: 1; }
.widget.theme-dark .text-input,
.widget.theme-dark select.text-input,
.widget.theme-dark textarea.text-input { background: rgba(255, 255, 255, 0.92); color: #22303c; }
.widget.theme-dark .widget-settings { background: rgba(255, 255, 255, 0.08); }
.widget.theme-dark .glyph,
.widget.theme-dark .tool .glyph { color: #22303c; }
.widget-header {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px 4px 16px; /* the 26px corner curves further in — keep the title clear of it */
  cursor: grab;
  user-select: none;
  flex-shrink: 0;
}
.widget-header:active { cursor: grabbing; }
.widget-title {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--ink-soft);
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  display: flex;
  align-items: center;
  gap: 6px;
}
.widget-title .ic { color: var(--ink); }
.widget-title .ic svg { width: 15px; height: 15px; }
.wbtn .ic svg { width: 13.5px; height: 13.5px; }
.widget-header .wbtn {
  width: 24px;
  height: 24px;
  border-radius: 7px;
  display: grid;
  place-items: center;
  font-size: 12px;
  color: var(--ink-soft);
  opacity: 0.55;
}
.widget:hover .wbtn { opacity: 1; }
.widget-header .wbtn:hover { background: rgba(15, 118, 110, 0.12); color: var(--ink); }
.widget-header .wbtn.close:hover { background: #fee2e2; color: var(--danger); }

.widget-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: 4px 12px 12px;
  overflow: auto;
  min-height: 0;
}

.widget-settings {
  border-top: 1px dashed var(--panel-border);
  padding: 8px 12px;
  display: none;
  flex-direction: column;
  gap: 7px;
  font-size: 14px;
  background: rgba(241, 245, 244, 0.7);
  flex-shrink: 0;
  border-radius: 0 0 calc(var(--radius-lg) - 2px) calc(var(--radius-lg) - 2px);
}

/* ---------- Settings side panel ---------- */
.spanel {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(380px, 92vw);
  background: var(--panel-solid);
  box-shadow: -12px 0 40px rgba(15, 30, 45, 0.2);
  z-index: 4800;
  display: flex;
  flex-direction: column;
  animation: spanel-in 0.18s ease;
}
@keyframes spanel-in {
  from { transform: translateX(30px); opacity: 0; }
}
.spanel-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--panel-border);
  flex-shrink: 0;
}
.spanel-head .ic svg { width: 27px; height: 27px; }
.spanel-head h3 { flex: 1; font-size: 19px; font-family: var(--font-display); }
.spanel-close {
  width: 36px;
  height: 36px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  color: var(--ink-soft);
}
.spanel-close:hover { background: rgba(15, 118, 110, 0.1); color: var(--ink); }
.spanel-close .ic svg { width: 16px; height: 16px; }
.spanel-body {
  flex: 1;
  overflow: auto;
  padding: 14px 20px 26px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.spanel-body h4 {
  font-size: 14px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--ink-soft);
  margin-top: 12px;
}
.spanel-sec { display: flex; flex-direction: column; gap: 9px; font-size: 14px; }

/* per-widget color themes (mini theme cards) */
.theme-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(56px, 1fr));
  gap: 8px;
}
.theme-card {
  height: 48px;
  border-radius: 11px;
  border: 2px solid rgba(34, 48, 60, 0.14);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 6px;
  transition: transform 0.1s ease;
}
.theme-card:hover { transform: scale(1.07); }
.theme-card.active { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.theme-card.checker {
  background: repeating-conic-gradient(#cbd5e1 0% 25%, #fff 0% 50%) 0 0 / 8px 8px;
}
.tc-bar { width: 26px; height: 5px; border-radius: var(--radius-pill); display: block; }
.tc-row { display: flex; align-items: center; gap: 3px; }
.tc-bar.tc-short { width: 16px; }
.tc-dot { width: 5px; height: 5px; border-radius: 50%; }

/* floating text formatting toolbar */
.text-toolbar {
  position: absolute;
  bottom: 100%;
  left: 0;
  margin-bottom: 8px;
  display: none;
  align-items: center;
  gap: 2px;
  background: var(--panel-solid);
  border: 1px solid var(--panel-border);
  border-radius: 12px;
  box-shadow: var(--shadow);
  padding: 4px 6px;
  z-index: 60;
  white-space: nowrap;
  color: #22303c;
}
.widget.editing .text-toolbar { display: flex; }
.text-toolbar.below {
  bottom: auto;
  top: 100%;
  margin: 8px 0 0;
}
.tb-btn {
  min-width: 28px;
  height: 28px;
  padding: 0 4px;
  border-radius: 8px;
  display: grid;
  place-items: center;
  font-size: 14px;
  font-weight: 700;
}
.tb-btn:hover { background: rgba(15, 118, 110, 0.12); }
.tb-btn.i { font-style: italic; }
.tb-btn.u { text-decoration: underline; }
.tb-btn .ic svg { width: 16px; height: 16px; }
.tb-btn.tb-dot {
  min-width: 16px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 1px solid rgba(34, 48, 60, 0.3);
  margin: 0 2px;
}
.tb-sep { width: 1px; height: 18px; background: rgba(34, 48, 60, 0.15); margin: 0 4px; }
.tb-btn.tb-fontbtn {
  min-width: 92px;
  justify-content: flex-start;
  display: flex;
  align-items: center;
  padding: 0 8px;
}
.tb-fontname {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}
.tb-btn.tb-fontbtn::after {
  content: "";
  margin-left: auto;
  border: 4px solid transparent;
  border-top-color: var(--ink-soft);
  transform: translateY(2px);
}
.tb-size {
  width: 52px;
  border: 1px solid var(--panel-border);
  border-radius: 8px;
  font-size: 14px;
  font-weight: 700;
  text-align: center;
  padding: 4px 2px;
  background: var(--panel-solid);
}
.tb-grip { cursor: grab; }
.tb-grip:active { cursor: grabbing; }
.tb-cur {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 1px solid rgba(34, 48, 60, 0.25);
  display: block;
}

/* toolbar popovers (font menu, color palettes) */
.tb-pop {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  background: var(--panel-solid);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  padding: 12px;
  z-index: 240;
  white-space: normal;
}
.text-toolbar.below .tb-pop { top: calc(100% + 8px); }
.tb-fontmenu {
  display: flex;
  flex-direction: column;
  min-width: 190px;
  max-height: 320px;
  overflow: auto;
  padding: 6px;
}
.tb-fontmenu button {
  text-align: left;
  padding: 8px 12px;
  border-radius: 9px;
  font-size: 16px;
  color: #22303c;
}
.tb-fontmenu button:hover { background: rgba(15, 118, 110, 0.1); }
.tb-swatch-row { display: flex; gap: 8px; margin-top: 8px; }
.tb-swatch-row:first-child { margin-top: 0; }
.tb-swatch {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 1px solid rgba(34, 48, 60, 0.22);
  transition: transform 0.1s ease;
}
.tb-swatch:hover { transform: scale(1.15); }
.tb-swatch.tb-none {
  position: relative;
  background: #fff;
}
.tb-swatch.tb-none::after {
  content: "";
  position: absolute;
  inset: 3px;
  border-radius: 50%;
  background: linear-gradient(to top right, transparent 44%, #dc2626 46%, #dc2626 54%, transparent 56%);
}
.tb-swatch.tb-add {
  background: rgba(34, 48, 60, 0.07);
  font-size: 14px;
  font-weight: 700;
  color: var(--ink-soft);
  display: grid;
  place-items: center;
}

/* widget ⋮ menu */
.wmenu {
  position: absolute;
  top: 32px;
  right: 4px;
  background: var(--panel-solid);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  padding: 6px;
  z-index: 220;
  min-width: 216px;
  color: #22303c;
}
.wmenu button {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 7px 10px;
  border-radius: 9px;
  font-size: 14px;
  font-weight: 600;
  color: #22303c;
}
.wmenu button:hover { background: rgba(15, 118, 110, 0.1); }
.wmenu .ic svg { width: 15px; height: 15px; }
.wmenu kbd {
  margin-left: auto;
  background: rgba(34, 48, 60, 0.08);
  border-radius: 6px;
  padding: 2px 7px;
  font-size: 14px;
  font-family: inherit;
  color: var(--ink-soft);
}
.wmenu hr { border: none; border-top: 1px solid rgba(34, 48, 60, 0.1); margin: 4px 6px; }

/* locked widgets */
.widget.locked .resize-handle { display: none; }
.widget.locked .widget-header { cursor: default; }

/* spotlight */
.spotlight-overlay {
  position: absolute;
  inset: 0;
  background: rgba(8, 18, 28, 0.72);
  cursor: pointer;
}
.spotlight-hint {
  position: absolute;
  bottom: 26px;
  left: 50%;
  transform: translateX(-50%);
  color: rgba(255, 255, 255, 0.75);
  font-size: 14px;
  font-weight: 600;
}
.widget.show-settings .widget-settings { display: flex; }

.resize-handle {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 20px;
  height: 20px;
  cursor: nwse-resize;
  opacity: 0.4;
}
.resize-handle::after {
  content: "";
  position: absolute;
  right: 5px;
  bottom: 5px;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--ink-soft);
  border-bottom: 2px solid var(--ink-soft);
  border-radius: 2px;
}

/* generic controls inside widgets */
.row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.grow { flex: 1; }
.btn {
  background: var(--accent);
  color: #fff;
  font-weight: 600;
  font-size: 14px;
  padding: 7px 14px;
  border-radius: 10px;
  transition: filter 0.12s ease;
}
.btn:hover { filter: brightness(1.1); }
.btn.ghost {
  background: rgba(15, 118, 110, 0.1);
  color: var(--accent);
}
.btn.small { padding: 4px 10px; font-size: 14px; }
/* --danger-ink, not --danger: these are all small red words on the tint, which
   is the case that comment was written for. #dc2626 was 4.0:1 here, under the
   floor; #a13b4b is 5.3:1. */
.btn.danger { background: #fee2e2; color: var(--danger-ink); }
/* The class list editor's action row runs green → amber → red. Inks are picked
   the way --danger-ink was: #166534 is 6.5:1 on its tint and #92400e is 6.4:1,
   both clear of 4.5:1. These say what the button does, unlike the --tint-*
   swatches, which stay decorative. */
.btn.go { background: #dcfce7; color: #166534; }
.btn.warn { background: #fef3c7; color: #92400e; }

.text-input, select.text-input {
  border: 1px solid var(--panel-border);
  background: var(--panel-solid);
  border-radius: 9px;
  padding: 6px 9px;
  font-size: 14px;
  width: 100%;
}
input[type="range"] { accent-color: var(--accent); }
input[type="checkbox"] { accent-color: var(--accent); width: 15px; height: 15px; }

.hint { font-size: 14px; color: var(--ink-soft); }

/* ---------- Widget specifics ---------- */

/* clock */
.clock-digital {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  text-align: center;
  line-height: 1.05;
  font-family: var(--font-display);
  margin: auto;
}
.clock-date { font-size: max(0.3em, 14px); font-weight: 600; color: var(--ink-soft); margin-top: 6px; }
.clock-analog { margin: auto; }

/* timer / stopwatch */
.time-display {
  font-variant-numeric: tabular-nums;
  font-weight: 800;
  font-family: var(--font-display);
  text-align: center;
  margin: auto;
  line-height: 1;
}
.time-display.finished { color: var(--danger); animation: pulse 0.8s infinite; }
@keyframes pulse { 50% { opacity: 0.35; } }
.timer-bar {
  height: 7px;
  border-radius: 99px;
  background: rgba(34, 48, 60, 0.12);
  overflow: hidden;
  margin: 6px 0;
  flex-shrink: 0;
}
.timer-bar > div { height: 100%; background: var(--accent); border-radius: 99px; transition: width 0.3s linear; }
.center-row { display: flex; justify-content: center; gap: 8px; flex-wrap: wrap; flex-shrink: 0; }

/* traffic light */
.tl-wrap { display: flex; align-items: center; justify-content: center; flex: 1; }
.tl-body {
  background: #26323c;
  border-radius: 22px;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.tl-light {
  border-radius: 50%;
  border: none;
  opacity: 0.25;
  transition: opacity 0.15s ease, box-shadow 0.15s ease;
}
.tl-light.on { opacity: 1; }
.tl-light.red { background: #ef4444; }
.tl-light.red.on { box-shadow: 0 0 24px 4px rgba(239, 68, 68, 0.7); }
.tl-light.amber { background: #f59e0b; }
.tl-light.amber.on { box-shadow: 0 0 24px 4px rgba(245, 158, 11, 0.7); }
.tl-light.green { background: #22c55e; }
.tl-light.green.on { box-shadow: 0 0 24px 4px rgba(34, 197, 94, 0.7); }

/* text widget */
.text-edit {
  flex: 1;
  outline: none;
  line-height: 1.4;
  overflow: auto;
}
.text-edit:empty::before { content: "Type here…"; color: var(--ink-soft); opacity: 0.6; }

/* name picker */
.picker-result {
  flex: 1;
  display: grid;
  place-items: center;
  font-weight: 800;
  text-align: center;
  overflow: hidden;
  word-break: break-word;
}
.picker-result.rolling { color: var(--accent); }

/* dice */
.dice-row { flex: 1; display: flex; align-items: center; justify-content: center; gap: 14px; }
.die {
  background: #fff;
  border: 2px solid var(--ink);
  border-radius: 18%;
  display: grid;
  grid-template: repeat(3, 1fr) / repeat(3, 1fr);
  padding: 10%;
  aspect-ratio: 1;
  cursor: pointer;
  box-shadow: 0 4px 10px rgba(15, 30, 45, 0.15);
}
.die span { border-radius: 50%; background: var(--ink); transform: scale(0); transition: transform 0.1s; }
.die span.on { transform: scale(0.72); }
.dice-total { text-align: center; font-weight: 700; color: var(--ink-soft); flex-shrink: 0; }

/* sound meter */
.sound-canvas { flex: 1; width: 100%; min-height: 0; border-radius: 10px; }
.sound-status { text-align: center; font-weight: 800; padding: 4px 0; flex-shrink: 0; }

/* work symbols */
.symbol-display { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; text-align: center; min-height: 0; }
.symbol-face { line-height: 1; color: var(--ink); }
.symbol-face svg { width: 1em; height: 1em; display: block; }
.symbol-label { font-weight: 800; }
.symbol-picker { display: flex; gap: 6px; justify-content: center; flex-wrap: wrap; flex-shrink: 0; }
.symbol-picker button {
  padding: 6px 8px;
  border-radius: 10px;
  color: var(--ink);
  background: color-mix(in srgb, var(--acc, #c7d2fe) 22%, #fff);
  border: 2px solid transparent;
}
.symbol-picker button .ic svg { width: 21px; height: 21px; }
.symbol-picker button.active { border-color: var(--accent); }

/* poll */
.poll-question { font-weight: 800; text-align: center; padding: 2px 0 8px; }
.poll-options { display: flex; flex-direction: column; gap: 8px; flex: 1; overflow: auto; }
.poll-opt { display: flex; align-items: center; gap: 8px; }
.poll-opt .bar-wrap { flex: 1; background: rgba(34, 48, 60, 0.09); border-radius: 9px; overflow: hidden; height: 30px; position: relative; }
.poll-opt .bar { height: 100%; background: var(--accent); opacity: 0.85; border-radius: 9px; transition: width 0.25s ease; }
.poll-opt .bar-label {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 10px; font-weight: 700; font-size: 13.5px;
}
.poll-opt .vote { font-size: 16px; }

/* agenda */
.agenda-list { display: flex; flex-direction: column; gap: 4px; flex: 1; overflow: auto; }
.agenda-item { display: flex; align-items: center; gap: 8px; padding: 5px 6px; border-radius: 9px; }
.agenda-item:hover { background: rgba(34, 48, 60, 0.05); }
.agenda-item.done .agenda-text { text-decoration: line-through; opacity: 0.5; }
.agenda-time { font-weight: 700; color: var(--accent); font-variant-numeric: tabular-nums; font-size: 0.9em; }
.agenda-text { flex: 1; }
.agenda-item .rm { opacity: 0; color: var(--danger); }
.agenda-item:hover .rm { opacity: 0.8; }

/* image / embed / qr */
.media-fill { flex: 1; min-height: 0; position: relative; display: grid; place-items: center; overflow: hidden; }
.media-fill img,
.media-fill canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  border-radius: 10px;
}
.media-fill img.cover { object-fit: cover; }
.media-fill iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: none; border-radius: 10px; background: #fff; }
.media-fill video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  border-radius: 10px;
  background: #000;
}
.media-fill video.mirror { transform: scaleX(-1); }

/* document previews */
.document-scroll {
  position: absolute;
  inset: 0;
  overflow: auto;
  border-radius: 10px;
  background: #fff;
  color: #22303c;
  text-align: left;
}
.document-text {
  min-width: 100%;
  min-height: 100%;
  box-sizing: border-box;
  margin: 0;
  padding: 14px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font: 13px/1.5 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.document-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.document-table th,
.document-table td {
  max-width: 320px;
  padding: 6px 8px;
  border: 1px solid #dbe3e8;
  overflow-wrap: anywhere;
  vertical-align: top;
}
.document-table th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: #edf6f4;
  font-weight: 800;
}
.document-table tr:nth-child(even) td { background: #f8fafc; }
.document-loading { padding: 18px; color: #5b6b7b; }
.document-note {
  position: sticky;
  left: 0;
  bottom: 0;
  padding: 6px 9px;
  background: #fff7ed;
  color: #9a3412;
  font-size: 11px;
  font-weight: 700;
}
.document-message {
  max-width: 300px;
  padding: 18px;
  display: grid;
  justify-items: center;
  gap: 8px;
  text-align: center;
  color: var(--ink-soft);
}
.document-message strong { color: var(--ink); }
.document-message-icon { font-size: 38px; }

/* calendar */
.cal-head { display: flex; align-items: center; gap: 6px; padding-bottom: 6px; flex-shrink: 0; }
.cal-title { flex: 1; text-align: center; font-weight: 800; border-radius: 8px; padding: 3px 0; }
.cal-title:hover { background: rgba(15, 118, 110, 0.08); }
.cal-grid { flex: 1; display: grid; grid-template-columns: repeat(7, 1fr); grid-auto-rows: 1fr; gap: 2px; min-height: 0; }
.cal-dow { font-size: 10px; text-transform: uppercase; color: var(--ink-soft); display: grid; place-items: center; font-weight: 700; }
.cal-day { display: grid; place-items: center; border-radius: 8px; font-weight: 600; font-size: 13px; }
.cal-day.other { opacity: 0.3; }
.cal-day.today { background: var(--accent); color: #fff; font-weight: 800; }

/* countdown */
.count-label { text-align: center; font-weight: 700; color: var(--ink-soft); flex-shrink: 0; }
.count-main { flex: 1; display: grid; place-items: center; font-weight: 800; text-align: center; min-height: 0; }
.count-sub { text-align: center; color: var(--ink-soft); font-weight: 600; flex-shrink: 0; }

/* hyperlink */
.link-big { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; }
.link-big .btn { font-size: 17px; padding: 12px 20px; }
.link-url { font-size: 11px; color: var(--ink-soft); word-break: break-all; text-align: center; }

/* sticker */
.sticker-face { flex: 1; display: grid; place-items: center; line-height: 1; user-select: none; }

/* scoreboard */
.score-grid { flex: 1; display: grid; gap: 8px; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); overflow: auto; }
.score-card {
  background: rgba(15, 118, 110, 0.07);
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 8px;
}
.score-name { font-weight: 700; font-size: 13px; text-align: center; }
.score-val { font-family: var(--font-display); font-weight: 800; font-size: 40px; line-height: 1; font-variant-numeric: tabular-nums; }
.score-btns { display: flex; gap: 6px; }
.score-btns button {
  width: 36px;
  height: 30px;
  border-radius: 9px;
  background: rgba(34, 48, 60, 0.08);
  font-weight: 800;
  font-size: 16px;
}
.score-btns button:hover { background: rgba(15, 118, 110, 0.18); }

/* activity games --------------------------------------------------------- */
.prompt-game,
.word-game,
.memory-game,
.ttt-game,
.connect-game,
.countdown-game,
.strategy-game {
  min-height: 0;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.game-title-row {
  min-height: 28px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-shrink: 0;
}
.game-title-row strong { font-size: clamp(15px, 2.3vh, 21px); }
.game-score { color: var(--ink-soft); font-size: 12px; font-weight: 800; text-align: right; }
.game-actions { display: flex; align-items: center; justify-content: center; gap: 8px; flex-wrap: wrap; flex-shrink: 0; }

/* prompt cards */
.prompt-card {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-rows: auto 1fr auto;
  place-items: center;
  gap: 8px;
  padding: clamp(15px, 4vw, 34px);
  border-radius: 22px;
  color: #172033;
  background:
    radial-gradient(circle at 12% 18%, rgba(255,255,255,.75) 0 7%, transparent 7.4%),
    radial-gradient(circle at 88% 82%, rgba(255,255,255,.55) 0 10%, transparent 10.4%),
    linear-gradient(145deg, #fde68a, #f9a8d4 54%, #c4b5fd);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.5), 0 8px 20px rgba(88,28,135,.12);
  text-align: center;
  overflow: hidden;
}
.prompt-card.is-hidden {
  background:
    repeating-linear-gradient(135deg, rgba(255,255,255,.08) 0 8px, transparent 8px 16px),
    linear-gradient(145deg, #0f766e, #1e3a8a);
  color: #fff;
  cursor: pointer;
}
.prompt-kicker { font-size: 11px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; opacity: .7; }
.prompt-word { align-self: center; font-size: clamp(28px, 7vh, 64px); line-height: 1.08; font-weight: 800; overflow-wrap: anywhere; }
.prompt-progress { font-size: 12px; font-weight: 800; opacity: .65; }

/* word builder */
.word-main { flex: 1; min-height: 0; display: grid; grid-template-columns: minmax(120px, .72fr) minmax(240px, 1.7fr); gap: 14px; }
.word-build-art {
  position: relative;
  min-height: 0;
  display: grid;
  place-items: center;
  border-radius: 20px;
  background: color-mix(in srgb, var(--skin) 15%, #fff);
  border: 2px dashed color-mix(in srgb, var(--skin) 55%, #fff);
  overflow: hidden;
}
.word-build-ghost,
.word-build-reveal {
  position: absolute;
  font-size: clamp(68px, 14vw, 150px);
  line-height: 1;
  user-select: none;
}
.word-build-ghost { filter: grayscale(1); opacity: .11; }
.word-build-reveal { transition: clip-path .32s ease; filter: drop-shadow(0 8px 8px rgba(15,30,45,.15)); }
.word-build-count {
  position: absolute;
  right: 9px;
  bottom: 8px;
  padding: 4px 8px;
  border-radius: 999px;
  background: rgba(255,255,255,.82);
  color: #475569;
  font-size: 11px;
  font-weight: 800;
}
.word-play { min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: 12px; }
.word-mask { display: flex; align-items: flex-end; justify-content: center; gap: 5px; flex-wrap: wrap; min-height: 44px; }
.word-letter {
  width: clamp(23px, 4.2vw, 42px);
  min-height: clamp(32px, 5.2vw, 50px);
  display: grid;
  place-items: center;
  border-bottom: 4px solid currentColor;
  font-size: clamp(20px, 4vw, 38px);
  line-height: 1;
  font-weight: 800;
}
.word-space { width: 14px; }
.word-keys { display: grid; grid-template-columns: repeat(9, 1fr); gap: 5px; }
.word-key {
  min-width: 0;
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  border-radius: 8px;
  background: rgba(34,48,60,.08);
  font-size: clamp(10px, 1.7vw, 15px);
  font-weight: 800;
}
.word-key:hover:not(:disabled) { background: color-mix(in srgb, var(--accent) 18%, transparent); }
.word-key.hit { background: #bbf7d0; color: #166534; }
.word-key.miss { background: #fee2e2; color: #991b1b; opacity: .7; }
.word-result { border-radius: 10px; padding: 6px 10px; text-align: center; font-size: 12px; font-weight: 800; }
.word-result.won { background: #dcfce7; color: #166534; }
.word-result.lost { background: #fff7ed; color: #9a3412; }

/* memory */
.memory-grid {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(var(--memory-cols, 4), minmax(42px, 1fr));
  gap: clamp(5px, 1vw, 10px);
  perspective: 900px;
}
.memory-card {
  position: relative;
  min-height: 38px;
  border-radius: 13px;
  transform-style: preserve-3d;
  transition: transform .28s ease, opacity .2s ease;
  background: transparent;
}
.memory-card.open,
.memory-card.matched { transform: rotateY(180deg); }
.memory-card.matched { opacity: .48; }
.memory-card > span {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  border-radius: inherit;
  backface-visibility: hidden;
  overflow: hidden;
}
.memory-back {
  color: #fff;
  background:
    radial-gradient(circle at 30% 25%, rgba(255,255,255,.25) 0 8%, transparent 8.5%),
    linear-gradient(145deg, #0f766e, #2563eb);
  box-shadow: inset 0 0 0 2px rgba(255,255,255,.35);
  font-size: clamp(18px, 4vh, 34px);
}
.memory-face {
  transform: rotateY(180deg);
  background: #fffdf5;
  color: #243142;
  border: 2px solid rgba(34,48,60,.09);
  padding: 6px;
  text-align: center;
  font-size: clamp(17px, 4.2vh, 34px);
  font-weight: 800;
  overflow-wrap: anywhere;
}

/* tic tac toe */
.ttt-grid {
  width: min(100%, 330px);
  flex: 1;
  min-height: 0;
  aspect-ratio: 1;
  align-self: center;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 7px;
  padding: 8px;
  border-radius: 20px;
  background: #173d36;
  box-shadow: inset 0 0 0 2px rgba(255,255,255,.13);
}
.ttt-cell {
  border-radius: 13px;
  background: #f8fafc;
  font-size: clamp(34px, 9vh, 72px);
  line-height: 1;
  font-weight: 800;
  transition: transform .12s ease, background .15s ease;
}
.ttt-cell:hover:empty { background: #ecfeff; }
.ttt-cell.mark-X { color: #f59e0b; }
.ttt-cell.mark-O { color: #10b981; }
.ttt-cell.winner { background: #fef3c7; animation: game-pop .55s ease infinite alternate; }
@keyframes game-pop { to { transform: scale(.94); } }

/* connect four */
.connect-board { flex: 1; min-height: 0; display: flex; flex-direction: column; align-items: center; }
.connect-drops,
.connect-grid { width: min(100%, 480px); display: grid; grid-template-columns: repeat(7, 1fr); }
.connect-drops { padding: 0 9px; }
.connect-drops button { color: #4f46e5; font-size: 12px; padding: 2px; opacity: .25; }
.connect-drops button:hover { opacity: 1; transform: translateY(2px); }
.connect-grid {
  flex: 1;
  min-height: 0;
  aspect-ratio: 7 / 6;
  gap: clamp(3px, .7vw, 7px);
  padding: clamp(7px, 1.2vw, 12px);
  border-radius: 20px;
  background: linear-gradient(145deg, #6366f1, #4338ca);
  box-shadow: inset 0 0 0 3px rgba(255,255,255,.18), 0 8px 20px rgba(49,46,129,.18);
}
.connect-slot { min-width: 0; min-height: 0; display: grid; place-items: center; }
.connect-slot span {
  width: 100%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: color-mix(in srgb, var(--ink) 11%, #fff);
  box-shadow: inset 0 3px 8px rgba(15,30,45,.18);
}
.connect-slot.coral span { background: #fb7185; }
.connect-slot.gold span { background: #facc15; }
.connect-slot.winner span { outline: 4px solid #fff; outline-offset: -5px; animation: game-pop .55s ease infinite alternate; }

/* numbers and letters */
.countdown-tabs { display: flex; gap: 4px; padding: 3px; border-radius: 10px; background: rgba(34,48,60,.07); }
.countdown-tabs button { padding: 4px 9px; border-radius: 7px; font-size: 11px; font-weight: 800; }
.countdown-tabs button.active { background: #fff; color: #2563eb; box-shadow: 0 2px 6px rgba(15,30,45,.12); }
.countdown-target {
  align-self: center;
  min-width: 155px;
  padding: 10px 20px;
  border-radius: 14px;
  background: #e0f2fe;
  border: 3px solid #38bdf8;
  color: #075985;
  font: 800 clamp(34px, 8vh, 68px)/1 "Graduate", monospace;
  text-align: center;
  letter-spacing: .08em;
}
.countdown-target.word-target { font-size: clamp(18px, 4vh, 32px); }
.countdown-tiles { flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; gap: clamp(5px, 1.3vw, 12px); flex-wrap: wrap; }
.countdown-tiles span {
  min-width: clamp(42px, 8vw, 72px);
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  border-radius: 11px;
  background: linear-gradient(145deg, #2563eb, #1d4ed8);
  color: #fff;
  box-shadow: inset 0 0 0 2px rgba(255,255,255,.2), 0 4px 10px rgba(30,64,175,.2);
  font: 800 clamp(21px, 5vh, 42px)/1 "Graduate", monospace;
}
.countdown-instruction { color: var(--ink-soft); font-size: 12px; font-weight: 700; text-align: center; }

/* strategy boards */
.strategy-board-wrap { flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; gap: 12px; }
.strategy-grid {
  height: 100%;
  max-width: calc(100% - 58px);
  aspect-ratio: 1;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  overflow: hidden;
  border: 6px solid #27364b;
  border-radius: 14px;
  background: #fff7ed;
}
.strategy-cell { min-width: 0; min-height: 0; display: grid; place-items: center; background: #fff7ed; }
.strategy-cell:nth-child(8n + 2),
.strategy-cell:nth-child(8n + 4),
.strategy-cell:nth-child(8n + 5),
.strategy-cell:nth-child(8n + 7) { background: #fb923c; }
.strategy-piece {
  width: 67%;
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  border-radius: 50%;
  font-size: clamp(20px, 5.6vh, 46px);
  line-height: 1;
  filter: drop-shadow(0 3px 2px rgba(15,30,45,.25));
}
.strategy-cell.side-light .strategy-piece { color: #fffaf0; background: #fff; text-shadow: 0 1px 2px #786f60; }
.strategy-cell.side-dark .strategy-piece { color: #111827; background: #26323c; }
.strategy-cell.selected { outline: 5px solid #22c55e; outline-offset: -5px; }
.strategy-choices { display: flex; flex-direction: column; gap: 6px; }
.strategy-choices button { width: 42px; height: 42px; border-radius: 10px; background: rgba(34,48,60,.08); font-size: 25px; }
.strategy-choices button.active { background: #c4b5fd; outline: 2px solid #7c3aed; }

@media (max-width: 680px) {
  .word-main { grid-template-columns: 1fr; }
  .word-build-art { min-height: 95px; }
  .word-build-ghost, .word-build-reveal { font-size: 76px; }
  .word-keys { grid-template-columns: repeat(7, 1fr); }
  .game-title-row { align-items: flex-start; }
}

/* "More" panel */
.tool-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: 6px; }
.tool-cell {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 12px 4px 8px;
  border-radius: 12px;
  cursor: pointer;
}
.tool-cell:hover { background: rgba(15, 118, 110, 0.08); }
.tool-cell .glyph {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  color: var(--ink);
  background: #f1f5f4;
  background: color-mix(in srgb, var(--acc, #c7d2fe) 26%, #fff);
  border-radius: 10px;
}
.tool-cell .label {
  font-size: 11px;
  font-weight: 600;
  color: var(--ink-soft);
  /* wraps rather than clips. nowrap + overflow:hidden in a 92px cell was quietly
     eating the last word of the longest names — "Numbers & letters" lost its
     tail long before "Place value counters" arrived to make it obvious. A widget
     you cannot read the name of is one you cannot find. */
  text-align: center;
  line-height: 1.25;
  overflow-wrap: break-word;
  max-width: 100%;
}
.pin-btn {
  position: absolute;
  top: 2px;
  right: 2px;
  color: var(--ink-soft);
  opacity: 0.25;
  padding: 3px 4px;
  border-radius: 6px;
}
.pin-btn .ic svg { width: 12px; height: 12px; }
.pin-btn.pinned { opacity: 1; color: var(--ink); }
.pin-btn:hover { background: rgba(15, 118, 110, 0.15); opacity: 1; }

/* groups */
.groups-out { flex: 1; overflow: auto; display: grid; gap: 8px; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); align-content: start; }
.group-card { background: rgba(15, 118, 110, 0.07); border-radius: 12px; padding: 8px 10px; }
.group-card h4 { font-size: 12px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--accent); margin-bottom: 4px; }
.group-card div { font-size: 14px; line-height: 1.45; }

/* ---------- Panels & modals ---------- */
.panel {
  position: fixed;
  left: 50%;
  bottom: 92px;
  transform: translateX(-50%);
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  backdrop-filter: blur(14px);
  padding: 16px;
  z-index: 4500;
  width: min(560px, calc(100vw - 40px));
  max-height: min(430px, calc(100vh - 130px));
  overflow: auto;
}
.panel h3 { font-size: 16px; margin-bottom: 10px; font-family: var(--font-display); }
.panel h4 { font-size: 14px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--ink-soft); margin: 12px 0 6px; }
.swatches { display: flex; flex-wrap: wrap; gap: 8px; }
.swatch {
  width: 64px;
  height: 42px;
  border-radius: 10px;
  border: 2px solid transparent;
  box-shadow: inset 0 0 0 1px rgba(34, 48, 60, 0.12);
  transition: transform 0.1s;
}
.swatch:hover { transform: scale(1.06); }
.swatch.active { border-color: var(--accent); }

/* background slide-out drawer */
.bg-drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(400px, 92vw);
  background: var(--panel);
  border-left: 1px solid var(--panel-border);
  box-shadow: var(--shadow);
  backdrop-filter: blur(14px);
  z-index: 4500;
  display: flex;
  flex-direction: column;
  animation: bg-drawer-in 0.22s ease;
}
@keyframes bg-drawer-in {
  from { transform: translateX(40px); opacity: 0; }
}
.bg-drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid var(--panel-border);
  flex-shrink: 0;
}
.bg-drawer-head h3 { font-size: 16px; font-family: var(--font-display); }
.bg-drawer-head .rm { font-size: 15px; padding: 4px 8px; border-radius: 8px; color: var(--ink-soft); }
.bg-drawer-head .rm:hover { background: rgba(15, 118, 110, 0.1); color: var(--ink); }
.bg-drawer-body { flex: 1; overflow-y: auto; padding: 2px 18px 18px; }
.bg-drawer-body h4 {
  font-size: 14px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--ink-soft);
  margin: 14px 0 6px;
}
.bg-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
.bg-thumb {
  padding: 0;
  aspect-ratio: 16 / 10;
  border-radius: 10px;
  overflow: hidden;
  border: 2px solid transparent;
  box-shadow: inset 0 0 0 1px rgba(34, 48, 60, 0.12);
  transition: transform 0.1s;
}
.bg-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.bg-thumb:hover { transform: scale(1.03); }
.bg-thumb.active { border-color: var(--accent); }

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(15, 30, 45, 0.4);
  z-index: 5000;
  display: grid;
  place-items: center;
}
.modal {
  background: var(--panel-solid);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-window);
  width: min(620px, calc(100vw - 40px));
  max-height: calc(100vh - 80px);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.modal-head { display: flex; align-items: center; padding: 16px 20px 10px; }
.modal-head h3 { flex: 1; font-size: 17px; font-family: var(--font-display); }
.modal-body { padding: 6px 20px 20px; overflow: auto; display: flex; flex-direction: column; gap: 10px; }
/* the ? system's three opt-in surfaces (docs/help-system-design.md):
   hover card on the ?, the What's-this pointing card, and its exit pill */
.help-hover {
  position: fixed; z-index: 5100; max-width: 340px;
  background: var(--panel-solid); border: 1.5px solid rgba(15, 118, 110, 0.35);
  border-radius: 12px; box-shadow: var(--shadow); padding: 12px 14px;
  display: grid; gap: 6px; pointer-events: none;
  font-size: 13.5px; color: var(--ink-soft); line-height: 1.45;
}
.help-hover b { color: var(--ink); font-size: 14px; }
.help-hover i { font-style: normal; font-size: 12px; color: var(--ink-soft); opacity: 0.8; }
.help-card {
  position: fixed; z-index: 5100; max-width: 320px;
  background: var(--panel-solid); border: 1.5px solid rgba(15, 118, 110, 0.45);
  border-radius: 12px; box-shadow: var(--shadow); padding: 11px 14px;
  display: grid; gap: 4px; pointer-events: none;
  font-size: 13.5px; color: var(--ink-soft); line-height: 1.45;
}
.help-card b { color: var(--ink); font-size: 14px; }
.help-pill {
  position: fixed; z-index: 5090; top: 14px; left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; gap: 10px;
  background: var(--panel-solid); border: 1.5px solid rgba(15, 118, 110, 0.45);
  border-radius: 999px; box-shadow: var(--shadow); padding: 8px 10px 8px 16px;
  font-size: 13.5px; font-weight: 600; color: var(--ink);
}
body.helping, body.helping * { cursor: help !important; }
.dash-help .ic svg { width: 17px; height: 17px; }

/* the ? modal's folded compliance answers — three headings at a glance,
   one open question for the deputy head sent to ask it */
.help-faq { border: 1.5px solid rgba(34, 48, 60, 0.12); border-radius: 12px; padding: 9px 14px; margin: 0; background: var(--panel-solid); }
.help-faq summary { cursor: pointer; font-weight: 700; font-size: 14px; color: var(--ink); }
.help-faq summary:hover { color: var(--accent); }
.help-faq[open] { border-color: rgba(15, 118, 110, 0.35); }
.help-faq[open] summary { margin-bottom: 4px; }
.help-faq p:last-child { margin-bottom: 2px; }
/* headings appended into modal bodies by callers — mirror the .panel h3/h4 pair
   so the two dialog forms agree, and stay below the 17px title */
.modal-body h3 { font-size: 16px; font-family: var(--font-display); margin-top: 4px; }
.modal-body h4 { font-size: 14px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--ink-soft); margin: 8px 0 2px; }

.confirm-modal { width: min(380px, calc(100vw - 40px)); }
.confirm-modal .modal-body { padding-top: 20px; }

.lists-cols { display: grid; grid-template-columns: 180px 1fr; gap: 14px; min-height: 260px; }
.lists-side { display: flex; flex-direction: column; gap: 4px; }
.lists-side button {
  text-align: left; padding: 8px 10px; border-radius: 9px; font-weight: 600; font-size: 14px;
}
.lists-side button:hover { background: rgba(15, 118, 110, 0.08); }
.lists-side button.active { background: var(--accent-soft); color: var(--accent); }
.names-area { width: 100%; height: 240px; resize: vertical; border: 1px solid var(--panel-border); border-radius: 10px; padding: 9px; font-size: 14px; }
.names-area:disabled { background: var(--accent-soft); cursor: not-allowed; }
.names-src { margin-bottom: 8px; }
/* what the paste did, and the two ways back out of it. The count is the whole
   point of the row, so it wraps rather than ellipsing — the buttons drop to the
   next line on a narrow modal instead */
.names-paste { margin-top: 8px; }
.names-paste .hint { flex: 1 1 auto; min-width: 24ch; }

/* ---------- Drawing overlay ---------- */
/* the ink layer is always visible so annotations persist over the lesson;
   it only takes pointer input while draw mode is active */
#drawLayer { position: fixed; inset: 0; z-index: 3000; touch-action: none; pointer-events: none; }
#drawLayer.active { pointer-events: auto; cursor: crosshair; }
#drawLayer.active.selecting { cursor: default; }
#drawTools {
  position: fixed;
  top: 14px;
  left: 50%;
  transform: translateX(-50%);
  display: none;
  align-items: center;
  gap: 7px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  padding: 7px 10px;
  z-index: 4600;
}
#drawTools.active { display: flex; }
#drawTools.dragging { opacity: 0.85; transition: none; }
.dt-grip { cursor: grab; color: var(--ink-soft); }
.dt-grip:active { cursor: grabbing; }
/* docked to a screen edge: vertical layout */
#drawTools.side-left,
#drawTools.side-right {
  top: 50%;
  left: 14px;
  transform: translateY(-50%);
  flex-direction: column;
  gap: 5px;
  padding: 7px 6px;
}
#drawTools.side-right { left: auto; right: 14px; }
/* docked just above the widget dock — handy at child height on touch boards */
#drawTools.side-bottom {
  top: auto;
  bottom: 88px;
  left: 50%;
  transform: translateX(-50%);
}
#drawTools.side-bottom .dt-pop { top: auto; bottom: calc(100% + 8px); }
/* compact the vertical docks so the whole bar clears shorter screens */
#drawTools.side-left .dt-btn,
#drawTools.side-right .dt-btn { width: 33px; height: 33px; border-radius: 9px; }
#drawTools.side-left .dt-btn .ic svg,
#drawTools.side-right .dt-btn .ic svg { width: 20px; height: 20px; }
#drawTools.side-left > .dt-sep,
#drawTools.side-right > .dt-sep { width: 26px; height: 1px; margin: 0; }
#drawTools.side-left .dt-swatches,
#drawTools.side-right .dt-swatches { display: grid; grid-template-columns: repeat(3, auto); gap: 3px; justify-items: center; }
#drawTools.side-left .dt-swatch,
#drawTools.side-right .dt-swatch { width: 18px; height: 18px; }
#drawTools.side-left .dt-swatch-row,
#drawTools.side-right .dt-swatch-row { display: contents; }
#drawTools.side-left .dt-sizes,
#drawTools.side-right .dt-sizes { flex-direction: column; gap: 3px; }
#drawTools.side-left .dt-size,
#drawTools.side-right .dt-size { width: 30px; height: 30px; }
#drawTools.side-left .dt-pop { left: calc(100% + 10px); top: 8px; transform: none; }
#drawTools.side-right .dt-pop { left: auto; right: calc(100% + 10px); top: 8px; transform: none; }
/* on narrower screens the centered bar would cover the brand / Home buttons,
   which share the top 14px band — drop it just below the topbar instead
   (side/bottom docks are untouched: their class rules are more specific) */
@media (max-width: 1300px) {
  #drawTools { top: 70px; }
}
.dt-btn {
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  color: var(--ink);
  transition: background 0.12s ease;
}
.dt-btn .ic svg { width: 22px; height: 22px; }
.dt-btn:hover { background: rgba(15, 118, 110, 0.1); }
.dt-btn.active { background: var(--accent-soft); box-shadow: inset 0 0 0 1.5px var(--accent); }
.dt-sep { width: 1px; height: 30px; background: var(--panel-border); }
.dt-swatches { display: flex; flex-direction: column; gap: 4px; }
.dt-swatch-row { display: flex; gap: 4px; }
.dt-swatch {
  width: 21px;
  height: 21px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(34, 48, 60, 0.18);
  transition: transform 0.1s ease;
}
.dt-swatch:hover { transform: scale(1.12); }
.dt-swatch.active { box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--ink); }
.dt-rainbow { background: conic-gradient(#f43f5e, #f59e0b, #22c55e, #06b6d4, #6366f1, #d946ef, #f43f5e); }
.dt-sizes { display: flex; align-items: center; gap: 2px; }
.dt-size {
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border-radius: 9px;
}
.dt-size span { display: block; border-radius: 50%; background: var(--ink); }
.dt-size:hover { background: rgba(15, 118, 110, 0.1); }
.dt-size.active { background: var(--accent-soft); box-shadow: inset 0 0 0 1.5px var(--accent); }
.dt-pop {
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 4px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 12px;
  box-shadow: var(--shadow);
  padding: 6px;
  z-index: 5;
}

/* geometry tools (ruler / protractor / set square) overlay */
#geoLayer { position: fixed; inset: 0; z-index: 4200; pointer-events: none; }
#geoLayer svg { position: absolute; inset: 0; pointer-events: none; overflow: visible; touch-action: none; }
#geoLayer text { user-select: none; }
.dt-pop-geo { flex-wrap: wrap; max-width: 220px; }
.dt-pop-geo .dt-sep { width: 1px; height: 30px; }

/* geometry settings drawer controls */
.geo-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 10px 2px;
  cursor: pointer;
  border-bottom: 1px solid var(--panel-border);
}
.geo-row-label { font-size: 14px; font-weight: 600; }
.geo-row .hint { margin-top: 2px; }
.geo-sw {
  flex-shrink: 0;
  width: 44px;
  height: 26px;
  border-radius: var(--radius-pill);
  background: rgba(34, 48, 60, 0.18);
  position: relative;
  transition: background 0.15s ease;
}
.geo-sw::after {
  content: '';
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
  transition: transform 0.15s ease;
}
.geo-sw.on { background: var(--accent); }
.geo-sw.on::after { transform: translateX(18px); }
.geo-seg { display: flex; gap: 8px; }
.geo-seg-btn {
  flex: 1;
  padding: 9px 10px;
  border-radius: 10px;
  border: 1px solid var(--panel-border);
  background: rgba(255, 255, 255, 0.6);
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
}
.geo-seg-btn.active { background: var(--accent-soft); box-shadow: inset 0 0 0 1.5px var(--accent); }
.bg-drawer-body input[type="range"] { width: 100%; accent-color: var(--accent); }

/* selection mini toolbar (select tool) */
.sel-bar {
  position: fixed;
  display: flex;
  align-items: center;
  gap: 2px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 12px;
  box-shadow: var(--shadow);
  backdrop-filter: blur(14px);
  padding: 4px;
  z-index: 4700;
}
.sel-dot {
  display: block;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(34, 48, 60, 0.2);
}
.sel-dot-ink { background: var(--ink); }
.sel-pop { left: 0; transform: none; align-items: center; }
.sel-colors { flex-wrap: wrap; max-width: 180px; }
.sel-menu { flex-direction: column; min-width: 200px; align-items: stretch; }

/* Draw pad widget — the rose tint marks these as pad-scoped tools, visually
   distinct from the teal full-screen annotation tools */
.sketch-body { gap: 6px; }
.sketch-bar {
  position: relative;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 1px;
  padding: 3px 4px;
  background: rgba(251, 207, 232, 0.35);
  border-radius: 10px;
}
.sk-btn {
  width: 27px;
  height: 27px;
  display: grid;
  place-items: center;
  border-radius: 8px;
  color: var(--ink);
  flex-shrink: 0;
}
.sk-btn .ic svg { width: 16px; height: 16px; }
.sk-btn .sel-dot { width: 15px; height: 15px; }
.sk-btn:hover { background: rgba(219, 39, 119, 0.1); }
.sk-btn.active { background: #fbcfe8; box-shadow: inset 0 0 0 1.5px #db2777; color: #22303c; }
.sk-sep { width: 1px; height: 18px; background: var(--panel-border); margin: 0 3px; flex-shrink: 0; }
.sketch-pop { top: calc(100% + 4px); left: 0; transform: none; }
.sketch-colors { flex-wrap: wrap; max-width: 176px; }
.sketch-lock-note {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0 4px;
  font-size: 14px;
  color: var(--ink-soft);
}
.sketch-lock-note .ic svg { width: 14px; height: 14px; }
/* column "menu" popups (clear options, pad options) */
.sk-menu { flex-direction: column; align-items: stretch; min-width: 200px; }
.sk-menu button {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 6px 10px;
  border-radius: 9px;
  font-size: 14px;
  font-weight: 600;
  color: #22303c;
  text-align: left;
}
.sk-menu button:hover { background: rgba(219, 39, 119, 0.08); }
.sk-menu .ic svg { width: 15px; height: 15px; }
.sk-menu hr { border: none; border-top: 1px solid rgba(34, 48, 60, 0.1); margin: 4px 6px; }
.sketch-paper-pop {
  flex-direction: column;
  align-items: stretch;
  max-width: 356px;
  max-height: 320px;
  overflow: auto;
}
/* floating context bar for selected pad objects */
.sketch-selbar {
  position: absolute;
  z-index: 6;
  display: flex;
  align-items: center;
  gap: 1px;
  padding: 3px;
  border-radius: 10px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  box-shadow: var(--shadow);
}
.sketch-selbar .dt-pop { top: calc(100% + 4px); left: 0; transform: none; }
/* floating formatting bar shown while a pad text box is being typed */
.sketch-textbar {
  position: absolute;
  z-index: 7;
  display: flex;
  align-items: center;
  gap: 1px;
  padding: 3px;
  border-radius: 10px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  box-shadow: var(--shadow);
  white-space: nowrap;
}
.sketch-textbar .stb-size { width: 22px; font-weight: 700; color: var(--ink); }
.sketch-textbar .stb-font { width: 26px; font-size: 14px; color: var(--ink); }
.sketch-textbar .stb-swatch { width: 15px; height: 15px; margin: 0 1px; }
/* inline text-box editor */
.sketch-text-edit {
  position: absolute;
  z-index: 5;
  background: rgba(255, 255, 255, 0.65);
  border: 1.5px dashed #db2777;
  border-radius: 6px;
  padding: 3px;
  margin: 0;
  font-family: system-ui, sans-serif;
  font-weight: 600;
  line-height: 1.25;
  white-space: pre;
  resize: none;
  overflow: hidden;
  outline: none;
}
/* transparent surface: the drawing area takes on the widget's color theme */
.sketch-wrap {
  position: relative;
  flex: 1;
  min-height: 0;
  border-radius: 10px;
  box-shadow: inset 0 0 0 1px rgba(34, 48, 60, 0.1);
  overflow: hidden;
}

/* paper pattern thumbnails in the draw pad settings */
.paper-grid { display: flex; flex-wrap: wrap; gap: 8px; }
.paper-swatch {
  width: 72px;
  height: 52px;
  border-radius: 10px;
  background-color: #fff;
  background-clip: padding-box;
  border: 2px solid rgba(34, 48, 60, 0.12);
  transition: transform 0.1s ease;
}
.paper-swatch:hover { transform: scale(1.05); }
.paper-swatch.active { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.sketch-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  touch-action: none;
  cursor: crosshair;
}

/* ---------- Collapsible dock ---------- */
#toolbar.hidden { display: none; }
.dock-sep { width: 1px; height: 38px; background: var(--panel-border); margin: 0 4px; flex-shrink: 0; }
.dock-annotate {
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  border-radius: 12px;
  color: var(--ink);
  flex-shrink: 0;
}
.dock-annotate .ic svg { width: 24px; height: 24px; }
.dock-annotate:hover { background: rgba(15, 118, 110, 0.1); }
.dock-annotate.active { background: var(--accent-soft); color: var(--accent); box-shadow: inset 0 0 0 1.5px var(--accent); }
.dock-hide {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  color: var(--ink-soft);
  flex-shrink: 0;
  margin-left: 2px;
}
.dock-hide .ic svg { width: 18px; height: 18px; }
.dock-hide:hover { background: rgba(15, 118, 110, 0.1); color: var(--ink); }
.mini-dock {
  position: fixed;
  left: 50%;
  bottom: 14px;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 2px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  backdrop-filter: blur(14px);
  padding: 6px;
  z-index: 4000;
}
.mini-btn {
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border-radius: 11px;
  color: var(--ink);
}
.mini-btn .ic svg { width: 21px; height: 21px; }
.mini-btn:hover { background: rgba(15, 118, 110, 0.1); }
.mini-btn.active { background: var(--accent-soft); color: var(--accent); }
.mini-sep { width: 1px; height: 24px; background: var(--panel-border); margin: 0 3px; }

/* ---------- Screen deck sidebar ---------- */
.deck-panel {
  position: fixed;
  top: 12px;
  right: 12px;
  bottom: 12px;
  width: 300px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow);
  backdrop-filter: blur(14px);
  z-index: 4500;
  display: flex;
  flex-direction: column;
  animation: deck-in 0.18s ease;
}
@keyframes deck-in {
  from { transform: translateX(24px); opacity: 0; }
  to { transform: none; opacity: 1; }
}
.deck-head {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 14px 14px 10px;
  border-bottom: 1px solid var(--panel-border);
}
.deck-title {
  flex: 1;
  min-width: 0;
  border: none;
  background: none;
  font-weight: 700;
  font-family: var(--font-display);
  font-size: 17px;
  border-radius: 8px;
  padding: 4px 6px;
}
.deck-title:hover, .deck-title:focus { background: rgba(15, 118, 110, 0.07); outline: none; }
.deck-close { box-shadow: none; border: none; background: none; width: 32px; height: 32px; }
.deck-list {
  flex: 1;
  overflow-y: auto;
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.deck-card {
  border-radius: var(--radius-sm);
  padding: 8px;
  background: rgba(34, 48, 60, 0.04);
  cursor: pointer;
  transition: background 0.12s ease;
}
.deck-card:hover { background: rgba(15, 118, 110, 0.08); }
.deck-card.active { background: var(--accent-soft); }
.deck-thumb-wrap { position: relative; }
.deck-thumb {
  position: relative;
  border-radius: 10px;
  overflow: hidden;
  background-size: cover;
  box-shadow: inset 0 0 0 1px var(--panel-border);
}
.deck-thumb-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.deck-mini {
  position: absolute;
  display: grid;
  place-items: center;
  background: var(--panel);
  border-radius: 4px;
  box-shadow: 0 1px 4px rgba(15, 30, 45, 0.25);
  overflow: hidden;
  color: var(--ink);
}
.deck-mini .ic svg { width: 14px; height: 14px; }
.deck-mini-img {
  width: 100%;
  height: 100%;
}
.deck-mini-text {
  width: 100%;
  height: 100%;
  padding: 2px 3px;
  font-size: 6px;
  line-height: 1.25;
  font-weight: 600;
  text-align: left;
  color: var(--ink-soft);
  overflow: hidden;
  word-break: break-word;
}
.deck-kebab {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 8px;
  background: var(--accent);
  color: #fff;
  opacity: 0;
  transition: opacity 0.12s ease;
}
.deck-thumb-wrap:hover .deck-kebab, .deck-kebab:focus { opacity: 1; }
.deck-kebab .ic svg { width: 15px; height: 15px; }
.deck-label {
  text-align: center;
  font-weight: 700;
  font-size: 14px;
  color: var(--ink-soft);
  padding: 7px 2px 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.deck-card.active .deck-label { color: var(--accent); }
.deck-num {
  position: absolute;
  top: 6px;
  left: 6px;
  min-width: 24px;
  height: 24px;
  padding: 0 7px;
  display: grid;
  place-items: center;
  border-radius: 8px;
  background: var(--panel);
  color: var(--accent);
  font-size: 14px;
  font-weight: 800;
  box-shadow: 0 1px 4px rgba(15, 30, 45, 0.2);
}

/* drag to reorder */
.deck-card img { -webkit-user-drag: none; }
.deck-list.dragging .deck-card { transition: transform 0.2s ease; }
.deck-card.drag-slot {
  background: rgba(15, 118, 110, 0.06);
  outline: 2px dashed rgba(15, 118, 110, 0.35);
  outline-offset: -2px;
}
.deck-card.drag-slot > * { visibility: hidden; }
.deck-ghost {
  position: fixed;
  margin: 0;
  z-index: 7000;
  pointer-events: none;
  background: var(--panel-solid);
  box-shadow: 0 18px 40px rgba(15, 30, 45, 0.28);
  scale: 1.04;
  rotate: 1.2deg;
  animation: ghost-pickup 0.15s ease;
  will-change: transform;
}
@keyframes ghost-pickup {
  from { scale: 1; rotate: 0deg; box-shadow: 0 2px 8px rgba(15, 30, 45, 0.1); }
}
.deck-ghost.drop {
  scale: 1;
  rotate: 0deg;
  transition: transform 0.2s ease, scale 0.2s ease, rotate 0.2s ease;
}
body.deck-dragging { user-select: none; -webkit-user-select: none; cursor: grabbing; }
.deck-menu {
  /* portaled to <body> and placed with fixed coords by placeMenuAt() so it
     always paints above cards, panels and the dashboard */
  position: fixed;
  z-index: 6500;
  max-height: calc(100vh - 16px);
  overflow-y: auto;
  min-width: 190px;
  background: var(--panel-solid);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  padding: 6px;
  display: flex;
  flex-direction: column;
}
.deck-menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border-radius: 9px;
  font-weight: 600;
  font-size: 14px;
  text-align: left;
}
.deck-menu-item:hover { background: rgba(15, 118, 110, 0.08); }
a.deck-menu-item { text-decoration: none; color: inherit; }
.deck-menu-item.danger { color: var(--danger); }
/* Move up on screen 1 / Move down on the last: visibly off, not silently inert */
.deck-menu-item[disabled] { opacity: 0.35; cursor: default; }
.deck-menu-item[disabled]:hover { background: none; }
.deck-menu-item .ic svg { width: 17px; height: 17px; }
.deck-add {
  border-radius: var(--radius-sm);
  padding: 22px;
  background: rgba(34, 48, 60, 0.04);
  display: grid;
  place-items: center;
  transition: background 0.12s ease;
}
.deck-add:hover { background: rgba(15, 118, 110, 0.08); }
.deck-add-plus {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
}
.deck-add-plus .ic svg { width: 22px; height: 22px; }

/* toast */
#toast {
  position: fixed;
  bottom: 100px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--ink);
  color: #fff;
  padding: 10px 18px;
  border-radius: 12px;
  font-size: 14px;
  font-weight: 600;
  z-index: 6000;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
}
#toast.show { opacity: 1; }

/* ---------- Dashboard (landing page) ---------- */
.dashboard {
  position: fixed;
  inset: 0;
  z-index: 4900; /* above panels & deck sidebar, below modals (5000) and toast */
  background: var(--surface-page);
  overflow-y: auto;
  animation: dash-in 0.2s ease;
}
@keyframes dash-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}
.dash-page {
  max-width: 1240px;
  margin: 0 auto;
  padding: 18px 28px 48px;
}

/* top row: brand · tabs · close */
.dash-topbar {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}
.dash-brand { display: flex; align-items: center; gap: 10px; margin-right: auto; }
.dash-brand-tile {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 15px;
  background: var(--surface-accent);
  font-size: 24px;
}
.dash-brand-name { font-family: var(--font-display); font-weight: 600; font-size: 21px; letter-spacing: 0.2px; }
.dash-tag {
  font-size: 14px;
  font-weight: 800;
  color: var(--info-ink);
  background: var(--surface-info);
  border-radius: var(--radius-pill);
  padding: 5px 11px;
}
/* the reading-font cycler renders in whatever face is active, so the button
   itself is the preview */
.dash-font-btn {
  min-width: 44px;
  padding: 8px 14px;
  border-radius: var(--radius-pill);
  background: var(--panel);
  box-shadow: var(--shadow-2);
  font-size: 15px;
  font-weight: 700;
  transition: background 0.12s ease;
}
.dash-font-btn:hover { background: var(--panel-solid); }
.dash-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  background: rgba(255, 255, 255, 0.75);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-sm);
  padding: 4px;
  box-shadow: var(--shadow-2);
  backdrop-filter: blur(8px);
}
.dash-tab {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 8px 16px;
  border-radius: 10px;
  font-weight: 700;
  font-size: 14px;
  color: var(--ink-soft);
  transition: background 0.12s ease, color 0.12s ease;
}
.dash-tab .ic svg { width: 16px; height: 16px; }
.dash-tab:hover { color: var(--ink); }
.dash-tab.active { background: var(--accent); color: #fff; box-shadow: var(--shadow-accent); }
.dash-close {
  background: rgba(255, 255, 255, 0.85);
  border: 1px solid var(--panel-border);
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
}

/* hero: mascot · greeting · class stars */
.dash-hero {
  display: flex;
  align-items: center;
  gap: 28px;
  background: var(--panel-solid);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-2xl);
  box-shadow: var(--shadow-3);
  padding: 28px 32px;
  margin-bottom: 24px;
}

/* the sprout — CSS shapes only, no image asset. The rotated leaf's ink reaches
   ~17px above the tile, ~24px at the top of the bob — inside the hero's 28px
   top padding (25px at narrow widths, see the 700px media block). */
.dash-mascot {
  position: relative;
  flex: none;
  width: 108px;
  height: 108px;
  border-radius: 36px;
  background: var(--surface-accent);
  animation: mascot-bob 4.4s ease-in-out infinite;
}
@keyframes mascot-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-7px); }
}
.dash-mascot i { position: absolute; display: block; }
/* the teacher's own face (memoji or photo) fills the tile; transparent memoji
   PNGs keep the mint tile behind them. Note an animated GIF/APNG keeps playing
   under prefers-reduced-motion — CSS cannot pause image formats; the bob stops,
   the face is the teacher's own choice. */
.dash-mascot .m-face {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
}
.dash-mascot .m-leaf {
  width: 28px;
  height: 42px;
  border-radius: 28px 4px 28px 4px;
  background: var(--accent);
  top: -14px;
  right: 12px;
  transform: rotate(-18deg);
}
.dash-mascot .m-eye { width: 15px; height: 15px; border-radius: 50%; background: var(--ink); top: 40px; }
.dash-mascot .m-eye-l { left: 27px; }
.dash-mascot .m-eye-r { right: 27px; }
.dash-mascot .m-smile {
  width: 32px;
  height: 16px;
  border-radius: 0 0 20px 20px;
  background: var(--ink);
  left: 50%;
  top: 63px;
  transform: translateX(-50%);
}

.dash-greet { flex: 1; min-width: 0; }
.dash-greet-line {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(26px, 3.4vw, 44px);
  line-height: 1.05;
  letter-spacing: 0.2px;
  overflow-wrap: anywhere; /* the class name is teacher-typed — never push the stars strip out */
}
/* OpenDyslexic's ink spans ~1.15em: at 1.05 wrapped greeting lines collide */
html[data-reading-font='dys'] .dash-greet-line { line-height: 1.18; }
.dash-hero .dash-sub { color: var(--ink-soft); font-size: 17px; font-weight: 600; margin-top: 5px; }
.greet-edit {
  flex: none;
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border-radius: 12px;
  color: var(--ink-soft);
  font-size: 17px;
  /* 0.75, not lower: the gear is the only door to the class-name form, and on
     a touch board there is no hover to reveal it — it must clear 3:1 at rest */
  opacity: 0.75;
  transition: opacity 0.12s ease, background 0.12s ease;
}
.dash-hero:hover .greet-edit, .greet-edit:focus-visible { opacity: 1; }
.greet-edit:hover { background: var(--surface-muted); }

/* the greeting's edit face: name the class, decide about stars */
.greet-lab { display: block; font-size: 14px; font-weight: 700; color: var(--ink-soft); margin-bottom: 6px; }
.greet-input { max-width: 360px; font-size: 16px; }
.greet-row { display: flex; align-items: center; flex-wrap: wrap; gap: 14px; margin-top: 12px; }
.greet-chk { display: inline-flex; align-items: center; gap: 7px; font-size: 14px; font-weight: 700; }
.greet-chk input { width: 17px; height: 17px; accent-color: var(--accent); }
.greet-reset { font-size: 14px; font-weight: 700; color: var(--danger-ink); }
.greet-reset:hover { text-decoration: underline; }
.greet-done { background: var(--accent); color: #fff; }

/* the stars strip is display-only — awarding happens on the stage */
.dash-rewards {
  flex: none;
  width: 200px;
  background: var(--surface-muted);
  border-radius: var(--radius-lg);
  padding: 16px 20px;
}
.dr-stars {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 32px;
  line-height: 1;
  color: var(--accent);
}
.dr-cap { font-size: 14px; font-weight: 700; color: var(--ink-soft); margin-top: 3px; }
.dr-streak {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  font-weight: 800;
  color: var(--ink-soft);
  margin-top: 10px;
}
.dr-streak .ic svg { width: 16px; height: 16px; }

/* quick tools: one tap from the hero to a working widget */
.dash-tools {
  display: grid;
  /* 175px floor: "Name picker" in OpenDyslexic needs ~144px of label width —
     anything narrower wraps two of the six labels and misaligns the row */
  grid-template-columns: repeat(auto-fit, minmax(175px, 1fr));
  gap: 16px;
  margin-bottom: 24px;
}
.dash-tool {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 18px 12px;
  background: var(--panel-solid);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
  transition: box-shadow 0.15s ease, transform 0.15s ease;
}
.dash-tool:hover { box-shadow: var(--shadow-2); transform: translateY(-2px); }
.dash-tool-ic {
  width: 60px;
  height: 60px;
  display: grid;
  place-items: center;
  border-radius: var(--radius-md);
}
.dash-tool-ic .ic svg { width: 32px; height: 32px; }
.dash-tool-label { font-size: 16px; font-weight: 800; color: var(--ink); }

/* the one primary action on the page */
.dash-primary {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 22px;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: #fff;
  font-size: 16px;
  font-weight: 800;
  box-shadow: var(--shadow-accent);
  transition: transform 0.12s ease;
}
.dash-primary:hover { transform: translateY(-1px); }
.dash-primary .ic svg { width: 16px; height: 16px; }

/* section head: title + search/sort */
.dash-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  margin: 4px 2px 16px;
}
.dash-section-head h3 {
  font-family: var(--font-display);
  font-size: 22px;
  background: rgba(255, 255, 255, 0.8);
  border-radius: var(--radius-pill);
  padding: 6px 18px;
  box-shadow: var(--shadow-2);
}
.dash-section-sub {
  color: var(--ink-soft);
  font-weight: 600;
  font-size: 14px;
  background: rgba(255, 255, 255, 0.7);
  border-radius: var(--radius-pill);
  padding: 6px 14px;
}
.dash-section-tools { display: flex; align-items: center; gap: 10px; }
.dash-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.dash-pill {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 6px 17px 6px 7px;
  border: 0;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.8);
  box-shadow: var(--shadow-2);
  font-weight: 700;
  font-size: 15px;
  color: var(--accent);
  cursor: pointer;
  transition: background 0.12s ease, transform 0.12s ease;
}
.dash-pill:hover { background: var(--panel-solid); transform: translateY(-1px); }
.dash-pill-ic {
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
}
.dash-pill-ic .ic svg { width: 16px; height: 16px; }
.dash-search {
  width: 220px;
  padding: 10px 15px;
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.9);
  box-shadow: 0 2px 10px rgba(15, 30, 45, 0.05);
}
.dash-search:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent); }
.dash-sort {
  padding: 10px 12px;
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.9);
  font-weight: 600;
  box-shadow: 0 2px 10px rgba(15, 30, 45, 0.05);
}

/* deck / list card grid */
.dash-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 18px;
}
.dash-card {
  border-radius: var(--radius-md);
  padding: 10px;
  background: var(--panel-solid);
  border: 1px solid var(--panel-border);
  box-shadow: var(--shadow-3);
  cursor: pointer;
  text-align: left;
  transition: box-shadow 0.15s ease, transform 0.15s ease;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.dash-card:hover { box-shadow: 0 14px 30px rgba(15, 30, 45, 0.14); transform: translateY(-3px); }
.dash-card.active { outline: 3px solid var(--accent); outline-offset: -1px; }
.dash-card .deck-thumb { min-height: 130px; border-radius: var(--radius-sm); }
.dash-card-name { font-weight: 700; font-size: 16.5px; padding: 4px 6px 0; overflow-wrap: anywhere; }
.dash-meta { color: var(--ink-soft); font-size: 14px; font-weight: 600; padding: 0 6px; }
.dash-chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 2px 6px 6px; min-height: 0; }
.chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 11px;
  border-radius: var(--radius-pill);
  font-size: 14px;
  font-weight: 700;
}
.chip .ic svg { width: 13px; height: 13px; }
.chip-class { background: var(--accent-soft); color: var(--accent); }
.chip-subject { background: var(--tint-yellow); color: #92400e; }
.dash-pin {
  position: absolute;
  top: 8px;
  left: 8px;
  width: 27px;
  height: 27px;
  display: grid;
  place-items: center;
  border-radius: 9px;
  background: var(--panel);
  color: var(--accent);
  box-shadow: 0 2px 6px rgba(15, 30, 45, 0.18);
}
.dash-pin .ic svg { width: 14px; height: 14px; }
.dash-new {
  align-items: center;
  justify-content: center;
  gap: 12px;
  min-height: 200px;
  border: 2.5px dashed rgba(15, 118, 110, 0.35);
  background: rgba(255, 255, 255, 0.55);
  font-weight: 700;
  font-size: 15.5px;
  color: var(--accent);
}
.dash-new:hover { background: rgba(255, 255, 255, 0.85); }
.dash-card .deck-kebab { top: 8px; right: 8px; }

/* name-list cards */
.list-card { cursor: default; gap: 8px; align-self: start; }
.list-card-head { display: flex; align-items: center; gap: 8px; padding: 4px 4px 0; position: relative; }
.list-card-head .dash-card-name { flex: 1; padding: 0; }
.list-kebab { position: static; opacity: 1; background: rgba(34, 48, 60, 0.07); color: var(--ink-soft); }
.list-kebab:hover { background: var(--accent); color: #fff; }
.name-chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 4px; }
.name-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 5px 7px 5px 12px;
  border-radius: var(--radius-pill);
  background: rgba(15, 118, 110, 0.08);
  font-size: 14px;
  font-weight: 600;
}
.name-chip-x {
  width: 18px;
  height: 18px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  color: var(--ink-soft);
  font-size: 14px;
  line-height: 1;
}
.name-chip-x:hover { background: var(--danger); color: #fff; }
.name-add {
  border: 1.5px dashed var(--border-dashed);
  border-radius: 11px;
  padding: 8px 12px;
  font-size: 14px;
  background: none;
  margin: 2px 4px 4px;
}
.name-add:focus { outline: none; border-color: var(--accent); background: var(--panel-solid); }

/* wallpaper tab: the shared bg picker in a card */
.dash-bg-card {
  background: var(--panel-solid);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-3);
  padding: 20px 22px;
}
.dash-bg-card .bg-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.dash-bg-card .bg-drawer-body { padding: 0; overflow: visible; }

@media (max-width: 700px) {
  .dash-page { padding: 12px 14px 32px; }
  .dash-hero { padding: 25px 20px 20px; gap: 18px; } /* 25px top: the bobbing leaf peaks ~24px above its tile */
  .dash-rewards { display: none; }
  .dash-search { width: 140px; }
}

/* ---------- Templates tab ---------- */
.tpl-search-row { display: flex; margin: 0 2px 12px; }
.tpl-search { width: min(460px, 100%); }
.tpl-cats { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 2px 18px; }
.tpl-cat {
  padding: 7px 16px;
  border-radius: var(--radius-pill);
  font-weight: 700;
  font-size: 14px;
  color: var(--ink-soft);
  background: rgba(255, 255, 255, 0.8);
  border: 1px solid var(--panel-border);
  box-shadow: var(--shadow-2);
}
.tpl-cat:hover { color: var(--ink); }
.tpl-cat.active { background: var(--accent); color: #fff; border-color: var(--accent); }
.tpl-card { align-items: stretch; min-width: 0; }
.tpl-card .deck-thumb-wrap {
  width: 100%;
  min-width: 0;
  overflow: hidden;
  border-radius: var(--radius-sm);
  flex: none;
}
.tpl-card .deck-thumb { min-height: 120px; }
.tpl-card[hidden] { display: none; }
.tpl-cover {
  position: relative;
  width: 100%;
  min-width: 0;
  min-height: 0;
  aspect-ratio: 16 / 7.4;
  overflow: hidden;
  border-radius: var(--radius-sm);
  isolation: isolate;
  color: #fff;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.2);
}
.tpl-cover-copy {
  position: absolute;
  left: 20px;
  top: 50%;
  z-index: 3;
  max-width: 68%;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  text-shadow: 0 2px 10px rgba(15,30,45,.28);
}
.tpl-cover-copy strong { font-size: clamp(22px, 2.25vw, 30px); line-height: 1; letter-spacing: -.025em; }
.tpl-cover-eyebrow { font-size: 9.5px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; opacity: .78; }
.tpl-cover-sub { font-size: 10.5px; font-weight: 700; opacity: .82; }
.tpl-cover-emoji {
  position: absolute;
  right: 7%;
  bottom: -12%;
  z-index: 2;
  font-size: clamp(65px, 8vw, 106px);
  line-height: 1;
  filter: drop-shadow(0 8px 8px rgba(15,30,45,.24));
  transform: rotate(5deg);
}
.tpl-cover-badge {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 4;
  padding: 4px 8px;
  border-radius: var(--radius-pill);
  background: rgba(255,255,255,.9);
  color: #334155;
  font-size: 9px;
  font-weight: 800;
  box-shadow: 0 3px 10px rgba(15,30,45,.15);
}
.tpl-cover-shape { position: absolute; z-index: 1; border-radius: 46% 54% 63% 37% / 52% 38% 62% 48%; opacity: .33; }
.tpl-cover-shape.shape-a { width: 150px; height: 150px; right: 9%; top: -55%; background: #fff; transform: rotate(18deg); }
.tpl-cover-shape.shape-b { width: 190px; height: 120px; left: -18%; bottom: -55%; background: #fff; transform: rotate(-12deg); }
.cover-berry { background: linear-gradient(145deg, #831843, #db2777 55%, #c4b5fd); }
.cover-ocean { background: linear-gradient(145deg, #0c4a6e, #0284c7 52%, #67e8f9); }
.cover-meadow { background: linear-gradient(145deg, #14532d, #16a34a 55%, #bef264); }
.cover-sunset { background: linear-gradient(145deg, #9a3412, #f97316 52%, #fde68a); }
.cover-midnight { background: radial-gradient(circle at 75% 20%, #4f46e5, transparent 30%), linear-gradient(145deg, #020617, #1e293b 60%, #312e81); }
.cover-paper { color: #243142; background: repeating-linear-gradient(0deg, transparent 0 19px, rgba(59,130,246,.12) 20px), linear-gradient(145deg, #fffdf7, #fdecc8); }
.cover-paper .tpl-cover-copy { text-shadow: none; }
.cover-chalk { background: radial-gradient(circle at 30% 20%, rgba(255,255,255,.07), transparent 20%), linear-gradient(145deg, #173d36, #245c4c); }
.cover-candy { color: #4c1d3d; background: radial-gradient(circle at 20% 20%, #fff 0 2%, transparent 2.5%), linear-gradient(145deg, #fce7f3, #f9a8d4 48%, #fde68a); }
.cover-candy .tpl-cover-copy { text-shadow: none; }
.tpl-thumb-empty {
  min-height: 120px;
  display: grid;
  place-items: center;
  font-size: 34px;
  background: var(--accent-soft);
  border-radius: var(--radius-sm);
}
.tpl-desc { font-size: 14px; line-height: 1.45; }
.tpl-mini-tag { padding: 4px 8px; border-radius: var(--radius-pill); background: var(--surface-info); color: var(--info-ink); font-size: 10.5px; font-weight: 800; }
.tpl-byline { font-size: 14px; font-weight: 700; color: var(--ink-soft); margin-left: auto; align-self: center; }
.tpl-source-empty { display: none; }
.tpl-source-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 26px 2px 12px;
}
.tpl-source-head h4 {
  font-family: var(--font-display);
  font-size: 16px;
  background: rgba(255, 255, 255, 0.8);
  border-radius: var(--radius-pill);
  padding: 6px 16px;
  box-shadow: var(--shadow-2);
}
.tpl-source-x {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.8);
  color: var(--ink-soft);
  font-size: 15px;
  line-height: 1;
}
.tpl-source-x:hover { background: var(--danger); color: #fff; }
.tpl-hint { background: rgba(255, 255, 255, 0.75); border-radius: 12px; padding: 12px 16px; margin: 0 2px; }
.tpl-actions { margin-top: 26px; }
.tpl-actions .btn.ghost { background: rgba(255, 255, 255, 0.85); }
.tpl-url-list {
  margin: 6px 0 10px 20px;
  font-size: 14px;
  color: var(--ink-soft);
  word-break: break-all;
  max-height: 120px;
  overflow-y: auto;
}

/* ---------- Teaching clock ---------- */
.tclock { gap: 6px; }
.tclock-task {
  flex-shrink: 0;
  background: rgba(15, 118, 110, 0.1);
  border-radius: 12px;
  padding: 8px 12px;
  font-size: 15px;
  font-weight: 600;
  text-align: center;
  line-height: 1.35;
}
.tclock-task.ok { background: #dcfce7; color: #15803d; }
.tclock-task.no { background: #fee2e2; color: #b91c1c; }
.tclock-canvas {
  display: grid;
  place-items: center;
  min-height: 0;
}
.tclock-canvas canvas { cursor: grab; }
.tclock-canvas canvas:active { cursor: grabbing; }
.tclock-readout {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.tclock-digital {
  font-variant-numeric: tabular-nums;
  font-size: 26px;
  font-weight: 700;
  letter-spacing: 0.5px;
}
.tclock-ampm {
  font-size: 12px;
  font-weight: 700;
  padding: 3px 8px;
  border-radius: 8px;
  background: rgba(15, 118, 110, 0.12);
  color: var(--ink);
}
.tclock-ampm:hover { background: rgba(15, 118, 110, 0.24); }
.tclock-words {
  flex-shrink: 0;
  text-align: center;
  font-size: 16.5px;
  font-style: italic;
  color: var(--ink-soft);
  min-height: 21px;
}
.tclock-game {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 5px;
  flex-wrap: wrap;
  justify-content: center;
  border-top: 1px dashed var(--panel-border);
  padding-top: 7px;
}
.tclock-game .tclock-level { font-size: 12.5px; max-width: 132px; }
.tclock-game .btn.small { padding: 4px 10px; }
.tclock-game .btn.active { background: rgba(15, 118, 110, 0.16); }
.tclock-game .btn:disabled { opacity: 0.4; pointer-events: none; }
.tclock-score {
  font-weight: 700;
  font-size: 14px;
  background: #fef3c7;
  border-radius: 9px;
  padding: 4px 9px;
}

/* ---------- Spotlight tool ---------- */
.spot-root {
  position: fixed;
  inset: 0;
  z-index: 3200;
  overflow: hidden;
  touch-action: none;
}
.spot-hole {
  position: absolute;
  cursor: grab;
}
.spot-hole:active { cursor: grabbing; }
.spot-size {
  position: absolute;
  right: 6%;
  bottom: 6%;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.9);
  border: 2px solid rgba(8, 18, 28, 0.5);
  cursor: nwse-resize;
}
.spot-bar {
  position: absolute;
  top: 18px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 8px;
  background: rgba(255, 255, 255, 0.94);
  border-radius: 14px;
  padding: 8px 12px;
  box-shadow: 0 10px 30px rgba(8, 18, 28, 0.35);
}
.spot-bar input[type='range'] { width: 110px; }
.spot-btn {
  width: 30px;
  height: 30px;
  border-radius: 9px;
  display: grid;
  place-items: center;
  color: var(--ink-soft);
}
.spot-btn:hover { background: rgba(15, 118, 110, 0.12); color: var(--ink); }
.spot-btn.active { background: rgba(15, 118, 110, 0.16); color: var(--ink); }
.spot-btn .ic svg { width: 17px; height: 17px; }

/* ---------- Screen shades (pull tabs) ---------- */
.shade-root { position: fixed; inset: 0; z-index: 3100; pointer-events: none; }
.shade {
  position: absolute;
  background: linear-gradient(135deg, #1f2937, #22303c);
  pointer-events: auto;
  box-shadow: 0 0 24px rgba(8, 18, 28, 0.45);
}
.shade-top { top: 0; left: 0; right: 0; height: 0; }
.shade-bottom { bottom: 0; left: 0; right: 0; height: 0; }
.shade-left { top: 0; bottom: 0; left: 0; width: 0; }
.shade-right { top: 0; bottom: 0; right: 0; width: 0; }
.shade-tab {
  position: absolute;
  width: 64px;
  height: 26px;
  background: #f8fafc;
  border: 1px solid rgba(34, 48, 60, 0.25);
  box-shadow: 0 4px 12px rgba(8, 18, 28, 0.3);
  display: grid;
  place-items: center;
  cursor: grab;
  touch-action: none;
}
.shade-tab:active { cursor: grabbing; }
.shade-grip {
  width: 26px;
  height: 4px;
  border-radius: 2px;
  background: rgba(34, 48, 60, 0.4);
}
.shade-top .shade-tab { bottom: -26px; left: 50%; transform: translateX(-50%); border-radius: 0 0 12px 12px; border-top: none; }
.shade-bottom .shade-tab { top: -26px; left: 50%; transform: translateX(-50%); border-radius: 12px 12px 0 0; border-bottom: none; }
.shade-left .shade-tab,
.shade-right .shade-tab { width: 26px; height: 64px; top: 50%; transform: translateY(-50%); }
.shade-left .shade-tab { right: -26px; border-radius: 0 12px 12px 0; border-left: none; }
.shade-right .shade-tab { left: -26px; border-radius: 12px 0 0 12px; border-right: none; }
.shade-left .shade-grip,
.shade-right .shade-grip { width: 4px; height: 26px; }

/* teaching clock — quick teacher bar */
.tclock-quick {
  flex-shrink: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  align-items: center;
  justify-content: center;
}
.tq-btn {
  font-size: 11.5px;
  font-weight: 700;
  padding: 4px 9px;
  border-radius: 9px;
  background: rgba(34, 48, 60, 0.07);
  color: var(--ink-soft);
}
.tq-btn.active { background: rgba(15, 118, 110, 0.16); color: var(--ink); }
.tq-step {
  display: inline-flex;
  align-items: center;
  border-radius: 9px;
  background: rgba(34, 48, 60, 0.06);
  overflow: hidden;
}
.tq-mini {
  width: 20px;
  padding: 4px 0;
  font-weight: 800;
  font-size: 12px;
  color: var(--ink-soft);
}
.tq-mini:hover { background: rgba(15, 118, 110, 0.15); color: var(--ink); }
.tq-mini:disabled { opacity: 0.35; pointer-events: none; }
.tq-snap {
  font-size: 11px;
  font-weight: 700;
  padding: 4px 5px;
  color: var(--ink-soft);
}
.tq-snap.active { background: rgba(15, 118, 110, 0.22); color: var(--ink); }

/* ---------- Money pieces, tray & mat ---------- */
.mn-piece {
  position: relative;
  display: grid;
  place-items: center;
  border-radius: 50%;
  font-weight: 800;
  user-select: none;
  touch-action: none;
  flex-shrink: 0;
  box-shadow: 0 2px 5px rgba(15, 30, 45, 0.28);
}
.mn-label { position: relative; z-index: 1; letter-spacing: -0.2px; }
.mn-copper { background: radial-gradient(circle at 35% 30%, #d99a5b, #a05f2c 78%); color: #47270e; border: 2px solid #8a4f22; }
.mn-silver { background: radial-gradient(circle at 35% 30%, #eef1f4, #b3bcc6 78%); color: #38424d; border: 2px solid #939ea9; }
.mn-gold { background: radial-gradient(circle at 35% 30%, #f3d878, #cba43d 78%); color: #57430e; border: 2px solid #b28d2e; }
.mn-bimetal { background: radial-gradient(circle at 35% 30%, #f3d878, #cba43d 78%); color: #38424d; border: 2px solid #b28d2e; }
.mn-bimetal .mn-inner { position: absolute; inset: 20%; border-radius: 50%; background: radial-gradient(circle at 35% 30%, #eef1f4, #b9c2cb); }
.mn-bimetal2 { background: radial-gradient(circle at 35% 30%, #eef1f4, #b3bcc6 78%); color: #57430e; border: 2px solid #939ea9; }
.mn-bimetal2 .mn-inner { position: absolute; inset: 20%; border-radius: 50%; background: radial-gradient(circle at 35% 30%, #f3d878, #cba43d); }
.mn-hept { clip-path: polygon(50% 0%, 89% 19%, 98% 61%, 71% 95%, 29% 95%, 2% 61%, 11% 19%); border-radius: 0; border: none; box-shadow: none; filter: drop-shadow(0 2px 3px rgba(15, 30, 45, 0.3)); }
.mn-tok1 { background: radial-gradient(circle at 35% 30%, #a5b4fc, #6366f1 80%); color: #fff; border: 2px solid #4f46e5; }
.mn-tok2 { background: radial-gradient(circle at 35% 30%, #f9a8d4, #ec4899 80%); color: #fff; border: 2px solid #db2777; }
.mn-tok3 { background: radial-gradient(circle at 35% 30%, #5eead4, #14b8a6 80%); color: #fff; border: 2px solid #0d9488; }
.mn-tok4 { background: radial-gradient(circle at 35% 30%, #fcd34d, #f59e0b 80%); color: #fff; border: 2px solid #d97706; }
.mn-tok5 { background: radial-gradient(circle at 35% 30%, #86efac, #22c55e 80%); color: #fff; border: 2px solid #16a34a; }
.mn-tok6 { background: radial-gradient(circle at 35% 30%, #fca5a5, #ef4444 80%); color: #fff; border: 2px solid #dc2626; }
.mn-note { border-radius: 7px; border: 1.5px solid rgba(34, 48, 60, 0.35); color: rgba(34, 48, 60, 0.85); }
.mn-note::after {
  content: "";
  position: absolute;
  inset: 3px;
  border: 1px dashed rgba(255, 255, 255, 0.55);
  border-radius: 4px;
}
.mn-tray {
  display: flex;
  gap: 7px;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap; /* big money wraps onto extra rows instead of scrolling away */
  flex-shrink: 0;
  padding: 7px 8px;
  border-radius: 12px;
  background: rgba(34, 48, 60, 0.06);
  min-height: 58px;
}
.mn-cell { display: grid; place-items: center; cursor: grab; flex-shrink: 0; }
.mn-cell:active { cursor: grabbing; }
.mn-mat {
  position: relative;
  min-height: 110px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.5);
  border: 1px dashed rgba(34, 48, 60, 0.15);
  overflow: hidden;
  touch-action: none; /* the mat handles its own gestures: drag pieces, pinch to resize them */
}
.mn-loose { position: absolute; cursor: grab; }
.mn-loose:active { cursor: grabbing; }
.mn-anim .mn-loose { transition: left 0.3s ease, top 0.3s ease; }
.mn-binning { opacity: 0.35; }
.mn-bin {
  position: absolute;
  right: 10px;
  bottom: 10px;
  width: 62px;
  height: 62px;
  display: grid;
  place-items: center;
  font-size: 30px;
  border-radius: 16px;
  border: 2px dashed rgba(34, 48, 60, 0.25);
  background: rgba(255, 255, 255, 0.7);
  opacity: 0.45;
  pointer-events: none; /* a drop target only — never steals taps from the money */
  transition: opacity 0.15s ease, transform 0.15s ease, background 0.15s ease;
  z-index: 5000;
}
.mn-dragging .mn-bin { opacity: 1; }
.mn-bin.hot { background: #fee2e2; border-color: #ef4444; border-style: solid; transform: scale(1.12); }
.mntray { gap: 7px; }

/* classroom scale: money-widget lettering must read from the back of the room */
.mntray .tclock-task { font-size: 28px; padding: 12px 18px; }
.mntray .tq-btn { font-size: 19px; padding: 8px 14px; border-radius: 12px; }
.mntray .tq-step { border-radius: 12px; }
.mntray .tq-mini { width: 36px; font-size: 19px; padding: 8px 0; }
.mntray .tq-snap { font-size: 16px; padding: 8px 9px; min-width: 46px; text-align: center; }
.mntray .tclock-game .btn.small { font-size: 16px; padding: 6px 14px; }
.mntray .tclock-game .tclock-level { font-size: 15px; max-width: 220px; }
.mntray .tclock-score { font-size: 18px; padding: 5px 12px; }
.mntray .mn-tray { min-height: 66px; }
.mntray .shop-sign { font-size: 32px; }
.mntray .shop-screen { font-size: 32px; }
.mntray .shop-till { width: 220px; }
.mntray .shop-side-label { font-size: 19px; }

/* ---------- Frame tiles ---------- */
.fttiles .mn-tray { min-height: 52px; }
.ft-tile { position: relative; filter: drop-shadow(0 2px 3px rgba(15, 30, 45, 0.28)); }
.ft-cell {
  position: absolute;
  box-sizing: border-box;
  border: 2px solid rgba(15, 30, 45, 0.22);
  border-radius: 18%;
  display: grid;
  place-items: center;
}
.ft-hole {
  width: 58%;
  height: 58%;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.92);
  box-shadow: inset 0 2px 4px rgba(15, 30, 45, 0.35);
}
.ft-num {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-weight: 800;
  pointer-events: none;
}
.ft-frame { position: absolute; z-index: 1; pointer-events: none; }
.mn-loose.ft-tile { position: absolute; z-index: 2; }
.ft-fcell {
  position: absolute;
  box-sizing: border-box;
  border: 2px dashed rgba(34, 48, 60, 0.35);
  border-radius: 18%;
  background: rgba(255, 255, 255, 0.4);
}
.ft-frame.done {
  animation: ft-glow 0.6s ease;
  border-radius: 10px;
  box-shadow: 0 0 0 4px rgba(245, 158, 11, 0.55), 0 0 22px 8px rgba(245, 158, 11, 0.4);
}
.ft-frame.done .ft-fcell { border-color: #f59e0b; border-style: solid; background: #fef3c7; }
@keyframes ft-glow {
  50% { transform: scale(1.05); }
}

/* Flash: hide the holes and numerals so children recall the shape's value */
.ft-flash .ft-hole { opacity: 0; }
.ft-flash .ft-num { opacity: 0; }

/* segmented mat-mode buttons in the mode bar */
.ft-modebar { border-bottom: 1px dashed var(--panel-border); padding-bottom: 6px; }
.ft-seg { padding: 0; }
.ft-seg .tq-btn { border-radius: 0; background: transparent; }
.ft-seg .tq-btn + .tq-btn { border-left: 1px solid rgba(34, 48, 60, 0.12); }
.ft-seg .tq-btn.active { background: rgba(15, 118, 110, 0.16); color: var(--ink); }

/* number-line ruler backdrop */
.ft-ruler { position: absolute; inset: 0; pointer-events: none; z-index: 1; }
.ft-axis { position: absolute; height: 3px; background: #334155; border-radius: 2px; }
.ft-tick { position: absolute; width: 2px; height: 13px; background: #334155; transform: translate(-1px, -5px); }
.ft-tlabel { position: absolute; transform: translateX(-50%); font-weight: 800; font-size: 13px; color: #475569; }

/* compare balance backdrop */
.ft-divider { position: absolute; top: 6%; height: 88%; width: 2px; background: rgba(34, 48, 60, 0.22); border-radius: 2px; z-index: 1; }
.ft-panlabel { position: absolute; top: 8px; font-size: 24px; font-weight: 800; color: rgba(34, 48, 60, 0.28); z-index: 1; }
.ft-subtotal {
  position: absolute;
  top: 42px;
  font-weight: 800;
  font-size: 15px;
  background: rgba(255, 255, 255, 0.92);
  border-radius: 9px;
  padding: 3px 10px;
  box-shadow: 0 1px 4px rgba(15, 30, 45, 0.14);
  z-index: 1;
}
.ft-cmp {
  position: absolute;
  left: 50%;
  top: 42%;
  transform: translateX(-50%);
  font-size: 34px;
  font-weight: 900;
  color: #0f766e;
  background: rgba(255, 255, 255, 0.92);
  border-radius: 12px;
  min-width: 46px;
  text-align: center;
  padding: 2px 10px;
  box-shadow: 0 2px 8px rgba(15, 30, 45, 0.16);
  z-index: 1;
}

/* board scale: mode bar reads from the back of the room too */
.mntray.fttiles .ft-modebar .tq-btn { font-size: 19px; padding: 8px 14px; }
.mntray.fttiles .ft-panlabel { font-size: 34px; }
.mntray.fttiles .ft-subtotal { font-size: 22px; padding: 5px 13px; }
.mntray.fttiles .ft-cmp { font-size: 46px; padding: 4px 16px; }
.mntray.fttiles .ft-tlabel { font-size: 17px; }

/* ---------- Bar model ---------- */
.bm-mat {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 20px;
  min-height: 90px;
  padding: 16px 18px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.5);
  border: 1px dashed rgba(34, 48, 60, 0.15);
  overflow: hidden;
}
.bm-row { display: flex; align-items: flex-end; gap: 10px; }
.bm-name {
  width: 88px;
  flex-shrink: 0;
  border: none;
  background: rgba(34, 48, 60, 0.06);
  border-radius: 9px;
  padding: 7px 9px;
  font: inherit;
  font-size: 16px;
  font-weight: 700;
  color: var(--ink, #22303c);
  text-align: right;
}
.bm-track { flex: 1; min-width: 0; }
.bm-brk {
  position: relative;
  height: 13px;
  margin-bottom: 7px;
  min-width: 34px;
  border: 2.5px solid var(--ink, #22303c);
  border-bottom: none;
  border-radius: 9px 9px 0 0;
  transition: width 0.25s ease;
}
.bm-brk-chip {
  position: absolute;
  left: 50%;
  top: 0;
  transform: translate(-50%, -55%);
  padding: 2px 13px;
  border-radius: 999px;
  background: #fff;
  border: 2px solid #22303c;
  font-weight: 800;
  color: #22303c;
  line-height: 1.25;
  white-space: nowrap;
}
.bm-bar {
  display: flex;
  min-width: 34px;
  border-radius: 10px;
  filter: drop-shadow(0 2px 3px rgba(15, 30, 45, 0.22));
  transition: width 0.25s ease, height 0.15s ease;
}
.bm-seg {
  position: relative;
  display: grid;
  place-items: center;
  min-width: 30px;
  padding: 0;
  border: 2.5px solid;
  border-radius: 0;
  margin-left: -2.5px; /* neighbouring parts share one border line */
  font-weight: 800;
  color: #22303c;
  touch-action: manipulation;
  transition: width 0.25s ease;
}
.bm-seg:first-of-type { border-radius: 10px 0 0 10px; margin-left: 0; }
.bm-seg:last-of-type { border-radius: 0 10px 10px 0; }
.bm-seg:only-of-type { border-radius: 10px; }
.bm-seg.active { z-index: 2; outline: 3px solid rgba(15, 118, 110, 0.7); outline-offset: 2px; }
.bm-seg.hidden-val::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: repeating-linear-gradient(45deg, rgba(255, 255, 255, 0.5) 0 9px, rgba(255, 255, 255, 0) 9px 18px);
  pointer-events: none;
}
.bm-val { position: relative; z-index: 1; }
.bm-units {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  opacity: 0.65;
  pointer-events: none;
}
.bm-live .bm-units { display: none; } /* cell count goes stale mid-drag */

/* sub-bracket: brace under a run of parts, chip hangs below */
.bm-brk.bm-sub {
  border: 2.5px solid var(--ink, #22303c);
  border-top: none;
  border-radius: 0 0 9px 9px;
  margin-top: 7px;
  margin-bottom: 0;
  transition: width 0.25s ease, margin-left 0.25s ease;
}
.bm-brk-chip.on-sub { top: auto; bottom: 0; transform: translate(-50%, 55%); }

/* number sentence strip (fact families) */
.bm-sent {
  flex-shrink: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 22px;
  align-items: center;
  justify-content: center;
  padding: 2px 6px;
  font-weight: 800;
  font-size: 21px;
  color: var(--ink, #22303c);
}
.bm-fact { white-space: nowrap; }

/* join + end drag handles: zero-width flex children that ride the boundaries */
.bm-div,
.bm-end {
  position: relative;
  width: 0;
  flex: 0 0 0;
  align-self: stretch;
  z-index: 3;
  cursor: ew-resize;
  touch-action: none;
}
.bm-div::before,
.bm-end::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: -10px;
  width: 20px;
}
.bm-div::after,
.bm-end::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  transform: translate(-50%, -50%);
  width: 5px;
  height: 46%;
  border-radius: 3px;
  background: rgba(34, 48, 60, 0.3);
  pointer-events: none;
  transition: background 0.15s ease;
}
.bm-end::after { height: 62%; background: rgba(34, 48, 60, 0.45); }
.bm-div:hover::after,
.bm-end:hover::after { background: rgba(15, 118, 110, 0.8); }
.bm-live .bm-seg,
.bm-live .bm-bar,
.bm-live .bm-brk { transition: none; }

/* difference arrow between neighbouring bars (comparison models) */
.bm-diff {
  position: relative;
  height: 14px;
  margin-bottom: 8px;
  min-width: 26px;
  z-index: 2;
  transition: width 0.25s ease, margin-left 0.25s ease;
}
.bm-diff::before {
  content: "";
  position: absolute;
  left: 2px;
  right: 2px;
  top: 50%;
  margin-top: -1.25px;
  border-top: 2.5px solid var(--ink, #22303c);
}
.bm-diff-l,
.bm-diff-r {
  position: absolute;
  top: 50%;
  width: 0;
  height: 0;
  border: 6px solid transparent;
  transform: translateY(-50%);
}
.bm-diff-l { left: -2px; border-left: none; border-right: 9px solid var(--ink, #22303c); }
.bm-diff-r { right: -2px; border-right: none; border-left: 9px solid var(--ink, #22303c); }
.bm-brk-chip.on-line { top: 50%; transform: translate(-50%, -50%); }

@keyframes bm-pop {
  0% { transform: scale(0.2); opacity: 0; }
  60% { transform: scale(1.25); }
  100% { transform: scale(1); opacity: 1; }
}
.bm-pop { animation: bm-pop 0.45s cubic-bezier(0.34, 1.56, 0.64, 1); }
.bm-empty { text-align: center; color: var(--ink-soft, #5b6b7b); font-weight: 700; padding: 20px; }
.bm-ctx { border-bottom: 1px dashed var(--panel-border); padding-bottom: 6px; }
.bm-vin {
  width: 74px;
  border: none;
  background: transparent;
  text-align: center;
  font: inherit;
  font-size: 18px;
  font-weight: 800;
  color: var(--ink, #22303c);
  padding: 4px 2px;
}
.bm-vin.bm-lin {
  width: 92px;
  background: rgba(34, 48, 60, 0.06);
  border-radius: 9px;
  font-size: 15px;
  font-weight: 700;
}
.bm-swatch { display: inline-flex; align-items: center; gap: 6px; }
.bm-swdot {
  width: 15px;
  height: 15px;
  border-radius: 5px;
  background: var(--sw, #fca5a5);
  border: 1.5px solid rgba(34, 48, 60, 0.4);
}

/* ---------- Two-colour counters ---------- */
.ct-mat {
  position: relative;
  min-height: 90px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.5);
  border: 1px dashed rgba(34, 48, 60, 0.15);
  overflow: hidden;
  touch-action: none;
}
.ct-c {
  position: absolute;
  z-index: 1;
  padding: 0;
  border-radius: 50%;
  border: 2.5px solid;
  touch-action: none;
  filter: drop-shadow(0 2px 3px rgba(15, 30, 45, 0.25));
}
.ct-c::after {
  content: "";
  position: absolute;
  inset: 10%;
  border-radius: 50%;
  background: radial-gradient(circle at 32% 28%, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0) 58%);
  pointer-events: none;
}
.ct-c.ct-drag { filter: drop-shadow(0 5px 9px rgba(15, 30, 45, 0.35)); }
.ct-c.ct-out { opacity: 0.35; }
.ct-frame {
  position: absolute;
  z-index: 0;
  pointer-events: none;
  background-color: #e9edf2; /* light grey — red and especially yellow counters pop against it */
  border: 3.5px solid var(--ink, #22303c);
  border-radius: 10px;
  background-image:
    linear-gradient(to right, var(--ink, #22303c) 3px, transparent 3px),
    linear-gradient(to bottom, var(--ink, #22303c) 3px, transparent 3px);
  box-shadow: 0 3px 8px rgba(15, 30, 45, 0.14);
}
.ct-bin {
  position: absolute;
  right: 10px;
  bottom: 10px;
  z-index: 0;
  width: 62px;
  height: 62px;
  display: grid;
  place-items: center;
  font-size: 30px;
  border-radius: 16px;
  border: 2px dashed rgba(34, 48, 60, 0.25);
  background: rgba(255, 255, 255, 0.7);
  opacity: 0.45;
  pointer-events: none; /* a drop target only — taps pass through to the mat */
  transition: opacity 0.15s ease, transform 0.15s ease, background 0.15s ease;
}
.ct-mat.ct-dragging .ct-bin { opacity: 1; }
.ct-bin.hot { background: #fee2e2; border-color: #ef4444; border-style: solid; transform: scale(1.12); }
.ct-grid {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: radial-gradient(circle, rgba(34, 48, 60, 0.35) 2px, transparent 2.5px);
}
.ct-ring {
  position: absolute;
  z-index: 0;
  border: 3px solid var(--ink, #22303c);
  border-radius: 50%;
  background: #e9edf2; /* opaque (branch lines stop at the rim) — grey to match the frame cells */
  pointer-events: none;
}
.ct-blind {
  position: absolute;
  inset: 6px;
  z-index: 5;
  display: grid;
  place-items: center;
  border-radius: 10px;
  background: linear-gradient(135deg, #334155, #22303c);
  color: #fff;
  font-size: 64px;
  font-weight: 800;
}
.ct-hint {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 12px;
  z-index: 2; /* floats over the frame edge on tall mats instead of striking through it */
  width: max-content;
  max-width: calc(100% - 24px);
  margin: 0 auto;
  padding: 6px 14px;
  font-size: 13px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.88);
  border: 1px solid rgba(34, 48, 60, 0.12);
  box-shadow: 0 2px 6px rgba(15, 30, 45, 0.1);
  pointer-events: none; /* taps must reach the mat beneath — the hint is the one thing a tap dismisses */
}

/* ---------- Base 10 (Dienes) ---------- */
.dn-col {
  position: absolute;
  top: 0;
  z-index: 0;
}
.dn-col + .dn-col { border-left: 2.5px solid rgba(34, 48, 60, 0.45); }
.dn-head {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  font-weight: 800;
  color: var(--ink, #22303c);
  letter-spacing: 0.01em;
  background: rgba(255, 255, 255, 0.55);
  border-bottom: 3px solid rgba(34, 48, 60, 0.55);
}
.dn-count {
  min-width: 24px;
  padding: 1px 8px;
  border-radius: 999px;
  background: rgba(34, 48, 60, 0.08);
  font-size: 0.82em;
  text-align: center;
}
.dn-count.hot { background: #fee2e2; color: #b91c1c; }
.dn-xchip {
  border: none;
  cursor: pointer;
  font: inherit;
  font-size: 0.78em;
  font-weight: 800;
  padding: 2px 10px;
  border-radius: 999px;
  background: #fbbf24;
  color: #78350f;
  animation: dn-glow 1.5s ease-in-out infinite;
}
@keyframes dn-glow {
  0%, 100% { transform: scale(1); box-shadow: 0 2px 5px rgba(180, 83, 9, 0.3); }
  50% { transform: scale(1.07); box-shadow: 0 3px 12px rgba(180, 83, 9, 0.55); }
}
.dn-chips {
  position: absolute;
  top: 8px;
  left: 0;
  right: 0;
  z-index: 2;
  display: flex;
  justify-content: center;
  gap: 8px;
  pointer-events: none;
}
.dn-chips .dn-xchip { pointer-events: auto; font-size: 15px; }
.dn-p {
  position: absolute;
  z-index: 1;
  display: grid;
  place-items: center;
  padding: 0;
  margin: 0;
  background: none;
  border: none;
  cursor: grab;
  touch-action: none;
}
.dn-p svg {
  display: block;
  filter: drop-shadow(0 2px 2.5px rgba(15, 30, 45, 0.28));
  pointer-events: none;
}
.dn-p.ct-drag svg { filter: drop-shadow(0 6px 10px rgba(15, 30, 45, 0.4)); }
.dn-p.ct-out { opacity: 0.35; }
.dn-merge { transition: left 0.34s ease-in, top 0.34s ease-in, transform 0.34s ease-in, opacity 0.34s ease-in; }
.dn-tray {
  display: flex;
  align-items: stretch;
  gap: 8px;
}
.dn-tpc {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: 3px;
  padding: 5px 10px;
  border-radius: 12px;
  border: 2px solid rgba(34, 48, 60, 0.12);
  background: rgba(255, 255, 255, 0.6);
  cursor: pointer;
  touch-action: none;
}
.dn-tpc.active { border-color: #f59e0b; background: #fef3c7; }
.dn-tpc svg { display: block; }
.dn-tval { font-size: 12.5px; font-weight: 800; color: var(--ink-soft, #5b6b7b); }
.dn-value {
  margin-left: auto;
  align-self: center;
  min-width: 96px;
  padding: 4px 18px;
  border-radius: 14px;
  border: 2.5px solid rgba(34, 48, 60, 0.65);
  background: #fff;
  font-weight: 800;
  font-size: 34px;
  color: var(--ink, #22303c);
  text-align: center;
  cursor: pointer;
}
.dn-value.masked { background: linear-gradient(135deg, #334155, #22303c); color: #fff; }
.dn-nts {
  position: absolute;
  right: 84px; /* clear of the bin — the leftmost column hosts the tallest towers */
  bottom: 8px;
  z-index: 0;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.03em;
  color: var(--ink-soft, #5b6b7b);
  opacity: 0.65;
  pointer-events: none;
}
.dn-goal { font-size: 26px; font-weight: 900; padding: 0 10px; color: var(--ink, #22303c); }
.dn-goal.done { color: #16a34a; }
.dn-streak { font-size: 19px; font-weight: 800; color: var(--ink-soft, #5b6b7b); }

/* ---------- Place value counters ---------- */
/* seven-place stem sentences outgrow one line — let them wrap mid-fact */
.pvwidget .bm-fact { white-space: normal; text-align: center; }
.pv-c {
  position: absolute;
  z-index: 1;
  display: grid;
  place-items: center;
  padding: 0;
  border-radius: 50%;
  border: 2.5px solid;
  font-family: inherit;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1;
  cursor: grab;
  touch-action: none;
  filter: drop-shadow(0 2px 3px rgba(15, 30, 45, 0.25));
}
.pv-c::after {
  content: "";
  position: absolute;
  inset: 9%;
  border-radius: 50%;
  background: radial-gradient(circle at 32% 28%, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 55%);
  pointer-events: none;
}
.pv-c.ct-drag { filter: drop-shadow(0 5px 9px rgba(15, 30, 45, 0.35)); }
.pv-c.ct-out { opacity: 0.35; }
.pv-fr {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  line-height: 1.08;
}
.pv-fr b { font-weight: inherit; border-bottom: 0.09em solid currentColor; padding: 0 0.3em 0.05em; }
.pv-fr i { font-style: normal; padding-top: 0.05em; }
.pv-dp {
  position: absolute;
  z-index: 2;
  border-radius: 50%;
  background: var(--ink, #22303c);
  border: 2.5px solid #fff;
  box-shadow: 0 1px 4px rgba(15, 30, 45, 0.35);
  pointer-events: none;
}
.pv-tc {
  position: relative;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 2.5px solid;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1;
  filter: drop-shadow(0 1.5px 2px rgba(15, 30, 45, 0.2));
}
.pv-tc::after {
  content: "";
  position: absolute;
  inset: 9%;
  border-radius: 50%;
  background: radial-gradient(circle at 32% 28%, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 55%);
  pointer-events: none;
}

/* ---------- Rekenrek ---------- */
.ct-mat.rk-mat {
  border: 11px solid #b45309;
  border-radius: 20px;
  background: linear-gradient(180deg, #fffdf5, #fdf6e3);
  box-shadow: inset 0 2px 8px rgba(120, 53, 15, 0.18), 0 3px 8px rgba(15, 30, 45, 0.12);
}
.rk-rod {
  position: absolute;
  left: 4px;
  right: 4px;
  height: 6px;
  border-radius: 3px;
  background: linear-gradient(180deg, #cbd5e1, #64748b 55%, #94a3b8);
  box-shadow: 0 1px 2px rgba(15, 30, 45, 0.35);
}
.rk-bead {
  position: absolute;
  z-index: 1;
  padding: 0;
  border-radius: 50%;
  border: 2px solid;
  cursor: grab;
  touch-action: none;
  transition: left 0.18s ease;
  filter: drop-shadow(0 2px 2.5px rgba(15, 30, 45, 0.3));
}
.rk-bead::after {
  content: "";
  position: absolute;
  inset: 8%;
  border-radius: 50%;
  background: radial-gradient(circle at 33% 28%, rgba(255, 255, 255, 0.65), rgba(255, 255, 255, 0) 52%);
  pointer-events: none;
}
.rk-bead.rk-drag { transition: none; z-index: 3; filter: drop-shadow(0 5px 8px rgba(15, 30, 45, 0.4)); }
.rk-red { background: radial-gradient(circle at 40% 35%, #f87171, #dc2626 55%, #b91c1c); border-color: #7f1d1d; }
.rk-white { background: radial-gradient(circle at 40% 35%, #ffffff, #f1f5f9 60%, #e2e8f0); border-color: #94a3b8; }

/* ---------- Number line ---------- */
.nl-mat { touch-action: none; }
.nl-svg { position: absolute; inset: 0; pointer-events: none; }
.nl-svg .nl-line, .nl-svg .nl-ticks, .nl-svg .nl-mtick { stroke: var(--ink, #22303c); fill: none; }
.nl-svg .nl-line { stroke-width: 3.5; stroke-linecap: round; }
.nl-svg .nl-ticks { stroke-width: 2.5; }
.nl-svg .nl-mtick { stroke: #0f766e; stroke-width: 3.5; stroke-linecap: round; }
.nl-svg .nl-cap { fill: var(--ink, #22303c); }
.nl-svg .nl-jump { stroke: #0f766e; stroke-width: 3.5; fill: none; stroke-linecap: round; }
.nl-svg .nl-arrow { fill: #0f766e; }
.nl-svg .nl-prev { stroke-dasharray: 7 6; opacity: 0.65; }
.nl-lab {
  position: absolute;
  transform: translate(-50%, 0);
  font-weight: 800;
  line-height: 1.05;
  text-align: center;
  color: var(--ink, #22303c);
  pointer-events: none;
}
.nl-lab .pv-fr, .nl-jlab .pv-fr { font-size: 0.82em; vertical-align: middle; }
.nl-jlab, .nl-mlab {
  position: absolute;
  transform: translate(-50%, -50%);
  font: inherit;
  font-weight: 800;
  line-height: 1.05;
  padding: 2px 11px;
  border-radius: 999px;
  background: #fff;
  border: 2px solid rgba(15, 118, 110, 0.55);
  color: var(--ink, #22303c);
  cursor: pointer;
  touch-action: none;
  box-shadow: 0 2px 5px rgba(15, 30, 45, 0.14);
}
.nl-mlab { transform: translate(-50%, 0); border-color: rgba(34, 48, 60, 0.4); }
.nl-jlab.empty, .nl-mlab.empty { color: var(--ink-soft, #5b6b7b); border-style: dashed; }
.nl-jlab.ct-out, .nl-mlab.ct-out, .nl-dot.ct-out { opacity: 0.35; }
.nl-dot {
  position: absolute;
  z-index: 1;
  width: 26px;
  height: 26px;
  padding: 0;
  border: none;
  background: none;
  cursor: grab;
  touch-action: none;
}
.nl-dot::after {
  content: "";
  position: absolute;
  inset: 6px;
  border-radius: 50%;
  background: #0f766e;
  border: 2.5px solid #fff;
  box-shadow: 0 1px 4px rgba(15, 30, 45, 0.35);
}
.nl-ed {
  position: absolute;
  transform: translate(-50%, -50%);
  z-index: 6;
  display: flex;
  align-items: center;
  gap: 4px;
}
.nl-ed input {
  width: 86px;
  font: inherit;
  font-weight: 800;
  text-align: center;
  padding: 3px 8px;
  border: 2.5px solid #0f766e;
  border-radius: 10px;
  background: #fff;
  color: var(--ink, #22303c);
}
.nl-ed button {
  font: inherit;
  font-weight: 800;
  padding: 3px 9px;
  border-radius: 10px;
  border: 2px solid rgba(185, 28, 28, 0.5);
  background: #fee2e2;
  color: #b91c1c;
  cursor: pointer;
}

/* ---------- Part–whole model ---------- */
.pw-mat {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 90px;
  padding: 14px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.5);
  border: 1px dashed rgba(34, 48, 60, 0.15);
  overflow: hidden;
}
.pw-diag {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 52px;
  max-width: 100%;
  max-height: 100%;
}
.pw-diag.o-top { flex-direction: column; }
.pw-diag.o-bottom { flex-direction: column-reverse; }
.pw-diag.o-left { flex-direction: row; }
.pw-diag.o-right { flex-direction: row-reverse; }
.pw-lines { position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: visible; }
.pw-lines line { stroke: var(--ink, #22303c); stroke-width: 3.5px; stroke-linecap: round; }
.pw-zone { display: flex; align-items: center; justify-content: center; }
.pw-parts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 16px;
  max-width: 100%;
}
.o-left .pw-parts,
.o-right .pw-parts { flex-direction: column; flex-wrap: nowrap; }
.pw-node {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  flex-shrink: 0;
  padding: 0;
  border-radius: 50%;
  border: 3px solid var(--ink, #22303c);
  background: #fff;
  font-weight: 800;
  color: #22303c;
  touch-action: manipulation;
  filter: drop-shadow(0 2px 3px rgba(15, 30, 45, 0.18));
}
.pw-whole { border-width: 3.5px; }
.pw-node.active { z-index: 2; outline: 3px solid rgba(15, 118, 110, 0.7); outline-offset: 2px; }
.pw-node.hidden-val::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: repeating-linear-gradient(45deg, rgba(255, 255, 255, 0.5) 0 9px, rgba(255, 255, 255, 0) 9px 18px);
  pointer-events: none;
}
.pw-val { position: relative; z-index: 1; }
.pw-dots {
  position: relative;
  z-index: 1;
  display: grid;
  gap: 3px;
  justify-content: center;
  align-content: center;
}
.pw-dots i {
  display: block;
  width: var(--dot, 12px);
  height: var(--dot, 12px);
  box-sizing: border-box;
  border-radius: 50%;
  border: 1.5px solid;
}

/* ---------- Class shop ---------- */
.shop-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; flex-shrink: 0; }
.shop-sign { font-weight: 800; font-size: 21px; padding-top: 4px; }
.shop-till { width: 150px; flex-shrink: 0; }
.shop-screen {
  background: #22303c;
  color: #a7f3d0;
  border-radius: 9px;
  padding: 6px 10px;
  text-align: center;
  font-weight: 800;
  font-size: 21px;
  font-variant-numeric: tabular-nums;
}
.shop-drawer {
  height: 8px;
  margin: 3px auto 0;
  width: 86%;
  background: #64748b;
  border-radius: 0 0 9px 9px;
  text-align: center;
  font-size: 13px;
  line-height: 26px;
  overflow: hidden;
  transition: height 0.35s ease, background 0.35s ease;
}
.shop-till.open .shop-drawer { height: 26px; background: #475569; }
.shop-mat::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 6px;
  bottom: 6px;
  border-left: 3px dashed rgba(34, 48, 60, 0.22);
}
.shop-side-label {
  position: absolute;
  top: 6px;
  font-size: 12px;
  font-weight: 700;
  color: var(--ink-soft);
  pointer-events: none;
}
.shop-side-label.shop-left { left: 10px; }
.shop-side-label.shop-right { right: 10px; }

/* money pieces wearing real photos */
.mn-hasimg { overflow: hidden; }
.mn-piece .mn-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}
.mn-coin.mn-hasimg { border-color: rgba(34, 48, 60, 0.25); }
.mn-hasimg .mn-label {
  position: absolute;
  bottom: 1px;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(255, 255, 255, 0.88);
  border-radius: 6px;
  padding: 0 4px;
  /* font-size comes from moneyPieceEl so it scales with the money zoom */
  line-height: 1.35;
  color: #22303c;
  white-space: nowrap;
}
.mn-note.mn-hasimg::after { display: none; }

/* per-denomination upload manager in settings */
.mn-uplist { display: flex; flex-direction: column; gap: 6px; }
.mn-uprow { display: flex; align-items: center; gap: 8px; }
.mn-uprow .mn-piece { transform: scale(0.72); margin: -5px; flex-shrink: 0; }
.mn-upimg {
  width: 34px;
  height: 34px;
  object-fit: cover;
  border-radius: 50%;
  border: 1px solid var(--panel-border);
  flex-shrink: 0;
}

/* ---------------------------------------------------------------- screen export */
.deck-select-check {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.9);
  border: 2px solid var(--accent);
  color: #fff;
  font-weight: 800;
  font-size: 15px;
}
.deck-select-check.on { background: var(--accent); }
.deck-card.selected .deck-thumb { outline: 3px solid var(--accent); outline-offset: -1px; }
.deck-select-bar {
  position: sticky;
  bottom: 0;
  display: flex;
  gap: 6px;
  justify-content: flex-end;
  padding: 8px 2px;
  background: var(--panel);
  border-top: 1px solid var(--panel-border);
}
.btn.disabled { opacity: 0.45; pointer-events: none; }

.export-formats { display: grid; gap: 8px; margin: 12px 0; }
.export-format-card {
  text-align: left;
  padding: 10px 14px;
  border-radius: 12px;
  border: 2px solid var(--panel-border);
  background: transparent;
  cursor: pointer;
}
.export-format-card.active { border-color: var(--accent); background: rgba(15, 118, 110, 0.06); }
.export-format-title { font-weight: 800; }
.export-format-desc { font-size: 12.5px; color: var(--ink-soft); margin-top: 2px; }

.export-progress {
  height: 10px;
  border-radius: 6px;
  background: var(--panel-border);
  overflow: hidden;
  margin-top: 10px;
}
.export-progress-fill {
  height: 100%;
  width: 2%;
  border-radius: 6px;
  background: var(--accent);
  transition: width 0.25s ease;
}
.export-progress-label { font-weight: 700; }
.export-warnings { margin: 8px 0 14px; padding-left: 20px; font-size: 13.5px; }
.export-warnings li { margin: 3px 0; }

.export-placeholder {
  height: 100%;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 6px;
  text-align: center;
  padding: 10px;
  color: var(--ink, #22303c);
}
.export-placeholder-icon .ic svg { width: 42px; height: 42px; }
.export-placeholder-title { font-weight: 800; }
.export-placeholder-url {
  font-size: 12px;
  color: var(--ink-soft, #5b6b7b);
  word-break: break-all;
}

/* ---------------------------------------------------------------- phoneme tiles (english-word.js) */
.pt-mat { touch-action: none; }
.pt-target {
  position: absolute;
  left: 50%;
  top: 8px;
  transform: translateX(-50%);
  z-index: 2;
  padding: 3px 18px;
  border-radius: 999px;
  background: #fef3c7;
  border: 2px solid #f59e0b;
  color: #78350f;
  font-weight: 800;
  font-size: 21px;
  letter-spacing: 0.12em;
}
.pt-tile {
  position: absolute;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 0.28em;
  border-radius: 10px;
  border: 2.5px solid #b45309;
  background: #fcd34d;
  color: #78350f;
  font-weight: 800;
  line-height: 1;
  touch-action: none;
  filter: drop-shadow(0 2px 3px rgba(15, 30, 45, 0.25));
}
.pt-tile.ct-drag { filter: drop-shadow(0 5px 9px rgba(15, 30, 45, 0.35)); }
.pt-tile.ct-out { opacity: 0.35; }
.pt-trick {
  border-radius: 999px;
  background: #fbcfe8;
  border-color: #be185d;
  color: #831843;
  padding: 0 0.7em;
  white-space: nowrap;
}
.pt-trick::before { content: '★'; font-size: 0.5em; margin-right: 0.35em; color: #be185d; }
.pt-split { position: absolute; z-index: 1; pointer-events: none; touch-action: none; }
.pt-split .pt-half {
  position: absolute;
  top: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  border: 2.5px solid #b45309;
  background: #fcd34d;
  color: #78350f;
  font-weight: 800;
  line-height: 1;
  pointer-events: auto;
  touch-action: none;
  filter: drop-shadow(0 2px 3px rgba(15, 30, 45, 0.25));
}
.pt-split .pt-half:first-of-type { left: 0; }
.pt-split .pt-half:last-of-type { right: 0; }
.pt-split.ct-drag .pt-half { filter: drop-shadow(0 5px 9px rgba(15, 30, 45, 0.35)); }
.pt-split.ct-out { opacity: 0.35; }
.pt-splitarc { position: absolute; left: 14%; right: 14%; bottom: -7px; width: 72%; height: 13px; display: none; }
.pt-split.pt-split-loose .pt-splitarc { display: block; }
.pt-sounds { position: absolute; z-index: 0; pointer-events: none; overflow: visible; }
.pt-sg {
  stroke: var(--ink, #22303c);
  fill: none;
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 0.2s ease, stroke 0.2s ease, fill 0.2s ease;
}
circle.pt-sg { fill: var(--ink, #22303c); stroke: none; }
/* the sustained beat: the button grows and holds while the sound is voiced */
.pt-sg.pt-pulse { stroke: #0f766e; transform: scale(1.65); }
circle.pt-sg.pt-pulse { fill: #0f766e; }
/* during sound-talk everything steps back and one grapheme takes the light —
   the cue carries with no words: this sound, now, for this long */
.pt-tile, .pt-split { transition: opacity 0.2s ease, transform 0.18s ease; }
.pt-talking .pt-tile:not(.pt-say),
.pt-talking .pt-split:not(.pt-say) { opacity: 0.32; }
.pt-tile.pt-say, .pt-split.pt-say { transform: scale(1.16); z-index: 30; }
.pt-tile.pt-say { box-shadow: 0 0 0 5px #0f766e, 0 0 20px 6px rgba(13, 148, 136, 0.5); }
.pt-split.pt-say .pt-half { box-shadow: 0 0 0 5px #0f766e, 0 0 20px 6px rgba(13, 148, 136, 0.5); }
.pt-sweep {
  position: absolute;
  z-index: 0;
  border-radius: 999px;
  background: rgba(34, 48, 60, 0.1);
}
.pt-sweep i { position: absolute; left: 0; top: 0; bottom: 0; width: 0; border-radius: 999px; background: #14b8a6; }
.pt-sweep.run i { animation: pt-sweeprun var(--sweep-ms, 1200ms) linear forwards; }
@keyframes pt-sweeprun { from { width: 0; } to { width: 100%; } }
/* the follow-along ball riding the sweep's leading edge */
.pt-sweep b {
  position: absolute;
  top: 50%;
  left: 0;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: #0f766e;
  transform: translate(-50%, -50%);
  opacity: 0;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.92), 0 2px 8px rgba(15, 30, 45, 0.35);
}
.pt-sweep.run b { opacity: 1; animation: pt-sweepball var(--sweep-ms, 1200ms) linear forwards; }
@keyframes pt-sweepball { from { left: 0%; } to { left: 100%; } }
/* the tray never scrolls or clips — every grapheme stays visible to choose
   from; tiles scale with the widget (--pt-tray set from the mat width) and
   the mat above takes whatever height the wrapped rows leave */
.pt-tray {
  flex-shrink: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.3em;
  align-items: center;
  justify-content: center;
  padding: 2px 4px;
  font-size: var(--pt-tray, 17px);
}
.pt-tray-tile {
  font-weight: 800;
  color: #78350f;
  background: #fef3c7;
  border: 2px solid #fbbf24;
  border-radius: 0.45em;
  padding: 0.22em 0.55em;
  font-size: 1em;
  touch-action: none;
}
.pt-tray-tile.pt-trickchip {
  background: #fce7f3;
  border-color: #f9a8d4;
  color: #831843;
  border-radius: 999px;
}
.pt-ph {
  font-size: 0.62em;
  font-weight: 700;
  color: var(--ink-soft, #5b6b7b);
  background: rgba(34, 48, 60, 0.07);
  border-radius: 999px;
  padding: 0.3em 0.85em;
}
.pt-star {
  margin-left: 0.4em;
  font-weight: 800;
  font-size: 0.74em;
  color: #831843;
  background: #fce7f3;
  border: 2px solid transparent;
  border-radius: 999px;
  padding: 0.28em 0.75em;
}
.pt-star.active { border-color: #be185d; }
.pt-saylab {
  font-size: 11px;
  font-weight: 700;
  color: var(--ink-soft, #5b6b7b);
  padding: 0 4px 0 10px;
  align-self: center;
  white-space: nowrap;
}
.mntray .pt-saylab { font-size: 15px; }

/* ---- word class sorter: cards into labelled class columns (design §6.3) ---- */
.wswidget .ws-cols,
.wswidget .ws-pool { font-size: var(--ws-fs, 16px); }
.ws-cols {
  position: relative;
  display: flex;
  gap: 8px;
  padding: 4px 6px 0;
  min-height: 0;
}
.ws-col {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  border: 2px dashed rgba(34, 48, 60, 0.28);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.55);
  transition: border-color 0.15s ease, background 0.15s ease;
}
.ws-col.ws-over,
.ws-pool.ws-over { border-style: solid; border-color: #0f766e; background: rgba(20, 184, 166, 0.14); }
.ws-cols.ws-dragging .ct-bin { opacity: 1; }
.ws-col-h {
  text-align: center;
  font-weight: 800;
  font-size: max(0.82em, 12px);
  color: #134e4a;
  padding: 0.32em 0.2em;
  border-bottom: 2px solid rgba(34, 48, 60, 0.1);
  white-space: nowrap;
  overflow: hidden;
}
.ws-col-cards {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  justify-content: center;
  gap: 0.35em;
  padding: 0.4em 0.25em;
  overflow: hidden;
}
.ws-card {
  position: relative;
  font-weight: 800;
  color: #1f2937;
  background: #fff;
  border: 2px solid #94a3b8;
  border-radius: 0.5em;
  padding: 0.26em 0.55em;
  font-size: 1em;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}
.ws-card.ws-lift { opacity: 0.35; }
.ws-card.ws-ok { border-color: #16a34a; background: #f0fdf4; }
.ws-card.ws-no { border-color: #dc2626; background: #fef2f2; }
/* the trap's gold ring: correct in more than one column — the discussion cue */
.ws-card.ws-gold { box-shadow: 0 0 0 3px #f59e0b, 0 0 14px 2px rgba(245, 158, 11, 0.4); }
.ws-badge {
  position: absolute;
  top: -0.6em;
  right: -0.5em;
  width: 1.4em;
  height: 1.4em;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  font-size: 0.64em;
  color: #fff;
  background: #16a34a;
  box-shadow: 0 1px 4px rgba(15, 30, 45, 0.3);
}
.ws-no .ws-badge { background: #dc2626; }
.ws-gold .ws-badge { background: #f59e0b; }
.ws-pool {
  flex-shrink: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35em;
  align-items: center;
  justify-content: center;
  padding: 4px 6px;
  min-height: 2.4em;
  border-top: 2px dashed rgba(34, 48, 60, 0.14);
  transition: border-color 0.15s ease, background 0.15s ease;
}
.ws-poolhint { font-size: max(0.72em, 12px); font-weight: 600; color: var(--ink-soft, #5b6b7b); }
.ws-ghost {
  position: fixed;
  z-index: 9999;
  margin: 0;
  pointer-events: none;
  transform: translate(-50%, -50%) scale(1.1);
  box-shadow: 0 7px 16px rgba(15, 30, 45, 0.4);
}
.ws-ghost.ct-out { opacity: 0.4; }
/* settings: the word list editor */
.ws-edit {
  max-height: 260px;
  overflow: auto;
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin: 4px 0;
}
.ws-edrow { display: flex; align-items: center; gap: 6px; }
.ws-edrow b { min-width: 86px; font-size: 13px; }
.ws-chips { display: flex; flex-wrap: wrap; gap: 3px; flex: 1; }
.ws-chip {
  font-size: 11px;
  font-weight: 700;
  color: var(--ink-soft, #5b6b7b);
  background: rgba(34, 48, 60, 0.06);
  border: 1.5px solid transparent;
  border-radius: 999px;
  padding: 2px 8px;
}
.ws-chip.active { color: #134e4a; background: rgba(20, 184, 166, 0.16); border-color: #0f766e; }
.ws-edx {
  font-size: 14px;
  font-weight: 800;
  color: #9f1239;
  background: none;
  border: none;
  padding: 2px 6px;
}
.ws-imp {
  width: 100%;
  min-height: 70px;
  font-family: inherit;
  font-size: 12px;
  line-height: 1.5;
  resize: vertical;
}

/* ---------------------------------------------------------------- word bank
   The corkboard, its three tier lanes, and the teach card. Cards are one
   component in both views, sized from --wb-fs so a bank of long words shrinks
   to fit rather than bursting a lane. */
.wbwidget { position: relative; }
.wb-board {
  background:
    radial-gradient(circle at 22% 28%, rgba(180, 120, 60, 0.07) 0 2px, transparent 3px),
    radial-gradient(circle at 74% 66%, rgba(180, 120, 60, 0.06) 0 2px, transparent 3px),
    rgba(253, 246, 233, 0.72);
  border-color: rgba(146, 104, 52, 0.3);
}
.wb-card {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 0.16em;
  max-width: 92%;
  font-size: var(--wb-fs, 18px);
  font-weight: 800;
  line-height: 1.15;
  color: #1f2937;
  background: #fff;
  border: 2px solid #cbb894;
  border-left-width: 7px;
  border-radius: 0.5em;
  padding: 0.3em 0.6em;
  box-shadow: 0 2px 5px rgba(15, 30, 45, 0.16);
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}
.wb-board .wb-card { position: absolute; z-index: 1; }
.wb-card .wb-w { white-space: nowrap; }
.wb-card.wb-popped { border-color: #0f766e; box-shadow: 0 0 0 3px rgba(20, 184, 166, 0.35), 0 4px 10px rgba(15, 30, 45, 0.24); }
.wb-card.ct-drag { box-shadow: 0 6px 14px rgba(15, 30, 45, 0.34); }
.wb-card.ct-out { opacity: 0.35; }
.wb-card.ws-lift { opacity: 0.35; }
/* The three tiers, as a spine down the card's left edge. Interactive
   whiteboards are notoriously badly calibrated — washed out, colour-shifted,
   viewed off-axis from the back of a room — so these are three widely
   separated, fully saturated hues rather than tasteful tints, and the spine
   is wide enough to read as a block of colour from the carpet. */
.wbwidget {
  --wb-t1: #1d4ed8;
  --wb-t2: #ea580c;
  --wb-t3: #047857;
}
.wb-card.wb-t1, .wb-card.wb-t2, .wb-card.wb-t3 { border-left-width: 11px; }
.wb-card.wb-t1 { border-left-color: var(--wb-t1); }
.wb-card.wb-t2 { border-left-color: var(--wb-t2); }
.wb-card.wb-t3 { border-left-color: var(--wb-t3); }
.wb-thumb {
  width: 3.6em;
  height: 2.6em;
  object-fit: cover;
  border-radius: 0.28em;
  pointer-events: none;
}
.wb-pinned {
  position: absolute;
  top: -0.5em;
  right: -0.4em;
  font-size: 0.66em;
  filter: drop-shadow(0 1px 2px rgba(15, 30, 45, 0.35));
  pointer-events: none;
}
.wb-book {
  position: absolute;
  bottom: -0.55em;
  right: -0.55em;
  width: 1.5em;
  height: 1.5em;
  display: grid;
  place-items: center;
  font-size: 0.7em;
  border-radius: 50%;
  background: #0f766e;
  box-shadow: 0 2px 5px rgba(15, 30, 45, 0.35);
}
/* opened in place: the teaching moment happens on the board, so the card
   grows where it stands instead of the wall being replaced by one word */
.wb-card.wb-open {
  max-width: min(320px, 88%);
  border-color: #0f766e;
  box-shadow: 0 0 0 3px rgba(20, 184, 166, 0.3), 0 8px 20px rgba(15, 30, 45, 0.28);
}
.wb-lane-cards .wb-card.wb-open,
.wb-pool .wb-card.wb-open { max-width: 100%; }
.wb-reveal {
  display: flex;
  flex-direction: column;
  gap: 0.3em;
  width: 100%;
  margin-top: 0.34em;
  padding-top: 0.34em;
  border-top: 1.5px dashed rgba(34, 48, 60, 0.18);
  text-align: left;
  cursor: pointer;
}
/* On the board the meanings HANG OFF the card rather than growing it, so the
   card keeps one size for its whole life. That is what lets a teacher nudge an
   opened card without it snapping shut — over weeks those little closes add up
   (Glenn, 2026-07-24). In a lane the panel stays in the column flow. */
.wb-board .wb-card .wb-reveal {
  position: absolute;
  top: calc(100% + 7px);
  left: -2px;
  /* a FIXED width, deliberately not a share of the card's: if the panel
     re-wrapped whenever the card changed size, switching a picture on would
     change its height and bounce it to the other side of the card */
  width: 230px;
  margin: 0;
  padding: 0.5em 0.7em;
  border: 2px solid #0f766e;
  border-radius: 0.6em;
  background: #fff;
  box-shadow: 0 8px 22px rgba(15, 30, 45, 0.26);
}
/* its exact place is set in pixels by paintBoard, clamped inside the board */
.wb-rline { display: flex; flex-direction: column; gap: 0.04em; }
.wb-rlab {
  font-size: max(0.5em, 9px);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #0f766e;
}
.wb-rval {
  font-size: 0.74em;
  font-weight: 600;
  line-height: 1.3;
  color: var(--ink, #22303c);
  white-space: normal;
  overflow-wrap: anywhere;
}
.wb-rempty {
  font-size: 0.68em;
  font-weight: 600;
  font-style: italic;
  line-height: 1.3;
  color: var(--ink-soft, #5b6b7b);
  white-space: normal;
}
/* per-word picture switch, right where the teaching happens */
.wb-picrow {
  align-self: flex-start;
  margin-top: 0.15em;
  padding: 0.24em 0.6em;
  border-radius: 999px;
  font-size: 0.62em;
  font-weight: 800;
  white-space: nowrap;
  color: #0b5f58;
  background: #d8f1ec;
  border: 1.5px solid #7fcfc3;
}
.wb-picrow.on { color: #78350f; background: #fdeccd; border-color: #eec284; }
/* the pin toggle on the teach card: a state you can read across the room */
.mntray .wb-pinbtn { font-weight: 800; border: 2px solid transparent; }
.mntray .wb-pinbtn.on {
  background: #fde68a; color: #78350f; border-color: #d97706;
  box-shadow: 0 0 0 2px rgba(217, 119, 6, 0.22);
}
/* pictures on/off — a teaching control, so it reads as clearly off as on */
.mntray .wb-picbtn { font-weight: 800; }
.mntray .wb-picbtn.wb-picoff {
  background: rgba(34, 48, 60, 0.1); color: var(--ink-soft, #5b6b7b);
  text-decoration: line-through;
}
.mntray .wb-picbtn:disabled { opacity: 0.4; text-decoration: none; }
.wb-quick .wb-cap { min-width: 120px; font-size: 17px; }
.mntray .wb-quick .wb-addbtn { font-weight: 800; }

/* ---- lanes ---- */
.wb-lanes {
  position: relative;
  display: flex;
  gap: 8px;
  padding: 4px 6px 0;
  min-height: 0;
}
.wb-lane {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  border: 2px dashed rgba(34, 48, 60, 0.28);
  border-top-width: 5px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.55);
  transition: border-color 0.15s ease, background 0.15s ease;
}
.wb-lane { border-top-width: 9px; }
.wb-lane.wb-t1 { border-top-color: var(--wb-t1); }
.wb-lane.wb-t2 { border-top-color: var(--wb-t2); }
.wb-lane.wb-t3 { border-top-color: var(--wb-t3); }
/* the heading carries its lane's colour too — one more cue that survives a
   projector that has given up on blue */
.wb-lane.wb-t1 .wb-lane-h { color: var(--wb-t1); }
.wb-lane.wb-t2 .wb-lane-h { color: var(--wb-t2); }
.wb-lane.wb-t3 .wb-lane-h { color: var(--wb-t3); }
.wb-lane-h { font-size: max(0.92em, 13px); }
.wb-lane.ws-over,
.wb-pool.ws-over { border-style: solid; border-color: #0f766e; background: rgba(20, 184, 166, 0.14); }
.wb-lanes.ct-dragging .ct-bin { opacity: 1; }
.wb-lane-h {
  text-align: center;
  font-weight: 800;
  font-size: max(0.82em, 12px);
  color: #134e4a;
  padding: 0.32em 0.2em;
  border-bottom: 2px solid rgba(34, 48, 60, 0.1);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* a lane scrolls rather than clipping: a bank runs to 60 picture cards, and a
   card you cannot see is a word the class has lost */
.wb-lane-cards {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  justify-content: center;
  gap: 0.35em;
  padding: 0.4em 0.25em;
  overflow-y: auto;
  font-size: var(--wb-fs, 16px);
}
.wb-pool {
  flex-shrink: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35em;
  align-items: center;
  justify-content: center;
  padding: 4px 6px;
  min-height: 2.6em;
  max-height: 38%;
  overflow-y: auto;
  border-top: 2px dashed rgba(34, 48, 60, 0.14);
  font-size: var(--wb-fs, 16px);
  transition: border-color 0.15s ease, background 0.15s ease;
}
.wb-poolhint { font-size: max(0.72em, 12px); font-weight: 600; color: var(--ink-soft, #5b6b7b); }

/* ---- teach card ---- */
.wb-teach {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 0;
  overflow-y: auto;
  padding: 2px 2px 6px;
  /* a double-tap on a whiteboard would otherwise blue-select the big word */
  user-select: none;
  -webkit-user-select: none;
}
.wb-teach-top { display: flex; align-items: center; gap: 6px; }
.wb-teach-head { position: relative; display: flex; align-items: center; gap: 14px; }
.wb-teach-word { flex: 1; min-width: 0; }
.wb-big { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.wb-bigw {
  font-size: clamp(34px, 7vw, 68px);
  font-weight: 800;
  line-height: 1.05;
  color: var(--ink, #22303c);
  overflow-wrap: anywhere;
}
.wb-sound {
  font-size: clamp(17px, 2.6vw, 28px);
  font-weight: 800;
  color: #0e7490;
  background: #ecfeff;
  border: 2.5px solid #67e8f9;
  border-radius: 0.3em;
  padding: 0.06em 0.35em;
}
.wb-slot {
  flex: 0 0 auto;
  width: clamp(96px, 22%, 168px);
  aspect-ratio: 4 / 3;
  display: grid;
  place-items: center;
  padding: 0;
  border: 2.5px dashed rgba(34, 48, 60, 0.3);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.6);
  overflow: hidden;
}
.wb-slot-full { border-style: solid; border-color: rgba(34, 48, 60, 0.18); }
.wb-slot img { width: 100%; height: 100%; object-fit: cover; }
.wb-slot-hint {
  font-size: 13px;
  font-weight: 700;
  white-space: pre-line;
  text-align: center;
  color: var(--ink-soft, #5b6b7b);
}
.wb-imgx {
  position: absolute;
  top: -6px;
  left: calc(clamp(96px, 22%, 168px) - 10px);
  width: 22px;
  height: 22px;
  display: grid;
  place-items: center;
  font-size: 15px;
  font-weight: 800;
  color: #9f1239;
  background: #fff;
  border: 1.5px solid rgba(34, 48, 60, 0.2);
  border-radius: 50%;
  box-shadow: 0 1px 3px rgba(15, 30, 45, 0.2);
}
.wb-sylrow { display: flex; align-items: center; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.mntray .wb-step { min-width: 40px; font-weight: 800; }
.wb-syls { display: flex; align-items: center; gap: 9px; min-height: 26px; }
.wb-syl {
  width: 22px;
  height: 22px;
  padding: 0;
  border-radius: 50%;
  border: 2.5px solid #0f766e;
  background: #99f6e4;
}
.wb-syl.wb-clap { animation: wb-clap 0.4s cubic-bezier(0.34, 1.56, 0.64, 1); }
@keyframes wb-clap {
  0% { transform: scale(1); }
  45% { transform: scale(1.55); background: #f59e0b; }
  100% { transform: scale(1); }
}
.wb-sylhint { font-size: 12px; font-weight: 600; color: var(--ink-soft, #5b6b7b); }
.wb-line {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 0.4em 0.6em;
  border-radius: 10px;
  border: 1.5px solid rgba(34, 48, 60, 0.12);
  background: rgba(255, 255, 255, 0.6);
  cursor: pointer;
}
.wb-linelab {
  font-size: max(0.62em, 11px);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #0f766e;
}
.wb-lineval { font-size: clamp(15px, 2.1vw, 21px); font-weight: 600; color: var(--ink, #22303c); }
.wb-line-empty .wb-lineval { font-weight: 500; font-style: italic; color: var(--ink-soft, #5b6b7b); }

/* ---- settings ---- */
.wb-edit {
  max-height: 260px;
  overflow: auto;
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin: 4px 0;
}
.wb-edrow { display: flex; align-items: center; gap: 6px; }
.wb-edrow b { min-width: 86px; font-size: 13px; }
.wb-chips { display: flex; flex-wrap: wrap; gap: 3px; flex: 1; }
.wb-chip {
  font-size: 11px;
  font-weight: 700;
  color: var(--ink-soft, #5b6b7b);
  background: rgba(34, 48, 60, 0.06);
  border: 1.5px solid transparent;
  border-radius: 999px;
  padding: 2px 8px;
}
.wb-chip.active { color: #fff; font-weight: 800; }
.wb-chip.wb-t1.active { background: #1d4ed8; border-color: #1d4ed8; }
.wb-chip.wb-t2.active { background: #ea580c; border-color: #ea580c; }
.wb-chip.wb-t3.active { background: #047857; border-color: #047857; }
.wb-edpin { font-size: 12px; background: none; border: none; padding: 2px 4px; opacity: 0.35; }
.wb-edpin.active { opacity: 1; }
.wb-imp {
  width: 100%;
  min-height: 70px;
  font-family: inherit;
  font-size: 12px;
  line-height: 1.5;
  resize: vertical;
}

/* ---- settings actions, coloured by what they DO ------------------------
   A column of identical pale pills makes a teacher read every label to find
   the one they want. Bringing something in, sending something out and the
   helper are three different jobs, so they are three different colours and
   all of them are bolder than the app's default ghost button. */
.wb-act {
  font-weight: 800;
  border: 1.5px solid transparent;
  padding: 6px 13px;
  border-radius: 999px;
}
.wb-act.in { background: #d8f1ec; color: #0b5f58; border-color: #7fcfc3; }
.wb-act.in:hover { background: #c6ebe4; }
.wb-act.out { background: #fdeccd; color: #8a5209; border-color: #eec284; }
.wb-act.out:hover { background: #fbe2b6; }
.wb-act.help { background: #e6e6f6; color: #443f7a; border-color: #b3b1de; }
.wb-act.help:hover { background: #dcdcf1; }
/* the one that cuts a sheet up is the headline action of the whole panel */
.wb-act.in.lead { background: #0f766e; color: #fff; border-color: #0f766e; }
.wb-act.in.lead:hover { background: #115e56; filter: none; }

/* ---- the contact-sheet slicer: a full-screen confirm-and-assign panel ---- */
.wb-slicer {
  position: fixed; inset: 0; z-index: 5000;
  display: grid; place-items: center;
  background: rgba(15, 30, 45, 0.55); backdrop-filter: blur(2px);
  padding: 20px;
}
.wb-slicer-card {
  display: flex; flex-direction: column;
  width: min(940px, 100%); max-height: 92vh;
  background: #fff; color: var(--ink, #22303c);
  border-radius: 16px; box-shadow: 0 18px 50px rgba(15, 30, 45, 0.4);
  overflow: hidden;
}
.wb-slicer-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  padding: 16px 20px; border-bottom: 1px solid var(--panel-border, #e2e6e1);
}
.wb-slicer-head h3 { margin: 0 0 2px; font-size: 18px; }
.wb-slicer-head p { margin: 0; font-size: 13px; color: var(--ink-soft, #5b6b7b); }
.wb-slice-steppers { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.wb-slice-steplabel { font-size: 12px; font-weight: 700; color: var(--ink-soft, #5b6b7b); }
.wb-slice-steplab { min-width: 26px; text-align: center; font-weight: 800; font-variant-numeric: tabular-nums; }
.wb-slice-grid {
  flex: 1; min-height: 0; overflow-y: auto;
  display: grid; gap: 12px; padding: 18px 20px;
  grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
  align-content: start;
}
.wb-slice-tile {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  padding: 7px; border-radius: 12px; cursor: pointer;
  border: 1.5px solid var(--panel-border, #e2e6e1); background: rgba(255, 255, 255, 0.6);
  transition: border-color 0.12s ease, opacity 0.12s ease, box-shadow 0.12s ease;
}
.wb-slice-tile:hover { border-color: #0f766e; }
.wb-slice-tile.picked { border-color: #0f766e; box-shadow: 0 0 0 3px rgba(20, 184, 166, 0.4); }
.wb-slice-x {
  position: absolute; top: 3px; right: 3px;
  width: 22px; height: 22px; display: grid; place-items: center;
  font-size: 14px; font-weight: 800; line-height: 1; cursor: pointer;
  color: #9f1239; background: rgba(255, 255, 255, 0.92);
  border: 1px solid rgba(34, 48, 60, 0.18); border-radius: 50%;
}
.wb-slice-x:hover { background: #fee2e2; }
.wb-slice-tile.skip .wb-slice-x { color: #0f766e; }
.wb-slice-tile img {
  width: 100%; aspect-ratio: 1 / 1; object-fit: contain;
  background: #fff; border-radius: 8px;
}
.wb-slice-blank {
  width: 100%; aspect-ratio: 1 / 1; display: grid; place-items: center;
  border-radius: 8px; background: rgba(34, 48, 60, 0.06); color: var(--ink-soft, #5b6b7b); font-size: 22px;
}
.wb-slice-cap {
  font-size: 13px; font-weight: 700; text-align: center; line-height: 1.2;
  overflow-wrap: anywhere; color: var(--ink, #22303c);
}
.wb-slice-cap.spare { color: var(--ink-soft, #5b6b7b); font-weight: 600; font-style: italic; }
.wb-slice-tile.skip { opacity: 0.45; }
.wb-slice-tile.skip img { filter: grayscale(1); }
.wb-slice-tile.skip .wb-slice-cap { color: var(--ink-soft, #5b6b7b); font-weight: 600; font-style: italic; }
.wb-slicer-foot {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 14px 20px; border-top: 1px solid var(--panel-border, #e2e6e1);
}
.wb-slice-note { font-size: 13px; font-weight: 600; color: var(--ink-soft, #5b6b7b); }
.wb-slice-go { background: #0f766e; color: #fff; border-color: #0f766e; }
.wb-slice-go:hover { background: #115e56; }

/* ---------------------------------------------------------------- sentence builder (english-word.js, docs/sentence-builder-design.md §7) */
/* One track engine, five faces, four zones (V0.1): reference rail · the
   sentence slab · ONE waiting band · the bar. Dashes mean "drop here" and
   nothing else. Type scales from the sentence itself (--sb-fs set from the
   mat width and character count) and its CAP scales with the widget, so a
   board-sized widget gets board-sized cards. No counters anywhere: nothing
   in this widget celebrates length. */
.sbwidget { --sb-fs: 20px; position: relative; }
.sb-mat {
  position: relative; display: flex; flex-direction: column; gap: 8px;
  min-height: 0; overflow-y: auto; padding: 4px 2px 8px;
  /* no touch-action:none here — this is the one mat in the app that scrolls,
     and cards set their own; a finger on empty mat must pan */
  touch-action: pan-y;
}
.sb-rail { display: flex; flex-direction: column; gap: 6px; flex-shrink: 0; }
/* the slab: a white card the sentence work sits on, visually one storey
   above the waiting band — the ranking the old layout never had */
.sb-slab {
  flex: 1 0 auto; display: flex; flex-direction: column; gap: 8px;
  background: #fffdf9; border: 2px solid rgba(34, 48, 60, 0.09);
  border-radius: 16px; padding: 10px 14px;
  box-shadow: inset 0 2px 8px rgba(34, 48, 60, 0.04);
}
.sb-line {
  flex: 1; display: flex; flex-wrap: wrap; align-content: center; align-items: center;
  gap: 0.28em; min-height: calc(var(--sb-fs, 20px) * 2.3);
  font-size: var(--sb-fs, 20px); padding: 20px 6px 16px;
  /* the handwriting rules are painted by paint() itself, PHASED TO THE
     CONTENT: a rule lands exactly under the cards' feet (or the hint's
     baseline), whatever the slab's height — ruled paper is a lie unless
     the words actually sit on the lines */
  background-repeat: repeat;
}
/* the empty-state hint is a fixed quiet whisper, never em-scaled: tied to
   the type scale it shouted at a different size in every mode */
.sb-linehint { color: var(--ink-soft); font-size: 17px; font-weight: 600; }
.mntray .sb-line .sb-linehint { font-size: 19px; }
.sb-ghosthint { color: var(--ink-soft); font-size: 14px; font-weight: 600; padding: 10px 6px; }
.sb-card {
  position: relative; font-weight: 800; color: #1f2937; background: #fff;
  border: 2.5px solid #94a3b8; border-radius: 0.42em; padding: 0.22em 0.5em;
  font-size: 1em; touch-action: none; user-select: none; -webkit-user-select: none;
  cursor: grab; box-shadow: 0 2px 0 rgba(34, 48, 60, 0.08);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.sb-card:hover { transform: translateY(-2px); box-shadow: 0 5px 10px rgba(34, 48, 60, 0.14); }
.sb-card.sb-p { min-width: 1.5em; text-align: center; background: #f8fafc; border-color: #cbd5e1; border-radius: 0.4em; }
/* the joining word is combining's special ingredient — it reads differently */
.sb-card.sb-join { background: #fdf4ff; border-color: #c084fc; color: #6b21a8; }
/* the grammar-names overlay tags join cards on the line — terminology is
   an overlay, never the gate */
.sbwidget.sb-terms .sb-line .sb-card.sb-join { z-index: 1; } /* the tag must paint over the next row's cards when the sentence wraps */
.sbwidget.sb-terms .sb-line .sb-card.sb-join::after {
  content: 'joining word'; position: absolute; left: 50%; transform: translateX(-50%);
  bottom: -1.05em; font-size: max(10px, 0.26em); font-weight: 800; color: #78350f;
  background: #fef3c7; border: 1.5px solid #fbbf24; border-radius: 999px;
  padding: 0.06em 0.6em; white-space: nowrap; pointer-events: none;
}
.sb-card.ws-lift { opacity: 0.35; transform: none; box-shadow: none; }
.sb-card.sb-popped { border-color: #0f766e; box-shadow: 0 0 0 3px rgba(20, 184, 166, 0.35); z-index: 5; }
/* the fix-it flag: same gold ring as the sorter's traps — "look here" */
.sb-card.sb-flag { box-shadow: 0 0 0 3px #f59e0b, 0 0 14px 2px rgba(245, 158, 11, 0.4); }
/* a card mid-flight in the Deal it back ceremony */
.sb-card.sb-fly { position: fixed; margin: 0; z-index: 4500; pointer-events: none; }
.sb-mini {
  position: absolute; top: -0.7em; display: grid; place-items: center;
  min-width: max(1.55em, 28px); height: max(1.55em, 28px); padding: 0 0.2em;
  font-size: max(0.6em, 13px);
  font-weight: 800; border-radius: 999px; background: #0f766e; color: #fff;
  box-shadow: 0 2px 6px rgba(15, 30, 45, 0.3); cursor: pointer;
}
.sb-mini.cap { left: -0.7em; }
.sb-mini.x { right: -0.7em; background: #9f1239; }
.sb-mini.flagb { left: 50%; transform: translateX(-50%); background: #b45309; }
.sb-caret { width: 3px; height: 1.5em; border-radius: 2px; background: #0f766e; flex-shrink: 0; }

/* say-it: everything steps back, one word takes the light (pt precedent) */
.sb-talking .sb-card:not(.sb-say) { opacity: 0.35; }
.sb-card.sb-say { transform: scale(1.14); box-shadow: 0 0 0 4px #0f766e, 0 0 18px 5px rgba(13, 148, 136, 0.45); z-index: 6; }
.sb-sweep { position: relative; height: 11px; border-radius: 999px; background: rgba(34, 48, 60, 0.08); margin: 0 10px; flex-shrink: 0; }
.sb-sweep i { position: absolute; left: 0; top: 0; bottom: 0; width: 0; border-radius: 999px; background: #14b8a6; }
.sb-sweep.run i { animation: pt-sweeprun var(--sweep-ms, 1200ms) linear forwards; }
.sb-sweep b {
  position: absolute; top: 50%; left: 0; width: 20px; height: 20px; border-radius: 50%;
  background: #0f766e; transform: translate(-50%, -50%); opacity: 0;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.92), 0 2px 8px rgba(15, 30, 45, 0.35);
}
.sb-sweep.run b { opacity: 1; animation: pt-sweepball var(--sweep-ms, 1200ms) linear forwards; }
.sb-srcs { display: flex; flex-direction: column; gap: 5px; flex-shrink: 0; }
.sb-src {
  display: flex; align-items: center; gap: 8px; text-align: left; font-weight: 700;
  font-size: max(0.7em, 14px); color: var(--ink); background: #fff;
  border: 2px solid #e2e8f0; border-radius: 12px; padding: 6px 11px;
}
.sb-src small { color: #0f766e; font-weight: 800; white-space: nowrap; font-size: 11px; }
.sb-src.quiet { background: rgba(255, 255, 255, 0.65); border-style: dashed; }
.sb-src.dealt { opacity: 0.55; }
.sb-src.dealt small { color: var(--ink-soft); }
.sb-src.quiet small { color: var(--ink-soft); }
.sb-alts { display: flex; flex-direction: column; gap: 4px; flex-shrink: 0; }
.sb-alt {
  display: flex; align-items: center; gap: 8px; font-weight: 700;
  background: #ecfeff; border: 2px solid #67e8f9; border-radius: 10px;
  padding: 5px 10px; font-size: max(0.68em, 14px); text-align: left;
}
.sb-alt.quiet { background: rgba(236, 254, 255, 0.7); }
.sb-altx { color: #9f1239; font-weight: 800; font-size: 15px; min-width: 28px; min-height: 28px; display: grid; place-items: center; border-radius: 8px; flex-shrink: 0; }
.sb-altx:hover { background: rgba(159, 18, 57, 0.08); }
.sb-prompts { display: flex; flex-wrap: wrap; gap: 6px; flex-shrink: 0; }
.sb-prompt {
  border: 2px solid rgba(34, 48, 60, 0.2); border-radius: 999px; padding: 3px 12px;
  font-weight: 800; font-size: max(0.6em, 13px); background: rgba(255, 255, 255, 0.7);
  text-align: center;
}
.sb-term { display: block; font-size: max(0.5em, 12px); font-weight: 700; color: var(--ink-soft); }
/* fix-it's closing image: the mended sentence fills the slab, big and
   green — never a quiet strip. The error is gone; this is what stays. */
.sb-fixedbanner {
  flex: 1; display: flex; flex-direction: column; gap: 10px; align-items: center;
  justify-content: center; text-align: center; padding: 12px; min-height: 7em;
}
.sb-fixedbanner small { font-size: 12px; font-weight: 800; letter-spacing: 0.06em; color: #16a34a; text-transform: uppercase; }
.sb-fixedbanner .sb-fixbig {
  font-size: clamp(22px, 4vw, 44px); font-weight: 800; color: var(--ink);
  background: #f0fdf4; border: 3px solid #16a34a; border-radius: 16px;
  padding: 12px 22px; text-wrap: balance;
}
/* fix-it model strip: calm before the mend */
.sb-model {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; font-weight: 800;
  background: #fff; border: 2px solid #e2e8f0; border-radius: 12px; padding: 8px 12px;
  font-size: max(0.8em, 16px); flex-shrink: 0;
}
.sb-model small { font-size: 11px; font-weight: 800; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 0.04em; }
.sb-model.big { font-size: clamp(20px, 3.6vw, 36px); border-color: #16a34a; background: #f0fdf4; }
.sb-model.big small { color: #16a34a; }
/* roles: coloured slots, the sentence reads itself along the readout */
.sb-readout {
  font-weight: 800; font-size: calc(var(--sb-fs, 20px) * 0.62); padding: 8px 12px; background: #fff;
  border-radius: 12px; border: 2px solid #e2e8f0; min-height: 1.6em; flex-shrink: 0;
}
.sb-readout.empty { color: var(--ink-soft); font-size: max(0.6em, 13px); font-weight: 600; }
.sb-slots { display: flex; gap: 8px; flex: 1; min-height: 7em; align-items: stretch; }
.sb-slot {
  flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center;
  gap: 6px; padding: 8px 6px; border-radius: 14px;
  border: 2px dashed rgba(34, 48, 60, 0.15); border-top: 6px solid var(--sbc, #94a3b8);
  background: rgba(255, 255, 255, 0.6); font-size: calc(var(--sb-fs, 20px) * 0.6);
}
.sb-slot.hot { border-style: solid; border-color: #0f766e; border-top-color: var(--sbc, #94a3b8); background: rgba(15, 118, 110, 0.08); }
/* headers and scaffolds are CLAMPED against the type scale: the sentence
   may grow board-sized, the furniture must not follow it into a scroll */
.sb-slot-h { display: flex; align-items: center; justify-content: center; gap: 5px; font-size: clamp(14px, 0.8em, 24px); font-weight: 800; color: var(--ink); text-align: center; }
.sb-slot-h::before { content: ''; width: 11px; height: 11px; border-radius: 50%; background: var(--sbc, #94a3b8); flex-shrink: 0; }
/* an empty slot scaffolds: topic examples in ghost grey — "words like
   these live here" — gone the moment a real card lands */
.sb-eg { display: flex; flex-direction: column; gap: 4px; align-items: center; margin-top: 0.3em; }
.sb-eg i { font-style: normal; font-size: clamp(11px, 0.55em, 15px); font-weight: 700; color: rgba(91, 107, 123, 0.5); }
.sb-eg span { color: rgba(91, 107, 123, 0.6); font-weight: 700; font-size: clamp(13px, 0.65em, 19px); text-align: center; }
/* the waiting band: ONE zone, and it LOOKS like one — the mock's soft
   grey box, not a rule floating in white space */
.sb-tray {
  flex-shrink: 0; display: flex; flex-direction: column; gap: 8px;
  background: rgba(34, 48, 60, 0.045); border-radius: 14px;
  padding: 10px 12px 12px; margin-top: 2px;
}
.sb-cardsrow { display: flex; align-items: flex-start; gap: 10px; }
/* the empty band announces itself like the mock's cap — a quiet pill,
   not a stray sentence */
.sb-cards .sb-linehint {
  font-size: 11px; font-weight: 800; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--ink-soft); background: #fff;
  border: 1.5px solid rgba(34, 48, 60, 0.12); border-radius: 999px;
  padding: 3px 10px; align-self: center;
}
/* the scroll cap clips at the padding box on BOTH axes (overflow-y:auto
   forces overflow-x to auto), and a popped card's mini buttons overhang
   the card by ~0.7em top and sides — the padding is their headroom inside
   the clip, same job as .sb-line's 20px (max-height grows by the top
   padding so the visible card area stays put) */
.sb-cards { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; gap: 6px; min-height: 2em; align-content: flex-start; font-size: calc(var(--sb-fs, 20px) * 0.8); max-height: 6.4em; overflow-y: auto; padding: 12px 12px 0; border-radius: 12px; }
.sb-cards.hot { outline: 3px dashed rgba(15, 118, 110, 0.5); outline-offset: -3px; }
/* the docks live OUTSIDE the cards row's scroll clip and only exist while
   a card is in the air — no card in the air, no docks on screen */
.sb-docks { display: flex; gap: 8px; align-items: center; align-self: center; flex-shrink: 0; visibility: hidden; opacity: 0; transition: opacity 0.15s ease; }
.sbwidget.ct-dragging .sb-docks { visibility: visible; opacity: 1; }
.sb-dock { width: 50px; height: 50px; display: grid; place-items: center; border: 2.5px dashed rgba(34, 48, 60, 0.35); border-radius: 14px; font-weight: 800; font-size: 17px; color: var(--ink-soft); }
.sb-dock.bin { font-size: 22px; }
.sb-dock.hot { border-color: #0f766e; background: rgba(15, 118, 110, 0.09); color: #0f766e; transform: scale(1.08); }
.sb-dock.bin.hot { border-color: #9f1239; background: rgba(159, 18, 57, 0.09); }
.sb-tiles { display: flex; flex-wrap: wrap; gap: 6px; row-gap: 7px; align-items: center; }
.sb-tilegrp { display: inline-flex; gap: 6px; align-items: center; margin-left: auto; }
.sb-tile { font-weight: 800; background: #fef3c7; border: 2px solid #fbbf24; color: #78350f; border-radius: 8px; padding: 2px 9px; font-size: 15px; }
.sb-tile.p { background: #f8fafc; border-color: #cbd5e1; color: #1f2937; min-width: 1.9em; }
.sb-tilecap { font-size: 11px; font-weight: 700; color: var(--ink-soft); margin-right: 2px; }
.sb-tiles.sb-nudge { animation: sb-nudge 0.7s ease 2; }
@keyframes sb-nudge {
  0%, 100% { transform: none; }
  30% { transform: translateY(-3px); }
  60% { transform: translateY(2px); }
}
.sb-bank { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; }
.sb-bankchip { font-weight: 800; font-size: 13px; background: #d8f1ec; border: 1.5px solid #7fcfc3; color: #0b5f58; border-radius: 999px; padding: 2px 10px; }
.sb-bankchip:hover { background: #c6ebe4; }
.sb-add { max-width: 220px; }
.sb-addcluster { display: inline-flex; align-items: center; gap: 6px; order: 4; } /* rightmost seat of the act corner, after the leads */
.sb-addcluster.hidden { display: none; }
.sb-addwrap { display: none; align-items: center; gap: 5px; }
.sb-addwrap.open { display: inline-flex; }
/* the bar's colour grammar (V0.1 decision 8), four levels: INK = which
   face of the scheme, the TRAFFIC light = whose turn, grey = tools — and
   solid TEAL only ever means "press to act". The bar is the mock's
   full-bleed sand strip: it runs edge to edge under everything (negative
   margins swallow the widget body's 4/12/12 padding), so the whole
   bottom row reads as ONE zone — and the tclock centring is overridden:
   clusters anchor left, the act buttons anchor right across a flex gap. */
.sb-quick {
  display: flex; gap: 10px; row-gap: 9px; align-items: center; flex-wrap: wrap;
  justify-content: flex-start;
  margin: 6px -12px -12px; padding: 10px 14px 12px;
  background: #f7efe3; border-top: 1.5px solid rgba(34, 48, 60, 0.08);
  border-radius: 0 0 12px 12px;
}
.sb-qleft { display: contents; }
.sb-qgap { flex: 1 1 0; min-width: 8px; }
.sb-qbreak { flex-basis: 100%; height: 0; }
.sb-leads { display: inline-flex; gap: 8px; align-items: center; }
/* every pill on the bar speaks the same two-line language: label over a
   plain-word sub — the beats included, so nothing needs an outboard label */
.sb-modeseg .tq-btn, .sb-stageseg .tq-btn, .sb-sayseg .tq-btn { padding: 7px 16px 6px; line-height: 1.2; }
.sb-sayseg .tq-btn.sb-go { padding: 9px 18px; }
.sb-quick .btn.small { border-radius: 12px; }
.sb-quick .btn.sb-chip { background: rgba(34, 48, 60, 0.07); color: var(--ink-soft); border-radius: 12px; font-weight: 800; }
.sb-quick .btn.sb-chip:hover { background: rgba(34, 48, 60, 0.13); filter: none; }
.sb-modeseg .tq-btn.active { background: var(--ink); color: #fdf6ec; }
.sb-modeseg .tq-btn.active .sb-turn { color: rgba(253, 246, 236, 0.8); }
.sb-sayseg .tq-btn.active { background: rgba(34, 48, 60, 0.16); color: var(--ink); }
.sb-sayseg .tq-btn.sb-go { background: #0f766e; color: #fff; font-weight: 800; }
.sb-sayseg .tq-btn.sb-go:hover { background: #115e56; }
.sb-lead { background: #0f766e; color: #fff; }
.sb-lead:hover { background: #115e56; filter: none; }
.sb-leadghost { background: none; color: #0f766e; border: 2px solid rgba(15, 118, 110, 0.4); }
.sb-leadghost:hover { background: rgba(15, 118, 110, 0.08); }
/* the stage pills carry their turn (my/our/your turn) AND the traffic
   light: red watch me, amber we build it, green go. The underline is
   always on so the class can learn the format; the active stage fills.
   Position and label carry the meaning too — colour is never the only
   channel (colour-blind children). */
/* solid ink-soft, no alpha: 11px meaning-bearing text needs 4.5:1 */
.sb-turn { display: block; font-size: 11px; font-weight: 700; color: #5b6b7b; margin-top: 1px; }
.mntray .sb-turn { font-size: 12px; }
.sb-stageseg .tq-btn { border-bottom: 3px solid transparent; }
.sb-stageseg .sb-st-model { border-bottom-color: #dc2626; }
.sb-stageseg .sb-st-together { border-bottom-color: #f59e0b; }
.sb-stageseg .sb-st-you { border-bottom-color: #16a34a; }
.sb-stageseg .sb-st-model.active { background: rgba(220, 38, 38, 0.13); color: #7f1d1d; }
.sb-stageseg .sb-st-together.active { background: rgba(245, 158, 11, 0.22); color: #78350f; }
.sb-stageseg .sb-st-you.active { background: rgba(22, 163, 74, 0.15); color: #14532d; }
/* active-turn colours match the pills' main labels — the shades that pass */
.sb-stageseg .sb-st-model.active .sb-turn { color: #b91c1c; }
.sb-stageseg .sb-st-together.active .sb-turn { color: #92400e; }
.sb-stageseg .sb-st-you.active .sb-turn { color: #14532d; }
/* over to you, the closing ritual: say it, write it, check it */
.sb-steps { display: flex; gap: 16px; flex-wrap: wrap; justify-content: center; }
.sb-step { display: inline-flex; align-items: center; gap: 7px; font-weight: 700; color: #0f766e; font-size: 15px; }
.sb-step b { width: 22px; height: 22px; border-radius: 50%; background: #0f766e; color: #fff; display: grid; place-items: center; font-size: 13px; flex-shrink: 0; }
.mntray .sb-step { font-size: 17px; }
/* over to you: the widget goes quiet and the writing starts */
.sb-handoff {
  flex: 1; display: flex; flex-direction: column; gap: 14px; align-items: center;
  justify-content: center; text-align: center; padding: 14px;
}
.sb-handoff .sb-big { font-size: clamp(24px, 4.6vw, 50px); font-weight: 800; text-wrap: balance; }
.sb-cue { color: var(--ink-soft); font-weight: 700; font-size: 14px; }
.sb-stems { display: flex; flex-direction: column; gap: 5px; align-items: stretch; width: min(560px, 100%); }
/* the ⚙ panel graduates (V0.1 decision 13): a section announces itself —
   rule, strong heading, one plain sub-caption. The panel speaks the bar's
   colour grammar too: ink = the topic you're on, teal = press to act,
   rose = removes something. */
.sb-sph { font-size: 13px; font-weight: 800; color: var(--ink); margin-top: 10px; padding-top: 12px; border-top: 1.5px solid rgba(34, 48, 60, 0.12); }
.sb-sph:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.sb-spsub { font-size: 12.5px; font-weight: 600; color: var(--ink-soft); margin-top: -4px; }
/* a flex column gives flex:1 children a ZERO height basis — that is what
   squashed the mock's boxes. Fields size to content and never shrink. */
.spanel-sec .sb-ta { width: 100%; flex-shrink: 0; resize: vertical; min-height: 5.5em; line-height: 1.5; }
.sb-topics { display: flex; flex-wrap: wrap; gap: 6px; }
.sb-topic { font-size: 13px; font-weight: 700; color: var(--ink); background: #fff; border: 1.5px solid rgba(34, 48, 60, 0.28); border-radius: 999px; padding: 5px 13px; }
.sb-topic:hover { border-color: var(--ink); background: rgba(34, 48, 60, 0.05); }
.sb-topic.on { background: var(--ink); color: #fdf6ec; border-color: var(--ink); }
.sb-bankitem { display: flex; align-items: center; gap: 8px; background: rgba(34, 48, 60, 0.05); border-radius: 10px; padding: 6px 10px; font-weight: 600; font-size: 13px; }
.sb-bankitem .grow { min-width: 0; }
.sb-use { font-weight: 800; font-size: 12.5px; color: #fff; background: #0f766e; border-radius: 999px; padding: 4px 12px; flex-shrink: 0; }
.sb-use:hover { background: #115e56; }
.sb-act { font-weight: 700; font-size: 13px; color: #fff; background: #0f766e; border-radius: 999px; padding: 6px 14px; }
.sb-act:hover { background: #115e56; }
.sb-dangerp { font-size: 13px; font-weight: 700; color: #9f1239; background: #fff; border: 1.5px solid rgba(159, 18, 57, 0.4); border-radius: 999px; padding: 5px 13px; }
.sb-dangerp:hover { background: rgba(159, 18, 57, 0.07); border-color: #9f1239; }
/* compound, not descendant: mntray and sbwidget sit on the SAME element */
.mntray.sbwidget .sb-quick .btn.small { font-size: 17px; padding: 8px 14px; }
.mntray .sb-term { font-size: 14px; }
.mntray .sb-tile { font-size: 18px; padding: 3px 12px; }
.mntray .sb-bankchip { font-size: 15px; }
.mntray .sb-tilecap { font-size: 13px; }
.mntray .sb-cue { font-size: 17px; }
.mntray .sb-dock { width: 56px; height: 56px; }

/* ------------------------------------------------------------------------ */
/* SagePrint (print.js) — poster dialog + print route                        */
/* docs/poster-print-design.md §4 (dialog) and §6 (route)                    */

.sp-dialog { display: flex; gap: 18px; align-items: flex-start; flex-wrap: wrap; }
/* the preview is a column of PAGES; each page holds its own grid of sheets */
.sp-prev { display: flex; flex-direction: column; gap: 16px; width: 430px;
  max-width: 46vw; align-content: start; max-height: 62vh; overflow-y: auto; }
.sp-doc-grid { display: grid; gap: 8px; }
.sp-doc-lab { font-size: 12px; font-weight: 650; opacity: .75; margin-bottom: 5px; }

/* §4.6 page picker — one chip per widget page, its sheet split drawn over its
   own thumbnail so how a page divides is visible without rendering it big */
.sp-pages { display: flex; flex-direction: column; gap: 4px; }
.sp-page-row { display: flex; flex-wrap: wrap; gap: 7px; }
.sp-page-chip { display: flex; flex-direction: column; align-items: center; gap: 3px;
  width: 74px; padding: 5px 4px 6px; cursor: pointer; background: transparent;
  border: 2px solid rgba(34, 48, 60, .18); border-radius: 8px; font: inherit; }
.sp-page-chip.active { border-color: #0e7490; background: rgba(14, 116, 144, .08); }
.sp-page-chip.bad { opacity: .5; cursor: not-allowed; border-style: dashed; }
.sp-page-thumb { position: relative; width: 46px; aspect-ratio: 1 / 1.414;
  background: #fff; border: 1px solid rgba(34, 48, 60, .25); overflow: hidden; }
.sp-page-thumb > svg { width: 100%; height: 100%; display: block; }
.sp-page-thumb > svg.sp-page-grid { position: absolute; left: 0; top: 0; }
.sp-page-name { font-size: 11px; line-height: 1.1; text-align: center; }
.sp-page-sheets { font-size: 10.5px; opacity: .65; }
/* the preview shows the whole SHEET now — paper edge, margins and trim lines —
   not just the printable box; showing only the box is what hid the seam defect
   (2026-07-26). White + shadow belong to the paper, so they live on .sp-sheet. */
.sp-prev .sp-sheet { background: #fff; box-shadow: 0 1px 5px rgba(0, 0, 0, .35);
  border-radius: 2px; }
.sp-prev svg.sp-page { width: 100%; height: 100%; display: block; }
/* edge furniture is an svg over the whole sheet — it draws in the margin the
   page svg cannot reach, and scales with the preview for free */
.sp-furniture { position: absolute; left: 0; top: 0; }
.sp-ctrl { display: flex; flex-direction: column; gap: 10px; min-width: 250px; flex: 1; }
.sp-lab { font-size: 11.5px; font-weight: 700; opacity: .7;
  text-transform: uppercase; letter-spacing: .05em; }
.sp-seg { display: flex; flex-wrap: wrap; gap: 6px; }
.sp-seg-btn.active { outline: 2px solid #0e7490; outline-offset: -1px; font-weight: 700; }
.sp-guides-row { display: flex; align-items: center; gap: 8px; font-size: 14px; cursor: pointer; }
.sp-readout { font-size: 13.5px; font-weight: 650; }
.sp-warn { color: #b45309; font-size: 13px; }
.sp-err { color: #b91c1c; font-size: 13px; font-weight: 700; }

/* ---- modelled writing (modelwrite): the flip-chart easel replaced ---- */
.mwwidget { display: flex; flex-direction: column; gap: 6px; padding: 8px; }
/* Two tiers (2026-07-26). Tier 1 is the tools and never reflows; tier 2 is
   whatever the live tool is set to, in a fixed home of its own. Injecting
   options into tier 1 shoved every button to their right along and stranded
   the eraser's sizes eight controls from the eraser. */
.mw-tools { display: flex; flex-direction: column; gap: 0; flex: none; }
/* 5px of breathing room all round: the active tool's ring is a 3px outline at
   2px offset, and with no padding the bar clipped it — the selected ink dot
   looked shaved off, worse in a side bar where overflow hard-clips it */
.mw-bar { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; padding: 5px; }
/* tier 1 is ten controls; a little tighter keeps it on one row at the default
   widget width, which matters because two rows of chrome is page area lost */
/* 7px not 8px: the cue pills carry a 1px border, and 2px x nine buttons was
   enough to tip tier 1 back onto a second row */
.mw-bar > .btn.small { padding: 3px 7px; }
/* Colour cues. The tint IS the cue — a leading dot would have cost ~90px across
   nine pills and pushed tier 1 onto two rows. Hue encodes family: amber takes
   marks away, indigo moves them, cyan adds, green is the page, red is the one
   that destroys. Pen and Highlighter wear their current ink.
   Specificity has to clear .btn.ghost, which sets its own background. */
.mw-bar .btn.mw-pill { background: var(--cue-bg, rgba(15, 118, 110, .08));
  border: 1px solid var(--cue-bd, rgba(34, 48, 60, .18));
  color: var(--ink); transition: background .12s; }
.mw-bar .btn.mw-pill:hover { filter: brightness(.96); }
/* icon + word while the row has room for words; icon alone the moment it
   would cost a second row, which is the one thing tier 1 must never do */
.mw-bar .btn.mw-pill { display: inline-flex; align-items: center; gap: 5px; }
.mw-bar .btn.mw-pill svg { width: 17px; height: 17px; flex: none; }
.mw-bar.mw-compact .mw-pill-lab { display: none; }
.mw-bar.mw-compact .btn.mw-pill { padding: 4px 7px; gap: 0; }
.mw-bar.mw-compact .btn.mw-pill svg { width: 19px; height: 19px; }
.mw-bar .btn.mw-pill.mw-active { outline: 2px solid var(--cue, #0e7490);
  outline-offset: -1px; font-weight: 700; }
.mw-sep { width: 1px; height: 18px; background: rgba(34, 48, 60, .16); margin: 0 1px; flex: none; }
/* the spacer before Print must be able to collapse to nothing, or it is the
   one thing that tips tier 1 onto a second row */
.mw-bar > .grow { flex: 1 1 0; min-width: 0; }
.mw-opts { display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
  padding: 5px 6px; min-height: 32px; border-top: 1px solid rgba(34, 48, 60, .09);
  background: rgba(34, 48, 60, .035); border-radius: 0 0 8px 8px; }
.mw-opt-lab { font-size: 11px; font-weight: 700; opacity: .5; text-transform: uppercase;
  letter-spacing: .05em; min-width: 62px; flex: none; }
.mw-opt-hint { font-size: 12px; opacity: .6; }
.mw-nib.mw-hlnib::before { border-radius: 2px; background: #fde047;
  border: 1px solid rgba(0, 0, 0, .18); }
/* highlighter swatches in tier 2 keep full opacity so the selected ring stays
   crisp — the pastel inks already read as highlighter without dimming them */
.mw-opts .mw-tool.mw-hl { opacity: 1; border-style: solid;
  border-color: rgba(34, 48, 60, .22); }
.mw-family { display: inline-flex; gap: 5px; align-items: center; }
.mw-tool { width: 26px; height: 26px; border-radius: 50%; border: 2px solid rgba(0, 0, 0, .18);
  background: var(--ink, #111827); cursor: pointer; padding: 0; flex: none; }
.mw-tool.mw-hl { opacity: .55; border-style: dashed; }
.mw-tool.active { outline: 3px solid #0e7490; outline-offset: 2px; }
.mw-active { outline: 2px solid #0e7490; outline-offset: -1px; font-weight: 700; }
.mw-print { display: inline-flex; align-items: center; gap: 6px; }
.mw-stage { flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; }
.mw-pagebox { height: 100%; max-width: 100%; aspect-ratio: 1000 / 1414; }
.mw-page { width: 100%; height: 100%; display: block; background: transparent;
  filter: drop-shadow(0 2px 7px rgba(0, 0, 0, .3));
  touch-action: none; cursor: crosshair; }
/* page white + shadow come from the CONTENT (the svg's own white rect), so a
   distorted element box in narrow widgets shows no white beyond the page —
   input mapping compensates in toUnits (review finding, 2026-07-26) */
.mw-strip { display: flex; gap: 6px; align-items: flex-start; overflow-x: auto;
  flex: none; padding: 3px 2px; min-height: 78px; }
.mw-thumb { position: relative; width: 44px; height: 60px; flex: none; cursor: pointer;
  border: 2px solid rgba(0, 0, 0, .22); border-radius: 4px; background: #fff; overflow: hidden; }
.mw-thumb.active { border-color: #0e7490; box-shadow: 0 0 0 2px rgba(14, 116, 144, .35); }
.mw-thumb svg { width: 100%; height: 100%; display: block; pointer-events: none; }
.mw-thumb-x { position: absolute; top: 1px; right: 1px; width: 17px; height: 17px;
  border: none; border-radius: 4px; background: rgba(185, 28, 28, .88); color: #fff;
  font-size: 11px; line-height: 1; cursor: pointer; padding: 0; }
.mw-add { width: 44px; height: 60px; flex: none; border: 2px dashed rgba(0, 0, 0, .3);
  border-radius: 4px; background: transparent; font-size: 22px; cursor: pointer; opacity: .75; }
.mw-add:hover { opacity: 1; }
.mw-dangerp { color: #b91c1c; }

/* the washing line as a document: every page carries its number or its name,
   so a unit reads as a sequence of lessons rather than a row of small pictures */
.mw-cell { display: flex; flex-direction: column; align-items: center; gap: 2px; flex: none; }
.mw-cell-lab { font-size: 10px; line-height: 1.1; max-width: 48px; text-align: center;
  opacity: .55; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mw-cell-lab.named { opacity: .85; font-weight: 650; }
.mw-thumb-m { position: absolute; top: 1px; left: 1px; width: 17px; height: 17px;
  border: none; border-radius: 4px; background: rgba(15, 23, 42, .72); color: #fff;
  font-size: 12px; line-height: 1; cursor: pointer; padding: 0; }
.mw-lockbadge { position: absolute; bottom: 1px; right: 1px; font-size: 10px; line-height: 1;
  pointer-events: none; filter: drop-shadow(0 1px 1px rgba(255, 255, 255, .9)); }
.mw-thumb.mw-locked { border-color: #a16207; border-style: dashed; }
/* picked up off the line — it follows the finger, and the gap it will drop
   into is the one lit up */
.mw-thumb.mw-dragging { opacity: .45; transform: scale(.92); }
.mw-strip.mw-reordering { cursor: grabbing; }
.mw-strip.mw-reordering .mw-thumb { transition: transform .12s ease; }
.mw-thumb.mw-droptarget { box-shadow: 0 0 0 3px #0e7490; transform: translateY(-3px); }

.mw-pagemenu { position: fixed; z-index: 60; min-width: 172px; padding: 5px;
  border: 1px solid var(--panel-border); border-radius: 10px; background: var(--panel);
  box-shadow: 0 12px 30px rgba(15, 23, 42, .22); display: flex; flex-direction: column; gap: 1px; }
.mw-pm-item { text-align: left; padding: 7px 10px; border: 0; border-radius: 7px;
  background: transparent; color: inherit; font: inherit; font-size: 13px; cursor: pointer; }
.mw-pm-item:hover { background: rgba(14, 116, 144, .12); }
.mw-pm-item.mw-pm-off { opacity: .35; pointer-events: none; }
.mw-pm-sep { height: 1px; margin: 3px 6px; background: rgba(34, 48, 60, .16); }

/* snapshots list in Your data — grouped by the thing the copy is of */
.snap-group { padding: 6px 0; border-bottom: 1px solid rgba(34, 48, 60, .1); }
.snap-group:last-child { border-bottom: 0; }
.snap-title { font-size: 13px; font-weight: 700; opacity: .8; padding: 2px 0 4px; }
.snap-versions { display: flex; flex-direction: column; gap: 2px; padding-left: 10px;
  border-left: 2px solid rgba(14, 116, 144, .25); }
.snap-versions .bin-row { font-size: 12px; }

/* the undo button that lives inside a toast */
#toast .toast-action { margin-left: 12px; padding: 3px 11px; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, .5); border-radius: 999px;
  background: rgba(255, 255, 255, .16); color: inherit; font: inherit; font-weight: 650; }
#toast .toast-action:hover { background: rgba(255, 255, 255, .3); }
/* #toast is pointer-events:none so a message floating over the stage never eats
   a click meant for a widget underneath — but that inherits, and it was killing
   the one button we most need pressed. The button alone takes clicks back, and
   only while .show is on: the toast sits at opacity 0 the rest of the time, and
   a transparent element is still hit-testable, so an unscoped rule would leave
   an invisible target parked mid-screen. */
#toast.show .toast-action { pointer-events: auto; }

/* the paper panel: swatches are real renders of the candidate paper, through
   the same mwPageInner the page and the print use — a swatch cannot lie */
.mw-pop { flex: none; border: 1px solid var(--panel-border); border-radius: 10px;
  padding: 9px 10px 10px; background: rgba(255, 255, 255, .96); }
.mw-sw-lab { font-size: 11px; font-weight: 700; opacity: .6; text-transform: uppercase;
  letter-spacing: .05em; margin: 6px 0 4px; }
.mw-sw-row { display: flex; gap: 6px; flex-wrap: wrap; }
.mw-sw { width: 56px; aspect-ratio: 1000 / 1414; padding: 0; cursor: pointer;
  border: 2px solid rgba(34, 48, 60, .2); border-radius: 4px; background: #fff; overflow: hidden; }
.mw-sw.active { border-color: #0e7490; box-shadow: 0 0 0 2px rgba(14, 116, 144, .3); }
.mw-sw svg { width: 100%; height: 100%; display: block; }
.mw-size-row { display: flex; gap: 5px; align-items: stretch; }
.mw-size { min-width: 38px; padding: 3px 6px; cursor: pointer; line-height: 1.6;
  border: 1px solid rgba(34, 48, 60, .2); border-radius: 6px; background: #fff; }
.mw-size.active { border-color: #0e7490; background: rgba(14, 116, 144, .1); font-weight: 700; }
.mw-pop-tick { display: flex; align-items: center; gap: 7px; font-size: 13px;
  margin-top: 9px; cursor: pointer; }
/* selection chrome and divider grips live outside mwPageInner, so they can
   never reach paper */
.mw-page .mw-handle { cursor: nwse-resize; }
.mw-page .mw-grip { cursor: grab; }

/* pen and rubber sizes: the control shows the weight it gives you */
.mw-nibs { gap: 4px; }
.mw-nib { width: 24px; height: 24px; padding: 0; flex: none; cursor: pointer;
  border: 1px solid rgba(34, 48, 60, .18); border-radius: 50%; background: #fff;
  display: inline-flex; align-items: center; justify-content: center; }
.mw-nib::before { content: ''; width: var(--nib, 7px); height: var(--nib, 7px);
  border-radius: 50%; background: var(--ink, #22303c); }
.mw-nib.mw-rub::before { border-radius: 3px; background: #94a3b8; }
.mw-nib.active { border-color: #0e7490; box-shadow: 0 0 0 2px rgba(14, 116, 144, .3); }

/* page turning, pinned to the page's own borders and draggable up and down so
   it never sits on the writing */
.mw-pagebox { position: relative; }
.mw-turn { position: absolute; transform: translateY(-50%); z-index: 3;
  width: 30px; height: 46px; padding: 0; cursor: pointer; font-size: 22px; line-height: 1;
  border: 1px solid rgba(34, 48, 60, .16); border-radius: 9px; touch-action: none;
  background: rgba(255, 255, 255, .93); color: var(--ink); box-shadow: 0 1px 5px rgba(0, 0, 0, .18); }
.mw-turn:hover { background: #fff; }
.mw-turn-l { left: -13px; }
.mw-turn-r { right: -13px; }

/* zoom cluster, pinned to the page's own bottom-left corner — a fixed home,
   out of tier 1, so nothing in the toolbar has to move to make space for it */
.mw-zoom { position: absolute; left: 4px; bottom: 4px; z-index: 4; display: flex; gap: 2px;
  padding: 2px; border-radius: 8px; background: rgba(255, 255, 255, .82);
  box-shadow: 0 1px 6px rgba(15, 23, 42, .18); opacity: .5; transition: opacity .15s; }
.mw-pagebox:hover .mw-zoom, .mw-zoom.mw-zoomed { opacity: 1; }
.mw-zbtn, .mw-zlab { border: 0; background: transparent; cursor: pointer; padding: 2px 5px;
  border-radius: 6px; font: inherit; font-size: 13px; line-height: 1.4; color: #0f172a; }
.mw-zlab { font-size: 11px; min-width: 38px; opacity: .75; }
.mw-zbtn:hover, .mw-zlab:hover { background: rgba(14, 116, 144, .14); }
.mw-zbtn:disabled { opacity: .3; cursor: default; background: transparent; }
.mw-zbtn.mw-zactive { background: #0e7490; color: #fff; }
.mw-pagebox.mw-panning .mw-page { cursor: grab; }

/* school colours — a square swatch, so it never reads as one of the four
   round writing inks it sits beside */
.mw-pal-cell { position: relative; display: inline-flex; }
.mw-pal-swatch { width: 30px; height: 28px; padding: 0; cursor: pointer;
  border: 1px solid rgba(0, 0, 0, .25); border-radius: 6px; background: none; }
.mw-pal-x { position: absolute; top: -6px; right: -6px; width: 15px; height: 15px; padding: 0;
  border: 0; border-radius: 50%; background: rgba(15, 23, 42, .8); color: #fff;
  font-size: 9px; line-height: 1; cursor: pointer; }
.mw-opts .mw-tool.mw-school { border-radius: 6px; }
/* pen edge: freehand · straight line · box */
.mw-shapes { margin-left: 2px; }
.mw-nib.mw-shape { display: inline-flex; align-items: center; justify-content: center; }
.mw-nib.mw-shape::before { content: none; }
.mw-nib.mw-shape svg { width: 16px; height: 16px; }
.mw-page .mw-cropgrip { cursor: move; }

/* marking palette — the colour AND what it means, because a marking code
   only works if the room can read it off the board */
.mw-mark { display: inline-flex; align-items: center; gap: 6px; padding: 3px 9px 3px 4px;
  border: 1.5px solid var(--panel-border); border-radius: 999px; background: var(--panel);
  cursor: pointer; font: inherit; font-size: 12px; color: inherit; }
.mw-mark:hover { border-color: var(--ink, #7e22ce); }
.mw-mark.active { border-color: var(--ink, #7e22ce); box-shadow: 0 0 0 2px color-mix(in srgb, var(--ink, #7e22ce) 35%, transparent); font-weight: 650; }
.mw-mark-dot { width: 17px; height: 17px; border-radius: 50%; background: var(--ink, #7e22ce);
  border: 1px solid rgba(0, 0, 0, .18); flex: none; }
.mw-mark-dot.hl { border-radius: 4px; opacity: .75; }
.mw-mark-vfdot { display: inline-flex; align-items: center; justify-content: center;
  width: 21px; height: 21px; border-radius: 50%; border: 2px solid #7e22ce; color: #7e22ce;
  font-size: 8.5px; font-weight: 800; flex: none; }
.mw-mark-pair { display: inline-flex; align-items: center; gap: 5px; }
.mw-mark-label { width: 120px; }
.mw-lens-area { width: 100%; min-height: 62px; }

/* the teaching tags in the page menu */
.mw-pm-lab { font-size: 10px; font-weight: 700; opacity: .5; text-transform: uppercase;
  letter-spacing: .04em; padding: 5px 10px 2px; }
.mw-pm-chips { display: flex; flex-wrap: wrap; gap: 4px; padding: 0 8px 4px; }
.mw-pm-chip { padding: 3px 9px; border-radius: 999px; cursor: pointer; font: inherit; font-size: 11.5px;
  border: 1.5px solid color-mix(in srgb, var(--chip, #475569) 55%, transparent);
  background: color-mix(in srgb, var(--chip, #475569) 10%, transparent); color: inherit; }
.mw-pm-chip:hover { background: color-mix(in srgb, var(--chip, #475569) 22%, transparent); }
.mw-pm-chip.on { background: var(--chip, #475569); border-color: var(--chip, #475569);
  color: #fff; font-weight: 650; }

/* Big Write: the page, a clock, and as little else as possible. The tools and
   the washing line go, so nothing on the screen competes with the writing. */
.mwwidget.mw-bigwrite .mw-tools,
.mwwidget.mw-bigwrite .mw-strip,
.mwwidget.mw-bigwrite .mw-zoom { display: none; }
.mwwidget.mw-bigwrite .mw-turn { opacity: .25; }
.mwwidget.mw-bigwrite .mw-turn:hover { opacity: 1; }
.mw-bw { display: flex; align-items: center; gap: 7px; flex: none; padding: 7px 10px;
  border-bottom: 1px solid var(--panel-border); }
.mw-bw-title { font-weight: 700; font-size: 13px; letter-spacing: .02em; }
.mw-bw-lens { font-size: 12px; padding: 2px 9px; border-radius: 999px;
  background: rgba(71, 85, 105, .12); color: var(--ink-soft); }
.mw-bw-clock { font-variant-numeric: tabular-nums; font-size: 20px; font-weight: 700;
  min-width: 62px; text-align: right; }
.mw-bw > .grow { flex: 1 1 0; }
.mw-bwbtn { display: inline-flex; align-items: center; gap: 5px; }
.mw-bwbtn svg { width: 16px; height: 16px; }
.mw-rot { width: 108px; accent-color: #0e7490; }

/* saved papers — a named paper built once and reused all year */
.mw-sets { display: flex; gap: 7px; flex-wrap: wrap; }
.mw-set { position: relative; width: 62px; padding: 2px; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  border: 2px solid var(--panel-border); border-radius: 7px; background: var(--panel); }
.mw-set:hover { border-color: #0e7490; }
.mw-set svg { width: 100%; aspect-ratio: 1000 / 1414; display: block; background: #fff; border-radius: 3px; }
.mw-set-name { font-size: 10px; line-height: 1.15; max-width: 56px; text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; opacity: .8; }
.mw-set-x { position: absolute; top: -6px; right: -6px; width: 16px; height: 16px; padding: 0;
  border: 0; border-radius: 50%; background: rgba(15, 23, 42, .82); color: #fff;
  font-size: 9px; line-height: 1; cursor: pointer; }
.mw-set-add { justify-content: center; font-size: 20px; color: var(--ink-soft);
  border-style: dashed; min-height: 64px; }

/* the washing line skims like a book: a big preview follows the finger.
   Centred over the whole widget and taken right out of flow — anchoring it to
   the strip put it off-screen as soon as the bar moved to a side (Glenn,
   item 3), and a transient preview reads fine in the middle. */
.mwwidget { position: relative; }
.mw-peek-wrap { position: absolute; inset: 0; z-index: 8; pointer-events: none;
  display: flex; align-items: center; justify-content: center; }
.mw-peek { padding: 6px; border-radius: 10px;
  background: rgba(255, 255, 255, .97); box-shadow: 0 6px 24px rgba(0, 0, 0, .3); }
.mw-peek svg { width: 150px; aspect-ratio: 1000 / 1414; display: block; background: #fff;
  border: 1px solid rgba(34, 48, 60, .18); }
.mw-peek-lab { font-size: 12px; text-align: center; padding-top: 4px; opacity: .75; }
.mw-strip { touch-action: pan-x; }

/* the bar goes to whichever edge the teacher works from */
.mwwidget[data-bar-at="bottom"] { flex-direction: column-reverse; }
/* bar at the bottom: tier 2 belongs above tier 1, so the options still sit
   between the page and the tools rather than hanging off the bottom edge */
.mwwidget[data-bar-at="bottom"] .mw-tools { flex-direction: column-reverse; }
.mwwidget[data-bar-at="bottom"] .mw-opts { border-top: 0;
  border-bottom: 1px solid rgba(34, 48, 60, .09); border-radius: 8px 8px 0 0; }
.mwwidget[data-bar-at="bottom"] .mw-strip { order: -1; }
/* no align-items:start here — it stopped the stage stretching into its row, so
   the page rendered small with a band of dead space under it (Glenn, item 2).
   The bar occupies the STAGE row only and the strip spans the full width: when
   the bar spanned both rows it ran 72px past the stage, and the .grow spacer
   then threw Print 685px down the column, on top of the thumbnails. */
.mwwidget[data-bar-at="left"], .mwwidget[data-bar-at="right"] { display: grid; gap: 6px;
  grid-template-areas: 'bar stage' 'strip strip'; grid-template-columns: auto minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr) auto; }
.mwwidget[data-bar-at="right"] { grid-template-areas: 'stage bar' 'strip strip';
  grid-template-columns: minmax(0, 1fr) auto; }
.mwwidget[data-bar-at="left"] .mw-tools, .mwwidget[data-bar-at="right"] .mw-tools {
  grid-area: bar; width: 84px; min-height: 0; overflow-y: auto; }
.mwwidget[data-bar-at="left"] .mw-bar, .mwwidget[data-bar-at="right"] .mw-bar,
.mwwidget[data-bar-at="left"] .mw-opts, .mwwidget[data-bar-at="right"] .mw-opts {
  flex-direction: column; align-items: stretch; flex-wrap: nowrap; }
/* in a column the options sit under the tools, still their own fixed home */
.mwwidget[data-bar-at="left"] .mw-opts, .mwwidget[data-bar-at="right"] .mw-opts {
  border-radius: 8px; }
.mwwidget[data-bar-at="left"] .mw-opt-lab, .mwwidget[data-bar-at="right"] .mw-opt-lab {
  min-width: 0; text-align: center; }
.mwwidget[data-bar-at="left"] .mw-sep, .mwwidget[data-bar-at="right"] .mw-sep {
  width: 100%; height: 1px; margin: 2px 0; }
.mwwidget[data-bar-at="left"] .mw-bar > button, .mwwidget[data-bar-at="right"] .mw-bar > button {
  width: 100%; }
/* grid children need these or an over-wide child stretches the track — the
   main source of the Chrome/Firefox difference */
.mwwidget[data-bar-at="left"] > *, .mwwidget[data-bar-at="right"] > * { min-width: 0; min-height: 0; }
.mwwidget[data-bar-at="left"] .mw-family, .mwwidget[data-bar-at="right"] .mw-family {
  flex-direction: column; gap: 4px; }
/* a vertical bar stacks everything the horizontal one lays side by side, so it
   runs tall fast. Tighten it, and when it does overflow give it a hairline
   scrollbar rather than the OS's chunky one sitting over the ink dots. */
.mwwidget[data-bar-at="left"] .mw-bar, .mwwidget[data-bar-at="right"] .mw-bar { gap: 4px; }
.mwwidget[data-bar-at="left"] .mw-tools, .mwwidget[data-bar-at="right"] .mw-tools {
  scrollbar-width: thin; scrollbar-color: rgba(34, 48, 60, .28) transparent; }
.mwwidget[data-bar-at="left"] .mw-tools::-webkit-scrollbar,
.mwwidget[data-bar-at="right"] .mw-tools::-webkit-scrollbar { width: 5px; }
.mwwidget[data-bar-at="left"] .mw-tools::-webkit-scrollbar-thumb,
.mwwidget[data-bar-at="right"] .mw-tools::-webkit-scrollbar-thumb {
  background: rgba(34, 48, 60, .28); border-radius: 3px; }
.mwwidget[data-bar-at="left"] .mw-tools::-webkit-scrollbar-track,
.mwwidget[data-bar-at="right"] .mw-tools::-webkit-scrollbar-track { background: transparent; }
.mwwidget[data-bar-at="left"] .mw-tool, .mwwidget[data-bar-at="right"] .mw-tool {
  width: 22px; height: 22px; }
.mwwidget[data-bar-at="left"] .mw-nib, .mwwidget[data-bar-at="right"] .mw-nib {
  width: 20px; height: 20px; }
.mwwidget[data-bar-at="left"] .mw-bar .btn.small, .mwwidget[data-bar-at="right"] .mw-bar .btn.small {
  padding: 2px 6px; font-size: 12px; }
/* a tall thin bar keeps its buttons together: stretching the spacer would
   strand Print at the far end of a 700px column */
.mwwidget[data-bar-at="left"] .mw-bar .grow, .mwwidget[data-bar-at="right"] .mw-bar .grow {
  flex: 0 0 10px; }
.mwwidget[data-bar-at="left"] .mw-print, .mwwidget[data-bar-at="right"] .mw-print {
  width: 100%; justify-content: center; }
.mwwidget[data-bar-at="left"] .mw-stage, .mwwidget[data-bar-at="right"] .mw-stage { grid-area: stage; }
.mwwidget[data-bar-at="left"] .mw-strip, .mwwidget[data-bar-at="right"] .mw-strip { grid-area: strip; }
.mwwidget[data-bar-at="left"] .mw-pop, .mwwidget[data-bar-at="right"] .mw-pop {
  grid-area: stage; z-index: 6; }

/* the print root is invisible furniture until the moment of printing */
#sage-print-root { display: none; }

@media print {
  /* §6: our 10mm insets are the only margin system; @page margin 0 (injected
     per job) also suppresses the browser's own URL/date header-footer.
     Sheets are exact paper-sized boxes with the inset as padding (print.js
     wraps each page svg in .sp-sheet) — margins would be renegotiable under
     fragmentation, padding inside a fixed box is not. */
  /* The app is a kiosk screen: html/body carry height:100% + overflow:hidden,
     which in print clips the flow to a single viewport — every poster came out
     ~2 pages whatever the sheet count, because sheets 3..n were simply cut off.
     Neither the preview nor the tiling maths can show this; only a real PDF
     does. Found by printing one (Glenn, 2026-07-26). */
  html, body { height: auto !important; overflow: visible !important; margin: 0 !important; }
  body.sp-printing > *:not(#sage-print-root) { display: none !important; }
  body.sp-printing #sage-print-root { display: block !important; }
  #sage-print-root .sp-sheet { break-after: page; page-break-after: always; overflow: hidden; }
  #sage-print-root .sp-sheet:last-of-type { break-after: auto; page-break-after: auto; }
  #sage-print-root svg.sp-page { display: block; width: 100%; height: 100%;
    print-color-adjust: exact; -webkit-print-color-adjust: exact; }
  /* cut lines and seam shapes live in the margin and must survive a driver's
     "ink saving" — they are the assembly instructions */
  #sage-print-root .sp-furniture { display: block; width: 100%; height: 100%;
    print-color-adjust: exact; -webkit-print-color-adjust: exact; }
}

/* Recently closed — the second way back, for a mis-click noticed days later */
.bin-list { display: flex; flex-direction: column; gap: 4px; margin: 6px 0 2px; }
.bin-row { align-items: center; gap: 8px; font-size: 13.5px;
  padding: 5px 8px; border-radius: 8px; background: rgba(34, 48, 60, .05); }

/* ---------- Genre toolkit (english-text.js, docs/genre-toolkit-design.md) ----------
   Three faces in one widget: the success criteria that grow through a unit, the
   model text they were found in, and the genre's word bank. Everything sizes off
   the widget's own width (container query, with a plain fallback first) because
   the same list has to read from the back of the room at board size and stay
   legible in a corner at 300px. */
/* ---- story map (english-text.js, docs/story-map-design.md) ----
   Board-scale target sizes are written HERE and never inherited: .mntray
   contributes only gap:7px plus its named selectors, so anything this widget does
   not state for itself arrives at whatever the app's default happens to be.
   Everything sizes off @container on .sm-face, never a viewport query — a 900px
   widget on a 1920px stage must not keep a two-column layout it cannot fit. */
.smwidget {
  /* The board's measured widely-separated set, re-declared because --wb-t1/2/3 are
     scoped to .wbwidget. Widget-internal literals: never var(--ink), which applyTheme
     re-declares per widget, and a var() inside a printed SVG string means nothing. */
  --sm-t1: #1d4ed8;  /* channel 0 · circle */
  --sm-t2: #ea580c;  /* channel 1 · square */
  --sm-t3: #047857;  /* channel 2 · triangle */
  --sm-ink: #1e2c33; --sm-soft: #5b6b7b; --sm-faint: #8b9aa2;
  --sm-line: #e4eae8; --sm-firm: #cfdad7; --sm-ground: #f7faf9;
  --sm-acc: #0f766e; --sm-acc-soft: #d8f3ef; --sm-acc-ink: #0a544e;
  --sm-danger: #a13b4b; --sm-danger-soft: #fbe9ec;
  --sm-fs-beat: 15px; --sm-fs-box: 15.5px; --sm-fs-hint: 12.5px;
  --sm-tap: 44px; --sm-beatw: 158px;
  position: relative;
  display: flex; flex-direction: column; min-height: 0;
  color: var(--sm-ink);
  border-top: 4px solid transparent;
}
/* the lock reads from the back of the room without anyone reading the bar */
.smwidget.sm-locked { border-top-color: #1d7a4c; }

/* THE ROOM. Everything above is sized for a wall three metres away and thirty
   children. A teaching assistant with four children round a laptop is a different
   room: closer, smaller, and the children SHOULD be touching it. Custom properties
   inherit, so one class on the body does the whole thing — a TA changes a DISTANCE
   rather than eleven separate sizes. On the BODY, because mounts only ever touch
   the body and .widget.locked is already the app's own position-lock class. */
.smwidget.sm-table {
  --sm-fs-beat: 13px; --sm-fs-box: 13px; --sm-fs-hint: 11.5px;
  --sm-tap: 36px; --sm-beatw: 124px;
}

.sm-title {
  display: flex; align-items: center; gap: 9px; padding: 2px 2px 6px;
  font-size: 11.5px; letter-spacing: .15em; text-transform: uppercase;
  color: var(--sm-faint); font-weight: 700;
}
.sm-roomtag {
  font-size: 10.5px; font-weight: 800; letter-spacing: .09em;
  padding: 3px 9px; border-radius: 99px; background: #ede4fd; color: #5b21b6;
}
.sm-lockmark { color: #1d7a4c; letter-spacing: 0; text-transform: none; font-size: 12.5px; }
.sm-head { display: flex; align-items: baseline; gap: 11px; flex-wrap: wrap; padding: 0 2px 6px; }
/* the plan's name is CONTENT, not a control: it wraps and is never truncated */
.sm-plan { font-size: 20px; font-weight: 700; letter-spacing: -.012em; }
.sm-bandchip {
  font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  background: var(--sm-acc-soft); color: var(--sm-acc-ink); padding: 4px 10px; border-radius: 99px;
}
.sm-bandchip.none { background: #fdeee3; color: #94491a; }

/* the stage band: declarative, and it gates nothing */
.sm-stage {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 8px 10px; margin: 0 0 6px; border-radius: 9px;
  border-left: 5px solid transparent; background: #eef3f4;
}
.sm-stage.s-model { background: #eef3f4; border-left-color: #3f5a63; }
.sm-stage.s-together { background: #fdf1e0; border-left-color: #b4671a; }
.sm-stage.s-yours { background: #e6f5ec; border-left-color: #1d7a4c; }
.sm-stbtn {
  font-size: 13.5px; font-weight: 700; background: rgba(255,255,255,.72);
  border: 1.5px solid transparent; color: var(--sm-soft); border-radius: 99px;
  padding: 8px 17px; cursor: pointer; min-height: var(--sm-tap);
}
.sm-stbtn:hover { background: #fff; }
.sm-stbtn.on { color: #fff; }
.sm-stbtn.on.b-model { background: #3f5a63; }
.sm-stbtn.on.b-together { background: #b4671a; }
.sm-stbtn.on.b-yours { background: #1d7a4c; }
.sm-stseq {
  margin-left: auto; font-size: 11.5px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--sm-faint); font-weight: 700;
}

/* .sm-face is the ONE scroller. touch-action:none goes on the writing SVG and
   nowhere else, or a finger cannot scroll the face at all. */
.sm-face {
  container-type: inline-size;
  display: flex; flex-direction: column; gap: 6px;
  flex: 1; min-height: 0; overflow: auto;
  padding: 2px 2px 10px; background: var(--sm-ground); border-radius: 9px;
}
.sm-grow { flex: 1; }
.sm-empty { padding: 22px 6px; color: var(--sm-faint); font-size: 15px; font-style: italic; }

.sm-bar {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  padding: 9px 2px 2px; border-top: 1px solid var(--sm-line); margin-top: 6px;
}
/* Each face owns a hue and wears it selected or not, so a child reads the face by
   colour from the back of the room. Selected = saturated fill, unselected = the
   same hue as a tint, never grey. The three are chosen deliberately AWAY from the
   graph's blue/orange/green so a pill can never be mistaken for a line. */
.sm-pill {
  font-size: 15px; font-weight: 800; border: 2.5px solid; border-radius: 11px;
  padding: 10px 18px; cursor: pointer; min-height: calc(var(--sm-tap) + 2px);
}
.sm-pill.f-map { color: #0d6e66; border-color: #0d6e66; background: #d5f0ec; }
.sm-pill.f-box { color: #7c3aed; border-color: #7c3aed; background: #ede4fd; }
.sm-pill.f-graph { color: #b02a5b; border-color: #b02a5b; background: #fbe3ec; }
.sm-pill.on { color: #fff; }
.sm-pill.f-map.on { background: #0d6e66; }
.sm-pill.f-box.on { background: #7c3aed; }
.sm-pill.f-graph.on { background: #b02a5b; }
.sm-barbtn {
  font-size: 14.5px; font-weight: 700; background: #edf2f1; border: 1.5px solid transparent;
  color: var(--sm-soft); border-radius: 10px; padding: 10px 16px; cursor: pointer;
  min-height: var(--sm-tap);
}
.sm-barbtn.on { background: var(--sm-ink); color: #fff; }
.sm-barbtn.ghost { background: none; border-color: var(--sm-firm); }
.sm-barbtn.lockon { background: #1d7a4c; color: #fff; border-color: transparent; }

/* ---- text map ---- */
.sm-band { padding: 11px 0 13px; border-top: 1px solid var(--sm-line); }
.sm-band:first-of-type { border-top: none; }
.sm-bandhead { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin: 0 0 9px; }
.sm-boxname {
  font-size: var(--sm-fs-box); font-weight: 800; letter-spacing: .04em;
  text-transform: uppercase; color: var(--sm-acc);
}
/* the hint is permanent band-head furniture and measures identically whether the
   box holds four beats or none — a fixed size on a fixed base, because an em-sized
   fallback once made the EMPTY state shout */
.sm-boxhint { font-size: var(--sm-fs-hint); color: var(--sm-faint); font-style: italic; }
.sm-beats { display: flex; gap: 11px; align-items: flex-start; flex-wrap: wrap; }
.sm-beat {
  width: var(--sm-beatw); border: 1px solid var(--sm-firm); border-radius: 11px;
  padding: 8px; cursor: pointer; background: #fff; text-align: left;
  display: flex; flex-direction: column; font: inherit; color: inherit;
}
.sm-beat:hover { border-color: var(--sm-acc); }
.sm-beat.sel { border-color: var(--sm-acc); border-width: 2px; padding: 7px; box-shadow: 0 0 0 3px var(--sm-acc-soft); }
.sm-beat.blank { border-style: dashed; background: #fdfefe; }
/* a picture and a ghost frame occupy the SAME footprint, so a picture arriving can
   never change the card's size */
.sm-thumb { width: 100%; height: 78px; border-radius: 8px; background: #eff4f3; overflow: hidden; }
.sm-thumb.ghost { border: 1.5px dashed var(--sm-firm); background: #f8fbfa; }
.sm-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sm-btext {
  font-size: var(--sm-fs-beat); line-height: 1.34; margin: 7px 2px 1px; font-weight: 500;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden; min-height: 2.7em;
}
.sm-btext.blank { color: var(--sm-faint); font-weight: 400; font-style: italic; }
.sm-btext.cov { background: var(--sm-ink); color: transparent; border-radius: 5px; }
.sm-bmeta { display: flex; gap: 4px; flex-wrap: wrap; margin: 5px 2px 0; }
.sm-bmeta span {
  font-size: 11px; background: var(--sm-acc-soft); color: var(--sm-acc-ink);
  padding: 2px 7px; border-radius: 99px; font-weight: 700;
}
.sm-bmeta span.cp { background: #ede4fd; color: #5b21b6; }
.sm-bnote { font-size: 11.5px; color: var(--sm-danger); margin: 4px 2px 0; line-height: 1.32; }
.sm-addbeat {
  width: 72px; min-height: 118px; border: 1.5px dashed var(--sm-firm); border-radius: 11px;
  background: none; color: var(--sm-faint); font-size: 24px; cursor: pointer;
}
.sm-addbeat:hover { border-color: var(--sm-acc); color: var(--sm-acc); background: var(--sm-acc-soft); }
/* A dead control teaches nothing and a class reads it as the map being full, so at
   the cap the + is REPLACED by the teaching point rather than dimmed — and the
   sentence stands on the board instead of in a toast nobody re-reads. */
.sm-capnote {
  font-size: 12.5px; color: var(--sm-danger); font-weight: 700;
  padding: 10px 4px; max-width: 210px; line-height: 1.38;
}
.sm-tray { padding: 8px 0 10px; border-bottom: 1px solid var(--sm-line); }
.sm-traylab {
  font-size: 10.5px; letter-spacing: .13em; text-transform: uppercase;
  color: var(--sm-danger); font-weight: 800; margin: 0 0 6px;
}
/* The gap is the teaching point: closing it is what better word choice, sentence
   shape and pacing are FOR. So every box says its own gap out loud. */
.sm-gap {
  display: inline-flex; align-items: center; gap: 7px; font-size: 12px; font-weight: 700;
  background: #f4eefe; color: #5b21b6; border: 1.5px solid #d9c8fb;
  border-radius: 99px; padding: 4px 11px; margin: 4px 0 2px;
}
.sm-gap.met { background: var(--sm-acc-soft); color: var(--sm-acc-ink); border-color: #9fd8d0; }

/* ---- the beat panel ---- */
.sm-panel {
  margin: 11px 0 3px; border: 2px solid var(--sm-acc); border-radius: 12px;
  background: #fff; padding: 14px 15px; max-width: 690px;
}
.sm-ptop { display: flex; align-items: flex-start; gap: 10px; }
.sm-beatin, .sm-noteline {
  flex: 1; font-size: 17px; font-weight: 600; padding: 11px 12px;
  border: 1.5px solid var(--sm-firm); border-radius: 9px; color: var(--sm-ink);
  min-height: var(--sm-tap); font-family: inherit; width: 100%;
}
.sm-noteline { font-size: 14px; font-weight: 400; }
.sm-beatin:focus, .sm-noteline:focus { outline: none; border-color: var(--sm-acc); box-shadow: 0 0 0 3px var(--sm-acc-soft); }
.sm-pclose {
  font-size: 19px; line-height: 1; background: none; border: 1px solid var(--sm-firm);
  border-radius: 9px; cursor: pointer; color: var(--sm-soft);
}
.sm-pclose:hover { border-color: var(--sm-danger); color: var(--sm-danger); }
/* The 72px floor stands for the two controls a lesson presses dozens of times.
   --sm-tap is 44 at board and 36 at table for everything else, which the room
   setting makes defensible; these two are pressed under time pressure with a
   class watching, and they keep the floor at every band. */
.sm-big { min-width: 72px; min-height: 72px; }
.sm-plab {
  font-size: 10.5px; font-weight: 800; letter-spacing: .13em; text-transform: uppercase;
  color: var(--sm-faint); margin: 13px 0 6px;
}
.sm-enterhint { font-size: 11.5px; color: var(--sm-faint); margin: 5px 0 0; }
.sm-pickrow { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
/* stretch, so seven chips are one height: the axis words are the class's own and
   run to different lengths, and a ragged row of steps reads as a broken control */
.sm-chiprow { display: flex; gap: 6px; flex-wrap: wrap; align-items: stretch; }
.sm-step {
  font-size: 13px; font-weight: 700; border: 1.5px solid var(--sm-line); background: #fff;
  border-radius: 9px; padding: 7px 10px; cursor: pointer;
  min-width: 50px; min-height: var(--sm-tap); color: var(--sm-soft); line-height: 1.18;
}
.sm-step.mid { background: #f6f8f8; }
.sm-step .sm-num { display: block; font-size: 15px; font-weight: 800; font-variant-numeric: tabular-nums; }
.sm-step .sm-wd {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  font-size: 10px; font-weight: 600; color: var(--sm-faint); max-width: 78px; line-height: 1.2;
}
.sm-step.set { color: #fff; border-color: transparent; }
.sm-step.set .sm-wd { color: rgba(255,255,255,.86); }
.sm-pick {
  min-width: 56px; min-height: var(--sm-tap); border-radius: 7px; border: 1.5px solid var(--sm-line);
  cursor: pointer; background: #fff; color: var(--sm-soft); font-size: 16px;
}
.sm-pick.on, .sm-pick:hover { border-color: var(--sm-acc); }
.sm-pick.none { border-style: dashed; }
.sm-pickimg { width: 78px; height: 46px; object-fit: cover; border-radius: 7px; border: 1px solid var(--sm-line); }
.sm-mvrow { display: flex; gap: 6px; flex-wrap: wrap; margin: 14px 0 0; padding-top: 12px; border-top: 1px solid var(--sm-line); }
.sm-mv {
  font-size: 12.5px; background: #fff; border: 1px solid var(--sm-line); border-radius: 8px;
  padding: 8px 11px; cursor: pointer; color: var(--sm-soft); min-height: 40px;
}
.sm-mv.del { color: var(--sm-danger); border-color: var(--sm-danger-soft); }

/* ---- the word bank: class-facing furniture ---- */
.sm-bank { background: #fff; border: 1px solid var(--sm-firm); border-radius: 11px; padding: 11px 13px; margin: 0 0 10px; }
.sm-bankhead { display: flex; align-items: center; gap: 9px; margin: 0 0 8px; flex-wrap: wrap; }
.sm-banktitle { font-size: 10.5px; letter-spacing: .13em; text-transform: uppercase; color: var(--sm-faint); font-weight: 800; }
.sm-words { display: flex; gap: 6px; flex-wrap: wrap; }
.sm-word {
  display: inline-flex; align-items: center; gap: 6px; font-size: 14.5px; font-weight: 600;
  border: 1.5px solid var(--sm-firm); border-radius: 99px; padding: 6px 12px 6px 8px;
  cursor: pointer; background: #fff; color: var(--sm-ink); min-height: 38px;
}
.sm-word:hover { border-color: var(--sm-acc); }
.sm-word.picked { background: var(--sm-acc-soft); border-color: var(--sm-acc); }
/* covered by PAINTING the chip — proven by measured rendering, never by textContent */
.sm-word.hid { background: var(--sm-ink); border-color: var(--sm-ink); color: transparent; }
.sm-word.hid .sm-lad, .sm-word.hid .sm-tag, .sm-word.hid .sm-beyond { visibility: hidden; }
.sm-lad { width: 22px; height: 22px; flex: 0 0 22px; }
.sm-lad svg { width: 100%; height: 100%; display: block; }
.sm-tag { font-size: 9.5px; font-weight: 800; letter-spacing: .06em; padding: 1px 5px; border-radius: 4px; }
.sm-beyond { font-size: 11px; color: #b45309; }
.sm-moodgrp { margin: 0 0 9px; }
.sm-moodhead { display: flex; align-items: baseline; gap: 8px; margin: 0 0 5px; }
.sm-moodlab { font-size: 10.5px; letter-spacing: .11em; text-transform: uppercase; font-weight: 800; }
.sm-moodn { font-size: 11px; color: var(--sm-faint); font-variant-numeric: tabular-nums; }
.sm-moodgrp.thin .sm-moodn { color: var(--sm-danger); font-weight: 800; }
/* the want ring: the mood the open beat is asking for */
.sm-moodgrp.want .sm-moodhead { padding: 3px 9px; border-radius: 99px; background: #fff7e6; box-shadow: 0 0 0 1.5px #e8c98a; }
.sm-moodempty { font-size: 12.5px; color: var(--sm-danger); font-style: italic; font-weight: 600; }
.sm-banknote { font-size: 12px; color: var(--sm-faint); margin-top: 8px; line-height: 1.5; }
/* Words offered against the tone are a CHOICE, not a warning: The Road's characters
   crack jokes, and gallows humour and bathos are devices with names. Nothing here
   calls one wrong. */
.sm-rd { font-size: 9.5px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; padding: 1px 6px; border-radius: 4px; margin-left: 5px; }
.sm-rd.serves { background: var(--sm-acc-soft); color: var(--sm-acc-ink); }
.sm-rd.counter { background: #ede4fd; color: #5b21b6; }
.sm-rd.level { background: #eceff1; color: #4b5563; }

/* ---- the capture bar ---- */
.sm-cap {
  display: flex; gap: 7px; align-items: center; flex-wrap: wrap; padding: 9px 11px; margin: 0 0 10px;
  background: var(--sm-acc-soft); border: 1.5px solid #9fd8d0; border-radius: 11px;
}
.sm-caplab { font-size: 10.5px; letter-spacing: .11em; text-transform: uppercase; color: var(--sm-acc-ink); font-weight: 800; width: 100%; }
.sm-capin {
  flex: 1; min-width: 180px; font-size: 16px; font-weight: 600; padding: 10px 12px;
  border: 1.5px solid var(--sm-firm); border-radius: 9px; color: var(--sm-ink);
  min-height: var(--sm-tap); font-family: inherit; background: #fff;
}
.sm-capin:focus { outline: none; border-color: var(--sm-acc); box-shadow: 0 0 0 3px #fff; }
.sm-scores, .sm-capmoods { display: flex; gap: 3px; }
.sm-sp {
  width: 42px; min-height: var(--sm-tap); border: 1.5px solid var(--sm-firm); background: #fff;
  border-radius: 9px; cursor: pointer; display: flex; flex-direction: column;
  align-items: center; justify-content: center; color: var(--sm-soft); font-size: 13px;
}
.sm-sp.on { border-color: var(--sm-acc); border-width: 2.5px; background: var(--sm-acc-soft); }
.sm-sp .sm-spa { width: 16px; height: 16px; }
.sm-sp .sm-spa svg { width: 100%; height: 100%; display: block; }
.sm-spn { font-size: 12px; font-weight: 800; font-variant-numeric: tabular-nums; }
.sm-sp.beyond { border-color: #b45309; color: #8a4d09; }
.sm-sp.beyond.on { background: #fdf0dc; border-color: #b45309; }
.sm-capmood {
  width: 40px; min-height: var(--sm-tap); border: 1.5px solid var(--sm-firm);
  background: #fff; border-radius: 9px; cursor: pointer; font-size: 17px; font-weight: 800;
}
.sm-capmood.on { color: #fff; }
.sm-whorow { display: flex; gap: 5px; flex-wrap: wrap; align-items: center; width: 100%; margin-top: 7px; }
.sm-who {
  font-size: 12.5px; background: #fff; border: 1.5px solid var(--sm-firm); border-radius: 99px;
  padding: 5px 11px; cursor: pointer; color: var(--sm-soft); min-height: 36px;
}
.sm-who.on { background: var(--sm-ink); color: #fff; border-color: transparent; }

/* ---- boxing up: a handwritten ruled page ---- */
.sm-wctl {
  display: flex; gap: 7px; align-items: center; flex-wrap: wrap;
  padding: 8px 0 10px; border-bottom: 1px solid var(--sm-line);
}
.sm-wbtn {
  font-size: 13.5px; font-weight: 700; background: #edf2f1; border: 1.5px solid transparent;
  color: var(--sm-soft); border-radius: 9px; padding: 9px 13px; cursor: pointer; min-height: 42px;
}
.sm-wbtn.on { background: var(--sm-ink); color: #fff; }
.sm-wbtn.ghost { background: none; border-color: var(--sm-firm); font-weight: 600; }
.sm-wbtn.ghost:hover { border-color: var(--sm-acc); color: var(--sm-acc); }
.sm-wbtn.del { color: var(--sm-danger); border-color: var(--sm-danger-soft); }
.sm-wcount { font-size: 12.5px; color: var(--sm-soft); font-variant-numeric: tabular-nums; min-width: 60px; text-align: center; }
.sm-locknote { font-size: 13px; color: #1d7a4c; font-weight: 700; padding: 11px 3px; }
.sm-boxwrap { display: block; }
.sm-graphref { background: #fff; border: 1px solid var(--sm-firm); border-radius: 11px; padding: 10px 12px; margin: 10px 0; }
.sm-graphsvg { width: 100%; height: auto; display: block; }
.sm-brow {
  display: grid; grid-template-columns: 250px minmax(0, 1fr); gap: 16px;
  border-top: 1px solid var(--sm-line); padding: 12px 0;
}
.sm-mchip { display: flex; gap: 8px; align-items: flex-start; margin: 0 0 6px; }
.sm-mchip .sm-mt { width: 56px; height: 40px; border-radius: 6px; overflow: hidden; flex: 0 0 56px; background: #eff4f3; }
.sm-mchip .sm-mt.ghost { border: 1.5px dashed var(--sm-firm); }
.sm-mchip .sm-mt img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sm-mchip .sm-mx { font-size: 13px; line-height: 1.36; }
.sm-warea { display: block; }
.sm-wsvgwrap { border: 1.5px solid var(--sm-firm); border-radius: 9px; overflow: hidden; background: #fffdf7; }
/* touch-action:none belongs HERE and nowhere else — a finger inside a writing area
   draws, and anywhere else on the face it scrolls */
.sm-wsvg { width: 100%; height: auto; display: block; touch-action: none; cursor: crosshair; }
/* The pen has to be beside the box you are writing in: one toolbar at the top of a
   700px face is a stretch back up the wall for box 4, and on a wall-mounted board
   that stretch is the whole objection. */
.sm-rowtools { display: flex; gap: 5px; align-items: center; margin: 0 0 6px; flex-wrap: wrap; }
.sm-rt {
  font-size: 12.5px; font-weight: 700; background: #fff; border: 1.5px solid var(--sm-firm);
  border-radius: 8px; padding: 6px 10px; cursor: pointer; color: var(--sm-soft); min-height: 38px;
}
.sm-rt.on { background: var(--sm-ink); color: #fff; border-color: transparent; }
.sm-rt.del { color: var(--sm-danger); border-color: var(--sm-danger-soft); }
.sm-rtink { width: 28px; height: 28px; border-radius: 99px; border: 2.5px solid #fff; box-shadow: 0 0 0 1.5px var(--sm-firm); cursor: pointer; padding: 0; }
.sm-rtink.on { box-shadow: 0 0 0 3px var(--sm-acc); }
.sm-rtsep { width: 1px; height: 26px; background: var(--sm-line); margin: 0 3px; }

/* ---- the graph ---- */
.sm-legend { display: flex; gap: 8px; flex-wrap: wrap; margin: 8px 0 3px; }
.sm-lchip {
  font-size: 13.5px; font-weight: 700; background: #fff; border: 1.5px solid var(--sm-firm);
  border-radius: 99px; padding: 8px 14px; cursor: pointer; display: flex; align-items: center;
  gap: 8px; min-height: 42px; color: var(--sm-soft);
}
/* ON (swatch filled) and ARMED (thicker border plus a halo) are two INDEPENDENT
   states — a chip can be on and not armed, and that is the common case. */
.sm-lchip .sm-sw { width: 14px; height: 14px; border-radius: 99px; border: 2.5px solid currentColor; background: none; }
.sm-lchip .sm-sw.on { background: currentColor; }
.sm-lchip.armed { border-width: 2.5px; border-color: currentColor; box-shadow: 0 0 0 3px rgba(15,118,110,.09); }
.sm-lchip.off { opacity: .48; text-decoration: line-through; }
/* an empty channel holds its position, so the legend's three places never move */
.sm-lchip.empty { border-style: dashed; color: #b9c5c1; cursor: default; }
.sm-lchip .sm-kd { font-size: 10px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; opacity: .72; }
/* MEASURED, 2026-07-31, at the shipped 1180x660 def on a 1500px stage: the app's
   own title bar leaves 620px of body, the plan header (33) + stage band (60) +
   bar (58) take 151 of it, and the face gets 420 with the legend taking 42 of
   that. A 1000x440 plot at 1139px of width wants 499px and would scroll — and a
   class reads the shape whole or not at all.

   So the plot takes the room that is left rather than a number: the holder
   flexes, the SVG fills it, and preserveAspectRatio's own meet scaling does the
   rest. No measurement in JS, and it stays right when a teacher resizes. */
.sm-graphhold {
  background: #fff; border-radius: 9px;
  flex: 1 1 auto; min-height: 190px; display: flex;
}
.sm-graphhold .sm-graphsvg { height: 100%; max-height: 100%; }

/* ---- the settings panel ---- */
.sm-planbtn {
  font-size: 13.5px; text-align: left; background: #fff; border: 1.5px solid var(--sm-line);
  border-radius: 10px; padding: 10px 12px; cursor: pointer; display: block; width: 100%; margin: 0 0 7px;
}
.sm-planbtn.cur { border-color: var(--sm-acc); background: var(--sm-acc-soft); }
.sm-planbtn .pn { font-weight: 700; display: block; }
.sm-planbtn .pb { font-size: 11.5px; color: var(--sm-faint); margin-top: 2px; display: block; }
.sm-lrow { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin: 0 0 6px; }
.sm-lrow input[type="text"] { flex: 1; min-width: 110px; font: inherit; padding: 7px 9px; border: 1.5px solid var(--sm-line); border-radius: 8px; }
.sm-paste { width: 100%; font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 12.5px; padding: 8px; border: 1.5px solid var(--sm-line); border-radius: 8px; }
.sm-wordname { flex: 1; min-width: 90px; font-size: 13.5px; font-weight: 600; }
.sm-lvlname { font-size: 12px; color: var(--sm-faint); min-width: 92px; }
.sm-ladpick { display: inline-flex; gap: 2px; padding: 5px 7px; border: 1.5px solid var(--sm-line); border-radius: 9px; background: #fff; cursor: pointer; }
.sm-ladpick.on { border-color: var(--sm-acc); background: var(--sm-acc-soft); }
.sm-moment { border-left: 3px solid #b45309; padding: 7px 0 7px 11px; margin: 0 0 9px; font-size: 13.5px; line-height: 1.5; }
.sm-moment .sm-ctx { display: block; font-size: 11.5px; color: var(--sm-faint); margin: 2px 0 4px; }
/* the case for moments, rendered: what a report can say, against the stock
   sentence it replaces */
.sm-insert { background: #f7f4ee; border: 1px dashed #cbbda2; border-radius: 9px; padding: 11px 13px; margin-top: 9px; font-family: Georgia, serif; font-size: 14px; line-height: 1.6; color: #3a3228; }
.sm-insertlab { font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: #8a7a5e; font-weight: 800; margin-bottom: 5px; font-family: inherit; }
.sm-rhet { color: var(--sm-danger); text-decoration: line-through; opacity: .75; margin-top: 8px; }

/* A CONTAINER query, never a viewport one: a 900px widget on a 1920px stage must
   not keep a two-column layout it cannot fit. */
@container (min-width: 900px) {
  .sm-boxwrap.side { display: grid; grid-template-columns: 340px minmax(0, 1fr); gap: 18px; align-items: start; }
  .sm-boxwrap.side .sm-graphref { position: sticky; top: 4px; }
  .sm-boxwrap.side .sm-brow { grid-template-columns: 186px minmax(0, 1fr); }
}
@container (max-width: 620px) {
  .sm-brow { grid-template-columns: 1fr; }
}

.gtwidget { position: relative; }
.gt-face {
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-height: 0;
  overflow: auto;
}
/* TWO DELIBERATE ROWS (english-text.js paintQuick). The bar used to be one
   centred wrapping row, so every control that comes and goes with the face —
   Cover, Size, New text, undo — re-centred the whole thing and orphaned
   whatever fell over the edge. Rows with anchored ends instead: the faces are
   pinned left and Print is pinned right, so the two controls a teacher reaches
   for without looking are always in the same place. */
/* align-items:stretch overrides .tclock-quick's centring, which would otherwise
   shrink each row to its contents and centre it — and a shrink-wrapped row
   cannot pin anything to an edge. */
.gt-quick {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 5px;
  padding-top: 4px;
}
.gt-row { display: flex; align-items: center; gap: 5px; min-width: 0; }
.gt-row-nav { flex-wrap: wrap; }
.gt-tools { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; justify-content: flex-end; }
/* Reveal owns its row and takes everything the chevron and undo do not, which
   is what lets it carry a criterion in full without shoving anything sideways. */
.gt-row-act > .gt-reveal { flex: 1; min-width: 0; }
.gt-row-act > .btn:not(.gt-reveal) { flex-shrink: 0; }
.gt-seg { display: flex; gap: 2px; padding: 2px; border-radius: 11px; background: rgba(34, 48, 60, .07); }
.gt-seg .btn.small { border-radius: 9px; }
/* The face you are on, said three ways — fill, ring and ink — because a pale
   fill on its own reads as "slightly lighter" across a badly calibrated
   projector rather than as "this one". The ring is what carries it at the back
   of the room; the ink also lifts the label off its own fill. */
.gtwidget .gt-active {
  background: var(--acc, #c7d2fe);
  border-color: var(--acc-ink, #4338ca);
  color: var(--acc-ink, #4338ca);
  font-weight: 800;
}
.gtwidget .gt-dim { opacity: .55; }
.gt-chev { padding-left: 7px; padding-right: 7px; }
/* The Reveal button carries the criterion the class is about to be shown —
   often the lesson's learning intention, and children read it off the board.
   It wraps rather than clipping, and takes its own row on the bar when it
   needs one (.tclock-quick already wraps). Capped at the bar width so a
   200-character criterion from a hand-authored pack cannot widen the widget. */
.gt-reveal {
  white-space: normal;
  overflow-wrap: anywhere;
  text-align: left;
  line-height: 1.3;
  max-width: 100%;
}
/* icon + word, like modelled writing's print pill — layout only, so the button
   keeps whatever weight its class gives it (ghost here, solid there) */
.gt-print { display: inline-flex; align-items: center; gap: 6px; }

/* ---- the genre picker: nothing is chosen for the teacher ----
   Twelve solid Soft Daylight tints, one per genre (GT_LOOK, english-text.js),
   each carrying a deep-ink drawing of its own text-form. The colour is the
   welcome; the name and counts stay quiet slate on top of it. */
.gt-pick-lead { font-weight: 700; font-size: 18px; color: #22303c; padding: 2px 2px 0; }
.gt-pick { display: grid; grid-template-columns: repeat(auto-fit, minmax(168px, 1fr)); gap: 9px; }
.gt-pick-card {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 5px;
  align-items: flex-start;
  text-align: left;
  min-height: 92px;
  padding: 12px 14px;
  border: 2px solid rgba(34, 48, 60, .08);
  border-radius: 14px;
  background: var(--gt-tint, rgba(255, 255, 255, .6));
  cursor: pointer;
  font: inherit;
  transition: transform .12s ease, border-color .12s ease, box-shadow .12s ease;
}
.gt-pick-card:hover {
  border-color: var(--gt-ink, #64748b);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(34, 48, 60, .13);
}
.gt-pick-card:focus-visible { outline: 3px solid var(--gt-ink, #334155); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  .gt-pick-card { transition: none; }
  .gt-pick-card:hover { transform: none; }
}
.gt-pick-art {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 44px;
  height: 44px;
  color: var(--gt-ink, #475569);
  pointer-events: none;
}
.gt-pick-art svg { width: 100%; height: 100%; }
.gt-pick-name { font-weight: 800; font-size: 17px; color: #1e293b; padding-right: 46px; }
.gt-pick-sub {
  margin-top: auto;
  font-size: 12px;
  color: #3f4c5a;
  background: rgba(255, 255, 255, .55);
  padding: 2px 9px;
  border-radius: 999px;
}
.gt-pick-row { gap: 6px; flex-wrap: wrap; padding-top: 2px; }

/* ---- checklist face ---- */
.gt-list { display: flex; flex-direction: column; gap: 5px; }
.gt-none { padding: 14px 10px; font-size: 14.5px; color: #64748b; text-align: center; }
.gt-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 11px;
  background: rgba(34, 48, 60, .04);
  border: 2px solid transparent;
  cursor: pointer;
}
.gt-row:hover { background: rgba(34, 48, 60, .07); }
.gt-row.gt-on { border-color: #475569; background: rgba(34, 48, 60, .09); }
.gt-sw { flex: 0 0 auto; width: 22px; height: 22px; border-radius: 6px; border: 1.5px solid rgba(34, 48, 60, .35); }
.gt-crit {
  flex: 1;
  min-width: 0;
  color: #1e293b;
  font-weight: 500;
  line-height: 1.35;
  font-size: 19px;
  font-size: clamp(15px, 2.7cqw, 27px);
}
.gt-tick {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-width: 34px;
  height: 30px;
  padding: 0 5px;
  border: 2px solid rgba(34, 48, 60, .35);
  border-radius: 8px;
  background: #fff;
  cursor: pointer;
  color: #0f172a;
}
.gt-tick .ic { width: 20px; height: 20px; }
.gt-tick.on { background: #dcfce7; border-color: #16a34a; }
/* The evidence count: how many times the class found this feature in the model
   text. It sits OUTSIDE the tick box and reads as a fact, not as a claim — the
   tick beside it is the separate question of whether the class can do it yet.
   Slate rather than the tick's green, and sized to be read from the room
   rather than squinted at (it was 12px inside the box, which is where it got
   mistaken for part of the tick). */
.gt-ev {
  flex: 0 0 auto;
  min-width: 26px;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(34, 48, 60, .09);
  color: #3f4c5a;
  font-weight: 800;
  font-size: 14px;
  font-size: clamp(13px, 1.9cqw, 20px);
  text-align: center;
}
/* covered along with the words: a count of what is behind the cover is a clue */
.gt-covered .gt-ev { color: transparent; }
/* Cover: the words go, the swatches and the ticks stay — it has to read as
   covered, not as broken */
.gt-covered .gt-crit,
.gt-covered .gt-word { color: transparent; background: rgba(34, 48, 60, .13); border-radius: 6px; }

/* ---- model text face ---- */
/* Since the chips stopped ellipsizing they wrap, and a flex-shrink:0 strip
   with no ceiling grows without bound — twenty revealed criteria measured
   1016px of chips on a 510px face, which left .gt-text (flex:1, min-height:0)
   at its padding and took away the model text, the entire point of this face.
   The ceiling is a share of the face rather than a row count, so a whole
   unit's criteria still show on a big widget and a small one still keeps its
   text; past it the strip scrolls rather than pushing. */
.gt-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  flex-shrink: 0;
  max-height: 42%;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.gt-chips-none { font-size: 13px; color: #64748b; padding: 3px 2px; }
/* The chips are the class's learning intentions in surrogate — they read in
   full or they aren't doing their job. Wrap, never ellipsize. */
.gt-chip {
  white-space: normal;
  /* a hand-authored pack can hold a 200-character criterion with no space in
     it; without this the chip renders wider than the face and scrolls the
     whole thing sideways */
  overflow-wrap: anywhere;
  text-align: left;
  line-height: 1.3;
  padding: 5px 12px;
  border-radius: 999px;
  border: 2px solid transparent;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  color: #1e293b;
  cursor: pointer;
}
.gt-chip.on { border-color: #1e293b; font-weight: 800; }
.gt-text {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: 8px 10px;
  border-radius: 11px;
  background: #fff;
  color: #0f172a;
  white-space: pre-wrap;
  overflow-wrap: break-word;
  line-height: 1.95;
  /* a drag across words must paint, not select or scroll sideways */
  user-select: none;
  -webkit-user-select: none;
  touch-action: pan-y;
}
.gt-size0 { font-size: 19px; }
.gt-size1 { font-size: 25px; }
.gt-size2 { font-size: 33px; }
.gt-tk { cursor: pointer; padding: 3px 0; border-radius: 3px; }
.gt-gap { padding: 3px 0; }
/* The empty model-text face fills its face instead of sitting in the top
   third of it with a dead void underneath — the paste box takes the room, so
   what a teacher sees is somewhere to put the text rather than a gap. */
.gt-empty { display: flex; flex-direction: column; gap: 7px; flex: 1; min-height: 0; }
.gt-paste { flex: 1; height: auto; min-height: 96px; resize: none; }
.gt-empty .hint { flex-shrink: 0; }

/* ---- word bank face ---- */
.gt-bank { display: flex; flex-direction: column; gap: 10px; }
.gt-grp { display: flex; flex-direction: column; gap: 5px; }
.gt-glab {
  font-weight: 800;
  font-size: 13px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: #64748b;
}
.gt-words { display: flex; flex-wrap: wrap; gap: 5px; }
.gt-word {
  padding: 5px 12px;
  border-radius: 9px;
  background: #fff;
  border: 1.5px solid rgba(34, 48, 60, .22);
  color: #1e293b;
  font-weight: 500;
  font-size: 18px;
  font-size: clamp(14px, 2.4cqw, 26px);
}

/* ---- reveal-out-of-order menu: sits over the bar, never on the board ---- */
.gt-menu {
  position: absolute;
  left: 10px;
  right: 10px;
  bottom: 46px;
  z-index: 6;
  max-height: 62%;
  overflow: auto;
  padding: 6px;
  border-radius: 12px;
  border: 1px solid var(--panel-border);
  background: var(--panel-bg, #fff);
  box-shadow: 0 10px 30px rgba(15, 23, 42, .22);
}
.gt-menu-lab {
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: #64748b;
  padding: 6px 6px 3px;
}
.gt-menu-it {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  text-align: left;
  padding: 6px 7px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  font: inherit;
  font-size: 14px;
  color: #1e293b;
  cursor: pointer;
}
.gt-menu-it:hover { background: rgba(34, 48, 60, .08); }
.gt-menu-it.on { font-weight: 700; }
.gt-menu-it .gt-sw { width: 16px; height: 16px; border-radius: 5px; }
.gt-menu-it .ic { width: 16px; height: 16px; margin-left: auto; color: #16a34a; }
.gt-menu-t { flex: 1; min-width: 0; }
/* says the menu stays open, because a menu that used to shut on the first tap
   has taught every teacher who met it that one tap is all they get */
.gt-menu-foot {
  /* sticky, because a twenty-criterion menu scrolls and an instruction that
     only appears once you have scrolled to the end is an instruction nobody
     reads */
  position: sticky;
  bottom: -6px;
  font-size: 12px;
  color: #64748b;
  padding: 7px 7px 9px;
  margin-top: 3px;
  background: var(--panel-bg, #fff);
  border-top: 1px solid var(--panel-border);
}

/* ---- the editor, in the settings side panel ---- */
.gt-edit-lab { font-size: 12px; font-weight: 700; color: #64748b; margin-top: 4px; }
.gt-edit-area { height: auto; min-height: 62px; font-size: 13px; }
/* the genre names itself on the checklist face — three weeks on a wall, titled */
.gt-title {
  flex-shrink: 0;
  font-weight: 800;
  color: #1e293b;
  padding: 2px 2px 0;
  font-size: 20px;
  font-size: clamp(16px, 3cqw, 30px);
}

/* ---------- Reduced motion ---------- */
/* These three keyframes are only used by the @media block below. They are
   hoisted out of it so nothing has to parse @keyframes inside a conditional
   group rule. */
@keyframes rm-fade { from { opacity: 0; } }
@keyframes rm-wb-clap { 0%, 100% { background: #99f6e4; } 45% { background: #f59e0b; } }
@keyframes rm-sb-nudge {
  0%, 100% { box-shadow: 0 0 0 0 rgba(251, 191, 36, 0); }
  30%, 60% { box-shadow: 0 0 0 3px rgba(251, 191, 36, 0.9); }
}
/* The guard is property-based, not blanket. Movement (transform / left / top /
   scale / rotate / clip-path) goes; colour, opacity, width and height stay --
   those carry state, not motion, and stripping them takes feedback away from
   exactly the children who need the clearest feedback.
   Deliberately NOT `*, *::before, *::after { animation: ... !important }`:
   `.pt-sweep i` and `.sb-sweep i` start at width:0 and are filled by a
   `forwards` animation, so a blanket kill leaves the blending sweep either
   permanently empty or instantly full with the ball parked at the far end --
   broken, not calm. */
@media (prefers-reduced-motion: reduce) {
  /* entrances: keep the fade, drop the slide */
  .spanel,
  .bg-drawer,
  .deck-panel,
  .dashboard { animation: rm-fade 0.14s ease; }

  /* the mascot sits still; it is decoration and nothing else */
  .dash-mascot { animation: none; }

  /* decorative pops and glows -- the static state in the same rule already reads */
  .deck-ghost { animation: none; }                /* the 1.04 scale / 1.2deg tilt stay; only the pickup tween goes */
  .ttt-cell.winner,
  .connect-slot.winner span { animation: none; }  /* the amber cell / white ring is the win */
  .ft-frame.done { animation: none; }             /* the amber ring in the same rule is the "done" */
  .bm-pop { animation: rm-fade 0.3s ease; }       /* most uses mark a value that just changed — keep the blink, drop the bounce */

  /* the exchange chip must still shout, standing still: frozen at the glow's brightest frame */
  .dn-xchip { animation: none; box-shadow: 0 3px 12px rgba(180, 83, 9, 0.55); }

  /* the syllable clap has no static fallback -- the class is added on tap and
     never removed -- so keep a transient COLOUR flash and drop the 1.55 scale */
  .wb-syl.wb-clap { animation: rm-wb-clap 0.4s ease; }

  /* same problem, same answer: the "finish the sentence" nudge */
  .sb-tiles.sb-nudge { animation: rm-sb-nudge 0.7s ease 2; border-radius: 8px; }

  /* the blend sweep IS the lesson: the track keeps filling (a width-only
     progress bar, no vestibular motion); the travelling ball is retired */
  .pt-sweep.run b,
  .sb-sweep.run b { animation: none; opacity: 0; }

  /* transitions that move something -- instant state change instead */
  .icon-btn,
  .theme-card,
  .tb-swatch,
  .die span,
  .word-build-reveal,
  .memory-card,
  .ttt-cell,
  .swatch,
  .bg-thumb,
  .dt-swatch,
  .geo-sw::after,
  .paper-swatch,
  .deck-list.dragging .deck-card,
  .deck-ghost.drop,
  .dash-pill,
  .dash-card,
  .dash-tool,
  .dash-primary,
  .star-pill,
  .mn-anim .mn-loose,
  .mn-bin,
  .ct-bin,
  .dn-merge,
  .rk-bead,
  .pt-sg,
  .pt-tile,
  .pt-split,
  .mw-strip.mw-reordering .mw-thumb { transition: none; }

  /* folded in from the old sentence-builder-only reduced-motion block */
  .sb-card, .sb-card:hover { transition: none; transform: none; }
}
