
      .settings-view { max-width: 900px; margin: 0 auto; padding: 1.5rem 1rem 4rem; }
      .settings-view-header { display: flex; align-items: center; gap: 1rem; margin-bottom: 1.75rem; flex-wrap: wrap; }
      .settings-view-title { font-size: 1.25rem; font-weight: 700; color: var(--text-1); margin: 0; }
      .settings-view-subtitle { font-size: 0.8rem; color: var(--text-muted); margin: 0; }

      .settings-section { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--r-md); margin-bottom: 0.75rem; overflow: hidden; }
      .settings-section[open] > .settings-section-summary { border-bottom: 1px solid var(--border-subtle); }
      /* Elevation: lifted sub-cards cast a subtle shadow so grouped blocks read
         as raised above the section card (was flat — every surface shared one tone). */
      .linked-card, .analyzer-device-details, .trace-block, .rec-job-card,
      .picker-item, .det-bands-host { box-shadow: 0 1px 3px rgba(0,0,0,0.4); }
      /* Eyebrow label for a grouped sub-block inside a card. */
      .group-eyebrow { font-size: 0.68rem; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: var(--text-2); margin: 0.45rem 0 0.2rem; display: flex; align-items: center; gap: 0.4rem; }
      .group-eyebrow::before { content: ''; width: 3px; height: 0.8rem; background: var(--accent); border-radius: 2px; flex-shrink: 0; }
      .settings-section-summary { list-style: none; display: flex; align-items: center; gap: 0.75rem; padding: 0.9rem 1.1rem; cursor: pointer; user-select: none; }
      .settings-section-summary::-webkit-details-marker { display: none; }
      .settings-section-summary::before { content: ''; width: 0.4rem; height: 0.4rem; border-right: 1.6px solid var(--text-muted); border-bottom: 1.6px solid var(--text-muted); transform: rotate(-45deg); transition: transform 0.15s; flex-shrink: 0; }
      .settings-section[open] > .settings-section-summary::before { transform: rotate(45deg); }
      .settings-section-name { font-size: 0.9rem; font-weight: 600; color: var(--text-1); flex: 1; }
      .settings-section-body { padding: 1.1rem; display: flex; flex-direction: column; gap: 0.65rem; }
      .settings-section-title { font-size: 0.75rem; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.06em; margin: 0.35rem 0 0.25rem; align-self: stretch; }

      .settings-subsection { border: 1px solid var(--border-subtle); border-radius: var(--r-sm); margin-bottom: 0.5rem; overflow: hidden; }
      .settings-subsection-summary { list-style: none; display: flex; align-items: center; gap: 0.5rem; padding: 0.6rem 0.85rem; cursor: pointer; font-size: 0.85rem; font-weight: 600; color: var(--text-2); user-select: none; }
      .settings-subsection-summary::-webkit-details-marker { display: none; }
      .settings-subsection-summary::before { content: ''; width: 0.36rem; height: 0.36rem; border-right: 1.5px solid var(--text-muted); border-bottom: 1.5px solid var(--text-muted); transform: rotate(-45deg); transition: transform 0.15s; flex-shrink: 0; }
      .settings-subsection[open] > .settings-subsection-summary::before { transform: rotate(45deg); }
      .settings-subsection-body { padding: 0.75rem 0.85rem; display: flex; flex-direction: column; gap: 0.5rem; }

      /* ── Text-aware width root rule ───────────────────────────────────────────
         The section/subsection bodies are flex columns with align-items:flex-start,
         so by default every control (input, select, standalone button) hugs its
         content and left-aligns instead of stretching full-width. Elements that
         legitimately span the row opt back in to full width below. */
      .settings-section-body > hr,
      .settings-subsection-body > hr,
      .settings-section-body > table,
      .settings-subsection-body > table,
      .settings-section-body > .member-table,
      .settings-section-body > .tag-list,
      .settings-section-body > .marker-file-list,
      .settings-section-body > .rec-job-list,
      .settings-section-body > .venue-addr-field,
      .settings-section-body > .det-bands-table,
      .settings-section-body > .coverage-map,
      .settings-section-body > .linked-status-wrap,
      .settings-section-body > .schedule-status-row,
      .settings-section-body > .venue-map-placeholder,
      .settings-subsection-body > .form-grid,
      .settings-subsection-body > .help-body,
      .settings-section-body > .full,
      .settings-subsection-body > .full { align-self: stretch; width: 100%; }

      /* Standalone buttons that are direct children of a body hug their label and
         left-align (Save Y-axis, Save retention, Prune all, Save detection, etc.).
         Buttons inside row()/stack() wrappers are unaffected. Groups wrap. */
      .settings-section-body > .btn,
      .settings-subsection-body > .btn { align-self: flex-start; width: auto; }
      .settings-actions-bar { display: flex; flex-wrap: wrap; gap: 0.5rem; align-self: flex-start; }

      .form-label { font-size: 0.8rem; color: var(--text-1); font-weight: 500; max-width: 100%; }
      .form-label--block { display: block; }
      .form-hint { font-size: 0.75rem; color: var(--text-2); margin: 0; }
      /* .form-input / .form-select appearance and token widths live in
         styles/components.css (loaded at boot). This sheet keeps only the
         phone override below, which has to come after the .form-input width: 280px rule. */
      /* color-scheme:dark (tokens.css) already renders the native calendar/clock
         picker indicators light on our dark inputs — so do NOT invert them (that
         flipped the white glyph back to dark/invisible). Just keep the pointer cursor. */
      .settings-view input[type="date"]::-webkit-calendar-picker-indicator,
      .settings-view input[type="time"]::-webkit-calendar-picker-indicator,
      .modal input[type="date"]::-webkit-calendar-picker-indicator,
      .modal input[type="time"]::-webkit-calendar-picker-indicator { cursor: pointer; }
      .form-check { width: 1rem; height: 1rem; cursor: pointer; accent-color: var(--accent); flex-shrink: 0; }
      .form-row { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
      .form-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 0.75rem; }
      .form-field { display: flex; flex-direction: column; gap: 0.25rem; }
      .color-swatch-input { width: 32px; height: 28px; padding: 1px; border: 1px solid var(--border-subtle); border-radius: var(--r-sm); cursor: pointer; background: none; flex-shrink: 0; }
      .check-label { display: flex; align-items: center; gap: 0.4rem; cursor: pointer; }
      .check-text { font-size: 0.825rem; color: var(--text-2); }
      .dirty-dot { color: var(--warn, #f59e0b); font-size: 1.1rem; line-height: 1; }

      .member-table { display: flex; flex-direction: column; gap: 0.5rem; }
      .member-row { display: flex; align-items: center; gap: 0.75rem; padding: 0.5rem 0; flex-wrap: wrap; }
      .member-info { display: flex; flex-direction: column; flex: 1; min-width: 160px; }
      .member-name { font-size: 0.85rem; color: var(--text-1); font-weight: 500; }
      .member-email { font-size: 0.75rem; color: var(--text-muted); }
      .add-member-bar { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }

      /* Flex column + gap (same pattern as .settings-section-body): the card, the
         action row, hints, inbox and key row can never touch. Was a plain block,
         so its children had no spacing at all. */
      .linked-status-wrap { min-height: 2rem; display: flex; flex-direction: column; gap: var(--s3); min-width: 0; }
      .linked-status-wrap > .btn { align-self: flex-start; }
      .linked-status-wrap > .form-hint, .linked-status-wrap > .linked-action-result { margin: 0; }
      .linked-card { background: var(--bg-surface, #1e293b); border: 1px solid var(--border-subtle); border-radius: var(--r-sm); padding: 0.75rem 1rem; display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
      .linked-info { display: flex; flex-direction: column; gap: 0.2rem; flex: 1; }
      .linked-name { font-size: 0.875rem; font-weight: 600; color: var(--text-1); }
      .linked-meta { font-size: 0.75rem; color: var(--text-muted); }

      .analyzer-device-details { background: var(--bg-2); border: 1px solid var(--border); border-radius: var(--r-sm); overflow: hidden; }
      /* Collapsed height matches the §9 Miscellaneous sub-cards
         (.settings-subsection-summary: 0.6rem pad + ~16px text line ≈ 35px,
         operator feedback 2026-09-01). The old 0.65rem padding wasn't the
         driver — the gear/Detach .btn (min-height 33px) was, pushing the row
         to ~54px. Compact the header buttons (scoped: body buttons untouched)
         and trim the padding so 0.35rem + 24px btn + 0.35rem ≈ 35px. */
      .analyzer-device-summary { list-style: none; display: flex; align-items: center; gap: 0.5rem; padding: 0.35rem 0.85rem; cursor: pointer; user-select: none; flex-wrap: wrap; }
      .analyzer-device-summary .btn { min-height: 24px; padding: 3px 9px; font-size: 12px; }
      .analyzer-device-summary .btn.btn-icon { padding: 3px; min-width: 24px; }
      .analyzer-device-summary::-webkit-details-marker { display: none; }
      .analyzer-device-summary::before { content: ''; width: 0.36rem; height: 0.36rem; border-right: 1.5px solid var(--text-muted); border-bottom: 1.5px solid var(--text-muted); transform: rotate(-45deg); transition: transform 0.15s; flex-shrink: 0; }
      .analyzer-device-details[open] > .analyzer-device-summary::before { transform: rotate(45deg); }
      .analyzer-device-name { font-size: 0.875rem; font-weight: 700; color: var(--text-1); flex: 1; }
      .analyzer-device-body { padding: 0.75rem 0.85rem; display: flex; flex-direction: column; gap: 0.5rem; border-top: 1px solid var(--border); }

      /* Collapsible per-trace editor (§4): compact summary row; full editor hidden
         until expanded — matches the section/analyzer collapse pattern. */
      .trace-block { background: var(--bg-raised); border: 1px solid var(--border); border-radius: var(--r-sm); overflow: hidden; }
      .trace-summary { list-style: none; display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; padding: 0.5rem 0.7rem; cursor: pointer; user-select: none; }
      /* The source line sits under the name, the full card width, so a long device name or address wraps instead of crowding the range. */
      .trace-summary-src { flex: 1 0 100%; order: 9; min-width: 0; color: var(--text-muted); font-size: 0.72rem; overflow-wrap: anywhere; }
      .trace-summary::-webkit-details-marker { display: none; }
      .trace-summary::before { content: ''; width: 0.34rem; height: 0.34rem; border-right: 1.5px solid var(--text-muted); border-bottom: 1.5px solid var(--text-muted); transform: rotate(-45deg); transition: transform 0.15s; flex-shrink: 0; }
      .trace-block[open] > .trace-summary::before { transform: rotate(45deg); }
      .trace-block[open] > .trace-summary { border-bottom: 1px solid var(--border-subtle); }
      .trace-dot { width: 8px; height: 8px; border-radius: 50%; background: #5b6473; flex-shrink: 0; }
      .trace-dot.on { background: var(--ok, #34d399); }
      .trace-summary-name { font-weight: 600; color: var(--text-1); font-size: 0.85rem; }
      .trace-summary-meta { color: var(--text-2); font-size: 0.72rem; font-family: var(--font-mono, monospace); margin-left: auto; }
      .trace-block > :not(summary) { margin: 0.45rem 0.7rem; }
      /* The "Covers:" read-out. It had NO rule anywhere, so it inherited the panel
         default while the .form-label beside it declares its own size — two type
         sizes on one row (owner report 2026-09-18: "the text after Covers: 'All
         Zones' seems to be different size and font then the rest of the page").
         Read-only value text beside a control in this panel is .check-text, so this
         takes that treatment rather than a size invented for it. */
      .trace-coverage-state { font-size: 0.825rem; color: var(--text-2); }

      .tag-list { display: block; max-width: 100%; overflow-x: auto; }
      .tag-table { border-collapse: separate; border-spacing: 0 0.35rem; }
      .tag-table th { text-align: left; font-size: 11px; font-weight: 600; color: var(--text-2); padding: 0 0.45rem 0 0; white-space: nowrap; }
      .tag-table td { padding: 0 0.45rem 0 0; vertical-align: middle; }
      .tag-table td:last-child, .tag-table th:last-child { padding-right: 0; }

      /* One shared grid so every file's controls line up and the name field
         grows to fill (never truncated). Cols: swatch | name(grows) | update | sync | manage | delete. */
      .marker-file-list { display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto auto auto; align-items: center; column-gap: 0.5rem; row-gap: 0.2rem; }
      .marker-file-list .mf-meta,
      .marker-file-list .mf-hr { grid-column: 1 / -1; }
      /* §8 header row (Visible fields + Add marker) sits above the file list. */
      .mf-section-header { margin-bottom: 0.5rem; }
      /* Time slots (§3 of the 2026-09-18 design): one box per slot. */
      .time-slot-list { display: flex; flex-direction: column; gap: 0.6rem; }
      .time-slot-box { border: 1px solid var(--border-subtle); border-radius: var(--r-sm, 6px); padding: 0.55rem 0.7rem; display: flex; flex-direction: column; gap: 0.45rem; }
      .time-slot-name { font-weight: 600; color: var(--text-1); font-size: 0.85rem; }
      .time-slot-whole { font-style: italic; }
      .time-slot-guessed { margin: 0; font-style: italic; }
      .time-slot-zones { margin: -0.25rem 0 0; font-size: 0.75rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
      .time-slot-need-times { margin-left: 0.35rem; }
      /* §8 → Time slots pointer: one quiet line under the file list. */
      .mf-slots-link { margin: 0.5rem 0 0.25rem; }
      .mf-slots-link .btn { margin-left: 0.15rem; }
      .time-slot-head .badge { margin-left: 0.2rem; }
      /* Ungrouped pseudo-entry: a muted dot in the swatch column + italic name. */
      .mf-ungrouped-dot { width: 14px; height: 14px; border-radius: 50%; background: var(--text-muted, #7f93b5); opacity: 0.5; justify-self: center; }
      .mf-ungrouped-name { color: var(--text-muted, #7f93b5); font-style: italic; padding: 0.35rem 0; }

      /* ── Per-file marker manager modal (full-width aligned table) ─────────────
         The modal goes NEAR-FULL-SCREEN (see .mm-modal-full below, scoped to this
         one modal via openModal({ className })) so the field columns have room.
         The table's id columns (eye/color · name · freq · status) are frozen
         (position:sticky left); the field columns fill the rest and only THEY
         scroll horizontally when they overflow — the id columns stay put. */

      /* Full-width modal — overrides .modal / .modal--wide width for THIS modal
         only. ~96vw wide and tall so the spreadsheet gets real estate. */
      .modal.mm-modal-full {
        width: 96vw; max-width: 96vw;
        height: 92vh; max-height: 92vh;
      }
      .modal.mm-modal-full .modal-body { display: flex; flex-direction: column; }

      .mm-body { display: flex; flex-direction: column; gap: 0.65rem; min-width: 0; flex: 1 1 auto; min-height: 0; }
      .mm-head { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap; }
      .mm-head-info { display: flex; align-items: baseline; gap: 0.6rem; min-width: 0; }
      .mm-file-name { font-weight: 600; color: var(--text-1, #e6edf7); }
      .mm-counts { font-size: 0.8rem; color: var(--text-muted, #7f93b5); }

      .mm-toolbar { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
      .mm-search { flex: 1 1 220px; min-width: 0; padding: 0.35rem 0.55rem; background: var(--bg-surface, #1e293b); border: 1px solid var(--border-subtle, #2a3854); border-radius: var(--r-sm, 6px); color: var(--text-1, #e6edf7); font-size: 0.85rem; }
      .mm-showhidden { display: flex; align-items: center; gap: 0.35rem; font-size: 0.82rem; color: var(--text-muted, #7f93b5); white-space: nowrap; }

      /* Table wrap fills the remaining modal height; the inner .mm-scroll owns the
         ONLY horizontal scrollbar so the frozen columns can stay sticky within it. */
      .mm-table-wrap { flex: 1 1 auto; min-height: 0; display: flex; }
      .mm-scroll {
        flex: 1 1 auto; min-width: 0; overflow: auto;
        border: 1px solid var(--border-subtle, #2a3854); border-radius: var(--r-sm, 6px);
      }
      .mm-table {
        border-collapse: separate; border-spacing: 0; width: 100%;
        font-size: 0.78rem; color: var(--text-1, #e6edf7);   /* ≈12.5px — matches the monitor pane header */
      }
      /* Header row — sticks to the TOP while body rows scroll vertically. */
      .mm-thead .mm-h {
        position: sticky; top: 0; z-index: 3;
        background: var(--bg-2, #141c2e); text-align: left; font-weight: 600;
        font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.03em;
        color: var(--text-muted, #7f93b5); white-space: nowrap;
        padding: 0.4rem 0.6rem; border-bottom: 1px solid var(--border-subtle, #2a3854);
        vertical-align: top;
      }
      /* Header cell content — sortable label stacked above the per-column filter. */
      .mm-h-inner { display: flex; flex-direction: column; gap: 0.3rem; align-items: stretch; }
      /* Click-to-sort label (a real <button> for keyboard access); reset chrome so
         it reads as the header text plus a ▲/▼ sort indicator. */
      .mm-h-label {
        display: inline-flex; align-items: center; gap: 0.3rem;
        background: none; border: 0; padding: 0; margin: 0; cursor: pointer;
        font: inherit; color: inherit; text-transform: inherit; letter-spacing: inherit;
        text-align: left; white-space: nowrap;
      }
      .mm-h-label:hover .mm-h-text { color: var(--text-1, #e6edf7); }
      .mm-h-label:focus-visible { outline: 2px solid var(--accent, #6366f1); outline-offset: 2px; border-radius: 3px; }
      .mm-sort-ind { font-size: 0.6rem; line-height: 1; color: var(--accent-text, #6366f1); min-width: 0.7em; display: inline-block; }
      /* Unit suffix kept on dropdown-filter headers (no placeholder to carry it) —
         not uppercased, dimmer, so "(MHz)" reads correctly and stays out of the way. */
      .mm-h-unit { text-transform: none; font-weight: 400; letter-spacing: normal; opacity: 0.7; }
      /* Per-column filter control — plain (not uppercase) so it reads as an input. */
      .mm-filter {
        box-sizing: border-box; padding: 0.2rem 0.35rem;
        background: var(--bg-input, #090a0d); border: 1px solid var(--border-subtle, #2a3854);
        border-radius: var(--r-sm, 6px); color: var(--text-1, #e6edf7);
        font-size: 0.72rem; font-weight: 400; text-transform: none; letter-spacing: normal;
      }
      .mm-filter[data-field="fill"] { width: 100%; }
      .mm-filter::placeholder { color: var(--text-muted, #7f93b5); }
      .mm-filter:focus { outline: none; border-color: var(--accent, #6366f1); box-shadow: 0 0 0 2px var(--accent-soft, rgba(99,102,241,0.16)); }
      .mm-filter-select { cursor: pointer; }
      .mm-td {
        padding: 0.35rem 0.6rem; vertical-align: top;
        border-bottom: 1px solid var(--border-subtle, #2a3854);
      }
      .mm-row:hover .mm-td { background: var(--bg-hover, rgba(255,255,255,0.03)); }

      /* Frozen id columns — position:sticky with cumulative left offsets and a
         SOLID background so scrolled field cells don't bleed through. z-index is
         above the field cells (2) and, in the header, above the sticky header (3
         base → 4 for frozen headers). Left offsets: eye 0, name 44, freq 200,
         status 320 — keep these in sync with the column min-widths below. */
      .mm-sticky { position: sticky; z-index: 2; background: var(--bg-surface, #1e293b); }
      .mm-thead .mm-sticky { z-index: 4; background: var(--bg-2, #141c2e); }
      .mm-sticky-eye    { left: 0; }
      .mm-sticky-name   { left: 56px; }   /* = eye width */
      .mm-sticky-freq   { left: 212px; }  /* = eye 56 + name 156 */
      .mm-sticky-status { left: 332px; box-shadow: 1px 0 0 var(--border-subtle, #2a3854); }  /* + freq 120 */
      .mm-thead .mm-sticky-status { box-shadow: 1px 0 0 var(--border-subtle, #2a3854); }
      /* Frozen-RIGHT actions column (delete) — always reachable. */
      .mm-sticky-r { position: sticky; right: 0; z-index: 2; background: var(--bg-surface, #1e293b); box-shadow: -1px 0 0 var(--border-subtle, #2a3854); }
      .mm-thead .mm-sticky-r { z-index: 4; background: var(--bg-2, #141c2e); }
      /* Hover on frozen cells stays OPAQUE (--bg-hover is translucent and would let
         scrolled cells show through): lift the surface instead. */
      .mm-row:hover .mm-sticky, .mm-row:hover .mm-sticky-r { background: color-mix(in srgb, var(--bg-surface) 94%, #fff); }

      /* Column sizing — the frozen id columns are fixed-ish; field columns get a
         readable min-width and wrap long values (a long Device Name grows TALLER,
         not absurdly wide) but cap so one field can't dominate the row. */
      .mm-h-eye, .mm-td-eye { width: 56px; }
      .mm-h-name, .mm-td-name { min-width: 156px; max-width: 240px; }
      .mm-h-freq, .mm-td-freq { min-width: 120px; }
      .mm-h-status, .mm-td-status { min-width: 120px; }
      .mm-h-field, .mm-td-field { min-width: 130px; max-width: 260px; }
      /* Short-value columns don't need the default 130px floor — narrow them so the
         wide table wastes less horizontal room (units now live in the filter row). */
      .mm-h-field[data-key="bw_hz"], .mm-td-field[data-key="bw_hz"],
      .mm-h-field[data-key="channel_number"], .mm-td-field[data-key="channel_number"],
      .mm-h-field[data-key="coordination_status"], .mm-td-field[data-key="coordination_status"],
      .mm-h-field[data-key="tunable"], .mm-td-field[data-key="tunable"],
      .mm-h-field[data-key="tuning_from_mhz"], .mm-td-field[data-key="tuning_from_mhz"],
      .mm-h-field[data-key="tuning_to_mhz"], .mm-td-field[data-key="tuning_to_mhz"],
      .mm-h-field[data-key="filter_from_mhz"], .mm-td-field[data-key="filter_from_mhz"],
      .mm-h-field[data-key="filter_to_mhz"], .mm-td-field[data-key="filter_to_mhz"],
      .mm-h-field[data-key="tx_power_mw"], .mm-td-field[data-key="tx_power_mw"],
      .mm-h-field[data-key="tuning_steps_khz"], .mm-td-field[data-key="tuning_steps_khz"],
      .mm-h-field[data-key="channel_spacing_khz"], .mm-td-field[data-key="channel_spacing_khz"],
      .mm-h-field[data-key="amount_mobile"], .mm-td-field[data-key="amount_mobile"],
      .mm-h-field[data-key="amount_portable"], .mm-td-field[data-key="amount_portable"] {
        min-width: 92px; max-width: 150px;
      }
      /* Columns carrying a unit filter placeholder ("Filter… (MHz)") need a touch
         more room than the bare-"Filter…" ones so the unit isn't clipped. */
      .mm-h-field[data-key="bw_hz"], .mm-td-field[data-key="bw_hz"],
      .mm-h-field[data-key="tuning_from_mhz"], .mm-td-field[data-key="tuning_from_mhz"],
      .mm-h-field[data-key="tuning_to_mhz"], .mm-td-field[data-key="tuning_to_mhz"],
      .mm-h-field[data-key="filter_from_mhz"], .mm-td-field[data-key="filter_from_mhz"],
      .mm-h-field[data-key="filter_to_mhz"], .mm-td-field[data-key="filter_to_mhz"],
      .mm-h-field[data-key="tx_power_mw"], .mm-td-field[data-key="tx_power_mw"],
      .mm-h-field[data-key="tuning_steps_khz"], .mm-td-field[data-key="tuning_steps_khz"],
      .mm-h-field[data-key="channel_spacing_khz"], .mm-td-field[data-key="channel_spacing_khz"] {
        min-width: 112px;
      }
      .mm-td-field .mm-cell-val { display: inline-block; max-width: 100%; overflow-wrap: anywhere; }
      .mm-h-actions, .mm-td-actions { width: 44px; text-align: center; }

      .mm-td-eye { white-space: nowrap; }
      /* Color swatch — comfortable, consistent gap to the eye toggle; a
         transparent placeholder (.mm-dot-empty) reserves the same slot on rows
         with no color so the eye keeps a constant x-position down the column. */
      .mm-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 0.5rem; vertical-align: middle; box-shadow: 0 0 0 1px rgba(0,0,0,0.25); }
      .mm-dot-empty { background: transparent; box-shadow: none; }
      .mm-eye { cursor: pointer; user-select: none; display: inline-flex; align-items: center; line-height: 1; vertical-align: middle; color: var(--text-1, #e6edf7); }
      .mm-eye.off { color: var(--text-muted, #7f93b5); }   /* hidden marker — the eye-off icon reads muted */
      .mm-eye:hover { color: var(--accent-text, #6366f1); }
      .mm-eye:focus-visible { outline: 2px solid var(--accent, #6366f1); border-radius: 4px; }
      .mm-name { font-weight: 600; color: var(--text-1, #e6edf7); overflow-wrap: anywhere; }
      .mm-freq { color: var(--text-muted, #7f93b5); font-family: var(--font-mono, monospace); white-space: nowrap; }
      .mm-cell-val { color: var(--text-1, #e6edf7); }
      .mm-field .k { display: none; }               /* renderEditableField's own label span — the column header already names the field */
      .mm-field .v { color: var(--text-1, #e6edf7); }
      /* Select-backed editable cells (Status, Location) render as an always-visible
         platform dropdown — the SAME <select class="form-select"> used across the
         platform (see selectEl / .form-select above), so the affordance reads as a
         dropdown at rest and there is no span→box morph on click. Only a compact
         report-cell variant here: fit the dense table row, never overflow the cell. */
      .mm-field .form-select.mm-select {
        max-width: 100%; font-size: 0.8rem; padding: 0.28rem 0.45rem;
        vertical-align: middle;
      }
      /* Select-backed cells (Location, Status): lay the reset-dot + dropdown out
         as one flex row so the <select> shrinks to fit BESIDE the dot instead of
         wrapping under it (the dot + a max-width:100% select overflow an
         inline-block cell → line break). flex:1 min-width:0 lets it shrink. */
      .mm-field:has(.form-select.mm-select) {
        display: flex; align-items: center; flex-wrap: nowrap;
      }
      .mm-field:has(.form-select.mm-select) .form-select.mm-select {
        flex: 1 1 auto; min-width: 0;
      }
      /* renderEditableField's reset-dot (• = "edited locally"): the shared .mi-resetdot
         rule is scoped to the monitor popup, so restyle it for the report and — the
         reported bug — give it clear separation (it sat jammed against the value). */
      .mm-field .mi-resetdot {
        margin-right: 0.4rem; padding: 0; background: none; border: 0;
        color: var(--text-muted, #7f93b5); font-size: 0.95rem; line-height: 1;
        cursor: pointer; vertical-align: middle;
      }
      .mm-field .mi-resetdot.on { color: var(--warn, #fbbf24); }
      .mm-field .mi-resetdot:hover { color: var(--text-1, #e6edf7); }
      .mm-row.hidden .mm-field, .mm-row.hidden .mm-name, .mm-row.hidden .mm-freq, .mm-row.hidden .mm-eye { opacity: 0.5; text-decoration: line-through; }
      .mm-empty { margin: 0.75rem 0; color: var(--text-muted, #7f93b5); font-size: 0.85rem; }

      /* Loading shell (instant open): shimmer placeholders under the real table
         chrome while the marker list is in flight — replaced by data rows the
         moment they land (openMarkerManager renderSkeleton). */
      .mm-skel {
        display: inline-block; width: 72%; height: 0.8rem; border-radius: 4px;
        background: var(--bg-hover, rgba(255,255,255,0.06));
        animation: mm-skel-pulse 1.1s ease-in-out infinite;
      }
      .mm-skel-dot { width: 10px; height: 10px; border-radius: 50%; }
      .mm-skel-row .mm-td-name .mm-skel { width: 82%; }
      .mm-skel-row .mm-td-freq .mm-skel { width: 64%; }
      .mm-skel-row .mm-td-status .mm-skel { width: 58%; }
      @keyframes mm-skel-pulse { 0%, 100% { opacity: 0.45; } 50% { opacity: 0.95; } }

      /* Visible-fields picker — now mounted as the body of a centered modal (was a
         position:fixed anchored popover), so it carries NO chrome of its own (no
         border / shadow / fixed width); the modal supplies those. The modal header
         already shows the "Visible marker fields" title, so the picker's own
         .mfp-title is hidden inside the modal to avoid a duplicate heading (kept in
         the DOM for the standalone openFieldPicker unit test). */
      .mfp-pop { min-width: 0; }
      .modal-body .mfp-title { display: none; }
      .mfp-title { margin: 0 0 3px; font-size: 13px; }
      .mfp-sub { margin: 0 0 10px; font-size: 11px; color: var(--text-muted, #7f93b5); }
      .mfp-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 12px; max-height: 50vh; overflow: auto; }
      .mfp-item { display: flex; align-items: center; gap: 6px; font-size: 12px; }

      /* ── Add-marker dialog (V8) ───────────────────────────────────────────────
         Settings control standard (same pattern as the fixed notification-rule
         modal — operator feedback 2026-09-01): each field is an inline
         "Label: [control]" row built from the shared form-label / form-input /
         form-select classes, with content-aware widths (freq/bw compact mono,
         name a comfortable text width, selects natural fit-content) instead of
         full-modal-width inputs under uppercase eyebrow labels. The am-* classes
         remain as functional hooks for wiring + tests. */
      .am-body { display: flex; flex-direction: column; gap: var(--s2, 8px); min-width: min(420px, 78vw); }
      .am-field, .am-file-field { display: flex; flex-direction: row; flex-wrap: wrap; align-items: center; gap: var(--s2, 8px); min-width: 0; }
      /* Content-aware widths — the compound selectors out-specify .form-input's
         default 240px. Numeric fields are compact mono; text fields medium. */
      .am-body .form-input.am-w-name { width: 17rem; max-width: 100%; }
      .am-body .form-input.am-w-freq { width: 7rem; }
      .am-body .form-input.am-w-bw   { width: 6rem; }
      .am-body .form-input.am-w-num  { width: 7rem; }
      .am-body .form-input.am-w-text { width: 14rem; max-width: 100%; }
      /* Added-field rows stack with the same rhythm; each carries a small ×
         (.am-remove-field, after the input) to take the field back out. */
      .am-added { display: flex; flex-direction: column; gap: var(--s2, 8px); }
      .am-added:empty { display: none; }
      .am-remove-field {
        background: none; border: none; padding: 0 0.2rem; line-height: 1;
        color: var(--text-muted, #6e727c); font-size: 1rem; cursor: pointer;
      }
      .am-remove-field:hover { color: var(--danger, #e5484d); }
      .am-add-field { display: flex; flex-direction: column; gap: var(--s1, 4px); }
      /* "+ Add field…" keeps its accent affordance on top of the shared select. */
      .am-add-select { align-self: flex-start; color: var(--accent-text, #5e6ad2); cursor: pointer; }
      /* Buttons wrapped in .am-footer inside the modal's own .modal-footer — lay
         them out right-aligned with the standard gap (the footer container only
         sees .am-footer as a single child, so the row spacing lives here). */
      .am-footer { display: flex; align-items: center; justify-content: flex-end; gap: var(--s2, 8px); width: 100%; }

      .coverage-map { display: flex; gap: 6px; align-items: flex-end; flex-wrap: wrap; padding: 0.5rem; background: var(--bg-surface, #1e293b); border-radius: var(--r-sm); border: 1px solid var(--border-subtle); }
      .coverage-band-bar { background: none; border: none; cursor: pointer; padding: 2px; display: flex; flex-direction: column; align-items: center; gap: 2px; }
      .coverage-band-bar:hover .coverage-band-fill { opacity: 1; }
      .coverage-popover { min-width: 200px; padding: 0.5rem; }
      .coverage-popover-title { font-size: 0.85rem; font-weight: 600; color: var(--text-1); margin: 0 0 0.4rem; }
      .coverage-bar-row { display: flex; align-items: center; gap: 0.4rem; margin-bottom: 0.3rem; }
      .coverage-bar { flex: 1; height: 8px; background: var(--bg-card); border-radius: 4px; overflow: hidden; }
      .coverage-bar-fill { height: 100%; background: var(--accent); border-radius: 4px; }

      /* Detection-bands grid: NATIVE table layout so the header row and every
         input row share ONE set of column tracks (labels sit exactly above their
         fields at any width). The previous display:flex override made thead and
         tbody lay out their columns independently — headers drifted off their
         inputs, worsening rightward. Row spacing comes from border-spacing on the
         table element (inline), not flex gaps. */
      .det-bands-table th { white-space: normal; overflow-wrap: anywhere; vertical-align: bottom; }
      .det-bands-msg:empty { display: none; }
      /* Phone: at ≤760px the bands grid CRUSHED to fit — headers letter-wrapped
         ("Sta rt (M Hz)") and number inputs collapsed to spinner-only ~20px.
         Give columns sane floors and let the table scroll sideways instead
         (display:block keeps the shared column tracks). Same treatment for the
         audit-log table, which was clipped at the card edge with the Detail
         column unreachable. */
      @media (max-width: 760px) {
        .det-bands-table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
        .det-bands-table th { min-width: 64px; overflow-wrap: normal; }
        .det-bands-table input { min-width: 64px; }
        .settings-subsection-body > table.dt,
        .settings-section-body > table.dt { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
      }

      /* Recordings manage modal: one consistent vertical rhythm for all sections so the
         Retention row, Save/Prune buttons, the card list, and the footer buttons share even
         spacing instead of the mixed 0 / 0.6rem gaps the per-element margins produced. */
      .rec-modal-body { display: flex; flex-direction: column; gap: 0.85rem; align-items: stretch; }
      .rec-modal-body > hr { margin: 0 !important; }    /* gap owns the spacing now; !important beats hline()'s inline margin */
      .rec-modal-body > .settings-section-title { margin: 0; }
      .rec-modal-body > .form-hint { margin: 0; }

      .rec-job-list { display: flex; flex-direction: column; gap: 0.5rem; }
      .rec-job-row { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; padding: 0.4rem 0; }
      .job-windows { display: flex; flex-direction: column; gap: 0.5rem; }
      /* WHEN: each window is a bordered card — From/To on one row with aligned
         eyebrow sublabels, optional Label beneath, × spanning both. minmax(0,1fr)
         keeps the native datetime inputs from overflowing the modal at any width. */
      .job-window-row { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr) auto; gap: 0.5rem 0.7rem; align-items: end; padding: 0.6rem 0.7rem; border: 1px solid var(--border-subtle); border-radius: var(--r-sm); background: var(--bg-input); }
      .jwr-field { display: flex; flex-direction: column; gap: 0.25rem; min-width: 0; }
      .jwr-field--label { grid-column: 1 / 3; }
      .jwr-field .form-input[data-field="fill"] { width: 100%; min-width: 0; }
      .jwr-sublabel { font-size: 0.65rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-muted); }
      .jwr-remove { grid-column: 3; grid-row: 1 / -1; align-self: center; }
      /* WHAT: identity cell (checkbox | name | status chip) | range cell. The range
         cell is a fixed width every row, so the inputs line up column-to-column
         across rows and never crowd the name+chip. */
      .job-trace-row { display: grid; grid-template-columns: minmax(0,1fr) auto; align-items: center; column-gap: 1rem; row-gap: 0.3rem; margin-bottom: 0.35rem; }
      .jtr-id { display: flex; align-items: center; gap: 0.5rem; min-width: 0; }
      .jtr-id .check-label { min-width: 0; }
      .jtr-id .check-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
      .rec-fresh-badge { flex-shrink: 0; }
      /* Start – End MHz as the row's right cell. Uniform-width inputs (overrides the
         content-sizing number rule so "606" and the "full" placeholder match). */
      .range-group { display: inline-flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; justify-self: end; }
      .range-dash, .range-unit { color: var(--text-2); font-size: 0.78rem; }
      .range-unit { font-family: var(--font-mono, monospace); }
      .rec-stale-caution { color: var(--warn); font-size: 0.72rem; margin: 0 0 0.4rem 1.65rem; line-height: 1.4; }
      .rec-stale-caution:empty { display: none; }


      .picker-results { display: flex; flex-direction: column; gap: 0.4rem; margin-top: 0.5rem; }
      .picker-item { display: flex; align-items: center; gap: 0.75rem; padding: 0.5rem 0.75rem; background: var(--bg-surface, #1e293b); border: 1px solid var(--border-subtle); border-radius: var(--r-sm); flex-wrap: wrap; }
      .picker-item-info { display: flex; flex-direction: column; gap: 0.2rem; flex: 1; }
      .picker-item-name { font-size: 0.85rem; font-weight: 600; color: var(--text-1); }
      .picker-item-meta { font-size: 0.75rem; color: var(--text-muted); }
      /* "Attach scan traces from device": streams grouped under their device. */
      .attach-group { display: flex; flex-direction: column; gap: 0.4rem; margin-top: 0.5rem; }
      .attach-group-head { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 0.35rem; row-gap: 0.1rem; margin-top: 0.35rem; min-width: 0; overflow-wrap: anywhere; }
      .attach-shared-hint { margin-top: 0.35rem; }

      .wizard-steps { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-bottom: 0.75rem; }
      .wizard-step { font-size: 0.78rem; padding: 0.2rem 0.5rem; border-radius: var(--r-sm); background: var(--bg-surface, #1e293b); color: var(--text-muted); border: 1px solid var(--border-subtle); }
      .wizard-step--active { background: var(--accent); color: #fff; border-color: var(--accent); font-weight: 600; }
      .wizard-step--done { background: transparent; color: var(--accent-text); border-color: var(--accent); }
      .wizard-body { min-height: 120px; }

      .gear-menu { display: flex; flex-direction: column; min-width: 180px; }
      .gear-menu-item { background: none; border: none; text-align: left; padding: 0.5rem 0.85rem; font-size: 0.85rem; color: var(--text-1); cursor: pointer; }
      .gear-menu-item:hover { background: var(--bg-surface, #1e293b); }

      .trace-bands-wrap { display: flex; align-items: center; gap: 0.35rem; flex-wrap: wrap; }
      .chip--clickable { cursor: pointer; border: 1px solid var(--accent); }
      .chip--clickable:hover { background: var(--accent); color: #fff; }

      .venue-map-placeholder { border-radius: var(--r-sm); }
      .schedule-status-row { margin-bottom: 0.25rem; }

      .help-toggle-wrap { display: contents; }

      .help-body { flex: 1 1 100%; font-size: 0.78rem; color: var(--text-2); background: var(--bg-surface, #1e293b); border: 1px solid var(--border-subtle); border-radius: var(--r-sm); padding: 0.6rem 0.75rem; line-height: 1.5; }
      .help-body p { margin: 0 0 0.45rem; }
      .help-body code { background: #1a1a1a; padding: 0 3px; border-radius: 3px; font-family: var(--font-mono, monospace); }

      /* ── §5 detection coverage map (ported) ─────────────────────────────── */
      .coverage-map-host { background: #0a0a0a; border: 1px solid var(--border-subtle); border-radius: var(--r-sm); padding: 4px; overflow-x: auto; }
      .coverage-map-host svg { min-width: 320px; }
      .coverage-empty { color: #777; font-style: italic; font-size: 0.78rem; padding: 0.75rem; }

      /* Coverage-map bar popover — centered floating editor (mobile-friendly). */
      .cov-popover-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.55); display: flex; align-items: center; justify-content: center; z-index: 1200; padding: 1rem; }
      .cov-popover { background: var(--bg-card, #111827); border: 1px solid var(--border-subtle); border-radius: var(--r-md); box-shadow: 0 12px 40px rgba(0,0,0,0.6); width: 100%; max-width: 340px; max-height: 90vh; overflow-y: auto; display: flex; flex-direction: column; }
      .cov-popover-title { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; padding: 0.75rem 0.9rem; border-bottom: 1px solid var(--border-subtle); font-size: 0.9rem; font-weight: 600; color: var(--text-1); }
      .cov-popover-close { width: auto; background: none; border: none; color: var(--text-muted); font-size: 1.1rem; cursor: pointer; line-height: 1; padding: 0 0.25rem; }
      .cov-popover-body { padding: 0.9rem; display: flex; flex-direction: column; gap: 0.6rem; }
      .cov-popover-body label { display: flex; flex-direction: column; gap: 0.25rem; font-size: 0.78rem; color: var(--text-2); }
      .cov-popover-body label.cov-popover-checkbox { flex-direction: row; align-items: center; gap: 0.45rem; }
      .cov-popover-body input[type="number"]:not(.freq-field), .cov-popover-body input[type="text"]:not(.freq-field), .cov-popover-body select { background: var(--bg-input); border: 1px solid var(--border); border-radius: var(--r-sm); color: var(--text-1); font-size: 0.825rem; padding: 0.4rem 0.5rem; width: var(--field-m); max-width: 100%; box-sizing: border-box; box-shadow: inset 0 1px 2px rgba(0,0,0,0.28); }
      .cov-popover-body input[type="checkbox"] { width: 1rem; height: 1rem; accent-color: var(--accent); }
      .cov-popover-hint { font-size: 0.72rem; color: var(--text-muted); margin: 0; line-height: 1.4; }
      .cov-popover-err { color: var(--danger, #f87171); font-size: 0.75rem; min-height: 0; }
      .cov-popover-err:empty { display: none; }
      .cov-popover-footer { display: flex; gap: 0.5rem; flex-wrap: wrap; padding: 0.75rem 0.9rem; border-top: 1px solid var(--border-subtle); }
      .cov-popover-footer-btn { width: auto; padding: 0.4rem 0.9rem; border-radius: var(--r-sm); font-size: 0.8rem; font-weight: 600; cursor: pointer; border: 1px solid var(--border-subtle); background: var(--bg-surface, #1e293b); color: var(--text-1); }
      .cov-popover-footer-btn.cov-btn-apply { background: var(--accent); border-color: var(--accent); color: #fff; }
      .cov-popover-footer-btn.cov-btn-delete { background: #2a1414; border-color: #4a2a2a; color: #f88; margin-right: auto; }

      .span-override-warning { background: #1a1200; border: 1px solid #5a4a00; border-radius: var(--r-sm); color: #e0c060; font-size: 0.78rem; padding: 0.55rem 0.7rem; line-height: 1.4; }
      .span-override-warning .muted { color: #9a8030; }
      .det-bands-host { overflow-x: auto; }
      .audio-live-badge { padding: 0.2rem 0; }

      /* ── §2 Linked freq-coord event (ported) ───────────────────────────────── */
      .webtool-deleted-banner { background: #2a1a00; border: 1px solid #5a3a00; border-radius: var(--r-sm); color: #f0b860; font-size: 0.78rem; padding: 0.55rem 0.7rem; line-height: 1.4; align-self: stretch; }
      .linked-name-row { display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; }
      .linked-open-link { color: var(--accent-text); text-decoration: none; font-size: 0.72rem; font-weight: 500; white-space: nowrap; }
      .linked-open-link:hover { text-decoration: underline; }
      .linked-action-result { font-size: 0.75rem; color: var(--text-muted); align-self: stretch; }
      .linked-action-result[hidden] { display: none; }
      /* Super-admin-only platform key row: secondary (muted, small), last in the panel. */
      .webtool-key-row { display: flex; flex-direction: column; align-items: flex-start; gap: var(--s2); min-width: 0; }
      .webtool-key-status { overflow-wrap: anywhere; }

      /* ── §3 Schedule local-edit dots + address autocomplete (ported) ───────── */
      .local-edit-dot { width: 10px; height: 10px; border-radius: 50%; border: 1px solid var(--border); background: transparent; flex-shrink: 0; cursor: default; display: inline-block; }
      .local-edit-dot.edited { background: var(--warn, #fbbf24); border-color: var(--warn, #fbbf24); cursor: pointer; box-shadow: 0 0 0 2px var(--warn-dim, #3d2f08); }
      .venue-addr-field { position: relative; align-self: stretch; }
      .venue-addr-suggest { position: absolute; left: 0; right: 0; top: 100%; margin-top: 2px; background: var(--bg-raised, #1b2536); border: 1px solid var(--border); border-radius: var(--r-sm); box-shadow: 0 8px 24px rgba(0,0,0,0.5); max-height: 240px; overflow-y: auto; z-index: 50; font-size: 0.78rem; }
      .venue-addr-suggest-row { padding: 0.45rem 0.6rem; cursor: pointer; border-bottom: 1px solid var(--border-subtle); color: var(--text-1); }
      .venue-addr-suggest-row:last-child { border-bottom: none; }
      .venue-addr-suggest-row:hover { background: var(--bg-2, #161f2e); }
      .venue-addr-cc { color: var(--accent-text); font-size: 0.65rem; font-weight: 600; margin-right: 0.4rem; }

      /* ── §6 Recording job cards: When / What grid (ported) ─────────────────── */
      .rec-job-card { background: var(--bg-surface, #1e293b); border: 1px solid var(--border-subtle); border-radius: var(--r-sm); padding: 0.6rem 0.75rem; display: flex; flex-direction: column; gap: 0.5rem; align-self: stretch; }
      .rec-job-head { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
      /* Title + badge take the free space; min-width:0 (+ overflow-wrap) lets a long
         name shrink/wrap instead of squeezing the action buttons. Every action button
         keeps its intrinsic width (flex:0 0 auto) so its label is never clipped — at
         narrow widths a button wraps onto a new line as a whole unit instead. */
      .rec-job-name { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; font-weight: 600; color: var(--text-1); font-size: 0.85rem; }
      .rec-job-head > .btn { flex: 0 0 auto; }
      .rec-when-what-grid { display: grid; grid-template-columns: 52px 1fr; gap: 0.25rem 0.6rem; font-size: 0.75rem; }
      .rec-when-what-key { color: var(--text-muted); text-transform: uppercase; font-size: 0.65rem; font-weight: 600; padding-top: 0.15rem; }
      .rec-when-what-list { margin: 0; padding-left: 0.9rem; color: var(--text-2); display: flex; flex-direction: column; gap: 0.1rem; }
      .rec-continuous { color: var(--ok, #34d399); font-style: italic; }
      .rec-none { color: var(--text-muted); font-style: italic; }
      .rec-full-bw { color: var(--text-muted); }
      .rec-window-label, .rec-range-label { color: var(--text-muted); }
      .rec-trace-label { color: var(--text-1); }
      /* Item 2 — per-job stats line (recorded from→to · size · chunks). */
      .rec-job-stats { display: flex; flex-wrap: wrap; gap: 0.4rem 1.25rem; padding-top: 0.4rem; border-top: 1px solid var(--border-subtle); font-size: 0.72rem; }
      .rec-job-stat { display: inline-flex; align-items: baseline; gap: 0.45rem; }
      .rec-job-stat-key { color: var(--text-muted); text-transform: uppercase; font-size: 0.6rem; font-weight: 600; letter-spacing: 0.04em; }
      .rec-job-stat-val { color: var(--text-1); font-variant-numeric: tabular-nums; }
      .rec-job-stat--none, .rec-job-stat--load { color: var(--text-muted); font-style: italic; }
      .rec-job-stat--gone, .rec-job-stat--gone .rec-job-stat-val { color: var(--warn); }

      /* ── §9 Sound override rows ──────────────────────────────────────────────
         ONE shared column template on EVERY row (grid, not per-row flex — same
         lesson as the detection-bands header fix) so select/slider/%/Ack/test
         align vertically across all five rows regardless of label length (the
         longer "Pinned/watched threshold" label used to push its controls out
         of line). The label track is fixed-width for that longest label; no
         wrapping, one line per use case. */
      .sound-mappings { display: flex; flex-direction: column; gap: 0.4rem; align-self: stretch; }
      .sound-mapping-row {
        display: grid;
        grid-template-columns: 172px minmax(180px, 1fr) 100px 34px auto max-content;
        align-items: center;
        gap: 0.5rem;
      }
      .sound-mapping-label { font-size: 0.8rem; color: var(--text-2); font-weight: 500; }
      .sound-mapping-pick { min-width: 0; width: 100%; }
      /* Inherited rows: dimmed select face ("Inherit — Chime @ 80%"); dropdown
         options keep full contrast. */
      .sound-mapping-pick.is-inherit { color: var(--text-muted); }
      .sound-mapping-pick.is-inherit option { color: var(--text-1); }
      .sound-mapping-vol { width: 100%; min-width: 0; accent-color: var(--accent); }
      .sound-mapping-vol-num { font-size: 0.72rem; color: var(--text-muted); font-variant-numeric: tabular-nums; text-align: right; }
      .sound-mapping-ack { display: flex; align-items: center; gap: 0.3rem; cursor: pointer; white-space: nowrap; }
      /* Ack n/a (no toast for this use case): visibly inert, tooltip explains. */
      .sound-mapping-ack.is-na { opacity: 0.45; cursor: default; }

      @media (max-width: 640px) {
        .settings-view { padding: 0.75rem 0.4rem 3rem; }
        .form-grid { grid-template-columns: 1fr 1fr; }
        .member-row { flex-direction: column; align-items: flex-start; }
        .analyzer-device-body { padding: 0.5rem 0.6rem; }
        .settings-section-body { padding: 0.75rem 0.65rem; }
        /* Phones: text inputs stay comfortably wide (capped to viewport via max-width),
           numeric (sm/xs) inputs nudge a touch wider for easier tapping. */
        .form-input { width: 280px; }
        /* ...EXCEPT a --grow field, which sizes to its own text everywhere. This
           phone rule and the base .form-input--grow rule (above) have the SAME
           specificity (0,1,0) — a media query adds none — and this block comes
           later in the sheet, so without this line the later width:280px wins,
           and field-sizing only governs the INTRINSIC size: an explicit width
           still decides. The trace name box would be pinned to 280px inside a
           ~330px column, i.e. the owner's "across the whole width" report again,
           just at 640px and under. Criterion 6 is not scoped to desktop.
           .form-input itself stays untouched (spec E forbids editing it); the
           zone Select never carries .form-input, so it was never affected. */
        .form-input--grow { width: auto; }
        .form-input--sm { width: 130px; }
        .form-input--xs { width: 96px; }
        /* Phones: sound-override rows stack label and select on their own
           full-width lines; the slider/%/Ack/test line keeps SHARED tracks so
           those columns still align across rows. */
        .sound-mapping-row { grid-template-columns: minmax(0, 1fr) 34px auto max-content; row-gap: 0.25rem; }
        .sound-mapping-label, .sound-mapping-pick { grid-column: 1 / -1; }
        /* Recording editor: stack each per-trace row (name row, then range row) so
           the inputs never crowd the name on a narrow phone modal. */
        .job-trace-row { grid-template-columns: 1fr; }
        .range-group { justify-self: start; }
        .rec-stale-caution { margin-left: 1.65rem; }
      }
    
