/* GameHub portal stylesheet — copied from hub/portal/portal.css (main@7509b11) plus the
   live-only header auth rules from funnyorca.com/portal-mvp.css. Colour custom properties
   come from tokens.css (same names: --ink, --muted, --bg, --panel, --line, --lime, --lime-ink, --cyan, --focus). */
:root { color-scheme: dark; font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; font-size: 16px; }


* { box-sizing: border-box; }
html { background: var(--bg); scroll-behavior: smooth; }
body { margin: 0; min-width: 320px; min-height: 100vh; color: var(--ink); background: radial-gradient(circle at 85% 0%, #24295b 0, transparent 30rem), var(--bg); }
button, a { -webkit-tap-highlight-color: transparent; }
button { font: inherit; }
button:focus-visible, a:focus-visible, iframe:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
[hidden] { display: none !important; }
.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; }
.app-shell { min-height: 100vh; }

.site-header { position: sticky; top: 0; z-index: 20; min-height: 60px; display: flex; align-items: center; padding: max(8px, env(safe-area-inset-top)) max(16px, env(safe-area-inset-right)) 8px max(16px, env(safe-area-inset-left)); background: rgb(9 11 32 / .9); border-bottom: 1px solid rgb(255 255 255 / .08); backdrop-filter: blur(18px); }
.brand { display: inline-flex; align-items: center; gap: 8px; color: var(--ink); text-decoration: none; font-weight: 950; letter-spacing: -.04em; }
.brand img { width: 36px; height: 36px; object-fit: contain; filter: drop-shadow(0 5px 10px rgb(0 0 0 / .24)); }

.home-view { width: min(1180px, 100%); margin: 0 auto; padding: 16px 16px 0; }
.eyebrow { margin: 0 0 7px; color: var(--lime); font: 850 .73rem/1.2 ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: .12em; }
h1, h2, h3, p { margin-top: 0; }
.featured { position: relative; display: grid; grid-template-columns: minmax(0, 1.42fr) minmax(310px, .78fr); min-height: 420px; overflow: hidden; border: 1px solid #3b4272; border-radius: 28px; background: #151938; box-shadow: 0 30px 90px rgb(0 0 0 / .3); isolation: isolate; }
.feature-art { position: relative; min-height: 390px; overflow: hidden; background: #101536; }
.feature-art::after { content: ""; position: absolute; inset: 0; z-index: 2; background: linear-gradient(90deg, transparent 68%, #151938), linear-gradient(0deg, rgb(9 11 32 / .22), transparent 50%); }
.feature-art > img { width: 100%; height: 100%; object-fit: cover; object-position: center; }
.feature-copy { position: relative; z-index: 4; display: flex; flex-direction: column; align-items: flex-start; justify-content: center; padding: clamp(24px, 3.2vw, 44px); }
.feature-copy h1 { margin-bottom: 12px; font-size: clamp(3.2rem, 4.5vw, 4.6rem); line-height: .86; letter-spacing: -.075em; }
.feature-copy > p:not(.eyebrow) { max-width: 360px; margin-bottom: 18px; color: #d1d3e5; font-size: 1rem; line-height: 1.5; }
.feature-copy > small { margin-top: 12px; color: var(--muted); font-size: .78rem; }
.button, .icon-button, .player-back, .text-button { min-height: 44px; border: 0; cursor: pointer; }
.button { display: inline-flex; align-items: center; justify-content: center; gap: 10px; padding: 10px 15px; border-radius: 12px; font-weight: 850; }
.button-play { min-width: 180px; min-height: 54px; justify-content: space-between; color: var(--lime-ink); background: var(--lime); box-shadow: 0 12px 30px rgb(217 255 87 / .15); transition: transform .18s ease, box-shadow .18s ease; }
.button-play:hover { transform: translateY(-2px); box-shadow: 0 16px 36px rgb(217 255 87 / .22); }
.button-play:active { transform: translateY(1px) scale(.99); }
.button-play b { width: 30px; height: 30px; display: grid; place-items: center; color: var(--ink); background: var(--bg); border-radius: 50%; font-size: .75rem; }
.button-primary { color: var(--lime-ink); background: var(--lime); }
.button-secondary { color: var(--ink); background: transparent; border: 1px solid var(--line); }

.catalogue { padding: 30px 0 60px; }
.section-heading { display: flex; align-items: end; justify-content: space-between; gap: 20px; margin-bottom: 18px; }
.section-heading h2 { margin-bottom: 0; font-size: clamp(1.8rem, 4vw, 2.8rem); letter-spacing: -.045em; }
.section-heading > span { padding-bottom: 6px; color: var(--muted); font-size: .85rem; }
.game-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
.game-card { overflow: hidden; display: block; padding: 0; color: var(--ink); text-align: left; background: var(--panel); border: 1px solid var(--line); border-radius: 18px; cursor: pointer; transition: transform .18s ease, border-color .18s ease; }
.game-card:hover { transform: translateY(-3px); border-color: #6972ad; }
.game-card:active { transform: translateY(0) scale(.99); }
.card-art { min-height: 165px; display: grid; place-items: center; overflow: hidden; background: #242955; }
.card-art img { width: 100%; height: 100%; min-height: inherit; display: block; object-fit: cover; }
.card-bubble .card-art { background: linear-gradient(145deg, #2f86e9, #11182c); }
.card-wheel .card-art { background: linear-gradient(145deg, #075aa6, #101d3a); }
.card-stacker .card-art { background: linear-gradient(145deg, #ff855d, #9f2f6e); }
.card-launch .card-art { background: linear-gradient(145deg, #41e6ff, #3051c7); }
.card-block .card-art { background: linear-gradient(145deg, #facd45, #e85f42); }
.card-bounce .card-art { background: linear-gradient(145deg, #a3f36b, #279f92); }
.card-copy { display: block; padding: 15px; }
.card-copy strong, .card-copy small, .card-copy i { display: block; }
.card-copy strong { line-height: 1.2; }
.card-copy small { min-height: 34px; margin-top: 5px; color: var(--muted); line-height: 1.35; }
.card-copy i { margin-top: 12px; color: var(--lime); font: 800 .69rem/1.2 ui-monospace, monospace; font-style: normal; letter-spacing: .08em; text-transform: uppercase; }

.site-footer { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 16px; margin: 0 -16px; padding: 24px max(16px, calc((100vw - 1180px) / 2)); border-top: 1px solid var(--line); color: var(--muted); }
.footer-brand { justify-self: start; }
.footer-brand img { width: 30px; height: 30px; }
.site-footer p { margin: 0; text-align: center; }
.site-footer > span { justify-self: end; font-size: .78rem; text-transform: uppercase; letter-spacing: .08em; }

.player-view { min-height: 100vh; background: #050612; }
.player-header { position: relative; z-index: 8; min-height: 62px; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 12px; padding: max(7px, env(safe-area-inset-top)) max(10px, env(safe-area-inset-right)) 7px max(10px, env(safe-area-inset-left)); background: #11132f; border-bottom: 1px solid #292e55; }
.player-back { justify-self: start; display: inline-flex; align-items: center; gap: 8px; padding: 7px 10px; color: var(--ink); background: transparent; }
.player-back span:first-child { font-size: 1.35rem; }
.player-title { display: flex; align-items: center; gap: 8px; }
.player-title img { width: 36px; height: 36px; border-radius: 9px; }
.player-title strong { font-size: .86rem; }
.icon-button { justify-self: end; width: 44px; display: grid; place-items: center; color: var(--ink); background: #23274d; border: 1px solid #3e4572; border-radius: 12px; font-size: 1.35rem; }
.player-stage { min-height: calc(100vh - 62px); display: grid; place-items: center; padding: 10px max(8px, env(safe-area-inset-right)) max(10px, env(safe-area-inset-bottom)) max(8px, env(safe-area-inset-left)); background: radial-gradient(circle at 50% 30%, #1c2150, #050612 60%); }
.game-frame-wrap { height: calc(100vh - 82px); max-height: 900px; aspect-ratio: 9 / 16; max-width: 100%; overflow: hidden; background: #111; border-radius: 16px; box-shadow: 0 24px 80px #000; animation: player-in .2s ease-out; }
.game-frame-wrap iframe { width: 100%; height: 100%; border: 0; background: #111; }
.player-state { width: min(420px, calc(100% - 24px)); padding: 34px 26px; color: var(--ink); background: var(--panel); border: 1px solid var(--line); border-radius: 22px; text-align: center; animation: player-in .2s ease-out; }
.player-state h2 { margin-bottom: 8px; font-size: 2rem; letter-spacing: -.045em; }
.player-state > p:not(.eyebrow) { color: var(--muted); line-height: 1.5; }
.loader-mark { position: relative; width: 76px; height: 76px; margin: 0 auto 22px; }
.loader-mark img { width: 100%; height: 100%; object-fit: contain; }
.loader-mark span { position: absolute; inset: -8px; border: 2px solid transparent; border-top-color: var(--lime); border-radius: 50%; animation: spin 1s linear infinite; }
.loader-mark.has-art img { object-fit: cover; border-radius: 18px; box-shadow: 0 10px 30px rgb(0 0 0 / .45); }
.loader-mark.has-art span { inset: -12px; }
.text-button { padding: 8px; color: var(--muted); background: transparent; text-decoration: underline; }
.state-symbol { width: 60px; height: 60px; display: grid; place-items: center; margin: 0 auto 18px; color: var(--lime); background: #292f5b; border-radius: 18px; font-size: 2rem; font-weight: 900; }
.state-actions { display: grid; gap: 9px; margin-top: 22px; }
.toast { position: fixed; z-index: 80; left: 50%; bottom: max(18px, env(safe-area-inset-bottom)); width: max-content; max-width: calc(100% - 28px); padding: 12px 16px; transform: translateX(-50%); color: var(--ink); background: #262b50; border: 1px solid #4c5586; border-radius: 12px; box-shadow: 0 16px 44px rgb(0 0 0 / .4); font-weight: 700; animation: toast-in .18s ease-out; }

@keyframes spin { to { transform: rotate(360deg); } }
@keyframes player-in { from { opacity: 0; transform: translateY(8px); } }
@keyframes toast-in { from { opacity: 0; transform: translate(-50%, 8px); } }

@media (max-width: 767px) {
  .home-view { padding-top: 8px; }
  .featured { grid-template-columns: 1fr; min-height: 0; border-radius: 22px; }
  .feature-art { min-height: 164px; }
  .feature-art::after { background: linear-gradient(0deg, #151938 0%, transparent 55%); }
  .feature-art > img { object-position: center; }
  .feature-copy { padding: 13px 18px 15px; }
  .feature-copy .eyebrow { margin-bottom: 4px; }
  .feature-copy h1 { margin-bottom: 7px; font-size: 2.5rem; line-height: .9; }
  .feature-copy > p:not(.eyebrow) { margin-bottom: 11px; font-size: .9rem; line-height: 1.4; }
  .button-play { width: 100%; min-height: 46px; }
  .feature-copy > small { align-self: center; margin-top: 7px; }
  .catalogue { padding-top: 27px; }
  .section-heading { margin-bottom: 12px; }
  .section-heading h2 { font-size: 1.65rem; }
  .game-grid { grid-template-columns: 1fr 1fr; gap: 10px; }
  .card-art { min-height: 112px; }
  .card-copy { padding: 12px; }
  .card-copy strong { font-size: .9rem; }
  .card-copy small { font-size: .75rem; }
  .site-footer { grid-template-columns: 1fr auto; }
  .site-footer p { display: none; }
  .player-header { grid-template-columns: auto 1fr auto; }
  .player-back span:last-child { display: none; }
  .player-title { justify-self: center; }
  .game-frame-wrap { height: calc(100dvh - 78px); }
}

@media (max-width: 380px) {
  .feature-art { min-height: 148px; }
  .feature-copy { padding: 12px 16px 14px; }
  .feature-copy .eyebrow { font-size: .65rem; }
  .feature-copy h1 { font-size: 2.25rem; }
  .feature-copy > p:not(.eyebrow) { margin-bottom: 9px; font-size: .84rem; }
  .feature-copy > small { font-size: .7rem; }
  .section-heading > span { display: none; }
  .card-art { min-height: 96px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto !important; animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}

/* Header auth (live on funnyorca.com, not yet in the repository's portal.css) */
.auth { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.auth-guest { display: flex; align-items: center; gap: 10px; }
.auth-user { display: inline-flex; align-items: center; gap: 8px; color: var(--ink); text-decoration: none; font-weight: 700; font-size: .9rem; padding: 4px 8px 4px 4px; border-radius: 999px; border: 1px solid transparent; }
.auth-user:hover { border-color: var(--line); background: var(--panel); }
.auth-user img { width: 30px; height: 30px; border-radius: 50%; object-fit: cover; background: var(--panel); }
.points-pill { display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px; border-radius: 999px; background: rgb(217 255 87 / .12); color: var(--lime); font: 800 .82rem/1 ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: .02em; }
.points-pill.bump { animation: bump .35s ease; }
@keyframes bump { 30% { transform: scale(1.18); } }
@media (max-width: 640px) { .auth-user span[data-name] { display: none; } }
.gwrap { position: relative; display: inline-block; height: 36px; border-radius: 999px; overflow: hidden; }
.gfake { display: inline-flex; align-items: center; justify-content: center; height: 36px; padding: 0 16px; border-radius: 999px; background: var(--lime); color: var(--lime-ink); font-weight: 800; font-size: .9rem; letter-spacing: -.01em; box-shadow: 0 6px 18px rgb(217 255 87 / .22); transition: transform .12s, filter .12s; }
.gwrap:hover .gfake { filter: brightness(1.06); transform: translateY(-1px); }
.greal { position: absolute; inset: 0; opacity: 0.001; overflow: hidden; }
.greal > div { width: 100% !important; height: 100% !important; }
.greal iframe { width: 100% !important; height: 100% !important; transform: scale(1.6); transform-origin: center; }
.gwrap.large { height: 48px; }
.gwrap.large .gfake { height: 48px; padding: 0 28px; font-size: 1.05rem; }

/* ===================== Home v2 (proposed) — prefix hv- =====================
   Netflix-derived Home: see-through top bar, art-first billboard, rails, detail sheet, launch morph.
   Motion tokens live here as custom properties (the token file has no motion family). */
:root {
  --dur-press: 120ms; --dur-base: 220ms; --dur-sheet: 320ms; --dur-enter: 420ms; --dur-morph: 380ms; --dur-drift: 16s;
  --ease-out: cubic-bezier(.2, .8, .2, 1); --ease-spring: cubic-bezier(.34, 1.56, .64, 1);
  --font-display-v2: "Bricolage Grotesque", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  /* The page gutter: 16px on a phone, 32px on a tablet, then a centred 1240px column. */
  --hv-gutter: 16px;
}
@media (min-width: 768px) { :root { --hv-gutter: 32px; } }
@media (min-width: 1024px) { :root { --hv-gutter: max(40px, calc((100vw - 1240px) / 2)); } }
.hv-topbar { position: fixed; inset: 0 0 auto; z-index: 30; display: flex; align-items: center; gap: 10px; min-height: 56px; padding: max(8px, env(safe-area-inset-top)) var(--hv-gutter) 8px;
  background: linear-gradient(180deg, rgb(9 11 32 / .72), rgb(9 11 32 / 0)); transition: background var(--dur-base) var(--ease-out), box-shadow var(--dur-base); }
.hv-topbar.solid { background: rgb(9 11 32 / .94); box-shadow: 0 1px 0 rgb(255 255 255 / .07); backdrop-filter: blur(16px); }
.hv-topbar .brand { min-height: 44px; }
.hv-topbar .brand img { width: 32px; height: 32px; }
.hv-spacer { flex: 1; }
@media (max-width: 380px) { .hv-topbar { gap: 6px; } .hv-topbar .brand span { display: none; } }
.hv-signin { min-height: 44px; display: inline-flex; align-items: center; text-decoration: none; color: var(--ink); }
.hv-signin span { display: inline-flex; align-items: center; height: 34px; padding: 0 14px; border-radius: 999px; border: 1px solid var(--card-hover-line); background: rgb(9 11 32 / .5); font-weight: 750; font-size: .88rem; }
/* The live Sign in is Google's button laid invisibly over .gfake; on the top bar it takes the hv-signin outline, since lime is only for Play. */
.hv-topbar .gfake { color: var(--ink); background: rgb(9 11 32 / .5); border: 1px solid var(--card-hover-line); box-shadow: none; font-weight: 750; font-size: .88rem; }
.hv-topbar .gwrap:hover .gfake { filter: none; background: rgb(255 255 255 / .06); }

.hv-billboard { position: relative; isolation: isolate; }
.hv-bb-art { position: relative; height: clamp(220px, 30vh, 300px); overflow: hidden; background: var(--card-art-bg); margin-bottom: -1px; }
.hv-bb-art img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 45%; transform-origin: 60% 40%; animation: hv-drift var(--dur-drift) ease-in-out infinite alternate; }
.hv-bb-art::after { content: ""; position: absolute; inset: 0; z-index: 1; background: linear-gradient(0deg, var(--bg) 0%, var(--bg) 6%, rgb(9 11 32 / .82) 28%, rgb(9 11 32 / 0) 62%); }
.hv-bb-copy { position: relative; z-index: 2; margin-top: -118px; padding: 0 var(--hv-gutter); display: grid; gap: 10px; background: linear-gradient(180deg, transparent 0, transparent 112px, var(--bg) 117px); }
.hv-bb-title { margin: 0; font: 800 clamp(2.7rem, 12vw, 4.4rem)/.88 var(--font-display-v2); letter-spacing: -.045em; text-wrap: balance; text-shadow: 0 2px 24px rgb(0 0 0 / .45); }
.hv-bb-tagline { margin: 0; max-width: 34ch; color: var(--feature-body); line-height: 1.42; }
.hv-bb-actions { display: grid; grid-template-columns: 1fr auto; gap: 10px; margin-top: 4px; }
.hv-bb-support { margin: 0; color: var(--muted); font-size: .8rem; }
/* Until the catalogue arrives the billboard keeps its place, so nothing below it jumps. */
.hv-billboard.is-loading .hv-bb-copy > *, .hv-billboard.is-loading .hv-bb-art img { visibility: hidden; }
/* Featured carousel dots: 44px targets with a pill inside, the current one wider and solid. */
.hv-bb-dots { display: flex; gap: 0; margin: -6px 0 -10px -12px; }
.hv-bb-dot { display: grid; place-items: center; width: 40px; height: 44px; padding: 0; border: 0; background: none; cursor: pointer; }
.hv-bb-dot span { position: relative; width: 22px; height: 4px; overflow: hidden; border-radius: 999px; background: rgb(255 255 255 / .28); transition: width var(--dur-base) var(--ease-out), background var(--dur-base); }
.hv-bb-dot[aria-current] span { width: 30px; background: var(--ink); }
.hv-bb-dot:focus-visible { outline: 3px solid var(--focus); outline-offset: -3px; border-radius: 12px; }

.hv-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.hv-chip { display: inline-flex; align-items: center; height: 24px; padding: 0 9px; border-radius: 999px; font: 800 .75rem/1 ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: .08em; text-transform: uppercase; background: rgb(255 255 255 / .1); color: var(--ink); }
.hv-chip.lime { background: var(--lime); color: var(--lime-ink); }

.hv-play { display: inline-flex; align-items: center; justify-content: center; gap: 10px; min-height: 52px; padding: 0 20px; border: 0; border-radius: 12px; cursor: pointer;
  background: var(--lime); color: var(--lime-ink); font-weight: 850; font-size: 1.05rem; box-shadow: 0 12px 30px rgb(217 255 87 / .18); transition: transform var(--dur-press) var(--ease-out); }
.hv-play:active { transform: scale(.97); }
.hv-info { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 52px; padding: 0 16px; border-radius: 12px; cursor: pointer;
  border: 1px solid var(--card-hover-line); background: rgb(255 255 255 / .06); color: var(--ink); font-weight: 750; transition: transform var(--dur-press) var(--ease-out); }
.hv-info:active { transform: scale(.97); }
.hv-play svg, .hv-info svg { width: 18px; height: 18px; }

/* LiveOps: the Tide Wheel and the Leaderboard, between the billboard and the rails. They look like
   fo-extras.js, not like the catalogue: sea-blue 3D buttons in a rounded face, gold when a spin
   waits, and a live countdown. */
.hv-liveops { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-top: 18px; padding: 0 var(--hv-gutter); }
.hv-lo { display: flex; align-items: center; gap: 10px; min-height: 60px; margin-bottom: 4px; padding: 8px 14px 8px 8px; border: 0; border-radius: 20px;
  background: linear-gradient(180deg, var(--liveops-sea), var(--liveops-deep)); box-shadow: var(--shadow-liveops); color: #fff;
  font: 700 1rem/1 var(--font-liveops); text-align: left; cursor: pointer; transition: transform var(--dur-press) var(--ease-out), box-shadow var(--dur-press); }
.hv-lo:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--liveops-edge); }
.hv-lo:focus-visible { outline: 3px solid var(--liveops-gold); outline-offset: 3px; }
@media (hover: hover) { .hv-lo:hover { filter: brightness(1.08); } }
.hv-lo-ic { flex: none; width: 44px; height: 44px; display: grid; place-items: center; border-radius: 50%; background: var(--liveops-deep); box-shadow: inset 0 0 0 2px rgb(255 255 255 / .14); color: var(--liveops-gold); }
.hv-lo-ic svg { width: 24px; height: 24px; }
.hv-lo-copy { display: grid; gap: 4px; min-width: 0; }
.hv-lo-copy strong { font-weight: 800; font-size: 1.05rem; line-height: 1; white-space: nowrap; }
.hv-lo-copy b { color: var(--liveops-foam); font-weight: 700; font-size: .92rem; line-height: 1; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* The Tide Wheel's own colours, from fo-extras.js. */
.hv-wheel-mini { width: 34px; height: 34px; border-radius: 50%; border: 3px solid #8a5a2b;
  background: radial-gradient(circle, #ffc53d 0 3px, #8a5a2b 3.5px 5.5px, transparent 6px),
    conic-gradient(#12628f 0 36deg, #eaf6fb 0 72deg, #ff6b5b 0 108deg, #eaf6fb 0 144deg, #2fb58a 0 180deg, #eaf6fb 0 216deg, #0b3a5b 0 252deg, #eaf6fb 0 288deg, #ffc53d 0 324deg, #eaf6fb 0); }
/* Hot: a spin is waiting, or a guest can sign in for one. The disc turns gold, the wheel rocks, the label says Spin! */
.hv-lo.hot .hv-lo-ic { background: var(--liveops-gold); box-shadow: 0 0 0 3px rgb(255 197 61 / .28); }
.hv-lo.hot .hv-wheel-mini { animation: hv-bob 1.6s ease-in-out infinite; }
.hv-lo.hot b { color: var(--liveops-gold); font-weight: 800; font-size: 1.05rem; }
@media (max-width: 400px) {
  .hv-liveops { gap: 10px; }
  .hv-lo { gap: 8px; padding: 7px 10px 7px 7px; }
  .hv-lo-ic { width: 38px; height: 38px; }
  .hv-wheel-mini { width: 30px; height: 30px; border-width: 2.5px; }
  .hv-lo-copy strong { font-size: .95rem; }
}

.hv-rail { margin-top: 26px; animation: hv-rise var(--dur-enter) var(--ease-out) both; animation-delay: calc(var(--i, 0) * 70ms + 80ms); }
.hv-rail-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 0 var(--hv-gutter); margin-bottom: 10px; }
.hv-rail-head h2 { margin: 0; font: 800 1.28rem/1.1 var(--font-display-v2); letter-spacing: -.02em; }
.hv-rail-head span { color: var(--muted); font-size: .8rem; }
.hv-track { display: flex; gap: 10px; overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-inline: var(--hv-gutter); padding: 2px var(--hv-gutter) 6px; scrollbar-width: none; }
.hv-track::-webkit-scrollbar { display: none; }
.hv-card { flex: 0 0 148px; scroll-snap-align: start; display: grid; gap: 8px; text-align: left; color: var(--ink); background: none; border: 0; padding: 0; cursor: pointer; }
.hv-card.wide { flex-basis: 236px; }
.hv-art { position: relative; aspect-ratio: 1; border-radius: 14px; overflow: hidden; background: var(--card-art-bg); box-shadow: 0 10px 24px rgb(0 0 0 / .35); transition: transform var(--dur-press) var(--ease-out); }
.hv-card.wide .hv-art { aspect-ratio: 16 / 9; }
.hv-art img { width: 100%; height: 100%; object-fit: cover; display: block; }
.hv-card:active .hv-art { transform: scale(.96); }
@media (hover: hover) { .hv-card:hover .hv-art { transform: translateY(-3px); } }
.hv-badge { position: absolute; top: 8px; left: 8px; z-index: 2; }
.hv-card-play { position: absolute; right: 8px; bottom: 8px; z-index: 2; width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center;
  background: rgb(9 11 32 / .72); color: var(--ink); border: 1px solid rgb(255 255 255 / .28); }
.hv-card-play svg { width: 14px; height: 14px; }
.hv-card-copy { display: grid; gap: 3px; padding: 0 2px; }
.hv-card-copy strong { font-size: .95rem; line-height: 1.2; }
.hv-card-copy small { color: var(--muted); font-size: .8rem; line-height: 1.3; }
.hv-card.soon .hv-art img { opacity: .62; filter: saturate(.7); }
.hv-card.soon .hv-art::after { content: ""; position: absolute; inset: 0; background: linear-gradient(0deg, rgb(9 11 32 / .55), transparent 60%); }
.hv-soon { position: absolute; left: 10px; bottom: 9px; z-index: 2; color: var(--lime); font: 800 .75rem/1 ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: .1em; text-transform: uppercase; }

.hv-scrim { position: fixed; inset: 0; z-index: 40; background: rgb(3 4 12 / .6); opacity: 0; transition: opacity var(--dur-sheet) var(--ease-out); }
.hv-scrim.open { opacity: 1; }
.hv-sheet { position: fixed; left: 0; right: 0; bottom: 0; z-index: 41; max-width: 560px; margin: 0 auto; max-height: 88vh; overflow: auto; background: var(--feature-surface);
  border: 1px solid var(--feature-line); border-bottom: 0; border-radius: 22px 22px 0 0; transform: translateY(104%); transition: transform var(--dur-sheet) var(--ease-out); padding-bottom: calc(18px + env(safe-area-inset-bottom)); }
.hv-sheet.open { transform: none; }
.hv-sheet-art { position: relative; aspect-ratio: 16 / 9; overflow: hidden; }
.hv-sheet-art img { width: 100%; height: 100%; object-fit: cover; display: block; }
.hv-sheet-art::after { content: ""; position: absolute; inset: 0; background: linear-gradient(0deg, var(--feature-surface), transparent 55%); }
.hv-sheet-close { position: absolute; top: 10px; right: 10px; z-index: 3; width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center; background: rgb(9 11 32 / .7); color: var(--ink); border: 0; }
.hv-sheet-body { position: relative; z-index: 2; margin-top: -26px; padding: 0 20px; display: grid; gap: 12px; }
.hv-sheet-body h2 { margin: 0; font: 800 2rem/.95 var(--font-display-v2); letter-spacing: -.035em; }
.hv-sheet-body p { margin: 0; color: var(--feature-body); line-height: 1.45; }
.hv-sheet-body .note { color: var(--muted); font-size: .88rem; }
.hv-sheet-body .hv-play { width: 100%; }

/* Player: the game fills the screen under one slim bar, edge to edge on a phone. A double tap
   on the bar must not zoom the page mid-game. */
.player-view { display: flex; flex-direction: column; height: 100vh; height: 100dvh; min-height: 0; overflow: hidden; touch-action: manipulation; }
body:has(.player-view:not([hidden])), body:has(.player-view:not([hidden])) .app-shell { min-height: 0; overflow: hidden; }
.player-view .player-header { flex: none; min-height: 52px; gap: 8px; padding: max(4px, env(safe-area-inset-top)) max(8px, env(safe-area-inset-right)) 4px max(8px, env(safe-area-inset-left)); }
.player-view .player-back { min-height: 44px; gap: 6px; padding: 0 12px 0 10px; border: 1px solid var(--card-hover-line); border-radius: 999px; background: rgb(255 255 255 / .06); font-weight: 750; }
.player-view .player-back span:first-child { font-size: 1.5rem; line-height: 1; margin-top: -2px; }
.player-view .player-back img { width: 24px; height: 24px; }
.player-view .player-title img { width: 28px; height: 28px; border-radius: 8px; }
.player-view .player-stage { flex: 1; min-height: 0; padding: 0 env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left); }
.player-view .game-frame-wrap { width: 100%; height: 100%; max-height: none; aspect-ratio: auto; border-radius: 0; box-shadow: none; background: var(--player-bg); }
.player-view .game-frame-wrap iframe { background: var(--player-bg); }
/* One-time iPhone Safari hint under the player bar: it takes its own row, so the game is never covered. */
.install-hint { flex: none; display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 4px max(8px, env(safe-area-inset-right)) 4px max(14px, env(safe-area-inset-left)); color: var(--ink); background: var(--feature-surface); border-bottom: 1px solid var(--feature-line); font-size: .86rem; font-weight: 650; line-height: 1.25; animation: player-in .2s ease-out; }
.install-hint span { flex: 1; min-width: 0; }
.install-hint-how { flex: none; min-height: 36px; padding: 0 14px; border: 0; border-radius: 999px; color: var(--lime-ink); background: var(--lime); font: inherit; font-weight: 800; cursor: pointer; }
.install-hint-close { flex: none; display: grid; place-items: center; width: 44px; height: 44px; margin-right: -6px; padding: 0; border: 0; color: var(--muted); background: none; cursor: pointer; }
.install-hint-close svg { width: 16px; height: 16px; }
.install-hint.open { align-items: flex-start; padding-top: 10px; padding-bottom: 10px; }
.install-hint ol { margin: 6px 0 0; padding-left: 20px; display: grid; gap: 4px; font-weight: 550; color: var(--feature-body); }
.install-hint ol b, .install-hint > span > b { color: var(--ink); }
.install-hint-how:focus-visible, .install-hint-close:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
/* Where fullscreen can't work, its button is invisible but keeps its slot, so the game's title stays centred. */
.player-view .player-header .icon-button.is-unavailable { display: none; }
/* Share sits with fullscreen on the right of the player bar; the actions group keeps the title centred. */
.player-actions { justify-self: end; display: flex; align-items: center; gap: 8px; min-width: 44px; }
.player-actions .icon-button { justify-self: auto; }
.player-share svg, .hv-share svg { width: 20px; height: 20px; }
.hv-sheet-actions { display: grid; grid-template-columns: 1fr auto; gap: 10px; }
.hv-share { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 52px; padding: 0 18px; border: 1px solid var(--control-line, #4c5586); border-radius: 12px; color: var(--ink); background: rgb(255 255 255 / .06); font: inherit; font-weight: 800; cursor: pointer; }
.hv-share:focus-visible, .player-share:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }

::view-transition-group(game-art) { animation-duration: var(--dur-morph); animation-timing-function: var(--ease-out); }
@keyframes hv-drift { from { transform: scale(1.02); } to { transform: scale(1.09) translate3d(-1.5%, 1%, 0); } }
@keyframes hv-rise { from { opacity: 0; transform: translateY(14px); } }
@keyframes hv-bob { 0%, 100% { transform: rotate(-12deg); } 50% { transform: rotate(12deg); } }
/* Billboard v3.2 (Home 3.2, HUB-27): the featured carousel, after the App Store's Today, Google Play and
   Apple TV. A native scroller with CSS scroll snap (the phone's own momentum and rubber band), one card per
   stop, the next card peeking in at the right so the swipe needs no telling, nothing moving by itself. Each
   card carries its own title and Play; the copy of a card not yet in view is hidden, so the peek reads as
   art. While a card slides, its art moves a little slower than the card (a scroll-driven animation on the
   compositor, where the browser has it). A computer gets arrows at the edges; reduced motion stops the art.
   Scoped to a billboard with a track, so the single-slot billboard above keeps its rules. */
.hv-billboard:has(> .hv-bb-track) { position: relative; padding: calc(var(--header-height, 60px) + env(safe-area-inset-top, 0px) + 8px) 0 0; touch-action: auto; }
.hv-bb-track { position: relative; display: flex; gap: 10px; overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--hv-gutter); padding: 0 var(--hv-gutter) 22px; scrollbar-width: none; }
.hv-bb-track::-webkit-scrollbar { display: none; }
.hv-bb-slide { position: relative; flex: 0 0 calc(100% - 36px); scroll-snap-align: start; scroll-snap-stop: always; overflow: hidden; isolation: isolate;
  border-radius: 20px; background: var(--card-art-bg); box-shadow: 0 10px 24px rgb(0 0 0 / .35); -webkit-tap-highlight-color: transparent; }
.is-single .hv-bb-slide { flex-basis: 100%; }
.hv-bb-slide .hv-bb-art { cursor: pointer; }
.hv-bb-slide .hv-bb-copy { transition: opacity 240ms var(--ease-out), translate 240ms var(--ease-out); }
.hv-bb-slide:not(.is-current) .hv-bb-copy { opacity: 0; translate: 12px 0; pointer-events: none; }
.hv-billboard:has(> .hv-bb-track) .hv-bb-dots { justify-content: center; margin: -14px 0 -10px; }
@media (max-width: 767px) {
  .hv-bb-slide .hv-bb-art { position: relative; height: auto; aspect-ratio: 4 / 3; margin: 0; }
  .hv-bb-slide .hv-bb-art::after { background: linear-gradient(0deg, rgb(9 11 32 / .92) 0%, rgb(9 11 32 / .7) 30%, rgb(9 11 32 / 0) 62%); }
  .hv-bb-slide .hv-bb-copy { position: absolute; inset: auto 0 0; margin: 0; padding: 0 16px 16px; gap: 6px; background: none; }
  .hv-bb-slide .hv-chips { display: none; }
  .hv-bb-slide .hv-bb-title { font-size: clamp(1.875rem, 8vw, 2.5rem); line-height: 1; letter-spacing: -.035em; text-wrap: balance; }
  .hv-bb-slide .hv-bb-tagline { margin: 0; font-size: .9375rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .hv-bb-slide .hv-bb-actions { margin-top: 4px; }
  .hv-bb-slide .hv-bb-actions .hv-play, .hv-bb-slide .hv-bb-actions .hv-info { min-height: 44px; height: 44px; }
  .hv-bb-slide .hv-bb-actions .hv-info { width: 44px; }
  .hv-bb-slide .hv-bb-support { display: none; }   /* "Free · No download · No account needed" is in the sheet */
}
@media (min-width: 768px) {
  .hv-billboard:has(> .hv-bb-track) { display: block; min-height: 0; margin: 76px 0 0; padding: 0; overflow: visible; border: 0; border-radius: 0; background: none; box-shadow: none; }
  .hv-bb-track { gap: 16px; padding-bottom: 30px; }
  .hv-bb-slide { display: grid; align-items: center; flex-basis: calc(100% - 96px); min-height: clamp(340px, 52vh, 500px); border: 1px solid var(--feature-line);
    border-radius: var(--radius-feature); background: var(--feature-surface); box-shadow: var(--shadow-feature); }
  .is-single .hv-bb-slide { flex-basis: 100%; }
  .hv-billboard:has(> .hv-bb-track) .hv-bb-dots { margin: -22px 0 -8px; }
}
@media (min-width: 768px) and (max-height: 520px) { .hv-billboard:has(> .hv-bb-track) { margin-top: 64px; } .hv-bb-slide { min-height: 0; } }
@supports (animation-timeline: view()) {
  .hv-bb-slide .hv-bb-art img { scale: 1.12; animation: hv-bb-parallax linear both; animation-timeline: view(inline); }
  @keyframes hv-bb-parallax { from { translate: 6% 0; } to { translate: -6% 0; } }
}
.hv-bb-arrow { display: none; }
@media (hover: hover) and (pointer: fine) {
  .hv-bb-arrow { position: absolute; top: calc(var(--header-height, 60px) + 8px + (100vw - 32px - 36px) * .375 - 24px); z-index: 3; display: grid; place-items: center;
    width: 48px; height: 48px; padding: 0; border: 0; border-radius: 50%; background: var(--ink); color: var(--bg); box-shadow: 0 8px 24px rgb(0 0 0 / .45); cursor: pointer;
    opacity: 0; transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-press) var(--ease-out); }
  .hv-bb-arrow svg { width: 22px; height: 22px; }
  .hv-bb-prev { left: max(8px, calc(var(--hv-gutter) - 24px)); }
  .hv-bb-prev svg { rotate: 180deg; }
  .hv-bb-next { right: max(8px, calc(var(--hv-gutter) - 24px)); }
  .hv-billboard:has(> .hv-bb-track):hover .hv-bb-arrow:not(:disabled), .hv-bb-arrow:focus-visible { opacity: 1; }
  .hv-bb-arrow:hover { transform: scale(1.06); }
  .hv-bb-arrow:active { transform: scale(.94); }
  .hv-bb-arrow:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
}
@media (min-width: 768px) and (hover: hover) and (pointer: fine) { .hv-bb-arrow { top: calc(50% - 24px - 7px); } }
/* Tablet and web: the billboard becomes a contained card, copy on the left and art on the right, so
   the 900px art is never blown up; the detail sheet becomes a centred dialog. */
@media (min-width: 768px) {
  .hv-billboard { display: grid; align-items: center; min-height: clamp(340px, 52vh, 500px); margin: 76px var(--hv-gutter) 0; overflow: hidden;
    border: 1px solid var(--feature-line); border-radius: var(--radius-feature); background: var(--feature-surface); box-shadow: var(--shadow-feature); }
  .hv-bb-art { position: absolute; inset: 0 0 0 auto; width: 66%; height: auto; margin: 0; background: none; }
  /* The fade is on the image, not its box: Chrome composites the drifting image apart from a parent's mask. */
  .hv-bb-art img { -webkit-mask-image: linear-gradient(90deg, transparent 0, transparent 8%, #000 52%); mask-image: linear-gradient(90deg, transparent 0, transparent 8%, #000 52%); }
  .hv-bb-art::after { display: none; }
  .hv-bb-copy { max-width: 580px; margin: 0; padding: 40px clamp(28px, 4vw, 56px); background: none; }
  .hv-bb-title { font-size: clamp(2.8rem, 5.2vw, 4.6rem); }
  .hv-bb-actions { grid-template-columns: auto auto; justify-content: start; }
  .hv-bb-actions .hv-play { min-width: 200px; }
  .hv-liveops { grid-template-columns: repeat(2, minmax(0, 300px)); gap: 16px; margin-top: 24px; }
  .hv-rail { margin-top: 34px; }
  .hv-track { gap: 14px; }
  .hv-card { flex-basis: 200px; }
  .hv-card.wide { flex-basis: 320px; }
  .hv-sheet { top: 50%; bottom: auto; left: 50%; right: auto; width: min(560px, calc(100vw - 64px)); max-height: min(88vh, 720px); margin: 0;
    border-bottom: 1px solid var(--feature-line); border-radius: 22px; padding-bottom: 22px; opacity: 0;
    transform: translate(-50%, -46%); transition: transform var(--dur-sheet) var(--ease-out), opacity var(--dur-sheet) var(--ease-out); }
  .hv-sheet.open { opacity: 1; transform: translate(-50%, -50%); }
  .player-view .player-stage { padding: 16px; }
  .player-view .game-frame-wrap { width: auto; height: calc(100vh - 86px); height: calc(100dvh - 86px); max-height: 900px; aspect-ratio: 9 / 16; border-radius: 16px; box-shadow: 0 24px 80px #000; }
}
/* Web: cards grow with the screen, inside the 1240px column. */
@media (min-width: 1024px) {
  .hv-card { flex-basis: clamp(200px, 15vw, 236px); }
  .hv-card.wide { flex-basis: clamp(320px, 25vw, 380px); }
  .hv-rail-head h2 { font-size: 1.5rem; }
}
/* A phone on its side: too short for the card billboard, so it shrinks to fit. */
@media (min-width: 768px) and (max-height: 520px) {
  .hv-billboard { min-height: 0; margin-top: 64px; }
  .hv-bb-copy { padding-block: 22px; }
  .hv-bb-title { font-size: 2.6rem; }
}
@media (prefers-reduced-motion: reduce) {
  .hv-bb-art img, .hv-rail, .hv-wheel-mini { animation: none !important; }
  .hv-bb-track { scroll-behavior: auto; } .hv-bb-slide .hv-bb-copy { transition: none; }
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}
}

/* ===================== v3 · A Evolved (chosen 12 Oct 2026) — prefix fo- =====================
   Pictures, not words. A three-tab bar (Home · Ollie’s Bay · Me), coins in gold, stars in
   star cyan, icon tiles, the How it works explainer, the daily gift and the build task. Every value
   reads a token; motion tokens live here. */
:root {
  --dur-fly: 620ms; --dur-reveal: 900ms; --dur-pop: 500ms; --dur-stagger: 70ms;
  --ease-reveal: cubic-bezier(.2, 1.15, .3, 1); --ease-fly: cubic-bezier(.5, 0, .25, 1);
}
.fo-display { font-family: var(--font-display); font-weight: 800; }

/* Tab bar: three tabs, floating over the page, the page's own colour (no blur, Safari 27's toolbar sits under it). */
.fo-tabbar { position: fixed; left: 14px; right: 14px; bottom: calc(22px + env(safe-area-inset-bottom)); z-index: 40; height: var(--tabbar-height);
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); padding: 6px; border-radius: var(--radius-tile);
  background: var(--tile); border: 1px solid rgb(255 255 255 / .12); box-shadow: var(--shadow-tabbar); }
.fo-tab { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; border-radius: 18px;
  color: var(--muted); text-decoration: none; font: 700 12px/1 var(--font-sans); transition: background var(--dur-base) var(--ease-out), color var(--dur-base); }
.fo-tab svg { width: 22px; height: 22px; }
.fo-tab[aria-current="page"] { background: rgb(255 255 255 / .09); color: var(--ink); }
.fo-tab[aria-current="page"] svg { color: var(--lime); }
.fo-tab .fo-dot { top: 6px; right: calc(50% - 20px); }
.fo-tabbar.is-hidden { transform: translateY(calc(100% + 40px)); transition: transform var(--dur-sheet) var(--ease-out); }

/* Balance pills: coins (gold) and stars (star). Icon and number, no word. */
.fo-balance { height: 44px; padding: 0 14px; border-radius: var(--radius-pill); background: rgb(255 255 255 / .08); display: inline-flex; align-items: center; gap: 7px;
  font: 800 17px/1 var(--font-display); font-variant-numeric: tabular-nums; border: 0; color: var(--gold-text); }
.fo-balance.stars { color: var(--star); }
.fo-coin { flex: none; display: inline-block; width: 19px; height: 19px; border-radius: 50%; background: var(--coin); box-shadow: inset 0 0 0 1px rgb(120 70 0 / .45); }
.fo-coin.sm { width: 14px; height: 14px; }
.fo-coin.lg { width: 30px; height: 30px; }
.fo-star { flex: none; width: 19px; height: 19px; fill: var(--star); }
.fo-balance.bump { animation: fo-bump var(--dur-pop) var(--ease-spring); }

/* Continue card: the last game, big, one Play disc. Dots pick another recent game; never autoplay. */
.fo-continue { position: relative; height: var(--continue-height); border-radius: 28px; overflow: hidden; box-shadow: var(--shadow-dialog); }
.fo-continue > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.fo-continue::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgb(9 11 32 / 0) 40%, rgb(9 11 32 / .9)); }
.fo-continue-copy { position: absolute; z-index: 1; left: 18px; right: 18px; bottom: 18px; display: flex; align-items: flex-end; gap: 12px; }
.fo-continue-title { flex: 1; display: grid; gap: 8px; font: 800 32px/1 var(--font-display); letter-spacing: -.03em; }
.fo-chip-v3 { justify-self: start; height: 30px; padding: 0 12px; border-radius: var(--radius-pill); background: rgb(255 255 255 / .16); display: inline-flex; align-items: center; gap: 6px; font: 800 15px/1 var(--font-display); letter-spacing: 0; }
.fo-play-disc { flex: none; width: 72px; height: 72px; border-radius: 50%; border: 0; display: grid; place-items: center; background: var(--lime); color: var(--lime-ink);
  box-shadow: 0 10px 30px rgb(217 255 87 / .3); transition: transform var(--dur-press) var(--ease-out); }
.fo-play-disc:active { transform: scale(.94); }
.fo-play-disc svg { width: 26px; height: 28px; fill: currentColor; }
.fo-dots { position: absolute; z-index: 1; top: 10px; left: 0; right: 0; display: flex; justify-content: center; }
.fo-dots button { width: 44px; height: 24px; border: 0; padding: 0; background: none; display: grid; place-items: center; }
.fo-dots span { width: 8px; height: 8px; border-radius: 8px; background: rgb(255 255 255 / .45); transition: width var(--dur-base) var(--ease-out), background var(--dur-base); }
.fo-dots [aria-current="true"] span { width: 26px; background: var(--ink); }

/* Icon tile: one picture, one word. Hot = gold ring and the alert dot. */
.fo-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.fo-tile { position: relative; height: var(--tile-size); border-radius: var(--radius-tile); background: var(--tile); box-shadow: inset 0 0 0 1px var(--line);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; color: var(--ink); text-decoration: none; border: 0;
  font: 800 16px/1 var(--font-display); transition: transform var(--dur-press) var(--ease-out); }
.fo-tile:active { transform: scale(.96); }
.fo-tile.hot { background: linear-gradient(170deg, #3b2a0a, var(--tile)); box-shadow: inset 0 0 0 2px var(--gold); }
.fo-tile.hot > svg:first-of-type { animation: fo-bob 1.4s ease-in-out 4; }
.fo-dot { position: absolute; top: 10px; right: 10px; width: 12px; height: 12px; border-radius: 50%; background: var(--alert); box-shadow: 0 0 0 3px var(--tile); }

/* The i button and the How it works explainer: 3-4 pictures, 2-3 words each, arrows, then Tap to continue. */
.fo-info { width: 44px; height: 44px; border-radius: 50%; border: 0; display: grid; place-items: center; background: rgb(255 255 255 / .08); color: var(--ink); }
.fo-info svg { width: 22px; height: 22px; }
.fo-explainer { position: absolute; inset: 0; z-index: 60; border: 0; padding: 96px 30px 64px; background: var(--scrim); color: var(--ink);
  display: grid; grid-template-rows: auto 1fr auto; text-align: center; animation: fo-fade .4s var(--ease-out) both; }
.fo-explainer-title { font: 800 34px/1 var(--font-display); }
.fo-steps { display: grid; align-content: center; gap: 4px; }
.fo-step { width: 150px; display: grid; justify-items: center; gap: 8px; font: 800 18px/1.1 var(--font-display); animation: fo-pop var(--dur-pop) var(--ease-spring) both; }
.fo-step:nth-child(4n+1) { justify-self: start; } .fo-step:nth-child(4n+3) { justify-self: end; }
.fo-step img, .fo-step .pic { width: 96px; height: 96px; border-radius: 24px; object-fit: cover; }
.fo-arrow { justify-self: center; width: 80px; height: 56px; fill: none; stroke: var(--gold); stroke-width: 5; stroke-linecap: round; stroke-dasharray: 120; animation: fo-draw .5s ease-out both; }
.fo-explainer-hint { font: 800 18px/1 var(--font-display); color: var(--muted); animation: fo-fade .4s ease-out both; }

/* Coach mark: once, the first time something matters. A spotlight on the real control, a big arrow, Ollie's bubble. */
.fo-coach { position: absolute; inset: 0; z-index: 60; border: 0; padding: 0; background: none; }
.fo-coach-ring { position: absolute; border-radius: var(--radius-pill); box-shadow: 0 0 0 3px var(--star), 0 0 0 2000px rgb(5 7 20 / .82); }
.fo-coach-arrow { position: absolute; width: 64px; height: 80px; animation: fo-point .9s ease-in-out infinite; }
.fo-bubble { display: flex; align-items: center; gap: 12px; padding: 14px 18px; border-radius: 24px; background: var(--cream); color: var(--gold-ink); font: 800 24px/1.1 var(--font-display); text-align: left; }

/* Daily gift: a dialog, seven days with their real rewards, a month track of chests. */
.fo-dialog { border-radius: var(--radius-dialog); background: var(--feature-surface); box-shadow: 0 0 0 1px var(--feature-line), var(--shadow-dialog); padding: 16px; display: grid; gap: 16px; }
.fo-dialog-head { display: flex; align-items: center; gap: 10px; }
.fo-dialog-title { flex: 1; text-align: center; font: 800 28px/1 var(--font-display); }
.fo-days { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.fo-day { position: relative; height: 112px; border-radius: 20px; background: var(--tile); box-shadow: inset 0 0 0 1px var(--line); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
  font: 800 16px/1 var(--font-display); }
.fo-day small { font: 800 13px/1 var(--font-display); color: var(--muted); }
.fo-day.today { background: linear-gradient(170deg, #3b2a0a, var(--tile)); box-shadow: inset 0 0 0 3px var(--gold); }
.fo-day.today small { color: var(--gold-text); }
.fo-day.done { opacity: .55; }
.fo-day-7 { height: 84px; border-radius: 22px; background: linear-gradient(120deg, #3b2a0a, var(--tile) 70%); box-shadow: inset 0 0 0 2px var(--gold); display: flex; align-items: center; gap: 14px; padding: 0 16px; }
.fo-check { position: absolute; right: 8px; top: 8px; width: 28px; height: 28px; border-radius: 50%; background: var(--lime); display: grid; place-items: center; }
.fo-check svg { width: 16px; height: 16px; fill: none; stroke: var(--lime-ink); stroke-width: 3.4; stroke-linecap: round; stroke-linejoin: round; }
.fo-check.stamp { animation: fo-stamp .4s cubic-bezier(.3, 1.6, .5, 1) both; }
.fo-month { position: relative; height: 54px; }
.fo-month-track { position: absolute; left: 8px; right: 8px; top: 20px; height: 10px; border-radius: 10px; background: rgb(255 255 255 / .12); }
.fo-month-fill { position: absolute; left: 8px; top: 20px; height: 10px; border-radius: 10px; background: var(--gold); transition: width .8s var(--ease-reveal); }
.fo-claim { height: 60px; border: 0; border-radius: 18px; background: var(--gold); color: var(--gold-ink); font: 800 22px/1 var(--font-display); box-shadow: var(--shadow-gold); transition: transform var(--dur-press) var(--ease-out); }
.fo-claim:active { transform: scale(.97); }

/* Build task: the next task's picture, three words and its star cost. Stars fly to the spot; the art reveals in a circle. */
.fo-task { width: 100%; height: var(--task-height); border: 0; border-radius: var(--radius-task); background: var(--lime); color: var(--lime-ink); display: flex; align-items: center; gap: 14px; padding: 0 12px 0 10px; text-align: left;
  box-shadow: var(--shadow-play-v2); transition: transform var(--dur-press) var(--ease-out); }
.fo-task:active { transform: scale(.97); }
.fo-task-thumb { flex: none; width: 56px; height: 56px; border-radius: 16px; object-fit: cover; background-repeat: no-repeat; box-shadow: inset 0 0 0 2px rgb(0 0 0 / .15); }
.fo-task-label { flex: 1; font: 800 21px/1.05 var(--font-display); }
.fo-cost { height: 44px; padding: 0 14px; border-radius: 14px; background: var(--lime-ink); color: var(--star); display: inline-flex; align-items: center; gap: 6px; font: 800 20px/1 var(--font-display); }
.fo-cost .fo-star { width: 18px; height: 18px; }
.fo-segments { display: flex; align-items: center; gap: 6px; }
.fo-seg { flex: 1; height: 10px; border-radius: 10px; background: rgb(255 255 255 / .14); transition: background .4s; }
.fo-seg.done { background: var(--star); }
.fo-reveal { position: absolute; inset: 0; width: 100%; height: 100%; transition: clip-path var(--dur-reveal) var(--ease-reveal); }
.fo-ring { position: absolute; width: 180px; height: 180px; border-radius: 50%; border: 6px solid #fff6c8; box-shadow: 0 0 40px #ffe27a; animation: fo-ring .9s cubic-bezier(.2, .8, .3, 1) both; pointer-events: none; }
.fo-flyer { position: absolute; pointer-events: none; transition: left var(--dur-fly) var(--ease-fly), top var(--dur-fly) cubic-bezier(.2, 0, .3, 1), opacity .2s linear; }

/* Reward card: cream, one picture, the amount, one action. */
.fo-reward { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: var(--radius-task); background: var(--cream); color: var(--gold-ink); animation: fo-pop var(--dur-pop) var(--ease-spring) both; }
.fo-reward-title { flex: 1; display: grid; gap: 4px; font: 800 21px/1 var(--font-display); }
.fo-reward-amount { display: inline-flex; align-items: center; gap: 6px; font: 800 16px/1 var(--font-display); }
.fo-reward button { height: 48px; padding: 0 16px; border: 0; border-radius: 14px; background: var(--gold-ink); color: var(--cream); font: 800 16px/1 var(--font-display); }
.fo-reward-pill { display: inline-flex; align-items: center; gap: 10px; padding: 10px 16px; border-radius: var(--radius-pill); background: var(--cream); color: var(--gold-ink); font: 800 20px/1 var(--font-display); box-shadow: var(--shadow-toast); }

/* Capsule: the only Hub chrome while a game runs. Coins, menu, back to Funny Orca. */
.fo-capsule { position: fixed; right: 12px; top: calc(10px + env(safe-area-inset-top)); z-index: 50; height: 44px; padding: 0 6px; border-radius: var(--radius-pill);
  background: rgb(9 11 32 / .78); border: 1px solid rgb(255 255 255 / .18); box-shadow: 0 8px 22px rgb(0 0 0 / .35); display: flex; align-items: center; gap: 2px; }
.fo-capsule .fo-balance { height: 32px; padding: 0 10px; background: none; font-size: 14px; }
.fo-capsule button { width: 40px; height: 40px; border: 0; border-radius: 50%; background: none; color: var(--ink); display: grid; place-items: center; }
.fo-capsule hr { width: 1px; height: 22px; margin: 0; border: 0; background: rgb(255 255 255 / .2); }

/* Bottom sheet: coins open the shop and the leaderboard; a sheet over Home, never a tab. */
.fo-sheet { position: absolute; left: 0; right: 0; bottom: 0; z-index: 55; padding: 18px 16px 34px; border-radius: 28px 28px 0 0; background: var(--feature-surface); border-top: 1px solid var(--feature-line);
  display: grid; gap: 14px; animation: fo-up var(--dur-sheet) var(--ease-out) both; }
.fo-sheet-grip { justify-self: center; width: 40px; height: 5px; border-radius: 5px; background: var(--icon-button-line); }

@keyframes fo-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes fo-pop { 0% { transform: scale(.3); opacity: 0; } 70% { transform: scale(1.08); opacity: 1; } 100% { transform: scale(1); opacity: 1; } }
@keyframes fo-ring { 0% { transform: translate(-50%, -50%) scale(.2); opacity: 1; } 100% { transform: translate(-50%, -50%) scale(1.7); opacity: 0; } }
@keyframes fo-bob { 0%, 100% { transform: translateY(0) rotate(0); } 50% { transform: translateY(-6px) rotate(-3deg); } }
@keyframes fo-shake { 0%, 100% { transform: rotate(0); } 20% { transform: rotate(-10deg) scale(1.1); } 40% { transform: rotate(9deg) scale(1.15); } 60% { transform: rotate(-6deg) scale(1.15); } 80% { transform: rotate(4deg) scale(1.1); } }
@keyframes fo-stamp { 0% { transform: scale(2.2); opacity: 0; } 100% { transform: scale(1); opacity: 1; } }
@keyframes fo-bump { 0% { transform: scale(1); } 40% { transform: scale(1.25); } 100% { transform: scale(1); } }
@keyframes fo-draw { from { stroke-dashoffset: 120; } to { stroke-dashoffset: 0; } }
@keyframes fo-hop { 0%, 100% { transform: translateY(0); } 40% { transform: translateY(-16px); } }
@keyframes fo-point { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-12px); } }
@keyframes fo-up { from { transform: translateY(100%); } to { transform: translateY(0); } }
@media (prefers-reduced-motion: reduce) {
  [class^="fo-"], [class*=" fo-"] { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
