/* ==========================================================================
   Global reset — no scroll, no zoom, fills the viewport exactly.
   ========================================================================== */

html,
body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  /* dvh accounts for mobile browser chrome; 100vh is a fallback for
     browsers that don't support dvh yet. */
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  overscroll-behavior: none;
  /* Disable browser touch gestures (scroll/pinch/double-tap-zoom) app-wide —
     this is a fixed, full-screen app that should never scroll or zoom.
     Needed because iOS Safari ignores the viewport's user-scalable=no. */
  touch-action: none;
  background: #111;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
}

* {
  box-sizing: border-box;
}

:root {
  /* Sheet-music pane background. The staff stage's edge gradients fade into
     this same white, so the pane and those gradients stay in sync via one var
     (change the sheet colour here and the dissolve follows). */
  --sheet-bg: #ffffff;
  /* Reading-mode control buttons (Play/Stop, Reset) in the sidebar. */
  --btn-play: #1565c0;
  --btn-stop: #c62828;
  --btn-reset: #6a1b9a;
  /* Control sidebar: fixed column of icon buttons pinned to the staff pane's
     left edge (see .control-sidebar). Shared by the sidebar's own width and
     the staff-container's left inset, so the two always stay in sync. */
  --sidebar-width: 56px;
  --sidebar-btn-size: 40px;
}

/* ==========================================================================
   App shell — two full-width panes stacked vertically, each ~half height.
   ========================================================================== */

#app {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100vh;
  height: 100dvh;
}

.pane {
  flex: 1 1 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  min-height: 0; /* allow flex children to shrink instead of overflowing */
}

/* Top pane: hosts the staff, which fills the pane's full height. White,
   sheet-music-style background — VexFlow's default black clef/stave/notes
   read clearly on it. A strong border-bottom (below) separates it from the
   dark keyboard pane. */
#staff-pane {
  background: var(--sheet-bg);
  border-bottom: 4px solid #000;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
  position: relative;
}

/* ==========================================================================
   VexFlow staff — the SVG
   renders into this container, which fills the staff pane's full width and
   height so the staff can scale to fill the pane vertically (see
   notation.js for the fill-height sizing).
   ========================================================================== */
.staff-container {
  position: relative;
  /* Inset by the sidebar's width (+ safe area) so the staff — and its clef —
     renders entirely to the right of the icon column, never behind it. */
  margin-left: calc(var(--sidebar-width) + env(safe-area-inset-left));
  width: calc(100% - var(--sidebar-width) - env(safe-area-inset-left));
  height: 100%;
  min-height: 0;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.staff-container svg {
  display: block;
  max-width: 100%;
}

/* Animated staff stage: two stacked line surfaces that roll up, framed by
   thin white gradients so a line dissolves into the sheet-music white at the
   top/bottom edges as it slides. Only present in Reading mode (app.js). */
.staff-stage {
  position: absolute;
  inset: 0;
  overflow: hidden;
}
.staff-line {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  will-change: transform;
}
.staff-gradient {
  position: absolute;
  left: 0;
  right: 0;
  height: 10%;
  pointer-events: none;
  z-index: 5; /* above the lines, so they dissolve behind it */
}
.staff-gradient--top {
  top: 0;
  background: linear-gradient(to bottom, var(--sheet-bg) 0%, rgba(255, 255, 255, 0) 100%);
}
.staff-gradient--bottom {
  bottom: 0;
  background: linear-gradient(to top, var(--sheet-bg) 0%, rgba(255, 255, 255, 0) 100%);
}

/* ==========================================================================
   Control sidebar — every toggle/action button consolidated into one icon
   column pinned to the far-left edge of the window. Positioned absolutely
   within (white) #staff-pane so it spans only that pane's height — it never
   extends into the keyboard pane below or affects the keyboard's own
   layout. Order top->bottom: fullscreen, labels, colors, mode, play/stop,
   reset (see index.html). Top-anchored (not centered) as a flex column, so
   the first four icons stay at a fixed position whether or not Play/Reset
   are present — Reading mode only ever appends below them, never reflows
   them.
   ========================================================================== */
.control-sidebar {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: calc(var(--sidebar-width) + env(safe-area-inset-left));
  z-index: 10;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 10px;
  padding-top: calc(20px + env(safe-area-inset-top));
  padding-bottom: env(safe-area-inset-bottom);
  padding-left: env(safe-area-inset-left);
}

/* Shared shape for every sidebar button — same size, same pill/circle
   styling, so all six icons read as one consistent set. Per-button rules
   below only ever touch color/background, never size. */
.sidebar-btn {
  appearance: none;
  width: var(--sidebar-btn-size);
  height: var(--sidebar-btn-size);
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.06);
  border: 1px solid rgba(0, 0, 0, 0.15);
  border-radius: 999px;
  color: #333;
  font: inherit;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  touch-action: manipulation;
}

.sidebar-btn[hidden] {
  display: none;
}

.sidebar-btn.is-active {
  background: #1565c0;
  border-color: #1565c0;
  color: #fff;
}

/* Every icon (SVG or the letter glyph) is sized identically regardless of
   which button it's in, per the "all icons equally sized" requirement. */
.sidebar-btn .icon {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.sidebar-btn .icon.icon-fill {
  fill: currentColor;
  stroke: none;
}

.sidebar-btn--letter {
  font-size: 1rem;
  font-weight: 700;
  line-height: 1;
}

/* Full-screen toggle: the maximize/minimize icon halves share one <svg> (see
   index.html) and are swapped via this class, toggled in app.js. */
.icon-minimize-part {
  display: none;
}
.sidebar-btn.is-fullscreen .icon-maximize-part {
  display: none;
}
.sidebar-btn.is-fullscreen .icon-minimize-part {
  display: inline;
}

/* Play/Stop: tempo-plays the loaded Reading-mode song. Only shown in Reading
   mode (see app.js's updatePlayButtonVisibility); its two icons (play
   triangle / stop square, see index.html) are swapped via .is-playing,
   toggled in app.js, rather than by hiding/showing separate buttons. */
.sidebar-btn--play {
  background: var(--btn-play);
  border-color: var(--btn-play);
  color: #fff;
}

.sidebar-btn--play.is-playing {
  background: var(--btn-stop);
  border-color: var(--btn-stop);
}

.icon-stop {
  display: none;
}
.sidebar-btn--play.is-playing .icon-play {
  display: none;
}
.sidebar-btn--play.is-playing .icon-stop {
  display: block;
}

/* Reset — Reading mode only; forces an animated roll-up back to the first
   line (see app.js's resetToStart). A distinct colour so it's never
   confused with Play. */
.sidebar-btn--reset {
  background: var(--btn-reset);
  border-color: var(--btn-reset);
  color: #fff;
}

/* Disabled: nothing to reset (on the first line already, or auto-playback is
   running). Greyed out and non-interactive so its unavailability is obvious. */
.sidebar-btn--reset:disabled {
  background: rgba(0, 0, 0, 0.15);
  border-color: transparent;
  color: rgba(0, 0, 0, 0.4);
  cursor: default;
  pointer-events: none;
}

/* Bottom pane: piano keyboard placeholder. */
#keyboard-pane {
  background: #14161b;
}

/* ==========================================================================
   Playable keyboard — white/black keys, multitouch pressed state.
   ========================================================================== */

/* .keyboard fills #keyboard-pane completely; .pane's centering has no
   visible effect once this is 100% x 100%. touch-action/user-select kill
   scrolling, text selection, and double-tap zoom during multitouch play. */
.keyboard {
  position: relative;
  width: 100%;
  height: 100%;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

.key {
  position: absolute;
  top: 0;
  box-sizing: border-box;
  border: 1px solid #000;
  cursor: pointer;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  /* Kill the long-press callout menu (copy/lookup/etc.) on multitouch play.
     .keyboard already has this, but keys are re-created on every rebuild, so
     it's repeated here too. */
  -webkit-touch-callout: none;
}

.key--white {
  height: 100%;
  background: #f7f5f0;
  border-radius: 0 0 8px 8px;
  z-index: 1;
  box-shadow: inset 0 -6px 10px -8px rgba(0, 0, 0, 0.4);
}

.key--white.key--pressed {
  background: #9fc8ff;
  box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.35);
}

.key--black {
  background: #1a1a1a;
  border: 1px solid #000;
  border-radius: 0 0 5px 5px;
  z-index: 2;
  box-shadow: 0 3px 4px rgba(0, 0, 0, 0.5);
}

.key--black.key--pressed {
  background: #3f7fd6;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
}

/* White-key letter labels — non-interactive (pointer-events: none
   + user-select: none) so they never intercept the pointer events driving
   multitouch play; purely decorative text near the bottom of each white
   key. Black keys never get one (see keyboard.js). */
.key__label {
  position: absolute;
  left: 0;
  bottom: 10px;
  width: 100%;
  text-align: center;
  /* Doubled from 0.9rem — small labels were hard to read on a tablet. */
  font-size: 2.5rem;
  font-weight: 600;
  color: rgba(0, 0, 0, 0.4);
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

/* In color mode the white keys are tinted, so the grey label loses contrast —
   render it white (with a soft shadow so it stays legible on lighter hues). */
.keyboard--colored .key__label {
  color: #fff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
}

/* pressed, color mode ON (new, only applies under the gate) */
.keyboard--colored .key--white.key--pressed {
    box-shadow: inset 0 3px 8px rgba(0, 0, 0, .9);
    /*border: 4px  rgba(255,255,0);*/
}

/* Playback highlight — lit by the tempo player (player.js, via
   app.js) while a note is auto-sounding, distinct (gold) from the blue
   user-pressed state above so the two are visually distinguishable if a
   child also presses the key while it's playing. */
.key--white.key--playing {
  background: #ffd54f;
  box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.35);
}

.keyboard--colored .key--white.key--playing {
    box-shadow: inset 0 3px 8px rgba(0, 0, 0, .9);
}

.key--black.key--playing {
  background: #f9a825;
}

/* Color mode + playback: fade every key so the auto-played (or physically
   pressed) key stands out. Gated on `.keyboard--colored` (color mode) AND
   `.keyboard--playback` (added by app.js while the tempo player runs), so
   nothing dims in plain (non-color) mode. */
.keyboard--colored.keyboard--playback .key {
  opacity: 0.33;
  transition: opacity 0.12s ease;
}

.keyboard--colored.keyboard--playback .key--playing,
.keyboard--colored.keyboard--playback .key--pressed {
  opacity: 1;
}

/* ==========================================================================
   Orientation handling — CSS-only portrait/landscape switch.
   ========================================================================== */

/* Rotate hint hidden by default (landscape is the expected/default case). */
#rotate-hint {
  display: none;
}

@media (orientation: portrait) {
  /* Hide the two-pane app and show the rotate-to-landscape overlay instead. */
  #app {
    display: none;
  }

  #rotate-hint {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100vh;
    height: 100dvh;
    background: #111;
    color: #fff;
    text-align: center;
    padding: 2rem;
  }

  #rotate-hint p {
    font-size: 1.5rem;
    line-height: 1.4;
    max-width: 20ch;
  }
}

@media (orientation: landscape) {
  #rotate-hint {
    display: none;
  }

  #app {
    display: flex;
  }
}
