/* Existing Prodigies world, clearer browsing. Loaded after web/native styles. */
html:has(.kid-grid) { overflow-y: auto; height: auto; }
body.home-scene:has(.kid-grid) {
  overflow: visible; height: auto; min-height: 100dvh;
  color: #182944; background-color: #c2eaf6;
}
body.home-scene .home-shell:has(.kid-grid) {
  --kid-shell-pad: clamp(16px, 3vw, 44px);
  display: flex; flex-direction: column; height: auto; min-height: 100dvh;
  width: min(1160px, 100%); margin: 0 auto;
  /* max(): a phone held sideways puts the Dynamic Island on one side, and the
     gear, the shelf titles and "See all" sat under it. No effect elsewhere. */
  padding: 20px max(var(--kid-shell-pad), env(safe-area-inset-right)) 64px max(var(--kid-shell-pad), env(safe-area-inset-left));
  overflow: visible; box-sizing: border-box; gap: 20px;
}
/* The shelves view drops the 1160 reading-column cap: these are sliders, not
   paragraphs, and the cap is what kept them 92% of the way to full width
   instead of all the way. The category grid below keeps the cap.

   Body's own 18px goes too, or a row that has cancelled the shell's padding
   still stops 18px short of the glass and the bleed looks like a mistake
   rather than a choice. The shell supplies the only inset from here down. */
body.home-scene[data-view="shelves"] { padding-inline: 0; }
body.home-scene[data-view="shelves"] .home-shell:has(.kid-grid) {
  width: 100%; max-width: none;
}
/* THE LOGO RIDES UP INTO THE PILL ROW (Rob, 2026-09-18: "theres a little too
   much space in the top middle above the games logo"). The places nav used to
   sit in the flow and claim a full row of its own above the masthead, so the
   wordmark could never start higher than that row ended. Floating the nav to
   the top-right corner gives that band back to the logo and puts the two on
   roughly one line. Only from tablet width up: on a phone a 70vw wordmark and
   a right-hand pill stack would collide, so there the nav keeps its own row
   (see the narrow override at the bottom of this file). */
body.home-scene .home-shell:has(.kid-grid) { position: relative; }
body.home-scene .scene-masthead {
  flex: none; height: auto; min-height: 0; margin: 0; padding: 0 0 4px;
}
/* 420px wide is exactly Compose's hero wordmark at this viewport. The two
   marks have different aspects (Games 1266x445, Compose ~3.3:1), so matching
   WIDTH is what makes them feel interchangeable; height follows, and the cap
   is raised to let 420 actually be reached rather than clamped back to 364. */
body.home-scene .scene-logo, body.home-scene .scene-logo-night {
  /* 357 = 420 less 15% (Rob, 2026-09-20). 420 was Compose's hero width and
     matching it is what made the two front doors feel interchangeable, so
     Compose came down by the same 15% in the same breath — change one and the
     other has to follow or the swap stops working. */
  width: min(357px, 66vw); height: auto; max-height: 129px; object-fit: contain;
}
/* ── The three places, as hero buttons ────────────────────────────────────
   These sat in the top-right corner until 2026-09-19. They now hold the same
   slot Compose gives "Open the Compose Tool" / "Browse the library" — directly
   under the bobbing dots, centred, same 45px height and 16px radius — because
   the two heroes are meant to read as one product (Rob: "unified/seemless/
   swapped").

   This deliberately reverses the shrink from the day before, when they were
   cramped into a corner at 38px and read as shouting. In the CTA slot the
   Compose size is the right size; corner rules no longer apply. */
body.home-scene .scene-corner {
  position: static; margin-top: -2px;
  display: flex; flex-wrap: wrap;
  justify-content: center; align-items: center;
  width: 100%; transform: none; gap: 13px; margin: 0;
}
body.home-scene .corner-pill,
body.home-scene .scene-night-toggle {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 45px; min-width: 45px; box-sizing: border-box;
  padding: 10px 20px; gap: 8px;
  border-radius: 16px;
  font-size: 0.95rem; font-weight: 800;
  box-shadow: 0 2px 10px rgba(27, 35, 62, 0.16);
}
body.home-scene .scene-night-toggle { padding: 10px; min-width: 52px; }
/* The purse is painted by coin-purse.js, so it is sized from the outside. */
body.home-scene .corner-purse > * {
  min-height: 45px !important;
  border-radius: 16px !important;
  font-size: 0.95rem !important;
  padding: 10px 18px !important;
}

/* ── Bobbing bells ────────────────────────────────────────────────────────
   Eight dots, C through high C — the deskbell stripes, never the twelve
   chromatic — lifted from Compose's hero at the same 13px, 12px gap, and the
   same 2.6s bob staggered 0.15s apart, so the two pages breathe together. */
/* The negative margins buy back .home-shell's 20px flex gap so the four hero
   beats land on Compose's spacing exactly: 13px wordmark-to-dots, 18px
   dots-to-buttons, 30px buttons-to-"New here?". Measured off the live Compose
   hero rather than guessed, because "about right" is what makes two pages
   feel like two pages. */
.hero-dots {
  display: flex; justify-content: center; gap: 12px;
  margin: -13px 0 0;
}
.hero-dots span {
  width: 13px; height: 13px; border-radius: 50%;
  animation: dot-bob 2.6s ease-in-out infinite;
}
.hero-dots span:nth-child(1) { background: #e72829; animation-delay: 0s; }
.hero-dots span:nth-child(2) { background: #f39422; animation-delay: 0.15s; }
.hero-dots span:nth-child(3) { background: #f1e606; animation-delay: 0.3s; }
.hero-dots span:nth-child(4) { background: #6ab845; animation-delay: 0.45s; }
.hero-dots span:nth-child(5) { background: #009999; animation-delay: 0.6s; }
.hero-dots span:nth-child(6) { background: #7b569e; animation-delay: 0.75s; }
.hero-dots span:nth-child(7) { background: #ea6ba3; animation-delay: 0.9s; }
.hero-dots span:nth-child(8) { background: #e72829; animation-delay: 1.05s; }
@keyframes dot-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-7px); }
}
@media (prefers-reduced-motion: reduce) {
  .hero-dots span { animation: none; }
}

body.home-scene .category-tab {
  min-height: 42px; margin: 0; padding: 8px 14px;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  font-size: 14px; font-weight: 800; line-height: 1.2;
  color: #263955; background: #fff; border: 2px solid transparent;
  box-shadow: none; backdrop-filter: none;
}
body.home-scene .category-tab:first-child, body.home-scene .category-tab:last-child { margin: 0; }
body.home-scene .category-tab.is-active { color: #fff; background: #176877; border-color: #fff; }
body.home-scene .category-tab:hover { color: #182944; background: #e7f3f5; }
body.home-scene .category-tab.is-active:hover { color: #fff; background: #145967; }
body.home-scene .category-tab[hidden], body.home-scene .rail-arrow { display: none !important; }
body.home-scene[data-shelf="start"] .category-tab[data-cat]:not([data-cat=""]):not([data-cat="start"]) { display: none; }
body.home-scene .tab-glyph { width: 17px; height: 17px; }
.kid-shelf-title { font-size: clamp(24px, 3vw, 32px); line-height: 1.2; margin: 8px 0 0; text-align: center; color: #182944; }
body.home-scene .rail-frame { flex: none; display: block; min-height: 0; width: 100%; }
body.home-scene .game-rail.kid-grid {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); grid-auto-flow: row;
  grid-template-rows: none; grid-auto-columns: auto; gap: 24px;
  width: 100%; max-width: none; height: auto; min-height: 0; flex: none;
  padding: 4px; margin: 0; overflow: visible; mask-image: none; -webkit-mask-image: none;
  scroll-snap-type: none;
}
body.home-scene .kid-grid .game-card {
  width: 100%; height: auto; min-width: 0; aspect-ratio: auto;
  display: flex; flex-direction: column; border: 0; border-radius: 16px;
  background: #fff; box-shadow: 0 6px 14px rgba(22,70,88,.17); overflow: hidden;
  transition: transform 160ms ease-out;
}
body.home-scene .kid-grid .game-art { aspect-ratio: 518 / 298; width: 100%; height: auto; min-height: 0; flex: none; }
body.home-scene .kid-grid .game-shot { width: 100%; height: 100%; object-fit: cover; }
body.home-scene .kid-grid .game-tab { position: static; min-height: 60px; padding: 12px; background: #fff; color: #182944; }
body.home-scene .kid-grid .game-tab h3 { font-size: 20px; line-height: 1.2; color: #182944; }
body.home-scene .kid-grid .game-tab-badge { display: none; }
body.home-scene .kid-grid .game-card:active { transform: scale(.97); }
body.home-scene .songbook-strip { animation: none; }
body.home-scene .native-bar { position: static; width: 100%; margin: 0; min-height: 48px; }
body.home-scene .native-gear { width: 48px; height: 48px; }
:where(button, a):focus-visible { outline: 4px solid #183e74; outline-offset: 4px; }
html.is-night .kid-shelf-title { color: #fff; }
@media (max-width: 700px) {
  body.home-scene .home-shell:has(.kid-grid) { padding: 12px max(16px, env(safe-area-inset-right)) 40px max(16px, env(safe-area-inset-left)); gap: 16px; }
  body.home-scene .game-rail.kid-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
  body.home-scene .category-tab { font-size: 13px; padding: 7px 11px; min-height: 40px; }
  /* ⚠️ SUPERSEDES "places below the games" (Rob, 2026-09-02). app.css still
     carries `order: 10` on this cluster for phones, from when it sat in a
     corner and crowded the top of a small screen. The hero rebuild of
     2026-09-19 gives it a real slot under the wordmark — the same slot
     Compose uses on mobile — and a unified hero that rearranges itself on
     phones is not unified. The old rule is overridden here rather than
     deleted from app.css, which the sibling release checkout still shares. */
  body.home-scene .scene-corner {
    order: 0;
    padding: 0;
    justify-content: center; flex-wrap: wrap;
  }
  body.home-scene .corner-pill,
  body.home-scene .scene-night-toggle { font-size: 0.86rem; padding: 9px 15px; }
  body.home-scene .corner-purse > * { font-size: 0.86rem !important; padding: 9px 14px !important; }
  body.home-scene .kid-grid .game-tab h3 { font-size: 17px; }
  body.home-scene .kid-grid .game-tab { min-height: 64px; padding: 10px; }
}
@media (prefers-reduced-motion: reduce) {
  body.home-scene .kid-grid .game-card { transition: none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   SHELVES — the home screen (2026-09-19)

   Rows by vibe instead of a filtered list, matching the Compose home so the
   three front doors (Play, Compose, Games) feel like one product. Rob, after
   watching a child use an iPad game app: rows beat "one long list to scroll".

   Two views share this page and never both show: [data-view="shelves"] is the
   home, [data-view="category"] is what a See all opens. The pill row and the
   old single rail belong to the second; the stack belongs to the first.
   ══════════════════════════════════════════════════════════════════════════ */

body.home-scene[data-view="shelves"] .category-tabs,
body.home-scene[data-view="shelves"] .kid-shelf-title,
body.home-scene[data-view="shelves"] .rail-frame { display: none; }

body.home-scene[data-view="category"] .shelf-stack,
body.home-scene[data-view="category"] .kid-newhere { display: none; }
body.home-scene[data-view="shelves"] .shelf-back-wrap { display: none; }

/* "New here?" — quiet, directly under the wordmark, same role as Compose's. */
/* WHITE HERE, TEAL ON COMPOSE (Rob, 2026-09-19). Same line, same job, but
   this one sits on a blue sky and Compose's sits on near-white — the ink has
   to differ for the two to LOOK the same. A soft shadow keeps it legible over
   the lighter part of the gradient without turning into a halo. */
.kid-newhere {
  margin: 10px 0 0; text-align: center;
  font-size: 15px; font-weight: 700; color: #fff;
  text-shadow: 0 1px 3px rgba(12, 42, 74, 0.34);
}
.kid-newhere button {
  border: 0; background: none; padding: 2px 4px; cursor: pointer;
  font: inherit; font-weight: 800; color: #fff;
  text-decoration: underline; text-underline-offset: 3px;
  text-shadow: inherit;
}
.kid-newhere button:hover { color: #eaf6ff; }

.shelf-stack { display: flex; flex-direction: column; gap: 30px; width: 100%; }

.shelf-row { display: flex; flex-direction: column; gap: 8px; }
.shelf-row-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 0 4px;
}
.shelf-row-head h2 {
  margin: 0; font-size: clamp(20px, 2.3vw, 26px); font-weight: 900; color: #182944;
}

.shelf-more {
  flex: 0 0 auto; border: 0; cursor: pointer; font: inherit;
  font-size: 14px; font-weight: 800; color: #176877;
  background: #fff; border-radius: 999px; padding: 8px 16px; min-height: 40px;
  box-shadow: 0 2px 0 rgba(27, 35, 62, 0.10);
}
.shelf-more:hover { background: #e7f3f5; }
.shelf-more:active { transform: translateY(1px); box-shadow: none; }

/* ── FULL-BLEED ROWS ──────────────────────────────────────────────────────
   Rob, 2026-09-19: "the game my daughter was playing was verrry full width".
   The headings stay in the content column; the row of cards breaks out to the
   window's edges and runs off both sides. Negative margins against the
   shell's own padding rather than 100vw — 100vw ignores the scrollbar and
   would hand the page a horizontal wobble on every desktop. */
.shelf-viewport {
  position: relative;
  margin-inline: calc(-1 * var(--kid-shell-pad));
}

.shelf-scroller {
  display: grid; grid-auto-flow: column;
  grid-auto-columns: clamp(228px, 21vw, 300px);
  gap: 18px;
  overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x proximity;
  scroll-padding-left: var(--kid-shell-pad);
  /* Side padding equals the shell inset, so the first card sits directly
     under its heading while the row itself reaches the glass. */
  padding: 6px var(--kid-shell-pad) 14px;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-x pan-y;      /* row sideways, page up */
  overscroll-behavior-x: contain;

  /* ── the fade ──
     Brought back from the old single rail. Each edge answers for itself: the
     left feather appears only once the row has actually moved, the right one
     disappears at the end, and a row too short to scroll has neither. A fade
     against a first card nobody has scrolled past announces "more over here"
     in the one direction where there is nothing. */
  --feather-l: 0px;
  --feather-r: 0px;
  -webkit-mask-image: linear-gradient(to right,
      transparent 0, #000 var(--feather-l),
      #000 calc(100% - var(--feather-r)), transparent 100%);
  mask-image: linear-gradient(to right,
      transparent 0, #000 var(--feather-l),
      #000 calc(100% - var(--feather-r)), transparent 100%);
}
.shelf-scroller.is-faded-left  { --feather-l: var(--rail-feather); }
.shelf-scroller.is-faded-right { --feather-r: var(--rail-feather); }
.shelf-scroller::-webkit-scrollbar { display: none; }
.shelf-scroller > * { scroll-snap-align: start; }
.shelf-scroller .game-card { height: 100%; }

/* The arrows themselves reuse .rail-arrow from app.css (flat navy circle,
   58% chevron); only their placement is ours. They sit over the feather, so
   at rest they cover blank space rather than a card. */
body.home-scene .shelf-viewport .rail-arrow { display: grid !important; }
.shelf-viewport .rail-arrow-prev { left: max(4px, calc((var(--kid-shell-pad) - var(--rail-arrow-size)) / 2)); }
.shelf-viewport .rail-arrow-next { right: max(4px, calc((var(--kid-shell-pad) - var(--rail-arrow-size)) / 2)); }
/* MUST out-specify the show rule above, not merely follow it. `body.home-scene
   .shelf-viewport .rail-arrow` carries an element selector, so it beats a
   plain `.shelf-viewport .rail-arrow[hidden]` and a hidden arrow kept
   painting — a dead button on a row with nothing to scroll, which is the
   affordance-does-not-match-behaviour bug this arrow set exists to avoid. */
body.home-scene .shelf-viewport .rail-arrow[hidden] { display: none !important; }

.shelf-back-wrap { margin: 0; text-align: center; }
.shelf-back {
  border: 0; cursor: pointer; font: inherit; font-size: 15px; font-weight: 800;
  color: #176877; background: #fff; border-radius: 999px;
  padding: 9px 18px; min-height: 42px; box-shadow: 0 2px 0 rgba(27, 35, 62, 0.10);
}
.shelf-back:hover { background: #e7f3f5; }

@media (max-width: 700px) {
  .shelf-stack { gap: 22px; }
  .shelf-scroller { grid-auto-columns: clamp(180px, 66vw, 240px); gap: 12px; }
  .shelf-row-head h2 { font-size: 19px; }
  /* Arrows come off below tablet width: swiping IS the gesture there, and two
     44px circles would sit on top of the only cards on screen. */
  body.home-scene .shelf-viewport .rail-arrow { display: none !important; }
}

/* ══════════════════════════════════════════════════════════════════════════
   NIGHT (2026-09-19)

   The sky at night is #200e80 indigo, and three things were still dressed for
   daylight against it: the shelf headings stayed navy and all but vanished,
   the sun toggle kept a 72%-white pill that read as a smudge rather than a
   button, and the Trophy Room stayed the same dark brown it wears at noon —
   a brown that has nothing to contrast with once the field goes dark.
   ══════════════════════════════════════════════════════════════════════════ */

/* Headings first: navy ink on an indigo sky is the actual legibility bug. */
html.is-night .shelf-row-head h2 { color: #fff; }
html.is-night .kid-shelf-title { color: #fff; }

/* One night skin for the three places, so they read as a set. Indigo lifted
   off the sky rather than a translucent wash — transparency over a starfield
   picks up whatever star happens to be behind it. */
html.is-night body.home-scene .corner-pill,
html.is-night body.home-scene .scene-night-toggle,
html.is-night body.home-scene .corner-purse > * {
  background: #382a7a !important;
  color: #fff !important;
  -webkit-backdrop-filter: none; backdrop-filter: none;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.32);
}
html.is-night body.home-scene .corner-pill:hover,
html.is-night body.home-scene .scene-night-toggle:hover { background: #46368f !important; }

/* …and the Trophy Room breaks out of it, in gold. It is the one place here
   that is a reward rather than a utility, and at night it is the only warm
   thing on the screen — which is exactly the emphasis it should have. */
html.is-night body.home-scene .corner-pill.is-trophy {
  background: linear-gradient(180deg, #f2b53c, #dd9420) !important;
  color: #3d2410 !important;
  box-shadow: 0 2px 12px rgba(221, 148, 32, 0.34);
}
html.is-night body.home-scene .corner-pill.is-trophy:hover {
  background: linear-gradient(180deg, #ffc65a, #e8a02c) !important;
}

/* The sun itself, not just its pill: a warm glyph on the indigo. */
html.is-night .scene-night-toggle .nt-sun { filter: saturate(1.15) brightness(1.1); }

/* See all keeps its white pill — it is the one control that must stay
   obviously pressable on both skies — but the ink warms to match. */
html.is-night .shelf-more { background: #fff; color: #1b4f8a; }
html.is-night .shelf-more:hover { background: #e8f1ff; }

/* ── NO DROP SHADOW ON THE CARDS (Rob, 2026-09-20) ────────────────────────
   "theres like a gray dark shadow or box underneath the games we dont need."

   The shadow (0 10px 22px) was drawn for a card sitting on a pale page. On
   this blue sky it does not read as lift at all: it is a grey wash offset
   below each card, and because the shelf gap is 18px while the blur is 22px,
   NEIGHBOURING shadows overlap and fuse into one continuous dark band running
   the width of the row. That band — not the individual shadows — is what
   reads as a box under the games.

   Removed rather than softened. A white card on a mid-blue sky already has
   all the separation it needs; the shadow was solving a problem this page
   does not have. The hover lift stays, as transform only. */
body.home-scene .shelf-scroller .game-card,
body.home-scene .kid-grid .game-card,
html.is-night body.home-scene .shelf-scroller .game-card,
html.is-night body.home-scene .kid-grid .game-card {
  box-shadow: none;
}
body.home-scene .shelf-scroller .game-card:hover,
body.home-scene .kid-grid .game-card:hover {
  box-shadow: none;
  transform: translateY(-3px);
}
