/* =====================================================
   kid-games.css — shared page chrome for abby-games.html
   and bella-games.html.

   Loaded AFTER css/style.css, which owns the tokens, the header shell, the
   paper card (.game-area), the hub tiles (.game-hub-card/.game-hub-grid),
   .big-btn, .icon-btn, .game-toolbar, .game-msg and .hidden. Nothing here
   restyles any of those: every selector below either introduces a kg- class
   or qualifies a shared class WITH one.

   style.css is one flat namespace shared with the reader and the arcade, so
   an unprefixed class here would reach across three pages. Everything is
   prefixed kg-.

   Reduced motion is already handled globally at style.css:546-549 and is
   deliberately not repeated here. Per-game art lives in css/kidgames/<id>.css.
   ===================================================== */

/* Bella taps at 76 CSS px, Abby at 57 — brief §4, absolute floor 44 anywhere.
   Gutters and hit-area slop scale with the child, so one shared .kg-target
   sizes correctly on either page. */
/* --kg-tint is the theme's palest wash. Written out per theme rather than
   mixed from --accent: color-mix() is Safari 16.2+, and this site is played on
   whatever iPad is in the house. */
body.theme-bella { --kg-target: 76px; --kg-gap: 34px; --kg-slop: 18px; --kg-tint: #fff0f6; }
body.theme-abby  { --kg-target: 57px; --kg-gap: 30px; --kg-slop: 18px; --kg-tint: #f4efff; }
/* The same number .game-area pads itself with, named so the hub card can take
   it off the CARD and give it back to the three text runs instead — see the
   "picture takes the card's full width" block in css/kid-hub.css. Changing it
   here changes both, which is the point of it being one token. */
body.theme-bella, body.theme-abby { --kg-card-pad: clamp(18px, 5vw, 28px); }

/* ---------------- Page shell ----------------
   flex: 1 makes this column take whatever height .storybody's 100dvh leaves
   under the header, instead of stopping at the height of its own contents.
   On a 390x844 phone the hub used to end 270px short of the bottom edge and
   the rest was bare gradient, which reads as a page that failed to finish
   loading. This rule only CLAIMS that room; css/kid-hub.css's "Filling the
   screen" block is what shares it out. A flex item only grows into free
   space, so a page with none — landscape, or a mounted game taller than the
   viewport — is left exactly as it was. */
.kg-main {
  width: 100%; max-width: 900px; margin: 0 auto;
  flex: 1 1 auto;
  display: flex; flex-direction: column; align-items: center;
  /* 10, not 20: css/kid-hub.css centres this column, so whatever height is
     left over is split above the progress jar and below the card — and this
     padding is only ever on the bottom half of that split. At 20 the sky
     under the card came out 17px deeper than the sky above the jar, which is
     enough to read as the page having sagged. The card keeps its own 12px
     bottom margin, so nothing is ever flush with the edge. */
  padding: 0 12px calc(10px + var(--safe-bottom));
}

/* Storage is full. Visible, not a console line, because the child would
   otherwise keep earning tokens that quietly evaporate. */
.kg-banner {
  width: 100%; max-width: 820px; margin: 12px auto 0;
  background: #fff4d6; color: #7a5a12; border-radius: var(--radius);
  padding: 12px 16px; font-size: .95rem; text-align: center;
  box-shadow: var(--shadow);
}

/* ---------------- Header controls ----------------
   THE GLYPHS ARE DRAWN. Both pages used to put a 🏠, a 🔊 and a 🎯/🎈 in the
   header: three emoji rendered by whatever font the device ships, which on
   iOS are glossy 3D objects sitting on a flat painted page. They are inline
   SVG in the markup now, and everything below only paints them — the boxes
   are still .home-link's 44px and .kg-mute's 48px, untouched, so no target
   moved or shrank.

   SCOPED WITH kg-, DELIBERATELY. .home-link and .icon-btn are style.css's,
   shared with the story reader and the Arcade, and both of those still ship
   their own emoji. Every selector here is qualified with a kg- class that
   exists only on these two pages: .kg-home, .kg-mute, .kg-page-title. */
.kg-glyph {
  display: block; width: 26px; height: 26px;
  color: var(--accent);
  /* An SVG has no baseline to sit on; without this it can pick up the line
     box's descender space and sit a pixel or two high in its circle. */
  flex: 0 0 auto;
}
.kg-home .kg-glyph { width: 24px; height: 24px; }
/* The mark beside a title: sized in em so it tracks the heading it belongs
   to, at both ends of .story-title's clamp() and .game-area h2's. */
.kg-mark {
  display: inline-block; width: 1.02em; height: 1.02em;
  vertical-align: -.14em; margin-right: .3em;
  color: var(--accent);
}
.kg-mark-after { margin-right: 0; margin-left: .34em; }

.kg-mute {
  width: 48px; min-width: 48px; height: 48px; min-height: 48px;
  display: grid; place-items: center; font-size: 1.35rem; padding: 0;
  border-radius: 50%; background: #fff;
}
.kg-mute[aria-pressed="true"] { background: #efe9fd; opacity: .85; }
/* One glyph, two states, off the attribute the button already carries — so
   there is exactly one source of truth for muted and js/kidgames/host.js sets
   nothing but aria-pressed and the label. */
.kg-mute[aria-pressed="false"] .kg-glyph-cross { display: none; }
.kg-mute[aria-pressed="true"] .kg-glyph-wave { display: none; }
.kg-mute[aria-pressed="true"] .kg-glyph { color: var(--ink-soft); }

/* ---------------- Picker ----------------
   The gap is height-aware for one reason: this column is the same ~780px on a
   844x390 phone in landscape as it is on a 820x1180 tablet, and on the first
   of those every pixel is scroll while on the second it is composition. dvh
   is not a breakpoint — it moves continuously, so there is no size at which
   the layout jumps. */
.kg-picker { gap: clamp(12px, 2.2dvh, 24px); }
.kg-picker-title { color: var(--accent); }
.kg-picker-sub { color: var(--ink-soft); font-size: .95rem; margin-top: -8px; }

/* Wider minimum than the arcade's 150px, and a real gutter: two big tiles
   side by side beat three cramped ones for either of them. */
.kg-grid {
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--kg-gap);
}

.kg-tile {
  position: relative;
  min-height: calc(var(--kg-target) + 96px);
  padding: 24px 18px;
  gap: 8px;
  border: 3px solid #f0ecfa;
}
.kg-tile .g-emoji { font-size: 3.2rem; line-height: 1; }
.kg-tile .g-title { font-size: 1.15rem; }
.kg-tile .g-desc { opacity: .78; }

/* Earned once = a token that stays on the tile. Two visual states and nothing
   to read, which is the whole progression surface for a pre-reader. */
.kg-tile-token {
  position: absolute; top: 10px; right: 12px;
  font-size: 1.5rem; opacity: 0; transform: scale(.7);
  transition: opacity .2s var(--ease), transform .2s var(--ease);
}
.kg-tile.kg-done { border-color: var(--accent); }
.kg-tile.kg-done .kg-tile-token { opacity: 1; transform: scale(1); }

/* ---------------- Progress: the star jar ----------------
   WHAT THIS REPLACES. Three ⭐ from the device's emoji font, greyed out with
   opacity and grayscale(1) and floating on the gradient with nothing around
   them. Three problems in one element: they were a stranger's drawing on a
   painted page (the same reason the header glyphs and the spot props were
   drawn), "off" was rendered as "faded", which a five-year-old reads as
   broken rather than as not-yet, and there was no container, so the row had
   no size, no edge and no identity of its own.

   IT IS A VESSEL NOW, BECAUSE A VESSEL IS READ WITHOUT COUNTING. A jar with
   a level in it says how far along you are pre-verbally — the level is the
   answer, and it is legible at a glance and from across a room. The three
   stars are still in there and still countable, so "N of 3" survives exactly:
   level for the gist, stars for the number, and neither needs reading. Both
   are drawn in the child's own accent, inline, in js/kidgames/host.js.

   NOTHING HERE ANIMATES ON ITS OWN. The fill and the stars carry transitions,
   which css/style.css:559 already flattens for a child who asked for less
   motion; there is no keyframe and no JS timer behind either. */
.kg-progress {
  width: 100%; max-width: 820px;
  margin: clamp(8px, 1.8dvh, 20px) auto 0;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
}
/* Sized off the height it has to spare, never off the width: this block is
   the difference between a landscape phone scrolling a little more and a
   tablet in portrait having a hole in the page. 38px is a floor, not a size —
   only a screen under ~420px tall ever reaches it, and there compact is
   right. line-height: 0 keeps the inline SVG off the descender space. */
.kg-vessel { display: block; line-height: 0; }
.kg-vessel-svg {
  display: block;
  /* Landscape's share, which is a scroll budget: at 1024x768 this column is
     already almost exactly the height of the screen. css/kid-hub.css raises
     it in portrait, where the height is free. */
  height: clamp(38px, 8dvh, 84px);
  width: auto;
  overflow: visible;
}
/* Glass, not paper: it has to sit on a gradient and read as a container. */
.kg-vessel-glass {
  fill: rgba(255, 255, 255, .76);
  stroke: var(--accent);
  stroke-opacity: .5;
  stroke-width: 3.2;
  stroke-linejoin: round;
}
.kg-vessel-lid { fill: var(--accent); }
/* Full is a state, not a milestone banner: the glass firms up and that is the
   whole of it. Three stars in a full jar is already the news. */
.kg-vessel[data-full="on"] .kg-vessel-glass { stroke-opacity: .95; stroke-width: 4; }
/* The level. y and height are presentation attributes, so they are also CSS
   properties, and a transition on them is the fill RISING rather than
   jumping — one place finished, one step up. */
.kg-vessel-fill {
  fill: var(--accent-2);
  transition: y .5s var(--ease), height .5s var(--ease);
}
.kg-vessel-shine {
  fill: none; stroke: #fff; stroke-width: 5; stroke-linecap: round; opacity: .75;
}
/* Not-yet is an empty socket with an edge, never a faded star: "off" and
   "broken" have to look different to someone who cannot read the caption. */
.kg-vessel-star {
  fill: #fff; fill-opacity: .5;
  stroke: var(--ink-soft); stroke-opacity: .34; stroke-width: 2.6;
  stroke-linejoin: round;
  transition: fill .3s var(--ease), fill-opacity .3s var(--ease),
              stroke-opacity .3s var(--ease);
}
/* Earned is GOLD, not accent. An accent star inside accent-2 liquid was the
   one state that came out backwards: at 2 of 3 the two she had won read as
   hollow outlines and the one she had not read as the solid shape. Gold is
   the only fill that separates from both children's liquid and from the white
   above it, and it is the colour of the token a finished spot already wears
   on the map — the same reward, twice, in the same yellow. */
.kg-vessel-star.kg-on {
  fill: #ffc93c; fill-opacity: 1;
  stroke: #fff; stroke-opacity: .95;
}
.kg-progress-label { font-weight: 800; color: var(--ink-soft); font-size: 1rem; }
/* Set by js/kidgames/host.js for as long as a game is mounted. The jar is
   the map screen's ornament and the game screen's footnote: same drawing,
   same level, drawn at the floor of its clamp so it costs the game the same
   height the old row of emoji did. */
.kg-progress-compact { margin-top: 8px; gap: 4px; }
.kg-progress-compact .kg-vessel-svg { height: 38px; }
.kg-progress-compact .kg-progress-label { font-size: .9rem; }

/* ---------------- Mounted game ---------------- */
/* The way out sits above the game and a clear 28px clear of it, so a mis-tap
   at the top of a target never dumps her out of the round (brief §4: >=60px
   before any exit control, counting the card's own padding). */
.kg-mountbar { width: 100%; max-width: 820px; margin: 14px auto 0; justify-content: flex-start; }
.kg-mount { margin-top: 28px; }
.kg-game-root { width: 100%; display: flex; flex-direction: column; align-items: center; gap: 16px; }
.kg-game-root h2 { color: var(--accent); }

/* The always-visible replay. Every game puts one in its .game-toolbar; it is
   never the only way to know what to do. */
.kg-replay {
  min-width: 56px; min-height: 56px; font-size: 1.4rem;
  display: inline-grid; place-items: center; padding: 12px 16px;
}

/* ---------------- Answer targets ----------------
   Shared so all six games meet the size, spacing and pointer rules from one
   place. A game may re-skin these in its own css/kidgames/<id>.css. */
/* The 30px floor is asserted HERE, in the one shared rule, rather than in six
   per-game sheets — brief §4 makes >=30px between adjacent targets a hard
   requirement, and a game that never restates it must still get it. */
.kg-choices {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: max(30px, var(--kg-gap)); width: 100%;
}
.kg-target {
  position: relative;
  min-width: var(--kg-target); min-height: var(--kg-target);
  /* The slop extends the hit area ~18px past the artwork on all sides. */
  padding: var(--kg-slop);
  display: grid; place-items: center; gap: 4px;
  border-radius: var(--radius); background: #fff; color: var(--ink);
  font-family: inherit; font-size: 1.15rem; font-weight: 700;
  border: 4px solid transparent; box-shadow: var(--shadow);
  transition: transform .15s var(--ease), border-color .15s var(--ease), opacity .2s var(--ease);
}
/* Touchdown is acknowledged instantly; the answer only commits on lift. */
.kg-target:active { transform: scale(.95); border-color: var(--accent); }
.kg-target.kg-correct { border-color: var(--teal); background: #e9fbf7; }
.kg-target.kg-wrong { border-color: var(--amber); }
/* Dimmed by the scaffold's second miss. Still visible, still not an error. */
.kg-target.kg-dim { opacity: .35; }
/* ONE reserved highlight treatment, used by the hint and the reveal so the
   glow always means the same thing. */
.kg-target.kg-hint {
  border-color: var(--accent);
  box-shadow: 0 0 0 5px var(--accent-2), var(--shadow-lg);
}
.kg-target[disabled] { cursor: default; }

/* ---------------- Win banner ----------------
   Local to the game's own root. Nothing here hides the page. */
.kg-win {
  width: 100%; display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: 22px 18px; border-radius: var(--radius-lg);
  background: linear-gradient(160deg, #fff, var(--kg-tint, #fff));
  border: 4px solid var(--accent); box-shadow: var(--shadow-lg);
}
.kg-win-emoji { font-size: 3.4rem; line-height: 1; }
.kg-win-title { font-size: clamp(1.3rem, 5vw, 1.7rem); font-weight: 800; color: var(--accent); text-align: center; }
.kg-win-actions { display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; margin-top: 6px; }

/* ---------------- Focus ----------------
   4px, high contrast, offset clear of the enlarged hit area — never the UA
   default alone. Covers what the games create as well as the chrome. */
.kg-picker :focus-visible,
.kg-mount :focus-visible,
.kg-mountbar :focus-visible,
.kg-mute:focus-visible,
.kg-tile:focus-visible,
.kg-target:focus-visible {
  outline: 4px solid var(--accent);
  outline-offset: 4px;
  border-radius: 18px;
}

/* ---------------- Breakpoints (only the ones style.css already uses) ------- */
@media (hover: hover) {
  .kg-tile:hover { transform: translateY(-6px); border-color: var(--accent); }
  .kg-target:hover { border-color: var(--accent-2); }
}

@media (max-width: 560px) {
  .kg-grid { grid-template-columns: 1fr; gap: 18px; }
  .kg-tile { min-height: calc(var(--kg-target) + 72px); }
  /* Phones tighten the gutter, but never past the floor: max(30px, ...) means
     the narrow-screen relief only ever applies to a kid whose gap is bigger
     than 30 to begin with. Bella 34 -> 30, Abby 30 -> 30. Targets are flex
     children with a width cap, so the wider gutter takes its space out of the
     artwork or wraps a row — it never pushes the page sideways. */
  .kg-choices { gap: max(30px, calc(var(--kg-gap) - 8px)); }
}

@media (max-width: 360px) {
  .kg-tile .g-emoji { font-size: 2.6rem; }
  .kg-win-emoji { font-size: 2.8rem; }
}

@media (min-width: 720px) {
  .kg-main { padding-left: 20px; padding-right: 20px; }
  .kg-tile { min-height: calc(var(--kg-target) + 120px); }
}
