/* ==========================================================================
   TreeListView documentation site
   ==========================================================================
   Deliberately the same design language as binarymission.co.uk and
   treelistview.com: the same ten theme palettes under the same
   `html[data-theme]` selectors, the same type stack, the same
   `bm-theme` localStorage key. A reader moving between the three sites
   should not feel they have left.

   This file is checked in under `scripts/docs-site-assets/` and copied into
   `docs-site/assets/` by `npm run build:docs`. Edit it here.
   ========================================================================== */

/* ---------- Theme palettes ---------- */

:root,
html[data-theme="dark"] {
  --bg: #0a0d14; --bg-alt: #0d1119; --surface: #12161f; --surface-2: #171c27;
  --border: rgba(255,255,255,.08); --border-strong: rgba(255,255,255,.14);
  --text: #eef1f7; --text-dim: #aab2c5; --text-faint: #6b7386;
  --accent: #7c6cf6; --accent-2: #4f9dff; --accent-3: #22d3c9;
  --btn-ink: #060810; --shadow: 0 20px 60px -20px rgba(0,0,0,.6);
}
html[data-theme="light"] {
  --bg: #f6f7fb; --bg-alt: #eef0f6; --surface: #fff; --surface-2: #f4f5fa;
  --border: rgba(15,23,42,.09); --border-strong: rgba(15,23,42,.16);
  --text: #12141c; --text-dim: #4b5468; --text-faint: #7c869c;
  --accent: #6d5ef0; --accent-2: #2f7fe0; --accent-3: #0fb8ac;
  --btn-ink: #fff; --shadow: 0 20px 50px -22px rgba(30,41,59,.25);
}
html[data-theme="ocean"] {
  --bg: #061820; --bg-alt: #08212b; --surface: #0d2733; --surface-2: #123240;
  --border: rgba(255,255,255,.07); --border-strong: rgba(255,255,255,.13);
  --text: #e6f6f7; --text-dim: #9fc4c9; --text-faint: #5f8a90;
  --accent: #17b8c4; --accent-2: #2f9bff; --accent-3: #5fe0c0;
  --btn-ink: #04141a; --shadow: 0 20px 60px -20px rgba(0,0,0,.65);
}
html[data-theme="sunset"] {
  --bg: #1a0f14; --bg-alt: #20131a; --surface: #26161f; --surface-2: #2e1a26;
  --border: rgba(255,255,255,.08); --border-strong: rgba(255,255,255,.14);
  --text: #fbeef0; --text-dim: #d3aab0; --text-faint: #8f6870;
  --accent: #f6607c; --accent-2: #ff9a4f; --accent-3: #c86cf6;
  --btn-ink: #1a0508; --shadow: 0 20px 60px -20px rgba(0,0,0,.6);
}
html[data-theme="aurora"] {
  --bg: #08131c; --bg-alt: #0a1826; --surface: #0f1f30; --surface-2: #142839;
  --border: rgba(255,255,255,.08); --border-strong: rgba(255,255,255,.14);
  --text: #eaf6f2; --text-dim: #a9c9c0; --text-faint: #688f88;
  --accent: #33e0a1; --accent-2: #4f9dff; --accent-3: #9b6cf6;
  --btn-ink: #04140f; --shadow: 0 20px 60px -20px rgba(0,0,0,.62);
}
html[data-theme="royal"] {
  --bg: #0f0a1c; --bg-alt: #140f24; --surface: #1a1330; --surface-2: #20193a;
  --border: rgba(255,255,255,.08); --border-strong: rgba(255,255,255,.15);
  --text: #f1edfb; --text-dim: #c1b3e0; --text-faint: #7c6ba0;
  --accent: #a06cf6; --accent-2: #6c7bf6; --accent-3: #e0b256;
  --btn-ink: #0c0616; --shadow: 0 20px 60px -20px rgba(0,0,0,.65);
}
html[data-theme="mint"] {
  --bg: #f2faf6; --bg-alt: #e9f6ef; --surface: #fff; --surface-2: #eefaf3;
  --border: rgba(6,78,59,.10); --border-strong: rgba(6,78,59,.18);
  --text: #0b1f18; --text-dim: #3f6357; --text-faint: #75948a;
  --accent: #12b886; --accent-2: #0b7f96; --accent-3: #7cc957;
  --btn-ink: #fff; --shadow: 0 20px 50px -22px rgba(6,78,59,.20);
}
html[data-theme="forest"] {
  --bg: #0a140e; --bg-alt: #0d1a12; --surface: #122016; --surface-2: #17281c;
  --border: rgba(255,255,255,.08); --border-strong: rgba(255,255,255,.14);
  --text: #eaf6ee; --text-dim: #a9c9b2; --text-faint: #688f73;
  --accent: #4fce6b; --accent-2: #2fb39c; --accent-3: #a9e05a;
  --btn-ink: #06120a; --shadow: 0 20px 60px -20px rgba(0,0,0,.6);
}
html[data-theme="slate"] {
  --bg: #121317; --bg-alt: #16171c; --surface: #1c1e24; --surface-2: #23252c;
  --border: rgba(255,255,255,.07); --border-strong: rgba(255,255,255,.13);
  --text: #eceef2; --text-dim: #a7acb8; --text-faint: #6b7078;
  --accent: #7c8cf6; --accent-2: #5fb0d9; --accent-3: #c8ccd6;
  --btn-ink: #0a0b0e; --shadow: 0 20px 60px -20px rgba(0,0,0,.55);
}
html[data-theme="amber"] {
  --bg: #160f06; --bg-alt: #1c1308; --surface: #241a0c; --surface-2: #2c2010;
  --border: rgba(255,255,255,.08); --border-strong: rgba(255,255,255,.14);
  --text: #fbf1e3; --text-dim: #d9bd94; --text-faint: #8f7955;
  --accent: #f6a93c; --accent-2: #f66c4f; --accent-3: #e0c250;
  --btn-ink: #160a02; --shadow: 0 20px 60px -20px rgba(0,0,0,.6);
}

:root {
  --font-sans: Inter, "Segoe UI", Roboto, system-ui, sans-serif;
  --font-display: Sora, Inter, system-ui, sans-serif;
  --font-mono: "JetBrains Mono", "SF Mono", Menlo, Consolas, monospace;
  --radius: 12px;
  --sidebar-w: 250px;
  --toc-w: 200px;
  --header-h: 60px;
}

/* ---------- Base ---------- */

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

html { scroll-behavior: smooth; scroll-padding-top: calc(var(--header-h) + 1.5rem); -webkit-text-size-adjust: 100%; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.7;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent-2); text-decoration: none; }
a:hover { text-decoration: underline; }
img { max-width: 100%; height: auto; }
code, pre, kbd { font-family: var(--font-mono); font-size: .875em; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 6px; }

.skip-link {
  position: fixed; top: .6rem; left: .6rem; z-index: 200;
  padding: .6rem .95rem; border-radius: 99px;
  background: var(--accent); color: var(--btn-ink); font-weight: 700;
  transform: translateY(-160%); transition: transform .18s ease;
}
.skip-link:focus { transform: translateY(0); text-decoration: none; }

/* ---------- Header ---------- */

.site-header {
  position: sticky; top: 0; z-index: 100;
  height: var(--header-h);
  display: flex; align-items: center;
  padding: 0 1.25rem;
  gap: 1rem;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  border-bottom: 1px solid var(--border);
}
/* No backdrop-filter: it creates a containing block for fixed descendants,
   which is what puts an open mobile menu behind the page instead of over it. */

.brand { display: flex; align-items: center; gap: .6rem; color: var(--text); font-weight: 700; font-family: var(--font-display); }
.brand:hover { text-decoration: none; }
.brand-mark {
  display: grid; place-items: center; width: 30px; height: 30px; border-radius: 8px;
  background: linear-gradient(135deg, var(--accent-2), var(--accent));
  color: var(--btn-ink); font-size: 15px;
}
.brand small { display: block; font-size: 11px; font-weight: 500; color: var(--text-faint); letter-spacing: .02em; }

.header-spacer { flex: 1; }

.header-nav { display: flex; gap: .25rem; align-items: center; }
.header-nav a {
  padding: .4rem .7rem; border-radius: 8px; color: var(--text-dim); font-size: 14px; font-weight: 500;
}
.header-nav a:hover { background: var(--surface); color: var(--text); text-decoration: none; }

.theme-pick { display: flex; align-items: center; gap: .45rem; }
.theme-swatch {
  width: 15px; height: 15px; border-radius: 50%; flex: none;
  border: 1px solid var(--border-strong);
  background: linear-gradient(120deg, var(--accent-2), var(--accent), var(--accent-3));
}
.theme-picker {
  appearance: none; -webkit-appearance: none;
  padding: .35rem 1.6rem .35rem .6rem; border-radius: 8px;
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text);
  font: inherit; font-size: 13px; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 12px center, right 7px center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

.nav-toggle {
  display: none; width: 38px; height: 38px; border-radius: 9px;
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text);
  cursor: pointer; font-size: 17px; line-height: 1;
}

/* ---------- Layout ---------- */

.layout {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr) var(--toc-w);
  gap: 2.5rem;
  max-width: 1500px;
  margin: 0 auto;
  padding: 2rem 1.5rem 5rem;
  align-items: start;
}

.sidebar, .toc {
  position: sticky;
  top: calc(var(--header-h) + 1.5rem);
  max-height: calc(100vh - var(--header-h) - 3rem);
  overflow-y: auto;
  font-size: 14px;
}

.sidebar h4, .toc h4 {
  margin: 1.4rem 0 .4rem;
  font-size: 11px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: var(--text-faint);
}
.sidebar h4:first-child, .toc h4:first-child { margin-top: 0; }
.sidebar a, .toc a {
  display: block; padding: .3rem .6rem; border-radius: 7px;
  color: var(--text-dim); line-height: 1.4;
}
.sidebar a:hover, .toc a:hover { background: var(--surface); color: var(--text); text-decoration: none; }
.sidebar a.current { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--text); font-weight: 600; }
.toc a { font-size: 13px; border-left: 2px solid var(--border); border-radius: 0; padding-left: .7rem; }
.toc a.lvl-3 { padding-left: 1.4rem; font-size: 12.5px; }

/* ---------- Content ---------- */

.content { min-width: 0; }
.content > :first-child { margin-top: 0; }

.content h1 {
  margin: 0 0 .5rem; font-family: var(--font-display);
  font-size: 2.1rem; font-weight: 780; line-height: 1.1; letter-spacing: -.03em;
}
.content h2 {
  margin: 2.6rem 0 .8rem; padding-top: .6rem;
  font-family: var(--font-display); font-size: 1.45rem; font-weight: 720; letter-spacing: -.02em;
  border-top: 1px solid var(--border);
}
.content h3 { margin: 1.8rem 0 .5rem; font-size: 1.12rem; font-weight: 680; }
.content h4 { margin: 1.4rem 0 .4rem; font-size: 1rem; font-weight: 650; }
.content p { margin: 0 0 1rem; }
.content ul, .content ol { margin: 0 0 1rem; padding-left: 1.3rem; }
.content li { margin-bottom: .35rem; }
.content hr { border: 0; border-top: 1px solid var(--border); margin: 2.5rem 0; }

.content blockquote {
  margin: 1.2rem 0; padding: .85rem 1.1rem;
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--surface); color: var(--text-dim);
}
.content blockquote > :last-child { margin-bottom: 0; }

.content :not(pre) > code {
  padding: .15em .4em; border-radius: 5px;
  background: var(--surface-2); border: 1px solid var(--border);
  /* Was `white-space: nowrap`, which kept short identifiers intact but made a
     long one unbreakable: `wrappers/angular/src/bm-tree-list-view.component.ts`
     in a paragraph on integration.html is 415px wide and pushed the page
     sideways at every width up to 414px. `overflow-wrap: anywhere` only breaks
     a token that does not fit, so short code still reads as one piece. The
     `.content td code` override below was this same problem solved for tables
     alone, before anyone checked the prose. */
  color: var(--accent-3); overflow-wrap: anywhere;
}

.content pre {
  margin: 0 0 1.2rem; padding: 1rem 1.1rem;
  border-radius: var(--radius); border: 1px solid var(--border);
  background: var(--bg-alt);
  overflow-x: auto; line-height: 1.6;
}
.content pre code { color: var(--text); background: none; border: 0; padding: 0; white-space: pre; }

/* Wide content scrolls inside its own box - the page itself must never
   scroll sideways. */
.table-wrap { overflow-x: auto; margin: 0 0 1.3rem; border: 1px solid var(--border); border-radius: var(--radius); }
.content table { border-collapse: collapse; width: 100%; font-size: 14px; }
.content th, .content td { padding: .6rem .85rem; text-align: left; border-bottom: 1px solid var(--border); vertical-align: top; }
.content th { background: var(--surface); font-weight: 650; white-space: nowrap; }
.content tr:last-child td { border-bottom: 0; }
.content td code { white-space: normal; }

/* ---------- Home page pieces ---------- */

.hero { padding: 1rem 0 2rem; }
.hero p.lede { font-size: 1.12rem; color: var(--text-dim); max-width: 62ch; }
.pill {
  display: inline-block; padding: .25rem .7rem; margin-bottom: .9rem;
  border-radius: 99px; border: 1px solid var(--border-strong);
  background: var(--surface); color: var(--text-dim);
  font-size: 12px; font-weight: 600; letter-spacing: .03em;
}
.btn {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .6rem 1.1rem; border-radius: 10px; font-weight: 650; font-size: 14px;
}
.btn:hover { text-decoration: none; }
.btn-primary { background: var(--accent); color: var(--btn-ink); }
.btn-ghost { border: 1px solid var(--border-strong); color: var(--text); }
.btn-row { display: flex; flex-wrap: wrap; gap: .7rem; margin: 1.4rem 0 0; }

.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 1rem; margin: 1.5rem 0; }
.card {
  padding: 1.1rem 1.2rem; border-radius: var(--radius);
  border: 1px solid var(--border); background: var(--surface);
}
.card:hover { border-color: var(--border-strong); text-decoration: none; }
.card h3 { margin: .1rem 0 .35rem; font-size: 1rem; }
.card p { margin: 0; font-size: 14px; color: var(--text-dim); }
.card-icon { font-size: 20px; line-height: 1; }

/* ---------- API reference ---------- */

.api-filter {
  /* A flex item will not shrink below its content, so the search box and the
     "252 members" count together held this row at 359px on a 320px screen.
     Letting it wrap, and letting the input shrink, costs nothing at any width. */
  position: sticky; top: calc(var(--header-h) + .5rem); z-index: 20;
  display: flex; flex-wrap: wrap; gap: .6rem; align-items: center;
  margin: 0 0 1.5rem; padding: .7rem 0;
  background: var(--bg);
}
.api-filter input {
  flex: 1 1 12rem; min-width: 0; padding: .6rem .9rem; border-radius: 10px;
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text);
  font: inherit; font-size: 14px;
}
.api-filter .count { font-size: 13px; color: var(--text-faint); white-space: nowrap; }

.member {
  margin: 0 0 1rem; padding: 1rem 1.2rem;
  border-radius: var(--radius); border: 1px solid var(--border); background: var(--surface);
}
.member.is-hidden { display: none; }
tr.is-hidden { display: none; }
.member-head { display: flex; flex-wrap: wrap; gap: .5rem; align-items: baseline; margin-bottom: .5rem; }
/* An API member name is one unbreakable token, and some of them are long
   enough to push a 320px page sideways on their own. Note `.member-type` on the
   next line already had `word-break` for exactly this reason -- the same
   problem, solved for the type and not the name. */
.member-name { font-family: var(--font-mono); font-size: 15px; font-weight: 700; color: var(--text); overflow-wrap: anywhere; }
.member-type { font-family: var(--font-mono); font-size: 12.5px; color: var(--accent-3); word-break: break-word; }
.member-meta { display: flex; flex-wrap: wrap; gap: .4rem; margin-left: auto; }
.tag {
  padding: .1rem .5rem; border-radius: 99px; font-size: 11px; font-weight: 650;
  border: 1px solid var(--border-strong); color: var(--text-faint);
  /* Tags carry property default values, and those are not always short:
     `default 'Drag a column header here to group by it'` renders at 331px.
     `nowrap` made it unbreakable. */
  overflow-wrap: anywhere;
}
.tag-since { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.member-docs { color: var(--text-dim); font-size: 14px; }
.member-docs > :last-child { margin-bottom: 0; }
.member-docs p { margin: 0 0 .6rem; }

.empty-note { padding: 2rem; text-align: center; color: var(--text-faint); }

/* ---------- Footer ---------- */

.site-footer {
  border-top: 1px solid var(--border);
  background: var(--bg-alt);
  padding: 2rem 1.5rem;
  color: var(--text-dim); font-size: 13.5px;
}
.footer-inner { max-width: 1500px; margin: 0 auto; display: flex; flex-wrap: wrap; gap: 1rem 2rem; align-items: center; }
.footer-inner nav { display: flex; flex-wrap: wrap; gap: 1rem; margin-left: auto; }

/* ---------- Responsive ---------- */

@media (max-width: 1200px) {
  .layout { grid-template-columns: var(--sidebar-w) minmax(0, 1fr); }
  .toc { display: none; }
}

@media (max-width: 900px) {
  .layout { grid-template-columns: minmax(0, 1fr); gap: 1.5rem; padding-top: 1.25rem; }
  .header-nav { display: none; }
  .nav-toggle { display: block; }

  /* The subtitle wraps to a second line at this width, which pushes the brand
     past the header's fixed height. The version is on every page's footer and
     in the API page's opening line, so nothing is lost by dropping it here. */
  .brand small { display: none; }
  .brand { font-size: 15px; }

  /* The sidebar becomes a panel over the page. Fixed, not sticky, and with
     its own scroll - a nav that scrolls the page behind it is worse than no
     nav at all. */
  .sidebar {
    position: fixed; inset: var(--header-h) auto 0 0; z-index: 90;
    width: min(300px, 82vw); max-height: none;
    padding: 1.25rem;
    background: var(--bg-alt); border-right: 1px solid var(--border);
    box-shadow: var(--shadow);
    transform: translateX(-102%); transition: transform .2s ease;
  }
  body.nav-open .sidebar { transform: translateX(0); }
  body.nav-open::after {
    content: ""; position: fixed; inset: var(--header-h) 0 0 0; z-index: 80;
    background: rgba(0, 0, 0, .45);
  }
}

/* The header is a flex row and its items will not shrink below their content,
   so at 320px it measured 340px wide and pushed every documentation page
   sideways by 20. Losing 16px of padding and the decorative theme swatch is
   enough, and neither is load-bearing at that width. */
@media (max-width: 400px) {
  .site-header { padding: 0 .75rem; gap: .5rem; }
  .theme-swatch { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .sidebar { transition: none; }
}

@media print {
  .site-header, .sidebar, .toc, .site-footer, .api-filter, .skip-link { display: none !important; }
  .layout { display: block; padding: 0; }
  .member { break-inside: avoid; border-color: #999; }
  a { color: inherit; text-decoration: none; }
}
