@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');

html, body {
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

a, .btn-link {
    color: #0366d6;
}

.btn-primary {
    color: #fff;
    background-color: #1b6ec2;
    border-color: #1861ac;
}

.content {
    padding-top: 1.1rem;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid red;
}

.validation-message {
    color: red;
}

#blazor-error-ui {
    background: grey;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
}

/* global CSS file */
.dropzone {
    position: relative;
    border: 2px dashed rgba(0,0,0,0.15);
    border-radius: 8px;
    padding: 24px;
    height: 200px;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    background: transparent;
    color: white;
}

    .dropzone label {
        z-index: 1;
        pointer-events: none;
        color: white;
    }

    .dropzone input[type="file"] {
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        opacity: 0;
        cursor: pointer;
        z-index: 2;
    }

.dropzone-active {
    border-color: #3399ff;
    background: rgba(51, 153, 255, 0.06);
}


.rich-text-content ol,
.rich-text-content ul {
    margin: 0 0 1rem;
    padding-left: 1.5rem;
}

.rich-text-content li {
    list-style-position: outside;
}

.rich-text-content li > .ql-ui {
    display: none;
}

.rich-text-content li[data-list="bullet"]::marker {
    content: "•  ";
}

.rich-text-content li[data-list="bullet"].ql-indent-1 {
    margin-left: 1.5rem;
}

.rich-text-content li[data-list="bullet"].ql-indent-1::marker {
    content: "◦  ";
}

.rich-text-content li[data-list="bullet"].ql-indent-2 {
    margin-left: 3rem;
}

.rich-text-content li[data-list="bullet"].ql-indent-2::marker {
    content: "▪  ";
}

.rich-text-content li[data-list="ordered"]::marker {
    content: counter(list-item) ". ";
}

/* ===== Notes page layout (global because scoped CSS does not reach RenderFragment-emitted elements) ===== */

/* On the Notes page, turn the main-content area into a flex column so the shell
   fills exactly the height left under the heading — no hardcoded viewport math,
   which left a dead gap at short resolutions (e.g. 1366x768). */
.mud-main-content:has(.notes-shell) {
    display: flex;
    flex-direction: column;
    height: 100vh;   /* fallback */
    height: 100dvh;
    min-height: 0;
    overflow: hidden;
}

.notes-shell {
    display: flex !important;
    flex-direction: row !important;
    align-items: stretch !important;
    justify-content: flex-start !important;
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
    max-width: 100%;
    overflow-x: auto;
    overflow-y: hidden;
    gap: 4px;
    padding: 6px;
    scrollbar-gutter: stable;
    background: #0d1117 !important; /* outer shell — shows in the gap between columns */
}

/* Tweak these three to recolor the columns. */
.notes-shell .notes-rail {
    background: #0a0d12; /* column 1 */
}
.notes-shell .notes-browser {
    display: flex !important;
    flex-direction: column !important;
    align-items: stretch !important;
    justify-content: flex-start !important;
    align-self: stretch !important;
    overflow: hidden;
    box-sizing: border-box;
    flex: 0 0 auto !important;
    background: #11151d;
}

/* Collapsed browser: the sliver column that keeps the hamburger reachable, and the
   rule that folds the search row + rail + middle away. Desktop only — below md the
   browser is a slide-over and must stay reachable from the editor toolbar. */
@media (min-width: 960px) {
    .notes-shell .notes-browser-collapsed {
        display: none !important;
    }
}

.notes-shell .notes-collapsed-bar {
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
    justify-content: flex-start !important;
    align-self: stretch !important;
    flex: 0 0 auto !important;
    width: 40px;
    min-width: 40px;
    /* Centers the icon in the same 56px band the search row occupies, so it stays
       put when toggling between the collapsed and expanded states. */
    padding: 13px 0 4px 0;
    min-height: 56px;
    box-sizing: border-box;
    background: #11151d;
    border-right: 1px solid rgba(255,255,255,0.08);
}

.notes-shell .notes-browser-search {
    display: flex !important;
    flex-direction: row !important;
    align-items: center !important;
    gap: 6px;
    padding: 4px 8px;
    min-height: 56px;
    flex: 0 0 auto !important;
    box-sizing: border-box;
    background: #151a24;
}

.notes-shell .notes-browser-actions {
    display: flex !important;
    flex-direction: row !important;
    align-items: center !important;
    gap: 4px;
    min-height: 40px;
    flex: 0 0 auto !important;
    box-sizing: border-box;
    background: #11151d;
}

.notes-shell .notes-browser-actions .rail-toolbar,
.notes-shell .notes-browser-actions .middle-toolbar {
    min-height: 40px;
    align-items: center !important;
    padding: 0 8px;
}

.notes-shell .notes-browser-body {
    display: flex !important;
    flex-direction: row !important;
    align-items: stretch !important;
    gap: 4px;
    flex: 1 1 auto !important;
    min-height: 0 !important;
    overflow: hidden;
}

.notes-shell .notes-middle {
    background: #1f1f1f; /* column 2 */
}
.notes-shell .notes-editor {
    background: #1c1c1c; /* notes / editor area */
}

.notes-shell .notes-rail,
.notes-shell .notes-middle,
.notes-shell .notes-editor {
    display: flex !important;
    flex-direction: column !important;
    align-items: stretch !important;
    justify-content: flex-start !important;
    align-self: stretch !important;
    overflow: hidden;
    box-sizing: border-box;
}

.notes-shell .notes-rail {
    width: 260px;
    min-width: 220px;
    border-right: 1px solid rgba(255,255,255,0.08);
    padding-right: 6px;
}

.notes-shell .rail-toolbar {
    display: flex !important;
    flex-direction: row !important;
    align-items: flex-end !important;
    gap: 4px;
    padding: 4px 8px;
    min-height: 56px;
    flex: 0 0 auto !important;
    box-sizing: border-box;
}

.notes-shell .rail-scroll {
    display: block !important;
    flex: 1 1 auto !important;
    min-height: 0 !important;
    overflow-y: auto;
    padding: 4px 0 16px 0;
}

.notes-shell .rail-section,
.notes-shell .rail-group-header {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 8px 8px;
    cursor: pointer;
    user-select: none;
    border-radius: 4px;
    margin: 2px 4px;
    border-left: 3px solid transparent;
    min-height: 36px;
}

.notes-shell .rail-section:hover,
.notes-shell .rail-group-header:hover {
    background: rgba(255,255,255,0.05);
}

.notes-shell .rail-selected {
    background: rgba(63, 81, 181, 0.32) !important;
    border-left-color: #7986cb !important;
    font-weight: 600;
}

.notes-shell .rail-section,
.notes-shell .rail-group-header,
.notes-shell .note-row {
    position: relative;
}

/* Note-drop highlight on rail rows (CanDropClass of the per-section OnlyZones). */
.notes-shell .rail-drop-into {
    outline: 2px solid #7986cb !important;
    outline-offset: -2px;
    background: rgba(121, 134, 203, 0.28) !important;
}

/* NoDropClass: a group hovering over another group's child zone can't land there. */
.notes-shell .rail-no-drop {
    outline: 2px dashed rgba(244, 67, 54, 0.55) !important;
    outline-offset: -2px;
}

/* Rail drag grips */
.notes-shell .rail-grip-icon {
    opacity: .45;
    flex-shrink: 0;
}

/* Rail reorder placeholders (root zone + group child zones). */
.notes-shell .notes-rail .mud-dropitem-placeholder {
    min-height: 32px;
    padding: 0 !important;
    border: 1px dashed #7986cb;
    border-radius: 4px;
    margin: 2px 4px;
}

.notes-shell .rail-name {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.92rem;
}

.notes-shell .rail-name-edit {
    flex: 1 1 auto;
    display: inline-flex;
    align-items: center;
    margin-left: 4px;
}

.notes-shell .rail-kebab {
    display: inline-flex;
    align-items: center;
    margin-left: auto;
}

.notes-shell .rail-group {
    margin: 4px 0;
}

/* Group child drop zone: indented like the old children wrapper; min-height keeps an
   empty (but expanded) group droppable — its reorder placeholder needs somewhere to land. */
.notes-shell .rail-group-children {
    display: block;
    min-height: 14px;
    padding-left: 18px;
    border-left: 1px solid rgba(255,255,255,0.06);
    margin-left: 12px;
}

/* Root rail zone fills the scroll area so end-of-list drops land. */
.notes-shell .rail-root-dropzone {
    display: block;
    min-height: 24px;
}

.notes-shell .rail-section-system {
    opacity: 0.85;
    font-style: italic;
}

.notes-shell .notes-middle {
    width: 320px;
    min-width: 260px;
    border-right: 1px solid rgba(255,255,255,0.08);
    padding-right: 6px;
}

.notes-shell .middle-toolbar {
    display: flex !important;
    flex-direction: row !important;
    align-items: flex-end !important;
    gap: 6px;
    padding: 4px 8px;
    min-height: 56px;
    flex: 0 0 auto !important;
    box-sizing: border-box;
}

.notes-shell .notes-browser-body > .notes-middle > .middle-toolbar,
.notes-shell .notes-browser-body > .notes-middle > .middle-toolbar + .mud-divider {
    display: none !important;
}

.notes-shell .middle-scroll {
    display: block !important;
    flex: 1 1 auto !important;
    min-height: 0 !important;
    overflow-y: auto;
}

.notes-shell .note-row {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 10px 10px;
    cursor: pointer;
    border-bottom: 1px solid rgba(255,255,255,0.04);
    border-left: 3px solid transparent;
    min-height: 40px;
    user-select: none;
    -webkit-user-select: none;
}

/* The middle column's MudBlazor drop zone: fill the scroll area so end-of-list drops land. */
.notes-shell .notes-middle-dropzone {
    display: block;
    min-height: 40px;
}

/* Row content inside a rail section's note-drop OnlyZone — replicates the row's flex layout. */
.notes-shell .rail-note-target {
    display: flex;
    align-items: center;
    gap: 4px;
    flex: 1 1 auto;
    min-width: 0;
}

/* Reorder placeholder for note rows (override the chunky pa-4 default). */
.notes-shell .middle-scroll .mud-dropitem-placeholder {
    min-height: 32px;
    padding: 0 !important;
    border: 1px dashed #7986cb;
    border-radius: 4px;
    margin: 2px 4px;
}

/* EbookHighlight notes aren't draggable (ItemDisabled) — don't gray them out. */
.notes-shell .note-item-static {
    cursor: default;
    opacity: 1;
}

/* Safety net: rows use MudDragHandle grips, so the item wrapper itself should never be
   draggable. If a row ever ends up whole-draggable again, keep it scrollable by touch
   (MudBlazor's default touch-action:none would freeze the list). The grip keeps its own
   touch-action:none via MudBlazor's .mud-drag-handle rule, so handle-drags still work. */
.notes-shell .mud-drop-item[draggable="true"],
.tasks-shell .mud-drop-item[draggable="true"],
.audio-page .mud-drop-item[draggable="true"] {
    touch-action: pan-y;
}

/* Drag-handle grips: pad the hit area for touch without shifting the row layout. */
.tasks-shell .row-drag-handle,
.notes-shell .row-drag-handle,
.audio-page .row-drag-handle {
    padding: 6px;
    margin: -6px;
    flex-shrink: 0;
}

.notes-shell .note-drag-icon {
    opacity: .45;
    flex-shrink: 0;
}

.notes-shell .note-row:hover {
    background: rgba(255,255,255,0.05);
}

.notes-shell .note-selected {
    background: rgba(63, 81, 181, 0.32) !important;
    border-left-color: #7986cb !important;
    font-weight: 600;
}

/* Audio playlist reorder uses MudBlazor drag & drop (MudDropContainer/MudDropZone). */
.audio-page .playlist-entry-row {
    position: relative;
    display: flex;
    align-items: center;
    width: 100%;
}

/* Unresolved rows aren't draggable (ItemDisabled) — keep them looking normal, not grayed. */
.audio-page .playlist-entry-static {
    cursor: default;
    opacity: 1;
}

/* Reorder placeholder shown while dragging an entry (override the chunky pa-4 default). */
.audio-page .mud-dropitem-placeholder {
    min-height: 40px;
    padding: 0 !important;
    border: 1px dashed #7986cb;
    border-radius: 4px;
    margin: 2px 4px;
}

.notes-shell .note-name {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    -webkit-user-drag: none;
}

.notes-shell .notes-editor {
    /* Shrinkable down to min-width so narrow viewports squeeze the editor
       before falling back to the shell's horizontal scrollbar. */
    flex: 1 1 520px !important;
    min-width: 420px;
    padding-left: 6px;
}

.notes-shell .editor-toolbar {
    display: flex !important;
    flex-direction: row !important;
    /* Wrap based on the editor's own width, not a viewport media query — the
       fixed-width rail/middle columns can squeeze the editor at any resolution. */
    flex-wrap: wrap;
    align-items: center !important;
    gap: 8px;
    padding: 4px 8px;
    min-height: 56px;
    flex: 0 0 auto !important;
    box-sizing: border-box;
}

.notes-shell .editor-status {
    font-size: 0.8rem;
    min-width: 110px;
    text-align: right;
}

.notes-shell .editor-body {
    display: block !important;
    flex: 1 1 auto !important;
    min-height: 0 !important;
    overflow: auto;
    padding: 8px;
}

.notes-shell .empty-editor {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
    font-style: italic;
}

.notes-shell .rail-chevron {
    display: inline-flex;
    align-items: center;
    cursor: pointer;
    padding: 2px;
    margin-right: 2px;
    border-radius: 3px;
}

.notes-shell .rail-chevron:hover {
    background: rgba(255,255,255,0.12);
}

/* Force MudDivider inside a Notes column (or popout) to a 1px line — without
   this it stretches to fill remaining vertical space and creates a huge gap. */
.notes-shell hr.mud-divider,
.notes-popout-shell hr.mud-divider {
    flex: 0 0 auto !important;
    height: 1px !important;
    min-height: 0 !important;
    max-height: 1px !important;
    margin: 0 !important;
    padding: 0 !important;
    border-width: 1px 0 0 0 !important;
    box-sizing: border-box !important;
    align-self: stretch !important;
}

/* Custom rounded-tab SVG icons for sections and section groups.
   fill="currentColor" makes the tint follow the CSS color property,
   so changing color is just a matter of overriding the color rule. */
.notes-shell .rail-section-icon,
.notes-shell .rail-group-icon {
    color: #4a90e2; /* default tab color; override per-row via inline style if needed */
    flex-shrink: 0;
    display: inline-block;
}

.notes-shell .rail-group-icon {
    color: #9aa0a6; /* neutral; section groups never participate in the color palette */
}

/* Column resize handles (column 1 + column 2). Thin transparent strip at the right edge
   that highlights on hover; drag changes the column width. */
.notes-shell .col-resize-handle {
    position: absolute;
    top: 0;
    right: 0;
    width: 6px;
    height: 100%;
    cursor: ew-resize;
    z-index: 20;
    background: transparent;
    user-select: none;
}

.notes-shell .col-resize-handle:hover,
.notes-shell .col-resize-handle.resizing {
    background: rgba(121, 134, 203, 0.4);
}

/* The columns must be position: relative so the absolute handle anchors correctly. */
.notes-shell .notes-rail,
.notes-shell .notes-middle {
    position: relative;
}

/* Read-only note badge in the notes list. */
.notes-shell .note-readonly-badge {
    color: #9aa0a6;
    flex-shrink: 0;
    opacity: 0.85;
}

/* Read-only visual cues for the body editor. Input is actually blocked by
   MudHtmlEditor.ReadOnly (which calls Quill's enable(false)); these styles
   just reinforce the read-only feel without breaking scroll. */
.notes-shell .editor-body-readonly .ql-editor {
    cursor: default;
    caret-color: transparent;
}

@media (max-width: 900px) {
    .notes-shell {
        padding: 4px;
        gap: 4px;
    }
}

@media (max-width: 600px) {
    .mud-main-content:has(.notes-shell) {
        padding-left: 8px !important;
        padding-right: 8px !important;
    }

    .notes-shell {
        padding: 2px;
        gap: 2px;
    }

    .notes-shell .notes-browser-body {
        gap: 2px;
    }

    .notes-shell .editor-toolbar {
        gap: 6px;
        padding: 4px 6px;
    }

    .notes-shell .editor-body {
        padding: 6px;
    }
}

/* ===== Notes mobile: editor owns the screen; rail+middle become a drill-down slide-over.
   Same DOM as desktop (both drag & drop containers keep working) — only re-positioned. ===== */

.notes-mobile-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.5);
    z-index: 1299;
}

@media (min-width: 960px) {
    .notes-mobile-overlay {
        display: none;
    }
}

@media (max-width: 959.98px) {
    /* Editor takes the full shell width (overrides the desktop flex-basis rules). */
    .notes-shell .notes-editor {
        flex: 1 1 100% !important;
        flex-basis: auto !important;
        width: 100%;
        min-width: 0;
    }

    /* The browser column becomes a fixed slide-over panel (inline px width overridden). */
    .notes-shell .notes-browser {
        position: fixed;
        top: 0;
        left: 0;
        bottom: 0;
        width: min(92vw, 400px) !important;
        z-index: 1300;
        transform: translateX(-105%);
        transition: transform .18s ease-out;
        box-shadow: 4px 0 16px rgba(0,0,0,0.5);
    }

    .notes-shell .notes-browser.mobile-open {
        transform: translateX(0);
    }

    /* Drill-down: one pane at a time, full panel width. Pane 1 = rail, pane 2 = notes. */
    .notes-shell .notes-browser.mobile-pane-rail .notes-middle,
    .notes-shell .notes-browser.mobile-pane-rail .notes-browser-actions .middle-toolbar {
        display: none !important;
    }

    .notes-shell .notes-browser.mobile-pane-notes .notes-rail,
    .notes-shell .notes-browser.mobile-pane-notes .notes-browser-actions .rail-toolbar {
        display: none !important;
    }

    /* Panes and their toolbars stretch to the panel (inline px widths overridden). */
    .notes-shell .notes-rail,
    .notes-shell .notes-middle,
    .notes-shell .notes-browser-actions .rail-toolbar,
    .notes-shell .notes-browser-actions .middle-toolbar {
        width: 100% !important;
    }

    /* No column resizing in the slide-over. */
    .notes-shell .col-resize-handle {
        display: none;
    }
}

/* Match the Save button height to the Name textfield (Outlined + Dense ≈ 40px). */
.notes-shell .editor-toolbar .save-button {
    height: 40px;
    min-height: 40px;
    padding-top: 0;
    padding-bottom: 0;
}

.notes-shell .editor-toolbar .editor-name-field {
    flex: 1 1 auto;
    min-width: 220px;
    max-width: none;
}

.notes-shell .editor-toolbar .editor-last-modified-field {
    flex: 0 0 220px;
    min-width: 190px;
}

@media (max-width: 900px) {
    .notes-shell .editor-toolbar {
        align-items: flex-start !important;
    }

    .notes-shell .editor-toolbar .editor-name-field {
        flex: 1 1 170px;
        min-width: 140px;
    }

    .notes-shell .editor-toolbar .editor-last-modified-field {
        flex: 1 1 170px;
        min-width: 150px;
    }

    .notes-shell .editor-toolbar .save-button,
    .notes-shell .editor-toolbar .mud-icon-button {
        flex: 0 0 auto;
    }

    .notes-shell .editor-status {
        flex: 1 1 100px;
        min-width: 0;
        text-align: left;
    }
}

@media (max-width: 600px) {
    .notes-shell .editor-toolbar .editor-name-field,
    .notes-shell .editor-toolbar .editor-last-modified-field {
        flex: 0 0 100%;
        width: 100%;
        min-width: 100%;
        max-width: 100%;
    }
}

/* Popout window: edge-to-edge editor only, no rail / middle column. */
.notes-popout-shell {
    display: flex;
    flex-direction: column;
    height: 100vh;
    background: #1c1c1c;
    color: var(--mud-palette-text-primary, #e0e0e0);
}

.notes-popout-shell .editor-toolbar {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    padding: 6px 10px;
    min-height: 56px;
    flex: 0 0 auto;
}

.notes-popout-shell .editor-body {
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
    padding: 8px;
}

.notes-popout-shell .editor-body-readonly .ql-editor {
    cursor: default;
    caret-color: transparent;
}

.notes-popout-shell .save-button {
    height: 40px;
    min-height: 40px;
    padding-top: 0;
    padding-bottom: 0;
}

/* ===== Markdown notes (MarkdownNoteEditor: Milkdown Crepe, tools/milkdown) ===== */

/* "MD" marker on Markdown notes: notes list, editor toolbar (next to Name), quick note. */
.note-md-badge {
    flex-shrink: 0;
    font-size: 0.65rem;
    font-weight: 600;
    line-height: 1;
    padding: 2px 4px;
    border-radius: 3px;
    border: 1px solid currentColor;
    color: #9aa0a6;
    opacity: 0.85;
}

/* Fill the editor area: wrapper -> Crepe host -> .milkdown -> ProseMirror, so clicking empty space
   below the text still lands in the editor. */
.md-note-editor {
    display: flex;
    flex-direction: column;
    min-height: 100%;
}

/* Pinned to the top of the scrolling editor area. Shrink-wrapped to the buttons (align-self) with
   its own background, so it reads as a small floating cluster rather than a full-width band. */
.md-note-editor-actions {
    display: flex;
    justify-content: flex-end;
    gap: 2px;
    flex: 0 0 auto;
    align-self: flex-end;
    position: sticky;
    top: 0;
    z-index: 3;
    background: var(--mud-palette-surface);
    border-radius: 4px;
}

.md-note-crepe,
.md-note-crepe > .milkdown {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
}

/* Visible edit box (like Quill's bordered container), with a minimum typing area. */
.md-note-crepe {
    min-height: 10rem;
    border: 1px solid var(--mud-palette-lines-inputs);
    border-radius: 4px;
}

.md-cheatsheet-anchor {
    position: relative;
    display: inline-flex;
}

.md-cheatsheet-popover {
    width: min(520px, 92vw);
    padding: 8px 12px 12px 12px;
}

.md-cheatsheet-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-weight: 600;
    margin-bottom: 4px;
}

.md-cheatsheet-code {
    white-space: pre;
    font-family: 'Fira Code', Menlo, Consolas, 'Courier New', monospace;
    font-size: 0.82rem;
}

.md-cheatsheet-tips {
    margin-top: 8px;
    font-size: 0.8rem;
    line-height: 1.5;
}

/* Crepe's theme colors (frame.css) remapped to the MudBlazor palette, so the editor follows the
   app theme. Higher specificity than the theme's bare .milkdown rule. */
.md-note-editor .milkdown {
    --crepe-color-background: transparent;
    --crepe-color-on-background: var(--mud-palette-text-primary);
    --crepe-color-surface: var(--mud-palette-background-gray);
    --crepe-color-surface-low: var(--mud-palette-surface);
    --crepe-color-on-surface: var(--mud-palette-text-primary);
    --crepe-color-on-surface-variant: var(--mud-palette-text-secondary);
    --crepe-color-outline: var(--mud-palette-lines-inputs);
    --crepe-color-primary: var(--mud-palette-primary);
    --crepe-color-secondary: var(--mud-palette-action-disabled-background);
    --crepe-color-on-secondary: var(--mud-palette-text-primary);
    --crepe-color-inverse: var(--mud-palette-text-primary);
    --crepe-color-on-inverse: var(--mud-palette-surface);
    --crepe-color-inline-code: var(--mud-palette-error);
    --crepe-color-error: var(--mud-palette-error);
    --crepe-color-hover: var(--mud-palette-action-default-hover);
    --crepe-color-selected: var(--mud-palette-action-disabled-background);
    --crepe-color-inline-area: var(--mud-palette-background-gray);
    --crepe-base-font-size: 15px;
    --crepe-font-title: var(--mud-typography-default-family, Roboto, Arial, sans-serif);
    --crepe-font-default: var(--mud-typography-default-family, Roboto, Arial, sans-serif);
    --crepe-font-code: 'Fira Code', Menlo, Consolas, 'Courier New', monospace;
}

/* The theme pads 60px 120px for a full-page editor; the left gutter here keeps room for
   Crepe's block handle (the "+ ⋮⋮" that appears beside the hovered block). */
.md-note-editor .milkdown .ProseMirror {
    flex: 1 1 auto;
    padding: 8px 16px 24px 72px;
}

.md-note-source {
    flex: 1 1 auto;
    width: 100%;
    min-height: 20rem;
    resize: vertical;
    box-sizing: border-box;
    padding: 12px;
    font-family: 'Fira Code', Menlo, Consolas, 'Courier New', monospace;
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--mud-palette-text-primary);
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-inputs);
    border-radius: 4px;
    outline: none;
}

@media (max-width: 600px) {
    .md-note-editor .milkdown .ProseMirror {
        padding: 8px 8px 24px 36px;
    }
}

/* Placeholder shown in the main window while the note is open in a popup. */
.notes-shell .popout-placeholder {
    flex-direction: column;
    text-align: center;
    gap: 4px;
}

/* Popout window: strip the app bar, nav drawer, and any layout padding. */
body.notes-popout-active .mud-appbar,
body.notes-popout-active .mud-drawer,
body.notes-popout-active .mud-drawer-container,
body.notes-popout-active .mud-overlay {
    display: none !important;
}

body.notes-popout-active .mud-main-content {
    padding: 0 !important;
    margin: 0 !important;
}

body.notes-popout-active .mud-layout {
    height: 100vh !important;
}

body.notes-popout-active {
    overflow: hidden;
}

body.notes-popout-active.notes-quick-active {
    overflow-x: hidden !important;
    overflow-y: auto !important;
}

body.notes-popout-active.notes-quick-active .mud-layout {
    height: auto !important;
    min-height: 100dvh !important;
}

/* Ebook pure reader mode: center-tap in nav mode hides app and reader chrome. */
html.reader-pure-active,
body.reader-pure-active {
    background: #1e1e1e !important;
    height: 100%;
    margin: 0;
    overflow: hidden;
    overscroll-behavior: none;
}

body.reader-pure-active .mud-appbar,
body.reader-pure-active .mud-drawer,
body.reader-pure-active .mud-drawer-container {
    display: none !important;
}

body.reader-pure-active .mud-main-content {
    position: fixed !important;
    inset: 0 !important;
    z-index: 1200;
    padding: 0 !important;
    margin: 0 !important;
    width: 100vw !important;
    max-width: 100vw !important;
    height: var(--sx-reader-viewport-height, 100vh) !important;
    height: var(--sx-reader-viewport-height, 100dvh) !important;
    min-height: 0 !important;
    background: #1e1e1e !important;
    overflow: hidden;
}

body.reader-pure-active .mud-layout {
    height: var(--sx-reader-viewport-height, 100vh) !important;
    height: var(--sx-reader-viewport-height, 100dvh) !important;
    background: #1e1e1e !important;
    overflow: hidden;
}

.audio-page .audio-main-grid {
    align-items: stretch;
}

.audio-page .audio-main-grid > .mud-grid-item {
    display: flex;
    flex-direction: column;
}

.audio-page .audio-browser-card {
    box-sizing: border-box;
    width: 100%;
    height: 100%;
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.audio-page .audio-browser-tabs,
.audio-page .audio-browser-tabs .mud-tabs-panels,
.audio-page .audio-browser-tabs .mud-tab-panel,
.audio-page .audio-tab-stack {
    min-height: 0;
}

.audio-page .audio-browser-tabs {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    height: 100%;
}

.audio-page .audio-browser-tabs .mud-tabs-panels {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    height: 100%;
    min-height: 0;
    overflow: hidden;
}

/* MudBlazor 9 no longer applies MudTabPanel's Class to the panel content wrapper (it moved to the
   tab header button), and that wrapper now defaults to display:block; flex-grow:0 — so it no longer
   stretches to fill .mud-tabs-panels, which collapsed the inner scroll list to 0 height on desktop
   (tracks vanished ≥960px while mobile, which doesn't use this fill chain, was fine). Style the real
   wrapper class (.mud-tab-panel) directly so it fills and acts as the flex column the stack needs. */
.audio-page .audio-browser-tabs .mud-tab-panel {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    height: 100%;
    min-height: 0;
    overflow: hidden;
}

.audio-page .audio-tab-stack {
    display: flex;
    flex-direction: column;
    height: 100%;
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
}

.audio-page .audio-tab-stack > :not(.audio-tab-scroll-list) {
    flex: 0 0 auto;
}

.audio-page .audio-player-card {
    box-sizing: border-box;
    width: 100%;
    overflow: visible;
}

.audio-page .audio-player-empty {
    min-height: 60vh;
}

.audio-page .audio-player-status-row {
    display: flex;
    align-items: center;
    align-content: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 6px;
    width: 100%;
    margin-top: 8px;
    line-height: 1;
}

.audio-page .audio-player-status-chips {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 6px;
    min-width: 0;
    max-width: 100%;
}

.audio-page .audio-player-speed-control {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    justify-content: center;
    min-width: 0;
}

.audio-page .audio-player-speed-menu,
.audio-page .audio-player-sleep-menu {
    font-size: .75rem;
}

.audio-page .audio-player-status-row .mud-button-root,
.audio-page .audio-player-status-row .mud-chip {
    align-self: center;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 28px;
    min-height: 28px;
    margin-top: 0;
    margin-bottom: 0;
}

.audio-page .audio-player-status-row .mud-chip {
    padding-top: 0;
    padding-bottom: 0;
}

.audio-page .audio-player-status-row .mud-icon-button {
    width: 28px;
    height: 28px;
    padding: 0;
}

.audio-page .audio-player-status-row .mud-menu .mud-button-root {
    height: 28px;
    min-height: 28px;
}

.audio-page .audio-player-status-row .mud-chip-content {
    display: inline-flex;
    align-items: center;
    line-height: 1;
}

.audio-page .audio-player-status-chips .mud-chip {
    max-width: 100%;
}

.audio-page .audio-player-status-chips .mud-chip-content {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.audio-page .audio-player-shortcuts-info {
    opacity: .72;
}

.audio-page .audio-track-search {
    width: 100%;
}

@media (min-width: 960px) {
    .audio-page .audio-track-search {
        max-width: calc(66.666667% - 6px);
    }
}

.audio-page .audio-player-controls {
    width: 100%;
    max-width: 100%;
    justify-content: center;
    flex-wrap: nowrap;
    /* Tighter vertical gap BETWEEN the two control rows (bookmark/offline + transport) so they
       read as a single control cluster. The breathing room the user asked for goes BELOW the
       transport row, between the last button and the volume slider — see audio-player-volume. */
}

/* Bigger touch targets across all viewports. Two rows of controls leaves room to size up
   without horizontal overflow. Default Size.Large in MudBlazor is ~40px button / 24px icon;
   we push to 56/28 on desktop and scale down on phones. */
.audio-page .audio-player-controls .mud-icon-button {
    width: 56px;
    height: 56px;
    padding: 12px;
}

.audio-page .audio-player-controls .mud-icon-root {
    font-size: 1.85rem;
}

.audio-page .audio-player-volume {
    width: min(240px, 100%);
    /* Extra breathing room between the last button row and the volume slider — the user
       perceives the transport controls as a separate "thing" from the volume, this gap
       reinforces it. */
    margin-top: 20px;
}

.audio-page .audio-tab-scroll-list {
    flex: 1 1 0;
    min-height: 0;
    max-height: 100%;
    overflow-x: hidden;
    overflow-y: auto;
    scrollbar-gutter: stable;
}

@media (max-width: 959.95px) {
    .audio-page .audio-main-grid {
        align-items: stretch;
    }

    .audio-page .audio-main-grid > .mud-grid-item,
    .audio-page .audio-browser-card,
    .audio-page .audio-browser-tabs,
    .audio-page .audio-browser-tabs .mud-tabs-panels,
    .audio-page .audio-browser-tabs .mud-tab-panel,
    .audio-page .audio-tab-stack {
        height: auto;
        flex: 0 1 auto;
    }

    .audio-page .audio-main-grid > .mud-grid-item {
        width: 100%;
        max-width: 100%;
        flex-basis: 100%;
    }

    .audio-page .audio-browser-card,
    .audio-page .audio-player-card,
    .audio-page .audio-browser-tabs .mud-tabs-panels,
    .audio-page .audio-browser-tabs .mud-tab-panel,
    .audio-page .audio-tab-stack {
        overflow: visible;
    }

    .audio-page .audio-tab-scroll-list {
        flex: 0 1 auto;
        max-height: calc(60vh - 120px);
    }
}

@media (max-width: 600px) {
    .audio-page {
        padding-left: 8px !important;
        padding-right: 8px !important;
    }

    .audio-page .audio-player-controls {
        gap: 6px !important;
        justify-content: space-between;
    }

    .audio-page .audio-player-controls .mud-icon-button {
        width: 52px;
        height: 52px;
        padding: 10px;
        flex: 0 0 52px;
    }

    .audio-page .audio-player-controls .mud-icon-root {
        font-size: 1.7rem;
    }

    .audio-page .audio-player-volume {
        margin-top: 16px;
    }
}

@media (max-width: 390px) {
    .audio-page .audio-player-controls {
        gap: 2px !important;
    }

    .audio-page .audio-player-controls .mud-icon-button {
        width: 46px;
        height: 46px;
        padding: 8px;
        flex-basis: 46px;
    }

    .audio-page .audio-player-controls .mud-icon-root {
        font-size: 1.55rem;
    }

    .audio-page .audio-player-volume {
        margin-top: 14px;
    }
}

/* Note history dialog content fill. Replaces the now-obsolete MudDialog.ContentStyle
   (MudBlazor 9 prefers ContentClass + CSS). Global because MudDialog renders its content in the
   dialog provider's DOM, outside the component's scoped-CSS boundary. */
.note-history-dialog-content {
    height: 100%;
    padding-bottom: 8px;
}

/* Ebook add/edit-note dialog: a large (~90vw) two-column layout — highlighted-text reference on
   the left (25%), the note editor on the right (75%). Global for the same reason as above (dialog
   content renders outside the component's scoped CSS). The reference column stretches to the
   editor's height; the editor's textarea defines that height via min-height. */
.sx-note-dialog-content {
    width: min(90vw, 1400px);
    display: flex;
    gap: 16px;
    align-items: stretch;
}

.sx-note-dialog-ref {
    flex: 0 0 25%;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.sx-note-dialog-ref-text {
    flex: 1 1 0;
    min-height: 0;
    overflow-y: auto;
    background: #1e1e1e;
    border: 1px solid #424242;
    border-radius: 4px;
    padding: 12px;
    color: #e0e0e0;
}

.sx-note-dialog-editor {
    flex: 1 1 75%;
    min-width: 0;
}

.sx-note-dialog-editor textarea {
    min-height: 60vh;
    resize: vertical;
}

/* On narrow/mobile viewports a 25% reference column is too cramped — stack the columns instead.
   Narrower than desktop so the dialog leaves margins (its padding is a bigger share of a phone's
   width), with the quote box given a real height (the stacked column would otherwise collapse it). */
@media (max-width: 700px) {
    .sx-note-dialog-content {
        flex-direction: column;
        width: min(85vw, 600px);
    }
    .sx-note-dialog-ref {
        flex: 0 0 auto;
    }
    .sx-note-dialog-ref-text {
        flex: 0 0 auto;
        min-height: 16vh;
        max-height: 26vh;
    }
    .sx-note-dialog-editor textarea {
        min-height: 38vh;
    }
}

/* ===================== Tasks page (multi-list shell) ===================== */
/* Mirrors the Notes rail UI language: same row metrics, hover, selection and
   resize-handle styling, but with MudBlazor drop-zone drag & drop for the rail. */

.tasks-shell .tasks-body {
    display: flex;
    align-items: stretch;
    overflow: hidden;
    min-height: calc(100vh - 230px);
}

.tasks-shell .tasks-rail {
    position: relative;
    display: flex;
    flex-direction: column;
    flex: 0 0 auto;
    min-width: 170px;
    border-right: 1px solid rgba(255,255,255,0.08);
    padding-right: 6px;
}

.tasks-shell .tasks-main {
    flex: 1 1 auto;
    min-width: 0;
    padding: 8px 12px;
    overflow-y: auto;
}

/* Desktop search: inline in the header row, right of the sort menu. The dense
   outlined MudTextField carries a top margin meant for forms — zero it so the
   field centers on the toolbar row. Mobile uses .tasks-search, stacked full width. */
.tasks-shell .tasks-search-inline {
    width: 300px;
    flex-shrink: 1;
    min-width: 120px;
}

.tasks-shell .tasks-search-inline .mud-input-control {
    margin-top: 0;
}

/* Active task rows: compact metrics so they match the dense completed table.
   Row height floor is the Dense+Small checkbox (28px); dnd doesn't need more. */
.tasks-shell .task-row {
    padding: 1px 8px;
    margin: 2px 0;
    border-left: 3px solid #7986cb;
    transition: border-left-color 0.15s ease;
}

/* Rank number on active rows: the row's 1-based position in the list. Tabular
   digits keep multi-digit ranks aligned; muted so the name stays the focus. */
.tasks-shell .task-rank-cell {
    display: flex;
    align-items: center;
    gap: 2px;
}

.tasks-shell .task-rank {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    font-size: .8rem;
    opacity: .55;
    min-width: 16px;
    text-align: right;
}

.tasks-shell .task-rank-mobile {
    flex-shrink: 0;
    margin: 0 2px;
}

/* Completed table: pull MudBlazor's dense 6px cell padding in further so
   completed rows sit at the same height as the active rows above. */
.tasks-shell .task-table .mud-table-row .mud-table-cell {
    padding-top: 2px;
    padding-bottom: 2px;
}

.tasks-shell .rail-toolbar,
.tasks-mobile-panel .rail-toolbar {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 4px 8px;
    min-height: 44px;
    flex: 0 0 auto;
}

.tasks-shell .rail-title,
.tasks-mobile-panel .rail-title {
    text-transform: uppercase;
    letter-spacing: .04em;
    opacity: .8;
}

.tasks-shell .rail-scroll,
.tasks-mobile-panel .rail-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: 4px 0 16px 0;
}

.tasks-shell .rail-section,
.tasks-mobile-panel .rail-section {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 8px 8px;
    cursor: pointer;
    user-select: none;
    border-radius: 4px;
    margin: 2px 4px;
    border-left: 3px solid transparent;
    min-height: 36px;
}

.tasks-shell .rail-section:hover,
.tasks-mobile-panel .rail-section:hover {
    background: rgba(255,255,255,0.05);
}

.tasks-shell .rail-selected,
.tasks-mobile-panel .rail-selected {
    background: rgba(63, 81, 181, 0.32) !important;
    border-left-color: #7986cb !important;
    font-weight: 600;
}

.tasks-shell .rail-name,
.tasks-mobile-panel .rail-name {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.92rem;
}

.tasks-shell .rail-name-edit,
.tasks-mobile-panel .rail-name-edit {
    flex: 1 1 auto;
    display: inline-flex;
    align-items: center;
    margin-left: 4px;
}

.tasks-shell .rail-kebab,
.tasks-mobile-panel .rail-kebab {
    display: inline-flex;
    align-items: center;
    margin-left: auto;
}

.tasks-shell .rail-drag-icon {
    opacity: .55;
    flex-shrink: 0;
}

.tasks-shell .rail-dropzone {
    min-height: 40px;
}

/* MudBlazor wraps each rail row in a .mud-drop-item (mud-drop-item-draggable when it can drag). */
.tasks-shell .tasks-rail .mud-drop-item-draggable {
    cursor: grab;
}

.tasks-shell .tasks-rail .mud-drop-item-draggable:active {
    cursor: grabbing;
}

/* Non-manual sort / renaming rows aren't draggable (ItemDisabled) — normal cursor,
   and don't let MudBlazor's disabled styling gray the row out. */
.tasks-shell .tasks-rail .rail-item-static,
.tasks-shell .tasks-rail .rail-item-static .rail-section {
    cursor: default;
    opacity: 1;
}

/* Reorder placeholder shown while dragging a list row (override the chunky pa-4 default). */
.tasks-shell .tasks-rail .mud-dropitem-placeholder {
    min-height: 36px;
    padding: 0 !important;
    border: 1px dashed #7986cb;
    border-radius: 4px;
    margin: 2px 4px;
}

/* MudDivider defaults to FullWidth → .mud-divider-fullwidth has flex-grow:1, which in a
   flex COLUMN grows vertically and swallows the free space (rows end up vertically
   centered). Same clamp Notes uses: force dividers back to a 1px line. */
.tasks-shell hr.mud-divider,
.tasks-mobile-panel hr.mud-divider {
    flex: 0 0 auto !important;
    height: 1px !important;
    min-height: 0 !important;
    max-height: 1px !important;
    margin: 0 !important;
    padding: 0 !important;
    border-width: 1px 0 0 0 !important;
    box-sizing: border-box !important;
    align-self: stretch !important;
}

.tasks-shell .col-resize-handle {
    position: absolute;
    top: 0;
    right: 0;
    width: 6px;
    height: 100%;
    cursor: ew-resize;
    z-index: 20;
    background: transparent;
    user-select: none;
}

.tasks-shell .col-resize-handle:hover,
.tasks-shell .col-resize-handle.resizing {
    background: rgba(121, 134, 203, 0.4);
}

/* ===== Mobile slide-over list panel ===== */

.tasks-mobile-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.5);
    z-index: 1299;
}

.tasks-mobile-panel {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: min(85vw, 320px);
    z-index: 1300;
    display: flex;
    flex-direction: column;
    background: var(--mud-palette-surface);
    box-shadow: 4px 0 16px rgba(0,0,0,0.5);
    animation: tasks-panel-in .18s ease-out;
}

@keyframes tasks-panel-in {
    from { transform: translateX(-100%); }
    to   { transform: translateX(0); }
}

/* Below MudBlazor's md breakpoint (960px) the rail hides; the slide-over takes its place. */
@media (max-width: 959.98px) {
    .tasks-shell .tasks-rail {
        display: none;
    }

    .tasks-shell .tasks-main {
        padding: 4px 6px;
    }

    /* Mobile cards stack several lines — give them a little more breathing room. */
    .tasks-shell .task-row {
        padding: 6px 8px;
    }
}

/* Never show the mobile panel on desktop, even if it was left open while resizing. */
@media (min-width: 960px) {
    .tasks-mobile-overlay,
    .tasks-mobile-panel {
        display: none;
    }
}

/* Video library: reclaim the generic layout padding on phones. The page has its own compact
   spacing and needs the width for a usable two-column poster grid. */
.video-pagination-controls {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    flex-wrap: wrap;
    gap: 8px 14px;
    width: 100%;
    min-width: 0;
    padding: 4px 0;
}

.video-pagination-range,
.video-pagination-pages,
.video-pagination-page-size {
    min-width: 0;
}

.video-pagination-page-size {
    flex: 0 0 132px !important;
    width: 132px !important;
    min-width: 132px !important;
    max-width: 132px !important;
}

.video-pagination-page-size .mud-input-control,
.video-pagination-page-size .mud-input,
.video-pagination-page-size .mud-select {
    width: 132px !important;
    min-width: 132px !important;
    max-width: 132px !important;
}

@media (max-width: 599.98px) {
    /* Leave Safari's top control row, including Picture in Picture, unobstructed. */
    .video-player-bookmark-tap-zone {
        top: 48px !important;
        width: 30% !important;
        height: 28% !important;
    }

    .mud-main-content:has(.video-page) {
        padding-left: 8px !important;
        padding-right: 8px !important;
    }

    .video-pagination-controls {
        flex-direction: column;
        flex-wrap: nowrap;
        justify-content: flex-start;
        gap: 5px;
        padding: 6px 0 8px;
    }

    .video-pagination-range,
    .video-pagination-pages {
        max-width: 100%;
    }

    .video-pagination-page-size {
        flex: 0 0 auto !important;
        width: 100% !important;
        min-width: 0 !important;
        max-width: 100% !important;
    }

    .video-pagination-page-size .mud-input-control,
    .video-pagination-page-size .mud-input,
    .video-pagination-page-size .mud-select {
        width: 100% !important;
        min-width: 0 !important;
        max-width: 100% !important;
    }

    .video-pagination-pages {
        overflow-x: auto;
        overflow-y: hidden;
        scrollbar-width: none;
    }

    .video-pagination-pages::-webkit-scrollbar {
        display: none;
    }

    .video-pagination-pages .mud-pagination {
        justify-content: center;
        max-width: 100%;
    }

    .video-player-toolbar {
        flex-wrap: wrap;
        width: 100%;
        min-width: 0;
        column-gap: 4px !important;
        row-gap: 4px !important;
    }

    .video-player-toolbar .video-player-title {
        flex: 1 0 100% !important;
        width: 100%;
        max-width: 100%;
    }

    .video-player-toolbar .mud-icon-button {
        width: 44px;
        min-width: 44px;
        height: 44px;
        min-height: 44px;
    }

    .video-player-pip-control {
        flex: 0 0 44px;
        width: 44px;
        min-width: 44px;
        height: 44px;
        min-height: 44px;
        align-items: center;
        justify-content: center;
        padding: 10px;
        border: 0;
        border-radius: 50%;
        background: transparent;
        color: var(--mud-palette-text-primary);
        cursor: pointer;
    }
}

@media (min-width: 600px) {
    .video-player-pip-control {
        display: none !important;
    }
}

/* ---------- Streamazor poster layout ----------
   Fixed-size tiles rather than responsive grid columns, so the catalog, the search sections and the
   Continue watching rail all present posters at the SAME scale. The responsive-column approach they
   used before made a poster grow to a quarter of a wide screen, which dwarfed the rail. */
.streamazor-poster-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
}

/* Same cell, but scrolling sideways instead of wrapping (Continue watching). */
.streamazor-poster-rail {
    display: flex;
    gap: 12px;
    overflow-x: auto;
    padding-bottom: 6px;
}

.streamazor-poster-cell {
    flex: 0 0 auto;
    width: 150px;
}

/* Two per row still fits the narrowest phones (150 + 12 + 150 = 312px). */
@media (max-width: 340px) {
    .streamazor-poster-cell {
        width: 132px;
    }
}

/* ---------- Streamazor narrow-screen layout (SR-7) ----------
   Measured, not guessed: at a 375px viewport the player header laid out to 539px in a 355px row and
   the bookmarks table forced the whole PAGE to 790px. Both are fixed below; verified back down to a
   375px body with no sideways scroll.

   Note the source-list name column's width lives here rather than in an inline style, so the media
   query can override it without !important. */

.streamazor-source-name {
    width: 132px;
}

@media (max-width: 700px) {

    /* Player header carries up to 13 controls (title, quality chip, A/B loop, clear-loop, audio,
       subtitles, bookmark, bookmarks, watched, PiP, switch-source, close). Let the cluster wrap and
       give the title its own line rather than pushing controls off-screen. */
    .streamazor-player-bar {
        flex-wrap: wrap;
    }

    .streamazor-player-title {
        flex: 1 0 100%;
    }

    /* Source list: three columns become three stacked blocks. The middle one is AIO's own multi-line
       release text, and at ~139px it degrades into an unreadable ribbon. */
    .streamazor-source-row {
        flex-wrap: wrap;
    }

    .streamazor-source-name {
        width: 100%;
        flex: 1 0 100%;
    }

    .streamazor-source-desc {
        flex: 1 0 100%;
    }

    .streamazor-source-action {
        flex: 1 0 100%;
        display: flex;
        justify-content: flex-end;
    }

    /* Diagnostics: the 72px indent aligns fields under the message on a desktop; on a phone it is a
       fifth of the screen spent on alignment. */
    .streamazor-trace-fields {
        margin-left: 0 !important;
    }
}

/* A wide table must scroll inside its own box, never drag the page with it. */
.streamazor-table-wrap {
    overflow-x: auto;
}

/* ---- Sentry (rcSentry viewer) ---- */
.sentry-tile, .sentry-drive, .sentry-volume-pick {
    transition: transform .15s ease, box-shadow .15s ease;
}
.sentry-drive:hover, .sentry-volume-pick:hover {
    transform: translateY(-2px);
}
.sentry-bad {
    color: var(--mud-palette-error);
    font-weight: 600;
}
.sentry-kv td {
    border-bottom: none !important;
    padding-top: 2px !important;
    padding-bottom: 2px !important;
}
.sentry-kv td:first-child {
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
    width: 1%;
    padding-right: 16px !important;
}
.sentry-strip {
    display: flex;
    flex-wrap: wrap;
    gap: 3px;
}
.sentry-strip-dot {
    display: inline-block;
    width: 11px;
    height: 11px;
    border-radius: 2px;
}
.sentry-strip-dot.ok {
    background: var(--mud-palette-success);
}
.sentry-strip-dot.fail {
    background: var(--mud-palette-error);
}

/* Global scan overlays (VideoScanStatusBar, PhotoScanStatusBar), stacked so concurrent scans in
   both pillars don't sit on top of each other. Above the responsive navigation drawer, which can
   otherwise cover the cards' left edge at narrower desktop widths; below snackbars and dialogs so
   higher-priority feedback still wins. Empty (and click-through) when nothing is scanning. */
.scan-status-stack {
    position: fixed;
    top: 68px;
    right: 16px;
    /* One step below the photo lightbox (snackbar - 1), which would otherwise be covered. */
    z-index: calc(var(--mud-zindex-snackbar) - 2);
    width: min(560px, calc(100vw - 32px));
    display: flex;
    flex-direction: column;
    gap: 8px;
    pointer-events: none;
}

@media (max-width: 600px) {
    .scan-status-stack {
        top: 60px;
        right: 6px;
        width: calc(100vw - 12px);
    }
}
