    /* ---- embedded typefaces --------------------------------------------------
       Self-hosted rather than linked, so the page renders identically on every
       OS and still works with no network.

       What this replaces was entirely platform-proprietary: Avenir Next
       Condensed and SF Mono ship only on Apple systems and Consolas only on
       Windows, so the same page was three different designs depending on where
       it was opened — and on Linux it fell all the way back to generic
       sans-serif. Roboto Condensed and JetBrains Mono are the closest open-licensed
       stand-ins at the same 0.6em monospace advance, so nothing reflows.

       These are the variable files, one per subset, declaring a weight range
       rather than a value. The UI uses five weights (400, 500, 600, 700, 800);
       shipping static 400 and 700 would have been slightly smaller but left the
       other three to be faux-bolded by the browser, which smears badly at the
       letter-spacing these headings use.

       Latin, Latin Extended and Greek are covered — the Chaos Engine's rho needs
       the last of those. CJK, emoji, arrows and box-drawing exist in no Latin
       webfont and still come from the system, which is correct.

       JetBrains Mono rather than Roboto Mono for the monospace: Roboto Mono has
       no U+2192, and the chord readout joins every progression with an arrow.

       SIL Open Font License 1.1 — see fonts/OFL.txt. */
    @font-face {
      font-family: 'Roboto Condensed';
      font-style: normal;
      font-weight: 100 900;
      font-display: swap;
      src: url(fonts/robotocondensed-greek.woff2) format('woff2');
      unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
    }
    @font-face {
      font-family: 'Roboto Condensed';
      font-style: normal;
      font-weight: 100 900;
      font-display: swap;
      src: url(fonts/robotocondensed-latin-ext.woff2) format('woff2');
      unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
    }
    @font-face {
      font-family: 'Roboto Condensed';
      font-style: normal;
      font-weight: 100 900;
      font-display: swap;
      src: url(fonts/robotocondensed-latin.woff2) format('woff2');
      unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
    }
    @font-face {
      font-family: 'JetBrains Mono';
      font-style: normal;
      font-weight: 100 800;
      font-display: swap;
      src: url(fonts/jetbrainsmono-greek.woff2) format('woff2');
      unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
    }
    @font-face {
      font-family: 'JetBrains Mono';
      font-style: normal;
      font-weight: 100 800;
      font-display: swap;
      src: url(fonts/jetbrainsmono-latin-ext.woff2) format('woff2');
      unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
    }
    @font-face {
      font-family: 'JetBrains Mono';
      font-style: normal;
      font-weight: 100 800;
      font-display: swap;
      src: url(fonts/jetbrainsmono-latin.woff2) format('woff2');
      unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
    }

    /* '43 — black lacquer, brass and a neon sign over the door. Art Deco gold on
       a midnight panel for the band, electric teal for everything that belongs
       to the club. The old variable names are kept (cyan is the primary accent,
       magenta the secondary) so every shared rule below still reads. */
    :root{
      --panel:#10151b; --panel-2:#151b22; --panel-3:#080b0e;
      --ink:#f1e9d6; --ink-dim:#8f96a0;
      --cyan:#e0b05a; --cyan-dim:#8d6c2f;
      --magenta:#38e0c4; --magenta-hi:#9ff3e4; --electric:#b98d45;
      --amber:#e0b05a;
      --gold:#f2cf85; --gold-dim:#6f5a2c;
      --amber-hi:#f5d99b; --red:#ff5f6d;
      --line:#232c35; --bevel:#34404c; --lip:#05070a;
      --lcd:#070a0d;
      --disp:"Roboto Condensed","Avenir Next Condensed","Arial Narrow",sans-serif;
      --mono:"JetBrains Mono",ui-monospace,"SF Mono",Menlo,Consolas,monospace;
    }
    * { box-sizing: border-box; margin: 0; padding: 0; }
    body {
      font-family: var(--disp);
      /* The page surround: a deep bottle green centred just above the middle,
         falling to near-black at the edges — the colour of a velvet booth in a
         supper club, far enough round the wheel from the brass to set the panel
         off without fighting it. Fixed, because the ellipse is sized to the
         viewport; left to scroll it stretches over the page and the centre
         drifts off-screen. */
      background: radial-gradient(ellipse at 50% 40%, #0f2a26 0%, #05090a 100%);
      background-attachment: fixed;
      background-color: #05090a;
      color: var(--ink);
      padding: 24px 12px 48px;
      min-height: 100vh;
    }
    .app-container {
      max-width: 960px;
      margin: 0 auto;
      position: relative;
      background: linear-gradient(180deg, var(--panel-2), var(--panel) 12%, var(--panel) 88%, #0a0e12);
      border: 1px solid #000;
      border-radius: 10px;
      box-shadow: 0 24px 70px rgba(0,0,0,.7), 0 0 40px rgba(224,176,90,.05), inset 0 1px 0 var(--bevel);
      padding: 20px 22px 26px;
    }
    /* A double hairline under the header — the most Art Deco thing a rule can do. */
    .app-header {
      position: relative; margin-bottom: 18px; padding-bottom: 14px;
      border-bottom: 1px solid var(--gold-dim);
      box-shadow: 0 3px 0 -2px var(--panel), 0 4px 0 -2px rgba(224,176,90,.28);
    }
    .brand {
      display: flex; align-items: center; justify-content: center;
      gap: 15px; padding: 0 206px; flex-wrap: wrap;
    }
    .brand-icon {
      width: 52px; height: 52px; display: block; flex-shrink: 0;
      /* the icon's own corner — 22.37% is the iOS app-icon radius, and a
         percentage keeps it right at every size the icon is drawn */
      border-radius: 22.37%;
      box-shadow: 0 3px 12px rgba(0,0,0,.6), 0 0 18px rgba(224,176,90,.25);
    }
    h1 {
      font-size: 30px; font-weight: 700; letter-spacing: .06em;
      text-transform: uppercase; margin-bottom: 3px;
      text-shadow: 0 0 18px rgba(224,176,90,.25);
    }
    h1 em { font-style: normal; color: var(--magenta); text-shadow: 0 0 18px rgba(56,224,196,.4); }
    .tagline { font-size: 12px; letter-spacing: .22em; text-transform: uppercase; color: var(--ink-dim); }
    .brand-text { text-align: left; }
    /* Header controls sit as one group in the top-right corner; the brand's
       horizontal padding below is sized to keep the title clear of them. */
    .header-actions {
      position: absolute; top: 0; right: 0;
      display: flex; align-items: center; gap: 8px;
    }
    .help-btn {
      width: 32px; height: 32px; padding: 0; flex-shrink: 0;
      display: flex; align-items: center; justify-content: center; border-radius: 50%;
      font-size: 15px; line-height: 1; letter-spacing: 0; color: var(--cyan);
      background: linear-gradient(180deg, #1e2630, #121820);
      box-shadow: 0 2px 0 var(--lip), inset 0 1px 0 var(--bevel);
    }
    .help-btn:hover { border-color: var(--cyan); color: var(--cyan); }
    .store-btn {
      display: inline-flex; align-items: center; gap: 7px; flex-shrink: 0;
      height: 32px; padding: 0 13px; border-radius: 16px;
      font-family: var(--disp); font-size: 11px; font-weight: 700;
      letter-spacing: .1em; text-transform: uppercase; white-space: nowrap;
      color: var(--cyan); text-decoration: none;
      background: linear-gradient(180deg, #1e2630, #121820);
      border: 1px solid #000;
      box-shadow: 0 2px 0 var(--lip), inset 0 1px 0 var(--bevel);
      transition: border-color .1s, color .1s;
    }
    .store-btn:hover { border-color: var(--cyan); color: var(--cyan); }
    .store-btn:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
    .store-btn svg { display: block; flex-shrink: 0; }
    /* The labelled pill needs ~206px reserved either side of the brand to keep the
       title centred and clear of it, and below roughly 1000px that reservation is
       what makes the title wrap. So the label drops at exactly that point and the
       button becomes a circle matching the help icon, which needs only ~82px. */
    @media (max-width: 1000px) {
      .brand { padding: 0 82px; }
      .store-btn { width: 32px; padding: 0; justify-content: center; border-radius: 50%; }
      .store-btn .store-label { display: none; }
      /* The tagline is the widest thing in the brand, so it — not the title — is
         what decides when the block wraps under its own icon. Easing both back a
         little buys the width the second control costs. */
      h1 { font-size: 26px; }
      .tagline { font-size: 10.5px; letter-spacing: .14em; }
    }

    /* --- modals --- */
    .modal-backdrop {
      position: fixed; inset: 0; background: rgba(4, 7, 9, .86);
      display: flex; align-items: center; justify-content: center;
      padding: 24px 14px; z-index: 50;
    }
    .modal-backdrop[hidden] { display: none; }
    .modal {
      position: relative; width: min(680px, 100%); max-height: 84vh; overflow-y: auto;
      background: linear-gradient(180deg, var(--panel-2), var(--panel) 10%, var(--panel) 90%, #0a0e12);
      border: 1px solid #000; border-radius: 10px;
      box-shadow: 0 24px 70px rgba(0,0,0,.75), 0 0 40px rgba(56,224,196,.06), inset 0 1px 0 var(--bevel);
      padding: 0 26px 26px; color: var(--ink);
      scrollbar-width: thin; scrollbar-color: var(--bevel) #0a0e12;
    }
    .modal::-webkit-scrollbar { width: 10px; }
    .modal::-webkit-scrollbar-track { background: #0a0e12; border-radius: 6px; margin: 6px 0; }
    .modal::-webkit-scrollbar-thumb {
      background: linear-gradient(180deg, #34404c, #1b232b);
      border: 1px solid #000; border-radius: 6px; box-shadow: inset 0 1px 0 var(--bevel);
    }
    .modal::-webkit-scrollbar-thumb:hover { background: linear-gradient(180deg, #46525e, #242e38); }
    .modal::-webkit-scrollbar-thumb:active { background: var(--cyan); }
    .modal-head {
      position: sticky; top: 0; z-index: 3; margin: 0 -26px 12px; padding: 16px 26px 12px;
      background: var(--panel-2); border-bottom: 1px solid var(--line);
      display: flex; align-items: center; gap: 14px;
    }
    .modal h2 { color: var(--cyan); font-size: 15px; letter-spacing: .2em; flex: 1; min-width: 0; margin: 0; padding: 0; }
    .modal h3 { color: var(--magenta); font-size: 11px; letter-spacing: .22em; text-transform: uppercase; margin: 18px 0 6px; }
    .modal p, .modal li { font-family: var(--mono); font-size: 11.5px; line-height: 1.75; color: var(--ink-dim); }
    .modal b { color: var(--ink); font-weight: 400; }
    .modal i { color: var(--cyan); font-style: normal; }
    .modal ul, .modal ol { margin: 4px 0 0 18px; }
    .modal li { margin-bottom: 3px; }
    .modal-lead { color: var(--ink); }
    .modal-credit { color: var(--cyan); margin-top: 6px; }
    .modal-credit b { color: var(--cyan); }
    .modal-fine { font-size: 10.5px; margin-top: 12px; opacity: .8; }
    .modal-contact { margin-top: 10px; }
    /* shares the header store button's pill language, so the manual's one
       outbound action reads as a control rather than as another body link */
    .modal a.contact-btn {
      display: inline-flex; align-items: center; gap: 7px;
      height: 30px; padding: 0 14px; border-radius: 15px;
      font-family: var(--disp); font-size: 11px; font-weight: 700;
      letter-spacing: .1em; text-transform: uppercase; white-space: nowrap;
      color: var(--cyan); text-decoration: none;
      background: linear-gradient(180deg, #1e2630, #121820);
      border: 1px solid #000;
      box-shadow: 0 2px 0 var(--lip), inset 0 1px 0 var(--bevel);
      transition: border-color .1s, color .1s;
    }
    .modal a.contact-btn:hover { border-color: var(--cyan); color: var(--cyan); }
    .modal a.contact-btn:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
    .modal a { color: var(--magenta); }
    .modal-close {
      flex-shrink: 0; width: 30px; height: 30px; padding: 0;
      display: flex; align-items: center; justify-content: center; letter-spacing: 0;
      font-size: 18px; line-height: 1; border-radius: 5px; color: var(--ink-dim); background: var(--panel-3);
    }
    .modal-close:hover { color: var(--red); border-color: var(--red); }

    /* --- export: single-file vs stems --- */
    .export-choice { display: grid; gap: 10px; margin: 4px 0 14px; }
    .choice-btn {
      display: block; width: 100%; text-align: left;
      padding: 13px 15px; border-radius: 8px;
      border: 1px solid var(--line); background: var(--panel-3);
      letter-spacing: normal; text-transform: none; font-weight: 400;
      box-shadow: inset 0 1px 0 #1e2630;
    }
    .choice-btn:hover:not(:disabled) { border-color: var(--cyan); background: #16202a; }
    .choice-btn .choice-name {
      display: block; font-family: var(--disp); font-size: 13px; font-weight: 700;
      letter-spacing: .14em; text-transform: uppercase; color: var(--cyan);
    }
    .choice-btn .choice-desc {
      display: block; margin-top: 5px; font-family: var(--mono); font-size: 11px;
      line-height: 1.6; color: var(--ink-dim);
    }

    /* --- export progress dialog --- */
    .modal-narrow { width: min(420px, 100%); max-height: none; }
    .export-stage { font-family: var(--mono); font-size: 12px; letter-spacing: .04em; color: var(--ink); margin: 4px 0 12px; }
    .export-bar {
      box-sizing: border-box; height: 12px; background: #080b0e;
      border: 1px solid rgba(224,176,90,.5); border-radius: 4px;
      box-shadow: inset 0 1px 3px #000; overflow: hidden;
    }
    .export-bar > span {
      display: block; height: 100%; width: 0; border-radius: 3px;
      background: linear-gradient(90deg, var(--cyan-dim), var(--cyan)); transition: width .15s ease-out;
    }
    .modal.indeterminate .export-bar > span { width: 34% !important; transition: none; animation: export-sweep 1.05s ease-in-out infinite; }
    @keyframes export-sweep { 0% { transform: translateX(-110%); } 100% { transform: translateX(360%); } }
    .modal.error .export-bar > span { background: var(--red); }
    .modal.error .export-stage { color: var(--red); }
    .export-detail { font-family: var(--mono); font-size: 11px; line-height: 1.6; color: var(--ink-dim); margin-top: 12px; min-height: 1em; }
    @media (prefers-reduced-motion: reduce) { .modal.indeterminate .export-bar > span { animation: none; width: 100% !important; opacity: .5; } }

    /* --- the "More" button, and the apps panel it opens --- */
    /* In the header's top-left corner, mirroring the App Store and help
       buttons on the right; the brand's side padding already reserves the room. */
    .more-fab {
      position: absolute; left: 0; top: 0; z-index: 2;
      padding: 8px 14px; border-radius: 16px; font-size: 11px; letter-spacing: .18em;
      text-transform: uppercase; color: var(--cyan);
      background: linear-gradient(180deg, #1e2630, #121820);
      box-shadow: 0 4px 16px rgba(0,0,0,.6), 0 0 18px rgba(224,176,90,.12), 0 2px 0 var(--lip), inset 0 1px 0 var(--bevel);
    }
    .more-fab:hover { border-color: var(--cyan); color: var(--cyan); }
    /* the More Apps dialog: a large frame onto the shared app directory, with
       the dialog's own chrome reduced to the title bar */
    .modal-frame {
      width: min(1100px, 100%); height: min(86vh, 900px); max-height: none;
      overflow: hidden; display: flex; flex-direction: column; padding: 0;
    }
    .modal-frame .modal-head { margin: 0; position: static; }
    .apps-wrap { flex: 1; position: relative; display: flex; min-height: 0; }
    .apps-frame { flex: 1; width: 100%; border: 0; background: #080b0e; border-radius: 0 0 10px 10px; }
    /* Covers the frame while the directory loads, so the dialog is never an
       unexplained black rectangle. Same ground as the frame, so it simply
       gives way when the page arrives. */
    .apps-loading {
      position: absolute; inset: 0; display: flex; flex-direction: column;
      align-items: center; justify-content: center; gap: 14px;
      background: #080b0e; border-radius: 0 0 10px 10px;
      font-family: var(--mono); font-size: 11px; letter-spacing: .08em; color: var(--ink-dim);
      transition: opacity .25s ease;
    }
    .apps-loading[hidden] { display: none; }
    .apps-loading.leaving { opacity: 0; }
    .apps-spinner {
      width: 30px; height: 30px; border-radius: 50%;
      border: 2px solid rgba(224,176,90,.18); border-top-color: var(--cyan);
      box-shadow: 0 0 14px rgba(224,176,90,.15);
      animation: apps-spin .9s linear infinite;
    }
    @keyframes apps-spin { to { transform: rotate(360deg); } }
    .apps-loading.slow .apps-spinner { border-top-color: var(--gold); }
    .apps-loading-link { color: var(--magenta); text-decoration: none; }
    .apps-loading-link:hover { text-decoration: underline; }
    .apps-loading-link[hidden] { display: none; }
    @media (prefers-reduced-motion: reduce) {
      .apps-spinner { animation: none; border-top-color: rgba(224,176,90,.18); border-color: var(--cyan); opacity: .6; }
      .apps-loading { transition: none; }
    }
    .modal-open-tab {
      font-family: var(--mono); font-size: 11px; color: var(--magenta); text-decoration: none;
      white-space: nowrap; opacity: .85;
    }
    .modal-open-tab:hover { opacity: 1; text-decoration: underline; }

    /* --- section chrome --- */
    h2 {
      color: var(--cyan); font-size: 12px; letter-spacing: .24em; text-transform: uppercase;
      border-bottom: 1px solid var(--line); padding-bottom: 8px; margin-bottom: 12px; font-weight: 700;
      /* flex so a panel's help button can sit out at the right-hand end */
      display: flex; align-items: center; gap: 8px;
    }
    /* Gold, so it reads as "explain this" rather than as another control — the
       rack's own switches are all cyan and its labels magenta. */
    .panel-help {
      margin-left: auto; flex-shrink: 0;
      width: 20px; height: 20px; padding: 0;
      display: flex; align-items: center; justify-content: center;
      border-radius: 50%;
      font-family: var(--disp); font-size: 12px; font-weight: 700;
      line-height: 1; letter-spacing: 0;
      color: var(--gold);
      background: linear-gradient(180deg, #232114, #16140b);
      border: 1px solid #000;
      box-shadow: 0 1px 0 var(--lip), inset 0 1px 0 var(--gold-dim);
      transition: border-color .1s, box-shadow .1s, color .1s;
    }
    .panel-help:hover {
      border-color: var(--gold); color: #fff0c8;
      box-shadow: 0 0 9px rgba(242,207,133,.4), inset 0 1px 0 var(--gold-dim);
    }
    .panel-help:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
    .panel-help[aria-expanded="true"] {
      border-color: var(--gold); color: #fff0c8;
      box-shadow: 0 0 9px rgba(242,207,133,.4), inset 0 1px 0 var(--gold-dim);
    }
    /* Panel popover: a few sentences about this panel only. Sits under the
       button rather than in the heading, which is uppercase and letter-spaced. */
    .panel-tip {
      position: absolute; z-index: 40;
      top: 34px; right: 12px;
      width: min(430px, calc(100% - 24px));
      padding: 12px 34px 12px 14px;
      background: linear-gradient(180deg, #141b22, #0d1217);
      border: 1px solid var(--gold-dim); border-radius: 7px;
      box-shadow: 0 14px 34px rgba(0,0,0,.66), 0 0 20px rgba(242,207,133,.1);
      animation: tip-in .13s ease-out;
    }
    .panel-tip::before {                   /* pointer up to the ? button */
      content: ""; position: absolute; top: -5px; right: 12px;
      width: 8px; height: 8px; transform: rotate(45deg);
      background: #141b22;
      border-left: 1px solid var(--gold-dim); border-top: 1px solid var(--gold-dim);
    }
    .panel-tip .tip-title {
      display: block; margin-bottom: 6px;
      font-family: var(--disp); font-size: 10px; font-weight: 700;
      letter-spacing: .2em; text-transform: uppercase; color: var(--gold);
    }
    .panel-tip p {
      margin: 0; font-family: var(--mono); font-size: 11px; line-height: 1.75;
      letter-spacing: 0; text-transform: none; color: var(--ink-dim);
    }
    .panel-tip b { color: var(--ink); font-weight: 500; }
    .tip-close {
      position: absolute; top: 6px; right: 8px;
      width: 18px; height: 18px; padding: 0;
      background: none; border: 0; border-radius: 3px;
      font-family: var(--disp); font-size: 15px; line-height: 1;
      color: var(--ink-dim); cursor: pointer;
    }
    .tip-close:hover { color: var(--gold); }
    .tip-more {
      margin-top: 9px; padding: 0;
      background: none; border: 0; cursor: pointer;
      font-family: var(--disp); font-size: 10px; font-weight: 700;
      letter-spacing: .16em; text-transform: uppercase; color: var(--gold);
      opacity: .8;
    }
    .tip-more:hover { opacity: 1; text-decoration: underline; }
    .tip-close:focus-visible, .tip-more:focus-visible {
      outline: 2px solid var(--gold); outline-offset: 2px;
    }
    @keyframes tip-in { from { opacity: 0; transform: translateY(-4px); } }
    @media (prefers-reduced-motion: reduce) { .panel-tip { animation: none; } }
    /* the manual briefly marks the section a panel button jumped to */
    .help-flash { animation: help-flash 1.4s ease-out; border-radius: 4px; }
    @keyframes help-flash {
      from { background: rgba(242,207,133,.26); box-shadow: 0 0 0 6px rgba(242,207,133,.26); }
      to   { background: transparent;           box-shadow: 0 0 0 6px transparent; }
    }
    @media (prefers-reduced-motion: reduce) { .help-flash { animation: none; } }
    h2 span { color: var(--ink-dim); letter-spacing: .12em; }
    .section {
      position: relative;                  /* anchors the panel help popover */
      background: var(--panel-3); border: 1px solid #000; border-radius: 6px;
      box-shadow: inset 0 1px 0 #1e2630, inset 0 2px 12px rgba(0,0,0,.55);
      padding: 14px 16px 16px; margin-bottom: 14px;
    }
    .controls-row, .seq-controls, .effects-row, .algo-select {
      display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-top: 10px;
    }

    /* --- buttons --- */
    button {
      appearance: none; font-family: var(--disp); font-size: 13px; font-weight: 700;
      letter-spacing: .14em; text-transform: uppercase; color: var(--ink);
      background: linear-gradient(180deg, #1e2630, #121820);
      border: 1px solid #000; border-radius: 5px; padding: 10px 15px; cursor: pointer;
      box-shadow: 0 3px 0 var(--lip), inset 0 1px 0 var(--bevel);
      transition: border-color .1s, transform .05s, box-shadow .05s, color .1s;
    }
    button:hover:not(:disabled) { border-color: var(--cyan-dim); }
    button:active:not(:disabled) { transform: translateY(2px); box-shadow: 0 1px 0 var(--lip), inset 0 1px 0 var(--bevel); }
    button:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
    button:disabled { opacity: 0.4; cursor: not-allowed; }
    .btn-primary {
      background: linear-gradient(180deg, #f2cf85, #8d6c2f);
      color: #080b0e; border-color: #0b0a06;
      box-shadow: 0 3px 0 #4a3a14, inset 0 1px 0 rgba(255,255,255,.3), 0 0 20px rgba(224,176,90,.25);
    }
    .btn-secondary { font-family: var(--mono); font-size: 11px; letter-spacing: .06em; text-transform: none; }
    button.playing { color: var(--magenta); border-color: var(--magenta); }

    /* --- LCD readouts --- */
    .info-box {
      background: var(--lcd); border-radius: 3px; box-shadow: inset 0 2px 12px #000;
      padding: 8px 11px; margin-top: 10px; font-family: var(--mono); font-size: 11.5px;
      line-height: 1.7; color: var(--cyan); text-shadow: 0 0 7px rgba(224,176,90,.4);
      font-variant-numeric: tabular-nums;
    }
    .info-box b { color: var(--cyan); font-weight: 700; }
    /* Arrangement sections — the one playing lights up magenta */
    .arr-sec {
      padding: 0 4px; border-radius: 3px; white-space: nowrap;
      transition: color .12s, background .12s, box-shadow .12s, text-shadow .12s;
    }
    .arr-sec.playing {
      color: #080b0e; background: var(--magenta); font-weight: 700;
      text-shadow: none; box-shadow: 0 0 11px rgba(56,224,196,.65);
    }
    .chords { font-family: var(--mono); font-size: 11px; letter-spacing: .12em; color: var(--ink-dim); margin-top: 8px; }
    .chords .lbl { text-transform: uppercase; letter-spacing: .2em; }
    .chords b { color: var(--magenta); font-weight: 400; }

    /* --- synth cards --- */
    .synth-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 10px; margin-top: 10px; }
    .operator-card {
      background: linear-gradient(180deg, #161d25, #0d1217); border: 1px solid #000;
      border-radius: 6px; box-shadow: inset 0 1px 0 #2a3440; padding: 10px 11px 11px;
    }
    .operator-card h3 {
      margin: 0 0 8px 0; font-size: 11px; letter-spacing: .16em; text-transform: uppercase;
      color: var(--magenta); border-bottom: 1px solid var(--line); padding-bottom: 6px;
    }
    .operator-card label {
      display: flex; justify-content: space-between; align-items: center; font-size: 10.5px;
      letter-spacing: .14em; text-transform: uppercase; margin: 5px 0; color: var(--ink-dim); gap: 6px;
    }
    .operator-card input[type="range"] { width: 78px; }
    .operator-card select.synth-sel { flex: 1; min-width: 0; margin-left: 6px; }
    .operator-card .val { width: 34px; text-align: right; font-family: var(--mono); font-size: 10.5px; color: var(--cyan); font-variant-numeric: tabular-nums; }

    /* --- presets --- */
    .preset-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(104px, 1fr)); gap: 8px; margin-top: 10px; }
    .preset-btn {
      font-family: var(--mono); font-size: 11px; font-weight: 400; letter-spacing: .06em;
      text-transform: uppercase; color: var(--ink); background: var(--panel-3);
      border: 1px solid var(--line); border-radius: 4px; padding: 8px 11px; box-shadow: inset 0 1px 0 #1e2630;
    }
    .preset-btn:hover { border-color: var(--cyan-dim); }
    .preset-btn.on { color: var(--cyan); border-color: var(--cyan); box-shadow: 0 0 8px rgba(224,176,90,.3); }
    .preset-btn.edited::after { content: ' *'; color: var(--magenta); }

    /* --- sequencer --- */
    .sequencer { display: grid; gap: 4px; margin-top: 10px; }
    .seq-line { display: grid; grid-template-columns: 78px 1fr; gap: 8px; align-items: center; }
    .seq-row { display: grid; grid-template-columns: repeat(16, 1fr); gap: 3px; }
    .seq-step {
      aspect-ratio: 1; background: #080b0e; border: 1px solid rgba(224,176,90,.35);
      border-radius: 3px; box-shadow: inset 0 1px 2px #000; cursor: pointer;
      transition: background .1s, box-shadow .1s, border-color .1s;
    }
    .seq-step:nth-child(4n+1) { background: #0c1116; border-color: rgba(224,176,90,.55); }
    .seq-step:hover { border-color: var(--magenta); }
    .seq-step.active {
      background: linear-gradient(180deg, #f2cf85, #8d6c2f); border-color: #f5d99b;
      box-shadow: 0 0 9px rgba(224,176,90,.55), inset 0 1px 0 rgba(255,255,255,.25);
    }
    .seq-step.playing { border-color: var(--magenta-hi); box-shadow: 0 0 12px rgba(56,224,196,.8), inset 0 0 7px rgba(56,224,196,.3); }
    .seq-note { width: 100%; }

    /* --- keyboard --- */
    .keyboard {
      display: flex; justify-content: safe center; gap: 2px; margin-top: 10px; padding: 12px 10px;
      background: var(--panel-3); border: 1px solid #000; border-radius: 6px;
      box-shadow: inset 0 2px 12px #000; overflow-x: auto;
      -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
    }
    .key {
      width: 40px; height: 120px;
      background: linear-gradient(to bottom, #f1e9d6, #c9bca0);
      border: 1px solid #000; border-radius: 0 0 4px 4px;
      box-shadow: inset 0 -6px 8px rgba(0,0,0,.2); cursor: pointer;
      display: flex; align-items: flex-end; justify-content: center; padding-bottom: 8px;
      color: #5a5040; font-family: var(--mono); font-size: 9.5px; transition: all 0.1s;
      flex-shrink: 0; user-select: none; touch-action: none;
    }
    /* Past the end of the neck. Dimmed and unresponsive rather than hidden,
       because the shape of the keyboard should not jump around when the voice
       changes — you can see where the instrument stops. */
    .key.out {
      opacity: .3;
      cursor: not-allowed;
      background: linear-gradient(to bottom, #4c545c, #353c43);
      color: #7c848c;
      box-shadow: inset 0 -4px 8px rgba(0,0,0,.35);
    }
    .key.out:hover { filter: none; }

    .key.black {
      width: 28px; height: 80px; background: linear-gradient(to bottom, #121820, #080b0e);
      margin-left: -15px; margin-right: -15px; z-index: 1; color: var(--ink-dim);
      box-shadow: inset 0 -4px 6px rgba(0,0,0,.6);
    }
    .key.pressed { background: linear-gradient(to bottom, #f2cf85, #8d6c2f); box-shadow: 0 0 16px rgba(224,176,90,.55); color: #080b0e; }

    /* --- labelled controls --- */
    .effects-row label, .gen-controls label {
      display: flex; flex-direction: column; align-items: center; font-size: 10.5px;
      letter-spacing: .16em; text-transform: uppercase; color: var(--ink-dim); gap: 5px;
    }
    /* One column per control, however many there are, so the rack stays a single
       row instead of orphaning the last fader onto a line of its own. */
    .effects-row {
      display: grid;
      grid-auto-flow: column;
      grid-auto-columns: 1fr;
      gap: 10px 12px;
      align-items: end;
    }
    /* the labels have to survive ~115px columns: tighter tracking, and a long
       one ("Delay Feedback") wraps rather than overflowing its column */
    .effects-row > label { letter-spacing: .08em; text-align: center; min-width: 0; }
    .effects-row input[type="range"] { width: 100%; min-width: 0; }
    .gen-controls { display: flex; gap: 16px; align-items: flex-end; flex-wrap: wrap; margin-top: 10px; }
    .gen-controls .readout { font-family: var(--mono); color: var(--cyan); font-variant-numeric: tabular-nums; }

    /* The chaos row is four sliders and nothing else, so it gets the same
       treatment as the pedal rack above: one column each, filling the width.
       Left as flex it sized every control to its label and bunched all four
       into the left half of the panel, which wasted most of the row and made
       the sliders far shorter than the resolution they deserve — these are
       continuous parameters where a few pixels is a real change in the music.
       Two classes deep so it beats the `.gen-controls` flex rule above. */
    .gen-controls.chaos-controls {
      display: grid;
      grid-auto-flow: column;
      grid-auto-columns: 1fr;
      gap: 10px 14px;
      align-items: end;
    }
    .chaos-controls > label { text-align: center; min-width: 0; letter-spacing: .08em; }
    .chaos-controls input[type="range"] { width: 100%; min-width: 0; }
    .ctl-group { display: flex; gap: 12px; align-items: flex-end; }
    /* The song writer's two rows run the full width of the panel rather than
       stopping short of it. In the settings row the menus and the two sliders
       take the spare room — a longer slider is a finer control, and Tempo in
       particular is set a beat per minute at a time. In the buttons row the
       three exports share what is left. The phone layout below has its own
       grid, so this only applies above it. */
    @media (min-width: 561px) {
      /* grow into spare room, but never shrink a menu below the width of its
         longest entry — the row wraps instead of cutting "Dorian (jazz minor)" */
      .song-controls > label { flex: 1 1 auto; }
      .song-controls > label:first-child { flex: 0 0 auto; }            /* Key: a note name */
      .song-controls > label:nth-child(2),
      .song-controls > label:nth-child(3) { flex-grow: 1.4; }            /* Scale, Style */
      .song-controls > label:nth-child(4),
      .song-controls > label:nth-child(5) { min-width: 120px; }          /* Tempo, Density */
      .song-controls select, .song-controls input[type="range"] { width: 100%; }
      .song-controls > .ctl-group { flex: 0 0 auto; }
      .song-actions .export-btn { flex: 1 1 0; white-space: nowrap; }
    }
    .ctl-group .checkbox { padding-bottom: 5px; }
    .lock-btn {
      width: 30px; height: 28px; padding: 0; display: flex; align-items: center; justify-content: center;
      letter-spacing: 0; line-height: 1; flex-shrink: 0; color: var(--ink-dim);
    }
    .lock-btn .ico { display: block; }
    .lock-btn .ico-shut, .lock-btn[aria-pressed="true"] .ico-open { display: none; }
    .lock-btn[aria-pressed="true"] .ico-shut { display: block; }
    .lock-btn[aria-pressed="true"] { color: var(--cyan); border-color: var(--cyan); background: #2c2512; }
    .checkbox { flex-direction: row !important; gap: 7px !important; align-items: center !important; color: var(--ink-dim); }
    .checkbox input { accent-color: var(--cyan); }

    /* --- mixer --- */
    /* --- sound kit selector (below the mixer) --- */
    /* The rig buttons and the two switches beside them on one line, and the
       sample status on a line of its own underneath. Sized to fit the 880 px
       row with room to spare — the buttons a little tighter than the preset
       grid's, the switches in the same small capitals as the "Rig" label
       rather than in body text. The buttons wrap only on screens too narrow
       to hold them. */
    .kit-row { display: flex; align-items: center; gap: 9px 9px; margin-top: 12px; flex-wrap: wrap; }
    .kit-label { font-size: 10.5px; letter-spacing: .2em; text-transform: uppercase; color: var(--magenta); flex-shrink: 0; }
    .kit-grid { display: flex; gap: 5px; flex-wrap: nowrap; flex-shrink: 0; }
    .kit-opts { display: flex; align-items: center; gap: 10px; flex-wrap: nowrap; flex-shrink: 0; }
    .kit-opts .checkbox {
      font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase; gap: 5px !important; white-space: nowrap;
    }
    .kit-btn {
      font-family: var(--mono); font-size: 11px; font-weight: 400; letter-spacing: .06em;
      text-transform: uppercase; color: var(--ink); background: var(--panel-3);
      border: 1px solid var(--line); border-radius: 4px; padding: 7px 8px; box-shadow: inset 0 1px 0 #1e2630;
      letter-spacing: .02em; white-space: nowrap;
    }
    .kit-btn:hover { border-color: var(--cyan-dim); }
    .kit-btn.on { color: var(--cyan); border-color: var(--cyan); box-shadow: 0 0 8px rgba(224,176,90,.3); }
    /* seven strips — the band and the beat — so they are narrower than the rock
       rack's six, or the last one orphans itself onto a row of its own */
    .mixer { display: grid; grid-template-columns: repeat(auto-fit, minmax(104px, 1fr)); gap: 8px; margin-top: 14px; }
    .mixer-strip {
      background: linear-gradient(180deg, #161d25, #0d1217); border: 1px solid #000; border-radius: 6px;
      box-shadow: inset 0 1px 0 #2a3440; padding: 10px 9px; text-align: center;
    }
    .mixer-strip .name { display: block; font-size: 10.5px; letter-spacing: .2em; text-transform: uppercase; color: var(--magenta); margin-bottom: 8px; }
    .mixer-strip input[type="range"] { width: 100%; }
    .mixer-strip button {
      margin-top: 6px; padding: 3px 10px; font-family: var(--mono); font-size: 10px; font-weight: 400;
      letter-spacing: .06em; background: var(--panel-3); border-color: var(--line); box-shadow: inset 0 1px 0 #1e2630;
    }
    .mixer-strip.muted { opacity: 0.45; }
    .mixer-strip.muted button { color: var(--red); border-color: var(--red); }

    /* --- sliders --- */
    input[type="range"] { appearance: none; -webkit-appearance: none; height: 22px; background: transparent; cursor: pointer; }
    input[type="range"]::-webkit-slider-runnable-track {
      box-sizing: border-box; height: 6px; background: #080b0e;
      border: 1px solid rgba(224,176,90,.5); border-radius: 3px; box-shadow: inset 0 1px 2px #000;
    }
    input[type="range"]::-webkit-slider-thumb {
      -webkit-appearance: none; width: 12px; height: 20px; margin-top: -7px; border-radius: 3px;
      background: linear-gradient(180deg, #f2cf85, #8d6c2f); border: 1px solid #080b0e; box-shadow: 0 2px 3px rgba(0,0,0,.6), 0 0 8px rgba(224,176,90,.35);
    }
    input[type="range"]::-moz-range-track { box-sizing: border-box; height: 6px; background: #080b0e; border: 1px solid rgba(224,176,90,.5); border-radius: 3px; }
    input[type="range"]::-moz-range-thumb { width: 12px; height: 20px; border-radius: 3px; background: #e0b05a; border: 1px solid #080b0e; }
    input[type="range"]:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }

    /* --- fields --- */
    select, input[type="number"], input[type="text"] {
      font-family: var(--mono); font-size: 11px; color: var(--ink); background: var(--panel-3);
      border: 1px solid var(--line); border-radius: 4px; padding: 6px 9px; box-shadow: inset 0 1px 0 #1e2630;
    }
    select:hover, input:hover { border-color: var(--cyan-dim); }
    select:focus-visible, input:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }

    /* --- misc --- */
    footer {
      margin-top: 18px; border-top: 1px solid var(--line); padding-top: 12px;
      display: flex; justify-content: center; align-items: center; flex-wrap: wrap; gap: 12px;
      font-size: 10.5px; letter-spacing: .18em; text-transform: uppercase;
    }
    footer a { color: var(--cyan); text-decoration: none; }
    footer a:hover { color: var(--magenta); text-decoration: underline; }
    footer a:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px; }
    footer .sep { color: var(--line); }

    #chaos-scope, #visualizer {
      width: 100%;
      background: radial-gradient(ellipse at center, #0f151b 0%, #080b0e 80%);
      border: 1px solid #000; border-radius: 3px; box-shadow: inset 0 2px 12px #000;
      margin-top: 10px; display: block;
    }
    .hint { text-align: center; color: var(--ink-dim); font-size: 10.5px; letter-spacing: .16em; text-transform: uppercase; margin-top: 10px; }
    .progress {
      box-sizing: border-box; height: 7px; background: #080b0e; border: 1px solid rgba(224,176,90,.5);
      border-radius: 3px; box-shadow: inset 0 1px 2px #000; margin-top: 12px; overflow: hidden;
    }
    .progress span { display: block; height: 100%; width: 0; background: linear-gradient(90deg, var(--electric), var(--cyan)); }


    /* ---- the rig: channels, effects, sample status ---------------------------
       Reuses the operator-card chrome the synth panel used, because a channel
       and a synth section are the same thing on a rack: a titled group of
       controls belonging to one voice. */
    .operator-card select.amp-sel { flex: 1; min-width: 0; margin-left: 6px; }
    .amp-card h3 { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
    .amp-tag {
      font-family: var(--mono); font-size: 9px; font-weight: 400; letter-spacing: .1em;
      text-transform: uppercase; color: var(--cyan-dim); flex-shrink: 0;
    }

    .readout { font-family: var(--mono); color: var(--cyan); font-variant-numeric: tabular-nums; }
    #oct-label { min-width: 34px; text-align: center; }

    /* A rig button keeps its highlight once a knob has been turned but picks up
       a dot: the preset is still loaded, it just isn't quite what you're
       hearing any more. Same convention the preset buttons use. */
    .kit-btn.edited::after,
    .preset-btn.edited::after {
      content: ''; display: inline-block; width: 4px; height: 4px; border-radius: 50%;
      background: var(--gold); margin-left: 6px; vertical-align: middle;
      box-shadow: 0 0 5px rgba(242,207,133,.8);
    }

    .sample-status {
      font-family: var(--mono); font-size: 10px; letter-spacing: .06em;
      color: var(--ink-dim); flex-basis: 100%; text-align: right;
    }
    @media (max-width: 820px) {
      .kit-grid { flex-wrap: wrap; flex-shrink: 1; }
    }
    .sample-status.ok { color: var(--cyan-dim); }
    .sample-status.warn { color: var(--gold); }

    /* Write waits for the samples on the first press rather than racing them,
       so the button has to say so. */
    .btn-primary.waiting { opacity: .7; cursor: progress; }
    .btn-primary.waiting::after { content: ' — loading the band…'; font-weight: 400; }


    /* ---- loading screen ---------------------------------------------------
       Covers the one genuinely slow moment in the app: pulling about seven
       megabytes of guitar and drum recordings off disk. It sits above
       everything, is in the markup from the first paint, and takes itself away
       when the samples are in. */
    .boot {
      position: fixed; inset: 0; z-index: 200;
      display: flex; align-items: center; justify-content: center;
      padding: 24px;
      background:
        radial-gradient(900px 420px at 50% 32%, #16202a, transparent),
        var(--panel-3);
      transition: opacity .45s ease, visibility .45s ease;
    }
    .boot.done { opacity: 0; visibility: hidden; pointer-events: none; }
    .boot-panel { width: min(420px, 100%); text-align: center; }
    .boot-icon {
      width: 72px; height: 72px; border-radius: 22.37%; margin-bottom: 16px;
      box-shadow: 0 8px 30px rgba(0,0,0,.6), 0 0 34px rgba(224,176,90,.22);
    }
    .boot-title {
      font-size: 27px; letter-spacing: .04em; text-transform: uppercase;
      color: var(--ink); margin-bottom: 5px;
    }
    .boot-title em { font-style: normal; color: var(--magenta); }
    .boot-tag {
      font-size: 10.5px; letter-spacing: .17em; text-transform: uppercase;
      color: var(--ink-dim); margin-bottom: 22px;
    }
    .boot-bar {
      box-sizing: border-box; height: 8px; background: var(--lcd);
      border: 1px solid rgba(224,176,90,.45); border-radius: 4px;
      box-shadow: inset 0 1px 3px #000; overflow: hidden;
    }
    .boot-bar > span {
      display: block; height: 100%; width: 0;
      background: linear-gradient(90deg, #8d6c2f, #f2cf85);
      box-shadow: 0 0 12px rgba(224,176,90,.5);
      /* Short on purpose. Progress ticks once per file — ninety-odd times in
         about a second — and every tick restarts the transition from wherever
         the animation had got to. At a quarter second the bar falls a long way
         behind the number beside it; at 80 ms it tracks. */
      transition: width .08s linear;
    }
    .boot-status {
      margin-top: 12px; font-family: var(--mono); font-size: 11px;
      letter-spacing: .06em; color: var(--cyan);
    }
    .boot.failed .boot-status { color: var(--gold); }
    .boot-fine {
      margin-top: 7px; font-size: 10px; letter-spacing: .1em; color: var(--ink-dim);
    }
    @media (prefers-reduced-motion: reduce) {
      .boot, .boot-bar > span { transition: none; }
    }

    @media (max-width: 560px) {
      .brand { gap: 11px; padding: 0 82px; }   /* two 32px controls + gap */
      .brand-icon { width: 42px; height: 42px; }
      .brand-text { text-align: center; }
      h1 { font-size: 23px; }
      .tagline { font-size: 10px; letter-spacing: .12em; }
      body { padding: 12px 8px 32px; }
      .app-container { padding: 14px 12px 18px; }
      .section { padding: 12px 11px 13px; }
      /* seven faders across a phone would be 40px each — go back to two columns
         (grid-auto-flow has to be reset, or the columns keep marching sideways) */
      .gen-controls, .effects-row {
        display: grid;
        grid-auto-flow: row;
        grid-template-columns: 1fr 1fr;
        gap: 12px 14px;
      }
      .effects-row > label { letter-spacing: .14em; }
      .gen-controls > label, .effects-row > label { width: 100%; }
      /* four columns is 70px a slider on a phone, which is not a control any
         more — the same two-up the rest of the panel uses, overriding the
         one-column-per-control rule that is right on a desktop */
      .gen-controls.chaos-controls {
        grid-auto-flow: row;
        grid-template-columns: 1fr 1fr;
        grid-auto-columns: auto;
      }
      .gen-controls > .ctl-group { width: 100%; }
      .ctl-group > label:first-child { flex: 1 1 auto; min-width: 0; }
      .gen-controls select, .gen-controls input[type="text"] { width: 100%; }
      .gen-controls .checkbox, .seq-controls .checkbox { justify-content: center; }
      .controls-row button, .seq-controls button { flex: 1 1 auto; }
      input[type="range"] { height: 28px; }
      .checkbox { min-height: 34px; padding: 4px 8px; }
      .checkbox input[type="checkbox"] { width: 20px; height: 20px; }
      .mixer-strip button { padding: 7px 12px; font-size: 11px; }
      .preset-btn { padding: 11px 8px; }
      .sequencer { overflow-x: auto; padding-bottom: 6px; }
      .seq-line { min-width: 470px; grid-template-columns: 62px 1fr; }
      .seq-note { font-size: 10px; padding: 5px 4px; }
      .synth-grid { grid-template-columns: 1fr 1fr; gap: 8px; }
      .operator-card { padding: 8px 7px 9px; }
      .operator-card input[type="range"] { width: 100%; min-width: 0; }
      .operator-card label { font-size: 9.5px; letter-spacing: .08em; gap: 4px; }
      .operator-card .val { width: 26px; font-size: 9.5px; }
      .keyboard { justify-content: flex-start; padding: 10px 6px; }
      .key { width: 46px; height: 132px; touch-action: pan-x; }
      .key.black { width: 32px; height: 88px; margin-left: -17px; margin-right: -17px; }
      .mixer { grid-template-columns: 1fr 1fr; }
      footer { gap: 9px; font-size: 9.5px; letter-spacing: .14em; }
      .modal { padding: 0 15px 20px; }
      .modal-head { margin: 0 -15px 12px; padding: 14px 15px 10px; }
      .more-fab { padding: 7px 11px; font-size: 10px; }
      .modal-frame .modal-head { margin: 0; padding: 14px 15px 10px; }
      .sample-status { text-align: left; }
      .kit-opts .checkbox { padding-left: 0; }   /* line up under the rig buttons */
      .amp-tag { display: none; }
      .boot-title { font-size: 22px; }
      .boot-icon { width: 60px; height: 60px; }
    }
