/* Lesson engine styles. Lunar tokens from lib/theme.dart. Single-theme on
   purpose: a scene at night, painted explicitly so it holds on any host. Fonts
   are subset woff2 files next door; the app host inlines them. */
@font-face { font-family: "DM Sans"; font-weight: 400; font-style: normal; font-display: block; src: url(../fonts/dmsans-400.woff2) format("woff2"); }
@font-face { font-family: "DM Sans"; font-weight: 600; font-style: normal; font-display: block; src: url(../fonts/dmsans-600.woff2) format("woff2"); }
@font-face { font-family: "DM Sans"; font-weight: 800; font-style: normal; font-display: block; src: url(../fonts/dmsans-800.woff2) format("woff2"); }
@font-face { font-family: "DM Sans"; font-weight: 900; font-style: normal; font-display: block; src: url(../fonts/dmsans-900.woff2) format("woff2"); }
@font-face { font-family: "Source Serif 4"; font-weight: 500; font-style: normal; font-display: block; src: url(../fonts/sourceserif-500.woff2) format("woff2"); }
@font-face { font-family: "Source Serif 4"; font-weight: 700; font-style: normal; font-display: block; src: url(../fonts/sourceserif-700.woff2) format("woff2"); }
@font-face { font-family: "IBM Plex Mono"; font-weight: 600; font-style: normal; font-display: block; src: url(../fonts/plexmono-600.woff2) format("woff2"); }
:root {
  --bg: #0A0E1A;
  --surface: #121829;
  --raised: #1A2136;
  --line: rgba(234, 227, 215, .14);
  --line-strong: rgba(234, 227, 215, .28);
  --text: #EAE3D7;
  --dim: #A69F93;
  --faint: #6E6960;
  --violet: #7B5CFD;
  --violet-bright: #A99BFF;
  --violet-deep: #5B45C8;
  --gold: #FCC050;
  --gold-deep: #C98C1B;
  --mint: #3FD69A;
  --mint-ink: #0B2E20;
  --red: #D85555;
  --red-ink: #2E0B0B;
  --streak: #FB9679;
  --serif: "Source Serif 4", Georgia, "Times New Roman", serif;
  --sans: "DM Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, Menlo, Consolas, monospace;
}
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
html, body { height: 100%; }
body {
  margin: 0; background: #05070E; color: var(--text); font-family: var(--sans);
  font-size: 16px; line-height: 1.4; -webkit-font-smoothing: antialiased;
  overflow: hidden;
}
button { font: inherit; color: inherit; border: 0; background: none; cursor: pointer; }
button:focus-visible, [tabindex]:focus-visible { outline: 2px solid var(--violet-bright); outline-offset: 2px; }

/* ---------- phone frame ---------- */
#frame {
  position: fixed; inset: 0; margin: auto; width: 100%; height: 100%;
  background: var(--bg); overflow: hidden; display: flex; flex-direction: column;
}
@media (min-width: 520px) and (min-height: 700px) {
  #frame { width: 400px; height: min(860px, 96vh); border-radius: 44px; border: 8px solid #1c1f2b; box-shadow: 0 30px 90px rgba(0,0,0,.6); }
}

/* ---------- top bar ---------- */
#top {
  display: flex; align-items: center; gap: 12px; padding: 14px 16px 6px; flex: none;
}
#close { width: 44px; height: 44px; margin-left: -12px; display: grid; place-items: center; color: var(--dim); font-size: 22px; }
/* Look back: hit areas abut the close button's and the bar, and the chevron
   keeps its slot while hidden, like the combo pill, so the bar never jumps. */
#back, #fwd { flex: none; width: 44px; height: 44px; margin: 0 -12px; display: grid; place-items: center; color: var(--dim); }
#fwd { display: none; margin-left: 0; } #top.lk #fwd { display: grid; }
#back svg, #fwd svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
#back { visibility: hidden; } #back.on { visibility: visible; } #back[disabled] { opacity: .35; }
#track { flex: 1; position: relative; }
#bar { height: 18px; border-radius: 999px; background: var(--raised); overflow: hidden; position: relative; }
/* The fill springs past its mark and settles. It never reads empty: the first
   beat already shows a nub. */
#menu { width: 44px; height: 44px; margin-right: -12px; display: grid; place-items: center; color: var(--dim); }
#menu svg { width: 20px; height: 20px; fill: currentColor; }
#menu[hidden] { display: none; }
#bar > i {
  display: block; position: relative; height: 100%; width: 0; min-width: 20px; border-radius: 999px;
  background: linear-gradient(90deg, var(--violet-deep), var(--violet), var(--violet-bright));
  transition: width .7s cubic-bezier(.34,1.5,.5,1), filter .3s;
}
#bar > i::after { content: ""; position: absolute; top: 3px; left: 8px; right: 8px; height: 4px; border-radius: 4px; background: rgba(255,255,255,.3); }
/* A right answer moves the bar and a gloss runs along the new fill. */
#bar > i::before { content: ""; position: absolute; inset: 0; border-radius: inherit; background: linear-gradient(100deg, transparent 30%, rgba(255,255,255,.55) 50%, transparent 70%) no-repeat; background-size: 60% 100%; background-position: -120% 0; }
#bar.grow > i::before { animation: barGloss .8s .15s ease-out; }
@keyframes barGloss { to { background-position: 220% 0; } }
#bar.hot > i { background: linear-gradient(90deg, var(--gold-deep), var(--gold), #FFE7A3); }
#bar.flare > i { animation: barFlare .7s ease-out; }
@keyframes barFlare { 25% { filter: brightness(1.7) drop-shadow(0 0 8px var(--gold)); } }
/* The combo is a label over the bar, absent until three right in a row, and
   gold. Never the streak's orange or a flame: those are the app's daily
   streak. Absolute, so the bar never moves when it comes and goes. */
#combo {
  position: absolute; left: 4px; bottom: calc(100% + 3px); font-size: 11.5px; font-weight: 900; letter-spacing: .1em; text-transform: uppercase;
  color: var(--gold); white-space: nowrap; font-variant-numeric: tabular-nums; text-shadow: 0 0 10px rgba(252,192,80,.55);
  opacity: 0; translate: 0 6px; transition: opacity .25s, translate .35s cubic-bezier(.34,1.56,.64,1);
}
#combo b { font-weight: 900; }
#combo.on { opacity: 1; translate: 0 0; }
#combo.pop { animation: comboPop .45s cubic-bezier(.34,1.56,.64,1); }
@keyframes comboPop { 35% { scale: 1.35; } }
.stat { display: inline-flex; align-items: center; gap: 5px; font-weight: 700; font-size: 14px; font-variant-numeric: tabular-nums; padding: 5px 9px; border-radius: 999px; }
.stat.pop { transform: scale(1.18); }

/* ---------- effects layer: the combo moment ---------- */
.fx { position: absolute; inset: 0; z-index: 20; pointer-events: none; overflow: hidden; }
.fx > svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.fx .bolt { fill: none; stroke-linejoin: round; stroke-linecap: round; stroke-dasharray: 1; stroke-dashoffset: 1; animation: boltDraw .16s ease-out forwards, boltFlicker .7s linear forwards; }
.fx .bolt.core { stroke: #FFFBEA; stroke-width: 4.5; }
.fx .bolt.glow { stroke: var(--gold); stroke-width: 16; opacity: .7; filter: blur(4px); }
.fx .bolt.fork.core { stroke-width: 2.2; } .fx .bolt.fork.glow { stroke-width: 8; } .fx .bolt.fork { animation-delay: .06s, .06s; }
.fx .bolt.run { stroke-width: 2.4; }
.fx .bolt.run.glow { stroke-width: 7; }
@keyframes boltDraw { to { stroke-dashoffset: 0; } }
@keyframes boltFlicker { 0%, 22% { opacity: 1; } 30% { opacity: .25; } 40% { opacity: 1; } 52% { opacity: .5; } 60% { opacity: 1; } 100% { opacity: 0; } }
.fx .flash { position: absolute; inset: 0; background: radial-gradient(circle at var(--x) var(--y), rgba(255,243,196,.5), rgba(252,192,80,.18) 35%, transparent 70%); animation: fxFlash .45s ease-out forwards; }
@keyframes fxFlash { 0% { opacity: 0; } 20% { opacity: 1; } 100% { opacity: 0; } }
.fx .ring { position: absolute; width: 120px; height: 120px; margin: -60px 0 0 -60px; border-radius: 50%; border: 3px solid var(--gold); box-shadow: 0 0 16px rgba(252,192,80,.7); animation: fxRing .6s cubic-bezier(.2,.8,.2,1) forwards; }
@keyframes fxRing { from { scale: .3; opacity: 1; } to { scale: 2.4; opacity: 0; } }
.fx .spark { position: absolute; width: 7px; height: 7px; margin: -3.5px 0 0 -3.5px; border-radius: 50%; background: #FFE7A3; box-shadow: 0 0 8px var(--gold); animation: fxSpark .6s cubic-bezier(.2,.8,.2,1) forwards; }
@keyframes fxSpark { to { translate: var(--dx) var(--dy); scale: .2; opacity: 0; } }
/* The reward itself: the XP it pays, big, then it flies back into the bar. */
.fx .badge { position: absolute; display: flex; flex-direction: column; align-items: center; gap: 8px; translate: -50% -50%; animation: badgeIn .5s cubic-bezier(.34,1.56,.64,1) backwards; transition: left .42s cubic-bezier(.55,0,.8,.4), top .42s cubic-bezier(.55,0,.8,.4), scale .42s cubic-bezier(.55,0,.8,.4), opacity .2s .3s; }
.fx .badge .pill {
  display: flex; align-items: center; gap: 10px; padding: 12px 26px 12px 14px; border-radius: 28px;
  background: linear-gradient(180deg, #FFE7A3, var(--gold) 55%); border: 4px solid #FFF6D8; box-shadow: 0 7px 0 var(--gold-deep), 0 0 40px rgba(252,192,80,.65);
  font: 900 58px/1 var(--sans); color: #2A1B00; font-variant-numeric: tabular-nums;
}
.fx .badge .pill svg { flex: none; width: 58px; height: 58px; color: var(--gold-deep); }
.fx .badge::before { content: ""; position: absolute; left: 50%; top: 42%; width: 340px; height: 260px; translate: -50% -50%; z-index: -1; border-radius: 50%; background: radial-gradient(closest-side, rgba(5,7,14,.82), rgba(5,7,14,.5) 55%, transparent); }
.fx .badge .cap { font-size: 15px; font-weight: 900; letter-spacing: .14em; text-transform: uppercase; color: var(--gold); text-shadow: 0 0 12px rgba(252,192,80,.7); }
.fx .badge.go { scale: .2; opacity: 0; }
.fx .badge.go::before { opacity: 0; transition: opacity .15s; }
@keyframes badgeIn { 0% { scale: .2; rotate: -10deg; opacity: 0; } 60% { scale: 1.15; rotate: 3deg; opacity: 1; } 100% { scale: 1; rotate: 0deg; } }

/* ---------- stage ---------- */
#stage { flex: 1; min-height: 0; display: flex; flex-direction: column; padding: 4px 18px 0; overflow: hidden; position: relative; }
#eyebrow, #look .lk-eb { font-size: 12px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--violet-bright); margin: 6px 0 4px; min-height: 16px; }
#copy, #look .lk-copy {
  font-family: var(--sans); font-size: 20px; line-height: 1.36; font-weight: 600; letter-spacing: -0.01em;
  text-wrap: pretty; margin: 0 0 10px; min-height: 56px;
}
#copy.small, #look .lk-copy.small { font-size: 18.5px; }
#copy strong, #look .lk-copy strong { font-weight: 800; color: #fff; }
/* The copy is the game's voice, in the app's sans. The serif is kept for the
   concept itself: its name on the first screen, and the card. */
#stage:has(.hero.orient) #copy strong { font-family: var(--serif); font-weight: 700; font-size: 1.12em; }
#copy .g, #look .lk-copy .g { color: var(--gold); font-weight: 600; }
#copy.in, #look .lk-copy.in { animation: copyIn .32s cubic-bezier(.2,.8,.2,1) both; }
@keyframes copyIn { from { opacity: 0; transform: translateY(6px); } }
/* The Duolingo layout: the copy is pinned at the top so the question sits
   at the same height on every beat, the scene sits directly under it, and
   the controls sit at the bottom; spare height falls between the scene and
   the controls. Nothing moves when a feedback sheet rises: it covers the
   controls, and on a tall phone rarely reaches the scene. The controls area
   reserves one height (three options' worth) whether the beat shows one
   button or three, so tap targets stay put. When the screen is too short
   the reserve gives way first (its flex-shrink is high), and a scene that
   still does not fit clips at its bottom rather than painting over the
   copy; play.mjs fails a lesson that gets there. */
#scene, #look .lk-scene { flex: 0 1 auto; min-height: 0; position: relative; display: flex; flex-direction: column; padding-top: 10px; overflow: hidden; }
/* Room below the scene for a hero image's drop-shadow glow, which overflow
   would otherwise cut in a hard line; the negative margin keeps layout as it
   was, and the controls sit above the overlap so they still take the taps.
   engine.js subtracts it wherever it measures the scene. */
#scene { padding-bottom: 44px; margin-bottom: -44px; }
#controls { position: relative; z-index: 1; }
#controls, #look .lk-controls { flex: 0 20 184px; margin-top: auto; display: flex; flex-direction: column; justify-content: flex-end; gap: 10px; padding: 12px 0 calc(16px + env(safe-area-inset-bottom)); }
/* A screen whose scene is the control (tap the word, tap the spot) has
   nothing in the controls, so the scene drops into the free space toward the
   thumb. engine.js sets the offset once the screen opens and eases it when
   the scene grows. */
#scene { transition: translate .4s cubic-bezier(.2,.8,.2,1); }
/* The bold question gets its own line in the app's sans, as an instruction,
   while the setup before it stays in the serif. */
#copy .ask { display: block; margin-top: 8px; font-family: var(--sans); font-weight: 800; font-size: 21px; line-height: 1.25; letter-spacing: -.01em; color: #fff; }
#copy .ask.solo { margin-top: 0; }
#copy.small .ask { font-size: 19px; margin-top: 6px; }
/* DM Sans sets wider than the serif it replaced; the small phone takes it a
   size down so prompts written for the serif keep their line count. */
@media (max-height: 700px) { #copy, #look .lk-copy { font-size: 19px; } #copy.small, #look .lk-copy.small { font-size: 17.5px; } #copy .ask { font-size: 20px; } #copy.small .ask { font-size: 18.5px; } }
/* The last give on a screen that doesn't fit (engine.js fit()). */
#stage.tight #copy { line-height: 1.28; margin-bottom: 6px; }
#copy.small .ask.solo { margin-top: 0; }
/* The eyebrow of a screen that asks something carries its kind's glyph. */
#eyebrow { display: flex; align-items: center; gap: 8px; }
#eyebrow .ico { flex: none; width: 22px; height: 22px; margin: -3px 0; border-radius: 7px; display: grid; place-items: center; background: linear-gradient(145deg, var(--violet-bright), var(--violet)); box-shadow: 0 2px 0 var(--violet-deep); animation: icoIn .4s cubic-bezier(.34,1.56,.64,1) backwards; }
#eyebrow .ico svg { width: 14px; height: 14px; fill: none; stroke: #fff; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
@keyframes icoIn { from { scale: .3; opacity: 0; } }
/* Duolingo's header has air: a larger eyebrow with a clear gap under it, a
   larger question, and room before the scene. The small phone has none to
   spare and keeps the tight set. */
@media (min-height: 701px) {
  #top { padding-top: 20px; }
  #eyebrow { font-size: 13.5px; margin: 10px 0 14px; }
  #eyebrow .ico { width: 26px; height: 26px; margin: -5px 0; border-radius: 8px; }
  #eyebrow .ico svg { width: 16px; height: 16px; }
  #copy, #look .lk-copy { font-size: 22px; line-height: 1.38; letter-spacing: -.012em; }
  #copy.small, #look .lk-copy.small { font-size: 20px; }
  #copy .ask { font-size: 24px; margin-top: 14px; }
  #copy.small .ask { font-size: 21px; margin-top: 10px; }
  #scene { padding-top: 24px; }
  /* A screen that can't spare the air gets the tight set back. */
  #stage.tight #eyebrow { margin: 6px 0 4px; }
  #stage.tight #scene { padding-top: 10px; }
}
/* Entrances. Options, chips and bins rise in one after another; a new
   screen's scene rises with them. :where keeps these at zero specificity, so
   any animation a lesson gives its own elements wins. */
@keyframes rise { from { opacity: 0; translate: 0 14px; } }
:where(.choices, .pairs) > .choice, :where(.bank) > .word, :where(.sortrow) > .btn, :where(#controls) > .btn, :where(#controls) > .slider {
  animation: rise .34s cubic-bezier(.2,.8,.2,1) calc(var(--i, 0) * 45ms) backwards;
}
:where(.choices, .pairs, .bank, .sortrow) > :nth-child(2) { --i: 1; } :where(.choices, .pairs, .bank, .sortrow) > :nth-child(3) { --i: 2; }
:where(.choices, .pairs, .bank, .sortrow) > :nth-child(4) { --i: 3; } :where(.choices, .pairs, .bank, .sortrow) > :nth-child(5) { --i: 4; }
:where(.choices, .pairs, .bank, .sortrow) > :nth-child(6) { --i: 5; } :where(.choices, .pairs, .bank, .sortrow) > :nth-child(n+7) { --i: 6; }
:where(#scene[data-enter]:not(.takeaway):not(.ending)) > * { animation: rise .4s cubic-bezier(.2,.8,.2,1) backwards; }
/* A screen the reader left, laid over the live stage (which keeps running
   under it) with the stage's own layout. Its scene is frozen: animations
   jump to where they end rather than replaying on every visit. */
#look { position: absolute; inset: 0; z-index: 7; display: flex; flex-direction: column; padding: 4px 18px 0; background: var(--bg); }
#look .lk-scene { pointer-events: none; }
#look .lk-scene *, #look .lk-scene *::before, #look .lk-scene *::after { animation-duration: 0s !important; animation-delay: 0s !important; animation-iteration-count: 1 !important; transition: none !important; }

/* ---------- buttons ---------- */
.btn {
  display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; min-height: 52px;
  border-radius: 999px; font-weight: 900; font-size: 16px; letter-spacing: .04em; text-transform: uppercase;
  background: var(--violet); color: #fff; box-shadow: 0 5px 0 var(--violet-deep);
  transition: transform .08s, box-shadow .08s, opacity .2s;
}
.btn:active { transform: translateY(4px); box-shadow: 0 1px 0 var(--violet-deep); }
.btn .unit { text-transform: none; }
/* Outline: the ledge is the border colour; an outer shadow never paints under the face. */
.btn.ghost { background: transparent; color: var(--text); border: 2px solid var(--line-strong); box-shadow: 0 5px 0 var(--line-strong); }
.btn.ghost:active { box-shadow: 0 1px 0 var(--line-strong); }
.btn.gold { background: var(--gold); color: #2A1B00; box-shadow: 0 5px 0 var(--gold-deep); }
.btn.gold:active { box-shadow: 0 1px 0 var(--gold-deep); }
.btn.red { background: var(--red); color: #fff; box-shadow: 0 5px 0 #8f2f2f; }
.btn.red:active { box-shadow: 0 1px 0 #8f2f2f; }
.btn[disabled] { background: #262D47; color: #626985; border-color: transparent; box-shadow: none; transform: translateY(5px); pointer-events: none; }
.btn.hide { opacity: 0; pointer-events: none; }

/* choices */
.choices { display: flex; flex-direction: column; gap: 10px; }
.choice {
  text-align: left; padding: 14px 16px; min-height: 54px; border-radius: 14px; font-size: 16px; font-weight: 600;
  background: var(--surface); border: 2px solid var(--line); box-shadow: 0 4px 0 var(--ledge, #2b2e38);
  display: flex; align-items: center; gap: 12px; transition: transform .08s, border-color .15s, background .15s, opacity .3s;
}
.choice:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--ledge, #2b2e38); }
.choice.picked { --ledge: color-mix(in srgb, var(--violet-bright) 50%, #070a14); border-color: var(--violet-bright); background: rgba(123,92,253,.12); }
.choice.right { --ledge: color-mix(in srgb, var(--mint) 50%, #070a14); border-color: var(--mint); background: rgba(63,214,154,.14); }
.choice.wrong { --ledge: color-mix(in srgb, var(--red) 50%, #070a14); border-color: var(--red); background: rgba(216,85,85,.14); }
.choice.locked { pointer-events: none; }
.choice.off { opacity: .6; pointer-events: none; } .choice.right.off { opacity: 1; }
.choice .mini { flex: none; width: 56px; height: 34px; }

/* pair matching */
.pairs { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.pairs .choice { min-height: 60px; justify-content: center; text-align: center; font-size: 15px; padding: 10px 12px; }
.pairs .choice.done { opacity: .28; pointer-events: none; border-color: var(--mint); }
/* Image options: cls 'pics' on a pick, 'pics two' for a pair. Each option's
   html is an img (the lesson's own webp) followed by a span caption. */
.choices.pics { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.choices.pics.two { grid-template-columns: 1fr 1fr; }
.choices.pics .choice { flex-direction: column; align-items: stretch; gap: 6px; padding: 8px; font-size: 13px; font-weight: 700; text-align: center; line-height: 1.2; }
.choices.pics .choice span { text-align: center; }
.choices.pics:has(> :nth-child(4)) { grid-template-columns: 1fr 1fr; }
.choices.pics.rows { grid-template-columns: 1fr; }
.choices.pics.rows .choice { font-size: 14px; }
.choices.pics img { width: 100%; height: clamp(96px, 14vh, 132px); object-fit: cover; border-radius: 10px; display: block; }
.choices.pics.two img, .choices.pics:has(> :nth-child(4)) img { height: clamp(118px, 17vh, 160px); }
@media (max-height: 700px) { .choices.pics img { height: 76px; } .choices.pics.two img, .choices.pics:has(> :nth-child(4)) img { height: 96px; } }
/* gauge(): a labelled bar. .ok / .bad / .cap tint it. */
.gauge { display: flex; flex-direction: column; gap: 5px; }
.gauge .gl { display: flex; justify-content: space-between; font-size: 12px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--dim); }
.gauge .gl b { font: 600 13px var(--mono); color: var(--text); text-transform: none; letter-spacing: 0; }
.gauge .gt { height: 8px; border-radius: 999px; background: var(--raised); overflow: hidden; }
.gauge .gt i { display: block; height: 100%; width: 0; border-radius: 999px; background: var(--violet-bright); transition: width .45s cubic-bezier(.2,.8,.2,1); }
.gauge.ok .gt i { background: var(--mint); } .gauge.bad .gt i, .gauge.cap .gt i { background: var(--red); }
/* compare(): two images, one wiper. */
.compare { display: flex; flex-direction: column; gap: 6px; }
.compare .cmp { position: relative; width: 100%; aspect-ratio: 3 / 2; border-radius: 14px; overflow: hidden; background: var(--surface); }
.compare .cmp img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.compare .cmp .edge { position: absolute; top: 0; bottom: 0; left: 50%; width: 2px; margin-left: -1px; background: #fff; box-shadow: 0 0 0 1px rgba(0,0,0,.35); pointer-events: none; }
.compare .cmp .wiper { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: ew-resize; }
.compare .caps { display: flex; justify-content: space-between; font-size: 12px; font-weight: 700; color: var(--dim); letter-spacing: .04em; text-transform: uppercase; }
/* credits in the browser ending */
.endstage .credits { position: absolute; left: 0; right: 0; bottom: 4px; text-align: center; font-size: 10px; color: var(--faint); padding: 0 12px; }

/* sort */
.rulecard { font-size: 14px; line-height: 1.4; padding: 10px 14px; margin-bottom: 10px; border-radius: 12px; background: var(--surface); border: 1px solid var(--line); color: var(--dim); text-align: center; transition: opacity .35s; }
.rulecard b { color: var(--text); }
.rulecard.gone { opacity: 0; }
.sorthold { min-height: 120px; display: grid; place-items: center; }
.sortcard {
  width: 100%; background: var(--surface); border: 2px solid var(--line); border-radius: 20px; padding: 20px 18px; text-align: center;
  font-family: var(--sans); font-size: 19px; font-weight: 700; line-height: 1.28; display: flex; flex-direction: column; gap: 8px; text-wrap: balance;
  animation: cardIn .25s cubic-bezier(.2,.8,.2,1) both;
}
@keyframes cardIn { from { opacity: 0; transform: scale(.94) translateY(8px); } }
.sortcard.right { border-color: var(--mint); }
.sortcard.wrong { border-color: var(--red); }
.sortcard .why { font-family: var(--sans); font-size: 14px; font-weight: 600; color: #FF8A8A; }
.sortrow { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
/* three or more bins leave about 105px a button on the small phone: shrink the label rather than wrap it */
.sortrow.many .btn { font-size: 13px; letter-spacing: .03em; padding-left: 6px; padding-right: 6px; }
.dots { display: flex; gap: 6px; justify-content: center; margin-top: 10px; }
.dots i { width: 8px; height: 8px; border-radius: 50%; background: var(--raised); }
.dots i.ok { background: var(--mint); } .dots i.no { background: var(--red); }

/* slider */
.slider { display: flex; flex-direction: column; gap: 8px; padding: 12px 14px; border-radius: 16px; background: var(--surface); border: 1px solid var(--line); }
/* Reset the home screen's .row card, which otherwise draws a box inside the slider. */
.slider .row { display: flex; justify-content: space-between; align-items: baseline; padding: 0; min-height: 0; border: 0; border-radius: 0; background: none; font-size: 13px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--dim); }
.slider .val { font-family: var(--mono); font-size: 18px; color: var(--text); text-transform: none; letter-spacing: 0; }
input[type=range] { -webkit-appearance: none; appearance: none; width: 100%; height: 44px; background: transparent; margin: 0; }
input[type=range]::-webkit-slider-runnable-track { height: 10px; border-radius: 999px; background: var(--raised); }
input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 30px; height: 30px; margin-top: -10px; border-radius: 50%; background: var(--violet-bright); border: 4px solid var(--bg); box-shadow: 0 0 0 2px var(--violet); }
input[type=range]::-moz-range-track { height: 10px; border-radius: 999px; background: var(--raised); }
input[type=range]::-moz-range-thumb { width: 22px; height: 22px; border-radius: 50%; background: var(--violet-bright); border: 4px solid var(--bg); box-shadow: 0 0 0 2px var(--violet); }

/* word bank (fill, label, place) */
.bank { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.word {
  padding: 10px 16px; min-height: 44px; border-radius: 12px; font-weight: 700; font-size: 15px; background: var(--surface); border: 2px solid var(--line); box-shadow: 0 4px 0 var(--ledge, #2b2e38);
  transition: transform .08s, border-color .15s, background .15s, opacity .2s;
}
.word:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--ledge, #2b2e38); }
.word.picked { border-color: var(--violet-bright); background: rgba(123,92,253,.16); }
.word.right { border-color: var(--mint); background: rgba(63,214,154,.14); }
.word.wrong { border-color: var(--red); background: rgba(216,85,85,.14); }
.word.locked { pointer-events: none; opacity: .6; } .word.locked.right { opacity: 1; }
.word.off, .spot.off { opacity: .6; pointer-events: none; }
/* slots (place) */
.slot {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; min-height: 64px; padding: 6px 4px;
  border-radius: 14px; border: 2px dashed var(--line-strong); background: var(--surface); color: var(--dim);
  transition: border-color .15s, background .15s;
}
.slot .n { font-family: var(--mono); font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--faint); }
.slot .v { font-weight: 800; font-size: 14px; color: var(--mint); line-height: 1.1; text-align: center; }
.slot.done { border-style: solid; border-color: var(--mint); background: rgba(63,214,154,.12); pointer-events: none; }
.slot.done .v { animation: slotIn .25s cubic-bezier(.34,1.56,.64,1) both; }
@keyframes slotIn { from { transform: scale(.6); opacity: 0; } }
.blank { display: inline-block; min-width: 110px; border-bottom: 3px solid var(--violet-bright); padding: 0 6px; margin: 0 2px; color: #fff; font-weight: 700; transition: border-color .15s; }
.blank.right { border-color: var(--mint); color: var(--mint); } .blank.wrong { border-color: var(--red); color: #FF8A8A; }

/* figure with tap markers */
.figure { position: relative; width: min(100%, 300px); margin: 0 auto; }
.figure img { width: 100%; height: auto; display: block; filter: drop-shadow(0 16px 24px rgba(0,0,0,.5)); }
.spot { position: absolute; width: 44px; height: 44px; margin: -22px 0 0 -22px; display: grid; place-items: center; }
.spot i { width: 22px; height: 22px; border-radius: 50%; background: var(--violet-bright); border: 3px solid var(--bg); box-shadow: 0 0 0 3px var(--violet); animation: pulse 1.6s ease-in-out infinite; }
@keyframes pulse { 50% { transform: scale(1.25); box-shadow: 0 0 0 7px rgba(123,92,253,.35); } }
.spot.locked { pointer-events: none; } .spot.locked i { animation: none; }
.spot.right i { background: var(--mint); box-shadow: 0 0 0 3px var(--mint), 0 0 24px 6px rgba(63,214,154,.5); }
.spot.wrong i { background: var(--red); box-shadow: 0 0 0 3px var(--red); }
.spot b { position: absolute; top: 40px; left: 50%; transform: translateX(-50%); font-size: 12px; font-weight: 700; white-space: nowrap; background: rgba(10,14,26,.85); padding: 3px 8px; border-radius: 999px; }
.spot.right b { color: var(--mint); } .spot.wrong b { color: #FF8A8A; }

/* labeled diagram */
.diagram { width: min(100%, 300px); margin: 0 auto; }
.diagram svg { width: 100%; height: auto; display: block; overflow: visible; }
.diagram .cap { fill: var(--faint); font: 700 10px var(--sans); letter-spacing: .1em; text-transform: uppercase; }
.diagram .tgt { cursor: pointer; }
.diagram .tgt .hit { fill: transparent; }
.diagram .tgt .pin { fill: var(--violet); stroke: var(--bg); stroke-width: 2.5; animation: pinpulse 1.6s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
@keyframes pinpulse { 50% { transform: scale(1.2); } }
.diagram .tgt .num { fill: #fff; font: 800 13px var(--sans); text-anchor: middle; pointer-events: none; }
.diagram .tgt .tag { fill: var(--mint); font: 700 12px var(--sans); }
.diagram .tgt.done .pin { fill: var(--mint); animation: none; } .diagram .tgt.done .num { opacity: 0; }
.diagram .tgt.done .hit { pointer-events: none; }
.shake { animation: shake .4s; }
/* nudge(): three pulses over a scene target, then gone. */
/* It grows by its shadow, not by scale, and nudge() keeps its box inside the scene: anything past the edge adds to #scene's scroll height and fails play.mjs. */
.nudge { position: absolute; pointer-events: none; border-radius: 16px; border: 2px solid var(--gold); animation: nudge 1.1s ease-out 3 both; z-index: 3; }
@keyframes nudge { 0% { opacity: 0; box-shadow: 0 0 0 0 rgba(252,192,80,.5); } 30% { opacity: .95; } 100% { opacity: 0; box-shadow: 0 0 0 10px rgba(252,192,80,0); } }
@keyframes shake { 25% { transform: translateX(-4px); } 75% { transform: translateX(4px); } }

.mini { display: block; flex: none; width: 56px; height: 34px; }
.mini path { fill: none; stroke: var(--text); stroke-width: 2.5; stroke-linecap: round; }
.mini line { stroke: var(--faint); stroke-width: 1; stroke-dasharray: 3 3; }

/* hero image, reveal box */
.hero { display: grid; place-items: center; }
.hero img { width: 210px; max-width: 100%; height: auto; filter: drop-shadow(0 18px 30px rgba(123,92,253,.35)); }
/* The opening screen: the card art, large, under the sentence that names the concept. */
.hero.orient img { width: 270px; max-height: 38vh; object-fit: contain; }
.revealbox { display: grid; place-items: center; }
@media (max-height: 700px) { .hero img { width: 170px; } .choice { min-height: 48px; padding: 11px 14px; } }


/* ---------- ending: the card beat, then the map beat ---------- */
#scene.ending { padding-top: 0; flex: 1 1 auto; }
.endstage { position: absolute; inset: 0; margin: 0 !important; }
.endcanvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.ecard {
  position: absolute; left: 50%; top: 50%; width: min(196px, 40vh * .66); aspect-ratio: 2 / 3;
  transform: translate(-50%, -54%) scale(.86); opacity: 0; transition: transform .6s cubic-bezier(.2,.8,.2,1), opacity .5s;
}
.ecard.in { opacity: 1; transform: translate(-50%, -54%) scale(1); }
.ecard.claimed { transform: translate(-50%, -54%) scale(1.06); }
.ecard.collapse { transform: translate(-50%, -50%) scale(.08); opacity: 0; transition: transform .45s cubic-bezier(.6,0,.9,.4), opacity .3s .15s; }
.ecard .face {
  position: absolute; inset: 0; border-radius: 16px; overflow: hidden; display: flex; flex-direction: column; padding: 9px;
  background: linear-gradient(160deg, #1d2440 0%, #101528 55%, #1a1f3a 100%); border: 1.5px solid rgba(234,227,215,.22);
  box-shadow: 0 18px 40px rgba(0,0,0,.55), 0 0 0 0 rgba(252,192,80,0); transition: box-shadow .7s;
}
.ecard.claimed .face { box-shadow: 0 18px 40px rgba(0,0,0,.55), 0 0 40px 6px rgba(252,192,80,.38); border-color: rgba(252,192,80,.7); }
.ecard.foil .face { border-color: rgba(169,155,255,.8); }
.ecard.gold .face { border-color: var(--gold); background: linear-gradient(160deg, #3a2a10, #1a1408 55%, #3a2c12); }
.ecard .art { flex: 0 0 52%; border-radius: 10px; background: radial-gradient(circle at 50% 40%, #2a2f55, #121829 75%); display: grid; place-items: center; overflow: hidden; }
.ecard .art img { width: 82%; height: 82%; object-fit: contain; filter: drop-shadow(0 8px 14px rgba(0,0,0,.5)); }
.ecard .name { font-family: var(--serif); font-size: 17px; font-weight: 700; line-height: 1.15; margin: 9px 2px 4px; color: #fff; text-wrap: balance; }
.ecard .line { font-size: 10.5px; line-height: 1.32; color: var(--dim); margin: 0 2px; flex: 1; min-height: 0; overflow: hidden; }
.ecard .meter { position: relative; height: 14px; border-radius: 999px; background: rgba(234,227,215,.1); overflow: hidden; margin-top: 6px; }
.ecard .meter i { position: absolute; left: 0; top: 0; bottom: 0; width: 0; border-radius: 999px; background: linear-gradient(90deg, var(--gold-deep), var(--gold)); transition: width .9s cubic-bezier(.2,.8,.2,1); }
.ecard .meter span { position: absolute; inset: 0; display: grid; place-items: center; font-size: 8.5px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--text); }
.ecard .shine { position: absolute; inset: 0; background: linear-gradient(115deg, transparent 38%, rgba(255,255,255,.22) 48%, rgba(169,155,255,.25) 52%, transparent 62%); transform: translateX(-120%); }
.ecard.claimed .shine { animation: sheen .9s ease-in-out 3; }
@keyframes sheen { to { transform: translateX(120%); } }
.ecard .tag {
  position: absolute; left: 50%; top: -14px; transform: translate(-50%, 6px); opacity: 0; z-index: 2;
  font-size: 10.5px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; color: #2A1B00; background: var(--gold); padding: 4px 10px; border-radius: 999px; box-shadow: 0 3px 0 var(--gold-deep); white-space: nowrap;
  transition: opacity .3s, transform .3s cubic-bezier(.34,1.56,.64,1);
}
.ecard.claimed .tag { opacity: 1; transform: translate(-50%, 0); }
.endxp {
  position: absolute; left: 50%; bottom: 6px; transform: translate(-50%, 8px); opacity: 0; transition: opacity .3s, transform .3s;
  font-family: var(--mono); font-size: 15px; color: var(--gold); font-variant-numeric: tabular-nums; text-align: center; white-space: nowrap;
}
.endxp b { font-family: var(--sans); font-size: 26px; font-weight: 900; text-shadow: 0 0 18px rgba(252,192,80,.6); }
.endxp small { display: block; font-family: var(--sans); font-size: 12px; font-weight: 700; color: var(--dim); }
.endxp.in { opacity: 1; transform: translate(-50%, 0); }
@media (max-height: 700px) { .ecard { width: min(150px, 34vh * .66); } .ecard .name { font-size: 14px; margin-top: 6px; } .ecard .line { font-size: 9.5px; } .endxp { bottom: 0; } .endxp b { font-size: 22px; } }


/* ---------- feedback sheet ---------- */
#sheet {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 18px 18px calc(16px + env(safe-area-inset-bottom)); border-radius: 24px 24px 0 0;
  transform: translateY(110%); transition: transform .3s cubic-bezier(.2,.8,.2,1); z-index: 5;
  background: var(--raised); box-shadow: 0 -10px 40px rgba(0,0,0,.5);
}
#sheet.on { transform: none; }
#sheet.ok { background: #143327; } #sheet.ok .t { color: var(--mint); } #sheet.ok .btn { background: var(--mint); color: var(--mint-ink); box-shadow: 0 5px 0 #1f8a63; }
#sheet.neu { background: #221E3F; } #sheet.neu .t { color: var(--violet-bright); } #sheet.neu .btn { background: var(--violet); color: #fff; box-shadow: 0 5px 0 #4a36b3; }
#sheet.no { background: #3A1717; } #sheet.no .t { color: #FF8A8A; } #sheet.no .btn { background: var(--red); color: #fff; box-shadow: 0 5px 0 #8f2f2f; }
#sheet.ok .btn:active { box-shadow: 0 1px 0 #1f8a63; } #sheet.neu .btn:active { box-shadow: 0 1px 0 #4a36b3; } #sheet.no .btn:active { box-shadow: 0 1px 0 #8f2f2f; }
#sheet .t { font-weight: 800; font-size: 20px; display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
#sheet .t .ic { width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center; font-size: 16px; background: currentColor; flex: none; }
#sheet .t .ic span { color: var(--bg); font-weight: 900; }
/* A wrong sheet whose title is the right answer says so above it. */
#sheet .t .tt { display: flex; flex-direction: column; gap: 1px; }
#sheet .t .k { font-size: 12px; font-weight: 900; letter-spacing: .12em; text-transform: uppercase; opacity: .85; }
#sheet .t .combo { margin-left: auto; display: inline-flex; align-items: center; padding: 4px 10px; border-radius: 999px; background: rgba(252,192,80,.16); color: var(--gold); font-size: 14px; font-weight: 800; white-space: nowrap; animation: comboIn .45s .15s cubic-bezier(.34,1.56,.64,1) both; }
@keyframes comboIn { from { opacity: 0; transform: scale(.4); } }
/* The story's report flag: a ghost 32px circle on a 44px hit area, at the title's end. */
#sheet .t .flag { margin-left: auto; flex: none; width: 44px; height: 44px; margin-right: -6px; display: grid; place-items: center; background: none; border: 0; padding: 0; }
#sheet .t .combo + .flag { margin-left: 2px; }
#sheet .t .flag svg { width: 32px; height: 32px; padding: 8.5px; border-radius: 50%; background: rgba(255,255,255,.06); border: .8px solid rgba(255,255,255,.18); fill: none; stroke: rgba(234,227,215,.55); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; box-sizing: border-box; }
#sheet .t .flag.on svg { fill: rgba(234,227,215,.55); }
#sheet .b { font-size: 15.5px; line-height: 1.45; color: var(--text); margin-bottom: 14px; text-wrap: pretty; }
/* Swipe the sheet down (or tap its handle) and it folds to its button, to see
   the scene behind it; swipe up to read it again. As the story's sheet does. */
#sheet { touch-action: none; }
#sheet .grip { display: block; width: 100%; height: 36px; margin: -18px 0 -6px; position: relative; }
#sheet .grip::before { content: ""; position: absolute; left: 50%; top: 10px; width: 36px; height: 4px; margin-left: -18px; border-radius: 2px; background: rgba(234,227,215,.3); }
#sheet .t, #sheet .b { max-height: 360px; transition: max-height .3s cubic-bezier(.2,.8,.2,1), opacity .2s, margin .3s; }
#sheet.min .t, #sheet.min .b { max-height: 0; opacity: 0; margin-bottom: 0; overflow: hidden; }
#sheet .b b { color: #fff; }
/* Report, beside the verdict: the moment a reader knows an answer is wrong. */
#sheet .t .flag { margin-left: auto; margin-right: -10px; width: 44px; height: 44px; display: grid; place-items: center; color: currentColor; opacity: .55; flex: none; }
#sheet .t .combo ~ .flag { margin-left: 0; }
#sheet .t .flag svg { width: 18px; height: 18px; }
#sheet .acts { display: flex; gap: 10px; }
#sheet .acts .btn { flex: 1; width: auto; }
#sheet .nova { flex: none; width: 52px; min-height: 52px; border-radius: 50%; display: grid; place-items: center; background: rgba(255,255,255,.08); box-shadow: 0 5px 0 rgba(0,0,0,.35); transition: transform .08s, box-shadow .08s; }
#sheet .nova:active { transform: translateY(4px); box-shadow: 0 1px 0 rgba(0,0,0,.35); }
#sheet .nova svg { width: 32px; height: 32px; }

/* toasts */
#toast { position: absolute; top: 2px; right: 18px; pointer-events: none; z-index: 6; }
/* Tappable term. The negative margin grows the hit area without moving the line. */
.term { text-decoration: underline dotted var(--gold-deep); text-decoration-thickness: 1.5px; text-underline-offset: 3px; cursor: pointer; padding: 10px 2px; margin: -10px -2px; }
.defpop { position: fixed; z-index: 40; max-width: min(320px, calc(100vw - 24px)); background: var(--raised); border: 1px solid var(--line-strong); border-radius: 12px; padding: 10px 12px; font-size: 14.5px; line-height: 1.4; color: var(--text); box-shadow: 0 8px 24px rgba(0,0,0,.5); animation: copyIn .2s ease-out both; }
.defpop b { display: block; color: var(--gold); margin-bottom: 2px; }
/* A clip: hidden until it is the answer, at its own shape (README 26). */
.clip { display: none; position: relative; margin: 0 auto; max-width: 100%; border-radius: 16px; overflow: hidden; background: #000; }
.clip.shown { display: block; }
.clip.v { height: min(50vh, 440px); aspect-ratio: 9 / 16; }
.clip.h { width: 100%; aspect-ratio: 16 / 9; }
.clip video { width: 100%; height: 100%; object-fit: contain; display: block; opacity: 0; }
.clip.live video { opacity: 1; }
.clip-cap { position: absolute; left: 10px; right: 10px; bottom: 14px; text-align: center; font: 700 15px/1.3 var(--sans); color: #fff; text-shadow: 0 1px 3px #000, 0 0 10px rgba(0,0,0,.85); pointer-events: none; }
.clip-cap:empty { display: none; }
.clip-skip { position: absolute; right: 8px; top: 8px; min-width: 64px; min-height: 44px; padding: 0 14px; border-radius: 22px; font: 700 13px var(--sans); color: #fff; background: rgba(0,0,0,.55); opacity: 0; pointer-events: none; transition: opacity .2s; }
.clip.on .clip-skip { opacity: 1; pointer-events: auto; }
.clip-gone { display: none !important; }
@media (max-height: 700px) { .clip.v { height: min(46vh, 300px); } }
.tst { font-weight: 800; color: var(--gold); font-size: 14px; background: rgba(252,192,80,.16); border: 1px solid var(--gold-deep); padding: 4px 10px; border-radius: 999px; animation: tst 1.1s ease-out both; }
.tst small { font-size: 11px; color: var(--dim); }
@keyframes tst { 0% { opacity: 0; transform: translateY(6px); } 20% { opacity: 1; } 100% { opacity: 0; transform: translateY(-26px); } }

/* ---------- screens (home, end) ---------- */
.screen { position: absolute; inset: 0; display: flex; flex-direction: column; padding: 24px 22px; background: var(--bg); z-index: 4; overflow-y: auto; }
#scene .screen { padding: 8px 0 0; z-index: 1; position: relative; inset: auto; }
#home { display: none; } #home.on { display: flex; }
.screen .eyebrow { font-size: 12px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--violet-bright); }
.screen h1 { font-family: var(--serif); font-size: 32px; line-height: 1.1; margin: 8px 0 10px; letter-spacing: -0.01em; text-wrap: balance; font-weight: 600; }
.screen p { color: var(--dim); font-size: 15.5px; margin: 0 0 16px; text-wrap: pretty; }
.screen .grow { flex: 1; }
.rows { display: flex; flex-direction: column; gap: 8px; }
.row { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 10px; padding: 12px 14px; min-height: 52px; border-radius: 14px; background: var(--surface); border: 1px solid var(--line); text-align: left; color: var(--faint); }
.row.live { color: var(--text); border-color: var(--line-strong); box-shadow: 0 4px 0 #070a14; }
.row.got { border-color: var(--gold-deep); background: rgba(252,192,80,.08); }
.row .rt { font-weight: 700; font-size: 15px; display: flex; flex-direction: column; }
.row .rt small { font-size: 11px; font-weight: 600; color: var(--dim); }
.row .st { font-size: 11.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--dim); }
.row.live .st { color: var(--violet-bright); } .row.got .st { color: var(--gold); }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}

/* ---------- takeaway: the back of the card, turned over to claim it ---------- */
#copy:empty, #look .lk-copy:empty { min-height: 0; margin: 0; }
#scene.takeaway { flex: 1 1 auto; align-items: center; justify-content: center; padding-top: 4px; }
/* The takeaway has one button and no prompt, so the room the beats hold for
   answer options and the eyebrow goes to the card. */
#stage.tk #controls { flex-basis: auto; }
#stage.tk #eyebrow { display: none; }
.tkcard { position: relative; width: min(100%, 340px); perspective: 1400px; opacity: 0; transform: translateY(46px) rotate(-3deg) scale(.94); transition: transform .7s cubic-bezier(.2,.8,.2,1), opacity .5s; }
.tkcard.in { opacity: 1; transform: none; }
.tkcard.away { opacity: 0; transform: translateY(-24px) scale(.9); transition-duration: .4s; }
.tk-inner { position: relative; transform-style: preserve-3d; transition: transform .9s cubic-bezier(.3,.7,.2,1); }
.tkcard.flipped .tk-inner { transform: rotateY(180deg); }
.tk-back, .tk-front { backface-visibility: hidden; -webkit-backface-visibility: hidden; }
/* The back has the real card's shape and corners; engine.js sizes it and sets --r. */
.tk-back { position: relative; border-radius: var(--r, 22px); overflow: hidden; border: 1.5px solid rgba(234,227,215,.22); box-shadow: 0 24px 50px rgba(0,0,0,.55); padding: 20px 20px 24px; display: flex; flex-direction: column;
  background: radial-gradient(120% 70% at 100% 0%, rgba(123,92,253,.28), transparent 60%), radial-gradient(90% 60% at 0% 100%, rgba(252,192,80,.14), transparent 60%), linear-gradient(160deg, #1d2440 0%, #101528 55%, #1a1f3a 100%); }
.tk-back::before { content: ""; position: absolute; inset: 7px; border-radius: max(4px, calc(var(--r, 22px) - 7px)); border: 1px solid rgba(252,192,80,.22); pointer-events: none; }
.tkcard.foil .tk-back { border-color: rgba(169,155,255,.8); }
.tkcard.gold .tk-back { border-color: var(--gold); }
.tk-head { display: grid; gap: 2px; padding-bottom: 14px; margin-bottom: 18px; border-bottom: 1px solid rgba(234,227,215,.14); }
.tk-head span { font-size: 12px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; color: var(--gold); }
.tk-head b { font-family: var(--serif); font-size: 27px; font-weight: 700; line-height: 1.1; color: #fff; text-wrap: balance; }
.tk-lines { flex: none; display: grid; gap: calc(var(--tk-fs, 19px) * .9); }
/* What the words leave over goes mostly under them. */
.tk-sp { flex: 2 1 0; } .tk-sp.b { flex-grow: 3; }
.tk-line { display: grid; grid-template-columns: 24px 1fr; gap: 10px; align-items: start; opacity: 0; transform: translateY(10px); transition: opacity .5s, transform .5s cubic-bezier(.2,.8,.2,1); }
.tk-line.in { opacity: 1; transform: none; }
.tk-line p { margin: 0; font-family: var(--serif); font-size: var(--tk-fs, 19px); line-height: 1.36; font-weight: 500; color: var(--text); text-wrap: pretty; }
.tk-line p b { font-weight: 700; color: #fff; -webkit-box-decoration-break: clone; box-decoration-break: clone; background: linear-gradient(transparent 60%, rgba(252,192,80,.42) 60%) no-repeat left / 0% 100%; transition: background-size .8s .35s cubic-bezier(.2,.8,.2,1); }
.tk-line.in p b { background-size: 100% 100%; }
.tk-tick { width: 22px; height: 22px; margin-top: 3px; fill: none; stroke: var(--gold); stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 24; stroke-dashoffset: 24; transition: stroke-dashoffset .45s .1s ease-out; }
.tk-line.in .tk-tick { stroke-dashoffset: 0; }
.tk-shine { position: absolute; inset: 0; pointer-events: none; background: linear-gradient(115deg, transparent 38%, rgba(255,255,255,.14) 48%, rgba(169,155,255,.16) 52%, transparent 62%); transform: translateX(-120%); }
.tkcard.in .tk-shine { animation: sheen 1.4s .3s ease-in-out 1; }
/* The front is the ending's own card, laid out at the ending's size and scaled
   up to fill the takeaway, so it can be handed over without changing. */
.tk-front { position: absolute; inset: 0; transform: rotateY(180deg); }
.tkcard .tk-front > .ecard { left: 0; top: 0; transform-origin: 0 0; transform: scale(var(--k, 1)); transition: none; }
.btn.tk-cta { position: relative; overflow: hidden; animation: tkIn .45s cubic-bezier(.2,.8,.2,1) both; }
.btn.tk-cta::after { content: ""; position: absolute; top: 0; bottom: 0; left: -60%; width: 45%; background: linear-gradient(100deg, transparent, rgba(255,255,255,.6), transparent); animation: tkShine 1.5s .5s ease-in-out 2; }
@keyframes tkIn { from { opacity: 0; transform: translateY(10px); } }
@keyframes tkShine { to { left: 130%; } }
@media (max-height: 700px) {
  .tk-back { padding: 16px 16px 18px; }
  .tk-head { padding-bottom: 10px; margin-bottom: 12px; } .tk-head b { font-size: 22px; }
  .tk-lines { gap: 12px; } .tk-line p { font-size: var(--tk-fs, 16.5px); line-height: 1.32; }
}
@media (prefers-reduced-motion: reduce) { .btn.tk-cta::after, .tkcard.in .tk-shine { animation: none; } }
