/* docs.css — Documentation + Project files (Drawing Set): catalog rail with ports, reading sheet, splitters,
   doc search, repository tiles + file panel, notebook and mermaid containers, breadcrumb. Loads after style.css
   on every page, so everything here is scoped to this surface's own classes (.filelist is shared with Home). */

/* ── mermaid diagrams (rendered client-side from <pre class="mermaid">; theme in mermaid.js) ── */
.content pre.mermaid { margin: 0 0 14px; padding: 16px; overflow-x: auto; text-align: center; color: var(--rc-text); background: var(--rc-field); border: 1px solid var(--rc-line-strong); }
.content pre.mermaid svg { max-width: 100%; height: auto; }
/* on a phone a wide diagram keeps its natural size and scrolls inside its box (mermaid.js publishes --mm-w) instead of shrinking to unreadable text */
@media (max-width: 767px) { .content pre.mermaid svg { width: var(--mm-w, 100%); max-width: none !important; } }

/* ── page states (no sources / no repositories / nothing open): the drafting sheet is allowed behind empty states ── */
.doc-state { padding: 32px 16px; border: 1px solid var(--rc-line-strong); border-top: var(--sec-w, 1px) solid var(--sec, var(--rc-line-strong)); }
.doc-state--pane { min-height: 480px; }
/* base.html also prints `error` as a red banner; the state above says the same thing in place, once. */
.container:has(.doc-state, .repo-error) > .flash.error { display: none; }

/* ── breadcrumb: mono path, current crumb bright ── */
.breadcrumb { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; min-width: 0; margin: 0; color: var(--rc-text-mute); font: 500 13px/1.4 var(--rc-font-mono); }
.breadcrumb a { color: var(--rc-text-soft); text-decoration: none; }
.breadcrumb a:hover { color: var(--rc-text); text-decoration: underline; text-underline-offset: 3px; }
.breadcrumb a[aria-current="page"], .breadcrumb [aria-current="page"] { color: var(--rc-text); }
.breadcrumb .sep { color: var(--rc-text-faint); }

/* ═══ Documentation: catalog | reading sheet ═══════════════════════════════════
   [data-doc-layout] is the common ancestor docs.js reads. --cat-w / --pane-w have real defaults here
   (docs.js sets them inline once the reader drags or restores a saved width). */
.sidebar-layout[data-doc-layout] { --cat-w: 280px; --pane-w: 860px; --doc-row: 32px; --vis-w: 28px; display: flex; align-items: flex-start; gap: 12px; }
.sidebar-layout[data-doc-layout] .doc-catalog { flex: 0 0 var(--cat-w); }
/* the sheet sits against the catalog (as the Library's content does); spare width falls to its right */
.sidebar-layout[data-doc-layout] .doc-section { flex: 1 1 auto; min-width: 0; display: flex; justify-content: flex-start; }
.sidebar-layout[data-doc-layout] .doc-pane { flex: 0 1 var(--pane-w); min-width: 0; max-width: 100%; }
/* nothing open: the empty sheet takes the whole reading area */
.sidebar-layout[data-doc-layout]:not(.has-doc) .doc-pane { flex: 1 1 auto; }

/* splitters: a short handle mark at rest (the panels already draw the edges), a full accent hairline on hover/focus */
.doc-splitter, .doc-pane-resizer {
  flex: 0 0 8px; align-self: stretch; min-height: 240px; cursor: col-resize; touch-action: none;
  background: linear-gradient(var(--rc-line-bright), var(--rc-line-bright)) center / 1px 28px no-repeat;
}
.doc-splitter:hover, .doc-pane-resizer:hover, .doc-splitter:focus-visible, .doc-pane-resizer:focus-visible {
  background: linear-gradient(var(--rc-accent-ui), var(--rc-accent-ui)) center / 2px 100% no-repeat;
}

/* catalog rail: a raised panel, sticky under the chrome + layer bar */
.doc-catalog {
  position: sticky; top: calc(var(--topbar-h) + var(--rc-bar-h) + 16px); align-self: flex-start;
  max-height: calc(100vh - var(--topbar-h) - var(--rc-bar-h) - 32px); max-height: calc(100dvh - var(--topbar-h) - var(--rc-bar-h) - 32px);
  overflow-y: auto; padding: 14px 12px 12px; background: var(--rc-raised); border: 1px solid var(--rc-line-strong); border-top: var(--sec-w, 1px) solid var(--sec, var(--rc-line-strong));
}
.doc-cat-title { margin: 0 0 12px; }

/* search: one bordered control (input + clear + submit); the container carries hover/focus */
.doc-search {
  display: flex; align-items: stretch; height: 36px; margin: 0 0 6px; border: 1px solid var(--rc-control); background: var(--rc-field);
  transition: border-color var(--rc-dur-fast) var(--rc-ease), box-shadow var(--rc-dur-fast) var(--rc-ease);
}
.doc-search:hover { border-color: var(--rc-text-faint); }
.doc-search:focus-within { border-color: var(--rc-accent-ui); box-shadow: 0 0 0 1px var(--rc-accent-ui); }
.doc-search input[type="search"] { flex: 1 1 auto; width: auto; min-width: 0; height: auto; padding: 0 10px; border: 0; background: none; box-shadow: none; appearance: none; -webkit-appearance: none; }
.doc-search input[type="search"]:focus-visible { outline: none; }
.doc-search input[type="search"]::-webkit-search-cancel-button, .doc-search input[type="search"]::-webkit-search-decoration { display: none; -webkit-appearance: none; }
.doc-search-clear, .doc-search-go {
  flex: none; display: inline-grid; place-items: center; width: 34px; padding: 0; border: 0; background: none; color: var(--rc-text-mute); cursor: pointer; text-decoration: none;
  transition: color var(--rc-dur-fast) var(--rc-ease), background-color var(--rc-dur-fast) var(--rc-ease);
}
.doc-search-go { border-left: 1px solid var(--rc-line-strong); }
.doc-search-clear:hover, .doc-search-go:hover { color: var(--rc-text); background: var(--rc-hover); text-decoration: none; }
.doc-search-clear:focus-visible, .doc-search-go:focus-visible { outline-offset: -2px; }

/* expand / collapse / flatten: quiet text controls (JS un-hides them) */
.doc-cat-tools { display: flex; flex-wrap: wrap; gap: 0 2px; margin: 0 0 4px -6px; }
.doc-cat-tools .btn.sm { min-height: 28px; padding: 0 6px; font-size: 12px; }
.doc-note { margin: 6px 2px 4px; }
.doc-note a { color: var(--rc-accent); }

/* sources: a department square + name + mono count, then the tree hangs off it */
.doc-cat-src { margin-top: 8px; }
.doc-cat-src + .doc-cat-src { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--rc-line); }
.doc-cat-head { display: flex; align-items: center; gap: 8px; min-height: 34px; padding: 0 4px 0 8px; font: 600 14px/1.25 var(--rc-font-sans); color: var(--rc-text); }
.doc-cat-name { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.doc-n { flex: none; justify-self: auto; }

/* tree: hairline rail per list, 8px elbows, 5x5 ports (the port of the open document fills with the accent).
   Rows are li > a (documents) and li > details > summary (folders); the pseudo-elements sit outside the row,
   so rows must not clip (ellipsis lives on .doc-name). */
.doctree { list-style: none; margin: 0; padding: 0 0 0 22px; }
.doctree > li { position: relative; margin: 0; }
.doctree > li::before { content: ""; position: absolute; left: -11px; top: 0; bottom: 0; width: 1px; background: var(--rc-line-bright); }
.doctree > li:last-child::before { bottom: auto; height: calc(var(--doc-row) / 2); }
.doctree:has(+ .doctree) > li:last-child::before { bottom: 0; height: auto; }
.doctree summary, .docfile a {
  position: relative; display: flex; align-items: center; gap: 6px; min-height: var(--doc-row); padding: 0 4px 0 0;
  color: var(--rc-text-soft); font: 400 13px/1.2 var(--rc-font-sans); text-decoration: none; cursor: pointer; list-style: none;
  transition: background-color var(--rc-dur-fast) var(--rc-ease), color var(--rc-dur-fast) var(--rc-ease);
}
.docfile a { padding-left: 8px; }
.doctree summary::-webkit-details-marker { display: none; }
.doctree summary::marker { content: ""; }
.doctree summary::before, .docfile a::before { content: ""; position: absolute; left: -11px; top: 50%; width: 8px; height: 1px; background: var(--rc-line-bright); }
.doctree summary::after, .docfile a::after { content: ""; position: absolute; left: -5px; top: calc(50% - 2px); width: 5px; height: 5px; background: var(--rc-raised); box-shadow: inset 0 0 0 1px var(--rc-line-bright); }
.doctree summary:hover, .docfile a:hover { background: var(--rc-hover); color: var(--rc-text); text-decoration: none; }
.doctree summary:focus-visible, .docfile a:focus-visible { outline-offset: -2px; }
.doctree summary { color: var(--rc-text); font-weight: 500; }
.doctree summary .doc-caret { width: 14px; height: 14px; margin: 0 5px; color: var(--rc-text-faint); transition: transform var(--rc-dur-base) var(--rc-ease-out), color var(--rc-dur-fast) var(--rc-ease); }
.doctree details[open] > summary .doc-caret { transform: rotate(90deg); }
.doctree summary:hover .doc-caret { color: var(--rc-text); }
.docfile { display: flex; align-items: center; }
.docfile a { flex: 1 1 auto; min-width: 0; }
.docfile a svg { color: var(--rc-text-mute); }
.doc-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* hidden from clients (operator only): quieter text plus the dashed eye-off control below */
.docfile.is-hidden a, .folder.is-hidden > details > summary { color: var(--rc-text-faint); }
.docfile.is-hidden a svg { color: var(--rc-text-faint); }
.docfile a.active { background: var(--rc-accent-wash); color: var(--rc-accent); font-weight: 500; }
.docfile a.active svg { color: var(--rc-accent); }
.docfile a.active::after { background: var(--rc-accent-ui); box-shadow: none; }

/* search hit count + in-document hit marks */
.hitcount { flex: none; display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 5px; border: 1px solid var(--rc-line-strong); background: none; color: var(--rc-text-soft); font: 500 12px/1 var(--rc-font-mono); font-variant-numeric: tabular-nums; margin-left: 0; border-radius: 0; }
mark.hit { background: var(--rc-highlight); color: inherit; padding: 0 1px; border-radius: 0; }

/* operator visibility toggle: a quiet icon button; hidden state = dashed outline + eye-off */
.vis-toggle { flex: none; margin: 0; }
.vis-toggle button { display: inline-grid; place-items: center; width: var(--vis-w, 28px); height: var(--vis-w, 28px); padding: 0; border: 1px solid transparent; border-radius: 0; background: none; color: var(--rc-text-mute); cursor: pointer; transition: color var(--rc-dur-fast) var(--rc-ease), background-color var(--rc-dur-fast) var(--rc-ease), border-color var(--rc-dur-fast) var(--rc-ease); }
.vis-toggle button:hover { color: var(--rc-text); border-color: var(--rc-line-strong); background: var(--rc-hover); }
.vis-toggle button:focus-visible { outline-offset: -2px; }
.docfile.is-hidden > .vis-toggle button, .folder.is-hidden > details > summary > .vis-toggle button { border: 1px dashed var(--rc-line-bright); color: var(--rc-text-soft); }
/* Operator catalog: every eye button ends at the row edge, and every count ends one button-width (+4px) in from it. A folder's toggle
   sits inside its summary (4px padding, 6px gap), a file's outside its link, so the folder one is pulled flush; sources have no toggle,
   so their head reserves the same gutter. */
.doctree summary > .vis-toggle { margin: 0 -4px 0 -2px; }
.doc-catalog.is-operator .doc-cat-head { padding-right: calc(var(--vis-w) + 4px); }
.doc-legend { display: flex; flex-wrap: wrap; gap: 4px 14px; margin: 14px 0 0; padding-top: 10px; border-top: 1px solid var(--rc-line); }
.doc-legend__k { display: inline-flex; align-items: center; gap: 6px; }

/* hide folders: flatten to documents only, no rail */
.folders-hidden .doctree summary { display: none; }
.folders-hidden .doctree, .folders-hidden .doc-cat-src > .doctree { padding-left: 0; }
.folders-hidden .doctree > li::before, .folders-hidden .docfile a::before, .folders-hidden .docfile a::after { display: none; }
.folders-hidden details:not([open]) > ul { display: block; }
.folders-hidden details::details-content { content-visibility: visible; }

/* ── reading sheet: a panel with a mono path bar, then the document ── */
.doc-pane { min-width: 0; }
.doc-sheet { margin: 0; }
.doc-sheet--page { max-width: 960px; }
.doc-readbar { min-width: 0; padding-block: 8px; }
/* a long document keeps its path bar in view under the chrome + layer bar */
@media (min-width: 768px) { .doc-sheet > .doc-readbar { position: sticky; top: calc(var(--topbar-h) + var(--rc-bar-h)); z-index: 5; } }
.doc-readbar > .rc-dept { flex: none; }
.doc-crumb { min-width: 0; flex: 1 1 auto; font: 500 13px/1.35 var(--rc-font-mono); color: var(--rc-text-mute); overflow-wrap: anywhere; }
.doc-readtitle { color: var(--rc-text); overflow-wrap: anywhere; }
.doc-flags { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; margin-left: auto; }
.doc-sheet__body { padding: 24px 28px 32px; }
.doc-sheet__body--frame { padding: 0; }
/* HTML documents: a white page on the dark display mat (the plate), sandboxed (no scripts, no links) */
.doc-plate { border-bottom: 0; }
.doc-frame { display: block; width: 100%; height: max(560px, 78vh); border: 0; background: #fff; }

/* ── repositories (Project files) ── */
.doc-sheet .rc-notice > p, .repo-error > p { margin: 0; }
.repo-tiles { margin-bottom: 20px; }
.repo-tile.tile { padding: 0; gap: 0; }
.repo-tile__bar { display: flex; align-items: center; gap: 8px; height: 32px; min-width: 0; padding: 0 8px 0 10px; background: var(--sec-band, var(--rc-band)); border-bottom: 1px solid var(--sec-rule, var(--rc-line)); }
.repo-tile__bar .repo-branch { margin-left: auto; text-transform: none; min-width: 0; overflow: hidden; }
.repo-tile__body { flex: 1 1 auto; display: grid; align-content: start; gap: 4px; padding: 12px 14px 14px; min-width: 0; }
.repo-tile__body h2 { margin: 0; font: 600 16px/1.3 var(--rc-font-display); letter-spacing: -.005em; overflow-wrap: anywhere; }
.repo-tile__body .tile-sub { overflow-wrap: anywhere; }
.repo-tile__body .repo-path { font: 500 12px/1.4 var(--rc-font-mono); }
.repo-tile__foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; height: 36px; padding: 0 12px 0 14px; border-top: 1px solid var(--rc-line); color: var(--rc-text-soft); font: 500 12px/1 var(--rc-font-mono); letter-spacing: .06em; text-transform: uppercase; }
.repo-tile__foot svg { color: var(--rc-text-faint); transition: color var(--rc-dur-fast) var(--rc-ease), transform var(--rc-dur-base) var(--rc-ease-out); }
@media (hover: hover) { a.repo-tile:hover .repo-tile__foot svg { color: var(--rc-accent); transform: translateX(2px); } }

.repo-panel { margin: 0; }
.repo-bar { min-width: 0; padding-block: 8px; }
.repo-bar > .rc-dept { flex: none; align-self: center; }
.repo-bar .breadcrumb { flex: 1 1 0; min-width: 0; overflow-wrap: anywhere; }
.repo-bar .repo-branch { margin-left: auto; text-transform: none; }
.repo-body { padding: 0; }
.repo-body > .content { padding: 24px 28px 32px; }
.repo-panel .filelist li:last-child { border-bottom: 0; }
.repo-panel .filelist li a { min-height: 40px; padding: 8px 16px; color: var(--rc-text); }
.repo-panel .filelist li a:hover { color: var(--rc-text); }
.repo-panel .filelist .fi { display: inline-grid; place-items: center; width: 18px; color: var(--rc-text-mute); }
.repo-name { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.repo-size { flex: none; color: var(--rc-text-mute); font: 500 12px/1 var(--rc-font-mono); font-variant-numeric: tabular-nums; }
.repo-go { flex: none; color: var(--rc-text-faint); }
.repo-panel .filelist li a:hover .repo-go { color: var(--rc-accent); }
.repo-none { margin: 0; padding: 20px 16px; color: var(--rc-text-soft); }
.repo-state { padding: 24px 16px; }

/* code view: Pygments paints its own light/dark token colours (its dark rule is [data-theme=dark] .highlight, injected after this
   file, hence the extra class); the box background follows the theme tokens instead of Pygments' own */
.repo-panel .repo-code .highlight { margin: 0; padding: 16px 18px; border: 0; background: var(--rc-field); color: var(--rc-text); overflow-x: auto; font: 500 13px/1.6 var(--rc-font-mono); }
.repo-panel .repo-code .highlight pre { margin: 0; line-height: 1.6; }
/* notebook (.ipynb) rendering: same theme-following code cells, hairline separated */
.notebook .nb-md { padding: 4px 2px; }
.notebook .nb-md:first-child > :first-child { margin-top: 0; }
/* code reads literally: no -> or == ligatures in JetBrains Mono. The font shorthands above and in style.css reset this property,
   so the selectors out-rank them (the shared .content pre / code is a style.css request). */
.repo-panel .repo-body :is(.highlight, pre, code), .doc-sheet .content :is(pre, code) { font-variant-ligatures: none; }
.notebook .nb-code { margin: 10px 0; }
.notebook .nb-code .highlight { padding: 12px 14px; border: 1px solid var(--rc-line-strong); background: var(--rc-field); color: var(--rc-text); }

/* Touch/press feedback (split out of the shared affordances block in style.css). */
.docfile a:active, .doctree summary:active { background: var(--rc-hover); }

/* ── docs on small screens: index ↔ reader ─────────────────────────────────── */
/* Under the stacked breakpoint the desktop split view becomes two screens:
   the catalog IS the page until a document is opened; an open document takes
   the whole screen with a back link. The sticky catalog previously pinned
   itself over the scrolling document — unstick it in stacked mode always. */
.doc-back { display: none; min-height: 44px; margin: 0 0 8px -10px; }
@media (max-width: 1100px) {
  .sidebar-layout[data-doc-layout] { flex-direction: column; align-items: stretch; }
  .sidebar-layout[data-doc-layout] .doc-catalog, .sidebar-layout[data-doc-layout] .doc-pane { flex: 1 1 auto; }
  .sidebar-layout[data-doc-layout] .doc-catalog { position: static; max-height: none; width: 100%; }
  .doc-splitter, .doc-pane-resizer { display: none; }
  .sidebar-layout[data-doc-layout].has-doc .doc-catalog { display: none; }
  .sidebar-layout[data-doc-layout].has-doc .doc-back { display: inline-flex; }
  .sidebar-layout[data-doc-layout]:not(.has-doc) .doc-section { display: none; }
}
@media (max-width: 767px) {
  .doc-sheet__body { padding: 16px 16px 24px; }
  .doc-sheet__body--frame { padding: 0; }
  .repo-body > .content { padding: 16px 16px 24px; }
  .doc-crumb__dir, .doc-readbar .rc-stamp { font-size: 12px; }
  /* the crumb takes what the stamp leaves; two stamps (operator "Hidden from clients" + type) drop to their own row instead of squeezing it */
  .doc-readbar { flex-wrap: wrap; }
  .doc-crumb { flex: 1 1 0; }
  .doc-flags:has(> :nth-child(2)) { flex: 1 1 100%; justify-content: flex-start; margin-left: 0; }
  .repo-bar .repo-branch { display: none; }
  /* a wrapped path keeps its dept square on the FIRST line (centred on the whole block it floated into the row gap).
     The crumb carries the vertical padding that keeps a single line centred in the 44px bar; the square's font-size
     matches the crumb's so 1.4em is exactly one 13px/1.4 line. Stamps keep their own centring.
     Only bars that actually hold the square: the standalone raw-HTML page (doc_view.html) has none, and its 24px chip
     would grow a single-line bar past 44px. */
  .doc-readbar:has(> .rc-dept), .repo-bar:has(> .rc-dept) { align-items: flex-start; --bar-pad: 4px; }
  .doc-readbar:has(> .rc-dept) > .doc-crumb, .doc-readbar:has(> .rc-dept) > .breadcrumb, .repo-bar:has(> .rc-dept) > .breadcrumb { padding-block: var(--bar-pad); }
  .doc-readbar > .rc-dept, .repo-bar > .rc-dept { align-self: auto; font-size: 13px; margin-top: calc(var(--bar-pad) + (1.4em - 8px) / 2); }
  .doc-flags { align-self: center; }
  .doc-frame { height: 70vh; min-height: 420px; }
}

/* Touch floor for this surface: 44px rows, 44px controls. */
@media (max-width: 767px), (pointer: coarse) {
  .sidebar-layout[data-doc-layout] { --doc-row: 44px; --vis-w: 44px; }
  .doc-search { height: 46px; }
  /* a crumb's hit area is its line plus half the row gap each side, so wrapped lines never overlap (44px would need a 26px gap) */
  .breadcrumb { row-gap: 26px; }
  .breadcrumb a { position: relative; }
  .breadcrumb a::after { content: ""; position: absolute; inset: -13px -4px; }
  .doc-search input[type="search"] { font-size: 16px; }
  .doc-search-clear, .doc-search-go { width: 44px; }
  .doc-cat-tools .btn.sm { min-height: 44px; }
  .repo-panel .filelist li a { min-height: 48px; }
  .doc-note a { display: inline-block; padding: 12px 0; }
}
