/* Launcher, game menu, cross-game settings and shared game primitives. Tidegrid's own board art stays in app.css. */

/* Shared game primitives. Per-game styles keep palettes and board art only. */
.game-hud, .game-stats, .game-win, .game-level-tile, .game-pack-tile, .game-controls, .game-chip { box-sizing: border-box; }
.game-level-tile { position: relative; }
.game-controls button { display: inline-flex; align-items: center; justify-content: center; gap: var(--s2); min-height: 2.75rem;
  border-radius: var(--pill); touch-action: manipulation; transition: transform var(--fast) var(--ease), background-color var(--fast) var(--ease); }
.game-controls button:not(:disabled):active { transform: scale(.96); }

.game-menu { position: relative; flex-shrink: 0; }
.game-switcher { min-height: var(--control); padding: var(--s1) var(--s3) var(--s1) var(--s1); border: 1px solid transparent; border-radius: var(--pill); background: transparent; color: var(--ink); font-size: var(--text-xl); }
.game-switcher:hover, .game-switcher[aria-expanded="true"] { border-color: var(--line); background: var(--surface); }
.game-switcher img { border-radius: .45rem; }
.game-switcher .chevron { width: 1rem; height: 1rem; color: var(--muted); transition: transform var(--fast) var(--ease); }
.game-switcher[aria-expanded="true"] .chevron { transform: rotate(180deg); }
.game-menu-scrim { position: fixed; inset: 0; z-index: 302; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.game-menu .game-switcher { position: relative; z-index: 1; }
.game-menu-panel { position: absolute; z-index: 303; top: calc(100% + var(--s2)); left: 0; width: min(20rem, calc(100vw - 2 * var(--s4))); display: grid; gap: 2px; padding: var(--s2); border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); box-shadow: var(--shadow), 0 1px 0 var(--line); transform-origin: top left; animation: menu-in var(--fast) var(--ease-enter); }
.game-hud-settings-actions { display: flex; justify-content: center; gap: var(--s3); }
@keyframes menu-in { from { opacity: 0; transform: scale(.97) translateY(-4px); } }
.game-menu-panel a { display: flex; align-items: center; gap: var(--s3); min-height: var(--control); padding: var(--s2) var(--s3); border-radius: var(--radius-sm); color: var(--ink); font-weight: var(--weight-label); font-size: var(--text-sm); text-decoration: none; }
.game-menu-panel a:hover, .game-menu-panel a:focus-visible { background: var(--elevated); }
.game-menu-label { margin: var(--s2) var(--s3) 0; font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; font-weight: var(--weight-title); color: var(--muted); }
#games-label { display: flex; align-items: center; justify-content: space-between; margin-top: 0; }
.game-menu-panel a.game-menu-all { min-height: 0; padding: var(--s1) var(--s2); color: var(--sea); font-size: var(--text-xs); letter-spacing: normal; text-transform: none; }
/* The tap-away layer sits above the phone tab bar (z 300), so tapping anywhere outside an open menu closes it.
   While one is open the header buttons rise above it, so the bug button or another menu opens on the first tap
   (Popover closes the others). */
body:has(.game-menu-scrim, .bell-scrim) :is(.game-switcher, .bell-button, .account-link, .bug-button) { position: relative; z-index: 304; }
.game-menu-game img { width: 2.25rem; height: 2.25rem; border-radius: .6rem; }
.game-menu-game span { display: grid; min-width: 0; }
.game-menu-game small { color: var(--muted); font-weight: var(--weight-body); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.game-menu-game.current { background: color-mix(in srgb, var(--sea) 10%, transparent); }

.shell:has(.hub-heading) main { padding: var(--s6) 0; }
.hub-heading { margin-bottom: var(--s4); }
.hub-heading h1 { font-size: var(--text-2xl); }
.hub-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s6); }
.hub-card { display: grid; grid-template-rows: auto 1fr; overflow: hidden; border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--surface); color: var(--ink); text-decoration: none; transition: border-color var(--fast) var(--ease), transform var(--normal) var(--ease), box-shadow var(--normal) var(--ease); }
.hub-card:hover { border-color: var(--sea); box-shadow: var(--shadow); }
.hub-card:active { transform: translateY(1px); }
.hub-art { height: 12rem; overflow: hidden; display: grid; place-items: center; }
.tidegrid-art { background: radial-gradient(ellipse at 50% 38%, #2f7a80 0%, #174a56 42%, #0a2129 85%); }
.tidegrid-art svg { width: 100%; height: 100%; }
@media (prefers-reduced-motion: no-preference) {
  .th-art .th-escape { animation: th-slide 3.6s var(--ease) infinite; }
  .th-art .th-spill, .th-art .th-gate-orange { animation: th-pulse 3.6s var(--ease) infinite; }
  .th-art .th-tide path { animation: th-tide 7s ease-in-out infinite alternate; }
  .th-art .th-tide path + path { animation-duration: 9s; }
}
@keyframes th-slide { 0%, 18% { transform: translateX(-14px); } 55%, 80% { transform: translateX(0); } 100% { transform: translateX(-14px); } }
@keyframes th-pulse { 0%, 18%, 100% { opacity: .55; } 55%, 80% { opacity: 1; } }
@keyframes th-tide { to { transform: translateX(-18px); } }
.sand-art { background: radial-gradient(ellipse at 50% 110%, #ff8a3d55, transparent 60%), linear-gradient(160deg, #4b2394, #22104f); }
.sand-art svg { width: 100%; height: 100%; }
.hub-body { display: grid; align-content: start; gap: var(--s2); padding: var(--s6); }
.hub-body h2 { display: flex; align-items: center; gap: var(--s2); margin: 0; font-size: var(--text-xl); letter-spacing: var(--tracking-title); }
.hub-body h2 img { border-radius: .45rem; }
.hub-body p { margin: 0; }
.hub-meta { font-size: var(--text-sm); font-weight: var(--weight-label); color: var(--accent); }
.hub-risk { font-size: var(--text-sm); font-weight: var(--weight-title); color: var(--warning); }
.hub-extras { margin-top: var(--s8); border-block: 1px solid var(--line); }
.hub-extras > summary { display: flex; align-items: center; gap: var(--s3); min-height: var(--control); padding: var(--s3) 0; list-style: none; cursor: pointer; font-weight: var(--weight-label); transition: color var(--fast) var(--ease); }
.hub-extras > summary::-webkit-details-marker { display: none; }
.hub-extras > summary:hover { color: var(--sea); }
.hub-extras > summary > .ui-icon { color: var(--muted); transition: transform var(--fast) var(--ease); }
.hub-extras[open] > summary > .ui-icon { transform: rotate(180deg); }
.hub-extras-balance { display: inline-flex; align-items: center; gap: var(--s1); margin-left: auto; color: var(--muted); font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
.hub-extras-content { display: grid; }
.hub-extras :is(.coin-goal, .hub-streak, .wheel-promo, .install-banner, .heard) { margin: 0; padding: var(--s4) 0; border: 0; border-radius: 0; background: none; box-shadow: none; }
.hub-reward-link { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); min-height: var(--control); padding: var(--s4) 0; color: var(--ink); text-decoration: none; transition: color var(--fast) var(--ease); }
.hub-reward-link > span { display: grid; gap: var(--s1); }
.hub-reward-link:hover { color: var(--sea); }
.hub-extras .hub-extras-content > * { border-top: 1px solid var(--line); }
.hub-extras :is(.friend-streak-actions > button, .friend-streak-actions > .button, .coin-goal-picker > summary, .heard-option, .heard-skip, .install-banner > .bell-icon-button) { min-height: var(--control); }
.hub-extras :is(.heard-skip, .install-banner > .bell-icon-button) { min-width: var(--control); }
.hub-streak { display: block; margin: var(--s3) 0 0; padding: var(--s3) var(--s4); border: 1px solid color-mix(in srgb, var(--warning) 40%, var(--line));
  border-radius: var(--radius-lg); color: inherit; text-decoration: none; font-size: var(--text-sm); background: color-mix(in srgb, var(--warning) 8%, var(--surface)); }
a.hub-streak:hover { border-color: var(--warning); }
/* Friend streaks: the Home card, the Friends rows and badge, and the Daily result's line. */
.friend-streak { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s3); }
.friend-streak-text { flex: 1 1 12rem; min-width: 0; }
.friend-streak-risk { color: var(--warning); font-weight: var(--weight-title); }
.friend-streak-more { margin-left: var(--s1); color: var(--muted); white-space: nowrap; }
.friend-streak-actions { display: flex; align-items: center; gap: var(--s2); flex-shrink: 0; max-width: 100%; }
.friend-streak-actions > button, .friend-streak-actions > .button { min-height: 2.25rem; padding: var(--s1) var(--s3); font-size: var(--text-sm); border-radius: var(--pill); text-align: center; overflow-wrap: anywhere; }
.friend-streak-badge { display: inline-flex; align-items: center; justify-content: center; gap: 2px; min-width: 2.75rem; min-height: 2rem; padding: 0 var(--s2); flex-shrink: 0;
  border-radius: var(--pill); background: color-mix(in srgb, var(--warning) 14%, var(--surface)); color: var(--ink); font-size: var(--text-sm); font-weight: var(--weight-title); white-space: nowrap; text-decoration: none; }
.daily-friend-streak { font-size: var(--text-sm); }
.daily-friend-streak .link-button { margin-left: var(--s1); font-size: inherit; }
.offline-status .dot { width: .5rem; height: .5rem; flex-shrink: 0; border-radius: 50%; background: var(--sea); transform: translateY(-1px); }
@media (hover: hover) and (prefers-reduced-motion: no-preference) { .hub-card:hover { transform: translateY(-2px); } }

.offline-status { margin-top: var(--s8); display: grid; gap: var(--s4); }
.offline-status.ready { border-color: color-mix(in srgb, var(--sea) 55%, var(--line)); }
.offline-head { display: flex; gap: var(--s4); align-items: center; }
.offline-head h2 { margin: 0; font-size: var(--text-lg); }
.offline-head p { margin: var(--s1) 0 0; }
.offline-icon { width: 2.75rem; height: 2.75rem; flex-shrink: 0; display: grid; place-items: center; border-radius: 50%; background: var(--elevated); color: var(--sea); font-size: 1.3rem; }
.offline-status[data-online="false"] .offline-icon { background: var(--sea); color: var(--surface); }
.offline-status button { justify-self: start; }
.offline-list { margin: 0; padding-left: var(--s6); display: grid; gap: var(--s2); color: var(--muted); }
.offline-list strong { color: var(--ink); }
.profile-links { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2); }
.profile-links a { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) 0; font-weight: var(--weight-label); }
.profile-links img { border-radius: .4rem; }

.sand-levels { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(5.5rem, 1fr)); gap: var(--s2); }
.sand-levels a { display: grid; justify-items: center; padding: var(--s3) var(--s2); border: 1px solid var(--line); border-radius: var(--radius-sm); color: var(--ink); text-decoration: none; }
.sand-levels a:hover { border-color: var(--sea); }
.sand-levels span { font-size: var(--text-xs); color: var(--muted); }
.sand-levels .level-stars { color: var(--accent); }
.sand-levels .level-stars i { color: var(--line); }

@media (max-width: 767px) {
  .hub-grid { gap: var(--s3); }
  .hub-art { height: 6.5rem; }
  .hub-body { gap: var(--s1); padding: var(--s3); }
  .hub-body h2 { font-size: var(--text-md); gap: var(--s1); }
  .hub-body h2 img { width: 22px; height: 22px; }
  .hub-meta, .hub-risk { font-size: var(--text-xs); }
  /* Two columns leave no room for the tagline; the art and name say what each game is. */
  .hub-body .muted { display: none; }
  .game-switcher { font-size: var(--text-lg); }
}

/* ── Sand Sort ─────────────────────────────────────────────────────────────
   Visual: a stage per world at two times of day, jewel sand with grain, thick lit glass on shelves.
   Day is written first and night overrides it. app.js resolves the player's Appearance setting
   (auto, light, dark) against the device and publishes the answer as data-scene, so one selector
   covers both following the device and choosing explicitly.
   Motion: calm-playful. One signature ease-out; small overshoot only on lift and rewards;
   no linear spatial motion; reduced motion keeps fades only. */
body:has(.sand-layout) {
  color-scheme: light;
  --background: #f3edfd; --surface: #fffcff; --elevated: #e9e1fa;
  --ink: #23134d; --muted: #5b4b87; --line: #23134d26;
  --accent: #8f5207; --on-accent: #fff6ea; --sea: #0f6d86; --ring: #8f5207; --error: #b3261e;
  --sand-nav: #f4eeff;
  --sand-quick: 140ms; --sand-std: 220ms; --sand-slow: 380ms; --sand-reward: 620ms;
  --sand-ease: var(--ease);
  --sand-ease-pop: var(--ease-pop);
  --sand-ease-move: cubic-bezier(.45, 0, .25, 1);
  --sand-ease-exit: cubic-bezier(.3, 0, 1, 1);
  --sand-ease-fall: cubic-bezier(.55, 0, 1, .6);
}
html[data-scene="night"] body:has(.sand-layout) {
  color-scheme: dark;
  --background: #140a33; --surface: #2a1760; --elevated: #3a2380;
  --ink: #f7f2ff; --muted: #c3b6ea; --line: #ffffff26;
  --accent: #ffd23f; --on-accent: #2a1400; --sea: #7ce8ff; --ring: #ffd23f; --error: #ff9a9e;
  --sand-nav: #1b0f45;
}
/* Sand colors (SandArt) */
:root {
  --sc-coral: #ff5d73; --sc-blue: #4f86ff; --sc-sunshine: #ffcb3d; --sc-mint: #3fd192; --sc-violet: #a877ff; --sc-tangerine: #ff8e3c;
  --sc-pink: #ff74c9; --sc-sky: #44d7ea; --sc-pearl: #e9ebff; --sc-lime: #b6ea3e; --sc-cocoa: #b9825a; --sc-indigo: #5a55d6;
  --sand-mystery: #2b2350; --sand-mystery-l: #4a3f82; --sand-mystery-d: #1d1638;
}
html[data-scene="night"] {
  --sc-indigo: #7a75f5;
  --sand-mystery: #7466b8; --sand-mystery-l: #9184d0; --sand-mystery-d: #5a4d9a;
}
.grain { fill: var(--c); }
.grain-l { fill: color-mix(in srgb, var(--c) 55%, var(--shine)); }
.grain-d { fill: color-mix(in srgb, var(--c) 80%, var(--piece-shade)); }
.mystery .grain-l { fill: var(--sand-mystery-l); }
.mystery .grain-d { fill: var(--sand-mystery-d); }
/* The stage itself. Pages carry both palettes inline (SandArt.Vars); these rules pick one, along with
   the neutrals every stage rule is written against: --stage-film for translucent overlays, --stage-lift
   for what glows are brightened toward, --stage-base for what frosted panels mix toward. */
.sand-layout, .sand-world {
  --world-top: var(--day-top); --world-bottom: var(--day-bottom); --world-glow: var(--day-glow); --world-shelf: var(--day-shelf);
  --stage-film: #2b1a56; --stage-lift: #2c1a57; --stage-base: #fff; --stage-glass: #37206b;
  --stage-well: #6a52a8; --stage-well-opacity: .2; --stage-cast: .16; --stage-shadow: #23134d3d;
  --stage-ink: #22134a; --stage-star: color-mix(in srgb, #8f5207 60%, var(--stage-ink));
  --world-label: color-mix(in srgb, var(--world-glow) 40%, var(--stage-ink));
}
html[data-scene="night"] .sand-layout, html[data-scene="night"] .sand-world {
  --world-top: var(--night-top); --world-bottom: var(--night-bottom); --world-glow: var(--night-glow); --world-shelf: var(--night-shelf);
  --stage-film: #fff; --stage-lift: #fff; --stage-base: #0b0520; --stage-glass: #fff;
  --stage-well: #0a041c; --stage-well-opacity: .38; --stage-cast: .35; --stage-shadow: #0009;
  --stage-ink: #f5f1ff; --stage-star: #ffd76a;
  --world-label: color-mix(in srgb, var(--world-glow) 62%, var(--stage-ink));
}
body:has(.sand-layout) .masthead { border-bottom-color: var(--line); }
body:has(.sand-layout) nav { background: color-mix(in srgb, var(--sand-nav) 90%, transparent); border-color: var(--line); -webkit-backdrop-filter: blur(16px) saturate(1.2); backdrop-filter: blur(16px) saturate(1.2); }
.sand-layout { --track-film: var(--stage-film); --track-glow: color-mix(in srgb, var(--world-glow) 70%, var(--stage-lift) 30%); --track-ring: color-mix(in srgb, var(--world-glow) 60%, transparent); --hud-film: color-mix(in srgb, var(--stage-film) 7%, transparent); --hud-eyebrow: var(--world-label); --sand-panel: color-mix(in srgb, var(--world-top) 60%, var(--stage-base) 40%); }

.sand-backdrop { position: fixed; inset: 0; z-index: -1; overflow: hidden; pointer-events: none;
  background: radial-gradient(ellipse 90% 45% at 50% 108%, color-mix(in srgb, var(--world-glow) 42%, transparent), transparent 70%),
              radial-gradient(ellipse 60% 50% at 15% 5%, color-mix(in srgb, var(--world-top) 90%, #fff 10%), transparent 70%),
              linear-gradient(180deg, var(--world-top), var(--world-bottom));
  transition: background var(--sand-slow) var(--sand-ease); }
.sand-backdrop span { position: absolute; left: calc(var(--b) * 15% + 3%); top: calc(90% - var(--b) * 11%); width: calc(3rem + var(--b) * .9rem); aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--world-glow) 40%, var(--stage-lift) 10%), transparent 68%); opacity: .22; filter: blur(2px);
  animation: sand-bokeh calc(14s + var(--b) * 2.5s) ease-in-out calc(var(--b) * -3s) infinite alternate; }
@keyframes sand-bokeh { to { transform: translate(calc(18px - var(--b) * 5px), -46px) scale(1.15); opacity: .34; } }



.sand-stage { position: relative; display: grid; place-items: center; margin-top: var(--s4); }
.sand-board { width: 100%; height: auto; max-height: min(var(--fit-h, 64dvh), 44rem); overflow: visible; touch-action: manipulation; user-select: none; -webkit-user-select: none; -webkit-tap-highlight-color: transparent; }
:root[data-focus] .sand-board { max-height: var(--fit-h, calc(100dvh - 8rem)); }
.shelf { filter: drop-shadow(0 6px 10px var(--stage-shadow)); }
.bottle-shadow { fill: #000; opacity: var(--stage-cast); }

.bottle-enter { animation: bottle-in var(--sand-slow) var(--sand-ease) both; animation-delay: calc(var(--i) * 35ms); }
@keyframes bottle-in { from { opacity: 0; transform: translateY(26px); } }
.bottle { cursor: pointer; outline: none; transition: transform var(--sand-quick) var(--sand-ease-exit); }
.bottle.selected { transform: translateY(-24px); transition: transform var(--sand-std) var(--sand-ease-pop); }
.bottle-hit { fill: transparent; }
.bottle-focus { fill: none; stroke: var(--ring); stroke-width: 3; opacity: 0; }
.bottle:focus-visible .bottle-focus { opacity: 1; }
.bottle.nope-a { animation: bottle-nope-a 340ms var(--sand-ease) both; }
.bottle.nope-b { animation: bottle-nope-b 340ms var(--sand-ease) both; }
@keyframes bottle-nope-a { 20% { transform: translateX(-9px); } 45% { transform: translateX(7px); } 70% { transform: translateX(-4px); } 100% { transform: none; } }
@keyframes bottle-nope-b { 20% { transform: translateX(-9px); } 45% { transform: translateX(7px); } 70% { transform: translateX(-4px); } 100% { transform: none; } }

.bottle-back { fill: var(--stage-well); fill-opacity: var(--stage-well-opacity); }
.bottle-inner { fill: none; stroke: #000; stroke-opacity: .28; stroke-width: 2; }
.bottle-glass { fill: url(#glass-fill); stroke: url(#glass-rim); stroke-width: 3.4; stroke-linejoin: round; }
.bottle-shine { fill: url(#glass-shine); }
.bottle-glint { fill: #fff; opacity: .75; }
.bottle-lip { fill: color-mix(in srgb, var(--stage-glass) 22%, transparent); stroke: color-mix(in srgb, var(--stage-glass) 82%, transparent); stroke-width: 2.2; }
.sand-surface { fill: none; stroke: color-mix(in srgb, var(--c) 55%, var(--shine)); stroke-width: 2.5; stroke-opacity: .85; }
html:not([data-scene="night"]) .sand-surface { stroke: color-mix(in srgb, var(--c) 50%, var(--stage-ink)); stroke-opacity: 1; stroke-width: 3; }
.sand-symbol { font-size: 20px; font-weight: 700; fill: #140a33; fill: oklch(from var(--c) clamp(0, (.6 - l) * 1e3, 1) 0 0); pointer-events: none; }
.bottle.complete .bottle-glass { stroke: color-mix(in srgb, var(--accent) 45%, var(--stage-lift)); }
.bottle.hinted .bottle-glass { stroke: var(--accent); stroke-width: 4.5; animation: sand-hint 900ms ease-in-out infinite alternate; }
@keyframes sand-hint { to { stroke-opacity: .45; } }
.hint-arrow { pointer-events: none; fill: none; stroke: var(--accent); stroke-width: 4; stroke-linecap: round; stroke-linejoin: round; animation: hint-bob 900ms ease-in-out infinite alternate; }
@keyframes hint-bob { to { transform: translateY(6px); } }

.cork-body { fill: #c98a52; }
.cork-top { fill: #e7b27d; }
.cork-grain { stroke: #9c6536; stroke-width: 1.6; stroke-linecap: round; }
.cork { transform-box: fill-box; transform-origin: 50% 100%; }
.cork.popping { animation: cork-pop var(--sand-std) var(--sand-ease-pop) calc(var(--pour-ms) * .68) both; }
@keyframes cork-pop { from { opacity: 0; transform: translateY(-30px) scale(.6); } }
.sparkle { transform-box: fill-box; transform-origin: center; opacity: 0; animation: sparkle var(--sand-reward) var(--sand-ease) calc(var(--pour-ms) * .7 + var(--s) * 12ms) both; }
@keyframes sparkle {
  0% { opacity: 0; transform: rotate(var(--a)) translateY(0) scale(.4); }
  25% { opacity: 1; }
  100% { opacity: 0; transform: rotate(var(--a)) translateY(-40px) scale(1.1); }
}

/* The pour: lift on an arc, tip over the target, trickle, and come home (--pour-ms total). */
.bottle-slot.flying .bottle { opacity: 0; transition: none; }
.bottle-slot.flying .bottle-shadow { opacity: .12; }
.pour-flight { pointer-events: none; animation: sand-flight var(--pour-ms) both; }
@keyframes sand-flight {
  0% { transform: translate(var(--x0), var(--y0)) rotate(0deg); animation-timing-function: var(--sand-ease-move); }
  15% { transform: translate(var(--xm), var(--ym)) rotate(var(--rot-mid)); animation-timing-function: var(--sand-ease); }
  30%, 66% { transform: translate(var(--x1), var(--y1)) rotate(var(--rot)); animation-timing-function: var(--sand-ease-move); }
  84% { transform: translate(var(--xm), var(--ym)) rotate(calc(var(--rot-mid) * .4)); animation-timing-function: var(--sand-ease); }
  100% { transform: translate(var(--x0), var(--y0)) rotate(0deg); }
}
.pour-out { animation: sand-drain var(--pour-ms) both; }
@keyframes sand-drain { 0%, 32% { transform: none; animation-timing-function: var(--sand-ease-move); } 64%, 100% { transform: translateY(var(--drop)); } }
.pour-in { animation: sand-fill var(--pour-ms) both; }
@keyframes sand-fill { 0%, 33% { transform: translateY(var(--drop)); animation-timing-function: var(--sand-ease); } 68%, 100% { transform: none; } }
.bottle-body.receiving { animation: bottle-receive var(--pour-ms) both; }
@keyframes bottle-receive { 0%, 33% { transform: none; animation-timing-function: var(--sand-ease); } 42% { transform: translateY(3px); animation-timing-function: var(--sand-ease-move); } 60%, 100% { transform: none; } }
.pour-stream { pointer-events: none; }
.stream-core { transform-box: fill-box; transform-origin: 50% 0; opacity: .9; animation: stream-core var(--pour-ms) both; }
@keyframes stream-core { 0%, 28% { transform: scaleY(0); opacity: .9; animation-timing-function: var(--sand-ease-fall); } 35%, 62% { transform: none; opacity: .9; } 70%, 100% { transform: translateY(var(--len)) scaleY(0); opacity: .9; } }
.stream-grain { opacity: 0; animation: grain-fall 260ms var(--sand-ease-fall) calc(var(--pour-ms) * .3 + var(--g) * 24ms) both; }
@keyframes grain-fall { 0% { opacity: 1; transform: none; } 90% { opacity: 1; } 100% { opacity: 0; transform: translateY(var(--len)); } }
.splash-grain { opacity: 0; animation: grain-splash 300ms var(--sand-ease) calc(var(--pour-ms) * .38 + var(--g) * 30ms) both; }
@keyframes grain-splash { 0% { opacity: 1; transform: none; } 100% { opacity: 0; transform: translate(var(--dx), -14px); } }

/* Level clear: bottles wave, confetti bursts, then the result card. */
.sand-stage.won .bottle-body { animation: bottle-hop var(--sand-slow) var(--sand-ease-pop) calc(var(--win-at) + var(--i, 0) * 40ms) both; }
.sand-stage.won .bottle-enter .bottle-body { animation-delay: calc(var(--win-at) + var(--i) * 40ms); }
@keyframes bottle-hop { 40% { transform: translateY(-16px); } 100% { transform: none; } }
.confetti-layer { position: fixed; inset: 0; overflow: hidden; pointer-events: none; z-index: 2; }
/* Confetti flies past the edges; the fixed, clipped layer keeps it from widening the page (which made iOS zoom out). */
.confetti { position: absolute; left: 50%; top: 36%; width: 0; height: 0; }
.confetti i { position: absolute; width: var(--w); height: 6px; border-radius: 2px; background: var(--c); opacity: 0;
  animation: confetti 1500ms calc(var(--win-at) + var(--d)) both; }
@keyframes confetti {
  0% { opacity: 1; transform: translate(0, 0) rotate(0deg) scale(.6); animation-timing-function: cubic-bezier(.1, .7, .3, 1); }
  35% { opacity: 1; transform: translate(var(--dx), var(--dy)) rotate(calc(var(--r) * .5)) scale(1); animation-timing-function: var(--sand-ease-fall); }
  100% { opacity: 0; transform: translate(calc(var(--dx) * 1.25), calc(var(--dy) + 340px)) rotate(var(--r)) scale(1); }
}
.sand-win { position: absolute; z-index: 3; touch-action: manipulation; inset: auto var(--s4) 22%; margin: auto; max-width: 22rem; display: grid; gap: var(--s3); justify-items: center; text-align: center;
  padding: var(--s8) var(--s6) var(--s6); border: 1px solid var(--line); border-radius: var(--radius-lg);
  background: linear-gradient(180deg, color-mix(in srgb, var(--sand-panel) 88%, var(--stage-lift) 12%), var(--sand-panel)); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px); box-shadow: 0 1.5rem 4rem var(--stage-shadow), inset 0 1px 0 color-mix(in srgb, var(--stage-film) 15%, transparent);
  animation: sand-win var(--sand-slow) var(--sand-ease) calc(var(--win-at) + 420ms) both; }
@keyframes sand-win { from { opacity: 0; transform: translateY(18px) scale(.96); } }
.sand-win h2 { margin: 0; font-size: var(--text-2xl); }
.sand-win p { margin: 0; color: var(--muted); }
.sand-win .eyebrow { color: var(--accent); }
.sand-win .win-world { color: color-mix(in srgb, var(--world-glow) 70%, var(--stage-lift)); font-weight: var(--weight-label); font-size: var(--text-sm); }
.sand-win button { width: 100%; justify-content: center; }
.win-stars { display: flex; gap: var(--s2); align-items: end; }
.win-stars .star { width: 2.75rem; height: 2.75rem; fill: color-mix(in srgb, var(--stage-film, var(--ink)) 12%, transparent); }
.win-stars .star:nth-child(2) { width: 3.4rem; height: 3.4rem; }
.win-stars .star.on { fill: var(--accent); filter: drop-shadow(0 0 10px color-mix(in srgb, var(--accent) 60%, transparent));
  animation: star-pop var(--sand-std) var(--sand-ease-pop) calc(var(--win-at) + 620ms + var(--s) * 130ms) both; }
@keyframes star-pop { from { opacity: 0; transform: scale(.4) rotate(-25deg); } }

.sand-controls { display: flex; justify-content: center; gap: var(--s3); flex-wrap: wrap; }
.sand-controls button { background: color-mix(in srgb, var(--stage-film) 7%, transparent); border-color: var(--line); }
.hint-button { position: relative; }
.hint-count { display: inline-grid; place-items: center; min-width: 1.5rem; height: 1.5rem; margin-left: var(--s2); padding: 0 var(--s1);
  border-radius: var(--pill); background: var(--accent); color: var(--surface); font-size: .75rem; font-weight: var(--weight-label); font-variant-numeric: tabular-nums; }
/* After a few restarts the next hint is free: the badge says so, with one gentle nudge. */
.hint-free .hint-count { background: var(--success); }
.hint-free { animation: hint-nudge 1.2s var(--sand-ease, ease) 2; }
@keyframes hint-nudge { 50% { transform: scale(1.06); } }
@media (prefers-reduced-motion: reduce) { .hint-free { animation: none; } }
/* Stuck on a phone, the Free badge and a friend's ask need room: the tools tighten into one row around the hint.
   At 320px no row of three fits every label either way, so the narrowest phones keep equal tools. */
@media (min-width: 321px) and (max-width: 767px) {
  .game-controls:has(> .hint-free, > .hint-ask) > button { padding-inline: var(--s2); }
  .game-controls:has(> .hint-free, > .hint-ask) > button:not(.hint-button, .hint-ask) { flex: 1 1 0; min-width: 0; }
  .game-controls:has(> .hint-free, > .hint-ask) > .hint-button { flex: none; }
}
/* Asking a friend for a hint takes a short row of its own under the tools. */
.game-controls:has(> .hint-ask) { flex-wrap: wrap; }
.game-controls > button.hint-ask { order: 1; flex: 1 0 100%; grid-column: 1 / -1; min-height: 2rem; padding-block: 0; font-size: var(--text-sm); }
/* On the shortest phones the row sits closer under them, leaving the board that much more room. */
@media (max-width: 767px) and (max-height: 600px) { .game-controls:has(> .hint-ask) { row-gap: var(--s1); } }

.sand-layout.zen .game-hud-title h1 { letter-spacing: .08em; }

.rank-track { display: flex; align-items: center; gap: var(--s3); }
.rank-track ol { list-style: none; margin: 0; padding: 0; display: flex; gap: 6px; }
.rank-track li { width: 22px; height: 6px; border-radius: var(--pill); background: color-mix(in srgb, var(--stage-film) 11%, transparent); transition: background var(--sand-std) var(--sand-ease); }
.rank-track li.done { background: color-mix(in srgb, var(--world-glow) 75%, var(--stage-lift) 25%); }
.rank-track p { margin: 0; font-size: var(--text-xs); color: var(--muted); }

.sand-tip { display: flex; align-items: center; gap: var(--s4); padding: var(--s3) var(--s4); border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--sand-panel) 80%, var(--stage-lift) 8%); border: 1px solid color-mix(in srgb, var(--world-glow) 45%, transparent);
  animation: sand-tip-in var(--sand-slow) var(--sand-ease) both; }
.sand-tip div { flex: 1; }
.sand-tip strong { color: var(--world-glow); }
.sand-tip p { margin: 2px 0 0; font-size: var(--text-sm); color: var(--muted); }
@keyframes sand-tip-in { from { opacity: 0; transform: translateY(-6px); } }

.sand-loading { min-height: 20rem; display: grid; place-content: center; justify-items: center; gap: var(--s3); color: var(--muted); }
.sand-loading p { margin: 0; }
.sand-hourglass { width: 28px; height: 40px; border: 2px solid color-mix(in srgb, var(--world-glow) 70%, var(--stage-lift)); border-radius: 6px;
  background: linear-gradient(180deg, transparent 50%, var(--world-glow) 50%) no-repeat; background-size: 100% 200%;
  animation: sand-hourglass 1.6s var(--sand-ease-move) infinite; }
@keyframes sand-hourglass { 0% { background-position: 0 0; transform: none; } 80% { background-position: 0 100%; transform: none; } 100% { background-position: 0 100%; transform: rotate(180deg); } }
.mystery-mark { font: 700 15px var(--font-sans, system-ui); fill: var(--shine); }

.win-coins { display: inline-flex; align-items: center; gap: var(--s2); font-weight: var(--weight-title); color: var(--accent) !important;
  animation: star-pop var(--sand-std) var(--sand-ease-pop) calc(var(--win-at) + 1100ms) both; }
.sand-coin .sand-coin-halo { fill: var(--shine); opacity: .9; }
.sand-coin .sand-coin-face { fill: var(--coin-face); stroke: var(--coin-edge); stroke-width: 2; }
.sand-coin .sand-coin-rim { fill: none; stroke: var(--coin-rim); stroke-width: 1.2; }
.block-coin { pointer-events: none; }
.block-coin .block-coin-halo { fill: var(--shine); opacity: .85; }
.block-coin .block-coin-face { fill: var(--coin-face); stroke: var(--coin-edge); stroke-width: 3; }
.block-coin .block-coin-rim { fill: none; stroke: var(--coin-rim); stroke-width: 2; }
.win-coin-sand { margin-top: 0; }
.win-rank { color: color-mix(in srgb, var(--world-glow) 70%, var(--stage-lift)) !important; font-weight: var(--weight-title); }


@media (hover: hover) and (pointer: fine) {
  .bottle:not(.selected):not(.complete):hover { transform: translateY(-4px); transition: transform var(--sand-std) var(--sand-ease); }
  .sand-controls button:not(:disabled):hover { background: color-mix(in srgb, var(--stage-film) 13%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
  .confetti-layer, .sparkle { display: none; }
}
@media (max-width: 767px) {
  .sand-board { max-height: var(--fit-h, calc(100dvh - 22rem)); }
  .sand-controls { flex-wrap: nowrap; gap: var(--s2); }
  .sand-controls button { padding-inline: var(--s4); }
}

/* A dead end the hint found: what happened, and the one tap that gets you out. */
.sand-nudge { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--s4); border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--sand-panel) 82%, var(--stage-lift) 8%); border: 1px solid color-mix(in srgb, var(--accent) 55%, transparent);
  animation: sand-tip-in var(--sand-slow) var(--sand-ease) both; }
.sand-nudge p { flex: 1; margin: 0; font-size: var(--text-sm); }
.sand-nudge button { flex: none; border-radius: var(--pill); }
@media (max-width: 479px) { .sand-nudge { flex-direction: column; align-items: stretch; text-align: center; } }

/* Out of hints: buy a bundle without leaving the board. */
.hint-shop { display: grid; gap: var(--s3); padding: var(--s3) var(--s4); border-radius: var(--radius-sm); background: var(--surface);
  border: 1px solid color-mix(in srgb, var(--accent) 55%, transparent); box-shadow: var(--shadow); }
.hint-shop p { margin: 0; font-size: var(--text-sm); }
.hint-shop p .caption { display: block; }
.hint-shop-actions { display: flex; flex-wrap: wrap; gap: var(--s2); }
.hint-shop-actions :is(button, .button) { border-radius: var(--pill); }
.hint-shop-price { display: inline-flex; align-items: center; gap: var(--s1); margin-left: var(--s2); opacity: .85; }

/* Friends (cross-game) */
.menu-badge { margin-left: auto; min-width: 1.5rem; padding: 0 var(--s2); border-radius: var(--pill); background: var(--accent); color: var(--on-accent); font-size: var(--text-xs); line-height: 1.5rem; text-align: center; }
.friends-layout { margin-bottom: var(--s8); }
.friend-add { display: grid; gap: var(--s2); }
.friend-add-row { display: flex; gap: var(--s2); }
.friend-add-row input { flex: 1; min-width: 0; }
.friend-invite { display: grid; gap: var(--s3); justify-items: start; padding-top: var(--s4); border-top: 1px solid var(--line); }
.friends-section { display: grid; gap: var(--s4); margin-bottom: var(--s8); }
.friends-section h2 { display: flex; align-items: center; gap: var(--s2); }
.friend-count { min-width: 1.75rem; padding: 0 var(--s2); border-radius: var(--pill); background: var(--elevated); color: var(--muted); font-size: var(--text-sm); line-height: 1.75rem; text-align: center; }
.friends-empty { padding: var(--s6); border: 1px dashed var(--line); border-radius: var(--radius); }
.friend-pending { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2); }
.friend-pending li { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); padding: var(--s3) var(--s4); border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); }
.friend-pending li > span:first-child { display: grid; min-width: 0; }
.friend-actions { display: flex; gap: var(--s2); flex-shrink: 0; }
.friend-grid { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 19rem), 1fr)); gap: var(--s4); }
.friend-card { display: grid; gap: var(--s2); align-content: start; padding: var(--s3); border: 1px solid var(--line); border-radius: var(--radius); background: linear-gradient(160deg, color-mix(in srgb, var(--pet, var(--sea)) 12%, var(--surface)), var(--surface) 55%); }
.friend-card-head { display: flex; align-items: center; gap: var(--s2); }
.friend-pet { display: grid; place-items: center; width: 2.75rem; height: 2.75rem; flex-shrink: 0; border-radius: var(--radius); background: color-mix(in srgb, var(--pet, var(--sea)) 16%, transparent); }
/* Their chosen background behind the pet, as on their player card. */
.friend-pet.sky-swatch.pet-habitat { width: 2.75rem; height: 2.75rem; margin: 0; border-radius: var(--radius); }
.friend-pet.pet-habitat .pet-avatar { position: relative; z-index: 3; }
.friend-initial { font-size: var(--text-xl); font-weight: var(--weight-title); color: var(--muted); }
.friend-name { display: grid; grid-template-columns: minmax(0, 1fr); min-width: 0; }
.friend-name strong { font-size: var(--text-md); line-height: 1.2; overflow: hidden; text-overflow: ellipsis; }
.friend-name small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.friend-name .friend-caption { display: flex; flex-wrap: wrap; column-gap: 0.3em; white-space: normal; overflow: visible; }
.friend-caption > span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.friend-caption > span:not(:last-child)::after { content: "\00a0·"; }
.friend-tags { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1); }
.friend-tags > ul { display: contents; }
.friend-games { list-style: none; margin: 0; padding: 0; }
.friend-games li { display: inline-flex; align-items: center; gap: var(--s1); padding: 2px var(--s2) 2px 3px; border: 1px solid var(--line); border-radius: var(--pill); font-size: var(--text-xs); color: var(--muted); }
.friend-games img { border-radius: .3rem; flex-shrink: 0; }
.friend-games-more { min-height: 0; padding: 2px var(--s2); border-radius: var(--pill); font-size: var(--text-xs); }
.friend-card-bar { display: flex; align-items: center; gap: var(--s1); }
.friend-card-bar:has(.friend-challenge, .friend-remove-confirm) { flex-wrap: wrap; }
.friend-card-bar > .friend-card-actions { flex: 1; min-width: 0; }
.friend-card-bar:has(.friend-challenge) > .friend-card-foot { display: none; }
.friend-card-foot { display: flex; align-items: center; gap: var(--s2); }
.friend-card-foot:has(.friend-remove-confirm) { flex-basis: 100%; }
.friend-remove-confirm { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.friend-remove-confirm .caption { flex-basis: 100%; }
.friend-card-foot button { min-height: 2rem; padding: var(--s1) var(--s3); font-size: var(--text-sm); }
.friend-remove { border-color: transparent; background: transparent; color: var(--muted); }
.friend-card-foot .friend-remove { padding: var(--s1); min-width: 2rem; }
.friend-remove:hover:not(:disabled) { color: var(--danger); }
.friend-name { flex: 1; }
.friend-favorite { align-self: start; display: grid; place-items: center; min-width: 2rem; min-height: 2rem; padding: var(--s1); border-color: transparent; background: transparent; color: var(--muted); }
.friend-favorite[aria-pressed="true"] { color: var(--accent); }
.friend-favorite[aria-pressed="true"] .ui-icon { fill: currentColor; }
.friend-list-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); flex-wrap: wrap; }
.friend-sort { display: inline-flex; align-items: center; gap: var(--s2); color: var(--muted); }
.friend-sort select { min-height: 2.25rem; font-size: var(--text-sm); }
@media (max-width: 40rem) {
  .friend-add-row { flex-direction: column; }
  .friend-pending li { flex-wrap: wrap; }
}
.friend-card-actions { display: flex; flex-wrap: wrap; gap: var(--s1); }
.friend-card-actions > button { flex: 1; min-height: 2rem; padding: var(--s1) var(--s2); font-size: var(--text-sm); }
.friend-card-actions .ui-icon, .inbox-item .ui-icon { width: 1.1rem; height: 1.1rem; }
.friend-challenge { display: flex; flex-wrap: wrap; gap: var(--s1); width: 100%; }
.friend-challenge-top { flex-basis: 100%; display: flex; align-items: center; gap: var(--s1); }
.friend-challenge button { min-height: 2rem; padding: var(--s1) var(--s2); font-size: var(--text-xs); }
.friend-challenge .friend-challenge-game { flex: 1 1 auto; gap: var(--s1); white-space: nowrap; }
.friend-challenge img { border-radius: .35rem; }
.friend-challenge .friend-challenge-close { flex: 0 0 auto; border-color: transparent; background: transparent; color: var(--muted); }

/* Inbox (cross-game) */
.inbox-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2); }
.inbox-item { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--s4); border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); }
.inbox-item > img { border-radius: .5rem; flex-shrink: 0; }
.inbox-item-body { display: grid; flex: 1; min-width: 0; gap: 2px; }
.inbox-item-body strong { overflow: hidden; text-overflow: ellipsis; }
.inbox-item .friend-actions button, .inbox-item .friend-actions a { min-height: 2.25rem; padding: var(--s1) var(--s4); font-size: var(--text-sm); }
.inbox-item .friend-actions .icon-button { flex: none; width: 2.25rem; height: 2.25rem; padding: 0; }
.inbox-gift-mark { display: grid; place-items: center; width: 2.5rem; height: 2.5rem; flex-shrink: 0; border-radius: .6rem; background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent); }
.inbox-outcome { font-weight: var(--weight-title); }
.inbox-outcome.won { color: var(--sea); }
.inbox-outcome.lost { color: var(--muted); }
.inbox-expiring { color: var(--error); }
.inbox-cap { font-size: var(--text-sm); color: var(--muted); font-weight: normal; margin-left: auto; }
.battle-result { display: grid; gap: var(--s3); justify-items: center; text-align: center; }
.battle-result .battle-title { margin: 0; font-size: var(--text-xl); line-height: 1.15; overflow-wrap: anywhere; }
.battle-result .eyebrow, .battle-result p { margin: 0; }
.battle-result .button { min-width: 12rem; }
.battle-score { display: grid; grid-template-columns: 1fr auto 1fr; gap: var(--s3); align-items: center; width: 100%; max-width: 22rem; }
.battle-score > span { display: grid; gap: 2px; padding: var(--s2) var(--s3); border-radius: var(--radius); background: color-mix(in srgb, currentColor 8%, transparent); min-width: 0; }
.battle-score > span small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.battle-score > span.caption { padding: 0; background: none; }
.battle-score strong { font-size: var(--text-xl); line-height: 1.1; }
/* Arena results read at a glance: the verdict takes the color, the winning side of the score lights up. */
.arena-outcome .battle-title { font-size: var(--text-2xl); }
.arena-outcome.is-won .eyebrow, .arena-outcome.is-won .battle-title { color: var(--sea); }
.arena-outcome.is-lost .eyebrow { color: var(--muted); }
.arena-outcome.is-pending .eyebrow { color: var(--accent); }
.arena-outcome.is-won .battle-score > span:first-child, .arena-outcome.is-lost .battle-score > span:last-child { background: color-mix(in srgb, var(--sea) 16%, transparent); box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--sea) 45%, transparent); }
.arena-outcome-actions { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s2); width: 100%; max-width: 22rem; }
.arena-outcome-actions .button { min-width: 0; }
.arena-outcome > a.caption { color: var(--muted); text-decoration: underline; text-underline-offset: 3px; }
/* Tidegrid's board has no overlay of its own, so its Arena result is a pop-up over the page. */
.arena-pop { position: fixed; inset: 0; z-index: 300; display: grid; place-items: center; padding: var(--s4); background: rgb(0 0 0 / .45); animation: fade-in .18s ease-out; }
.arena-pop-card { display: grid; gap: var(--s3); justify-items: center; width: min(26rem, 100%); max-height: calc(100dvh - 2 * var(--s4)); overflow: auto; box-shadow: 0 var(--s4) var(--s12) rgb(0 0 0 / .3); animation: result-arrives var(--normal) var(--ease-enter); }
.arena-pop-card .coin-reward { margin: 0; }
.arena-pop-card:focus { outline: none; }
/* Every game's Daily result: one fixed card that scrolls inside itself, so a tall result never runs off screen. */
.daily-pop { position: fixed; inset: 0; z-index: 300; display: grid; place-items: center; overflow: auto; overscroll-behavior: contain;
  padding: max(var(--s4), env(safe-area-inset-top)) var(--s4) max(var(--s4), env(safe-area-inset-bottom)); background: rgb(0 0 0 / .45);
  animation: daily-pop-in 260ms var(--ease-enter, ease-out) var(--pop-delay, 0ms) both; }
@keyframes daily-pop-in { from { opacity: 0; pointer-events: none; } to { opacity: 1; pointer-events: auto; } }
.daily-pop-card { display: grid; gap: var(--s3); justify-items: center; text-align: center; width: min(24rem, 100%); box-sizing: border-box;
  max-height: calc(100dvh - 2 * var(--s4)); overflow: auto; overscroll-behavior: contain; padding: var(--s6) var(--s4) var(--s4);
  box-shadow: 0 var(--s4) var(--s12) rgb(0 0 0 / .3); animation: result-arrives var(--normal) var(--ease-enter) var(--pop-delay, 0ms) both; }
.daily-pop-card:focus { outline: none; }
.daily-pop-card > * { margin: 0; max-width: 100%; }
.daily-pop-card h2 { font-size: var(--text-2xl); }
.daily-pop-score { color: var(--muted); font-variant-numeric: tabular-nums; }
/* The share signature: big enough to read as a picture, since this is what gets pasted into a chat. */
.daily-pop-signature { margin: .35rem 0 0; font-size: 1.35rem; line-height: 1.1; letter-spacing: .1em; }
.daily-pop-card .win-pet { margin: 0; width: 100%; box-sizing: border-box; }
.daily-pop-card .wheel-callout { margin: 0; width: 100%; box-sizing: border-box; text-align: left; }
/* A friend's shared Daily, on the how-to-play card a new player sees first. */
.coach-challenge { margin: 0 0 var(--s3); padding: var(--s2) var(--s3); border-radius: var(--radius, .75rem); font-weight: 600;
  background: color-mix(in srgb, var(--accent, currentColor) 12%, transparent); }
/* A friend's shared Daily: who won, and adding them. Guests with a streak or pet: keep it safe. */
.daily-pop-card :is(.daily-challenge-result, .daily-save-prompt, .daily-install) { display: grid; gap: var(--s2); justify-items: center; width: 100%; box-sizing: border-box;
  padding: var(--s3); border-radius: var(--radius, .75rem); background: color-mix(in srgb, var(--accent, currentColor) 10%, transparent); text-align: center; }
.daily-pop-card :is(.daily-challenge-result, .daily-save-prompt, .daily-install) p { margin: 0; }
/* After a win, a player on a streak: the app on their home screen. */
.daily-install-actions { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: var(--s2) var(--s4); }
.daily-install-quick { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 4px; font-size: var(--text-sm); }
.daily-install-quick svg { width: 1.1em; height: 1.1em; color: var(--accent); }
/* A guest's 5th, 15th… level: keeping it comes first, so the game's own buttons step back to plain ones. The card
   fades in after the pop-up and its button only takes taps a moment later, so a quick tap meant for Next can't land on
   it. A guest's pet to pick (WinPetPick) sits there too, and arrives the same way. */
.daily-pop-card > :is(.level-signup, .win-pet-pick) { animation: fade-in 200ms var(--ease) calc(var(--pop-delay, 0ms) + 450ms) both; }
.daily-pop-card > .level-signup > .button, .daily-pop-card > .win-pet-pick button { animation: signup-arm 1ms linear calc(var(--pop-delay, 0ms) + 900ms) both; }
@keyframes signup-arm { from { pointer-events: none; } to { pointer-events: auto; } }
.daily-pop-card > .level-signup ~ :is(button, .button).primary { background: var(--surface); border-color: var(--line); color: var(--ink); }
@media (hover: hover) and (pointer: fine) { .daily-pop-card > .level-signup ~ :is(button, .button).primary:hover { background: var(--elevated); } }
/* One row of three on the narrowest phone; outranks each game's full-width win buttons (e.g. .bus-win button). */
.win-pet-starters { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s2); width: 100%; }
.daily-pop-card .win-pet-starters .win-pet-starter { display: grid; justify-items: center; gap: 2px; width: 100%; min-width: 0; min-height: 0; padding: var(--s2) var(--s1); font-size: var(--text-sm); }
@media (hover: hover) and (pointer: fine) { .daily-pop-card .win-pet-starters .win-pet-starter:hover { background: var(--elevated); } }
/* Color Bus: a player 3-starring the first pack can jump to the second. */
.daily-pop-card .win-skip { font-size: var(--text-sm); font-weight: var(--weight-label); color: var(--sea); text-underline-offset: .2em; }
/* After a win: another game this device hasn't started (WinOffers). */
.daily-pop-card .win-suggest { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--s3); width: 100%; box-sizing: border-box;
  padding: var(--s3); border: 1px solid var(--line); border-radius: var(--radius, .75rem); color: var(--ink); text-align: left; text-decoration: none;
  transition: background-color var(--fast) var(--ease); }
.win-suggest img { width: 40px; height: 40px; border-radius: var(--radius-sm); }
.win-suggest-text { display: grid; gap: 2px; min-width: 0; }
.win-suggest-text .caption { line-height: 1.3; }
.win-suggest-go { display: inline-flex; align-items: center; font-weight: var(--weight-label); color: var(--sea); }
.win-suggest-go .ui-icon { width: 1.1em; height: 1.1em; }
@media (hover: hover) and (pointer: fine) { .daily-pop-card .win-suggest:hover { background: var(--elevated); } }
/* After a win on a computer that can't install the app (Firefox, Safari): the bookmark shortcut (WinBookmark). */
.win-bookmark kbd { padding: 0 .35em; border: 1px solid var(--line); border-bottom-width: 2px; border-radius: var(--radius-sm);
  background: var(--surface); font: inherit; font-weight: var(--weight-label); white-space: nowrap; }
/* After a win, a player on a streak in the installed app: one reminder at 7 p.m. (PushOffer). */
.daily-pop-card .daily-push { display: grid; gap: var(--s2); justify-items: center; width: 100%; box-sizing: border-box;
  padding: var(--s3); border-radius: var(--radius, .75rem); background: color-mix(in srgb, var(--accent, currentColor) 10%, transparent); text-align: center; }
.daily-pop-card .daily-push p { margin: 0; }
.daily-push-actions { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: var(--s2) var(--s4); }
/* You and your friends on today's Daily, best first. */
.daily-pop-card :is(.daily-friends-board, .daily-group-board) { display: grid; gap: var(--s2); width: 100%; box-sizing: border-box; margin: 0; text-align: center; }
.daily-pop-card :is(div.daily-friends-board, .daily-group-board) { padding: var(--s3); border-radius: var(--radius, .75rem); background: color-mix(in srgb, var(--accent, currentColor) 6%, transparent); }
:is(.daily-friends-board, .daily-group-board) p { margin: 0; }
:is(.daily-friends-board, .daily-group-board) ol { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s1); font-size: var(--text-sm); }
:is(.daily-friends-board, .daily-group-board) li { display: flex; justify-content: space-between; gap: var(--s3); }
:is(.daily-friends-board, .daily-group-board) li.you { font-weight: 700; }
.daily-pop-card .daily-rank { font-weight: 700; }
.daily-pop-card .daily-freeze { margin: 0; font-size: var(--text-sm); }
.daily-pop-card .daily-view { justify-self: center; font-size: var(--text-sm); color: var(--muted); }
/* While the board is on view, the way back floats above the phone tab bar. */
.daily-peek-back { position: fixed; z-index: 300; left: 50%; translate: -50% 0; bottom: calc(var(--nav-h, 4.5rem) + max(var(--s4), env(safe-area-inset-bottom)));
  box-shadow: 0 var(--s2) var(--s6) rgb(0 0 0 / .3); animation: fade-in 160ms var(--ease); }
@media (min-width: 48rem) { .daily-peek-back { bottom: max(var(--s6), env(safe-area-inset-bottom)); } }
@media (prefers-reduced-motion: reduce) { .daily-pop, .daily-pop-card, .daily-pop-card > :is(.level-signup, .win-pet-pick) { animation-duration: 1ms; } }
@media (max-width: 40rem) { .inbox-item { flex-wrap: wrap; } .inbox-item .friend-actions { width: 100%; } .inbox-item .friend-actions > * { flex: 1; } .inbox-item .friend-actions:has(> .icon-button:only-child) { width: auto; } .inbox-item .friend-actions > .icon-button { flex: none; } }

/* Header: bell, account menu and toasts. The bell and the account menu share one round shape. */
.bell, .account-menu { position: relative; flex-shrink: 0; }
.bell-button { position: relative; display: grid; place-items: center; width: var(--control); height: var(--control); min-height: 0; padding: 0; border: 1px solid var(--line); border-radius: 50%; background: var(--surface); color: var(--muted); -webkit-tap-highlight-color: transparent; }
.bell-button:hover, .bell-button.open { border-color: var(--accent); color: var(--ink); }
.bell-button:active { transform: scale(.94); }
.bell-button .ui-icon { width: 1.1rem; height: 1.1rem; }
.bell-button, .account-menu .account-link { position: relative; z-index: 1; }
.bell-count { position: absolute; top: -4px; right: -6px; min-width: 1.15rem; height: 1.15rem; padding: 0 .3rem; display: grid; place-items: center; border-radius: var(--pill); background: var(--error); color: var(--background); font-size: .68rem; font-weight: var(--weight-title); line-height: 1; box-shadow: 0 0 0 2px var(--background); font-variant-numeric: tabular-nums; animation: bell-count-in var(--normal) var(--ease-enter); }
@keyframes bell-count-in { from { transform: scale(.4); opacity: 0; } }
.bell-scrim { position: fixed; inset: 0; z-index: 302; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.bell-panel { position: absolute; z-index: 303; top: calc(100% + var(--s2)); right: 0; width: min(24rem, calc(100vw - 2 * var(--s4))); max-height: min(34rem, calc(100dvh - 7rem)); display: flex; flex-direction: column; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); box-shadow: var(--shadow), 0 1px 0 var(--line); transform-origin: top right; animation: menu-in var(--fast) var(--ease-enter); overflow: hidden; }
.bell-head { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--s3) var(--s3) var(--s4); border-bottom: 1px solid var(--line); }
.bell-head strong { flex: 1; font-size: var(--text-md); }
.bell-head-link { display: inline-flex; align-items: center; min-height: 1.75rem; font-size: var(--text-sm); font-weight: var(--weight-label); }
.bell-close, .bell-icon-button { display: grid; place-items: center; width: 2.25rem; height: 2.25rem; min-height: 0; padding: 0; border-radius: 50%; border-color: transparent; background: transparent; color: var(--muted); }
.bell-close:hover, .bell-icon-button:hover { background: var(--elevated); color: var(--ink); }
.bell-close .ui-icon, .bell-icon-button .ui-icon { width: 1rem; height: 1rem; }
.bell-close { display: none; }
.bell-body { overflow-y: auto; overscroll-behavior: contain; padding: var(--s1) var(--s2) var(--s2); }
.bell-label { display: flex; align-items: center; justify-content: space-between; margin: var(--s3) var(--s2) var(--s1); font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; font-weight: var(--weight-title); color: var(--muted); }
.bell-label-action { min-height: 0; padding: var(--s1) var(--s2); border: 0; background: transparent; color: var(--sea); font-size: var(--text-xs); letter-spacing: 0; text-transform: none; }
.bell-label-action:hover { background: var(--elevated); }
.bell-item { display: flex; align-items: center; gap: var(--s3); padding: var(--s2); border-radius: var(--radius-sm); }
.bell-item:hover { background: color-mix(in srgb, var(--elevated) 60%, transparent); }
.bell-avatar, .bell-mark { flex-shrink: 0; width: 2.25rem; height: 2.25rem; border-radius: 50%; }
.bell-avatar { display: grid; place-items: center; background: color-mix(in srgb, var(--sea) 16%, var(--surface)); color: var(--sea); font-weight: var(--weight-title); }
.bell-avatar.gift { background: color-mix(in srgb, var(--coin-face) 22%, var(--surface)); color: var(--warning); }
.bell-avatar .ui-icon { width: 1.1rem; height: 1.1rem; }
.bell-mark { border-radius: .6rem; }
.bell-text { flex: 1; min-width: 0; display: grid; font-size: var(--text-sm); line-height: 1.35; overflow-wrap: anywhere; }
.bell-text small { color: var(--muted); font-size: var(--text-xs); }
.bell-outcome.won { color: var(--sea); } .bell-outcome.lost { color: var(--muted); }
.bell-actions { display: flex; align-items: center; gap: var(--s1); flex-shrink: 0; }
.bell-actions > button:not(.bell-icon-button), .bell-actions > .button { min-height: 2.25rem; padding: var(--s1) var(--s3); font-size: var(--text-sm); border-radius: var(--pill); }
.bell-note, .bell-message { margin: var(--s2) var(--s3); color: var(--muted); font-size: var(--text-sm); }
.bell-message { margin: var(--s2) var(--s3) 0; padding: var(--s2) var(--s3); border-radius: var(--radius-sm); background: color-mix(in srgb, var(--sea) 10%, transparent); color: var(--ink); }
.bell-empty { display: grid; justify-items: center; gap: var(--s3); padding: var(--s8) var(--s4); text-align: center; }
.bell-empty p { margin: 0; }
.bell-empty-mark { display: grid; place-items: center; width: 3rem; height: 3rem; border-radius: 50%; background: var(--elevated); color: var(--muted); }
.bell-empty-mark .ui-icon { width: 1.4rem; height: 1.4rem; }
.bell-foot { border-top: 1px solid var(--line); }
.bell-foot a { display: flex; justify-content: center; gap: var(--s2); padding: var(--s3); font-size: var(--text-sm); font-weight: var(--weight-label); text-decoration: none; }
.bell-foot a:hover { background: var(--elevated); }
@media (max-width: 639px) {
  .bell-scrim { z-index: 320; background: rgb(0 0 0 / .35); animation: fade-in var(--fast) var(--ease-enter); }
  .bell-panel { position: fixed; z-index: 321; top: auto; left: 0; right: 0; bottom: 0; width: auto; max-height: 82dvh; border-radius: var(--radius) var(--radius) 0 0; border-bottom: 0; padding-bottom: env(safe-area-inset-bottom); animation: sheet-in var(--normal) var(--ease-enter); }
  .bell-close { display: grid; }
  .bell-item { padding: var(--s3) var(--s2); }
}
@keyframes sheet-in { from { transform: translateY(100%); } }

.account-link { gap: var(--s2); }
.account-pet { display: grid; place-items: center; width: 1.75rem; height: 1.75rem; margin: -2px -2px -2px -6px; border-radius: 50%; background: var(--elevated); overflow: hidden; }
.account-pet svg { width: 100%; height: 100%; }
.account-menu-panel { position: absolute; z-index: 303; top: calc(100% + var(--s2)); right: 0; width: min(17rem, calc(100vw - 2 * var(--s4))); display: grid; gap: var(--s1); padding: var(--s2); border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); box-shadow: var(--shadow), 0 1px 0 var(--line); transform-origin: top right; animation: menu-in var(--fast) var(--ease-enter); }
.account-menu-panel { max-height: calc(100dvh - var(--control) - var(--s16) - env(safe-area-inset-bottom)); overflow-y: auto; overscroll-behavior: contain; }
.account-menu-who { display: grid; gap: 2px; padding: var(--s2) var(--s3) var(--s3); border-bottom: 1px solid var(--line); }
.account-menu-who small { color: var(--muted); font-size: var(--text-xs); }
.account-menu-who .button { margin-top: var(--s2); }
.account-menu-links { position: static; display: grid; gap: 2px; padding: 0; border: 0; background: none; box-shadow: none; }
.account-menu-links a { display: flex; align-items: center; gap: var(--s3); min-height: var(--control); padding: var(--s2) var(--s3); border-radius: var(--radius-sm); color: var(--ink); font-size: var(--text-sm); font-weight: var(--weight-label); text-decoration: none; }
.account-menu-links a:hover, .account-menu-links a:focus-visible { background: var(--elevated); }
.account-menu-links .ui-icon, .account-menu-links img { display: block; width: 1.1rem; height: 1.1rem; color: var(--muted); border-radius: .3rem; }
.account-menu-appearance { display: grid; gap: var(--s2); padding: var(--s3); border-top: 1px solid var(--line); font-size: var(--text-xs); font-weight: var(--weight-title); color: var(--muted); letter-spacing: var(--tracking-label); text-transform: uppercase; }
.segmented { display: grid; grid-template-columns: repeat(3, 1fr); padding: 3px; border-radius: var(--pill); background: var(--elevated); }
.segmented button { min-height: 2rem; padding: 0 var(--s2); border: 0; border-radius: var(--pill); background: transparent; color: var(--muted); font-size: var(--text-sm); letter-spacing: 0; text-transform: none; }
.segmented button.on { background: var(--surface); color: var(--ink); box-shadow: 0 1px 2px rgb(0 0 0 / .12); }

.toast-host { position: fixed; z-index: 310; top: calc(var(--s16) + var(--s4)); right: var(--s4); display: grid; gap: var(--s2); width: min(22rem, calc(100vw - 2 * var(--s4))); pointer-events: none; }
.toast { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) var(--s2) var(--s2) var(--s3); border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); box-shadow: var(--shadow); font-size: var(--text-sm); pointer-events: auto; animation: toast-in var(--normal) var(--ease-enter); }
@keyframes toast-in { from { opacity: 0; transform: translateY(-8px) scale(.98); } }
.toast-mark { width: 1.75rem; height: 1.75rem; border-radius: .45rem; flex-shrink: 0; }
.toast-icon { display: grid; place-items: center; width: 1.75rem; height: 1.75rem; flex-shrink: 0; border-radius: 50%; background: color-mix(in srgb, var(--sea) 14%, var(--surface)); color: var(--sea); }
.toast-icon .ui-icon { width: 1rem; height: 1rem; }
.toast-text { flex: 1; min-width: 0; }
.toast-action { font-weight: var(--weight-title); white-space: nowrap; padding: var(--s1) var(--s2); }
.toast-close { display: grid; place-items: center; width: 2rem; height: 2rem; min-height: 0; padding: 0; border: 0; border-radius: 50%; background: transparent; color: var(--muted); }
.toast-close .ui-icon { width: .9rem; height: .9rem; }
@media (max-width: 767px) {
  .toast-host { top: auto; left: var(--s2); right: var(--s2); width: auto; bottom: max(var(--s2), env(safe-area-inset-bottom)); }
  /* Clear the fixed game nav bar, which only game pages have. */
  body:has(.masthead > nav) .toast-host { bottom: calc(var(--s16) + var(--s8) + env(safe-area-inset-bottom)); }
  @keyframes toast-in { from { opacity: 0; transform: translateY(8px) scale(.98); } }
}

/* Social: Activity and Friends share one heading and a pair of tabs. */
.social-heading { margin-bottom: var(--s3); }
.social-tabs { display: inline-flex; gap: var(--s1); padding: var(--s1); margin-bottom: var(--s4); border: 1px solid var(--line); border-radius: var(--pill); background: var(--surface); }
.social-tabs a { display: inline-flex; align-items: center; gap: var(--s2); min-height: var(--control); padding: var(--s2) var(--s4); border-radius: var(--pill); color: var(--muted); font-size: var(--text-sm); font-weight: var(--weight-label); text-decoration: none; }
.social-tabs a:hover { color: var(--ink); }
.social-tabs a.active { background: var(--elevated); color: var(--accent); }
.social-callout { display: flex; align-items: center; gap: var(--s3); margin: var(--s6) 0 0; padding: var(--s3) var(--s4); border: 1px solid color-mix(in srgb, var(--sea) 40%, var(--line)); border-radius: var(--radius); background: color-mix(in srgb, var(--sea) 8%, var(--surface)); color: var(--ink); text-decoration: none; font-size: var(--text-sm); }
.social-callout > span:first-of-type { flex: 1; }
.social-callout .ui-icon { width: 1.1rem; height: 1.1rem; color: var(--sea); }
.social-callout:hover { border-color: var(--sea); }
button.social-callout.gift-new { width: 100%; margin: 0 0 var(--s3); text-align: left; font: inherit; font-size: var(--text-sm); cursor: pointer; }
.bell-panel:focus { outline: none; }

/* Header: "Get the app" and bug report buttons share the bell's round shape. */
.install-button, .bug-button { position: relative; display: inline-flex; align-items: center; justify-content: center; gap: var(--s2); flex-shrink: 0; height: var(--control); min-width: var(--control); min-height: 0; padding: 0; border: 1px solid var(--line); border-radius: var(--pill); background: var(--surface); color: var(--muted); -webkit-tap-highlight-color: transparent; }
.install-button { padding: 0 var(--s3); color: var(--ink); font-size: var(--text-sm); font-weight: var(--weight-label); }
.install-button:hover, .bug-button:hover, .bug-button.open { border-color: var(--accent); color: var(--ink); }
.install-button:active, .bug-button:active { transform: scale(.94); }
.install-button .ui-icon, .bug-button .ui-icon { width: 1.1rem; height: 1.1rem; }
/* Admins only: a gold sparkle to the sandbox, so it never passes for a player button. */
.admin-button { color: var(--warning); border-color: color-mix(in srgb, var(--coin-face) 70%, transparent); background: color-mix(in srgb, var(--coin-face) 22%, var(--surface)); }
.admin-button:hover { border-color: var(--coin-face); }
.quick-play { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 55%, var(--line)); background: color-mix(in srgb, var(--accent) 14%, var(--surface)); }
.quick-play .ui-icon { fill: currentColor; }
@media (max-width: 1023px) { .install-button { padding: 0; width: var(--control); } .install-button-label { display: none; } }
@media (max-width: 639px) { .install-button { display: none; } }
/* Phones: the game's mark stands in for its name so every header button fits. */
@media (max-width: 430px) { .masthead .game-switcher .brand-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } }

/* Shared modal sheet: centered card on wide screens, bottom sheet on phones. */
.sheet-scrim { position: fixed; inset: 0; z-index: 330; background: rgb(0 0 0 / .4); animation: fade-in var(--fast) var(--ease-enter); }
.app-sheet { position: fixed; z-index: 331; top: 50%; left: 50%; transform: translate(-50%, -50%); width: min(28rem, calc(100vw - 2 * var(--s4))); max-height: calc(100dvh - 4rem); overflow-y: auto; overscroll-behavior: contain; display: grid; gap: var(--s4); padding: var(--s5, 1.25rem); border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); color: var(--ink); box-shadow: var(--shadow); text-align: left; }
.app-sheet:focus { outline: none; }
.app-sheet h2 { margin: 0; font-size: var(--text-lg, 1.2rem); }
.app-sheet-head { display: flex; align-items: center; gap: var(--s3); }
.app-sheet-head > span:nth-child(2) { flex: 1; display: grid; gap: 2px; }
.app-sheet-head small { color: var(--muted); font-size: var(--text-sm); line-height: 1.35; }
.app-sheet-head img { border-radius: .7rem; flex-shrink: 0; }
@media (max-width: 639px) {
  .app-sheet { top: auto; bottom: 0; left: 0; right: 0; transform: none; width: auto; max-height: 88dvh; border-radius: var(--radius) var(--radius) 0 0; border-bottom: 0; padding-bottom: calc(var(--s5, 1.25rem) + env(safe-area-inset-bottom)); animation: sheet-in var(--normal) var(--ease-enter); }
}

/* "Want the app?" steps. */
.install-tabs { grid-template-columns: repeat(2, 1fr); }
.install-steps { display: grid; gap: var(--s3); margin: 0; padding: 0; list-style: none; counter-reset: step; }
.install-steps li { display: flex; align-items: flex-start; gap: var(--s3); counter-increment: step; }
.install-steps li > span:last-child { display: grid; gap: 2px; font-size: var(--text-sm); line-height: 1.4; }
.install-steps li > span:last-child strong::before { content: counter(step) ". "; color: var(--sea); }
.install-steps small { color: var(--muted); }
.install-step-icon { display: grid; place-items: center; width: 2.25rem; height: 2.25rem; flex-shrink: 0; border-radius: .65rem; background: color-mix(in srgb, var(--sea) 14%, var(--surface)); color: var(--sea); }
.install-step-icon .ui-icon { width: 1.15rem; height: 1.15rem; }
/* The friend picker for favors: who gets a look, or who's asked for a hint. Most recently active first. */
.friend-pick-list { display: grid; gap: var(--s2); margin: 0; padding: 0; list-style: none; }
.friend-pick-list li { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) var(--s3); border: 1px solid var(--line); border-radius: var(--radius); }
.friend-pick-list .friend-name strong { white-space: nowrap; }
.friend-pick-list button { flex: none; min-height: 2.25rem; padding: var(--s1) var(--s4); font-size: var(--text-sm); }
.friend-pick-done { display: flex; align-items: center; gap: var(--s2); margin: 0; color: var(--success); font-weight: var(--weight-label); }
.friend-pick-done .ui-icon { flex: none; width: 1.25rem; height: 1.25rem; }
.friend-pick-error { margin: 0; color: var(--error); font-size: var(--text-sm); }
.bell-item .look-preview { width: 2.25rem; height: 2.25rem; }
.install-note { display: flex; gap: var(--s2); margin: 0; padding: var(--s2) var(--s3); border-radius: var(--radius-sm); background: var(--elevated); font-size: var(--text-sm); line-height: 1.4; }
.install-note .ui-icon { width: 1rem; height: 1rem; flex-shrink: 0; margin-top: 2px; color: var(--sea); }
.install-now { width: 100%; }
.install-or, .install-foot { margin: 0; text-align: center; }
.install-banner { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--s2) var(--s3); margin: var(--s3) 0 0; padding: var(--s3); border: 1px solid color-mix(in srgb, var(--sea) 40%, var(--line)); border-radius: var(--radius); background: color-mix(in srgb, var(--sea) 8%, var(--surface)); }
.install-banner img { border-radius: .6rem; }
.install-banner > span { min-width: 0; display: grid; gap: 2px; font-size: var(--text-sm); line-height: 1.35; }
.install-banner small { color: var(--muted); }
.install-banner .primary { grid-column: 1 / -1; grid-row: 2; min-height: 2.5rem; padding: var(--s1) var(--s3); font-size: var(--text-sm); border-radius: var(--pill); }
.install-banner .bell-icon-button { grid-column: 3; grid-row: 1; }

/* Bug report form. */
.bug-kind { grid-template-columns: repeat(2, 1fr); }
.bug-form { display: grid; gap: var(--s3); }
.bug-form label { display: grid; gap: var(--s1); font-size: var(--text-sm); font-weight: var(--weight-label); }
.bug-form input, .bug-form textarea { width: 100%; font: inherit; font-size: 16px; font-weight: normal; }
.bug-form textarea { resize: vertical; min-height: 6rem; }
.bug-form .caption { margin: 0; }
.bug-error { margin: 0; color: var(--error); font-size: var(--text-sm); }
@media (max-width: 374px) {
  .header-actions { --control: 2.75rem; gap: 2px; }
  .header-actions .account-link { width: var(--control); height: var(--control); min-height: 0; padding: 0; justify-content: center; }
  .header-actions .coin-chip { height: var(--control); min-height: 0; padding: 0 var(--s1); }
}

/* Discord Activity: today's Daily in every game. */
.daily-picker { display: grid; gap: var(--s3); margin: 0; padding: 0; list-style: none; }
.daily-pick { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--s4); padding: var(--s4); border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--surface); color: var(--ink); text-decoration: none; transition: border-color var(--fast) var(--ease), transform var(--fast) var(--ease); }
.daily-pick:hover { border-color: var(--sea); }
.daily-pick:active { transform: translateY(1px); }
.daily-pick img { border-radius: var(--radius); }
.daily-pick-body { display: grid; gap: var(--s1); min-width: 0; }
.daily-pick-body strong { font-size: var(--text-lg); }
.daily-pick-state { min-width: 5.5rem; padding: var(--s2) var(--s3); border-radius: var(--pill); background: var(--accent); color: var(--on-accent); font-weight: 600; text-align: center; }
.daily-pick-state.done { min-width: 0; width: 2.5rem; height: 2.5rem; padding: 0; display: grid; place-items: center; background: var(--elevated); color: var(--sea); }
.daily-pick.done { background: var(--background); }
.daily-picker-note { margin-top: var(--s4); text-align: center; }

/* Player profile (/u/name): one hero band, then a tile per game. */
.profile-crumb { display: flex; align-items: center; gap: var(--s2); margin: 0 0 var(--s3); font-size: var(--text-sm); color: var(--muted); min-width: 0; }
.profile-crumb a { display: inline-flex; align-items: center; gap: var(--s1); min-height: 2.75rem; font-weight: var(--weight-label); }
.profile-crumb [aria-current] { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Someone else's profile leads with their trading card: the pet large on its backdrop. */
.profile-top { display: grid; gap: var(--s4); }
.profile-main { min-width: 0; }
.profile-card { justify-self: center; width: 100%; max-width: 20rem; }
.profile-card .trading-card { width: 100%; }
@media (min-width: 760px) {
  .profile-top.with-card { grid-template-columns: minmax(15rem, 19rem) minmax(0, 1fr); align-items: start; gap: var(--s6); }
  .profile-top.with-card .profile-card { position: sticky; top: var(--s4); }
}
@media (min-width: 760px) and (max-width: 1099px) {
  .profile-top.with-card .profile-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.profile-hero { display: grid; gap: var(--s4); padding: var(--s6); border-radius: var(--radius-lg); border: 1px solid var(--line);
  background: linear-gradient(135deg, color-mix(in srgb, var(--pet, var(--sea)) 16%, var(--surface)), var(--surface) 60%); }
.profile-who { display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap; }
.profile-pet { position: relative; flex-shrink: 0; display: grid; place-items: center; width: 88px; height: 88px; border-radius: 50%;
  background: color-mix(in srgb, var(--pet, var(--sea)) 22%, var(--surface)); }
.profile-pet.empty svg { width: 40px; height: 40px; color: var(--muted); }
.profile-pet-level { position: absolute; right: -2px; bottom: -2px; min-width: 1.6rem; height: 1.6rem; padding: 0 var(--s1); display: grid; place-items: center;
  border-radius: var(--pill); background: var(--ink); color: var(--surface); font-size: var(--text-xs); font-weight: var(--weight-title); border: 2px solid var(--surface); }
.profile-name { display: grid; gap: 2px; min-width: 0; flex: 1; }
.profile-name .eyebrow { margin: 0; }
.profile-name h1 { margin: 0; font-size: var(--text-xl); line-height: var(--leading-title); letter-spacing: var(--tracking-title); overflow-wrap: anywhere; }
.profile-name .caption { margin: 0; }
.profile-actions { display: flex; gap: var(--s2); flex-wrap: wrap; align-items: center; }
.profile-actions .caption { margin: 0; }
.profile-kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s2); margin: 0; }
.profile-kpis > div { padding: var(--s3); border-radius: var(--radius-sm); background: color-mix(in srgb, var(--surface) 70%, transparent); border: 1px solid var(--line); min-width: 0; }
.profile-kpis dt { font-size: var(--text-xs); color: var(--muted); font-weight: var(--weight-label); }
.profile-kpis dd { margin: 2px 0 0; font-size: var(--text-lg); font-weight: var(--weight-title); font-variant-numeric: tabular-nums; line-height: 1.2;
  display: grid; overflow-wrap: anywhere; }
.profile-kpis small { font-size: var(--text-xs); font-weight: var(--weight-body); color: var(--muted); }
.profile-hero .showcase { margin: 0; }
.profile-hero > .caption { margin: 0; }
.profile-missing { font-size: var(--text-xl); }

.profile-section { margin-top: var(--s8); display: grid; gap: var(--s3); }
.profile-section h2 { margin: 0; font-size: var(--text-lg); }
.profile-section-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s2) var(--s3); }
.profile-section-head .caption { font-weight: var(--weight-body); }
.profile-kpi-link { position: relative; }
.profile-kpi-link:hover, .profile-kpi-link:focus-within { border-color: var(--accent); }
.profile-kpi-link a { display: grid; color: inherit; text-decoration: none; }
.profile-kpi-link a::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
.profile-kpi-link dt::after { content: " →"; }
.profile-games { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); }
.profile-game { display: grid; gap: var(--s3); align-content: start; padding: var(--s4); border-radius: var(--radius); background: var(--surface); border: 1px solid var(--line);
  scroll-margin-top: var(--s16); }
.profile-game header { display: flex; align-items: center; gap: var(--s3); }
.profile-game header img { border-radius: .6rem; flex-shrink: 0; }
.profile-game header div { flex: 1; min-width: 0; }
.profile-game h3 { margin: 0; font-size: var(--text-md); }
.profile-game header .caption { margin: 0; }
.profile-game header .button { min-height: 2.25rem; padding-block: 0; }
.profile-bar { height: 6px; border-radius: var(--pill); background: var(--elevated); overflow: hidden; }
.profile-bar span { display: block; height: 100%; background: var(--sea); transform-origin: left; transition: transform var(--slow) var(--ease-enter); }
.profile-game dl { margin: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(4.5rem, 1fr)); gap: var(--s2); }
.profile-game dt { font-size: var(--text-xs); color: var(--muted); }
.profile-game dd { margin: 0; font-weight: var(--weight-label); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.profile-game dd small { display: block; font-size: var(--text-xs); font-weight: var(--weight-body); color: var(--muted); }
.profile-preview-note { margin: 0; padding: var(--s2) var(--s3); border-radius: var(--radius); border: 1px dashed var(--line); font-size: var(--text-sm); color: var(--muted); }
.profile-more { font-size: var(--text-sm); font-weight: var(--weight-label); justify-self: start; }
.profile-game:target { border-color: var(--sea); box-shadow: 0 0 0 2px color-mix(in srgb, var(--sea) 30%, transparent); }
@media (max-width: 640px) {
  .profile-hero { padding: var(--s4); }
  .profile-actions { width: 100%; }
  .profile-actions .button { flex: 1; }
  .profile-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Invite welcome (signed-out visitor from a friend's link) and invite panel */
.invite-welcome { display: grid; grid-template-columns: auto 1fr; gap: var(--s6); align-items: center; padding: var(--s6); border-radius: var(--radius-lg);
  border: 1px solid var(--line); background: linear-gradient(135deg, color-mix(in srgb, var(--pet, var(--sea)) 14%, var(--surface)), var(--surface) 65%); }
/* The tint can be any pet colour, so the small print leans a little toward ink. */
.invite-welcome .caption { color: color-mix(in srgb, var(--muted) 85%, var(--ink)); }
.invite-welcome-pet { display: grid; place-items: center; width: 144px; height: 144px; border-radius: 50%;
  background: color-mix(in srgb, var(--pet, var(--sea)) 24%, var(--surface)); }
.invite-welcome-pet .friend-initial { font-size: var(--text-xl); }
.invite-welcome-copy { display: grid; gap: var(--s2); min-width: 0; }
.invite-welcome-copy > * { margin: 0; }
.invite-welcome-copy h2 { font-size: var(--text-xl); line-height: var(--leading-title); letter-spacing: var(--tracking-title); overflow-wrap: anywhere; }
.invite-challenge { justify-self: start; padding: var(--s1) var(--s3); border-radius: var(--pill); background: color-mix(in srgb, var(--pet, #ebc18b) 22%, transparent); }
.invite-welcome-actions { display: flex; gap: var(--s2); flex-wrap: wrap; margin-top: var(--s2); }
.invite-offer { margin: 0; }
.invite-actions { display: flex; gap: var(--s2); flex-wrap: wrap; }
.invite-share { display: grid; gap: var(--s2); margin-bottom: var(--s4); }
.invite-share > * { margin: 0; }
.invite-choices { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--s3); }
.invite-choice { display: grid; justify-items: start; align-content: start; gap: var(--s1); padding: var(--s3) var(--s4); text-align: left; }
.invite-choice > span { display: inline-flex; align-items: center; gap: var(--s2); }
.invite-choice small { font-weight: normal; opacity: .85; }
.invite-qr { margin: 0; display: grid; gap: var(--s2); justify-items: start; }
.invite-qr svg { width: 200px; height: 200px; border-radius: var(--radius); box-shadow: 0 0 0 1px var(--line); }
.invite-milestones { display: grid; gap: var(--s2); width: 100%; }
.invite-milestones > p { margin: 0; }
.invite-milestones ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2); }
.invite-milestones li { display: grid; grid-template-columns: auto 1fr; column-gap: var(--s3); row-gap: var(--s1); align-items: center;
  padding: var(--s2) var(--s3); border-radius: var(--radius); border: 1px solid var(--line); }
.invite-milestones li > span:nth-child(2) { display: grid; }
.invite-gear { grid-row: span 2; display: grid; }
.invite-milestones li:not(.earned) .invite-gear { opacity: .45; filter: grayscale(1); }
.invite-bar { grid-column: 2; height: 4px; border-radius: var(--pill); background: var(--line); overflow: hidden; }
.invite-bar i { display: block; height: 100%; background: var(--sea); border-radius: inherit; }
.invite-milestones li.earned .invite-bar i { background: var(--sun, var(--sea)); }
@media (max-width: 560px) {
  .invite-welcome { grid-template-columns: 1fr; justify-items: center; text-align: center; padding: var(--s6) var(--s4); gap: var(--s4); }
  .invite-welcome-actions { justify-content: center; }
  .invite-welcome-actions .button { flex: 1 1 100%; }
}

/* The narrowest phones: the title, pet and switches share one row, so everything gives a little. */
@media (max-width: 360px) {
  .sand-controls button { flex: 1 1 0; min-width: 0; justify-content: center; padding-inline: var(--s2); }
}

/* Live Arena: the race bar beside the board, the countdown and the search pulse. */
.live-rival { display: grid; gap: var(--s1); width: 100%; }
.live-lane { display: grid; grid-template-columns: 5.5rem 1fr; align-items: center; gap: var(--s2); }
.live-rival.points .live-lane { grid-template-columns: 5.5rem 1fr 4.5rem; }
/* In a game HUD (Swarm) the race takes its own compact row under the stats. */
.game-hud-stats > .live-rival { flex-basis: 100%; gap: 2px; }
.game-hud-stats > .live-rival p { min-height: 0; }
.game-hud-stats > .live-rival p:empty { display: none; }
.live-score { font-variant-numeric: tabular-nums; font-weight: 700; text-align: end; }
.live-lane .caption { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.live-track { height: .5rem; border-radius: 999px; background: var(--line); overflow: hidden; }
.live-track > span { display: block; height: 100%; border-radius: inherit; background: var(--accent); transition: width .3s ease-out; }
.live-lane.rival .live-track > span { background: var(--muted); }
.live-rival p { margin: 0; min-height: 1.2em; }
.live-count { font-variant-numeric: tabular-nums; }
.live-search { height: .25rem; border-radius: 999px; background: var(--line); overflow: hidden; }
.live-search > span { display: block; width: 30%; height: 100%; background: var(--accent); animation: live-search 1.4s ease-in-out infinite alternate; }
@keyframes live-search { from { transform: translateX(-10%); } to { transform: translateX(240%); } }
@media (prefers-reduced-motion: reduce) { .live-search > span, .live-track > span { animation: none; transition: none; } }
.friend-challenge .friend-challenge-mode { display: flex; flex: 1; }
.friend-challenge .friend-challenge-mode { padding: 2px; }
.friend-challenge .friend-challenge-mode button { flex: 1 1 0; min-height: 1.75rem; padding: 0 var(--s2); font-size: var(--text-xs); }
.friend-challenge .friend-challenge-close { min-height: 1.75rem; padding: 0 var(--s1); }

/* Board overlays that became result pop-ups sit in the pop-up card, not over the board. */
.daily-pop-card:is(.sand-win, .flow-win, .bus-win) { position: relative; inset: auto; z-index: auto; min-height: 0; margin: 0; max-width: none; width: min(24rem, 100%); transform: none;
  animation: result-arrives var(--normal) var(--ease-enter) var(--pop-delay, 0ms) both; }
.daily-pop-card.bus-win { background: var(--surface); backdrop-filter: none; }
.game-pop .daily-pop-card > :is(button, .button) { width: 100%; justify-content: center; }
.game-pop-best { margin: 4px 0 -2px; text-align: center; }
/* After an Endless sitting or a finished run: dare a friend to beat it. */
.daily-pop-card .endless-challenge { display: grid; gap: var(--s2); width: 100%; }
.daily-pop-card .endless-challenge > button { width: 100%; justify-content: center; }
.daily-pop-card .endless-challenge p { margin: 0; text-align: center; }
.daily-pop-card .level-challenge p { text-wrap: balance; }
.game-hud-stats > :is(.coin-bonus, .game-hud-toggle) ~ .game-hud-end { margin-left: 0; }
.friend-card-shell { list-style: none; min-width: 0; }
.friend-card-shell .friend-card { height: 100%; }
.friend-self { display: grid; gap: var(--s2); margin-top: var(--s5, 1.25rem); max-width: 30rem; }
.friend-self-title { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s2); margin: 0; font-size: var(--text-md); }
.friend-self-title small { font-weight: var(--weight-body, 400); }
.friend-trophies .keepsake-chip { min-height: 0; min-width: 0; padding: 2px; gap: 0; border-radius: 50%; font-size: var(--text-xs); }
.friend-trophies .keepsake-chip .trophy-badge { margin-left: 0; }
.friend-add-plus { display: grid; place-items: center; width: 2.25rem; height: 2.25rem; border-radius: 50%; background: transparent; color: var(--sea); }
.friend-add-plus:hover { background: var(--elevated); }
.friend-add-plus .ui-icon { width: 1.35rem; height: 1.35rem; }
.inbox-head-action { margin-left: auto; min-height: 0; padding: var(--s1) var(--s2); border: 0; background: transparent; color: var(--sea); font-size: var(--text-sm); font-weight: normal; letter-spacing: 0; text-transform: none; }
.inbox-head-action:hover { background: var(--elevated); }

/* Mahjong Learn glossary terms: dotted-underlined words that open a centered definition card. */
.mj-term-wrap { display: inline; }
.mj-term { display: inline; min-height: 0; padding: 0; border: 0; border-radius: 0; background: none; color: inherit; font: inherit; text-decoration: underline dotted; text-decoration-thickness: 2px; text-underline-offset: .2em; text-decoration-color: var(--accent); cursor: help; }
.mj-term:hover, .mj-term[aria-expanded="true"] { background: none; color: inherit; text-decoration-style: solid; }
.mj-term-scrim { position: fixed; inset: 0; z-index: 340; background: rgb(0 0 0 / .25); animation: fade-in var(--fast) var(--ease-enter); }
.mj-term-pop { position: fixed; z-index: 341; top: 50%; left: 50%; transform: translate(-50%, -50%); display: block; width: min(22rem, calc(100vw - 2 * var(--s4))); padding: var(--s4) calc(var(--s4) + 2.25rem) var(--s4) var(--s4); border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface); color: var(--ink); box-shadow: 0 12px 32px rgb(0 0 0 / .25); font-size: var(--text-md); font-weight: var(--weight-body); letter-spacing: normal; line-height: 1.45; text-align: left; animation: fade-in var(--fast) var(--ease-enter); }
.mj-term-pop b { display: block; margin-bottom: var(--s1); }
.mj-term-close { position: absolute; top: var(--s2); right: var(--s2); width: 2.25rem; height: 2.25rem; }
.arena-my-card { margin-top: var(--s6); }

/* Friends leaderboards (today's Daily or Endless), and friends' boards on the Friends page. */
.leaderboard-modes { display: grid; grid-template-columns: 1fr 1fr; gap: 2px; padding: 2px; border-radius: 999px;
  background: color-mix(in srgb, currentColor 8%, transparent); }
.leaderboard-modes a { text-align: center; padding: var(--s1) var(--s3); border-radius: 999px; color: inherit; text-decoration: none;
  font-size: var(--text-sm); font-weight: 600; }
.leaderboard-modes a.active { background: var(--surface, #fff); box-shadow: 0 1px 2px rgb(0 0 0 / .12); }
.leaderboard-tabs { display: flex; gap: var(--s2); overflow-x: auto; padding-bottom: var(--s1); scrollbar-width: none; }
.leaderboard-tabs a { display: inline-flex; align-items: center; gap: var(--s2); flex: none; padding: var(--s1) var(--s3); border-radius: 999px;
  border: 1px solid var(--line, rgb(0 0 0 / .12)); color: inherit; text-decoration: none; font-size: var(--text-sm); font-weight: 600; }
.leaderboard-tabs a.active { background: color-mix(in srgb, var(--accent, currentColor) 14%, transparent); border-color: transparent; }
.leaderboard-tabs img { width: 1.5rem; height: 1.5rem; border-radius: .35rem; }
.leaderboard-rows { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s1); }
.leaderboard-rows li { display: grid; grid-template-columns: 2rem 1fr auto; align-items: center; gap: var(--s2); padding: var(--s2) var(--s3);
  border-radius: var(--radius, .75rem); background: color-mix(in srgb, var(--accent, currentColor) 5%, transparent); }
.leaderboard-rows li:nth-child(-n+3) .leaderboard-rank { font-weight: 800; color: var(--accent, currentColor); }
.leaderboard-rows a { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.leaderboard-score { font-variant-numeric: tabular-nums; font-weight: 600; }
.leaderboard-day { color: var(--muted); font-weight: 400; font-size: var(--text-sm); white-space: nowrap; }
/* Group boards: one card per chat the player's Daily links went to. */
.leaderboard-group { display: grid; gap: var(--s2); padding: var(--s3); border-radius: var(--radius, .75rem); border: 1px solid var(--line, rgb(0 0 0 / .12)); }
.leaderboard-group :is(h3, p) { margin: 0; }
.leaderboard-group-actions { display: flex; flex-wrap: wrap; gap: var(--s2); }
.leaderboard-group-manage { display: grid; gap: var(--s1); margin: 0; padding: 0; list-style: none; }
.leaderboard-group-manage li { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); min-height: 2.75rem; }
.leaderboard-group-manage li > span { flex: 1 1 8rem; overflow-wrap: anywhere; }
/* Friends' Dailies: a header that collapses the list, then one compact row per game. */
.friends-today { gap: var(--s2); }
.friends-today h2 { margin: 0; }
.friends-today-toggle { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 0 var(--s2); width: 100%; min-height: 2.75rem; padding: 0; border: 0; background: none; box-shadow: none; color: inherit; font: inherit; letter-spacing: inherit; text-align: left; justify-content: flex-start; }
.friends-today-toggle .caption { font-size: var(--text-sm); font-weight: 400; }
.friends-today-toggle .ui-icon { grid-column: 2; grid-row: 1 / span 2; transition: rotate 200ms var(--ease); }
.friends-today-toggle[aria-expanded="false"] .ui-icon { rotate: -90deg; }
.friends-today-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr)); gap: var(--s1) var(--s3); }
.friends-today-game a { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--s2); min-height: 2.75rem; padding: var(--s1) var(--s2);
  border-radius: var(--radius-sm, .5rem); background: color-mix(in srgb, var(--accent, currentColor) 5%, transparent); color: inherit; text-decoration: none; }
.friends-today-game img { width: 1.5rem; height: 1.5rem; border-radius: .35rem; }
.friends-today-body { display: grid; min-width: 0; line-height: 1.25; }
.friends-today-body strong { font-size: var(--text-sm); }
.friends-today-top { overflow: hidden; color: var(--muted); font-size: var(--text-xs); text-overflow: ellipsis; white-space: nowrap; font-variant-numeric: tabular-nums; }
.friends-today-top .you { color: var(--ink); font-weight: 700; }
.friends-today-place { color: var(--muted); font-size: var(--text-xs); font-weight: 700; white-space: nowrap; }
.friends-today-place.first { color: var(--accent); }
.friends-today-place.play { padding: 2px var(--s2); border-radius: var(--pill); background: var(--accent); color: var(--on-accent); }
