/* Fredoka (SIL Open Font License, web/fonts/OFL.txt), latin subset, weights 400-700 */
@font-face { font-family: Fredoka; src: url(fonts/fredoka.woff2) format("woff2"); font-weight: 400 700; font-display: swap; }
/* Spellpet, style A (Daylight) with B's magic touches. Buttons, panels and icons are Codex art in web/img/kit/; no emoji.
   Game frame: one portrait 390x844 stage, scaled to fit any screen. Sizes are in cqw (1cqw = 1% of the stage width),
   so everything keeps the same proportions on a small phone, a big phone or an iPad. */
:root { --ink: #3b1f73; --violet: #6c3fd1; }
html, body { height: 100%; margin: 0; overflow: hidden; overscroll-behavior: none; }
body { font-family: Fredoka, ui-rounded, system-ui, sans-serif; color: var(--ink);
  background: #d9cdf6;
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
input { -webkit-user-select: text; user-select: text; }

/* #app is the stage (the size container, always 390:844); .frame inside it holds the zones, so cqw = % of the stage.
   The world picture is height-fitted to the stage, so its magic ring is always at the same spot (see .hero). */
#app { position: fixed; inset: 0; margin: auto; container-type: size;
  width: min(var(--vw, 100vw), var(--vh, 100dvh) * 390 / 844); height: min(var(--vh, 100dvh), var(--vw, 100vw) * 844 / 390); }
/* World picture, centred on the stage at height Hi = max(stage height, screen height), so on a phone it fills the screen
   and the ring stays where .hero puts it. On wide screens (iPad) its sides fade into a blurred copy that fills the rest. */
body::before { content: ''; position: fixed; inset: -40px; background: url(img/world/lake.jpg) center / cover; filter: blur(24px) saturate(1.1); }
#app::before { content: ''; position: absolute; left: 50%; top: 50%; translate: -50% -50%; z-index: -1; height: max(100cqh, var(--vh, 100dvh)); aspect-ratio: 941 / 1672;
  background: url(img/world/lake.jpg) center / cover; }
@media (min-aspect-ratio: 941 / 1672) { #app::before { mask: linear-gradient(90deg, #0000, #000 6%, #000 94%, #0000); } } /* only when the screen is wider than the picture */
.frame { position: relative; box-sizing: border-box; height: 100%; display: grid; grid-template-rows: auto minmax(0, 1fr) auto auto; grid-template-columns: minmax(0, 1fr);
  text-align: center; font-size: 5.6cqw; line-height: 1.3;
  padding: max(3cqw, env(safe-area-inset-top)) 5cqw max(4cqw, env(safe-area-inset-bottom)); }
.hud { display: flex; align-items: center; justify-content: center; gap: 2cqw; min-height: 15cqw; z-index: 2; }
.mid { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 2cqw; min-height: 0; z-index: 2; }
.act { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 2cqw; min-height: 20cqw; z-index: 2; }
.lb .mid { overflow-y: auto; padding-top: 2cqw; }
.spell .act { min-height: 10cqw; }
.spell .mid { padding-top: 5cqw; gap: 4cqw; } /* room between the top buttons and the answer card */

h1, h2, p { margin: 0; }
.title { font-size: 10cqw; font-weight: 700; line-height: 1.1; color: #ffcf3a; letter-spacing: .3cqw;
  text-shadow: .8cqw 0 var(--ink), -.8cqw 0 var(--ink), 0 .8cqw var(--ink), 0 -.8cqw var(--ink), .55cqw .55cqw var(--ink), -.55cqw .55cqw var(--ink), .55cqw -.55cqw var(--ink), -.55cqw -.55cqw var(--ink), 0 1.6cqw var(--ink); }
.logo img { width: 72cqw; display: block; margin: 1cqw auto 0; }
.splash .logo img { width: 86cqw; margin-top: 8cqw; }

/* Buttons are drawn art; words go on top in code. */
.btn { border: 0; padding: 0; margin: 0; background: center / 100% 100% no-repeat; font: inherit; font-weight: 700; color: var(--ink);
  cursor: pointer; touch-action: manipulation; flex: none; }
.btn:active:not(:disabled) { transform: translateY(.8cqw) scale(.97); filter: brightness(.94); }
.btn:disabled { opacity: .4; }
.pill { width: 58cqw; aspect-ratio: 512 / 217; padding-bottom: 1.6cqw; font-size: 8cqw; background-image: url(img/kit/btn-pill.png); }
.mic { width: 26cqw; aspect-ratio: 370 / 380; background-image: url(img/kit/btn-mic.png); }
.mic.on { background-image: url(img/kit/btn-stop.png); }
.word, .sentence, .back, .delete, .add { width: 15cqw; aspect-ratio: 353 / 372; }
.word { margin-left: auto; background-image: url(img/kit/btn-word.png); }
.sentence { background-image: url(img/kit/btn-sentence.png); }
.back { background-image: url(img/kit/btn-back.png); }
.delete { background-image: url(img/kit/btn-delete.png); }
.add { width: 18cqw; background-image: url(img/kit/btn-add.png); }
.tile { width: 16cqw; aspect-ratio: 1; padding-bottom: 1.3cqw; font-size: 8.5cqw; background-image: url(img/kit/tile.png); }
.tile:disabled { background-image: url(img/kit/tile-down.png); }
.parent { flex-basis: 100%; font: inherit; font-size: 3.6cqw; color: var(--violet); background: none; border: 0; }

/* Cards (9-sliced so the round corners keep their shape at any size). */
.card { box-sizing: border-box; border-style: solid; border-width: 4cqw 5cqw; border-image: url(img/kit/card.png) 60 70 fill stretch; }
.cloud { display: grid; place-items: center; box-sizing: border-box; width: 100%; min-height: 24cqw; font: inherit; color: var(--ink);
  border-style: solid; border-width: 5cqw 6cqw; border-image: url(img/kit/card-answer.png) 60 70 fill stretch; }
.cloud input { width: 100%; border: 0; padding: 0; background: none; outline: none; font: inherit; color: inherit; text-align: center; }
.cloud input::placeholder { color: #a593cf; }
.answer, .cloud .answer { font-size: 11cqw; font-weight: 700; letter-spacing: .8cqw; }
.say { font-size: 5.6cqw; line-height: 1.25; } .ok { color: #2a8a3e; } .no { color: #c0661a; }
.said .cloud { margin-top: 4cqw; }

/* Spelling: answer box at the top of the stage, controls pushed down to the thumb zone. */
#in { flex: 1; display: flex; width: 100%; min-height: 0; }
.stage-pet { flex: 1; min-height: 0; width: 100%; display: grid; place-items: center; }
.stage-pet .mini { width: 34cqw; height: 34cqw; }
.answer-area { flex: 1; min-height: 0; display: flex; flex-direction: column; align-items: center; gap: 3cqw; }
.tiles { display: flex; flex-wrap: wrap; justify-content: center; gap: 2cqw; }
.controls { margin-top: auto; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 3cqw; }
.controls .mic { flex-basis: 100%; max-width: 26cqw; }
.hint { flex-basis: 100%; font-size: 4cqw; color: var(--ink); min-height: 1em; }

/* Top bar: coins and gems chips, level badge on the right. */
.chip { display: inline-flex; align-items: center; gap: 1.5cqw; height: 10cqw; box-sizing: border-box; padding: 0 1cqw 0 0; font-weight: 700; font-size: 5.6cqw;
  border-style: solid; border-width: 0 4.5cqw; border-image: url(img/kit/chip.png) 0 66 fill stretch; }
.chip .ico { height: 7.5cqw; margin-left: -2.5cqw; }
.badge { margin-left: auto; width: 14cqw; aspect-ratio: 261 / 266; display: grid; place-items: center; padding-bottom: .5cqw; box-sizing: border-box;
  background: url(img/kit/level-badge.png) center / contain no-repeat; color: #fff; font-weight: 700; font-size: 6.4cqw; text-shadow: 0 .4cqw var(--ink); }
.row { display: flex; justify-content: center; flex-wrap: wrap; gap: 3cqw; }
.name { font-weight: 700; font-size: 6.4cqw; }

/* My Pet card and XP bar. Bar: drawn track and fill, 9-sliced so the round ends keep their shape. --p = percent. */
/* Pet card: one slim row (name, Lv, bar, XP) under the logo. */
.mypet { width: 80cqw; margin-top: 1cqw; border-width: 2.4cqw 4cqw; display: flex; align-items: center; gap: 2.5cqw; }
.mypet .name { font-size: 5cqw; max-width: 22cqw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mypet .xp { flex: 1; font-size: 3.4cqw; gap: 1.5cqw; } .mypet .xp .lv { font-size: 3.8cqw; } .mypet .bar { height: 4cqw; }
.xp { display: flex; align-items: center; gap: 2cqw; font-size: 3.8cqw; font-weight: 600; }
.xp .lv { font-weight: 700; font-size: 4.4cqw; }
.xp .n { white-space: nowrap; }
.bar { flex: 1; box-sizing: border-box; height: 5.5cqw; padding: .8cqw 0;
  border-style: solid; border-width: 0 2.8cqw; border-image: url(img/kit/bar-track.png) 0 29 fill stretch; }
.bar i { display: block; box-sizing: border-box; height: 100%; margin-left: -2cqw; min-width: 4cqw; width: calc((100% + 4cqw) * var(--p) / 100);
  border-style: solid; border-width: 0 2cqw; border-image: url(img/kit/bar-fill.png) 0 28 fill stretch; transition: width .6s; }
.dots { display: flex; justify-content: center; gap: 1.6cqw; }
.dots i { width: 5cqw; height: 5cqw; background: url(img/kit/dot.png) center / contain no-repeat; }
.dots i.on { background-image: url(img/kit/dot-on.png); }

/* Home shortcuts: small tiles with an icon and a label. */
.shortcuts { display: flex; justify-content: center; gap: 4cqw; flex-basis: 100%; margin: 3cqw 0 3cqw; }
.home .pill { width: 50cqw; font-size: 7.4cqw; }
.short { width: 15cqw; aspect-ratio: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .5cqw;
  padding-bottom: 1.5cqw; box-sizing: border-box; background-image: url(img/kit/tile.png); font-size: 2.9cqw; }
.short .ico { height: 7.5cqw; }

/* Bottom tab bar. */
.tabs { display: flex; justify-content: space-around; margin: 1cqw -3cqw 0; padding: 0; height: 18cqw; box-sizing: border-box; z-index: 2;
  border-style: solid; border-width: 0 9cqw; border-image: url(img/kit/tabbar.png) 0 72 fill stretch; }
.tab { flex: 1; margin: 0 -3cqw; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .3cqw; border: 0; background: none;
  font: inherit; font-size: 3.3cqw; font-weight: 600; color: var(--ink); padding: 0; }
.tab .ico { height: 8.5cqw; }
.tab.on { margin: 1.5cqw 0 2.5cqw; background: url(img/kit/tab-on.png) center / 100% 100% no-repeat; color: #fff; }
.tab:disabled { opacity: .45; }

/* End of a round: ribbon title, stars, rewards. */
.ribbon { width: 84cqw; aspect-ratio: 512 / 150; display: grid; place-items: center; grid-template-rows: 61% 1fr; /* band is the top 61% of the art; tails below */ box-sizing: border-box;
  background: url(img/kit/ribbon.png) center / contain no-repeat; color: #fff; font-size: 7cqw; text-shadow: 0 .5cqw var(--ink); }
.stars { display: flex; align-items: flex-end; gap: 1cqw; }
.stars .star { width: 14cqw; animation: pop .4s cubic-bezier(.3, 1.4, .5, 1) backwards; }
.stars .star:nth-child(2) { width: 17cqw; margin-bottom: 1.5cqw; animation-delay: .15s; }
.stars .star:nth-child(3) { animation-delay: .3s; }
.done .say { flex-basis: 100%; font-weight: 700; text-shadow: 0 0 2cqw #fff, 0 0 1cqw #fff; }
@keyframes pop { from { transform: scale(.4); opacity: 0; } }

/* Leaderboard row on a white card. */
.plate { display: flex; align-items: center; gap: 2.5cqw; box-sizing: border-box; width: 100%; height: 19.5cqw; padding: 0; flex: none;
  background: none; border-style: solid; border-width: 2cqw 5cqw; border-image: url(img/kit/card.png) 60 70 fill stretch;
  font-size: 6.2cqw; text-align: left; }
.plate.me { filter: drop-shadow(0 0 1.5cqw #ffd23f) drop-shadow(0 0 .5cqw #ffd23f); }
.plate .rank { width: 10cqw; text-align: center; font-weight: 700; } .plate .medal { width: 9cqw; display: block; margin: auto; }
.plate .mini { width: 13cqw; height: 13cqw; }
.plate .who { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.plate .n { display: inline-flex; align-items: center; gap: 1.5cqw; } .plate .n .ico { height: 6.7cqw; }

.mini { width: 18cqw; height: 18cqw; display: grid; place-items: center; }
.mini img { width: 100%; height: 100%; object-fit: contain; animation: bob 1.6s ease-in-out infinite; }
.mini.thinking { transform: rotate(-8deg); } .mini.sleepy img { animation: none; filter: saturate(.5); }
.boss img { width: 30cqw; height: auto; animation: bob 2s ease-in-out infinite; }
.egg { width: 24cqw; border: 0; padding: 0; background: none; } .egg img { width: 100%; display: block; animation: bob 2.4s ease-in-out infinite; }
.egg:active img { transform: scale(.94); }

/* The pet on the world's magic ring: 51% across, 57% down the picture (Hi tall, see #app::before), centred on the stage. */
.hero { position: absolute; left: calc(50% + .0056 * max(100cqh, var(--vh, 100dvh))); top: calc(50% + .07 * max(100cqh, var(--vh, 100dvh))); width: 0; height: 0; z-index: 1; }
.hero .sprite { position: absolute; left: 0; bottom: 0; translate: -50% 0; width: 36cqw; } /* width per form: pets.json w */
.sprite img { display: block; width: 100%; animation: bob 1.6s ease-in-out infinite; }
.sprite .egg-img { animation: bob 2.4s ease-in-out infinite; }
.sprite::after { content: ''; position: absolute; z-index: -1; left: 18%; width: 64%; bottom: -4%; aspect-ratio: 4; border-radius: 50%; background: rgba(59, 31, 115, .22); }
.hero.thinking .sprite { transform: rotate(-6deg); transition: transform .3s; }
.hero.sleepy .sprite > * { animation: none; filter: saturate(.5) brightness(.9); }
.sprite.grew { animation: hatchpop .8s cubic-bezier(.3, 1.4, .5, 1) .3s backwards; transform-origin: 50% 100%; }
@keyframes bob { 50% { transform: translateY(-4%); } }

.ico { height: 1em; vertical-align: -0.15em; }
.steps { margin: 3cqw 5cqw; padding: 3cqw 4cqw 3cqw 9cqw; font-size: 4.4cqw; line-height: 1.35; text-align: left; background: #ffffffd8; border-radius: 4cqw; } .steps li { margin: 1cqw 0; }
/* Hatching (~3 s): egg wobbles, cracks, cracks more, shell splits, pet pops out. Each egg frame is hidden
   except while its own animation runs, so they hand over one to the next. */
.eggs { position: relative; width: 100%; }
.eggs img { position: absolute; left: 0; top: 0; width: 100%; opacity: 0; transform-origin: 50% 90%; } /* frames share the egg's canvas (scripts/hatch-frames.py) */
.eggs .h0 { position: static; display: block; width: 100%; animation: wobble .3s ease-in-out 0s 3; }
.eggs .h0.solo { animation: wobble .3s ease-in-out 0s 8; } /* no crack frames: wobble until the pop */
.eggs .h1 { animation: wobble .27s ease-in-out .9s 3; }
.eggs .h2 { animation: wobble .18s ease-in-out 1.7s 4; }
.eggs .top { animation: fly .8s ease-out 2.42s; }
.eggs .bot { animation: fade 1.2s ease-in 2.42s; }
.hero .hatching { z-index: 1; }
.sprite.hatching::after { display: none; }
.sprite.hatched { animation: hatchpop .8s cubic-bezier(.3, 1.4, .5, 1) 2.42s backwards; transform-origin: 50% 100%; }
@keyframes wobble { 0%, 100% { opacity: 1; transform: rotate(0); } 25% { opacity: 1; transform: rotate(-6deg); } 75% { opacity: 1; transform: rotate(6deg); } }
@keyframes fly { from { opacity: 1; } to { opacity: 0; transform: translate(-60%, -160%) rotate(-50deg); } }
@keyframes fade { 0%, 50% { opacity: 1; } to { opacity: 0; } }
@keyframes hatchpop { from { transform: scale(0); } }
.opts { display: flex; flex-direction: column; gap: 2.5cqw; padding: 4cqw; margin: 0 4cqw; background: #ffffffd8; border-radius: 5cqw; }
.opts .name { font-size: 5cqw; margin: 2cqw 0 0; }
.opts .tile { font-size: 5cqw; }
.opts .tile:not(.on):not([data-peek]) { opacity: .5; }
.opts .parent { margin-top: 3cqw; font-size: 4.4cqw; color: #c0661a; text-decoration: underline; }
/* Outfits on the pet (web/img/outfits). Back items sit behind the pet, above its ground shadow. */
.sprite .wear { position: absolute; display: block; max-width: none; }
.sprite .wear.behind { z-index: -1; }
.sprite:has(.wear.behind)::after { z-index: -2; }
.closet { display: grid; grid-template-columns: repeat(3, 19cqw); justify-content: center; gap: 2.5cqw 4cqw; }
.closet .tile { width: 19cqw; padding: 0; position: relative; display: grid; place-items: center; }
.closet .tile img { width: 72%; max-height: 72%; object-fit: contain; }
.closet .tile.on { transform: translateY(-1cqw); filter: drop-shadow(0 0 1.6cqw #ffcf3a) drop-shadow(0 0 .6cqw #ffcf3a); }
.closet .tile:disabled { opacity: 1; background-image: url(img/kit/tile.png); }
.closet .tile:disabled img { filter: grayscale(1); opacity: .45; }
.closet .need { position: absolute; bottom: 1.5cqw; display: flex; align-items: center; gap: .5cqw; font-size: 4.2cqw; font-weight: 700; }
.closet .need .ico { height: 4.6cqw; }
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation: none !important; transition: none !important; } }

/* Story level: hearts in the top bar, the place name over the answer card. */
.hearts { display: flex; gap: .5cqw; } .hearts .ico { height: 8cqw; }
.where { font-weight: 700; font-size: 5cqw; color: #fff; text-shadow: 0 .4cqw var(--ink), 0 0 1.5cqw var(--ink); }
.pill.violet { background-image: url(img/kit/btn-pill-violet.png); color: #fff; }
.pill.half { width: 42cqw; font-size: 6.4cqw; }

/* Quests: segmented Daily / Story / Challenge, then a scrolling list of cards. */
.quests .ribbon { width: 64cqw; font-size: 6cqw; margin: 0; }
.seg { display: flex; gap: 1cqw; padding: 1cqw; border-radius: 6cqw; background: #ffffffd8; box-shadow: inset 0 0 0 .5cqw #c9b6f2; }
.seg button { font: inherit; font-size: 4.4cqw; font-weight: 700; color: var(--ink); border: 0; border-radius: 5cqw; padding: 1.5cqw 4cqw; background: none; }
.seg .on { background: var(--violet); color: #fff; box-shadow: inset 0 -.8cqw 0 #0002; }
.list { flex: 1; min-height: 0; width: 100%; overflow-y: auto; display: flex; flex-direction: column; align-items: center; gap: 2cqw; padding-bottom: 2cqw; }
.quest { width: 100%; display: flex; align-items: center; gap: 3cqw; text-align: left; flex: none; }
.quest .qi { height: 12cqw; width: 12cqw; object-fit: contain; }
.qt { flex: 1; } .qt p { font-weight: 700; font-size: 4.8cqw; } .qt small { font-size: 3.6cqw; } .qt small .ico { height: 4cqw; }
.reward { width: 17cqw; aspect-ratio: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; font-size: 4cqw;
  background-image: url(img/kit/tile.png); padding-bottom: 1cqw; }
.reward .ico { height: 6cqw; }
.reward.ready { background-image: url(img/kit/btn-square-gold.png); animation: pop .5s; }
.reward:disabled { opacity: .55; }
.list .pill { flex: none; margin-top: 2cqw; }
.place { width: 100%; flex: none; }
.pn { font-weight: 700; font-size: 5cqw; text-align: left; } .pn small { font-weight: 500; font-size: 3.6cqw; color: var(--violet); }
.nodes { display: flex; flex-wrap: wrap; gap: 2cqw 3cqw; margin-top: 1cqw; }
.node { width: 15cqw; aspect-ratio: 330 / 336; position: relative; display: grid; place-items: center; padding-bottom: 2cqw;
  background-image: url(img/kit/node.png); font-size: 6cqw; }
.node.done { background-image: url(img/kit/node-done.png); color: #fff; text-shadow: 0 .4cqw #a8670c; }
.node:disabled { opacity: .55; }
.node .lk { height: 6.5cqw; }
.mini-stars { position: absolute; bottom: -2.2cqw; left: 50%; translate: -50% 0; display: flex; }
.mini-stars .ico { height: 4cqw; }
.pill.wide { width: 66cqw; font-size: 6.6cqw; }

/* Parents: a small lock in the home top bar. */
.gear { width: 9cqw; aspect-ratio: 1; margin-left: 1cqw; background-image: url(img/kit/gear.png); } /* Settings */

/* Decor in the world: x, y, w in px of the 941x1672 picture (Hi tall, centred on the stage, as .hero). Base at x, y. */
.deco { position: absolute; z-index: 0; pointer-events: none; --H: max(100cqh, var(--vh, 100dvh));
  left: calc(50% + (var(--x) / 941 - .5) * var(--H) * .5628); top: calc(50% + (var(--y) / 1672 - .5) * var(--H));
  width: calc(var(--w) / 941 * var(--H) * .5628); translate: -50% -100%; animation: pop .5s ease-out both; }
.deco.front { z-index: 1; }

/* Shop: 2-column grid of item cards. */
.goods { display: grid; grid-template-columns: 1fr 1fr; gap: 2.5cqw; width: 100%; }
.good { position: relative; display: flex; flex-direction: column; align-items: center; gap: .5cqw; font-size: 4cqw; color: var(--ink); }
.good img { height: 17cqw; max-width: 100%; object-fit: contain; }
.gn { font-weight: 600; font-size: 3.8cqw; }
.price { display: flex; align-items: center; gap: 1cqw; font-weight: 700; } .price .ico { height: 5cqw; }
.good.have .price { color: #2a8a3e; }
.count { position: absolute; top: -1cqw; right: -1cqw; min-width: 7cqw; height: 7cqw; border-radius: 4cqw; display: grid; place-items: center;
  background: var(--violet); color: #fff; font-size: 4cqw; font-weight: 700; box-shadow: 0 0 0 .6cqw #fff; }
.shop .hint { flex: none; margin-top: 1cqw; font-weight: 600; text-shadow: 0 0 1.5cqw #fff, 0 0 1cqw #fff; }
.closet .tile.locked img { filter: grayscale(1); opacity: .45; }

/* My Pet: Feed / Care / Play, the food tray, the snack flying to the pet, hearts from a pat. */
.petroom .mid, .petroom .act { pointer-events: none; } .petroom .mid > *, .petroom .act > * { pointer-events: auto; }
.petroom .hero { cursor: pointer; } .petroom .hero .sprite { pointer-events: auto; }
.care-row, .tray { display: flex; justify-content: center; flex-wrap: wrap; gap: 3cqw; flex-basis: 100%; }
.snack { position: relative; width: 17cqw; padding: 0; display: grid; place-items: center; } .snack img { width: 72%; }
.eaten { position: absolute; z-index: 3; left: 50%; top: 80%; width: 14cqw; translate: -50% -50%; animation: munch .8s ease-in forwards; pointer-events: none; }
@keyframes munch { to { top: calc(50% + .03 * max(100cqh, var(--vh, 100dvh))); transform: scale(.2); opacity: 0; } }
.float-heart { position: absolute; left: 0; bottom: 40cqw; width: 7cqw; translate: -50% 0; opacity: 0; pointer-events: none; animation: floatup 1.2s ease-out forwards; }
@keyframes floatup { 15% { opacity: 1; } to { opacity: 0; transform: translate(var(--dx), -22cqw) scale(1.3); } }

/* Library: word card on top, words as chips coloured by status (also used on the parents' progress page). */
.wordcard { width: 100%; flex: none; display: flex; flex-direction: column; align-items: center; gap: 1.5cqw; }
.wordcard .big { font-size: 10cqw; font-weight: 700; letter-spacing: .5cqw; line-height: 1; }
.wordcard .def { font-size: 4.4cqw; } .wordcard .bar { flex: none; width: 70cqw; }
.wordcard .word { margin-left: 0; width: 13cqw; } .wordcard .sentence { width: 13cqw; }
.key { display: flex; gap: 1.5cqw; justify-content: center; flex-wrap: wrap; }
.wchips { display: flex; flex-wrap: wrap; gap: 1.5cqw; margin-top: 1.5cqw; }
.wchip { font: inherit; font-size: 3.8cqw; font-weight: 600; border: 0; border-radius: 4cqw; padding: .8cqw 2.6cqw; color: var(--ink);
  background: #f1ecfb; box-shadow: inset 0 -.6cqw 0 #0001; }
.wchip.st-mastered { background: #ffd54a; } .wchip.st-learning { background: #d9ccff; } .wchip.st-tricky { background: #ffc79a; }
.wchip.st-new { color: #9a8cc0; }
.wchip.on { outline: .7cqw solid var(--violet); }
/* Parents' progress page. */
.report { gap: 1.8cqw; text-align: left; }
.stack { display: flex; height: 5cqw; border-radius: 3cqw; overflow: hidden; background: #f1ecfb; }
.stack i { height: 100%; } .stack .st-mastered { background: #ffc93c; } .stack .st-learning { background: #a98bff; } .stack .st-tricky { background: #ff9d57; }
.unit { display: flex; align-items: baseline; gap: 2cqw; font-size: 4.2cqw; } .unit small { color: var(--violet); flex: 1; }
.tricky { display: flex; flex-wrap: wrap; gap: 1.5cqw; font-size: 4cqw; }

/* Unscramble: slots on top, mixed-up letters below. Tile size fits the longest word (--n letters) on one row. */
.game .title { margin-top: 4cqw; }
.scramble { --t: min(15cqw, 88cqw / var(--n) - 1.5cqw); display: flex; flex-direction: column; align-items: center; gap: 8cqw; margin-top: 6cqw; width: 100%; }
.slots, .pool { display: flex; justify-content: center; gap: 1.5cqw; }
.scramble .tile { width: var(--t); font-size: calc(var(--t) * .55); touch-action: none; }
.slot.empty { background: #ffffff70; border-radius: 3cqw; box-shadow: inset 0 0 0 .6cqw #c9b6f2; }
.pool .tile:disabled { opacity: 0; }
.slots.right .tile { filter: drop-shadow(0 0 1.5cqw #7be07b); animation: pop .4s; }
.slots.shake { animation: shake .5s; }
@keyframes shake { 20%, 60% { transform: translateX(-3cqw); } 40%, 80% { transform: translateX(3cqw); } }
.ghost { position: fixed; z-index: 10; margin: 0; pointer-events: none; font-size: 7vw; scale: 1.1; filter: drop-shadow(0 2vw 2vw #0003); }
.act > .row { flex-basis: 100%; }

/* Start-over card. */
/* "Your pet grew!" clip (Jamal pod), over the level-complete screen. */
.clip { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 20; transition: opacity .4s; }
.clip.out { opacity: 0; }
/* Parents: six settings fit one phone screen. */
.opts { gap: 1.2cqw; padding: 3cqw 4cqw; }
.opts .name { margin-top: 1cqw; font-size: 4.6cqw; }
.opts .tile { width: 13cqw; font-size: 4.4cqw; }
.opts .pill.wide { width: 50cqw; font-size: 5cqw; align-self: center; margin-bottom: 1cqw; } /* centred: .opts is a stretch column */

/* Library: each place folds open (native <details>), so the page is short and nothing is cut off at the bottom. */
.place summary { list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between; }
.place summary::-webkit-details-marker { display: none; }
.place summary::after { content: '+'; font-weight: 700; font-size: 6cqw; color: var(--violet); }
.place[open] summary::after { content: '\2013'; }
.place[open] .wchips { margin-top: 1.5cqw; }
/* Quests: room between the ribbon and the tabs under it. */
.quests .ribbon + .seg { margin-top: 1.5cqw; }
/* Wardrobe: one sheet docked to the bottom, ribbon title sitting on its top edge, so the outfits belong to the pet above. */
.closet-screen .act { margin: 0 -5cqw calc(-1 * max(4cqw, env(safe-area-inset-bottom)) - 6cqw); }
.sheet { position: relative; width: 100%; padding: 9cqw 0 calc(max(4cqw, env(safe-area-inset-bottom)) + 6cqw); display: flex; flex-direction: column; align-items: center; gap: 3cqw; }
.sheet .ribbon { position: absolute; top: -12cqw; left: 50%; translate: -50% 0; width: 70cqw; font-size: 6.4cqw; margin: 0; }
.sheet .pill { width: 50cqw; font-size: 7cqw; }
.closet-screen .deco { display: none; } /* dressing up: just the pet */
/* Colour trial (?look=A|B|C on the URL): calm the world so the pet is the focal point. Pick one, then bake it in. */
#app::after { content: ''; position: absolute; left: 50%; top: 50%; translate: -50% -50%; z-index: -1; pointer-events: none;
  height: max(100cqh, var(--vh, 100dvh)); aspect-ratio: 941 / 1672; }
[data-look=A] #app::before { filter: saturate(.55); }
[data-look=A] #app::after { background: radial-gradient(ellipse 45% 26% at 51% 54%, #fff8d040, #0000 70%); }
[data-look=B] #app::before { filter: saturate(.5) brightness(1.08); }
[data-look=B] #app::after { background: linear-gradient(#f3ecff55, #f3ecff70); }
[data-look=C] #app::before { filter: saturate(.6) brightness(.68); }
[data-look=C] #app::after { background: radial-gradient(ellipse 42% 24% at 51% 54%, #fff3b8aa, #fff3b800 70%); mix-blend-mode: screen; }
