/* =============================================================================
   [STYLES]
   ============================================================================= */
/* =============================================================================
   [STYLES]  -- Rewritten for v6.17 UI Refresh
   ---------------------------------------------------------------------------------
   Design notes:
   - Mindray-style monitor look up top (black, bright vital-coloured numerics)
   - Muted grey "workstation" below with three cleanly-separated columns
   - Consistent slider widths via --slider-w
   - Responsive grid collapses on narrow screens
   ============================================================================= */
:root {
    --bg: #050505;
    --panel: #1a1a1a;
    --panel-2: #222;
    --accent: #007bff;
    --accent-muted: #2a4a6a;
    --text-dim: #888;
    --text-mid: #aaa;
    --divider: #2a2a2a;
    --slider-w: 55%;
}
body {
    background: var(--bg);
    color: white;
    font-family: 'Segoe UI', sans-serif;
    margin: 0;
    font-size: 14px;
    /* v3.13 default = mobile-friendly natural flow with page scroll.
       Desktop layout overridden below in @media (min-width: 901px). */
    overflow-y: auto;
    overflow-x: hidden;
}

/* === DESKTOP LAYOUT (fixed viewport, no body scroll) ===================== */
@media (min-width: 901px) and (pointer: fine) {
    body {
        height: 100vh;
        overflow: hidden;
        display: flex;
        flex-direction: column;
    }
    #brand-bar { flex: 0 0 auto; }
    /* v3.21: explicit 60/40 flex-basis between monitor area and controls.
       min-height:0 on both lets them shrink below intrinsic content height
       so overflow:hidden + scrolling on children behaves correctly. */
    #main-row { flex: 1 1 60%; min-height: 0; height: auto; }
    #controls {
        flex: 1 1 40%;
        min-height: 0;
        overflow: hidden;            /* container doesn't scroll - cols do */
    }
    /* Each column scrolls internally; flex-column with content top-anchored. */
    #controls > .col {
        height: 100%;
        overflow-y: auto;
        min-height: 0;
        display: flex;
        flex-direction: column;
        justify-content: flex-start;
        box-sizing: border-box;
    }
    /* Children don't shrink - they use natural height; col scrolls when total exceeds height */
    #controls > .col > * { flex: 0 0 auto; margin-bottom: 8px; }
    #controls > .col > *:last-child { margin-bottom: 0; }
}

/* === TOP METADATA BAR ====================================================== */
#brand-bar {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    padding: 6px 12px 4px;
    background: #050505;
    border-bottom: 1px solid #1a1a1a;
}
/* v4.62: Hypnos/Synapse brand lockup - the Hypnos Medical brand kit's compact
   horizontal lockup, on-dark (80% of the standard lockup, defined in the kit for
   dense app bars like this one): white moon 18px, "Hypnos" Gelasio 10.5px,
   MEDICAL Geist 600 6.5px at 0.18em, rule 21px, "Synapse" Geist 600 13.5px.
   Replaces the v4.16 scaled-down lockup (teal crescent, Playfair Display).
   The two fonts are embedded as base64 subsets of just the glyphs in "Hypnos",
   "MEDICAL" and "Synapse" (SIL OFL), keeping the single-file, offline
   guarantee: no request to Google Fonts. Changing that text means re-subsetting.
   Sizes and colours come from the kit - change the kit, not this. */
@font-face { font-family: "HM Gelasio"; font-weight: 400; font-style: normal; font-display: swap;
    src: url(data:font/woff2;base64,d09GMgABAAAAAAWUABAAAAAACigAAAU4AAECDAAAAAAAAAAAAAAAAAAAAAAAAAAAGhYbIBxKBmA/U1RBVEgATBEIColQiBkBNgIkAyALEgAEIAWDdAcgDAcbSQhRVHAqKX4e2I0dhkAYatMawQhQD3bNeBppRbnAIIqIGit7dvcRFKIMl0efL59TQUmkgXT0q0gEoxPFxqXu7+f2hqcdIXE/TpRkSUTyRKxUYiIUUuf44T3tVVOaraPRAczk9M4DM8gHKunf6QtQ/sMKTVxOfyzxxhZpiycy1jfGAFyTxgTqwsTSsjF54qYugcIAowBzTkO85hevSjPyRoJhQBHRK4JBc3qwo8f3d+ho0AVAlDV9tVz8Yif1AUfBlKfTcVPooHNrwthfEdh8UcXU9ipdeujZ377AM0GWnz52OXtLx488tTsD+Gat6nP/z8HgVkVAoH7veYAldRH9CqbVsKZ29YyZYsC5S5KLNUUzrY6S5CnlE6oo6a0cLMEKYYxIbTgCDFZSWpwUSlQDJdcg/sDue4Qe7R3wRSK3sSHZFMaBYfKcsgNAA5qjmaAvKVtb7ehADttGjGvPYSMt6zSe7VE+rZ53htKZ76fxNhC0dQ1wq0OPoAa/TWrP9QG+KoLCQt9Jr6OJA9KyTEAssH/IiCyfj7TOycOKSCVJYOKnL3OBRRE2ExjRXUjjx++ItDx6pIe4SOvEncDzI3Gj3MFHUTGJD2nlU3oKNsT5AwP9r56lCZfX9vBe4sIF/DppfbhYeS7KVJnGOTHXyLQWf/KIJkAQIkWS1NtH463wMfkhkgtoSnRSAUZVfeSX2IjswMIv8xLgjwCfImcjp8x6kb5zgPsayYrJuGTMBRrvIcJdeMiPqdu+YzNo4AqylJOUwqNsjhjyCK1Dp8xqNh+93QUt1Wk6YInu8EaAk63igogG/XO0gjpIORiSbuznkzcyiKD4GyuSyqrtgzycvJblM2XxpoT5dmLvC5uFmoWQI44i6gyvEHn1Bpckb+F9xBNJ9tnNVNYoXV/IVRYTLw6b8k52L9Ryz88NNfv6bXf+yCCo+Aq7LmdH7aO/ulK7+PsMR5dyvQT741FuAUqeVayGikPQ666yN1Rbf//9tqI3XV3Ya1Iz5UFbyWuq83rR04GBvKfXxbPPwHGJo4zIvnbfVb/PkFUXeP6grj5Dbj7jp4jIt/v3Jb+7SoyHtqi+EPb9L2OFscsY6ggqbvAKqyo1OldTY/LznzDMtt5Rr/dxkTEcUYyIUT46KoF+/SYqnsZRYwSxAhnu0rKeqCKXK+mm7TsebMWV0o6p9vdxDguotXvsoV4R5lcVH5dbOWjvmxKrIy+THRcvLIyaiwvTA4xNE0WlxRD5UEGrlBTvKNsAtXh9r46EZJNgrQNhUQWhrZdW4OvHNEztu4bXV5n6WmLau1G/XFoz7n6q54gEUc7YgI/09OKof+7/0a8ewvHsgj7UeBSZN+6e5+5LfPbxd+wLbyuMh39K/RqWcKa8Iun0JlZfv4rFna4oTzyzjtVysaT18fG0tWIBrD1A6joA7gINCJ290nDiboqY01chhhDAT96XN+Df4+Kgvy/+EoO9IuoAeqEABOyI5B2E+BPSA2jwNvYfwJ9rL6QyT4AxaTs7tLehetm8/rxt3ICh30fD7ukpxNjiWUPuq9IGsIeGFqP2wIK+oFX7fGjNgj+tx0y61F4LoXjCcE62pDB7eqzo7r30GsxpM4FQJWYxmFJIn6CvD7kzaZAVjUuSsASQs1jAplG4yROZlCkQSyBEcZNSocQIj2ewsEkZGUcR8PBu0ascFt9dJaThq+xEalOvNIYsfq+YiCMQDIzd3M2MqQ4sVwnhh8CnOc66fKiSeooGX9ph9G+kEegGFdfupkh8dW9Z3diS3+X/3ls7AAAA) format("woff2"); }
@font-face { font-family: "HM Geist"; font-weight: 600; font-style: normal; font-display: swap;
    src: url(data:font/woff2;base64,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) format("woff2"); }
#hypnos-brand {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    text-decoration: none;
    white-space: nowrap;
    flex-shrink: 0;
    align-self: center;
}
.brand-icon { display: block; width: 18px; height: 18px; flex-shrink: 0; }
.brand-text { display: flex; flex-direction: column; line-height: 1.05; }
.brand-hypnos {
    font-family: "HM Gelasio", Georgia, "Times New Roman", serif;
    font-weight: 400;
    font-size: 10.5px;
    letter-spacing: 0.02em;
    color: #fff;
}
.brand-medical {
    font-family: "HM Geist", Arial, Helvetica, sans-serif;
    font-weight: 600;
    font-size: 6.5px;
    letter-spacing: 0.18em;
    margin-right: -0.18em;   /* letter-spacing trails the last letter; pull it back */
    text-transform: uppercase;
    color: #9babb8;
}
.brand-divider {
    width: 1px;
    height: 21px;
    background: rgba(255, 255, 255, 0.25);
    flex-shrink: 0;
}
.brand-product {
    font-family: "HM Geist", Arial, Helvetica, sans-serif;
    font-weight: 600;
    font-size: 13.5px;
    letter-spacing: -0.015em;
    line-height: 1;
    color: #fff;
    white-space: nowrap;
}
/* ---------------------------------------------------------------------------- */
/* v4.18: delivery tray - chips appear here while a bolus is "going in".
   Sits between the brand lockup and the right-hand button group; flex:1 +
   min-width:0 lets it absorb spare bar width and truncate rather than
   pushing the buttons off-screen when several chips are active. */
#delivery-tray {
    flex: 1 1 auto;
    min-width: 0;
    align-self: center;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 0 10px;
    overflow: hidden;
}
.delivery-chip {
    flex: 0 1 auto;
    min-width: 90px;
    max-width: 180px;
    display: flex;
    flex-direction: column;
    gap: 3px;
    background: rgba(20, 32, 44, 0.9);
    border: 1px solid var(--accent-muted);
    border-radius: 3px;
    padding: 3px 8px;
    opacity: 1;
    transition: opacity 0.4s;
}
.delivery-chip.done { opacity: 0; }
.delivery-chip .dc-label {
    font-size: 0.58rem;
    letter-spacing: 0.04em;
    color: #cfe2f5;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.delivery-chip .dc-bar {
    height: 3px;
    background: #1a2530;
    border-radius: 2px;
    overflow: hidden;
}
.delivery-chip .dc-fill {
    height: 100%;
    width: 0%;
    background: var(--accent);
    border-radius: 2px;
    /* width transition duration is set inline per-delivery by showDelivery() */
}
.delivery-chip.fluid .dc-fill { background: #1B7A8A; }
/* v4.19: infusion chips - persistent while the pump runs. The bar is full
   width with flowing stripes (continuous delivery) rather than the bolus
   chip's one-shot linear fill. Created/removed by updateInfusionChips(). */
.delivery-chip.infusion .dc-fill {
    width: 100%;
    background: repeating-linear-gradient(90deg,
        var(--accent) 0px, var(--accent) 6px,
        rgba(0, 123, 255, 0.30) 6px, rgba(0, 123, 255, 0.30) 12px);
    animation: inf-flow 0.9s linear infinite;
}
@keyframes inf-flow {
    from { background-position: 0 0; }
    to   { background-position: 12px 0; }
}

/* v4.21: active-event chips in the brand bar. Persistent (unlike the transient
   drug-delivery chips): one chip per active state.events flag. Scenario-driven
   activation; users disable an event by clicking (two-click confirm). */
#event-tray {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 0 1 auto;
    min-width: 0;
    align-self: center;
    overflow: hidden;
    padding: 0 6px;
}
.event-chip {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    /* default (data-sev="red") appearance; other severities override below */
    background: rgba(120,28,28,0.9);
    border: 1px solid #b45;
    color: #ffdede;
    font-size: 0.6rem;
    letter-spacing: 0.4px;
    text-transform: uppercase;
    padding: 4px 10px;
    border-radius: 3px;
    cursor: pointer;
    white-space: nowrap;
    max-width: 220px;
    overflow: hidden;
    text-overflow: ellipsis;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    transition: background-color 0.2s, border-color 0.2s;
}
.event-chip:hover { filter: brightness(1.12); }
/* v4.22: severity grading (yellow -> orange -> red) */
.event-chip[data-sev="yellow"] { background: rgba(140,112,16,0.9); border-color: #d8b020; color: #fff6d8; }
.event-chip[data-sev="orange"] { background: rgba(148,78,16,0.9);  border-color: #e08624; color: #ffe6d0; }
.event-chip[data-sev="red"]    { background: rgba(120,28,28,0.9);  border-color: #b45;    color: #ffdede; }
/* Pulsing status dot marks a live event; dot colour follows severity */
.event-chip .ec-dot {
    width: 6px; height: 6px;
    border-radius: 50%;
    background: #ff6b6b;
    flex: 0 0 auto;
    animation: event-dot-pulse 1.6s ease-in-out infinite;
}
.event-chip[data-sev="yellow"] .ec-dot { background: #ffd84d; }
.event-chip[data-sev="orange"] .ec-dot { background: #ff9d4d; }
.event-chip[data-sev="red"]    .ec-dot { background: #ff6b6b; }
@keyframes event-dot-pulse {
    0%, 100% { opacity: 1;   box-shadow: 0 0 4px currentColor; }
    50%      { opacity: 0.35; box-shadow: 0 0 0 currentColor; }
}
/* Confirm state: amber, "Disable? " prompt, dot becomes an ✕ glyph */
.event-chip[data-state="confirm"] {
    background: rgba(150,96,18,0.95);
    border-color: #e0a020;
    color: #fff;
}
.event-chip[data-state="confirm"] .ec-dot {
    width: auto; height: auto;
    border-radius: 0;
    background: none;
    animation: none;
    box-shadow: none;
    font-size: 0.62rem;
    line-height: 1;
    color: #fff;
}
.event-chip[data-state="confirm"] .ec-dot::before { content: '✕'; }

/* v3.7: fullscreen toggle button in brand bar */
#fullscreen-toggle {
    background: transparent;
    border: 1px solid #333;
    color: #888;
    width: 26px;
    height: 22px;
    border-radius: 3px;
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}
#fullscreen-toggle:hover { color: #ddd; border-color: #666; }
#fullscreen-exit {
    display: none;            /* hidden unless body.fullscreen-monitor */
    position: fixed;
    top: 8px;
    right: 12px;
    z-index: 1500;
    background: rgba(20,20,20,0.7);
    border: 1px solid #444;
    color: #ccc;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    padding: 0;
}
#fullscreen-exit:hover { background: rgba(40,40,40,0.9); color: #fff; }

/* v3.8: fullscreen-monitor mode no longer hides controls - we just claim
   the OS fullscreen via the API so browser chrome disappears, but all sim
   controls stay visible. The exit button is the only added affordance. */
body.fullscreen-monitor #fullscreen-exit { display: flex; align-items: center; justify-content: center; }

/* (v3.23: removed orphan #meta-bar / .meta-* / .btn-mini / .profile-group
   styles - this top-bar UI was replaced by the brand-bar/modal flow.) */
/* (v3.23: removed bare #scenarioSelect rule - element only renders inside
   #panel-config, which has its own ruleset.) */
/* Floating Silence button: positioned over the top-right of the waveform area.
   Always visible regardless of which left-panel tab is open. */
/* Waveform trace labels: small colour-coded text on the left edge of the
   monitor area, aligned with each trace's y-centre. pointer-events:none so
   they don't swallow clicks on the trace below. */
.wf-label {
    position: absolute;
    left: 6px;            /* v3.5: back to far left. With 6 lanes the PANEL handle
                             sits in the middle, so no labels are obscured. */
    font-family: 'Consolas', 'Courier New', monospace;
    font-size: 0.55rem;
    font-weight: bold;
    letter-spacing: 0.5px;
    pointer-events: none;
    z-index: 20;
    text-shadow: 0 0 3px #000;
}
.wf-label.wf-ecg   { color: #00ff00; }
.wf-label.wf-pleth { color: #00ffff; }
.wf-label.wf-art   { color: #ff3333; }
.wf-label.wf-paw   { color: #ffffff; }
.wf-label.wf-flow  { color: #9cf; }
.wf-label.wf-co2   { color: #ffff00; }

/* v3.28: #floating-silence rules removed - SILENCE button now in brand bar
   (see #brand-silence-btn styling near the panel-handle replacement). */

/* === MONITOR AREA ========================================================== */
#monitor {
    display: grid;
    grid-template-columns: 1fr 260px;
    height: 100%;
    min-height: 0;    /* v6.18: without this, #monitor (a flex item of #main-row)
                         refuses to shrink below its content's natural height on
                         short viewports, pushing #controls past the fold. */
    background: black;
    border-bottom: 2px solid #333;
}
#waveforms { position: relative; overflow: hidden; background: #000; }
canvas { display: block; width: 100%; height: 100%; }

#numerics {
    border-left: 2px solid #222;
    padding: 8px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    background: #000;
    position: relative;
    min-height: 0;    /* v6.18: grid item default min-height:auto sizes to the
                         11 fixed-height .box rows (~540px); without this the
                         boxes overflow #monitor's grid cell downward instead
                         of scrolling, clipping the top of the controls deck
                         below on non-fullscreen/non-maximized windows. */
    overflow-y: auto;
}
.box {
    height: 46px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding-right: 10px;
    border-bottom: 1px solid #111;
    cursor: pointer;
    position: relative;
}
.label {
    font-size: 0.6rem;
    font-weight: bold;
    color: var(--text-dim);
    letter-spacing: 0.5px;
}
.value {
    font-size: 2.1rem;
    font-family: 'Consolas', 'Courier New', monospace;
    text-align: right;
    line-height: 1;
    font-weight: bold;
}
.green  { color: #00ff00; }
.cyan   { color: #00ffff; }
.red    { color: #ff3333; }
.yellow { color: #ffff00; }
.white  { color: #ffffff; }
.purple { color: #d4ff00; }
.orange { color: #ff9933; }

/* Waveform overlays (click to "connect") */
.conn-label {
    position: absolute;
    left: 50%;
    transform: translate(-50%, -50%);
    background: rgba(0,0,0,0.85);
    border: 1px dashed #555;
    padding: 8px 16px;
    border-radius: 4px;
    font-weight: bold;
    color: #777;
    cursor: pointer;
    z-index: 10;
    font-size: 0.8rem;
}
#ov-bis {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: rgba(0,0,0,0.9);
    border: 1px dashed #555;
    padding: 6px 10px;
    border-radius: 4px;
    font-weight: bold;
    color: #d4ff00;
    cursor: pointer;
    z-index: 10;
    font-size: 0.7rem;
}

/* === BOTTOM CONTROL DECK ================================================== */
#controls {
    /* v3.11: natural height, normal flow. Page scrolls if content exceeds
       viewport. Two columns on desktop, single column on mobile (media query). */
    display: grid;
    grid-template-columns: 1.2fr 1fr;
    gap: 0;
    background: var(--panel);
    border-top: 2px solid #333;
}
.col {
    /* v3.19: block layout (was flex). Flex children shrink to fit when the
       column is height-capped on desktop, which suppresses overflow scroll.
       Block layout lets each child take its natural height, the column then
       overflows correctly, and overflow-y:auto engages. */
    display: block;
    padding: 10px 12px;
    border-right: 1px solid var(--divider);
}
.col > * { margin-bottom: 8px; }     /* replaces flex gap */
.col > *:last-child { margin-bottom: 0; }
.col:last-child { border-right: none; }

/* Scrollbar polish for columns */
.col::-webkit-scrollbar { width: 6px; }
.col::-webkit-scrollbar-track { background: transparent; }
.col::-webkit-scrollbar-thumb { background: #444; border-radius: 3px; }
.col::-webkit-scrollbar-thumb:hover { background: #555; }

h3 {
    margin: 0;
    font-size: 0.72rem;
    color: var(--accent);
    text-transform: uppercase;
    letter-spacing: 1px;
    border-bottom: 1px solid var(--divider);
    padding-bottom: 3px;
    font-weight: 600;
}
h4 {
    margin: 4px 0 2px 0;
    font-size: 0.62rem;
    color: var(--text-mid);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    font-weight: 500;
}

/* === BUTTON GROUPS (mode/airway/tabs) ====================================== */
.btn-group {
    display: flex;
    gap: 2px;
}
.btn-group button {
    flex: 1;
    font-size: 0.65rem;
    padding: 5px 4px;
    background: #2a2a2a;
    border: 1px solid #444;
    color: #aaa;
    cursor: pointer;
    border-radius: 2px;
    transition: background 0.15s;
}
.btn-group button:hover { background: #333; color: #ddd; }
.btn-group button.active {
    background: var(--accent);
    color: white;
    border-color: var(--accent);
}

/* === DRUG BOLUS GRID =======================================================
   New layout: one drug per row. Drug name on left, dose buttons on right. */
.drug-grid {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.drug-row {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 0.68rem;
}
.drug-row .drug-name {
    flex: 1 1 auto;
    min-width: 0;
    color: #ddd;
    padding: 3px 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.drug-row .dose-btns {
    display: flex;
    gap: 3px;
    flex: 0 0 auto;
}
.drug-row button {
    background: #2e2e2e;
    border: 1px solid #4a4a4a;
    font-size: 0.66rem;
    padding: 5px 10px;    /* v4.19: 4x8 -> 5x10 for easier tapping */
    color: white;
    cursor: pointer;
    border-radius: 2px;
    transition: background 0.15s;
    min-width: 44px;      /* v4.19: 40 -> 44 */
    /* v4.19: no grey tap flash on touch - the .dosing pulse is the feedback */
    -webkit-tap-highlight-color: transparent;
}
.drug-row button:hover { background: #3a3a3a; border-color: #666; }
/* v4.18: clicked dose button pulses while the bolus is delivered. Class is
   added/removed by showDelivery(); ref-counted via data-dosing so rapid
   repeat clicks keep pulsing until the last delivery finishes. */
.drug-row button.dosing {
    background: var(--accent);
    border-color: var(--accent);
    animation: dose-pulse 0.8s ease-in-out infinite;
}
@keyframes dose-pulse {
    0%, 100% { filter: brightness(1.35); }
    50%      { filter: brightness(0.75); }
}

/* v4.19: tablet friendliness. touch-action: manipulation kills the browser's
   double-tap-to-zoom wait on all buttons - matters when re-dosing quickly.
   On coarse-pointer devices (tablet/phone) enlarge the drug deck's touch
   targets toward the ~44px guideline and widen gaps so adjacent dose
   buttons aren't mis-tapped. Desktop density is unchanged. */
button { touch-action: manipulation; }
@media (pointer: coarse) {
    .drug-grid { gap: 6px; }
    .drug-row { font-size: 0.78rem; }
    .drug-row .dose-btns { gap: 6px; }
    .drug-row button {
        min-height: 42px;
        min-width: 56px;
        font-size: 0.78rem;
        padding: 8px 12px;
    }
    #tabs-container button {
        min-height: 40px;
        font-size: 0.75rem;
        padding: 8px 6px;
    }
}

/* === SLIDER ROWS =========================================================== */
.slider-row {
    font-size: 0.65rem;
    color: #ccc;
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: 8px;
}
.slider-row .label-pair {
    display: flex;
    justify-content: space-between;
    padding-right: 4px;
}
.slider-row .label-pair .val {
    color: white;
    font-family: 'Consolas', monospace;
    font-weight: bold;
    min-width: 40px;
    text-align: right;
}
input[type=range] {
    width: var(--slider-w);
    min-width: 110px;
    margin: 0;
    cursor: pointer;
    /* v3.57: let vertical swipes pass through to page scroll on mobile.
       Without this, a tap-then-drag on the slider track (when the user is
       trying to scroll the panel) snaps the slider to the touch x-position
       before the browser detects scroll intent. With pan-y, the browser
       handles vertical pans natively (page scrolls) and only horizontal
       gestures reach the slider. */
    touch-action: pan-y;
}
/* Full-width slider variant */
.slider-full input[type=range] { width: 100%; }
.slider-full { grid-template-columns: 1fr; }
.slider-full .label-pair { margin-bottom: 2px; }

/* === BAG BUTTON (manual ventilation) ======================================= */
#bagBtn {
    padding: 14px;
    font-weight: bold;
    background: #1a3a5a;
    color: white;
    border: 1px solid #2a5a8a;
    cursor: pointer;
    font-size: 0.8rem;
    border-radius: 3px;
    user-select: none;
    -webkit-user-select: none;
    transition: background 0.1s;
}
#bagBtn:hover { background: #235078; }
#bagBtn.squeezing { background: #2a7ab5; border-color: #4ac; }

/* v3.69: Suction airway action button. Momentary action - not a toggle.
   Sits below the airway device buttons. Becomes prominent (amber) when
   there's something to suction (aspiration event active). */
.suction-btn {
    width: 100%;
    margin-top: 6px;
    padding: 8px;
    background: #2a2a2a;
    color: #aaa;
    border: 1px solid #444;
    border-radius: 3px;
    cursor: pointer;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.suction-btn:hover { background: #353535; color: #ddd; border-color: #888; }
.suction-btn.urgent {
    background: #6a4a1a;
    color: #fff;
    border-color: #c88;
    animation: suction-pulse 1.5s ease-in-out infinite;
}
@keyframes suction-pulse {
    0%, 100% { background: #6a4a1a; }
    50%      { background: #8a6020; }
}

/* === EVENT SYSTEM (collapsible groups) ==================================== */
.evt-group {
    border-top: 1px solid var(--divider);
    padding-top: 4px;
}
.evt-group-header {
    font-size: 0.62rem;
    color: var(--text-mid);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    cursor: pointer;
    padding: 2px 0;
    user-select: none;
    display: flex;
    align-items: center;
    gap: 4px;
}
.evt-group-header::before {
    content: "\25BE";    /* v3.49: was literal "▾" Unicode char which rendered as garbled "A-3/4" if file was served as latin-1. CSS escape works regardless of charset. */
    font-size: 0.7rem;
    transition: transform 0.2s;
}
.evt-group.collapsed .evt-group-header::before {
    transform: rotate(-90deg);
}
.evt-group.collapsed .evt-buttons { display: none; }
.evt-buttons {
    display: flex;
    flex-direction: column;
    gap: 3px;
    margin-top: 3px;
}
.evt-btn {
    font-size: 0.66rem;
    padding: 5px 6px;
    background: #2a2020;
    border: 1px solid #554035;
    color: #ddcc99;
    cursor: pointer;
    border-radius: 2px;
    text-align: left;
    transition: background 0.15s;
}
.evt-btn:hover { background: #382a25; }
.evt-btn.active {
    background: #722015;
    border-color: #c96;
    color: white;
    font-weight: bold;
}
/* v3.49: visual styling for disabled event buttons (those awaiting individual verification).
   Greyed out, no hover effect, "not allowed" cursor. */
.evt-btn:disabled,
.evt-btn[disabled] {
    background: #1a1818;
    border-color: #2a2625;
    color: #555;
    cursor: not-allowed;
    opacity: 0.6;
}
.evt-btn:disabled:hover,
.evt-btn[disabled]:hover {
    background: #1a1818;
}

/* Cardiac rhythm buttons - arrest rhythms are tinted red */
.rh-btn { background: #1f2028; border-color: #3a4055; color: #bcc; }
.rh-btn:hover { background: #2a2d3a; }
.rh-btn.active { background: #274b7a; border-color: #6cf; color: #fff; }
.rh-btn.rh-arrest { background: #2a1515; border-color: #663; color: #edc; }
.rh-btn.rh-arrest:hover { background: #3a1a1a; }
.rh-btn.rh-arrest.active { background: #a01818; border-color: #f66; color: #fff; }

/* Anaphylaxis: orange-red while active */
.evt-btn.evt-anaph.active { background: #a02020; border-color: #f66; }

/* Graded haemorrhage: inline row with label and 3 small buttons */
.bleed-row {
    display: flex;
    align-items: center;
    gap: 4px;
}
.bleed-label {
    font-size: 0.66rem;
    color: #ddcc99;
    flex: 0 0 auto;
    padding: 0 4px;
}
.bleed-btn {
    flex: 1 1 auto;
    padding: 5px 4px;
    font-size: 0.62rem;
    text-align: center;
}

/* === SCENARIOS DROPDOWN (stub) ============================================= */
/* (v3.23: removed orphan #scenarioBtn rules - replaced by modal-based scenario picker) */
#resetBtn {
    margin-top: auto;
    padding: 6px;
    background: #3a2020;
    color: #eed;
    border: 1px solid #663;
    cursor: pointer;
    border-radius: 2px;
    font-size: 0.65rem;
    text-transform: uppercase;
}
#resetBtn:hover { background: #4a2a2a; }

/* === MAIN LAYOUT ROW (left panel + monitor) ============================== */
/* Flex row: panel is collapsible via width transition, monitor fills remaining space.
   The row itself has the explicit height that used to be on #monitor alone, so
   flex children can stretch predictably. */
#main-row {
    /* v3.18: no bare height. Mobile @media sets 60vh; desktop @media sets
       flex: 1 1 auto. Putting it bare here caused source-order override
       on desktop. */
    display: flex;
    align-items: stretch;
    width: 100%;
    position: relative;   /* anchor for the absolutely-positioned handle */
}
#main-row > #monitor { flex: 1 1 auto; min-width: 0; height: 100%; }

/* === LEFT POP-OUT PANEL with tabs ========================================= */
/* Collapsed: width 0 (invisible). Open: width 420px, pushing the monitor right.
   v3.28: panel toggled via the PANEL button in the brand bar (was a vertical
   handle on the left edge, removed because it overlapped trace labels). */
#left-panel {
    position: relative;
    width: 0;
    height: 100%;
    background: rgba(10,10,10,0.98);
    border-right: 2px solid var(--accent);
    transition: width 0.3s ease;
    z-index: 50;
    font-size: 0.65rem;
    color: #ddd;
    display: flex;
    flex-direction: column;
    flex-shrink: 0;
    overflow: hidden;
}
#left-panel.open { width: 420px; }

/* Handle: sits in the main-row (not inside panel) so it's never clipped.
   Positioned absolutely at the left edge; its left offset is 0 when panel
   closed, or ~420px (panel width) when open - we animate by making it sit
   immediately after the panel using left:0 + a margin that tracks panel state. */
/* v3.28: panel-handle and floating-silence removed - both now live in brand bar
   as standard buttons. Brand bar button styling: */
#brand-silence-btn {
    padding: 4px 10px;
    font-size: 0.65rem;
    border: none;
    border-radius: 3px;
    cursor: pointer;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
/* v3.30: silence button has three states with distinct colours */
#brand-silence-btn { background: rgba(42,42,42,0.85); color: #ccc; border: 1px solid #666; }
#brand-silence-btn:hover { filter: brightness(1.2); }
#brand-silence-btn.audio-silent { background: rgba(42,42,42,0.85);  color: #aaa; border-color: #666; }
#brand-silence-btn.audio-on     { background: rgba(56,128,56,0.85); color: #fff; border-color: #4a4; }
#brand-silence-btn.audio-alarms { background: rgba(160,90,30,0.85); color: #fff; border-color: #c70; }
#brand-silence-btn.audio-ecg    { background: rgba(56,90,128,0.85); color: #fff; border-color: #4a8; }

/* v3.52: About button (small, low-contrast - it's reference info, not a primary control) */
#brand-about-btn,
#brand-scenarios-btn,
#brand-phys-btn,
#brand-resources-btn,
#brand-panel-btn {     /* v3.64: SCENARIOS button uses same styling. v4.17: PANEL too - it
                           only turns accent-blue while the side panel is actually open.
                           v4.20: PHYSIOLOGY button shares the styling. v4.40: RESOURCES too. */
    padding: 4px 10px;
    font-size: 0.6rem;
    background: rgba(42,42,42,0.85);
    color: #aaa;
    border: 1px solid #555;
    border-radius: 3px;
    cursor: pointer;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
#brand-about-btn:hover,
#brand-scenarios-btn:hover,
#brand-phys-btn:hover,
#brand-resources-btn:hover,
#brand-panel-btn:hover { background: rgba(60,60,60,0.85); color: #ddd; border-color: #888; }
/* v4.20: PHYSIOLOGY button lights up accent-blue while its modal is open */
#brand-phys-btn.active { background: var(--accent); color: #fff; border-color: var(--accent); }
#brand-phys-btn.active:hover { filter: brightness(1.15); }
/* v4.40: RESOURCES button shares the same active-state treatment */
#brand-resources-btn.active { background: var(--accent); color: #fff; border-color: var(--accent); }
#brand-resources-btn.active:hover { filter: brightness(1.15); }
/* v4.25: compact surgical-stimulus slider in the brand bar
   v4.32: now sits on the left, beside the brand lockup - margin-left gives it
   breathing room from the wordmark */
#brand-noci {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    align-self: center;
    margin-left: 14px;
    padding: 3px 9px;
    border: 1px solid #555;
    border-radius: 3px;
    background: rgba(42,42,42,0.85);
    flex: 0 0 auto;
}
#brand-noci .bn-label {
    font-size: 0.55rem; letter-spacing: 0.5px; color: #aaa;
    text-transform: uppercase; white-space: nowrap;
}
#brand-noci input[type="range"] {
    width: 90px; height: 4px; margin: 0; cursor: pointer;
    accent-color: var(--accent);
    touch-action: manipulation;
}
#brand-noci .bn-val {
    font-family: 'Consolas', monospace; font-size: 0.62rem; color: #fff;
    min-width: 20px; text-align: right;
}
/* v3.64: highlight the SCENARIOS button when a scenario is active. */
#brand-scenarios-btn.active { background: #235; color: #def; border-color: #6cf; }
/* v4.17: PANEL button lights up accent-blue only while the panel is open */
#brand-panel-btn.active { background: var(--accent); color: #fff; border-color: var(--accent); }
#brand-panel-btn.active:hover { filter: brightness(1.15); }

/* v3.52: About modal */
/* v3.83: "Start here" novice orientation modal.
   Re-openable from the brand bar. Four stepped sections; section 2 is an
   annotated monitor mock whose colours match the live monitor traces/numerics. */
#sh-overlay {
    display: none;
    position: fixed;
    top: 0; left: 0; right: 0; bottom: 0;
    background: rgba(0,0,0,0.8);
    z-index: 10001;
    align-items: center;
    justify-content: center;
    padding: 20px;
}
#sh-overlay.open { display: flex; }
#sh-modal {
    background: #181818;
    border: 1px solid #444;
    border-radius: 6px;
    color: #ccc;
    max-width: 800px;
    width: 100%;
    max-height: 92vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    font-size: 0.82rem;
    line-height: 1.55;
}
#sh-modal-head {
    padding: 16px 24px 12px;
    border-bottom: 1px solid #333;
    flex: 0 0 auto;
}
#sh-modal-head h2 { margin: 0; font-size: 1.15rem; color: #eee; letter-spacing: 0.3px; }
#sh-modal-head .sh-sub { color: #888; font-size: 0.72rem; margin-top: 2px; }
#sh-steps { display: flex; gap: 6px; margin-top: 12px; }
#sh-steps .dot { flex: 1; height: 4px; border-radius: 2px; background: #333; cursor: pointer; transition: background 0.15s; }
#sh-steps .dot.active { background: #3aa777; }
#sh-body { padding: 18px 24px; overflow-y: auto; flex: 1 1 auto; }
.sh-section { display: none; }
.sh-section.active { display: block; }
.sh-section h3 { color: #8cc8ff; font-size: 1rem; margin: 0 0 12px; }
.sh-section p { margin: 0 0 12px; }
.sh-section p.lead { color: #ddd; font-size: 0.9rem; }
/* annotated monitor mock */
.sh-mock {
    background: #000; border: 1px solid #2a2a2a; border-radius: 4px;
    padding: 10px; margin: 0 0 8px; display: flex; gap: 10px;
}
.sh-mock-waves { flex: 1.5; display: flex; flex-direction: column; gap: 4px; }
.sh-wave {
    height: 24px; border-radius: 2px; background: #080808;
    display: flex; align-items: center; padding-left: 8px;
    font-size: 0.58rem; font-weight: bold; letter-spacing: 1.5px;
    border-left: 3px solid currentColor;
}
.sh-mock-nums { flex: 1; display: flex; flex-direction: column; gap: 3px; }
.sh-num {
    background: #080808; border-radius: 2px; padding: 3px 8px;
    display: flex; justify-content: space-between; align-items: baseline; gap: 6px;
}
.sh-num .lbl { font-size: 0.52rem; color: #888; text-transform: uppercase; letter-spacing: 0.5px; }
.sh-num .val { font-size: 0.88rem; font-weight: bold; }
.sh-mock-cap { color: #666; font-size: 0.68rem; font-style: italic; margin: 0 0 16px; }
/* callout cards */
.sh-cards-head { color: #888; font-size: 0.68rem; text-transform: uppercase; letter-spacing: 1px; margin: 16px 0 6px; }
.sh-cards { display: flex; flex-direction: column; gap: 7px; }
.sh-card { background: #1e1e1e; border-left: 3px solid #555; border-radius: 0 4px 4px 0; padding: 7px 12px; }
.sh-card .tag { font-weight: bold; font-size: 0.82rem; }
.sh-card .desc { color: #bbb; font-size: 0.77rem; margin-top: 2px; line-height: 1.45; }
/* controls section helpers */
.sh-loop { background: #14241c; border: 1px solid #2a5; border-radius: 4px; padding: 10px 14px; margin: 6px 0 14px; color: #cde; font-size: 0.82rem; }
.sh-loop strong { color: #6e9; }
/* footer nav */
#sh-foot {
    padding: 12px 24px 16px; border-top: 1px solid #333;
    display: flex; justify-content: space-between; align-items: center;
    flex: 0 0 auto; gap: 10px;
}
#sh-foot .sh-nav-right { display: flex; gap: 8px; }
#sh-foot button {
    padding: 6px 16px; font-size: 0.72rem; border-radius: 3px; cursor: pointer;
    border: 1px solid #555; background: rgba(42,42,42,0.85); color: #ccc;
}
#sh-foot button.primary { background: #2a8060; border-color: #3aa777; color: #eafff5; font-weight: bold; }
#sh-foot button:disabled { opacity: 0.3; cursor: default; }
#sh-skip { background: none; border: none; color: #777; padding-left: 0; }
/* v4.23: left-side footer group + About link (subtle text, styled like Skip)
   v4.30: same treatment for the Download link */
#sh-foot .sh-foot-left { display: flex; align-items: center; gap: 16px; }
#sh-foot #sh-about-link {
    background: none; border: none; color: #777; padding: 0;
    text-decoration: underline; font-size: 0.72rem; cursor: pointer;
}
#sh-foot #sh-about-link:hover { color: #aaa; }
/* v4.68: Admin link, styled to match the About link beside it */
#sh-foot #sh-admin-link { color: #777; text-decoration: underline; font-size: 0.72rem; }
#sh-foot #sh-admin-link:hover { color: #aaa; }
/* v4.31: offline-copy notice. Shown at load only when the sim is running from
   file:// (a copy saved via the Download link or "Save page as"). A slim
   dismissible strip; sits above the modals (they are z-index 10000-10001) so
   it stays readable whatever is open. Hidden by default - the [INIT] protocol
   check flips it to flex. */
#local-copy-note {
    display: none; position: fixed; top: 8px; left: 50%; transform: translateX(-50%);
    z-index: 10500; max-width: min(92vw, 640px);
    align-items: center; gap: 12px;
    padding: 8px 12px; border-radius: 5px;
    background: rgba(20, 24, 30, 0.97); border: 1px solid #8a6d1a;
    color: #e8d9a0; font-size: 0.74rem; line-height: 1.4;
    box-shadow: 0 4px 18px rgba(0,0,0,0.6);
}
#local-copy-note a { color: #ffd45e; font-weight: bold; text-decoration: underline; }
#local-copy-note button {
    background: none; border: none; color: #b09b55; font-size: 1rem;
    cursor: pointer; padding: 0 2px; line-height: 1;
}
#local-copy-note button:hover { color: #ffd45e; }
/* brand bar button - subtly highlighted so newcomers notice it */
#brand-starthere-btn {
    padding: 4px 10px; font-size: 0.6rem;
    background: #2a8060; color: #eafff5; border: 1px solid #3aa777;
    border-radius: 3px; cursor: pointer; text-transform: uppercase;
    letter-spacing: 0.5px; font-weight: bold;
}
#brand-starthere-btn:hover { background: #34a078; }

#about-modal-overlay {
    display: none;
    position: fixed;
    top: 0; left: 0; right: 0; bottom: 0;
    background: rgba(0,0,0,0.75);
    z-index: 10000;
    align-items: center;
    justify-content: center;
    padding: 20px;
}
#about-modal-overlay.open { display: flex; }
#about-modal {
    background: #181818;
    border: 1px solid #444;
    border-radius: 6px;
    color: #ccc;
    max-width: 640px;
    width: 100%;
    max-height: 90vh;
    overflow-y: auto;
    padding: 20px 24px;
    font-size: 0.78rem;
    line-height: 1.5;
}
#about-modal h2 {
    margin: 0 0 6px 0;
    color: #e4e4e4;
    font-size: 1.1rem;
    font-weight: 500;
    letter-spacing: 0.5px;
}
#about-modal h3 {
    margin: 18px 0 6px 0;
    color: #ddd;
    font-size: 0.85rem;
    font-weight: 500;
    border-top: 1px solid #2a2a2a;
    padding-top: 14px;
}
#about-modal h3:first-of-type { border-top: none; padding-top: 0; }
#about-modal .author {
    color: #888;
    font-size: 0.7rem;
    margin-bottom: 4px;
}
#about-modal .version {
    color: #666;
    font-size: 0.7rem;
    margin-bottom: 14px;
}
#about-modal p { margin: 6px 0; }
#about-modal ul { margin: 6px 0 6px 18px; padding: 0; }
#about-modal li { margin: 2px 0; }
#about-modal .disclaimer {
    background: #2a1a10;
    border-left: 3px solid #c33;
    padding: 10px 14px;
    color: #e4cac0;
    font-size: 0.78rem;
}
#about-modal a { color: #6cf; text-decoration: none; }
#about-modal a:hover { text-decoration: underline; }
#about-modal-close {
    background: transparent;
    color: #888;
    border: 1px solid #555;
    padding: 5px 14px;
    border-radius: 3px;
    cursor: pointer;
    margin-top: 14px;
    font-size: 0.75rem;
}
#about-modal-close:hover { color: #ccc; border-color: #888; }

/* v3.64: scenarios picker modal (re-uses much of the about modal's styling
   but is its own DOM tree so layout changes don't bleed). */
#scenarios-modal-overlay {
    display: none;
    position: fixed;
    top: 0; left: 0; right: 0; bottom: 0;
    background: rgba(0,0,0,0.75);
    z-index: 10000;
    align-items: center;
    justify-content: center;
    padding: 20px;
}
#scenarios-modal-overlay.open { display: flex; }
#scenarios-modal {
    background: #181818;
    border: 1px solid #444;
    border-radius: 6px;
    color: #ccc;
    max-width: 480px;
    width: 100%;
    max-height: 90vh;
    overflow-y: auto;
    padding: 20px 24px;
    font-size: 0.78rem;
    line-height: 1.5;
}
#scenarios-modal h2 {
    margin: 0 0 4px 0;
    color: #e4e4e4;
    font-size: 1.1rem;
    font-weight: 500;
    letter-spacing: 0.5px;
}
#scenarios-modal .hint {
    color: #777;
    font-size: 0.7rem;
    margin: 0 0 14px 0;
}
#scenarios-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 14px;
}
#scenarios-list .scenario-btn {
    background: #222;
    color: #ddd;
    border: 1px solid #444;
    border-radius: 3px;
    padding: 10px 14px;
    cursor: pointer;
    font-size: 0.85rem;
    text-align: left;
    font-family: inherit;
    transition: background 0.15s, border-color 0.15s;
}
#scenarios-list .scenario-btn:hover {
    background: #2a2a2a;
    border-color: #6cf;
}
#scenarios-list .scenario-btn.active {
    background: #235;
    border-color: #6cf;
    color: #def;
}
#scenarios-list .scenario-btn.reset {
    color: #aaa;
    font-style: italic;
    border-style: dashed;
}
/* v4.33: voucher-gated Pro scenarios. Locked buttons stay in the list (it
   doubles as the shop window) but read as unavailable; the voucher entry
   area sits under the list and is hidden entirely when ENT_CONFIG is empty. */
#scenarios-list .scenario-btn.locked {
    color: #778;
    background: #1b1b1f;
}
#scenarios-list .scenario-btn.locked:hover {
    border-color: #c93;
    background: #221f1a;
}
#scenarios-list .scenario-btn .pro-badge {
    float: right;
    color: #c93;
    font-size: 0.7rem;
    letter-spacing: 0.08em;
    font-style: normal;
}
#voucher-area {
    margin: 0 0 14px;
    padding: 10px 12px;
    border: 1px dashed #444;
    border-radius: 3px;
    transition: border-color 0.3s;
}
#voucher-area.attention { border-color: #c93; }
/* v4.64 */
#voucher-buy { display: inline-block; margin-top: 8px; font-size: 0.75rem; color: #6cf; }
#scenarios-list .scenarios-note { font-size: 0.8rem; color: #9ab; padding: 8px 2px; }
#scenarios-list .scenarios-note.err { color: #e98; }
#voucher-status { font-size: 0.75rem; color: #9ab; margin-bottom: 6px; }
#voucher-row { display: flex; gap: 6px; }
#voucher-input {
    flex: 1;
    background: #161616;
    border: 1px solid #444;
    color: #ddd;
    padding: 6px 8px;
    border-radius: 3px;
    font-family: inherit;
    font-size: 0.85rem;
    text-transform: uppercase;
}
#voucher-input:focus { outline: none; border-color: #6cf; }
#voucher-apply {
    background: #235;
    color: #def;
    border: 1px solid #6cf;
    border-radius: 3px;
    padding: 6px 14px;
    cursor: pointer;
    font-family: inherit;
    font-size: 0.8rem;
}
#voucher-apply:hover { background: #346; }
#voucher-msg { font-size: 0.75rem; min-height: 1em; margin-top: 6px; color: #9ab; }
#voucher-msg.err { color: #e66; }
#voucher-msg.ok  { color: #6d9; }
#scenarios-modal-close {
    background: transparent;
    color: #888;
    border: 1px solid #555;
    padding: 5px 14px;
    border-radius: 3px;
    cursor: pointer;
    font-size: 0.75rem;
}
#scenarios-modal-close:hover { color: #ccc; border-color: #888; }
#scenarios-modal-close2 { /* same as close button */
    background: transparent;
    color: #888;
    border: 1px solid #555;
    padding: 5px 14px;
    border-radius: 3px;
    cursor: pointer;
    font-size: 0.75rem;
}
#scenarios-modal-close2:hover { color: #ccc; border-color: #888; }

/* v3.72: brief view tabs (Setup / Objectives / Hints) */
.brief-tabs {
    display: flex;
    gap: 4px;
    margin-bottom: 12px;
    border-bottom: 1px solid #333;
}
.brief-tab {
    background: transparent;
    color: #888;
    border: none;
    border-bottom: 2px solid transparent;
    padding: 8px 12px;
    cursor: pointer;
    font-family: inherit;
    font-size: 0.75rem;
    letter-spacing: 0.3px;
    transition: color 0.15s, border-color 0.15s;
}
.brief-tab:hover { color: #ccc; }
.brief-tab.active {
    color: #def;
    border-bottom-color: #6cf;
}
.brief-content {
    min-height: 100px;
    padding: 8px 4px 16px;
    line-height: 1.55;
    color: #ccc;
    font-size: 0.78rem;
}
.brief-content ul {
    margin: 0;
    padding-left: 18px;
}
.brief-content ul li {
    margin-bottom: 6px;
}
.brief-content .empty {
    color: #777;
    font-style: italic;
    padding: 12px 0;
}
.brief-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 8px;
}
.brief-link {
    background: transparent;
    color: #888;
    border: none;
    padding: 4px 0;
    cursor: pointer;
    font-family: inherit;
    font-size: 0.72rem;
    letter-spacing: 0.3px;
}
.brief-link:hover { color: #ccc; text-decoration: underline; }
/* v4.58: the brief footer now carries two buttons on the right (Reset and
   Close), so they get their own flex box rather than fighting the
   space-between that separates them from the "choose different" link. */
.brief-footer-right {
    display: flex;
    align-items: center;
    gap: 8px;
}
#scenarios-reset {
    background: transparent;
    color: #9bb4cc;
    border: 1px solid #2f4a63;
    border-radius: 3px;
    padding: 6px 12px;
    cursor: pointer;
    font-family: inherit;
    font-size: 0.72rem;
    letter-spacing: 0.3px;
}
#scenarios-reset:hover {
    background: #16283a;
    color: #cfe0ef;
    border-color: #3f6488;
}


/* Tab strip inside panel */
#panel-tabs {
    display: flex;
    flex-shrink: 0;
    border-bottom: 1px solid var(--accent);
}
#panel-tabs button {
    flex: 1;
    padding: 8px 2px;
    background: #1a1a1a;
    border: none;
    border-right: 1px solid #333;
    color: #888;
    cursor: pointer;
    font-size: 0.6rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
#panel-tabs button:last-child { border-right: none; }
#panel-tabs button.active {
    background: var(--accent);
    color: white;
}

/* Tab content area */
.panel-content {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 12px;
    display: none;
    /* v3.58: explicitly permit vertical panning at the scroll container
       level. Belt-and-braces alongside the touch-action: pan-y on each
       range input, since some mobile browsers (notably iOS Safari) have
       been observed to not propagate touch-action correctly from a range
       input up to its scrollable ancestor unless the ancestor also opts in. */
    touch-action: pan-y;
}
.panel-content.active { display: block; }

/* Variables panel: holds the live physiology graph SVG. */
#panel-vars { display: none; padding: 12px; }
#panel-vars.active { display: block; }
#vg-header { margin-bottom: 4px; }
/* Node styles (used inside the SVG). Only classes that rely on host CSS vars
   live here; the rest is inline on the SVG elements for streaming safety. */
.vg-node-rect { fill: #1a1a1a; stroke: #444; stroke-width: 1; }
.vg-node-label { font-family: inherit; font-size: 8.5px; fill: #aaa; pointer-events: none; }
.vg-node-value { font-family: 'Consolas', monospace; font-size: 12px; fill: #fff; font-weight: 500; pointer-events: none; }
/* v3.32: column header text */
.vg-col-header { font-family: inherit; font-size: 8px; fill: #888; letter-spacing: 1.2px; pointer-events: none; }
/* v3.5: smooth transitions on stroke-width so edges glide as contribution
   changes. 400ms matches the ~250ms render cadence with a little slack. */
.vg-edge-pos, .vg-edge-neg { fill: none; opacity: 0.6; transition: stroke-width 0.4s ease-out; stroke-linejoin: round; stroke-linecap: round; }
.vg-edge-pos { stroke: #3a8; stroke-width: 1.3; }
.vg-edge-neg { stroke: #c64; stroke-width: 1.3; }
/* v3.32: feedback edges (MAP -> tones) drawn dashed and dimmer to distinguish
   from forward CV flow. */
.vg-edge-feedback { opacity: 0.45; stroke-dasharray: 4 3; }

/* === PHYSIOLOGY DASHBOARD MODAL (v4.20) ================================== */
#phys-modal-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.78);
    z-index: 10000;
    align-items: center;
    justify-content: center;
    padding: 20px;
}
#phys-modal-overlay.open { display: flex; }
#phys-modal {
    background: #141414;
    border: 1px solid #444;
    border-radius: 6px;
    color: #ccc;
    width: 100%;
    max-width: 900px;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
#phys-modal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 20px 10px;
    border-bottom: 1px solid #262626;
    flex: 0 0 auto;
}
#phys-modal-head h2 {
    margin: 0;
    font-size: 1.0rem;
    font-weight: 500;
    letter-spacing: 0.5px;
    color: #e4e4e4;
}
#phys-modal-head .sub {
    font-size: 0.6rem;
    color: #666;
    margin-top: 2px;
}
#phys-modal-close {
    background: transparent;
    color: #999;
    border: 1px solid #555;
    width: 28px; height: 28px;
    border-radius: 3px;
    cursor: pointer;
    font-size: 16px;
    line-height: 1;
    flex: 0 0 auto;
}
#phys-modal-close:hover { color: #fff; border-color: #888; }
/* Tab strip */
#phys-tabs {
    display: flex;
    gap: 2px;
    padding: 8px 20px 0;
    border-bottom: 1px solid #262626;
    flex: 0 0 auto;
    overflow-x: auto;
}
#phys-tabs button {
    background: #1e1e1e;
    border: 1px solid #333;
    border-bottom: none;
    color: #999;
    padding: 8px 16px;
    font-size: 0.68rem;
    letter-spacing: 0.4px;
    text-transform: uppercase;
    cursor: pointer;
    border-radius: 4px 4px 0 0;
    white-space: nowrap;
    touch-action: manipulation;
}
#phys-tabs button:hover { color: #ddd; }
#phys-tabs button.active {
    background: var(--accent);
    color: #fff;
    border-color: var(--accent);
}
/* Body / panes */
#phys-body {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 16px 20px 20px;
}
.phys-pane { display: none; }
.phys-pane.active { display: block; }
/* Gauge grid: two columns on wide, one on narrow */
.phys-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px 26px;
}
@media (max-width: 640px) { .phys-grid { grid-template-columns: 1fr; } }
.phys-section-label {
    grid-column: 1 / -1;
    font-size: 0.62rem;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    color: #777;
    margin: 10px 0 2px;
    border-top: 1px solid #262626;
    padding-top: 10px;
}
.phys-section-label:first-child { border-top: none; padding-top: 0; margin-top: 0; }
/* A single gauge */
.phys-gauge { display: flex; flex-direction: column; gap: 4px; padding: 4px 0; }
.pg-top { display: flex; justify-content: space-between; align-items: baseline; }
.pg-label { font-size: 0.72rem; color: #ccc; }
.pg-val {
    font-family: 'Consolas', monospace;
    font-size: 0.82rem;
    color: #fff;
    font-weight: 500;
}
.pg-val .pg-unit { font-size: 0.6rem; color: #888; margin-left: 3px; font-weight: 400; }
.pg-row { display: flex; align-items: center; gap: 8px; }
.pg-track {
    position: relative;
    flex: 1 1 auto;
    height: 12px;
    background: #222;
    border-radius: 3px;
    overflow: hidden;
}
.pg-fill {
    position: absolute;
    top: 0; left: 0; bottom: 0;
    width: 0%;
    background: var(--accent);
    border-radius: 3px 0 0 3px;
    transition: width 0.35s ease-out, background-color 0.35s;
}
.pg-fill.warn   { background: #d9a520; }
.pg-fill.danger { background: #d24545; }
/* v4.34: the numeric readout carries the status colour as well as the bar.
   A gauge in trouble at the LOW end (circulating volume 0.5 L, cardiac output
   0.9 L/min) has almost no bar left to colour - a 6%-wide red sliver is easy
   to miss, which is most of why low-side danger read as "not changing colour"
   even on the gauges that did have a floor threshold. */
.pg-val.warn   .pg-num { color: #e8bd4a; }
.pg-val.danger .pg-num { color: #e86a6a; }
/* Baseline tick: a vertical marker at the resting value */
.pg-base {
    position: absolute;
    top: -2px; bottom: -2px;
    width: 2px;
    background: #cfcfcf;
    opacity: 0.85;
    transform: translateX(-1px);
    pointer-events: none;
}
.pg-spark {
    flex: 0 0 auto;
    width: 88px;
    height: 22px;
    display: block;
}
.pg-spark polyline { fill: none; stroke: #5a9bd8; stroke-width: 1.2; }
.pg-spark line { stroke: #444; stroke-width: 1; stroke-dasharray: 2 2; }
/* Pathways tab holds the influence graph SVG at full width */
#phys-pane-pathways .vg-hint {
    font-size: 0.62rem; color: #666; margin: 0 0 8px;
}

/* === RESOURCES MODAL (v4.40) =============================================
   Opens via the RESOURCES brand-bar button. A flat list of student-facing
   PDFs/videos/links, grouped by type. Same overlay/head/close chrome as the
   Physiology modal above; no tabs since the list is small and flat. */
#resources-modal-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.78);
    z-index: 10000;
    align-items: center;
    justify-content: center;
    padding: 20px;
}
#resources-modal-overlay.open { display: flex; }
#resources-modal {
    background: #141414;
    border: 1px solid #444;
    border-radius: 6px;
    color: #ccc;
    width: 100%;
    max-width: 640px;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
#resources-modal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 20px 10px;
    border-bottom: 1px solid #262626;
    flex: 0 0 auto;
}
#resources-modal-head h2 {
    margin: 0;
    font-size: 1.0rem;
    font-weight: 500;
    letter-spacing: 0.5px;
    color: #e4e4e4;
}
#resources-modal-head .sub {
    font-size: 0.6rem;
    color: #666;
    margin-top: 2px;
}
#resources-modal-close {
    background: transparent;
    color: #999;
    border: 1px solid #555;
    width: 28px; height: 28px;
    border-radius: 3px;
    cursor: pointer;
    font-size: 16px;
    line-height: 1;
    flex: 0 0 auto;
}
#resources-modal-close:hover { color: #fff; border-color: #888; }
#resources-body {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 6px 20px 20px;
}
.res-empty {
    color: #777;
    font-size: 0.8rem;
    padding: 20px 0;
    text-align: center;
}
.res-group-label {
    font-size: 0.62rem;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    color: #777;
    margin: 14px 0 6px;
    border-top: 1px solid #262626;
    padding-top: 12px;
}
.res-group-label:first-child { border-top: none; padding-top: 0; margin-top: 0; }
.res-item {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 8px 4px;
    border-radius: 4px;
    text-decoration: none;
    color: inherit;
}
.res-item:hover { background: #1c1c1c; }
.res-icon {
    flex: 0 0 auto;
    width: 26px; height: 26px;
    border-radius: 4px;
    background: #222;
    color: #999;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.6rem;
    font-weight: 600;
    letter-spacing: 0.2px;
}
.res-item:hover .res-icon { background: var(--accent); color: #fff; }
.res-text { flex: 1 1 auto; min-width: 0; }
.res-title { font-size: 0.82rem; color: #ddd; font-weight: 500; }
.res-item:hover .res-title { color: #fff; text-decoration: underline; }
.res-desc { font-size: 0.68rem; color: #888; margin-top: 2px; }

/* === SCENARIO BRIEFING MODAL (v3.6) ===================================== */
#scenario-briefing-modal {
    display: none;                    /* shown via JS */
    position: fixed;
    inset: 0;                          /* full viewport */
    background: rgba(0,0,0,0.75);
    z-index: 1000;
    align-items: center;
    justify-content: center;
    padding: 20px;
}
#scenario-briefing-modal.visible { display: flex; }
#sbm-card {
    background: #1a1a1a;
    border: 1px solid #444;
    border-radius: 8px;
    max-width: 540px;
    width: 100%;
    max-height: 90vh;
    overflow-y: auto;
    padding: 22px 26px;
    box-shadow: 0 4px 24px rgba(0,0,0,0.7);
}
#sbm-title {
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--accent);
    margin: 0 0 14px;
}
#sbm-description {
    font-size: 0.92rem;
    line-height: 1.5;
    color: #ddd;
    margin: 0 0 16px;
}
#sbm-objectives-heading {
    font-size: 0.85rem;
    font-weight: 600;
    color: #aaa;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin: 0 0 8px;
}
#sbm-objectives {
    margin: 0 0 22px 18px;
    padding: 0;
    color: #ddd;
    font-size: 0.9rem;
    line-height: 1.55;
}
#sbm-objectives li { margin-bottom: 4px; }
#sbm-start {
    background: #336;
    color: #fff;
    border: 1px solid #99c;
    padding: 8px 18px;
    font-size: 0.95rem;
    border-radius: 4px;
    cursor: pointer;
    width: 100%;
}
#sbm-start:hover { background: #449; }

.config-item {
    display: flex;
    justify-content: space-between;
    border-bottom: 1px solid #222;
    padding: 3px 0;
    font-family: monospace;
}
.config-header {
    color: var(--accent);
    font-weight: bold;
    margin-top: 10px;
    border-bottom: 1px solid #444;
    padding-bottom: 2px;
    text-transform: uppercase;
    font-size: 0.7rem;
    letter-spacing: 0.5px;
}

/* Config tab styling: grouped sections with labelled rows of buttons */
.config-section { margin-bottom: 18px; }
.config-section-label {
    font-size: 0.6rem;
    color: #888;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    margin-bottom: 6px;
}
.config-row {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}
.cfg-btn {
    flex: 1 1 auto;
    min-width: 60px;
    padding: 6px 8px;
    font-size: 0.65rem;
    background: #222;
    color: #ccc;
    border: 1px solid #444;
    border-radius: 2px;
    cursor: pointer;
    text-align: center;
    font-family: inherit;
}
.cfg-btn:hover { background: #2a2a2a; border-color: #666; }
.cfg-btn.active { background: var(--accent); color: #fff; border-color: #fff; }
/* Profile buttons get a slightly different active colour */
#panel-config .cfg-btn[id^="pr-"].active { background: #336; border-color: #99c; }

#panel-config #scenarioSelect {
    padding: 5px 8px;
    font-size: 0.65rem;
    background: #222;
    border: 1px solid #444;
    color: #ccc;
    cursor: pointer;
    border-radius: 2px;
    font-family: inherit;
}
#panel-config #scenarioSelect option { background: #222; color: #ccc; }

/* Log panel specifics */
#log-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
    font-family: monospace;
    font-size: 0.68rem;
}
.log-entry {
    padding: 4px 6px;
    border-left: 2px solid #333;
    background: #111;
    display: flex;
    gap: 8px;
}
.log-entry .ts {
    color: #888;
    flex: 0 0 55px;
}
.log-entry .msg {
    color: #9f9;
    flex: 1 1 auto;
    word-break: break-word;
}
#log-clear {
    margin-top: 10px;
    padding: 5px;
    width: 100%;
    background: #2a2a2a;
    color: #ccc;
    border: 1px solid #444;
    cursor: pointer;
    border-radius: 2px;
}

/* PK/PD reference table */
.pk-table {
    width: 100%;
    border-collapse: collapse;
    font-family: monospace;
    font-size: 0.65rem;
    margin-top: 8px;
}
.pk-table th, .pk-table td {
    border-bottom: 1px solid #222;
    padding: 3px 4px;
    text-align: left;
}
.pk-table th {
    color: var(--accent);
    border-bottom: 1px solid #444;
    background: #0a0a0a;
    position: sticky;
    top: 0;
}
.pk-note {
    color: #999;
    font-size: 0.65rem;
    font-style: italic;
    margin: 6px 0 4px 0;
}

/* (v3.23: removed orphan .status-bar styles - log is rendered inside the
   panel-log tab, not as a fixed-position bar.) */

/* === ANIMATIONS ============================================================ */
.cuff-inflating { animation: pulse 1s infinite; }
@keyframes pulse { 50% { background: #112233; } }

/* Alarm visuals: medium (yellow, slow) and high (red, fast) flashing */
@keyframes alarmMed  { 0%, 100% { background: transparent; } 50% { background: #665a00; } }
@keyframes alarmHigh { 0%, 100% { background: transparent; } 50% { background: #882211; } }
.alarm-med  { animation: alarmMed  1s infinite; }
.alarm-high { animation: alarmHigh 0.5s infinite; }


.hide { display: none !important; }

/* === RESPONSIVE ============================================================ */
@media (max-width: 1100px) {
    #controls { grid-template-columns: 1fr 1fr; }
    #controls > .col:nth-child(3) { grid-column: span 2; border-right: none; border-top: 1px solid var(--divider); }
    .drug-grid { grid-template-columns: repeat(3, 1fr); }
}
/* v3.12: mobile / touch devices.
   - Single-column drug controls
   - Monitor: waveforms on top (most space), numerics row below (compact)
   - #waveforms gets an explicit grid row height so canvas has somewhere to draw. */
@media (max-width: 900px), (pointer: coarse) {
    #main-row {
        height: 60vh;       /* a bit more vertical so both waveforms + numerics fit */
    }
    #monitor {
        grid-template-columns: 1fr;
        grid-template-rows: 1fr auto;     /* waveforms grow, numerics natural */
        height: 100%;
    }
    #waveforms {
        min-height: 0;       /* allow grid row to shrink if needed */
        height: 100%;
    }
    #numerics {
        border-left: none;
        border-top: 2px solid #222;
        flex-direction: row;
        flex-wrap: wrap;
        gap: 4px;
        padding: 4px;
    }
    /* Compact numeric boxes on mobile so they wrap into rows */
    #numerics .box {
        flex: 1 1 calc(33% - 4px);
        min-width: 100px;
        height: 40px;
        padding-right: 6px;
    }
    #controls {
        grid-template-columns: 1fr;
    }
    #controls > .col {
        border-right: none;
        border-bottom: 1px solid var(--divider);
    }
}
