/* Devices tab. Was #analyzers-panel-css. .as-level* rules are in views-rx-vitals.css (the same rules, not repeated).
   Hashed into the shell by scripts/build.mjs (ensure, after views-admin).
   The view appends this link at render so it still follows sheets injected later. */
.ea-wrap{padding:14px;max-width:900px;margin:0 auto}
.ea-intro{margin:0 0 12px}
.ea-intro{color:var(--text-2);font-size:13px;margin:0}
.ea-actions{display:flex;gap:8px;flex-wrap:wrap}
.ea-add{flex-shrink:0}
/* Sub-headings inside a bridge card: Scan sources / Receivers / Devices / Audio streams. */
.ea-group-head{margin:12px 0 0;color:var(--text-muted);font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase}
.ea-empty{color:var(--text-2);font-size:13px;line-height:1.5;background:var(--bg-card);border:1px solid var(--border-subtle);border-radius:var(--r-md);padding:14px}
.ea-empty-sub{color:var(--text-muted);font-size:12px;margin-top:6px}
.ea-pi{margin:14px 0;border:1px solid var(--border);border-radius:var(--r-md);padding:10px;background:var(--bg-card)}
.ea-pi-hdr{display:flex;align-items:center;gap:8px}
.ea-pi-name{font-weight:600;color:var(--text-1);font-size:14px}
.an-err{color:var(--danger);font-size:13px}

.an-devrow{margin-top:8px;padding:8px;background:var(--bg-raised);border-radius:var(--r-sm)}
/* The head is the whole top line of the row and the click target to open / close it.
   Padding + the matching negative margin let it fill the row's padding box, so the
   open state can paint a full-width bar without moving anything when it opens. */
.an-devrow-btn{all:unset;cursor:pointer;display:flex;gap:10px;align-items:center;box-sizing:border-box;width:calc(100% + 16px);margin:-8px -8px 0;padding:8px;border-bottom:1px solid transparent;border-radius:var(--r-sm)}
.an-devrow-btn:hover{background:color-mix(in srgb, var(--text-1) 4%, var(--bg-raised))}
.an-devrow-btn:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
/* Open: a header bar — fill, a rule under it, square at the bottom where the panel starts. */
.an-devrow-btn[aria-expanded="true"]{background:color-mix(in srgb, var(--text-1) 8%, var(--bg-raised));border-bottom-color:var(--border);border-radius:var(--r-sm) var(--r-sm) 0 0}
.an-dev-chev{flex:none;box-sizing:border-box;width:8px;height:8px;margin:0 4px 0 2px;border-right:2px solid var(--text-muted);border-bottom:2px solid var(--text-muted);transform:rotate(-45deg);transition:transform .12s ease,border-color .12s ease}
.an-devrow-btn:hover .an-dev-chev{border-color:var(--text-2)}
.an-devrow-btn[aria-expanded="true"] .an-dev-chev{transform:rotate(45deg);border-color:var(--text-1)}
@media (prefers-reduced-motion:reduce){.an-dev-chev{transition:none}}
.an-dev-name{font-weight:600;color:var(--text-1);font-size:13px}
.an-dev-kind{color:var(--text-muted);font-size:12px;font-family:var(--font-mono)}
/* The event trace(s) the device feeds, by their Monitor name. */
.an-dev-traces{color:var(--text-2);font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.an-trace-name{color:var(--text-2);font-size:12px}
/* The status badge is now a human phrase ("In sync", "Settings differ"),
   not an enum token, so it takes the UI font — same reasoning as
   .an-conn-why below. Mono made a sentence look like a code value, which
   is half of what made this column read as machine output. */
.an-dev-status{margin-left:auto;font-size:12px;font-family:var(--font-ui)}

.an-panel{margin-top:8px}
/* AXT600 card heading (analyzers-panel.js mountAxt600Card). */
.an-axt-title{font-weight:600;color:var(--text-1);font-size:13px;margin:2px 0 6px}
/* Read-only-observer banner — WWB owns this AD600, nothing here can write to
   it. Amber (matches .an-drift / the 'drift' status colour) rather than red:
   this is expected/informational, not an error state. */
/* Nothing saved for this device yet (analyzers-panel.js noConfigState): a
   plain explanatory note, neutral — it is not an error. */
.an-noconfig{color:var(--text-2);background:var(--bg-2);border:1px solid var(--border-subtle);border-radius:var(--r-sm);padding:6px 10px;font-size:12px;line-height:1.5;max-width:72ch;margin:2px 0 8px}
.an-observer-banner{display:flex;align-items:center;gap:6px;color:var(--warn);background:color-mix(in srgb, var(--warn) 12%, transparent);border:1px solid color-mix(in srgb, var(--warn) 35%, transparent);border-radius:var(--r-sm);padding:6px 10px;font-size:12px;margin-bottom:8px}
/* Why the device is in that state, straight from the relay's own status line
   (source_status.reason). Prose, so it takes the UI font rather than the mono
   the chip above uses, and it wraps instead of stretching a panel. */
.an-conn-why{font-family:var(--font-ui);font-size:11px;color:var(--text-muted);line-height:1.5;max-width:72ch;margin:-2px 0 6px}
.an-infra{color:var(--text-muted);font-size:12px;font-family:var(--font-mono);margin-bottom:4px}
/* The device's own error (source_status.last_error): warning amber, prose,
   wraps; the colour is set inline (DEVICE_ERROR_COLOR) so every host matches. */
.an-device-error{font-family:var(--font-ui);font-size:12px;font-weight:600;line-height:1.5;max-width:72ch;margin:2px 0 6px;padding:4px 8px;border-left:3px solid currentColor;background:color-mix(in srgb, currentColor 8%, transparent);border-radius:4px;overflow-wrap:anywhere}
.an-requested-note{font-family:var(--font-ui);font-size:11px;color:var(--text-muted);font-style:italic;margin:2px 0 4px}
.an-tree{margin-top:6px}
.an-group-head{font-weight:600;color:var(--text-1);font-size:13px;margin:8px 0 4px}
.an-group-nested{margin-left:14px;border-left:1px solid var(--border);padding-left:10px}
.an-leaf{display:flex;gap:8px;align-items:center;margin:3px 0;flex-wrap:wrap}
.an-leaf-label{min-width:200px;color:var(--text-2);font-size:13px;display:inline-flex;align-items:center;gap:5px}
/* Per-field "?" help badge — subtle muted glyph that brightens to the accent on
   hover/focus; click-to-reveal popover (see helpBadge in analyzers-panel.js). */
.an-help{all:unset;display:inline-flex;align-items:center;justify-content:center;cursor:help;color:var(--text-muted);line-height:0;border-radius:50%}
.an-help:hover,.an-help:focus-visible{color:var(--accent-text)}
.an-help:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
.an-help-pop{font-size:12px;line-height:1.5;color:var(--text-1);max-width:280px}
.an-unit{color:var(--text-muted);font-size:12px}
/* The device's limit beside a sweep-point field ("Max 450 for this device"),
   turning to the danger colour once the typed value is past it. */
.an-limit{color:var(--text-muted);font-size:12px}
.an-limit.an-limit-bad{color:var(--danger);font-weight:600}
.an-field.an-field-bad{border-color:var(--danger)}
/* AR-DV1 presets: a collapsed section, one line per preset (name · frequency ·
   mode), wrapping on a phone. */
.an-presets{margin:8px 0 4px}
.an-presets-head{cursor:pointer;margin:0 0 4px}
.an-preset-line{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin:3px 0 3px 14px}
.an-preset-cell{display:inline-flex;align-items:center;gap:4px;min-width:0}
.an-preset-cell .an-field{max-width:100%}
.an-preset-label .an-field{min-width:14ch}
.an-preset-frequency_mhz .an-field.an-num{min-width:9ch;max-width:14ch}
.an-drift{color:var(--warn);font-size:12px;font-family:var(--font-mono)}
.an-readonly{color:var(--text-2);font-size:13px;font-family:var(--font-mono)}
/* Live stream rows use the shared .field. The label column fits "RTSA display
   range"; under 560px the shared field rule stacks the label, and this matches
   it so a two-column grid cannot force a sideways scroll. */
.an-live .field{grid-template-columns:minmax(0,11.5rem) minmax(0,1fr)}
.an-live .field-label{white-space:normal;overflow:visible;text-overflow:clip;line-height:1.3;padding-top:8px}
.an-live-val{font-family:var(--font-mono);font-size:13px;color:var(--text-1);overflow-wrap:anywhere}
.an-live-val[data-liveness="up"]{color:var(--ok)}
.an-live-val[data-liveness="flat"],.an-live-val[data-liveness="stale"],.an-live-val[data-liveness="paused"]{color:var(--warn)}
.an-live-val[data-liveness="down"],.an-live-val[data-liveness="silent"]{color:var(--danger)}
.an-live-val[data-clock="unreported"]{color:var(--text-2)}
@media (max-width:560px){
  .an-live .field{grid-template-columns:1fr}
  .an-live .field-label{line-height:1.4;padding-top:0}
}
/* Inputs are SHORT by default, in ch (one shared scale, no per-field hacks):
     .an-num   numbers     ~10ch   (a frequency, a level, a gain)
     .an-field text        ~16ch   (a short value)
     .an-name  names       ~28ch   (a device / channel / input name)
   The width is a fixed fallback; where the browser can size to content
   (field-sizing, Chrome/Edge) the box shrinks to its value and grows only up to
   the same cap. max-width:100% lets every box wrap to a phone's width. The +18px
   is the box's padding and border. Selects and checkboxes keep their own width. */
.an-field{background:var(--bg-input);border:1px solid var(--border);color:var(--text-1);border-radius:var(--r-sm);padding:4px 8px;font-size:13px;font-family:var(--font-mono);box-sizing:border-box;width:calc(16ch + 18px);max-width:100%}
.an-field.an-name{width:calc(28ch + 18px)}
select.an-field,.an-field.an-check{width:auto}
@supports (field-sizing:content){
  .an-field{field-sizing:content;width:auto;min-width:calc(9ch + 18px);max-width:min(100%,calc(16ch + 18px))}
  .an-field.an-name{max-width:min(100%,calc(28ch + 18px))}
  select.an-field{max-width:100%}
}
/* A select draws its own chevron: the native arrow sat flush against the box
   edge. appearance:none + 28px of right padding keeps it clear (same look as
   the AD600 / AXT600 cards and the shared Select component). */
select.an-field{-webkit-appearance:none;appearance:none;cursor:pointer;padding-right:28px;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='10' height='10' fill='none' stroke='%238a93a6' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>");background-repeat:no-repeat;background-position:right 10px center;background-size:10px 10px}
select.an-field:disabled{cursor:not-allowed}
.an-field:focus-visible{outline:none;border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-soft)}
.an-field.an-num{width:calc(10ch + 18px);text-align:right}
@supports (field-sizing:content){.an-field.an-num{width:auto;min-width:calc(5ch + 18px);max-width:min(100%,calc(10ch + 18px))}}
.an-field.an-check{field-sizing:auto;min-width:0;max-width:none;width:auto;accent-color:var(--accent)}
.an-field:disabled{opacity:.5;cursor:not-allowed}
.an-actions{margin-top:10px;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.an-msg{color:var(--text-muted);font-size:12px;align-self:center}
/* Audio streams: one plain line per stream, no head button (nothing to open). */
.as-row{display:flex;gap:10px;align-items:baseline;flex-wrap:wrap}
