/* =============================================================================
   EQ — the live microphone equaliser.  labs.llc/eq/           (labs build 521)
   =============================================================================

   TWO PALETTES AND TWO EDITIONS, AND THEY ARE NOT THE SAME CONTROL.

   `data-edition` / `data-dark` belong to the estate.  They own the page: the
   nav, the footer, the console frame, the chips, the sliders, the type.  The
   ED:HEAD block in <head> sets them before first paint and this sheet never
   writes them.

   `data-eq-palette` belongs to EQ.  It owns the picture: the colours the
   canvas is drawn in, and the ground the stage sits on.  Its two values are
   `go` (grey and orange) and `normal` (blue and violet) and BOTH ARE DARK —
   which is exactly why it cannot be folded into the edition switch.  Calling
   one of two darks "paper" would be a lie the switch told on every page.

   Until 528 the stage was dark in both editions.  From 529 the palette has
   a paper form and a dark form, and the EDITION picks which: in paper the
   stage and the canvas are paper and the displays draw as ink on it (both
   palettes — GO in the estate's orange ink, Normal in indigo and violet).
   The edition is still ED:HEAD's alone; this sheet and eq.js only read it.
   The paper tokens are scoped to #stage (section 6b), so the control strip
   below the stage keeps exactly the palette colours it had.
   ========================================================================== */


/* ---------------------------------------------------------------- 1. tokens
   The estate's own values, lifted from assets/css/site.css and dark.css so
   that EQ carries one stylesheet instead of five.  If those move, these are
   the lines to move with them. */
:root {
    --ink:        #1E262B;
    --ink-77:     rgba(30, 38, 43, .77);
    --ink-55:     rgba(30, 38, 43, .64);
    --paper:      #ffffff;
    --tint:       #FAFAFA;
    --deep:       #11161C;
    --line:       rgba(30, 38, 43, .12);
    --line-soft:  rgba(30, 38, 43, .07);
    --line-dark:  rgba(255, 255, 255, .13);
    --muted:      #717171;
    --accent:     #C2410C;
    --accent-fill:#FB923C;
    --on-accent:  #2A1206;
    --danger:     #B91C1C;
    --ok:         #15803D;

    --measure:    1265px;
    --gutter:     clamp(20px, 5vw, 56px);
    --nav-h:      64px;
    --ease:       cubic-bezier(.22, .61, .36, 1);
    --radius:     10px;
}

html[data-dark] {
    --ink:        #FFFFFF;
    --ink-77:     rgba(255, 255, 255, .72);
    --ink-55:     rgba(255, 255, 255, .58);
    --paper:      #0C1116;
    --tint:       #0F151B;
    --deep:       #1A222C;
    --line:       rgba(255, 255, 255, .16);
    --line-soft:  rgba(255, 255, 255, .09);
    --line-dark:  rgba(30, 38, 43, .22);
    --muted:      #8A9199;
    --accent:     #F97316;
    --accent-fill:#F97316;
    --on-accent:  #1A0E04;
    --danger:     #F87171;
    --ok:         #4ADE80;
}

/* The canvas palette.  These values are the ones eq.js draws with — the
   `bg` here and the `bg` in palette() in eq.js are the same colour twice, on
   purpose: the CSS one is what the stage shows for the handful of frames
   before the first draw lands, and a mismatch there is a flash. */
:root,
:root[data-eq-palette="go"] {
    --eq-bg:        #1a1a1a;
    --eq-bg-deep:   #121212;
    --eq-accent:    #ff6a00;
    --eq-accent2:   #ff8c33;
    --eq-grad:      linear-gradient(135deg, #ff6a00, #ff8c33);
    --eq-glow:      rgba(255, 106, 0, .40);
    /* the PRESSED state of the small controls (chips, a · b · c, the palette
       switch, the recorder's size): 10-12px type on the gradient.  White on
       GO's #ff6a00 → #ff8c33 is 2.9 → 2.3:1, so GO keeps its orange and
       takes charcoal type (6.1 → 7.5:1); Normal keeps white type on its
       own gradient deepened a step (5.0 → 5.3:1, was 3.1 → 3.4). */
    --eq-press:     var(--eq-grad);
    --eq-press-ink: #1a1a1a;
    --eq-stage-a:   rgba(60, 60, 60, .40);
    --eq-stage-b:   rgba(255, 106, 0, .08);
}
:root[data-eq-palette="normal"] {
    --eq-bg:        #07080c;
    --eq-bg-deep:   #050608;
    --eq-accent:    #6c8cff;
    --eq-accent2:   #a78bfa;
    --eq-grad:      linear-gradient(135deg, #6c8cff, #8b7cf0);
    --eq-glow:      rgba(108, 140, 255, .35);
    --eq-press:     linear-gradient(135deg, #4c63e0, #6a55e0);
    --eq-press-ink: #fff;
    --eq-stage-a:   rgba(40, 50, 90, .35);
    --eq-stage-b:   rgba(80, 40, 100, .15);
}


/* --------------------------------------------------------------- 1b. type
   The house face, declared here because EQ carries its own sheet rather than
   the estate's site.css.  The <head> preloads the latin file; without this
   rule the browser fetches it and never uses it, which is a wasted request
   and a console warning that says so. */
@font-face {
    font-family: 'DM Sans';
    font-style: normal;
    font-weight: 200 700;
    font-display: swap;
    src: url('/assets/fonts/dm-sans-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: 'DM Sans';
    font-style: normal;
    font-weight: 200 700;
    font-display: swap;
    src: url('/assets/fonts/dm-sans-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;
}


/* ------------------------------------------------------------------ 2. base */
*, *::before, *::after { box-sizing: border-box; }
body, h1, h2, h3, p, ul, figure { margin: 0; }

html { -webkit-text-size-adjust: 100%; }

body {
    background: var(--paper);
    color: var(--ink);
    font-family: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    font-size: 16px;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
}

.wrap { max-width: var(--measure); margin: 0 auto; padding-inline: var(--gutter); }

a { color: inherit; }

/* One ring, on everything, in both editions.  The app shipped with zero focus
   styling on thirty-nine controls; this rule is the whole fix. */
:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
    border-radius: 4px;
}
/* Inside the stage the ring is drawn on near-black whatever the edition is,
   so it takes the palette's accent rather than the page's. */
#eq-app :focus-visible { outline-color: var(--eq-accent); }
/* …but the controls BELOW the stage are only near-black in the dark edition.
   In paper they sit on rgb(250,250,250), where the two palette accents measure
   2.87:1 (GO, #ff6a00) and 3.10:1 (Normal, #6c8cff) — either side of the 3:1 a
   non-text indicator needs, which is thinner than a focus ring has any business
   being.  The estate already solved this for itself: its paper accent is
   #C2410C, 5.18:1 on white, where its dark accent is #F97316.  So in paper the
   ring off the stage takes the estate's accent and the ring ON the stage keeps
   the palette's, which is where the palette's is right.  Both editions keep one
   ring on every control; only the colour of the light half changes. */
:root[data-edition="paper"] #eq-app :focus-visible { outline-color: var(--accent); }
:root[data-edition="paper"] #stage  :focus-visible { outline-color: var(--eq-accent); }

.skip {
    position: absolute; left: -9999px; top: 0; z-index: 400;
    background: var(--ink); color: var(--paper);
    padding: .8rem 1.2rem; text-decoration: none;
}
.skip:focus { left: 0; }

/* A visually-hidden utility used to live here and nothing on the page ever wore
   it — everything EQ says to a screen reader it says in visible text, in
   #vizLabel, #recStatus and #errorMsg. A class in a stylesheet that no template
   emits is the same defect as a selector in a script that matches nothing, so
   it is gone rather than kept "in case". */


/* --------------------------------------------------------------- 3. the nav
   The house header, same shape as every other property: the LABS plate, the
   property's own name, its section links, the edition pill. */
.nav {
    position: sticky; top: 0; z-index: 60;
    background: color-mix(in srgb, var(--paper) 86%, transparent);
    backdrop-filter: saturate(180%) blur(14px);
    -webkit-backdrop-filter: saturate(180%) blur(14px);
    border-bottom: 1px solid var(--line-soft);
}
.nav__in {
    max-width: var(--measure); margin: 0 auto;
    padding: 0 var(--gutter); height: var(--nav-h);
    display: flex; align-items: center; gap: 1rem;
}
.nav__mark { display: flex; align-items: center; gap: .8rem; margin-right: auto; min-width: 0; }
.nav__mark a { display: flex; align-items: center; gap: .8rem; text-decoration: none; }
.nav__plate { display: block; height: 28px; width: auto; }
html[data-dark] .nav__plate { filter: invert(1) hue-rotate(180deg) brightness(1.08); }
.nav__mark b { font-size: .95rem; font-weight: 600; letter-spacing: -.03em; color: var(--ink); }
.nav__mark span {
    font-size: .6rem; font-weight: 700; letter-spacing: .32em; text-transform: uppercase;
    color: var(--ink-55); padding-left: .8rem; border-left: 1px solid var(--line);
    white-space: nowrap;
}
.nav__links { display: flex; align-items: center; gap: 1.6rem; }
.nav__links a {
    text-decoration: none; font-size: .875rem; font-weight: 500;
    color: var(--ink-77); letter-spacing: -.01em;
    position: relative; padding-block: .4rem; white-space: nowrap;
}
.nav__links a::after {
    content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
    background: var(--ink); transform: scaleX(0); transform-origin: left;
    transition: transform .32s var(--ease);
}
.nav__links a:hover::after { transform: scaleX(1); }


/* ------------------------------------------------------- 4. the edition pill
   Lifted from the house sheet, because it is the same control doing the same
   job and a visitor who has met one should not have to learn the other.  The
   segments are <button data-ed-set> and ED:HEAD drives them; nothing in this
   sheet writes a bare `button {}` rule that could reach them. */
.mode-pill {
    position: relative; flex: 0 0 auto;
    display: inline-flex; align-items: center;
    padding: 3px; border-radius: 999px;
    border: 1px solid var(--line);
    background: linear-gradient(180deg, rgba(30,38,43,.045), rgba(30,38,43,.025));
    box-shadow: inset 0 1px 2px rgba(30, 38, 43, .055);
}
html[data-dark] .mode-pill {
    background: linear-gradient(180deg, rgba(255,255,255,.05), rgba(255,255,255,.02));
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, .35);
}
.mode-pill__thumb {
    position: absolute; z-index: 0;
    top: 3px; bottom: 3px; left: 3px; width: calc(50% - 3px);
    border-radius: 999px; background: var(--ink);
    box-shadow: 0 1px 2px rgba(30, 38, 43, .26), 0 6px 18px rgba(30, 38, 43, .14);
    transition: transform .42s var(--ease);
}
.mode-pill--dark .mode-pill__thumb { transform: translateX(100%); }
.mode-pill:has(.mode-pill__seg:not(.is-on):hover) .mode-pill__thumb { transform: translateX(100%); }
.mode-pill--dark:has(.mode-pill__seg:not(.is-on):hover) .mode-pill__thumb { transform: none; }
.mode-pill__seg {
    position: relative; z-index: 1;
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 2.5rem; padding: .4rem .45rem; border-radius: 999px;
    text-decoration: none; color: var(--ink-55);
    transition: color .32s var(--ease);
}
.mode-pill__seg.is-on { color: var(--paper); cursor: default; }
.mode-pill__seg:not(.is-on):hover { color: var(--ink); }
.mode-pill:has(.mode-pill__seg:hover) .mode-pill__seg.is-on { color: var(--ink-55); }
.mode-pill:has(.mode-pill__seg:hover) .mode-pill__seg:hover { color: var(--paper); }
.mode-pill__i { width: 13px; height: 13px; flex: 0 0 auto; display: block; }


/* ------------------------------------------------------------ 5. the console
   #eq-app is the instrument: a strip of identity and status, the stage, and a
   strip of controls.  It is a fixed slab on the page rather than the whole
   viewport, because there is a house nav above it and a house footer below.
   Its height is what #stage measures, and #stage is what the ResizeObserver
   in eq.js watches. */
/* minmax(240px, 1fr) on the stage row, and min-height rather than height, are
   both there for one measured reason: opening the recorder panel grew the
   control strip by about 210px and the stage — a 1fr row inside a fixed
   height — gave up every one of them.  Measured: a 1151 × 489 canvas became
   1151 × 120, and the recording made from it was 120px tall.  The floor keeps
   the stage a stage, and min-height lets the console grow instead when there
   is no room left to take. */
#eq-app {
    display: grid;
    grid-template-rows: auto minmax(240px, 1fr) auto;
    min-height: min(80svh, 760px);
    margin: 1.6rem auto 0;
    max-width: var(--measure);
    border: 1px solid var(--line);
    border-radius: 14px;
    overflow: hidden;
    background: var(--tint);
    box-shadow: 0 1px 2px rgba(30,38,43,.05), 0 18px 46px rgba(30,38,43,.07);
}
html[data-dark] #eq-app { box-shadow: 0 18px 46px rgba(0,0,0,.45); }

.eq-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px; padding: 8px 12px;
    background: var(--tint);
    border-bottom: 1px solid var(--line);
    min-height: 44px;
}
.eq-head__mark { display: flex; align-items: baseline; gap: 9px; min-width: 0; }
.eq-h1 {
    font-size: 15px; font-weight: 700; letter-spacing: .02em;
    color: var(--ink); line-height: 1.3;
}
/* The page has to say what it is in its opening clause: "EQ" on its own reads
   as a tone control, and VIZZI's own feature list already contains the word.
   So the tail is part of the <h1>, not a subtitle that disappears on a phone. */
.eq-h1 span { font-size: 11.5px; font-weight: 400; color: var(--ink-55); }
.eq-head__right { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }

/* The palette control.  Labelled "Palette", never "Theme": the sun/moon in the
   nav above is the theme, and two controls that both look like a theme switch
   is one control too many. */
.eq-palette {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 10px; color: var(--ink-55);
}
.eq-palette__set {
    display: inline-flex; background: color-mix(in srgb, var(--ink) 6%, transparent);
    border: 1px solid var(--line); border-radius: 999px; padding: 2px;
}
.eq-palette__btn {
    appearance: none; -webkit-appearance: none;
    border: 0; background: transparent; color: var(--ink-55);
    font: inherit; font-size: 10px; font-weight: 700; letter-spacing: .04em;
    padding: 3px 10px; border-radius: 999px; cursor: pointer;
    transition: background .15s, color .15s;
}
/* Which segment LOOKS chosen is painted from :root[data-eq-palette], which the
   ten-line bootstrap in <head> sets before the first paint — not from
   aria-pressed, which eq.js can only correct once the document has been
   parsed.  Measured on the built page: the aria correction landed at 36.4 ms
   against the browser's own first-paint entry at 44.0 ms, and one screencast
   frame of a Normal-stored reload still caught the GO segment lit while the
   accent colours were already Normal.  Eight milliseconds is not a margin, it
   is the same machine being lucky.  aria-pressed is still written and is still
   what a screen reader is told; it is simply no longer what draws. */
:root[data-eq-palette="go"]     .eq-palette__btn[data-eq-set="go"],
:root[data-eq-palette="normal"] .eq-palette__btn[data-eq-set="normal"] {
    background: var(--eq-press); color: var(--eq-press-ink);
    box-shadow: 0 0 10px var(--eq-glow);
}

.eq-status { display: flex; align-items: center; gap: 6px; font-size: 10px; color: var(--ink-55); }
.eq-dot {
    width: 7px; height: 7px; border-radius: 50%;
    background: var(--muted); box-shadow: 0 0 0 2px color-mix(in srgb, var(--muted) 22%, transparent);
}
.eq-dot.live {
    background: var(--ok); box-shadow: 0 0 0 2px color-mix(in srgb, var(--ok) 25%, transparent);
    animation: eq-pulse 1.6s ease-in-out infinite;
}
.eq-dot.err { background: var(--danger); box-shadow: 0 0 0 2px color-mix(in srgb, var(--danger) 25%, transparent); }
@keyframes eq-pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50% { opacity: .7; transform: scale(.85); }
}


/* --------------------------------------------------------------- 6. the stage
   Dark in the dark edition, paper in the paper edition (6b).  These
   gradients are what shows for the frames before eq.js first draws; after
   that the canvas covers the stage and paints the same ground itself (on
   paper, paperGround() in eq.js paints these two washes at these sizes). */
#stage {
    position: relative;
    outline-offset: -3px;
    min-height: 0;
    background:
        radial-gradient(ellipse 80% 60% at 50% 40%, var(--eq-stage-a), transparent 70%),
        radial-gradient(ellipse 50% 40% at 80% 80%, var(--eq-stage-b), transparent),
        var(--eq-bg);
}
#canvas { display: block; width: 100%; height: 100%; }

/* align-items:flex-start plus margin:auto on the card, NOT align-items:center.
   A centred flex child that is taller than its container overflows in BOTH
   directions and the top of it cannot be scrolled to — which on a short stage
   with the reduced-motion note showing means the start card opens halfway down
   its own second paragraph and the heading is unreachable.  margin:auto
   centres it while there is room and gives the top back when there is not. */
.eq-overlay {
    position: absolute; inset: 0;
    display: flex; align-items: flex-start; justify-content: center;
    background: color-mix(in srgb, var(--eq-bg) 58%, transparent);
    backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
    z-index: 3; overflow: auto; overscroll-behavior: contain;
    padding: 14px;
    transition: opacity .35s ease, visibility .35s;
}
.eq-overlay.hidden { opacity: 0; visibility: hidden; pointer-events: none; }

/* The start card is on the stage, so it follows the stage: dark here, paper
   in the paper edition (6b). */
.eq-card {
    text-align: left;
    padding: 20px 22px;
    background: rgba(16, 18, 24, .94);
    border: 1px solid rgba(255, 255, 255, .10);
    border-radius: 14px;
    box-shadow: 0 8px 28px rgba(0, 0, 0, .5);
    max-width: 400px; margin: auto;
    color: #e8eaf0;
}
.eq-card h2 { font-size: 16px; font-weight: 700; margin-bottom: 8px; color: #fff; }
.eq-card p { color: #a8adbb; font-size: 12px; line-height: 1.5; margin-bottom: 12px; }
.eq-card p strong { color: #e8eaf0; }
.eq-card__acts { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.eq-card :focus-visible { outline-color: var(--eq-accent); }

.eq-btn {
    appearance: none; -webkit-appearance: none;
    border: 0; cursor: pointer; font: inherit;
    border-radius: 8px; padding: 6px 12px;
    font-weight: 600; font-size: 12px;
    transition: transform .15s, background .15s, box-shadow .15s, opacity .15s;
}
.eq-btn:active { transform: scale(.97); }
.eq-btn:disabled,
.eq-btn[aria-disabled="true"] { opacity: .45; cursor: not-allowed; }
.eq-btn--primary {
    background: var(--eq-grad); color: #fff;
    box-shadow: 0 4px 14px var(--eq-glow);
    padding: 9px 18px; font-size: 13px;
}
.eq-btn--primary:hover:not(:disabled) { box-shadow: 0 6px 20px var(--eq-glow); }
.eq-btn--quiet {
    background: rgba(255, 255, 255, .08); color: #e8eaf0;
    border: 1px solid rgba(255, 255, 255, .14);
    padding: 6px 11px; font-size: 11px;
}
.eq-btn--quiet:hover:not(:disabled) { background: rgba(255, 255, 255, .14); }
/* .eq-btn--quiet above is written for the start card, which is dark in BOTH
   editions.  In the control strip, which is not, it painted #e8eaf0 text on a
   #FAFAFA strip: measured contrast 1.15:1, which is not low contrast, it is
   invisible.  It caught "Save a frame" and the "Stop the mic" button that was
   already there.  The strip's copies take the edition's own tokens. */
.eq-foot .eq-btn--quiet {
    background: color-mix(in srgb, var(--ink) 6%, transparent);
    color: var(--ink);
    border: 1px solid var(--line);
}
.eq-foot .eq-btn--quiet:hover:not(:disabled) { background: color-mix(in srgb, var(--ink) 12%, transparent); }

/* The two failure messages.  #errorMsg is role="alert"; #rmNote is the
   reduced-motion explanation and is on screen from first paint, so it is a
   plain note and not an alert. */
.eq-error {
    color: #ff8a9e; font-size: 11.5px; line-height: 1.45;
    margin-top: 10px; display: none;
}
.eq-error.show { display: block; }
.eq-note {
    font-size: 11.5px; line-height: 1.45; color: #a8adbb;
    border-left: 2px solid var(--eq-accent);
    padding-left: 10px; margin-bottom: 12px;
}
.eq-note.hidden { display: none; }
.eq-note p { margin: 8px 0 0; }


/* ------------------------------------------------ 6b. the stage, on paper
   The paper edition is html[data-edition="paper"] with no data-dark — the
   same test isPaper() makes in eq.js.  The tokens are redefined ON #stage,
   not on :root, so they reach the canvas ground, the overlay, the start card,
   its button and the focus ring on the stage, and nothing below it: the
   chips, sliders and recorder keep the palette's own colours.
   The accents are the paper palette's (eq.js palette()): #C2410C / #EA580C
   for GO (5.18:1 and 3.56:1 on white), #3B4FD8 / #6D4AE0 for Normal (6.3:1,
   5.6:1), so white type on the start button and a focus ring on white both
   clear their contrast bars on paper, which the dark accents did not. */
:root[data-edition="paper"]:not([data-dark]) #stage {
    --eq-bg:        #ffffff;
    --eq-bg-deep:   #f7f6f3;
    --eq-accent:    #C2410C;
    --eq-accent2:   #EA580C;
    --eq-grad:      linear-gradient(135deg, #C2410C, #EA580C);
    --eq-glow:      rgba(194, 65, 12, .22);
    --eq-stage-a:   rgba(120, 104, 90, .075);
    --eq-stage-b:   rgba(234, 88, 12, .05);
}
:root[data-edition="paper"][data-eq-palette="normal"]:not([data-dark]) #stage {
    --eq-bg:        #ffffff;
    --eq-bg-deep:   #f6f7fb;
    --eq-accent:    #3B4FD8;
    --eq-accent2:   #6D4AE0;
    --eq-grad:      linear-gradient(135deg, #3B4FD8, #6D4AE0);
    --eq-glow:      rgba(59, 79, 216, .22);
    --eq-stage-a:   rgba(59, 79, 216, .05);
    --eq-stage-b:   rgba(109, 74, 224, .045);
}
/* The overlay over a paper stage is frosted paper (the 58% mix of --eq-bg
   above already makes it so); the card on it is a sheet of the page's own
   paper with the page's own ink, the way every card on the estate is. */
:root[data-edition="paper"]:not([data-dark]) .eq-card {
    background: rgba(255, 255, 255, .97);
    border: 1px solid var(--line);
    box-shadow: 0 1px 2px rgba(30, 38, 43, .06), 0 14px 36px rgba(30, 38, 43, .13);
    color: var(--ink);
}
:root[data-edition="paper"]:not([data-dark]) .eq-card h2 { color: var(--ink); }
:root[data-edition="paper"]:not([data-dark]) .eq-card p { color: var(--ink-77); }
:root[data-edition="paper"]:not([data-dark]) .eq-card p strong { color: var(--ink); }
:root[data-edition="paper"]:not([data-dark]) .eq-card .eq-note { color: var(--ink-77); }
:root[data-edition="paper"]:not([data-dark]) .eq-card .eq-error { color: var(--danger); }
:root[data-edition="paper"]:not([data-dark]) .eq-card .eq-btn--quiet {
    background: color-mix(in srgb, var(--ink) 6%, transparent);
    color: var(--ink);
    border: 1px solid var(--line);
}
:root[data-edition="paper"]:not([data-dark]) .eq-card .eq-btn--quiet:hover:not(:disabled) {
    background: color-mix(in srgb, var(--ink) 12%, transparent);
}


/* ------------------------------------------------------ 7. the control strip */
.eq-foot {
    padding: 8px 10px 10px;
    background: var(--tint);
    border-top: 1px solid var(--line);
}
.eq-controls {
    display: flex; flex-wrap: wrap; align-items: center;
    gap: 6px 12px; margin-bottom: 7px;
}
.eq-icon {
    width: 30px; height: 30px; padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
    background: color-mix(in srgb, var(--ink) 6%, transparent);
    border: 1px solid var(--line); color: var(--ink);
    border-radius: 7px; font-size: 15px; line-height: 1; cursor: pointer;
    appearance: none; -webkit-appearance: none; font-family: inherit;
}
.eq-icon:hover { background: color-mix(in srgb, var(--ink) 12%, transparent); }
.eq-vizlabel {
    font-size: 11.5px; font-weight: 600; color: var(--ink);
    min-width: 168px; font-variant-numeric: tabular-nums;
}
.eq-sliders { display: flex; align-items: center; gap: 12px; flex: 1; flex-wrap: wrap; }
.eq-slider { display: flex; align-items: center; gap: 7px; font-size: 10px; color: var(--ink-55); }
.eq-slider label { white-space: nowrap; }
/* NO `outline: none` here.  The original sheet carried one on the range input
   and it is the reason a `:focus-visible` rule added later does nothing: the
   element selector is more specific than the pseudo-class on its own, so the
   ring computed to style:none and the slider was the one control on the page
   still invisible to a keyboard.  Measured before removing it. */
.eq-slider input[type="range"] {
    -webkit-appearance: none; appearance: none;
    width: 86px; height: 3px; border-radius: 2px;
    background: color-mix(in srgb, var(--ink) 18%, transparent);
}
.eq-slider input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 12px; height: 12px; border-radius: 50%;
    background: var(--eq-accent); cursor: pointer;
    box-shadow: 0 0 6px var(--eq-glow);
}
.eq-slider input[type="range"]::-moz-range-thumb {
    width: 12px; height: 12px; border: 0; border-radius: 50%;
    background: var(--eq-accent); cursor: pointer;
}
.eq-toggle {
    display: flex; align-items: center; gap: 5px;
    font-size: 10px; color: var(--ink-55); cursor: pointer; user-select: none;
}
.eq-toggle input { accent-color: var(--eq-accent); cursor: pointer; }

.eq-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(102px, 1fr));
    gap: 3px;
    max-height: 76px; overflow-y: auto;
    padding-right: 2px;
    scrollbar-width: thin;
}
.eq-chip {
    appearance: none; -webkit-appearance: none;
    border: 1px solid var(--line);
    background: color-mix(in srgb, var(--ink) 3%, transparent);
    color: var(--ink-55);
    font: inherit; font-size: 10px; line-height: 1.2;
    padding: 4px 6px; border-radius: 5px; cursor: pointer;
    text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    transition: background .12s, color .12s, border-color .12s;
}
.eq-chip:hover { background: color-mix(in srgb, var(--ink) 9%, transparent); color: var(--ink); }
.eq-chip[aria-pressed="true"] {
    background: var(--eq-press); border-color: transparent;
    color: var(--eq-press-ink); box-shadow: 0 0 8px var(--eq-glow);
}
.eq-hint { font-size: 9.5px; color: var(--ink-55); margin-top: 5px; }

/* a · b · c (529).  The three lettered displays sit in a slim column to the
   RIGHT of the chip grid: a flex row, the grid taking 1fr of it and the
   column its own 22px, so whatever the chips do — ten across, eleven, three
   on a phone — the letters stay a stack of three at the right edge, top-
   aligned with the chip rows.  Each button is exactly a chip's height (10px
   type at 1.2 + 4px padding top and bottom + a 1px border = 22px) with the
   grid's 3px gap, so a, b and c line up with rows one, two and three.  The
   same family as a chip — its border, its radius, its hover and its pressed
   gradient — so a pressed letter and a pressed chip are one signal. */
.eq-modes { display: flex; align-items: flex-start; gap: 5px; }
.eq-modes .eq-grid { flex: 1 1 auto; min-width: 0; }
.eq-abc {
    flex: 0 0 auto;
    display: flex; flex-direction: column; gap: 3px;
    padding-left: 5px;
    border-left: 1px solid var(--line-soft);
}
.eq-abc__btn {
    appearance: none; -webkit-appearance: none;
    box-sizing: border-box;
    width: 22px; height: 22px; aspect-ratio: 1; padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--line);
    background: color-mix(in srgb, var(--ink) 3%, transparent);
    color: var(--ink-77);
    font: inherit; font-size: 11px; font-weight: 600; line-height: 1;
    border-radius: 5px; cursor: pointer;
    transition: background .12s, color .12s, border-color .12s;
}
.eq-abc__btn:hover { background: color-mix(in srgb, var(--ink) 9%, transparent); color: var(--ink); }
.eq-abc__btn[aria-pressed="true"] {
    background: var(--eq-press); border-color: transparent;
    color: var(--eq-press-ink); box-shadow: 0 0 8px var(--eq-glow);
}


/* --------------------------------------------------------- 7b. the recorder
   Two pieces in two places, on purpose.  .eq-rec__bar lives in the control
   strip and is the part a person reaches for; .eq-rec is a panel under the
   displays and is the part a person READS, because three paragraphs about
   bitrates do not belong in a strip of buttons.  Everything the panel says is
   written by eq.js from the canvas as it is at that moment. */
.eq-rec__bar {
    display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.eq-btn--rec {
    display: inline-flex; align-items: center; gap: 6px;
    background: color-mix(in srgb, var(--danger) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--danger) 45%, transparent);
    color: var(--ink);
}
.eq-btn--rec:hover:not(:disabled):not([aria-disabled="true"]) { background: color-mix(in srgb, var(--danger) 22%, transparent); }
/* The dot is decoration.  The state is carried by the button's own label
   ("Record" / "Stop recording"), by aria-pressed, and by the word "Recording"
   in the live status beside it — a state that is only a colour is a state a
   good fraction of the people using this page cannot read. */
.eq-rec__led {
    width: 8px; height: 8px; border-radius: 50%;
    background: color-mix(in srgb, var(--danger) 55%, transparent);
    flex: none;
}
.is-rec .eq-rec__led {
    background: var(--danger);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--danger) 25%, transparent);
    animation: eq-pulse 1.2s ease-in-out infinite;
}
.is-rec .eq-btn--rec { background: color-mix(in srgb, var(--danger) 26%, transparent); }
.eq-rec__meter {
    font-size: 10.5px; font-weight: 700; color: var(--ink);
    font-variant-numeric: tabular-nums; white-space: nowrap;
}
.eq-rec__status { font-size: 10px; color: var(--ink-77); max-width: 42ch; }
.eq-rec__why { font-size: 10px; color: var(--ink-55); max-width: 42ch; }
/* No stylesheet on this estate styles <code>, and the reading section now uses
   it for two literal things a visitor may have to type or recognise: ?debug on
   the address, and window.EQ.  Default UA monospace renders a size step larger
   than the surrounding text in most browsers, so it is pinned here. */
.eq-read code {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .92em; color: var(--ink);
    background: color-mix(in srgb, var(--ink) 7%, transparent);
    border-radius: 4px; padding: 0 4px;
    /* Measured at the pane's narrow width: without this, "?debug" broke after
       the question mark and read as two words on two lines. */
    white-space: nowrap;
}

/* The format warning in the strip.  It is NOT --ink-55 at 10px like the two
   lines above it: it is the one thing here that changes what the file you are
   about to make will and will not open in, and the panel version of it was
   already invisible behind a closed disclosure triangle.  It gets the body
   ink and a rule down its side so it reads as a notice rather than as more
   fine print. */
.eq-rec__fmt {
    font-size: 10px; line-height: 1.4; color: var(--ink);
    max-width: 46ch; border-left: 2px solid var(--danger); padding-left: 7px;
}

.eq-rec {
    margin-top: 6px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: color-mix(in srgb, var(--ink) 3%, transparent);
}
.eq-rec__sum {
    font-size: 10.5px; font-weight: 700; color: var(--ink-77);
    padding: 5px 9px; cursor: pointer; border-radius: 8px;
    list-style: none;
}
.eq-rec__sum::-webkit-details-marker { display: none; }
.eq-rec__sum::before { content: "\25B8"; display: inline-block; margin-right: 6px; transition: transform .15s var(--ease); }
.eq-rec[open] .eq-rec__sum::before { transform: rotate(90deg); }
/* The panel's own content measures about 456px at a desktop width; capping it
   at 190 put a nested scrollbar inside a page that already scrolls, and hid
   the file-type menu — the control the owner's request is really about —
   below the fold of a box most people would not think to scroll.  The cap is
   now high enough to show all of it on an ordinary screen and still bounded
   on a short one. */
.eq-rec__body { padding: 2px 9px 9px; max-height: min(480px, 55svh); overflow-y: auto; }
.eq-rec__row {
    display: flex; flex-wrap: wrap; gap: 14px; align-items: flex-start;
    margin-bottom: 7px;
}
.eq-rec__lab {
    display: block; font-size: 9.5px; font-weight: 700; letter-spacing: .06em;
    text-transform: uppercase; color: var(--ink-55); margin-bottom: 4px;
}
/* The qualifier sits ON the control group, not three paragraphs below it:
   the S / M / L buttons print configured bitrates flatly, and a visitor who
   reads only the buttons should still learn that those numbers are a ceiling.
   Lower case and un-tracked so it reads as a sentence inside the label rather
   than as more label. */
.eq-rec__labnote {
    text-transform: none; letter-spacing: 0; font-weight: 400;
    color: var(--ink-55);
}
.eq-rec__qset { display: flex; gap: 5px; flex-wrap: wrap; }
.eq-rec__qbtn {
    appearance: none; -webkit-appearance: none;
    display: flex; flex-direction: column; gap: 1px;
    min-width: 150px; text-align: left;
    border: 1px solid var(--line);
    background: color-mix(in srgb, var(--ink) 3%, transparent);
    color: var(--ink-55); font: inherit;
    padding: 5px 8px; border-radius: 6px; cursor: pointer;
}
.eq-rec__qbtn:hover:not(:disabled) { background: color-mix(in srgb, var(--ink) 9%, transparent); }
.eq-rec__qbtn:disabled { opacity: .5; cursor: not-allowed; }
.eq-rec__qbtn b { font-size: 12px; color: var(--ink); letter-spacing: .04em; }
.eq-rec__qbtn[aria-pressed="true"] {
    border-color: transparent; background: var(--eq-press); color: var(--eq-press-ink);
    box-shadow: 0 0 8px var(--eq-glow);
}
.eq-rec__qbtn[aria-pressed="true"] b { color: var(--eq-press-ink); }
.eq-rec__spec { font-size: 10px; font-variant-numeric: tabular-nums; }
.eq-rec__sub { font-size: 9.5px; opacity: .8; }
.eq-rec__f { min-width: 230px; flex: 1 1 230px; }
.eq-rec__f select {
    width: 100%; font: inherit; font-size: 11px; color: var(--ink);
    background: var(--paper); border: 1px solid var(--line);
    border-radius: 6px; padding: 4px 6px;
}
.eq-rec__where, .eq-rec__note, .eq-rec__rate, .eq-rec__result, .eq-rec__fine {
    font-size: 10px; line-height: 1.45; color: var(--ink-55);
    margin-top: 4px; max-width: 78ch;
}
.eq-rec__note { color: var(--ink-77); }
.eq-rec__rate { color: var(--ink-77); }
.eq-rec__result {
    color: var(--ink); font-weight: 600;
    border-left: 2px solid var(--eq-accent); padding-left: 8px;
}
/* .eq-rec__link and .eq-rec__again went with the "Save … again" anchor they
   dressed: that link held the finished recording's blob: URL in the document,
   and a rule for a class no template emits is the orphan half of the same
   contract. Both are gone from index.html, so both are gone from here. */
.eq-rec__debug {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 10px; color: var(--ink-77); margin-top: 6px;
    border-top: 1px dashed var(--line); padding-top: 5px;
    overflow-x: auto; white-space: nowrap;
}


/* ------------------------------------------------------------- 8. the prose */
.eq-read { padding: 2.4rem 0 3rem; }
.eq-read h2 {
    font-size: 1.12rem; font-weight: 650; letter-spacing: -.02em;
    margin: 2rem 0 .5rem;
}
.eq-read h2:first-child { margin-top: 0; }
.eq-read p { font-size: .94rem; color: var(--ink-77); max-width: 68ch; margin-bottom: .7rem; }
.eq-read ul { font-size: .94rem; color: var(--ink-77); max-width: 68ch; padding-left: 1.1rem; }
.eq-read li { margin-bottom: .3rem; }
.eq-read a { color: var(--accent); text-underline-offset: 3px; }
/* Specific enough to beat `.eq-read a`, which is for links inside a sentence:
   this one is a card, and a card of orange body text reads as a warning. */
.eq-read a.eq-cross {
    display: block; max-width: 68ch;
    border: 1px solid var(--line); border-radius: 10px;
    padding: .9rem 1.1rem; margin: 1.2rem 0 0;
    background: var(--tint); font-size: .92rem;
    text-decoration: none; color: var(--ink-77);
}
.eq-read a.eq-cross:hover { border-color: var(--ink-55); }
.eq-cross b { color: var(--accent); }

.eq-noscript {
    max-width: var(--measure); margin: 1.6rem auto 0;
    padding: 1rem 1.2rem;
    border: 1px solid var(--accent); border-radius: 10px;
    background: color-mix(in srgb, var(--accent) 8%, transparent);
    font-size: .94rem;
}


/* ------------------------------------------------------------ 9. the footer */
.foot { border-top: 1px solid var(--line-dark); background: var(--deep); color: rgba(255,255,255,.5); }
.foot__in { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 2rem; padding-block: 2.2rem; }
.foot__in p { margin: 0; font-size: .78rem; }
.foot__links { display: flex; flex-wrap: wrap; gap: 1.4rem; margin-left: auto; }
.foot__links a { font-size: .78rem; text-decoration: none; color: rgba(255,255,255,.5); }
.foot__links a:hover { color: #fff; }
.foot :focus-visible { outline-color: #fff; }


/* ------------------------------------------------- 10. reduced motion, small
   The page is entirely movement, so it does not silently refuse to move: it
   starts paused, says why on the stage, and offers a control to start anyway.
   eq.js does that part; this only stops the chrome's own animations. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
    }
}

@media (max-width: 860px) {
    .nav__links { display: none; }
    .nav__mark span { display: none; }
}
@media (max-width: 700px) {
    #eq-app { min-height: min(78svh, 640px); grid-template-rows: auto minmax(200px, 1fr) auto; border-radius: 10px; margin-top: 1rem; }
    .eq-vizlabel { min-width: 0; flex: 1 1 100%; }
    /* The chips are a short scrolling block here, and the letters stay
       outside it.  72px, not 528's 64: exactly three chip rows (3 × 22px +
       2 × 3px), so a, b and c sit beside rows one, two and three as they do
       on a desktop, at the same 22px and 3px — 20px buttons on a 2px gap
       would have put the three letters closer than a 24px target allows.
       The stage does not pay for the 8px: on a phone it is already at its
       200px floor and the console grows instead. */
    .eq-grid { max-height: 72px; grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); }
    .eq-abc { padding-left: 4px; }
    .eq-palette__btn { padding: 3px 8px; }
    .eq-head { flex-wrap: wrap; row-gap: 4px; }
    .eq-h1 { font-size: 14px; }
    /* On a phone the recorder's status and the reason the button is off each
       take the whole width rather than squeezing the buttons off the row. */
    .eq-rec__bar { flex: 1 1 100%; }
    .eq-rec__status, .eq-rec__why, .eq-rec__fmt { flex: 1 1 100%; max-width: none; }
    .eq-rec__qbtn { min-width: 0; flex: 1 1 100%; }
    .eq-rec__f { min-width: 0; flex: 1 1 100%; }
    .eq-rec__body { max-height: min(360px, 48svh); }
}

/* =============================================================================================================
   LABS 536 — the control bar on one line, the recorder panel in two equal columns under three equal cards,
   colour on the numbers that matter, and the menu on the picture.
   ============================================================================================================= */
:root { --eq-warm: #A15C07; }                                  /* the per-minute figures: amber on paper … */
html[data-dark] { --eq-warm: #F2B544; }                          /* … gold on dark */
.vh { position: absolute !important; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
      clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }

/* ---- the bar: three groups and a status chip, one line from 1080 px up ---- */
.eq-controls { flex-wrap: nowrap; gap: 10px; margin-bottom: 8px; min-width: 0; }
.eq-cg { display: flex; align-items: center; gap: 8px; flex: none; }
.eq-cg--nav { gap: 5px; }
.eq-cg--tune { gap: 14px; padding: 0 12px; border-left: 1px solid var(--line); border-right: 1px solid var(--line); }
.eq-sliders { flex: none; flex-wrap: nowrap; }
.eq-slider input[type="range"] { width: 76px; }
.eq-vizlabel { width: 12.5rem; min-width: 0; margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.eq-cg--act { gap: 6px; }
.eq-foot .eq-cg--act .eq-btn { height: 30px; min-width: 88px; padding: 0 12px; font-size: 11.5px;
    display: inline-flex; align-items: center; justify-content: center; gap: 6px; white-space: nowrap; }
.eq-rec__meter { min-width: 4.5em; font-size: 11px; }
.eq-rec__status {
    flex: 1 1 auto; min-width: 0; max-width: none;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    font-size: 10.5px; color: var(--ink-77); line-height: 1;
    padding: 7px 11px; border-radius: 999px;
    background: color-mix(in srgb, var(--ink) 5%, transparent); border: 1px solid var(--line);
}
.eq-rec__status:empty { display: none; }
@media (max-width: 1080px) {
    .eq-controls { flex-wrap: wrap; }
    .eq-rec__status { flex-basis: 100%; }
}
@media (max-width: 720px) {
    .eq-cg { flex: 1 1 100%; flex-wrap: wrap; min-width: 0; }
    .eq-cg--tune { border: 0; padding: 0; gap: 10px 16px; }
    .eq-slider { flex: 1 1 9rem; }
    .eq-slider input[type="range"] { flex: 1; width: auto; min-width: 70px; }
    .eq-vizlabel { width: auto; flex: 1; }
    .eq-foot .eq-cg--act .eq-btn { flex: 1 1 0; min-width: 0; }
}

/* ---- the recorder panel ---- */
.eq-rec__sum { font-size: 11px; padding: 7px 12px; }
.eq-rec__body { max-height: none; overflow: visible; padding: 2px 12px 12px; }
.eq-rec__head { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin: 2px 0 10px; }
.eq-seg { display: inline-flex; padding: 3px; gap: 2px; border-radius: 999px;
          background: color-mix(in srgb, var(--ink) 6%, transparent); border: 1px solid var(--line); }
.eq-seg__b { appearance: none; -webkit-appearance: none; border: 0; background: transparent; color: var(--ink-77);
             font: inherit; font-size: 11.5px; font-weight: 600; padding: 6px 15px; border-radius: 999px; cursor: pointer;
             min-width: 8.5rem; transition: background .15s, color .15s; }
.eq-seg__b[aria-checked="true"] { background: var(--eq-press); color: var(--eq-press-ink); box-shadow: 0 0 8px var(--eq-glow); }
.eq-seg__b:disabled { opacity: .55; cursor: not-allowed; }
.eq-rec__rate { font-size: 11.5px; color: var(--ink-77); margin: 0; max-width: none; }
.eq-num { font-weight: 700; font-variant-numeric: tabular-nums; }
.eq-num--mb { color: var(--eq-warm); }
.eq-num--size { color: var(--eq-accent); }
.eq-num--name { font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.eq-num--bad { color: var(--danger); }

.eq-rec__qset { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin-bottom: 12px; flex-wrap: nowrap; }
.eq-rec__qbtn {
    min-width: 0; display: grid; grid-template-columns: 2.1rem minmax(0, 1fr); grid-template-rows: auto auto auto;
    column-gap: 10px; row-gap: 1px; align-items: center; text-align: left;
    padding: 9px 12px; border-radius: 10px; border: 1px solid var(--line);
    background: color-mix(in srgb, var(--ink) 3%, transparent);
}
.eq-rec__qbtn b { grid-row: 1 / span 3; font-size: 22px; font-weight: 800; line-height: 1; text-align: center; color: var(--eq-accent); }
.eq-rec__spec { font-size: 12px; font-weight: 600; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.eq-rec__bits { font-size: 11px; color: var(--ink-77); font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.eq-rec__mb { font-size: 11px; font-weight: 700; color: var(--eq-warm); font-variant-numeric: tabular-nums; }
.eq-rec__qbtn[aria-pressed="true"] { border-color: transparent; background: var(--eq-press); box-shadow: 0 0 10px var(--eq-glow); }
.eq-rec__qbtn[aria-pressed="true"] b,
.eq-rec__qbtn[aria-pressed="true"] .eq-rec__spec,
.eq-rec__qbtn[aria-pressed="true"] .eq-rec__bits,
.eq-rec__qbtn[aria-pressed="true"] .eq-rec__mb { color: var(--eq-press-ink); }

.eq-rec__cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.eq-rec__f { min-width: 0; flex: none; }
.eq-rec__f select { height: 34px; font-size: 12px; padding: 0 8px; }
.eq-rec__where { font-size: 11px; line-height: 1.45; color: var(--ink-55); margin: 6px 0 0; max-width: none; }
.eq-rec__fmt { margin-top: 10px; max-width: none; font-size: 11px; }
.eq-rec__result {
    font-size: 11.5px; line-height: 1.5; color: var(--ink-77); margin: 10px 0 0; max-width: none;
    padding: 8px 12px; border-radius: 8px; border-left: 3px solid var(--eq-accent);
    background: color-mix(in srgb, var(--eq-accent) 7%, transparent);
}
.eq-rec__fine { font-size: 10.5px; color: var(--ink-55); margin: 10px 0 0; max-width: none; }
@media (max-width: 720px) {
    .eq-rec__qset, .eq-rec__cols { grid-template-columns: 1fr; }
    .eq-seg__b { min-width: 0; }
}

/* ---- the prose: short facts instead of paragraphs ---- */
.eq-facts { list-style: none; padding: 0; margin: 0 0 .9rem; max-width: 68ch; display: grid; gap: .5rem; }
.eq-facts li { font-size: .94rem; line-height: 1.55; color: var(--ink-77); padding-left: 16px; position: relative; }
.eq-facts li::before { content: ""; position: absolute; left: 0; top: .6em; width: 6px; height: 6px; border-radius: 50%; background: var(--eq-accent); }
.eq-facts b { color: var(--ink); }
.eq-small { font-size: .85rem !important; color: var(--ink-55) !important; }

/* ---- the menu on the picture ---- */
.eq-menu {
    position: fixed; z-index: 1000; min-width: 16rem; max-width: 20rem; padding: 5px;
    border-radius: 12px; background: var(--paper); color: var(--ink);
    border: 1px solid var(--line); box-shadow: 0 16px 42px rgba(0, 0, 0, .24);
    font-size: 12px;
}
.eq-menu__h { font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-55); margin: 5px 9px 4px; }
.eq-menu__s { height: 1px; background: var(--line); margin: 4px 6px; }
.eq-menu__i {
    appearance: none; -webkit-appearance: none; display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 10px;
    width: 100%; text-align: left; border: 0; background: transparent; color: var(--ink); font: inherit;
    padding: 6px 9px; border-radius: 7px; cursor: pointer;
}
.eq-menu__i b { font-size: 12.5px; font-weight: 600; }
.eq-menu__i span { grid-column: 1 / -1; font-size: 10.5px; color: var(--ink-55); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.eq-menu__i kbd { grid-row: 1; grid-column: 2; font: inherit; font-size: 10px; color: var(--ink-55); border: 1px solid var(--line); border-radius: 4px; padding: 0 5px; align-self: center; }
.eq-menu__i:not([aria-disabled="true"]):hover,
.eq-menu__i:not([aria-disabled="true"]):focus-visible { background: var(--eq-press); color: var(--eq-press-ink); outline: none; }
.eq-menu__i:not([aria-disabled="true"]):hover span, .eq-menu__i:not([aria-disabled="true"]):focus-visible span,
.eq-menu__i:not([aria-disabled="true"]):hover kbd, .eq-menu__i:not([aria-disabled="true"]):focus-visible kbd { color: inherit; border-color: currentColor; opacity: .9; }
.eq-menu__i[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }
.eq-menu__sens { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 4px; padding: 0 6px 6px; }
.eq-menu__sb { appearance: none; -webkit-appearance: none; border: 1px solid var(--line); background: transparent; color: var(--ink-77);
               font: inherit; font-size: 11px; padding: 5px 0; border-radius: 6px; cursor: pointer; }
.eq-menu__sb:hover, .eq-menu__sb:focus-visible { border-color: var(--eq-accent); color: var(--ink); outline: none; }
.eq-menu__sb[aria-checked="true"] { background: var(--eq-press); color: var(--eq-press-ink); border-color: transparent; }
#stage:focus-visible { outline: 2px solid var(--eq-accent); outline-offset: -2px; }

/* ---- 537: the prose in two equal columns, as wide as the recorder box ----
   .eq-read sits in the same .wrap as the box, so a column pair spanning it lines up with both of the box's
   edges. A pair is one grid row (both halves start level); the privacy section flows through two balanced
   columns under a heading that spans them. One column below 860px. */
.eq-read p, .eq-read ul, .eq-facts, .eq-read a.eq-cross { max-width: none; }
.eq-read__pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 3rem; align-items: start; }
.eq-read__pair + .eq-read__flow, .eq-read__flow + .eq-read__pair { margin-top: 2.6rem; padding-top: 2.2rem; border-top: 1px solid var(--line); }
.eq-read__flow { column-count: 2; column-gap: 3rem; }
.eq-read__flow h2 { column-span: all; margin-top: 0; margin-bottom: .9rem; }
.eq-read__flow p { orphans: 3; widows: 3; }
@media (max-width: 860px) {
    .eq-read__pair { grid-template-columns: minmax(0, 1fr); }
    .eq-read__col + .eq-read__col { margin-top: 2rem; }
    .eq-read__flow { column-count: 1; }
}

/* TAPZOOM558:START — labs 558, written by tools/tapzoom558.py (the one source; do not edit here). The owner:
   "(double tap zoom on mobile) other pages may have the same issue , chk other pages". On the root, on every
   page that carries this sheet: a double tap no longer zooms and a tap is not held back for one. PINCH-ZOOM AND
   SCROLLING STAY (never user-scalable=no); an element with gestures of its own keeps its own touch-action. */
html { touch-action: manipulation; }
/* TAPZOOM558:END */
