/* EDF Viewer Styles */

:root {
    /* Accent (teal) */
    --accent: #0d7d7d;
    --accent-hover: #0a6363;
    --accent-light: #5fb8b8;
    --accent-bg: #e3f4f4;
    --accent-bg-strong: #cceaea;
    --accent-text: #0a6363;

    /* Neutrals (slate) */
    --gray-50: #f8fafc;
    --gray-100: #f1f5f9;
    --gray-200: #e2e8f0;
    --gray-300: #cbd5e1;
    --gray-400: #94a3b8;
    --gray-500: #64748b;
    --gray-600: #475569;
    --gray-700: #334155;
    --gray-800: #1e293b;

    /* Semantic */
    --success: #16a34a;
    --success-hover: #15803d;
    --success-hover-border: #166534;
    --danger: #dc2626;
    --danger-hover: #b91c1c;

    --font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

    /* Width of the montage dock. Declared here rather than left to a fallback because
       five separate rules have to agree on it - the dock itself, the EEG container it
       takes the space from, the DSA strip below it, and the watermark that has to
       step aside for it. */
    --montage-dock-width: 340px;
}

* {
    box-sizing: border-box;
}

body {
    margin: 0;
    padding: 0;
    font-family: var(--font-family);
    background-color: var(--gray-100);
}

/* Professional Header Bar */
.header-bar {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 40px;
    background-color: var(--gray-50);
    border-bottom: 1px solid var(--gray-200);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 15px;
    z-index: 1000;
    font-size: 13px;
}

.header-left,
.header-right {
    display: flex;
    align-items: center;
    gap: 10px;
}

.header-center {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 1;
    justify-content: center;
}

/* Groups the primary display/filter/time controls into one visual cluster */
.header-group {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 8px;
    background-color: #fff;
    border: 1px solid var(--gray-200);
    border-radius: 6px;
}

/* Header Buttons */
.header-btn {
    padding: 4px 12px;
    border: 1px solid var(--gray-300);
    border-radius: 3px;
    background-color: #fff;
    color: var(--gray-700);
    font-size: 13px;
    cursor: pointer;
    transition: all 0.2s;
}

.header-btn.primary {
    background-color: var(--accent);
    color: white;
    border-color: var(--accent);
}

.header-btn.secondary {
    background-color: #fff;
    color: var(--gray-600);
    border-color: var(--gray-300);
}

.header-btn:hover {
    background-color: var(--gray-100);
}

.header-btn.primary:hover {
    background-color: var(--accent-hover);
}

.header-btn.secondary:hover {
    background-color: var(--gray-100);
    border-color: var(--gray-400);
    color: var(--gray-700);
}

/* Clip menu ------------------------------------------------------------------
   The two mark buttons used to sit in the header as solid green .scissors buttons -
   the loudest block of colour in the bar, and lit at full strength even with nothing
   marked. They are now items in this dropdown, on the same pattern as Tools, and the
   trigger only takes colour once something is actually marked. */
.clip-menu-wrap {
    position: relative;
    display: flex;
    align-items: center;
}

/* Fixed, so the dot that appears once a mark is set cannot widen it. */
.clip-btn {
    width: 68px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    padding: 4px 0;
}

.clip-btn.open {
    background-color: var(--accent-bg);
    border-color: var(--accent-light);
    color: var(--accent-text);
}

.clip-btn.open .tools-caret {
    color: var(--accent-text);
}

/* Something is marked. Green because that is what the markers are drawn in on the
   canvas, but as a tint rather than a fill - it is a status, not a call to action. */
.clip-btn.marked {
    background-color: rgba(22, 163, 74, 0.12);
    border-color: var(--success);
    color: var(--success);
}

.clip-btn.marked:hover {
    background-color: rgba(22, 163, 74, 0.2);
}

.clip-btn.marked .tools-caret {
    color: var(--success);
}

/* Right-aligned: this one hangs off the end of the header, and .tools-menu's centring
   would push it past the viewport edge. Qualified with .tools-menu rather than left
   bare - the two selectors otherwise tie on specificity and .tools-menu, being later
   in the file, would win. */
.tools-menu.clip-menu {
    width: 232px;
    left: auto;
    right: 0;
    transform: none;
}

/* A time that has been marked, shown in the item's own hint line. */
.tools-menu-hint.is-set {
    color: var(--success);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* Fixed width for annotations toggle button to prevent layout shift */
#toggleAnnotationsButton {
    width: 85px;
    text-align: center;
    padding: 4px 0; /* Remove left/right padding to ensure centering */
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* Fixed width so swapping the label between Full and Exit does not shift the header */
/* Square icon button. Icon-only: four-arrows-out is self-explanatory in a way that
   needs no label, and dropping the text buys back header width on mobile. */
#fullscreenButton {
    width: 30px;
    height: 26px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.fs-icon {
    width: 16px;
    height: 16px;
    display: block;
}

/* Exactly one of the pair is shown; .is-fullscreen is set from the fullscreenchange
   handler, so an Esc exit swaps the icon just as a click does. */
#fullscreenButton .fs-icon-exit,
#fullscreenButton.is-fullscreen .fs-icon-enter {
    display: none;
}

#fullscreenButton.is-fullscreen .fs-icon-exit {
    display: block;
}

/* Fixed width for channel groups toggle button to prevent layout shift */
#toggleChannelGroupsButton {
    width: 85px;
    text-align: center;
    padding: 4px 0; /* Remove left/right padding to ensure centering */
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* Header Selects */
.header-select {
    padding: 4px 8px;
    border: 1px solid var(--gray-300);
    border-radius: 3px;
    background-color: #fff;
    color: var(--gray-700);
    font-size: 13px;
    min-width: 70px;
    cursor: pointer;
}

.header-select:focus {
    border-color: var(--accent-light);
    outline: 0;
    box-shadow: 0 0 0 0.2rem rgba(13, 125, 125, 0.25);
}

/* Lit while the dock is open, matching how .clip-btn.open reads with its menu up. */
#settingsButton[aria-pressed="true"] {
    background-color: var(--accent-bg);
    border-color: var(--accent-light);
    color: var(--accent-text);
}

/* Region select is armed. It changes what dragging the canvas does, so it has to be
   visible with the dock shut - and since Tools moved inside Settings, the Settings
   button is the only header control left that stands for it. Carries an id so it
   outranks the dock-open rule above, which it may be wearing at the same time. */
#settingsButton.armed {
    background-color: var(--accent);
    border-color: var(--accent);
    color: #fff;
}

#settingsButton.armed:hover {
    background-color: var(--accent-hover);
    border-color: var(--accent-hover);
}

/* Tools Menu ------------------------------------------------------------------
   The analysis launchers (region select, frequency spectrum, spectrogram, DSA)
   used to sit inside the Settings modal, where they were both undiscoverable and
   miscategorised - they open windows, they are not preferences. Collapsed into one
   header dropdown so they cost a single slot instead of four. */
.tools-menu {
    display: none;
    position: absolute;
    top: calc(100% + 6px);
    left: 50%;
    transform: translateX(-50%);
    width: 268px;
    padding: 4px;
    background-color: #fff;
    border: 1px solid var(--gray-200);
    border-radius: 6px;
    box-shadow: 0 6px 20px rgba(15, 23, 42, 0.16);
    z-index: 1100;
}

.tools-menu.open {
    display: block;
}

.tools-menu-item {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1px;
    width: 100%;
    padding: 7px 10px;
    border: 0;
    border-radius: 4px;
    background: none;
    text-align: left;
    font-family: inherit;
    color: var(--gray-700);
    cursor: pointer;
}

.tools-menu-item:hover {
    background-color: var(--gray-100);
}

.tools-menu-label {
    font-size: 13px;
    font-weight: 500;
    line-height: 1.3;
}

.tools-menu-hint {
    font-size: 11px;
    color: var(--gray-500);
    line-height: 1.3;
}

/* Region-select toggles this on itself while armed */
.tools-menu-item.armed {
    background-color: var(--accent-bg);
    color: var(--accent-text);
}

.tools-menu-item.armed .tools-menu-hint {
    color: var(--accent-text);
}

/* Tools that need a loaded file. Left visible rather than hidden so the menu does
   not change height between the empty and loaded states. */
.tools-menu-item.disabled {
    opacity: 0.45;
    pointer-events: none;
}

/* Distinguish LFF/HFF "Off" state so it's obvious filtering is disabled */
#lowFrequencyFilterSelect option[value="off"],
#highFrequencyFilterSelect option[value="off"] {
    color: #d9534f;
}

/* Header Checkbox */
.header-checkbox-label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 8px;
    border: 1px solid var(--gray-300);
    border-radius: 3px;
    background-color: #fff;
    color: var(--gray-700);
    font-size: 13px;
    cursor: pointer;
    transition: all 0.2s;
    user-select: none;
}

.header-checkbox-label:hover {
    background-color: var(--gray-50);
}

.header-checkbox {
    margin: 0;
    cursor: pointer;
}

.header-checkbox-label span {
    white-space: nowrap;
}

/* Canvas Container - Scrollable */
#canvasContainer {
    position: fixed;
    top: 40px; /* Space for header bar */
    left: 0;
    right: 0;
    bottom: 0; /* No space needed for status message */
    overflow-y: auto;
    overflow-x: hidden;
    background-color: #fff;
}
#canvasContainer::-webkit-scrollbar {
    width: 14px;
}
#canvasContainer::-webkit-scrollbar-track {
    background: #2a2a2a;
}
#canvasContainer::-webkit-scrollbar-thumb {
    background: #888;
    border-radius: 7px;
    border: 2px solid #2a2a2a;
}
#canvasContainer::-webkit-scrollbar-thumb:hover {
    background: #bbb;
}

/* Full Screen Canvas */
#eegCanvas {
    position: relative;
    top: 0;
    left: 0;
    background-color: #fff;
    display: block;
    /* Width and height now handled by JavaScript for high-DPI support */
    /* Let the browser handle vertical scroll natively; horizontal pan and pinch stay JS-driven */
    touch-action: pan-y;
}

/* Header info icon */
.header-info-icon {
    margin-right: 10px;
    font-size: 16px;
    color: var(--accent);
    cursor: help;
}

.header-info-icon:hover {
    color: var(--accent-hover);
}

.file-info-tooltip {
    left: 0 !important;
    right: auto !important;
    transform: none !important;
    top: 30px !important;
    width: 250px !important;
    white-space: pre-line !important;
}

.file-info-tooltip::before {
    content: '';
    position: absolute;
    left: 10px !important;
    right: auto !important;
    transform: none !important;
    bottom: 100% !important;
    top: auto !important;
    border: 6px solid transparent;
    border-bottom-color: var(--gray-800);
}

/* Responsive Design */
@media (max-width: 768px) {
    .control-panel {
        flex-direction: column;
        align-items: stretch;
    }
    
    .control-group {
        justify-content: space-between;
        flex-wrap: wrap;
    }
    
    .control-group label {
        min-width: auto;
    }
    
    .status-panel {
        flex-direction: column;
    }
    
    .edf-info {
        justify-content: center;
    }
    
    /* Canvas sizing handled by JavaScript for all screen sizes */
}

/* Loading States */
.loading {
    opacity: 0.6;
    pointer-events: none;
}

.loading::after {
    content: "Loading...";
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: rgba(0,0,0,0.8);
    color: white;
    padding: 10px 20px;
    border-radius: 4px;
    z-index: 1000;
}

/* Error States */
.error {
    background-color: #f8d7da;
    color: #721c24;
    border: 1px solid #f5c6cb;
}

.success {
    background-color: #d4edda;
    color: #155724;
    border: 1px solid #c3e6cb;
}

/* Fixed Annotation Sidebar */
.annotation-sidebar {
    position: fixed;
    top: 70px; /* Below header bar */
    right: 15px;
    width: 300px;
    max-height: 400px;
    min-height: 200px;
    background-color: #fff;
    border: 1px solid var(--gray-200);
    border-radius: 6px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
    z-index: 1001;
    display: flex;
    flex-direction: column;
    transform: translateX(110%); /* Hidden by default */
    transition: transform 0.3s ease;
}

.annotation-sidebar.open {
    transform: translateX(0); /* Slide in when open */
}

.annotation-sidebar-header {
    padding: 8px 12px;
    border-bottom: 1px solid var(--gray-200);
    background-color: var(--gray-50);
    border-radius: 6px 6px 0 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.annotation-master-toggle {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 12px;
    color: var(--gray-600);
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
}

.annotation-master-toggle input {
    margin: 0;
    cursor: pointer;
}

.annotation-sidebar-header h4 {
    margin: 0;
    font-size: 14px;
    color: var(--gray-700);
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 6px;
}

/* Info icon and tooltip */
.info-icon {
    position: relative;
    display: inline-flex;
    align-items: center;
    cursor: help;
    font-size: 13px;
    color: var(--gray-500);
    font-weight: normal;
}

.info-icon:hover {
    color: var(--gray-700);
}

.info-tooltip {
    visibility: hidden;
    opacity: 0;
    position: absolute;
    left: 20px;
    top: 50%;
    transform: translateY(-50%);
    background-color: var(--gray-800);
    color: white;
    padding: 8px 12px;
    border-radius: 4px;
    font-size: 11px;
    font-weight: normal;
    white-space: normal;
    width: 200px;
    z-index: 10001;
    transition: opacity 0.2s, visibility 0.2s;
    box-shadow: 0 2px 8px rgba(0,0,0,0.2);
    line-height: 1.4;
}

.info-icon:hover .info-tooltip {
    visibility: visible;
    opacity: 1;
}

/* Tooltip arrow */
.info-tooltip::before {
    content: '';
    position: absolute;
    right: 100%;
    top: 50%;
    transform: translateY(-50%);
    border: 6px solid transparent;
    border-right-color: var(--gray-800);
}

.ann-btn {
    padding: 4px 8px;
    border: 1px solid var(--gray-300);
    border-radius: 3px;
    background-color: #fff;
    color: var(--gray-700);
    font-size: 12px;
    cursor: pointer;
    transition: all 0.2s;
}

.ann-btn:hover {
    background-color: var(--gray-100);
}

.ann-btn.close {
    background-color: var(--danger);
    color: white;
    border-color: var(--danger);
    font-weight: bold;
}

.ann-btn.close:hover {
    background-color: var(--danger-hover);
}

.annotation-list {
    flex: 1;
    overflow-y: auto;
    padding: 8px;
    max-height: 250px;
}

.annotation-item {
    padding: 6px 8px;
    border-radius: 4px;
    margin-bottom: 4px;
    background-color: var(--gray-50);
    font-size: 11px;
    cursor: pointer;
    transition: background-color 0.2s;
    border-left: 3px solid transparent;
    position: relative;
}

.annotation-item:hover {
    background-color: var(--gray-100);
}

/* Annotation action icons */
.annotation-actions {
    display: flex;
    gap: 6px;
    align-items: center;
    margin-left: auto;
    flex-shrink: 0;
}

.annotation-icon {
    opacity: 0;
    transition: opacity 0.2s;
    cursor: pointer;
    padding: 2px 4px;
    border-radius: 3px;
    font-size: 16px;
    background: transparent;
    border: none;
    color: var(--gray-500);
    font-weight: normal;
    line-height: 1;
}

.annotation-item:hover .annotation-icon {
    opacity: 1;
}

.annotation-icon:hover {
    color: var(--gray-700);
    background-color: rgba(0,0,0,0.05);
}

.annotation-icon.delete:hover {
    color: var(--danger);
    background-color: rgba(220, 38, 38, 0.1);
}

.annotation-icon.visibility.hidden {
    position: relative;
}

.annotation-icon.visibility.hidden::after {
    content: '';
    position: absolute;
    left: 50%;
    top: 50%;
    width: 60%;
    height: 1.5px;
    background-color: currentColor;
    transform: translate(-50%, -50%) rotate(-45deg);
}

.annotation-icon.visibility:hover {
    color: var(--accent);
    background-color: rgba(13, 125, 125, 0.1);
}

.annotation-item.file {
    border-left-color: var(--accent);
}

.annotation-item.user {
    border-left-color: var(--danger);
}

.annotation-time {
    font-weight: bold;
    color: var(--gray-700);
    font-size: 12px;
    display: block;
    margin-bottom: 2px;
}

.annotation-text {
    color: var(--gray-500);
    line-height: 1.2;
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Additional styles for edf-viewer annotation sidebar */
.annotation-sidebar .annotation-item {
    border: none; /* Remove border for cleaner look */
}

.annotation-sidebar .annotation-item.file {
    border-left: 3px solid var(--accent);
}

.annotation-sidebar .annotation-item.user {
    border-left: 3px solid var(--danger);
}

/* Channel Groups Panel (for intracranial EEGs) */
.channel-groups-panel {
    position: fixed;
    top: 70px; /* Below header bar */
    right: 330px; /* Position to the right of annotation panel (300px width + 15px margin + 15px gap) */
    width: 250px;
    max-height: 500px;
    min-height: 200px;
    background-color: #fff;
    border: 1px solid var(--gray-200);
    border-radius: 6px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
    z-index: 1001;
    display: none; /* Hidden by default */
    flex-direction: column;
}

.channel-groups-panel.open {
    display: flex; /* Show when open */
}

.channel-groups-header {
    padding: 8px 12px;
    border-bottom: 1px solid var(--gray-200);
    background-color: var(--gray-50);
    border-radius: 6px 6px 0 0;
}

.channel-groups-header h4 {
    margin: 0;
    font-size: 14px;
    color: var(--gray-700);
    font-weight: 600;
}

.channel-groups-list {
    flex: 1;
    overflow-y: auto;
    padding: 10px;
}

.channel-group-item {
    padding: 6px 8px;
    margin-bottom: 4px;
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    cursor: move;
    border-radius: 4px;
    transition: background-color 0.2s, transform 0.2s, box-shadow 0.2s;
    background-color: #fff;
    border: 1px solid transparent;
}

.channel-group-item:hover {
    background-color: var(--gray-50);
}

/* Drag handle */
.drag-handle {
    color: var(--gray-400);
    font-size: 14px;
    cursor: move;
    user-select: none;
    line-height: 1;
}

/* Dragging state */
.channel-group-item.dragging {
    opacity: 0.5;
    transform: scale(0.95);
}

/* Drag over state */
.channel-group-item.drag-over {
    background-color: var(--accent-bg);
    border-color: var(--accent);
    border-style: dashed;
    transform: translateY(-2px);
    box-shadow: 0 2px 8px rgba(13, 125, 125, 0.3);
}

.channel-group-item input[type="checkbox"] {
    cursor: pointer;
    width: 16px;
    height: 16px;
}

.channel-group-item label {
    cursor: pointer;
    flex: 1;
    user-select: none;
}

.channel-group-count {
    font-size: 11px;
    color: var(--gray-500);
    font-style: italic;
}

/* Hidden individual channels — restore list inside the Channels panel */
.hidden-channels-section {
    margin-top: 10px;
    padding-top: 8px;
    border-top: 1px solid var(--gray-200);
}

.hidden-channels-heading {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--gray-500);
    margin-bottom: 6px;
}

.restore-channel-btn {
    font-size: 11px;
    padding: 2px 8px;
    border: 1px solid var(--gray-200);
    border-radius: 3px;
    background-color: #fff;
    color: var(--gray-500);
    cursor: pointer;
}

.restore-channel-btn:hover {
    border-color: var(--accent);
    color: var(--accent);
}

.show-all-hidden-btn {
    width: 100%;
    margin-top: 6px;
    padding: 5px;
    font-size: 11px;
    border: 1px solid var(--gray-200);
    border-radius: 4px;
    background-color: #fff;
    cursor: pointer;
}

.show-all-hidden-btn:hover {
    border-color: var(--accent);
    color: var(--accent);
}

/* Right-click menu on a channel label */
.channel-context-menu {
    position: absolute;
    z-index: 2000;
    min-width: 160px;
    padding: 4px 0;
    background-color: #fff;
    border: 1px solid var(--gray-200);
    border-radius: 6px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    font-size: 12px;
    user-select: none;
}

.channel-context-menu-item {
    padding: 7px 14px;
    cursor: pointer;
    white-space: nowrap;
}

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

.channel-context-menu-item.disabled,
.channel-context-menu-item.disabled:hover {
    color: var(--gray-400);
    background-color: transparent;
    cursor: default;
}

/* Hidden-channel count on the Channels button. Absolutely positioned so the button's
   footprint stays fixed — putting the count in the label would reflow the header row. */
#toggleChannelGroupsButton {
    position: relative;
}

#toggleChannelGroupsButton[data-hidden-count]::after {
    content: attr(data-hidden-count);
    position: absolute;
    top: -4px;
    right: -4px;
    min-width: 14px;
    height: 14px;
    padding: 0 3px;
    box-sizing: border-box;
    border-radius: 7px;
    background-color: var(--accent);
    color: #fff;
    font-size: 9px;
    font-weight: 600;
    line-height: 14px;
    text-align: center;
    pointer-events: none;
}

/* Watermark Logo - Fixed Top Left */
.watermark-logo {
    position: fixed;
    top: 38px; /* Right at the header bar edge to avoid blocking signals */
    left: 60px; /* More to the right, past channel labels */
    z-index: 2000; /* Above all other elements */
    pointer-events: none; /* Allow clicks to pass through */
    user-select: none; /* Prevent text selection */
}

.watermark-text {
    display: inline-block;
    font-family: var(--font-family);
    font-size: 10px;
    font-weight: bold;
    letter-spacing: 0.5px;
    color: var(--gray-500);
}

/* Watermark Canvas Image - Fixed Bottom Right */
.watermark-canvas {
    position: fixed;
    bottom: 40px; /* Near bottom edge */
    right: 20px;
    width: 150px; /* Adjust based on your watermark.png dimensions */
    height: 40px; /* Adjust based on your watermark.png dimensions */
    background-image: url('img/watermark.png');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: right bottom;
    pointer-events: none; /* Allow clicks to pass through */
    user-select: none; /* Prevent text selection */
    z-index: 3000; /* Above all other elements */
    opacity: 0.8;
}

/* Background caching ---------------------------------------------------------
   The readout was a 292px strip in the centre of the header carrying a label, a
   track, two byte counts and a Pause button, every one of which changed while it
   ran - so every one of them had to be pinned to a fixed width to stop the filter
   controls being shoved sideways mid-session. Split in two instead:

     - the hairline below, which is the at-a-glance progress and costs no layout;
     - this chip, whose only moving part is the percent, with the byte counts and
       the pause control behind a click.

   Together they give back ~300px of header and remove the last thing in the bar
   that resized itself. */
.dl-chip-wrap {
    display: none;
    position: relative;
    align-items: center;
}

.dl-chip-wrap.active {
    display: flex;
}

/* Fixed: the percent runs 0% to 100% and the chip must not breathe as it climbs. */
.dl-chip {
    position: relative;
    overflow: hidden;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    width: 62px;
    height: 26px;
    padding: 0;
    border: 1px solid var(--gray-300);
    border-radius: 3px;
    background-color: #fff;
    color: var(--gray-600);
    font-family: inherit;
    font-size: 11px;
    cursor: pointer;
    transition: all 0.2s;
}

/* Progress, drawn on the chip itself ------------------------------------------
   This replaced a 2px hairline that ran the full width of the page under the
   header. Two things were wrong with it: a page-wide bar pinned below the top
   chrome is the page-load idiom (GitHub, YouTube), which misdescribes what this
   is - a background prefetch of EDF blocks, not a page loading - and at 1400px
   away from a 62px chip, nothing connected the two.

   Both cues below read one --dl-progress property set by the JS, so there is a
   single number to update and they can never disagree. */
.dl-chip-fill {
    position: absolute;
    inset: 0 auto 0 0;
    width: var(--dl-progress, 0%);
    /* A pale wash, not a solid fill: the percent sits on top of this and crosses
       the boundary as it advances, so the fill has to stay light enough for dark
       text to clear it on both sides. Same reasoning the old inline track used. */
    background-color: rgba(13, 125, 125, 0.22);   /* --accent */
    transition: width 0.2s ease;
}

/* The crisp leading edge. The wash alone gives mass but no readable boundary at
   62px wide; this gives a definite one without darkening the text's background. */
.dl-chip::after {
    content: '';
    position: absolute;
    left: 0;
    bottom: 0;
    height: 2px;
    width: var(--dl-progress, 0%);
    background-color: var(--accent);
    transition: width 0.2s ease;
}

/* Icon and percent sit above the fill. */
.dl-chip-icon,
.dl-chip-percent {
    position: relative;
    z-index: 1;
}

.dl-chip:hover {
    background-color: var(--gray-100);
    border-color: var(--gray-400);
    color: var(--gray-700);
}

.dl-chip-wrap.open .dl-chip {
    background-color: var(--accent-bg);
    border-color: var(--accent-light);
    color: var(--accent-text);
}

.dl-chip-icon {
    width: 11px;
    height: 11px;
    flex: none;
}

/* Tabular figures so the digits hold still while the number climbs. */
.dl-chip-percent {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    letter-spacing: 0.01em;
}

/* Paused reads as stalled rather than broken: grey, no motion. */
.dl-chip-wrap.paused .dl-chip {
    color: var(--gray-500);
    border-color: var(--gray-300);
}

.dl-chip-wrap.paused .dl-chip-fill {
    background-color: rgba(148, 163, 184, 0.3);   /* --gray-400 */
}

.dl-chip-wrap.paused .dl-chip::after {
    background-color: var(--gray-400);
}

/* Finished. Held for a beat at full green before the whole chip goes. */
.dl-chip-wrap.complete .dl-chip {
    border-color: var(--success);
    color: var(--success);
}

.dl-chip-wrap.complete .dl-chip-fill {
    background-color: rgba(22, 163, 74, 0.2);     /* --success */
}

.dl-chip-wrap.complete .dl-chip::after {
    background-color: var(--success);
}

/* Lit while a block the viewer actually needs is in flight - the job the separate
   "Loading…" label in the header used to do, folded in here so it costs no slot of
   its own. Opacity only, so nothing reflows as it blinks on and off during scroll. */
.dl-chip-wrap.fetching .dl-chip {
    border-color: var(--accent-light);
    color: var(--accent-text);
}

.dl-chip-wrap.fetching .dl-chip-icon {
    animation: dl-chip-pulse 0.9s ease-in-out infinite;
}

@keyframes dl-chip-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.25; }
}

@media (prefers-reduced-motion: reduce) {
    .dl-chip-wrap.fetching .dl-chip-icon {
        animation: none;
    }
}

/* Detail popover. Everything that used to churn in the header lives here, where it
   is read on demand and can size to its content. */
.cache-progress {
    display: none;
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    min-width: 168px;
    padding: 9px 11px;
    background-color: #fff;
    border: 1px solid var(--gray-200);
    border-radius: 6px;
    box-shadow: 0 6px 20px rgba(15, 23, 42, 0.16);
    font-size: 11px;
    color: var(--gray-600);
    white-space: nowrap;
    z-index: 1100;
}

.cache-progress.open {
    display: block;
}

.cache-progress-label {
    display: block;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--gray-700);
}

.cache-progress-text {
    display: block;
    margin-top: 2px;
    font-variant-numeric: tabular-nums;
    color: var(--gray-500);
}

.cache-progress-toggle {
    margin-top: 8px;
    width: 100%;
    background-color: #fff;
    border: 1px solid var(--gray-300);
    color: var(--gray-600);
    border-radius: 3px;
    padding: 3px 4px;
    font-family: inherit;
    font-size: 11px;
    line-height: 1.5;
    cursor: pointer;
}

.cache-progress-toggle:hover {
    background-color: var(--gray-100);
    border-color: var(--gray-400);
    color: var(--gray-700);
}

/* Loading Progress Overlay
   Same vocabulary as the header chip and its popover: white card, gray-200 hairline,
   slate shadow, teal fill. Always laid out and faded with opacity/visibility rather
   than display, so it can ease in and out instead of popping. */
.loading-overlay {
    display: flex;
    position: fixed;
    inset: 0;
    padding: 16px;
    background-color: rgba(15, 23, 42, 0.32);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    z-index: 10001;
    justify-content: center;
    align-items: center;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.2s ease, visibility 0s linear 0.2s;
}

.loading-overlay.active {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transition: opacity 0.15s ease, visibility 0s;
}

.loading-content {
    width: 380px;
    max-width: 100%;
    box-sizing: border-box;
    padding: 16px 18px 14px;
    background-color: #fff;
    border: 1px solid var(--gray-200);
    border-radius: 8px;
    box-shadow: 0 12px 32px rgba(15, 23, 42, 0.18);
    font-family: var(--font-family);
    transform: translateY(4px) scale(0.99);
    transition: transform 0.2s ease;
}

.loading-overlay.active .loading-content {
    transform: none;
}

.progress-text {
    flex-shrink: 0;
    font-size: 12px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--accent-text);
}

.progress-bar-container {
    position: relative;
    width: 100%;
    height: 6px;
    background-color: var(--gray-100);
    border-radius: 999px;
    overflow: hidden;
}

.progress-bar {
    position: relative;
    height: 100%;
    width: 0%;
    background-color: var(--accent);
    border-radius: inherit;
    transition: width 0.25s ease-out;
    overflow: hidden;
}

/* Soft sheen travelling along the fill, so a slow stretch still reads as alive. */
.progress-bar::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.35), transparent);
    transform: translateX(-100%);
    animation: loading-sheen 1.6s ease-in-out infinite;
}

.progress-bar.no-transition {
    transition: none;
}

/* Unknown total: a segment sweeps the track instead of claiming a percentage. */
.progress-bar-container.indeterminate .progress-bar {
    width: 35% !important;
    transition: none;
    animation: loading-sweep 1.2s ease-in-out infinite;
}

.progress-bar-container.indeterminate .progress-bar::after {
    display: none;
}

@keyframes loading-sheen {
    to { transform: translateX(100%); }
}

@keyframes loading-sweep {
    from { transform: translateX(-100%); }
    to   { transform: translateX(290%); }
}

/* One line: what's happening on the left, bytes and percentage on the right. */
.loading-status {
    display: flex;
    align-items: baseline;
    gap: 10px;
    margin-bottom: 10px;
    font-size: 12px;
    color: var(--gray-700);
}

.loading-label {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 500;
}

@media (prefers-reduced-motion: reduce) {
    .loading-overlay,
    .loading-content,
    .progress-bar {
        transition: none;
    }
    .progress-bar::after {
        animation: none;
    }
    .progress-bar-container.indeterminate .progress-bar {
        width: 100% !important;
        animation: none;
        opacity: 0.5;
    }
}

/* Settings Modal */
.settings-modal {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.5);
    z-index: 10000;
    justify-content: center;
    align-items: center;
}

.settings-modal.open {
    display: flex;
}

.settings-modal-content {
    background-color: #fff;
    border-radius: 8px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
    width: 90%;
    max-width: 500px;
    max-height: 80vh;
    display: flex;
    flex-direction: column;
}

.settings-modal-header {
    padding: 16px 20px;
    border-bottom: 1px solid var(--gray-200);
    display: flex;
    justify-content: space-between;
    align-items: center;
    background-color: var(--gray-50);
    border-radius: 8px 8px 0 0;
}

.settings-modal-header h3 {
    margin: 0;
    font-size: 18px;
    color: var(--gray-700);
    font-weight: 600;
}

.close-settings-btn {
    background: none;
    border: none;
    font-size: 32px;
    line-height: 1;
    color: var(--gray-500);
    cursor: pointer;
    padding: 0;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 4px;
    transition: all 0.2s;
}

.close-settings-btn:hover {
    background-color: var(--gray-100);
    color: var(--gray-700);
}

/* Spectrogram Modal */
.spectrogram-modal {
    display: none;
    position: fixed;
    top: 0; left: 0; right: 0; bottom: 0;
    background-color: rgba(0, 0, 0, 0.65);
    z-index: 10000;
    justify-content: center;
    align-items: center;
}

.spectrogram-modal.open {
    display: flex;
}

.spectrogram-modal-content {
    background-color: #fff;
    border-radius: 8px;
    box-shadow: 0 4px 24px rgba(0, 0, 0, 0.3);
    width: 92%;
    max-width: 1100px;
    display: flex;
    flex-direction: column;
}

.spectrogram-modal-header {
    padding: 12px 20px;
    border-bottom: 1px solid var(--gray-200);
    display: flex;
    justify-content: space-between;
    align-items: center;
    background-color: var(--gray-50);
    border-radius: 8px 8px 0 0;
}

.spectrogram-modal-header h3 {
    margin: 0;
    font-size: 16px;
    color: var(--gray-700);
    font-weight: 600;
}

.spectrogram-controls {
    display: flex;
    align-items: center;
    gap: 8px;
}

.spectrogram-channel-label {
    font-size: 13px;
    color: var(--gray-600);
}

.spectrogram-modal-body {
    padding: 16px;
    display: flex;
    justify-content: center;
    background-color: #111;
    border-radius: 0 0 8px 8px;
}

#spectrogramCanvas {
    display: block;
    border-radius: 4px;
}

/* Density spectral array — docked strip below the EEG canvas */
.dsa-dock {
    display: none;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    height: var(--dsa-dock-height, 77px);
    background-color: #111;
    border-top: 1px solid #333;
    z-index: 900;
    /* Canvas first, control rail on the right */
    flex-direction: row-reverse;
}

body.dsa-open .dsa-dock {
    display: flex;
}

/* Give the strip its space back out of the EEG area rather than overlapping it */
body.dsa-open #canvasContainer {
    bottom: var(--dsa-dock-height, 77px);
}

/* The watermark is pinned to the viewport bottom, which the dock now occupies, and it
   outranks the dock on z-index. Lift it clear so it keeps sitting over the EEG. */
body.dsa-open .watermark-canvas {
    bottom: calc(var(--dsa-dock-height, 77px) + 12px);
}

.dsa-info-icon {
    /* A serif italic 'i' rather than the circled glyph, which rendered inconsistently
       across platforms and read as heavier than the buttons beside it. */
    font-family: Georgia, "Times New Roman", serif;
    font-style: italic;
    font-weight: 700;
    font-size: 14px;
    line-height: 1;
    color: #8a8a95;
}

.dsa-info-icon:hover {
    color: #e2e2ea;
}

.dsa-info-tooltip {
    width: 300px;
    border: 1px solid #3a3a40;
    font-family: var(--font-family);
    font-style: normal;
    left: auto;
    right: 22px;
    /* Grows upward from the rail. The dock is short and pinned to the bottom of the
       viewport, so a tooltip anchored at the top would run off the screen. */
    top: auto;
    bottom: 0;
    transform: none;
    text-transform: none;
    letter-spacing: normal;
    font-weight: normal;
}

.dsa-dock-rail {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    flex: 0 0 auto;
    width: 26px;
    padding: 4px 0;
    border-left: 1px solid #2a2a2e;
}

.dsa-rail-btn {
    width: 20px;
    height: 18px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    line-height: 1;
    color: #ccc;
    background-color: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.22);
    border-radius: 3px;
    cursor: pointer;
}

.dsa-rail-btn:hover {
    background-color: rgba(255, 255, 255, 0.18);
    color: #fff;
}

.dsa-rail-close {
    font-size: 16px;
    font-weight: 700;
    color: #e05555;
    background: none;
    border: none;
}

.dsa-rail-close:hover {
    color: #ff7070;
    background: none;
}


.dsa-dock-close {
    margin-left: auto;
    padding: 0 4px;
    font-size: 18px;
    line-height: 1;
    color: #999;
    background: none;
    border: none;
    cursor: pointer;
}

.dsa-dock-close:hover {
    color: #fff;
}

#dsaCanvas {
    display: block;
    height: 100%;
    flex: 1 1 auto;
    min-width: 0;
    cursor: pointer;
}

.dsa-dock-btn {
    padding: 2px 8px;
    font-size: 11px;
    color: #ccc;
    background-color: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.25);
    border-radius: 3px;
    cursor: pointer;
}

/* Hidden until a range is actually selected, so the header does not carry a control
   that would do nothing. */
.dsa-dock-btn-reset {
    display: none;
}

.dsa-dock-btn-reset.visible {
    display: flex;
}

.dsa-range-label {
    font-size: 8px;
    line-height: 1.15;
    color: #8fd0ef;
    text-align: center;
    word-break: break-all;
}

.dsa-dock-btn:hover {
    background-color: rgba(255, 255, 255, 0.16);
    color: #fff;
}

/* Derivation picker, anchored inside the dock over the DSA canvas */
.dsa-picker {
    display: none;
    /* Fixed, not absolute. The dock is 230px tall and pinned to the bottom of the
       viewport, while this panel wants ~300px, so it can never fit inside its own
       container - positioning it against the dock left the bottom third hanging off
       the screen. Fixed lets it open upward over the EEG canvas, where there is room.
       Still inside .dsa-dock's stacking context, so it keeps painting above the dock. */
    position: fixed;
    /* Last resort for short viewports: the list below shrinks rather than overflowing. */
    max-height: calc(100vh - 16px);
    z-index: 20;
    gap: 14px;
    padding: 12px;
    background-color: #1c1c1f;
    border: 1px solid #3a3a40;
    border-radius: 6px;
    box-shadow: 0 8px 28px rgba(0, 0, 0, 0.55);
}

.dsa-picker.open {
    display: flex;
}

.dsa-picker-close {
    position: absolute;
    top: 4px;
    right: 6px;
    padding: 0 4px;
    font-size: 16px;
    line-height: 1;
    color: #8f8f96;
    background: none;
    border: none;
    cursor: pointer;
}

.dsa-picker-close:hover {
    color: #fff;
}

.dsa-picker-col {
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: 190px;
    /* Lets the list shrink past its own height when the picker hits its max-height;
       a flex item defaults to min-height:auto, which would refuse to. */
    min-height: 0;
}

.dsa-picker-col:last-child .dsa-picker-title {
    padding-right: 18px;
}

.dsa-picker-title {
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: #8f8f96;
}

.dsa-picker-count {
    color: #7fc4e8;
}

.dsa-picker-filter {
    padding: 4px 6px;
    font-size: 12px;
    color: #eee;
    background-color: #131316;
    border: 1px solid #3a3a40;
    border-radius: 3px;
}

.dsa-picker-filter:focus {
    outline: 2px solid #7fc4e8;
    outline-offset: -1px;
}

.dsa-picker-list {
    /* Preferred size, but shrinkable - see .dsa-picker-col */
    height: 190px;
    min-height: 80px;
    overflow-y: auto;
    border: 1px solid #2e2e34;
    border-radius: 3px;
    background-color: #151518;
}

.dsa-picker-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
    width: 100%;
    padding: 4px 8px;
    font-size: 12px;
    text-align: left;
    color: #ddd;
    background: none;
    border: none;
    border-bottom: 1px solid #232328;
    cursor: pointer;
}

.dsa-picker-row:hover {
    background-color: #26262c;
}

.dsa-picker-row:focus-visible {
    outline: 2px solid #7fc4e8;
    outline-offset: -2px;
}

.dsa-picker-row[disabled] {
    color: #5c5c63;
    cursor: default;
}

.dsa-picker-row[disabled]:hover {
    background: none;
}

.dsa-picker-index {
    color: #7f7f88;
    font-variant-numeric: tabular-nums;
}

.dsa-picker-remove {
    color: #9a9aa2;
    font-size: 13px;
    line-height: 1;
}

.dsa-picker-row:hover .dsa-picker-remove {
    color: #fff;
}

.dsa-picker-empty {
    padding: 8px;
    font-size: 11px;
    color: #6f6f77;
}

/* Sits above the list, not below it. Below, it was pushed past the bottom of a 190px
   scrolling list and off the edge of the dock entirely. Directly under the filter it
   holds a fixed position no matter how long the candidate list is. */
.dsa-picker-mirror {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 6px;
    font-size: 11px;
    color: #d5d5dd;
    background-color: #131316;
    border: 1px solid #2e2e34;
    border-radius: 3px;
    cursor: pointer;
    user-select: none;
}

.dsa-picker-mirror:hover {
    border-color: #4a4a52;
    color: #f0f0f5;
}

.dsa-picker-mirror input {
    width: 12px;
    height: 12px;
    margin: 0;
    flex: none;
    cursor: pointer;
    accent-color: #7fc4e8;
}

.dsa-picker-hint {
    margin: 0;
    font-size: 10px;
    color: #6f6f77;
}

@media (max-width: 900px) {
    .dsa-dock {
        height: var(--dsa-dock-height-mobile, 57px);
    }

    body.dsa-open #canvasContainer {
        bottom: var(--dsa-dock-height-mobile, 57px);
    }

    body.dsa-open .watermark-canvas {
        bottom: calc(var(--dsa-dock-height-mobile, 57px) + 12px);
    }

    .dsa-picker-col {
        width: 150px;
    }

    .dsa-picker-list {
        height: 120px;
    }

    .header-group {
        flex: 0 0 auto;
        gap: 4px;
        padding: 3px 6px;
    }

    .header-select {
        min-width: 56px;
        padding: 3px 6px;
        font-size: 12px;
    }

    .header-btn {
        padding: 4px 9px;
        font-size: 12px;
        white-space: nowrap;
    }

}

@media (max-width: 1280px) {
    /* Mobile header --------------------------------------------------------
       The bar carries roughly 1240px of controls at its intrinsic minimum. It
       previously just overflowed and clipped, with no way to reach anything past the
       first few items. It now scrolls sideways instead of wrapping to a second row:
       vertical space is the scarcest thing on a phone, and the traces have first
       claim on it, so the bar stays 40px and #canvasContainer's top offset is
       untouched.

       This breakpoint is deliberately much wider than the one that shrinks the
       controls, above. The two used to share a 900px cutoff, which left a dead band
       from 901px to ~1250px - wide enough that the bar still overflowed, narrow
       enough that it did not scroll - so Save and Clip sat clipped off the right edge
       with no way to reach them. That covers 1024 and 1152, both ordinary laptop
       widths. The scroll affordance now starts wherever the overflow actually does. */
    .header-bar {
        /* No slack left to distribute, and space-between would push the left
           section away from the scroll origin. */
        justify-content: flex-start;
        gap: 8px;
        padding: 0 10px;
        overflow-x: auto;
        overflow-y: hidden;
        -webkit-overflow-scrolling: touch;
        /* A scrollbar inside a 40px strip would eat the controls it scrolls. */
        scrollbar-width: none;
        /* Edge shadows marking that there is more in that direction, using the
           two-layer trick: the cover gradients scroll with the content (local) and
           mask the shadow whenever that end is actually reached, while the shadows
           themselves stay pinned to the frame (scroll). Cover colour has to track
           --gray-50 (#f8fafc); Safari renders bare `transparent` as grey here, so
           the stops are spelled out as rgba. */
        background-image:
            linear-gradient(to right, #f8fafc 30%, rgba(248, 250, 252, 0)),
            linear-gradient(to left, #f8fafc 30%, rgba(248, 250, 252, 0)),
            radial-gradient(farthest-side at 0 50%, rgba(15, 23, 42, 0.16), rgba(15, 23, 42, 0)),
            radial-gradient(farthest-side at 100% 50%, rgba(15, 23, 42, 0.16), rgba(15, 23, 42, 0));
        background-position: left center, right center, left center, right center;
        background-size: 20px 100%, 20px 100%, 10px 100%, 10px 100%;
        background-repeat: no-repeat;
        background-attachment: local, local, scroll, scroll;
    }

    .header-bar::-webkit-scrollbar {
        display: none;
    }

    /* Intrinsic width, no shrinking - the sections have to keep their natural size
       for the bar to have anything to scroll. .header-center in particular is
       flex: 1 by default, which would stretch it and re-centre its contents. */
    .header-left,
    .header-center,
    .header-right {
        flex: 0 0 auto;
        gap: 6px;
    }

    /* The bar is an overflow-x scroller here, with overflow-y: hidden to keep a
       scrollbar out of a 40px strip - which also clips any absolutely-positioned
       dropdown inside it, and scrolls it sideways away from its trigger. So at this
       width the menus detach from their triggers and pin to the viewport, just under
       the bar: position: fixed escapes the scroller entirely (nothing above these
       creates a containing block). They stay anchored to the end of the header they
       live in, which is the end their trigger scrolls towards. */
    .tools-menu,
    .tools-menu.clip-menu,
    .cache-progress {
        position: fixed;
        top: 46px;
        transform: none;
        max-width: calc(100vw - 20px);
    }

    .tools-menu,
    .cache-progress {
        left: 10px;
        right: auto;
    }

    /* Qualified for the same reason as the desktop rule above: bare .clip-menu ties
       with .tools-menu.clip-menu and loses on source order, leaving right: 0 in place. */
    .tools-menu.clip-menu {
        left: auto;
        right: 10px;
    }
}

.settings-modal-body {
    padding: 18px 20px;
    overflow-y: auto;
}

.settings-panel {
    display: none;
}

.settings-panel.active {
    display: block;
}

.settings-section + .settings-section {
    margin-top: 22px;
}

.settings-section-title {
    margin: 0 0 8px;
    padding-bottom: 5px;
    border-bottom: 1px solid var(--gray-200);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--gray-500);
}

.settings-section-hint {
    margin: 0 0 10px;
    font-size: 12px;
    color: var(--gray-500);
    line-height: 1.4;
}

/* One row per setting: label and hint on the left, the control on the right.
   The old layout stacked a bold heading above a full-width description paragraph
   for every option, which cost roughly triple the height for the same content. */
.settings-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 9px 0;
}

.settings-row + .settings-row {
    border-top: 1px solid var(--gray-100);
}

/* Rows that do something rather than set something: the three analysis launchers and
   the drill-down into the builder. Buttons, so they only need the element defaults
   cleared - the geometry comes from .settings-row. */
.settings-row-action {
    width: 100%;
    border: 0;
    background: none;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
}

.settings-row-action:hover {
    background-color: var(--gray-100);
}

.settings-row-drill {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
}

.settings-row-chevron {
    flex: none;
    font-size: 17px;
    line-height: 1;
    color: var(--gray-400);
}

/* Region-select is a mode, not a one-shot, so the row stays lit while it is armed. */
.settings-row-action.armed {
    background-color: var(--accent-bg);
}

.settings-row-action.armed .settings-row-label,
.settings-row-action.armed .settings-row-hint {
    color: var(--accent-text);
}

/* Tools that need a loaded recording. Dimmed rather than hidden, so the section does
   not change height between the empty and loaded states. */
.settings-row-action.disabled {
    opacity: 0.45;
    pointer-events: none;
}

.settings-row-main {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    cursor: pointer;
    user-select: none;
}

.settings-row-label {
    font-size: 13px;
    font-weight: 600;
    color: var(--gray-700);
}

.settings-row-hint {
    font-size: 11px;
    color: var(--gray-500);
    line-height: 1.4;
}

.settings-empty {
    padding: 14px;
    border: 1px dashed var(--gray-300);
    border-radius: 6px;
    font-size: 12px;
    color: var(--gray-500);
    text-align: center;
}

.settings-checkbox {
    flex: none;
    width: 18px;
    height: 18px;
    cursor: pointer;
}

/* Was five inline style attributes repeated on each picker */
.settings-color {
    flex: none;
    width: 40px;
    height: 26px;
    padding: 2px;
    border: 1px solid var(--gray-300);
    border-radius: 4px;
    background-color: #fff;
    cursor: pointer;
}

.settings-select {
    width: 100%;
    padding: 8px 12px;
    border: 1px solid var(--gray-300);
    border-radius: 4px;
    font-size: 14px;
    color: var(--gray-700);
    background-color: #fff;
    margin-top: 8px;
}

/* Instructions - the dock's third panel. Was a 560px modal; the sections now stack
   in a 340px column, so the only thing that had to change is where the gap lives. */
.settings-panel[data-dock-panel="help"] {
    gap: 18px;
}

.settings-panel[data-dock-panel="help"].active {
    display: flex;
    flex-direction: column;
}

.help-section h4 {
    margin: 0 0 8px;
    font-size: 14px;
    font-weight: 600;
    color: var(--gray-700);
    border-bottom: 1px solid var(--gray-200);
    padding-bottom: 4px;
}

.help-section ul {
    margin: 0;
    padding-left: 20px;
}

.help-section li {
    font-size: 13px;
    color: var(--gray-600);
    line-height: 1.6;
}

.help-section kbd {
    display: inline-block;
    padding: 1px 6px;
    font-size: 11px;
    font-family: inherit;
    color: var(--gray-700);
    background-color: var(--gray-100);
    border: 1px solid var(--gray-300);
    border-radius: 3px;
    box-shadow: 0 1px 0 rgba(0,0,0,0.06);
}

/* Numbered steps at the top of the montage builder. Deliberately always visible
   rather than behind a tooltip: the builder is a task people do rarely, and the
   two-click pairing gesture has no affordance on the electrode buttons themselves. */
.builder-steps {
    margin: 0 0 12px;
    padding: 10px 12px 10px 28px;
    background-color: var(--gray-50);
    border: 1px solid var(--gray-200);
    border-radius: 6px;
    font-size: 12px;
    color: var(--gray-600);
    line-height: 1.5;
}

.builder-steps li + li {
    margin-top: 5px;
}

.builder-steps code {
    padding: 0 3px;
    font-family: monospace;
    font-size: 11px;
    color: var(--gray-700);
    background-color: var(--gray-100);
    border: 1px solid var(--gray-200);
    border-radius: 3px;
}

/* Matches the glyphs actually used on the pair rows, so the instruction and the
   thing it points at look the same */
.builder-steps-glyph {
    color: var(--gray-500);
    font-size: 13px;
}

/* Custom Montage Builder */
.custom-montage-electrodes {
    display: flex;
    flex-direction: row;
    gap: 14px;
    margin-top: 10px;
    align-items: flex-start;
}

.custom-montage-electrode-col {
    display: flex;
    flex-direction: column;
    gap: 5px;
    flex: 1;
}

.custom-montage-electrode-col-label {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--gray-400);
    margin-bottom: 2px;
}

.custom-montage-electrode-btn {
    padding: 4px 10px;
    font-size: 12px;
    font-weight: 500;
    border: 1px solid var(--gray-300);
    border-radius: 4px;
    background: var(--gray-50);
    color: var(--gray-700);
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
}

.custom-montage-electrode-btn:hover {
    background: var(--gray-100);
    border-color: var(--gray-400);
}

.custom-montage-electrode-btn.selected {
    background: var(--accent-bg-strong);
    border-color: var(--accent);
    color: var(--accent-text);
}

.custom-montage-pairs {
    margin-top: 14px;
    border-top: 1px solid var(--gray-100);
    padding-top: 10px;
}

.custom-montage-pairs-empty {
    font-size: 12px;
    color: var(--gray-400);
    margin: 0;
}

.custom-montage-pairs-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.custom-montage-pair-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 13px;
    font-family: monospace;
    color: var(--gray-800);
    background: var(--gray-50);
    border: 1px solid var(--gray-100);
    border-radius: 4px;
    padding: 4px 8px;
}

.custom-montage-pair-remove {
    background: none;
    border: none;
    color: var(--gray-400);
    cursor: pointer;
    font-size: 14px;
    line-height: 1;
    padding: 0 2px;
}

.custom-montage-pair-remove:hover {
    color: var(--danger);
}

.custom-montage-group-break {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 8px;
    background: var(--gray-100);
    border: 1px dashed var(--gray-300);
    border-radius: 4px;
    font-size: 11px;
    color: var(--gray-500);
    font-style: italic;
}

.custom-montage-pair-label {
    flex: 1;
    text-align: center;
}

.custom-montage-break-label {
    flex: 1;
    text-align: center;
}

.pair-drag-handle {
    color: var(--gray-400);
    font-size: 14px;
    cursor: grab;
    user-select: none;
    flex-shrink: 0;
}

.custom-montage-pair-item[draggable="true"],
.custom-montage-group-break[draggable="true"] {
    cursor: default;
}

.custom-montage-pair-item.pair-dragging,
.custom-montage-group-break.pair-dragging {
    opacity: 0.4;
}

.custom-montage-pair-item.pair-drop-above,
.custom-montage-group-break.pair-drop-above {
    border-top: 2px solid var(--accent-light);
}

.custom-montage-pair-item.pair-drop-below,
.custom-montage-group-break.pair-drop-below {
    border-bottom: 2px solid var(--accent-light);
}

.custom-montage-break-btn {
    width: 100%;
    padding: 5px;
    font-size: 12px;
    color: var(--gray-500);
    background: none;
    border: 1px dashed var(--gray-300);
    border-radius: 4px;
    cursor: pointer;
}

.custom-montage-break-btn:hover {
    border-color: var(--gray-400);
    color: var(--gray-700);
}

.custom-montage-reset-btn {
    padding: 5px 10px;
    font-size: 12px;
    color: var(--danger);
    background: none;
    border: 1px solid var(--danger);
    border-radius: 4px;
    cursor: pointer;
}

.custom-montage-reset-btn:hover {
    background: var(--danger);
    color: #fff;
}

.custom-montage-save-row {
    display: flex;
    gap: 8px;
    margin-top: 12px;
}

.custom-montage-name-input {
    flex: 1;
    padding: 6px 10px;
    font-size: 13px;
    border: 1px solid var(--gray-300);
    border-radius: 4px;
    color: var(--gray-700);
}

.custom-montage-save-btn {
    padding: 6px 16px;
    font-size: 13px;
    font-weight: 600;
    background: var(--accent);
    color: #fff;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}

.custom-montage-save-btn:hover {
    background: var(--accent-hover);
}

.saved-montages-list {
    list-style: none;
    margin: 8px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.saved-montage-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 13px;
    color: var(--gray-800);
    background: var(--gray-50);
    border: 1px solid var(--gray-100);
    border-radius: 4px;
    padding: 6px 10px;
}

.saved-montage-item.active {
    border-color: var(--accent);
    background: var(--accent-bg-strong);
    color: var(--accent-text);
    font-weight: 600;
}

.saved-montage-edit {
    background: none;
    border: 1px solid var(--accent-light);
    border-radius: 3px;
    color: var(--accent-light);
    cursor: pointer;
    font-size: 11px;
    padding: 2px 6px;
    line-height: 1;
}

.saved-montage-edit:hover {
    background: var(--accent-light);
    color: #fff;
}

.saved-montage-delete {
    background: none;
    border: none;
    color: var(--gray-400);
    cursor: pointer;
    font-size: 14px;
    padding: 0 2px;
    line-height: 1;
}

.saved-montage-delete:hover {
    color: var(--danger);
}

/* Custom Montage Dock ---------------------------------------------------------
   The builder used to be a tab in the Settings modal, which meant authoring a
   montage while the traces you were authoring it against sat behind a scrim. It
   is now a dock on the left that takes its width out of #canvasContainer, the
   same trick .dsa-dock plays with height on the bottom edge - the EEG narrows and
   redraws rather than being covered. The one other thing pinned to the left edge
   steps aside by the same variable.

   Kept at the end of the file, after the @media blocks above, because the mobile
   overrides at the bottom of this section have the same specificity as their
   desktop counterparts - a media query adds none - and so have to come later in
   source order to win. This is why .dsa-dock's own mobile rules sit inside the
   earlier @media block rather than beside it. */

.montage-dock {
    display: none;
    position: fixed;
    top: 40px; /* below the header bar */
    left: 0;
    bottom: 0;
    width: var(--montage-dock-width);
    /* Tinted rather than white. A white panel butted against a white canvas needs its
       1px border to do all the work of saying "this is not the recording", and at the
       left edge - where the channel labels start immediately - that border was lost.
       The tint separates them even before you reach the rule. */
    background-color: var(--gray-50);
    border-right: 3px solid var(--gray-300);
    box-shadow: 4px 0 14px rgba(15, 23, 42, 0.10);
    z-index: 1001;
    flex-direction: column;
}

body.montage-open .montage-dock {
    display: flex;
}

/* Give the dock its space out of the EEG area rather than overlapping it. The
   canvas is sized from canvasContainer.clientWidth, so the JS side only has to
   call resizeCanvas() once this rule has applied. */
body.montage-open #canvasContainer {
    left: var(--montage-dock-width);
}

/* The DSA strip spans the full width under the EEG, so it gives up the same slice. */
body.montage-open .dsa-dock {
    left: var(--montage-dock-width);
}

/* The only other thing anchored to the left edge: the watermark, deliberately offset
   past the channel labels. It keeps that offset, measured from the dock rather than
   the viewport. The annotation sidebar, channel-groups panel and watermark image are
   all on the right and need nothing - the dock never reaches them. */
body.montage-open .watermark-logo {
    left: calc(var(--montage-dock-width) + 60px);
}

.montage-dock-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex: none;
    padding: 8px 8px 8px 12px;
    border-bottom: 1px solid var(--gray-200);
    background-color: var(--gray-100);
}

.montage-dock-header h4 {
    margin: 0;
    font-size: 14px;
    font-weight: 600;
    color: var(--gray-700);
}

/* Dock tabs ------------------------------------------------------------------
   The strip sits where a title would, so the second panel costs no extra row. The
   Settings button is the dock's only trigger; these switch which panel it shows. */
.dock-tabs {
    display: flex;
    align-items: center;
    gap: 2px;
}

.dock-tab {
    padding: 4px 10px;
    border: 0;
    border-radius: 4px;
    background: none;
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    color: var(--gray-500);
    cursor: pointer;
}

.dock-tab:hover {
    color: var(--gray-700);
    background-color: var(--gray-200);
}

.dock-tab.active {
    background-color: #fff;
    color: var(--gray-700);
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.08);
}

.montage-dock-close {
    background: none;
    border: 0;
    padding: 0 6px;
    font-size: 24px;
    line-height: 1;
    color: var(--gray-500);
    cursor: pointer;
}

.montage-dock-close:hover {
    color: var(--gray-700);
}

.montage-dock-body {
    flex: 1;
    overflow-y: auto;
    padding: 14px 14px 20px;
}

/* Tighter than in the modal: the steps have to share a 340px column with the
   electrode grid rather than a 500px one. */
.montage-dock .builder-steps {
    padding: 9px 10px 9px 24px;
    font-size: 11px;
    line-height: 1.45;
}

/* Three columns of electrode buttons at ~70px plus gaps clear 340px comfortably,
   but a file with unusual channel names adds an "Other" column - let it wrap
   rather than squeeze the labels. */
.montage-dock .custom-montage-electrodes {
    flex-wrap: wrap;
    gap: 10px;
}

.montage-dock .custom-montage-electrode-col {
    min-width: 62px;
}

/* These three were var(--gray-50) blocks reading as raised cards on the modal's white
   body. On the dock's tinted body they would be the same colour as the ground, so they
   swap to white and keep the same figure/ground relationship. */
.montage-dock .builder-steps,
.montage-dock .custom-montage-electrode-btn,
.montage-dock .saved-montage-item {
    background: #fff;
}

.montage-dock .custom-montage-electrode-btn:hover {
    background: var(--gray-100);
}

/* The two rules above are descendant selectors, so they outrank the unscoped
   .custom-montage-electrode-btn.selected and would paint the first-clicked electrode
   white mid-pair. Restate the selected state at matching depth, hover included. */
.montage-dock .custom-montage-electrode-btn.selected,
.montage-dock .custom-montage-electrode-btn.selected:hover {
    background: var(--accent-bg-strong);
}

/* Montage dock on a phone. Splitting a sub-900px viewport leaves the traces too
   narrow to read anything off, so the dock stops reflowing and covers the EEG
   instead. Everything it displaces on the desktop layout goes back to its normal
   offset - the dock is on top of them now, not beside them. */
@media (max-width: 900px) {
    .montage-dock {
        width: 100%;
    }

    body.montage-open #canvasContainer,
    body.montage-open .dsa-dock {
        left: 0;
    }

    body.montage-open .watermark-logo {
        left: 60px;
    }
}

/* Snapshot Modal */
.snapshot-modal {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.5);
    z-index: 10000;
    justify-content: center;
    align-items: center;
}

.snapshot-modal.open {
    display: flex;
}

.snapshot-modal-content {
    background-color: #fff;
    border-radius: 8px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
    width: 90%;
    max-width: 500px;
    display: flex;
    flex-direction: column;
}

.snapshot-modal-header {
    padding: 16px 20px;
    border-bottom: 1px solid var(--gray-200);
    display: flex;
    justify-content: space-between;
    align-items: center;
    background-color: var(--gray-50);
    border-radius: 8px 8px 0 0;
}

.snapshot-modal-header h3 {
    margin: 0;
    font-size: 18px;
    color: var(--gray-700);
    font-weight: 600;
}

.close-snapshot-btn {
    background: none;
    border: none;
    font-size: 32px;
    line-height: 1;
    color: var(--gray-500);
    cursor: pointer;
    padding: 0;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 4px;
    transition: all 0.2s;
}

.close-snapshot-btn:hover {
    background-color: var(--gray-100);
    color: var(--gray-700);
}

.snapshot-modal-body {
    padding: 20px;
}

.snapshot-info {
    margin-bottom: 20px;
    padding: 12px;
    background-color: var(--gray-50);
    border-radius: 4px;
    text-align: center;
}

.snapshot-info p {
    margin: 0;
    font-size: 14px;
    color: var(--gray-700);
}

.snapshot-info strong {
    color: var(--accent);
    font-weight: 600;
}

.snapshot-mode-selector {
    margin-bottom: 20px;
    padding: 15px;
    background-color: var(--gray-50);
    border-radius: 4px;
}

.snapshot-mode-option {
    display: block;
    padding: 10px;
    margin-bottom: 8px;
    cursor: pointer;
    font-size: 14px;
    color: var(--gray-700);
}

.snapshot-mode-option:last-child {
    margin-bottom: 0;
}

.snapshot-mode-option input[type="radio"] {
    margin-right: 8px;
    cursor: pointer;
}

.snapshot-mode-option:hover {
    background-color: var(--gray-100);
    border-radius: 4px;
}

.snapshot-section {
    margin-bottom: 20px;
}

.snapshot-field {
    margin-bottom: 20px;
}

.snapshot-field label {
    display: block;
    margin-bottom: 8px;
    font-size: 14px;
    font-weight: 600;
    color: var(--gray-700);
}

.snapshot-input {
    width: 100%;
    padding: 8px 12px;
    border: 1px solid var(--gray-300);
    border-radius: 4px;
    font-size: 14px;
    color: var(--gray-700);
    background-color: #fff;
    margin-bottom: 8px;
}

.snapshot-input:focus {
    border-color: var(--accent-light);
    outline: 0;
    box-shadow: 0 0 0 0.2rem rgba(13, 125, 125, 0.25);
}

.snapshot-input-group {
    margin-bottom: 20px;
}

.snapshot-input-group label {
    display: block;
    margin-bottom: 8px;
    font-size: 14px;
    font-weight: 600;
    color: var(--gray-700);
}

.snapshot-textarea {
    width: 100%;
    padding: 8px 12px;
    border: 1px solid var(--gray-300);
    border-radius: 4px;
    font-size: 14px;
    color: var(--gray-700);
    background-color: #fff;
    font-family: var(--font-family);
    resize: vertical;
}

.snapshot-textarea:focus {
    border-color: var(--accent-light);
    outline: 0;
    box-shadow: 0 0 0 0.2rem rgba(13, 125, 125, 0.25);
}

.snapshot-select {
    width: 100%;
    padding: 8px 12px;
    border: 1px solid var(--gray-300);
    border-radius: 4px;
    font-size: 14px;
    color: var(--gray-700);
    background-color: #fff;
    cursor: pointer;
}

.snapshot-select:focus {
    border-color: var(--accent-light);
    outline: 0;
    box-shadow: 0 0 0 0.2rem rgba(13, 125, 125, 0.25);
}

.snapshot-slider {
    width: 100%;
    height: 6px;
    border-radius: 3px;
    background: var(--gray-200);
    outline: none;
    cursor: pointer;
}

.snapshot-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--accent);
    cursor: pointer;
    transition: background 0.2s;
}

.snapshot-slider::-webkit-slider-thumb:hover {
    background: var(--accent-hover);
}

.snapshot-slider::-moz-range-thumb {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--accent);
    cursor: pointer;
    border: none;
    transition: background 0.2s;
}

.snapshot-slider::-moz-range-thumb:hover {
    background: var(--accent-hover);
}

/* Takes no space until there is something to say, so the modal does not jump. */
.snapshot-status {
    margin: 0 0 12px;
    font-size: 13px;
    color: var(--gray-600);
}

.snapshot-status:empty {
    display: none;
}

.snapshot-buttons {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    margin-top: 20px;
}

.snapshot-btn {
    padding: 8px 20px;
    border: 1px solid var(--gray-300);
    border-radius: 4px;
    font-size: 14px;
    cursor: pointer;
    transition: all 0.2s;
    font-weight: 500;
}

.snapshot-btn.primary {
    background-color: var(--accent);
    color: white;
    border-color: var(--accent);
}

.snapshot-btn.primary:hover {
    background-color: var(--accent-hover);
    border-color: var(--accent-hover);
}

.snapshot-btn.secondary {
    background-color: var(--gray-500);
    color: white;
    border-color: var(--gray-500);
}

.snapshot-btn.secondary:hover {
    background-color: var(--gray-600);
    border-color: var(--gray-600);
}

/* Custom value modal - reuses the snapshot modal shell, just narrower */
.custom-value-modal-content {
    max-width: 340px;
}

.custom-value-label {
    display: block;
    margin-bottom: 8px;
    font-size: 14px;
    font-weight: 600;
    color: var(--gray-700);
}

.custom-value-field {
    position: relative;
}

.custom-value-field .snapshot-input {
    margin-bottom: 0;
    padding-right: 64px;
    font-size: 16px;
}

.custom-value-unit {
    position: absolute;
    right: 12px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 14px;
    color: var(--gray-500);
    pointer-events: none;
}

.custom-value-hint {
    margin: 8px 0 0;
    min-height: 18px;
    font-size: 13px;
    color: var(--gray-500);
}

.custom-value-hint.error {
    color: #c0392b;
}

.custom-value-field .snapshot-input.invalid {
    border-color: #c0392b;
    box-shadow: 0 0 0 0.2rem rgba(192, 57, 43, 0.2);
}

/* Hide elements when embedded in an iframe */
.in-iframe #toggleAnnotationsButton,
.in-iframe #annotationSidebar,
.in-iframe #clipMenuWrap,
.in-iframe #saveButton,
/* Embedded inside an exam question - nobody is authoring montages there. The dock
   itself has to stay, though: Settings lives in it now and the Settings button is
   still shown in embeds, so hiding the whole dock (as this rule used to) would leave
   Settings with no way to open. Only the montage half goes, leaving a one-tab dock, and the
   traces still lose no width until someone actually opens it. */
.in-iframe #dockTabMontage,
.in-iframe [data-dock-panel="montage"] {
    display: none !important;
}


/* ---- RAVE 3D brain panel -------------------------------------------------
   Sits beside the traces rather than over them: canvasContainer's right edge
   is pulled in by the same custom property the panel is sized from, so one
   value moves both and they can never disagree. */
:root {
    --brain-panel-width: 42%;
}
.brain-panel {
    position: fixed;
    top: 40px;
    right: 0;
    bottom: 0;
    width: var(--brain-panel-width);
    display: none;
    flex-direction: column;
    background: #fff;
    border-left: 1px solid #ccc;
    z-index: 5;
}
body.brain-open .brain-panel {
    display: flex;
}
body.brain-open #canvasContainer {
    right: var(--brain-panel-width);
}
.brain-panel-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    padding: 4px 8px 4px 14px;
    font-size: 12px;
    font-weight: 600;
    color: #333;
    background: #f1f1f1;
    border-bottom: 1px solid #ddd;
}
/* The brain panel's help: a solid "?" badge that opens the Brain tab of the side dock.
   Its header is busy with checkboxes, so it needs to read as a button at a glance. */
.brain-info-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: #222;
    color: #fff;
    font-family: inherit;
    font-size: 12px;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
}
.brain-info-icon:hover {
    background: #555;
    color: #fff;
}
.brain-panel-status {
    font-weight: 400;
    color: #6c757d;
    margin-left: auto;
}
.brain-panel-close {
    border: 0;
    background: none;
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    color: #666;
    padding: 0 2px;
}
.brain-panel-close:hover {
    color: #000;
}
.brain-frame-wrap {
    position: relative;
    flex: 1 1 auto;
    display: flex;
    min-height: 0;
}
.brain-frame {
    flex: 1 1 auto;
    width: 100%;
    border: 0;
    min-height: 0;
}
/* Covers the frame while the bundle downloads and builds, so the first open is not a
   long blank panel. Over the frame rather than instead of it: a display:none iframe
   would load, but the viewer inside would size its canvas to nothing. */
.brain-loading {
    position: absolute;
    inset: 0;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    background: #fff;
}
.brain-loading[hidden] {
    display: none;
}
.brain-loading-spinner {
    width: 56px;
    height: 56px;
    margin-bottom: 6px;
    border: 5px solid #e3e3e3;
    border-top-color: #222;
    border-radius: 50%;
    animation: brain-loading-spin 0.9s linear infinite;
}
@keyframes brain-loading-spin {
    to { transform: rotate(360deg); }
}
.brain-loading-title {
    font-size: 18px;
    font-weight: 600;
    color: #333;
}
.brain-loading-hint {
    font-size: 13px;
    color: #6c757d;
}
/* Grab strip on the panel's left edge. Sits outside the border so it does not
   overlap the iframe, which would swallow the drag once the pointer entered it. */
.brain-resizer {
    position: absolute;
    top: 0;
    bottom: 0;
    left: -3px;
    width: 7px;
    cursor: col-resize;
    z-index: 6;
}
.brain-resizer:hover,
body.brain-resizing .brain-resizer {
    background: rgba(0, 123, 255, 0.35);
}
/* While dragging, the iframe must not receive the pointer or the drag stops
   the moment it crosses into the brain. */
body.brain-resizing .brain-frame {
    pointer-events: none;
}
body.brain-resizing {
    cursor: col-resize;
    user-select: none;
}
@media (max-width: 900px) {
    :root {
        --brain-panel-width: 100%;
    }
    body.brain-open #canvasContainer {
        display: none;
    }
}

/* Follow toggle in the brain panel header. Lives with the panel rather than the main
   header bar: it only means anything while the brain is open. */
.brain-follow-label {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-weight: 400;
    font-size: 11px;
    color: #555;
    cursor: pointer;
    user-select: none;
}
.brain-follow-label input {
    margin: 0;
    cursor: pointer;
}
/* Slice position slider, beside the slice dropdown while a slice is shown */
.brain-slice-control {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-weight: 400;
    font-size: 11px;
    color: #555;
}
.brain-slice-control[hidden] {
    display: none;
}
.brain-slice-control input[type="range"] {
    width: 90px;
    margin: 0;
    cursor: pointer;
}
.brain-slice-value {
    min-width: 44px;
    font-variant-numeric: tabular-nums;
}
/* Brain / Transparent / Superimposed - sized to sit in line with the toggles */
.brain-view-select {
    font-size: 11px;
    height: 20px;
    padding: 0 2px;
    color: #333;
    background: #fff;
    border: 1px solid #ccc;
    border-radius: 3px;
    cursor: pointer;
}

/* Zoom nudges in the brain panel header. The brain's apparent size is camera zoom, not
   canvas size, so widening the panel alone never fills the reclaimed space. */
.brain-zoom-group {
    display: inline-flex;
    gap: 2px;
}
.brain-zoom-btn {
    border: 1px solid #ccc;
    background: #fff;
    color: #333;
    font-size: 12px;
    line-height: 1;
    width: 20px;
    height: 18px;
    border-radius: 3px;
    cursor: pointer;
    padding: 0;
}
.brain-zoom-btn:hover {
    background: #e9e9e9;
}
