/* ============================================================================
   The child's desk: her dragon, her roads, the day's question
   (docs/engineering/CHILD_DESK.md; the brief is section 6 of
   docs/design/ONBOARDING_DESKS.md).
   ============================================================================
   Paper and ink, flat colour, one shade (docs/brand/README.md). The dragon is
   large and floats on the paper with nothing behind it: that is the brand's
   exception for the child's own dragon on her own desk. The rows are washed
   with the colour of the road's guide, taken from the sketchbook's dragons,
   so there is no colour here that is not already the brand's.

   Every state's final look is the base style. The celebration only adds
   motion on the way to it, so with reduced motion the same pictures stand
   still and nothing is missing. Nothing here is a loop that draws: a phone
   floats the dragon with a transform and that is all.
   ========================================================================== */
/* The stage reaches the screen's edge from inside the page's column, so it is a hundred viewport widths wide: nothing may scroll sideways for the few pixels a scrollbar takes. Hidden first for a browser that has no clip. */
.child-desk { overflow-x: hidden; overflow-x: clip; }
.child-desk [hidden] { display: none !important; }

/* ------------------------------------------------------------ the stage */
/* The stage clips its own sideways life: sparks and the level pill can fly a little past its edge, and they must never widen the page. */
.desk-stage { position: relative; }

/* The greeting is the masthead: the logo steps aside once her name is there to take its place, just her name said back to her. */
.child-desk .mast { min-height: 58px; }
.child-desk .mast:has(.hello:not([hidden])) .brand { display: none; }
.child-desk .mast .hello { margin: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 14px; min-width: 0; }
.child-desk .mast .hello .eye { display: none; }
.child-desk .mast .hello h1 { margin: 0; font: 500 28px / 1.2 var(--serif); text-wrap: balance; }
.child-desk .mast .hello .hello-line { margin: 0; font: 400 18px / 1.3 var(--serif); color: var(--ink-soft); }
.child-desk .mast .hello .help-line { flex-basis: 100%; font-size: 14px; }
.child-desk .mast .hello .cta-row { margin: 0; }
.child-desk .mast .hello .cta-row .tool { min-height: 36px; padding: 6px 12px; font-size: 14px; }
.child-desk .mast .hello .cta-row .btn { min-height: 36px; padding: 6px 14px; font-size: 14px; }

/* --------------------------------------------------------------- the sky */
/* One scene, the full width of the window: her tower floats at its heart, and every road is a ring of little lands circling it. The sky is the archipelago's own painting, blurred into soft cloud: the painted lands melt into weather, and the tower's shade drifts on it far below the foot, which is what makes the tower float. */
.road-desk .sky {
  position: relative;
  height: max(820px, calc(100dvh - 100px));
  max-height: 1100px;
  margin-inline: calc(50% - 50vw);
  --tower-w: min(14vw, 160px);
  --dragon-w: clamp(84px, 10vw, 128px);
  overflow: hidden;
  background: var(--paper);
}
/* The sky itself is the painted archipelago, softened past recognition into cloud banks. */
.road-desk .sky::before {
  content: ""; position: absolute; inset: -64px; z-index: 0; pointer-events: none;
  background: url("/primer/art/sky-isles.jpg") center / cover;
  filter: blur(52px) saturate(0.7) brightness(1.55);
  opacity: 0.38;
  mask-image: linear-gradient(transparent, #000 16%, #000 82%, transparent);
}
.motes { display: none; }
.road-desk .top { margin: 26px 0 0; max-width: none; display: grid; grid-template-columns: minmax(0, 1fr); gap: 24px; align-content: start; }
/* child.css caps a tile-less top at 760px through :has(#missionTile[hidden]); on her desk the stage owns the whole width, so the override must match its weight. */
.road-desk .top:has(#missionTile[hidden]) { max-width: none; }

/* ------------------------------------------------------------- the tower */
/* A voxel keep of weathered stone hung in the middle of the sky: chunky isometric courses on a floating rock, a dark doorway, windows that light one per floor she has climbed, a broken crown and a little pennant. --lv is the floors she has climbed, written by the stage (desk-stage.js), which also lights the windows (the .w paths, bottom to top). It never stands anywhere: the shade on the paper far below and the slow hover say it hangs. */
.tower { position: absolute; left: 50%; top: 37%; translate: -50% -50%; width: var(--tower-w); aspect-ratio: 200 / 520; max-height: min(84%, 600px); z-index: 5; animation: tower-drift 10s ease-in-out infinite; }
.tower-shaft { position: absolute; inset: 0; }
/* The keep is a painting, so its pale paper ground has to join the sky: multiply drops the light and keeps the shade. */
.tower-art { width: 100%; height: 100%; display: block; object-fit: contain; object-position: center 55%; }
.tb-windows { position: absolute; inset: 0; }
/* Her windows: dark slots until her climb lights them, one floor at a time. */
.tw { position: absolute; left: var(--wx); top: var(--wy); width: 8.5%; aspect-ratio: 5 / 6; translate: -50% -50%; border-radius: 46% 46% 10% 10%; background: rgba(44, 40, 30, 0.3); transition: background 0.5s ease, box-shadow 0.5s ease; }
.tw.lit { background: var(--lemon); box-shadow: 0 0 9px 2px color-mix(in srgb, var(--lemon) 78%, transparent), inset 0 0 3px #fff4cf; }
/* A warm glow at her floor, from within. */
.tower::before { content: none; }
/* The shadow it casts is nowhere near its foot: that is what says "floating". */
.tower::after { content: ""; position: absolute; left: -30%; right: -30%; bottom: -14%; height: 6%; border-radius: 50%; background: radial-gradient(closest-side, rgba(23, 58, 50, 0.2), transparent); animation: tower-shade 8s ease-in-out infinite; }
/* Ruins: chips of the tower drift off it and sink away, one after another. */
.ruin { position: absolute; width: 11px; height: 8px; border-radius: 2px; background: color-mix(in srgb, var(--ink) 42%, var(--paper)); box-shadow: 0 1px 0 rgba(23, 58, 50, 0.2); opacity: 0; animation: ruin-fall 7s ease-in infinite; }
.ruin:nth-of-type(1) { left: -18%; top: 30%; animation-delay: 0s; }
.ruin:nth-of-type(2) { right: -16%; top: 44%; width: 6px; height: 6px; animation-delay: 2.4s; animation-duration: 8.5s; }
.ruin:nth-of-type(3) { left: -12%; top: 58%; width: 7px; height: 5px; animation-delay: 4.6s; animation-duration: 6.4s; }
.ruin:nth-of-type(4) { right: -22%; top: 22%; width: 5px; height: 5px; animation-delay: 6.2s; animation-duration: 9.2s; }
/* The hover: a slow rise and fall with the gentlest tilt, the shade below swelling in answer. */
@keyframes tower-drift { 0%, 100% { transform: translateY(6px) rotate(-0.5deg); } 50% { transform: translateY(-12px) rotate(0.5deg); } }
@keyframes tower-shade { 0%, 100% { transform: scale(1.06); opacity: .85; } 50% { transform: scale(0.9); opacity: .6; } }
@keyframes ruin-fall { 0% { opacity: 0; transform: translate(0, 0) rotate(0); } 12% { opacity: 0.85; } 100% { opacity: 0; transform: translate(calc(-30% + 10%), 240px) rotate(70deg); } }

/* ----------------------------------------------------------- the dragon */
.desk-dragon {
  appearance: none; background: none; border: 0; padding: 0; margin: 0; color: inherit; font: inherit; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  position: absolute; display: block;
  left: 50%; translate: -50% 0; bottom: calc(23% + var(--lv, 0) * 5.8%);
  width: max-content;
  z-index: 1;
  /* When the level turns, the plaque climbs the tower to her new floor. */
  transition: bottom 0.9s cubic-bezier(0.3, 1.3, 0.5, 1);
}
/* Her dragon no longer stands on the tower: it is met in the welcome and seen in the level sheet, so its pose stays drawn but out of sight here. */
.desk-dragon .dragon-float, .desk-dragon .dragon-shadow { display: none; }
.desk-dragon:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; border-radius: 32px; }
.dragon-float { display: block; transform-origin: 50% 92%; animation: dragon-float 4.4s ease-in-out infinite; }
.dragon-pose { position: relative; display: block; width: 100%; aspect-ratio: var(--ratio, 1 / 1); transform-origin: 50% 90%; transition: transform 0.16s ease; }
/* It answers a touch: a little lift when the pointer is over it, a squash when it is pressed. */
.desk-dragon:hover .dragon-pose { transform: scale(1.02); }
.desk-dragon:active .dragon-pose { transform: scale(0.97, 0.95); }
.dragon-frame { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.dragon-frame.blink, .dragon-frame.cheer { opacity: 0; }
.dragon-frame.blink { animation: dragon-blink 5.8s linear infinite; }
/* Cheering is a pose, not a motion: the frame is simply shown, so reduced motion sees the same picture. */
.is-cheering .dragon-frame.cheer { opacity: 1; }
.is-cheering .dragon-frame.blink { animation: none; opacity: 0; }
/* A soft patch of ink on the paper under the feet, breathing against the float. It is the ground, not a box. */
.dragon-shadow { position: absolute; left: 24%; right: 18%; bottom: 22px; height: 20px; border-radius: 50%; background: radial-gradient(closest-side, rgba(23, 58, 50, 0.24), transparent); animation: dragon-shadow 4.4s ease-in-out infinite; pointer-events: none; }
.dragon-level {
  position: relative;
  display: inline-flex; align-items: center; gap: 8px; padding: 8px 16px 8px 11px; border-radius: 999px; white-space: nowrap;
  background: var(--paper); border: 1.5px solid color-mix(in srgb, var(--ink) 58%, var(--paper)); box-shadow: 2px 3px 0 rgba(23, 58, 50, 0.16);
  font: 600 16px/1 var(--sans); color: var(--ink); transition: box-shadow 0.2s ease, transform 0.2s ease;
}
.dragon-star { display: inline-grid; place-items: center; width: 22px; height: 22px; color: var(--accent); }
.dragon-star svg { width: 22px; height: 22px; fill: var(--lemon); }
.desk-dragon:hover .dragon-level, .desk-dragon:focus-visible .dragon-level { box-shadow: 3px 5px 0 rgba(23, 58, 50, 0.2); transform: translateY(-2px); }
.dragon-level.pop { animation: level-pop 0.8s cubic-bezier(0.3, 1.6, 0.5, 1); }
.dragon-sparks { position: absolute; left: 44%; top: 38%; width: 0; height: 0; pointer-events: none; }
.spark { position: absolute; left: -17px; top: -17px; width: 34px; height: 34px; opacity: 0; filter: drop-shadow(1px 2px 0 rgba(23, 58, 50, 0.22)); }
.spark svg { width: 100%; height: 100%; display: block; }

/* ------------------------------------------------------------- the roads */
/* One island, not a ring of them (the founder, 2026-10-08: "remove the floating
   islands other than the first one and instead put their mission roads there,
   the next mission from each of their mission roads"): her home island floats
   in the sky's front clearing, and where the other lands were, each road she
   is on is a card with its one next mission. */
.roads { position: absolute; inset: 0; }
.road-strip { position: static; list-style: none; margin: 0; padding: 0; }
.road-rows { position: absolute; z-index: 6; left: 4%; top: 120px; width: min(360px, 30%); display: grid; gap: 14px; margin: 0; padding: 0; list-style: none; }
.road-row {
  --road: #ed9ead; --road-shade: #cb748d; --road-ink: #ad5776;
  position: relative; display: grid; grid-template-columns: 56px minmax(0, 1fr); gap: 12px; align-items: start;
  padding: 14px 16px 16px; border: 1.5px solid color-mix(in srgb, var(--road-ink) 45%, transparent);
  border-radius: 20px 16px 22px 16px / 16px 22px 16px 20px;
  background: color-mix(in srgb, var(--paper) 84%, var(--road) 16%);
  box-shadow: 0 10px 24px rgba(23, 58, 50, 0.12);
}
.road-icon img { display: block; width: 56px; height: 56px; object-fit: contain; }
.road-text { display: grid; justify-items: start; min-width: 0; }
.road-name { margin: 0; font: 500 23px / 1.15 var(--serif); padding-bottom: 3px; border-bottom: 1px solid var(--road-ink); text-wrap: balance; }
.road-count { margin: 4px 0 0; font: 500 13px / 1.3 var(--sans); color: var(--ink-soft); }
/* Her last page on the road, the way back to it: a tick and its name, underlined in the road's colour. */
.road-last { display: inline-flex; align-items: center; gap: 6px; margin-top: 8px; font: 500 15px / 1.3 var(--serif); color: var(--ink-soft); text-decoration: underline; text-decoration-color: var(--road-ink); text-underline-offset: 3px; overflow-wrap: anywhere; }
.road-last:hover, .road-last:focus-visible { color: var(--ink); }
.road-last-tick { display: grid; place-items: center; width: 20px; height: 20px; flex: none; border-radius: 50%; background: var(--leaf); color: var(--paper); }
.road-last-tick svg { width: 13px; height: 13px; }
.road-next-title { margin: 10px 0 0; font: 600 19px / 1.25 var(--serif); color: var(--ink); overflow-wrap: anywhere; }
/* The road's own Play: the same pill her island wears. */
.road-row .road-go { display: inline-flex; width: auto; align-items: center; justify-content: center; gap: 8px; min-width: 96px; min-height: 48px; margin-top: 10px; padding: 10px 20px; border-radius: 999px; background: var(--ink); color: var(--paper); font: 700 15px / 1 var(--sans); text-decoration: none; position: relative; }
.road-row .road-go svg { width: 14px; height: 14px; }
.road-row .road-go:hover, .road-row .road-go:focus-visible { background: var(--oxblood); color: var(--paper); }
.road-row .road-go:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
.road-row .road-go .isle-sparks { top: 50%; }
.road-wait { display: flex; align-items: center; gap: 10px; margin: 10px 0 0; font: 500 16px / 1.3 var(--serif); color: var(--ink-soft); }
.road-wait-icon { position: relative; display: grid; place-items: center; width: 32px; height: 32px; flex: none; border: 1.5px solid var(--ink); border-radius: 50%; background: var(--paper); color: var(--ink); }
.road-wait-icon svg { width: 16px; height: 16px; display: block; }
.road-wait-icon .badge-lock, .road-wait-icon .badge-key { display: grid; place-items: center; }
.road-wait[data-icon="lock"] .badge-key { display: none; }
/* A key is a lock that has turned: the lock stays in the page, out of sight, so the turn has something to leave. */
.road-wait[data-icon="key"] .badge-lock { position: absolute; opacity: 0; }
.road-wait[data-icon="key"] .road-wait-icon { background: var(--lemon); }
/* Back from a mission: the road she finished stamps its tick, and a lock that became a key turns. */
.road-row.just-done .road-last-tick { animation: tick-stamp 0.7s cubic-bezier(0.3, 1.6, 0.5, 1) backwards; }
.road-row.just-keyed .road-wait-icon { animation: key-turn 0.9s cubic-bezier(0.3, 1.5, 0.5, 1) 0.4s backwards; }
@keyframes tick-stamp { 0% { transform: scale(0.2); } 100% { transform: scale(1); } }
@keyframes key-turn { 0% { transform: rotate(-70deg) scale(0.6); } 100% { transform: rotate(0) scale(1); } }
/* Her home island stands a little larger than a ring's land did: it is the one in front of her. */
.home-strip .isle { z-index: 6; }

.isle { position: absolute; left: var(--map-x); top: var(--map-y); translate: -50% 0; display: grid; justify-items: center; align-content: start; width: var(--isle-size); z-index: 4; pointer-events: none; }
.isle .isle-link { pointer-events: auto; }
.isle-art { position: relative; display: block; width: 100%; aspect-ratio: 1; animation: isle-bob 9s ease-in-out infinite; animation-delay: calc(var(--at) * -1.4s); }
.isle:hover .isle-art, .isle:focus-within .isle-art { animation-play-state: paused; }
/* A pool of shade on the paper under each land: the thing that makes it float. */
.isle-art::after { content: ""; position: absolute; left: 24%; right: 24%; bottom: 0; height: 5%; border-radius: 50%; background: rgba(23, 58, 50, 0.12); filter: blur(6px); pointer-events: none; }
.isle-art img, .isle-place { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.isle-art img:not(.isle-place) { filter: saturate(1.1) contrast(1.04) drop-shadow(0 8px 7px rgba(23, 58, 50, 0.15)); }
.isle-art.has-picture .isle-place { visibility: hidden; }
.isle-name { margin-top: 8px; padding-inline: 2px; font: 500 17px / 1.25 var(--serif); text-align: center; color: var(--ink); text-wrap: balance; overflow-wrap: anywhere; text-shadow: 0 1px 0 var(--paper); }

.isle[data-state="planned"] .isle-art { opacity: 0.92; filter: saturate(0.9); }
.isle[data-state="planned"] .isle-name { color: var(--ink-soft); }
.isle[data-state="next"] .isle-art { opacity: 0.95; filter: saturate(0.92); }
.isle[data-state="next"] .isle-name { color: var(--ink-soft); }

/* The picture says the state, so no badge floats over it: the strip reads as painted lands, nothing else. */
.isle-badge { display: none; }
.isle-badge svg { width: 16px; height: 16px; display: block; }
.badge-check { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.isle-badge .badge-lock, .isle-badge .badge-key { display: grid; place-items: center; }
.isle[data-badge="lock"] .badge-key { display: none; }
/* A key is a lock that has turned: the lock stays in the page, out of sight, so the turn has something to leave. */
.isle[data-badge="key"] .badge-lock { position: absolute; opacity: 0; }

/* Today's island: the one she plays. Lifted a little, lit when the question is answered. */
.isle[data-state="open"] { z-index: 6; }
.isle-link { position: relative; display: grid; justify-items: center; width: 100%; color: inherit; text-decoration: none; }
.isle-link:focus-visible { outline: 3px solid var(--accent); outline-offset: 4px; border-radius: 8px; }
.isle-lift { display: block; width: 100%; transform-origin: 50% 80%; }
.isle-burst { display: none; }
/* The day's land, named at the ring's bottom where a phone has no room under each island. --row staggers the captions so one road's line never sits on another's. */
.isle-sparks { position: absolute; left: 50%; top: 34%; width: 0; height: 0; pointer-events: none; z-index: 3; }
.isle-sparks .spark { width: 26px; height: 26px; left: -13px; top: -13px; }
.roads.is-opening .isle-sparks .spark { animation: spark-fly 1.3s ease-out both; animation-delay: var(--d); }
.isle-today { display: none; }
.isle-play { display: none; align-items: center; justify-content: center; min-width: 90px; min-height: 44px; gap: 8px; margin-top: 10px; padding: 8px 18px; border-radius: 999px; background: var(--ink); color: var(--paper); font: 600 15px / 1 var(--sans); }
.isle-link:hover .isle-play, .isle-link:focus-visible .isle-play { background: var(--oxblood); }
.isle-play svg { width: 14px; height: 14px; }
.isle-play b { font-weight: 700; }
/* Waiting for the question, today's island already has a little light of its own. */
.isle[data-state="open"] .isle-burst { opacity: 0.3; transform: translate(-50%, -50%) scale(0.9); }
.roads.is-open .isle[data-state="open"] .isle-burst { opacity: 0.6; transform: translate(-50%, -50%) scale(1); animation: isle-glow 2.8s ease-in-out infinite; }
/* Today's land always carries its door: the name says which mission, the pill takes her in. */
.isle[data-state="open"] .isle-play { display: inline-flex; }
.isle[data-state="open"] .isle-today { display: none; }
.isle[data-state="open"]:hover .isle-lift { animation-play-state: paused; }
/* Before the question is answered the island is there and waiting, not lit. */
.roads:not(.is-open) .isle[data-state="open"] .isle-art { filter: saturate(0.9); }

/* ------------------------------------------------------ question and praise */
.gate { margin: 0; padding: 22px clamp(18px, 2.4vw, 28px) 22px; border-radius: 26px 22px 28px 22px / 22px 28px 22px 26px; border: 1.5px solid color-mix(in srgb, var(--ink) 52%, var(--paper)); background: var(--paper-2); box-shadow: 4px 5px 0 rgba(23, 58, 50, 0.13); }
.gate h2 { margin: 6px 0 18px; font: 500 clamp(24px, 2.8vw, 32px) / 1.28 var(--serif); max-width: 30ch; }
.gate .gate-choices { display: flex; flex-wrap: wrap; gap: 12px; }
.gate .gate-choices button { min-width: 112px; min-height: 64px; padding: 0 22px; font: 600 24px / 1 var(--serif); border: 1.5px solid var(--ink); border-radius: 18px; background: var(--paper); box-shadow: 0 4px 0 color-mix(in srgb, var(--ink) 30%, var(--paper)); transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease; }
.gate .gate-choices button:hover:not(:disabled), .gate .gate-choices button:focus-visible { background: color-mix(in srgb, var(--lemon) 40%, var(--paper)); transform: translateY(-2px); box-shadow: 0 6px 0 color-mix(in srgb, var(--ink) 30%, var(--paper)); }
.gate .gate-choices button:active:not(:disabled) { transform: translateY(2px); box-shadow: 0 1px 0 color-mix(in srgb, var(--ink) 30%, var(--paper)); }
.gate .gate-choices button:disabled { opacity: 0.55; cursor: default; }
.gate .gate-typed input { width: min(240px, 100%); min-height: 60px; padding: 8px 18px; font: 600 24px / 1 var(--serif); border: 1.5px solid var(--ink); border-radius: 18px; background: var(--paper); }
.gate .gate-typed .tool { min-height: 60px; padding-inline: 22px; font-size: 17px; }
.gate-help { margin: 18px 0 0; padding: 12px 16px; max-width: 52ch; border-left: 3px solid var(--oxblood); border-radius: 0 12px 12px 0; background: color-mix(in srgb, var(--paper) 70%, transparent); font: 400 19px / 1.5 var(--serif); }
.gate.nudge { animation: gate-nudge 0.7s ease; }

.praise { padding: 24px clamp(18px, 2.6vw, 30px) 22px; border-radius: 28px 24px 30px 24px / 24px 30px 24px 28px; border: 2px solid var(--ink); background: linear-gradient(180deg, color-mix(in srgb, var(--lemon) 26%, var(--paper)), var(--paper) 80%); box-shadow: 5px 6px 0 rgba(23, 58, 50, 0.16); animation: praise-in 0.7s cubic-bezier(0.3, 1.4, 0.5, 1) both; }
.praise h2 { font: 500 clamp(26px, 3.4vw, 40px) / 1.18 var(--serif); max-width: 22ch; }
.praise-open { margin: 10px 0 0; font: 600 18px / 1.3 var(--sans); color: var(--oxblood); }
.praise-acts { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 18px; }
.praise #gateExplainForm { margin-top: 22px; padding-top: 16px; border-top: 1.5px dashed color-mix(in srgb, var(--ink) 30%, var(--paper)); }
.praise #gateExplainForm label { font: 400 17px / 1.4 var(--serif); }

/* After a mission: what happens next, in words, with a key. */
.next-note { display: flex; align-items: center; gap: 14px; padding: 16px 20px; border-radius: 22px 26px 22px 26px / 26px 22px 26px 22px; background: color-mix(in srgb, var(--lemon) 28%, var(--paper)); border: 1.5px solid color-mix(in srgb, var(--accent) 64%, var(--paper)); box-shadow: 3px 4px 0 rgba(182, 106, 54, 0.18); animation: praise-in 0.7s cubic-bezier(0.3, 1.4, 0.5, 1) backwards; }
.is-celebrating .next-note { animation-delay: 1.9s; }
.next-key { flex: none; display: grid; place-items: center; width: 40px; height: 40px; border-radius: 50%; background: var(--paper); border: 1.5px solid color-mix(in srgb, var(--accent) 70%, var(--ink)); color: var(--accent); }
.next-key svg { width: 22px; height: 22px; }
.next-note p { font: 500 clamp(19px, 2.2vw, 24px) / 1.3 var(--serif); }

/* The words today taught her: a soft row under the day's note, each pill a press to hear the word again in the guide's voice. */
.desk-learned { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 12px 0 0; padding: 14px 20px; border-radius: 22px 26px 22px 26px / 26px 22px 26px 22px; background: color-mix(in srgb, var(--paper) 88%, var(--lemon)); border: 1.5px solid color-mix(in srgb, var(--accent) 40%, var(--paper)); animation: praise-in 0.7s cubic-bezier(0.3, 1.4, 0.5, 1) backwards; }
.desk-learned-line { font: 500 clamp(15px, 1.8vw, 18px) / 1.3 var(--serif); color: var(--ink-soft); }
.desk-word { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 8px 18px; border: 1.5px solid var(--ink); border-radius: 999px; background: var(--paper); color: var(--ink); font: 600 17px / 1.1 var(--serif); cursor: pointer; box-shadow: 2px 3px 0 rgba(23, 58, 50, 0.15); }
.desk-word:hover, .desk-word:focus-visible { background: color-mix(in srgb, var(--lemon) 34%, var(--paper)); outline: none; }
.desk-word:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.desk-word-dot { flex: none; width: 12px; height: 12px; border-radius: 50%; border: 1.5px solid var(--ink); background: var(--word-colour, var(--lemon)); }

/* --------------------------------------------------------- the level sheet */
.level-sheet { width: min(580px, calc(100% - 32px)); max-height: calc(100dvh - 32px); padding: 24px clamp(18px, 3vw, 30px) 22px; border: 2px solid var(--ink); border-radius: 28px 24px 30px 24px / 24px 30px 24px 28px; background: var(--paper); color: var(--ink); box-shadow: 6px 8px 0 rgba(23, 58, 50, 0.22); overflow: auto; }
.level-sheet::backdrop { background: color-mix(in srgb, var(--ink) 40%, transparent); }
.level-sheet[open] { animation: sheet-in 0.4s cubic-bezier(0.3, 1.3, 0.5, 1); }
.sheet-head { display: flex; align-items: center; gap: 16px; }
.sheet-dragon { width: 96px; height: auto; flex: none; }
.level-sheet h2 { font: 500 clamp(26px, 3.4vw, 34px) / 1.12 var(--serif); }
#levelLines p { margin-top: 12px; font: 400 19px / 1.45 var(--serif); }
.stat-list { list-style: none; margin: 18px 0 0; padding: 0; display: grid; gap: 14px; }
.stat-list li { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 16px; align-items: center; padding-top: 12px; border-top: 1.5px dashed color-mix(in srgb, var(--ink) 22%, var(--paper)); }
.stat-name { font: 600 19px / 1.2 var(--serif); }
.stat-means { grid-column: 1; font: 400 14px / 1.35 var(--sans); color: var(--ink-soft); }
.sheet-acts { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 12px; margin-top: 22px; }

/* ----------------------------------------------------------- the moments */
@keyframes dragon-float { 0%, 100% { transform: translateY(0) rotate(-0.8deg); } 50% { transform: translateY(-14px) rotate(0.9deg); } }
@keyframes dragon-shadow { 0%, 100% { transform: scale(1); opacity: 0.95; } 50% { transform: scale(0.8); opacity: 0.6; } }
@keyframes dragon-blink { 0%, 91%, 100% { opacity: 0; } 93%, 96% { opacity: 1; } }
/* Three hops, each a squash, a stretch and a landing: she is glad. */
@keyframes dragon-hop {
  0% { transform: translateY(0) scale(1, 1); }
  7% { transform: translateY(0) scale(1.07, 0.92); }
  20% { transform: translateY(-44px) scale(0.95, 1.06) rotate(-3deg); }
  34% { transform: translateY(0) scale(1.08, 0.91); }
  42% { transform: translateY(0) scale(1, 1); }
  45% { transform: translateY(0) scale(1.07, 0.92); }
  58% { transform: translateY(-58px) scale(0.94, 1.08) rotate(3deg); }
  72% { transform: translateY(0) scale(1.09, 0.9); }
  80% { transform: translateY(-24px) scale(0.97, 1.04) rotate(-2deg); }
  90% { transform: translateY(0) scale(1.04, 0.96); }
  100% { transform: translateY(0) scale(1, 1); }
}
.is-celebrating .dragon-float { animation: dragon-hop 2.4s ease-in-out 1 both; }
@keyframes spark-fly { 0% { opacity: 0; transform: translate(0, 0) scale(0.2) rotate(0deg); } 14% { opacity: 1; } 100% { opacity: 0; transform: translate(var(--x), var(--y)) scale(1) rotate(150deg); } }
.is-celebrating .spark { animation: spark-fly 1.5s ease-out both; animation-delay: var(--d); }
@keyframes level-pop { 0% { transform: translateX(-50%) scale(1); } 35% { transform: translateX(-50%) scale(1.28) rotate(-3deg); } 100% { transform: translateX(-50%) scale(1); } }
@keyframes isle-bob { 0%, 100% { transform: translateY(3px); } 50% { transform: translateY(-4px); } }
@keyframes isle-glow { 0%, 100% { opacity: 0.6; transform: translate(-50%, -50%) scale(1); } 50% { opacity: 0.36; transform: translate(-50%, -50%) scale(1.08); } }
/* The grand moment: the light bursts out of today's island and the island rises to meet it. */
@keyframes isle-burst { 0% { opacity: 0; transform: translate(-50%, -50%) scale(0.2); } 35% { opacity: 1; } 100% { opacity: 0.6; transform: translate(-50%, -50%) scale(1); } }
@keyframes isle-rise { 0%, 100% { transform: translateY(0); } 30% { transform: translateY(-12px); } }
.roads.is-opening .isle[data-state="open"] .isle-burst { animation: isle-burst 1.1s ease-out both, isle-glow 2.8s ease-in-out 1.1s infinite; }
.roads.is-opening .isle[data-state="open"] .isle-lift { animation: isle-rise 1s cubic-bezier(0.3, 1.4, 0.5, 1) both; }
@keyframes praise-in { from { opacity: 0; transform: translateY(18px) scale(0.96); } to { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes gate-nudge { 0%, 100% { transform: translateX(0); } 20% { transform: translateX(-7px); } 45% { transform: translateX(6px); } 70% { transform: translateX(-3px); } }
@keyframes sheet-in { from { opacity: 0; transform: translateY(24px) scale(0.97); } to { opacity: 1; transform: translateY(0) scale(1); } }
/* Badges keep their final state without an animation waiting forever for a
   display:none ancestor to become visible. */

/* --------------------------------------------------------------- narrow */
@media (max-width: 759px) {
  /* The masthead keeps to one row: her name, a small Hear it again, and Sign out. */
  .child-desk .mast { gap: 8px; }
  .child-desk .mast .hello { gap: 2px 10px; flex: 1 1 auto; min-width: 0; }
  .child-desk .mast .hello h1 { font-size: 19px; white-space: normal; }
  .child-desk .mast .hello .hello-line { font-size: 14px; }
  .child-desk .mast .hello .cta-row .tool { min-height: 34px; padding: 6px 10px; font-size: 13px; }
  .child-desk .mast-nav { flex: none; }
  /* On the phone the tag is a small stacked plaque hung on the keep: it never reaches over a caption or a Play. */
  .dragon-level { flex-direction: column; gap: 3px; width: 56px; padding: 6px 4px; border-radius: 14px; white-space: normal; text-align: center; font-size: 11px; line-height: 1.1; }
  .dragon-level .dragon-star { width: 14px; height: 14px; }
  .dragon-level .dragon-star svg { width: 14px; height: 14px; }
  .desk-dragon:hover .dragon-level, .desk-dragon:focus-visible .dragon-level { transform: translateY(-2px); }
  .road-name { font-size: 20px; }
  .road-count { font-size: 12px; }
  .isle-name { font-size: 15px; }
  .isle-badge { width: 24px; height: 24px; top: 10px; right: 4%; }
  .isle-badge svg { width: 14px; height: 14px; }
  .isle-play { padding: 7px 12px 7px 10px; font-size: 14px; }
  .gate .gate-choices { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .gate .gate-choices button { min-width: 0; font-size: 22px; }
  .level-sheet { width: 100%; max-width: none; margin: auto 0 0; border-radius: 28px 28px 0 0; }
  .sheet-dragon { width: 76px; }
}
@media (min-width: 481px) and (max-width: 1099px) {
  .road-desk .sky { height: 900px; --tower-w: min(18vw, 150px); }
  .road-rows { left: 3%; top: 110px; width: 34%; }
}
@media (max-width: 480px) {
  /* A phone: the tower on top, her island under it, her roads at the foot of the sky, one card each across the width. */
  /* The stage sizes the sky from its rows (layoutHome); the codes under each mission made three rows taller than the old 1100 ceiling. */
  .road-desk .sky { height: 940px; max-height: none; --tower-w: 80px; --dragon-w: 72px; }
  .tower { top: 160px; }
  /* The stage sets the rows' top and the sky's height from where her island landed (desk-stage.js layoutHome). */
  .road-rows { left: 16px; right: 16px; top: 580px; width: auto; gap: 12px; }
  .road-row { grid-template-columns: 44px minmax(0, 1fr); gap: 10px; padding: 12px 14px 14px; }
  .road-icon img { width: 44px; height: 44px; }
  .road-next-title { font-size: 18px; }
}
@media (max-width: 380px) {
  .road-desk .sky { --dragon-w: 64px; }
  .child-desk .mast .hello h1 { font-size: 19px; }
}

/* ------------------------------------------------------------- teleport */
/* Pressing today's island: it rises to meet her, light wells out of where she stood, and the page hands over to the mission. */
.tele-veil { position: fixed; inset: 0; z-index: 60; pointer-events: none; opacity: 0; background: radial-gradient(circle at var(--tx, 50%) var(--ty, 46%), color-mix(in srgb, var(--lemon) 88%, #fff) 0 10%, color-mix(in srgb, var(--lemon) 55%, transparent) 34%, transparent 62%); }
.tele-veil.go { animation: veil-in 0.55s ease both; }
@keyframes veil-in { 0% { opacity: 0; } 45% { opacity: 1; } 100% { opacity: 1; } }
@keyframes isle-tele { 0% { transform: scale(1.16) translateY(0); } 60% { transform: scale(1.3) translateY(-26px); } 100% { transform: scale(1.3) translateY(-26px); } }
.isle.is-teleporting .isle-lift { animation: isle-tele 0.55s cubic-bezier(0.3, 1.3, 0.5, 1) both; }
.isle.is-teleporting .isle-burst { animation: isle-burst 0.55s ease-out both; }

/* -------------------------------------------------------- reduced motion */
/* Still pictures. primer.css already turns every animation and transition off under reduced motion, on every page, so what is left here is only what a still picture needs: the base style is every state's final look, and a celebration is a pose, a few stars and the new state. */
@media (prefers-reduced-motion: reduce) {
  .dragon-frame.blink { opacity: 0; }
  .isle-lift { transform: none; }
  .isle-burst { transform: translate(-50%, -50%) scale(1); }
  .is-celebrating .spark, .roads.is-opening .isle-sparks .spark { opacity: 0.9; transform: translate(var(--x), var(--y)); }
}

/* ---------------------------------------------------------- the arrival */
/* The tower's own door: Play at her front step, the same pill the open island wears. */
.tower-play { position: absolute; left: 50%; bottom: 4%; translate: -50%; z-index: 3; display: inline-flex; align-items: center; gap: 6px; padding: 9px 18px 9px 14px; border: 0; border-radius: 999px; background: var(--ink); color: var(--paper); font: 700 15px / 1 var(--sans); cursor: pointer; box-shadow: 2px 3px 0 rgba(23, 58, 50, 0.25); }
.tower-play svg { width: 14px; height: 14px; }
.tower-play:hover, .tower-play:focus-visible { background: var(--oxblood); outline-offset: 3px; }

/* Which way, little one: her roads as little pictured lands above the door. */
.path-choose { position: absolute; right: calc(50% + 97px); top: 0; z-index: 4; display: flex; flex-direction: column; gap: 8px; }
.path-card { display: grid; justify-items: center; gap: 6px; width: 86px; padding: 10px 10px 9px; border: 2px solid transparent; border-radius: 8px; background: color-mix(in srgb, var(--paper) 88%, transparent); cursor: pointer; font: 600 13px / 1.2 var(--serif); color: var(--ink); box-shadow: 0 8px 18px rgba(23, 58, 50, 0.16); }
.path-card img { width: 100%; aspect-ratio: 1; object-fit: contain; }
.path-card:hover, .path-card:focus-visible { border-color: var(--accent); outline-offset: 2px; }
.path-card[aria-pressed="true"] { border-color: var(--road-ink, var(--accent)); }

/* Her dragon, painted, floating on the paper while it is met; dots for where she is, never a count. */
.dragon-welcome .welcome-art { width: min(380px, 52dvh); flex: none; }
.welcome-art .pose-img { display: block; width: 100%; }
.welcome-dots { display: flex; justify-content: center; gap: 10px; margin: 18px 0 0; }
.welcome-dots i { width: 10px; height: 10px; border-radius: 50%; border: 1.5px solid var(--ink); background: transparent; }
.welcome-dots i.on { background: var(--ink); }
@media (max-width: 600px) { .dragon-welcome .welcome-art { width: min(290px, 38dvh); } }

/* A device that cannot draw the dragon keeps the tower rail, the rows and the question: the column still says how far she has climbed. */
/* A separate maths entry never replaces or resizes the child's story island. */

/* 2026-10-14, the child's desk: maths is an island, its button the one primary button; every island and mission card carries its code in small monospace. */
.mission-tag { display: block; margin-top: 4px; font: 500 11px / 1.2 var(--mono, "JetBrains Mono", ui-monospace, monospace); letter-spacing: 0.02em; color: var(--ink-soft); text-align: center; overflow-wrap: anywhere; }
.road-text .mission-tag { text-align: left; margin-top: 2px; }
.maths-go, .road-maths-go { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 48px; padding: 10px 20px; border-radius: 999px; background: var(--ink); color: var(--paper); font: 700 15px / 1.15 var(--sans); text-decoration: none; text-align: center; position: relative; }
.maths-go { margin-top: 10px; max-width: 100%; z-index: 7; pointer-events: auto; }
.maths-go svg, .road-maths-go svg { width: 14px; height: 14px; flex: none; }
.maths-go:hover, .maths-go:focus-visible, .road-maths-go:hover, .road-maths-go:focus-visible { background: var(--oxblood); color: var(--paper); }
.maths-go:focus-visible, .road-maths-go:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
.maths-isle .isle-lift { display: block; width: 100%; }
.maths-isle[data-state="done"] .isle-art { filter: saturate(0.95); }
.maths-done { margin: 8px 0 0; font: 600 15px / 1.3 var(--sans); color: var(--ink-soft); text-align: center; }
.maths-isle .isle-name, .isle[data-second] .isle-name { max-width: 100%; }
.road-maths-go { margin-top: 10px; min-width: 96px; width: auto; max-width: 100%; }
.maths-card { display: grid; justify-items: start; gap: 6px; padding: 16px 0; border-bottom: 1px solid #cbd5cc; }
.maths-card[hidden] { display: none; }
.maths-card h2 { margin: 0; font-size: 20px; }
.maths-card .mission-tag { text-align: left; margin: 0; }
.maths-card .maths-go { margin-top: 4px; }
@media (max-width: 480px) {
  .maths-go, .road-maths-go { font-size: 14px; padding: 9px 14px; min-height: 46px; }
  .mission-tag { font-size: 10px; }
}
/* The welcome back: the arrival's own sky and dragon, one line and one door. */
.welcome-back .welcome-copy { padding-top: 12px; }
.welcome-back h2 { min-height: 0; }
.maths-go[hidden], .road-maths-go[hidden] { display: none; }
.next-note { flex-wrap: wrap; }
.next-note .road-maths-go { margin: 0 0 0 auto; }
@media (max-width: 480px) { .next-note .road-maths-go { margin: 0; } }
/* Her maths on the floating tower: under the keep, in the sky, not inside the drifting tower. */
.tower-maths { position: absolute; left: 50%; translate: -50% 0; z-index: 7; width: min(260px, 70%); display: grid; justify-items: center; gap: 2px; text-align: center; }
.tower-maths[hidden] { display: none; }
.tower-maths .isle-name { margin: 0; }
.tower-maths .mission-tag { margin: 0; }
.tower-maths .maths-go { margin-top: 8px; }
