/* ============================================================
   WAVE 24 — Polyphonic synth styling (no external fonts/assets)
   ------------------------------------------------------------
   Layout model (mobile-first):
     .app  = column of two bands
       .deck   (auto)   control deck: patch / hold / efx
       .keys   (grows)  two-octave piano keyboard
   The keyboard is drawn with pure CSS: 14 white keys in flex flow
   plus 10 absolutely positioned black keys.
   ============================================================ */

:root {
  --bg: #090b11;
  --bg-deep: #05070c;
  --panel: #12172280;
  --panel-solid: #131926;
  --panel-2: #1a2130;
  --line: #263042;
  --text: #e8eef7;
  --dim: #7d8ba3;
  --accent: #ffb347;   /* amber   */
  --accent-2: #4dd0e1; /* cyan    */
  --accent-3: #ff5fa2; /* magenta */

  --key-white-top: #fbfcfe;
  --key-white-bot: #d5dbe4;
  --key-black-top: #2b3344;
  --key-black-bot: #0b0e15;

  --radius: 10px;
  --deck-h: auto;

  --font: ui-monospace, "SFMono-Regular", "Cascadia Mono", "Consolas",
    "Segoe UI Mono", "Courier New", monospace;
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  -webkit-tap-highlight-color: transparent;
}

html,
body {
  height: 100%;
}

body {
  height: 100dvh;
  overflow: hidden;
  font-family: var(--font);
  color: var(--text);
  letter-spacing: 0.5px;
  background-color: var(--bg-deep);
  background-image:
    radial-gradient(ellipse at 50% -10%, rgba(77, 208, 225, 0.10), transparent 55%),
    radial-gradient(ellipse at 50% 120%, rgba(255, 179, 71, 0.10), transparent 55%),
    linear-gradient(180deg, #090b11 0%, #05070c 100%);
  -webkit-font-smoothing: antialiased;
}

/* ============================================================
   1. Portrait warning overlay
   ------------------------------------------------------------
   Spec asks for @media (orientation: portrait). A desktop browser
   window is *also* portrait, so the rule is additionally gated on
   a coarse pointer (touch device) — that keeps phones covered while
   leaving a vertical desktop window fully usable.
   ============================================================ */
.rotate-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 9999;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background:
    radial-gradient(ellipse at 50% 40%, #131a28 0%, #05070c 70%);
}

.rotate-overlay__card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  max-width: 320px;
  padding: 28px 24px;
  text-align: center;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--panel-solid);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.6);
}

/* Phone outline rotating into landscape — pure CSS, no icon font. */
.rotate-overlay__icon {
  width: 44px;
  height: 78px;
  border: 3px solid var(--accent);
  border-radius: 10px;
  box-shadow: 0 0 18px rgba(255, 179, 71, 0.5);
  animation: rotate-hint 2.2s ease-in-out infinite;
}

@keyframes rotate-hint {
  0%, 40%   { transform: rotate(0deg); }
  60%, 100% { transform: rotate(90deg); }
}

.rotate-overlay__title {
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 1px;
  color: var(--accent);
}

.rotate-overlay__hint {
  font-size: 0.72rem;
  color: var(--dim);
}

@media (orientation: portrait) and (pointer: coarse) {
  .rotate-overlay { display: flex; }
  .app { display: none; }
}
/* Small phone fallback for browsers that do not report a coarse pointer. */
@media (orientation: portrait) and (max-width: 640px) {
  .rotate-overlay { display: flex; }
  .app { display: none; }
}

/* ============================================================
   2. App shell — two bands
   ------------------------------------------------------------
   Height budget (the whole point of the layout):
     .app  100dvh, column, never scrolls
     .deck flex: 0 0 auto  + max-height: 50%  -> compact band
     .keys flex: 1 1 auto  + min-height: 45%  -> everything left
   `dvh` follows Safari iOS' collapsing address bar; the `vh` line
   above it is the fallback for browsers that do not know `dvh`.
   ============================================================ */
.app {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  min-height: 0;
  /* Belt and braces: even if a panel ever misbehaves the page itself can
     never scroll, so the keyboard can never be pushed below the fold. */
  overflow: hidden;
  padding: env(safe-area-inset-top) env(safe-area-inset-right)
    env(safe-area-inset-bottom) env(safe-area-inset-left);
}

/* The control deck. `flex: 0 0 auto` keeps it at its natural height, while
   `max-height: 50%` hard-caps it: the keyboard below is therefore *always*
   guaranteed the other half of the screen. If a phone is so short that the
   capped deck still cannot show every control, the deck scrolls internally
   (overflow) instead of stealing space from the keys. */
.deck {
  flex: 0 0 auto;
  min-height: 0;
  max-height: 50%;
  overflow: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  display: flex;
  gap: 10px;
  padding: 10px;
}

/* Keyboard band: takes every pixel the deck leaves, and refuses to shrink
   below 45% of the screen even when the deck wants more. */
.keys {
  flex: 1 1 auto;
  min-height: 45%;
  padding: 0 10px 10px;
  display: flex;
}

/* ============================================================
   3. Panels
   ============================================================ */
.panel {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel-solid);
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.03), transparent);
}

.panel__label {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 2px;
  color: var(--dim);
}

.panel__brand {
  color: var(--accent);
  font-size: 0.78rem;
  letter-spacing: 3px;
  text-shadow: 0 0 10px rgba(255, 179, 71, 0.5);
}

.panel__sub {
  color: var(--dim);
  font-weight: 400;
  letter-spacing: 1px;
}

.panel__foot {
  font-size: 0.55rem;
  line-height: 1.5;
  color: var(--dim);
  letter-spacing: 0.5px;
}

.panel--patch { flex: 0 1 320px; min-width: 210px; }
.panel--hold  { flex: 0 0 auto; }
.panel--efx   { flex: 1 1 auto; min-width: 0; }
/* ============================================================
   4. Patch selector (segmented radio buttons)
   ============================================================ */
.patches {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
}

.patch {
  padding: 9px 10px;
  font-family: inherit;
  font-size: 0.62rem;
  letter-spacing: 0.5px;
  text-align: left;
  color: var(--dim);
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 7px;
  cursor: pointer;
  transition: color 0.12s, border-color 0.12s, background 0.12s, box-shadow 0.12s;
}

.patch:hover { color: var(--text); }

.patch[aria-checked="true"] {
  color: #10131a;
  font-weight: 700;
  background: linear-gradient(180deg, #ffd08a, var(--accent));
  border-color: var(--accent);
  box-shadow: 0 0 14px rgba(255, 179, 71, 0.45);
}

/* ============================================================
   5. Hold / sustain button
   ============================================================ */
.holdBtn {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 12px 16px;
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 3px;
  color: var(--dim);
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 8px;
  cursor: pointer;
  transition: color 0.12s, border-color 0.12s, box-shadow 0.12s;
}

.holdBtn__led {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #323b4d;
  box-shadow: inset 0 0 4px #000;
  transition: background 0.12s, box-shadow 0.12s;
}

.holdBtn[aria-pressed="true"] {
  color: var(--accent-2);
  border-color: var(--accent-2);
  box-shadow: 0 0 16px rgba(77, 208, 225, 0.4), inset 0 0 12px rgba(77, 208, 225, 0.15);
}

.holdBtn[aria-pressed="true"] .holdBtn__led {
  background: var(--accent-2);
  box-shadow: 0 0 10px var(--accent-2), 0 0 20px var(--accent-2);
}

/* ============================================================
   6. EFX grid + sliders
   ============================================================ */
.efxGrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 6px 14px;
}

.knobRow {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 2px 8px;
}

.knobRow__label {
  grid-column: 1 / 2;
  font-size: 0.55rem;
  letter-spacing: 1px;
  color: var(--dim);
}

.knobRow__value {
  grid-column: 2 / 3;
  font-size: 0.55rem;
  color: var(--accent);
  text-align: right;
  min-width: 42px;
}

.knobRow .slider { grid-column: 1 / 3; }

/* ---- range inputs, fully re-skinned ---- */
.slider {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 18px;
  background: transparent;
  cursor: pointer;
}

.slider::-webkit-slider-runnable-track {
  height: 5px;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--accent-2), var(--accent));
  box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.7);
}

.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 15px;
  height: 15px;
  margin-top: -5px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #fff, #b9c4d4);
  border: 1px solid #0b0e15;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.7);
}

.slider::-moz-range-track {
  height: 5px;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--accent-2), var(--accent));
}

.slider::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #fff, #b9c4d4);
  border: 1px solid #0b0e15;
}

.slider:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 3px rgba(77, 208, 225, 0.6); }

/* ============================================================
   7. Master mini slider
   ============================================================ */
.mini {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 8px;
}

.mini__label {
  font-size: 0.55rem;
  letter-spacing: 1px;
  color: var(--dim);
}

.slider--mini { height: 14px; }
.slider--mini::-webkit-slider-runnable-track { height: 4px; }
.slider--mini::-webkit-slider-thumb { width: 12px; height: 12px; margin-top: -4px; }
.slider--mini::-moz-range-thumb { width: 11px; height: 11px; }

/* ============================================================
   8. The keyboard — pure CSS
   ------------------------------------------------------------
   14 white keys stretch with flex; 10 black keys are taken out of
   flow and pinned over the correct white-key boundary.
     --white-count : 14
     black left    : calc((var(--k) - 0.3) * (100% / 14))
     black width   : calc(0.6 * (100% / 14))
   ============================================================ */
.keyboard {
  --white-count: 14;
  --black-width: 0.6;   /* black key width, as a fraction of one white slot */

  position: relative;
  display: flex;
  align-items: stretch;
  width: 100%;
  height: 100%;
  padding: 10px 10px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: linear-gradient(180deg, #0d121c, #070a11);
  box-shadow: inset 0 6px 18px rgba(0, 0, 0, 0.8);
  overflow: hidden;

  /* instrument surface: no scroll / zoom / text selection while playing */
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

/* The positioning context for the black keys. It spans the *content*
   box of .keyboard, so `left: (k-0.3)/14` lands exactly on the k-th
   white-key boundary (percentages resolve against the padding box of
   the containing block, which would otherwise be 20px too wide). */
.keyboard__keys {
  position: relative;
  display: flex;
  align-items: stretch;
  flex: 1 1 auto;
  min-width: 0;
}

.key {
  position: relative;
  font-family: inherit;
  border: none;
  cursor: pointer;
  touch-action: none;
  transition: transform 0.04s ease-out, box-shadow 0.06s, background 0.06s;
}

/* ---- white keys ----
   No margins: the 14 keys must divide the width exactly, so the
   separator between them is an inset shadow instead of a gap. */
.key--white {
  flex: 1 1 0;
  min-width: 0;
  border-radius: 3px 3px 7px 7px;
  background: linear-gradient(180deg, var(--key-white-top) 0%, #eef1f5 82%, var(--key-white-bot) 100%);
  box-shadow:
    inset -1px 0 0 rgba(108, 120, 140, 0.85),
    inset 0 -6px 10px rgba(0, 0, 0, 0.14),
    0 3px 0 #9aa3b2,
    0 4px 6px rgba(0, 0, 0, 0.55);
}

.key--white.is-active {
  background: linear-gradient(180deg, #ffe9c4, var(--accent));
  transform: translateY(2px);
  box-shadow:
    0 1px 0 #b8842f,
    0 0 16px rgba(255, 179, 71, 0.6),
    inset 0 -4px 10px rgba(0, 0, 0, 0.2);
}

/* ---- black keys: overlaid, about two thirds height ---- */
.key--black {
  position: absolute;
  top: 0;
  z-index: 2;
  height: 62%;
  width: calc(var(--black-width) * (100% / var(--white-count)));
  left: calc((var(--k) - 0.3) * (100% / var(--white-count)));
  border-radius: 2px 2px 5px 5px;
  background: linear-gradient(180deg, var(--key-black-top) 0%, #171d29 70%, var(--key-black-bot) 100%);
  box-shadow:
    0 3px 0 #05070c,
    0 5px 8px rgba(0, 0, 0, 0.7),
    inset 0 -3px 5px rgba(0, 0, 0, 0.6),
    inset 0 1px 0 rgba(255, 255, 255, 0.12);
}

.key--black.is-active {
  background: linear-gradient(180deg, #6fe3f0, var(--accent-2));
  transform: translateY(2px);
  box-shadow:
    0 1px 0 #1d7d8c,
    0 0 16px rgba(77, 208, 225, 0.7);
}

/* ============================================================
   9. Responsive
   ============================================================ */

/* Desktop / vertical window: the deck keeps a readable width and the
   keyboard gets the lion's share of the vertical space. */
@media (orientation: portrait) and (min-width: 641px) {
  .app { max-width: 1100px; margin: 0 auto; }
  .deck { flex-wrap: wrap; }
  .panel--efx { flex: 1 1 380px; }
}

/* Very narrow decks stack the panels instead of crushing them. */
@media (max-width: 700px) and (orientation: landscape) {
  .deck { flex-wrap: wrap; }
  .panel--patch { flex: 1 1 190px; }
  .panel--efx { flex: 1 1 100%; }
}

/* ------------------------------------------------------------
   Low-height landscape: phones rotated sideways, small laptop
   windows. This is the case where the deck used to push the
   keyboard off-screen.
   Three mechanisms now cooperate so that cannot happen:
     1. .deck is capped at max-height: 50% (rule 2) and scrolls
        internally if it still does not fit;
     2. .keys declares min-height: 50% here (45% as a base);
     3. every control is shrunk below, so the cap is normally
        never even reached (deck ends up around 1/3 of the height).
   In landscape the scarce resource is vertical space, so these
   rules only ever trade height (padding / font-size / track
   thickness) and never width — the keys stay finger-sized.
   ------------------------------------------------------------ */
@media (max-height: 600px) and (orientation: landscape) {

  /* --- deck: one compact row, never taller than the keys --- */
  .deck {
    flex: 0 0 auto;          /* compact: exactly as tall as its content */
    min-height: 0;
    max-height: 50%;         /* ...but never more than half the screen */
    flex-wrap: nowrap;       /* beats the narrow-deck wrap rule above */
    overflow: auto;          /* last-resort scroll, kills nothing */
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    gap: 6px;
    margin: 0;
    padding: 6px;
  }

  .panel {
    gap: 4px;
    margin: 0;
    padding: 6px;
    border-radius: 8px;
  }

  .panel__label { font-size: 0.5rem; letter-spacing: 1px; }
  .panel__brand { font-size: 0.68rem; letter-spacing: 2px; }
  /* Pure prose: two lines of height with no function while playing. */
  .panel__foot { display: none; }

  /* Only the EFX board stretches; the other two keep their content width. */
  .panel--patch { flex: 0 1 auto; min-width: 148px; }
  .panel--hold  { flex: 0 0 auto; }
  .panel--efx   { flex: 1 1 auto; min-width: 0; }

  /* --- patch buttons + HOLD: same touch targets, less air --- */
  .patches { gap: 4px; }

  .patch {
    padding: 5px 6px;
    font-size: 0.5rem;
    border-radius: 6px;
  }

  .holdBtn {
    gap: 6px;
    padding: 7px 10px;
    font-size: 0.7rem;
    letter-spacing: 2px;
    border-radius: 6px;
  }

  .holdBtn__led { width: 8px; height: 8px; }

  /* --- EFX board: denser grid, slimmer sliders --- */
  .efxGrid {
    grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
    gap: 2px 10px;
  }

  .knobRow { gap: 0 6px; }

  .knobRow__label,
  .knobRow__value {
    font-size: 0.48rem;
    letter-spacing: 0.5px;
  }

  .knobRow__value { min-width: 32px; }

  .slider { height: 12px; }
  .slider::-webkit-slider-runnable-track { height: 4px; }
  .slider::-webkit-slider-thumb { width: 12px; height: 12px; margin-top: -4px; }
  .slider::-moz-range-track { height: 4px; }
  .slider::-moz-range-thumb { width: 11px; height: 11px; }

  .mini { gap: 5px; }
  .mini__label { font-size: 0.48rem; }
  .slider--mini { height: 10px; }
  .slider--mini::-webkit-slider-thumb { width: 11px; height: 11px; margin-top: -3.5px; }
  .slider--mini::-moz-range-thumb { width: 10px; height: 10px; }

  /* --- keyboard: at least half the screen, always --- */
  .keys {
    flex: 1 1 auto;          /* whatever the deck leaves is the keyboard's */
    min-height: 50%;
    padding: 0 6px 6px;
  }

  .keyboard { padding: 6px 6px 8px; }
}

/* ------------------------------------------------------------
   Ultra-short viewports (very small phones in landscape, and
   desktop windows dragged down to ~420px tall): shave the last
   few pixels off the labels and the panel chrome instead of the
   keyboard. Comes after the 600px block on purpose, so it wins.
   ------------------------------------------------------------ */
@media (max-height: 460px) and (orientation: landscape) {
  .deck { gap: 5px; padding: 5px; }

  .panel { gap: 3px; padding: 5px; }

  /* "PATCH" / "ALGORITHMIC REVERB" subtitles: decorative, first to go. */
  .panel__sub { display: none; }

  .patch { padding: 4px 5px; }

  .holdBtn { padding: 6px 8px; }

  .efxGrid { gap: 1px 8px; }

  .keys { padding: 0 5px 5px; }

  .keyboard { padding: 5px 5px 7px; }
}


