/* ── Layout ──────────────────────────────────────────────────────────────── */

html, body {
    margin: 0;
    padding: 0;
    height: 100%;
    font-family: var(--font);
    color: var(--text);
    background-color: var(--bg);
}

/* Body is a flex column so the header (which may wrap to a second
   row at narrow viewports), #appMain, and the status bar each get
   their natural height — no more fixed-pixel calc() that breaks
   when the header reflows. Horizontal overflow scrolls on the body
   as a final fallback when content can't shrink any further. */
body {
    display: flex;
    flex-direction: column;
    height: 100vh;
    overflow-x: auto;
    overflow-y: hidden;
    /* Hard floor for the body. Below this, the html-level scrollbar
       picks up and the user can pan horizontally rather than seeing
       the right edge clipped. */
    min-width: 320px;
}

#appMain {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    height: auto;                  /* override the old calc(100vh - 2.65rem) */
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.browse-root {
    display: flex;
    flex-direction: column;
    flex: 1;
    height: 100%;
    overflow: hidden;
    background: var(--bg);
}

/* ── Toolbar ─────────────────────────────────────────────────────────────── */

.browse-toolbar {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.4rem 1rem;
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}

.view-mode-toggle {
    display: inline-flex;
    gap: 0;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
}

.view-mode-toggle .btn {
    border-radius: 0;
    border: none;
    border-right: 1px solid var(--border);
}

.view-mode-toggle .btn:last-child {
    border-right: none;
}

.view-mode-toggle .btn[aria-selected="true"] {
    background: var(--primary);
    color: var(--text-light);
}

/* Breadcrumbs */
.breadcrumbs {
    flex: 1;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.15rem 0.4rem;
    font-size: 0.85rem;
    color: var(--text-muted);
    min-width: 0;
}

.breadcrumbs a,
.breadcrumbs button {
    color: var(--text-muted);
    background: none;
    border: 0;
    padding: 0.1rem 0.3rem;
    border-radius: var(--radius);
    cursor: pointer;
    text-decoration: none;
    font: inherit;
}

.breadcrumbs a:hover,
.breadcrumbs button:hover {
    color: var(--text);
    background: var(--bg-hover);
}

.breadcrumbs .bc-sep {
    color: var(--text-muted);
    user-select: none;
}

.breadcrumbs .bc-current {
    color: var(--text);
    font-weight: 600;
    padding: 0.1rem 0.3rem;
}

.bc-home-icon {
    width: 1em;
    height: 1em;
    vertical-align: -0.15em;
}

/* ── Two-pane browse view ────────────────────────────────────────────────── */

.browse-view {
    display: flex;
    flex: 1;
    overflow: hidden;
    min-height: 0;
}

.pane {
    overflow: hidden;
    background: var(--bg);
    display: flex;
    flex-direction: column;
}

.tree-pane {
    width: 360px;
    min-width: 200px;
    max-width: 60%;
    border-right: 1px solid var(--border);
    flex-shrink: 0;
}

.tree-pane__toolbar {
    padding: 0.4rem 0.5rem;
    border-bottom: 1px solid var(--border);
    background: var(--bg-secondary);
    flex-shrink: 0;
}

/* Single-input autofilter — same grammar as the archive app's column
   filters (terms, quotes, !negation, multi-word AND). type=search so
   the browser ships the native clear-X for free; the .filter-active
   class amber-highlights the input while a query is set, matching
   the archive `.column-filter.filter-active` cue. */
.tree-filter {
    width: 100%;
    box-sizing: border-box;
    padding: 0.3rem 0.5rem;
    font-family: var(--font);
    font-size: 0.85rem;
    color: var(--text);
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    outline: none;
    transition: border-color 0.12s, background 0.12s;
}

.tree-filter:focus {
    border-color: var(--primary);
    box-shadow: 0 0 0 2px var(--primary-light);
}

.tree-filter.filter-active {
    background: rgba(234, 179, 8, 0.18);
    border-color: rgba(234, 179, 8, 0.7);
}

.tree-pane__body {
    flex: 1;
    overflow: auto;
    padding: 0.25rem 0;
    font-size: 0.875rem;
}

/* Pane resizer — 4px grab handle between tree and preview */
.pane-resizer {
    width: 4px;
    background: transparent;
    cursor: col-resize;
    flex-shrink: 0;
    position: relative;
    z-index: 1;
}

.pane-resizer:hover,
.pane-resizer.is-dragging {
    background: var(--primary);
}

.preview-pane {
    flex: 1;
    min-width: 0;
}

.preview-pane__header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 0.75rem;
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
    min-height: 2.1rem;
}

.preview-pane__title {
    flex: 1;
    font-size: 0.9rem;
    font-weight: 500;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

.preview-pane__meta {
    font-size: 0.8rem;
    color: var(--text-muted);
    white-space: nowrap;
}

.preview-pane__body {
    flex: 1;
    min-height: 0;          /* critical: lets the flex child shrink to fit
                               the viewport instead of growing to its
                               content's natural size (which clips the
                               YAML editor's bottom when there are many
                               lines, even with the editor's own scroll) */
    overflow: auto;
    display: flex;
    flex-direction: column;
    background: var(--bg);
}

/* The body's children fill the available space. Plugins inject
   different content here — img, iframe, pre, custom markdown editor. */
.preview-pane__body > * {
    flex: 1;
    min-height: 0;
}

.preview-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
    font-size: 0.95rem;
    padding: 2rem;
    text-align: center;
}

.preview-pane__body img.preview-image {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    margin: auto;
    display: block;
    flex: none; /* avoid flex sizing interfering with object-fit */
}

.preview-pane__body iframe.preview-iframe {
    width: 100%;
    height: 100%;
    border: none;
}

.preview-pane__body pre.preview-text {
    padding: 1rem;
    font-family: var(--font-mono);
    font-size: 0.85rem;
    white-space: pre-wrap;
    word-wrap: break-word;
    margin: 0;
    overflow: auto;
    background: var(--bg);
    color: var(--text);
}

/* ── Tree (vertical, file-explorer style) ───────────────────────────────── */

.tree-row {
    display: flex;
    /* Top-aligned so the chevron + icon anchor to the title line on
       two-line ZDDC rows. Single-line rows are unaffected because the
       icon, chevron, and label all share a top edge. */
    align-items: flex-start;
    gap: 0.25rem;
    padding: 0.2rem 0.5rem;
    cursor: pointer;
    user-select: none;
    border-radius: 0;
    color: var(--text);
}

.tree-row:hover {
    background: var(--bg-hover);
}

.tree-row.is-selected {
    background: var(--bg-selected);
    color: var(--text);
}

/* Per-row "⋯" actions button — the visible affordance that a row has a
   context menu. Hidden until the row is hovered/selected or the button
   itself is keyboard-focused, so it stays out of the way during reading
   but is discoverable without knowing to right-click. Pushed to the right
   edge; never part of the tab order (rows use roving tabindex). */
.tree-row__kebab {
    margin-left: auto;
    align-self: flex-start;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.4rem;
    height: 1.4rem;
    padding: 0;
    border: none;
    background: transparent;
    color: var(--text-muted, #888);
    border-radius: var(--radius);
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.1s, background 0.1s, color 0.1s;
}
.tree-row__kebab svg { width: 1em; height: 1em; }
.tree-row:hover .tree-row__kebab,
.tree-row.is-selected .tree-row__kebab,
.tree-row__kebab:focus-visible {
    opacity: 1;
}
.tree-row__kebab:hover,
.tree-row__kebab:focus-visible {
    background: var(--bg-hover);
    color: var(--text);
}

/* Tree-pane toolbar controls row (New folder/file, Sort, Show hidden),
   sitting under the filter input. */
.tree-pane__controls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    margin-top: 0.4rem;
}
.tree-pane__controls .tp-control {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.8rem;
    color: var(--text-muted, #888);
}
.tree-pane__controls .tp-control--check { cursor: pointer; }
.tree-pane__controls select {
    font-family: var(--font);
    font-size: 0.8rem;
    color: var(--text);
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 0.15rem 0.3rem;
}

/* Per-row drop target highlight: applied while a file/folder drag is
   hovering this row. The dashed outline reads as "drop here" without
   shifting layout. */
.tree-row.is-droptarget {
    background: var(--primary-light);
    outline: 2px dashed var(--primary);
    outline-offset: -2px;
}

.tree-row.is-selected .tree-name__label {
    color: var(--text);
}

.tree-name__chevron {
    /* Fixed-width slot so leaf rows (empty chevron) still align with
       expandable rows. The SVG inside is sized via the rule below.
       Top-anchored to the title-line baseline by the row's flex-start
       alignment + this small top offset. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1rem;
    height: 1.2em;
    flex-shrink: 0;
    color: var(--text-muted);
}

.tree-name__chevron svg {
    width: 0.85em;
    height: 0.85em;
    transition: transform 0.12s ease;
}

/* Expanded state — rotate the same chevron 90° rather than swapping
   to a second glyph. Smooth, single-sprite, and consistent with the
   way most modern file trees indicate expand state. */
.tree-row.expanded .tree-name__chevron svg {
    transform: rotate(90deg);
}

.tree-name__icon {
    flex-shrink: 0;
    /* Stacked column — glyph on top, extension chip below for files.
       Wider min-width than the 1em glyph itself so common extensions
       (pdf/docx/xlsx/json) don't push the label sideways. Height
       grows with content; flex-start anchors to the title-line. */
    min-width: 2.2em;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    color: var(--text-muted);
    gap: 1px;
}

.tree-name__icon svg {
    width: 1em;
    height: 1em;
    display: block;
}

.tree-name__ext {
    font-size: 0.58rem;
    line-height: 1;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 600;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Folder rows get the primary accent so directories stand out from
   files at a glance — same convention as macOS Finder / GNOME Files. */
.tree-row[data-isdir="true"] .tree-name__icon,
.tree-row[data-iszip="true"] .tree-name__icon {
    color: var(--primary);
}

/* Selected rows tint icon to match the label color (the bg-selected
   token already differentiates the row background). */
.tree-row.is-selected .tree-name__icon {
    color: var(--text);
}

.tree-name__label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--text);
    min-width: 0;
}

/* Two-line ZDDC variant. Top line is monospace + small + muted so the
   trackingNumber / revision / status fields line up vertically across
   adjacent rows (every field has a fixed width by convention). Bottom
   line is the human-readable title at normal weight. */
.tree-name__label--zddc {
    display: flex;
    flex-direction: column;
    line-height: 1.15;
    /* Tight gap between meta and title; tweak by 1-2 px if the rows
       feel crowded on dense lists. */
    gap: 0.05rem;
}

.tree-name__meta {
    font-family: var(--font-mono);
    font-size: 0.7rem;
    /* Explicit weight: the folder-row rule below bolds .tree-name__label,
       which would otherwise inherit through to the meta span. We want
       the meta to stay light + muted on every row. */
    font-weight: 400;
    color: var(--text-muted);
    /* Belt-and-braces: monospace already gives column-alignment, but
       tabular-nums hardens it on the rare proportional fallback. */
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.01em;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tree-name__title {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--text);
}

.tree-row.is-selected .tree-name__title {
    color: var(--text);
}

.tree-row[data-isdir="true"] .tree-name__label,
.tree-row[data-iszip="true"] .tree-name__label {
    font-weight: 500;
}

/* ── Drag-drop upload overlay ─────────────────────────────────────────────── */
/* Shown only while a drag is active over the page AND the current scope
   accepts uploads. Pointer-events:none below dragover so the underlying
   drop event still reaches the document handlers. */
.upload-overlay {
    position: fixed;
    inset: 0;
    z-index: 50;
    pointer-events: none;
    background: rgba(42, 90, 138, 0.18);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.12s ease;
}
.upload-overlay.is-active {
    opacity: 1;
}
.upload-overlay__panel {
    background: var(--bg);
    border: 2px dashed var(--primary);
    border-radius: var(--radius);
    padding: 1.5rem 2.25rem;
    text-align: center;
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18);
    pointer-events: none;
    color: var(--text);
    max-width: 80vw;
}
.upload-overlay__icon {
    font-size: 2.5rem;
    line-height: 1;
    color: var(--primary);
}
.upload-overlay__title {
    font-family: var(--font-display);
    font-size: 1.15rem;
    font-weight: 600;
    margin-top: 0.5rem;
}
.upload-overlay__path {
    margin-top: 0.35rem;
    font-family: var(--font-mono);
    font-size: 0.82rem;
    color: var(--text-muted);
    word-break: break-all;
}

/* Virtual rows: synthesized for folders/files declared by the
   cascade but absent from disk. The visual language reads as
   "expected, not yet materialized" — italic label, muted accent
   color, dashed left rail, and an outlined icon. Hover/select
   chrome still applies on top; the dashed rail sits inside the row
   so it doesn't fight padding-left indentation. */
.tree-row--virtual {
    box-shadow: inset 2px 0 0 0 transparent;
    position: relative;
}
.tree-row--virtual::before {
    content: '';
    position: absolute;
    top: 4px;
    bottom: 4px;
    left: 2px;
    border-left: 2px dashed var(--accent-muted, #8aa4cc);
    pointer-events: none;
}
.tree-row--virtual .tree-name__label {
    font-style: italic;
    color: var(--text-muted, #6b7280);
}
.tree-row--virtual .tree-name__icon {
    /* Hollow out the filled Lucide glyph: reduce fill opacity so
       the icon reads as an outline-only sketch — the conventional
       "placeholder, not actual" cue across UI systems. */
    opacity: 0.5;
}
.tree-row--virtual .tree-name__icon svg {
    fill: none;
    stroke: currentColor;
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.tree-row--virtual.is-selected::before {
    /* Selected virtual row: rail brightens to selection accent so the
       row reads as both selected and placeholder. */
    border-left-color: var(--accent, #2868c8);
}

.tree-name__hint {
    margin-left: 0.5rem;
    font-size: 0.78rem;
    color: var(--accent-muted, #8aa4cc);
    font-style: italic;
}

/* ── Grid view (Phase C) ─────────────────────────────────────────────────── */

.grid-view {
    flex: 1;
    overflow: auto;
    background: var(--bg);
    padding: 0;
}

.grid-empty {
    padding: 3rem;
    text-align: center;
    color: var(--text-muted);
}

/* ── Markdown plugin (right-pane internals when a .md is selected) ──────── */
/* CSS-Grid shell mirroring mdedit's layout: sidebar on the LEFT
   (front matter top + TOC bottom), content on the RIGHT (informational
   header above the Toast UI editor). The grid gives every cell a
   definite size, which Toast UI needs to compute its scroll regions
   correctly. */
.md-shell {
    display: grid;
    grid-template-rows: 1fr;
    /* minmax(0, …) on BOTH tracks is load-bearing: a bare `1fr` is
       `minmax(auto, 1fr)`, whose `auto` floor is the editor's min-content
       width (Toast UI's toolbar). That floor stops the content track from
       shrinking, so the whole shell overflows #previewBody as the window
       narrows instead of the editor getting narrower. minmax(0, 1fr) drops
       the floor so the editor reflows down to nothing. JS overrides the
       column widths on drag — it preserves the minmax(0, …) form. */
    grid-template-columns: minmax(0, 280px) minmax(0, 1fr);
    grid-template-areas: "sidebar content";
    height: 100%;
    min-height: 0;
    background: var(--bg);
    overflow: hidden;
}

/* Sidebar (col 1): three stacked items — Front matter (fixed height,
   drag-resizable), the horizontal resizer (between FM and TOC), then
   the TOC section taking the remaining height. Flexbox keeps the
   resizer position unambiguous; the previous grid-overlay approach
   was hard to read and prone to misplacement. */
.md-shell__sidebar {
    grid-area: sidebar;
    display: flex;
    flex-direction: column;
    min-width: 0;
    min-height: 0;
    overflow: hidden;
    border-right: 1px solid var(--border);
    background: var(--bg);
    position: relative;
}

/* Vertical sidebar/content resizer. Sits absolutely on the column
   boundary so it doesn't occupy a grid track. */
.md-shell__resizer {
    grid-area: sidebar;
    align-self: stretch;
    justify-self: end;
    width: 6px;
    margin-right: -3px;
    cursor: col-resize;
    background: transparent;
    z-index: 2;
    transition: background 0.12s;
}
.md-shell__resizer:hover,
.md-shell__resizer.is-dragging,
.md-shell__resizer:focus-visible {
    background: var(--primary);
    outline: none;
}

/* Horizontal resizer — a real flex item between FM and TOC. Drag
   it up/down to change the front-matter pane's height; the JS
   handler updates fmSection.style.height directly. */
.md-shell__fmresizer {
    flex: 0 0 6px;
    height: 6px;
    cursor: row-resize;
    background: var(--border);
    transition: background 0.12s;
    /* Subtle "grab" affordance — a slightly darker bar appears on
       hover so users see this is the drag handle. */
}
.md-shell__fmresizer:hover,
.md-shell__fmresizer.is-dragging,
.md-shell__fmresizer:focus-visible {
    background: var(--primary);
    outline: none;
}

/* Content (col 2): informational header above the Toast UI editor. */
.md-shell__content {
    grid-area: content;
    display: grid;
    grid-template-rows: auto 1fr;
    min-width: 0;
    min-height: 0;
    overflow: hidden;
}

/* Informational header above the editor: file name on the left, then
   dirty marker, status, source hint, save button. Reads as a header
   for the content panel — file metadata at a glance. */
.md-shell__infohdr {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 0.75rem;
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border);
    font-size: 0.85rem;
}
.md-shell__title {
    flex: 1;
    font-family: var(--font-display);
    font-size: 1rem;
    font-weight: 600;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
.md-shell__dirty {
    color: var(--text-muted);
    font-size: 0.85rem;
    min-width: 5.5rem;
    text-align: right;
}
.md-shell__status {
    color: var(--text-muted);
    font-size: 0.85rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 14rem;
}
.md-shell__source {
    color: var(--text-muted);
    font-size: 0.75rem;
    font-style: italic;
    padding: 0.15rem 0.4rem;
    border-radius: var(--radius);
    background: var(--bg);
    border: 1px solid var(--border);
}
.md-shell__download {
    /* Slightly tighter than the Save button so a row of three doesn't
       crowd the title. The base .btn styles still drive padding/color. */
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.02em;
}
.md-shell__download[disabled] {
    opacity: 0.55;
    cursor: progress;
}

/* Editor host: a single grid cell with overflow:hidden so Toast UI's
   internal scrollers handle the content. */
.md-shell__editor {
    min-width: 0;
    min-height: 0;
    overflow: hidden;
}

.md-side {
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}

/* Front-matter section: fixed (resizable) height, set inline by the
   markdown plugin's mount + drag-handler. flex:0 0 auto so the
   explicit height wins over the parent flex layout. */
.md-side--fm {
    flex: 0 0 auto;
}

/* TOC section: takes everything that's left. min-height:0 so the
   inner body's overflow:auto kicks in instead of pushing the
   resizer off-screen. */
.md-side--toc {
    flex: 1 1 auto;
    min-height: 0;
}

.md-side__header {
    /* Header is its own flex item so the body can stretch to fill. */
    flex: 0 0 auto;
    padding: 0.35rem 0.75rem;
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border);
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-muted);
}

.md-side__body {
    /* Both axes — the textarea uses white-space:pre so long YAML
       lines need horizontal scroll, and the TOC entries below now
       extend their full width so deep headings need it too. */
    flex: 1 1 auto;
    overflow: auto;
    min-height: 0;
    padding: 0.3rem 0;
    font-size: 0.85rem;
    line-height: 1.45;
}

/* ── Outline list ───────────────────────────────────────────────────────── */
.md-toc__empty {
    color: var(--text-muted);
    font-style: italic;
    padding: 0.5rem 0.75rem;
    margin: 0;
    font-size: 0.82rem;
}
.md-toc__list {
    list-style: none;
    margin: 0;
    padding: 0;
}
.md-toc__item {
    margin: 0;
    padding: 0.22rem 0.75rem;
    color: var(--text);
    cursor: pointer;
    border-left: 2px solid transparent;
    transition: background 0.1s, border-color 0.1s, color 0.1s;
    /* Single-line items but no ellipsis — long headings extend the
       item's intrinsic width, and the parent .md-side__body has
       overflow:auto, so they create a horizontal scrollbar instead
       of getting clipped. The title attribute still carries the
       full text for SR users. */
    white-space: nowrap;
}
.md-toc__item:hover {
    background: var(--bg-secondary);
    border-left-color: var(--primary);
}
.md-toc__item:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: -2px;
}
.md-toc__item--l1 { padding-left: 0.75rem; font-weight: 600; }
.md-toc__item--l2 { padding-left: 1.4rem; }
.md-toc__item--l3 { padding-left: 2.05rem; font-size: 0.82rem; }
.md-toc__item--l4 { padding-left: 2.7rem;  font-size: 0.8rem;  color: var(--text-muted); }
.md-toc__item--l5 { padding-left: 3.35rem; font-size: 0.78rem; color: var(--text-muted); }
.md-toc__item--l6 { padding-left: 4rem;    font-size: 0.78rem; color: var(--text-muted); }

/* Flash on click — applied to the heading element in the editor pane.
   The class is scoped to .md-toc__flash so it doesn't paint outside
   this plugin. */
.md-toc__flash {
    background-color: rgba(95, 168, 224, 0.25) !important;
    transition: background-color 0.3s ease;
}

/* ── Front matter editor ────────────────────────────────────────────────── */
.md-fm__body {
    /* Body cell owns the textarea; sized by the sidebar's grid row. */
    padding: 0;
    display: block;
    overflow: hidden;
}
.md-fm__textarea {
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    margin: 0;
    padding: 0.4rem 0.6rem;
    border: 0;
    background: transparent;
    color: var(--text);
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Consolas, monospace);
    font-size: 0.8rem;
    line-height: 1.45;
    resize: none;
    outline: none;
    white-space: pre;
    overflow: auto;
    tab-size: 2;
}
.md-fm__textarea::placeholder {
    color: var(--text-muted);
    font-style: italic;
}
.md-fm__textarea:focus {
    background: var(--surface-2, rgba(0, 0, 0, 0.025));
}
.md-fm__textarea[readonly] {
    color: var(--text-muted);
    cursor: not-allowed;
}

/* Older .md-fm-section / .fm-list / .md-toc-resizer rules were replaced
   by the .md-shell BEM block above. */

/* ── Hover info card ────────────────────────────────────────────────────── */
/* Singleton element appended to <body> by browse/js/hovercard.js.
   Replaces the native title="…" tooltip on tree rows with a rich
   metadata view (ZDDC parse fields + filesystem info). */
.tree-hovercard {
    position: fixed;
    z-index: 9000;
    max-width: 28rem;
    min-width: 17rem;
    background: var(--bg);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18),
                0 2px 6px  rgba(0, 0, 0, 0.10);
    padding: 0.5rem 0.7rem 0.45rem;
    font-family: var(--font);
    font-size: 0.8rem;
    line-height: 1.35;
    opacity: 0;
    visibility: hidden;
    /* pointer-events:auto so the user can mouse into the card to
       select text. The hide is delayed (HIDE_DELAY_MS in hovercard.js)
       so the cursor has time to traverse the gap between row and card
       before the card dismisses. */
    pointer-events: auto;
    /* The tree rows set user-select:none — explicitly allow it here
       so dragging across the card builds a real selection that can be
       Ctrl/Cmd-C'd or right-click-Copied via the browser's native menu. */
    user-select: text;
    cursor: default;
    transition: opacity 0.1s ease;
}

.tree-hovercard.is-visible {
    opacity: 1;
    visibility: visible;
}

/* Highlight selected text inside the card with the primary accent so
   it reads as "yes, you can copy this" rather than the default browser
   selection color. */
.tree-hovercard ::selection {
    background: var(--primary-light);
    color: var(--text);
}

.tree-hovercard__header {
    margin-bottom: 0.35rem;
}

.tree-hovercard__title {
    font-weight: 600;
    font-size: 0.95rem;
    line-height: 1.2;
    color: var(--text);
    word-break: break-word;
}

.tree-hovercard__sub {
    margin-top: 0.15rem;
    font-family: var(--font-mono);
    font-size: 0.72rem;
    color: var(--text-muted);
    letter-spacing: 0.01em;
}

.tree-hovercard__list {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 0.12rem 0.7rem;
    align-items: baseline;
}

.tree-hovercard__key {
    color: var(--text-muted);
    font-size: 0.74rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.tree-hovercard__val {
    color: var(--text);
    font-size: 0.82rem;
    word-break: break-word;
}

.tree-hovercard__val--mono {
    font-family: var(--font-mono);
    font-size: 0.78rem;
}

/* Archive-reference links inside the hovercard pick up the primary
   accent so they read as clickable, and stay inline with the mono
   font when they sit inside a mono cell. */
.tree-hovercard__val a {
    color: var(--primary, #2868c8);
    text-decoration: none;
}
.tree-hovercard__val a:hover {
    text-decoration: underline;
}

/* Separator stretches across both grid columns. Bleed into the
   card's padding so it visually reads as a divider, not a hairline. */
.tree-hovercard__sep {
    grid-column: 1 / -1;
    border-top: 1px solid var(--border);
    margin: 0.25rem -0.7rem;
}
