/* Uppies v3: Game tab. Light studio (DESIGN.md). Tokens from base.css only, no hard-coded colours.
   Pixel art: --s is the CSS size of one art pixel, chosen by game.js so that --s x devicePixelRatio is an integer
   (each art pixel is a whole number of device pixels). Every pet motion moves in whole art pixels, never scales. */

/* ---------- studio floor (shared by Play and How it works) ---------- */
.view-play, .how-stage { position: relative; isolation: isolate; overflow: clip; }
/* the studio key light: --key fading into the wall (no white glow, no hard-coded colour) */
.view-play {
  background:
    radial-gradient(38% 42% at 50% 46%, var(--key) 0%, color-mix(in srgb, var(--key) 55%, transparent) 50%, color-mix(in srgb, var(--key) 0%, transparent) 100%),
    linear-gradient(to bottom, var(--wall-top) 0%, var(--wall) 40%);
}
.floor {
  position: absolute; z-index: -1; left: 50%; width: 400vw; transform: translateX(-50%);
  top: 74%; height: 200vh; pointer-events: none;
  background: linear-gradient(to bottom, var(--floor-far) 0%, color-mix(in srgb, var(--floor-far), var(--floor-near)) 18vh, var(--floor-near) 36vh);
}
.floor::before {
  content: ''; position: absolute; left: 0; right: 0; bottom: 100%; height: 140px;
  background: linear-gradient(to bottom, color-mix(in srgb, var(--floor-far) 0%, transparent), color-mix(in srgb, var(--floor-far) 35%, transparent) 45%, color-mix(in srgb, var(--floor-far) 80%, transparent) 80%, var(--floor-far));
}

/* a pet standing on the floor: canvas + two-layer contact shadow */
.device, .how-pet { position: relative; flex: none; width: calc(var(--s, 7) * 64px); height: calc(var(--s, 7) * 64px); }
.device canvas, .how-pet canvas { position: absolute; left: 0; top: 0; display: block; width: 100%; height: 100%; image-rendering: pixelated; image-rendering: crisp-edges; }
.device-pet, .device-ov, .how-pet canvas { z-index: 1; }
.device::before, .device::after, .how-pet::before, .how-pet::after { content: ''; position: absolute; z-index: 0; pointer-events: none; border-radius: 50%; }
.device::after, .how-pet::after {
  left: 22%; right: 22%;
  bottom: calc(var(--s, 7) * 4px - var(--s, 7) * 1.6px);
  height: calc(var(--s, 7) * 3.2px);
  background: radial-gradient(closest-side, rgb(var(--shade) / .5), rgb(var(--shade) / .2) 60%, rgb(var(--shade) / 0));
  filter: blur(calc(var(--s, 7) * .5px));
  transition: transform .26s var(--ease);
}
.device::before, .how-pet::before {
  left: 8%; right: 8%;
  bottom: calc(var(--s, 7) * 4px - var(--s, 7) * 5px);
  height: calc(var(--s, 7) * 10px);
  background: radial-gradient(closest-side, rgb(var(--shade) / .16), rgb(var(--shade) / 0));
}
.device .floor, .how-pet .floor { top: calc(100% - var(--s, 7) * 9px); }

/* the device body moves as one (canvases + hotspots); the floor shadow stays and reacts.
   Motion is stepped (step-end) in whole art pixels and moves the box itself (top / left), not a transform: an
   animated transform is drawn through a compositor layer, which resamples the art at 2x (measured); a moved box is
   painted on whole device pixels like the resting pet. Six steps per hop, so the layout cost is negligible. */
.device-body { position: absolute; left: 0; top: 0; width: 100%; height: 100%; z-index: 1; }
.device.hop .device-body { animation: hop .32s step-end; }
.device.hop::after { animation: hop-shadow .32s var(--ease-out); }
@keyframes hop {
  0% { top: 0; }
  15% { top: calc(var(--s, 7) * -1px); }
  30% { top: calc(var(--s, 7) * -2px); }
  45% { top: calc(var(--s, 7) * -3px); }
  65% { top: calc(var(--s, 7) * -2px); }
  80% { top: calc(var(--s, 7) * -1px); }
  100% { top: 0; }
}
@keyframes hop-shadow { 45% { transform: scaleX(.8); opacity: .6; } }
/* small hop: idle life and pokes, one art pixel */
.device.hop-sm .device-body { animation: hop-sm .26s step-end; }
.device.hop-sm::after { animation: hop-sm-shadow .26s var(--ease-out); }
@keyframes hop-sm { 0% { top: 0; } 20% { top: calc(var(--s, 7) * -1px); } 75% { top: 0; } }
@keyframes hop-sm-shadow { 45% { transform: scaleX(.9); opacity: .8; } }
/* giggle when poked: one art pixel left and right */
.device.giggle .device-body { animation: giggle .34s step-end; }
@keyframes giggle {
  0% { left: 0; }
  15% { left: calc(var(--s, 7) * -1px); }
  40% { left: calc(var(--s, 7) * 1px); }
  65% { left: calc(var(--s, 7) * -1px); }
  85% { left: 0; }
}
/* cheer: the ritual is done, two quick hops */
.device.cheer .device-body { animation: hop .3s step-end 2; }
.device.cheer::after { animation: hop-shadow .3s var(--ease-out) 2; }
/* grow when the stage changes: a slow rise and settle */
.device.grow .device-body { animation: grow .7s step-end; }
@keyframes grow {
  0% { top: 0; }
  10% { top: calc(var(--s, 7) * -1px); }
  20% { top: calc(var(--s, 7) * -2px); }
  30% { top: calc(var(--s, 7) * -3px); }
  55% { top: calc(var(--s, 7) * -2px); }
  75% { top: calc(var(--s, 7) * -1px); }
  100% { top: 0; }
}

/* the pet's screen: poke it, or steer in the mini-game (art px: LCD 15,16 34x30) */
.lcd {
  position: absolute; z-index: 2; appearance: none; border: 0; padding: 0; background: none; cursor: pointer;
  left: calc(var(--s, 7) * 15px); top: calc(var(--s, 7) * 16px); width: calc(var(--s, 7) * 34px); height: calc(var(--s, 7) * 30px);
  border-radius: calc(var(--s, 7) * 1px); touch-action: manipulation; -webkit-tap-highlight-color: transparent; user-select: none;
}
.lcd:focus-visible { outline: 2px solid var(--ink); outline-offset: calc(var(--s, 7) * 2px); }
.lcd[disabled] { cursor: default; }
.is-game .lcd { touch-action: none; }

/* the shell buttons: pointer shortcuts over the art (art px: left 18,50 / middle 29,52 / right 40,50, 6x6), in the
   same order as the labelled buttons and the ritual: Check, Feed, Play. In the mini-game left and right steer.
   Hidden from the keyboard and screen readers: the labelled buttons below carry the same actions. */
.hot {
  position: absolute; z-index: 3; appearance: none; border: 0; padding: 0; background: none; cursor: pointer;
  width: calc(var(--s, 7) * 8px); height: calc(var(--s, 7) * 8px);
  border-radius: calc(var(--s, 7) * 2.5px); touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}
.hot[data-act='check'] { left: calc(var(--s, 7) * 17px); top: calc(var(--s, 7) * 49px); }
.hot[data-act='feed'] { left: calc(var(--s, 7) * 28px); top: calc(var(--s, 7) * 51px); }
.hot[data-act='play'] { left: calc(var(--s, 7) * 39px); top: calc(var(--s, 7) * 49px); }
.hot::after {
  content: ''; position: absolute; inset: calc(var(--s, 7) * 1px); border-radius: calc(var(--s, 7) * 1px);
  background: transparent; transition: background-color .15s ease-out;
}
.hot.is-pressed::after { background: rgb(var(--shade) / .32); transition: none; }
.hot[disabled] { cursor: default; }
@media (hover: hover) and (pointer: fine) { .hot:not([disabled]):hover::after { background: color-mix(in srgb, var(--surface-2) 22%, transparent); } }

/* ---------- Play ---------- */
.view-play { min-height: calc(100svh - var(--top) - var(--sub)); }
/* every view, and the empty main before game.js shows the first one (after the collection loads), fills the first
   screen, so the footer never rises into view and drops again (CLS) */
#main { min-height: calc(100svh - var(--top) - var(--sub)); }
/* --side: the narrowest info / care column; --ctrl-gap: space between the device's art and the action row.
   game.js reads both when it picks the scale. */
.play {
  --side: 250px; --ctrl-gap: 8px;
  display: grid; grid-template-columns: minmax(var(--side), 1fr) auto minmax(var(--side), 1fr); grid-template-areas: 'info stage care';
  align-items: center; column-gap: var(--s-6);
  min-height: calc(100svh - var(--top) - var(--sub)); padding-top: var(--s-6); padding-bottom: var(--s-8);
}
.play-info { grid-area: info; align-self: center; display: grid; gap: var(--s-2); justify-items: start; padding-bottom: var(--s-16); }
.play-stage { grid-area: stage; display: flex; flex-direction: column; align-items: center; }
.play-care, .play-ro { grid-area: care; justify-self: end; width: min(100%, 300px); align-self: center; padding-bottom: var(--s-16); }
.play-care[hidden], .play-ro[hidden] { display: none; }

.mode { display: flex; flex-wrap: wrap; align-items: center; gap: 0 var(--s-3); margin-bottom: var(--s-1); font-size: var(--t-small); line-height: 20px; }
.mode .chip { font-size: var(--t-small); }
/* text links that stand alone get a 44px target; the underline stays under the text */
.mode-link, .link-44, .mk-open {
  display: inline-flex; align-items: center; min-height: 44px;
  background: none; padding: 0; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px;
}
@media (hover: hover) and (pointer: fine) { .mode-link:hover, .link-44:hover, .mk-open:hover { text-decoration-color: transparent; } }
.mode .link[hidden] { display: none; }
.pet-name { font-size: var(--t-h2); line-height: 40px; letter-spacing: -0.03em; }
.pet-name:focus { outline: none; }
.pet-name .num { letter-spacing: -0.02em; }
.move { display: flex; align-items: baseline; gap: var(--s-3); font-size: var(--t-body); line-height: 24px; }
.move-tk { font-weight: 500; }
.move-foot { display: grid; gap: var(--s-2); justify-items: start; font-size: var(--t-small); line-height: 20px; }
.move-meta { display: block; color: var(--ink-2); max-width: 30ch; }
.up { color: var(--up); } .down { color: var(--down); }

/* speech bubble: one line, not a log (2 lines max, fixed height so the device never shifts) */
.bubble {
  position: relative; z-index: 2; max-width: 34ch; min-height: calc(40px + 2 * var(--s-3) + 2px); margin-bottom: var(--s-2);
  display: flex; align-items: center; justify-content: center;
  padding: var(--s-3) var(--s-4); border-radius: var(--r);
  background: var(--surface-2); border: 1px solid var(--line);
  font-size: var(--t-small); line-height: 20px; text-align: center; text-wrap: balance;
  pointer-events: none; /* not interactive: never covers the "Today's chart" hit area above it */
}
.bubble::after {
  content: ''; position: absolute; left: 50%; bottom: -7px; width: 12px; height: 12px; margin-left: -6px;
  background: var(--surface-2); border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); transform: rotate(45deg);
}
.bubble:empty { visibility: hidden; }
.bubble { transform-origin: 50% calc(100% + 7px); }
.bubble.pop { animation: bubble-in .18s var(--ease-out); }
@keyframes bubble-in { from { opacity: 0; transform: translateY(4px) scale(.92); } to { opacity: 1; transform: none; } }
.bubble .num { white-space: nowrap; }

.controls { position: relative; z-index: 2; display: flex; justify-content: center; align-items: center; gap: var(--s-3); min-height: 48px; margin-top: calc(var(--ctrl-gap) - var(--s, 7) * 3px); }
.controls .act { min-width: 120px; }
.controls [hidden] { display: none; }
.act-wide { min-width: 220px; }
.act[aria-pressed='true'].btn-ghost { color: var(--ink-2); }
.act[aria-pressed='true'].btn-ghost::before {
  content: ''; flex: none; width: 6px; height: 6px; border-radius: 50%; background: currentColor; margin-right: var(--s-1);
}
/* closed market: no ritual, a calm note where the buttons were */
.closed-note { font-size: var(--t-small); line-height: 20px; color: var(--ink-2); text-align: center; }
.closed-note b { font-weight: 500; color: var(--ink); }
.controls[hidden], .pad[hidden], .extras[hidden] { display: none; }

/* mini-game pad: replaces the three actions while a round runs */
.pad { position: relative; z-index: 2; display: flex; justify-content: center; gap: var(--s-3); margin-top: calc(var(--ctrl-gap) - var(--s, 7) * 3px); }
.pad-btn { width: 96px; padding: 0; touch-action: none; user-select: none; -webkit-user-select: none; -webkit-tap-highlight-color: transparent; }
.pad-btn svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.pad-btn.is-held { background: color-mix(in srgb, var(--surface-2) 70%, transparent); transform: scale(.97); }
.pad-stop { min-width: 120px; }
.pad kbd, .controls kbd {
  display: inline-grid; place-items: center; min-width: 22px; height: 22px; padding: 0 var(--s-1); margin-left: var(--s-1);
  border-radius: 6px; box-shadow: inset 0 0 0 1px currentColor; font: 500 var(--t-small)/1 var(--f-sans); opacity: .62;
}

/* secondary row: the mini-game and the sound toggle */
.extras.is-off { visibility: hidden; }
.extras { position: relative; z-index: 2; display: flex; justify-content: center; align-items: center; gap: var(--s-2); margin-top: var(--s-3); }
.extras .btn-sm { height: 44px; }
.game-btn svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.4; }
.game-btn .ic-fill { fill: currentColor; }
.game-len { color: var(--ink-2); font-weight: 400; }
.snd { width: 44px; padding: 0; }
.snd svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.snd .snd-body { fill: currentColor; stroke-width: 1.2; }
.snd[aria-pressed='true'] .snd-off, .snd[aria-pressed='false'] .snd-on { display: none; }
.snd[aria-pressed='false'] { color: var(--ink-2); }
.link-btn { appearance: none; border: 0; cursor: pointer; padding: 0; background: none; font: inherit; font-weight: 500; color: var(--ink); }
.mk-open { justify-self: start; font-size: var(--t-small); line-height: 20px; }
.mk-open[hidden] { display: none; }
@media (hover: none) { .controls kbd, .pad kbd { display: none; } }

/* care column */
.meters { display: grid; gap: var(--s-3); }
.meter { display: grid; grid-template-columns: 44px 1fr 32px; align-items: center; gap: var(--s-3); font-size: var(--t-small); line-height: 20px; }
.meter-label { color: var(--ink-2); }
.meter-val { text-align: right; }
.meter-bar { position: relative; display: block; height: 6px; border-radius: var(--r-pill); background: var(--line); overflow: hidden; }
.meter-fill { position: absolute; inset: 0; border-radius: inherit; background: var(--ink); transform-origin: 0 50%; transform: scaleX(var(--v, 0)); transition: transform .5s var(--ease-out); }
.meter.bump .meter-bar { animation: bar-bump .42s var(--ease-out); }
@keyframes bar-bump { 30% { transform: scaleY(1.7); } 100% { transform: none; } }
.meter.bump .meter-val { animation: val-bump .42s var(--ease-out); }
@keyframes val-bump { 30% { transform: translateY(-2px); } 100% { transform: none; } }
.meter-val { display: inline-block; }
.meter.is-low .meter-label, .meter.is-low .meter-val { color: var(--ink); font-weight: 500; }
.meter.is-low .meter-fill { background: repeating-linear-gradient(90deg, var(--ink) 0 6px, var(--ink-3) 6px 8px); }

.ritual { display: flex; align-items: center; gap: var(--s-4); margin-top: var(--s-6); padding-top: var(--s-4); border-top: 1px solid var(--line); font-size: var(--t-small); line-height: 20px; }
.ritual-title { color: var(--ink-2); width: 44px; flex: none; }
.ritual-dots { display: flex; gap: var(--s-4); margin: 0; padding: 0; list-style: none; }
.ritual-dots li { display: inline-flex; align-items: center; gap: 6px; color: var(--ink-2); }
.ritual-dots li::before { content: ''; width: 10px; height: 10px; border-radius: 50%; box-shadow: inset 0 0 0 1.5px var(--line-2); transition: background-color .2s ease-out, box-shadow .2s ease-out; }
.ritual-dots li.is-done { color: var(--ink); }
.ritual-dots li.is-done::before { background: var(--ink); box-shadow: none; }
.ritual-dots li.pop::before { animation: dot-pop .38s var(--ease-out) both; }
.ritual-dots li.pop:nth-child(2)::before { animation-delay: var(--wave, 0s); }
.ritual-dots li.pop:nth-child(3)::before { animation-delay: calc(var(--wave, 0s) * 2); }
.ritual.is-wave { --wave: .09s; }
.ritual.is-closed .ritual-dots { opacity: .5; }
@keyframes dot-pop { 0% { transform: scale(.35); } 55% { transform: scale(1.4); } 100% { transform: none; } }

.growth { display: grid; grid-template-columns: repeat(3, auto); justify-content: space-between; margin: var(--s-4) 0 0; padding-top: var(--s-4); border-top: 1px solid var(--line); }
.growth div { display: grid; gap: 2px; }
.growth dt { font-size: var(--t-small); line-height: 20px; color: var(--ink-2); }
.growth dd { margin: 0; font-size: var(--t-body); line-height: 24px; font-weight: 500; }
.growth-next { margin-top: var(--s-3); font-size: var(--t-small); line-height: 20px; color: var(--ink-2); }
.play-ro p { font-size: var(--t-small); color: var(--ink-2); }
.play-ro p + p { margin-top: var(--s-2); }

/* ---------- Check: today's market ---------- */
dialog.market { width: min(520px, calc(100vw - 2 * var(--gut))); }
.mk { padding: var(--s-6); }
.mk-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-4); }
.mk-head h2 { display: flex; align-items: baseline; gap: var(--s-3); }
.mk-x { appearance: none; border: 0; background: none; cursor: pointer; width: 44px; height: 44px; margin-right: calc(var(--s-2) * -1); display: grid; place-items: center; border-radius: 50%; }
.mk-x svg { width: 16px; height: 16px; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; }
@media (hover: hover) and (pointer: fine) { .mk-x:hover { background: var(--surface); } }
.mk-close { margin-top: var(--s-2); color: var(--ink-2); }
.mk-chart { margin: var(--s-6) 0 0; }
.mk-chart svg { display: block; width: 100%; height: 120px; }
.mk-chart rect { opacity: .42; }
.mk-chart rect.is-last { opacity: 1; }
.bar-up { fill: var(--up); } .bar-down { fill: var(--down); } .bar-flat { fill: var(--line-2); }
.mk-base { stroke: var(--line-2); stroke-width: 1; vector-effect: non-scaling-stroke; }
.mk-cap { margin-top: var(--s-2); font-size: var(--t-small); color: var(--ink-2); }
.mk-mood { margin-top: var(--s-4); }
.mk-src { margin-top: var(--s-2); font-size: var(--t-small); color: var(--ink-2); }
.mk-done { margin-top: var(--s-6); width: 100%; }

/* one h1 per view (only one view shows at a time), set at the h2 size */
.view-title { font-size: var(--t-h2); line-height: 1.1; letter-spacing: -0.03em; }

/* ---------- My pets ---------- */
.pets { padding-top: var(--s-12); padding-bottom: var(--s-16); }
.pets-head { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 520px); align-items: start; gap: var(--s-4) var(--s-12); margin-bottom: var(--s-8); }
.pets-count { margin-left: var(--s-2); color: var(--ink-2); letter-spacing: 0; }
.pets-state { display: grid; gap: var(--s-4); justify-items: start; }
.pets-state p { font-size: var(--t-small); }
.pets-actions { display: flex; flex-wrap: wrap; gap: var(--s-3); }
.pets-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(232px, 1fr)); gap: var(--s-4); margin: 0; padding: 0; list-style: none; }
.pets-grid > li { display: grid; min-width: 0; }
.pets-grid[hidden], .pets-demo[hidden] { display: none; }
.pets-grid + .pets-demo { margin-top: var(--s-12); }
.pets-demo-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-2) var(--s-4); margin-bottom: var(--s-4); }
.pets-demo-head .demo-title { font-size: var(--t-body); line-height: 24px; letter-spacing: -0.015em; }
.pets-demo-head p { font-size: var(--t-small); }
/* no wallet connected: the wallet prompt follows the house pets */
.pets-guest { display: grid; gap: var(--s-3); max-width: 560px; margin-top: var(--s-12); padding-top: var(--s-8); border-top: 1px solid var(--line); }
.pets-guest[hidden] { display: none; }
.pets-head:not(:has(.pets-state)) { margin-bottom: var(--s-6); } /* only the title: the house pets follow closely */
.pets-guest .demo-title { font-size: var(--t-body); line-height: 24px; letter-spacing: -0.015em; }

/* --cs: CSS size of one art pixel on a card (set by game.js, x devicePixelRatio is an integer) */
.pcard { display: grid; grid-template-rows: auto 1fr; align-content: start; border-radius: var(--r); background: var(--surface); border: 1px solid var(--line); overflow: hidden; transition: border-color .15s ease-out; }
@media (hover: hover) and (pointer: fine) {
  .pcard:hover { border-color: var(--line-2); }
  .pcard:hover .pcard-art canvas { top: calc(var(--cs, 3px) * -1); }
}
.pcard:focus-visible { outline-offset: 2px; border-radius: var(--r); }
.pcard-art {
  position: relative; height: calc(var(--cs, 3px) * 64 + 12px); display: grid; place-items: end center;
  background: linear-gradient(to bottom, var(--wall-top) 0%, var(--wall) 58%, var(--floor-far) 72%, var(--floor-near) 100%);
}
/* the pet hops one art pixel on hover: the box moves (top), so the art stays on whole device pixels */
.pcard-art canvas { grid-area: 1 / 1; width: calc(var(--cs, 3px) * 64); height: calc(var(--cs, 3px) * 64); margin-bottom: 0; image-rendering: pixelated; position: relative; top: 0; z-index: 1; }
.pcard-art::after {
  content: ''; position: absolute; left: 50%; bottom: 12px; width: 120px; height: 10px; margin-left: -60px; border-radius: 50%;
  background: radial-gradient(closest-side, rgb(var(--shade) / .38), rgb(var(--shade) / 0)); z-index: 0;
}
.pcard-body { display: grid; align-content: start; gap: var(--s-2); padding: var(--s-4); }
.pcard-row { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-3); }
.pcard-id { font-size: var(--t-body); font-weight: 500; }
.pcard-mv { font-size: var(--t-small); font-weight: 500; }
.pcard-status { font-size: var(--t-small); color: var(--ink-2); text-wrap: pretty; }
.pcard-status.is-urgent { color: var(--ink); font-weight: 500; }
.pcard-status.is-urgent::before { content: ''; display: inline-block; width: 6px; height: 6px; margin: 0 var(--s-2) 2px 0; border-radius: 50%; background: var(--ink); }
.pcard-meters { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-4); }
.mini-meter { display: grid; grid-template-columns: auto 1fr; align-items: center; gap: var(--s-2); font-size: var(--t-small); color: var(--ink-2); }
.mini-meter .meter-bar { height: 4px; }
.pcard-meta { font-size: var(--t-small); color: var(--ink-2); }
.pcard-skel { height: 300px; border-radius: var(--r); background: linear-gradient(100deg, var(--surface) 30%, var(--surface-2) 50%, var(--surface) 70%) 0 0 / 300% 100%; animation: skel 1.4s linear infinite; }
@keyframes skel { to { background-position: -150% 0; } }
.pets-demo.is-secondary .demo-title { color: var(--ink-2); }

/* ---------- How it works ---------- */
.how {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s-12); align-items: center;
  min-height: calc(100svh - var(--top) - var(--sub)); padding-top: var(--s-8); padding-bottom: var(--s-8);
}
.how-stage {
  display: flex; flex-direction: column; align-items: center; gap: var(--s-4); padding: var(--s-6) var(--s-4) var(--s-8);
  border-radius: 20px;
  background:
    radial-gradient(50% 50% at 50% 42%, var(--key) 0%, color-mix(in srgb, var(--key) 0%, transparent) 100%),
    linear-gradient(to bottom, var(--wall-top), var(--wall) 50%);
}
.how-stage .how-pet { margin-bottom: calc(var(--s, 5) * -3px); }
/* market closed: the key light is off */
.view-how.is-closed .how-stage { background: linear-gradient(to bottom, color-mix(in srgb, var(--wall-top), var(--line) 30%), var(--wall) 60%); }
.seg { position: relative; z-index: 1; display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s-2); }
.seg .chip { appearance: none; border: 0; cursor: pointer; height: 44px; padding: 0 var(--s-4); font-size: var(--t-small); transition: background-color .15s ease-out, color .15s ease-out; }
.seg .chip[aria-pressed='false'] { background: transparent; }
@media (hover: hover) and (pointer: fine) { .seg .chip[aria-pressed='false']:hover { background: color-mix(in srgb, var(--surface-2) 60%, transparent); color: var(--ink); } }
.how-line { position: relative; z-index: 1; min-height: 40px; max-width: 36ch; text-align: center; font-size: var(--t-small); line-height: 20px; color: var(--ink); }
.how-rules .view-title { margin-bottom: var(--s-3); }
.how-lede { color: var(--ink-2); max-width: 48ch; }
.rules { margin: var(--s-6) 0 0; padding: 0; list-style: none; counter-reset: r; display: grid; gap: var(--s-3); }
.rules li { counter-increment: r; position: relative; padding-left: 28px; font-size: var(--t-small); color: var(--ink-2); max-width: 80ch; text-wrap: pretty; }
.rules li::before { content: counter(r); position: absolute; left: 0; top: 0; font-family: var(--f-num); font-weight: 500; color: var(--ink-2); }
.rules b { font-weight: 500; color: var(--ink); }
.stages { display: flex; gap: var(--s-2); margin-top: var(--s-6); padding-top: var(--s-4); border-top: 1px solid var(--line); }
.stages figure { position: relative; margin: 0; display: grid; justify-items: center; }
/* --ss: CSS size of one art pixel in the strip (set by game.js) */
.stages canvas { width: calc(var(--ss, 2px) * 64); height: calc(var(--ss, 2px) * 64); image-rendering: pixelated; grid-area: 1 / 1; }
.stages .stage-ov { position: relative; z-index: 1; }
.stages figcaption { font-size: var(--t-small); color: var(--ink-2); margin-top: calc(var(--s-1) * -1); }
.how-src { margin-top: var(--s-4); font-size: var(--t-small); color: var(--ink-2); }

/* views fade in without moving: a sliding view would resample the pixel art for a moment */
.view.is-active { animation-name: game-view-in; }
@keyframes game-view-in { from { opacity: 0; } to { opacity: 1; } }

/* ---------- big screens (2560x1440 and the like): a bigger device (up to 640 px, game.js) in the same frame as the
   header, so the side columns keep the header's edges ---------- */
@media (min-width: 1800px) and (min-height: 1200px) {
  .play { --side: 280px; column-gap: var(--s-12); }
}

/* ---------- laptop heights ---------- */
@media (max-height: 820px) and (min-width: 760px) {
  .play { padding-top: var(--s-4); padding-bottom: var(--s-6); }
  .how { padding-top: var(--s-6); padding-bottom: var(--s-6); }
  .rules { gap: var(--s-2); }
}

/* ---------- tablet (2 rows: info + care, then the stage) ---------- */
@media (max-width: 999px) and (min-width: 760px) {
  .play { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-areas: 'info care' 'stage stage'; row-gap: var(--s-4); align-items: start; min-height: 0; }
  .play-info, .play-care, .play-ro { padding-bottom: 0; }
  .how { grid-template-columns: 1fr; }
}

/* ---------- phone ---------- */
@media (max-width: 759px) {
  .view-play { min-height: 0; }
  .play {
    grid-template-columns: minmax(0, 1fr); grid-template-areas: 'info' 'stage' 'care';
    min-height: 0; row-gap: var(--s-2); padding-top: var(--s-2); padding-bottom: var(--s-8);
  }
  /* compact identity block: chip + link, number + move, source + chart link */
  .play-info { padding: 0; grid-template-columns: minmax(0, 1fr) auto; column-gap: var(--s-3); row-gap: 0; align-items: center; width: 100%; }
  .mode { grid-column: 1 / -1; grid-row: 1; margin: 0; min-height: 44px; }
  .pet-name { grid-column: 1; grid-row: 2; line-height: 36px; }
  .move { grid-column: 2; grid-row: 2; justify-self: end; }
  /* the source line and the chart link share one text block: "Demo data, ... yet  Today's chart" (2 lines at 320) */
  .move-foot { grid-column: 1 / -1; grid-row: 3; display: block; }
  .move-meta { display: inline; max-width: none; margin-right: var(--s-2); }
  .mk-open { display: inline; position: relative; min-height: 0; vertical-align: baseline; }
  .mk-open::before { content: ''; position: absolute; left: -4px; right: -4px; top: 50%; height: 44px; transform: translateY(-50%); } /* 44px hit area */
  .bubble { max-width: 100%; }
  .controls, .pad { width: 100%; gap: var(--s-2); }
  .pad-btn { flex: 1 1 0; width: auto; }
  .pad-stop { flex: 0 0 auto; min-width: 0; padding: 0 var(--s-4); }
  .extras { margin-top: var(--s-2); }
  .controls .act { flex: 1 1 0; min-width: 0; padding: 0 var(--s-3); }
  .act-wide { flex: 1 1 auto; }
  .play-care, .play-ro { justify-self: stretch; width: 100%; padding: var(--s-2) 0 0; }
  .meters { grid-template-columns: 1fr 1fr; column-gap: var(--s-6); }
  .meter { grid-template-columns: auto 1fr 26px; gap: var(--s-2); }
  .ritual { margin-top: var(--s-4); padding-top: var(--s-3); }
  .growth { margin-top: var(--s-3); padding-top: var(--s-3); }

  .pets { padding-top: var(--s-6); }
  .pets-head { grid-template-columns: 1fr; margin-bottom: var(--s-6); }
  .pets-guest { margin-top: var(--s-8); padding-top: var(--s-6); }
  .pets-head:not(:has(.pets-state)) { margin-bottom: var(--s-4); }
  .pets-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-3); }
  .pcard-art::after { width: 80px; margin-left: -40px; bottom: 9px; height: 8px; }
  .pcard-body { padding: var(--s-3); }
  .pcard-meters { grid-template-columns: 1fr; gap: var(--s-1); }
  .pcard-row { flex-wrap: wrap; gap: 0 var(--s-2); }

  .how { grid-template-columns: 1fr; gap: var(--s-8); min-height: 0; padding-top: var(--s-4); }
  .how-stage { border-radius: var(--r); }
  .stages { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-2); }
  .mk { padding: var(--s-4); }
}
@media (max-width: 369px) {
  .controls .act { padding: 0 var(--s-2); }
  .controls kbd { display: none; }
}
/* short phones (320x568 and the like): a tighter info block and bubble so Check, Feed and Play fit the first screen */
@media (max-width: 759px) and (max-height: 640px) {
  .play { --ctrl-gap: 4px; padding-top: 0; row-gap: var(--s-1); }
  .bubble { min-height: calc(40px + 2 * var(--s-2) + 2px); padding: var(--s-2) var(--s-3); }
}

@media (prefers-reduced-motion: reduce) {
  .device .device-body, .device::after { animation: none !important; }
  .bubble.pop, .meter.bump .meter-bar, .meter.bump .meter-val, .ritual-dots li.pop::before { animation: none; }
  .pad-btn.is-held { transform: none; }
  .meter-fill { transition: none; }
  .pcard-skel { animation: none; }
  .pcard:hover .pcard-art canvas { top: 0; }
}
.no { white-space: nowrap; }
