* { box-sizing: border-box; }
/* Nothing may widen the page sideways: on iOS that lets the page zoom and pan, and the fixed bottom nav drifts. */
html, body { overflow-x: clip; overscroll-behavior-x: none; }
/* On a board, a pull past the top or bottom doesn't rubber-band or pull-to-refresh: the bounce resized the board
   under the player's finger and could push its controls under the tab bar. */
html:has([data-fit], .play-main) { overscroll-behavior-y: none; }
/* Games take quick repeated taps; never let them double-tap-zoom the page. Pinch zoom still works off the boards. */
html { touch-action: manipulation; }
/* While a game board is on screen the page only scrolls up and down: a stray pinch or sideways
   drag would zoom it and then slide the board left and right mid-play. */
html:has([data-play-surface]) { touch-action: pan-y; }
body { margin: 0; background: var(--background); color: var(--ink); font: var(--weight-body) var(--text-md)/var(--leading) var(--font); }
a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: var(--s1); }
button, input, select, textarea { font: inherit; }
/* iOS Safari zooms into any focused field under 16px and doesn't zoom back out (#48). */
@media (pointer: coarse) { input:not([type="checkbox"], [type="radio"], [type="range"]), select, textarea { font-size: max(1rem, 16px) !important; } }
button, .button { min-height: var(--control); padding: var(--s2) var(--s6); border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface); color: var(--ink); font-weight: var(--weight-label); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: var(--s2); text-decoration: none; }
button:active, .button:active { transform: translateY(1px); }
button:disabled { cursor: not-allowed; opacity: .5; }
button, .button, nav a { transition: background-color var(--fast) var(--ease), color var(--fast) var(--ease), transform var(--fast) var(--ease); }
button.primary, .button.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
:focus-visible { outline: 3px solid var(--ring); outline-offset: 3px; }
/* FocusOnNavigate moves focus to the page title for screen readers; the heading is not interactive, so no ring. */
h1:focus { outline: none; }
input, select, textarea { width: 100%; padding: var(--s3); color: var(--ink); background: var(--background); border: 1px solid var(--line); border-radius: var(--radius-sm); min-height: var(--control); }
/* Safari ignores sizing on native selects, so draw our own chevron and match the other controls. */
select { appearance: none; -webkit-appearance: none; padding: var(--s2) calc(var(--s6) + 10px) var(--s2) var(--s4); background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%); background-size: 5px 5px; background-position: calc(100% - var(--s4) - 5px) 55%, calc(100% - var(--s4)) 55%; background-repeat: no-repeat; cursor: pointer; }
label { display: grid; gap: var(--s2); font-weight: var(--weight-label); }
.checkbox-setting { display: flex; align-items: center; gap: var(--s3); min-height: var(--control); cursor: pointer; }
.checkbox-setting input { width: var(--s6); height: var(--s6); min-height: var(--s6); padding: 0; flex-shrink: 0; accent-color: var(--sea); }
fieldset { border: 0; padding: 0; margin: 0; min-width: 0; }
h1, h2, h3, p { margin: 0; }
h1 { font-size: var(--text-3xl); line-height: var(--leading-title); font-weight: var(--weight-title); letter-spacing: var(--tracking-title); overflow-wrap: anywhere; }
h2 { font-size: var(--text-2xl); line-height: var(--leading-title); letter-spacing: var(--tracking-title); }
h3 { font-size: var(--text-xl); line-height: var(--leading-title); letter-spacing: var(--tracking-title); }
small, .small { font-size: var(--text-sm); }
.muted { color: var(--muted); }
.eyebrow { font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; font-weight: var(--weight-title); color: var(--sea); }
.shell { max-width: var(--container); padding: 0 var(--s8); margin: auto; isolation: isolate; }
.masthead { display: flex; align-items: center; justify-content: space-between; gap: var(--s4); padding: var(--s6) 0; border-bottom: 1px solid var(--line); }
.brand { display: flex; flex-shrink: 0; align-items: center; gap: var(--s2); font-size: var(--text-xl); font-weight: var(--weight-title); letter-spacing: var(--tracking-title); text-decoration: none; }
.brand img { width: var(--s8); height: var(--s8); }
nav { display: flex; align-items: center; gap: var(--s1); border: 1px solid var(--line); background: var(--surface); border-radius: var(--pill); padding: var(--s1); }
nav a { min-height: var(--control); display: flex; align-items: center; justify-content: center; gap: var(--s2); padding: var(--s2) var(--s3); border-radius: var(--pill); font-size: var(--text-sm); font-weight: var(--weight-label); color: var(--muted); text-decoration: none; }
nav a.active { background: var(--elevated); color: var(--accent); }
.ui-icon { width: var(--icon-size); height: var(--icon-size); stroke-width: var(--icon-stroke); flex-shrink: 0; }
.header-actions { display: flex; align-items: center; gap: var(--s2); min-width: 0; }
.account-link { padding: var(--s2) var(--s3); font-size: var(--text-sm); min-width: var(--control); max-width: 10rem; border-radius: var(--pill); }
.account-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
main { padding: var(--s12) 0; }
.stack { display: grid; gap: var(--s6); }
.tight { gap: var(--s3); }
.row { display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap; }
.between { justify-content: space-between; }
.panel { padding: var(--s6); border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); }
.game-home { display: grid; grid-template-columns: minmax(0, 1fr); row-gap: var(--s8); align-items: start; }
.game-intro { display: grid; gap: var(--s2); align-content: center; }
.game-intro > p { max-width: 52ch; }
.home-modes { display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap: var(--s4); }
.home-challenge { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s4); margin-top: var(--s4); }
.home-challenge > .caption:empty { display: none; }
.home-boards { margin: var(--s3) 0 0; }
/* Four modes (Color Bus) sit two by two rather than four narrow columns. */
@media (min-width: 768px) { .home-modes:has(> :nth-child(4)) { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.home-tile { display: flex; align-items: center; gap: var(--s4); text-decoration: none; color: inherit; cursor: pointer; transition: border-color var(--fast) var(--ease), transform var(--fast) var(--ease); }
.home-tile > .ui-icon { color: var(--sea); width: var(--s8); height: var(--s8); flex: none; }
.home-tile-text { display: grid; gap: 2px; min-width: 0; }
.home-tile small { color: var(--muted); font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; }
.home-tile strong { font-size: var(--text-lg); }
.home-tile em { color: var(--muted); font-size: var(--text-sm); font-style: normal; }
.home-tile.has-progress { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; column-gap: var(--s4); row-gap: var(--s3); }
.home-tile-count { font-size: var(--text-xl); font-weight: var(--weight-title); font-variant-numeric: tabular-nums; }
.home-tile progress { grid-column: 1 / -1; width: 100%; height: var(--s1); accent-color: var(--sea); border: 0; border-radius: var(--pill); overflow: hidden; background: var(--elevated); }
.home-tile progress::-webkit-progress-bar { background: var(--elevated); }
.home-tile progress::-webkit-progress-value { background: var(--sea); border-radius: var(--pill); }
.home-tile progress::-moz-progress-bar { background: var(--sea); border-radius: var(--pill); }
/* The Daily is the same card as every other mode, lit up so today's puzzle still reads first. */
.daily-tile { border-color: color-mix(in srgb, var(--sea) 55%, var(--line)); background: color-mix(in srgb, var(--sea) 7%, var(--surface)); }
.daily-tile strong { color: color-mix(in srgb, var(--sea) 62%, var(--ink)); }
.daily-tile.daily-tile-done { border-color: var(--line); background: var(--surface); }
.daily-tile.daily-tile-done strong { color: inherit; }
.daily-streak { display: inline-flex; align-items: baseline; gap: var(--s1); font-size: var(--text-lg); font-variant-numeric: tabular-nums; }
.daily-freezes { font-size: var(--text-sm); color: var(--muted); }
/* In the evening, a streak only today's Daily keeps alive says so on the card: a line, never a pop-up. */
.daily-tile.daily-tile-risk { border-color: color-mix(in srgb, var(--warning) 55%, var(--line)); }
.daily-tile em.daily-risk { color: var(--warning); font-weight: var(--weight-label); }
.home-packs { margin-top: var(--s12); }
.home-packs h2 { margin-bottom: var(--s1); }
.home-packs ol { list-style: none; padding: 0; margin: var(--s4) 0 0; display: grid; gap: var(--s3); grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr)); }
.home-pack a, .home-pack > span { display: grid; gap: var(--s1); height: 100%; padding: var(--s3) var(--s4); border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface); text-decoration: none; color: inherit; }
.home-pack .pack-size { color: var(--muted); font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; }
.home-pack .pack-meter { height: .35rem; border-radius: var(--pill); background: var(--elevated); overflow: hidden; }
.home-pack .pack-meter i { display: block; height: 100%; width: var(--p); border-radius: inherit; background: var(--sea); }
.home-pack small { color: var(--muted); font-size: var(--text-xs); font-variant-numeric: tabular-nums; }
/* Locked packs recede through a dashed outline and no fill, never through opacity, so their text stays readable. */
.home-pack.locked > span { background: transparent; border-style: dashed; color: var(--muted); }
.streak-line { text-decoration: none; }
.account-perks { display: grid; gap: var(--s4); align-content: start; align-self: start; }
.account-perks h2 { font-size: var(--text-lg); }
.account-perk-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s4); grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); }
.account-perk-list li { display: flex; gap: var(--s3); align-items: flex-start; }
.account-perk-list li > span { display: grid; gap: 2px; }
.account-perk-list .ui-icon { color: var(--sea); }
.account-perks .button { justify-self: start; }
.streak-line strong { color: var(--ink); font-variant-numeric: tabular-nums; }
.caption { color: var(--muted); font-size: var(--text-sm); }
.coin-goal { display: grid; gap: var(--s3); margin: var(--s4) 0; padding: var(--s4); border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface); }
.coin-goal.compact { width: 100%; box-sizing: border-box; padding: var(--s2); margin: var(--s2) 0; gap: var(--s1); font-size: var(--text-sm); text-align: left; }
.coin-goal.compact .coin-goal-art, .coin-goal.compact .pet-gear-icon { width: var(--s8); height: var(--s8); }
.coin-goal.compact .eyebrow { font-size: var(--text-2xs); }
.coin-goal-main { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s3); }
.coin-goal-art { width: var(--control); height: var(--control); display: grid; place-items: center; flex: none; }
.coin-goal-art .sky-swatch { width: 100%; height: 100%; border-radius: var(--radius-sm); overflow: hidden; }
.coin-goal-copy { display: grid; gap: var(--s1); flex: 1 1 10rem; min-width: 0; overflow-wrap: anywhere; }
.coin-goal progress { width: 100%; height: var(--s1); accent-color: var(--sea); }
.coin-goal-picker summary { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); min-height: var(--control); cursor: pointer; color: var(--sea); font-weight: var(--weight-label); }
.coin-goal-picker[open] > div { margin-top: var(--s2); }
.coin-goal-picker select { max-width: 100%; min-width: 0; font-size: var(--text-md); }
.coin-goal .button, .coin-goal button, .daily-rewards .button { font-size: var(--text-sm); }
.goal-save-button { padding: var(--s2); font-size: var(--text-sm); color: var(--sea); flex: none; white-space: nowrap; transition: color var(--fast) var(--ease); }
.goal-save-button[aria-pressed="true"] { background: var(--elevated); }
.goal-save-button:hover, .coin-goal-picker summary:hover { color: var(--ink); }
.daily-rewards { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) 0; margin-bottom: var(--s4); border-bottom: 1px solid var(--line); }
.daily-rewards-copy { display: grid; gap: var(--s1); flex: 1; min-width: 0; }
.daily-rewards-title { display: flex; align-items: baseline; gap: var(--s2); }
.daily-rewards-count { color: var(--sea); font-size: var(--text-xs); font-weight: var(--weight-label); font-variant-numeric: tabular-nums; white-space: nowrap; }
.daily-rewards .caption { font-size: var(--text-xs); }
.daily-rewards .button { flex: none; gap: var(--s1); padding-inline: var(--s3); }
.daily-rewards-done { display: grid; place-items: center; width: var(--control); height: var(--control); color: var(--sea); }
/* The one line under every game's controls: how to play, or what just happened. */
.game-caption { width: min(100%, 32rem); margin: 0 auto; text-align: center; color: var(--muted); }
.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s4); padding: var(--s6) 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.stat strong { display: block; font-size: var(--text-2xl); font-variant-numeric: tabular-nums; line-height: var(--leading-title); margin-bottom: var(--s2); }
.stat span { color: var(--muted); font-size: var(--text-xs); }
.mode-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s4); margin-top: var(--s12); }
.mode-link { text-decoration: none; display: grid; grid-template-columns: auto 1fr; column-gap: var(--s3); row-gap: var(--s4); align-items: center; }
.mode-link > .ui-icon { color: var(--sea); width: var(--s6); height: var(--s6); }
.mode-link > span { grid-column: 1 / -1; }
.mode-link { cursor: pointer; transition: border-color var(--fast) var(--ease), background-color var(--fast) var(--ease); }
.footer { display: flex; justify-content: space-between; flex-wrap: wrap; gap: var(--s4); padding: var(--s6) 0; color: var(--muted); font-size: var(--text-xs); border-top: 1px solid var(--line); }
.build-label { display: flex; align-items: center; gap: var(--s3); }
/* Small print, but every link still gets a full 24px+ target. */
.footer a { display: inline-flex; align-items: center; min-height: 1.75rem; }
/* Status lines answer what the player just did, directly under the control that did it: borderless,
   full width, tinted by tone. Grey informs, green confirms, yellow warns, red reports an error. */
.banner { display: block; width: 100%; box-sizing: border-box; padding: var(--s2) var(--s3); margin: var(--s2) 0 0;
  border: 0; border-radius: .5rem; color: var(--ink); line-height: 1.4; overflow-wrap: anywhere;
  background: color-mix(in srgb, var(--muted) 14%, transparent); }
.banner.error { color: var(--error); background: color-mix(in srgb, var(--error) 12%, transparent); }
.banner:is(.success, .ok) { color: var(--success); background: color-mix(in srgb, var(--success) 13%, transparent); }
.banner.warning { color: var(--warning); background: color-mix(in srgb, var(--warning) 15%, transparent); }
/* Inline form errors: small red text directly under the field it is about, no box. --error meets 4.5:1 on every theme. */
.field-error { flex-basis: 100%; margin: var(--s1) 0 0; padding: 0; border: 0; background: none; color: var(--error); font-size: var(--text-sm); line-height: 1.35; }
.banner button { min-height: var(--s8); padding: var(--s1) var(--s3); margin-left: var(--s4); }
.page-heading { margin-bottom: var(--s8); display: grid; gap: var(--s3); }
.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s6); }
.scene-day { display: var(--scene-day); }.scene-night { display: var(--scene-night); }
.scene-tint { display: none; position: absolute; inset: 0; z-index: 5; background: var(--scene-accent); opacity: var(--grade-strength); mix-blend-mode: soft-light; pointer-events: none; }
.form { max-width: 30rem; width: 100%; }
.arena-ready { max-width: var(--board-size); margin: var(--s8) auto; }
.arena-ready:has(.versus-cards) { max-width: 40rem; }
/* Landscape phones: keep the whole ready card, Start included, above the fold. */
@media (max-height: 520px) {
  .arena-ready { max-width: 36rem; margin: var(--s3) auto; padding: var(--s4) var(--s6); gap: var(--s3); }
  .arena-ready h1 { font-size: var(--text-xl); }
}
.destructive { color: var(--error); }
.sign-in .provider { width: 100%; position: relative; }
.provider { gap: var(--s3); min-width: 0; }
.provider > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.provider-logo { flex: none; width: 1.25rem; height: 1.25rem; display: block; }
.provider.google { background: #fff; border-color: #dadce0; color: #1f1f1f; }
.provider.google:hover:not(:disabled) { background: #f8f9fa; border-color: #c6c9cc; }
.provider.discord { background: #5865f2; border-color: #5865f2; color: #fff; }
.provider.discord .provider-logo { width: 1.5rem; height: 1.5rem; }
.provider.discord:hover:not(:disabled) { background: #4752c4; border-color: #4752c4; }
.sign-in .divider { display: flex; align-items: center; gap: var(--s3); margin: var(--s2) 0; color: var(--muted); font-size: var(--text-sm); }
.sign-in .divider::before, .sign-in .divider::after { content: ""; flex: 1; border-top: 1px solid var(--line); }
.link-button { min-height: auto; padding: var(--s1) 0; border: 0; background: none; color: var(--ink); text-decoration: underline; text-underline-offset: .2em; font-weight: inherit; }
.sign-in-methods { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2); }
.sign-in-methods li { display: flex; align-items: center; gap: var(--s2); }
.sign-in-methods .ui-icon { color: var(--sea); width: 1.1em; height: 1.1em; }
.link-methods summary { cursor: pointer; color: var(--muted); }
.link-methods[open] summary { margin-bottom: var(--s3); }
.account-sections { display: grid; gap: var(--s4); grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr)); align-items: start; }
.account-sections > .panel { padding: var(--s4); }
.account-sections h2, .account-merge h2 { font-size: var(--text-lg); }
.account-merge { margin-bottom: var(--s4); border-color: color-mix(in srgb, var(--sea) 55%, var(--line)); }
.merge-choices { display: grid; gap: var(--s3); margin: 0; padding: 0; border: 0; min-width: 0; }
.merge-choices legend { padding: 0; margin-bottom: var(--s2); font-weight: var(--weight-label); }
.merge-choice { display: flex; gap: var(--s3); align-items: flex-start; padding: var(--s3) var(--s4); border: 1px solid var(--line); border-radius: var(--radius-sm); cursor: pointer; }
.merge-choice:has(input:checked) { border-color: var(--sea); background: color-mix(in srgb, var(--sea) 8%, var(--surface)); }
.merge-choice input { width: auto; min-height: auto; margin-top: .3em; accent-color: var(--sea); }
.merge-side { display: grid; gap: var(--s1); min-width: 0; overflow-wrap: anywhere; }
.link-code { margin: 0; font-size: var(--text-xl); letter-spacing: .12em; font-variant-numeric: tabular-nums; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.narrow { max-width: 36rem; margin-inline: auto; }
.prose { max-width: 44rem; margin-inline: auto; }
.prose h2 { margin-top: var(--s4); }
/* Arena hub: one column on phones; card beside the match panel, and standings beside results, from 960px. */
.arena-columns, .arena-board-columns { display: grid; gap: var(--s6); align-items: start; }
.arena-columns > .panel { align-content: start; min-width: 0; }
.arena-challenge { margin-bottom: var(--s6); }
.arena-challenge > button { justify-self: start; }
.arena-board { margin-top: var(--s8); }
.arena-board-columns > * { min-width: 0; align-content: start; }
.arena-results > h3 { margin: 0; }
@media (min-width: 960px) {
  .arena-columns { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); column-gap: var(--s8); }
  .arena-board-columns { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: var(--s8); }
}
.arena-score { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s6); margin: 0; }
.arena-score dt { color: var(--muted); font-size: var(--text-xs); text-transform: uppercase; letter-spacing: .06em; }
.arena-score dd { margin: 0; font-weight: 600; font-variant-numeric: tabular-nums; }
.ladder { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }
.ladder-row { display: grid; grid-template-columns: var(--s8) minmax(0, 1fr); gap: var(--s3); align-items: center; }
.ladder-place { font-size: var(--text-lg); font-weight: var(--weight-title); color: var(--muted); text-align: center; font-variant-numeric: tabular-nums; }
.ladder-row.mine .player-card { border-color: var(--accent); }
.player-card { --scene-accent: var(--sea); display: grid; gap: var(--s4); padding: var(--s4); min-width: 0; border: 1px solid var(--line); border-left: var(--s1) solid var(--scene-accent); border-radius: var(--radius); background: linear-gradient(100deg, color-mix(in srgb, var(--scene-accent) 12%, var(--surface)), var(--surface) 60%); }
.player-card.compact { gap: var(--s3); padding: var(--s3) var(--s4); }
.player-card-head { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s3); align-items: center; }
.player-card-head .cosmetic-dot { margin: 0; }
.player-card-name { display: grid; min-width: 0; }
.player-card-name > strong { overflow-wrap: anywhere; font-size: var(--text-lg); line-height: 1.2; }
.player-card-count { display: inline-flex; align-items: center; gap: var(--s1); color: var(--muted); font-size: var(--text-sm); font-variant-numeric: tabular-nums; white-space: nowrap; justify-self: start; }
.player-card-count .ui-icon { width: 1em; height: 1em; opacity: .8; }
.player-card-count strong { color: var(--ink); font-size: var(--text-md); }
.player-card-count-label { margin-left: .3em; font-size: var(--text-xs); }
.player-card-stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s3); margin: 0; }
.player-card-stats dt { color: var(--muted); font-size: var(--text-xs); }
.player-card-stats dd { margin: 0; font-weight: var(--weight-title); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.showcase { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--s2); }
.keepsake-chip { --set: var(--sea); display: inline-flex; align-items: center; gap: var(--s2); padding: var(--s1) var(--s3); border: 1px solid color-mix(in srgb, var(--set) 45%, var(--line)); border-radius: var(--pill); background: color-mix(in srgb, var(--set) 10%, var(--surface)); font-size: var(--text-sm); font-weight: var(--weight-label); }
[data-set="journey"] { --set: var(--accent); }
[data-set="endless"] { --set: var(--sea); }
[data-set="arena"] { --set: var(--aurora); }
.versus { display: grid; gap: var(--s2); }
.versus-mark { justify-self: center; color: var(--muted); font-size: var(--text-xs); font-weight: var(--weight-title); letter-spacing: var(--tracking-label); text-transform: uppercase; }
.cosmetic-dot { width: var(--s4); height: var(--s4); display: inline-block; border-radius: var(--s1); background: var(--sea); margin-right: var(--s2); }
.shell:has(.play-layout)::before { content: ""; position: fixed; z-index: -1; inset: 0; pointer-events: none; background: radial-gradient(ellipse at 30% 30%, color-mix(in srgb, var(--scene-accent) 14%, transparent), transparent 55%), radial-gradient(ellipse at 70% 80%, var(--game-lift), transparent 55%); }
.shell:has(.play-layout) main { padding: var(--s6) 0; }
/* Every game page shares one frame (GamePage): the same width and rhythm at every screen size. */
.game-page { width: 100%; min-width: 0; max-width: var(--game-width); margin-inline: auto; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s3); }
.play-layout > aside:not(:has(*)) { display: none; }
.play-main { min-width: 0; width: 100%; margin: 0 auto; display: grid; gap: var(--s2); }
.play-main .board-wrap { width: 100%; max-width: min(var(--board-fit, clamp(var(--board-min-size), calc((100svh - var(--game-chrome)) * var(--board-ratio)), 100%)), var(--board-size), 100%); margin-inline: auto; }
.coach .coach-traits-title { font-size: var(--text-md); margin: 0; }
.result.result-flash { animation: result-flash 900ms var(--ease-enter); }
@keyframes result-flash { 0%, 100% { box-shadow: 0 0 0 0 transparent; } 30% { box-shadow: 0 0 0 6px color-mix(in srgb, var(--sea) 45%, transparent); } }
@media (prefers-reduced-motion: reduce) { .result.result-flash { outline: 3px solid var(--sea); } }
.board-wrap { position: relative; isolation: isolate; background: var(--board); border: 1px solid var(--cell-edge); border-radius: var(--radius-lg); padding: var(--s3); touch-action: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; box-shadow: inset 0 1px 0 var(--frame-highlight), inset 0 calc(-1 * var(--s2)) var(--s6) var(--frame-shadow), var(--board-shadow); }
html.swiping, html.swiping * { user-select: none !important; -webkit-user-select: none !important; }
.board { display: block; width: 100%; height: auto; overflow: visible; }
.board-cell { stroke: var(--cell-edge); stroke-width: 1.5; }
.piece { cursor: grab; }
.piece:focus { outline: none; }
.piece[aria-disabled="true"] { cursor: default; }
.piece:active { cursor: grabbing; }
.piece-depth { fill: var(--piece-depth); pointer-events: none; }
.piece-sheen, .piece-bevel { pointer-events: none; }
.piece-glint { opacity: 0; pointer-events: none; }
.piece-bevel { fill: none; stroke-width: var(--fx-bevel); }
.piece-shape { stroke: color-mix(in srgb, var(--cargo-colour) var(--edge-tint, 86%), var(--edge-base, var(--shine))); stroke-opacity: var(--edge-alpha, .4); stroke-width: var(--piece-rim); }
.piece-glow { opacity: var(--piece-bloom); pointer-events: none; transition: opacity var(--fast) var(--ease); }
.piece-outline { fill: none; stroke: var(--board-ink); stroke-width: var(--piece-focus); opacity: 0; pointer-events: none; }
.piece.selected .piece-outline, .piece:focus .piece-outline { opacity: 1; }
.piece.selected .piece-glow, .piece.hinted .piece-glow { opacity: .55; }
.piece.hinted .piece-outline { stroke: var(--warning); opacity: 1; }
.piece-mark { transform: translate(var(--piece-mark-inset), var(--piece-mark-inset)) scale(calc(var(--piece-mark-size) / 80)); fill: var(--piece-symbol); stroke: var(--piece-symbol-edge); stroke-width: 1.5; stroke-linejoin: round; pointer-events: none; }
.trait-mark { pointer-events: none; }
.trait-mark circle { fill: color-mix(in srgb, var(--board) 78%, transparent); stroke: color-mix(in srgb, var(--board-ink) 22%, transparent); stroke-width: 1.5; }
.trait-mark path { fill: none; stroke: var(--board-ink); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.piece-frost { fill: #fff; fill-opacity: .3; stroke: #fff; stroke-opacity: .75; stroke-width: 10; pointer-events: none; }
.board-guide { display: grid; gap: var(--s2); margin: 0; padding: 0; list-style: none; }
.board-guide li { display: grid; grid-template-columns: auto 1fr; align-items: start; gap: var(--s2); font-size: var(--text-sm); line-height: 1.35; }
.board-guide li > span:last-child { display: block; }
.board-guide .new-tag { display: inline-block; margin: 0 var(--s1) 0 0; vertical-align: 1px; }
.board-guide li.new strong { color: var(--accent); }
.board-guide .trait-icon { display: grid; place-items: center; width: 1.75rem; height: 1.75rem; border-radius: 50%; background: var(--elevated); color: var(--ink); }
.board-guide .trait-icon svg { width: 1rem; height: 1rem; }
.board-guide .new-tag { justify-self: start; margin-bottom: var(--s1); padding: 0 var(--s2); border-radius: var(--pill); background: var(--accent); color: var(--surface); font-size: .75rem; font-weight: var(--weight-label); }
.gate { stroke-linecap: round; stroke-width: var(--gate-width); }
.gate-glow { opacity: .5; pointer-events: none; }
.gate-core { stroke: color-mix(in srgb, var(--gate-colour) var(--edge-tint, 100%), var(--edge-base, #000)); }
.gate-core, .gate-filament, .gate-glow { transition: opacity var(--normal) var(--ease); }
.gate-filament { stroke: var(--shine); stroke-width: 3; opacity: .2; pointer-events: none; }
.exit-gate.ready .gate-glow { opacity: .9; }
.exit-gate.ready .gate-filament { opacity: .65; }
.gate-mark { fill: var(--board); stroke: var(--board); stroke-width: 2; pointer-events: none; }
.effects-canvas { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 3; pointer-events: none; border-radius: inherit; }
.board-clear { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--s3); z-index: 2; pointer-events: none; color: var(--game-ink); background: radial-gradient(ellipse, var(--board) 25%, transparent 75%); border-radius: inherit; }
.board-clear > svg { width: var(--s16); height: var(--s16); fill: none; stroke: var(--game-accent); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.board-clear strong { font-size: var(--text-xl); letter-spacing: var(--tracking-title); }
.board-clear span { font-size: var(--text-sm); color: var(--game-muted); }
.board-stars { display: flex; gap: var(--s1); margin: 0; font-size: var(--text-xl); line-height: 1; }
.board-clear .star { font-size: inherit; color: var(--game-muted); opacity: .35; }
.board-clear .star.earned { color: var(--game-accent); opacity: 1; }
.board-clear .board-mastery.hit { color: var(--game-accent); font-weight: 600; }
.board-result-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s2); max-width: 100%; padding-inline: var(--s2); pointer-events: auto; }
.board-result-actions .board-result-button { padding: var(--s2) var(--s3); white-space: nowrap; }
.board-result-button { pointer-events: auto; font-size: var(--text-sm); display: inline-flex; align-items: center; gap: var(--s2); }
.board-wrap[data-instant="true"] .piece-glow, .board-wrap[data-instant="true"] .gate { transition: none; }
.controls { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s2); }
.controls button { padding: var(--s2); }

/* One shared look (#4): every game's HUD stats, level tiles, tool row and win buttons. Colors stay per game. */
/* LinkBanner: one slim line above a board a friend's link opened, tucked close to the HUD so short phones keep their
   board. The name gives way first (its shrink factor dwarfs the words', so they keep every letter until it's gone),
   then the rest ellipsizes. */
.link-banner { display: flex; align-items: center; gap: .3em; width: fit-content; max-width: 100%; min-width: 0; min-height: 1.75rem; box-sizing: border-box;
  margin: 0 0 calc(-1 * var(--s1)); padding: var(--s1) var(--s3); border-radius: var(--pill); background: var(--hud-film, color-mix(in srgb, var(--ink) 10%, transparent));
  color: var(--ink); font-size: var(--text-sm); font-weight: var(--weight-label); line-height: 1.3; }
.link-banner > :is(strong, span:not(.link-banner-pet)) { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.link-banner > strong { flex: 0 1000000 auto; }
.link-banner > span:not(.link-banner-pet) { flex: 0 1 auto; }
.link-banner-pet { flex: none; display: grid; margin: calc(-1 * var(--s1)) var(--s1) calc(-1 * var(--s1)) calc(-1 * var(--s1)); }
@media (max-width: 440px) { .link-banner { padding-inline: var(--s2); } }
/* The smallest phones (320px) give the pet's room to the words. */
@media (max-width: 359px) { .link-banner-pet { display: none; } }
/* GameHud: the top of every play page. Title left, pet and switches right, live stats below.
   A game tints it through --hud-film (switch and pet backing) and --hud-eyebrow. */
.game-hud { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; grid-template-areas: "title pet tools" "stats stats stats" "track track track";
  align-items: center; gap: var(--s2) var(--s3); min-width: 0; }
.game-hud-title { grid-area: title; min-width: 0; }
.game-hud-title .eyebrow { margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--hud-eyebrow, var(--muted)); }
.game-hud-title .eyebrow a { color: inherit; text-decoration: none; }
/* The rank/world link is small print but still a 24px-tall target; it spills into the padding, not the layout. */
.game-hud-title .eyebrow:has(> a) { overflow: visible; }
.game-hud-title .eyebrow > a { position: relative; display: block; overflow: hidden; text-overflow: ellipsis; padding-block: .35rem; margin-block: -.35rem; }
.game-hud-title .eyebrow a:hover { text-decoration: underline; }
.game-hud-title h1 { margin: 0; font-size: var(--text-2xl); letter-spacing: var(--tracking-title); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.game-hud-pet { grid-area: pet; position: relative; display: grid; place-items: center; width: 3.25rem; height: 3.25rem; border-radius: 50%;
  background: var(--hud-film, color-mix(in srgb, var(--ink) 10%, transparent)); color: var(--ink); text-decoration: none; }
.game-hud-pet .pet-avatar { margin-top: -6px; }
.game-hud-pet.adopt { width: auto; height: auto; padding: var(--s1) var(--s3); border: 1px dashed var(--line); border-radius: var(--pill); background: none;
  color: inherit; font-size: var(--text-sm); font-weight: var(--weight-label); }
.game-hud-pet-level { position: absolute; right: -4px; bottom: -2px; min-width: 1.25rem; padding: 1px 4px; border-radius: var(--pill); background: var(--ink);
  color: var(--surface); font-size: var(--text-xs); font-weight: var(--weight-title); text-align: center; }
.game-hud-tools { grid-area: tools; display: flex; gap: var(--s1); }
.game-hud-tool { display: grid; place-items: center; width: var(--control); height: var(--control); min-height: 0; padding: 0; border-color: var(--line);
  border-radius: 50%; background: var(--hud-film, var(--surface)); color: var(--ink); }
.game-hud-tool[aria-pressed="false"] { color: var(--muted); }
.game-hud-stats { grid-area: stats; display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s4); min-width: 0; min-height: 1.75rem; }
/* The bonus chip rides at the end of the stats row, so showing, losing or winning it never resizes the board. */
.game-hud-stats .coin-bonus { margin-left: auto; }
.game-hud-stats .coin-bonus-rule { left: auto; right: 0; translate: none; }
/* The narrowest phones (320px) show just the coin: the words would wrap the chip under the stats, a line taken from the
   board. The chip keeps its name for screen readers, and a tap still opens the rule. */
@media (max-width: 359px) { .game-hud-stats .coin-bonus-label { display: none; } }
.hud-stats { display: flex; flex-wrap: wrap; gap: var(--s1) var(--s6); margin: 0; }
.hud-stats div { display: flex; align-items: baseline; gap: var(--s2); }
.hud-stats dt { font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--muted); }
.hud-stats dd { margin: 0; font-size: var(--text-xl); font-weight: var(--weight-title); font-variant-numeric: tabular-nums; }
.hud-stats .urgent dd { color: var(--error); }
.hud-stats .timer { white-space: nowrap; }
.game-hud-toggle { margin-left: auto; min-height: 0; padding: var(--s1) var(--s3); font-size: var(--text-xs); }
/* Compact HUD controls keep their small look but get a 44px-tall touch target, without growing the HUD. */
:is(.game-hud-toggle, .coin-bonus-chip) { position: relative; }
:is(.game-hud-toggle, .coin-bonus-chip)::after { content: ""; position: absolute; inset: -8px -2px; min-height: 44px; }
@media (max-width: 640px) {
  .game-hud { gap: var(--s1) var(--s2); }
  .game-hud-title h1 { font-size: var(--text-xl); }
  .game-hud-pet { width: 3rem; height: 3rem; }
  .game-hud-tool { width: 2.5rem; height: 2.5rem; }
  .hud-stats dd { font-size: var(--text-lg); }
}
/* Landscape phones: one row, so the board keeps the height. */
@media (orientation: landscape) and (max-height: 520px) {
  .game-hud { grid-template-columns: minmax(0, 1fr) auto auto auto; grid-template-areas: "title stats pet tools" "track track track track"; }
  .game-hud-title h1 { font-size: var(--text-lg); }
  .game-hud-pet { width: 2.5rem; height: 2.5rem; }
  .game-hud-tool { width: 2.25rem; height: 2.25rem; }
}
/* Phones: the adopt pill stacks onto two short lines so the level title keeps its room. */
@media (max-width: 440px) {
  .game-hud-pet.adopt { max-width: 4.25rem; padding: 2px var(--s2); font-size: var(--text-xs); line-height: 1.15; text-align: center; }
}
@media (max-width: 380px) {
  .game-hud-title h1 { font-size: var(--text-lg); }
  .game-hud-tools { gap: 2px; }
  .game-hud-tool { width: 2.25rem; height: 2.25rem; }
}
/* Levels pages, shared by every game: a map of world cards, each a 5-wide grid of numbered tiles.
   A game colors a card through --world-* and --stage-* (Sand Sort sets its own); others pass --hue. */
.level-world {
  --world-glow: hsl(var(--hue, 175) 62% 52%); --world-top: color-mix(in srgb, var(--world-glow) 16%, var(--surface)); --world-bottom: var(--surface);
  --stage-film: var(--ink); --stage-lift: var(--ink); --stage-ink: var(--ink); --stage-star: color-mix(in srgb, var(--accent) 50%, var(--ink));
  --world-label: color-mix(in srgb, var(--world-glow) 32%, var(--ink));
}
.level-map { display: grid; gap: var(--s4); grid-template-columns: repeat(auto-fill, minmax(min(100%, 19rem), 1fr)); }
.level-world { padding: var(--s4); border-radius: var(--radius); color: var(--stage-ink); display: grid; gap: var(--s3); align-content: start;
  background: radial-gradient(ellipse 80% 60% at 50% 120%, color-mix(in srgb, var(--world-glow) 32%, transparent), transparent 70%), linear-gradient(160deg, var(--world-top), var(--world-bottom));
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--stage-film) 12%, transparent); }
.level-world.here { box-shadow: inset 0 1px 0 color-mix(in srgb, var(--stage-film) 12%, transparent), 0 0 0 2px var(--world-glow); }
/* Locked worlds and levels recede by losing their glow, fill and color, never their text contrast. */
.level-world.locked { background: linear-gradient(160deg, var(--world-top), var(--world-bottom)); outline: 1px dashed color-mix(in srgb, var(--stage-film) 24%, transparent); outline-offset: -1px; filter: saturate(.25); }
.level-world.locked h2 { color: color-mix(in srgb, var(--stage-ink) 72%, transparent); }
.level-world.locked .world-stars { color: color-mix(in srgb, var(--stage-ink) 82%, transparent); }
.level-world header { display: grid; grid-template-columns: 1fr auto; align-items: end; gap: 0 var(--s3); }
.level-world .eyebrow { grid-column: 1 / -1; margin: 0; color: var(--world-label); }
.level-world h2 { margin: 0; font-size: var(--text-xl); }
.level-world .world-stars { margin: 0; font-size: var(--text-sm); color: var(--stage-star); font-variant-numeric: tabular-nums; }
.level-world .muted { color: color-mix(in srgb, var(--stage-ink) 82%, transparent); margin: 0; }
.level-world ol { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; }
.level-world li a, .level-world li > span { position: relative; display: grid; justify-items: center; gap: 2px; padding: var(--s2) 0; border-radius: var(--radius-sm); background: color-mix(in srgb, var(--stage-film) 7%, transparent);
  color: inherit; text-decoration: none; border: 1px solid color-mix(in srgb, var(--stage-film) 9%, transparent); }
.level-world li a:hover { background: color-mix(in srgb, var(--stage-film) 14%, transparent); }
.level-world li.boss a, .level-world li.boss > span { border-color: color-mix(in srgb, var(--world-glow) 70%, transparent); }
.level-world li.current a { background: color-mix(in srgb, var(--world-glow) 22%, transparent); border-color: var(--world-glow); }
.level-world li.locked > span { background: transparent; border-style: dashed; color: color-mix(in srgb, var(--stage-ink) 78%, transparent); }
.level-world .level-stars { color: var(--stage-star); }
.level-world .level-stars i { color: color-mix(in srgb, var(--stage-film) 19%, transparent); }
.level-redesign-dot { position: absolute; top: 6px; right: 6px; width: .45rem; height: .45rem; border-radius: 50%; background: var(--stage-star); box-shadow: 0 0 0 2px var(--world-bottom); }
.redesign-pop-actions { display: grid; width: 100%; gap: var(--s2); }
.redesign-pop-actions > button { width: 100%; justify-content: center; }
/* Where this level sits in its world, under the play HUD. */
.game-hud-track { grid-area: track; padding-bottom: 10px; }
/* Short screens: keep the header compact so the board and its controls still fit. */
@media (max-height: 700px) {
  .game-hud { row-gap: var(--s1); }
  .game-hud-title h1 { font-size: var(--text-xl); }
}
.world-track { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(var(--track-cols, 10), 1fr); gap: 6px; }
.world-track li { position: relative; height: 6px; border-radius: var(--pill); background: color-mix(in srgb, var(--track-film, var(--ink)) 11%, transparent); }
.world-track li.done { background: var(--track-glow, var(--accent)); }
.world-track li.current { background: color-mix(in srgb, var(--track-film, var(--ink)) 33%, transparent); box-shadow: 0 0 0 2px var(--track-ring, color-mix(in srgb, var(--accent) 60%, transparent)); }
.world-track span { position: absolute; top: 9px; left: 0; right: 0; text-align: center; font-size: 9px; line-height: 1; letter-spacing: -1px; color: var(--accent); }
.level-tiles a, .level-tiles button { touch-action: manipulation; transition: transform var(--fast) var(--ease), background-color var(--fast) var(--ease), border-color var(--fast) var(--ease); }
.level-tiles a:active, .level-tiles button:not(:disabled):active { transform: scale(.95); }
.level-tiles strong { font-size: var(--text-lg); font-weight: var(--weight-title); font-variant-numeric: tabular-nums; }
.level-tiles .level-stars { font-size: var(--text-xs); letter-spacing: 1px; }
.level-tiles .level-stars i { font-style: normal; }
.direction-controls { display: flex; justify-content: center; gap: var(--s2); }
.direction-controls button { width: var(--control); padding: var(--s2); }
.instructions { display: grid; gap: var(--s4); color: var(--muted); font-size: var(--text-sm); }
.instructions h3 { color: var(--ink); }
.instructions summary { min-height: var(--control); cursor: pointer; display: flex; align-items: center; }
.status-line { min-height: var(--s12); font-size: var(--text-sm); color: var(--sea); }
.status-line .goal-line { color: var(--muted); }
.result { display: grid; gap: var(--s4); border-color: var(--sea); animation: result-arrives var(--normal) var(--ease-enter); }
.play-layout:has(.board-wrap[data-instant="true"]) .result { animation: none; }
@keyframes result-arrives { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.daily-win-actions { display: grid; gap: var(--s2); width: 100%; }
.daily-win-actions > :is(button, .button) { width: 100%; justify-content: center; }
.daily-next-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s2); }
.daily-next-row > .button { justify-content: center; }
.daily-next-wheel { aspect-ratio: 1; padding: 0 var(--s2); border-color: color-mix(in srgb, var(--accent) 55%, var(--line)); background: color-mix(in srgb, var(--accent) 10%, var(--surface)); }
.boot { text-align: center; min-height: 70dvh; display: grid; place-content: center; justify-items: center; gap: var(--s4); }
.loading-progress-text::after { content: var(--blazor-load-percentage-text, "Preparing the game"); }
#blazor-error-ui { display: none; position: fixed; inset: auto 0 0; z-index: 1000; padding: var(--s4); background: var(--surface); color: var(--error); border-top: 1px solid var(--error); }
/* Pull to refresh in the installed app (app.js): a round arrow that follows the pull and spins while reloading. */
.pull-refresh { position: fixed; top: calc(env(safe-area-inset-top) - 40px); left: calc(50% - 20px); z-index: 1001; display: grid; place-items: center; width: 40px; height: 40px;
  border: 1px solid var(--line); border-radius: 50%; background: var(--surface); color: var(--muted); box-shadow: var(--shadow); pointer-events: none; opacity: 0; transition: opacity .15s, color .15s; }
.pull-refresh.on, .pull-refresh.loading { opacity: 1; }
.pull-refresh.ready, .pull-refresh.loading { color: var(--accent); }
.pull-refresh.loading { transform: translateY(70px) !important; }
.pull-refresh.loading svg { animation: pull-spin .8s linear infinite; }
@keyframes pull-spin { to { rotate: 360deg; } }
.skip { position: fixed; top: var(--s2); left: var(--s2); transform: translateY(-200%); z-index: 100; }
.skip:focus { transform: none; }
@media (max-width: 1023px) {
  .shell { padding: 0 var(--s6); }
  .masthead { gap: var(--s4); }
  .game-home { row-gap: var(--s8); }
  .account-label { display: none; }
  .account-link { justify-content: center; padding-inline: 0; }
  .account-link .account-pet { margin: 0; }
  nav a { padding: var(--s2); }
  nav .ui-icon { display: none; }
}
@media (max-width: 767px) {
  .shell { padding: 0 var(--s4); }
  .masthead { padding: var(--s4) 0; }
  /* Anything scrolled into view (focus, find, links to #ids) stops above the floating tab bar. */
  html { scroll-padding-bottom: calc(var(--nav-h, 4.5rem) + max(var(--s2), env(safe-area-inset-bottom)) + var(--s2)); }
  /* app.js nudges it with a transform when iOS leaves it above the collapsed toolbar. */
  nav { position: fixed; bottom: max(var(--s2), env(safe-area-inset-bottom)); left: var(--s2); right: var(--s2); z-index: 40; justify-content: space-around; padding: var(--s1); box-shadow: var(--shadow); -webkit-backface-visibility: hidden; backface-visibility: hidden; }
  nav a { display: grid; gap: var(--s1); padding: var(--s2) var(--s1); font-size: var(--text-xs); flex: 1; min-width: 0; justify-items: center; white-space: nowrap; }
  /* app.js sets data-typing while a field has focus: the keyboard is up, and the bar would float on top of it. */
  :root[data-typing] nav { visibility: hidden; }
  nav .ui-icon { display: block; width: 1.375rem; height: 1.375rem; }
  /* Icons only on the phone tab bar; the label stays for screen readers. */
  nav .nav-label { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); }
  .account-link { padding: var(--s2); } .coin-chip { padding: 0 var(--s2); } .header-actions { gap: var(--s1); }
  .brand img { width: var(--s6); height: var(--s6); }
  .masthead { gap: var(--s2); }
  main { padding: var(--s6) 0; }
  .game-home, .columns { grid-template-columns: minmax(0, 1fr); gap: var(--s6); }
  .home-modes { grid-template-columns: minmax(0, 1fr); gap: var(--s3); }
  .home-packs { margin-top: var(--s8); }
  .game-intro { gap: var(--s2); }
  .mode-grid { grid-template-columns: 1fr; margin-top: var(--s6); }
  .player-card-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s2); }
  .mode-link { grid-template-columns: auto 1fr 1.5fr; }
  .mode-link > span { grid-column: auto; font-size: var(--text-sm); }
  .footer { padding-bottom: calc(var(--s16) + var(--s8) + env(safe-area-inset-bottom)); }
  .panel { padding: var(--s4); }
  .board-wrap { padding: var(--s2); }
  .play-main { --game-chrome: var(--game-chrome-mobile); }
}
/* Short touch phones (375x548): swiping moves blocks, so the arrow row gives its height to the tools. */
@media (max-width: 640px) and (max-height: 560px) and (orientation: portrait) and (pointer: coarse) { .direction-controls { display: none; } }
/* Seven tabs on the smallest phones (320px). */
@media (max-width: 359px) { nav { gap: 0; } nav a { padding-inline: 0; letter-spacing: -0.01em; } }
@media (hover: hover) and (pointer: fine) {
  button:hover, .button:hover { background: var(--elevated); }
  button.primary:hover, .button.primary:hover { background: color-mix(in srgb, var(--accent) 92%, var(--shine)); }
  nav a:hover { background: var(--elevated); color: var(--ink); }
  .mode-link:hover, .home-tile:hover, .home-pack a:hover { border-color: var(--sea); }
  .piece:not([aria-disabled="true"]):hover .piece-glow { opacity: .55; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; scroll-behavior: auto !important; }
  button:active, .button:active { transform: none; }
}

.coin { display: inline-block; flex: none; width: 1em; height: 1em; margin-right: 0.3em; vertical-align: -0.15em; border-radius: 50%; background: radial-gradient(circle at 35% 30%, #fff3b8 0 18%, #f5c542 42%, #c98b12 100%); box-shadow: inset 0 0 0 0.09em #a86f0a; }
.coin.large { width: 1.6em; height: 1.6em; }
.coin-chip { display: inline-flex; align-items: center; min-height: var(--control); padding: 0 var(--s3); border: 1px solid var(--line); border-radius: var(--pill); font-size: var(--text-sm); color: var(--ink); background: var(--surface); font-weight: var(--weight-title); font-variant-numeric: tabular-nums; text-decoration: none; white-space: nowrap; }
.coin-chip:hover { border-color: var(--accent); }
/* The bonus coin chip, shared by every game: one quiet line above the board; its rule floats over the board when open. */
.coin-bonus { position: relative; justify-self: center; align-self: center; display: flex; justify-content: center; margin: 0; z-index: 3; }
.coin-bonus-chip { display: inline-flex; align-items: center; gap: var(--s1); min-height: 1.75rem; padding: 0 var(--s3); border: 1px solid color-mix(in srgb, #f5c542 55%, transparent); border-radius: var(--pill);
  background: color-mix(in srgb, #f5c542 14%, var(--surface)); color: var(--ink); font: inherit; font-size: var(--text-xs); font-weight: var(--weight-title); letter-spacing: var(--tracking-label); text-transform: uppercase; white-space: nowrap; cursor: pointer; }
.coin-bonus-chip .coin { margin: 0; }
.coin-bonus-more { width: 0.9em; height: 0.9em; opacity: 0.6; }
.coin-bonus.lost .coin-bonus-chip { border-color: var(--line); background: var(--surface); color: var(--muted); }
.coin-bonus.lost .coin { filter: grayscale(1); opacity: 0.55; }
.coin-bonus-rule { position: absolute; top: calc(100% + var(--s1)); left: 50%; translate: -50% 0; width: max-content; max-width: min(18rem, 86vw); margin: 0; padding: var(--s2) var(--s3);
  border: 1px solid var(--line); border-radius: var(--radius, 12px); background: var(--surface); color: var(--ink); font-size: var(--text-sm); text-align: center; box-shadow: 0 6px 20px rgb(0 0 0 / 0.18); }
.coin-reward { display: flex; align-items: center; margin: 0; color: var(--muted); }
.coin-reward.earned { color: var(--ink); font-weight: var(--weight-title); }
.earn-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2); }
.earn-list li { display: grid; grid-template-columns: 5rem minmax(0, 1fr); gap: var(--s2); font-size: var(--text-sm); }
.earn-list span { color: var(--muted); }
.pack-options { display: grid; grid-template-columns: repeat(auto-fit, minmax(6.5rem, 1fr)); gap: var(--s2); }
.pack-options button { flex-direction: column; gap: var(--s1); font-variant-numeric: tabular-nums; }
.pack-options button.primary .caption { color: inherit; opacity: .85; }
[data-trying] { border-style: dashed; border-color: var(--accent); }
.season-banner { display: grid; width: 100%; justify-content: start; justify-items: start; gap: var(--s1); padding: var(--s4) var(--s6); text-align: left; border-left: var(--s1) solid var(--accent); }
.season-banner strong { font-size: var(--text-xl); }
.season-banner[aria-pressed="true"] { border-color: var(--accent); background: var(--elevated); }
/* Discord Activity: today's Daily for this server or chat. */
.room-entries { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s1); }
.room-entries li { display: grid; grid-template-columns: 2rem minmax(0, 1fr) auto; align-items: center; gap: var(--s3); padding: var(--s2) var(--s3); border-radius: var(--radius-sm); background: var(--background); }
.room-entries li.you { outline: 2px solid var(--sea); outline-offset: -2px; }
.room-rank { font-weight: var(--weight-title); font-variant-numeric: tabular-nums; color: var(--muted); }
.room-tabs { display: flex; gap: var(--s1); }
.room-tabs button { min-height: var(--s8); padding: var(--s1) var(--s3); border-radius: var(--pill); font-size: var(--text-sm); }
.room-tabs button[aria-selected="true"] { border-color: var(--accent); background: var(--elevated); }
.room-games { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s1); padding: var(--s1); border-radius: var(--pill); background: var(--background); border: 1px solid var(--line); }
.room-games button { min-height: var(--s8); padding: var(--s1) var(--s2); border: 1px solid transparent; border-radius: var(--pill); background: transparent; font-size: var(--text-sm); white-space: nowrap; }
.room-games button[aria-selected="true"] { border-color: var(--accent); background: var(--elevated); font-weight: 600; }
.room-name { color: inherit; text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: var(--weight-label); }
.room-actions { font-variant-numeric: tabular-nums; font-weight: var(--weight-title); }

/* First-puzzle coaching: the goal is to empty the board through color exits. */
.coach-backdrop { position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; padding: var(--s4); background: rgb(0 0 0 / 0.45); animation: fade-in .18s ease-out; }
.coach { display: grid; gap: var(--s3); width: min(28rem, 100%); padding: var(--s4) var(--s4) var(--s3); max-height: calc(100dvh - 2 * var(--s4)); overflow: auto; box-shadow: 0 var(--s4) var(--s12) rgb(0 0 0 / 0.3); }
.coach h2 { margin: calc(-1 * var(--s2)) 0 0; font-size: 1.4rem; }
.coach .eyebrow { margin: 0; }
.coach-demo { width: 100%; max-width: 20rem; max-height: 7.5rem; justify-self: center; overflow: visible; }
.coach-grid { fill: var(--elevated); stroke: var(--line); }
.coach-cell { stroke: var(--line); stroke-width: .5; }
.coach-exit { stroke-width: 4; stroke-linecap: round; }
.coach-blue { animation: coach-blue 5s ease-in-out infinite; }
.coach-red { animation: coach-red 5s ease-in-out infinite; }
.coach-steps { display: grid; gap: var(--s2); margin: 0; padding-left: 1.25rem; font-size: var(--text-sm); line-height: 1.35; color: var(--muted); }
.coach-steps strong { display: block; color: var(--ink); }
.coach-steps.quick { gap: var(--s2); font-size: var(--text-md); }
.coach-steps.quick strong { font-weight: var(--weight-label); }
.coach-note { margin: 0; }
.coach-hide { display: flex; align-items: center; gap: var(--s2); min-height: 2.25rem; font-size: var(--text-sm); color: var(--muted); cursor: pointer; }
.coach-hide input { width: 1.15rem; height: 1.15rem; margin: 0; accent-color: var(--accent); }
.coach-actions { display: grid; grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr)); gap: var(--s2); }
.coach-actions button { min-height: 2.75rem; padding-block: var(--s2); }
.coach-tips-title { font-size: var(--text-md); margin: 0; }
.coach-tips { display: grid; gap: var(--s1); margin: 0; padding-left: 1.25rem; font-size: var(--text-sm); line-height: 1.35; color: var(--muted); }
/* Tips and the rules list fold into rows so the full guide stays about one screen tall. */
.coach-more { border-top: 1px solid var(--line); }
.coach-more + .coach-more { margin-top: calc(-1 * var(--s3)); }
.coach-more > summary { display: flex; align-items: center; gap: var(--s2); min-height: 2.5rem; cursor: pointer; list-style: none; }
.coach-more > summary::-webkit-details-marker { display: none; }
.coach-more > summary > span:first-child { font-weight: var(--weight-title); font-size: var(--text-md); }
.coach-more-count { min-width: 1.4rem; padding: 0 var(--s2); border-radius: var(--pill); background: var(--elevated); font-size: var(--text-xs); font-weight: var(--weight-label); text-align: center; color: var(--muted); }
.coach-more > summary .ui-icon { margin-left: auto; width: 1.1rem; height: 1.1rem; color: var(--muted); transition: transform 160ms var(--ease); }
.coach-more[open] > summary .ui-icon { transform: rotate(180deg); }
.coach-more[open] > :last-child { margin-bottom: var(--s3); }
.coach-pour { fill: none; stroke: var(--muted); stroke-width: 2; stroke-dasharray: 3 3; stroke-linecap: round; }
.coach-pipe { fill: none; stroke-width: 8; stroke-linecap: round; stroke-linejoin: round; opacity: .75; }
.coach .bus-mini { justify-self: center; width: 7rem; height: 7rem; }
.coach .swarm-mini { justify-self: center; width: auto; height: 9rem; aspect-ratio: 1; border-radius: var(--radius); }
.help-glyph { font-size: var(--text-lg); font-weight: 700; line-height: 1; }
@keyframes fade-in { from { opacity: 0; } }
@keyframes coach-blue { 0%, 12% { transform: none; opacity: 1; } 32% { transform: translateY(-44px); opacity: 0; } 92% { transform: translateY(-44px); opacity: 0; } 100% { transform: none; opacity: 1; } }
@keyframes coach-red { 0%, 38% { transform: none; opacity: 1; } 62% { transform: translateX(110px); opacity: 0; } 92% { transform: translateX(110px); opacity: 0; } 100% { transform: none; opacity: 1; } }
/* Until the first move of a first puzzle, exits pulse so players can find where blocks go. */
.coach-exits .exit-gate .gate-glow { animation: coach-exit 1.6s ease-in-out infinite; }
@keyframes coach-exit { 50% { opacity: .95; } }

/* Phones: the primary action comes before the harbor, and the puzzle chrome is compact so the
   board gets the space. */
@media (max-width: 767px) {
  .game-intro h1 { font-size: clamp(var(--text-xl), 9vw, var(--text-2xl)); }
  .play-main .controls button, .direction-controls button { min-height: 2.5rem; }
  .shell:has(.play-layout) main { padding: var(--s3) 0; }
}
@media (max-width: 767px) and (max-height: 700px) {
  .masthead { padding: var(--s2) 0; }
  .game-intro > p.muted { font-size: var(--text-sm); }
}
/* Landscape phones: board on the left, the score and controls beside it. */
@media (orientation: landscape) and (max-height: 520px) {
  .masthead { padding: var(--s2) 0; }
  /* A bottom bar would eat a third of a landscape phone; the nav sits in the header instead. */
  nav, :root[data-typing] nav { position: static; box-shadow: none; visibility: visible; }
  nav a { display: flex; padding: var(--s2); font-size: var(--text-sm); }
  nav .ui-icon { display: none; }
  nav .nav-label { position: static; width: auto; height: auto; margin: 0; overflow: visible; clip: auto; }
  .footer { padding-bottom: var(--s6); }
  .shell:has(.play-layout) main { padding: var(--s2) 0; }
  .play-layout { grid-template-columns: minmax(0, 1fr); max-width: none; }
  .play-main { max-width: none; grid-template-columns: auto minmax(13rem, 1fr); column-gap: var(--s6); align-content: start; }
  .play-main > * { grid-column: 2; }
  .play-main .board-wrap { grid-column: 1; grid-row: 1 / span 7; align-self: start; width: var(--board-fit, 60vh); }
  .direction-controls { grid-column: 2; justify-content: start; }
  .game-home { row-gap: var(--s3); }
  .game-intro { gap: var(--s1); }
  .game-intro h1 { font-size: var(--text-2xl); }
}
/* Discord Activity: the Daily only; everything else points to the web app. */
.web-only { display: grid; gap: var(--s4); max-width: 38rem; margin: var(--s8) auto; }
.web-only.compact { margin: 0; max-width: none; grid-column: 1 / -1; }
.web-only .row { display: flex; flex-wrap: wrap; gap: var(--s2); }
@media (max-width: 767px) and (orientation: portrait), (max-width: 767px) and (min-height: 521px) {
  /* The bottom nav stays above scene overlays such as the collection button. */
  nav { z-index: 300; }
  /* One row for the score and timer; the nav already links home, so the heading keeps one line. */
  .play-main { grid-template-columns: minmax(0, 1fr) auto; column-gap: var(--s3); }
  .play-main > * { grid-column: 1 / -1; }
}

/* Choose / change name */
.name-panel { margin: 0; }
.rename-form { display: flex; gap: var(--s2); flex-wrap: wrap; }
.rename-form input { flex: 1 1 12rem; width: auto; }
.rename-form button { flex: 0 0 auto; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
/* Wording for the device in hand: .on-touch shows on phones and tablets, .on-mouse on computers. */
@media (pointer: coarse) { .on-mouse { display: none; } }
@media not all and (pointer: coarse) { .on-touch { display: none; } }

/* Mastery-target confetti: over everything, never intercepting taps. */
.confetti-canvas { position: fixed; inset: 0; width: 100vw; height: 100vh; pointer-events: none; z-index: 1000; }

/* Pets: the header and purse. The shop itself (card dock and shelves) is styled in pets.css. */
.collection-heading { position: relative; display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--s4) var(--s8); margin-bottom: var(--s8); }
.collection-heading h1 { margin: 0; overflow-wrap: anywhere; }
.collection-heading.has-pet { margin-bottom: var(--s4); }
.purse { position: static; }
.purse summary { list-style: none; display: inline-flex; align-items: center; gap: var(--s1); min-height: 2.25rem; padding: 0 var(--s3); border: 1px solid color-mix(in srgb, var(--accent) 40%, var(--line)); border-radius: var(--pill); background: color-mix(in srgb, var(--accent) 10%, var(--surface)); cursor: pointer; font-variant-numeric: tabular-nums; }
.purse summary::-webkit-details-marker { display: none; }
.purse summary strong { font-size: var(--text-md); }
.purse summary .coin { margin: 0; }
.purse summary::after { content: ""; width: .45em; height: .45em; margin-left: var(--s1); border: solid currentColor; border-width: 0 2px 2px 0; transform: translateY(-25%) rotate(45deg); transition: transform var(--fast) var(--ease); }
.purse[open] summary::after { transform: translateY(15%) rotate(-135deg); }
.purse-body { position: absolute; right: 0; top: calc(100% + var(--s2)); z-index: 30; width: min(19rem, calc(100vw - 2 * var(--s4))); padding: var(--s3); border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--surface); box-shadow: var(--shadow); }
.purse-body h3 { margin: var(--s2) 0 0; font-size: var(--text-sm); }
.purse-earn { margin: 0; }
/* Hints: your count, then small buy and sell buttons on one line each. */
.purse-hints + .purse-hints { margin-top: calc(-1 * var(--s1)); }
.purse-hints { display: grid; grid-template-columns: 3.5rem repeat(2, minmax(0, 1fr)); align-items: center; gap: var(--s1); }
.purse-count { display: inline-flex; align-items: center; gap: 3px; font-variant-numeric: tabular-nums; }
.purse-count .ui-icon { width: 1rem; height: 1rem; color: var(--gold); }
.purse-hints button { min-height: 2.25rem; padding: 0 var(--s2); gap: 2px; font-size: var(--text-sm); font-variant-numeric: tabular-nums; white-space: nowrap; }
.purse-hints button .coin { margin: 0 1px 0 2px; }
.purse[open] .purse-body { animation: drop-in var(--normal) var(--ease-enter); }
@keyframes drop-in { from { opacity: 0; transform: translateY(-4px); } }

.catalog { display: grid; gap: var(--s4); min-width: 0; }

.search { position: relative; flex: 1 1 14rem; display: flex; align-items: center; }
.search .ui-icon { position: absolute; left: var(--s3); width: 1.1rem; height: 1.1rem; color: var(--muted); pointer-events: none; }
.search input { padding-left: calc(var(--s3) + 1.1rem + var(--s2)); border-radius: var(--pill); background: var(--surface); }
.search input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.segmented { display: inline-flex; padding: 3px; border: 1px solid var(--line); border-radius: var(--pill); background: var(--surface); }
.segmented button { min-height: calc(var(--control) - 8px); padding: 0 var(--s3); border: 0; border-radius: var(--pill); background: transparent; color: var(--muted); font-size: var(--text-sm); white-space: nowrap; }
.segmented button[aria-pressed="true"] { background: var(--elevated); color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); }
.sort { flex: none; }
.sort select { width: auto; border-radius: var(--pill); background-color: var(--surface); font-size: var(--text-sm); }
.catalog .season-banner { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: var(--s3); row-gap: 0; padding: var(--s3) var(--s4); }
.catalog .season-banner strong { font-size: var(--text-lg); }
.catalog .season-banner .eyebrow { flex-basis: 100%; margin: 0; }
.sort select { min-height: var(--s8); padding-block: var(--s1); }
.group-title { margin: var(--s4) 0 0; font-size: var(--text-md); display: flex; align-items: center; gap: var(--s3); }
.group-title::after { content: ""; flex: 1; height: 1px; background: var(--line); }

/* Swatch tiles. */
.catalog .theme-options { grid-template-columns: repeat(auto-fill, minmax(min(100%, 8.5rem), 1fr)); }
.catalog .theme-options button { justify-content: flex-start; }
.theme-options button { font-weight: var(--weight-title); }
.theme-options .caption { font-weight: var(--weight-body); }
/* Scene swatches preview the real habitat, not a flat gradient. */
.sky-swatch { display: block; position: relative; margin-bottom: var(--s1); }
.sky-swatch.pet-habitat { width: 100%; height: 4rem; min-height: 0; border-radius: var(--radius-sm); box-shadow: inset 0 0 0 1px #070c1822; }
.sky-swatch .meadow svg { height: 100%; }
.sky-name { display: flex; align-items: center; }

/* Trophies: earned by playing, pinned to the player card. */
.trophy-intro { display: grid; gap: var(--s1); }
.trophy-intro p { margin: 0; }
.trophy-intro .eyebrow { margin: 0; }
.trophy-grid { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 14rem), 1fr)); gap: var(--s2); }
.trophy { --set: var(--sea); display: flex; align-items: flex-start; gap: var(--s2); padding: var(--s2) var(--s3); border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--background); }
.trophy[data-set="journey"] { --set: var(--accent); }
.trophy[data-set="arena"] { --set: var(--aurora); }
/* Still to earn reads as a quiet outline, so the earned ones stand out at a glance. */
.trophy:not(.earned) { border-style: dashed; background: transparent; }
.trophy:not(.earned) .trophy-text > strong { color: var(--muted); }
.trophy.earned { background: var(--surface); border-color: color-mix(in srgb, var(--set) 45%, var(--line)); box-shadow: var(--shadow); }
.trophy.focused { outline: 3px solid var(--accent); outline-offset: 2px; animation: trophy-found 1.2s ease-out 2; }
@keyframes trophy-found { 0% { box-shadow: 0 0 0 0 var(--accent); } 100% { box-shadow: 0 0 0 .9rem transparent; } }
@media (prefers-reduced-motion: reduce) { .trophy.focused { animation: none; } }
.trophy.pinned { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent), var(--shadow); }
.trophy-text { display: grid; gap: var(--s1); flex: 1; min-width: 0; }
.trophy-text strong { line-height: 1.3; }
.trophy-text .caption { line-height: 1.35; }
.trophy progress { width: 100%; height: var(--s1); margin-top: var(--s1); border: 0; border-radius: var(--pill); overflow: hidden; background: var(--elevated); accent-color: var(--set); }
.trophy progress::-webkit-progress-bar { background: var(--elevated); }
.trophy progress::-webkit-progress-value { background: var(--set); border-radius: var(--pill); }
.trophy progress::-moz-progress-bar { background: var(--set); border-radius: var(--pill); }
.trophy-count { font-size: var(--text-xs); font-variant-numeric: tabular-nums; }
.trophy .pin { flex: none; min-height: var(--s8); padding: var(--s1) var(--s3); font-size: var(--text-xs); background: transparent; }
.trophy .pin[aria-pressed="true"] { border-color: var(--accent); background: var(--accent); color: var(--on-accent); }
.pin-shelf { display: grid; gap: var(--s2); padding: var(--s3); border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); box-shadow: var(--shadow); }
.pin-shelf.swapping { border-color: var(--accent); }
.pin-shelf-head, .pin-shelf-note { margin: 0; }
.pin-shelf-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s2); }
.pin-slots { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s2); margin: 0; padding: 0; list-style: none; }
.pin-slot { --set: var(--sea); position: relative; min-width: 0; }
.pin-slot-face { display: grid; justify-items: center; align-content: start; gap: var(--s1); width: 100%; min-height: 6.5rem; padding: var(--s3) var(--s1) var(--s2); border: 1px solid color-mix(in srgb, var(--set) 45%, var(--line)); border-radius: var(--radius); background: color-mix(in srgb, var(--set) 10%, var(--surface)); color: var(--ink); font: inherit; text-align: center; }
.pin-slot-name { font-size: var(--text-xs); font-weight: var(--weight-label); line-height: 1.25; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.pin-slot.empty .pin-slot-face { border-style: dashed; border-color: var(--line); background: transparent; color: var(--muted); cursor: pointer; }
.pin-slot-plus { display: grid; place-items: center; width: 2.5rem; height: 2.5rem; border-radius: 50%; border: 2px dashed currentColor; font-size: var(--text-lg); line-height: 1; }
.pin-slot-x { position: absolute; top: -.4rem; right: -.4rem; width: 1.9rem; height: 1.9rem; border: 1px solid var(--line); background: var(--surface); box-shadow: var(--shadow); }
.pin-slot-swap { padding: 0 var(--s2); border-radius: var(--pill); background: var(--accent); color: var(--on-accent); font-size: var(--text-xs); font-weight: var(--weight-label); }
.pin-shelf.swapping .pin-slot.filled .pin-slot-face { cursor: pointer; animation: pin-wiggle 1.6s ease-in-out infinite; }
.pin-slot.popped .pin-slot-face { animation: pin-pop .45s cubic-bezier(.2, 1.4, .4, 1); }
@keyframes pin-pop { 0% { transform: scale(.7); opacity: .4; } 100% { transform: none; opacity: 1; } }
@keyframes pin-wiggle { 0%, 100% { transform: none; } 25% { transform: rotate(-1.5deg); } 75% { transform: rotate(1.5deg); } }
@media (prefers-reduced-motion: reduce) { .pin-slot.popped .pin-slot-face, .pin-shelf.swapping .pin-slot.filled .pin-slot-face { animation: none; } }

/* Phones: the harbor is a compact strip pinned above the catalog, clear of the bottom nav. */
@media (max-width: 767px) {
  .collection-heading { margin-bottom: var(--s4); align-items: center; }
  .collection-heading h1 { font-size: var(--text-xl); }
  .collection-heading .muted { display: none; }
}

/* Airplane mode: one button in every game's header. */
/* Phones keep appearance in the account menu. */

/* Daily reset: the board starts over but the score doesn't, so it asks first and says so. */
.reset-confirm { display: grid; gap: var(--s2); margin-top: var(--s3); padding: var(--s3) var(--s4); border: 1px solid color-mix(in srgb, var(--accent) 50%, var(--line)); border-radius: var(--radius-sm); background: var(--surface); }
.reset-confirm p { margin: 0; }
.arena-forfeit { justify-self: center; display: inline-flex; align-items: center; gap: var(--s1); min-height: 44px; padding: var(--s1) var(--s3); border-color: transparent; background: transparent; color: var(--muted); font-size: .9rem; }
.arena-forfeit:hover:not(:disabled) { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, var(--line)); }
.arena-forfeit-confirm { justify-self: center; width: min(100%, 26rem); border-color: color-mix(in srgb, var(--danger) 45%, var(--line)); }
.arena-forfeit-confirm button.danger { background: transparent; border-color: var(--danger); color: var(--danger); }
/* Focus lands on Keep playing when it opens; leave room for the phone tab bar below it. */
.arena-forfeit-confirm button { scroll-margin-bottom: calc(var(--control) * 2 + var(--s4)); }
.reset-actions { display: flex; flex-wrap: wrap; gap: var(--s2); }

/* Masthead fit levels, set by app.js only while the full header would overflow. */
.masthead > nav, .masthead > .header-actions, .masthead > .game-menu { flex-shrink: 0; }
.masthead:not([data-fit="0"]) .install-button { padding: 0; width: var(--control); }
.masthead:not([data-fit="0"]) .install-button-label,
.masthead:not([data-fit="0"]) .account-label { display: none; }
.masthead:not([data-fit="0"]) .account-link { justify-content: center; padding-inline: 0; }
.masthead:not([data-fit="0"]) .account-link .account-pet { margin: 0; }
.masthead:is([data-fit="2"], [data-fit="3"], [data-fit="4"]) nav .ui-icon { display: none; }
.masthead:is([data-fit="2"], [data-fit="3"], [data-fit="4"]) nav a { padding-inline: var(--s2); }
.masthead:is([data-fit="3"], [data-fit="4"]) { gap: var(--s2); }
.masthead:is([data-fit="3"], [data-fit="4"]) .header-actions { gap: var(--s1); }
.masthead:is([data-fit="3"], [data-fit="4"]) .game-switcher .brand-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.masthead[data-fit="4"] :is(.install-button, .admin-button, .quick-play) { display: none; }
.masthead[data-fit="4"] { gap: var(--s1); }
.masthead[data-fit="4"] .game-switcher { gap: var(--s1); padding-inline: var(--s1); }
.account-menu-links .header-shortcut { display: none; }
.masthead[data-fit="4"] .header-shortcut { display: flex; }
@media (max-width: 767px) {
  /* The tab bar is fixed to the bottom on phones, so it never counts against the header. */
  .masthead[data-fit] nav .ui-icon { display: block; }
  .masthead[data-fit] nav a { padding: var(--s2) var(--s1); }
}

/* Trophy tiers, medals, pedestal and the pet pop-up. */
[data-tier="bronze"] { --tier: #b87333; --tier-hi: #e7a46b; }
[data-tier="silver"] { --tier: #8f9aa6; --tier-hi: #dfe6ec; }
[data-tier="gold"] { --tier: #c9971c; --tier-hi: #ffd860; }
.trophy-badge { --badge-size: 40px; display: grid; place-items: center; flex: none; width: var(--badge-size); height: var(--badge-size); border-radius: 50%; color: #2b1d08;
  background: radial-gradient(circle at 32% 28%, var(--tier-hi), var(--tier) 70%); box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--tier) 70%, #000 10%), 0 1px 2px rgb(0 0 0 / .2); }
.trophy-badge .ui-icon { width: 55%; height: 55%; stroke-width: 2.2; }
.trophy-badge { position: relative; }
.trophy-badge-pip { position: absolute; right: -6%; bottom: -6%; width: 40%; height: 40%; border-radius: 28%; box-shadow: 0 0 0 1.5px #0b1220cc, 0 1px 2px #0006; }
.trophy-badge.locked .trophy-badge-pip { filter: grayscale(1); opacity: .7; }
.trophy-badge.locked { color: var(--muted); background: var(--elevated); box-shadow: inset 0 0 0 1px var(--line); opacity: .75; }
.trophy[data-tier] { --set: var(--tier); }
.trophy-meta { font-size: var(--text-xs); }
.trophy-filters { display: grid; gap: var(--s2); }
.trophy-filters .chip-row { margin: 0; }
.trophy-case { display: grid; gap: var(--s3); }
.trophy-case > p, .trophy-case .group-title { margin: 0; }
.trophy-case .chip-row { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
.trophy-case .chip-row::-webkit-scrollbar { display: none; }
.trophy-case .chip-row .chip { flex: none; }
.trophy-search { position: relative; display: flex; align-items: center; }
.trophy-search svg { position: absolute; left: var(--s3); width: 1.1rem; height: 1.1rem; color: var(--muted); pointer-events: none; }
.trophy-search input { width: 100%; padding-left: calc(var(--s3) * 2 + 1.1rem); }
.trophy-more { justify-self: start; margin-top: calc(-1 * var(--s2)); }
a.keepsake-chip { color: inherit; text-decoration: none; }
a.keepsake-chip:hover { border-color: var(--set); }
.keepsake-chip .trophy-badge { margin-left: calc(-1 * var(--s2)); }
.trophy-buddy { display: inline-flex; align-items: flex-end; gap: var(--s1); }
.trophy-pedestal { display: inline-grid; justify-items: center; align-self: flex-end; flex: none; line-height: 0; }
.trophy-pedestal-stand { display: block; width: 70%; height: 6px; margin-top: 2px; border-radius: 3px 3px 1px 1px; background: linear-gradient(var(--tier-hi), var(--tier)); }
.profile-who .trophy-pedestal { margin-left: calc(-1 * var(--s2)); }

/* The trophy pop-out: the pet peeks in, ducks, leaps on with a squash, holds its trophy up in a burst of
   confetti, then waves off. Sized by the screen's short side so it's a buddy on phones and a star on desktops. */
.trophy-callout { --pet-size: clamp(84px, 12vmin + 40px, 152px); --enter: 900ms; --land: cubic-bezier(.3, 1.4, .5, 1);
  position: fixed; z-index: 305; left: 0; bottom: calc(var(--s4) + env(safe-area-inset-bottom)); display: flex; align-items: flex-end;
  max-width: calc(100vw - var(--s2)); pointer-events: none; }
.trophy-callout > * { pointer-events: auto; }
.trophy-callout-stage { position: relative; z-index: 1; flex: none; width: var(--pet-size); padding-top: calc(var(--pet-size) * .44); margin-left: calc(var(--pet-size) * -.06);
  transform-origin: 50% 100%; animation: trophy-leap var(--enter) both, trophy-sway 3.2s ease-in-out calc(var(--enter) + 1.6s) infinite; }
.trophy-callout-pet { position: relative; z-index: 1; display: block; line-height: 0; filter: drop-shadow(0 6px 10px rgb(0 0 0 / .22)); }
.trophy-callout-pet .pet-avatar { width: var(--pet-size); height: var(--pet-size); }
.trophy-callout .pet-avatar.mood-cheer.animated .pet-rig { animation-iteration-count: 3; animation-delay: calc(var(--enter) - 80ms); }
.trophy-callout-prize { position: absolute; z-index: 0; left: 50%; top: 0; display: grid; place-items: center; width: calc(var(--pet-size) * .62); aspect-ratio: 1; translate: -50% 0; pointer-events: none; }
.trophy-callout-medal { position: relative; line-height: 0; animation: trophy-raise 700ms var(--land) calc(var(--enter) - 120ms) both, trophy-float 2.4s ease-in-out calc(var(--enter) + 600ms) infinite; }
.trophy-callout-medal .trophy-badge { --badge-size: calc(var(--pet-size) * .36) !important; box-shadow: 0 0 0 3px color-mix(in srgb, var(--tier-hi) 55%, transparent), 0 6px 16px color-mix(in srgb, var(--tier) 55%, transparent); }
.trophy-callout-rays { position: absolute; inset: -20%; border-radius: 50%; opacity: 0;
  background: repeating-conic-gradient(from 0deg, color-mix(in srgb, var(--tier-hi) 70%, transparent) 0 10deg, transparent 10deg 30deg);
  mask: radial-gradient(closest-side, #000 30%, transparent 100%); -webkit-mask: radial-gradient(closest-side, #000 30%, transparent 100%);
  animation: trophy-rays-in 500ms ease-out var(--enter) forwards, trophy-spin 9s linear infinite; }
.trophy-callout-confetti { position: absolute; z-index: 2; left: 50%; top: calc(var(--pet-size) * .3); width: 0; height: 0; pointer-events: none; }
.trophy-callout-confetti i { --bit: calc(var(--pet-size) * .065); position: absolute; left: calc(var(--bit) / -2); top: calc(var(--bit) / -2); width: var(--bit); height: var(--bit); background: var(--paint); opacity: 0;
  animation: trophy-confetti 1300ms cubic-bezier(.15, .7, .3, 1) calc(var(--enter) - 60ms + var(--delay)) forwards; }
.trophy-callout-confetti .bit-strip { width: calc(var(--bit) * .6); height: calc(var(--bit) * 1.4); border-radius: 1px; }
.trophy-callout-confetti .bit-dot { border-radius: 50%; }
.trophy-callout-confetti .bit-star { width: calc(var(--bit) * 1.4); height: calc(var(--bit) * 1.4); clip-path: polygon(50% 0, 62% 38%, 100% 50%, 62% 62%, 50% 100%, 38% 62%, 0 50%, 38% 38%); }
.trophy-callout-bubble { position: relative; display: grid; gap: var(--s1); width: min(22rem, calc(100vw - var(--pet-size) - var(--s6))); padding: var(--s3) var(--s4) var(--s4);
  margin: 0 0 calc(var(--pet-size) * .32) var(--s3); overflow: visible; border: 2px solid var(--tier); border-radius: var(--radius-lg);
  background: linear-gradient(160deg, color-mix(in srgb, var(--tier-hi) 16%, var(--surface)), var(--surface) 55%); box-shadow: var(--shadow), 0 10px 30px color-mix(in srgb, var(--tier) 25%, transparent);
  transform-origin: 0 100%; animation: trophy-bubble 420ms var(--land) calc(var(--enter) + 40ms) both; }
.trophy-callout-bubble::before { content: ""; position: absolute; left: -9px; bottom: var(--s4); width: 14px; height: 14px; background: var(--surface); border-left: 2px solid var(--tier); border-bottom: 2px solid var(--tier); transform: rotate(45deg); }
.trophy-callout-bubble > :not(.trophy-callout-timer) { animation: trophy-line-in 320ms var(--ease-enter) both; }
.trophy-callout-bubble > :nth-child(1) { animation-delay: calc(var(--enter) + 120ms); }
.trophy-callout-bubble > :nth-child(2) { animation-delay: calc(var(--enter) + 180ms); }
.trophy-callout-bubble > :nth-child(3) { animation-delay: calc(var(--enter) + 240ms); }
.trophy-callout-bubble > :nth-child(n+4) { animation-delay: calc(var(--enter) + 300ms); }
.trophy-callout-eyebrow { display: flex; align-items: center; gap: var(--s2); margin: 0; font-size: var(--text-xs); font-weight: var(--weight-label); text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.trophy-callout-title { position: relative; width: fit-content; font-size: clamp(1.05rem, .95rem + .6vw, 1.4rem); line-height: 1.2; }
.trophy-callout-title::after { content: ""; position: absolute; inset: -2px -6px; border-radius: var(--radius-sm); pointer-events: none; opacity: 0;
  background: linear-gradient(105deg, transparent 35%, color-mix(in srgb, var(--tier-hi) 70%, transparent) 50%, transparent 65%) no-repeat; background-size: 250% 100%;
  animation: trophy-sheen 900ms var(--ease-move) calc(var(--enter) + 420ms); }
.trophy-callout-line { margin: 0; line-height: 1.4; }
.trophy-callout-name { font-weight: var(--weight-label); }
.trophy-callout .caption { margin: 0; }
.trophy-callout-actions { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); margin-top: var(--s1); }
.trophy-callout-timer { position: absolute; left: var(--s4); right: var(--s4); bottom: 5px; height: 3px; border-radius: 2px; background: var(--tier); opacity: .55; transform-origin: 0 50%;
  animation: trophy-timer var(--life, 9s) linear forwards; }
.trophy-callout.held .trophy-callout-timer { animation-play-state: paused; opacity: .25; }
.trophy-callout.leaving .trophy-callout-stage { animation: trophy-dive 340ms var(--ease-move) both; }
.trophy-callout.leaving .trophy-callout-bubble { animation: trophy-pop-out 220ms cubic-bezier(.4, 0, 1, 1) both; }
@keyframes trophy-leap {
  0% { transform: translateX(-105%) rotate(0); animation-timing-function: cubic-bezier(.2, .8, .3, 1); }
  24% { transform: translateX(-52%) rotate(12deg); animation-timing-function: ease-in-out; }
  34% { transform: translateX(-62%) rotate(9deg) scale(1.04, .94); animation-timing-function: cubic-bezier(.2, .7, .4, 1); }
  66% { transform: translateX(6%) translateY(-22%) rotate(-8deg) scale(.96, 1.06); animation-timing-function: cubic-bezier(.5, 0, .9, .5); }
  80% { transform: translateX(0) translateY(0) rotate(0) scale(1.14, .84); animation-timing-function: cubic-bezier(.2, .8, .3, 1); }
  90% { transform: scale(.95, 1.06); }
  100% { transform: none; } }
@keyframes trophy-sway { 0%, 100% { transform: none; } 50% { transform: translateY(-3%) rotate(-2deg); } }
@keyframes trophy-raise { 0% { opacity: 0; transform: translateY(70%) scale(.4) rotateY(0); } 40% { opacity: 1; } 60% { transform: translateY(-12%) scale(1.15) rotateY(540deg); } 100% { opacity: 1; transform: none; } }
@keyframes trophy-float { 0%, 100% { transform: none; } 50% { transform: translateY(-8%) rotate(4deg); } }
@keyframes trophy-rays-in { to { opacity: .9; } }
@keyframes trophy-spin { to { rotate: 360deg; } }
@keyframes trophy-confetti {
  0% { opacity: 1; transform: translate(0, 0) scale(.3) rotate(0); }
  35% { opacity: 1; transform: translate(calc(var(--x) * var(--pet-size) * 1.3), calc(var(--y) * var(--pet-size) * .9)) scale(1) rotate(calc(var(--spin) * .5)); }
  100% { opacity: 0; transform: translate(calc(var(--x) * var(--pet-size) * 1.8), calc(var(--y) * var(--pet-size) * .4 + var(--pet-size) * .9)) scale(.8) rotate(var(--spin)); } }
@keyframes trophy-bubble { 0% { opacity: 0; transform: translateX(-12px) scale(.6) rotate(-4deg); } 60% { opacity: 1; } 100% { opacity: 1; transform: none; } }
@keyframes trophy-line-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes trophy-sheen { 0% { opacity: 1; background-position: 120% 0; } 100% { opacity: 1; background-position: -20% 0; } }
@keyframes trophy-timer { from { transform: scaleX(1); } to { transform: scaleX(0); } }
@keyframes trophy-dive { 0% { transform: none; } 30% { transform: translateY(-14%) rotate(6deg) scale(1.03); } 100% { transform: translateX(-125%) translateY(8%) rotate(-18deg); } }
@keyframes trophy-pop-out { to { opacity: 0; transform: translateX(-16px) scale(.85); } }
@media (max-width: 767px) { .trophy-callout { bottom: calc(5.5rem + env(safe-area-inset-bottom)); } .trophy-callout-bubble { padding: var(--s2) var(--s3) var(--s3); } }
@media (prefers-reduced-motion: reduce) {
  .trophy-callout-stage, .trophy-callout-medal, .trophy-callout-bubble, .trophy-callout-bubble > *, .trophy-callout .pet-avatar .pet-rig { animation: trophy-fade 200ms ease-out both !important; }
  .trophy-callout-rays { opacity: .6; }
  .trophy-callout-confetti, .trophy-callout-title::after { display: none; }
  .trophy-callout.leaving .trophy-callout-stage, .trophy-callout.leaving .trophy-callout-bubble { animation: fade-out 150ms ease-in both !important; } }
@keyframes trophy-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes fade-out { to { opacity: 0; } }

/* Admin playground: one slim bar (title + experiment tabs) above the experiment, which gets the full width. */
.playground { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s4); min-width: 0; }
.pg-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3) var(--s6); }
.pg-title { display: flex; align-items: center; gap: var(--s2); margin: 0; font-size: var(--text-xl); letter-spacing: var(--tracking-title); }
.pg-badge { padding: 2px var(--s2); border-radius: var(--pill); background: color-mix(in srgb, var(--sea) 16%, transparent); color: var(--sea);
  font-size: var(--text-2xs); font-weight: var(--weight-label); letter-spacing: var(--tracking-label); text-transform: uppercase; cursor: help; }
.pg-tabs { display: flex; gap: var(--s1); min-width: 0; padding: var(--s1); border: 1px solid var(--line); border-radius: var(--pill); background: var(--surface);
  overflow-x: auto; scrollbar-width: none; }
.pg-tabs::-webkit-scrollbar { display: none; }
.pg-tab { display: inline-flex; flex: none; align-items: center; gap: var(--s2); min-height: 2.25rem; padding: 0 var(--s3); border-radius: var(--pill);
  color: var(--muted); font-size: var(--text-sm); font-weight: var(--weight-label); text-decoration: none; white-space: nowrap;
  transition: background-color var(--fast) var(--ease), color var(--fast) var(--ease); }
.pg-tab .ui-icon { width: 1rem; height: 1rem; }
.pg-tab:hover { color: var(--ink); background: color-mix(in srgb, var(--ink) 6%, transparent); }
.pg-tab[aria-current="page"] { color: var(--on-accent); background: var(--sea); }
.playground-stage { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s4); min-width: 0; }
.playground-stage h2 { margin: 0; }
.playground-form { display: grid; grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr)); gap: var(--s3) var(--s4); }
.playground-form label { display: grid; gap: var(--s1); font-weight: var(--weight-label); }
.playground-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.playground-actions .checkbox-setting { margin-left: var(--s2); }
.swarm-controls select { width: auto; }
.swarm-stage { width: min(100%, 26rem, calc((100dvh - 11.5rem) * 9 / 16)); min-width: 15rem; margin-inline: auto; aspect-ratio: 9 / 16; }
.swarm-stage canvas { display: block; width: 100%; height: 100%; border-radius: var(--radius); background: #050914; touch-action: none; user-select: none; -webkit-user-select: none; }
.pet-studio-stage { display: grid; place-items: center; min-height: 18rem; padding: var(--s4); border: 1px dashed var(--line); border-radius: var(--radius-lg); background: var(--background); }
.pet-studio-roster { display: grid; grid-template-columns: repeat(auto-fill, minmax(6.5rem, 1fr)); gap: var(--s3); margin: 0; padding: 0; list-style: none; }
.pet-studio-roster li { display: grid; justify-items: center; gap: var(--s1); padding: var(--s2); border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--background); }

/* Playground motion lab: a permission gate, then a canvas (beat ring over the live signal) and its numbers. */
.motion-gate { display: grid; justify-items: start; gap: var(--s3); padding: var(--s4); border: 1px dashed var(--line); border-radius: var(--radius-lg); background: var(--background); }
.motion-facts, .motion-tally { display: grid; grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr)); gap: var(--s2) var(--s4); margin: 0; }
.motion-facts dt, .motion-tally dt { color: var(--muted); font-size: var(--text-sm); }
.motion-facts dd, .motion-tally dd { margin: 0; font-weight: var(--weight-label); font-variant-numeric: tabular-nums; }
.motion-tally dd { font-size: var(--text-xl); }
.motion-good { color: var(--sea); }
.motion-bad { color: var(--danger); }
.motion-stage { display: grid; gap: var(--s3); }
.motion-canvas { display: block; width: 100%; height: min(26rem, 52dvh); border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--background); touch-action: none; }
.motion-result { display: grid; gap: var(--s2); padding: var(--s4); border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--surface); }
.motion-result h3 { margin: 0; }
.motion-table-wrap { max-width: 100%; overflow-x: auto; border: 1px solid var(--line); border-radius: var(--s2); }
.motion-table { width: 100%; min-width: 28rem; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.motion-table th, .motion-table td { padding: var(--s2); border-bottom: 1px solid var(--line); text-align: right; white-space: nowrap; }
.motion-table tbody tr:last-child td { border-bottom: 0; }
.motion-table th:first-child, .motion-table td:first-child { text-align: left; }
.motion-table th { color: var(--muted); font-size: var(--text-sm); font-weight: var(--weight-label); }

/* Playground live analytics: a toolbar, a strip of headline numbers with trend lines, then cards; tables fold away. */
.live { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s3); min-width: 0; }
.live-toolbar { display: flex; align-items: center; gap: var(--s2); }
.live-seg { display: inline-flex; padding: 3px; border: 1px solid var(--line); border-radius: var(--pill); background: var(--surface); }
.live-seg button { min-height: 2rem; padding: 0 var(--s3); border: 0; border-radius: var(--pill); background: none; color: var(--muted); box-shadow: none;
  font: inherit; font-size: var(--text-sm); font-weight: var(--weight-label); font-variant-numeric: tabular-nums; cursor: pointer;
  transition: background-color var(--fast) var(--ease), color var(--fast) var(--ease); }
.live-seg button:hover { color: var(--ink); }
.live-seg button[aria-checked="true"] { background: var(--elevated); color: var(--ink); }
/* The status is the refresh button: when it last updated, and a tap to update it now. */
.live-updated { display: inline-flex; align-items: center; gap: var(--s2); min-height: 2.25rem; margin-left: auto; padding: 0 var(--s2) 0 var(--s3);
  border: 1px solid var(--line); border-radius: var(--pill); background: var(--surface); color: var(--muted); box-shadow: none;
  font: inherit; font-size: var(--text-sm); font-variant-numeric: tabular-nums; white-space: nowrap; cursor: pointer;
  transition: color var(--fast) var(--ease), border-color var(--fast) var(--ease); }
.live-updated:hover:not(:disabled) { border-color: color-mix(in srgb, var(--sea) 45%, var(--line)); color: var(--ink); }
.live-updated:disabled { cursor: default; }
.live-updated .ui-icon { flex: none; width: 1rem; height: 1rem; }
.live-updated.spinning .ui-icon { animation: live-spin .8s linear infinite; }
@keyframes live-spin { to { rotate: 360deg; } }
.live-dot { position: relative; display: inline-block; flex: none; width: .5rem; height: .5rem; border-radius: 50%; background: var(--green); }
.live-dot::after { content: ""; position: absolute; inset: 0; border-radius: inherit; background: var(--green); animation: live-ping 2s var(--ease) infinite; }
@keyframes live-ping { from { transform: scale(1); opacity: .7; } 70%, to { transform: scale(2.6); opacity: 0; } }
.live-warn { margin: 0; padding: var(--s2) var(--s3); border-radius: var(--radius-sm); background: color-mix(in srgb, var(--yellow) 12%, var(--surface)); }

/* Two groups of three, one per source, each headed by what it counts and over which day. */
.live-kpis { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }
.live-kpi-group { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); grid-auto-rows: 1fr; grid-template-rows: auto; gap: var(--s2); min-width: 0; }
.live-kpi-head { grid-column: 1 / -1; display: flex; align-items: center; gap: var(--s2); min-width: 0; margin: 0;
  color: var(--muted); font-size: var(--text-xs); font-weight: var(--weight-label); letter-spacing: 0; }
.live-tile { position: relative; display: grid; align-content: start; gap: 2px; min-width: 0; padding: var(--s3) var(--s3) 0; overflow: hidden;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface); }
.live-tile-label { overflow: hidden; color: var(--muted); font-size: var(--text-xs); font-weight: var(--weight-label); text-overflow: ellipsis; white-space: nowrap; }
.live-tile strong { font-size: var(--text-2xl); line-height: var(--leading-title); letter-spacing: var(--tracking-title); font-variant-numeric: tabular-nums; }
.live-tile.hero { border-color: color-mix(in srgb, var(--sea) 55%, var(--line)); background: color-mix(in srgb, var(--sea) 9%, var(--surface)); }
.live-tile.hero strong { color: var(--sea); }
.live-tile-note { overflow: hidden; color: var(--muted); font-size: var(--text-xs); text-overflow: ellipsis; white-space: nowrap; }
.live-tile .spark { display: block; width: calc(100% + 2 * var(--s3)); height: 1.75rem; margin: var(--s2) calc(-1 * var(--s3)) 0; }
.live-tile:not(:has(.spark)) { padding-bottom: var(--s3); }
.spark-line { fill: none; stroke: var(--sea); stroke-width: 1.5; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.spark-fill { fill: color-mix(in srgb, var(--sea) 16%, transparent); }
.live-src { flex: none; padding: 1px 6px; border-radius: var(--pill); background: color-mix(in srgb, var(--muted) 16%, transparent); color: var(--muted);
  font-size: var(--text-2xs); font-weight: var(--weight-label); letter-spacing: .04em; text-transform: uppercase; vertical-align: middle; cursor: help; }
.live-src.live { background: color-mix(in srgb, var(--green) 16%, transparent); color: var(--green); }

/* Two columns, so cards pair up whatever the mix: a card is half a row, or `full` for a whole one.
   The roster and the day charts are full rows; everything else pairs off in source order. */
.live-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); align-items: stretch; }
.live-grid > .live-card { align-content: start; }
.live-grid > .live-card.wide, .live-grid > .live-card.full { grid-column: 1 / -1; }
.live-card { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s3); min-width: 0; padding: var(--s4); border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); }
.live-card h3 { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); margin: 0; font-size: var(--text-md); letter-spacing: 0; }
.live-card h4 { margin: var(--s2) 0 0; color: var(--muted); font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; }
.live-empty { margin: 0; font-size: var(--text-sm); }
.live-footnote { margin: 0; color: var(--muted); font-size: var(--text-xs); line-height: 1.45; }

.live-chart { display: grid; gap: var(--s1); margin: 0; }
.live-bars { display: flex; align-items: flex-end; gap: 3px; height: 8.5rem; padding-top: var(--s4); border-bottom: 1px solid var(--line);
  background: repeating-linear-gradient(to top, transparent 0 calc(25% - 1px), color-mix(in srgb, var(--line) 45%, transparent) calc(25% - 1px) 25%); }
.live-bars.short { height: 4rem; padding-top: 0; gap: 2px; }
.live-bar { position: relative; flex: 1; min-width: 0; height: max(var(--h), 2px); border-radius: 3px 3px 0 0; background: var(--sea); transition: opacity var(--fast) var(--ease); }
.live-bar:hover { opacity: .75; }
.live-bar.estimated { opacity: .6; }
.live-bar.partial { background: repeating-linear-gradient(135deg, var(--sea) 0 4px, color-mix(in srgb, var(--sea) 55%, transparent) 4px 8px); }
.live-bar b { position: absolute; bottom: 100%; left: 50%; padding-bottom: 2px; transform: translateX(-50%); color: var(--muted);
  font-size: var(--text-2xs); font-weight: var(--weight-label); font-variant-numeric: tabular-nums; }
.live-axis { display: flex; justify-content: space-between; color: var(--muted); font-size: var(--text-2xs); font-variant-numeric: tabular-nums; }

/* When they play: hour bars over a weekday × hour heat grid, sharing one 24-column rhythm. */
.live-hours-peak { margin: 0; font-size: var(--text-sm); line-height: 1.45; }
.live-bar.peak { background: var(--green); }
.live-heat { display: grid; gap: 2px; }
.live-heat-row { display: grid; grid-template-columns: 2rem repeat(24, minmax(0, 1fr)); gap: 2px; align-items: center; }
.live-heat-day { color: var(--muted); font-size: var(--text-2xs); font-weight: var(--weight-label); }
.live-heat-cell { aspect-ratio: 1; max-height: 1.25rem; border-radius: 2px;
  background: color-mix(in srgb, var(--sea) var(--a), color-mix(in srgb, var(--line) 45%, transparent)); }
.live-bars.hours { gap: 2px; }
.live-hours-axis, .live-bars.hours { margin-left: calc(2rem + 2px); }

/* Rows with a bar behind them sized by --w, for "where they are" and plays by game. */
.live-meter-list { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s1); margin: 0; padding: 0; list-style: none; }
.live-meter-list li { position: relative; display: flex; align-items: center; gap: var(--s2); min-height: 2rem; padding: var(--s1) var(--s2); border-radius: var(--s2); isolation: isolate; font-size: var(--text-sm); line-height: 1.35; }
.live-meter-list li::before { content: ""; position: absolute; inset: 0 auto 0 0; z-index: -1; width: var(--w); max-width: 100%; border-radius: inherit; background: color-mix(in srgb, var(--sea) 18%, transparent); }
/* Labels wrap rather than clip: the notes carry the definitions, and the count must stay on the card. */
.live-meter-list span { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.live-meter-list small { margin-left: var(--s1); color: var(--muted); font-size: var(--text-xs); }
.live-meter-list strong { flex: none; font-variant-numeric: tabular-nums; }

.live-retention { display: grid; gap: var(--s3); margin: 0; padding: 0; list-style: none; }
.live-retention li { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; gap: 2px var(--s2); }
.live-retention-label { font-size: var(--text-sm); font-weight: var(--weight-label); }
.live-retention strong { font-size: var(--text-xl); line-height: 1; font-variant-numeric: tabular-nums; }
.live-retention-track { grid-column: 1 / -1; height: .375rem; border-radius: var(--pill); background: color-mix(in srgb, var(--line) 70%, transparent); overflow: hidden; }
.live-retention-track span { display: block; width: var(--p); height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--sea), var(--green)); }
.live-retention .live-tile-note { grid-column: 1 / -1; }

.live-details { display: block; padding: 0; }
.live-details > summary { display: flex; align-items: center; gap: var(--s2); padding: var(--s3) var(--s4); list-style: none; cursor: pointer; }
.live-details > summary::-webkit-details-marker { display: none; }
.live-details > summary .caption { margin-left: auto; }
.live-details > summary .ui-icon { width: 1rem; height: 1rem; color: var(--muted); transition: rotate var(--normal) var(--ease); }
.live-details[open] > summary .ui-icon { rotate: 180deg; }
.live-details[open] { padding-bottom: var(--s4); }
.live-details > :not(summary) { margin-inline: var(--s4); }
.live-details > h4 { margin-block: var(--s3) var(--s2); }
.live-details > .live-footnote { margin-top: var(--s3); }
.live-table-wrap { max-width: 100%; overflow-x: auto; border: 1px solid var(--line); border-radius: var(--s2); }
.live-table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
.live-table th, .live-table td { padding: var(--s1) var(--s3); border-bottom: 1px solid var(--line); text-align: right; white-space: nowrap; }
.live-table tbody tr:last-child td { border-bottom: 0; }
.live-table tbody tr:hover td { background: color-mix(in srgb, var(--sea) 7%, var(--surface)); }
.live-table th:first-child, .live-table td:first-child { position: sticky; left: 0; text-align: left; background: var(--surface); }
.live-table th { color: var(--muted); font-size: var(--text-xs); font-weight: var(--weight-label); }

/* What needs a look: sentences, worst first, colour-coded by tone rather than by severity. */
.live-signals ul { display: grid; gap: var(--s1); margin: 0; padding: 0; list-style: none; }
.live-signals li { display: flex; align-items: baseline; gap: var(--s2); padding: var(--s2) var(--s3); border-radius: var(--s2); background: color-mix(in srgb, var(--muted) 8%, transparent); font-size: var(--text-sm); line-height: 1.45; }
.live-signal-dot { flex: none; width: .5rem; height: .5rem; border-radius: var(--pill); translate: 0 -1px; background: var(--muted); }
.live-signals .tone-bad { background: color-mix(in srgb, var(--danger) 12%, transparent); }
.live-signals .tone-bad .live-signal-dot { background: var(--danger); }
.live-signals .tone-watch { background: color-mix(in srgb, var(--warning) 12%, transparent); }
.live-signals .tone-watch .live-signal-dot { background: var(--warning); }
.live-signals .tone-good { background: color-mix(in srgb, var(--green) 12%, transparent); }
.live-signals .tone-good .live-signal-dot { background: var(--green); }

/* The roster: one row per account, with the state as a pill so the table scans without reading dates. */
.live-roster-name { display: inline-flex; align-items: center; gap: var(--s2); padding: 0; border: 0; background: none; color: inherit; font: inherit; cursor: pointer; text-align: left; }
.live-row-open { cursor: pointer; }
.live-row-open:hover td, .live-row-open:focus-within td { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.live-row-open .live-roster-name strong { text-decoration: underline; text-decoration-color: color-mix(in srgb, currentColor 35%, transparent); text-underline-offset: 3px; }
.live-signal-link { padding: 0; border: 0; background: none; color: inherit; font: inherit; text-align: left; cursor: pointer; text-decoration: underline; text-decoration-color: color-mix(in srgb, currentColor 35%, transparent); text-underline-offset: 3px; }
.live-back { display: inline-flex; align-items: center; gap: var(--s1); min-height: 44px; padding: 0 var(--s3) 0 var(--s2); border: 1px solid var(--line); border-radius: var(--pill); background: var(--surface, transparent); color: inherit; font: inherit; font-weight: var(--weight-label); cursor: pointer; }
.live-player-head h2 { display: flex; align-items: center; gap: var(--s2); margin: var(--s3) 0 var(--s1); overflow-wrap: anywhere; }
.live-player-head p { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); margin: 0 0 var(--s3); color: var(--muted); font-size: var(--text-sm); }
.live-player-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: var(--s2); margin-bottom: var(--s2); }
.live-player-tiles div { display: flex; flex-direction: column; padding: var(--s3); border: 1px solid var(--line); border-radius: var(--s2); }
.live-player-tiles strong { font-size: var(--text-xl, 1.5rem); font-variant-numeric: tabular-nums; }
.live-player-tiles span { color: var(--muted); font-size: var(--text-xs); }
.live-timeline { display: grid; gap: var(--s3); margin: 0; padding: 0; list-style: none; }
.live-timeline time { display: block; color: var(--muted); font-size: var(--text-xs); font-weight: var(--weight-label); }
.live-timeline ul { margin: var(--s1) 0 0; padding-left: var(--s4, 1rem); font-size: var(--text-sm); line-height: 1.5; }
.live-facts { display: grid; grid-template-columns: minmax(90px, max-content) 1fr; gap: var(--s1) var(--s3); margin: 0; font-size: var(--text-sm); }
.live-facts dt { color: var(--muted); }
.live-facts dd { margin: 0; overflow-wrap: anywhere; }
.live-roster .live-row-team td, .live-table .live-row-team td { color: var(--muted); }
.live-arrivals :is(th, td) { padding-inline: var(--s1); }
.live-arrivals small { display: block; color: var(--muted); font-size: .78em; }
.live-tag { padding: 0 5px; border-radius: var(--pill); background: color-mix(in srgb, var(--muted) 16%, transparent); color: var(--muted); font-size: var(--text-xs); font-weight: var(--weight-label); }
.live-pill { display: inline-block; padding: 1px 8px; border-radius: var(--pill); background: color-mix(in srgb, var(--muted) 16%, transparent); color: var(--muted); font-size: var(--text-xs); font-weight: var(--weight-label); white-space: nowrap; }
.live-pill.new { background: color-mix(in srgb, var(--sea) 20%, transparent); color: var(--sea); }
.live-pill.active { background: color-mix(in srgb, var(--green) 18%, transparent); color: var(--green); }
.live-pill.cooling { background: color-mix(in srgb, var(--warning) 18%, transparent); color: var(--warning); }
.live-pill.one-day, .live-pill.gone { background: color-mix(in srgb, var(--danger) 15%, transparent); color: var(--danger); }
.live-roster td:nth-child(2) { text-align: left; }

/* The funnel reuses the meter list, but each rung keeps its own share of the first step. */
.live-funnel li { min-height: 2.25rem; }
.live-funnel li::before { background: color-mix(in srgb, var(--green) 16%, transparent); }

/* Guests: four tiles across, then their panels two by two. */
.live-guests-lede { margin: 0; color: var(--muted); font-size: var(--text-sm); }
.live-guest-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); grid-auto-rows: 1fr; gap: var(--s2); }
.live-guest-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s4) var(--s6); align-items: start; }
.live-guest-grid > section { display: grid; gap: var(--s2); min-width: 0; }
.live-guest-grid > section > h4:first-child { margin-top: 0; }
/* Flex like the card's h3: the Live badge also carries .live, the page's grid class, and would stretch. */
.live-guests h4 { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.live-guest-tiles .live-tile-note { white-space: normal; }

@media (max-width: 1023px) {
  .live-kpis { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 767px) {
  .playground { gap: var(--s3); padding-top: var(--s2); }
  .live-updated-word { display: none; }
  .pg-bar { gap: var(--s2); }
  .pg-tabs { flex: 1 1 100%; margin-inline: calc(-1 * var(--s1)); }
  .live-kpi-group { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .live-kpi-group > .live-tile:nth-of-type(1) { grid-column: 1 / -1; }
  .live-grid { grid-template-columns: minmax(0, 1fr); }
  .live-grid > .live-card.wide, .live-grid > .live-card.full { grid-column: auto; }
  .live-guest-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .live-guest-grid { grid-template-columns: minmax(0, 1fr); }
  .live-card { padding: var(--s3); }
  .live-details > summary { padding: var(--s3); }
  .live-details > summary .caption { display: none; }
  .live-details > :not(summary) { margin-inline: var(--s3); }
}
@media (prefers-reduced-motion: reduce) {
  .live-dot::after, .live-updated.spinning .ui-icon { animation: none; }
}

/* Purchases are applied with a full-screen hanko slide stamp (StampPress, StampScene). */
body:has(.stamp-press) { overflow: hidden; }
.stamp-scene.pet-habitat { position: absolute; inset: 0; min-height: 0; border-radius: 0; box-shadow: none; }
.stamp-figure { position: absolute; left: 50%; top: 56%; z-index: 6; width: min(34%, 15rem); translate: -50% -50%; }
.stamp-figure > svg { display: block; width: 100%; height: auto; }
.stamp-scene-icon { position: relative; display: block; width: 100%; aspect-ratio: 1; min-height: 0; border-radius: 50%; box-shadow: inset 0 0 0 2px #0002; }
.stamp-skip { position: absolute; top: max(var(--s4), env(safe-area-inset-top)); right: var(--s4); padding: var(--s2) var(--s4); border: 1px solid #fff4; border-radius: var(--pill); background: #fff1; color: #fff; font-weight: var(--weight-label); }
.stamp-skip:hover { background: #fff2; }

.stamp-press { --cy: 56%; --face: 30cqw; --drop: cubic-bezier(.55, 0, .9, .45); --spring: cubic-bezier(.3, 1.5, .5, 1);
  position: fixed; inset: 0; z-index: 400; display: grid; place-content: center; justify-items: center; gap: var(--s4); padding: var(--s4);
  background: radial-gradient(ellipse at 50% 45%, rgb(20 16 40 / .72), rgb(8 6 20 / .9)); backdrop-filter: blur(6px);
  touch-action: none; user-select: none; -webkit-user-select: none; outline: none; cursor: grab;
  animation: fade-in 260ms var(--ease-enter) both; }
.stamp-press.phase-press { cursor: grabbing; }
.stamp-sheet { position: relative; container-type: inline-size; width: min(92vw, 820px, 150vh); aspect-ratio: 16 / 10;
  animation: stamp-sheet-in 520ms var(--ease-enter) both; }
.stamp-paper { position: absolute; inset: 0; overflow: hidden; border: 1.4cqw solid #fff8ec; border-radius: 2.4cqw; background: #fff8ec;
  box-shadow: 0 2cqw 6cqw rgb(0 0 0 / .45), inset 0 0 0 1px #0001; }
.stamp-layer { position: absolute; inset: 0; }
.stamp-after { clip-path: circle(0 at 50% var(--cy)); }
.stamp-color { position: absolute; inset: 0; opacity: 0; }
.stamp-after::before { content: ""; position: absolute; inset: 0; background: #fff8ec; opacity: calc(var(--wash, 0) * .62); transition: opacity 500ms var(--ease); }
.phase-press .stamp-after, .phase-lift .stamp-after { --wash: 1; }
.stamp-ink { position: absolute; inset: 0; filter: url(#stamp-ink-filter); opacity: var(--depth); transition: opacity 90ms linear; }
.stamp-ring { position: absolute; left: 50%; top: var(--cy); width: calc(var(--face) + 1.2cqw); aspect-ratio: 1; translate: -50% -50%; border-radius: 50%;
  border: .9cqw solid #d4402f; opacity: 0; filter: url(#stamp-ink-filter); pointer-events: none; }
.stamp-defs { position: absolute; }

/* The stamp: its bottom edge sits on the contact point; everything moves with transform only. */
.stamp { position: absolute; left: 50%; top: var(--cy); width: var(--face); translate: -50% -100%; transform-origin: 50% 100%;
  transform: translateY(-14cqw) rotate(-4deg); filter: drop-shadow(0 1cqw 1.4cqw rgb(0 0 0 / .35)); z-index: 3;
  animation: stamp-drop 560ms var(--spring) both; }
.stamp-body { position: relative; height: calc(var(--face) * .92); border-radius: 4cqw 4cqw 1.6cqw 1.6cqw;
  background: linear-gradient(90deg, color-mix(in srgb, var(--plastic) 70%, #000) 0%, var(--plastic) 18%, color-mix(in srgb, var(--plastic) 55%, #fff) 34%, var(--plastic) 52%, color-mix(in srgb, var(--plastic) 78%, #000) 100%);
  box-shadow: inset 0 -1.2cqw 0 rgb(0 0 0 / .14), inset 0 .6cqw 0 rgb(255 255 255 / .45); }
.stamp-body::after { content: ""; position: absolute; left: 14%; top: 8%; width: 9%; height: 70%; border-radius: 999px; background: linear-gradient(#fff9, #fff0); }
.stamp-label { position: absolute; left: 50%; top: 40%; display: grid; place-items: center; width: 62%; aspect-ratio: 1; translate: -50% -50%; overflow: hidden;
  border-radius: 50%; background: #fffdf6; box-shadow: 0 0 0 .5cqw color-mix(in srgb, var(--plastic) 60%, #000 10%), inset 0 .4cqw .8cqw rgb(0 0 0 / .18); }
.stamp-label > * { width: 82% !important; height: 82% !important; }
.stamp-label .stamp-scene-icon { width: 100% !important; height: 100% !important; }
.stamp-grip { position: absolute; left: 6%; right: 6%; bottom: 7%; height: 8%; border-radius: 999px;
  background: repeating-linear-gradient(90deg, rgb(0 0 0 / .16) 0 .5cqw, transparent .5cqw 1.1cqw); }
.stamp-foot { height: calc(var(--face) * .16); margin: 0 4%; border-radius: 0 0 1cqw 1cqw;
  background: linear-gradient(#3a2a2a, #2a1c1c 60%, #d4402f 60%, #a82d22); }
.stamp-cap { position: absolute; left: -3%; right: -3%; bottom: -1.2cqw; height: calc(var(--face) * .3); border-radius: 1.4cqw 1.4cqw 2.4cqw 2.4cqw;
  background: linear-gradient(90deg, color-mix(in srgb, var(--plastic) 60%, #fff) 0%, color-mix(in srgb, var(--plastic) 35%, #fff) 30%, color-mix(in srgb, var(--plastic) 70%, #fff) 100%);
  box-shadow: inset 0 .5cqw 0 rgb(255 255 255 / .6), inset 0 -.8cqw 0 rgb(0 0 0 / .1); opacity: .96; }
.stamp-cap::before { content: ""; position: absolute; left: 10%; right: 10%; top: 35%; height: 14%; border-radius: 999px;
  background: repeating-linear-gradient(90deg, rgb(0 0 0 / .14) 0 .4cqw, transparent .4cqw 1cqw); }
.stamp-shadow { position: absolute; left: 50%; top: var(--cy); width: var(--face); height: calc(var(--face) * .22); translate: -50% -50%; border-radius: 50%;
  background: radial-gradient(closest-side, rgb(0 0 0 / .4), transparent); scale: .7; opacity: .5; filter: blur(.8cqw); z-index: 2; pointer-events: none;
  transition: scale 95ms var(--drop), opacity 95ms var(--drop); }
.stamp-hint { margin: 0; min-height: 1.6em; color: #fff; font-size: var(--text-lg); font-weight: var(--weight-title); text-align: center; text-shadow: 0 2px 8px #0008; }
.phase-ready .stamp-hint span { animation: dim-pulse 1.4s var(--ease-move) infinite; }
.phase-done .stamp-hint { animation: stamp-done 420ms var(--spring) both; }
.stamp-hint strong { color: #ffb3a8; margin-right: .3em; }

.phase-uncap .stamp-cap, .phase-ready .stamp-cap, .phase-press .stamp-cap, .phase-lift .stamp-cap, .phase-bloom .stamp-cap {
  transform: translateX(118%) rotate(8deg); opacity: 0; transition: transform 260ms var(--ease-move), opacity 200ms var(--ease) 120ms; }
.phase-recap .stamp-cap, .phase-done .stamp-cap { transition: transform 240ms var(--ease-move) 60ms, opacity 120ms var(--ease) 60ms; }
.phase-ready .stamp { animation: stamp-hover 1.6s var(--ease-move) infinite; }
.phase-press .stamp { transform: translateY(0) rotate(0); animation: stamp-squish 1.2s var(--ease-enter) 95ms both; transition: transform 95ms var(--drop); }
.phase-press .stamp-shadow { scale: 1.02; opacity: 1; }
.phase-press .stamp-paper { animation: stamp-thud 220ms var(--ease-move) 95ms; }
.phase-lift .stamp, .phase-bloom .stamp { transform: translateY(-18cqw) rotate(3deg); transition: transform 420ms var(--spring); }
.phase-recap .stamp { transform: translateY(-18cqw) rotate(3deg); }
.phase-done .stamp { transform: translateY(-120cqw) rotate(-14deg); opacity: 0; transition: transform 380ms var(--ease-move), opacity 300ms var(--ease) 80ms; }
.phase-press .stamp-after, .phase-lift .stamp-after { clip-path: circle(calc(var(--face) / 2) at 50% var(--cy)); transition: clip-path 0s 95ms; }
.phase-press .stamp-ring, .phase-lift .stamp-ring { opacity: .85; transition: opacity 0s 95ms; }
.phase-bloom .stamp-after, .phase-recap .stamp-after, .phase-done .stamp-after { clip-path: circle(120cqw at 50% var(--cy)); transition: clip-path 720ms var(--ease-enter) 120ms; }
.phase-bloom .stamp-color, .phase-recap .stamp-color, .phase-done .stamp-color { opacity: 1; transition: opacity 360ms var(--ease); }
.phase-bloom .stamp-ink, .phase-recap .stamp-ink, .phase-done .stamp-ink { opacity: 0; transition: opacity 520ms var(--ease) 200ms; }
.phase-bloom .stamp-ring { opacity: 0; scale: 1.6; transition: opacity 500ms var(--ease), scale 600ms var(--ease-enter); }
.phase-done { cursor: default; }

@media (orientation: portrait) and (max-width: 767px) { .stamp-press { --cy: 58%; --face: 46cqw; } .stamp-sheet { aspect-ratio: 4 / 5; width: min(94vw, 64vh); } .stamp-press .stamp-figure { width: min(60%, 15rem); top: 58%; } }
@keyframes stamp-sheet-in { from { opacity: 0; transform: translateY(3vh) scale(.94); } }
@keyframes stamp-drop { from { transform: translateY(-110vh) rotate(-16deg); } }
@keyframes stamp-hover { 0%, 100% { transform: translateY(-14cqw) rotate(-4deg); } 50% { transform: translateY(-16cqw) rotate(-2deg); } }
@keyframes stamp-squish { 0% { scale: 1.04 .9; } 18% { scale: .98 1.02; } 40%, 100% { scale: 1.02 .96; } }
@keyframes stamp-thud { 0% { transform: translate(0, 0); } 25% { transform: translate(-.4cqw, .6cqw); } 55% { transform: translate(.3cqw, -.2cqw); } 100% { transform: none; } }
@keyframes dim-pulse { 50% { opacity: .55; } }
@keyframes stamp-done { from { opacity: 0; transform: scale(.7); } }
@media (prefers-reduced-motion: reduce) {
  .stamp-press, .stamp-press * { animation: none !important; }
  .stamp-press .stamp, .stamp-press .stamp-cap { transition: opacity 200ms var(--ease) !important; transform: none !important; }
  .stamp-press:not(.phase-arrive):not(.phase-uncap):not(.phase-ready) .stamp { opacity: .25; }
}

/* DailyTrack: the Daily twin of the level track. Today's Daily in every game, ticked when cleared. */
.daily-track { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1) var(--s3); }
.daily-track ol { display: flex; gap: 6px; margin: 0; padding: 0; list-style: none; }
.daily-track li { position: relative; }
.daily-track li > a, .daily-track li > span { display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%;
  background: color-mix(in srgb, var(--track-film, var(--ink)) 11%, transparent); touch-action: manipulation; }
.daily-track img { width: 18px; height: 18px; border-radius: 4px; opacity: .5; filter: grayscale(.7); transition: opacity var(--fast) var(--ease), filter var(--fast) var(--ease); }
.daily-track li.done img, .daily-track li.current img { opacity: 1; filter: none; }
.daily-track li.current > span { box-shadow: 0 0 0 2px var(--track-ring, color-mix(in srgb, var(--accent) 60%, transparent)); }
.daily-track li.done::after { content: "✓"; position: absolute; right: -3px; bottom: -3px; display: grid; place-items: center; width: 13px; height: 13px;
  border-radius: 50%; background: var(--track-glow, var(--accent)); color: #fff; font-size: 9px; font-weight: 700; line-height: 1; }
.daily-track-note { font-size: var(--text-xs); color: var(--muted); font-variant-numeric: tabular-nums; }
.daily-track-streak { margin-right: var(--s1); color: var(--ink); font-weight: var(--weight-label); }

/* Daily prize wheel (/wheel, and the admin playground's free version): equal slices, real odds in PrizeWheel.
   The wheel stands in the pet meadow, so it follows day and night like the pet room; every color
   comes from the theme tokens and the pet stat palette. JS spins the rotor (tidegridGames.spinWheel),
   the flapper sits on top, and the hub itself is the Spin button. */
.wheel-lab { display: grid; grid-template-columns: minmax(0, 30rem) minmax(0, 1fr); gap: var(--s6); align-items: start; }
.wheel-stage { --w-coin: #c98a0b; --w-hint: #1d9e95; display: grid; gap: var(--s3); padding: var(--s4); border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--surface); box-shadow: var(--shadow); }
.wheel-scene.pet-habitat { display: grid; place-items: center; min-height: 0; padding: var(--s6) var(--s4); }
.wheel-scene .meadow svg { height: 100%; }
.prize-wheel { position: relative; z-index: 1; width: 100%; max-width: 24rem; aspect-ratio: 1; }
.prize-wheel > svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; pointer-events: none; }
.prize-wheel-frame { filter: drop-shadow(0 10px 18px rgb(7 12 24 / .22)); }
.prize-wheel-rotor { will-change: transform; }
.prize-wheel-rim { fill: var(--surface); stroke: var(--line); stroke-width: 1.5; }
.prize-wheel-well { fill: var(--line); }
.prize-wheel-collar { fill: var(--surface); stroke: var(--line); stroke-width: 2; }
.prize-wheel-rays { position: absolute; inset: -12%; border-radius: 50%; opacity: 0; background: repeating-conic-gradient(from 0deg, color-mix(in srgb, var(--surface) 60%, transparent) 0 6deg, transparent 6deg 15deg); -webkit-mask: radial-gradient(closest-side, #000 50%, transparent 100%); mask: radial-gradient(closest-side, #000 50%, transparent 100%); animation: wheel-rays 70s linear infinite; transition: opacity 500ms var(--ease), scale 600ms var(--ease); }
.wheel-stage.won .prize-wheel-rays { opacity: 1; scale: 1.06; }
.prize-bulb-socket { fill: var(--elevated); stroke: var(--line); stroke-width: .8; }
.prize-bulb { fill: #ffd45e; opacity: .2; animation: wheel-bulb 1.6s steps(1, end) infinite; }
.prize-bulb.odd { animation-delay: -.8s; }
.wheel-stage.spinning .prize-bulb { animation-duration: .4s; }
.wheel-stage.spinning .prize-bulb.odd { animation-delay: -.2s; }
.wheel-stage.won .prize-bulb, .wheel-stage.won .prize-bulb.odd { animation: wheel-bulb-flash .24s steps(1, end) 10, wheel-bulb 1.6s steps(1, end) 2.4s infinite; }
.wheel-stage.won .prize-bulb.odd { animation-delay: 0s, 1.7s; }
.prize-peg { fill: var(--surface); stroke: var(--line); stroke-width: 1; }
.prize-slice-fill { --c: var(--w-coin); fill: color-mix(in srgb, var(--c) 6%, var(--surface)); stroke: var(--line); stroke-width: 1; }
.prize-slice-fill.tint { fill: color-mix(in srgb, var(--c) 16%, var(--surface)); }
.prize-slice-fill.gold { fill: color-mix(in srgb, var(--c) 38%, var(--surface)); }
.prize-slice-fill.mint { --c: var(--w-hint); fill: color-mix(in srgb, var(--c) 30%, var(--surface)); }
.prize-slice-fill:is(.common, .uncommon, .rare, .epic, .legendary) { --c: var(--tier); fill: color-mix(in srgb, var(--c) 50%, var(--surface)); }
.prize-slice-fill.common { --tier: #2f9e5b; } .prize-slice-fill.uncommon { --tier: #1f8fbf; } .prize-slice-fill.rare { --tier: #6b58d6; } .prize-slice-fill.epic { --tier: #b3478f; } .prize-slice-fill.legendary { --tier: #e07b2a; }
.prize-slice text { text-anchor: middle; dominant-baseline: middle; font-family: inherit; fill: var(--ink); }
.prize-slice-amount { font-size: 12.5px; font-weight: 800; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.prize-slice-unit { font-size: 4.4px; font-weight: 700; letter-spacing: .1em; fill: var(--muted); }
.prize-slice.hints .prize-slice-unit { fill: color-mix(in srgb, var(--w-hint) 70%, var(--ink)); }
.prize-slice.coins .prize-slice-unit { fill: color-mix(in srgb, var(--w-coin) 75%, var(--ink)); }
.prize-wheel-glass circle { opacity: .5; }
.prize-slice-flash { fill: var(--surface); opacity: 0; pointer-events: none; }
.prize-slice.winner .prize-slice-flash { animation: wheel-winner 1.1s var(--ease) 3; }
.prize-wheel-flapper { position: absolute; z-index: 2; left: 50%; top: -1.5%; width: 11%; height: 15.5%; margin-left: -5.5%; transform-origin: 50% 17%; filter: drop-shadow(0 2px 3px rgb(7 12 24 / .3)); pointer-events: none; }
.prize-wheel-flapper svg { width: 100%; height: 100%; display: block; overflow: visible; }
.prize-flapper-body { fill: var(--accent); stroke: var(--surface); stroke-width: 1.6; stroke-linejoin: round; }
.prize-flapper-gem { fill: var(--on-accent); }
.prize-wheel-hub { position: absolute; z-index: 3; left: 50%; top: 50%; width: 25%; aspect-ratio: 1; min-width: 4.5rem; translate: -50% -50%; display: grid; place-items: center; padding: 0; border: 0; border-radius: 50%; color: var(--on-accent); font: inherit; font-size: clamp(1rem, 4.4vw, 1.25rem); font-weight: var(--weight-title); letter-spacing: .02em; cursor: pointer; background: var(--accent); box-shadow: 0 0 0 5px var(--surface), 0 0 0 6px var(--line), 0 8px 18px rgb(7 12 24 / .25); transition: transform 160ms var(--ease), filter 160ms var(--ease); }
.prize-wheel-hub::after { content: ""; position: absolute; inset: -8px; border-radius: 50%; border: 2px solid var(--accent); opacity: 0; animation: wheel-hub-call 2.4s var(--ease) infinite; pointer-events: none; }
.prize-wheel-hub:hover { background: var(--accent); }
.prize-wheel-hub:hover:not(:disabled) { transform: scale(1.05); }
.prize-wheel-hub:active:not(:disabled) { transform: scale(.94); }
.prize-wheel-hub:focus-visible { outline: 3px solid var(--ring); outline-offset: 8px; }
.prize-wheel-hub:disabled { cursor: default; opacity: 1; filter: saturate(.7); }
.prize-wheel-hub:disabled::after { animation: none; }
.wheel-stage-status { margin: 0; min-height: 1.5em; color: var(--ink); font-weight: var(--weight-title); text-align: center; }
.wheel-stage.won .wheel-stage-status { animation: wheel-prize-in 420ms var(--ease) both; }
.wheel-tier-common { --tier: #2f9e5b; } .wheel-tier-uncommon { --tier: #1f8fbf; } .wheel-tier-rare { --tier: #6b58d6; } .wheel-tier-epic { --tier: #b3478f; } .wheel-tier-legendary { --tier: #e07b2a; }
.wheel-lab-side { display: grid; gap: var(--s3); align-content: start; }
/* Today's Dailies on the wheel's card: lit games count toward the spin; extra ones add luck. */
.wheel-included { display: grid; justify-items: center; gap: var(--s1); }
.wheel-included ul { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s2); margin: 0; padding: 0; list-style: none; }
.wheel-included li { position: relative; display: grid; place-items: center; width: 2.25rem; height: 2.25rem; border-radius: .6rem; opacity: .35; filter: grayscale(1); transition: opacity 300ms var(--ease), filter 300ms var(--ease); }
.wheel-included li.on { opacity: 1; filter: none; }
.wheel-included img { width: 1.75rem; height: 1.75rem; border-radius: .4rem; }
.wheel-included-check { position: absolute; right: -3px; bottom: -3px; display: grid; place-items: center; width: 1rem; height: 1rem; border-radius: 50%; background: var(--accent); color: var(--on-accent); font-size: .625rem; font-weight: 800; box-shadow: 0 0 0 2px var(--surface); }
.wheel-included .caption { margin: 0; text-align: center; text-wrap: balance; }
.wheel-pop .wheel-prize { width: 100%; box-sizing: border-box; box-shadow: none; }
.wheel-pop .daily-pop-card > .button { width: 100%; }
.wheel-prize { position: relative; overflow: hidden; display: grid; justify-items: center; gap: var(--s1); padding: var(--s6) var(--s4) var(--s4); border: 1px solid var(--line); border-radius: var(--radius-lg); background: radial-gradient(90% 70% at 50% 30%, color-mix(in srgb, var(--tier) 12%, var(--surface)), var(--surface)); text-align: center; animation: wheel-prize-in 480ms cubic-bezier(.2, 1.4, .4, 1) both; box-shadow: var(--shadow); }
.wheel-prize.shine::after { content: ""; position: absolute; inset: 0; background: linear-gradient(105deg, transparent 35%, rgb(255 255 255 / .55) 50%, transparent 65%); translate: -120% 0; animation: wheel-shine 1.4s var(--ease) .35s 2; pointer-events: none; }
.wheel-prize.coins, .wheel-won.coins { --tier: #c98a0b; }
.wheel-prize.hints, .wheel-won.hints { --tier: #1d9e95; }
.wheel-prize .eyebrow { margin: 0; color: var(--tier); }
.wheel-prize strong { font-size: var(--text-lg); }
.wheel-prize-art { position: relative; display: grid; place-items: center; min-height: 7.5rem; }
.wheel-prize-art::before { content: ""; position: absolute; inset: -30%; z-index: -1; background: repeating-conic-gradient(from 0deg, color-mix(in srgb, var(--tier) 14%, transparent) 0 8deg, transparent 8deg 20deg); -webkit-mask: radial-gradient(closest-side, #000 30%, transparent 100%); mask: radial-gradient(closest-side, #000 30%, transparent 100%); animation: wheel-rays 30s linear infinite; }
.wheel-prize-art { isolation: isolate; }
.wheel-prize-icon { width: 6.5rem; height: 6.5rem; overflow: visible; }
.wheel-prize-art .sky-swatch.wheel-prize-scene { display: block; width: 11rem; height: 7rem; margin: 0; border-radius: var(--radius-sm); }
.wheel-lab-tally { display: flex; gap: var(--s4); margin: 0; }
.wheel-lab-tally div { display: grid; }
.wheel-lab-tally dt { color: var(--muted); font-size: var(--text-sm); }
.wheel-lab-tally dd { margin: 0; font-weight: var(--weight-title); font-variant-numeric: tabular-nums; }
.wheel-odds-scroll { overflow-x: auto; }
.wheel-odds { width: 100%; border-collapse: collapse; font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
.wheel-odds th, .wheel-odds td { padding: var(--s1) var(--s2); border-bottom: 1px solid var(--line); text-align: left; white-space: nowrap; }
.wheel-odds td:nth-child(n+5), .wheel-odds th:nth-child(n+5), .wheel-odds td:nth-child(3), .wheel-odds th:nth-child(3) { text-align: right; }
.wheel-odds tr[class*="wheel-tier-"] td:first-child { box-shadow: inset 4px 0 0 var(--tier); }
@keyframes wheel-prize-in { from { opacity: 0; transform: scale(.85); } }
@keyframes wheel-rays { to { rotate: 360deg; } }
@keyframes wheel-bulb { 0% { opacity: 1; } 50% { opacity: .15; } }
@keyframes wheel-bulb-flash { 0% { opacity: 1; } 50% { opacity: .1; } }
@keyframes wheel-winner { 0%, 100% { opacity: 0; } 40% { opacity: .38; } }
@keyframes wheel-hub-call { 0% { opacity: .7; transform: scale(1); } 70%, 100% { opacity: 0; transform: scale(1.35); } }
@keyframes wheel-shine { to { translate: 120% 0; } }
@media (prefers-reduced-motion: reduce) {
    .prize-wheel-rays, .wheel-prize-art::before, .prize-wheel-hub::after, .wheel-prize.shine::after { animation: none; }
    .prize-bulb, .prize-bulb.odd, .wheel-stage.won .prize-bulb { animation: none; opacity: 1; }
    .prize-slice.winner .prize-slice-flash { animation: none; opacity: .25; }
    .wheel-prize, .wheel-stage.won .wheel-stage-status { animation: none; }
}
/* The live wheel's page and its promos: the Hub card, the Daily track chip and the Daily win callout. */
.wheel-odds-details { margin-top: var(--s6); }
.wheel-odds-details summary { cursor: pointer; font-weight: var(--weight-label); }
.wheel-odds-details[open] summary { margin-bottom: var(--s3); }
.wheel-live .wheel-prize .button { margin-top: var(--s2); }
.wheel-done { display: grid; gap: var(--s4); max-width: 30rem; }
.wheel-icon-defs { position: absolute; width: 0; height: 0; overflow: hidden; }
.wheel-done-actions { display: grid; gap: var(--s2); }
.wheel-done-actions > :is(a.button, button) { width: 100%; justify-content: center; }
.wheel-done-actions img { flex: none; }
.wheel-won { display: grid; grid-template-columns: auto minmax(0, 1fr); grid-auto-flow: column; align-items: center; gap: var(--s3); padding: var(--s2) var(--s3); border: 1px solid var(--line); border-radius: var(--radius-lg); background: color-mix(in srgb, var(--tier, var(--accent)) 10%, var(--surface)); }
.wheel-won-art { display: grid; place-items: center; width: 44px; height: 44px; }
.wheel-won-art svg { width: 40px; height: 40px; overflow: visible; }
.wheel-won-scene { width: 44px; height: 44px; border-radius: var(--radius); overflow: hidden; }
.wheel-won-body { display: grid; gap: 1px; min-width: 0; }
.wheel-won-body .eyebrow { margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wheel-won-body strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wheel-progress { display: grid; gap: var(--s3); }
.wheel-progress-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: var(--s1) var(--s3); }
.wheel-progress-meter { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.wheel-progress-meter span { height: 8px; border-radius: var(--pill); background: var(--line); transition: background-color 300ms var(--ease); }
.wheel-progress-meter span.on { background: var(--accent); }
.wheel-dailies { gap: var(--s2); }
.wheel-dailies .daily-pick { gap: var(--s3); padding: var(--s3); }
.wheel-dailies .daily-pick-body strong { font-size: var(--text-md); }
.wheel-mark { flex: none; overflow: visible; color: var(--ink); }
.wheel-mark-pointer { fill: var(--accent); stroke: var(--surface); stroke-width: .8; stroke-linejoin: round; }
.wheel-mark.spin .wheel-mark-rotor { animation: wheel-rays 8s linear infinite; }
.wheel-promo { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--s4); margin-block: var(--s4); padding: var(--s4);
  border: 1px solid var(--line); border-radius: var(--radius-lg); color: inherit; text-decoration: none; background: var(--surface); box-shadow: var(--shadow);
  transition: border-color 160ms var(--ease), transform 160ms var(--ease); }
.wheel-promo:hover { border-color: var(--sea); }
.wheel-promo:active { transform: translateY(1px); }
.wheel-promo.ready { border-color: color-mix(in srgb, var(--accent) 55%, var(--line));
  background: radial-gradient(120% 140% at 0% 50%, color-mix(in srgb, var(--accent) 14%, transparent), transparent 60%), var(--surface); }
.wheel-promo-art { display: grid; place-items: center; }
.wheel-promo-body { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2px; min-width: 0; }
.wheel-promo-body .eyebrow { margin: 0; }
.wheel-promo-body > strong { text-wrap: balance; }
.wheel-promo-dailies { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; margin-top: var(--s1); }
.wheel-promo-dailies > span:not(.wheel-promo-count) { position: relative; display: grid; place-items: center; width: 24px; height: 24px; border-radius: 50%; background: color-mix(in srgb, var(--ink) 9%, transparent); }
.wheel-promo-dailies img { border-radius: 4px; opacity: .45; filter: grayscale(.7); }
.wheel-promo-dailies .done img { opacity: 1; filter: none; }
.wheel-promo-dailies .done::after { content: "✓"; position: absolute; right: -3px; bottom: -3px; display: grid; place-items: center; width: 13px; height: 13px;
  border-radius: 50%; background: var(--accent); color: var(--on-accent); font-size: 9px; font-weight: 700; line-height: 1; }
.wheel-promo-count { margin-left: 2px; color: var(--muted); font-size: var(--text-xs); font-weight: var(--weight-label); font-variant-numeric: tabular-nums; }
.wheel-promo-cta { padding: var(--s2) var(--s3); border-radius: var(--pill); background: var(--elevated); color: var(--ink); font-weight: 600; white-space: nowrap; }
.wheel-promo.ready .wheel-promo-cta { background: var(--accent); color: var(--on-accent); }
.first-puzzle .wheel-promo-art img { border-radius: .7rem; }
.daily-track-wheel { display: inline-flex; align-items: center; gap: 4px; min-height: 1.5rem; padding: 2px 8px 2px 3px; border-radius: var(--pill); color: inherit; text-decoration: none;
  background: color-mix(in srgb, var(--track-film, var(--ink)) 11%, transparent); font-size: var(--text-xs); font-weight: var(--weight-label); font-variant-numeric: tabular-nums; }
.daily-track-wheel.ready { background: var(--track-glow, var(--accent)); color: #fff; }
.wheel-callout { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--s3); padding: var(--s3) var(--s4); margin-bottom: var(--s3);
  border: 1px solid var(--line); border-radius: var(--radius-lg); color: inherit; text-decoration: none; text-align: left; background: var(--surface); }
.wheel-callout > span:nth-child(2) { display: grid; gap: 2px; }
.wheel-callout.ready { border-color: color-mix(in srgb, var(--accent) 55%, var(--line)); background: color-mix(in srgb, var(--accent) 10%, var(--surface)); }
.wheel-callout-cta { color: var(--accent); font-weight: 600; }
.wheel-callout.ready .wheel-callout-cta { padding: var(--s1) var(--s3); border-radius: var(--pill); background: var(--accent); color: var(--on-accent); }
/* Phones: the chip would wrap the Daily track and push the board under the tab bar; the Hub card and win callout carry the wheel there.
   Smaller marks keep the seven Dailies and the count on one line beside Prizes (an SE has about 190px for them). */
@media (max-width: 480px) { .wheel-promo { gap: var(--s2); padding: var(--s3); } .wheel-promo-art .wheel-mark { width: 40px; height: 40px; } .daily-track-wheel { display: none; }
  .wheel-promo-cta { padding: var(--s1) var(--s2); } .wheel-promo-dailies { column-gap: 4px; } .wheel-promo-count { margin-left: 0; }
  .wheel-promo-dailies > span:not(.wheel-promo-count) { width: 20px; height: 20px; } .wheel-promo-dailies img { width: 14px; height: 14px; } }
@media (prefers-reduced-motion: reduce) { .wheel-mark.spin .wheel-mark-rotor { animation: none; } }
@media (max-width: 767px) { .wheel-lab { grid-template-columns: minmax(0, 1fr); } .wheel-stage { padding: var(--s3); } .wheel-scene.pet-habitat { padding: var(--s4) var(--s2); } }

/* Small actions (refresh, copy, dismiss) as round icon buttons; the name lives in aria-label and title. */
.icon-button { display: inline-grid; place-items: center; flex: none; width: 2.75rem; height: 2.75rem; min-height: 0; padding: 0; border-radius: 50%; }
.icon-button .ui-icon { width: 1.15rem; height: 1.15rem; }
.banner .icon-button { width: 2.25rem; height: 2.25rem; min-height: 0; padding: 0; margin-left: var(--s2); vertical-align: middle; }

/* Focus mode (FocusToggle, app.js): the game alone, clear of the notch and the home indicator. */
.page-heading:has(> .page-heading-focus) { position: relative; padding-right: calc(var(--control) + var(--s2)); }
.page-heading-focus { position: absolute; top: 0; right: 0; }
:root[data-focus] { --container: none; --game-width: 100%; --board-size: 100%; }
:root[data-focus] :is(.masthead, .footer, .shell > .banner, .install-banner, .page-heading > .muted) { display: none; }
:root[data-focus] .shell { padding: env(safe-area-inset-top) max(var(--s4), env(safe-area-inset-right)) env(safe-area-inset-bottom) max(var(--s4), env(safe-area-inset-left)); }
:root[data-focus] main { padding: var(--s2) 0; }
:root[data-focus] .page-heading { margin-bottom: var(--s3); }
/* Full screen is the playable area alone: the board and its controls under one slim row of the HUD's tool
   buttons (so Exit stays in reach). Each game lifts its own size caps so the board takes the rest. */
:root[data-focus] :is(.game-hud > :not(.game-hud-tools, .game-hud-stats), .game-caption, .page-heading > :not(.page-heading-focus)) { display: none; }
:root[data-focus] .game-hud { display: flex; justify-content: flex-end; align-items: center; gap: var(--s2); }
/* Focus keeps the score that earns the stars (moves, time, goal) beside the tools, on one compact row. */
:root[data-focus] .game-hud > .game-hud-stats { order: -1; margin-right: auto; min-height: 0; }
:root[data-focus] .game-hud-stats > :not(.hud-stats) { display: none; }
:root[data-focus] .hud-stats { gap: 0 var(--s3); }
:root[data-focus] .hud-stats dd { font-size: var(--text-lg); }
:root[data-focus] .page-heading:has(> .page-heading-focus) { display: flex; justify-content: flex-end; padding-right: 0; margin-bottom: 0; }
:root[data-focus] .page-heading-focus { position: static; }
/* A board that runs out of width before height (a wide table on a portrait phone) sits centered under the tool row. */
:root[data-focus] .game-page { display: flex; flex-direction: column; min-height: calc(100dvh - 2 * var(--s2) - env(safe-area-inset-top) - env(safe-area-inset-bottom)); }
:root[data-focus] .game-page > * { min-width: 0; }
:root[data-focus] .game-page > .game-hud { margin-bottom: auto; }
:root[data-focus] .game-page::after { content: ""; margin-top: auto; }
/* While app.js measures the free space it drops that centering, so a small board's own gap can't keep it small. */
:root[data-focus][data-fit-measure] .game-page > .game-hud, :root[data-focus][data-fit-measure] .game-page::after { margin-block: 0; }
@media (max-width: 767px) { :root[data-focus] body .toast-host { bottom: max(var(--s2), env(safe-area-inset-bottom)); } }
/* Home nudge for a big coin balance: the wheel promo's card with the item's art. */
.shop-promo { position: relative; margin-block: calc(-1 * var(--s2)) var(--s4); }
.shop-promo > .wheel-promo { margin: 0; }
.shop-promo-close { position: absolute; top: -12px; right: -8px; width: 36px; height: 36px; border: 1px solid var(--line); border-radius: 50%; background: var(--surface); box-shadow: var(--shadow); }
.shop-promo-close .ui-icon { width: 14px; height: 14px; }
.shop-promo-art { width: 56px; height: 56px; }
.shop-promo-scene { display: block; width: 56px; height: 56px; border-radius: var(--radius); overflow: hidden; }
.shop-promo .eyebrow { display: inline-flex; align-items: center; gap: 4px; }
.heard { margin-block: var(--s4); padding: var(--s3) var(--s4) var(--s4); border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--surface); box-shadow: var(--shadow); }
.heard-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); }
.heard-skip { width: 2.25rem; height: 2.25rem; }
.heard-options { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s2); }
.heard-option { min-height: 2.5rem; padding: var(--s1) var(--s3); border-radius: var(--pill); font-weight: 600; }
.heard-thanks { margin-block: var(--s3); color: var(--muted); font-size: var(--text-sm); text-align: center; }
/* Headline tiles open who and what is behind the number. */
.live-tile-open { width: 100%; grid-template-columns: minmax(0, 1fr); justify-items: stretch; color: inherit; font: inherit; text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: border-color 160ms ease-out, transform 120ms ease-out; }
.live-tile-open:hover { border-color: color-mix(in srgb, var(--sea) 45%, var(--line)); }
.live-tile-open:active { transform: scale(0.98); }
.live-tile-open:focus-visible { outline: 2px solid var(--sea); outline-offset: 2px; }
.live-tile-more { position: absolute; top: var(--s2); right: var(--s2); display: inline-flex; color: var(--muted); opacity: 0.7; }
.live-tile-more svg { width: 14px; height: 14px; }
