/**
 * Report Builder
 * Dark/Light Theme with Toggle Support
 * 
 * Copyright © 2026-2027 SamshawKSE Ltd. All rights reserved.
 * Unauthorised use, copying, or distribution is strictly prohibited.
 * 
 * Version: 9.0
 * Build: 2026-02-09 v9.0 — color-mix() derived hue system
 * 
 * COLOR SCHEME: Clinical Mono
 * 
 *   Hue 0  Background     Grey scale
 *   Hue 1  Interactive    Teal
 *   Hue 2  Attention      Grey
 *   Hue 3  Auto           Ochre > Teal
 *   Hue 4  Normal         Green
 *   Hue 5  Warning        Red
 *   Hue 6  Beta           Purple
 *
 *   THEMING: Change the 5 base hues (--h1 to --h5) per theme.
 *   All derivatives (hover, bg, border, glow) are auto-derived via
 *   color-mix(). Opacity percentages are tuned per theme and stay fixed.
 *
 *   v8.11: Refactored H1–H5 to color-mix() derived system
 *          Base hues define each family; derivatives cascade automatically
 *          10 knobs total (5 dark + 5 light) control all hue-derived colors
 *   v8.10: Removed 25 dead/duplicate/alias variables (112 → 89)
 *          Collapsed semantic alias layer → hue-based variables (89 → 44)
 *          Merged: span-fixed→parameter, span-manual→dirty, span-summary→parameter
 *          Moved: calculated outputs from H2 (grey) → H3 (teal)
 *          Pivoted H1 from steel blue to pure grey (Clinical Mono)
 *          Fixed: --text-muted → --text-tertiary (was undefined)
 */

/* ============================================================================
   CLINICAL MONO THEME
   Optimised for extended use in dimly lit radiology environments
   6-hue semantic colour system: Background, Interactive, Attention, Auto,
   Normal, Abnormal
   ============================================================================ */

:root {
    /* ========================================================================
       GREY SCALE (8) — The foundation
       ======================================================================== */
    
    --grey-base: #0a0a0a;                    /* Page background - near black */
    --grey-surface: #111111;                 /* Panels, cards */
    --grey-elevated: #1a1a1a;                /* Headers, modals, hover states */
    --grey-border: #2a2a2a;                  /* Subtle borders */
    --grey-border-strong: #3a3a3a;           /* Emphasized borders */
    --grey-muted: #505050;                   /* Disabled, tertiary text */
    --grey-text: #787878;                    /* Secondary text, labels */
    --grey-bright: #b0b0b0;                  /* Primary text - soft, not white */
    
    /* ========================================================================
       BASE HUES — Change these 5 values to re-theme (dark mode)
       All derivatives below are auto-derived via color-mix().
       ======================================================================== */
    
    --h1: #567659;                           /* Interactive */
    --h2: #909090;                           /* Attention */
    --h3: #567659;                           /* Auto - previously #a37c0a */
    --h4: #5aaa64;                           /* Normal */
    --h5: #a13b3b;                           /* Abnormal */

    /* ========================================================================
       H1: INTERACTIVE — derived from --h1 (8)
       Buttons, focus rings, parameter/fixed/summary spans, embedded,
       secondary button bg
       ======================================================================== */
    
    --interactive:          var(--h1);
    --interactive-hover:    color-mix(in srgb, var(--h1) 88%, black);
    --interactive-dim:      color-mix(in srgb, var(--h1) 31%, black);  /* measurement highlight headers */
    --interactive-subtle:   color-mix(in srgb, var(--h1)  8%, transparent);
    --interactive-muted:    color-mix(in srgb, var(--h1) 14%, transparent);
    --interactive-glow:     color-mix(in srgb, var(--h1) 22%, transparent);
    --interactive-neutral:  color-mix(in srgb, var(--h1) 48%, black);  /* secondary button bg */
    --interactive-neutral-hover: color-mix(in srgb, var(--h1) 45%, black);
    
    /* ========================================================================
       H2: ATTENTION — derived from --h2
       Dirty spans, manual spans, empty embedded measurements
       ======================================================================== */
    
    --attention-dim:     color-mix(in srgb, var(--h2) 10%, transparent);
    --attention-muted:     color-mix(in srgb, var(--h2) 12%, transparent);
    --attention-border:    color-mix(in srgb, var(--h2) 28%, transparent);
    --attention-btn:       color-mix(in srgb, var(--h2) 45%, black);  /* H2 button bg */
    --attention-btn-hover: color-mix(in srgb, var(--h2) 45%, black);
    --attention-glow:      color-mix(in srgb, var(--h2) 22%, transparent);
    --attention-strong:    color-mix(in srgb, var(--h1) 45%, transparent);
    
    /* ========================================================================
       H3: AUTO — derived from --h3
       Algorithm spans, calculated outputs, calc inputs
       ======================================================================== */
    
    --auto:       var(--h3);
    --auto-hover: color-mix(in srgb, var(--h3) 88%, black);
    --auto-faint: color-mix(in srgb, var(--h3)  3%, transparent);
    --auto-subtle:color-mix(in srgb, var(--h3)  7%, transparent);
    --auto-muted: color-mix(in srgb, var(--h3) 25%, transparent);
    --auto-medium:color-mix(in srgb, var(--h3) 30%, transparent);
    --auto-glow:  color-mix(in srgb, var(--h3) 35%, transparent);
    --auto-strong:color-mix(in srgb, var(--h3) 45%, transparent);
    
    /* ========================================================================
       H4: NORMAL — derived from --h4
       Reference range: within normal limits
       ======================================================================== */
    
    --normal-bg:     color-mix(in srgb, var(--h4) 20%, transparent);
    --normal-border: color-mix(in srgb, var(--h4) 45%, transparent);
    
    /* ========================================================================
       H5: ABNORMAL — derived from --h5
       Reference range: outside normal limits, errors
       ======================================================================== */
    
    --status-error:        var(--h5);
    --abnormal-bg:     color-mix(in srgb, var(--h5) 22%, transparent);
    --abnormal-border: color-mix(in srgb, var(--h5) 45%, transparent);
    
    /* ========================================================================
       H5: CHECK — derived from --h5
       Check-algorithm mismatch highlighting (parameter ≠ algorithm recommendation)
       ======================================================================== */
    
    --check:       var(--h5);
    --check-hover: color-mix(in srgb, var(--h5) 88%, black);
    --check-faint: color-mix(in srgb, var(--h5)  20%, transparent);
    --check-subtle:color-mix(in srgb, var(--h5)  25%, transparent);
    --check-muted: color-mix(in srgb, var(--h5) 40%, transparent);
    --check-medium:color-mix(in srgb, var(--h5) 50%, transparent);
    --check-glow:  color-mix(in srgb, var(--h5) 60%, transparent);
    --check-strong:color-mix(in srgb, var(--h5) 70%, transparent);
    
    /* ========================================================================
       THEME-DEPENDENT MAPPINGS (4)
       Grey-scale step changes between dark/light
       ======================================================================== */
    
    --bg-surface-hover: var(--grey-elevated);
    --bg-modal-header: var(--grey-elevated);
    --bg-input: var(--grey-surface);
    --bg-input-focus: var(--grey-elevated);
    
    /* ========================================================================
       FIXED VALUES (3)
       ======================================================================== */
    
    --text-inverse: #ffffff;
    --modal-backdrop: rgba(0, 0, 0, 0.80);
    --modal-backdrop-light: rgba(0, 0, 0, 0.70);
    
    /* ========================================================================
       LAYOUT & SIZING
       ======================================================================== */
    
    --element-height: 32px;
    --border-radius-sm: 4px;
    --border-radius: 6px;
    --border-radius-lg: 8px;
    --border-width: 1px;
    --outline-width: 2px;
    --transition-fast: 0.1s ease;
    --transition: 0.15s ease;
    
    /* ========================================================================
       TYPOGRAPHY
       ======================================================================== */
    
    --font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    --font-family-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
    --line-height: 1.5;
    --font-weight-normal: 400;
    --font-weight-medium: 500;
    --font-weight-bold: 600;
}


/* ============================================================================
   LIGHT MODE THEME
   ============================================================================ */

[data-theme="light"] {
    /* Grey scale — inverted for light */
    --grey-base: #f0f0f0;
    --grey-surface: #fafafa;
    --grey-elevated: #ffffff;
    --grey-border: #d8d8d8;
    --grey-border-strong: #c0c0c0;
    --grey-muted: #a0a0a0;
    --grey-text: #808080;
    --grey-bright: #2a2a2a;
    
    /* ========================================================================
       BASE HUES — Change these 5 values to re-theme (light mode)
       Opacity percentages are lower than dark mode because the same alpha
       is more prominent against light backgrounds.
       ======================================================================== */
    
    --h1: #69916e;                           /* Interactive */
    --h2: #6a6a6a;                           /* Attention */
    --h3: #69916e;                           /* Auto - previously #a37c0a*/
    --h4: #7cd486;                           /* Normal */
    --h5: #c76b6b;                           /* Abnormal */

    /* H1: Interactive — light mode derivatives */
    --interactive-hover:    color-mix(in srgb, var(--h1) 90%, black);
    --interactive-dim:      color-mix(in srgb, var(--h1) 23%, white);  /* light tint for headers */
    --interactive-subtle:   color-mix(in srgb, var(--h1)  4%, transparent);
    --interactive-muted:    color-mix(in srgb, var(--h1)  8%, transparent);
    --interactive-glow:     color-mix(in srgb, var(--h1) 14%, transparent);
    --interactive-neutral:  color-mix(in srgb, var(--h1) 60%, black);  /* secondary button bg */
    --interactive-neutral-hover: color-mix(in srgb, var(--h1) 46%, black);
    
    /* H2: Attention — light mode derivatives */
    --attention-dim:     color-mix(in srgb, var(--h2) 5%, transparent);
    --attention-muted:     color-mix(in srgb, var(--h2)  6%, transparent);
    --attention-border:    color-mix(in srgb, var(--h2) 16%, transparent);
    --attention-btn:       color-mix(in srgb, var(--h2) 85%, black);  /* H2 button bg */
    --attention-btn-hover: color-mix(in srgb, var(--h2) 46%, black);
    --attention-glow:      color-mix(in srgb, var(--h2) 14%, transparent);
    --attention-strong:    color-mix(in srgb, var(--h1) 30%, transparent);
    
    /* H3: Auto — light mode derivatives */
    --auto-hover: color-mix(in srgb, var(--h3) 88%, black);
    --auto-faint: color-mix(in srgb, var(--h3)  2%, transparent);
    --auto-subtle:color-mix(in srgb, var(--h3)  6%, transparent);
    --auto-muted: color-mix(in srgb, var(--h3) 12%, transparent);
    --auto-medium:color-mix(in srgb, var(--h3) 14%, transparent);
    --auto-glow:  color-mix(in srgb, var(--h3) 20%, transparent);
    --auto-strong:color-mix(in srgb, var(--h3) 30%, transparent);
    
    /* H4/H5: Reference ranges — light mode derivatives */
    --normal-bg:     color-mix(in srgb, var(--h4) 14%, transparent);
    --normal-border: color-mix(in srgb, var(--h4) 35%, transparent);
    --abnormal-bg:     color-mix(in srgb, var(--h5) 16%, transparent);
    --abnormal-border: color-mix(in srgb, var(--h5) 35%, transparent);
    
    /* H5: Check — light mode derivatives */
    --check-hover: color-mix(in srgb, var(--h5) 88%, black);
    --check-faint: color-mix(in srgb, var(--h5)  15%, transparent);
    --check-subtle:color-mix(in srgb, var(--h5)  20%, transparent);
    --check-muted: color-mix(in srgb, var(--h5) 30%, transparent);
    --check-medium:color-mix(in srgb, var(--h5) 40%, transparent);
    --check-glow:  color-mix(in srgb, var(--h5) 50%, transparent);
    --check-strong:color-mix(in srgb, var(--h5) 60%, transparent);
    
    /* Theme-dependent mappings */
    --bg-surface-hover: var(--grey-base);
    --bg-modal-header: var(--grey-surface);
    --bg-input: var(--grey-elevated);
    --bg-input-focus: var(--grey-surface);
    
    /* Fixed overrides */
    --modal-backdrop: rgba(0, 0, 0, 0.5);
    --modal-backdrop-light: rgba(0, 0, 0, 0.4);
}

/* Light mode element overrides */
[data-theme="light"] select {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23666666' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
}

[data-theme="light"] select:focus {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23888888' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
}

/* Light mode: Secondary buttons need white text */
[data-theme="light"] button.secondary,
[data-theme="light"] .icon-button.secondary,
[data-theme="light"] .add-snippet-button,
[data-theme="light"] .inline-delete-button,
[data-theme="light"] #new-report-button {
    color: var(--text-inverse) !important;
}

[data-theme="light"] button.secondary svg,
[data-theme="light"] .icon-button.secondary svg,
[data-theme="light"] .add-snippet-button svg,
[data-theme="light"] .inline-delete-button svg {
    stroke: var(--text-inverse) !important;
}

/* ============================================================================
   SNIPPET PLACEHOLDERS (v8.0)
   Hidden during render - processed by insertTemplateSnippets()
   ============================================================================ */

.snippet-placeholder {
    display: none !important;
}

/* ============================================================================
   SNIPPETS PANEL (v7.3)
   ============================================================================ */

/* Add snippet button - attention/grey hue */
.add-snippet-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--element-height);
    height: var(--element-height);
    min-width: var(--element-height);
    padding: 0;
    margin: 0;
    flex-shrink: 0;
    background-color: var(--attention-btn);
    border: var(--border-width) solid var(--attention-btn);
    border-radius: var(--border-radius);
    color: var(--text-inverse);
    cursor: pointer;
    transition: background-color var(--transition),
                border-color var(--transition);
}

.add-snippet-button:hover {
    background-color: var(--attention-btn-hover);
    border-color: var(--attention-btn-hover);
}

.add-snippet-button:focus {
    outline: none;
    box-shadow: 0 0 0 var(--outline-width) var(--interactive-glow);
}

.add-snippet-button.active {
    background-color: var(--attention-btn-hover);
    border-color: var(--attention-btn-hover);
}

.add-snippet-button svg {
    stroke: var(--text-inverse);
}

/* Icon toggle - show plus when closed, X when open */
.add-snippet-button .icon-plus {
    display: block;
}

.add-snippet-button .icon-close {
    display: none;
}

.add-snippet-button.active .icon-plus {
    display: none;
}

.add-snippet-button.active .icon-close {
    display: block;
}

/* Snippets panel - overlays measurements panel only */
.snippets-panel {
    display: none;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: var(--grey-surface);
    border-radius: var(--border-radius-lg);
    z-index: 100;
    flex-direction: column;
    overflow: hidden;
}

.snippets-panel.active {
    display: flex;
}

.snippets-panel-header {
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    padding: 0.75rem 1rem;
    background-color: var(--grey-elevated);
    border-bottom: var(--border-width) solid var(--grey-border);
    flex-shrink: 0;
}

.snippets-panel-header h3 {
    margin: 0;
    font-size: 1rem;
    font-weight: var(--font-weight-medium);
    color: var(--grey-bright);
    text-align: center;
}

.snippets-panel-close {
    position: absolute;
    right: 0.75rem;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    background: transparent;
    border: none;
    border-radius: var(--border-radius);
    color: var(--grey-text);
    cursor: pointer;
    font-size: 1.25rem;
    line-height: 1;
    transition: background-color var(--transition), color var(--transition);
}

.snippets-panel-close:hover {
    background-color: var(--bg-surface-hover);
    color: var(--grey-bright);
}

.snippets-panel-content {
    flex: 1;
    overflow-y: auto;
    padding: 0.5rem;
}

/* Snippet items - simple cards with highlight color */
.snippet-item {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0.5rem 0.75rem;
    margin-bottom: 0.5rem;
    background-color: var(--bg-surface-hover);
    border: var(--border-width) solid var(--grey-border);
    border-radius: var(--border-radius);
    cursor: grab;
    transition: background-color var(--transition),
                border-color var(--transition),
                box-shadow var(--transition),
                transform var(--transition);
}

.snippet-item:hover {
    background-color: var(--grey-elevated);
    border-color: var(--grey-border-strong);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
    transform: translateY(-1px);
}

.snippet-item:active {
    cursor: grabbing;
    transform: translateY(0);
}

.snippet-item-name {
    font-size: 0.85rem;
    font-weight: var(--font-weight-normal);
    color: var(--grey-bright);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    text-align: center;
}

/* Snippet being dragged */
.snippet-item.snippet-dragging {
    opacity: 0.5;
    box-shadow: 0 0 0 2px var(--interactive-glow);
}

/* Empty state */
.snippets-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 2rem;
    text-align: center;
    color: var(--grey-text);
}

.snippets-empty-icon {
    font-size: 2rem;
    margin-bottom: 0.5rem;
    opacity: 0.5;
}

/* Make measurements panel position relative for overlay positioning */
#measurements-panel {
    position: relative;
}

/* ============================================================================
   THEME TOGGLE BUTTON
   ============================================================================ */

.theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--element-height);
    height: var(--element-height);
    min-width: var(--element-height);
    padding: 0;
    margin: 0;
    flex-shrink: 0;
    background-color: var(--grey-elevated);
    border: var(--border-width) solid var(--grey-border);
    border-radius: var(--border-radius);
    color: var(--grey-text);
    cursor: pointer;
    transition: background-color var(--transition),
                border-color var(--transition),
                color var(--transition);
}

.theme-toggle:hover {
    background-color: var(--bg-surface-hover);
    border-color: var(--grey-border-strong);
    color: var(--grey-bright);
}

.theme-toggle:focus {
    outline: none;
    box-shadow: 0 0 0 var(--outline-width) var(--interactive-glow);
}

.theme-toggle svg {
    width: 18px;
    height: 18px;
    stroke: currentColor;
    fill: none;
    transition: transform 0.3s ease;
}

/* Sun icon (shown in dark mode) */
.theme-toggle .icon-sun {
    display: block;
}

.theme-toggle .icon-moon {
    display: none;
}

/* Moon icon (shown in light mode) */
[data-theme="light"] .theme-toggle .icon-sun {
    display: none;
}

[data-theme="light"] .theme-toggle .icon-moon {
    display: block;
}


/* ============================================================================
   BASE STYLES
   ============================================================================ */

*,
*::before,
*::after {
    box-sizing: border-box;
    background-repeat: no-repeat;
}

html {
    font-family: var(--font-family);
    font-size: 100%;
    line-height: var(--line-height);
    color: var(--grey-bright);
    background-color: var(--grey-base);
    -webkit-text-size-adjust: 100%;
    -webkit-tap-highlight-color: transparent;
}

body {
    margin: 0;
    padding: 0;
    background-color: var(--grey-base);
    color: var(--grey-bright);
    position: relative;
}

/* v8.5: Texture overlay removed — was causing rendering flickers in some browsers */

html, body {
    height: 100%;
    overflow: hidden;
}

main {
    display: block;
    position: relative;
    z-index: 1;
}

main.container {
    height: 100%;
    padding: 0;
    max-width: none;
}

/* Custom Scrollbar - Dark Theme */
::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}

::-webkit-scrollbar-track {
    background: var(--grey-surface);
}

::-webkit-scrollbar-thumb {
    background: var(--grey-border);
    border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
    background: var(--grey-border-strong);
}

/* Selection */
::selection {
    background-color: var(--interactive-glow);
}


/* ============================================================================
   TYPOGRAPHY
   ============================================================================ */

h1, h2, h3, h4, h5, h6 {
    margin-top: 0;
    margin-bottom: 0.75rem;
    font-weight: var(--font-weight-bold);
    line-height: 1.25;
    color: var(--grey-bright);
}

h2 {
    font-size: 1.5rem;
}

h3 {
    font-size: 1.25rem;
}

hr {
    height: 0;
    border: 0;
    border-top: var(--border-width) solid var(--grey-border);
    color: inherit;
}


/* ============================================================================
   CONTAINER
   ============================================================================ */

.container {
    width: 100%;
    margin-right: auto;
    margin-left: auto;
    padding-right: 1rem;
    padding-left: 1rem;
}


/* ============================================================================
   BUTTONS
   ============================================================================ */

button {
    margin: 0;
    padding: 0.5rem 1rem;
    height: var(--element-height);
    font-family: inherit;
    font-size: 0.9rem;
    font-weight: var(--font-weight-normal);
    line-height: var(--line-height);
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    user-select: none;
    border: var(--border-width) solid var(--interactive);
    border-radius: var(--border-radius);
    background-color: var(--interactive);
    color: var(--text-inverse);
    transition: background-color var(--transition),
                border-color var(--transition),
                color var(--transition),
                box-shadow var(--transition);
}

button:hover {
    background-color: var(--interactive-hover);
    border-color: var(--interactive-hover);
}

button:focus {
    outline: none;
    box-shadow: 0 0 0 var(--outline-width) var(--interactive-glow);
}

button:active {
    background-color: var(--interactive-hover);
}

button:disabled,
button[disabled] {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Secondary buttons (grey) */
button.secondary {
    background-color: var(--interactive-neutral);
    border-color: var(--interactive-neutral);
    color: var(--grey-bright);
}

button.secondary:hover {
    background-color: var(--interactive-neutral-hover);
    border-color: var(--interactive-neutral-hover);
}

button.secondary:focus {
    box-shadow: 0 0 0 var(--outline-width) var(--interactive-glow);
}


/* ============================================================================
   FORM ELEMENTS - Inputs, Selects, Textareas
   ============================================================================ */

input,
select,
textarea {
    margin: 0;
    padding: 0.5rem 0.75rem;
    font-family: inherit;
    font-size: 1rem;
    font-weight: var(--font-weight-normal);
    line-height: var(--line-height);
    color: var(--grey-bright);
    background-color: var(--bg-input);
    border: var(--border-width) solid var(--grey-border);
    border-radius: var(--border-radius);
    outline: none;
    transition: background-color var(--transition),
                border-color var(--transition),
                color var(--transition),
                box-shadow var(--transition);
}

input:focus,
select:focus,
textarea:focus {
    background-color: var(--bg-input-focus);
    border-color: var(--interactive);
    box-shadow: 0 0 0 var(--outline-width) var(--interactive-glow);
}

input::placeholder,
textarea::placeholder {
    color: var(--grey-muted);
    opacity: 1;
}

input:disabled,
select:disabled,
textarea:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Select specific - dark dropdown arrow */
select {
    padding-right: 2rem;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23a0a0a0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
    background-position: right 0.5rem center;
    background-size: 1rem auto;
    background-repeat: no-repeat;
    appearance: none;
}

select:focus {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23787878' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
}

/* All selects match button height */
select {
    height: var(--element-height);
    font-size: 0.85rem;
    padding: 0 2rem 0 0.5rem;
    line-height: var(--element-height);
}

/* Textarea specific */
textarea {
    display: block;
    width: 100%;
    resize: vertical;
}

/* Input type=text specific */
input[type="text"] {
    width: 100%;
}


/* ============================================================================
   CHECKBOX - Dark Theme
   ============================================================================ */

input[type="checkbox"] {
    width: 1.25rem;
    height: 1.25rem;
    padding: 0;
    border-radius: var(--border-radius-sm);
    background-color: var(--bg-input);
    border-color: var(--grey-border);
    cursor: pointer;
    appearance: none;
    position: relative;
}

/* v10.x: Active-state checkbox — green tick on the same dark/light fill
   as the unchecked state, with a green border. The tick + border do all
   the "active" signalling; the box itself stays the same colour as when
   unchecked so the change is restrained.

   Global: this rule targets every native checkbox in the app (no class
   scoping). The SVG stroke is hardcoded #69916e (light-mode --h1 value)
   because data: URLs can't reference CSS variables; it reads on both
   dark and light surfaces. If you ever want it theme-adaptive, swap to
   a ::after pseudo-element with mask-image driven by var(--interactive). */
input[type="checkbox"]:checked {
    background-color: var(--bg-input);
    border-color: var(--interactive);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2369916e' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
    background-position: center;
    background-size: 0.75rem auto;
    background-repeat: no-repeat;
}

/* v10.x: Focus glow removed per UX feedback — too distracting on the small
   checkboxes that fire on every modal/popover interaction. Native browser
   focus outline is also suppressed by the base `button:focus { outline: none }`
   that doesn't apply here, but appearance: none on the checkbox means no
   default focus indicator either. Keyboard users currently get no focus
   cue; revisit with :focus-visible + subtler indicator if accessibility
   becomes a concern. */
input[type="checkbox"]:focus {
    box-shadow: none;
}


/* ============================================================================
   LABELS
   ============================================================================ */

label {
    display: block;
    margin-bottom: 0.25rem;
    font-weight: var(--font-weight-medium);
    color: var(--grey-bright);
}


/* ============================================================================
   TABLES
   ============================================================================ */

table {
    width: 100%;
    border-collapse: collapse;
    border-spacing: 0;
    text-align: left;
}

th,
td {
    padding: 0.5rem;
    border-bottom: var(--border-width) solid var(--grey-border);
}

th {
    font-weight: var(--font-weight-bold);
    text-align: left;
    color: var(--grey-bright);
}


/* ============================================================================
   TWO-COLUMN LAYOUT
   ============================================================================ */

/* v9.02: Options wrapper — flex column: toolbar above, grid below */
#options {
    height: 100%;
}

.options-wrapper {
    display: flex;
    flex-direction: column;
    height: 100%;
}

.two-column-layout {
    display: grid;
    grid-template-columns: 330px 1fr 330px; /* v11 5.1: review pane is permanent */
    gap: 1rem;
    flex: 1;
    min-height: 0;
    /* v11 5.1: top padding restored now the cross-column toolbar (which used to
       supply it) is gone — the header cards need breathing room from the top. */
    padding: 1rem;
}

.options-wrapper {
    margin: 0 auto;
}

/* v11 5.1: the review pane is permanent, so the layout is always three
   columns. Stay full-width until 1700px, then cap — narrowing shrinks the
   centre column smoothly (no snap, no side-whitespace jump). */
@media (min-width: calc(1700px + 2rem)) {
    .options-wrapper {
        max-width: 1700px;
    }
}


/* ============================================================================
   COLUMN CARDS (v11 5.1) — shared header/body chrome for all three columns.
   Each column (#measurements-panel / #options-panel / #review-panel) is a
   transparent flex wrapper holding a .col-header card and a .col-body card,
   separated by the wrapper's gap (the detached-card layout of
   mockup-5.1-layout.svg). Header height is pinned to one --element-height
   control + padding so the three headers align across columns.
   ============================================================================ */
.col-header {
    flex-shrink: 0;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 0.5rem;
    min-height: calc(var(--element-height) + 0.8rem + 2 * var(--border-width));
    background-color: var(--grey-elevated);
    border: var(--border-width) solid var(--grey-border);
    border-radius: var(--border-radius-lg);
}

.col-body {
    flex: 1;
    min-height: 0;
    position: relative;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background-color: var(--grey-surface);
    border: var(--border-width) solid var(--grey-border);
    border-radius: var(--border-radius-lg);
}


/* ============================================================================
   MEASUREMENTS PANEL (Left Column)
   ============================================================================ */

#measurements-panel {
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow: hidden;
    min-width: 0;
    /* v11 5.1: transparent column wrapper — the header card + body card
       carry their own chrome; the gap creates the detached-card look. */
    gap: 0.5rem;
}

.panel-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    position: sticky;
    top: 0;
    background: var(--grey-elevated);
    z-index: 10;
    padding: 0.75rem 1rem;
    border-bottom: var(--border-width) solid var(--grey-border);
    flex-shrink: 0;
}

.panel-header h2 {
    margin: 0;
    font-size: 1.1rem;
    color: var(--grey-bright);
}

.panel-header button {
    margin: 0;
    height: var(--element-height);
    padding: 0 0.8rem;
    font-size: 0.8rem;
}

#measurements-table {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 0 0.5rem 0.5rem 0.5rem;
    min-width: 0;
}

/* v11 5.1: Measurements header card — centred Import button (col 2) + the
   subtle Expand-all/Collapse-all toggle (col 3). Sits above #measurements-table
   (outside the scroll area) so it never overlaps section headers. */
/* v11 5.1: .col-header supplies the flex layout + card chrome. The expand-all
   toggle sits on the left; the Import button fills the rest of the header
   (mirroring Auto in the review header). */
#measurements-panel-bar {
    gap: 0.4rem;
}

/* v11 5.1: Import button — fills the measurements header beside the toggle.
   Flex-centres its label (the base button's line-height would otherwise sit
   the text low in the fixed height, as with #finalise-report / #review-auto). */
#measurements-panel-bar #open-import-modal {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 1;
    height: var(--element-height);
    margin: 0;
}

#measurements-expand-all {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    color: var(--grey-text);
    padding: 0.15rem;
    cursor: pointer;
    border-radius: var(--border-radius-sm);
    transition: color 0.15s ease, background-color 0.15s ease;
}

#measurements-expand-all:hover {
    color: var(--grey-bright);
    background-color: var(--grey-elevated);
}

#measurements-expand-all svg {
    display: block;
}


/* ============================================================================
   MEASUREMENTS TABLE
   ============================================================================ */

.measurement-group-header {
    font-size: 0.8rem;
    font-weight: var(--font-weight-medium);
    padding: 0.4rem 0.5rem;
    background-color: var(--grey-elevated);
    border-bottom: var(--border-width) solid var(--grey-border);
    margin-top: 0.5rem;
    margin-left: 0;
    margin-right: 0;
    border-radius: var(--border-radius-sm);
    /* v8.08: Removed sticky positioning - headers now scroll naturally */
    transition: background-color 0.3s ease;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--grey-text);
}

/* Highlighted measurement section header */
.measurement-group-header.highlight-header {
    background-color: var(--attention-glow);
    color: var(--grey-bright);
}

/* Highlighted measurement section rows */
.measurement-group-table.highlight-table tr td {
    background-color: var(--attention-muted);
}

/* v10.11: Collapsible sections. The header is the click target — a rotating
   chevron indicates state; a collapsed header hides its adjacent group table. */
.measurement-group-header {
    cursor: pointer;
    user-select: none;
}

.measurement-group-header::before {
    content: '';
    display: inline-block;
    width: 0.35rem;
    height: 0.35rem;
    margin-right: 0.4rem;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(45deg); /* expanded → chevron points down */
    transition: transform 0.15s ease;
    vertical-align: middle;
    position: relative;
    top: -2px;
}

.measurement-group-header.collapsed::before {
    transform: rotate(-45deg); /* collapsed → chevron points right */
}

.measurement-group-header.collapsed + .measurement-group-table {
    display: none;
}

.measurement-group-table {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
}

.measurement-group-table td:first-child {
    width: 145px;
}

.measurement-group-table td:last-child {
    width: 165px;
}

.measurement-group-table td {
    padding: 0.25rem 0.5rem;
    border-bottom: var(--border-width) solid var(--grey-border);
    font-size: 0.8rem;
    box-sizing: border-box;
    vertical-align: middle;
}

.measurement-label {
    white-space: normal;
    word-wrap: break-word;
    text-align: right;
    color: var(--grey-text);
}

.measurement-value {
    /* v8.08: Removed display:flex from td to fix border alignment with label cell */
    /* Input and unit span flow naturally as inline elements */
    white-space: nowrap;
}

/* Measurement inputs - dark theme specific */
#measurements-table .measurement-group-table input[type="text"].measurement-input,
.measurement-group-table input.measurement-input,
.measurement-input,
input.measurement-input[type="text"] {
    width: 80px !important;
    min-width: 0 !important;
    max-width: 80px !important;
    height: 26px !important;
    padding: 0.2rem 0.4rem !important;
    font-size: 0.8rem !important;
    background-color: var(--bg-input) !important;
    border: var(--border-width) solid var(--grey-border) !important;
    border-radius: var(--border-radius-sm) !important;
    color: var(--grey-bright) !important;
    margin: 0 !important;
    margin-bottom: 0 !important;
    text-align: right;
    box-sizing: border-box !important;
    vertical-align: middle;  /* v8.08: Align with unit span */
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
}

/* Full-width input */
#measurements-table .measurement-group-table input[type="text"].measurement-input.full-width,
.measurement-group-table input.measurement-input.full-width,
.measurement-input.full-width,
input.measurement-input.full-width[type="text"] {
    width: 149px !important;
    max-width: 149px !important;
    text-align: left;
}

.measurement-input:focus {
    border-color: var(--attention) !important;
    outline: none;
    box-shadow: 0 0 0 2px var(--attention-glow);
    background-color: var(--bg-input-focus) !important;
}

/* Calculated measurement inputs - high specificity to override base rules */
#measurements-table .measurement-group-table input[type="text"].measurement-input.calculated,
.measurement-group-table input.measurement-input.calculated,
.measurement-input.calculated,
input.measurement-input.calculated[type="text"] {
    background-color: var(--attention-dim) !important;
}

/* Redacted transient PII — a restored session carries "(redacted)" instead of
   the real name/DOB. Shown in italics to read as a placeholder, not a value. */
#measurements-table .measurement-group-table input[type="text"].measurement-input.pii-redacted,
.measurement-input.pii-redacted {
    font-style: italic;
    color: var(--grey-text);
}

#measurements-table .measurement-group-table input[type="text"].measurement-input.calculated:focus,
.measurement-group-table input.measurement-input.calculated:focus,
.measurement-input.calculated:focus,
input.measurement-input.calculated[type="text"]:focus {
    background-color: var(--attention-dim) !important;
    border-color: var(--attention-strong) !important;
    box-shadow: 0 0 0 2px var(--attention-glow);
}

#measurements-table .measurement-group-table input[type="text"].measurement-input.ref-normal,
.measurement-group-table input.measurement-input.ref-normal,
.measurement-input.ref-normal,
input.measurement-input.ref-normal[type="text"],
.modal-measurement-input.ref-normal {
    background-color: var(--normal-bg) !important;
}

#measurements-table .measurement-group-table input[type="text"].measurement-input.ref-abnormal,
.measurement-group-table input.measurement-input.ref-abnormal,
.measurement-input.ref-abnormal,
input.measurement-input.ref-abnormal[type="text"],
.modal-measurement-input.ref-abnormal {
    background-color: var(--abnormal-bg) !important;
}

.measurement-input.ref-normal:focus,
.modal-measurement-input.ref-normal:focus {
    background-color: var(--normal-bg) !important;
    border-color: var(--interactive) !important;
}

.measurement-input.ref-abnormal:focus,
.modal-measurement-input.ref-abnormal:focus {
    background-color: var(--abnormal-bg) !important;
    border-color: var(--interactive) !important;
}

/* Plausibility bound breached — the value is outside what is physiologically
   possible for that measurement (OUTSTANDING #50 / Hazard Log HL-006).

   REVERSED grey, the same treatment the value carries in the report body, so
   the two surfaces read as one thing (Pete, browser pass 2026-08-02 — an
   earlier dashed outline was too subtle). The grey scale is already inverted
   between the themes, so one pair of tokens gives light-on-dark in dark mode
   and dark-on-light in light.

   Specificity is deliberate, mirroring the .calculated and .ref-* blocks
   above: those reach #measurements-table .measurement-group-table
   input[type="text"] to beat the base rules, and this must in turn outrank
   THEM — an implausible value shows as implausible whatever its reference
   -range severity, because the severity is derived from a number that may be
   wrong. Equal specificity plus later source order is what settles it, so
   keep this block below those. */
#measurements-table .measurement-group-table input[type="text"].measurement-input.implausible,
.measurement-group-table input.measurement-input.implausible,
.measurement-input.implausible,
input.measurement-input.implausible[type="text"],
.modal-measurement-input.implausible {
    background-color: var(--grey-bright) !important;
    color: var(--grey-base) !important;
}

.measurement-unit {
    color: var(--grey-muted);
    font-size: 0.8rem;
    white-space: nowrap;
    width: 65px;
    display: inline-block;  /* v8.08: Replaces flex sizing */
    text-align: left;
    overflow: hidden;
    margin-left: 4px;  /* v8.08: Replaces flex gap */
    vertical-align: middle;
}

/* Hide unit when input is full-width */
.measurement-input.full-width + .measurement-unit {
    display: none;
}

/* v7.0: Hover feedback for measurement rows */
.measurement-group-table tr:hover {
    background-color: color-mix(in srgb, var(--h1) 6%, transparent);
}

/* v7.0: Measurement row being dragged */
.measurement-group-table tr.measurement-row-dragging {
    opacity: 0.5;
    background-color: color-mix(in srgb, var(--h1) 15%, transparent) !important;
}

/* Show grab cursor on measurement rows (except on inputs) */
.measurement-group-table tr td:not(:has(input)) {
    cursor: grab;
}

.measurement-group-table tr td:not(:has(input)):active {
    cursor: grabbing;
}

/* v8.08: Attention highlight when clicking measurement span in report */
.measurement-group-table tr.measurement-row-attention {
    animation: measurement-attention 2.5s ease-out;
}

@keyframes measurement-attention {
    0% {
        background-color: color-mix(in srgb, var(--h1) 40%, transparent);
        box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--h1) 40%, transparent);
    }
    50% {
        background-color: color-mix(in srgb, var(--h1) 30%, transparent);
        box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--h1) 25%, transparent);
    }
    100% {
        background-color: transparent;
        box-shadow: none;
    }
}


/* ============================================================================
   OPTIONS PANEL (Right Column)
   ============================================================================ */

#options-panel {
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow: hidden;
    min-width: 0;
    /* v11 5.1: transparent column wrapper (see #measurements-panel). */
    gap: 0.5rem;
}

/* Report column header — the .utility-buttons-group (undo/redo/settings/theme)
   is right-aligned via its own margin-left:auto. .col-header supplies the card
   chrome + height. */

/* v11 5.1: report editor + action row sit inside the body card with a small
   inset, so the editor reads as a nested box (mockup-5.1-layout.svg). */
#options-panel .col-body {
    padding: 0.6rem;
}

/* v11 5.1: New Report — primary (interactive/teal) text button ("New"),
   matching the Import and Auto buttons. Inherits the base <button> colours
   (interactive + interactive-hover); flex-centres its label so the text sits
   vertically centred in the fixed button height. */
#new-report-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* Hidden spacer — hides snippet button without affecting layout */
.add-snippet-button.hidden-spacer {
    display: none;
}

/* OUTSTANDING #1: the base-configuration + template selects moved out of the
   header into a panel launched by New. The control anchors the absolutely-
   positioned panel; the panel matches the .param-context-menu popover palette. */
.new-report-control {
    position: relative;
    display: inline-flex;
}

/* position:fixed (coordinates set in openNewReportPanel) so the panel escapes
   the measurements column's overflow:hidden — the column is 330px and the
   two-up panel is wider. Same approach as .param-context-menu. */
.new-report-panel {
    display: none;
    position: fixed;
    z-index: 10002;
    padding: 0.75rem;
    background: var(--grey-elevated);
    border: var(--border-width) solid var(--grey-border);
    border-radius: var(--border-radius);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
}

.new-report-panel.open {
    display: block;
}

/* The chooser dims the page behind it, like a modal. Its drop shadow does the
   work of separating it from the page in light mode and almost none in dark,
   where the shadow falls on an already-dark surface — so the panel read as
   floating text rather than as the thing to attend to (Pete 2026-08-11).
   --modal-backdrop-light is the token for a lighter dimming than a full modal
   takes, which is the right weight for a chooser this small.

   Panel and backdrop are BODY-level siblings (report.html), which is what
   makes this predictable: position:fixed is viewport-relative there, so the
   backdrop covers the whole page, and both sit in the root stacking context,
   so z-index alone decides the order. Nested in .new-report-control the
   dimming reached only the measurements column — full-page is the design
   Pete asked for on 2026-08-12. */
.new-report-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 10001;
    background-color: var(--modal-backdrop-light);
}

.new-report-backdrop.open {
    display: block;
}

/* The two choosers sit side by side, with Build inline to their right.
   flex-end bottom-aligns Build with the selects (the labels rise above). */
.new-report-panel-fields {
    display: flex;
    align-items: flex-end;
    gap: 0.6rem;
}

.new-report-panel-row {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 170px;
}

.new-report-panel-row label {
    font-size: 0.75rem;
    font-weight: var(--font-weight-medium);
    color: var(--grey-text);
}

/* Flex-centre the label so it sits vertically centred in the fixed button
   height (matches #new-report-button). */
#new-report-build {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

/* Right group - utility buttons. margin-left:auto pushes this group to the
   right edge, past the New Report control on the left. */
.utility-buttons-group {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    margin-left: auto;
}

/* OUTSTANDING #2: patient banner — prominent, horizontally centred in the
   report-column header. Absolutely centred so it stays centred regardless of
   the right-aligned utility buttons. Empty by default; shown only when it
   carries a real name/DOB (the .has-patient class). */
#options-panel-bar {
    position: relative;
}
.patient-banner {
    display: none;
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    max-width: 60%;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: 1.15rem;
    font-weight: var(--font-weight-medium);
    letter-spacing: 0.01em;
    color: var(--grey-bright);
    pointer-events: none;
}
.patient-banner.has-patient {
    display: block;
}

/* State dropdown — base configuration selector (fills the New Report panel). */
#state-config-select {
    width: 100%;
    height: var(--element-height);
    margin: 0;
    padding: 0 2rem 0 0.75rem;
    font-weight: var(--font-weight-medium);
}

/* Template dropdown — report layout selector (fills the New Report panel).
   Reads at the same contrast as the state dropdown beside it (the inherited
   --grey-bright): it used to sit at --grey-text and brighten on hover, which
   made a live selection look provisional until pointed at (Pete 2026-08-11).
   The lighter font-weight still marks it as the secondary of the two. */
#template-select {
    width: 100%;
    height: var(--element-height);
    margin: 0;
    padding: 0 2rem 0 0.75rem;
    font-weight: var(--font-weight-normal);
}

/* Legacy: Single dropdown (backward compatibility - can be removed later) */
#report-config-select {
    min-width: 300px;
    height: var(--element-height);
    margin: 0;
    padding: 0 2rem 0 0.75rem;
}



/* ============================================================================
   ICON BUTTONS
   ============================================================================ */

.icon-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--element-height);
    height: var(--element-height);
    min-width: var(--element-height);
    padding: 0 !important;
    margin: 0;
    background-color: var(--interactive);
    border: var(--border-width) solid var(--interactive);
    border-radius: var(--border-radius);
    color: var(--text-inverse);
    cursor: pointer;
    transition: background-color var(--transition),
                border-color var(--transition);
}

.icon-button:hover {
    background-color: var(--interactive-hover);
    border-color: var(--interactive-hover);
}

.icon-button:focus {
    outline: none;
    box-shadow: 0 0 0 var(--outline-width) var(--interactive-glow);
}

.icon-button svg {
    width: 16px;
    height: 16px;
    stroke: currentColor;
    fill: none;
}

/* H2: Secondary icon buttons (Undo, Redo, Help) — attention hue */
.icon-button.secondary {
    background-color: var(--attention-btn);
    border-color: var(--attention-btn);
    color: var(--grey-bright);
}

.icon-button.secondary:hover {
    background-color: var(--attention-btn-hover);
    border-color: var(--attention-btn-hover);
}

.icon-button.secondary:focus {
    box-shadow: 0 0 0 var(--outline-width) var(--attention-glow);
}

/* Disabled state for icon buttons */
.icon-button:disabled,
.icon-button.disabled {
    opacity: 0.4;
    cursor: not-allowed;
    pointer-events: none;
}

.icon-button.secondary:disabled,
.icon-button.secondary.disabled {
    background-color: var(--attention-btn);
    border-color: var(--attention-btn);
}

/* H3: Auto/Algorithm button - teal accent.
   Bolt icon is red (H5/check) with a white outline to signal that Process
   All now chains into Run Checks. paint-order puts the stroke
   fully behind the fill so it reads as a halo, not a centred outline. */
#run-algorithms {
    font-size: 0;
    background-color: var(--auto);
    border-color: var(--auto);
}

#run-algorithms svg {
    fill: var(--check);
    stroke: var(--text-inverse);
    stroke-width: 3;
    paint-order: stroke fill;
}

#run-algorithms:hover {
    background-color: var(--auto-hover);
    border-color: var(--auto-hover);
}

#run-algorithms:focus {
    box-shadow: 0 0 0 var(--outline-width) var(--auto-glow);
}

/* v10.2: Check report buttons — full-width pre-check (#run-checks-big) and
   compact post-arm (#run-checks-small). Both share the H5 (red) palette of
   the original toolbar flag. Visibility swap is driven by updateCheckCopyButtons(). */
#run-checks-big {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    flex: 1;
    min-width: 0;
    height: var(--element-height);
    background-color: var(--check);
    border-color: var(--check);
    color: var(--text-inverse);
}

#run-checks-big:hover {
    background-color: var(--check-hover);
    border-color: var(--check-hover);
}

#run-checks-big:focus {
    box-shadow: 0 0 0 var(--outline-width) var(--check-glow, var(--check-hover));
}

#run-checks-small {
    font-size: 0;
    background-color: var(--check);
    border-color: var(--check);
}

#run-checks-small:hover {
    background-color: var(--check-hover);
    border-color: var(--check-hover);
}

#run-checks-small:focus {
    box-shadow: 0 0 0 var(--outline-width) var(--check-glow, var(--check-hover));
}


/* ============================================================================
   REPORT TEXTAREA (Contenteditable)
   ============================================================================ */

#report-textarea,
.report-contenteditable {
    flex: 1;
    overflow-y: auto;
    white-space: pre-wrap;
    font-family: inherit;
    font-size: 0.9rem;
    font-weight: 300;
    line-height: 1.4;
    border: var(--border-width) solid var(--grey-border);
    border-radius: var(--border-radius-lg);
    padding: 0.75rem;
    padding-left: 46px;  /* v8.5: Wider for horizontal button group */
    padding-bottom: 3em;  /* Extra padding for scroll context below cursor */
    background-color: var(--grey-surface);
    color: var(--grey-bright);
    min-height: 0;
}

#report-textarea:focus,
.report-contenteditable:focus {
    outline: none;
    border-color: var(--interactive);
    box-shadow: 0 0 0 2px var(--interactive-glow);
}

/* v9.1: Visual feedback during rebuild — content fades out then back in */
#report-textarea {
    transition: opacity 0.15s ease;
}
#report-textarea.rebuilding {
    opacity: 0;
}

/* Copy button */
.copy-button-container {
    margin-top: 0.75rem;
    flex-shrink: 0;
    display: flex;
    gap: 0.5rem;
}

#finalise-report {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 1;
    min-width: 0;
    height: var(--element-height);
}

#freeze-report {
    flex-shrink: 0;
}

/* ----------------------------------------------------------------------------
   v11 (#48/#49): Finalise (clinician sign-off) modal — SECTIONED attestation.
   One section per device function, each with an explicit availability state
   (HL-011 — active / not activated / not enabled for this access code / not
   applicable to this report type). Assessments carry the "On report" column
   (#49); outstanding check flags carry a [⋯] resolution menu and gate
   Confirm-and-Copy until the table is empty (#48). Reuses .modal-overlay /
   .algo-modal chrome inside .modal-body (which has padding: 0).
   ---------------------------------------------------------------------------- */
.finalise-content {
    padding: 1rem 1.25rem 1.25rem;
}

/* At-a-glance strip (Pete 2026-09-06): five icons above the disclosure, one
   per section, in the three states the sections themselves are in — grey
   inactive, green active and nothing to resolve, red active and resolution
   required. Same ink as the sections: the ok green is the "normal" hue
   (--h4, as the On-report tick), the flag red the check family. */
.finalise-glance {
    display: flex;
    gap: 0.6rem;
    margin: 0 0 1rem;
}

.finalise-glance-item {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.35rem;
    padding: 0.6rem 0.4rem 0.5rem;
    border: var(--border-width) solid var(--grey-border);
    border-radius: var(--border-radius);
    background-color: var(--grey-surface);
    color: var(--grey-text);
    cursor: default;
}

.finalise-glance-item svg {
    width: 26px;
    height: 26px;
    display: block;
}

.finalise-glance-label {
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

.finalise-glance-sr {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

.finalise-glance-item.glance-ok {
    color: var(--h4);
    border-color: color-mix(in srgb, var(--h4) 45%, transparent);
    background-color: color-mix(in srgb, var(--h4) 12%, transparent);
}

.finalise-glance-item.glance-flag {
    color: var(--check);
    border-color: var(--check-muted);
    background-color: var(--check-faint);
}

/* Sections are FLAT by default (visual-burden pass, Pete 2026-09-06): a small
   heading over a hairline, no box. The border is carried transparent so
   .finalise-section-flag can turn it red without a second layout. */
.finalise-section {
    margin: 0 0 0.9rem;
    border: var(--border-width) solid transparent;
    border-radius: var(--border-radius);
    overflow: hidden;
}

.finalise-section-title {
    margin: 0;
    padding: 0.35rem 0.15rem;
    background-color: transparent;
    border-bottom: var(--border-width) solid var(--grey-border);
    color: var(--grey-text);
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

/* Collapsible sections: native <details>, the heading as its <summary>. A
   clean enumeration sits behind its heading and count; the content is real
   and in the page, one click away. */
.finalise-section-collapsible > summary.finalise-section-title {
    cursor: pointer;
    list-style: none;
    display: flex;
    align-items: center;
    gap: 0.45rem;
}
.finalise-section-collapsible > summary.finalise-section-title::-webkit-details-marker { display: none; }
.finalise-section-collapsible > summary.finalise-section-title::before {
    content: '\25B8';
    font-size: 0.8rem;
    line-height: 1;
}
.finalise-section-collapsible[open] > summary.finalise-section-title::before {
    content: '\25BE';
}

/* The one status line beneath the strip: each function's state in words. */
.finalise-status {
    margin: -0.2rem 0 1rem;
    color: var(--grey-text);
    font-size: 0.8rem;
    line-height: 1.55;
}
.finalise-status-key {
    color: var(--grey-bright);
    font-weight: 600;
}
.finalise-status-flag,
.finalise-status-flag .finalise-status-key {
    color: var(--check);
    font-weight: 600;
}
.finalise-status-sep {
    color: var(--grey-text);
}

.finalise-state-line {
    margin: 0;
    padding: 0.5rem 0.75rem;
    color: var(--grey-text);
    font-size: 0.9rem;
}

.finalise-subnote {
    margin: 0;
    padding: 0.5rem 0.75rem 0.25rem;
    color: var(--grey-text);
    font-size: 0.8rem;
    font-style: italic;
}

.finalise-table {
    width: 100%;
    border-collapse: collapse;
}

.finalise-table thead th {
    padding: 0.35rem 0.75rem 0.2rem;
    border-bottom: var(--border-width) solid var(--grey-border);
    color: var(--grey-text);
    font-size: 0.75rem;
    font-weight: 600;
    text-align: center;
}

.finalise-table td {
    padding: 0.45rem 0.75rem;
    border-top: var(--border-width) solid var(--grey-border);
    font-size: 0.9rem;
}

.finalise-table tbody tr:first-child td {
    border-top: none;
}

.finalise-cell-title {
    width: 36%;
    color: var(--grey-bright);
    font-weight: 600;
    text-align: right;
}

.finalise-cell-value {
    color: var(--auto);
    text-align: left;
}

.finalise-cell-vis,
.finalise-vis-head {
    width: 5.5rem;
    text-align: center;
}

/* A shown statement carries no mark (2026-09-06): only the cross is drawn. */
.finalise-vis-no  { color: var(--h5); font-weight: 700; white-space: nowrap; }

/* Implausible measurement values at Finalise (#50 / HL-006). Attention (--h2),
   matching the outline the same value carries in the measurements table, and
   deliberately not the check palette — this does not gate the sign-off. */
.finalise-plausibility-table .finalise-cell-value {
    color: var(--h2);
    font-weight: 600;
}

.finalise-plausibility-table .finalise-cell-bound {
    color: var(--grey-text);
    font-size: 0.8rem;
    text-align: left;
    white-space: nowrap;
}

/* #37: the sections a text deletion removed, named rather than counted. A
   statement with an undo, not a confirmation — see showSnippetRemovalNotice.
   Sized to its content: this is a short notice, not a working surface, so it
   drops the 750px modal default well below it (Pete 2026-08-08). */
#modal-snippet-removed .modal-content {
    max-width: 26rem;
}

#modal-snippet-removed .modal-body {
    padding: 1.25rem 1.5rem;
}

/* Header and body take the site's own scale rather than a heavier one of their
   own — the notice should read as part of the app, not as an alert. */
#modal-snippet-removed .modal-header h2 {
    font-size: 1.1rem;
    font-weight: 600;
}

#modal-snippet-removed .modal-body p {
    font-size: 0.9rem;
    line-height: var(--line-height);
    margin: 0 0 0.75rem 0;
}

#modal-snippet-removed .modal-body p:last-child {
    margin-bottom: 0;
}

#modal-snippet-removed .modal-actions {
    padding: 0.75rem 1.5rem 1rem;
}

/* Buttons carry a fixed --element-height, so their label needs the flex
   centring to sit on the vertical middle rather than ride the text baseline. */
#modal-snippet-removed .modal-actions button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.snippet-removed-list {
    margin: 0.5rem 0 0.9rem 0;
    padding-left: 1.25rem;
}

.snippet-removed-list li {
    color: var(--grey-bright);
    font-size: 0.9rem;
    font-weight: 600;
    margin: 0.2rem 0;
}

/* Measurements rendered on the report with no value (#68). A gap in the
   copied record is a potential error, so the row reads like a flag (Pete
   2026-09-06): red text, and the section takes the shared .finalise-section-flag
   border-and-title tint below — the same rule as Outstanding checks, so every
   section that lists a potential error looks the same. No cell wash: a full
   red background read as too dominant; the label stays neutral and only the
   value is red, as in the Outstanding rows. Like the implausible rows above
   it, this lists and does not gate. */
.finalise-empty-table .finalise-cell-empty {
    color: var(--check);
    font-weight: 700;
    text-align: left;
    white-space: nowrap;
}

/* Import landed values outside their plausible bounds — the modal holds open
   and says which, because a mis-mapped export field fails for every report at
   once and the moment it arrives is the moment to be loud. */
.import-plausibility-result {
    margin-top: 0.75rem;
    padding: 0.75rem;
    border: var(--border-width) solid var(--attention-border);
    border-radius: var(--border-radius);
    background-color: var(--attention-dim);
}

.import-plausibility-result p {
    margin: 0 0 0.5rem;
    color: var(--grey-bright);
    font-size: 0.9rem;
}

.import-plausibility-result ul {
    margin: 0 0 0.75rem;
    padding-left: 1.25rem;
    color: var(--grey-text);
    font-size: 0.9rem;
}

.import-plausibility-result strong {
    color: var(--h2);
}

.finalise-hidden-note {
    color: var(--grey-text);
    font-weight: 400;
    font-size: 0.75rem;
    font-style: italic;
}

/* A section that lists a potential error — Outstanding checks, and Measurement
   Values while it holds an empty slot — takes the check-tier red family on its
   border and title: the same signal as the report's flag paint. One rule for
   both, so the sections read consistently (Pete 2026-09-06). */
.finalise-section-flag {
    border-color: var(--check-muted);
}

/* The heading text stays the theme's primary colour: the red wash on the
   heading row is the attention signal, and red text on it was hard to read
   (Pete 2026-09-06). */
.finalise-section-flag .finalise-section-title {
    padding: 0.45rem 0.75rem;
    background-color: var(--check-faint);
    border-bottom-color: var(--check-muted);
    color: var(--grey-bright);
}

/* The flagged statement's text is tinted red too (Pete 2026-09-06 — it was
   neutral, being the clinician's own selection; consistency with the
   missing-measurement rows won). */
.finalise-outstanding-table .finalise-cell-value {
    color: var(--check);
}

.finalise-cell-action {
    width: 3rem;
    text-align: center;
}

/* The action affordance is deliberately loud (Pete 2026-07-30): filled
   check-red with a glow, so a row that requires action cannot be mistaken
   for an informational listing. */
.finalise-flag-options {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 1.5rem;
    padding: 0;
    background-color: var(--check-muted);
    border: var(--border-width) solid var(--check-strong);
    border-radius: var(--border-radius);
    color: var(--grey-bright);
    cursor: pointer;
    box-shadow: 0 0 8px var(--check-glow);
}

.finalise-flag-options:hover {
    background-color: var(--check-medium);
    box-shadow: 0 0 10px var(--check-strong);
}

.finalise-disclaimer {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    margin: 0;
    padding: 0.75rem;
    border: var(--border-width) solid var(--attention-border);
    border-radius: var(--border-radius);
    background-color: var(--attention-muted);
    color: var(--grey-bright);
    font-size: 0.9rem;
    line-height: 1.45;
    text-align: center;
    cursor: pointer;
}

.finalise-attest-checkbox {
    flex-shrink: 0;
    width: 1.1rem;
    height: 1.1rem;
    cursor: pointer;
}

.finalise-disclaimer-text {
    flex: 0 1 auto;
}

/* Button lives inside the scroll region (after the disclaimer) so it can only
   be reached — and is only enabled — once the user has scrolled through all. */
.finalise-actions {
    display: flex;
    justify-content: center;
    margin-top: 1rem;
}

#finalise-confirm-copy:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

#finalise-confirm-copy:disabled:hover {
    background-color: var(--auto);
    border-color: var(--auto);
}


/* ============================================================================
   BUTTON STYLES - Named Elements
   ============================================================================ */

/* H1: Interactive primary buttons (steel blue) */
#finalise-report,
#submit,
#open-import-modal,
.inline-edit-button,
.modal-done-button {
    background-color: var(--interactive);
    border-color: var(--interactive);
    color: var(--text-inverse);
}

#finalise-report:hover,
#submit:hover,
#open-import-modal:hover,
.inline-edit-button:hover,
.modal-done-button:hover {
    background-color: var(--interactive-hover);
    border-color: var(--interactive-hover);
}

/* v11 5.1: standardised typography for the four prominent primary action
   buttons — Import (measurements header), New (report header), Auto (review
   header) and Confirm and Copy (report action row) — so they read as one
   family. Same size + weight; each already flex-centres its own label. */
#measurements-panel-bar #open-import-modal,
#new-report-button,
#review-auto,
#finalise-report {
    font-size: 0.9rem;
    font-weight: var(--font-weight-medium);
}

/* H2: Back/Next navigation buttons — grey (attention) palette so they read
   as secondary affordances next to the primary Done button. */
.modal-back-button,
.modal-next-button {
    background-color: var(--attention-btn);
    border-color: var(--attention-btn);
    color: var(--text-inverse);
}

.modal-back-button:hover,
.modal-next-button:hover {
    background-color: var(--attention-btn-hover);
    border-color: var(--attention-btn-hover);
}

.modal-auto-button {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    padding: 0;
    border: 1px solid var(--auto);
    border-radius: var(--border-radius);
    background-color: var(--auto);
    color: var(--text-inverse);
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

.modal-auto-button:hover {
    background-color: var(--auto-hover);
    border-color: var(--auto-hover);
}

.modal-auto-button:focus {
    outline: none;
    box-shadow: 0 0 0 var(--outline-width) var(--auto-glow);
}

.modal-auto-button svg {
    width: 14px;
    height: 14px;
}

/* H5: Check button — red variant */
.modal-check-button {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    padding: 0;
    border: 1px solid var(--check);
    border-radius: var(--border-radius);
    background-color: var(--check);
    color: var(--text-inverse);
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

.modal-check-button:hover {
    background-color: var(--check-hover);
    border-color: var(--check-hover);
}

.modal-check-button:focus {
    outline: none;
    box-shadow: 0 0 0 var(--outline-width) var(--check-glow);
}

.modal-check-button svg {
    width: 14px;
    height: 14px;
}

/* Armed state: inverted (ghost) to distinguish from disarmed solid fill */
.modal-check-button.armed {
    background-color: var(--surface, transparent);
    color: var(--check);
}

.modal-check-button.armed:hover {
    background-color: var(--check-muted);
    border-color: var(--check-hover);
    color: var(--check);
}

.modal-check-button.armed svg {
    stroke: var(--check);
}

/* v9.1 Algorithm Modal Overrides */
.algo-modal {
    z-index: 1050;
}

/* v11 Phase 3.3: mandatory-field gate — greyed (but clickable) confirm button
   and highlighted unanswered rows. Uses the H5 abnormal tokens for the rows. */
.validation-blocked {
    opacity: 0.45;
    filter: saturate(0.4);
    cursor: not-allowed;
}
.modal-param-row.row-unanswered > td {
    background-color: var(--abnormal-bg);
    box-shadow: inset 3px 0 0 var(--abnormal-border);
}

.algo-confirm-button {
    background-color: var(--auto);
    border: 1px solid var(--auto);
    color: var(--text-inverse);
    padding: 0.4rem 1.2rem;
    border-radius: var(--border-radius);
    cursor: pointer;
    font-size: 0.9rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

/* HL-013 control 2 (2026-09-08, Pete): the report-copied identity popup —
   shown the moment Confirm-and-Copy succeeds, over the report, in the seconds
   before the paste into the RIS; it replaced the button's second line, which
   was not being noticed. Above every modal (1100) and the automation notice
   (10003). Teal, white text: a small lead line and the identity large. */
.report-copied-notice {
    position: fixed;
    top: 40%;
    left: 50%;
    transform: translate(-50%, -50%) scale(0.96);
    z-index: 10004;
    min-width: 22rem;
    max-width: min(90vw, 40rem);
    padding: 1.1rem 1.8rem 1.25rem;
    background: var(--h1);
    color: var(--text-inverse);
    border-radius: var(--border-radius-lg);
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.45);
    text-align: center;
    opacity: 0;
    transition: opacity 0.2s ease, transform 0.2s ease;
    pointer-events: none;
}
.report-copied-notice.visible {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
}
.report-copied-lead {
    font-size: 0.85rem;
    font-weight: var(--font-weight-medium);
    letter-spacing: 0.02em;
    opacity: 0.9;
    margin-bottom: 0.35rem;
}
.report-copied-identity {
    font-size: 1.7rem;
    font-weight: var(--font-weight-bold);
    line-height: 1.25;
    word-break: break-word;
}
.report-copied-identity.report-copied-none {
    font-size: 1.25rem;
    opacity: 0.9;
}

.algo-confirm-button:hover {
    background-color: var(--auto-hover);
    border-color: var(--auto-hover);
}

.algo-confirm-button:focus {
    outline: none;
    box-shadow: 0 0 0 var(--outline-width) var(--auto-glow);
}

/* H5: Check algorithm confirm button — red variant */
.algo-check-button {
    background-color: var(--check);
    border: 1px solid var(--check);
    color: var(--text-inverse);
    padding: 0.4rem 1.2rem;
    border-radius: var(--border-radius);
    cursor: pointer;
    font-size: 0.9rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

.algo-check-button:hover {
    background-color: var(--check-hover);
    border-color: var(--check-hover);
}

.algo-check-button:focus {
    outline: none;
    box-shadow: 0 0 0 var(--outline-width) var(--check-glow);
}

/* Disable Checking button in check-all confirm modal — H2 (attention/grey) */
.algo-check-disable {
    background-color: var(--attention-btn);
    border: 1px solid var(--attention-border);
    color: var(--text-inverse);
    padding: 0.4rem 1.2rem;
    border-radius: var(--border-radius);
    cursor: pointer;
    font-size: 0.9rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

.algo-check-disable:hover {
    background-color: var(--attention-btn-hover);
    border-color: var(--h2);
}

.algo-check-disable:focus {
    outline: none;
    box-shadow: 0 0 0 var(--outline-width) var(--attention-glow);
}

.algo-check-disable:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* v10.1: .check-mode rules deleted — replaced by separate #run-checks button */

/* Per-algorithm Done button uses interactive styling (commits changes) */
.algo-done-button {
    background-color: var(--interactive);
    border-color: var(--interactive);
}

.algo-done-button:hover {
    background-color: var(--interactive-hover);
    border-color: var(--interactive-hover);
}

.algo-done-button:focus {
    box-shadow: 0 0 0 var(--outline-width) var(--interactive-glow);
}

/* Auto (re-run) button in algorithm modal action bar — square icon */
.algo-auto-button {
    background-color: var(--auto);
    border: 1px solid var(--auto);
    color: var(--text-inverse);
    width: var(--element-height);
    height: var(--element-height);
    padding: 0;
    border-radius: var(--border-radius);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

.algo-auto-button:hover {
    background-color: var(--auto-hover);
    border-color: var(--auto-hover);
}

.algo-auto-button:focus {
    outline: none;
    box-shadow: 0 0 0 var(--outline-width) var(--auto-glow);
}

.algo-auto-button svg {
    width: 14px;
    height: 14px;
}

/* Algorithm modal section separator rows */
.algo-separator-row td.measurement-group-header {
    padding: 0.35rem 0.5rem;
    margin: 0;
    border-radius: 0;
    border-bottom: var(--border-width) solid var(--grey-border);
    background-color: var(--attention-muted);
    color: var(--grey-bright);
}

/* v9.1 Algorithm Output Section — pinned to bottom of modal */
.algo-output-section {
    flex-shrink: 0;
    border-top: 1px solid var(--auto-medium);
    background-color: var(--auto-subtle);
    border-radius: 0 0 var(--border-radius-lg) var(--border-radius-lg);
    padding: 0.25rem 0;
}

.algo-output-table {
    margin: 0;
}

.algo-output-row .param-label {
    color: var(--auto);
    font-weight: 500;
}

/* Ochre tint on output row dropdowns/textareas when showing auto value */
.algo-output-row.algo-output-auto .modal-select,
.algo-output-row.algo-output-auto .modal-custom-textarea,
.algo-output-row.algo-output-auto .modal-textarea {
    border-color: var(--auto-strong);
    background-color: var(--auto-muted);
}

/* Select elements need an opaque background — semi-transparent causes
   Chromium to fall back to OS-native dropdown popups */
.algo-output-row.algo-output-auto .modal-select {
    background-color: color-mix(in srgb, var(--h3) 16%, var(--bg-input));
}

.algo-output-row.algo-output-auto .modal-select:focus,
.algo-output-row.algo-output-auto .modal-custom-textarea:focus,
.algo-output-row.algo-output-auto .modal-textarea:focus {
    border-color: var(--auto);
    box-shadow: 0 0 0 var(--outline-width) var(--auto-glow);
}

/* Secondary/gray buttons */
#reset-selections {
    background-color: var(--interactive-neutral);
    border-color: var(--interactive-neutral);
    color: var(--grey-bright);
}

#reset-selections:hover {
    background-color: var(--interactive-neutral-hover);
    border-color: var(--interactive-neutral-hover);
}


/* ============================================================================
   INLINE BUTTONS (Edit button within report text)
   v8.5: Horizontal layout - [x] on left, [edit] on right (next to text)
   Fits within single line height to avoid overlap on adjacent snippet rows
   ============================================================================ */

.inline-button-group {
    display: inline-flex;
    flex-direction: row-reverse;  /* DOM order is edit,delete; visual is delete,edit */
    align-items: center;
    gap: 2px;
    float: left;
    margin-left: -46px;  /* Match padding-left on .report-contenteditable */
    width: 38px;
    margin-right: 5px;
    margin-bottom: 0;
    user-select: none;
    -webkit-user-select: none;
    white-space: nowrap;
    line-height: 1;
    vertical-align: top;
}

/* Edit button - small square, positioned next to text */
.inline-edit-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    padding: 0 !important;
    margin: 0 !important;
    min-width: 0 !important;
    min-height: 0 !important;
    border-radius: var(--border-radius-sm);
    cursor: pointer;
}

.inline-edit-button svg {
    width: 12px;
    height: 12px;
    flex-shrink: 0;
}

/* Delete button - matches secondary icon button styling */
.inline-delete-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 14px;
    height: 18px;
    padding: 0 !important;
    margin: 0 !important;
    min-width: 0 !important;
    min-height: 0 !important;
    border: none;
    border-radius: var(--border-radius-sm);
    background-color: var(--interactive-neutral);
    color: var(--grey-bright);
    cursor: pointer;
    transition: background-color var(--transition-fast),
                color var(--transition-fast);
}

.inline-delete-button:hover {
    background-color: var(--interactive-neutral-hover);
}

.inline-delete-button:active {
    background-color: var(--grey-base);
}

.inline-delete-button svg {
    width: 10px;
    height: 10px;
    flex-shrink: 0;
    stroke: currentColor;
}

/* Hide delete button in print */
@media print {
    .inline-delete-button {
        display: none !important;
    }
}


/* ============================================================================
   SPAN TEXT COLORING - Block-like appearance on interaction
   Uses box-shadow instead of border to avoid layout shifts
   ============================================================================ */

[data-type],
[data-handle] {
    border-radius: var(--border-radius-sm);
    transition: background-color var(--transition-fast),
                box-shadow var(--transition-fast),
                color var(--transition-fast);
    cursor: pointer;
}

/* ============================================================================
   PAINT AXIS 1 — FOCUS FAMILY (hover / select colour; groups 1 & 2). 4.8 (d2).
   Base transparent; a family-tinted highlight appears on HOVER (and on
   selection, via .span-selected below), coloured from --sel-hue: grey (--h2
   "text") or teal (--h1 "linked"). --sel-hue defaults to grey on the editor and
   is overridden to teal for the linked [data-handle] types in the SELECTION
   section below; spans WITHOUT a data-handle (the unit sibling, embedded alt
   values) inherit their context — a unit beside a standalone measurement
   inherits grey (5.2); a value/unit embedded inside a parameter inherits the
   parameter's teal (5.1). Persistent algo paint (auto / check —
   axis 2) is below and wins on hover by source order. Provenance (clean vs
   dirty) no longer paints — it is carried in data-status and attested (DR-004).
   ============================================================================ */

/* Measurement OUTER spans: transparent — the inner .embedded-measurement paints
   the value; the outer never carries a family or persistent highlight. */
[data-type="measurement"],
[data-type="measurement"]:hover {
    background-color: transparent;
    box-shadow: none;
}

/* Family highlight on HOVER — text-content field spans, the standalone unit
   sibling, and embedded ALT(n) spans, each tinted from its inherited --sel-hue
   (grey for text / standalone, teal for linked / embedded).
   The alt selectors are PREFIX matches ([data-type^="alt"], .embedded-alt…)
   so every level — alt, alt2, alt3 … — is covered without enumerating them.
   Nothing else in the editor starts with "alt", so the prefix cannot overreach. */
[data-type="manual"]:hover,
[data-type="parameter"]:hover,
[data-type^="alt"]:hover,
[data-type="summarystring"]:hover,
.measurement-unit-display:hover,
[class*="embedded-alt"]:hover {
    background-color: color-mix(in srgb, var(--sel-hue) 8%, transparent);
    border-radius: var(--border-radius);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--sel-hue) 22%, transparent);
}

/* ============================================================================
   PAINT AXIS 2 — PERSISTENT ALGO STATE (groups 3 & 4). Always-on background,
   attribute-driven (the .span-auto / .span-accepted classes were retired at d3;
   the 'accepted' status itself retired with the propose-accept excision).
   Ordered AFTER axis 1 so it wins the hover tie for an algo-set span.
   H3: Auto (algorithm-set) — teal, always visible.
   ============================================================================ */
[data-status="auto"] {
    background-color: var(--auto-muted);
    border-radius: var(--border-radius);
}

[data-status="auto"]:hover {
    background-color: var(--auto-medium);
    box-shadow: inset 0 0 0 1px var(--auto-strong);
}

/* H5: Check-mismatch (parameter ≠ algorithm recommendation) - Red (PERSISTENT - always visible) */
.check-mismatch {
    background-color: var(--check-muted) !important;
    border-radius: var(--border-radius);
}

.check-mismatch:hover {
    background-color: var(--check-medium) !important;
    box-shadow: inset 0 0 0 1px var(--check-strong) !important;
}

/* H5: Section modal mismatch — outline form controls when row is flagged */
.modal-param-row.check-mismatch .modal-select,
.modal-param-row.check-mismatch .modal-custom-textarea,
.modal-param-row.check-mismatch .modal-textarea {
    outline: 1px solid var(--check-strong);
    outline-offset: -1px;
    background-color: var(--check-muted);
}

.modal-param-row.check-mismatch .modal-select:focus,
.modal-param-row.check-mismatch .modal-custom-textarea:focus,
.modal-param-row.check-mismatch .modal-textarea:focus {
    outline: 1px solid var(--check);
    outline-offset: -1px;
    box-shadow: 0 0 0 var(--outline-width) var(--check-glow);
}

/* DISABLED - H5: Check-passed (armed, no mismatch). SaMD framing: communicates
   "examined" rather than "correct" — dotted underline only, no fill. 
.check-passed {
    text-decoration: underline dotted var(--check);
    text-decoration-thickness: 2px;
    text-underline-offset: 3px;
}
*/

/* Summary anchor - invisible placeholder */
.summary-anchor,
[data-type="summary-anchor"] {
    display: inline;
    background: none;
    padding: 0;
    margin: 0;
    box-shadow: none !important;
}

/* Summary line break spans */
.summary-linebreak,
[data-type="summary-linebreak"] {
    background-color: transparent;
}

.summary-linebreak:hover,
[data-type="summary-linebreak"]:hover {
    background-color: var(--interactive-subtle);
}

/* v7.0: Summary number spans - auto-generated line numbers */
.span-summary-number,
[data-type="summary-number"] {
    background-color: transparent;
    color: var(--grey-text);
    font-weight: 500;
    user-select: none;
    pointer-events: none;  /* Can't be clicked/edited */
}

/* ============================================================================
   EMBEDDED MEASUREMENT SPANS (v8.1 Phase 1)
   Nested spans within parameter body content that hold live measurement values.
   These are always visible (PERSISTENT) to indicate they are editable/linked.
   ============================================================================ */

.embedded-measurement {
    background-color: var(--attention-subtle);
    border-radius: 2px;
    padding: 0 2px;
    margin: 0 1px;
    cursor: text;
    transition: background-color var(--transition-fast), border-color var(--transition-fast);
    display: inline;
}

.embedded-measurement:hover {
    background-color: var(--attention-muted);
}

.embedded-measurement:focus {
    background-color: var(--attention-muted);
    outline: none;
}

/* Empty embedded measurement - minimal placeholder so span stays clickable.
   Inline, widened by horizontal padding (Pete 2026-09-08): it used to be an
   inline-block with a min-width, and an inline-block takes the full line
   height, so the box stood taller than the surrounding text and its unit
   (visible as a kink where the armed outline met the unit's). Inline
   padding gives the same ~2em width at exactly the text's height. */
.embedded-measurement.embedded-empty {
    background-color: var(--attention-dim);
    padding: 0 1em;
}

.embedded-measurement.ref-normal {
    background-color: color-mix(in srgb, var(--h4) 30%, transparent);
}

.embedded-measurement.ref-abnormal {
    background-color: color-mix(in srgb, var(--h5) 32%, transparent);
}

/* Implausible value, as read in the report body (#50 / HL-006).
   INVERTED grey, and it OUTRANKS every other highlight a measurement can
   carry — reference-range severity, auto/check paint, span status. A dashed
   underline was tried first and was too subtle at reading distance (Pete,
   browser pass 2026-08-02): a value that may be wrong should stop the eye
   before its clinical classification is even considered, because the
   classification is derived from it.
   The grey scale is inverted between the two themes, so ONE pair of tokens
   gives light-on-dark in dark mode and dark-on-light in light mode with no
   theme-specific rule. !important is what buys the priority — the ref-range
   rules above use the same device. Applies to both embedded and templated
   report values: they are one class, emitted by renderMeasurementValueSpan
   and by the template path in §11. */
.embedded-measurement.implausible {
    background-color: var(--grey-bright) !important;
    color: var(--grey-base) !important;
}

/* (Template-dirty paint retired 4.8 d2 — paint follows the span's family, not
   its provenance status; a template-dirty parameter reads teal like any other
   parameter. data-status="template-dirty" still drives the value cascade, the
   dropdown marker and the auto-overwrite guard.) */

/* The four section-modal placeholders — < empty >, < custom >, < removed >,
   < edited > — share ONE look: muted grey, upright. They are all "not a
   clinical option" markers, so a reader should recognise them as a class
   rather than have to read each one (Pete 2026-08-10). Their wording shares
   the < … > convention for the same reason.

   #78: this one is the dropdown's disabled placeholder, shown when no option
   can be indicated. Renamed from .template-dirty-placeholder, which named
   only the first of the two states it now covers. */
.modal-selection-placeholder {
    color: var(--grey-muted);
}


/* ============================================================================
   DRAG AND DROP - Span Reordering
   ============================================================================ */

/* v7.5: Normal text cursor for spans - Ctrl/Cmd+drag for reordering */
#report-textarea [data-type],
#report-textarea [data-handle] {
    cursor: text;
}

/* Grabbing cursor while dragging */
body.is-dragging-span,
body.is-dragging-span * {
    cursor: grabbing !important;
}

/* Dragging state - the element being dragged */
.span-dragging {
    opacity: 0.4;
    background-color: var(--bg-surface-hover) !important;
    box-shadow: none !important;
}

/* Drop indicator line - both vertical (between spans) and horizontal (empty lines) */
.drop-indicator {
    background-color: var(--interactive);
    border-radius: 1px;
    box-shadow: 0 0 4px var(--interactive),
                0 0 8px var(--interactive-glow);
}

/* Visual feedback when element is successfully moved */
.span-just-moved {
    animation: span-moved-flash 0.5s ease;
}

@keyframes span-moved-flash {
    0% {
        background-color: var(--interactive-muted);
        box-shadow: 0 0 8px var(--interactive-glow);
    }
    100% {
        background-color: transparent;
        box-shadow: none;
    }
}

/* v11 4.11: attention glow on a span navigated-to from an audit tile — drawn as
   an ::after OVERLAY so it is independent of the span's own selection paint
   (which sets box-shadow !important; a CSS animation can't override !important).
   Held then faded over ~0.9s to catch the eye as the span scrolls in.
   pointer-events:none so it never blocks a click. */
.span-attention-flash {
    position: relative;
}
.span-attention-flash::after {
    content: '';
    position: absolute;
    inset: -3px;
    border-radius: var(--border-radius);
    pointer-events: none;
    animation: span-attention-glow 1.4s ease forwards;
}
@keyframes span-attention-glow {
    0%   { box-shadow: 0 0 0 2px var(--interactive), 0 0 12px 3px var(--interactive-glow); opacity: 1; }
    65%  { box-shadow: 0 0 0 2px var(--interactive), 0 0 12px 3px var(--interactive-glow); opacity: 1; }
    100% { box-shadow: 0 0 0 2px transparent, 0 0 12px 3px transparent; opacity: 0; }
}

/* Disable text selection while dragging */
#report-textarea[data-dragging="true"] {
    user-select: none;
    -webkit-user-select: none;
}

#report-textarea[data-dragging="true"] * {
    user-select: none;
    -webkit-user-select: none;
}

/* Prevent pointer events on other elements while dragging */
body.is-dragging-span #report-textarea [data-type]:not(.span-dragging),
body.is-dragging-span #report-textarea [data-handle]:not(.span-dragging) {
    pointer-events: auto;
}


/* ============================================================================
   PARAM BLOCKS (conditional if-block wrappers)
   ============================================================================ */

.param-block {
    display: inline;
}

.param-block:not(.block-empty)::before {
    content: "\A";
    white-space: pre;
}

.param-block.block-empty {
    display: none;
}


/* ============================================================================
   LINE CONTAINERS (v8.0)
   Each template line becomes a .report-line div. Line breaks are implicit
   (one div = one line). Internal newlines within spans are just \n characters.
   ============================================================================ */

/* Base line container */
.report-line {
    display: block;
    min-height: 1.4em;  /* Ensure empty lines have height */
    line-height: 1.4;   /* Match min-height for consistent cursor positioning */
}

/* Hidden lines (if-block with empty value) */
.report-line.block-empty {
    display: none;
}

/* Inline if-blocks */
.if-inline {
    display: inline;
}

.if-inline.block-empty {
    display: none;
}

/* Line placeholder for empty lines - uses zero-width space for cursor positioning */
.report-line [data-type="line-placeholder"] {
    display: inline;
    color: transparent;
    user-select: none;
}

/* Ensure spans with internal newlines render correctly */
.report-line [data-handle] {
    white-space: pre-wrap;
    word-wrap: break-word;
}

/* Summary line containers */
.report-line.summary-line {
    display: block;  /* Use block so spans flow inline */
}

/* Summary number styling */
.report-line.summary-line [data-type="summary-number"] {
    display: inline-block;
    min-width: 1.5em;
    text-align: right;
    margin-right: 0.25em;
    white-space: nowrap;
}

/* Summarystring and manual spans flow inline within summary lines */
.report-line.summary-line [data-type="summarystring"],
.report-line.summary-line [data-type="manual"] {
    display: inline;
}

/* v8.0 Fix: Hide lines that ONLY contain the invisible summary-anchor */
.report-line:has([data-type="summary-anchor"]):not(:has([data-handle]:not([data-type="summary-anchor"]))) {
    display: none;
}

/* User-inserted lines */
.report-line[data-inserted="user"] {
    /* Optional: subtle visual indicator for user-inserted content */
}

/* Drag-drop target lines */
.report-line.drop-target {
    background-color: var(--interactive-muted);
    box-shadow: inset 0 0 0 1px var(--interactive);
    border-radius: var(--border-radius);
}


/* ============================================================================
   PARAMETER CONTEXT MENU - Dark Theme
   ============================================================================ */

.param-context-menu {
    position: fixed;
    z-index: 10002;
    background: var(--grey-elevated);
    border: var(--border-width) solid var(--grey-border);
    border-radius: var(--border-radius);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
    padding: 3px 0;
    margin: 0;
    list-style: none;
    min-width: 150px;
    max-width: 600px;
    max-height: 400px;
    overflow-y: auto;
}

.param-context-menu .context-menu-item {
    padding: 5px 12px;
    cursor: pointer;
    font-size: 0.85rem;
    color: var(--grey-bright);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.param-context-menu .context-menu-item:hover {
    background-color: var(--bg-surface-hover);
}

.param-context-menu .context-menu-item.selected {
    background-color: var(--interactive-muted);
    font-weight: var(--font-weight-medium);
}

.param-context-menu .context-menu-item.selected::before {
    content: "✓ ";
    color: var(--interactive);
}

.param-context-menu .context-menu-separator {
    height: 1px;
    background-color: var(--grey-border);
    margin: 3px 8px;
    padding: 0;
}

.param-context-menu .context-menu-custom {
    color: var(--grey-text);
    font-style: italic;
}

/* v7.5: Context menu action items */
.param-context-menu .context-menu-action {
    font-weight: var(--font-weight-medium);
}

/* H3: Auto option - teal background with white text */
.param-context-menu .context-menu-auto {
    background-color: var(--auto);
    color: var(--text-inverse);
}

.param-context-menu .context-menu-auto:hover {
    background-color: var(--auto-hover);
}

/* H5: Check option - red background with white text */
.param-context-menu .context-menu-check {
    background-color: var(--check);
    color: var(--text-inverse);
}

.param-context-menu .context-menu-check:hover {
    background-color: var(--check-hover);
}

/* v11 5.1: Dismiss/Restore check — MUTED red (red text, not the solid-red
   fill of the Check-arm item). A dismiss is a deliberate per-param override;
   the muted treatment sets it apart from arming a check. */
.param-context-menu .context-menu-dismiss,
.param-context-menu .context-menu-restore {
    color: var(--check);
}

.param-context-menu .context-menu-dismiss:hover,
.param-context-menu .context-menu-restore:hover {
    background-color: var(--check-muted);
}

/* Summary/Clear options - subtle accent background */
.param-context-menu .context-menu-summary,
.param-context-menu .context-menu-clear {
    background-color: var(--interactive-muted);
}

.param-context-menu .context-menu-summary:hover,
.param-context-menu .context-menu-clear:hover {
    background-color: var(--interactive-glow);
}

/* HL-012 (#47): transient refusal notice — Auto clicked while the algorithm
   set was still loading; the sweep declines to run on a partial set. */
.automation-unavailable-notice {
    position: fixed;
    top: 18px;
    left: 50%;
    transform: translateX(-50%) translateY(-8px);
    z-index: 10003;
    max-width: 30rem;
    padding: 0.6rem 1rem;
    background: var(--grey-elevated);
    border: var(--border-width) solid var(--attention-border);
    border-left: 3px solid var(--h2);
    border-radius: var(--border-radius);
    color: var(--grey-bright);
    font-size: 0.85rem;
    line-height: 1.4;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
    opacity: 0;
    transition: opacity 0.25s ease, transform 0.25s ease;
    pointer-events: none;
}

.automation-unavailable-notice.visible {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

/* ============================================================================
   MODAL STYLES - Base
   ============================================================================ */

.modal,
.modal-overlay {
    display: none;
    position: fixed;
    z-index: 1000;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    overflow: auto;
    background-color: var(--modal-backdrop);
}

#import-modal {
    z-index: 1100;
}

.modal.active,
.modal-overlay.active {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding-top: 5vh;
}

.modal-content {
    background-color: var(--grey-elevated);
    border-radius: var(--border-radius-lg);
    border: var(--border-width) solid var(--grey-border-strong);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6);
    min-width: 300px;
    max-width: 900px;
    width: 90%;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
}

#import-modal .modal-content {
    max-width: 600px;
}

.modal-header {
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 0.75rem 1rem;
    border-bottom: var(--border-width) solid var(--grey-border);
    background-color: var(--bg-modal-header);
    border-radius: var(--border-radius-lg) var(--border-radius-lg) 0 0;
    position: relative;
}

.modal-header h2 {
    margin: 0;
    font-size: 1.1rem;
    text-align: center;
    color: var(--grey-bright);
}

.modal-header .close-button {
    position: absolute;
    right: 1rem;
}

.close-button {
    background: none;
    border: none;
    font-size: 1.5rem;
    cursor: pointer;
    color: var(--grey-text);
    padding: 0;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--border-radius);
}

.close-button:hover {
    background-color: var(--bg-surface-hover);
    color: var(--grey-bright);
}

.modal-body {
    padding: 0;
    overflow-y: auto;
    flex: 1;
    min-height: 0;
}

.modal-body .template-options-table {
    margin: 0;
}

.modal-body .template-options-table thead {
    position: sticky;
    top: 0;
    z-index: 10;
}

.modal-body .template-options-table tbody td:first-child,
.modal-body .template-options-table tbody td:last-child {
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;
}

/* Custom-text sub-row — appears immediately below a .modal-param-row when
   the user picks the "< custom >" option. Three cells align with the param
   row above (label / options / summary). The textarea sits in the middle
   cell so it aligns horizontally with the dropdown above it.
   border-top is removed (the .custom-active rule on the param row above
   suppresses the divider between dropdown and textarea); border-bottom
   inherits the default tbody td separator so the grouped affordance is
   still cleanly distinguished from the next parameter row.
   .template-options-table prefix lifts specificity above the default
   tbody td border/padding rules below. */
.template-options-table .modal-custom-text-row > td {
    padding-top: 0;
    padding-bottom: 0.5rem;
    border-top: none;
}

.template-options-table .modal-custom-text-row > .modal-custom-text-cell {
    /* v10.x: padding-left bumped from 0.5rem → 1.5rem so the textarea
       slides 1rem right of the dropdown column above. Pairs with the
       reduced .modal-sub-label padding-right (now 0; was 1rem default —
       same 1rem rightward shift) so the label and textarea move together
       as a unit, reading as an indented "child" of the param row above. */
    padding-left: 1.5rem;
    padding-right: 0.5rem;
}

/* Summary-checkbox slot in the custom-text row. When the user picks the
   < custom > option, toggleCustomTextMode moves .modal-summary-checkbox here
   so it sits next to the custom textarea instead of beside the (now greyed)
   dropdown. Width/centering mirror .param-summary so the column stays the
   same width regardless of which row currently hosts the checkbox.

   The textarea inside .modal-custom-text-cell has `margin-top: 0.5rem
   !important` (.modal-custom-textarea, ~line 3267), which pushes its top
   edge ~8px below the cell top. Without compensating padding, this slot's
   content area would start at cell-top (y=0) while the textarea starts at
   y=8 — vertical-align: middle would then place the checkbox centre ~4px
   above the textarea's box centre. Adding padding-top: 0.5rem to this
   slot starts our content area at the same y, so the two centres line up. */
.template-options-table .modal-custom-text-row > .modal-custom-text-summary-slot {
    text-align: center;
    vertical-align: middle;
    width: 48px;
    padding-top: 0.5rem;
}

.template-options-table .modal-custom-text-row .modal-custom-textarea {
    width: 100%;
    margin: 0;
}

/* Drop the bottom border on the param row whenever any sub-row is visible
   beneath it (custom-text row, summary-text row, or both), so the param row
   merges with its sub-rows into one grouped affordance. The class is driven
   by syncSummaryTextRowVisibility / toggleCustomTextMode. */
.template-options-table .modal-param-row.has-sub-row > td {
    border-bottom: none;
}

/* When the summarystring row is visible, also suppress the custom-text row's
   bottom border so dropdown → body → summary read as one grouped affordance.
   The summarystring row keeps its default bottom border, closing the group. */
.template-options-table .modal-custom-text-row.summary-active > td {
    border-bottom: none;
}

/* Summarystring sub-row — section modals only; shown when custom-active AND
   summary checkbox is ticked. Three content cells (spacer / textarea / copy)
   plus a trailing spacer to keep the 4-column layout aligned with rows above. */
.template-options-table .modal-summarystring-row > td {
    padding-top: 0;
    padding-bottom: 0.5rem;
    border-top: none;
}

.template-options-table .modal-summarystring-row > .modal-summarystring-cell {
    /* v10.x: padding-left bumped from 0.5rem → 1.5rem to match the
       .modal-custom-text-cell indent. See the comment on that rule. */
    padding-left: 1.5rem;
    padding-right: 0.5rem;
}

.template-options-table .modal-summarystring-row .modal-summarystring-textarea {
    width: 100%;
    margin: 0;
    height: var(--element-height);
    min-height: var(--element-height);
    resize: none;
    font-family: inherit;
    font-size: 0.8rem;
    line-height: 1.4;
    padding: 0.4rem 0.6rem;
    /* Lighter than modal background (--grey-elevated #1a1a1a) so the summary
       textarea is visually distinct from both the modal surface and the body
       textarea (which uses --bg-input #111). */
    background-color: var(--grey-border);
    color: var(--grey-bright);
    border: var(--border-width) solid var(--grey-border-strong);
    border-radius: var(--border-radius);
    box-sizing: border-box;
    overflow: hidden;
}

.template-options-table .modal-summarystring-row > .modal-summarystring-action {
    text-align: center;
    vertical-align: middle;
    width: 48px;
    padding: 0 0.4rem;
}

/* Link/unlink button — mirrors the popover's link button. Icon is the
   copy-arrow glyph in both states; the .summary-linked / .summary-unlinked
   modifier classes set green vs grey. Sits at the right end of the
   summarystring row, visually aligned with the summary checkbox in the
   param row above. */
.modal-summarystring-link-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    padding: 0;
    border: var(--border-width) solid transparent;
    border-radius: var(--border-radius);
    background: transparent;
    cursor: pointer;
    flex-shrink: 0;
    vertical-align: middle;
}

.modal-summarystring-link-btn.summary-linked {
    color: var(--interactive);
}

.modal-summarystring-link-btn.summary-linked:hover {
    background-color: var(--interactive-dim);
}

.modal-summarystring-link-btn.summary-unlinked {
    color: var(--grey-muted);
}

.modal-summarystring-link-btn.summary-unlinked:hover {
    color: var(--grey-text);
    background-color: var(--bg-surface-hover);
}

/* v10.x: Suppress the inherited generic button:focus glow — too noisy
   on this small icon button that fires often during normal editing. */
.modal-summarystring-link-btn:focus,
.span-popover-link-btn:focus {
    box-shadow: none;
}

.modal-summarystring-link-btn svg {
    width: 14px;
    height: 14px;
}

/* Sub-row label cells ("Custom text" / "Summary text") — italic, muted, and
   right-aligned. v10.x: shrunk padding-right from 1rem → 0 so the label
   hugs the column boundary, shifting it 1rem rightward of the .param-label
   position above. Combined with the matching padding-left bump on
   .modal-custom-text-cell / .modal-summarystring-cell, the whole sub-row
   content slides rightward as a "child-of" indent (the param row's
   checkbox/actions columns are unaffected, so vertical alignment between
   the param row's controls and the sub-row's controls is preserved). */
.template-options-table .modal-sub-label {
    text-align: right;
    padding-right: 0;
    font-style: italic;
    font-size: 0.75rem;
    color: var(--grey-muted);
    vertical-align: middle;
    white-space: nowrap;
}

/* "< custom >" as the closed control's displayed value — the cue that the
   active value lives in the textarea below. Matched to the other three
   placeholders: the same muted grey, and no opacity, which used to fade the
   control's border along with its text. */
.modal-param-row.custom-active .modal-select {
    color: var(--grey-muted);
}

/* "< custom >" in the open dropdown list — same muted grey as the other three
   placeholders. Firefox honours option colour; other browsers may render it in
   the control's colour (acceptable degradation — the text still reads). */
.modal-select .custom-text-option {
    color: var(--grey-muted);
}

.modal-select .custom-text-separator {
    color: var(--text-muted, #888);
}

/* #78: a collapsed <select> paints its displayed text in the SELECT's colour,
   not the selected <option>'s — so styling .modal-selection-placeholder alone
   greys it in the open list and leaves it black in the closed control. The
   class goes on the select while a placeholder is what it is showing, so
   "< removed >" and "< edited >" read as the non-choices they are. A pill
   group needs no equivalent: an unlit row already says no option is
   selected, where a collapsed select must display something. */
.modal-select.shows-placeholder {
    color: var(--grey-muted);
}


/* ============================================================================
   MODAL ACTIONS BAR
   ============================================================================ */

.modal-actions {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem 1rem;
    border-bottom: var(--border-width) solid var(--grey-border);
    background-color: var(--bg-modal-header);
}

.modal-back-button,
.modal-done-button,
.modal-next-button {
    margin: 0 !important;
    padding: 0 1.25rem !important;
    height: var(--element-height) !important;
    font-size: 0.9rem !important;
}

.modal-back-placeholder {
    visibility: hidden;
    margin: 0 !important;
    padding: 0 1.25rem !important;
    height: var(--element-height) !important;
    font-size: 0.9rem !important;
    width: auto;
    min-width: 70px;
}

/* v10.1: Hide the Summary checkboxes in modals that don't surface that
   affordance (New Report confirmation modal, Process All, Run Checks).
   The .param-summary / .measurement-summary <td> cells are retained so the
   column reserves space and the layout stays balanced with the section-modal
   variant. */
#new-report-modal .param-summary .modal-summary-checkbox,
#modal-process-all .param-summary .modal-summary-checkbox,
#modal-check-report .param-summary .modal-summary-checkbox {
    visibility: hidden;
}


/* ============================================================================
   MODAL STYLES - Group Modals (Right Column Overlay)
   ============================================================================ */

/* v11 5.1: with the review pane permanent, the layout is always three
   columns (330px | 1fr | 330px), so the modal backdrop dims ONLY the centre
   report column and modals centre over it (Pete 2026-07-13). Left and right
   offsets are symmetric — each side column is 330px + its 1rem gap + the
   1rem panel padding = 330px + 2rem, plus the wrapper's centring margin once
   its max-width engages. Measurements AND review stay bright. */
.modal-overlay {
    left: calc(330px + 2rem);
    right: calc(330px + 2rem);
    width: auto;
    background-color: var(--modal-backdrop-light);
}

@media (min-width: calc(1700px + 2rem)) {
    .modal-overlay {
        left: calc((100% - 1700px) / 2 + 330px + 2rem);
        right: calc((100% - 1700px) / 2 + 330px + 2rem);
    }
}

/* ...EXCEPT the New Report modal, which dims the WHOLE page (Pete
   2026-08-12). The centre-column rule above fits a modal that edits the
   report's content — the measurements stay bright because you read them while
   you type. Starting a new report is not that: it is an application-level
   action that replaces everything on screen, so nothing behind it should look
   available. An id beats the class, in the media query too, so this one
   declaration covers every width. */
#new-report-modal {
    left: 0;
    right: 0;
    width: 100%;
}

.modal-overlay.active {
    padding: 5vh 1rem 1rem 1rem;
}

.modal-overlay .modal-content {
    max-width: 750px;
    width: 95%;
}

.modal-overlay .modal-body {
    padding-bottom: 1.5rem;
}


/* ============================================================================
   TEMPLATE OPTIONS TABLE - Dark Theme
   ============================================================================ */

.template-options-table {
    width: 100%;
    border-collapse: collapse;
}

.template-options-table thead {
    position: sticky;
    top: 0;
    z-index: 10;
    background-color: var(--bg-modal-header);
}

.template-options-table thead th {
    color: var(--grey-text);
    font-weight: 600;
    font-size: 0.8rem;
    padding: 0.75rem 0.5rem;
    border-bottom: 2px solid var(--grey-border);
    background-color: var(--bg-modal-header);
}

.template-options-table thead th:first-child {
    text-align: right;
    width: 25%;
    max-width: 220px;
}

/* STALE — leftover from the old 4-column layout (Label | Edit-40px | Value |
   Summary), where nth-child(2) was the 40px pencil/edit column. That column was
   removed; nth-child(2) now targets the "Value"/options column and wrongly tries
   to pin it to 40px. It's currently masked (dropdown/measurement content forces
   the column wider, and a th-summary col-3 lets col-2 take the slack — see
   v10.11 single-check modal fix), but it's misleading. Remove on next cleanup
   pass — the Value column should size automatically. */
.template-options-table thead th:nth-child(2) {
    text-align: center;
    width: 40px;
}

/* v10.x: 3-col layout — Summary is the last column (3rd). The widths and
   alignment for it are set on .th-summary further down in this file (since
   .th-summary needs to win against the :last-child padding rule below);
   here we just make sure the column auto-sizes. */
.template-options-table thead th:nth-child(3) {
    width: auto;
}

.template-options-table tbody td {
    border-bottom: var(--border-width) solid var(--grey-border);
    vertical-align: middle;
    padding: 0.35rem 0.5rem;
    font-size: 0.8rem;
}

.template-options-table tbody td:first-child {
    padding-left: 1rem;
}

.template-options-table tbody td:last-child {
    padding-right: 1rem;
}

.template-options-table thead th:first-child {
    padding-left: 1rem;
}

.template-options-table thead th:last-child {
    padding-right: 1rem;
}

.template-options-table .param-label,
.template-options-table .measurement-label {
    font-weight: var(--font-weight-medium);
    font-size: 0.8rem;
    white-space: nowrap;
    text-align: right;
    padding-right: 1rem;
    width: 220px;
    max-width: 220px;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--grey-text);
}

.template-options-table .param-options,
.template-options-table .measurement-value-cell {
    padding: 0.35rem 0.5rem;
}

.template-options-table .param-options select,
.template-options-table .param-options textarea {
    width: 100%;
    min-width: 250px;
    margin: 0;
    height: var(--element-height);
    font-size: 0.8rem;
}

.template-options-table .param-options textarea,
.template-options-table .modal-textarea {
    height: var(--element-height);
    min-height: var(--element-height);
    resize: none;
    font-family: inherit;
    font-size: 0.8rem;
    line-height: 1.4;
    padding: 0.4rem 0.6rem;
    box-sizing: border-box;
    overflow: hidden;
}

.modal-custom-textarea {
    width: 100%;
    margin-top: 0.5rem !important;
    height: var(--element-height);
    min-height: var(--element-height);
    resize: none;
    font-family: inherit;
    font-size: 0.8rem;
    line-height: 1.4;
    padding: 0.4rem 0.6rem;
    background-color: var(--bg-input);
    color: var(--grey-bright);
    border: var(--border-width) solid var(--grey-border);
    border-radius: var(--border-radius);
    box-sizing: border-box;
    overflow: hidden;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
}

.modal-custom-textarea:focus {
    border-color: var(--interactive);
    outline: none;
    box-shadow: 0 0 0 var(--outline-width) var(--interactive-glow);
}

/* Greyed out dropdown */
/* v8.1.1: greyed-out class removed - dropdown is now hidden during custom text mode */

/* v10.x: Chooser — segmented pill group, an alternative to .modal-select
   for params declared with chooser: true. flex-wrap allows long option
   lists to span multiple lines (config author's call — no fallback).
   Each pill: outlined when unselected, filled with var(--interactive)
   when selected — matches the wider H1-interactive accent language. */
.template-options-table .modal-chooser {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem;
}

.template-options-table .chooser-pill {
    margin: 0;
    padding: 0.25rem 0.75rem;
    height: var(--element-height);
    font-size: 0.85rem;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: var(--border-width) solid var(--grey-border-strong);
    border-radius: var(--border-radius);
    background-color: transparent;
    color: var(--grey-bright);
    cursor: pointer;
    transition: background-color var(--transition),
                border-color var(--transition),
                color var(--transition);
}

.template-options-table .chooser-pill:hover {
    border-color: var(--interactive);
    color: var(--interactive);
}

.template-options-table .chooser-pill.selected {
    background-color: var(--interactive);
    border-color: var(--interactive);
    color: var(--text-inverse);
}

.template-options-table .chooser-pill.selected:hover {
    background-color: var(--interactive-hover);
    border-color: var(--interactive-hover);
}

.template-options-table .chooser-pill:focus {
    outline: none;
    box-shadow: 0 0 0 var(--outline-width) var(--interactive-glow);
}

/* < custom > pill — muted grey + dashed border to read as "different kind of
   choice" (open up a free-text field) rather than another preset option. The
   colour matches the other three placeholders; the dashed border is the
   pill-specific half of the signal. Hover and selected states are a regular
   pill's, so it stays legible once picked. */
.template-options-table .chooser-pill-custom {
    color: var(--grey-muted);
    border-style: dashed;
}

/* v10.x: Merged summary column — hosts the summary checkbox AND any
   modal-auto / modal-check buttons (previously a separate
   .param-actions column to the right). Width auto-grows to fit content;
   white-space: nowrap keeps checkbox + buttons on one line. Dropping the
   fixed 48px width and the trailing column gives the .param-options cell
   substantially more horizontal room for dropdowns / textareas. The cell
   stays display: table-cell so it participates in column-width calculation;
   the inline-flex .modal-summary-cell-content wrapper inside handles
   horizontal split-alignment (checkbox left, actions right). */
.template-options-table .param-summary,
.template-options-table .measurement-summary {
    padding: 0.35rem 0.4rem;
    white-space: nowrap;
    vertical-align: middle;
}

/* v10.x: Summary column header.
   - text-align: left so "Summary" reads from the column's left edge,
     matching the left-aligned checkbox / link button below it.
   - width: 1% is the standard CSS trick to force a table column to
     shrink-to-fit its content: the browser takes max(min-content, 1%) =
     min-content. This overrides the inherited :last-child width: 60px
     hint (which becomes the Summary column in the 3-col layout) and
     lets the Value column take the remaining horizontal space.
   - Appears after the :last-child rule earlier in this file so the
     same-specificity conflict resolves in favour of these declarations. */
.template-options-table thead th.th-summary {
    text-align: left;
    width: 1%;
}

.template-options-table .modal-summary-checkbox {
    margin: 0;
    width: 20px;
    height: 20px;
}

/* Flex wrapper inside each summary-type cell. inline-flex so the td's
   vertical-align: middle keeps it vertically centred in the row; width:
   100% gives margin-left: auto on .modal-summary-actions room to push the
   action group to the right edge. gap: 0.5rem reserves a minimum visible
   space between the checkbox and the actions span — the auto-margin sits
   on top of this gap, so the gap is the floor when the cell is exactly
   content-width (widest row in the column). */
.modal-summary-cell-content {
    display: inline-flex;
    align-items: center;
    width: 100%;
    gap: 0.5rem;
}

/* Right-aligned group of action buttons (modal-auto /
   modal-check). The auto margin consumes whatever horizontal space is left
   over after the checkbox / link button on the cell's left side. */
.modal-summary-actions {
    display: inline-flex;
    align-items: center;
    margin-left: auto;
}

.modal-summary-actions > * + * {
    margin-left: 0.25rem;
}


/* ============================================================================
   MODAL MEASUREMENT ROWS
   ============================================================================ */

/* Measurement rows inherit default background like parameter rows */

.modal-measurement-input-wrapper {
    display: flex;
    align-items: center;
    gap: 4px;
    /* v10.1: span the cell so full-width measurement inputs can stretch to
       the full modal-row width (matches parameter customtext behaviour). */
    width: 100%;
}

.modal-measurement-input {
    width: 80px !important;
    min-width: 0 !important;
    max-width: 80px !important;
    height: var(--element-height);
    padding: 0.3rem 0.5rem;
    font-size: 0.8rem;
    text-align: right;
    background-color: var(--bg-input);
    color: var(--grey-bright);
    border: var(--border-width) solid var(--grey-border);
    border-radius: var(--border-radius);
    margin: 0 !important;
    margin-bottom: 0 !important;
    box-sizing: border-box;
}

/* v10.1: Full-width measurement input in modals now stretches to the row
   width (matches parameter customtext textareas). Previously fixed to
   149px to mirror the constrained main measurements table column. */
.modal-measurement-input.full-width {
    width: 100% !important;
    max-width: 100% !important;
    text-align: left;
}

.modal-measurement-input:focus {
    border-color: var(--interactive);
    outline: none;
    box-shadow: 0 0 0 2px var(--interactive-glow);
}

.modal-measurement-input.calculated {
    background-color: var(--attention-dim);
}

.modal-measurement-input.calculated:focus {
    background-color: var(--attention-dim);
    border-color: var(--attention-strong);
    box-shadow: 0 0 0 2px var(--attention-glow);
}

.modal-measurement-unit {
    color: var(--grey-muted);
    font-size: 0.8rem;
    white-space: nowrap;
    width: 65px;
    flex: 0 0 65px;
    text-align: left;
}

.modal-measurement-input.full-width + .modal-measurement-unit {
    display: none;
}


/* ============================================================================
   MODAL ACTIONS LAYOUT — shared across all modals
   ============================================================================ */

/* Modal action bar spacer/right layout — shared across all modals */
.modal-actions .modal-actions-spacer {
    flex: 1;
}

/* Without spacer: margin-left:auto pushes undo/redo to far right */
.modal-actions .modal-actions-right {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

/* With spacer: flex:1 on right group centers the Done button between them */
.modal-actions .modal-actions-spacer ~ .modal-actions-right {
    flex: 1;
    margin-left: 0;
    justify-content: flex-end;
}

/* Modal undo/redo buttons — use existing icon-button secondary styling, just control layout */
.modal-actions .icon-button.secondary {
    flex-shrink: 0;
}

/* ============================================================================
   v10: SPAN SELECTION & EDITING STATES
   Two-click interaction: first click selects, second click edits.
   ============================================================================ */

/* Focus-family hue (--sel-hue) — 4.8 (d2). Drives BOTH the hover highlight
   (axis 1, above) and the .span-selected paint (below): a span's focus colour
   follows its FAMILY, not its provenance status. Grey (--h2, "text") is the
   editor-wide baseline, so it is inherited by spans without a data-handle (the
   unit sibling, embedded values); the linked TYPES (parameter / ALT(n) /
   summarystring) override to teal (--h1), and their embedded children inherit
   that teal. auto / check keep their own .span-selected rules further
   down (persistent status background — a separate concern).
   [data-type^="alt"] is a prefix match so every ALT level is covered. */
#report-textarea                            { --sel-hue: var(--h2); }
[data-handle][data-type="parameter"],
[data-handle][data-type^="alt"],
[data-handle][data-type="summarystring"]    { --sel-hue: var(--h1); }

/* Selected state — full span highlight, no cursor */
[data-handle].span-selected {
    background-color: color-mix(in srgb, var(--sel-hue) 8%, transparent) !important;
    border-radius: var(--border-radius);
    box-shadow: inset 0 0 0 1px var(--sel-hue) !important;
    cursor: pointer;
    /* Prevent text cursor from appearing on selected spans */
    caret-color: transparent;
}

/* 4.8 stage (b): the .span-editing state class is retired — EDITING is derived
   from the live caret, so an edited span shows the browser's default caret and
   no box. Only SELECTED (no caret) carries a persistent highlight. */

/* Override hover styles when in selected state */
[data-handle].span-selected:hover {
    background-color: color-mix(in srgb, var(--sel-hue) 8%, transparent) !important;
    box-shadow: inset 0 0 0 1px var(--sel-hue) !important;
}

/* Arm-then-delete (2026-09-08, Pete): a measurement value+unit block armed by a
   Backspace/Delete that would otherwise dead-end — the selected-span teal on
   the value wrapper (and the standalone measurement/unit spans); a second
   press removes the block from the report. */
#report-textarea .block-armed,
#report-textarea .block-armed-unit {
    background-color: color-mix(in srgb, var(--h1) 8%, transparent) !important;
    caret-color: transparent;
}
#report-textarea .block-armed {
    border-radius: var(--border-radius);
    box-shadow: inset 0 0 0 1px var(--h1) !important;
}
/* Value + unit read as ONE box (Pete 2026-09-08): the value box drops its
   right edge when a unit follows, the unit box has no left edge. */
#report-textarea .block-armed.block-armed-has-unit {
    border-radius: var(--border-radius) 0 0 var(--border-radius);
    box-shadow: inset 1px 0 0 0 var(--h1), inset 0 1px 0 0 var(--h1), inset 0 -1px 0 0 var(--h1) !important;
}
#report-textarea .block-armed-unit {
    border-radius: 0 var(--border-radius) var(--border-radius) 0;
    box-shadow: inset -1px 0 0 0 var(--h1), inset 0 1px 0 0 var(--h1), inset 0 -1px 0 0 var(--h1) !important;
}

/* Keep auto/check persistent colour visible beneath the selection highlight —
   the :hover variants are REQUIRED: the base [data-handle].span-selected:hover
   is (0,3,0), so without an equally-specific selected+hover rule here a selected
   AND hovered algo span would fall back to the green/teal --sel-hue (the
   check-span-goes-green-on-select+hover bug). Placed after that rule so the tie
   resolves here. */
[data-status="auto"].span-selected,
[data-status="auto"].span-selected:hover {
    background-color: var(--auto-medium) !important;
    box-shadow: inset 0 0 0 1px var(--interactive) !important;
}

.check-mismatch.span-selected,
.check-mismatch.span-selected:hover {
    background-color: var(--check-medium) !important;
    box-shadow: inset 0 0 0 1px var(--check) !important;   /* red border, not the interactive/green selection hue */
}

/* (The manual-selected grey patch here is gone — manual now derives grey from
   --sel-hue in the base .span-selected rule above. 2026-07-24.) */

/* ============================================================================
   v10: SPAN POPOVER
   Shows summary↔report counterpart text with link/unlink toggle.
   ============================================================================ */

.span-popover {
    position: fixed;
    z-index: 10001;
    /* Marginally lighter than the modal/elevated layer so the popover reads
       as floating above it. In light mode this resolves to white-mixed-with-
       white (i.e. no change), so the rule is dark-mode-only in practice. */
    background: color-mix(in srgb, var(--grey-elevated), white 4%);
    border: var(--border-width) solid var(--grey-border);
    border-radius: var(--border-radius);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
    padding: 6px 8px;
    min-width: 120px;
    /* max-width set dynamically to match report textarea */
    font-size: 0.85rem;
}

.span-popover.span-popover--has-text {
    min-width: 400px;
}

/* Light-mode adjustments: the dark-mode shadow is too heavy against a white
   surface, and the modal-style textarea fill (--grey-border #d8d8d8) reads
   as high-contrast inside an otherwise white popover. Soften both. */
[data-theme="light"] .span-popover {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
}

[data-theme="light"] .span-popover-textarea {
    background: var(--grey-base);
}

.span-popover-header {
    display: flex;
    /* flex-start so the label, checkbox and trailing buttons stay anchored
       to the top of the row when the textarea grows multi-line. */
    align-items: flex-start;
    /* Lock the row to single-line-textarea height so toggling the checkbox
       doesn't jump the popover taller; non-textarea items each take this
       height with their content centered (see rules below). */
    min-height: var(--element-height);
    gap: 6px;
}

/* Italic, muted label — mirrors .modal-sub-label in section modals so the
   popover reads as the same affordance. Height matches the single-line
   textarea so it stays vertically centred with the textarea's first line
   regardless of how tall the textarea grows. */
.span-popover-label {
    display: inline-flex;
    align-items: center;
    height: var(--element-height);
    font-style: italic;
    font-size: 0.75rem;
    color: var(--grey-muted);
    flex-shrink: 0;
    white-space: nowrap;
}

.span-popover-link-btn,
.span-popover-close-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    /* Match the row's single-line-textarea height with the icon centred
       inside — keeps buttons vertically aligned with the textarea's first
       line as it grows multi-line. */
    height: var(--element-height);
    padding: 0;
    border: var(--border-width) solid transparent;
    border-radius: var(--border-radius);
    background: transparent;
    cursor: pointer;
    flex-shrink: 0;
}

.span-popover-link-btn.popover-linked {
    color: var(--interactive);
}

.span-popover-link-btn.popover-linked:hover {
    background-color: var(--interactive-dim);
}

.span-popover-link-btn.popover-unlinked {
    color: var(--grey-muted);
}

.span-popover-link-btn.popover-unlinked:hover {
    color: var(--grey-text);
    background-color: var(--bg-surface-hover);
}

.span-popover-close-btn {
    color: var(--grey-muted);
}

.span-popover-close-btn:hover {
    color: var(--grey-text);
    background-color: var(--bg-surface-hover);
}

/* Wrap around the native checkbox so we can vertically centre the (small)
   checkbox glyph inside a single-line-textarea-height box. The wrap itself
   sits at the top of the row (align-items: flex-start on the parent), so as
   the textarea grows multi-line the checkbox stays aligned with the
   textarea's first line rather than drifting downward. */
.span-popover-checkbox-wrap {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: var(--element-height);
    flex-shrink: 0;
}

.span-popover-summary-checkbox {
    margin: 0;
    cursor: pointer;
    flex-shrink: 0;
    transform: scale(0.8);
    transform-origin: center;
}

/* Actions sit next to the checkbox; hidden in narrow (unchecked) state */
.span-popover-actions {
    display: flex;
    gap: 4px;
}

.span-popover:not(.span-popover--has-text) .span-popover-actions {
    display: none;
}

/* Textarea sits inline in the single popover row. Fixed width drives the
   textarea size (textarea inside is width: 100%); min-width: 0 + flex-shrink
   let the cell give way if the popover hits its viewport cap on narrow
   windows. flex-grow stays at 0 — we don't want the cell to balloon if the
   popover is ever wider than intended. */
.span-popover-content {
    flex: 0 1 auto;
    width: 400px;
    min-width: 0;
}

.span-popover-textarea {
    width: 100%;
    min-height: 1.6em;
    max-height: 120px;
    padding: 4px 6px;
    border: var(--border-width) solid var(--grey-border-strong);
    border-radius: var(--border-radius);
    /* Match the section-modal summarystring textarea — slightly lighter than
       the popover background (--grey-elevated) for visual separation. */
    background: var(--grey-border);
    color: var(--grey-bright);
    font-family: inherit;
    font-size: 0.85rem;
    line-height: 1.4;
    resize: none;
    overflow-y: auto;
    box-sizing: border-box;
}

.span-popover-textarea:focus {
    outline: none;
    border-color: var(--interactive);
    box-shadow: 0 0 0 1px var(--interactive-glow);
}

/* ============================================================================
   IMPORT MODAL SPECIFIC
   ============================================================================ */

/* Import-modal control area — one header-style strip beneath the modal-header,
   with a border-bottom divider so the import modal reads as the section-modal
   "header row then body" pattern:
     [parse-config dropdown (visible ~200px → text area ~158px)] [cog] [Import] [Clear]
   The .format-selector itself is just a flex column wrapper — no padding,
   bg, or gap of its own; the .format-row provides those (matching
   .modal-actions). */
.format-selector {
    display: flex;
    flex-direction: column;
}

.format-selector .format-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.5rem 1rem;
    border-bottom: var(--border-width) solid var(--grey-border);
    background-color: var(--bg-modal-header);
}

.format-selector label {
    margin: 0;
    font-weight: var(--font-weight-medium);
    white-space: nowrap;
    color: var(--grey-text);
}

/* Visible dropdown ~200px (border-box). The select reserves ~32px on the
   right for the dropdown-arrow background image plus ~10px of side/
   borders, so the actual option-text area is ~158px — what the user sees
   as the "dropdown width". */
.format-selector select {
    width: 200px;
    margin: 0;
}

/* Restore explicit flex-centring on button text — the default `button`
   rule has height: 32px but line-height: 1.5 × 0.9rem (~21.6px) plus
   0.5rem vertical padding overflows the box, so text drifts off the
   vertical centre without inline-flex centring. */
.format-selector button {
    margin: 0;
    font-size: 0.9rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

#report {
    width: calc(100% - 2rem);
    min-height: 300px;
    font-family: var(--font-family-mono);
    font-size: 0.85rem;
    resize: vertical;
    margin: 0 1rem 1rem 1rem;
    background-color: var(--bg-input);
    color: var(--grey-bright);
}


/* ============================================================================
   UTILITY CLASSES
   ============================================================================ */

.text-muted {
    color: var(--grey-text);
}

.text-small {
    font-size: 0.85rem;
}

.hidden {
    display: none !important;
}


/* ============================================================================
   PASSWORD GATE OVERLAY - Dark Theme
   ============================================================================ */

#password-gate-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: linear-gradient(135deg, var(--grey-base) 0%, var(--grey-surface) 100%);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 999999;
    opacity: 1;
    transition: opacity 0.3s ease;
}

#password-gate-overlay.fade-out {
    opacity: 0;
}

.password-gate-modal {
    background: var(--grey-surface);
    border-radius: var(--border-radius-lg);
    padding: 2.5rem 3rem;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
    max-width: 400px;
    width: 90%;
    text-align: center;
    border: var(--border-width) solid var(--grey-border);
}

.password-gate-header h1 {
    margin: 0 0 0.5rem 0;
    font-size: 1.75rem;
    font-weight: var(--font-weight-bold);
    color: var(--interactive);
    letter-spacing: -0.5px;
}

.password-gate-header p {
    margin: 0 0 1.5rem 0;
    font-size: 0.9rem;
    color: var(--grey-text);
    font-weight: var(--font-weight-normal);
}

.password-gate-form {
    margin-bottom: 1.25rem;
}

.password-gate-input-group {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 1rem;
}

#password-gate-input {
    width: 250px;
    height: 40px;
    padding: 0 1rem;
    font-size: 1rem;
    background-color: var(--bg-input);
    color: var(--grey-bright);
    border: var(--border-width) solid var(--grey-border);
    border-radius: var(--border-radius);
    outline: none;
    transition: border-color var(--transition), box-shadow var(--transition);
}

#password-gate-input:focus {
    border-color: var(--interactive);
    box-shadow: 0 0 0 3px var(--interactive-glow);
}

#password-gate-input::placeholder {
    color: var(--grey-muted);
}

#password-gate-submit {
    width: 120px;
    height: 40px;
    padding: 0 1.25rem;
    font-size: 0.95rem;
    font-weight: 600;
    background-color: var(--interactive);
    color: var(--text-inverse);
    border: var(--border-width) solid var(--interactive);
    border-radius: var(--border-radius);
    cursor: pointer;
    transition: background-color var(--transition), border-color var(--transition);
}

#password-gate-submit:hover:not(:disabled) {
    background-color: var(--interactive-hover);
    border-color: var(--interactive-hover);
}

#password-gate-submit:active:not(:disabled) {
    transform: scale(0.98);
}

#password-gate-submit:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.password-gate-error {
    color: var(--status-error);
    font-size: 0.85rem;
    min-height: 1.25rem;
    margin-top: 0.5rem;
}

@keyframes password-gate-shake {
    0%, 100% { transform: translateX(0); }
    10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); }
    20%, 40%, 60%, 80% { transform: translateX(5px); }
}

.password-gate-form.shake {
    animation: password-gate-shake 0.5s ease;
}

@media (max-width: 480px) {
    .password-gate-modal {
        padding: 2rem 1.5rem;
    }
    
    #password-gate-input,
    #password-gate-submit {
        width: 100%;
    }
}

/* ============================================================================
   FRESH START MODAL
   ============================================================================ */

/* Full-page overlay (override the right-column-only default) */
#fresh-start-modal.modal-overlay {
    left: 0;
    right: 0;
    width: 100%;
    background-color: rgba(0, 0, 0, 0.85);
    z-index: 99999;
}

#fresh-start-modal .modal-content {
    max-width: 400px;
    width: 90%;
}

#fresh-start-modal .modal-header {
    justify-content: center;
    position: relative;
}

#fresh-start-modal .modal-header h2 {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    text-align: center;
}

#fresh-start-modal .modal-header .close-button {
    position: absolute;
    right: 0.75rem;
    top: 50%;
    transform: translateY(-50%);
}

#fresh-start-modal .modal-header-icon {
    color: var(--interactive);
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
}

#fresh-start-modal .modal-header-icon svg {
    width: 22px;
    height: 22px;
}

#fresh-start-modal .modal-body {
    padding: 1.25rem;
}

/* Session list */
.fs-list {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

/* Session item - div-based clickable container */
.fs-item {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    padding: 0.875rem 1rem;
    background: var(--grey-surface);
    border: 1px solid var(--grey-border);
    border-radius: 6px;
    cursor: pointer;
    text-align: left;
    color: inherit;
    font-family: inherit;
    font-size: inherit;
    transition: border-color 0.15s ease, background-color 0.15s ease;
    user-select: none;
    -webkit-user-select: none;
    box-sizing: border-box;
    overflow: hidden;
}

.fs-item:hover {
    border-color: var(--interactive);
    background: var(--grey-elevated);
}

.fs-item:focus {
    outline: none;
    border-color: var(--interactive);
    box-shadow: 0 0 0 2px var(--interactive-glow);
}

.fs-item-new {
    background: var(--grey-elevated);
    border-color: var(--grey-border-strong);
}

/* Danger/destructive action item */
.fs-item-danger {
    border-color: var(--grey-border);
    opacity: 0.85;
}

.fs-item-danger:hover {
    border-color: var(--status-error);
    background: color-mix(in srgb, var(--h5) 8%, transparent);
}

.fs-item-danger:focus {
    border-color: var(--status-error);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--h5) 15%, transparent);
}

.fs-item-danger .fs-name {
    color: var(--status-error);
}

.fs-item-danger .fs-name svg {
    stroke: var(--status-error);
}

/* Row inside session item */
.fs-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
    min-width: 0;
    gap: 0.75rem;
}

.fs-row + .fs-row {
    margin-top: 0.375rem;
}

/* Template name */
.fs-name {
    display: flex;
    align-items: center;
    font-weight: 500;
    font-size: 0.95rem;
    color: var(--grey-bright);
    min-width: 0;
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fs-name svg {
    width: 16px;
    height: 16px;
    margin-right: 0.5rem;
    flex-shrink: 0;
}

/* Timestamp */
.fs-time {
    font-size: 0.85rem;
    color: var(--grey-text);
}

/* Status badges */
.fs-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.2rem 0.5rem;
    border-radius: 4px;
    font-size: 0.75rem;
    font-weight: 500;
    white-space: nowrap;
}

.fs-badge svg {
    width: 12px;
    height: 12px;
}

.fs-badge-ok {
    background: var(--interactive-muted);
    color: var(--grey-text);
}

.fs-badge-freeze {
    background: var(--attention-muted);
    color: var(--grey-muted);
}

/* Frozen report visual indicator */
#report-textarea.text-frozen {
    border-style: dashed;
}

/* Section divider */
.fs-divider {
    display: flex;
    align-items: center;
    margin: 1.25rem 0 0.75rem;
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--grey-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.fs-divider::before,
.fs-divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--grey-border);
}

.fs-divider span {
    padding: 0 0.75rem;
}

/* Danger divider variant */
.fs-divider-danger {
    margin-top: 1.5rem;
    color: var(--grey-muted);
}

.fs-divider-danger::before,
.fs-divider-danger::after {
    background: var(--grey-border);
}

/* v11 5.3 UX-mode trial: divider for the UX Mode section (same shape). */
[data-theme="light"] .fs-item-danger .fs-name,
[data-theme="light"] .fs-item-danger .fs-name svg {
    color: color-mix(in oklch, var(--h5), #cc0000 70%);
    stroke: color-mix(in oklch, var(--h5), #cc0000 70%);
}

/* Empty state */
.fs-empty {
    padding: 1.5rem;
    text-align: center;
    color: var(--grey-text);
}

.fs-empty p {
    margin: 0;
}

/* =============================================================================
   HELP MODAL STYLES
   ============================================================================= */

/* Modal container */
.help-modal-content {
    max-width: 700px;
    max-height: 85vh;
    display: flex;
    flex-direction: column;
}

.help-modal-body {
    flex: 1;
    overflow-y: auto;
    padding: 1.5rem;
}

/* Tab navigation - uses base button styles via .secondary class */
/* Wraps to a second row rather than overflowing. The strip's width is NOT a
   function of the viewport width: .modal-overlay is inset by 330px + 2rem on
   each side for the three-column layout, so the modal is (viewport - 660px -
   4rem) wide, capped at 750px. Seven tabs need ~700px of strip and so spill
   out of the modal on any window narrower than ~1450px — which is why this
   must wrap unconditionally and cannot be left to a max-width media query
   (the one at the foot of this block measures the wrong axis). */
.help-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 1rem;
    background: var(--grey-surface);
    border-bottom: 1px solid var(--grey-border);
}

.help-tab {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    white-space: nowrap;
}

.help-tab:focus {
    box-shadow: none;
}

/* Tab content panels */
.help-tab-content {
    display: none;
}

.help-tab-content.active {
    display: block;
}

/* Content headings */
.help-tab-content h3 {
    margin: 0 0 1rem 0;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid var(--grey-border);
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--grey-bright);
}

.help-tab-content h3:not(:first-child) {
    margin-top: 1.75rem;
}

/* Content sections */
.help-section {
    margin-bottom: 1.25rem;
}

.help-section h4 {
    margin: 0 0 0.5rem 0;
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--grey-bright);
}

.help-section p {
    margin: 0 0 0.5rem 0;
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--grey-text);
}

.help-section p:last-child {
    margin-bottom: 0;
}

.help-section ul {
    margin: 0.5rem 0;
    padding-left: 1.5rem;
    font-size: 0.9rem;
    line-height: 1.6;
    color: var(--grey-text);
}

.help-section ul li {
    margin-bottom: 0.25rem;
}

.help-section strong {
    font-weight: 600;
    color: var(--grey-bright);
}

/* Clinical references tab — one block per reference. */
.help-reference {
    margin-bottom: 0.9rem;
    padding-left: 0.6rem;
    border-left: var(--border-width) solid var(--grey-border);
}

.help-reference:last-child {
    margin-bottom: 0;
}

.help-section .help-reference-name {
    margin-bottom: 0.15rem;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--grey-bright);
}

.help-section .help-reference-citation {
    margin-bottom: 0.15rem;
    font-size: 0.8rem;
    line-height: 1.45;
    color: var(--grey-text);
}

.help-section .help-reference-doi {
    margin-bottom: 0;
    font-size: 0.75rem;
    color: var(--grey-muted);
    overflow-wrap: anywhere;
}

/* Video container */
.video-container {
    position: relative;
    width: 100%;
    max-width: 800px;
    margin: 1rem auto;
    background: var(--grey-elevated);
    border-radius: 4px;
    overflow: hidden;
    border: 1px solid var(--grey-border);
}

.video-container video {
    width: 100%;
    height: auto;
    display: block;
    background: var(--grey-base);
}

.video-caption {
    text-align: center;
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--grey-text);
    margin: 0.5rem 0 1.5rem 0;
}

.download-link {
    color: var(--interactive);
    text-decoration: none;
    margin-left: 0.5rem;
}

.download-link:hover {
    color: var(--interactive-hover);
    text-decoration: underline;
}

/* Tables */
.help-table {
    width: 100%;
    margin: 0.75rem 0;
    font-size: 0.9rem;
    border-collapse: collapse;
}

.help-table td {
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid var(--grey-border);
    color: var(--grey-text);
}

.help-table tr:last-child td {
    border-bottom: none;
}

.help-table td:first-child {
    width: 45%;
    font-weight: 500;
    color: var(--grey-bright);
}

.help-table-summary td:first-child {
    width: 40%;
}

.help-table-summary td:last-child strong {
    color: var(--interactive);
}

.help-table kbd {
    display: inline-block;
    padding: 0.15rem 0.4rem;
    font-family: inherit;
    font-size: 0.8rem;
    color: var(--grey-bright);
    background: var(--grey-elevated);
    border: 1px solid var(--grey-border);
    border-radius: 3px;
}

/* Document link section */
.help-contact {
    margin-top: 1.5rem;
    text-align: center;
}

.help-contact p {
    margin: 0;
}

/* Document link styled as button */
.help-doc-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: var(--element-height);
    padding: 0 1rem;
    font-size: 0.9rem;
    font-weight: var(--font-weight-normal);
    text-align: center;
    text-decoration: none;
    color: var(--text-inverse);
    background-color: var(--interactive);
    border: var(--border-width) solid var(--interactive);
    border-radius: var(--border-radius);
    transition: background-color var(--transition), border-color var(--transition);
}

.help-doc-link:hover {
    text-decoration: none;
    color: var(--text-inverse);
    background-color: var(--interactive-hover);
    border-color: var(--interactive-hover);
}

/* About tab */
.help-about-header {
    margin-bottom: 1.5rem;
    padding-bottom: 1rem;
    text-align: center;
    border-bottom: 1px solid var(--grey-border);
}

.help-about-header h3 {
    margin: 0;
    padding: 0;
    font-size: 1.5rem;
    border: none;
}

.help-version {
    margin: 0.25rem 0 0 0;
    font-size: 0.95rem;
    color: var(--grey-text);
}

.help-copyright {
    margin-top: 2rem;
    padding-top: 1rem;
    text-align: center;
    border-top: 1px solid var(--grey-border);
}

.help-copyright p {
    color: var(--grey-muted);
}

.help-legal-note {
    font-size: 0.8rem;
    margin-top: 0.5rem;
}

/* Responsive. NB the tab strip is deliberately absent here — it wraps at every
   width (see .help-tabs). The horizontal-scroll rule that used to live here
   never fired, because the modal runs out of room long before the viewport
   reaches 600px. */
@media (max-width: 600px) {
    .help-tab {
        padding: 0.6rem 0.75rem;
        font-size: 0.85rem;
    }
    
    .help-modal-content {
        max-height: 90vh;
    }
    
    .help-modal-body {
        padding: 1rem;
    }
}

/* ============================================================================
   SECURITY TAB STYLES
   ============================================================================ */

/* Security check status indicators */
.security-check {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 1rem;
    border-radius: 4px;
    margin: 0.5rem 0;
    font-size: 0.9rem;
}

.security-check.pending {
    background: var(--grey-elevated);
    border: 1px solid var(--grey-border);
    color: var(--grey-text);
}

.security-check.pass {
    background: var(--interactive-muted);
    border: 1px solid var(--interactive-glow);
    color: var(--interactive);
}

.security-check.fail {
    background: var(--abnormal-bg);
    border: 1px solid var(--abnormal-border);
    color: var(--status-error);
}

.security-check.warn {
    background: var(--auto-muted);
    border: 1px solid var(--auto-glow);
    color: var(--auto);
}

.security-check.neutral {
    background: var(--grey-surface);
    border: 1px solid var(--grey-border);
    color: var(--grey-text);
}

.security-check .security-icon {
    font-size: 1.1rem;
    min-width: 1.5rem;
    text-align: center;
}

.security-check .security-text {
    flex: 1;
}

/* Security details box */
.security-details {
    background: var(--grey-surface);
    border: 1px solid var(--grey-border);
    border-radius: 4px;
    padding: 0.75rem 1rem;
    margin-top: 0.5rem;
    font-size: 0.85rem;
}

.security-details code {
    background: var(--grey-elevated);
    padding: 0.15rem 0.4rem;
    border-radius: 3px;
    font-family: var(--font-family-mono);
    font-size: 0.8rem;
    word-break: break-all;
}

.security-details ol {
    margin: 0.5rem 0;
    padding-left: 1.5rem;
}

.security-details li {
    margin: 0.25rem 0;
}

/* Security table cells */
.help-table-security td.security-cell {
    text-align: right;
    white-space: nowrap;
}

.security-cell .security-icon {
    display: inline-block;
    width: 1.2rem;
    text-align: center;
    margin-right: 0.25rem;
}

.security-cell .security-icon.pass { color: var(--interactive); }
.security-cell .security-icon.fail { color: var(--status-error); }
.security-cell .security-icon.neutral { color: var(--grey-text); }

/* Compact table for localStorage */
.help-table-compact {
    font-size: 0.85rem;
}

.help-table-compact td,
.help-table-compact th {
    padding: 0.4rem 0.75rem;
}

/* Test button */
.help-button-test {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--interactive-neutral);
    color: var(--grey-bright);
    border: 1px solid var(--grey-border-strong);
    padding: 0.5rem 1rem;
    border-radius: 4px;
    cursor: pointer;
    font-size: 0.9rem;
    transition: background-color 0.15s ease;
}

.help-button-test:hover {
    background: var(--interactive-neutral-hover);
}

/* Security intro text */
.help-security-intro {
    color: var(--grey-text);
    font-size: 0.9rem;
    margin-bottom: 1.5rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--grey-border);
}

/* Help note */
.help-note {
    font-size: 0.85rem;
    color: var(--grey-muted);
    margin-top: 0.75rem;
}

/* Light mode overrides */
[data-theme="light"] .help-button-test {
    color: var(--text-inverse) !important;
}

[data-theme="light"] .security-check.pending {
    background: var(--grey-surface);
    border-color: var(--grey-border);
}

[data-theme="light"] .security-check.pass {
    background: var(--interactive-subtle);
    border-color: var(--interactive-glow);
    color: var(--interactive);
}

[data-theme="light"] .security-check.fail {
    background: var(--abnormal-bg);
    border-color: var(--abnormal-border);
    color: var(--status-error);
}

[data-theme="light"] .security-details {
    background: var(--grey-surface);
    border-color: var(--grey-border);
}

[data-theme="light"] .security-details code {
    background: var(--grey-base);
}

/* ============================================================================
   REFERENCE RANGE TOOLTIPS
   Hover tooltips showing BSE reference range grading for measurements.
   Append to style.css.
   ============================================================================ */

.ref-tooltip {
    display: none;
    position: absolute;
    z-index: 1200;
    min-width: 180px;
    padding: 8px 12px;
    border-radius: var(--border-radius);
    border: var(--border-width) solid var(--grey-border-strong);
    background: var(--grey-elevated);
    color: var(--grey-bright);
    font-size: 0.78rem;
    line-height: 1.4;
    white-space: nowrap;
    pointer-events: none;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.35);
}

.ref-tooltip-title {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 16px;
    font-weight: 600;
    margin-bottom: 4px;
    padding-bottom: 4px;
    border-bottom: var(--border-width) solid var(--grey-border);
}

.ref-tooltip-unit {
    font-weight: 400;
    font-size: 0.72rem;
}

.ref-tooltip-table {
    border-collapse: collapse;
    width: 100%;
}

.ref-tooltip-table td {
    padding: 1px 0;
    vertical-align: top;
}

.ref-tooltip-label {
    padding-right: 16px;
}

.ref-tooltip-range {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Gender/age context note */
.ref-tooltip-note {
    margin-top: 4px;
    padding-top: 4px;
    border-top: var(--border-width) solid var(--grey-border);
    font-size: 0.7rem;
    font-style: italic;
}

/* Source attribution */
.ref-tooltip-source {
    margin-top: 2px;
    font-size: 0.65rem;
    color: var(--grey-muted);
    opacity: 0.7;
}

/* Light theme adjustments */
[data-theme="light"] .ref-tooltip {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
}

/* ============================================================================
   ALGORITHM TRACE TOOLTIPS (v10.10)
   Hover tooltips on algorithm-set parameter statements showing the pathway,
   the inputs read & compared, and the deciding step. Mirrors .ref-tooltip but
   wraps multi-line content and carries a per-tier left accent
   (auto = teal).
   ============================================================================ */

.algo-tooltip {
    display: none;
    position: absolute;
    z-index: 1200;
    min-width: 240px;
    max-width: 440px;
    padding: 8px 12px;
    border-radius: var(--border-radius);
    border: var(--border-width) solid var(--grey-border-strong);
    border-left: 3px solid var(--algo-accent, var(--grey-border-strong));
    background: var(--grey-elevated);
    color: var(--grey-bright);
    font-size: 0.78rem;
    line-height: 1.4;
    white-space: normal;
    pointer-events: none;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.35);
}

.algo-tooltip-auto { --algo-accent: var(--auto-strong); --algo-hue: var(--h3); }
/* Check-tier provenance (2026-07-20): red-family tint matching the check paint. */
.algo-tooltip-check { --algo-accent: var(--check-strong); --algo-hue: var(--h5); }

.algo-tooltip-title {
    font-weight: 600;
    text-align: center;
    margin-bottom: 4px;
    padding-bottom: 4px;
    border-bottom: var(--border-width) solid var(--grey-border);
}

/* Guideline line under the algorithm name. Matches .ref-tooltip-source so
   provenance reads the same wherever it appears. */
.algo-tooltip-reference {
    display: block;
    font-weight: 400;
    font-size: 0.65rem;
    color: var(--grey-muted);
    opacity: 0.7;
    margin-top: 2px;
    overflow-wrap: anywhere;
}

/* ============================================================================
   Flowchart tooltip (v10.10 model/view split)
   processParameter (2-col) / processMeasurement (3-col: box · verdict · value)
   / decision (arrow) / result / flag. Accent + hue come from the tier classes
   (.algo-tooltip-auto) above.
   ============================================================================ */

/* One grid for the whole flow so columns line up tooltip-wide (scan straight
   down). Criterion rows use display:contents so their box/verdict/value cells
   become direct grid items in the shared 3 columns; every other row spans all
   columns. The auto verdict/value columns size to their widest content, so every
   verdict starts at the same x and every value right-edge aligns. */
.algo-flow {
    display: grid;
    /* box + verdict size to content (verdict sits close to the boxes); the value
       column takes the slack, so any white-space falls between verdict and value. */
    grid-template-columns: auto auto 1fr;
    column-gap: 12px;
    row-gap: 3px;
    align-items: center;
    margin-top: 2px;
}
.algo-row { grid-column: 1 / -1; }
.algo-crit { display: contents; }

/* processParameter row (e.g. Rhythm) */
.algo-param {
    display: flex;
    justify-content: space-between;
    gap: 8px;
    padding: 2px 0;
}
.algo-param-label { font-size: 0.7rem; font-weight: 600; color: var(--grey-muted); }
.algo-param-val { color: var(--grey-bright); font-weight: 600; }

/* group heading */
.algo-proc-head {
    margin-top: 4px;
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--grey-muted);
}

/* col 1 — physical flowchart "process" box */
.algo-box-cell { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; }
.algo-box {
    display: inline-block;
    font-family: monospace;
    font-weight: 600;
    color: var(--grey-bright);
    border: var(--border-width) solid var(--grey-border-strong);
    border-radius: var(--border-radius);
    padding: 1px 6px;
    background: color-mix(in srgb, var(--grey-border) 28%, transparent);
}
.algo-box-qual {
    margin-top: 1px;
    font-size: 0.68rem;
    font-style: italic;
    color: var(--grey-muted);
}

/* col 2 — verdict (left-aligned; shared column width keeps all rows in line).
   Every verdict carries the SAME box (padding/radius) so the text stays aligned;
   only the background differs — transparent when not triggered. */
.algo-verdict {
    font-weight: 600;
    text-align: left;
    white-space: nowrap;
    padding: 0 6px;
    border-radius: var(--border-radius);
    background: transparent;
}
/* "triggered" (criterion met) — matches the result row: bright text on a subtle
   hue tint. No / Unavailable keep the plain (calm) style. */
.algo-verdict-yes {
    color: var(--grey-bright);
    background: color-mix(in srgb, var(--algo-hue, transparent) 14%, transparent);
}
.algo-verdict-no { color: var(--grey-muted); }
.algo-verdict-unavailable { color: var(--grey-muted); font-weight: 500; font-style: italic; }

/* col 3 — value(s) */
.algo-val-cell { display: flex; flex-direction: column; align-items: flex-end; text-align: right; }
.algo-val { color: var(--grey-bright); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* a measured value that crosses its threshold — same result-style tint as the
   triggered verdict, for a consistent "triggered" look across both columns. */
.algo-val-trig {
    color: var(--grey-bright);
    font-weight: 700;
    background: color-mix(in srgb, var(--algo-hue, transparent) 14%, transparent);
    border-radius: var(--border-radius);
    padding: 0 5px;
}

/* outcome arrow row */
.algo-decision {
    position: relative;
    padding: 3px 0 3px 20px;
    color: var(--grey-bright);
}
.algo-decision::before {
    content: "▸";
    position: absolute;
    left: 2px;
    top: 1px;
    font-size: 1.05rem;
    line-height: 1.25;
    color: var(--algo-hue, var(--grey-border-strong));
}

/* pathway branch node (AF / impaired / normal) — styled to match the result box */
.algo-decision-node {
    margin: 5px 0;
    padding: 5px 8px;
    border-radius: var(--border-radius);
    border-left: 2px solid var(--algo-accent, var(--grey-border-strong));
    background: color-mix(in srgb, var(--algo-hue, transparent) 14%, transparent);
    color: var(--grey-bright);
    font-weight: 600;
}

/* result — the verbatim output, emphasised */
.algo-result {
    margin-top: 6px;
    padding: 5px 8px;
    border-radius: var(--border-radius);
    border-left: 2px solid var(--algo-accent, var(--grey-border-strong));
    background: color-mix(in srgb, var(--algo-hue, transparent) 14%, transparent);
    color: var(--grey-bright);
    font-weight: 600;
}
.algo-result-unable {
    font-style: italic;
    font-weight: 500;
    color: var(--grey-muted);
}

/* secondary flags (e.g. HFpEF) — beneath the result */
.algo-flag {
    margin-top: 5px;
    padding: 3px 8px;
    font-size: 0.72rem;
    border-left: 2px solid var(--algo-accent, var(--grey-border-strong));
    color: var(--grey-muted);
}
.algo-flag-id { font-weight: 600; color: var(--algo-accent, var(--grey-bright)); }
.algo-flag-text { margin-left: 6px; }

/* Light theme adjustments */
[data-theme="light"] .algo-tooltip {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
}

/* ============================================================================
   REVIEW-QUEUE PANEL (v11 5.1) — a PERMANENT right column (Pete 2026-07-13):
   always present; shows a placeholder when the state carries no algorithms.
   A pure projection of registry + check state.
   ============================================================================ */

#review-panel {
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow: hidden;
    min-width: 0;
    /* v11 5.1: transparent column wrapper (see #measurements-panel). */
    gap: 0.5rem;
}

/* v11 5.1: .col-header supplies the card chrome + height; the header just
   tightens the gap between the big Auto button and the small checks button. */
#review-panel-bar {
    gap: 0.4rem;
}

/* v11 5.2: big "Auto" (Process All) fills the header; small checks-review
   button sits beside it. */
#review-auto {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 1;
    height: var(--element-height);
    margin: 0;
    line-height: 1;
    background-color: var(--interactive);
    color: var(--text-inverse);
    border: none;
    border-radius: var(--border-radius);
    cursor: pointer;
}

#review-auto:hover {
    background-color: var(--interactive-hover);
}

/* v11 5.2: checks button — red fill with a white flag outline (matching the
   check styling elsewhere), distinct from the blue Auto button. */
#review-run-checks {
    margin: 0;
    flex-shrink: 0;
    background-color: var(--check);
    color: var(--text-inverse);
    border: none;
}

#review-run-checks:hover {
    background-color: var(--check-hover);
}

#review-queue {
    flex: 1;
    overflow-y: auto;
    padding: 0.5rem;
    min-width: 0;
}

.review-queue-empty {
    font-size: 0.8rem;
    color: var(--grey-muted);
    text-align: center;
    padding: 1rem 0.5rem;
}

/* v11 5.3 addendum: the "N statements already match algorithm suggestions"
   note — context, not a queue row; muted teal so it reads as automation
   provenance without competing with live tiles. Click expands the matching
   statements; each entry can show its derivation (reuses the tile
   provenance pane styling); [✓] dismisses. */
/* Pane units: vertically condensed — title + sub-line, [⋯] button
   right-aligned at the top. Set (audit tile) = auto hue (teal); check
   (exception row / check tile) = the mismatch hue (red). */
.review-unit {
    border-radius: var(--border-radius);
    padding: 0.4rem 0.55rem;
    margin-bottom: 0.5rem;
    transition: opacity 0.25s ease, transform 0.25s ease;
}

.review-unit-set {
    background-color: var(--auto-muted);
    box-shadow: inset 0 0 0 1px var(--auto-strong);
}

.review-unit-check {
    background-color: var(--check-muted);
    box-shadow: inset 0 0 0 1px var(--check-strong);
}

.review-unit-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.4rem;
}

.review-unit-title {
    font-size: 0.7rem;
    font-weight: 500;
    letter-spacing: 0.01em;
    text-transform: uppercase;
    color: var(--grey-muted);
    min-width: 0;
    overflow-wrap: anywhere;
    padding-top: 2px;
}

.review-unit-buttons {
    display: flex;
    gap: 0.25rem;
    flex-shrink: 0;
}

.review-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    padding: 0;
    margin: 0;
    border: none;
    border-radius: var(--border-radius);
    background: transparent;
    color: var(--grey-bright);
    cursor: pointer;
}

.review-btn:hover {
    background-color: var(--interactive-muted);
}

.review-btn:disabled {
    opacity: 0.4;
    cursor: default;
}

.review-unit-value {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--grey-bright);
    margin-top: 0.1rem;
    overflow-wrap: anywhere;
}

.review-unit-sub {
    font-size: 0.76rem;
    color: var(--grey-muted);
    margin-top: 0.1rem;
    overflow-wrap: anywhere;
}

.review-unit-note {
    font-size: 0.72rem;
    font-style: italic;
    color: var(--grey-muted);
    margin-top: 0.15rem;
}

/* v11 5.3 tile provenance: the audit tile's / exception row's
   derivation pane — the algorithm flowchart rendered INLINE in the tile.
   Mirrors .algo-tooltip's look (background, accent bar, typography) minus
   the floating chrome; the inner .algo-* classes are shared with the
   hover tooltip, and the teal accent vars match .algo-tooltip-auto. */
.review-unit-provenance {
    --algo-accent: var(--auto-strong);
    --algo-hue: var(--h3);
    margin-top: 0.4rem;
    padding: 6px 8px;
    border-radius: var(--border-radius);
    border: var(--border-width) solid var(--grey-border-strong);
    border-left: 3px solid var(--algo-accent);
    background: var(--grey-elevated);
    color: var(--grey-bright);
    font-size: 0.74rem;
    line-height: 1.4;
    white-space: normal;
    cursor: default;
}

/* v11 5.2: "N to resolve" counter — the Confirm-and-copy / Freeze gate. */
