/* Ea Jane's Piano — the daytime, music-room sibling of the bedtime site. */
@font-face {
  font-family: 'Fredoka';
  src: url('fonts/fredoka-latin.woff2') format('woff2');
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}

:root {
  --ink: #33265a;
  --bg: #f7f0ff;
  --paper: #ffffff;
  --accent: #ff8fab;
  --gold: #ffc93c;
  --shade: rgba(51, 38, 90, 0.16);

  /* One colour per note name, a rainbow from C to B. The same colour is used
     on the key, on its label and on its pill in the ribbon, so "the yellow one"
     is a complete instruction for a child who cannot read yet. */
  --n-c: #ef4444;
  --n-cs: #d9455f;
  --n-d: #f5883b;
  --n-ds: #e0834a;
  --n-e: #eeb61f;
  --n-f: #52bf62;
  --n-fs: #3aa88d;
  --n-g: #23b0c4;
  --n-gs: #3d8cc4;
  --n-a: #5679e2;
  --n-as: #7a63d8;
  --n-b: #a05fd4;
}

* { box-sizing: border-box; }
/* Several things here are laid out with display:flex/grid and toggled with the
   `hidden` attribute; a class rule beats the UA's [hidden] rule, so say it once
   and loudly rather than remembering to guard each one. */
[hidden] { display: none !important; }
html, body { margin: 0; }
body {
  font-family: 'Fredoka', system-ui, sans-serif;
  background: var(--bg);
  color: var(--ink);
  min-height: 100svh;
  -webkit-text-size-adjust: 100%;
}

/* ---------- chrome ---------- */

.top {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: max(12px, env(safe-area-inset-top)) max(16px, env(safe-area-inset-right)) 4px
           max(16px, env(safe-area-inset-left));
}
.app-title { font-size: 1.5rem; margin: 0; flex: 1; }
.screen-title { font-size: 1.25rem; margin: 6px 16px 12px; }
main {
  /* index.html asks for viewport-fit=cover, which lets content under a phone's
     rounded corners and home indicator — so pay the safe area back here. */
  padding: 0 max(16px, env(safe-area-inset-right)) calc(24px + env(safe-area-inset-bottom))
           max(16px, env(safe-area-inset-left));
}

.pill-btn, .tool-btn {
  font: inherit;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--ink);
  background: var(--paper);
  border: 2px solid var(--ink);
  border-radius: 999px;
  padding: 7px 14px;
  min-height: 44px;
  text-decoration: none;
  cursor: pointer;
}

/* ---------- song list ---------- */

.song-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 12px;
}
.song-card {
  font: inherit;
  color: inherit;
  text-align: left;
  background: var(--paper);
  border: 3px solid var(--ink);
  border-radius: 18px;
  box-shadow: 0 4px 0 var(--shade);
  padding: 12px;
  cursor: pointer;
  display: grid;
  gap: 4px;
}
.song-emoji { font-size: 2.2rem; line-height: 1; }
.song-name { font-size: 1.05rem; font-weight: 600; }
.song-meta { font-size: 0.82rem; opacity: 0.75; }
.song-dots { letter-spacing: 2px; font-size: 0.8rem; }
.song-dots b { color: var(--accent); }
.song-dots i { opacity: 0.25; font-style: normal; }
.song-stars { font-size: 1.1rem; letter-spacing: 2px; min-height: 1.4em; }
.song-stars .off { filter: grayscale(1); opacity: 0.3; }
.tip { text-align: center; opacity: 0.7; font-size: 0.9rem; margin-top: 18px; }

/* ---------- play screen ---------- */

.play-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.play-title { font-size: 1.2rem; margin: 0; }

.mode-row { display: flex; gap: 8px; margin-bottom: 8px; }
.mode-btn {
  font: inherit;
  /* One row of four at every width: they still clear a fingertip at 320px, and
     wrapping to two rows costs the keyboard a chunk of the screen. */
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 8px 6px;
  min-height: 62px;
  color: var(--ink);
  background: var(--paper);
  border: 3px solid var(--ink);
  border-radius: 16px;
  box-shadow: 0 3px 0 var(--shade);
  cursor: pointer;
  font-size: 0.92rem;
}
.mode-emoji { font-size: 1.5rem; line-height: 1.1; }
.mode-btn[aria-pressed="true"] { background: var(--accent); box-shadow: 0 3px 0 #d96e8a; }

.tools { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.speed { display: flex; border: 2px solid var(--ink); border-radius: 999px; overflow: hidden; }
.speed button {
  font: inherit;
  font-size: 1.15rem;
  min-width: 46px;
  min-height: 44px;
  border: 0;
  background: var(--paper);
  cursor: pointer;
}
.speed button + button { border-left: 2px solid var(--ink); }
.speed button[aria-pressed="true"] { background: var(--gold); }
.tool-btn[aria-pressed="true"] { background: var(--gold); }

.status {
  font-size: 1.15rem;
  font-weight: 600;
  margin: 6px 0;
  min-height: 1.6em;
}
.status[data-tone="go"] { color: #136b39; }
.status[data-tone="win"] { color: #c2185b; }
.status[data-tone="oops"], .status[data-tone="hint"] { color: #8a4d05; }

.progress { display: flex; flex-wrap: wrap; gap: 5px; margin: 2px 0 8px; }
.progress span {
  width: 13px;
  height: 13px;
  border-radius: 50%;
  border: 2px solid var(--ink);
  background: var(--paper);
}
.progress span.on { background: var(--gold); }

.lyric { margin: 2px 0 6px; font-size: 1rem; opacity: 0.85; min-height: 1.4em; }

/* ---------- note ribbon ---------- */

.ribbon {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  padding: 6px 2px 10px;
  scrollbar-width: thin;
}
.ribbon:empty { display: none; }
.pill {
  flex: 0 0 auto;
  display: grid;
  justify-items: center;
  gap: 1px;
  min-width: 42px;
  padding: 5px 7px;
  border-radius: 12px;
  border: 2px solid var(--ink);
  background: var(--paper);
  transition: transform 140ms, opacity 140ms;
}
.pill b { font-size: 1rem; color: var(--note, var(--ink)); }
.pill i { font-style: normal; font-size: 0.72rem; opacity: 0.8; max-width: 8ch; overflow: hidden; text-overflow: ellipsis; }
.pill.phrase { background: #fff6d8; }
.pill.past { opacity: 0.4; }
.pill.now {
  background: var(--note, var(--accent));
  color: #fff;
  transform: scale(1.16);
  box-shadow: 0 0 0 3px var(--paper), 0 0 0 5px var(--note, var(--accent));
}
.pill.now b { color: #fff; }
.pill.now i { opacity: 0.95; }

/* ---------- the keyboard ---------- */

.kbd-scroll {
  /* `safe` centering: centred when the board fits, but pinned to the left edge
     when it overflows, so the low octave never becomes unreachable. */
  display: flex;
  justify-content: safe center;
  overflow-x: auto;
  overflow-y: hidden;
  touch-action: pan-x;      /* drag sideways to travel; a tap still plays */
  padding: 4px 0 10px;
  overscroll-behavior-x: contain;
}
.kbd {
  /* 21 white keys. On a wide screen they share the width; on a phone they stop
     shrinking at a thumb-sized 44px and the board scrolls instead. */
  --kw: max(44px, calc((min(100vw, 1240px) - 40px) / 21));
  --kh: clamp(132px, 25svh, 210px);
  --bw: calc(var(--kw) * 0.62);
  --bh: calc(var(--kh) * 0.62);
  position: relative;
  width: calc(var(--kw) * 21);
  /* It is a flex item now (the scroller centres it), and flex items shrink by
     default — which would squeeze the white keys while the black keys, placed
     from `--kw`, stayed put and slid off them. */
  flex: 0 0 auto;
  height: var(--kh);
  user-select: none;
  -webkit-user-select: none;
}
.kbd.is-big { --kw: 76px; --kh: clamp(160px, 30svh, 250px); }

.key {
  font: inherit;
  padding: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  /* pan-x, NOT none: the keys cover the whole board, so `none` here would be
     `none` for every touch that starts on the keyboard — and with 21 white keys
     in a phone-width window, two thirds of the piano would be unreachable.
     pan-x still rules out double-tap zoom and vertical drag-fighting. */
  touch-action: pan-x;
}
.key-white {
  position: absolute;
  top: 0;
  left: calc(var(--w) * var(--kw));
  width: var(--kw);
  height: 100%;
  background: linear-gradient(#fff 78%, #f0e9f7);
  border: 2px solid var(--ink);
  border-radius: 3px 3px 11px 11px;
  /* No negative margin to share edges: black keys are placed from the exact
     white-key grid, so any per-key nudge here would drift them a whole key out
     of place by the top octave. Two touching borders is the seam. */
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 8px;
}
.key-black {
  position: absolute;
  top: 0;
  left: calc((var(--w) + 1) * var(--kw) - var(--bw) / 2);
  width: var(--bw);
  height: var(--bh);
  background: linear-gradient(#4a3d70, #251b45);
  border: 2px solid var(--ink);
  border-radius: 0 0 7px 7px;
  box-shadow: 0 3px 0 rgba(0, 0, 0, 0.35);
  z-index: 2;
}

.key-label {
  font-size: clamp(0.68rem, 1.7vw, 0.9rem);
  font-weight: 600;
  color: #fff;
  background: var(--note, var(--ink));
  border-radius: 999px;
  padding: 2px 7px;
  pointer-events: none;
}
.key-home-dot {
  position: absolute;
  bottom: calc(1.1rem + 12px);
  left: 50%;
  transform: translateX(-50%);
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--gold);
  border: 2px solid var(--ink);
}

/* note colours, shared by keys and ribbon pills */
[data-letter="C"]  { --note: var(--n-c); }
[data-letter="C#"] { --note: var(--n-cs); }
[data-letter="D"]  { --note: var(--n-d); }
[data-letter="D#"] { --note: var(--n-ds); }
[data-letter="E"]  { --note: var(--n-e); }
[data-letter="F"]  { --note: var(--n-f); }
[data-letter="F#"] { --note: var(--n-fs); }
[data-letter="G"]  { --note: var(--n-g); }
[data-letter="G#"] { --note: var(--n-gs); }
[data-letter="A"]  { --note: var(--n-a); }
[data-letter="A#"] { --note: var(--n-as); }
[data-letter="B"]  { --note: var(--n-b); }

/* lit states */
.key-white.is-playing, .key-white.is-pressed {
  background: linear-gradient(color-mix(in srgb, var(--note) 55%, #fff), var(--note));
}
.key-black.is-playing, .key-black.is-pressed {
  background: linear-gradient(color-mix(in srgb, var(--note) 70%, #fff), var(--note));
}
.key.is-playing, .key.is-pressed { box-shadow: 0 0 14px 2px var(--note); }
/* The label pill is the note's colour, so on a lit key it would vanish into the
   key. Invert it: white pill, coloured letter. */
.key.is-playing .key-label, .key.is-pressed .key-label,
.key.is-target .key-label {
  background: var(--paper);
  color: var(--note);
}
.key-white.is-pressed { transform: translateY(2px); }

/* z-index below .key-black's 2: a raised *white* key would otherwise paint over
   the inner half of each black key beside it. The outline is drawn inside the
   key, so it stays visible either way. */
.key.is-target { outline: 4px solid var(--note); outline-offset: -4px; }
.key-black.is-target, .key-black.is-hint { z-index: 3; }
.key-white.is-target::after,
.key-black.is-target::after {
  content: '👆';
  position: absolute;
  left: 50%;
  /* Above the letter pill, not on top of it — she needs to read the letter. */
  bottom: 32px;
  transform: translateX(-50%);
  font-size: 1.3rem;
  pointer-events: none;
}
.key-black.is-target::after { bottom: 4px; font-size: 1rem; }
.key-white.is-target .key-home-dot { visibility: hidden; }

@media (prefers-reduced-motion: no-preference) {
  .key.is-target { animation: target-pulse 1.1s ease-in-out infinite; }
  @keyframes target-pulse { 50% { outline-color: var(--gold); } }
  .key-white.is-target::after, .key-black.is-target::after {
    animation: point-bob 0.9s ease-in-out infinite;
  }
  @keyframes point-bob { 50% { transform: translate(-50%, -5px); } }
  .key.is-hint { animation: hint-shake 420ms ease-in-out 2; }
  @keyframes hint-shake {
    25% { transform: translateX(-3px); }
    75% { transform: translateX(3px); }
  }
}
.key.is-hint { outline: 4px solid var(--gold); outline-offset: -4px; }

.hint-line { text-align: center; opacity: 0.65; font-size: 0.9rem; margin: 4px 0 0; }

/* ---------- celebration ---------- */

.party {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(51, 38, 90, 0.55);
  padding: 16px;
  z-index: 10;
}
.party-card {
  background: var(--paper);
  border: 4px solid var(--ink);
  border-radius: 24px;
  box-shadow: 0 10px 0 var(--shade);
  padding: 22px;
  text-align: center;
  max-width: 400px;
}
.party-emoji { font-size: 4rem; line-height: 1; }
.party-text { font-size: 1.3rem; font-weight: 600; margin: 10px 0; }
.party-stars { font-size: 2rem; letter-spacing: 4px; min-height: 1.2em; }
.party-stars .off { filter: grayscale(1); opacity: 0.28; }
@media (prefers-reduced-motion: no-preference) {
  .party-stars .fresh { display: inline-block; animation: star-land 800ms ease-out; }
  @keyframes star-land {
    0% { transform: scale(0) rotate(-90deg); }
    60% { transform: scale(1.4) rotate(10deg); }
  }
}
.party-btns { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin-top: 12px; }
.big-btn {
  font: inherit;
  font-size: 1.05rem;
  padding: 11px 20px;
  border-radius: 999px;
  border: 3px solid var(--ink);
  background: var(--accent);
  color: var(--ink);
  cursor: pointer;
}
@media (prefers-reduced-motion: no-preference) {
  .party-emoji { animation: party-pop 700ms ease-out; }
  @keyframes party-pop { from { transform: scale(0.3) rotate(-15deg); } }
}

/* ---------- shared feedback ---------- */

:is(button, a) { transition: transform 120ms; }
:is(.pill-btn, .tool-btn, .mode-btn, .big-btn, .song-card):active { transform: scale(0.95); }
:is(button, a):focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.key:focus-visible { outline: 3px solid var(--gold); outline-offset: -3px; }
.key-black:focus-visible { z-index: 4; }

/* Short screens (an SE-sized phone, or any phone in landscape): the controls
   above must not push the piano itself below the fold — that is the one thing
   on the page she needs to reach. */
@media (max-height: 700px) {
  .top { padding-top: max(6px, env(safe-area-inset-top)); padding-bottom: 0; }
  .app-title { font-size: 1.05rem; }
  .play-head { margin-bottom: 6px; }
  .play-title { font-size: 1rem; }
  .mode-row { gap: 5px; margin-bottom: 5px; }
  .mode-btn { min-height: 46px; padding: 4px 2px; font-size: 0.7rem; }
  .mode-emoji { font-size: 1.15rem; }
  .tools { gap: 6px; margin-bottom: 4px; }
  .status { font-size: 1rem; margin: 2px 0; min-height: 1.3em; }
  .progress { margin: 0 0 4px; }
  .lyric { margin: 0 0 2px; font-size: 0.92rem; }
  .ribbon { padding: 3px 2px 6px; }
  .hint-line { display: none; }
  .kbd { --kh: clamp(112px, 20svh, 170px); }
}

@media (max-width: 560px) {
  /* flex-basis, not width: `flex: 1` would otherwise keep the title on the
     button row and wrap it to two ragged lines. */
  .app-title { font-size: 1.2rem; flex: 0 0 100%; order: 3; }
  .play-head { flex-wrap: wrap; }
  .play-title { flex: 0 0 100%; font-size: 1.1rem; }
  .mode-btn { min-height: 54px; font-size: 0.8rem; }
  .mode-emoji { font-size: 1.3rem; }
  /* Icon-only tools so Again + speed + Big keys share one row. */
  .tool-btn span:not([aria-hidden]) { display: none; }
  .tool-btn { padding: 7px 12px; font-size: 1.1rem; }
  .kbd { --kh: clamp(122px, 22svh, 190px); }
  .status { font-size: 1.05rem; }
}

/* Phone landscape. Everything that is not the piano or the words gets out of
   the way. */
@media (max-height: 460px) {
  .app-title { display: none; }
  .progress { display: none; }
  /* The ribbon already prints a syllable per note, so the whole sung line is
     the one thing here that can go without losing anything she needs. */
  .lyric { display: none; }
  .top { gap: 8px; padding-bottom: 0; }
  .play-head { margin-bottom: 4px; }
  .tools { margin-bottom: 2px; }
  .status { margin: 0 0 2px; }
  .mode-btn { min-height: 40px; }
  .mode-emoji { font-size: 1rem; }
  .pill-btn, .tool-btn, .speed button { min-height: 40px; }
  .pill { min-width: 38px; padding: 3px 6px; }
  .ribbon { padding: 2px 2px 5px; }
  .kbd { --kh: clamp(96px, 26svh, 132px); }
}
