:root {
  --bg-0: #0e1020;
  --bg-1: #161a2e;
  --bg-2: #1c2140;
  --surface: rgba(255, 255, 255, 0.04);
  --surface-2: rgba(255, 255, 255, 0.08);
  --border: rgba(255, 255, 255, 0.08);
  --text: #e6e8f4;
  --text-dim: #9aa0c2;
  --accent: #6b8cff;
  --accent-2: #a87bff;
  --hot: #ff5577;
  --shadow: 0 20px 50px rgba(0, 0, 0, 0.45);
  --key-white: #fdfdfd;
  --key-white-shadow: #c5c8d6;
  --key-black: #1a1c25;
  --key-black-edge: #0a0b10;
  --key-active: #6b8cff;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
    "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
  color: var(--text);
  background:
    radial-gradient(ellipse at top left, rgba(107, 140, 255, 0.12), transparent 50%),
    radial-gradient(ellipse at bottom right, rgba(168, 123, 255, 0.10), transparent 50%),
    linear-gradient(180deg, var(--bg-0) 0%, var(--bg-1) 100%);
  min-height: 100vh;
  overflow-x: hidden;
  user-select: none;
}

body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* Topbar */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 28px;
  border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, rgba(255,255,255,0.02), transparent);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  position: sticky;
  top: 0;
  z-index: 10;
}

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
}

.brand h1 {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: 0.5px;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.brand-mark {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  object-fit: cover;
  display: block;
  box-shadow: 0 4px 12px rgba(107, 140, 255, 0.30);
}

.topbar-actions {
  display: flex;
  align-items: center;
  gap: 22px;
  flex-wrap: wrap;
}

/* Toggle switch */
.toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text-dim);
  cursor: pointer;
  user-select: none;
}
.toggle input { display: none; }
.toggle-track {
  width: 36px;
  height: 20px;
  background: #3a3f5f;
  border-radius: 999px;
  position: relative;
  transition: background 0.2s;
}
.toggle-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #fff;
  transition: transform 0.2s;
}
.toggle input:checked + .toggle-track { background: var(--accent); }
.toggle input:checked + .toggle-track .toggle-thumb { transform: translateX(16px); }

/* Volume */
.volume {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text-dim);
}
.volume input[type="range"] {
  appearance: none;
  -webkit-appearance: none;
  width: 110px;
  height: 4px;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  border-radius: 999px;
  outline: none;
  cursor: pointer;
}
.volume input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid var(--accent);
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(107, 140, 255, 0.5);
}
.volume input[type="range"]::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid var(--accent);
  cursor: pointer;
}

/* Instrument picker for MIDI playback (MusyngKite SoundFont) */
.midi-instrument {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text-dim);
}
.midi-instrument select {
  appearance: none;
  -webkit-appearance: none;
  height: 30px;
  padding: 0 28px 0 12px;
  font-size: 13px;
  color: var(--text);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 999px;
  cursor: pointer;
  outline: none;
  /* Inline caret using background gradient */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' stroke='%23b5bcd0' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 10px center;
  transition: border-color 0.15s, background-color 0.15s;
}
.midi-instrument select:hover,
.midi-instrument select:focus-visible {
  border-color: var(--accent);
  background-color: var(--panel-2, rgba(107, 140, 255, 0.08));
}
.midi-instrument select:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
/* Native dropdown menu items inherit the OS theme by default, which clashes
   with our dark UI. Force a dark background + light text on the option list
   for both the open menu and the closed <select>. */
.midi-instrument select,
.midi-instrument select option {
  color-scheme: dark;
  background-color: #1f2230;
  color: #e6e9f0;
}
.midi-instrument select option:checked {
  background-color: #2b3148 linear-gradient(0deg, #2b3148 0%, #2b3148 100%);
  color: #ffffff;
}
.midi-instrument select option:hover {
  background-color: #353a55;
  color: #ffffff;
}

/* MIDI control: file picker + play/pause toggle */
.midi-control {
  display: inline-flex;
  align-items: center;
  gap: 0;
}
.midi-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  font-size: 13px;
  font-family: inherit;
  color: var(--text-dim);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  cursor: pointer;
  user-select: none;
  transition: background 0.2s, color 0.2s, border-color 0.2s;
}
.midi-btn:hover {
  background: rgba(107, 140, 255, 0.12);
  color: var(--text);
  border-color: rgba(107, 140, 255, 0.35);
}
.midi-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.midi-btn .midi-icon {
  width: 14px;
  height: 14px;
  fill: currentColor;
  flex-shrink: 0;
}
/* Default: show the play icon (used to start playback or open file picker) */
.midi-btn .midi-icon-pause { display: none; }
.midi-btn.is-playing {
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  color: #fff;
  border-color: transparent;
}
.midi-btn.is-playing .midi-icon-play { display: none; }
.midi-btn.is-playing .midi-icon-pause { display: inline-block; }
.midi-btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}
.midi-reload {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  margin-left: 6px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 50%;
  color: var(--text-dim);
  cursor: pointer;
  transition: background 0.2s, color 0.2s, border-color 0.2s;
}
.midi-reload[hidden] { display: none; }
.midi-name[hidden] { display: none; }
.midi-reload:hover {
  background: rgba(107, 140, 255, 0.12);
  color: var(--text);
  border-color: rgba(107, 140, 255, 0.35);
}
.midi-reload:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.midi-reload svg {
  width: 14px;
  height: 14px;
  fill: currentColor;
}
.midi-name {
  margin-left: 8px;
  font-size: 12px;
  color: var(--text-dim);
  max-width: 180px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Stage */
.stage {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 16px 18px 0px;
  gap: 22px;
}

.hint {
  font-size: 13px;
  color: var(--text-dim);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 8px 18px;
  backdrop-filter: blur(6px);
}
.hint kbd {
  display: inline-block;
  padding: 1px 7px;
  font-size: 12px;
  background: rgba(255,255,255,0.08);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 4px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  margin: 0 2px;
}

/* Piano */
.piano {
  width: min(98vw, 1360px);
  background: linear-gradient(180deg, #1c1f30 0%, #0d0f1c 100%);
  border-radius: 14px;
  border: 1px solid rgba(255,255,255,0.06);
  box-shadow: var(--shadow), 0 0 0 1px rgba(255,255,255,0.02) inset;
  overflow: hidden;
}

.piano-band {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  height: 44px;
  padding: 0 18px;
  background:
    linear-gradient(180deg, #20243a, #14172a);
  border-bottom: 1px solid rgba(0,0,0,0.5);
  box-shadow: 0 1px 0 rgba(255,255,255,0.05) inset;
}

.brand-strip {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}
.brand-strip-text {
  font-size: 13px;
  letter-spacing: 6px;
  font-weight: 800;
  background: linear-gradient(180deg, #fff 0%, #b8bcd6 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  text-shadow: 0 1px 1px rgba(0,0,0,0.6);
}

.piano-tip {
  color: var(--text-dim);
  font-size: 12px;
  white-space: nowrap;
}

.piano-keys {
  --white-count: 36;
  position: relative;
  height: clamp(160px, 22vh, 260px);
  display: flex;
  background: #06070d;
  padding: 0;
}

.key-white {
  flex: 0 0 calc(100% / var(--white-count));
  position: relative;
  background:
    linear-gradient(180deg, #ffffff 0%, #f5f6fb 92%, #e3e6f1 100%);
  border-left: 1px solid #d8dbe8;
  border-right: 1px solid #d8dbe8;
  border-bottom: 1px solid #c5c8d6;
  border-radius: 0 0 6px 6px;
  box-shadow:
    inset 0 -4px 0 rgba(0,0,0,0.05),
    inset 0 1px 0 rgba(255,255,255,0.9),
    0 6px 8px rgba(0,0,0,0.4);
  cursor: pointer;
  transition: background 0.05s ease, transform 0.05s ease, box-shadow 0.05s ease;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
  padding: 0 0 14px;
  z-index: 1;
}
.key-white:hover {
  background: linear-gradient(180deg, #f3f5fb 0%, #e9ecf5 100%);
}
.key-white.active {
  background: linear-gradient(180deg, #6b8cff 0%, #4a6be0 100%);
  box-shadow:
    inset 0 -3px 0 rgba(0,0,0,0.15),
    inset 0 2px 0 rgba(255,255,255,0.3),
    0 2px 4px rgba(0,0,0,0.5);
  transform: translateY(1px);
}
.key-white.active .key-name,
.key-white.active .key-note { color: #fff; }

.key-black {
  position: absolute;
  top: 0;
  width: calc(100% / var(--white-count) * 0.62);
  height: 64%;
  background:
    linear-gradient(180deg, #2a2d3d 0%, #15171f 60%, #0a0b10 100%);
  border: 1px solid #000;
  border-top: 0;
  border-radius: 0 0 4px 4px;
  box-shadow:
    inset 0 -3px 0 rgba(255,255,255,0.08),
    inset 0 2px 0 rgba(0,0,0,0.6),
    0 5px 8px rgba(0,0,0,0.6);
  cursor: pointer;
  transition: background 0.05s ease, transform 0.05s ease, box-shadow 0.05s ease;
  z-index: 2;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
  padding: 0 0 8px;
}
.key-black:hover {
  background: linear-gradient(180deg, #353846 0%, #1a1c25 100%);
}
.key-black.active {
  background: linear-gradient(180deg, #ff8c42 0%, #e65100 100%);
  transform: translateY(1px);
  box-shadow:
    inset 0 -1px 0 rgba(255,255,255,0.15),
    inset 0 2px 0 rgba(0,0,0,0.3),
    0 1px 2px rgba(0,0,0,0.5);
}
.key-black.active .key-name { color: #fff; }

.key-name {
  display: inline-flex;
  align-items: baseline;
  justify-content: center;
  gap: 4px;
  font-size: 12px;
  font-weight: 600;
  color: #6b7290;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  text-transform: uppercase;
  pointer-events: none; /* let mouse events fall through to the key */
}
.key-name-primary {
  display: inline-block;
}
.key-name-extra {
  font-size: 10px;
  opacity: 0.55;
  font-weight: 500;
}
.key-note {
  font-size: 11px;
  color: var(--accent);
  font-weight: 700;
  margin-top: 2px;
  pointer-events: none; /* let mouse events fall through to the key */
}
.key-black .key-name {
  color: #d8dbe8;
  font-size: 11px;
}

.key-shift-hint {
  position: absolute;
  top: 6px;
  left: 0;
  right: 0;
  text-align: center;
  font-size: 10px;
  color: rgba(255,255,255,0.45);
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  letter-spacing: 0.5px;
  pointer-events: none; /* let mouse events fall through to the key */
}

/* Keyboard binding diagram */
.keyboard-diagram {
  --u: 36px;
  width: min(96vw, 1200px);
  margin: 0 auto;
  padding: 12px 20px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow-x: auto;
  user-select: none;
  text-align: center;
}
.kb-section {
  display: inline-flex;
  flex-direction: column;
  gap: 4px;
  vertical-align: top;
  text-align: left;
}

.kb-row {
  display: flex;
  gap: 4px;
  /* Lock the row to a single key's height so a rowSpan key (e.g. Enter)
     can overflow visually without inflating the row and creating a blank
     row underneath. */
  height: calc(var(--u) + 4px);
  flex: 0 0 auto;
}

.kb-key {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: calc(var(--u) + 4px);
  flex: 0 0 var(--u);
  padding: 1px 2px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 4px;
  color: var(--text-dim);
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  position: relative;
  cursor: default;
}
.kb-key.w09   { flex-basis: calc(var(--u) * .9); }
.kb-key.w095  { flex-basis: calc(var(--u) * .95); }
.kb-key.w15   { flex-basis: calc(var(--u) * 1.5); }
.kb-key.w165   { flex-basis: calc(var(--u) * 1.65); }
.kb-key.w17  { flex-basis: calc(var(--u) * 1.7); }
.kb-key.w175  { flex-basis: calc(var(--u) * 1.75); }
.kb-key.w2    { flex-basis: calc(var(--u) * 2); }
.kb-key.w205    { flex-basis: calc(var(--u) * 2.05); }
.kb-key.w21    { flex-basis: calc(var(--u) * 2.1); }
.kb-key.w215    { flex-basis: calc(var(--u) * 2.15); }
.kb-key.w22    { flex-basis: calc(var(--u) * 2.2); }
.kb-key.w225  { flex-basis: calc(var(--u) * 2.25); }
.kb-key.w23  { flex-basis: calc(var(--u) * 2.3); }
.kb-key.w235  { flex-basis: calc(var(--u) * 2.35); }
.kb-key.w275  { flex-basis: calc(var(--u) * 2.75); }
.kb-key.w28  { flex-basis: calc(var(--u) * 2.8); }
.kb-key.w285  { flex-basis: calc(var(--u) * 2.85); }
.kb-key.w125  { flex-basis: calc(var(--u) * 1.25); }
.kb-key.w625  { flex-basis: calc(var(--u) * 6.25); }

/* L-shape keys: span the current row + the row below. The row is fixed at
   a single key's height (see .kb-row), so this key intentionally overflows
   downward to cover the position of the next row's right-most key (e.g.
   Enter covers RShift, mirroring a real ANSI keyboard). */
.kb-key.row-span-2 {
  height: calc((var(--u) + 4px) * 2 + 4px);
  align-self: flex-start;
  justify-content: flex-start;
  padding-top: 4px;
  z-index: 2;
}

.kb-key.has-note {
  background: linear-gradient(180deg, rgba(107, 140, 255, 0.22), rgba(107, 140, 255, 0.10));
  border-color: rgba(107, 140, 255, 0.45);
  box-shadow: 0 0 0 1px rgba(107, 140, 255, 0.15) inset;
  cursor: pointer;
  transition: background 0.08s ease, box-shadow 0.08s ease, transform 0.05s ease;
}
.kb-key.has-note:hover {
  background: linear-gradient(180deg, rgba(107, 140, 255, 0.32), rgba(107, 140, 255, 0.16));
  border-color: rgba(107, 140, 255, 0.6);
}
.kb-key.has-note:active { transform: translateY(1px); }
.kb-key.has-note .kb-key-label { color: var(--text); }

/* Active highlight: mirrors the piano's key highlight when the bound note
   is triggered either by keyboard, mouse, or by clicking the diagram. */
.kb-key.has-note.active {
  background: linear-gradient(180deg, rgba(107, 140, 255, 0.55), rgba(107, 140, 255, 0.30));
  border-color: rgba(107, 140, 255, 0.85);
  box-shadow: 0 0 14px rgba(107, 140, 255, 0.55);
}
.kb-key.has-note.active .kb-key-label,
.kb-key.has-note.active .kb-key-notes { color: #fff; }

/* Modifier keys (e.g. ` and Backspace that toggle black-key mode) are
   tinted with a soft purple so they stand out from regular keys without
   screaming for attention. */
.kb-key.is-modifier {
  background: linear-gradient(180deg, rgba(168, 123, 255, 0.16), rgba(168, 123, 255, 0.06));
  border-color: rgba(168, 123, 255, 0.40);
  box-shadow: 0 0 0 1px rgba(168, 123, 255, 0.10) inset;
}
.kb-key.is-modifier:hover {
  background: linear-gradient(180deg, rgba(168, 123, 255, 0.24), rgba(168, 123, 255, 0.10));
  border-color: rgba(168, 123, 255, 0.55);
}
.kb-key.is-modifier .kb-key-label { color: #c4a8f0; }
.kb-key-sublabel {
  font-size: 12px;
  font-weight: 600;
  color: #c4a8f0;
  margin-top: 1px;
  letter-spacing: 0.5px;
  line-height: 1;
}

.kb-key-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.3px;
  line-height: 1;
}

.kb-key-notes {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  margin-top: 2px;
  line-height: 1.1;
}
.kb-note-white {
  font-size: 11px;
  color: var(--accent);
  font-weight: 700;
  letter-spacing: 0.2px;
}
.kb-note-black {
  font-size: 8px;
  color: rgba(234, 232, 244, 0.7);
  font-weight: 600;
}

.kb-legend {
  display: flex;
  gap: 16px;
  font-size: 11px;
  color: var(--text-dim);
  margin-top: 10px;
  flex-wrap: wrap;
}
.kb-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.kb-legend-swatch {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 3px;
}
.kb-legend-swatch.bound {
  background: linear-gradient(180deg, rgba(107, 140, 255, 0.45), rgba(107, 140, 255, 0.20));
  border: 1px solid rgba(107, 140, 255, 0.5);
}
.kb-legend-swatch.empty {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.1);
}

/* Footer */
.footer {
  text-align: center;
  padding: 8px 18px 8px;
  font-size: 12px;
  color: var(--text-dim);
  opacity: 0.6;
}

/* Responsive */
@media (max-width: 900px) {
  .piano-keys { height: 200px; }
  .key-name { font-size: 9px; }
  .key-note { font-size: 8px; }
  .brand h1 { font-size: 16px; }
  .topbar { padding: 14px 16px; }
  .topbar-actions { gap: 14px; }
  .midi-name { max-width: 120px; }
}
@media (max-width: 600px) {
  .piano-keys { height: 170px; }
  .piano-tip { display: none; }
  .topbar { flex-direction: column; gap: 10px; align-items: flex-start; }
  .topbar-actions { width: 100%; justify-content: space-between; }
  .hint { font-size: 12px; padding: 6px 12px; text-align: center; }
  .midi-name { display: none; }
  .midi-control { flex: 0 0 auto; }
}

/* Touch mode: dual-row fullscreen piano for mobile/touch */
.touch-piano {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  height: 100%;
  min-height: 0;
  background: linear-gradient(180deg, #1c1f30 0%, #0d0f1c 100%);
  border-radius: 14px;
  border: 1px solid rgba(255, 255, 255, 0.06);
  box-shadow: var(--shadow), 0 0 0 1px rgba(255, 255, 255, 0.02) inset;
  padding: 8px;
  overflow: hidden;
}

/* The default browser [hidden] rule uses display:none, but our .touch-piano
   uses display:flex with higher specificity, so we need to re-assert the
   hidden behavior explicitly. */
.touch-piano[hidden] {
  display: none;
}

.touch-row {
  position: relative;
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: #06070d;
  border-radius: 8px;
  overflow: hidden;
}

.touch-row-label {
  position: absolute;
  top: 6px;
  left: 10px;
  z-index: 3;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 1.5px;
  color: rgba(255, 255, 255, 0.5);
  text-transform: uppercase;
  pointer-events: none;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}

.touch-row-keys {
  flex: 1;
  --white-count: 1;
  position: relative;
  height: 100%;
  display: flex;
  background: #06070d;
  padding: 0;
  min-height: 0;
}

/* In touch mode, the original piano + keyboard diagram are hidden so the
   dual-row touch layout can fill the stage. The footer is also hidden to
   give the keys as much screen real-estate as possible on phones. */
body.touch-mode .piano,
body.touch-mode .keyboard-diagram,
body.touch-mode .footer {
  display: none;
}

body.touch-mode .stage {
  padding: 10px;
  gap: 0;
  justify-content: stretch;
}

body.touch-mode .topbar {
  padding: 8px 14px;
}

body.touch-mode .brand h1 {
  font-size: 15px;
}

body.touch-mode .topbar-actions {
  gap: 12px;
}

body.touch-mode .toggle {
  font-size: 12px;
}

/* In touch mode, hide the keyboard-binding labels on keys — they are
   keyboard-only hints and just add noise on a touch surface. The note
   name (C4 etc.) is still shown so players know what they're tapping. */
body.touch-mode .key-name {
  display: none !important;
}

body.touch-mode .key-black .key-shift-hint {
  display: none !important;
}

body.touch-mode .key-white {
  padding: 0 0 10px;
}

body.touch-mode .key-note {
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 0.3px;
  color: var(--accent);
}

body.touch-mode .key-black {
  height: 60%;
  padding: 0 0 6px;
}

/* In touch mode the dual-row renderTouchRow() helper sets three CSS
   custom properties on each black key: --bk-start (the offset of the
   boundary between two white keys, as a % of the row width), --bk-half
   (half the black key's own width), and --bk-size (the black key's
   width). In landscape we drive `left` from those, in portrait we drive
   `top` instead — see the @media block below. */
body.touch-mode .touch-row-keys .key-black {
  left: calc(var(--bk-start, 0%) - var(--bk-half, 0%));
  top: 0;
  width: var(--bk-size, 6%);
}

/* On very short landscape screens (typical phone landscape), keep the two
   rows but reduce gap so both rows stay usable. */
@media (max-height: 480px) {
  body.touch-mode .touch-piano {
    gap: 4px;
    padding: 4px;
  }
  body.touch-mode .touch-row-label {
    font-size: 9px;
    letter-spacing: 1px;
  }
}

/* Portrait phones: keep the dual-row touch piano, but lay it out as two
   side-by-side columns of vertical keys instead of stacked rows. The
   layout is mirrored top↔bottom vs. the landscape version, so the lower
   range (C2–E4) sits on the left and the higher range (F4–C7) on the
   right. White keys stretch full column width with equal vertical share;
   black keys are anchored to the right edge of their parent white key
   with 60% of its height, matching the visual rhythm of a real piano
   viewed from the side. The whole topbar group is also pulled to the
   right edge as a narrow column so the piano gets the long edge. */
@media (orientation: portrait) and (max-width: 768px) {
  body.touch-mode .topbar {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: 56px;
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
    padding: 8px 6px;
    z-index: 5;
    border-bottom: none;
    border-left: 1px solid var(--border);
  }
  body.touch-mode .topbar-actions {
    gap: 18px;
  }
  body.touch-mode .topbar h1 {
    display: none;
  }
  body.touch-mode .topbar .toggle,
  body.touch-mode .topbar .volume {
    flex-direction: column;
    gap: 12px;
    font-size: 12px;
    transform: rotate(180deg);
  }
  body.touch-mode .topbar .toggle-track {
    transform: rotate(90deg);
  }
  body.touch-mode .topbar .toggle span:last-child,
  body.touch-mode .topbar .volume span:first-child {
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    white-space: nowrap;
  }
  body.touch-mode .topbar .volume input[type="range"] {
    width: 120px !important;
    transform: rotate(90deg);
  }

  body.touch-mode .stage {
    padding: 0;
    padding-right: 56px; /* leave room for the rotated topbar */
  }

  body.touch-mode .touch-piano {
    flex-direction: row-reverse; /* high range on the left, low on the right */
    height: 100%;
  }
  body.touch-mode .touch-row {
    flex: 1 1 0;
    width: auto;
    max-width: none;
  }
  body.touch-mode .touch-row-keys {
    flex-direction: column;
  }
  body.touch-mode .touch-row-label {
    margin-left: 20px;
    font-size: 12px;
    letter-spacing: 2px;
  }

  /* White keys: full column width, equal vertical share. The existing
     landscape flex sizing uses flex: 0 0 calc(100% / var(--white-count))
     so we override width/height here. align-items → flex-start keeps the
     note label against the left edge of the key (away from the black
     key column on the right). */
  body.touch-mode .touch-row-keys .key-white {
    width: 100% !important;
    height: calc(100% / var(--white-count)) !important;
    flex: 0 0 calc(100% / var(--white-count)) !important;
    align-items: flex-start !important;
    padding: 6px 0 6px 8px !important;
  }

  /* Black keys: anchor to the right edge of the parent white key, drive
     their vertical position from --bk-start (the same offset the
     landscape layout uses for `left`). The black key is centered on the
     boundary between two white keys, so it visually "belongs" to both
     — matching the way sharps/flats sit between naturals on a real
     piano keyboard, just rotated 90°. In portrait the key is a wide,
     short sliver anchored to the right edge of the column: 50% of the
     column width and only 4% of the column height, so it reads as a
     thin horizontal bar at the boundary between two white keys. */
  body.touch-mode .touch-row-keys .key-black {
    left: auto !important;
    right: 0 !important;
    top: calc(var(--bk-start, 0%) - var(--bk-half, 0%)) !important;
    width: 60% !important;
    height: 3.5% !important;
  }

  /* Note label: rotate to read along the long axis of each key and pin
     it to the left edge of the white key (the side away from the black
     key column). The text reads top→bottom (the natural reading order
     when the head is tilted to the right) so it's instantly readable
     without the 180° flip that landscape touch mode uses. */
  body.touch-mode .key-note {
    writing-mode: vertical-rl;
    align-self: flex-start;
    font-size: 12px;
    font-weight: 800;
    letter-spacing: 1px;
  }
}

/* Animations */
@keyframes ripple {
  0% { box-shadow: 0 0 0 0 rgba(107, 140, 255, 0.6); }
  100% { box-shadow: 0 0 0 18px rgba(107, 140, 255, 0); }
}
.key-white.active {
  animation: ripple 0.4s ease-out;
}

/* Rainbow mode: each white-key pitch class (C/D/E/F/G/A/B) gets a soft
   pastel color. Black keys keep their dark fill so the visual rhythm of
   the keyboard is preserved. The note-name label at the bottom of the
   key inherits a darker variant of the same hue for legibility. */
body.rainbow-mode .key-white[data-name^="C"] { background: linear-gradient(180deg, #ffb3b3 0%, #ff8b8b 100%); border-color: #e57373; }
body.rainbow-mode .key-white[data-name^="D"] { background: linear-gradient(180deg, #ffd6a3 0%, #ffb570 100%); border-color: #e0945a; }
body.rainbow-mode .key-white[data-name^="E"] { background: linear-gradient(180deg, #fff3a3 0%, #ffe066 100%); border-color: #d4b942; }
body.rainbow-mode .key-white[data-name^="F"] { background: linear-gradient(180deg, #b8f0c8 0%, #87e5a3 100%); border-color: #5cb876; }
body.rainbow-mode .key-white[data-name^="G"] { background: linear-gradient(180deg, #b3eced 0%, #6fd9d9 100%); border-color: #4cb0b0; }
body.rainbow-mode .key-white[data-name^="A"] { background: linear-gradient(180deg, #b8d4f5 0%, #7aafe6 100%); border-color: #4f87c6; }
body.rainbow-mode .key-white[data-name^="B"] { background: linear-gradient(180deg, #e2c4f0 0%, #c792ea 100%); border-color: #a26fc4; }

body.rainbow-mode .key-white[data-name^="C"] .key-note { color: #b73a3a; }
body.rainbow-mode .key-white[data-name^="D"] .key-note { color: #b86a25; }
body.rainbow-mode .key-white[data-name^="E"] .key-note { color: #a08620; }
body.rainbow-mode .key-white[data-name^="F"] .key-note { color: #2f8a52; }
body.rainbow-mode .key-white[data-name^="G"] .key-note { color: #2a8080; }
body.rainbow-mode .key-white[data-name^="A"] .key-note { color: #2e5a96; }
body.rainbow-mode .key-white[data-name^="B"] .key-note { color: #6e3d96; }

body.rainbow-mode .key-white.active {
  filter: brightness(1.08) saturate(1.15);
}
body.rainbow-mode .key-black.active {
  filter: brightness(1.4);
}
