/* =====================================================================
   Core styles, shared by every subject and island.
   The idea: an exercise book that came alive. Graph-paper pages,
   a red margin line, a doodle helper living in the margin, highlighter
   colours for the steps, sticky notes, washi tape and a sticker book.
   ===================================================================== */

/* ---------- Fonts (stored locally so the app works offline) ---------- */
@font-face {
  font-family: 'Shantell Sans';
  src: url('../assets/fonts/shantell-sans-latin.woff2') format('woff2');
  font-weight: 300 800;
  font-display: swap;
}
@font-face {
  font-family: 'Rubik Doodle Shadow';
  src: url('../assets/fonts/rubik-doodle-shadow-latin.woff2') format('woff2');
  font-display: swap;
}

/* ---------- Tokens: the Notebook theme (default) ---------- */
:root {
  --font-hand: 'Shantell Sans', 'Chalkboard SE', 'Comic Sans MS', 'Marker Felt', system-ui, sans-serif;
  --font-doodle: 'Rubik Doodle Shadow', var(--font-hand);

  --desk: #D7E2F4;
  --desk-dot: #C4D3EC;
  --paper: #F8FBFF;
  --paper-raised: #FFFFFF;
  --grid: #E0E9F7;
  --grid-strong: #BACEEC;
  --margin-line: #F29DA6;
  --ink: #1D2452;
  --ink-2: #48517E;
  --ink-3: #626B96;
  --focus: #1D5FD6;
  --sheet: #FFFFFF;
  --sheet-grid: #D2E0F4;

  /* Step colours: words and board digits at 4.5 to 1 or more on paper, parchment, pizza box and their own stripe (ux-rules J1, scripts/contrast.js). */
  --c-blue: #1B59C9;   --hl-blue: #C9DEFF;
  --c-orange: #A14700; --hl-orange: #FFDAAB;
  --c-pink: #B31753; --hl-pink: #FFC9DE;
  --c-green: #087047;    --hl-green: #BDEED2;
  --c-purple: #6A3CCF;   --hl-purple: #E1D5FF;
  --c-sun: #48517E;     --hl-sun: #FFF09C;
  /* A line style beside each step colour (ux-rules C4: colour is never the only clue). Not set per theme. */
  --ln-blue: solid; --ln-orange: dashed; --ln-pink: dotted; --ln-green: double;
  --hl-yellow: #FFE45C;

  --btn: #FFE45C;
  --btn-ink: #1D2452;
  --btn-shadow: #1D2452;
  --sticky-yellow: #FFF4AE;
  --sticky-pink: #FFDCEA;
  --sticky-blue: #D8EAFF;
  --sticky-green: #D5F5E1;
  --sticky-orange: #FFE6CC;
  --sticky-purple: #EAE1FF;
  --sticky-ink: #1D2452;
  --tape: rgba(255, 196, 70, 0.62);
  --tape-2: rgba(105, 185, 255, 0.5);
  --tape-3: rgba(255, 120, 165, 0.45);
  --shadow: rgba(29, 36, 82, 0.22);

  --sea: #CDE4FF;
  --sea-deep: #B3D4FB;
  --sea-line: #7FAEEA;
  --sand: #FFE29A;
  --grass: #A3E39C;
  --leaf: #58B867;
  --trunk: #C08452;
  --flag: #FF7FA8;
  --pencil: #8E96B4;
  --heart: #F0457A;
  --dd-ink: #1D2452;

  --r-btn: 255px 18px 225px 18px / 18px 225px 18px 255px;
  --r-card: 28px 10px 24px 12px / 12px 26px 10px 28px;
  --r-key: 16px 10px 18px 9px / 10px 16px 9px 18px;
  --margin-w: 196px;
  --topbar-h: 68px;
  color-scheme: light;
}

/* Blueprint: a night-time theme, white ink on blue paper */
:root[data-theme='blueprint'] {
  --desk: #0A1C42;
  --desk-dot: #12295A;
  --paper: #143A7C;
  --paper-raised: #1C4891;
  --grid: rgba(150, 195, 255, 0.13);
  --grid-strong: rgba(150, 195, 255, 0.34);
  --margin-line: #FF8FA3;
  --ink: #F2F6FF;
  --ink-2: #C6D5F3;
  --ink-3: #9CB3E0;
  --focus: #FFE45C;
  --sheet: #1D4C9B;
  --sheet-grid: rgba(170, 210, 255, 0.22);
  --c-blue: #B8D5FF;   --hl-blue: rgba(110, 160, 255, 0.18);
  --c-orange: #FFC888; --hl-orange: rgba(255, 170, 80, 0.18);
  --c-pink: #FFB5D1; --hl-pink: rgba(255, 110, 160, 0.18);
  --c-green: #92EBBE;    --hl-green: rgba(80, 220, 150, 0.18);
  --c-purple: #D9C9FF;   --hl-purple: rgba(190, 160, 255, 0.16);
  --c-sun: #E6EEFF;     --hl-sun: rgba(255, 228, 92, 0.18);
  --btn-shadow: #071431;
  --shadow: rgba(0, 0, 0, 0.45);
  --sea: rgba(120, 180, 255, 0.16);
  --sea-deep: rgba(120, 180, 255, 0.28);
  --sea-line: rgba(170, 210, 255, 0.55);
  --pencil: #9CB3E0;
  color-scheme: dark;
}

/* Bubblegum: pink paper, purple ink */
:root[data-theme='bubblegum'] {
  --desk: #F3D3E3;
  --desk-dot: #EBC0D6;
  --paper: #FFF6FA;
  --grid: #F8DDEA;
  --grid-strong: #EFB9D1;
  --margin-line: #8F7CFF;
  --ink: #3A1846;
  --ink-2: #6A4777;
  --ink-3: #7E5E8E;
  --focus: #7A3CD6;
  --sheet-grid: #F5D3E3;
  --btn-shadow: #3A1846;
  --dd-ink: #3A1846;
  --sticky-ink: #3A1846;
  --shadow: rgba(80, 20, 70, 0.2);
}

/* Chalkboard: green board, chalk colours */
:root[data-theme='chalk'] {
  --desk: #0F201B;
  --desk-dot: #17302A;
  --paper: #1F3D35;
  --paper-raised: #28493F;
  --grid: rgba(255, 255, 255, 0.055);
  --grid-strong: rgba(255, 255, 255, 0.18);
  --margin-line: #F2C94C;
  --ink: #F5F2E7;
  --ink-2: #D2DBD2;
  --ink-3: #A7BBB1;
  --focus: #F2C94C;
  --sheet: #24473E;
  --sheet-grid: rgba(255, 255, 255, 0.12);
  --c-blue: #B2D7FF;   --hl-blue: rgba(120, 180, 255, 0.22);
  --c-orange: #FFCE94; --hl-orange: rgba(255, 180, 90, 0.22);
  --c-pink: #FFB5CF; --hl-pink: rgba(255, 120, 170, 0.22);
  --c-green: #B7F0AA;    --hl-green: rgba(140, 230, 120, 0.22);
  --c-purple: #DDCDFF;   --hl-purple: rgba(200, 170, 255, 0.22);
  --c-sun: #F5F2E7;     --hl-sun: rgba(242, 201, 76, 0.22);
  --btn-shadow: #0A1712;
  --shadow: rgba(0, 0, 0, 0.45);
  --sea: rgba(140, 200, 255, 0.12);
  --sea-deep: rgba(140, 200, 255, 0.22);
  --sea-line: rgba(190, 225, 255, 0.45);
  --pencil: #A7BBB1;
  color-scheme: dark;
}

/* ---------- Base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  color: var(--ink);
  background-color: var(--desk);
  background-image: radial-gradient(var(--desk-dot) 1.6px, transparent 1.8px);
  background-size: 22px 22px;
  font-family: var(--font-hand);
  font-size: 18px;
  line-height: 1.45;
  font-variation-settings: 'INFM' 30;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
button, input, select, textarea { font: inherit; color: inherit; font-variation-settings: inherit; }
button { -webkit-tap-highlight-color: transparent; }
a { color: inherit; }
p { margin: 0 0 0.6em; }
h1, h2, h3 { margin: 0; line-height: 1.1; font-weight: 800; font-variation-settings: 'INFM' 60; }
::selection { background: var(--hl-yellow); color: #1D2452; }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; border-radius: 10px; }
/* A screen's heading takes focus on arrival (ux-rules J4); it is not a control, so no ring. */
h1[tabindex='-1']:focus { outline: none; }
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.icon {
  width: 1.25em; height: 1.25em; flex: none;
  fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round;
}
.icon--fill { fill: currentColor; }

/* ---------- Numbers inside sentences: highlighter-underlined ---------- */
.n { font-weight: 800; font-variation-settings: 'INFM' 0; white-space: nowrap; padding: 0 0.08em; }
.n-blue {
  color: var(--c-blue); background: linear-gradient(transparent 58%, var(--hl-blue) 58%);
  text-decoration-line: underline; text-decoration-style: var(--ln-blue); text-decoration-color: var(--c-blue); text-decoration-thickness: 0.08em; text-underline-offset: 0.16em;
}
.n-orange {
  color: var(--c-orange); background: linear-gradient(transparent 58%, var(--hl-orange) 58%);
  text-decoration-line: underline; text-decoration-style: var(--ln-orange); text-decoration-color: var(--c-orange); text-decoration-thickness: 0.08em; text-underline-offset: 0.16em;
}
.n-pink {
  color: var(--c-pink); background: linear-gradient(transparent 58%, var(--hl-pink) 58%);
  text-decoration-line: underline; text-decoration-style: var(--ln-pink); text-decoration-color: var(--c-pink); text-decoration-thickness: 0.08em; text-underline-offset: 0.16em;
}
.n-green {
  color: var(--c-green); background: linear-gradient(transparent 58%, var(--hl-green) 58%);
  text-decoration-line: underline; text-decoration-style: var(--ln-green); text-decoration-color: var(--c-green); text-decoration-thickness: 0.06em; text-underline-offset: 0.16em;
}
.n-purple {
  color: var(--c-purple); background: linear-gradient(transparent 58%, var(--hl-purple) 58%);
  box-shadow: inset 0 0 0 0.09em var(--c-purple); border-radius: 0.7em; padding: 0 0.22em;
}
.step-name { font-weight: 800; font-variation-settings: 'INFM' 70; }
.praise {
  display: inline-block; font-weight: 800; color: var(--c-green);
  font-variation-settings: 'INFM' 90, 'BNCE' 60; transform: rotate(-3deg); margin-right: 0.15em;
}

/* ---------- The notebook sheet ---------- */
.sheet {
  position: relative;
  max-width: 1360px;
  min-height: 100vh;
  min-height: 100dvh;
  margin: 0 auto;
  background-color: var(--paper);
  background-image:
    linear-gradient(var(--grid) 1.5px, transparent 1.5px),
    linear-gradient(90deg, var(--grid) 1.5px, transparent 1.5px);
  background-size: 28px 28px;
  box-shadow: 0 0 0 1px var(--grid-strong), 0 24px 60px -24px var(--shadow);
  display: flex;
  flex-direction: column;
}
@media (min-width: 1420px) {
  .sheet { margin: 22px auto; min-height: calc(100dvh - 44px); border-radius: 8px; }
}
/* Paper: each subject picks one (subject.paper). Graph paper, above, is the default. */
body[data-paper='ruled'] .sheet {
  background-image: linear-gradient(transparent 0 calc(100% - 1.5px), var(--grid-strong) calc(100% - 1.5px));
  background-size: 100% 32px;
}
body[data-paper='dots'] .sheet {
  background-image: radial-gradient(var(--grid-strong) 1.5px, transparent 1.8px);
  background-size: 24px 24px;
}
body[data-paper='plain'] .sheet { background-image: none; }

/* The red margin line of an exercise book */
.sheet::before {
  content: '';
  position: absolute; top: 0; bottom: 0;
  left: calc(var(--margin-w) + 14px);
  width: 7px;
  background: linear-gradient(90deg, var(--margin-line) 0 2px, transparent 2px 5px, var(--margin-line) 5px 7px);
  opacity: 0.85;
  pointer-events: none;
  z-index: 0;
}

/* ---------- The island's look: accent, and its place (decision 0015, ux-rules M) ---------- */
:root { --accent: var(--c-blue); --accent-hl: var(--hl-blue); }
body[data-accent] .screen-title .squiggle { color: var(--accent); }
body[data-accent] .isle-pin, body[data-accent] .stop--current .stop-badge { background: var(--accent-hl); }
body[data-accent] .session-problem { color: var(--accent); }
body[data-accent] .tab[aria-current='page'] { box-shadow: inset 0 -5px 0 var(--accent-hl); }
body[data-accent] .finish-eq { color: var(--accent); }
:root[data-theme='blueprint'] body[data-accent] .finish-eq, :root[data-theme='chalk'] body[data-accent] .finish-eq { color: var(--sticky-ink); }   /* the finish card is a light sticky in the night themes */

/* The look shim: an island without scenery may draw a small scene in the margin, on wide screens */
.scene {
  position: absolute; left: 10px; bottom: 16px; z-index: 0;
  width: calc(var(--margin-w) - 12px);
  pointer-events: none;
  opacity: 0.95;
  display: none;
}
@media (min-width: 1100px) { .scene:not(:empty) { display: block; } }
.scene svg { width: 100%; height: auto; display: block; }
.scene .k { stroke: var(--dd-ink); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.scene .n { fill: none; }
body[data-screen='session'] .scene { bottom: 8px; }

/* The place: the island's world, under the island page, spot page, sessions and the story */
.place {
  position: fixed; z-index: 0;
  top: 0; bottom: 0; left: 50%;
  width: min(100%, 1360px);
  transform: translateX(-50%);
  overflow: hidden;
  pointer-events: none;
  background: var(--place-sky, var(--paper));
}
@media (min-width: 1420px) { .place { top: 22px; bottom: 22px; border-radius: 8px; } }
.place > svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; overflow: visible; }
.place .k { stroke: var(--dd-ink); stroke-width: 3px; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.place .t { stroke-width: 2.2px; }
.place .n { fill: none; }
/* Asleep: a pencil sketch on paper. Awake: the part's own colours (set on the part). */
.place .is-asleep .k { stroke: var(--pencil) !important; stroke-width: 2.4px; }
.place .is-asleep :not(.n) { fill: var(--paper) !important; }
.place .is-waking * { transition: fill 2s ease, stroke 2s ease; }
/* Behind a problem or the story the place is dimmed and still (ux-rules M4) */
.place--backdrop::after { content: ''; position: absolute; inset: 0; background: var(--paper); opacity: 0.5; }
/* Night without an island's own night colours: core darkens the day and adds stars */
.place-dusk { position: absolute; inset: 0; background: rgba(6, 14, 40, 0.5); }
.place-stars { position: absolute; left: 0; top: 0; width: 100%; height: 45%; }

/* On an island the page is the place: no margin line, a window to see it, and text on paper */
body[data-place] .sheet::before { display: none; }
.place-window { display: none; }
body[data-place='scene'] .place-window { display: block; height: clamp(170px, 40vh, 420px); }
body[data-place='scene'] .screen-head > div,
body[data-place='scene'] .section-title,
body[data-place] .helper-name,
html[data-stage] body[data-painted] .helper-name {
  background: var(--paper-raised);
  border: 2.5px solid var(--ink);
  border-radius: var(--r-card);
  box-shadow: 3px 4px 0 var(--btn-shadow);
}
body[data-place='scene'] .screen-head > div { padding: 12px 22px 14px; }
body[data-place='scene'] .section-title { display: inline-flex; justify-self: start; padding: 8px 20px 8px 14px; margin-top: 30px; }
body[data-place] .helper-name,
html[data-stage] body[data-painted] .helper-name { padding: 0 12px; }
body[data-place='scene'] .stop-btn { background: var(--paper-raised); border: 2px solid var(--grid-strong); box-shadow: 2px 3px 0 var(--shadow); padding: 8px 8px 10px; }
body[data-place='backdrop'] .content { background: var(--paper); border-radius: 12px; box-shadow: 0 0 0 10px var(--paper); }

/* The board's paper on an island (scenery.paper): notebook is the theme's own sheet */
body[data-sheet='parchment'] { --sheet: #FBF0D2; --sheet-grid: #E6D2A2; }
:root[data-theme='blueprint'] body[data-sheet='parchment'],
:root[data-theme='chalk'] body[data-sheet='parchment'] { --sheet: #4A3A26; --sheet-grid: rgba(255, 226, 170, 0.2); }
/* Pizza-box cardboard (Fractions Island): kraft brown by day, dark card by night */
body[data-sheet='pizzabox'] { --sheet: #F3DDB5; --sheet-grid: #DDBB86; }
:root[data-theme='blueprint'] body[data-sheet='pizzabox'],
:root[data-theme='chalk'] body[data-sheet='pizzabox'] { --sheet: #4B3828; --sheet-grid: rgba(255, 205, 150, 0.2); }

/* ---------- Top bar ---------- */
.topbar {
  position: sticky; top: 0; z-index: 30;
  min-height: var(--topbar-h);
  display: flex; align-items: center; gap: 10px;
  padding: 10px 18px 10px 14px;
  background: var(--paper);      /* solid first: older tablets have no color-mix or backdrop-filter */
  border-bottom: 2px dashed var(--grid-strong);
}
@supports (background: color-mix(in srgb, red 50%, transparent)) and ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .topbar {
    background: color-mix(in srgb, var(--paper) 90%, transparent);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
  }
}
/* The line index.html shows while the scripts load. */
.app-loading { margin: 0; padding: 28px 24px; font-size: 1.25rem; font-weight: 700; color: var(--ink); }
.topbar-back { visibility: hidden; }
.topbar-back.is-on { visibility: visible; }
.topbar-title {
  flex: 1; min-width: 0;
  font-size: 1.35rem; font-weight: 800; font-variation-settings: 'INFM' 75;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.topbar-title a { text-decoration: none; }
.topbar-tools { display: flex; align-items: center; gap: 8px; }

.icon-btn {
  display: inline-grid; place-items: center;
  width: 46px; height: 46px; flex: none;
  border: 2.5px solid var(--ink); border-radius: var(--r-key);
  background: var(--paper-raised); color: var(--ink);
  box-shadow: 2px 3px 0 var(--btn-shadow);
  cursor: pointer; text-decoration: none;
  transition: transform 0.08s ease, box-shadow 0.08s ease;
}
.icon-btn[hidden] { display: none; }
.icon-btn .icon { width: 24px; height: 24px; }
.icon-btn:hover { transform: translate(-1px, -1px) rotate(-2deg); box-shadow: 3px 4px 0 var(--btn-shadow); }
.icon-btn:active { transform: translate(2px, 2px); box-shadow: 0 1px 0 var(--btn-shadow); }
.icon-btn[aria-pressed='true'] { background: var(--hl-yellow); color: #1D2452; }

.stars-pill {
  display: inline-flex; align-items: center; gap: 6px;
  height: 46px; padding: 0 14px 0 10px;
  border: 2.5px solid var(--ink); border-radius: 999px 40px 999px 50px / 50px 999px 40px 999px;
  background: var(--sticky-yellow); color: #1D2452;
  font-weight: 800; font-size: 1.15rem; font-variation-settings: 'INFM' 0;
  box-shadow: 2px 3px 0 var(--btn-shadow);
  text-decoration: none;
}
.stars-pill .icon { color: #E7A400; width: 26px; height: 26px; }
.stars-pill.is-bump { animation: bump 0.5s cubic-bezier(.3, 1.6, .5, 1); }

.goal { display: inline-flex; align-items: center; gap: 4px; margin-right: 6px; color: var(--ink-2); font-size: 0.9rem; }
.goal-label { margin-right: 4px; font-weight: 700; }
.goal-box {
  width: 16px; height: 16px;
  border: 2px solid var(--ink-2); border-radius: 4px 2px 5px 3px;
  background: transparent;
}
.goal-box.is-done { background: var(--hl-yellow); border-color: var(--ink); transform: rotate(-6deg); }

@keyframes bump { 0% { transform: scale(1); } 40% { transform: scale(1.22) rotate(-4deg); } 100% { transform: scale(1); } }

/* ---------- Page: margin helper + bubble + content ---------- */
.page {
  position: relative; z-index: 1;
  flex: 1;
  display: grid;
  grid-template-columns: var(--margin-w) minmax(0, 1fr);
  grid-template-areas: 'helper bubble' 'helper content';
  grid-template-rows: auto 1fr;
  column-gap: 40px;
  row-gap: 18px;
  padding: 22px 32px 56px 0;
  width: 100%;
  align-content: start;
}
.helper-slot {
  grid-area: helper;
  position: sticky; top: 88px;
  align-self: start;
  display: flex; flex-direction: column; align-items: center;
  padding-top: 2px;
}
.helper {
  width: 168px; height: 174px;
  cursor: pointer;
  border: 0; padding: 0; background: none;
}
.helper svg { width: 100%; height: 100%; overflow: visible; }
.helper-name {
  margin-top: 2px;
  font-size: 0.95rem; font-weight: 800; color: var(--ink-2);
  font-variation-settings: 'INFM' 80;
  transform: rotate(-3deg);
}
.bubble-slot { grid-area: bubble; min-width: 0; }
/* While playing, the question stays in view even when the page scrolls. */
body[data-screen='session'] .bubble-slot,
body[data-screen='story'] .bubble-slot { position: sticky; top: 78px; z-index: 12; }
.content { grid-area: content; min-width: 0; }

body.is-cover .helper-slot, body.is-cover .bubble-slot { display: none; }
body.is-cover .page { grid-template-areas: 'content content'; padding-left: 32px; }
body.is-cover .sheet::before { display: none; }
body.is-pick .topbar-tools > :not(.fullscreen-btn) { display: none; }

/* Speech bubble */
.bubble {
  position: relative;
  min-height: 76px;
  padding: 16px 22px 16px 22px;
  background: var(--paper-raised);
  border: 2.5px solid var(--ink);
  border-radius: 30px 22px 28px 20px / 22px 30px 20px 28px;
  box-shadow: 3px 4px 0 var(--btn-shadow);
  font-size: 1.22rem;
  line-height: 1.45;
}
.bubble-tail {
  position: absolute; left: -27px; top: 24px;
  width: 30px; height: 26px; overflow: visible;
}
.bubble-tail path { fill: var(--paper-raised); stroke: var(--ink); stroke-width: 2.5; stroke-linejoin: round; }
.bubble-text { position: relative; }
.bubble-text small { display: block; font-size: 0.82em; color: var(--ink-2); margin-top: 0.3em; }
.bubble.is-new { animation: bubble-pop 0.32s cubic-bezier(.3, 1.5, .5, 1); }
.bubble-extra:empty { display: none; }
.bubble-extra { margin-top: 12px; display: flex; flex-wrap: wrap; gap: 10px; }
@keyframes bubble-pop { 0% { transform: scale(0.96) rotate(-0.6deg); } 100% { transform: none; } }

/* ---------- Reading out loud ---------- */
.bubble.has-read { padding-right: 72px; }
.read-btn {
  position: absolute; top: 12px; right: 12px; z-index: 2;
  display: grid; place-items: center;
  width: 46px; height: 46px; padding: 0;
  border: 2.5px solid var(--ink); border-radius: 50% 46% 52% 44% / 46% 52% 44% 50%;
  background: var(--hl-yellow); color: #1D2452;
  box-shadow: 2px 3px 0 var(--btn-shadow);
  cursor: pointer;
  transition: transform 0.12s ease;
}
.read-btn .icon { width: 25px; height: 25px; }
.read-btn:hover { transform: rotate(-8deg) scale(1.06); }
.read-btn.is-talking { background: var(--hl-green); animation: talk 0.9s ease-in-out infinite; }
@keyframes talk { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.12) rotate(-4deg); } }
.sticky .read-btn { top: 14px; right: 14px; width: 44px; height: 44px; border-color: #1D2452; box-shadow: 2px 3px 0 #1D2452; }
.sticky.has-read-btn h2 { padding-right: 50px; }
.finish.has-read-btn .finish-title { padding: 0 44px; }
/* The word being read lights up like a highlighter */
::highlight(ma-tts) { background-color: #FFE45C; color: #1D2452; }
.progress { height: 18px; border: 2.5px solid #1D2452; border-radius: 999px; background: #FFFFFF; overflow: hidden; }
.progress > span { display: block; width: 0; height: 100%; background: #08754A; transition: width 0.3s ease; }
.field-input.field-select {
  appearance: none; -webkit-appearance: none;
  font-size: 1.02rem; font-weight: 700; color: #1D2452; background-color: #FFFFFF; border-color: #1D2452;
  padding-right: 2.4em;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 9l6 6 6-6' fill='none' stroke='%231D2452' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 0.7em center; background-size: 1.1em;
}
.setting-tip { font-size: 0.92rem; }

/* Helper moods */
.helper[data-mood='idle'] svg { animation: bob 2.6s ease-in-out infinite; }
.helper[data-mood='happy'] svg { animation: hop 0.55s cubic-bezier(.3, 1.6, .5, 1) 2; }
.helper[data-mood='oops'] svg { animation: wobble 0.5s ease-in-out; }
.helper[data-mood='think'] svg { animation: tilt 1.4s ease-in-out infinite; }
@keyframes bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-5px); } }
@keyframes hop { 0%, 100% { transform: translateY(0) scale(1); } 40% { transform: translateY(-16px) scale(1.04, 0.97); } }
@keyframes wobble { 0%, 100% { transform: rotate(0); } 25% { transform: rotate(-7deg); } 75% { transform: rotate(6deg); } }
@keyframes tilt { 0%, 100% { transform: rotate(0); } 50% { transform: rotate(-5deg) translateY(-2px); } }

/* Doodle drawings (helpers, monsters, islands, stickers) */
.dd { overflow: visible; }
.dd .k { stroke: var(--dd-ink); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.dd .t { stroke-width: 2.2; }
.dd .n { fill: none; }
.dd .fa { fill: var(--dd-a); }
.dd .fb { fill: var(--dd-b); }
.dd .fc { fill: var(--dd-c); }
.dd .fw { fill: var(--dd-w); }
.dd .fi { fill: var(--dd-ink); }
.dd .fp { fill: #FFFFFF; }
.dd .fm { fill: #FF7A93; }
.dd .ck { fill: #FF8FAB; opacity: 0.55; }
.dd .kw { stroke: var(--dd-w); stroke-width: 3; stroke-linecap: round; fill: none; }
.dd .shine { stroke: #FFFFFF; stroke-width: 3; stroke-linecap: round; fill: none; opacity: 0.9; }
.dd .eyes { transform-box: fill-box; transform-origin: center; animation: blink 4.6s infinite; }
@keyframes blink { 0%, 93%, 100% { transform: scaleY(1); } 95% { transform: scaleY(0.1); } }

/* ---------- Buttons ---------- */
.btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: 0.45em;
  min-height: 50px;
  padding: 0.5em 1.15em;
  border: 2.5px solid var(--ink);
  border-radius: var(--r-btn);
  background: var(--paper-raised);
  color: var(--ink);
  box-shadow: 3px 4px 0 var(--btn-shadow);
  font-weight: 800; font-size: 1.08rem; line-height: 1.1;
  font-variation-settings: 'INFM' 55;
  text-decoration: none; cursor: pointer;
  transition: transform 0.08s ease, box-shadow 0.08s ease;
}
.btn:hover { transform: translate(-1px, -2px) rotate(-0.6deg); box-shadow: 4px 6px 0 var(--btn-shadow); }
.btn:active { transform: translate(2px, 3px); box-shadow: 1px 1px 0 var(--btn-shadow); }
.btn--go { background: var(--btn); color: var(--btn-ink); }
.btn--pink { background: var(--sticky-pink); color: #1D2452; }
.btn--blue { background: var(--sticky-blue); color: #1D2452; }
.btn--green { background: var(--sticky-green); color: #1D2452; }
.btn--quiet { background: transparent; box-shadow: none; border-style: dashed; }
.btn--quiet:hover { box-shadow: none; background: color-mix(in srgb, var(--hl-yellow) 35%, transparent); }
.btn--small { min-height: 44px; padding: 0.35em 0.9em; font-size: 0.98rem; }
.btn--big { min-height: 62px; font-size: 1.3rem; padding: 0.55em 1.5em; }
.btn[disabled], .btn[aria-disabled='true'] {
  opacity: 0.45; cursor: not-allowed; transform: none; box-shadow: 3px 4px 0 var(--btn-shadow);
}
.btn-row { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }

/* ---------- Sticky notes and tape ---------- */
.sticky {
  --bg: var(--sticky-yellow);
  position: relative;
  padding: 22px 22px 22px;
  background: var(--bg);
  color: var(--sticky-ink);
  border-radius: 3px 3px 26px 4px / 3px 3px 12px 4px;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.04), 2px 10px 16px -8px var(--shadow);
  transform: rotate(var(--tilt, -0.6deg));
}
.sticky--pink { --bg: var(--sticky-pink); }
.sticky--blue { --bg: var(--sticky-blue); }
.sticky--green { --bg: var(--sticky-green); }
.sticky--orange { --bg: var(--sticky-orange); }
.sticky--purple { --bg: var(--sticky-purple); }
.sticky .btn { color: #1D2452; border-color: #1D2452; box-shadow: 3px 4px 0 #1D2452; }
.sticky .btn--quiet { box-shadow: none; }
.sticky h2, .sticky h3 { color: var(--sticky-ink); }
.sticky :focus-visible { outline-color: #1D2452; }
.tape {
  position: absolute; top: -13px; left: 50%;
  width: 92px; height: 28px;
  background: var(--tape);
  transform: translateX(-50%) rotate(-4deg);
  clip-path: polygon(3% 0, 97% 6%, 100% 22%, 96% 42%, 100% 62%, 96% 82%, 98% 100%, 2% 95%, 4% 76%, 0 56%, 4% 36%, 0 16%);
  pointer-events: none;
}
.tape--blue { background: var(--tape-2); transform: translateX(-50%) rotate(3deg); }
.tape--pink { background: var(--tape-3); }

/* ---------- Headings on the page ---------- */
.screen-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 12px 24px; margin-bottom: 22px; }
.screen-title {
  font-size: clamp(2rem, 4.2vw, 3rem);
  font-weight: 800;
  font-variation-settings: 'INFM' 85, 'BNCE' 25;
  letter-spacing: -0.01em;
}
.screen-title .squiggle { display: block; width: min(260px, 70%); height: 14px; margin-top: 4px; color: var(--c-pink); }
.squiggle path { fill: none; stroke: currentColor; stroke-width: 4; stroke-linecap: round; }
.lead { color: var(--ink-2); font-size: 1.12rem; max-width: 46ch; margin: 6px 0 0; }
.section-title {
  display: flex; align-items: center; gap: 10px;
  font-size: 1.55rem; margin: 40px 0 16px;
  font-variation-settings: 'INFM' 80;
}
.section-title .icon { width: 28px; height: 28px; }

/* ---------- Chips and switches ---------- */
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  min-height: 44px; padding: 0.3em 0.9em;
  border: 2.2px solid var(--ink); border-radius: 999px 60px 999px 70px / 70px 999px 60px 999px;
  background: var(--paper-raised); color: var(--ink);
  font-weight: 700; cursor: pointer;
}
.sticky .chip { color: #1D2452; border-color: #1D2452; background: rgba(255, 255, 255, 0.7); }
.chip[aria-pressed='true'], .chip[aria-checked='true'] { background: var(--hl-yellow); color: #1D2452; box-shadow: 2px 2px 0 var(--btn-shadow); }
.switch {
  display: inline-flex; align-items: center; gap: 12px;
  border: 0; background: none; padding: 4px 0; cursor: pointer; text-align: left;
  font-weight: 700;
}
.switch-track {
  position: relative; width: 62px; height: 34px; flex: none;
  border: 2.5px solid var(--ink); border-radius: 999px 40px 999px 50px / 50px 999px 40px 999px;
  background: var(--paper-raised);
  transition: background 0.15s ease;
}
.switch-knob {
  position: absolute; top: 3px; left: 4px;
  width: 23px; height: 23px; border-radius: 50%;
  background: var(--ink);
  transition: transform 0.18s cubic-bezier(.3, 1.4, .5, 1);
}
.switch[aria-checked='true'] .switch-track { background: var(--hl-green); }
.switch[aria-checked='true'] .switch-knob { transform: translateX(26px); }
.switch-text small { display: block; font-weight: 400; color: var(--ink-2); }
.sticky .switch-text small { color: var(--sticky-ink); }   /* a sticky stays light in the night themes: --ink-2 is pale there */

/* ---------- Text inputs ---------- */
.field-input {
  min-height: 52px; width: 100%;
  padding: 0.3em 0.7em;
  border: 2.5px solid var(--ink);
  border-radius: var(--r-key);
  background: var(--paper-raised);
  color: var(--ink);
  font-size: 1.25rem; font-weight: 700;
  font-variation-settings: 'INFM' 0;
}
.field-input::placeholder { color: var(--ink-3); font-weight: 400; }
.field-input:focus-visible { outline-offset: 2px; }

/* ---------- Cover (first visit) ---------- */
.cover-wrap { display: grid; grid-template-columns: minmax(0, 1fr); place-items: center; min-height: calc(100dvh - 120px); padding: 12px 0 40px; }
.cover {
  position: relative;
  width: min(620px, 100%);
  padding: 42px clamp(20px, 6vw, 56px) 40px;
  border-radius: 10px 22px 22px 10px;
  background:
    radial-gradient(rgba(255, 255, 255, 0.16) 1.2px, transparent 1.4px) 0 0 / 9px 9px,
    linear-gradient(135deg, #3F67DA, #5B3FC9);
  color: #1D2452;
  box-shadow: inset 14px 0 0 rgba(0, 0, 0, 0.12), 0 30px 50px -24px rgba(20, 30, 80, 0.55), 6px 6px 0 #1D2452;
  border: 3px solid #1D2452;
  animation: cover-in 0.6s cubic-bezier(.2, 1.2, .4, 1);
}
.cover-band {
  position: absolute; top: -3px; bottom: -3px; right: 38px; width: 18px;
  background: #FF6F9A; border-left: 3px solid #1D2452; border-right: 3px solid #1D2452;
}
.cover-label {
  position: relative;
  background: #FFFBF0;
  border: 3px solid #1D2452;
  border-radius: 18px 26px 16px 24px / 22px 14px 26px 16px;
  padding: 26px 26px 24px;
  text-align: center;
  transform: rotate(-1.2deg);
  box-shadow: 4px 5px 0 #1D2452;
}
.logo {
  font-family: var(--font-doodle);
  font-weight: 400;
  font-size: clamp(2.7rem, 9vw, 4.4rem);
  line-height: 0.95;
  color: #1D2452;
  font-variation-settings: normal;
  letter-spacing: 0.01em;
}
.logo-sub { display: block; margin-top: 8px; font-size: 1.05rem; color: #48517E; font-weight: 700; }
.name-field { display: block; margin-top: 22px; text-align: left; font-weight: 700; color: #48517E; }
.name-input {
  display: block; width: 100%; margin-top: 4px;
  border: 0; border-bottom: 3px dashed #1D2452; border-radius: 0;
  background: transparent; color: #1D2452;
  font-size: 1.9rem; font-weight: 800; padding: 4px 2px;
  font-variation-settings: 'INFM' 90;
}
.name-input::placeholder { color: #9AA2C4; }
.name-input:focus-visible { outline: none; border-bottom-color: #FF4F87; background: rgba(255, 228, 92, 0.35); }
.helper-pick { margin: 30px 0 0; padding: 0; border: 0; min-inline-size: 0; }
.helper-pick legend { color: #FFFFFF; font-weight: 800; font-size: 1.25rem; margin-bottom: 12px; font-variation-settings: 'INFM' 80; }
.helper-options { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.helper-option {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 10px 4px 8px;
  border: 3px solid #1D2452; border-radius: var(--r-card);
  background: rgba(255, 255, 255, 0.86); color: #1D2452;
  cursor: pointer; font-weight: 800;
  box-shadow: 3px 4px 0 #1D2452;
  transition: transform 0.12s ease;
}
.helper-option svg { width: 100%; max-width: 92px; height: auto; aspect-ratio: 120 / 124; }
.helper-option small { font-weight: 400; color: #48517E; font-size: 0.82rem; }
.helper-option:hover { transform: translateY(-3px) rotate(-1deg); }
.helper-option[aria-checked='true'] { background: #FFE45C; transform: translateY(-4px) rotate(-2deg); }
.cover-open { margin-top: 30px; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 12px 16px; }
.cover-open .btn { border-color: #1D2452; box-shadow: 4px 5px 0 #1D2452; color: #1D2452; }
/* "Not now" on the new-explorer form: a quiet dashed button, white on the blue cover (7:1 on #5B3FC9). */
.cover-open .btn.cover-notnow { background: transparent; box-shadow: none; border-color: #FFFFFF; color: #FFFFFF; }
.cover-open .btn.cover-notnow:hover { background: rgba(255, 255, 255, 0.16); }
.cover-note { flex-basis: 100%; margin: 0; text-align: center; font-weight: 800; color: #FFFFFF; }
.cover-note:empty { display: none; }

/* ---------- Who's exploring? (the picker on the cover; ux-rules N1) ---------- */
/* One card per explorer, in the sticky-note colours (all light, so the navy name is 12 to 1 or more in
   every theme: the cover is the same blue in all four). Two to a row; four fit a phone with no scrolling. */
/* The picker is short: it centres in what is left, and never asks the phone's page to scroll. */
.cover-wrap--pick { min-height: calc(100dvh - 160px); }
.picker-title { font-size: clamp(2rem, 7.5vw, 3.2rem); }
.picker-cards { margin: 26px 0 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.picker-card {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  min-height: 116px; padding: 10px 6px 10px;
  border: 3px solid #1D2452; border-radius: var(--r-card);
  background: var(--tone, #FFDCEA); color: #1D2452;
  cursor: pointer; font: inherit; font-weight: 800;
  box-shadow: 3px 4px 0 #1D2452;
  transition: transform 0.12s ease;
}
.picker-card--pink { --tone: #FFDCEA; }
.picker-card--blue { --tone: #D8EAFF; }
.picker-card--green { --tone: #D5F5E1; }
.picker-card--orange { --tone: #FFE6CC; }
.picker-art { display: block; width: 100%; max-width: 76px; }
.picker-art svg { display: block; width: 100%; height: auto; aspect-ratio: 120 / 124; }
.picker-name { display: block; max-width: 100%; font-size: 1.2rem; line-height: 1.15; overflow-wrap: anywhere; text-align: center; font-variation-settings: 'INFM' 70; }
.picker-card:hover { transform: translateY(-3px) rotate(-1deg); }
.picker-card:focus-visible { outline: 4px solid #FFFFFF; outline-offset: 3px; background: #FFE45C; }

/* "Not <name>? Switch" in the journal foot (ux-rules N3): small and quiet, never in the way. */
.btn.switch-link { font-size: 0.92rem; background: var(--paper-raised); }   /* its own paper, so it reads on a painted sky too */

/* Settings: the explorers (ux-rules N4). */
.explorers { display: grid; gap: 12px; }
.explorer { display: grid; gap: 8px; }
.explorer-row { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.explorer-row .field-input { flex: 1 1 10em; min-width: 0; width: auto; }
.explorer-ask p { margin: 0 0 8px; }
@keyframes cover-in { from { transform: translateY(30px) rotate(2deg); opacity: 0; } to { transform: none; opacity: 1; } }

/* ---------- Age chips (cover and settings) ---------- */
.age-chips { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.age-chip {
  display: grid; gap: 2px; justify-items: center; text-align: center;
  padding: 10px 6px 8px;
  border: 3px solid #1D2452; border-radius: var(--r-card);
  background: rgba(255, 255, 255, 0.86); color: #1D2452;
  cursor: pointer; box-shadow: 3px 4px 0 #1D2452;
  transition: transform 0.12s ease;
}
.age-chip:hover { transform: translateY(-3px) rotate(-1deg); }
.age-chip[aria-checked='true'] { background: #FFE45C; transform: translateY(-4px) rotate(-2deg); }
.age-chip-label { font-size: 1.35rem; font-weight: 800; font-variation-settings: 'INFM' 0; }
.age-chip-name { font-weight: 800; font-size: 0.95rem; font-variation-settings: 'INFM' 80; }
.age-chip small { font-weight: 400; color: #48517E; font-size: 0.78rem; line-height: 1.2; }
.sticky .age-chip { box-shadow: 2px 3px 0 #1D2452; }

/* ---------- Age bands: young explorers get bigger text and targets (ux-rules L) ---------- */
body[data-band='young'] { font-size: 19px; }
body[data-band='young'] .bubble { font-size: 1.3rem; }
body[data-band='young'] .key { height: 64px; font-size: 1.9rem; }
body[data-band='young'] .answer-cell { width: 64px; height: 64px; font-size: 2.5rem; }
body[data-band='young'] .btn { min-height: 54px; }
body[data-band='young'] .gb-board { --cell: max(28px, min(72px, calc((100cqi - 20px) / (var(--cols) + 1.1)), calc((100cqh - 30px) / (var(--rows) + 0.6)))); }
@media (max-width: 719px) {
  body[data-band='young'] { font-size: 17px; }
  body[data-band='young'] .bubble { font-size: 1.05rem; }
  body[data-band='young'] .key { height: 48px; font-size: 1.5rem; }
  body[data-band='young'] .answer-cell { width: 48px; height: 48px; font-size: 1.8rem; }
  body[data-band='young'] .btn { min-height: 46px; }
}

/* ---------- Map ---------- */
.map-screen { display: grid; gap: 18px; }
.map {
  position: relative;
  width: 100%;
  /* The wide map is never taller than the window: it shrinks (islands are placed in percentages) so it fits without scrolling. */
  max-height: calc(100dvh - var(--topbar-h) - 400px);
  min-height: 260px;
  margin: 0 auto;
  border: 3px solid var(--ink);
  border-radius: 34px 18px 40px 22px / 22px 40px 18px 34px;
  background: var(--sea);
  overflow: hidden;
  box-shadow: 4px 6px 0 var(--btn-shadow);
  container-type: size;
}
/* A phone's tall map is never squeezed (ux-rules M10): it keeps its own shape and the page scrolls. */
.map[data-layout='tall'] { max-height: none; }
.map-svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.map-svg .wave { fill: none; stroke: var(--sea-line); stroke-width: 2.5; stroke-linecap: round; opacity: 0.7; }
.map-svg .trail { fill: none; stroke: var(--ink); stroke-width: 3.2; stroke-dasharray: 2 13; stroke-linecap: round; opacity: 0.55; }
/* The route's legs (ux-rules M10): solid ink into a built island, pencil dots into one still to come, a side trip's own short branch. */
.map-svg .trail--ink { stroke: var(--ink); stroke-dasharray: none; }
.map-svg .trail--soon { stroke: var(--ink-2); stroke-dasharray: 2 13; }   /* dots, not the pencil grey: it reads at 3:1 on its halo */
.map-svg .trail--side { stroke: var(--ink-2); stroke-width: 2.6; stroke-dasharray: 2 9; }
.map-svg .trail-halo { fill: none; stroke: var(--paper-raised); stroke-linecap: round; stroke-width: 9; opacity: 0.85; }
.map-svg .trail-halo--soon { stroke-dasharray: 2 13; }
.map-svg .trail-halo--side { stroke-width: 8; stroke-dasharray: 2 9; }
/* On a painted sea the route is the order signal, so it is bolder and fully opaque on its halo. */
html[data-stage] body[data-painted='sea'] .map-svg .trail { stroke-width: 4; opacity: 1; }
html[data-stage] body[data-painted='sea'] .map-svg .trail--side { stroke-width: 3.4; }
html[data-stage] body[data-painted='sea'] .map-svg .trail-halo { stroke-width: 11; opacity: 0.92; }
html[data-stage] body[data-painted='sea'] .map-svg .trail-halo--side { stroke-width: 10; }
.map-svg .compass-ring { fill: var(--paper-raised); stroke: var(--ink); stroke-width: 2.5; }
.map-svg .compass-star { fill: var(--hl-yellow); stroke: var(--ink); stroke-width: 2.5; stroke-linejoin: round; }
.map-svg .compass-n { font: 800 22px var(--font-hand); fill: var(--ink); }
.map-svg .x-mark { stroke: var(--c-pink); stroke-width: 6; stroke-linecap: round; }

.isle {
  position: absolute;
  left: var(--x); top: var(--y);
  width: var(--w, 21%);
  transform: translate(-50%, -50%);
  display: flex; flex-direction: column; align-items: center;
  border: 0; padding: 0; background: none;
  text-decoration: none; color: var(--ink);
  cursor: pointer;
  border-radius: 24px;
}
/* When the window is short the map is squeezed: an island then sizes to the map's height, so its name stays inside the frame. */
@supports (width: 1cqh) { .isle { width: min(var(--w, 21%), var(--wh, 100cqh)); } }
.isle-art { display: block; width: 100%; transition: transform 0.2s cubic-bezier(.3, 1.5, .5, 1); }
.isle-art svg { width: 100%; height: auto; }
.isle:hover .isle-art, .isle:focus-visible .isle-art { transform: translateY(-6px) rotate(-2deg) scale(1.04); }
.isle-name {
  margin-top: -6px;
  padding: 4px 12px 5px;
  background: var(--paper-raised);
  border: 2.5px solid var(--ink);
  border-radius: 14px 6px 16px 8px / 8px 14px 6px 16px;
  font-weight: 800; font-size: clamp(0.82rem, 1.45vw, 1.05rem); line-height: 1.15;
  text-align: center;
  box-shadow: 2px 3px 0 var(--btn-shadow);
  transform: rotate(-2deg);
}
.isle-sub { display: block; font-weight: 600; font-size: 0.8em; color: var(--ink-2); }
.isle--soon { color: var(--ink-2); }
.isle--soon .isle-name { border-style: dashed; box-shadow: none; background: color-mix(in srgb, var(--paper-raised) 70%, transparent); transform: rotate(1.5deg); }
.isle-pin {
  position: absolute; top: -6%; right: 6%;
  padding: 2px 10px; border-radius: 999px;
  background: var(--hl-yellow); color: #1D2452; border: 2px solid #1D2452;
  font-weight: 800; font-size: 0.85rem; white-space: nowrap;
  /* --dx, --dy: a nudge back inside the frame when the map is squeezed (fitPins in core/screens.js). */
  transform: translate(var(--dx, 0px), var(--dy, 0px)) rotate(8deg);
}
.isle-art .sea-ring { fill: var(--sea-deep); stroke: var(--sea-line); stroke-width: 2.5; stroke-dasharray: 3 7; }
.isle-art .fsand { fill: var(--sand); }
.isle-art .fgrass { fill: var(--grass); }
.isle-art .fleaf { fill: var(--leaf); }
.isle-art .ftrunk { fill: var(--trunk); }
.isle-art .fflag { fill: var(--flag); }
.isle-art .isle-sign { font: 800 24px var(--font-hand); fill: #1D2452; text-anchor: middle; }
.isle-art .soon-land { fill: url(#ma-hatch); stroke: var(--pencil); stroke-width: 2.6; stroke-dasharray: 7 6; stroke-linecap: round; }
.isle-art .soon-symbol { font: 800 42px var(--font-hand); fill: var(--pencil); text-anchor: middle; }
/* How awake an island is (ux-rules M10): a pencil sketch, land in colour with its buildings still in
   pencil, then all in colour with a signpost. The sea ring is always in colour, like a place's sky. */
.isle--sketch .isle-art g :not(.n), .isle--waking .isle-extra :not(.n) { fill: var(--paper) !important; }
.isle--sketch .isle-art g .k, .isle--waking .isle-extra .k { stroke: var(--pencil) !important; }
.isle--sketch .isle-art text, .isle--waking .isle-extra text { fill: var(--pencil) !important; stroke: none !important; }
/* At night the pencil on dark paper reads as a hole: the sketch is drawn in chalk, the island's lines in
   the ink colour on the raised paper of its name card, so a place still to visit is as clear as one in colour. */
:root[data-theme='blueprint'] .isle--sketch .isle-art g :not(.n), :root[data-theme='chalk'] .isle--sketch .isle-art g :not(.n),
:root[data-theme='blueprint'] .isle--waking .isle-extra :not(.n), :root[data-theme='chalk'] .isle--waking .isle-extra :not(.n) { fill: var(--paper-raised) !important; }
:root[data-theme='blueprint'] .isle--sketch .isle-art g .k, :root[data-theme='chalk'] .isle--sketch .isle-art g .k,
:root[data-theme='blueprint'] .isle--waking .isle-extra .k, :root[data-theme='chalk'] .isle--waking .isle-extra .k { stroke: var(--ink) !important; }
.isle-art { position: relative; }
.isle-alive { position: absolute; left: 14%; top: 45%; width: 14%; pointer-events: none; }
.isle-alive svg { width: 100%; height: auto; display: block; }

.map-foot { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; justify-content: space-between; }
.today-card { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; --tilt: 0.8deg; padding: 14px 20px; }
.today-card .goal-box { width: 26px; height: 26px; border-width: 2.5px; border-color: #1D2452; }
.today-card .goal-box.is-done { background: var(--hl-yellow); }
.today-text { font-weight: 800; }
.today-text small { display: block; font-weight: 400; color: #48517E; }

/* ---------- Regions: a world with several maps ---------- */
.region { display: grid; gap: 10px; }
.region + .region { margin-top: 10px; }
.region-title { font-size: 1.6rem; font-variation-settings: 'INFM' 85; display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 14px; }
.region-title small { font-size: 1rem; font-weight: 600; color: var(--ink-2); }

/* ---------- Bookshelf: one notebook per world ---------- */
.shelf-screen { display: grid; gap: 22px; }
.shelf { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 38px 30px; padding: 6px 12px 18px 4px; }
.book {
  position: relative;
  display: flex; flex-direction: column; justify-content: space-between;
  min-height: 280px;
  padding: 30px 40px 18px 24px;
  border: 3px solid #1D2452;
  border-radius: 8px 18px 18px 8px;
  background: radial-gradient(rgba(255, 255, 255, 0.16) 1.2px, transparent 1.4px) 0 0 / 9px 9px, var(--cover);
  box-shadow: inset 12px 0 0 rgba(0, 0, 0, 0.14), 5px 6px 0 #1D2452;
  color: #1D2452; text-decoration: none;
  transform: rotate(var(--tilt, -1deg));
  transition: transform 0.2s cubic-bezier(.3, 1.5, .5, 1);
}
.book:hover, .book:focus-visible { transform: rotate(0) translateY(-6px) scale(1.02); }
.book-pages {
  position: absolute; top: 9px; bottom: 9px; right: -11px; width: 10px;
  background: #FFFFFF; border: 2.5px solid #1D2452; border-left: 0; border-radius: 0 6px 6px 0;
}
.book-band {
  position: absolute; top: -3px; bottom: -3px; right: 24px; width: 14px;
  background: #FF6F9A; border-left: 3px solid #1D2452; border-right: 3px solid #1D2452;
}
.book-label {
  display: grid; gap: 6px; text-align: center;
  padding: 18px 12px 16px;
  background-color: #FFFBF0;
  border: 3px solid #1D2452;
  border-radius: 14px 20px 12px 18px / 18px 12px 20px 14px;
  box-shadow: 3px 4px 0 #1D2452;
  transform: rotate(-1.5deg);
}
/* The label is printed on the subject's own paper */
.book[data-paper='graph'] .book-label { background-image: linear-gradient(#D9E4F5 1px, transparent 1px), linear-gradient(90deg, #D9E4F5 1px, transparent 1px); background-size: 14px 14px; }
.book[data-paper='ruled'] .book-label { background-image: linear-gradient(transparent 0 calc(100% - 1.5px), #C9DAF3 calc(100% - 1.5px)); background-size: 100% 18px; }
.book[data-paper='dots'] .book-label { background-image: radial-gradient(#C9DAF3 1.3px, transparent 1.5px); background-size: 14px 14px; }
.book-name { font-family: var(--font-doodle); font-size: 2.4rem; line-height: 1; }
.book-tag { font-weight: 700; color: #48517E; font-size: 0.95rem; }
.book-meta {
  align-self: flex-start; margin-top: 18px;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 12px;
  background: #FFF4AE; border: 2.5px solid #1D2452; border-radius: 999px;
  font-weight: 800; font-size: 0.95rem;
}
.book-meta .icon { color: #E7A400; width: 20px; height: 20px; }
.book--last::before {
  content: ''; position: absolute; top: -3px; left: 44px;
  width: 16px; height: 46px;
  background: #FFE45C; border: 2.5px solid #1D2452; border-top: 0;
  clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 80%, 0 100%);
}

/* ---------- Island home ---------- */
.island-home { display: grid; gap: 8px; }
.ih-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 30px 26px; margin-top: 18px; align-items: start; }
.ih-card h2 { font-size: 1.45rem; margin-bottom: 8px; font-variation-settings: 'INFM' 85; }
.ih-card p { color: #48517E; }
.ih-card:nth-child(2) { --tilt: 0.7deg; }
.ih-card:nth-child(3) { --tilt: -0.3deg; }
/* A phone's island and spot page (decision 0032 section 2): a Go card, the trail, then folds. Both layouts
   are in the page; the stage keeps .ih-cards and a phone keeps .go-card and .ih-folds. */
html[data-stage] .phone-only { display: none; }
html:not([data-stage]) .stage-only { display: none; }
/* The Go card comes straight after the page's head and the picture window under it, so Go is on the first
   screen of a short phone even with the route tip in the bubble (the window is aria-hidden: the reading
   order still matches what shows). The window keeps its own size, a little smaller on a phone. */
html:not([data-stage]) .island-home > .screen-head { order: -2; margin-bottom: 4px; }
html:not([data-stage]) .island-home > .island-frame > .go-card { order: -1; }
html:not([data-stage]) body[data-place='scene'] .island-home > .place-window { height: clamp(110px, 20vh, 190px); }
.go-card { --tilt: -0.4deg; }
.go-card .btn-row { margin-top: 12px; }
.go-card .btn { width: 100%; min-height: 56px; font-size: 1.3rem; }
.ih-folds { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; margin-top: 8px; }
.fold > .ih-card { --tilt: -0.3deg; margin-top: 18px; }
summary.fold-tab {
  position: relative; display: flex; align-items: center; gap: 10px;
  min-height: 44px; padding: 8px 14px 8px 12px;
  background: var(--paper-raised); color: var(--ink);
  border: 2.5px solid var(--ink); border-radius: 14px 14px 4px 4px / 12px 12px 4px 4px;
  border-left: 12px solid var(--tape);
  font-weight: 800; font-size: 1.05rem; line-height: 1.2;
  cursor: pointer; list-style: none;
}
summary.fold-tab::-webkit-details-marker { display: none; }
summary.fold-tab::before { content: '+'; flex: none; width: 1.2em; text-align: center; font-size: 1.3rem; font-weight: 800; }   /* a static mark, no animation */
details.fold[open] > summary.fold-tab::before { content: '\2212'; }
summary.fold-tab:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
.own-form { display: grid; gap: 12px; }
.own-row { display: flex; align-items: center; gap: 10px; }
.own-row .field-input { text-align: center; color: #1D2452; background: rgba(255, 255, 255, 0.85); border-color: #1D2452; }
.own-row .own-a { flex: 1.3; }
.own-row .own-b { flex: 1; }
.own-sym { font-size: 2rem; font-weight: 800; }
.own-error { color: #A0124A; font-weight: 700; margin: 0; }
.own-error:empty { display: none; }

.trail { position: relative; margin-top: 10px; padding: 26px 0 10px; }
.trail-svg { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; }
.trail-svg path { fill: none; stroke: var(--ink-2); stroke-width: 3.2; stroke-dasharray: 2 12; stroke-linecap: round; }
.trail-list { position: relative; list-style: none; margin: 0; padding: 0; display: grid; gap: 34px 18px; }
.stop { display: flex; justify-content: center; }
.stop-btn {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 4px; width: 100%; max-width: 190px;
  border: 0; background: none; padding: 6px; cursor: pointer; color: var(--ink);
  border-radius: 20px;
}
.stop-badge {
  position: relative;
  display: grid; place-items: center;
  width: 84px; height: 84px;
  border: 3px solid var(--ink);
  border-radius: 50% 46% 52% 44% / 46% 52% 44% 50%;
  background: var(--paper-raised);
  font-size: 2.3rem; font-weight: 800; font-variation-settings: 'INFM' 40;
  box-shadow: 3px 4px 0 var(--btn-shadow);
  transition: transform 0.2s cubic-bezier(.3, 1.6, .5, 1);
}
.stop-btn:hover .stop-badge { transform: rotate(-6deg) scale(1.06); }
.stop--done .stop-badge { background: var(--hl-green); color: #1D2452; }
.stop--current .stop-badge { background: var(--hl-yellow); color: #1D2452; animation: glow 1.8s ease-in-out infinite; }
.stop--locked .stop-badge { background: transparent; border-style: dashed; color: var(--ink-3); box-shadow: none; }
.stop--locked .stop-name, .stop--locked .stop-blurb { color: var(--ink-3); }
.stop-badge .icon { width: 34px; height: 34px; }
.stop-crown { position: absolute; top: -22px; right: -14px; font-size: 1.8rem; transform: rotate(14deg); }
.stop-name { font-size: 1.2rem; font-weight: 800; font-variation-settings: 'INFM' 70; margin-top: 4px; }
.stop-blurb { font-size: 0.9rem; color: var(--ink-2); line-height: 1.25; }
.stop-wins { display: flex; gap: 4px; margin-top: 4px; align-items: center; }
.stop-wins .goal-box { width: 14px; height: 14px; }
.stop-wins .boss-mini { font-size: 1rem; margin-left: 4px; }
/* The spot map: places inside an island (decision 0012). Same stops, a bigger drawing each. */
.spot-btn { text-decoration: none; max-width: 210px; }
.spot-art {
  position: relative; display: grid; place-items: center;
  width: 118px; height: 104px;
  border: 3px solid var(--ink);
  border-radius: 48% 52% 44% 56% / 54% 44% 56% 46%;
  background: var(--paper-raised);
  box-shadow: 3px 4px 0 var(--btn-shadow);
  transition: transform 0.2s cubic-bezier(.3, 1.6, .5, 1);
}
.spot-art svg { width: 92px; height: 82px; }
.spot-num { font-size: 2.3rem; font-weight: 800; }
.spot-btn:hover .spot-art, .spot-btn:focus-visible .spot-art { transform: rotate(-4deg) scale(1.05); }
.stop--done .spot-art { background: var(--hl-green); }
.stop--current .spot-art { background: var(--hl-yellow); animation: glow 1.8s ease-in-out infinite; }
.spot-flag {
  position: absolute; left: 50%; bottom: -14px; transform: translateX(-50%) rotate(-3deg);
  padding: 1px 10px; white-space: nowrap;
  background: var(--sticky-pink); color: #1D2452; border: 2px solid var(--ink); border-radius: 8px;
  font-size: 0.85rem; font-weight: 800;
}
.spot-map .stop-wins .goal-box { width: 12px; height: 12px; }
.spot-cards { grid-template-columns: minmax(0, 1fr); max-width: 640px; }
.spot-card-body { color: #48517E; }
.spot-card-body p + p { margin-top: 8px; }

@keyframes glow { 0%, 100% { box-shadow: 3px 4px 0 var(--btn-shadow), 0 0 0 0 rgba(255, 228, 92, 0.7); } 50% { box-shadow: 3px 4px 0 var(--btn-shadow), 0 0 0 12px rgba(255, 228, 92, 0); } }

.museum-link { margin-top: 26px; }

/* ---------- Cycle: the 4 secret steps ---------- */
.cycle { position: relative; list-style: none; margin: 0 auto; padding: 0 0 26px; width: fit-content; max-width: 100%; display: flex; justify-content: center; gap: clamp(8px, 2.6vw, 30px); }
.cycle-again { position: absolute; left: 0; right: 0; bottom: 0; height: 30px; }
.cycle-again span {
  position: absolute; left: 50%; bottom: 0; transform: translateX(-50%) rotate(-2deg);
  padding: 0 6px; font-size: 0.78rem; font-weight: 800; color: var(--ink-2);
  background: var(--paper); font-variation-settings: 'INFM' 100; white-space: nowrap;
}
.sticky .cycle-again span { background: var(--bg); color: #48517E; }
.cycle-step { position: relative; display: flex; flex-direction: column; align-items: center; min-width: 64px; text-align: center; }
.cycle-dot {
  display: grid; place-items: center;
  width: 50px; height: 50px;
  border: 2.5px solid var(--ink);
  border-radius: 50% 44% 52% 46% / 46% 52% 44% 50%;
  background: var(--paper-raised);
  font-size: 1.55rem; font-weight: 800; font-variation-settings: 'INFM' 30;
  transition: transform 0.25s cubic-bezier(.3, 1.6, .5, 1), background 0.2s ease;
}
.cycle-word { font-weight: 800; font-size: 0.95rem; margin-top: 4px; font-variation-settings: 'INFM' 80; }
.cycle-name { font-size: 0.78rem; color: var(--ink-2); }
.cycle-step + .cycle-step::before {
  content: ''; position: absolute; top: 22px; left: calc(-1 * clamp(8px, 2.6vw, 30px) - 2px);
  width: clamp(8px, 2.6vw, 30px); height: 3px; background: var(--ink-3); border-radius: 2px;
}
.cycle-loop { position: absolute; left: 0; right: 0; bottom: 6px; height: 24px; width: 100%; overflow: visible; }
.cycle-loop path { fill: none; stroke: var(--ink-3); stroke-width: 2.6; stroke-dasharray: 5 6; stroke-linecap: round; }
.cycle-step[data-tone='blue'] { --c: var(--c-blue); --hl: var(--hl-blue); }
.cycle-step[data-tone='orange'] { --c: var(--c-orange); --hl: var(--hl-orange); }
.cycle-step[data-tone='pink'] { --c: var(--c-pink); --hl: var(--hl-pink); }
.cycle-step[data-tone='green'] { --c: var(--c-green); --hl: var(--hl-green); }
.cycle-dot { color: var(--c); }
/* The wheel's letter wears its step's line, so D, M, S, B double as the key (ux-rules C4). */
.cycle-step[data-tone='blue'] .cycle-dot, .cycle-step[data-tone='orange'] .cycle-dot,
.cycle-step[data-tone='pink'] .cycle-dot, .cycle-step[data-tone='green'] .cycle-dot {
  text-decoration-line: underline; text-decoration-color: var(--c); text-decoration-thickness: 0.08em; text-underline-offset: 0.16em;
}
.cycle-step[data-tone='blue'] .cycle-dot { text-decoration-style: var(--ln-blue); }
.cycle-step[data-tone='orange'] .cycle-dot { text-decoration-style: var(--ln-orange); }
.cycle-step[data-tone='pink'] .cycle-dot { text-decoration-style: var(--ln-pink); }
.cycle-step[data-tone='green'] .cycle-dot { text-decoration-style: var(--ln-green); text-decoration-thickness: 0.06em; }
.cycle-step[data-tone='purple'] .cycle-dot { box-shadow: inset 0 0 0 0.09em var(--c-purple); }
.cycle-step.is-active .cycle-dot { background: var(--hl); transform: scale(1.22) rotate(-6deg); box-shadow: 2px 3px 0 var(--btn-shadow); }
.cycle-step.is-active .cycle-word { color: var(--c); }
.sticky .cycle-dot { border-color: #1D2452; background: rgba(255, 255, 255, 0.8); }
.sticky .cycle-name { color: #48517E; }
.sticky .cycle-step + .cycle-step::before { background: #737CA6; }
.sticky .cycle-loop path { stroke: #737CA6; }
.cycle-hidden {
  text-align: center; color: var(--ink-2); font-weight: 700;
  padding: 10px; border: 2px dashed var(--grid-strong); border-radius: var(--r-card);
}

/* ---------- Session ---------- */
/* ---------- Play screens fit the window (ux-rules F2): no scrolling to see question, board, answer, keypad ---------- */
body[data-screen='session'] .sheet, body[data-screen='home'] .sheet, body[data-screen='subject'] .sheet, body[data-screen='map'] .sheet { margin-top: 0; margin-bottom: 0; min-height: 100dvh; }
body[data-screen='session'] .page {
  flex: none;
  height: calc(100dvh - var(--topbar-h));
  min-height: 0;
  grid-template-rows: auto minmax(0, 1fr);
  padding-bottom: 10px;
  row-gap: 12px;
  overflow: hidden;
}
body[data-screen='session'] .content { min-height: 0; display: flex; flex-direction: column; overflow: clip; }
body[data-screen='session'] .bubble-slot { position: static; }
.session { display: flex; flex-direction: column; min-height: 0; flex: 1; }
.session-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 10px 16px; }
.tabs { display: flex; gap: 6px; align-items: flex-end; flex-wrap: wrap; }
.tab {
  --bg: var(--sticky-blue);
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 48px; padding: 8px 16px 10px;
  border: 2.5px solid var(--ink); border-bottom: 0;
  border-radius: 16px 12px 0 0 / 14px 16px 0 0;
  background: var(--bg); color: #1D2452;
  font-weight: 800; font-size: 1.02rem; text-decoration: none; cursor: pointer;
  transform: translateY(7px);
  transition: transform 0.15s ease;
}
.tab:hover { transform: translateY(2px); }
.tab[aria-current='page'] { transform: translateY(0); padding-bottom: 14px; font-size: 1.1rem; }
/* The warm-up's head (decision 0033): sits where the tabs sit, nothing over the problem (ux-rules M4). */
.warmup-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 12px; min-width: 0; padding: 6px 0 8px; }
.warmup-count { font-family: var(--font-hand); font-weight: 800; font-size: 1.1rem; color: var(--ink); }
.warmup-where { font-size: 0.95rem; color: var(--ink-2); overflow-wrap: anywhere; }
.tab--learn { --bg: var(--sticky-blue); }
.tab--practice { --bg: var(--sticky-green); }
.tab--challenge { --bg: var(--sticky-orange); }
.tab--boss { --bg: var(--sticky-pink); }
.tab[aria-disabled='true'] { opacity: 0.55; cursor: not-allowed; border-style: dashed; }
.session-head-right { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 16px; padding-bottom: 10px; }
.session-wins { display: flex; align-items: center; gap: 6px; font-weight: 700; color: var(--ink-2); font-size: 0.95rem; }
.session-wins .goal-box { width: 18px; height: 18px; }
.session-body {
  position: relative;
  flex: 1; min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 330px;
  grid-template-rows: minmax(0, 1fr);
  gap: 16px 30px;
  padding-top: 14px;
  border-top: 2.5px solid var(--ink);
  align-items: stretch;
}
.session-main { min-width: 0; min-height: 0; display: flex; flex-direction: column; gap: 8px; }
.session-problemline { display: flex; align-items: center; justify-content: space-between; gap: 10px 24px; flex-wrap: wrap; }
.session-titleblock { flex: none; }
.cycle-slot { flex: 1 1 340px; display: flex; justify-content: center; min-width: 0; }
.cycle-slot .cycle-hidden { margin: 0; }
.session-problem { font-size: 1.7rem; font-weight: 800; font-variation-settings: 'INFM' 20; line-height: 1.1; }
.session-level { display: block; font-size: 0.95rem; color: var(--ink-2); font-weight: 700; }
.board-slot { container-type: size; min-width: 0; min-height: 0; flex: 1; overflow: hidden; }
.session-side { display: grid; gap: 14px; align-content: start; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 4px 6px 8px 2px; }
.aside-slot:empty, .monster-slot:empty { display: none; }


/* Answer box and keypad */
.controls { display: grid; gap: 14px; }
.answer { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; }
.answer-box {
  display: flex; align-items: center; justify-content: center; gap: 2px;
  min-height: 66px; padding: 4px 14px;
  border: 3px solid var(--ink);
  border-radius: 18px 28px 16px 26px / 26px 16px 28px 18px;
  background: var(--paper-raised);
  font-size: 2.3rem; font-weight: 800; font-variation-settings: 'INFM' 0;
  letter-spacing: 0.06em;
}
.answer-box.is-empty { border-style: dashed; color: var(--ink-3); }
.answer-box.is-wrong { color: var(--c-pink); text-decoration: line-through; text-decoration-thickness: 4px; animation: shake 0.4s ease; }
.answer-caret { width: 3px; height: 1em; background: var(--ink); border-radius: 2px; animation: caret 1s steps(1) infinite; }
.answer-box.is-wrong .answer-caret { display: none; }
@keyframes caret { 50% { opacity: 0; } }

/* One box per digit of the expected answer: little graph-paper squares, like the board's. */
.answer--cells { grid-template-columns: auto auto; justify-content: space-between; align-items: center; }
.answer-cells {
  --cc: var(--ink-2);
  display: flex; gap: 8px; flex-wrap: nowrap;
  padding: 8px;
  background: var(--sheet);
  border-radius: 6px;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.04), 3px 8px 16px -10px var(--shadow);
  transform: rotate(-0.8deg);
}
.answer-cells--blue { --cc: var(--c-blue); }
.answer-cells--orange { --cc: var(--c-orange); }
.answer-cells--pink { --cc: var(--c-pink); }
.answer-cells--green { --cc: var(--c-green); }
.answer-cells--purple { --cc: var(--c-purple); }
.answer-cell {
  position: relative;
  display: grid; place-items: center;
  width: 60px; height: 60px;
  border: 2px solid var(--sheet-grid);
  border-radius: 6px;
  color: var(--cc);
  font-size: 2.3rem; font-weight: 750; font-variation-settings: 'INFM' 0; line-height: 1;
}
.answer-cells--plain .answer-cell { color: var(--ink); }
.answer-cell.is-filled { animation: cell-write 0.3s cubic-bezier(.2, 1.3, .4, 1); }
.answer-cell.is-active { border: 3px dashed var(--cc); }
.answer-cell.is-active::after {
  content: ''; position: absolute; left: 50%; top: 22%; bottom: 22%;
  width: 3px; margin-left: -1.5px; border-radius: 2px; background: var(--cc);
  animation: caret 1s steps(1) infinite;
}
.answer-cells.is-wrong .answer-cell { color: var(--c-pink); text-decoration: line-through; text-decoration-thickness: 4px; }
.answer-cells.is-wrong { animation: shake 0.4s ease; }
.answer-cells.is-nudge, .answer-box.is-nudge { animation: shake 0.35s ease; }
/* The board is the answer (decision 0013): just Start again and Check under it. */
.answer--board { grid-template-columns: auto auto; justify-content: space-between; align-items: center; }
.answer--board.is-nudge { animation: shake 0.35s ease; }
.btn.is-ready { animation: key-glow 1.2s ease-in-out infinite; }
.answer--cells { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 10px; }
.answer-cells { flex-wrap: wrap; max-width: 100%; }
.answer-cells--text .answer-cell { width: 46px; height: 56px; font-size: 1.9rem; font-variation-settings: 'INFM' 40; }
.answer-cells--long { gap: 5px; }
.answer-cells--long .answer-cell { width: 34px; height: 46px; font-size: 1.45rem; }
.answer-cell.is-space { border-style: dotted; }

/* Letters for spelling and words: ABC order, big enough to tap. */
.keypad.keypad--letters { grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 7px; }
.keypad--letters .key.key { height: 50px; font-size: 1.4rem; font-variation-settings: 'INFM' 30; box-shadow: 0 3px 0 var(--btn-shadow); }
.key--wide { grid-column: span 2; font-size: 1rem; }

/* Choices: two side by side, or a 2 by 2 grid for three or four. */
.choice-row--many .btn { min-height: 64px; font-size: 1.15rem; padding: 0.4em 0.6em; }
/* Challenge and Boss: a tap selects, Check sends (decision 0029, ux-rules A8). The pick is a thick ink
   outline, a steady highlighter halo and a small tick, so it never rests on colour alone. The answer
   rule comes after it, so the green outline always shows after Show me (the selection is cleared too). */
.choice-row .btn.is-selected {
  position: relative; outline: 4px solid var(--ink); outline-offset: 2px;
  box-shadow: 0 4px 0 var(--btn-shadow), 0 0 0 9px var(--hl-sun);
}
.choice-tick {
  position: absolute; top: -12px; right: -10px; width: 26px; height: 26px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--ink); color: var(--paper); pointer-events: none;
}
.choice-tick .icon { width: 16px; height: 16px; stroke-width: 3.2; }
.choice-row .btn.is-answer { outline: 4px solid var(--c-green); outline-offset: 3px; }
.choice-row.is-wrong, .choice-row.is-nudge { animation: shake 0.4s ease; }
@keyframes cell-write {
  from { opacity: 0; transform: translateY(-0.25em) scale(1.4) rotate(-12deg); }
  to { opacity: 1; transform: none; }
}
@keyframes shake { 0%, 100% { transform: translateX(0); } 20% { transform: translateX(-8px); } 40% { transform: translateX(7px); } 60% { transform: translateX(-5px); } 80% { transform: translateX(3px); } }
.keypad { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.key {
  display: grid; place-items: center;
  height: 60px;
  border: 2.5px solid var(--ink);
  border-radius: var(--r-key);
  background: var(--paper-raised); color: var(--ink);
  box-shadow: 0 4px 0 var(--btn-shadow);
  font-size: 1.7rem; font-weight: 800; font-variation-settings: 'INFM' 0;
  cursor: pointer;
  touch-action: manipulation;
  transition: transform 0.06s ease, box-shadow 0.06s ease;
}
.key:nth-child(3n + 2) { border-radius: 10px 18px 9px 16px / 16px 9px 18px 10px; }
.key:active, .key.is-pressed { transform: translateY(3px); box-shadow: 0 1px 0 var(--btn-shadow); }
.key .icon { width: 28px; height: 28px; }
.key--action { background: var(--hl-green); color: var(--c-green); }
.key--back { background: var(--sticky-pink); color: #1D2452; }
.key--glow { animation: key-glow 1.2s ease-in-out infinite; }
@keyframes key-glow { 0%, 100% { box-shadow: 0 4px 0 var(--btn-shadow), 0 0 0 0 rgba(8, 117, 74, 0.5); } 50% { box-shadow: 0 4px 0 var(--btn-shadow), 0 0 0 9px rgba(8, 117, 74, 0); } }
.choice-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.choice-row .btn { min-height: 74px; font-size: 1.6rem; }
.choice-row .btn.choice-check { grid-column: 1 / -1; min-height: 56px; font-size: 1.3rem; }
.assist { display: flex; flex-wrap: wrap; gap: 10px; }
.assist .btn { flex: 1; }

/* A game takes the whole play area; the finish card appears where the game was */
.session--game .session-body { grid-template-columns: minmax(0, 1fr); }
.session--game .session-side { display: none; }
.session--game .cycle-slot { display: none; }
.game-slot { overflow: visible; display: flex; }
.game-slot.is-done { display: none; }
.game-finish-slot:empty { display: none; }
.game-finish-slot { flex: 1; min-height: 0; display: grid; place-items: center; overflow: auto; }
.game-finish-slot .finish { width: min(100%, 440px); }

/* Learn controls */
.learn-nav { display: grid; gap: 14px; }
.learn-buttons { display: grid; grid-template-columns: 1fr 1.4fr; gap: 10px; }
.learn-progress { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; color: var(--ink-2); font-weight: 700; }
.learn-dot { width: 13px; height: 13px; border-radius: 50%; border: 2px solid var(--ink-3); }
.learn-dot.is-seen { background: var(--ink-2); border-color: var(--ink-2); }
.learn-dot.is-now { background: var(--hl-yellow); border-color: var(--ink); transform: scale(1.35); }

/* Finish card */
.finish { --tilt: -1deg; text-align: center; padding: 28px 22px 24px; display: grid; gap: 10px; }
.finish-title { font-size: 2rem; font-variation-settings: 'INFM' 100, 'BNCE' 80; }
.finish-eq { font-size: 1.6rem; font-weight: 800; font-variation-settings: 'INFM' 10; }
.finish-stars { display: flex; justify-content: center; gap: 6px; }
.finish-hearts { display: flex; justify-content: center; gap: 8px; }
.finish-heart { width: 54px; height: 54px; color: var(--heart); }
.finish-heart .icon { width: 100%; height: 100%; fill: currentColor; stroke: #1D2452; stroke-width: 1.6; }
.finish-heart:not(.is-on) { color: transparent; opacity: 0.5; }
.finish-heart:not(.is-on) .icon { fill: transparent; stroke-dasharray: 3 3; }
.finish-star .icon { width: 54px; height: 54px; stroke-width: 2; color: #B9BED4; }
.finish-star.is-on .icon { color: #E7A400; fill: #FFD84A; animation: star-in 0.5s cubic-bezier(.3, 1.8, .5, 1) both; }
.finish-star:nth-child(2).is-on .icon { animation-delay: 0.25s; }
.finish-star:nth-child(3).is-on .icon { animation-delay: 0.5s; }
@keyframes star-in { 0% { transform: scale(0) rotate(-90deg); } 100% { transform: none; } }
.finish-note { margin: 0; color: #48517E; }
.finish-note b { color: #1D2452; }
.finish-actions { display: grid; gap: 10px; margin-top: 8px; }
/* A laptop window of ordinary height: the card in the side column keeps both buttons in reach without scrolling. */
@media (min-width: 720px) and (max-height: 860px) {
  .session-side .finish { padding: 16px 18px 14px; gap: 6px; }
  .session-side .finish-title { font-size: 1.6rem; line-height: 1.1; }
  .session-side .finish-eq { font-size: 1.35rem; }
  .session-side .finish-heart { width: 36px; height: 36px; }
  .session-side .finish-star .icon { width: 40px; height: 40px; }
  .session-side .finish-actions { gap: 8px; margin-top: 4px; }
}

/* Boss monster */
.monster-card { --tilt: 0.8deg; display: grid; justify-items: center; gap: 4px; padding: 20px 16px 16px; }
.monster { width: 170px; height: 160px; }
.monster svg { width: 100%; height: 100%; overflow: visible; }
.monster[data-mood='idle'] svg { animation: bob 1.8s ease-in-out infinite; }
.monster[data-mood='hit'] svg { animation: hit 0.45s ease; }
.monster[data-mood='beaten'] svg { animation: poof 0.9s ease forwards; }
@keyframes hit { 0% { transform: none; filter: none; } 30% { transform: translateX(10px) rotate(8deg); filter: brightness(1.8); } 60% { transform: translateX(-8px) rotate(-6deg); } 100% { transform: none; } }
@keyframes poof { 0% { transform: none; opacity: 1; } 40% { transform: scale(1.15) rotate(-10deg); } 100% { transform: scale(0.1) rotate(200deg); opacity: 0; } }
.monster-name { font-weight: 800; font-size: 1.25rem; font-variation-settings: 'INFM' 90; }
.monster-taunt { margin: 0; font-size: 0.95rem; color: #48517E; }
.hearts { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px; }
.heart { width: 22px; height: 22px; color: var(--heart); }
.heart .icon { width: 100%; height: 100%; fill: currentColor; stroke: #1D2452; stroke-width: 1.6; }
.heart.is-lost { color: transparent; opacity: 0.5; }
.heart.is-lost .icon { fill: transparent; stroke-dasharray: 3 3; }
/* The first Boss fight's rules card: compact, so the stage does not scroll on a phone */
.boss-rules { --tilt: -0.4deg; display: grid; gap: 6px; padding: 14px 16px 12px; }
.boss-rules .tape { left: 50%; }
.boss-rules-title { margin: 0; font-size: 1.1rem; }
.boss-rules-list { margin: 0; padding-left: 20px; display: grid; gap: 2px; font-size: 1rem; }
.boss-rules .btn { min-height: 44px; justify-self: stretch; }
.pow {
  position: absolute; z-index: 5;
  font-family: var(--font-doodle); font-size: 2.6rem; color: #FF4F87;
  pointer-events: none; animation: pow 0.8s ease-out forwards;
}
@keyframes pow { 0% { transform: scale(0.3) rotate(-20deg); opacity: 0; } 30% { transform: scale(1.2) rotate(8deg); opacity: 1; } 100% { transform: scale(1) translateY(-30px) rotate(0); opacity: 0; } }

/* ---------- Sticker book ---------- */
.sticker-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 26px 18px; }
.sticker { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 6px; }
.sticker-art {
  display: grid; place-items: center;
  width: 108px; height: 108px;
  font-size: 4.2rem; line-height: 1;
  border-radius: 50%;
}
.sticker.is-earned .sticker-art {
  transform: rotate(var(--spin, -6deg));
  filter:
    drop-shadow(3px 0 0 #fff) drop-shadow(-3px 0 0 #fff) drop-shadow(0 3px 0 #fff) drop-shadow(0 -3px 0 #fff)
    drop-shadow(0 4px 5px rgba(0, 0, 0, 0.28));
}
.sticker:not(.is-earned) .sticker-art {
  border: 3px dashed var(--grid-strong);
  color: var(--ink-3); font-size: 2.6rem; font-weight: 800;
  background: color-mix(in srgb, var(--paper-raised) 60%, transparent);
}
.sticker-name { font-weight: 800; font-size: 1.05rem; font-variation-settings: 'INFM' 70; }
.sticker-how { font-size: 0.88rem; color: var(--ink-2); line-height: 1.3; max-width: 20ch; }
.sticker:not(.is-earned) .sticker-name { color: var(--ink-2); }

/* ---------- Mistake Museum ---------- */
.frames { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 30px 24px; }
.frame {
  position: relative;
  padding: 18px;
  border: 10px solid #C08452;
  border-radius: 6px;
  outline: 3px solid var(--ink); outline-offset: 0;
  background: var(--paper-raised);
  box-shadow: inset 0 0 0 3px #8E5A32, 4px 6px 0 var(--btn-shadow);
  display: grid; gap: 8px; justify-items: center; text-align: center;
  transform: rotate(var(--tilt, -1deg));
}
.frame:nth-child(even) { --tilt: 1.2deg; }
.frame-label { font-size: 2rem; font-weight: 800; font-variation-settings: 'INFM' 20; }
.frame-meta { font-size: 0.88rem; color: var(--ink-2); margin: 0; }
.stamp {
  position: absolute; top: -18px; right: -22px;
  padding: 4px 14px;
  border: 4px solid #BE1858; border-radius: 10px;
  color: #BE1858; background: rgba(255, 255, 255, 0.75);
  font-family: var(--font-doodle); font-size: 1.7rem; letter-spacing: 0.04em;
  transform: rotate(14deg);
  pointer-events: none;
}
.frame.is-beaten .frame-label, .frame.is-beaten .frame-meta { opacity: 0.55; }
.empty-note { --tilt: 0.6deg; max-width: 560px; }
.empty-note p:last-child { margin-bottom: 0; }

/* ---------- Settings ---------- */
.settings-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 34px 30px; align-items: start; }
.settings-col { display: grid; gap: 34px; align-content: start; }
.setting { display: grid; gap: 12px; }
.setting h2 { font-size: 1.35rem; font-variation-settings: 'INFM' 80; }
.setting p { color: #48517E; margin: 0; }
/* The Learning log: a plain notebook table on a light sticky (ink from --sticky-ink, so the night themes keep 4.5:1). */
.learning-log { grid-template-columns: minmax(0, 1fr); }   /* the table is wider than a phone: the box scrolls inside, never the page */
.learning-log > * { min-width: 0; }
.log-wrap { max-width: 100%; overflow-x: auto; }
.log-table { border-collapse: collapse; width: 100%; font-size: 0.9rem; line-height: 1.3; color: var(--sticky-ink); }
.log-table th, .log-table td { border: 1.5px solid var(--sticky-ink); padding: 5px 7px; text-align: right; vertical-align: bottom; font-weight: 500; }
.log-table thead th { font-weight: 700; background: rgba(255, 255, 255, 0.55); }
.log-table th, .log-table td { padding: 5px 4px; }
.log-table thead .log-week span { display: block; }   /* "9" over "Oct": a week column stays narrow */
.log-table thead .log-week { text-align: right; }
.log-table .log-corner, .log-table tbody th { text-align: left; }
.log-table tbody th { font-weight: 700; width: 34%; }
.theme-cards { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
.theme-card {
  display: grid; gap: 6px; padding: 10px; text-align: left;
  border: 2.5px solid #1D2452; border-radius: var(--r-card);
  background: rgba(255, 255, 255, 0.8); color: #1D2452; cursor: pointer; font-weight: 800;
}
.theme-card[aria-checked='true'] { background: #FFE45C; box-shadow: 3px 4px 0 #1D2452; }
.theme-swatch { height: 44px; border-radius: 8px; border: 2px solid #1D2452; background-size: 11px 11px; }
.helper-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.helper-row .helper-option { box-shadow: 2px 3px 0 #1D2452; }
.saying-custom { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.saying-custom .field-input { font-size: 1rem; min-height: 44px; padding: 0.2em 0.5em; color: #1D2452; background: #fff; border-color: #1D2452; }
.danger { border-top: 2px dashed #F0457A; padding-top: 14px; display: grid; gap: 10px; }

/* ---------- Toasts (new sticker, daily goal) ---------- */
.toast-layer { position: fixed; z-index: 60; left: 0; right: 0; top: 84px; display: flex; flex-direction: column; align-items: center; gap: 12px; pointer-events: none; }
.toast {
  pointer-events: auto;
  display: flex; align-items: center; gap: 16px;
  padding: 16px 24px 16px 18px;
  background: var(--sticky-yellow); color: #1D2452;
  border: 3px solid #1D2452; border-radius: var(--r-card);
  box-shadow: 5px 6px 0 #1D2452;
  cursor: pointer;
  animation: slap 0.5s cubic-bezier(.3, 1.6, .5, 1);
  max-width: min(92vw, 460px);
}
.toast.is-leaving { animation: toast-out 0.3s ease forwards; }
.toast-art {
  font-size: 3.4rem; line-height: 1; transform: rotate(-8deg);
  filter: drop-shadow(2px 0 0 #fff) drop-shadow(-2px 0 0 #fff) drop-shadow(0 2px 0 #fff) drop-shadow(0 -2px 0 #fff) drop-shadow(0 3px 4px rgba(0, 0, 0, 0.25));
}
.toast-title { font-weight: 800; font-size: 1.25rem; font-variation-settings: 'INFM' 90, 'BNCE' 50; }
.toast-text { font-size: 0.95rem; color: #48517E; }
@keyframes slap { 0% { transform: scale(2.2) rotate(-12deg); opacity: 0; } 60% { transform: scale(0.94) rotate(2deg); opacity: 1; } 100% { transform: none; } }
@keyframes toast-out { to { transform: translateY(-20px) scale(0.9); opacity: 0; } }

#confetti { position: fixed; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 70; }

/* The error card (ux-rules C8, architecture 5.20): over everything, the theme's paper a little see-through,
   one sticky note and one button. Text is the sticky's own ink; the button is the 44 px yellow one. */
.oops {
  position: fixed; inset: 0; z-index: 90;
  display: flex; align-items: center; justify-content: center;
  padding: 16px; overflow: auto;
  background: var(--paper);   /* browsers without color-mix */
  background: color-mix(in srgb, var(--paper) 94%, transparent);
}
.oops-card { width: min(360px, 100%); text-align: center; padding: 30px 22px 24px; }
.oops-card h2 { margin: 6px 0 8px; font-size: 1.5rem; line-height: 1.2; }
.oops-card p { margin: 0 0 20px; font-size: 1.15rem; font-weight: 700; color: var(--sticky-ink); }
.oops-card .btn { min-height: 44px; }

/* Page enter */
.content.is-entering { animation: page-in 0.35s ease-out; }
@keyframes page-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

/* Zooming between depths (architecture 5.17): going deeper zooms in, coming back zooms out. The
   View Transition is only started for a change of depth and never with reduced motion (core/app.js). */
::view-transition { pointer-events: none; }   /* the pseudo-elements must never swallow a tap */
@keyframes zoom-in-old { from { transform: scale(1); opacity: 1; } to { transform: scale(1.12); opacity: 0; } }
@keyframes zoom-in-new { from { transform: scale(0.92); opacity: 0; } to { transform: scale(1); opacity: 1; } }
@keyframes zoom-out-old { from { transform: scale(1); opacity: 1; } to { transform: scale(0.92); opacity: 0; } }
@keyframes zoom-out-new { from { transform: scale(1.12); opacity: 0; } to { transform: scale(1); opacity: 1; } }
html[data-zoom]::view-transition-group(root) { animation-duration: 0.35s; }
html[data-zoom='in']::view-transition-old(root) { animation: zoom-in-old 0.35s ease-out both; }
html[data-zoom='in']::view-transition-new(root) { animation: zoom-in-new 0.35s ease-out both; }
html[data-zoom='out']::view-transition-old(root) { animation: zoom-out-old 0.35s ease-out both; }
html[data-zoom='out']::view-transition-new(root) { animation: zoom-out-new 0.35s ease-out both; }

/* Short windows (small laptops): tighter chrome so the board keeps its room */
@media (max-height: 820px) {
  .cycle-dot { width: 42px; height: 42px; font-size: 1.3rem; }
  .cycle-name { display: none; }
  .cycle { padding-bottom: 22px; }
  .monster-card { display: grid; grid-template-columns: 96px 1fr; justify-items: start; column-gap: 12px; padding: 10px 12px; }
  .monster { width: 96px; height: 90px; grid-row: 1 / 4; }
  .monster-name { font-size: 1.1rem; }
  .monster-taunt { display: none; }
  .key { height: 52px; }
  .answer-box { min-height: 58px; font-size: 2rem; }
  .answer-cell { width: 52px; height: 52px; font-size: 2rem; }
  .tab { min-height: 44px; padding: 6px 12px 8px; }
  .tab[aria-current='page'] { padding-bottom: 11px; }
}

/* ---------- Tablet ---------- */
@media (max-width: 1099px) {
  :root { --margin-w: 84px; }
  .sheet::before { display: none; }
  .page {
    grid-template-columns: 84px minmax(0, 1fr);
    grid-template-areas: 'helper bubble' 'content content';
    column-gap: 18px;
    padding: 18px 22px 48px;
  }
  .helper-slot { position: static; }
  .helper { width: 84px; height: 87px; }
  .helper-name { display: none; }
  .bubble { font-size: 1.12rem; min-height: 0; }
  .bubble-tail { left: -24px; top: 20px; }
  body[data-screen='session'] .page { padding: 12px 18px 10px; row-gap: 10px; }
  .ih-cards { grid-template-columns: 1fr 1fr; }
  .settings-grid { grid-template-columns: minmax(0, 1fr); }
  .ih-cards > :first-child { grid-column: 1 / -1; }
  .session-body { grid-template-columns: minmax(0, 1fr) 290px; gap: 20px; }
}

/* ---------- Phone ---------- */
@media (max-width: 719px) {
  body { font-size: 17px; }
  .topbar { padding: 6px 10px; gap: 6px; }
  .topbar-title { font-size: 1.12rem; }
  .topbar-tools { gap: 4px; }   /* five 44 px buttons now share the bar: the title ellipsizes, the buttons stay */
  .icon-btn { width: 44px; height: 44px; }
  .stars-pill { height: 44px; padding: 0 10px 0 8px; font-size: 1.02rem; }
  .topbar .goal, .topbar .hide-phone { display: none; }
  .page { grid-template-columns: 62px minmax(0, 1fr); padding: 14px 14px 40px; column-gap: 14px; row-gap: 14px; }
  .helper { width: 62px; height: 64px; padding: 4px 3px 2px; border: 2.5px solid var(--ink); border-radius: 50%; background: var(--paper-raised); box-shadow: 2px 3px 0 var(--btn-shadow); }
  .bubble { padding: 12px 14px; font-size: 1.02rem; border-radius: 22px 16px 20px 14px / 16px 22px 14px 20px; }
  .bubble-tail { top: 16px; }
  .bubble.has-read { padding-right: 60px; }
  .bubble .read-btn { top: 8px; right: 8px; width: 44px; height: 44px; }
  body[data-screen='session'] .bubble-slot,
  body[data-screen='story'] .bubble-slot { top: 66px; }
  body[data-screen='session'] .helper-slot { position: sticky; top: 66px; z-index: 12; }
  .screen-title { font-size: 2rem; }
  .ih-cards { grid-template-columns: 1fr; gap: 30px; }
  :root { --topbar-h: 58px; }
  body[data-screen='session'] .page { padding: 8px 10px 6px; row-gap: 6px; column-gap: 10px; }
  /* Decision 0021: on a phone the board keeps a floor (core/modes.js raises it to what the step needs); a step taller than the window scrolls down to the keypad. */
  body[data-screen='session'] .page { height: auto; min-height: calc(100dvh - var(--topbar-h)); overflow-x: clip; overflow-y: visible; }
  .board-slot { min-height: 180px; }
  body[data-screen='session'] .helper-slot { position: static; }
  body[data-screen='session'] .helper { width: 52px; height: 54px; }
  body[data-screen='session'] .bubble { font-size: 0.98rem; padding: 10px 54px 10px 12px; min-height: 52px; }
  body[data-screen='session'] .bubble .read-btn { width: 44px; height: 44px; top: 4px; right: 4px; }
  .session-head-right { display: none; }
  .tabs { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; padding-top: 6px; max-width: 100%; }
  .tabs::-webkit-scrollbar { display: none; }
  .session-head { flex-wrap: nowrap; }
  .tab { min-height: 36px; padding: 4px 9px 6px; font-size: 0.88rem; transform: translateY(5px); white-space: nowrap; }
  .tab[aria-current='page'] { padding-bottom: 9px; font-size: 0.92rem; }
  .session-body { display: flex; flex-direction: column; gap: 6px; padding-top: 6px; }
  .session-problemline { display: none; }
  .cycle-slot { display: none; }
  .session-main { flex: 1; min-height: 0; }
  .session-side { flex: none; overflow: visible; padding: 0; gap: 8px; }
  .controls { gap: 6px; }
  .answer { gap: 8px; }
  .answer-box { min-height: 52px; font-size: 1.8rem; }
  .answer-cells { padding: 5px; gap: 5px; }
  .answer-cell { width: 44px; height: 44px; font-size: 1.6rem; }
  .keypad { gap: 6px; }
  .key { height: 42px; font-size: 1.35rem; box-shadow: 0 3px 0 var(--btn-shadow); }
  .key .icon { width: 22px; height: 22px; }
  .assist .btn { flex: 1 1 auto; min-height: 44px; font-size: 0.88rem; white-space: nowrap; padding-inline: 10px; }   /* Show me (no win) stays on one line */
  .learn-buttons .btn { min-height: 44px; }
  .monster-card { display: flex; align-items: center; gap: 10px; padding: 6px 10px; }
  .monster { width: 60px; height: 56px; }
  .monster-name { font-size: 0.95rem; }
  .monster-taunt { display: none; }
  .hearts { gap: 3px; }
  .heart { width: 16px; height: 16px; }
  .aside-slot .ladder { padding: 10px 12px; }
  .tab { padding: 6px 10px 8px; min-height: 44px; font-size: 0.95rem; }
  .tab .icon { display: none; }
  .tab[aria-current='page'] { font-size: 1rem; padding-bottom: 12px; }
  .session-head-right { width: 100%; justify-content: space-between; padding-bottom: 6px; }
  .key { height: 56px; }
  .answer-cell { width: 54px; height: 54px; font-size: 2rem; }
  .cycle-dot { width: 42px; height: 42px; font-size: 1.3rem; }
  .cycle-step { min-width: 52px; }
  .cycle-step + .cycle-step::before { top: 19px; }
  .cycle-name { display: none; }
  .helper-options, .helper-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cover { padding: 34px 38px 30px 16px; }
  /* Three ages side by side do not fit a phone: one per row, the age on the left. */
  .age-chips { grid-template-columns: 1fr; }
  .age-chip { grid-template-columns: 6.4em 1fr; justify-items: start; text-align: left; column-gap: 10px; padding: 8px 12px; }
  .age-chip-label { grid-row: span 2; align-self: center; justify-self: start; white-space: nowrap; font-size: 1.2rem; }
  .age-chip[aria-checked='true'] { transform: translateY(-2px) rotate(-1deg); }
  .cover-band { right: 14px; width: 14px; }
  .cover-label { padding: 22px 16px 20px; }
  .name-input { font-size: 1.5rem; }
  .theme-cards { grid-template-columns: 1fr 1fr; }
  .saying-custom { grid-template-columns: 1fr 1fr; }
  .stop-badge { width: 70px; height: 70px; font-size: 1.9rem; }
  .spot-art { width: 100px; height: 88px; }
  .spot-art svg { width: 78px; height: 70px; }
  .sticker-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .frames { grid-template-columns: 1fr; }
  .toast-layer { top: 70px; }
  /* Cards at the end of a problem or a fight, and the Boss rules, sit flat and compact on a phone, so the
     stage never scrolls past the window; a hint card squeezes the keypad a little so Show me stays in reach. */
  .finish, .boss-rules { transform: none; }
  .choice-row:not(.choice-row--many) .btn:not(.choice-check) { font-size: 1.3rem; }
  .choice-row .btn.choice-check { font-size: 1.2rem; }
  .finish { padding: 16px 14px 12px; gap: 6px; }
  .finish-title { font-size: 1.7rem; line-height: 1.1; }
  .finish-eq { font-size: 1.4rem; }
  .finish-star .icon { width: 44px; height: 44px; }
  .finish-heart { width: 40px; height: 40px; }
  .finish-actions { gap: 8px; margin-top: 4px; }
  .session.has-aside .key { height: 44px; }
  .session.has-aside .board-slot { min-height: 130px; }
}

/* ---------- Phone landscape: the board left, the keypad right, chrome kept tiny ---------- */
@media (max-height: 520px) and (orientation: landscape) {
  :root { --topbar-h: 48px; }
  .topbar { padding: 4px 10px; }
  /* Under 44 px on purpose here: ux-rules E2's phone-landscape exception. */
  .icon-btn, .stars-pill { height: 40px; }
  .icon-btn { width: 40px; }
  body[data-screen='session'] .page { grid-template-columns: minmax(0, 1fr); grid-template-areas: 'bubble' 'content'; padding: 6px 12px 6px; row-gap: 6px; }
  body[data-screen='session'] .helper-slot { display: none; }
  body[data-screen='session'] .bubble { padding: 6px 48px 6px 14px; font-size: 0.98rem; min-height: 0; border-radius: 14px; }
  body[data-screen='session'] .bubble-tail { display: none; }
  body[data-screen='session'] .bubble .read-btn { top: 4px; right: 6px; width: 34px; height: 34px; }
  .session-head { gap: 4px 10px; }
  .tab { min-height: 34px; padding: 3px 10px 5px; font-size: 0.85rem; transform: translateY(5px); }
  .tab[aria-current='page'] { padding-bottom: 8px; font-size: 0.9rem; }
  .session-head-right { padding-bottom: 4px; }
  .session-wins { font-size: 0.8rem; }
  body[data-screen='session'] .btn--small { min-height: 32px; font-size: 0.85rem; padding: 0.2em 0.7em; }
  .session-body { display: grid; grid-template-columns: minmax(0, 1fr) 250px; grid-template-rows: minmax(0, 1fr); gap: 0 14px; padding-top: 6px; }
  .session-main { gap: 2px; }
  .session-problemline { gap: 2px 10px; }
  .session-problem { font-size: 1.1rem; }
  .session-level { display: none; }
  .cycle-slot { display: none; }
  .session-side { overflow-y: auto; gap: 6px; padding: 2px; }
  .answer { gap: 6px; }
  .answer-box { min-height: 40px; font-size: 1.4rem; }
  .answer-cells { padding: 4px; gap: 4px; }
  .answer-cell { width: 34px; height: 34px; font-size: 1.3rem; }
  .keypad { gap: 4px; }
  .key { height: 30px; font-size: 1.05rem; box-shadow: 0 2px 0 var(--btn-shadow); }
  .key .icon { width: 16px; height: 16px; }
  .assist .btn { min-height: 28px; font-size: 0.78rem; }
  body[data-screen='session'] .btn.btn--go { min-height: 34px; font-size: 0.9rem; }
  .controls { gap: 5px; }
  .session-problemline .monster-slot { flex: 1; display: flex; justify-content: flex-end; }
  .monster-card { display: flex; align-items: center; gap: 8px; padding: 2px 10px; transform: none; }
  .monster-card .tape { display: none; }
  .monster { width: 44px; height: 40px; }
  .monster-name { font-size: 0.85rem; }
  .monster-taunt { display: none; }
  .hearts { gap: 2px; }
  .heart { width: 13px; height: 13px; }
  .gb-board { padding: 6px 4px 4px; }
  .boss-rules { gap: 3px; padding: 6px 10px 6px; transform: none; }
  .boss-rules .tape { display: none; }
  .boss-rules-title { font-size: 0.95rem; }
  .boss-rules-list { gap: 0; padding-left: 16px; font-size: 0.8rem; line-height: 1.2; }
  .boss-rules .btn { min-height: 34px; font-size: 0.9rem; }
}

/* ---------- The stage (decision 0019, ux-rules F4): tablets and laptops, never scrolls ----------
   html[data-stage] is set by MA.stage.watch() while the window is at least 720 px wide and 521 px
   tall. The sheet is the window, the page takes what the top bar leaves, #view takes what is left of
   the page, and a screen fills #view. Overflow is fixed on the screen, never hidden here: a clip on
   these boxes would fool the stage check (tests/browser/stage.spec.mjs). Phones get no rules here. */
html[data-stage] .sheet {
  height: 100vh; height: 100dvh;
  min-height: 0;
  margin: 0 auto; /* no vertical margin, but keep the sheet centred past its max-width */
  border-radius: 0;
  display: flex; flex-direction: column;
}
html[data-stage] .page {
  flex: 1 1 auto;
  min-height: 0;
  grid-template-rows: auto minmax(0, 1fr);
  padding-bottom: 16px;
}
html[data-stage] #view { display: flex; flex-direction: column; min-height: 0; }
/* A play screen already filled the page (decision 0007); on the stage the page's own flex does it. */
html[data-stage] body[data-screen='session'] .page { flex: 1 1 auto; height: auto; padding-bottom: 10px; overflow: visible; }
html[data-stage] body[data-screen='session'] .content { overflow: visible; }

/* Pages (MA.pager, ux-rules F5): a screen's body sits in a frame that takes what the head leaves; what
   does not fit goes on the next page. The pager only hides with the hidden attribute, so the item
   classes' own display must not win. The bar exists only while the stage is on and holds 2+ pages. */
.stage-frame [hidden], .pager[hidden] { display: none !important; }
.pager {
  flex: none;
  display: flex; align-items: center; justify-content: center; gap: 16px;
  padding: 10px 0 0;
}
.pager .btn { min-height: 48px; min-width: 48px; }
.pager-status { margin: 0; min-width: 9ch; text-align: center; font-weight: 800; font-variation-settings: 'INFM' 70; color: var(--ink); }
.pager-status:focus { outline: none; }
h2[tabindex='-1']:focus { outline: none; }
html[data-stage] .stage-frame { flex: 1 1 0; min-height: 0; }
html[data-stage] .stage-frame .section-title { margin: 16px 0 10px; }
html[data-stage] .stage-frame .section-title:first-child { margin-top: 0; }
/* Settings: the two columns melt away so the sections flow as items of the two-column grid, a page at a time. */
html[data-stage] .settings-col { display: contents; }
html[data-stage] .settings-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px 26px; }
@media (max-width: 899px) { html[data-stage] .settings-grid { grid-template-columns: minmax(0, 1fr); } }   /* an upright tablet: the age chips need the width */
/* The cover: the welcome and the name left, the fieldsets right; the band's stripe keeps clear of both. */
html[data-stage] body.is-cover .page { grid-template-rows: minmax(0, 1fr); }   /* the one row is the cover's */
/* align-items: start with auto margins on the cover: it centres when there is room, and overflows
   downwards only (never above the frame, where the pager's measuring could not see it). */
html[data-stage] .cover-wrap { min-height: 0; padding: 6px 0 10px; align-items: start; }
html[data-stage] .cover-wrap .cover { margin-block: auto; }
html[data-stage] .cover {
  width: min(980px, 100%);
  display: grid; grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); gap: 14px 28px; align-items: center;
  padding: 28px 76px 26px 30px;
  animation-name: cover-in-stage;   /* a slide would count as overflow while the pager measures */
}
html[data-stage] .cover-label { grid-column: 1; grid-row: 1 / span 2; }
html[data-stage] .cover .picker-cards { grid-column: 2; margin: 0; }
html[data-stage] .cover .logo { font-size: clamp(2.2rem, 4.6vw, 3.4rem); }
html[data-stage] .cover .helper-pick { grid-column: 2; margin: 0; }
html[data-stage] .cover-open { grid-column: 1 / -1; margin-top: 4px; }
/* An upright tablet is tall rather than wide: one column, and the pager if even that is too much. */
@media (max-width: 899px) {
  html[data-stage] .cover { grid-template-columns: minmax(0, 1fr); }
  html[data-stage] .cover-label, html[data-stage] .cover .helper-pick, html[data-stage] .cover .picker-cards { grid-column: 1; grid-row: auto; }
  html[data-stage] .cover .logo { font-size: 3.4rem; }
}
@keyframes cover-in-stage { from { opacity: 0; } to { opacity: 1; } }
/* The journal's pages are compact on the stage, so a page holds more and a whole section fits one. */
html[data-stage] body[data-screen='stickers'] .screen-head,
html[data-stage] body[data-screen='museum'] .screen-head,
html[data-stage] body[data-screen='settings'] .screen-head,
html[data-stage] .shelf-screen .screen-head { margin-bottom: 8px; gap: 4px 24px; }
html[data-stage] body[data-screen='stickers'] .screen-title,
html[data-stage] body[data-screen='museum'] .screen-title,
html[data-stage] body[data-screen='settings'] .screen-title,
html[data-stage] .shelf-screen .screen-title { font-size: 2.3rem; }
html[data-stage] .screen-head .lead { margin-top: 2px; font-size: 1rem; }
html[data-stage] .stage-frame .sticky.setting { gap: 6px; padding: 12px 18px 12px; }
html[data-stage] .stage-frame .sticky.setting .setting { gap: 3px; }   /* a panel's own body (reading, island) */
html[data-stage] .stage-frame .sticky.setting p { line-height: 1.3; }
html[data-stage] .stage-frame .setting--wide { grid-column: 1 / -1; --tilt: 0.15deg; }   /* a wide note's tilt would add a strip of overflow */   /* the reading panel's voice chips need the width */
html[data-stage] .stage-frame .setting .field-input { min-height: 44px; }
html[data-stage] .stage-frame .age-chip { padding: 6px 6px 5px; }
html[data-stage] .stage-frame .helper-row .helper-option { padding: 6px 4px 5px; }
html[data-stage] .stage-frame .helper-row .helper-option svg { max-width: 56px; }
html[data-stage] .stage-frame .sticker-grid { gap: 14px; }
html[data-stage] .stage-frame .sticker-art { width: 84px; height: 84px; font-size: 3.2rem; }
html[data-stage] .stage-frame .frames { gap: 22px 20px; }
html[data-stage] .stage-frame .frame { padding: 12px; }
/* The shelf: its heading and the footer stay put, the books are the frame. */
html[data-stage] .shelf-screen { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; gap: 14px; }

/* The world map is a stage: the map takes what the cards under it leave, and keeps its proportions
   (the width is set from the height in core/screens.js map(); islands are placed in percentages). */
html[data-stage] .map-screen { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; gap: 14px; }
html[data-stage] .map-screen .region { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; gap: 8px; }
html[data-stage] .map { flex: 1 1 0; min-height: 0; max-height: none; align-self: center; }
html[data-stage] .map-foot { flex: none; }
/* A landscape stage with one region: the map is the whole stage (the box .painted covers, the .page), and
   the bubble, the helper, the daily note and the buttons float over it (ux-rules M10, architecture 5.19).
   core/screens.js map() sets data-layout='stage' and lays the islands out around those four boxes. */
html[data-stage] .map[data-layout='stage'] {
  position: absolute; inset: 0; width: auto; max-height: none; min-height: 0;
  align-self: stretch; justify-self: stretch;   /* the rule above centres it: an absolute box would then shrink to its (empty) content */
  border-width: 0; border-radius: 0; box-shadow: none; z-index: 1;
}
html[data-stage] .map-screen .region:has(> .map[data-layout='stage']) { position: static; }   /* the sea rule would make it the map's containing block */
html[data-stage] .page:has(.map[data-layout='stage']) :is(.helper-slot, .bubble-slot) { z-index: 2; }   /* a grid item takes a z-index while static, so the helper's sticky stays */
html[data-stage] .page:has(.map[data-layout='stage']) .bubble-slot { position: relative; }
html[data-stage] .map-screen:has(.map[data-layout='stage']) > .map-foot { position: relative; z-index: 2; margin-top: auto; }
.map[data-layout='stage'] .isle-name { font-size: var(--isle-font, 1.05rem); }
.map[data-layout='stage'] .isle-pin { font-size: calc(var(--isle-font, 1.05rem) * 0.85); }

/* Island and spot pages: head, the place window, then one frame holding the cards and the trail section,
   paged by MA.pager. On a phone the two wrappers melt away, so the page is what it was. The window is
   the scene's gap (the head sits above it); what the frame has left is small, so the head, the cards and
   the stops are all compact here, and what still does not fit goes on the next page. */
.island-frame, .trail-section { display: contents; }
html[data-stage] body[data-screen='island'] .page { padding-top: 10px; row-gap: 8px; padding-bottom: 10px; }
html[data-stage] .island-home { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; gap: 6px; }
html[data-stage] .island-home > .screen-head, html[data-stage] .island-home > .place-window { flex: none; }
html[data-stage] body[data-place='scene'] .place-window { height: clamp(120px, 26dvh, 300px); }
html[data-stage] .island-home .screen-head { margin-bottom: 0; gap: 0 24px; }
html[data-stage] .island-home .screen-title { font-size: 2rem; line-height: 1.15; }
html[data-stage] .island-home .screen-title .squiggle { display: none; }
html[data-stage] .island-home .lead { max-width: 90ch; margin-top: 2px; font-size: 0.98rem; line-height: 1.3; }
html[data-stage] body[data-place='scene'] .island-home .screen-head > div { padding: 6px 18px 8px; }
html[data-stage] .island-frame { display: grid; gap: 4px; align-content: start; }
html[data-stage] .trail-section { display: grid; gap: 0; }
/* The cards: as many in a row as fit; a card alone is as wide as the frame. */
html[data-stage] .island-frame .ih-cards { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); margin-top: 8px; gap: 16px 20px; }
html[data-stage] .island-frame .ih-cards > :first-child { grid-column: auto; }
html[data-stage] .island-frame .ih-cards:empty { display: none; }
html[data-stage] .island-frame .ih-card { padding: 12px 18px 14px; }
html[data-stage] .island-frame .ih-card h2 { font-size: 1.25rem; margin-bottom: 4px; }
html[data-stage] .island-frame .ih-card p { line-height: 1.3; }
html[data-stage] .island-frame .ih-card .btn-row { gap: 10px; }
html[data-stage] .island-frame .sticky .read-btn { top: 8px; right: 10px; }
html[data-stage] .island-frame .ih-card h2, html[data-stage] .island-frame .ih-card h2 + p { padding-right: 44px; }   /* the read-aloud button sits over the card's top right corner */
/* The trail: one compact row of stops at a time. */
html[data-stage] .island-frame .section-title { margin: 0; padding: 4px 16px 4px 12px; font-size: 1.3rem; }
html[data-stage] body[data-place='scene'] .island-frame .section-title { margin-top: 8px; }
html[data-stage] .island-home .pager { padding-top: 6px; }
html[data-stage] .island-frame .trail { margin-top: 0; padding: 6px 0 14px; }   /* room for the stops' wobble: 12 px down, 4 up (see snake) */
html[data-stage] .island-frame .trail-list { gap: 10px 14px; }
html[data-stage] .island-frame .stop-btn { gap: 2px; padding: 2px 4px; }
html[data-stage] .island-frame .stop-badge { width: 58px; height: 58px; font-size: 1.7rem; border-width: 2.5px; }
html[data-stage] .island-frame .stop-badge .icon { width: 26px; height: 26px; }
html[data-stage] .island-frame .stop-crown { top: -16px; right: -12px; font-size: 1.4rem; }
html[data-stage] .island-frame .stop-name { font-size: 1.05rem; margin-top: 2px; line-height: 1.15; }
html[data-stage] .island-frame .stop-blurb { font-size: 0.82rem; line-height: 1.15; }
html[data-stage] .island-frame .stop-wins { margin-top: 2px; }
html[data-stage] .island-frame .spot-art { width: 84px; height: 72px; border-width: 2.5px; }
html[data-stage] .island-frame .spot-art svg { width: 66px; height: 58px; }
html[data-stage] .island-frame .spot-flag { bottom: -12px; font-size: 0.78rem; }
html[data-stage] .island-frame .museum-link { margin-top: 0; }

/* Painted scenes (decision 0019, architecture §5.18): on the stage an island with a painting is the
   picture itself, edge to edge under the top bar, with a link on every spot (a button on every level
   inside a spot). The cards wait in a card the helper opens. A phone keeps the page above: the painted
   parts are hidden there, and on the stage the page's own head, window, frame and pager are. */
.painted, .painted-more, .painted-peek { display: none; }
html[data-stage] body[data-painted] .sheet { max-width: none; }   /* the picture goes edge to edge on a wide screen */
html[data-stage] body[data-painted] .painted { display: block; position: absolute; inset: 0; z-index: 0; overflow: hidden; }
html[data-stage] body[data-painted] .painted-more { display: inline-flex; position: absolute; right: 18px; bottom: 16px; z-index: 3; }
html[data-stage] body[data-painted] .painted-peek { display: inline-flex; position: absolute; left: 18px; bottom: 16px; z-index: 3; }   /* the mirror of "Story and tips" (decision 0028) */
html[data-stage] body[data-painted] .place,
html[data-stage] body[data-painted] .island-home > .place-window,
html[data-stage] body[data-painted] .island-home > .stage-frame,
html[data-stage] body[data-painted] .island-home .pager { display: none; }
html[data-stage] body[data-painted] .island-home > .screen-head { position: absolute; width: 1px; height: 1px; margin: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
html[data-stage] body[data-painted] .helper-slot { z-index: 2; }
html[data-stage] body[data-painted] .bubble-slot { position: relative; z-index: 2; justify-self: start; max-width: min(640px, 62%); }   /* the picture's top right stays clear */
/* A bubble with a button (the route tip) keeps it beside the words, so the bubble stays short and the picture keeps its room. */
html[data-stage] body[data-painted] .bubble:has(.bubble-extra:not(:empty)) { display: flex; flex-wrap: wrap; align-items: center; column-gap: 16px; }
html[data-stage] body[data-painted] .bubble:has(.bubble-extra:not(:empty)) .bubble-text { flex: 1 1 260px; }
html[data-stage] body[data-painted] .bubble-extra { margin-top: 0; }
/* A folded bubble keeps its box (so what it covers is still known) but is hidden from the eye, the reader and the finger; the helper shows a speech dot. */
.bubble-slot.is-folded .bubble { visibility: hidden; }
.bubble-slot.is-folded { pointer-events: none; }   /* the empty box must not catch a tap meant for the spot under it */
.helper-dot { position: absolute; right: -10px; top: 4px; width: 34px; height: 28px; pointer-events: none; }
.helper-dot[hidden] { display: none; }
.helper-dot svg { display: block; width: 100%; height: 100%; }
@media (max-width: 1099px) { html[data-stage] body[data-painted] .helper-slot { position: relative; } }
/* The page-in lift would move the picture's box for a moment (a transform holds absolute children). */
html[data-stage] body[data-painted] .content.is-entering { animation-name: painted-in; }
@keyframes painted-in { from { opacity: 0; } to { opacity: 1; } }
/* On the world map the island is its painting, soft at the edges like a vignette on the paper. */
.isle-photo {
  display: block; width: 100%; aspect-ratio: 220 / 150;
  object-fit: cover;
  -webkit-mask-image: radial-gradient(ellipse 50% 50% at 50% 50%, #000 58%, transparent 100%);
  mask-image: radial-gradient(ellipse 50% 50% at 50% 50%, #000 58%, transparent 100%);
  -webkit-user-drag: none; user-select: none;
}
:root[data-theme='blueprint'] .isle-photo, :root[data-theme='chalk'] .isle-photo { filter: brightness(0.82) saturate(0.9); }
/* Going in, the map's painting grows into the island page's (a View Transition, architecture 5.17). */
html[data-zoom]::view-transition-group(*.painted) { animation-duration: 0.45s; animation-timing-function: cubic-bezier(.3, .7, .3, 1); }
.painted-art { position: absolute; }
.painted-art svg { display: block; width: 100%; height: 100%; }
.painted-wake.is-fresh { opacity: 0; transition: opacity 2.2s ease; }
.painted-wake.is-fresh.is-in { opacity: 1; }
/* The colour peek (decision 0028): a veil of the awake copy over the whole picture; a mask rect slides right and the pencil comes back from the left. */
.painted-art .painted-peek-veil { position: absolute; left: 0; top: 0; width: 100%; height: 100%; pointer-events: none; }
.painted-peek-sweep { transition: transform 0.8s cubic-bezier(.45, .05, .55, .95); }
.painted-peek-veil.is-sweeping .painted-peek-sweep { transform: translateX(2700px); }
.painted-night { position: absolute; inset: 0; pointer-events: none; }
:root[data-theme='blueprint'] .painted-night,
:root[data-theme='chalk'] .painted-night { background: rgba(16, 26, 70, 0.42); mix-blend-mode: multiply; }
.painted-safe { position: absolute; --safe-h: 600px; }

/* A spot or a level on the picture: the button is its drawing (an invisible box), the paper tag its name. */
.hotspot {
  position: absolute;
  display: block;
  padding: 0; margin: 0; border: 0; background: none;
  color: var(--ink); text-decoration: none;
  border-radius: 18px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.hotspot::before { content: ''; position: absolute; inset: 0; border-radius: inherit; border: 3px dashed transparent; transition: border-color 0.15s, background-color 0.15s; }
.hotspot:hover::before { border-color: rgba(255, 255, 255, 0.95); background: rgba(255, 255, 255, 0.12); }
.hotspot:focus { outline: none; }
.hotspot:focus-visible::before { border-color: var(--ink); background: rgba(255, 255, 255, 0.18); box-shadow: 0 0 0 3px #fff; }
.hotspot-tag {
  position: absolute;
  transform: translate(-50%, -50%) rotate(-2deg);
  display: inline-flex; align-items: center; gap: 0.35em;
  padding: 0.18em 0.7em 0.22em;
  font-size: clamp(0.82rem, calc(var(--safe-h) * 0.026), 1.3rem);
  font-weight: 800; line-height: 1.15; white-space: nowrap;
  font-variation-settings: 'INFM' 70;
  color: #2B2B3A;
  background: #FFFDF6;
  border: 2.5px solid #2B2B3A;
  border-radius: 10px 14px 9px 13px / 12px 9px 14px 10px;
  box-shadow: 2px 3px 0 rgba(43, 43, 58, 0.45);
  transition: transform 0.15s ease;
}
/* A tag sits above every spot's invisible box, and the spot being pointed at comes to the front, so a tap on a tag goes to its own place. */
.painted-safe .hotspot-tag { z-index: 1; }
.painted-safe .hotspot:is(:hover, :focus-visible, :active) .hotspot-tag { z-index: 2; }
/* The separation pass (painted.js) wraps a tag onto two lines when that is what keeps it clear of its neighbour. */
.hotspot-tag.hotspot-tag--wrap { white-space: normal; width: max-content; max-width: 100%; text-align: center; justify-content: center; }
.hotspot:nth-child(even) .hotspot-tag { transform: translate(-50%, -50%) rotate(2deg); }
.hotspot:hover .hotspot-tag, .hotspot:focus-visible .hotspot-tag { transform: translate(-50%, -50%) rotate(0) scale(1.08); }
/* While the tags are measured (painted.js), each is at rest: no hover growth, no transition caught halfway. */
.painted-safe.is-measuring .hotspot .hotspot-tag { transition: none; transform: translate(-50%, -50%) rotate(-2deg); }
.painted-safe.is-measuring .hotspot:nth-child(even) .hotspot-tag { transform: translate(-50%, -50%) rotate(2deg); }
.hotspot.is-done .hotspot-tag { background: #FFF3B8; }
.hotspot.is-here .hotspot-tag, .hotspot.is-current .hotspot-tag { background: #FFE45C; }
.hotspot.is-locked .hotspot-tag { color: #5D5D6C; background: #ECEAE2; border-style: dashed; box-shadow: none; }
.hotspot-crown { font-size: 1.1em; line-height: 1; }
.hotspot-badge {
  display: inline-grid; place-items: center;
  min-width: 1.6em; height: 1.6em; padding: 0 0.2em;
  border: 2px solid currentColor; border-radius: 50%;
  background: #fff; font-size: 0.95em;
}
.hotspot-badge .icon { width: 0.95em; height: 0.95em; }
.hotspot-flag {
  position: absolute; left: 50%; bottom: calc(100% + 4px);
  transform: translateX(-50%) rotate(3deg);
  padding: 0.1em 0.6em;
  font-size: 0.85em; white-space: nowrap;
  background: #FFC9DE; color: #2B2B3A; font-weight: 800;
  border: 2px solid #2B2B3A; border-radius: 8px;
}

/* The card a painted page keeps its words in: a sticky note over the picture. */
dialog.painted-card {
  width: min(760px, calc(100vw - 48px));
  max-height: calc(100dvh - 48px);
  overflow: auto;
  padding: 22px 26px 18px;
  border: 0;
  box-shadow: 0 2px 0 rgba(0, 0, 0, 0.06), 4px 18px 30px -10px rgba(0, 0, 0, 0.55);
}
dialog.painted-card::backdrop { background: rgba(20, 22, 44, 0.42); }
dialog.painted-card h2 { font-size: 1.7rem; margin: 0 0 4px; padding-right: 48px; }
dialog.painted-card h2:focus { outline: none; }
.painted-card-lead { margin: 0 0 12px; color: var(--sticky-ink); opacity: 0.85; }
.painted-card-body .ih-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 14px 18px; margin: 0; }
.painted-card-body .ih-card { padding: 12px 18px 14px; }
.painted-card-body .ih-card h2 { font-size: 1.2rem; padding-right: 44px; }
.painted-card-body .museum-link { margin-top: 12px; }
.painted-card-foot { justify-content: flex-end; margin-top: 14px; }
dialog.painted-card .read-btn { position: absolute; top: 14px; right: 16px; }
dialog.painted-card .painted-card-body .read-btn { top: 8px; right: 10px; }

/* The story: head, the picture and board, then the Back and Next panel; the picture takes what is left. */
html[data-stage] body[data-screen='story'] .screen-head { margin-bottom: 6px; gap: 4px 24px; }
html[data-stage] body[data-screen='story'] .screen-title { font-size: 2.3rem; }
html[data-stage] body[data-screen='story'] .screen-head .lead { margin-top: 2px; font-size: 1rem; }

/* A Boss session's side column (decision 0019): nothing scrolls, so the monster is a single row with a
   picture of 80px at most and the gaps are tight. The keys stay 44px or more (ux-rules E2) and only the Boss shrinks them: the young band's 64px targets (ux-rules L2) stay in Learn and Practice; the phone
   landscape keypad (decision 0017) is outside the stage and keeps its own rules. */
html[data-stage] .session-side { overflow: visible; gap: 8px; padding: 2px 6px 4px 2px; }
html[data-stage] .monster-card { grid-template-columns: 80px minmax(0, 1fr); grid-template-rows: auto auto; align-content: center; justify-items: start; column-gap: 12px; row-gap: 2px; padding: 8px 12px; }
html[data-stage] .monster-card .tape { display: none; }
html[data-stage] .monster { width: 80px; height: 75px; grid-row: 1 / 3; }
html[data-stage] .monster-name { font-size: 1.1rem; align-self: end; }
html[data-stage] .monster-card .hearts { justify-content: flex-start; align-self: start; }
html[data-stage] .monster-taunt { display: none; }
html[data-stage] .controls { gap: 8px; }
html[data-stage] .keypad { gap: 8px; }
html[data-stage] .session--boss .key { height: 48px; }
html[data-stage] .answer-box { min-height: 52px; }
/* Long and text answers keep their own smaller cells (above), so they still fit the side column. */
html[data-stage] .session--boss .answer-cells:not(.answer-cells--long):not(.answer-cells--text) .answer-cell { width: 48px; height: 48px; }

/* The "turn me sideways" card over a picture screen held upright (MA.stage.askToTurn) */
.turn-card {
  grid-area: content;
  position: relative; z-index: 5;
  min-height: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
  padding: 24px 28px;
  text-align: center;
  background: var(--paper-raised); color: var(--ink);
  border: 2.5px solid var(--ink); border-radius: var(--r-card);
  box-shadow: 3px 4px 0 var(--btn-shadow);
}
.turn-art { width: 96px; height: 96px; color: var(--ink); }
.turn-art .icon { width: 100%; height: 100%; stroke-width: 1.6; }
.turn-title { font-size: 1.9rem; }
.turn-text { max-width: 30ch; margin: 0; color: var(--ink-2); }
.turn-keep { min-height: 48px; min-width: 44px; }

/* ---------- Travel (5.19): the sky and the sea (pictures are still, decision 0027) ---------- */
/* The sky and the sea use the painted rules above (a .painted covers the whole page, like an island's); what is on them stays in front. */
html[data-stage] .sky-screen { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; }
html[data-stage] .sky-screen > .map-foot { margin-top: auto; }
html[data-stage] body[data-painted] .sky-screen > .map-foot,
html[data-stage] body[data-painted='sea'] .map-screen > :not(.painted) { position: relative; z-index: 1; }
/* While a travel runs, the map it lands on holds its islands (and a landing's boat) unseen until core/travel.js settles them in. */
html[data-travel] .map .isle-art, html[data-travel='landing'] .map .boat { opacity: 0; }
/* The other planets have faded: a tap on one only skips the travel. */
html[data-travel] .planets { pointer-events: none; }
.travel-artbox { position: absolute; pointer-events: none; }
.travel-artbox img { display: block; width: 100%; height: 100%; max-width: none; }
.painted-art img { display: block; width: 100%; height: 100%; max-width: none; -webkit-user-drag: none; user-select: none; }

/* The sea: the painting is the water, so the map's own paper sea goes (its border stays, clear, so the geometry is the same). */
html[data-stage] body[data-painted='sea'] .map { background: transparent; border-color: transparent; box-shadow: none; }
html[data-stage] body[data-painted='sea'] .map-svg .wave { display: none; }
/* An island on the sea is its land cut-out: transparent all round, so no soft edge. */
.isle-photo--land { -webkit-mask-image: none; mask-image: none; }

/* The planets: one link (or button) per world, placed by percent of the safe area. The tag is the hotspot tag's twin. */
.planets { position: absolute; inset: 0; }
.planet {
  position: absolute; display: block;
  min-width: 44px; min-height: 44px;
  padding: 0; margin: 0; border: 0; background: none;
  color: #2B2B3A; font: inherit; text-decoration: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.planet-art { display: block; width: 100%; }
.planet-art img, .planet-art svg { display: block; width: 100%; height: auto; }
.planet:hover .planet-art img, .planet:focus-visible .planet-art img { filter: brightness(1.1); }
.planet:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; border-radius: 50%; box-shadow: 0 0 0 7px #fff; }
.planet-tag {
  position: absolute; left: 50%; top: 100%;
  transform: translate(-50%, 4px);
  display: inline-flex; align-items: center; gap: 0.35em;
  padding: 0.18em 0.7em 0.22em;
  font-size: clamp(0.82rem, calc(var(--safe-h) * 0.026), 1.3rem);
  font-weight: 800; line-height: 1.15; white-space: nowrap;
  font-variation-settings: 'INFM' 70;
  color: #2B2B3A;
  background: #FFFDF6;
  border: 2.5px solid #2B2B3A;
  border-radius: 10px 14px 9px 13px / 12px 9px 14px 10px;
  box-shadow: 2px 3px 0 rgba(43, 43, 58, 0.45);
}
.planet-tag .icon { width: 1em; height: 1em; }
.planet--soon .planet-tag { flex-direction: column; gap: 0; border-style: dashed; }
.planet-tag small { font-size: 0.72em; font-weight: 700; color: #5D5D6C; }

/* The first landing's ship (core/travel.js): in the sky's ink line, over everything on it. */
.travel-ship { position: absolute; left: 0; top: 0; z-index: 5; pointer-events: none; }
.travel-ship svg { display: block; width: 100%; height: 100%; overflow: visible; }

/* The cloud copies the travel builds (core/travel.js): still, clipped to the clouds, removed when the travel ends. */
.sky-clouds { overflow: hidden; }
.sky-cloud-band { position: absolute; inset: 0; opacity: 0.55; -webkit-clip-path: inset(58% 0 0 0); clip-path: inset(58% 0 0 0); }

/* Painted screens are still (ux-rules M13): the helper neither bobs nor blinks while idle. Its reactions stay; paper screens keep both. */
html[data-stage] body[data-painted] .helper[data-mood='idle'] svg { animation: none; }
html[data-stage] body[data-painted] .helper .eyes { animation: none; }

/* ---------- Motion off ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; }
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}
