/* =====================================================
   first-sounds.css — 🐚 Mermaid First Sounds (Bella).

   A memory board of shells. Loaded after css/style.css and css/kid-games.css,
   which own the tokens, the paper card, .game-msg, .game-toolbar and the
   shared .kg-target sizing, states and focus ring. Nothing here restyles a
   shared class on its own: every selector below either introduces a
   kg-first-sounds- class or qualifies a shared one WITH one, so the other
   seven games' sheets cannot collide with this.

   ---------------------------------------------------------------------------
   THE SIZE OF A CARD IS THE WHOLE LAYOUT PROBLEM

   Ten cards is the biggest board, and DESIGN-BRIEF §4 puts a hard floor under
   every one of them: 76 CSS px, with 30 px of clear space between adjacent
   targets. On a 360px phone the room a card can come out of is

     360  viewport
      -24  .kg-main's 12px each side
      -36  .game-area's clamp(18px, 5vw, 28px) each side
     = 300px

   Three columns with the 30px floor between them leaves (300 - 60) / 3 = 80px
   per card — over the floor, and the reason this board is three columns wide
   on a phone whatever size it is. A FOURTH column at that width would be
   (300 - 90) / 4 = 52px, which is under the floor, so it is not an option
   however much better two rows of five would look. A screen wide enough for
   the whole board gets it in two rows instead, because a memory board you
   have to scroll is a memory board about scrolling.

   The column count comes from the rules module, per board, as --kg-fs-wide
   and --kg-fs-narrow — the same two numbers the shuffle checked against when
   it made sure a pair never lands side by side or one directly above the
   other. Changing a number here without changing it there would quietly hand
   her free pairs.

   THE 18px OF HIT SLOP IS SPENT DIFFERENTLY HERE. .kg-target adds it as
   padding around small artwork; on a memory card the card IS the target, and
   what §4 is really buying — no mis-tap landing on the neighbour — is bought
   twice over by the 30px gutter between cards. So the padding comes off and
   the glyph is centred in a box that is 20-40px bigger than it on every side.

   Reduced motion is already handled globally at css/style.css:559-562, which
   flattens every animation and transition duration on the page — that is what
   turns the card flip into an instant state change. No prefers-reduced-motion
   block is added here (ADDENDUM). Belt and braces, the game also puts
   .kg-first-sounds-still on its root and that kills the flip outright. Every
   state below therefore changes a COLOUR or a BORDER as well as moving, so
   the signal survives when the movement does not.

   Palette is the theme's, via var(--accent)/var(--accent-2) — never
   var(--bella), which would not follow the body theme class.
   ===================================================== */

/* ---------------- The board ----------------
   The gutter mirrors kid-games.css's own narrow-screen relief for .kg-choices
   (Bella 34 -> 30, never below the 30px floor), so the two sheets cannot
   disagree about what a gutter is. */
.kg-first-sounds-board {
  --kg-fs-gap: max(30px, var(--kg-gap));
  --kg-fs-cols: var(--kg-fs-narrow, 3);
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-content: center;
  gap: var(--kg-fs-gap);
}

/* ---------------- One shell card ----------------
   The 1px taken off the basis is anti-wrap insurance: three cards and two
   gutters that add up to exactly 100% are one subpixel rounding away from
   becoming four rows instead of two. It costs a third of a pixel per card. */
.kg-target.kg-first-sounds-card {
  flex: 0 0 calc((100% - (var(--kg-fs-cols) - 1) * var(--kg-fs-gap) - 1px)
                 / var(--kg-fs-cols));
  max-width: 168px;
  aspect-ratio: 1 / 1.08;
  /* .kg-target's own floor, restated so it is visible at the place the size
     is decided. min-height wins over aspect-ratio if a card ever gets narrow
     enough for the ratio to take it under the floor. */
  min-width: var(--kg-target);
  min-height: var(--kg-target);
  position: relative;
  padding: 0;
  perspective: 900px;
  background: transparent;
  box-shadow: none;
  border-color: transparent;
}

/* Both faces live in here and it is the thing that turns. */
.kg-first-sounds-flip {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transition: transform .42s var(--ease);
}
.kg-first-sounds-card[data-face="up"] .kg-first-sounds-flip {
  transform: rotateY(180deg);
}
/* ctx.reducedMotion, as a class on the game's root: the card changes state
   instantly and the colour, the border and the glyph still say everything the
   turn said. */
.kg-first-sounds-still .kg-first-sounds-flip { transition: none; }

.kg-first-sounds-back,
.kg-first-sounds-front {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  border-radius: var(--radius);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  box-shadow: var(--shadow);
}

/* Face down: a shell on the water. The shell is the one sea word this game's
   vocabulary refuses to use as an answer (SH is not /s/), so the back of the
   card is exactly where it belongs — it is never claiming to start with
   anything. */
.kg-first-sounds-back {
  font-size: clamp(1.7rem, 7vw, 2.5rem);
  line-height: 1;
  color: #fff;
  background:
    radial-gradient(120% 90% at 50% 0%, #eaf7ff 0%, #cfeaf8 44%, #b6dcf1 100%);
  border: 4px solid var(--accent-2);
}

/* Face up. Turned a half-turn so it reads the right way round when the card
   has flipped. */
.kg-first-sounds-front {
  transform: rotateY(180deg);
  background: linear-gradient(170deg, #ffffff, #f6fcff);
  border: 4px solid #e3eef5;
}

/* ---------------- What is on a face-up card ---------------- */

/* A LETTER CARD. The letter-recognition half of the lesson and the only
   channel a muted child has, so it gets the largest type on the board.

   Sized in vw because the card is: below 700px the board is always three
   columns, so a card is a fixed fraction of the viewport and so is the type
   in it — about 46% of the card at every phone width. Past 700px the column
   count changes and that proportion would break, which is why the min-width
   block at the bottom re-states both sizes rather than letting these run on. */
.kg-first-sounds-letter {
  font-size: clamp(2.3rem, 10.5vw, 4rem);
  line-height: 1;
  font-weight: 800;
  color: var(--accent);
  letter-spacing: .02em;
  text-shadow: 0 3px 0 #fff, 0 5px 12px rgba(53, 49, 94, .16);
}

.kg-first-sounds-pic {
  font-size: clamp(2.1rem, 10vw, 3.8rem);
  line-height: 1;
  /* Nudged clear of the badge so neither ever covers the other. */
  margin: 4px 0 0 4px;
}

/* THE MUTE-SAFE ROUTE. Every picture card wears its own initial uppercase
   letter, so letter-to-letter matching finishes the game with the sound off.
   High contrast on purpose — this is not a decoration, it is half the game. */
.kg-first-sounds-badge {
  position: absolute;
  top: 5px;
  left: 5px;
  min-width: 27px;
  min-height: 27px;
  display: grid;
  place-items: center;
  padding: 0 4px;
  border-radius: 50%;
  background: #fff;
  color: var(--accent);
  border: 3px solid var(--accent);
  font-size: .95rem;
  font-weight: 800;
  line-height: 1;
  box-shadow: 0 0 0 2px #fff;
}

/* ---------------- Card states ----------------
   .kg-correct and .kg-hint are kid-games.css's, and they paint the outer
   button — the frame around the turning faces. These rules only carry the
   face along so it never contradicts the frame it sits in. */

/* A MADE PAIR. Teal, which is this site's "yes" everywhere, plus a wash, so
   the two cards read as done at a glance and from across the room. */
.kg-target.kg-first-sounds-card.kg-correct {
  border-color: var(--teal);
  background: transparent;
}
.kg-first-sounds-found .kg-first-sounds-front {
  background: #e9fbf7;
  border-color: var(--teal);
}
.kg-first-sounds-found .kg-first-sounds-badge {
  color: var(--teal);
  border-color: var(--teal);
}

/* NOT A PAIR — ON ITS WAY BACK OVER. Deliberately not .kg-wrong: nothing here
   was wrong. A quiet grey ring and a small step back, which says "these two
   are leaving" rather than "you failed". The colour is the whole signal, so
   it survives motion being flattened away. */
.kg-first-sounds-turning .kg-first-sounds-front {
  border-color: var(--ink-soft);
  background: #f4f4f8;
  opacity: .8;
}

/* The scaffold's held card and its briefly-shown partner both take .kg-hint,
   the ONE reserved highlight treatment (ADDENDUM) — the same glow means the
   same thing every time it appears. */
.kg-target.kg-first-sounds-card.kg-hint {
  border-color: var(--accent);
  box-shadow: 0 0 0 5px var(--accent-2), var(--shadow-lg);
}
.kg-first-sounds-card.kg-hint .kg-first-sounds-front {
  border-color: var(--accent);
}

/* .kg-target's shared touchdown acknowledgement is restated rather than
   inherited: this sheet loads later and its own .kg-target.kg-first-sounds-card
   rule above sets border-color at the same specificity as
   .kg-target:active, which would otherwise silently win and leave the card
   with no "I felt that" at all. Commit is still on lift. */
.kg-target.kg-first-sounds-card:active { transform: scale(.95); }
.kg-target.kg-first-sounds-card:active .kg-first-sounds-back,
.kg-target.kg-first-sounds-card:active .kg-first-sounds-front {
  border-color: var(--accent);
}

/* ---------------- Dealing a new board ----------------
   Added by the game only when ctx.reducedMotion is false, and flattened
   anyway by css/style.css:559 if it ever is not. `backwards` holds the first
   frame during the delay so a card cannot flash in before its turn. */
.kg-first-sounds-dealing .kg-first-sounds-card {
  animation: kg-first-sounds-deal .34s var(--ease) backwards;
  animation-delay: calc(var(--kg-fs-i, 0) * 55ms);
}
@keyframes kg-first-sounds-deal {
  from { opacity: 0; transform: translateY(-12px) scale(.9); }
}

/* ---------------- The made-pair bubbles ----------------
   Built in JS only when ctx.reducedMotion is false, so this never runs for a
   child who asked for stillness — the teal frame and the chime carry it. */
.kg-first-sounds-bubble {
  position: absolute;
  bottom: 6px;
  font-size: 1rem;
  pointer-events: none;
  opacity: 0;
  animation: kg-first-sounds-rise 1.4s var(--ease) forwards;
}
.kg-first-sounds-b0 { left: 14%; animation-delay: 0s; }
.kg-first-sounds-b1 { left: 38%; animation-delay: .12s; }
.kg-first-sounds-b2 { left: 62%; animation-delay: .24s; }
.kg-first-sounds-b3 { left: 84%; animation-delay: .36s; }
@keyframes kg-first-sounds-rise {
  0%   { opacity: 0; transform: translateY(4px) scale(.6); }
  25%  { opacity: 1; }
  100% { opacity: 0; transform: translateY(-56px) scale(1.05); }
}

/* ---------------- The shell track ----------------
   Twelve shells she can count — one per pair on all three boards. This is the
   whole progress surface: no numeral, no percentage, nothing to read, and it
   only ever fills. */
.kg-first-sounds-track {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-top: 2px;
}
.kg-first-sounds-bead {
  font-size: 1.35rem;
  line-height: 1;
  opacity: .24;
  filter: grayscale(1);
  transform: scale(.86);
  transition: opacity .25s var(--ease), filter .25s var(--ease),
              transform .25s var(--ease);
}
.kg-first-sounds-bead.kg-first-sounds-got {
  opacity: 1;
  filter: none;
  transform: scale(1);
}

/* ---------------- Breakpoints ----------------
   Only the widths css/style.css already uses. */
@media (hover: hover) {
  .kg-target.kg-first-sounds-card:hover .kg-first-sounds-back {
    border-color: var(--accent);
  }
}

@media (max-width: 560px) {
  /* The same relief kid-games.css gives .kg-choices, and by the same rule:
     max() means it only ever applies to a child whose gutter is bigger than
     the 30px floor to begin with. Bella 34 -> 30, which is what buys the
     third column its 80px on a 360px screen. */
  .kg-first-sounds-board { --kg-fs-gap: max(30px, calc(var(--kg-gap) - 8px)); }
  .kg-first-sounds-bead { font-size: 1.2rem; }
}

@media (max-width: 360px) {
  .kg-first-sounds-badge {
    min-width: 24px;
    min-height: 24px;
    font-size: .85rem;
    border-width: 2px;
  }
  .kg-first-sounds-track { gap: 6px; }
  .kg-first-sounds-bead { font-size: 1.1rem; }
}

/* Wide enough for the whole board in two rows — which is where the column
   count stops being three, so the type has to be re-sized against the new,
   narrower share of the viewport a card gets. */
@media (min-width: 700px) {
  .kg-first-sounds-board { --kg-fs-cols: var(--kg-fs-wide, 3); }
  .kg-target.kg-first-sounds-card { max-width: 180px; }
  .kg-first-sounds-letter { font-size: clamp(2.4rem, 7vw, 3.4rem); }
  .kg-first-sounds-pic { font-size: clamp(2.2rem, 6.6vw, 3.2rem); }
  .kg-first-sounds-badge { min-width: 32px; min-height: 32px; font-size: 1.05rem; }
}
