    /* ---- color tokens ----
       3 bases + error; mid/high are derived from foreground so changing
       --foreground retints the whole UI. --contrast is the emphasis pole
       (white on dark themes, black on light themes); applyTheme() sets it
       automatically from the background's luminance. */
    :root {
      --background: #000;
      --foreground: #7df;
      --accent:     #6c9;
      --error:      #e66;
      --contrast:   #fff;
      --mid:  color-mix(in srgb, var(--foreground) 40%, var(--background));   /* toned down */
      --high: color-mix(in srgb, var(--foreground) 45%, var(--contrast));     /* emphasis */
    }
    * { box-sizing: border-box; }
    /* Controls answer taps only: iOS otherwise reads two quick presses (a
       play button pressed again) as a double-tap and zooms the page. Pan and
       pinch-zoom still work; touch-action is not inherited, hence the list. */
    button, input, select, label, summary, [role=button], .cm-gutters { touch-action: manipulation; }
    /* Only the score and the console are text to select: line numbers, menus,
       labels and panels are not, so a drag or long-press never grabs them.
       Fields stay selectable — Safari will not type into one that is not. */
    body { -webkit-user-select: none; user-select: none; }
    .cm-content, #log, input, textarea {
      -webkit-user-select: text;
      user-select: text;
    }
    /* The document never scrolls: html and body are pinned to the (layout)
       viewport. iOS shortens that viewport while the on-screen keyboard is
       up; a body sized in 100dvh then hung past it, the page became
       scrollable, and an iPad left it scrolled after the keyboard closed.
       (While the keyboard is up, watchSoftKeyboard in index.html pins the
       app to the visible part of the screen.) */
    html, body {
      position: fixed;
      inset: 0;
      margin: 0;
      overflow: hidden;
      overscroll-behavior: none;
    }
    body {
      background: var(--background);
      color: var(--foreground);
      font-family: 'Open Sans', sans-serif;
      display: flex;
      flex-direction: column;
      /* Standalone PWA: with viewport-fit=cover the layout fills the screen,
         so inset content past notches / the home indicator. env() is 0 in an
         ordinary browser window, leaving the desktop layout untouched. */
      padding: env(safe-area-inset-top) env(safe-area-inset-right)
               env(safe-area-inset-bottom) env(safe-area-inset-left);
    }
    /* On-screen keyboard up (watchSoftKeyboard, index.html): the app is
       pinned to the part of the screen the keyboard leaves, and the console
       and the piano roll give their height to the editor. */
    html.soft-kb body {
      top: var(--kb-top);
      bottom: auto;
      height: var(--kb-h);
      padding-bottom: 0;
    }
    html.soft-kb #hDivider,
    html.soft-kb #consolePane,
    html.soft-kb #rollDivider,
    html.soft-kb #rollPane { display: none; }

    /* ---- top bar ---- */
    #topbar {
      display: flex;
      align-items: center;
      gap: 0.25rem;
      padding: 0 0.5rem;
      height: 36px;
      flex-shrink: 0;
      background: var(--background);
      border-bottom: 1px solid var(--mid);
    }
    #topbar select,
    .tb-btn,
    .kbd-btn,
    .menu-btn,
    .menu-item,
    .ms-btn {
      font-family: inherit;
      border-radius: 2px;
      cursor: pointer;
    }
    #topbar select,
    .tb-btn,
    .kbd-btn,
    .menu-btn,
    .menu-item,
    .menu-item-shortcut {
      font-size: 0.72rem;
    }
    #topbar select {
      background: var(--background);
      border: 1px solid var(--mid);
      color: var(--foreground);
      padding: 0.2rem 0.4rem;
    }
    #topbar select:hover { border-color: var(--high); color: var(--high); }
    .tb-btn,
    .kbd-btn {
      background: var(--background);
      border: 1px solid var(--mid);
      color: var(--foreground);
      white-space: nowrap;
      padding: 0.15rem 0.5rem;
    }
    @media (hover: hover) { .tb-btn:hover { border-color: var(--high); color: var(--high); } }
    .tb-btn:disabled { opacity: 0.3; cursor: default; }
    .tb-btn.active { border-color: var(--foreground); color: var(--background); background: var(--foreground); }
    #topbar .spacer { flex: 1; }
    /* Transport on a touch screen: drawn at the desktop's size, but each
       button answers across the bar's full height and halfway into the gap
       beside it, so a finger lands on one or the other. */
    @media (pointer: coarse) {
      #btnStop, #btnPlay { position: relative; }
      #btnPlay { margin-left: 12px; }
      #btnStop::after, #btnPlay::after {
        content: '';
        position: absolute;
        top: 50%;
        left: -9px;   /* 8px past the 1px border: half the 16px gap */
        right: -9px;
        height: 36px;
        transform: translateY(-50%);
      }
    }
    #btnPanel {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      line-height: 1;
      padding: 0 0.4rem;
    }
    #btnPanel svg {
      width: 0.95rem;
      height: 0.95rem;
      display: block;
      fill: currentColor;
      pointer-events: none;
    }

    /* ---- menu dropdowns ---- */
    .menu-wrap { position: relative; }
    /* Stretch top-level menu buttons to the full bar height so the dropdown,
       anchored at 100%, opens flush with the top bar's bottom border. */
    #topbar > .menu-wrap {
      align-self: stretch;
      display: flex;
      align-items: center;
    }
    .menu-btn {
      background: transparent;
      border: none;
      color: var(--foreground);
      padding: 0.2rem 0.5rem;
      white-space: nowrap;
    }
    @media (hover: hover) { .menu-btn:hover { color: var(--high); } }
    .menu-wrap.open .menu-btn { color: var(--high); }
    .menu-dropdown {
      display: none;
      position: absolute;
      top: 100%;
      left: 0;
      background: var(--background);
      border: 1px solid var(--mid);
      border-radius: 2px;
      z-index: 100;
      min-width: 200px;
    }
    .menu-wrap.open > .menu-dropdown { display: block; }
    .menu-item {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 1rem;
      width: 100%;
      padding: 0.35rem 0.75rem;
      background: none;
      border: none;
      color: var(--foreground);
      text-align: left;
      white-space: nowrap;
    }
    .menu-sep { height: 0; border-top: 1px solid var(--mid); margin: 0.25rem 0; }
    .menu-item[hidden], .menu-sep[hidden] { display: none; }
    /* A section's name inside a menu: not a command. */
    .menu-label {
      padding: 0.3rem 0.75rem 0.1rem;
      color: var(--mid);
      font-size: 0.72rem;
      white-space: nowrap;
      cursor: default;
    }
    .menu-item-shortcut {
      color: var(--mid);
    }
    .submenu-wrap {
      position: relative;
    }
    .submenu-dropdown {
      left: 100%;
      top: 0;
      margin-left: 0;
    }
    /* Unfolded in place when there is no room on the right (openSubmenu). */
    .submenu-wrap.inline > .submenu-dropdown {
      position: static;
      min-width: 0;
      border: none;
      border-radius: 0;
      padding-left: 0.75rem;
    }
    .submenu-wrap.inline.open > .menu-item .submenu-arrow { transform: rotate(45deg); }
    .submenu-arrow {
      width: 0.38rem;
      height: 0.38rem;
      border: solid currentColor;
      border-width: 0 1.5px 1.5px 0;
      transform: rotate(-45deg);
      color: var(--mid);
      flex-shrink: 0;
      pointer-events: none;
    }
    @media (hover: hover) { .menu-item:hover { background: color-mix(in srgb, var(--foreground) 14%, var(--background)); color: var(--high); } }
    @media (hover: hover) { .menu-item:hover .menu-item-shortcut { color: var(--high); } }
    @media (hover: hover) { .menu-item:hover .submenu-arrow { color: var(--high); } }

    /* ---- main area ---- */
    #main {
      display: flex;
      flex: 1;
      min-height: 0;
      overflow: hidden;
      position: relative;
      --panel-width: 400px;
    }

    /* ---- left column: editor + console ---- */
    #leftCol {
      display: flex;
      flex-direction: column;
      flex: 1;
      min-width: 0;
      min-height: 0;
      overflow: hidden;
    }
    #editorWrap {
      flex: 1;
      min-height: 0;
      overflow: hidden;
      border-bottom: none;
      position: relative;
      background: var(--background);
    }
    /* Oscilloscope visualizer canvas, faint behind the editor text. */
    #vizCanvas {
      position: absolute;
      inset: 0;
      z-index: 0;
      pointer-events: none;
      opacity: 0.5;
      display: none;
    }
    #editorWrap.viz-on #vizCanvas { display: block; }
    #editorWrap .cm-editor {
      height: 100%;
      font-size: var(--editor-font-size, 14px);
      background: var(--background);
      position: relative;
      z-index: 1;
    }
    /* While the roll is on, make the editor layers transparent so it shows through. */
    #editorWrap.viz-on .cm-editor,
    #editorWrap.viz-on .cm-scroller,
    #editorWrap.viz-on .cm-gutters { background: transparent; }
    #editorWrap .cm-scroller { overflow: auto; }
    #editorWrap .cm-content { color: var(--foreground); }
    #editorWrap .cm-gutters {
      background: var(--background);
      border-right: none;
      color: var(--mid);
    }
    /* Playhead highlights are drawn as a layer of rectangles over the text (not
       text spans), so they never affect line-wrap layout. */
    .cm-playheadLayer { pointer-events: none; }
    /* Per-track playhead cursors — outline the sounding token (no fill) */
    .cm-playTok-0, .cm-playTok-1, .cm-playTok-2, .cm-playTok-3 {
      border-radius: 2px;
      box-shadow: 0 0 0 1px var(--foreground);
    }
    /* Active step sequence ([...]) — outline the whole literal while it sounds */
    .cm-playSeq {
      border-radius: 2px;
      box-shadow: inset 0 0 0 1px var(--foreground);
    }
    /* Bracket structure, drawn as a layer for the same reason as the playhead
       (never touches the text DOM, so line wrapping is unaffected). */
    .cm-bracketLayer { pointer-events: none; }
    /* The form the cursor sits in — faint fill, single-line forms only */
    .cm-bracketForm {
      border-radius: 2px;
      background: color-mix(in srgb, var(--foreground) 8%, transparent);
    }
    /* The matching pair itself */
    .cm-bracketMatch {
      border-radius: 2px;
      background: color-mix(in srgb, var(--accent) 30%, transparent);
    }
    /* Unclosed opener / stray closer — underline, never auto-corrected */
    .cm-bracketBad {
      box-shadow: inset 0 -2px 0 var(--error);
    }
    /* Unmatched-bracket count, top-right of the editor; click to jump */
    #bracketStatus {
      position: absolute;
      top: 0.25rem;
      right: 0.75rem;
      z-index: 2;
      padding: 0.1rem 0.4rem;
      border: none;
      border-radius: 3px;
      font: inherit;
      font-size: 0.7rem;
      color: var(--error);
      background: color-mix(in srgb, var(--error) 12%, var(--background));
      cursor: pointer;
      opacity: 0.85;
    }
    #bracketStatus:hover { opacity: 1; }
    /* ---- Find / replace panel + match highlights ---- */
    /* The panel is CodeMirror's own (search()); only its colors are ours. It
       docks at the bottom, clear of the unmatched-bracket badge above. */
    #editorWrap .cm-panels {
      background: var(--background);
      color: var(--foreground);
      font-size: 0.72rem;
    }
    #editorWrap .cm-panels-bottom { border-top: 1px solid var(--mid); }
    #editorWrap .cm-panel.cm-search {
      padding: 0.35rem 0.5rem;
      line-height: 2;
    }
    #editorWrap .cm-panel.cm-search label { margin-right: 0.5rem; color: var(--mid); }
    #editorWrap .cm-panel.cm-search input[type="checkbox"] {
      accent-color: var(--accent);
      vertical-align: -0.1em;
      margin-right: 0.2rem;
    }
    #editorWrap .cm-textfield {
      font-family: inherit;
      font-size: 0.72rem;
      color: var(--foreground);
      background: color-mix(in srgb, var(--foreground) 8%, var(--background));
      border: 1px solid var(--mid);
      border-radius: 2px;
      padding: 0.15rem 0.3rem;
      margin-right: 0.35rem;
    }
    #editorWrap .cm-textfield:focus { outline: none; border-color: var(--foreground); }
    #editorWrap .cm-button {
      font-family: inherit;
      font-size: 0.72rem;
      color: var(--foreground);
      background: none;
      background-image: none;
      border: 1px solid var(--mid);
      border-radius: 2px;
      padding: 0.1rem 0.4rem;
      margin-right: 0.35rem;
      cursor: pointer;
    }
    #editorWrap .cm-button:hover,
    #editorWrap .cm-button:active {
      background: color-mix(in srgb, var(--foreground) 15%, var(--background));
      background-image: none;
    }
    #editorWrap .cm-panel.cm-search [name="close"] {
      color: var(--foreground);
      background: none;
      border: none;
      font-size: 1rem;
      padding: 0 0.3rem;
      cursor: pointer;
    }
    /* Every match of the query, with the current one accented. These are text
       spans (CodeMirror's own decorations), unlike the playhead/bracket layers,
       so they exist only while the panel is open. */
    #editorWrap .cm-searchMatch {
      border-radius: 2px;
      background: color-mix(in srgb, var(--accent) 22%, transparent);
    }
    #editorWrap .cm-searchMatch-selected {
      background: color-mix(in srgb, var(--accent) 45%, transparent);
    }
    /* Other occurrences of whatever is selected — what Cmd/Ctrl+D takes next. */
    #editorWrap .cm-selectionMatch {
      border-radius: 2px;
      background: color-mix(in srgb, var(--foreground) 14%, transparent);
    }
    /* Build-confirmation flash: fill the background of the text (fitted to each
       line's text width, not the full line) then fade out. Uses --foreground
       (which always contrasts the background) so it shows on any theme. */
    .cm-buildFlashLayer { pointer-events: none; }
    .cm-buildFlash {
      border-radius: 2px;
      background: var(--foreground);
      animation: buildFlash 0.3s ease-out forwards;
    }
    @keyframes buildFlash {
      from { opacity: 1; }
      to { opacity: 0; }
    }
    @media (prefers-reduced-motion: reduce) {
      .cm-buildFlash { animation-duration: 0.01s; }
    }

    /* ---- Interactive value editing ---- */
    /* Hover affordance: whole-token dotted underline + faint wash. */
    /* Edit > Logical Editor: the notes its condition picks */
    .cm-logical-match { background: color-mix(in srgb, var(--accent) 35%, transparent); border-radius: 2px; }
    .cm-logical-shared { background: none; outline: 1px dashed var(--accent); }
    .modal-overlay.logical-overlay { background: none; justify-content: flex-end; align-items: flex-start; pointer-events: none; }
    .logical-modal { pointer-events: auto; margin: 3.2rem 1rem 0 0; width: min(330px, 92vw); box-shadow: 0 4px 18px rgba(0,0,0,0.35); }
    .logical-modal .le-pair { display: flex; gap: 0.3rem; }
    .logical-modal input[type=text] {
      width: 4.5rem; background: var(--background); color: var(--foreground); border: 1px solid var(--mid);
      border-radius: 2px; padding: 0.15rem 0.3rem; font-family: inherit; font-size: 0.72rem;
    }
    .logical-modal .le-ops { margin-top: 0.6rem; padding-top: 0.6rem; border-top: 1px solid var(--mid); }
    .logical-modal .le-status { margin-top: 0.6rem; color: var(--mid); font-size: 0.7rem; min-height: 1em; }
    .import-field[hidden] { display: none; }
    .cm-valHover {
      border-radius: 2px;
      text-decoration: underline dotted var(--foreground);
      text-underline-offset: 3px;
      background: color-mix(in srgb, var(--foreground) 10%, transparent);
    }
    /* Floating hint that follows the pointer over an editable value. */
    .val-hint {
      position: fixed; z-index: 60; display: none;
      pointer-events: none;
      background: color-mix(in srgb, var(--foreground) 12%, var(--background));
      color: var(--high);
      border: 1px solid var(--mid);
      border-radius: 4px;
      padding: 2px 6px;
      font: 11px 'Open Sans', sans-serif;
      white-space: nowrap;
    }
    /* Shared popup: slider / stepper / piano / bar info. Matches the panels /
       modals — pure-black fill, thin toned border, sharp 2px corners. */
    .val-popup {
      position: fixed; z-index: 70;
      background: var(--background);
      border: none;
      border-radius: 2px;
      padding: 8px 10px;
      width: max-content; /* size to the content, not a fixed width */
      font: 12px 'Open Sans', sans-serif;
      color: var(--foreground);
    }
    .val-row { display: flex; align-items: center; gap: 6px; margin: 4px 0; }
    .val-label { min-width: 34px; color: var(--mid); }
    /* Steppers reuse the transport (.tb-btn) look; only the square size differs. */
    .val-step {
      width: 22px; height: 22px; flex: none;
      padding: 0; font-size: 14px; line-height: 1;
    }
    .val-row input[type=range] { flex: 1; min-width: 90px; accent-color: var(--foreground); }
    .val-num {
      flex: 1; min-width: 70px; text-align: right;
      background: var(--background); color: var(--foreground);
      border: 1px solid var(--mid); border-radius: 2px; padding: 2px 4px;
      -moz-appearance: textfield; appearance: textfield; /* no spinner */
    }
    .val-num::-webkit-outer-spin-button,
    .val-num::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
    /* One-octave piano for note tokens — same construction/look as the dock
       keyboard (#kbKeys): white grid + absolute black overlay, .kb-key styling. */
    .val-piano {
      position: relative;
      height: 4rem;
      width: 182px;
      user-select: none; touch-action: none;
      overflow: hidden; border-radius: 2px;
      background: var(--background);
      margin: 4px 0 2px;
    }
    .val-piano .kb-key.cur { box-shadow: inset 0 0 0 2px var(--high); }
    .val-bar-info { line-height: 1.5; }
    .val-bar-head { color: var(--high); font-weight: 600; }
    .val-stale { color: var(--error); font-weight: 400; }

    /* drag dividers */
    #hDivider, #rollDivider {
      height: 4px;
      background: var(--background);
      border-top: 1px solid var(--mid);
      border-bottom: 1px solid var(--mid);
      cursor: row-resize;
      flex-shrink: 0;
    }
    #hDivider:hover, #rollDivider:hover { background: var(--mid); }
    #rollDivider { touch-action: none; }

    /* MMLisp > View > Source off: the text and line numbers hide (the editor
       keeps its place for the oscilloscope behind it); with the oscilloscope
       off too the editor area folds away — unless a prompt there is showing
       (a shared link's Play, the folder grant) — and the piano roll takes the
       column. */
    #leftCol.source-off #editorWrap .cm-editor,
    #leftCol.source-off #bracketStatus { visibility: hidden; }
    #leftCol.source-off.scope-off #editorWrap:not(:has(> #sharedPlay:not([hidden]), > #folderAccess:not([hidden]))) {
      display: none;
    }
    #leftCol.source-off.scope-off #editorWrap:not(:has(> #sharedPlay:not([hidden]), > #folderAccess:not([hidden]))) ~ #rollDivider {
      display: none;
    }
    #leftCol.source-off.scope-off #editorWrap:not(:has(> #sharedPlay:not([hidden]), > #folderAccess:not([hidden]))) ~ #rollPane {
      flex: 1;
      height: auto !important; /* over the dragged height */
    }

    /* piano roll pane (under the editor) */
    #rollPane {
      height: 220px;
      min-height: 80px;
      display: flex;
      flex-direction: column;
      flex-shrink: 0;
      background: var(--background);
    }
    #rollPane[hidden], #rollDivider[hidden] { display: none; }
    /* The zoom sits over the roll's top-right corner. */
    #rollZoom {
      position: absolute;
      top: 4px;
      right: 6px;
      z-index: 1;
      background: var(--background);
    }
    #rollZoom .lib-seg-btn { flex: 0 0 auto; padding: 0.15rem 0.6rem; }
    #rollWrap { flex: 1; min-height: 0; position: relative; }
    #rollCanvas {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
      display: block;
      touch-action: none;
    }
    #rollTip {
      position: absolute;
      pointer-events: none;
      font-size: 0.66rem;
      font-family: ui-monospace, monospace;
      color: var(--foreground);
      background: var(--background);
      border: 1px solid var(--mid);
      border-radius: 3px;
      padding: 1px 5px;
      white-space: nowrap;
    }

    /* console */
    #consolePane {
      height: 100px;
      min-height: 40px;
      max-height: 60vh;
      overflow: hidden;
      display: flex;
      flex-direction: column;
      flex-shrink: 0;
      border-top: none;
    }
    #log {
      flex: 1;
      min-height: 0;
      overflow-y: auto;
      padding: 0.4rem 0.6rem;
      font-size: 0.72rem;
      color: var(--foreground);
      line-height: 1.5;
      background: var(--background);
    }
    #log .err { color: var(--error); }
    #log .info { color: var(--foreground); }
    #log .warn { color: var(--accent); }

    /* ---- right panel ---- */
    #rightPanel {
      position: relative;
      width: var(--panel-width);
      flex: 0 0 var(--panel-width);
      min-height: 0;
      display: flex;
      flex-direction: column;
      background: var(--background);
      border-left: 1px solid var(--mid);
      overflow: hidden;
      transform: translateX(0);
      transition: transform 0.18s ease, border-color 0.18s ease;
    }
    #rightPanel,
    #rightPanel * {
      -webkit-user-select: none;
      user-select: none;
    }
    #rightPanelBody {
      flex: 1;
      min-height: 0;
      overflow-y: auto;
      overflow-x: hidden;
      overscroll-behavior: contain;
    }
    @media (max-width: 480px) {
      #main { flex-direction: column; }
      #consolePane {
        height: 70px;
      }
      #rightPanel {
        position: absolute;
        right: 0;
        top: 0;
        bottom: 0;
        z-index: 5;
        width: 100%;
        flex-basis: auto;
        left: 0;
        border-left: none;
        transform: translateX(0);
        transition: transform 0.18s ease, border-color 0.18s ease;
      }
    }
    #rightPanel.collapsed {
      margin-right: calc(var(--panel-width) * -1);
      transform: translateX(100%);
      border-left-color: transparent;
      pointer-events: none;
      overflow: hidden;
    }
    @media (max-width: 480px) {
      #rightPanel.collapsed {
        margin-right: 0;
        width: 100%;
        flex-basis: auto;
        transform: translateX(100%);
      }
    }

    .rack-section {
      padding: 0.75rem;
    }
    .rack-title {
      font-size: 0.72rem;
      font-weight: bold;
      color: var(--foreground);
      margin-bottom: 0.5rem;
      cursor: pointer;
      user-select: none;
    }
    /* Same open/close chevrons as the editor's code-fold gutter (⌄ / ›). */
    .rack-title::before {
      content: '⌄';
      display: inline-block;
      width: 0.8em;
      margin-right: 0.4rem;
      text-align: center;
    }
    .rack-section.collapsed .rack-title::before { content: '›'; }
    .rack-section.collapsed .rack-title { margin-bottom: 0; }
    .rack-section.collapsed .rack-body { display: none; }
    .rack-title-row {
      display: flex;
      align-items: center;
      gap: 0.4rem;
    }
    .rack-title-row::before { margin-right: 0; }
    #fmParamStatus {
      margin-left: auto;
      color: var(--mid);
      font-size: 0.58rem;
      font-weight: normal;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    /* ---- knobs / sliders (right panel) ---- */
    .param-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
      gap: 0.5rem;
    }
    /* Sound Effects: one button per def-se, lit while the effect plays. */
    .se-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
      gap: 0.4rem;
      -webkit-touch-callout: none;
    }
    .se-btn { padding: 0.35rem 0.5rem; overflow: hidden; text-overflow: ellipsis; touch-action: none; }
    .se-btn .se-num { color: var(--mid); margin-right: 0.4em; font-size: 0.6rem; }
    .se-btn.active .se-num { color: var(--background); }
    .knob-wrap { display: flex; flex-direction: column; gap: 0; }
    .knob-label {
      font-size: 0.58rem;
      color: var(--mid);
      display: flex;
      justify-content: space-between;
    }
    .knob-label span.val { color: var(--foreground); }
    /* Panel numbers are tap-to-edit (openPanelValuePopup). */
    .knob-label span.val, .ch-vol-val { cursor: pointer; }
    @media (hover: hover) {
      .knob-label span.val:hover, .ch-vol-val:hover { text-decoration: underline dotted; }
    }
    input[type=range] {
      appearance: none;
      -webkit-appearance: none;
      width: 100%;
      height: 14px;
      background: var(--background);
      border: 1px solid var(--mid);
      border-radius: 7px;
      outline: none;
      cursor: pointer;
    }
    input[type=range]::-webkit-slider-thumb {
      -webkit-appearance: none;
      width: 11px; height: 11px;
      border-radius: 50%;
      background: var(--foreground);
      border: none;
    }
    input[type=range]::-moz-range-thumb {
      width: 11px; height: 11px;
      border-radius: 50%;
      background: var(--foreground);
      border: none;
    }
    input[type=range]:hover { border-color: var(--high); }
    input[type=range]:disabled { opacity: 0.4; cursor: default; }
    /* TIME (Global): the song's position, full width; the loop start marked. */
    .time-val { color: var(--foreground); font-variant-numeric: tabular-nums; }
    /* The track is exactly the range's box (block, no margin), so the mark
       runs border to border, drawn like the border. */
    .time-track { position: relative; }
    .time-track input[type=range] { display: block; margin: 0; }
    .time-loop {
      position: absolute;
      top: 0;
      bottom: 0;
      width: 1px;
      background: var(--mid);
      pointer-events: none;
    }
    .time-track:hover .time-loop { background: var(--high); }
    /* MIDI: the CC a slider answers to; MIDI Learn picks a slider by its
       whole .knob-wrap, so the range itself takes no press while learning. */
    .knob-label .midi-cc { color: var(--accent); margin-left: auto; margin-right: 0.3em; }
    body.midi-learn #rightPanel .knob-wrap { cursor: pointer; border-radius: 3px; outline: 1px dashed var(--mid); outline-offset: 1px; }
    body.midi-learn #rightPanel .knob-wrap input[type=range] { pointer-events: none; }
    body.midi-learn #rightPanel .knob-wrap.midi-learn-target { outline: 1px solid var(--accent); background: color-mix(in srgb, var(--accent) 15%, transparent); }
    /* Touch: the panel's sliders are driven from JS (index.html,
       setRangeFromX) through their whole .knob-wrap — a sideways drag sets the
       value, up/down scrolls the panel — with a track and thumb big enough for
       a finger. */
    @media (pointer: coarse) {
      .knob-wrap { touch-action: pan-y; }
      .knob-wrap input[type=range] { pointer-events: none; }
      input[type=range] { height: 20px; border-radius: 10px; }
      input[type=range]::-webkit-slider-thumb { width: 17px; height: 17px; }
      input[type=range]::-moz-range-thumb { width: 17px; height: 17px; }
    }

    .op-grid {
      display: grid;
      grid-template-columns: repeat(4, 1fr);
      gap: 0.5rem;
    }
    .op-col-title {
      font-size: 0.58rem;
      color: var(--mid);
      text-transform: uppercase;
      letter-spacing: 0.08em;
      display: flex;
      align-items: center;
      justify-content: space-between;
    }
    .op-col-title input[type=checkbox] {
      appearance: none;
      -webkit-appearance: none;
      width: 0.8rem;
      height: 0.8rem;
      margin: 0;
      padding: 0;
      cursor: pointer;
      flex-shrink: 0;
      box-sizing: border-box;
      position: relative;
      background: var(--background);
      border: 1px solid var(--mid);
      border-radius: 2px;
    }
    .op-col-title input[type=checkbox]:not(:disabled):hover { border-color: var(--high); }
    .op-col-title input[type=checkbox]:focus-visible {
      outline: 1px solid var(--high);
      outline-offset: 1px;
    }
    .op-col-title input[type=checkbox]:checked::after {
      content: '';
      position: absolute;
      left: 50%;
      top: 50%;
      width: 1.5px;
      height: 140%; /* box diagonal (√2) — spans corner to corner */
      background: var(--background);
      transform: translate(-50%, -50%) rotate(45deg);
    }
    /* Carrier / modulator roles — default is modulator */
    .op-col { --op-color: var(--accent); display: flex; flex-direction: column; gap: 0.5rem; }
    .op-col.carrier { --op-color: var(--foreground); }
    .op-col .op-col-title { color: var(--op-color); }
    .op-col .op-col-title input[type=checkbox]:checked {
      background: var(--op-color);
      border-color: var(--op-color);
    }
    .op-col input[type=range]::-webkit-slider-thumb { background: var(--op-color); }
    .op-col input[type=range]::-moz-range-thumb { background: var(--op-color); }
    .op-col .knob-label span.val { color: var(--op-color); }
    .rack-body { display: flex; flex-direction: column; gap: 0.5rem; }
    /* Dynamic Parameters (def-val sliders) — same grid/size as FM params */
    .dyn-param-body {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
      gap: 0.5rem;
    }
    /* ALG/FB / AMS/FMS on the left, algorithm diagram spanning both rows at right */
    .alg-grid {
      display: grid;
      grid-template-columns: 1fr 1fr 2fr;
      grid-template-areas: "a b d" "c e d";
      gap: 0.5rem;
      align-items: start;
    }
    .alg-diagram {
      grid-area: d;
      width: 100%;
      max-width: 140px; /* keep the diagram from stretching wide in its column */
      height: 100%;
      min-height: 58px;
      justify-self: center;
      cursor: pointer; /* click to preview the last-played note */
    }
    #fmParamSection.fm-disabled .alg-diagram { opacity: 0.4; cursor: default; }
    /* per-operator ADSR envelope graph at the bottom of each op column */
    .op-env { width: 100%; height: 30px; min-height: 30px; display: block; }
    #fmParamSection.fm-disabled .op-env { opacity: 0.4; }

    /* FM panel disabled state */
    #fmParamSection.fm-disabled .knob-label,
    #fmParamSection.fm-disabled .op-col-title {
      color: var(--mid);
    }
    #fmParamSection.fm-disabled .knob-label .val,
    #fmParamSection.fm-disabled .op-col .knob-label .val {
      color: var(--mid);
    }
    #fmParamSection.fm-disabled input[type=range] {
      background: var(--background);
      border-color: var(--mid);
      cursor: not-allowed;
      opacity: 0.6;
    }
    #fmParamSection.fm-disabled input[type=range]::-webkit-slider-thumb {
      background: var(--mid);
    }
    #fmParamSection.fm-disabled input[type=range]::-moz-range-thumb {
      background: var(--mid);
    }
    #fmParamSection.fm-disabled input[type=checkbox] {
      cursor: not-allowed;
      opacity: 0.55;
    }
    #fmParamSection.fm-disabled .op-col-title input[type=checkbox]:checked {
      background: var(--mid);
      border-color: var(--mid);
    }

    /* channel strips */
    .ch-strips-row {
      display: flex;
      gap: 0.3rem;
      overflow-x: auto;
      padding-bottom: 4px;
    }
    .ch-col {
      display: flex;
      flex-direction: column;
      gap: 0.25rem;
      align-items: stretch;
      flex: 0 0 auto;
      min-width: 2rem;
    }
    .ch-btns {
      position: relative;
      display: flex;
      flex-direction: column;
      gap: 0.25rem;
    }
    /* Rough VU overlay on the [F1][M][S] stack: foreground fill rising from bottom. */
    .ch-vu {
      position: absolute;
      inset: 0;
      transform-origin: bottom center;
      transform: scaleY(0);
      background: var(--foreground);
      opacity: 0.22;
      border-radius: 2px;
      pointer-events: none;
      transition: transform 0.08s linear;
    }
    .ms-btn {
      background: var(--background);
      border: 1px solid var(--mid);
      color: var(--mid);
      font-size: 0.58rem;
      width: 100%;
      text-align: center;
    }
    .ms-btn:hover { border-color: var(--high); color: var(--high); }
    .ms-btn.muted  { background: var(--background); border-color: var(--error); color: var(--error); }
    .ms-btn.soloed { background: var(--background); border-color: var(--accent); color: var(--accent); }
    .ms-btn.ch-sel { background: var(--background); border-color: var(--foreground); color: var(--foreground); }
    .ms-btn:disabled { opacity: 0.25; cursor: default; }
    .ch-knob {
      width: 1.15rem;
      height: 1.15rem;
      margin: 0.3rem auto 0;
      border-radius: 50%;
      background: var(--background);
      border: 1px solid var(--mid);
      position: relative;
      cursor: ns-resize;
      flex: 0 0 auto;
      touch-action: none;
    }
    .ch-knob:hover { border-color: var(--high); }
    @media (pointer: coarse) { .ch-knob { width: 1.6rem; height: 1.6rem; } }
    .ch-vol-val {
      font-size: 0.55rem;
      color: var(--mid);
      text-align: center;
    }
    .ch-knob-ind {
      position: absolute;
      left: 50%;
      bottom: 50%;
      width: 1.5px;
      height: 42%;
      margin-left: -0.75px;
      background: var(--foreground);
      border-radius: 1px;
      transform-origin: bottom center;
    }

    /* bottom keyboard */
    #keyboardDock {
      border-top: none;
      background: var(--background);
      padding: 0.55rem;
      display: flex;
      flex-direction: column;
      gap: 0.45rem;
      flex-shrink: 0;
      border-radius: 8px;
      overflow: hidden;
    }
    /* A held key is a note, never a long-press: no iOS callout, no selection. */
    #keyboardDock,
    #keyboardDock *,
    .val-piano,
    .val-piano * {
      -webkit-user-select: none;
      user-select: none;
      -webkit-touch-callout: none;
    }
    #keyboardControls {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 0.5rem;
      overflow-x: auto;
      scrollbar-width: thin;
      scrollbar-color: var(--mid) transparent;
      padding-bottom: 0.1rem;
    }
    .kbd-group {
      display: flex;
      align-items: center;
      gap: 0.35rem;
      min-width: 0;
    }
    .kbd-group.kbd-oct {
      margin-left: auto;
      flex-shrink: 0;
    }
    .kbd-btn {
      line-height: normal;
      height: auto;
      min-width: auto;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      text-align: center;
    }
    .kbd-btn[hidden] { display: none; }
    .kbd-btn svg {
      width: 0.8rem;
      height: 0.8rem;
      display: block;
      pointer-events: none;
      fill: currentColor;
    }
    .kbd-btn:hover { border-color: var(--high); color: var(--high); }
    .kbd-btn.active {
      background: var(--foreground);
      color: var(--background);
    }
    #kbKeys {
      position: relative;
      height: 4rem;
      user-select: none;
      touch-action: none;
      overflow: hidden;
      border: none;
      border-radius: 2px;
      background: var(--background);
    }
    .kb-white-row {
      display: grid;
      grid-template-columns: repeat(14, minmax(0, 1fr));
      gap: 2px;
      height: 100%;
      background: var(--background);
    }
    .kb-black-row {
      position: absolute;
      left: 0;
      right: 0;
      top: 0;
      height: 60%;
      pointer-events: none;
    }
    .kb-key {
      border: none;
      border-radius: 0 0 2px 2px;
      background: var(--foreground);
      color: var(--background);
      font-size: 0.58rem;
      display: flex;
      align-items: flex-end;
      justify-content: center;
      padding-bottom: 0.3rem;
      cursor: pointer;
      position: relative;
      outline: none;
    }
    .kb-oct-marker {
      font-size: 0.58rem;
      color: var(--mid);
      line-height: 1;
      pointer-events: none;
    }
    .kb-key.black {
      position: absolute;
      top: 0;
      background: var(--background);
      color: var(--foreground);
      height: 100%;
      width: calc((100% / 14) - 2px);
      transform: translateX(-50%);
      z-index: 1;
      pointer-events: auto;
      justify-content: center;
      padding-bottom: 0.15rem;
    }
    .kb-key.down {
      box-shadow: inset 0 0 0 2px var(--foreground);
      background: var(--high);
      color: var(--background);
    }
    .kb-key.black.down {
      box-shadow: inset 0 0 0 2px var(--high);
      background: var(--foreground);
      color: var(--background);
    }
    #keyboardDock.kb-disabled .kbd-btn,
    #keyboardDock.kb-disabled .kb-key {
      opacity: 0.25;
      cursor: not-allowed;
    }

    /* ---- loading overlay (covers the half-built UI until init is done) ---- */
    #loadingOverlay {
      position: fixed;
      inset: 0;
      z-index: 500;
      display: flex;
      align-items: center;
      justify-content: center;
      background: var(--background);
      opacity: 1;
      transition: opacity 0.25s ease;
    }
    #loadingOverlay.is-loaded { opacity: 0; pointer-events: none; }
    .loading-spinner {
      width: 34px;
      height: 34px;
      border: 3px solid color-mix(in srgb, var(--foreground) 25%, transparent);
      border-top-color: var(--accent);
      border-radius: 50%;
      animation: loading-spin 0.8s linear infinite;
    }
    @keyframes loading-spin { to { transform: rotate(360deg); } }
    @media (prefers-reduced-motion: reduce) {
      .loading-spinner { animation: none; }
    }

    /* ---- file drop overlay ----
       Shown while files are dragged over the window. pointer-events: none is
       load-bearing: the overlay must never become the drag target itself, or
       crossing into it would fire dragleave and hide it. */
    #dropOverlay {
      position: fixed;
      inset: 0;
      z-index: 300;
      pointer-events: none;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 0.4rem;
      background: color-mix(in srgb, var(--background) 82%, transparent);
      outline: 2px dashed var(--foreground);
      outline-offset: -10px;
      font: 14px 'Open Sans', sans-serif;
      color: var(--foreground);
      text-align: center;
      padding: 0 1rem;
    }
    #dropOverlay[hidden] { display: none; }
    .drop-hint { color: var(--mid); font-size: 12px; }
    /* Shift held: the (import …) branch is the active one, so swap the emphasis. */
    #dropOverlay.as-import .drop-open { color: var(--mid); }
    #dropOverlay.as-import .drop-import { color: var(--high); }
    #dropOverlay:not(.as-import) .drop-open { color: var(--high); }

    /* ---- modal (custom theme editor) ---- */
    .modal-overlay {
      position: fixed;
      inset: 0;
      z-index: 200;
      display: flex;
      align-items: center;
      justify-content: center;
      background: rgba(0,0,0,0.5);
    }
    .modal-overlay[hidden] { display: none; }
    .modal {
      background: var(--background);
      border: 1px solid var(--foreground);
      border-radius: 4px;
      padding: 1rem 1.25rem;
      min-width: 260px;
    }
    .modal-title {
      color: var(--foreground);
      font-size: 0.78rem;
      font-weight: bold;
      margin-bottom: 0.75rem;
    }
    .theme-fields {
      display: flex;
      flex-direction: column;
      gap: 0.5rem;
    }
    .theme-field {
      display: flex;
      align-items: center;
      gap: 0.5rem;
    }
    .theme-field label {
      flex: 1;
      color: var(--foreground);
      font-size: 0.72rem;
    }
    .theme-field input[type=color] {
      width: 1.5rem;
      height: 1.5rem;
      padding: 0;
      border: 1px solid var(--mid);
      border-radius: 2px;
      background: none;
      cursor: pointer;
    }
    .theme-field input[type=text] {
      width: 5.5rem;
      background: var(--background);
      border: 1px solid var(--mid);
      color: var(--foreground);
      border-radius: 2px;
      padding: 0.15rem 0.4rem;
      font-family: inherit;
      font-size: 0.72rem;
    }
    .modal-actions {
      display: flex;
      justify-content: flex-end;
      gap: 0.5rem;
      margin-top: 1rem;
    }
    /* About / Licenses info modals */
    .info-modal { max-width: min(460px, 90vw); }
    .info-body { color: var(--foreground); font-size: 0.72rem; line-height: 1.55; }
    .info-body p { margin: 0 0 0.6rem; }
    .info-body a { color: var(--accent); }
    .license-row { margin: 0 0 0.55rem; }
    .license-row b { color: var(--foreground); }

    /* A reference entry in the editor: completion info and the hover card */
    .ref-card { max-width: 26rem; padding: 0.35rem 0.5rem; font-size: 0.72rem; line-height: 1.4; }
    .ref-card-syntax { font-weight: bold; margin-bottom: 0.2rem; white-space: pre-wrap; }
    .ref-card-summary { opacity: 0.85; }

    /* The play mark, drawn as the toolbar's own triangle (an SVG mask) so it
       looks the same on every platform — never the colour emoji some systems
       substitute for ▶. Sized to the text it sits in; painted in its colour. */
    .ico-play {
      display: inline-block;
      width: 0.62em;
      height: 0.62em;
      vertical-align: 0.02em;
      background: currentColor;
      -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpolygon points='1,0 10,5 1,10'/%3E%3C/svg%3E") center / contain no-repeat;
      mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpolygon points='1,0 10,5 1,10'/%3E%3C/svg%3E") center / contain no-repeat;
    }

    /* Side panel tabs: Params | Library */
    .panel-tabs {
      display: flex;
      flex-shrink: 0;
      border-bottom: 1px solid var(--mid);
    }
    .panel-tab {
      flex: 1;
      background: none;
      border: 0;
      border-bottom: 2px solid transparent;
      color: var(--foreground);
      font: inherit;
      font-size: 0.72rem;
      font-weight: bold;
      letter-spacing: 0.08em;
      padding: 0.45rem 0;
      opacity: 0.6;
      cursor: pointer;
    }
    .panel-tab.active { opacity: 1; border-bottom-color: var(--foreground); }

    /* Library: one searchable list over the presets, snippets and scores */
    #libraryPane {
      flex: 1;
      min-height: 0;
      display: flex;
      flex-direction: column;
      gap: 0.4rem;
      padding: 0.6rem 0.75rem;
    }
    #libraryPane[hidden] { display: none; }
    #keyboardDock[hidden] { display: none; }
    #rightPanel .lib-search {
      -webkit-user-select: text;
      user-select: text;
      width: 100%;
      box-sizing: border-box;
      background: var(--background);
      border: 1px solid var(--mid);
      border-radius: 3px;
      color: var(--foreground);
      font: inherit;
      font-size: 0.8rem;
      padding: 0.35rem 0.5rem;
    }
    .lib-search:focus { outline: 1px solid var(--foreground); outline-offset: -1px; }
    .lib-filters { display: flex; flex-direction: column; gap: 0.3rem; }
    .lib-chips { display: flex; flex-wrap: wrap; gap: 0.25rem; }
    /* The source: one of a set, so one joined bar split evenly across the pane
       — not chips, which toggle on their own. */
    .lib-seg {
      display: flex;
      border: 1px solid var(--mid);
      border-radius: 3px;
      overflow: hidden;
    }
    .lib-seg-btn {
      flex: 1 1 0;
      min-width: 0;
      background: none;
      border: none;
      border-left: 1px solid var(--mid);
      color: var(--foreground);
      font: inherit;
      font-size: 0.66rem;
      padding: 0.2rem 0.25rem;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      cursor: pointer;
    }
    .lib-seg-btn:first-child { border-left: none; }
    .lib-seg-btn:hover { background: color-mix(in srgb, var(--foreground) 18%, var(--background)); }
    .lib-seg-btn.active {
      background: color-mix(in srgb, var(--foreground) 28%, var(--background));
      font-weight: bold;
    }
    .lib-chip {
      background: none;
      border: 1px solid var(--mid);
      border-radius: 3px;
      color: var(--foreground);
      font: inherit;
      font-size: 0.66rem;
      padding: 0.15rem 0.5rem;
      cursor: pointer;
    }
    /* A chip is as wide as its bold label, picked or not, so picking one does
       not shift the row: a hidden bold copy of the label holds the width. */
    .lib-chip { display: inline-flex; flex-direction: column; align-items: center; }
    .lib-chip::after {
      content: attr(data-label);
      font-weight: bold;
      height: 0;
      overflow: hidden;
      visibility: hidden;
      pointer-events: none;
    }
    .lib-chip:hover { background: color-mix(in srgb, var(--foreground) 18%, var(--background)); }
    .lib-chip:disabled { opacity: 0.35; cursor: default; }
    .lib-chip:disabled:hover { background: none; }
    .lib-chip.active {
      background: color-mix(in srgb, var(--foreground) 28%, var(--background));
      border-color: var(--foreground);
      font-weight: bold;
    }
    .lib-list {
      flex: 1;
      min-height: 0;
      overflow-y: auto;
      overscroll-behavior: contain;
      border: 1px solid var(--mid);
      border-radius: 3px;
    }
    .lib-list:focus { outline: none; }
    .lib-row, .lib-group {
      display: flex;
      align-items: center;
      gap: 0.4rem;
      padding: 0.3rem 0.45rem;
      color: var(--foreground);
      font-size: 0.72rem;
      cursor: pointer;
    }
    .lib-nested { padding-left: 1.1rem; }
    .lib-group { font-weight: bold; }
    .lib-group::before { content: '\203A'; width: 0.6rem; opacity: 0.7; }
    .lib-group.open::before { content: '\2304'; }
    .lib-row:hover, .lib-group:hover { background: color-mix(in srgb, var(--foreground) 18%, var(--background)); }
    .lib-row.active, .lib-group.active {
      background: color-mix(in srgb, var(--foreground) 24%, var(--background));
      outline: 1px solid var(--foreground);
      outline-offset: -1px;
    }
    .lib-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .lib-kind { opacity: 0.55; font-size: 0.64rem; font-weight: normal; white-space: nowrap; }
    .lib-mini {
      background: none;
      border: 1px solid var(--mid);
      border-radius: 2px;
      color: var(--foreground);
      font: inherit;
      font-size: 0.64rem;
      font-weight: normal;
      padding: 0.05rem 0.3rem;
      cursor: pointer;
    }
    .lib-mini:hover { background: color-mix(in srgb, var(--foreground) 22%, var(--background)); }
    .lib-empty { padding: 0.6rem; font-size: 0.72rem; opacity: 0.6; }
    .lib-note {
      color: var(--foreground);
      opacity: 0.75;
      font-size: 0.66rem;
      min-height: 2.2em;
      max-height: 32%;
      overflow-y: auto;
      white-space: pre-wrap;
      flex-shrink: 0;
    }
    /* Fingers: taller rows and buttons. */
    @media (pointer: coarse) {
      .lib-chip { padding: 0.35rem 0.7rem; font-size: 0.74rem; }
      .lib-seg-btn { padding: 0.4rem 0.25rem; font-size: 0.74rem; }
      .lib-row, .lib-group { padding: 0.6rem 0.55rem; font-size: 0.8rem; }
      .lib-nested { padding-left: 1.2rem; }
      .lib-mini { padding: 0.3rem 0.6rem; font-size: 0.72rem; }
    }

    /* Share: the link modal, and the play prompt a shared link opens with */
    .share-modal { width: min(520px, 92vw); }
    .share-url {
      width: 100%;
      box-sizing: border-box;
      background: var(--background);
      border: 1px solid var(--mid);
      color: var(--foreground);
      border-radius: 2px;
      padding: 0.3rem 0.4rem;
      font-family: inherit;
      font-size: 0.72rem;
    }
    .share-meta { color: var(--mid); margin-top: 0.4rem !important; }
    .share-warn { color: var(--error); }
    .share-actions { flex-wrap: wrap; }
    #sharedPlay, #folderAccess {
      position: absolute;
      left: 50%;
      bottom: 1.5rem;
      transform: translateX(-50%);
      z-index: 3;
      display: flex;
      align-items: center;
      gap: 0.5rem;
      max-width: calc(100% - 2rem);
      padding: 0.6rem 1.2rem;
      border: 1px solid var(--foreground);
      border-radius: 4px;
      font: inherit;
      font-size: 0.85rem;
      font-weight: 600;
      color: var(--background);
      background: var(--foreground);
      cursor: pointer;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    #sharedPlay[hidden], #folderAccess[hidden] { display: none; }

    /* Video export: the length field, and the recording badge */
    .video-field { display: flex; align-items: center; gap: 0.6rem; }
    .video-field label { flex: 1; }
    .video-field input { width: 6rem; }
    #recBadge {
      position: fixed;
      top: 0.4rem;
      left: 50%;
      transform: translateX(-50%);
      z-index: 150;
      display: flex;
      align-items: center;
      gap: 0.5rem;
      padding: 0.25rem 0.4rem 0.25rem 0.7rem;
      border: 1px solid var(--error);
      border-radius: 4px;
      background: var(--background);
      color: var(--foreground);
      font-size: 0.75rem;
      font-variant-numeric: tabular-nums;
    }
    #recBadge[hidden] { display: none; }
    #recBadge .rec-dot {
      width: 0.6rem;
      height: 0.6rem;
      border-radius: 50%;
      background: var(--error);
      animation: rec-blink 1s steps(2, start) infinite;
    }
    @keyframes rec-blink { to { visibility: hidden; } }

    /* Song import options (showImportDialog) */
    .import-modal { max-width: min(560px, 92vw); max-height: 86vh; display: flex; flex-direction: column; }
    .import-summary { color: var(--foreground); font-size: 0.72rem; line-height: 1.5; margin-bottom: 0.75rem; }
    .import-fields, .import-rows { display: flex; flex-direction: column; gap: 0.4rem; }
    .import-rows { overflow-y: auto; margin-top: 0.75rem; padding-top: 0.6rem; border-top: 1px solid var(--mid); min-height: 0; }
    .import-field, .import-row {
      display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 0.15rem 0.75rem;
      color: var(--foreground); font-size: 0.72rem;
    }
    .import-field small { grid-column: 1 / -1; color: var(--mid); font-size: 0.66rem; }
    .import-field input[type=number], .import-field select, .import-row select {
      background: var(--background); color: var(--foreground); border: 1px solid var(--mid);
      border-radius: 2px; padding: 0.15rem 0.3rem; font-family: inherit; font-size: 0.72rem;
    }
    .import-field input[type=number] { width: 6rem; }
