/* online-sound-test — design system v2 ("Rail + Content")
   Sticky left tool rail + scrolling right content column, top nav header.
   Palette/type derived from the approved SoundDeck-style mockup (brand blue,
   Manrope). Variable NAMES are unchanged from v1 — only values/layout moved —
   so every existing content/*.json fields_html/script keeps working as-is. */

:root{
  --bg:#F6F8FB;
  --surface:#FFFFFF;
  --border:#E2E8F0;
  --border-strong:#CBD5E1;
  --text:#101828;
  --text-secondary:#475569;
  --text-muted:#8A94A6;
  --accent:#0F62FE;
  --accent-dark:#0A44B3;
  --accent-soft:#EAF1FF;
  --accent-soft-border:#CFE0FF;
  --success:#0F9B6C;
  --success-bg:#EFFAF5;
  --warning:#B45309;
  --warning-bg:#FFFBEB;
  --danger:#D4552F;
  --danger-bg:#FDF0EB;
  --radius-lg:16px;
  --radius-md:12px;
  --radius-sm:8px;
  --radius-pill:999px;
  --shadow-card:0 1px 2px rgba(16,24,40,.04),0 1px 3px rgba(16,24,40,.06);
  --font-sans:"Manrope",system-ui,-apple-system,"Segoe UI",sans-serif;
  --header-height:64px;
  --rail-width:29rem;
  --page-max:1400px;
  --page-pad-x:24px;
}

*{box-sizing:border-box;}
html{-webkit-text-size-adjust:100%;}
output{display:block;}
body{
  margin:0;
  background:var(--bg);
  color:var(--text);
  font-family:var(--font-sans);
  font-size:15px;
  line-height:1.5;
  -webkit-font-smoothing:antialiased;
}
img{max-width:100%;}

a{color:var(--accent);font-weight:600;text-decoration:underline;text-underline-offset:2px;}
a:hover{color:var(--accent-dark);}
.article a{color:var(--accent);text-decoration:underline;}

h1,h2,h3,h4{margin:0;font-weight:800;letter-spacing:-.02em;}
p{margin:0;}

:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:4px;}

/* ---- site header / top nav ----
   Priority+ nav, ported from passwordhive.net / hexcalculator.dev's own
   nav (see those sites' own styles.css/generate.py for the source of this
   pattern). Logo + category strip share one .top-nav row; whichever
   .cat-menu-item[data-cat-key] items don't fit the remaining width are
   hidden by initPriorityNav() (see NAV_SCRIPT) and revealed instead inside
   the trailing "More" dropdown. Same algorithm at every viewport width —
   there is no separate mobile menu/hamburger. */
.site-header{
  position:sticky;top:0;z-index:50;
  background:rgba(255,255,255,.9);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
  border-bottom:1px solid var(--border);
}
.top-nav{
  max-width:var(--page-max);margin:0 auto;min-height:var(--header-height);
  display:flex;align-items:center;gap:20px;
  padding:12px var(--page-pad-x);
}
.brand{display:flex;align-items:center;gap:9px;font-weight:800;font-size:15.5px;color:var(--text);text-decoration:none;flex-shrink:0;}
.brand svg,.brand-logo{flex-shrink:0;}
.brand-logo{display:block;}

.category-strip{display:flex;align-items:center;justify-content:flex-end;gap:4px;flex:1;min-width:0;overflow:hidden;}
.cat-menu-item{flex:none;}
.cat-menu-btn{
  display:flex;align-items:center;gap:5px;background:none;border:none;font:inherit;text-decoration:none;
  font-weight:600;font-size:13px;color:var(--text-secondary);cursor:pointer;padding:8px 12px;border-radius:var(--radius-pill);white-space:nowrap;
}
.cat-menu-btn:hover{background:var(--bg);color:var(--text);}
.cat-menu-btn[aria-expanded="true"]{background:var(--accent-soft);color:var(--accent-dark);}
.cat-menu-btn.active{color:var(--accent-dark);}
.cat-menu-btn .chevron{flex:none;transition:transform .15s ease;}
.cat-menu-btn[aria-expanded="true"] .chevron{transform:rotate(180deg);}

/* .tools-menu is position:fixed, positioned inline by initCategoryDropdowns()
   (via getBoundingClientRect() on the trigger button) — escapes
   .category-strip's overflow:hidden, which exists only to clip items
   initPriorityNav() hasn't hidden yet on first paint, before its layout()
   runs. */
.tools-menu{
  display:none;position:fixed;padding:20px;
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);
  box-shadow:0 16px 40px rgba(16,24,40,.14);z-index:60;
}
.tools-menu.open{display:block;}
.cat-menu{width:420px;max-width:88vw;}
.cat-menu-header{display:flex;align-items:flex-start;gap:12px;margin-bottom:14px;padding-bottom:14px;border-bottom:1px solid var(--border);}
.cat-menu-icon{
  flex:none;width:32px;height:32px;border-radius:9px;font-size:10.5px;font-weight:800;letter-spacing:-.02em;
  background:linear-gradient(135deg,var(--accent),var(--accent-dark));color:#fff;
  display:flex;align-items:center;justify-content:center;
}
.cat-menu-title{font-weight:800;font-size:14.5px;color:var(--text);line-height:1.3;}
.cat-menu-tagline{font-size:12px;color:var(--text-muted);margin-top:3px;line-height:1.4;}
.cat-menu-links{column-count:2;column-gap:16px;column-rule:1px solid var(--border);max-height:340px;overflow-y:auto;}
.cat-menu-links a{display:block;break-inside:avoid;padding:7px 8px;border-radius:var(--radius-sm);font-size:13px;font-weight:500;color:var(--text-secondary);text-decoration:none;}
.cat-menu-links a:hover{background:var(--bg);color:var(--accent-dark);}
.cat-menu-links a.active{color:var(--accent-dark);font-weight:700;}

/* trailing "More" dropdown: every category exists in the DOM, hidden by
   default — initPriorityNav() reveals only the ones that didn't fit. */
.more-menu{width:340px;max-width:88vw;max-height:75vh;overflow-y:auto;}
.more-menu-section{display:none;padding:14px 0;border-top:1px solid var(--border);}
.more-menu-section:first-child{border-top:none;padding-top:0;}
.more-menu-section.cat-visible{display:block;}
.more-menu .cat-menu-links{column-count:1;}

/* ---- page shell / two-column tool layout ---- */
.page-shell{max-width:var(--page-max);margin:0 auto;padding:0 var(--page-pad-x) 64px;}
.page-shell-narrow{max-width:820px;margin:0;}

.tool-layout{display:block;padding-top:32px;}

.tool-rail{margin-bottom:32px;}
.tool-rail h1{margin-bottom:20px;}

.content-column{min-width:0;}

/* ---- hero ---- */
.hero h1{font-size:30px;line-height:1.16;margin-bottom:10px;}
.hero-subtitle{font-size:14.5px;line-height:1.65;color:var(--text-secondary);margin-bottom:24px;}
.page-shell-narrow .hero{padding-top:8px;margin-bottom:8px;}

/* ---- ad slot ---- */
.ad-slot{
  display:block;background:var(--bg);border:1px dashed var(--border-strong);border-radius:var(--radius-sm);
  padding:10px;text-align:center;font-size:10px;letter-spacing:.08em;color:var(--text-muted);
  text-transform:uppercase;margin:0 0 20px;overflow:hidden;
}
/* Same explicit gap above the ad-slot on both sides -- .tool-card's own
   margin-bottom (16px) and a bare content-card's (28px) differ, and
   adjacent-sibling margins collapse to the larger of the two rather than
   adding, so without this the tool-rail's card-to-ad gap would end up 12px
   shorter than the content-column's, throwing off the two columns' visible
   card-bottom alignment even once the ad-slots themselves line up (see the
   *:last-child rule below for that half of the fix). */
.tool-card + .ad-slot,
.content-card:last-of-type + .ad-slot{margin-top:28px;}
/* Reserve the JS-resized units' mobile-first size up front so there's no
   layout jump once the inline script sets the real width/height at the
   768px breakpoint (same reasoning as passwordhive's .ad-slot-header). */
.ad-slot-header{min-height:100px;}
.ad-slot-card{min-height:200px;}
@media(min-width:768px){
  .ad-slot-header{min-height:90px;}
  .ad-slot-card{min-height:250px;}
}

/* ---- tool card (the primary test panel) ---- */
.tool-card{
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);
  box-shadow:var(--shadow-card);
  padding:24px;margin-bottom:16px;overflow-x:auto;
}
.tool-section-wide .tool-card{max-width:none;}

.waveform{display:flex;gap:3px;margin-bottom:20px;height:28px;align-items:flex-end;}
.waveform div{width:5px;background:var(--border);border-radius:2px;}
.waveform div.active{background:var(--accent);}

.pill-toggle{
  display:inline-flex;gap:6px;background:var(--bg);border-radius:var(--radius-pill);
  padding:4px;margin-bottom:22px;max-width:100%;
}
.pill-toggle button{
  flex:1;text-align:center;padding:9px 18px;border-radius:var(--radius-pill);
  font-size:12px;font-weight:600;color:var(--text-muted);background:none;border:none;
  font-family:var(--font-sans);cursor:pointer;white-space:nowrap;
}
.pill-toggle button.active{background:var(--accent);color:#FFFFFF;font-weight:700;}

.play-row{display:flex;align-items:center;gap:14px;flex-wrap:wrap;}
.play-button{
  width:48px;height:48px;border-radius:50%;background:var(--accent);border:none;
  display:flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0;
}
.play-button:hover{background:var(--accent-dark);}
.play-button svg{fill:#FFFFFF;}
.play-hint{font-size:12px;color:var(--text-muted);}

.freq-chip-row{display:flex;gap:6px;margin-left:auto;flex-wrap:wrap;}
.freq-chip{
  font-size:11px;padding:6px 12px;border-radius:var(--radius-pill);color:var(--text-muted);
  border:1px solid var(--border);background:none;font-family:var(--font-sans);cursor:pointer;
}
.freq-chip.active{background:var(--accent);color:#FFFFFF;font-weight:700;border-color:var(--accent);}

.btn-row{display:flex;gap:10px;flex-wrap:wrap;}
.btn{
  font-size:12.5px;font-weight:700;padding:10px 20px;border-radius:var(--radius-sm);
  border:1px solid var(--border);background:var(--surface);color:var(--text-secondary);
  font-family:var(--font-sans);cursor:pointer;
}
.btn:hover{border-color:var(--border-strong);color:var(--text);}
.btn.primary{background:var(--accent);border-color:var(--accent);color:#FFFFFF;}
.btn.primary:hover{background:var(--accent-dark);border-color:var(--accent-dark);}

/* ---- tool grid (used by homepage L/R pads + 404 suggestion tiles) ---- */
.section-label{font-weight:800;font-size:15px;margin-bottom:14px;}

.tool-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px;margin-bottom:30px;}
@media (max-width:900px){.tool-grid{grid-template-columns:repeat(2,minmax(0,1fr));}}
@media (max-width:560px){.tool-grid{grid-template-columns:1fr;}}

.tool-tile{background:var(--surface);border:1.5px solid var(--border);border-radius:var(--radius-md);padding:16px;transition:border-color .15s ease,background-color .15s ease;}
.tool-tile:hover{border-color:var(--accent);background:var(--accent-soft);}
.tool-tile-icon{
  width:32px;height:32px;border-radius:8px;background:var(--accent-soft);
  display:flex;align-items:center;justify-content:center;margin-bottom:10px;
}
.tool-tile-title{font-weight:700;font-size:12.5px;margin-bottom:6px;overflow-wrap:break-word;}
.tool-tile-desc{font-size:11px;line-height:1.5;color:var(--text-muted);overflow-wrap:break-word;}

/* ---- content / article sections ----
   Typography sized to match the approved mockup (2.html): h2 text-2xl/
   font-extrabold, h3 plain font-bold, sitting bare — no divider, no badge,
   no accent-bar. (An earlier pass added a numbered circular badge + h2
   border-bottom + h3 left accent-bar that don't exist in the mockup —
   removed.) content-card itself (border+shadow wrapping a whole section)
   is kept — the mockup's own "procedure" section uses exactly that
   pattern (a .card wrapping an h2 + its content). */
.content-card{
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);
  box-shadow:var(--shadow-card);
  padding:28px;margin-bottom:28px;overflow-x:auto;
}
/* Whatever ends up last in each column (a content-card, or the footer
   ad-slot when ads are on) would otherwise leave its own trailing margin as
   invisible space inside that column's box -- misaligning its visible
   bottom edge against .tool-rail-sticky's, which .content-column is forced
   to match the height of (align-self:stretch). Zeroing both sides' true
   last child keeps both columns' visible content flush with the shared
   stretched height, so their bottom edges line up regardless of which
   element (card or ad) happens to be last on either side. */
.content-column > *:last-child,
.tool-rail-sticky > *:last-child{margin-bottom:0;}
.article h2{font-size:26px;line-height:1.25;font-weight:800;margin-bottom:16px;}
.article h3{font-size:17px;line-height:1.35;font-weight:800;margin:24px 0 10px;}
.article h3:first-child{margin-top:0;}
.article h4{font-size:14px;font-weight:800;margin:18px 0 8px;color:var(--text);}
.article p{font-size:14.5px;line-height:1.7;color:var(--text-secondary);margin-bottom:12px;}
.article ul,.article ol{font-size:14.5px;line-height:1.7;color:var(--text-secondary);list-style:none;padding-left:0;margin-bottom:14px;}
.article li{position:relative;margin-bottom:8px;padding-left:22px;}
.article ul li::before{
  content:"";position:absolute;left:2px;top:9px;width:6px;height:6px;border-radius:50%;background:var(--accent);
}
.article ol{counter-reset:art-ol;}
.article ol li{counter-increment:art-ol;padding-left:28px;}
.article ol li::before{
  content:counter(art-ol);position:absolute;left:0;top:-1px;width:19px;height:19px;
  display:flex;align-items:center;justify-content:center;
  background:var(--accent-soft);color:var(--accent-dark);font-size:10.5px;font-weight:800;border-radius:50%;
}
.article table{width:100%;border-collapse:collapse;margin-bottom:16px;font-size:12.5px;}
.article table th,.article table td{border:1px solid var(--border);padding:8px 10px;text-align:left;}
.article table th{background:var(--bg);font-weight:700;}
.article table caption{caption-side:top;text-align:left;font-size:12px;font-weight:600;color:var(--text-muted);margin-bottom:8px;}

/* ---- prose elements beyond h2-h4/p/ul/ol/table ----
   The SEO-optimizer content pipeline writes a much richer HTML vocabulary
   than the original migration accounted for (see audio-latency-test.json
   for an example using all of these in one page) — aside="pro tip"
   callouts, details/summary FAQ blocks, inline code + pre blocks,
   blockquote pull-quotes, dl/dt/dd worked examples, figure/figcaption,
   h5/h6, mark, sub/sup. Style every one so a `content_html` author never
   has to guess whether a semantic tag "just works" here. */
.article strong,.article b{color:var(--text);font-weight:700;}
.article em,.article i{font-style:italic;}
.article h5{font-size:13px;font-weight:800;margin:16px 0 6px;color:var(--text);}
.article h6{font-size:11.5px;font-weight:800;letter-spacing:.03em;text-transform:uppercase;margin:16px 0 6px;color:var(--text-muted);}

.article aside{
  background:var(--accent-soft);border:1px solid var(--accent-soft-border);border-radius:var(--radius-md);
  padding:14px 16px;margin:16px 0;font-size:14px;line-height:1.65;color:var(--accent-dark);
}
.article aside p{color:inherit;margin-bottom:0;}
.article aside p + p{margin-top:8px;}

.article blockquote{
  margin:16px 0;padding:4px 0 4px 18px;border-left:3px solid var(--accent-soft-border);
  font-size:14.5px;line-height:1.7;color:var(--text-secondary);font-style:italic;
}
.article blockquote p{margin-bottom:6px;}
.article blockquote p:last-child{margin-bottom:0;}

.article code{
  background:var(--bg);border:1px solid var(--border);border-radius:4px;
  padding:2px 6px;font-family:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:.9em;color:var(--accent-dark);
}
.article pre{
  background:var(--text);color:#F1F5F9;border-radius:var(--radius-md);
  padding:16px;margin-bottom:16px;overflow-x:auto;font-size:12.5px;line-height:1.6;
}
.article pre code{background:none;border:none;padding:0;color:inherit;font-size:1em;}

.article details{
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);
  padding:14px 16px;margin-bottom:10px;
}
.article summary{
  cursor:pointer;font-weight:700;font-size:14px;color:var(--text);
  display:flex;align-items:center;justify-content:space-between;gap:12px;list-style:none;
}
.article summary::-webkit-details-marker{display:none;}
.article summary::after{
  content:"";flex:none;width:9px;height:9px;margin-top:-3px;
  border-right:2px solid var(--text-muted);border-bottom:2px solid var(--text-muted);
  transform:rotate(45deg);transition:transform .15s ease;
}
.article details[open] summary::after{transform:rotate(-135deg);margin-top:3px;}
.article details p,.article details ul,.article details ol{margin-top:10px;margin-bottom:0;}
.article details > :last-child{margin-bottom:0;}

.article dl{margin-bottom:16px;}
.article dt{font-weight:700;font-size:14.5px;color:var(--text);margin:14px 0 6px;}
.article dt:first-child{margin-top:0;}
.article dd{margin:0 0 14px 0;padding-left:16px;border-left:2px solid var(--border);}
.article dd > :last-child{margin-bottom:0;}

.article figure{margin:16px 0;}
.article figure svg{max-width:100%;height:auto;color:var(--text-muted);}
.article figcaption{font-size:12px;color:var(--text-muted);margin-top:8px;line-height:1.5;}

.article mark{background:#FEF3C7;color:var(--text);padding:0 3px;border-radius:3px;}
.article sub,.article sup{line-height:0;}

.privacy-card{background:var(--accent-soft);border:1px solid var(--accent-soft-border);}
.privacy-card h2{color:var(--accent-dark);}
.privacy-card p{color:var(--accent-dark);}

.two-col{display:flex;gap:20px;flex-wrap:wrap;}
.two-col > *{flex:1;min-width:260px;}

/* ---- footer: brand blurb + mega link grid (one row per category) + legal bar ---- */
.site-footer{border-top:1px solid var(--border);margin-top:40px;padding:36px 0 0;}
.footer-brand-block{margin-bottom:28px;}
.footer-brand{font-size:15px;font-weight:800;margin-bottom:8px;}
.footer-brand-block p{font-size:13px;line-height:1.65;color:var(--text-muted);font-weight:500;max-width:42ch;}

.footer-mega{padding:4px 0;}
.footer-mega-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 24px;padding:16px 0;border-top:1px solid var(--border);}
.footer-mega-row:first-child{border-top:none;}
.footer-mega-label{flex:0 0 auto;width:180px;font-size:11px;letter-spacing:.05em;text-transform:uppercase;font-weight:700;color:var(--text);border-left:2px solid var(--accent);padding-left:10px;}
.footer-mega-count{font-weight:500;color:var(--text-muted);text-transform:none;letter-spacing:normal;}
.footer-mega-links{display:flex;flex-wrap:wrap;align-items:center;flex:1;min-width:0;}
.footer-mega-links a{display:inline-block;padding:4px 0;font-size:13px;font-weight:500;color:var(--text-secondary);text-decoration:none;}
.footer-mega-links a:hover{color:var(--accent-dark);}
.footer-mega-links a:not(:last-child)::after{content:"\2022";margin:0 10px;color:var(--text-muted);font-weight:700;}

.footer-bottom{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;font-size:12px;color:var(--text-muted);padding:20px 0;border-top:1px solid var(--border);}
.footer-legal-links{display:flex;flex-wrap:wrap;gap:4px 16px;}
.footer-legal-links a{font-size:12px;font-weight:500;color:var(--text-muted);text-decoration:none;}
.footer-legal-links a:hover{color:var(--accent-dark);}

@media (max-width:900px){
  .footer-mega-row{flex-direction:column;gap:8px;}
  .footer-mega-label{width:auto;}
}

/* ---- responsive ---- */
@media (max-width:640px){
  .top-nav{padding:10px 18px;gap:12px;}
}

@media (min-width:1024px){
  :root{--page-pad-x:32px;}
  .tool-layout{display:grid;grid-template-columns:var(--rail-width) 1fr;gap:40px;align-items:start;}
  /* .tool-rail stretches to the row's full height (matching .content-column,
     the taller sibling) so the inner sticky wrapper has room to ride all the
     way down and catch cleanly at the bottom, instead of running out of its
     own (short) box early and freezing with a gap above the footer. */
  .tool-rail{align-self:stretch;margin-bottom:0;}
  .tool-rail-sticky{position:sticky;top:calc(var(--header-height) + 24px);}
}

@media (max-width:640px){
  :root{--page-pad-x:18px;}
  .page-shell{padding-bottom:48px;}
  .tool-layout{padding-top:24px;}
  .hero h1{font-size:24px;}
  .tool-grid{gap:10px;}
  .tool-card{padding:18px;}
  .content-card{padding:18px;}
}

@media (max-width:560px){
  .two-col{flex-direction:column;}
  .two-col > *{min-width:0;}
}

/* ---- tool status banner + interactive tile states (used by ported per-page scripts) ---- */
.status-message{padding:12px 16px;border-radius:var(--radius-sm);font-size:13px;margin-bottom:20px;}
.status-message.info{background:var(--accent-soft);color:var(--accent-dark);}
.status-message.success{background:var(--success-bg);color:var(--success);}
.status-message.warning{background:var(--warning-bg);color:var(--warning);}
.status-message.danger{background:var(--danger-bg);color:var(--danger);}

button.tool-tile{font-family:inherit;width:100%;cursor:pointer;}
.tool-tile.active{border-color:var(--accent) !important;background:var(--accent-soft) !important;}
.tool-tile.playing{box-shadow:0 0 0 3px var(--accent-soft-border);}
.tool-tile .tool-tile-icon{font-weight:800;color:var(--accent);font-size:14px;}

.recording-dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--danger);margin-right:6px;animation:pulse-dot 1.5s infinite;}
@keyframes pulse-dot{0%{opacity:.5;}50%{opacity:1;}100%{opacity:.5;}}

/* ---- level meter (mic / decibel-meter live input bar) ---- */
.level-meter{position:relative;height:22px;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-pill);overflow:hidden;margin-bottom:4px;}
.level-meter-fill{position:absolute;inset:0 auto 0 0;width:0%;background:linear-gradient(90deg,var(--success) 0%,var(--success) 55%,var(--warning) 78%,var(--danger) 92%);transition:width .08s linear;}
.level-meter-peak{position:absolute;top:0;bottom:0;width:2px;background:var(--text);opacity:.5;left:0%;transition:left .12s linear;}
.level-meter-scale{display:flex;justify-content:space-between;font-size:10px;color:var(--text-muted);margin-bottom:16px;}

/* ---- big numeric readouts (dB, timers, etc) ---- */
.readout-row{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:18px;}
.readout{flex:1;min-width:110px;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-md);padding:14px 12px;text-align:center;}
.readout-value{font-size:28px;font-weight:800;color:var(--text);line-height:1.1;}
.readout-value small{font-size:12.5px;font-weight:700;color:var(--text-muted);margin-left:2px;}
.readout-label{font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-muted);margin-top:5px;}
.readout.primary{background:var(--accent-soft);border-color:var(--accent-soft-border);}
.readout.primary .readout-value{color:var(--accent-dark);}

/* ---- device / key-value info panel ---- */
.info-panel{background:var(--bg);border-radius:var(--radius-sm);padding:14px 16px;margin-bottom:16px;font-size:12.5px;}
.info-panel-title{font-weight:700;margin-bottom:8px;}
.info-panel-row{display:flex;flex-direction:column;gap:3px;padding:8px 0;border-bottom:1px dashed var(--border);color:var(--text-secondary);}
.info-panel-row:last-child{border-bottom:none;}
.info-panel-row span:first-child{font-weight:700;color:var(--text);}
.info-panel-row span:last-child{font-weight:400;color:var(--text-secondary);text-align:left;line-height:1.5;}

/* ---- calibration / guidance callout ---- */
.callout-box{background:var(--accent-soft);border:1px solid var(--accent-soft-border);border-radius:var(--radius-md);padding:16px 18px;margin-bottom:18px;}
.callout-box-title{font-weight:700;font-size:13px;color:var(--accent-dark);margin-bottom:6px;}
.callout-box p{font-size:12.5px;color:var(--accent-dark);line-height:1.6;margin-bottom:10px;}
.callout-box p:last-child{margin-bottom:0;}
.callout-box.warn{background:var(--warning-bg);border-color:#FDE68A;}
.callout-box.warn .callout-box-title{color:var(--warning);}
.callout-box.warn p{color:#78350F;}

/* ---- rolling history graph ---- */
.graph-wrap{background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-md);padding:10px;margin-bottom:18px;}
.graph-wrap canvas{display:block;width:100%;height:120px;}

/* ---- labeled on/off switch ---- */
.toggle-row{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:10px 0;border-bottom:1px solid var(--border);}
.toggle-row:last-child{border-bottom:none;}
.toggle-row-label{font-size:12.5px;font-weight:600;color:var(--text-secondary);}
.toggle-row-hint{font-size:11px;color:var(--text-muted);margin-top:2px;line-height:1.5;}
.switch{position:relative;display:inline-block;width:38px;height:22px;flex-shrink:0;}
.switch input{position:absolute;opacity:0;width:100%;height:100%;margin:0;cursor:pointer;}
.switch-track{position:absolute;inset:0;background:var(--border-strong);border-radius:999px;transition:background .15s;pointer-events:none;}
.switch-track::before{content:'';position:absolute;width:16px;height:16px;left:3px;top:3px;background:#fff;border-radius:50%;transition:transform .15s;box-shadow:0 1px 2px rgba(0,0,0,.25);}
.switch input:checked + .switch-track{background:var(--accent);}
.switch input:checked + .switch-track::before{transform:translateX(16px);}
.switch input:focus-visible + .switch-track{outline:2px solid var(--accent);outline-offset:2px;}

/* ---- cycle / countdown progress bar ---- */
.cycle-progress{height:10px;background:var(--bg);border:1px solid var(--border);border-radius:999px;overflow:hidden;margin-bottom:8px;}
.cycle-progress-fill{height:100%;width:0%;background:var(--accent);transition:width .15s linear;}
.cycle-status{display:flex;justify-content:space-between;gap:10px;font-size:11.5px;color:var(--text-muted);margin-bottom:18px;flex-wrap:wrap;}

/* ---- small status badges (clipping alert, mode tags, etc) ---- */
.badge{display:inline-flex;align-items:center;gap:5px;font-size:10.5px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;padding:4px 10px;border-radius:999px;background:var(--bg);color:var(--text-muted);border:1px solid var(--border);}
.badge.danger{background:var(--danger-bg);color:var(--danger);border-color:transparent;}
.badge.warning{background:var(--warning-bg);color:var(--warning);border-color:transparent;}
.badge.success{background:var(--success-bg);color:var(--success);border-color:transparent;}
.badge.pulse{animation:pulse-dot 1s infinite;}

/* ---- mode picker tiles (selectable, not just decorative) ---- */
.mode-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin-bottom:18px;}
@media (max-width:560px){.mode-grid{grid-template-columns:1fr;}}
.mode-tile{text-align:left;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);padding:13px 14px;cursor:pointer;font-family:inherit;width:100%;}
.mode-tile-title{font-weight:700;font-size:12.5px;margin-bottom:4px;display:flex;align-items:center;justify-content:space-between;gap:8px;}
.mode-tile-desc{font-size:11px;line-height:1.5;color:var(--text-muted);}
.mode-tile.active{border-color:var(--accent);background:var(--accent-soft);}
.mode-tile.active .mode-tile-desc{color:var(--accent-dark);}

@media (max-width:560px){
  .readout-value{font-size:23px;}
  .graph-wrap canvas{height:90px;}
}

/* utility */
.visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;}
