/*
 * design.css — shared styling for the Tally "Design" site.
 *
 * The site is a set of standalone, text-first HTML pages under design/. Each
 * page is fully readable as raw HTML and, with JavaScript disabled, renders as a
 * single readable column (no topbar, no sidebar — just the content). design.js
 * adds `body.enhanced`, which upgrades the layout to a topbar + sidebar TOC
 * shell. Nothing here injects content; the markup in each page stays the single
 * source of truth.
 *
 * Status colour-coding is driven by [data-status] attributes authored in the
 * page markup: implemented (green), planned (blue), proposal (amber),
 * reference (neutral). Dark by default; light via prefers-color-scheme.
 */

:root {
  --bg: #0f1419;
  --panel: #171c23;
  --panel-2: #1d242d;
  --text: #e6e9ee;
  --muted: #8a93a0;
  --border: #232a33;
  --border-2: #2c3540;
  --link: #46b3ff;
  --code-bg: #11161c;

  --st-implemented: #2FA84F;
  --st-planned: #46b3ff;
  --st-proposal: #D9A521;
  --st-reference: #8a93a0;

  --sidebar-w: 272px;
  --graph-w: 380px;
  --splitter-w: 6px;
  --measure: 74ch;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 15px/1.65 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

/* ---- Base (JS-off): single readable column ---------------------------- */
/* Cap the measure at the container width so narrow viewports never overflow —
   74ch is ~700px, wider than a phone, and margin:auto would otherwise let the
   column grow to that and clip. */
main.page {
  display: block;
  max-width: min(var(--measure), 100%);
  margin: 0 auto;
  padding: 28px 22px 80px;
}

/* ---- Enhanced (JS-on): topbar + sidebar shell ------------------------- */
/* The shell fills the viewport and the topbar + sidebar stay fixed; only the
   content column scrolls. `height` (not min-height) + the per-region overflow
   below are what pin the nav in place as you scroll long pages. */
body.enhanced {
  display: grid;
  grid-template-columns: var(--sidebar-w) var(--splitter-w) minmax(0, 1fr);
  grid-template-rows: auto 1fr;
  grid-template-areas:
    "topbar topbar   topbar"
    "toc    splitter content";
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}
/* min-width:0 lets the content column shrink below the intrinsic width of a
   wide child (e.g. a long code line) instead of overflowing the viewport; the
   wide child then scrolls within itself (see pre/table rules below). */
body.enhanced > main.page {
  grid-area: content;
  overflow-y: auto;
  min-width: 0;
  max-width: none;
  margin: 0;
  padding-inline: max(22px, calc((100% - var(--measure)) / 2));
}

/* Future graph-editor layouts can add a right column without changing the page
   content's scroll ownership: the main column remains the scroll container. */
body.enhanced.graph-open {
  grid-template-columns:
    var(--sidebar-w) var(--splitter-w) minmax(0, 1fr)
    var(--splitter-w) minmax(260px, var(--graph-w));
  grid-template-areas:
    "topbar topbar   topbar  topbar         topbar"
    "toc    splitter content graph-splitter graph";
}

/* Graph column — the embedded GraphEditor (see design.js). It is injected into
   the DOM only on pages that carry graph metadata, and shown only while
   `graph-open`; when closed it's display:none so it never claims an implicit
   grid track. */
body.enhanced:not(.graph-open) #graph-panel,
body.enhanced:not(.graph-open) .layout-splitter[data-splitter="graph"] {
  display: none;
}
#graph-panel {
  grid-area: graph;
  min-width: 0;
  background: var(--bg);
  overflow: hidden;
}
#graph-frame { width: 100%; height: 100%; border: 0; display: block; }

/* Graph icon injected next to a documented header; opens the graph column
   filtered to that header's files. */
.graph-open-btn {
  margin-left: 0.5em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5em;
  height: 1.5em;
  padding: 0;
  vertical-align: middle;
  color: var(--muted);
  background: transparent;
  border: 1px solid var(--border-2);
  border-radius: 6px;
  cursor: pointer;
  transition: color 0.12s ease, background 0.12s ease, border-color 0.12s ease;
}
.graph-open-btn:hover { color: var(--link); border-color: var(--link); }
.graph-open-btn.active {
  color: var(--link);
  border-color: var(--link);
  background: color-mix(in srgb, var(--link) 15%, transparent);
}
.graph-open-btn svg { width: 1em; height: 1em; display: block; }
h1 .graph-open-btn { width: 1.15em; height: 1.15em; }
dt .graph-open-btn { width: 1.35em; height: 1.35em; margin-left: 0.4em; }

#topbar {
  grid-area: topbar;
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 12px 20px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
}
#topbar .brand { font-weight: 700; letter-spacing: 0.02em; }
#topbar .brand a { color: var(--text); text-decoration: none; }
#topbar .tagline { color: var(--muted); font-size: 13px; }
#topbar .nav-toggle {
  margin-left: auto;
  display: none;
  background: none;
  border: 1px solid var(--border-2);
  color: var(--text);
  border-radius: 8px;
  padding: 4px 10px;
  cursor: pointer;
}

#toc {
  grid-area: toc;
  background: var(--panel);
  padding: 16px 12px;
  overflow: auto;
}

.layout-splitter {
  position: relative;
  z-index: 10;
  width: var(--splitter-w);
  min-width: var(--splitter-w);
  background: var(--panel);
  border-inline: 1px solid var(--border);
  cursor: col-resize;
  touch-action: none;
}
.layout-splitter::before {
  content: "";
  position: absolute;
  inset: 0 -4px;
}
.layout-splitter:hover,
.layout-splitter:focus-visible,
body.is-resizing-layout .layout-splitter {
  background: var(--panel-2);
  border-color: var(--border-2);
}
.layout-splitter:focus-visible { outline: 2px solid var(--link); outline-offset: -2px; }
.layout-splitter[data-splitter="sidebar"] { grid-area: splitter; }
.layout-splitter[data-splitter="graph"] { grid-area: graph-splitter; }
/* Group headers are buttons that fold/unfold their <ul>. Only the group
   containing the current page (or one the user opened) shows its links. */
/* Group headers are the primary structure of the nav, so they read stronger
   than the individual page names nested under them: brighter, bolder, a touch
   larger. */
#toc .toc-group {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  color: var(--text);
  font-size: 12.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin: 18px 0 4px;
  padding: 4px 8px;
  background: none;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-family: inherit;
}
#toc .toc-group:hover { color: var(--link); }
#toc .toc-group:first-of-type { margin-top: 4px; }
#toc .toc-group.has-active .toc-group-label { color: var(--link); }
#toc .toc-group-label { min-width: 0; }
#toc .toc-group-caret {
  width: 8px;
  height: 8px;
  flex: 0 0 auto;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
  transition: transform 0.15s ease;
}
#toc .toc-group[aria-expanded="true"] .toc-group-caret { transform: rotate(45deg); }
#toc ul { list-style: none; margin: 0; padding: 0; }
/* One line per link, truncated with an ellipsis rather than wrapping — the
   status dot (and the group caret, on group headers) must stay put regardless
   of how long the title is. min-width:0 lets the flex child actually shrink
   below its text's natural width so overflow:hidden can kick in. */
/* Page names are secondary to their group header: quieter by default, coming
   forward on hover or when active. */
#toc a {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: 8px;
  color: var(--muted);
  text-decoration: none;
  font-size: 13px;
  min-width: 0;
}
#toc a:hover { color: var(--text); background: var(--panel-2); }
#toc a.active { color: var(--text); background: var(--panel-2); font-weight: 600; }
#toc a .dot {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--st, var(--muted));
}
/* Reference is the default maturity for most pages, so its dot is noise rather
   than signal — hide it (keeping the slot so labels stay aligned) and let only
   the meaningful statuses (implemented / planned / proposal) show a colour. */
#toc a[data-status="reference"] .dot { background: transparent; }
/* The truncation target is the label span, not the flex row itself — a flex
   container's own text-overflow doesn't apply to a bare text node sitting next
   to another flex item (the dot). min-width:0 lets it shrink past its text's
   natural width so overflow:hidden + ellipsis can take effect. */
#toc a .label,
#toc .toc-group-label,
#toc .outline-link {
  display: block;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* A group whose single page is named after it: the header is a direct link
   (no caret). Reuses .toc-group sizing/case; text-decoration off. */
#toc a.toc-group-link { text-decoration: none; }
#toc a.toc-group-link:hover,
#toc a.toc-group-link.active { color: var(--text); background: var(--panel-2); }

/* Overview: the one ungrouped top-level link. */
#toc a.toc-top { margin-bottom: 2px; }

/* Current page's heading outline (h2/h3/h4), rendered under its nav entry.
   Depth comes from the heading level; deeper headings indent further. */
#toc .page-outline { list-style: none; margin: 2px 0 8px; padding: 0; }
#toc .outline-link {
  display: block;
  padding: 3px 8px 3px 26px;
  font-size: 13px;
  line-height: 1.35;
  color: var(--muted);
  text-decoration: none;
  border-radius: 6px;
}
#toc .outline-link:hover { background: var(--panel-2); color: var(--text); }
#toc .outline-link.active {
  background: color-mix(in srgb, var(--link) 18%, transparent);
  color: var(--text);
  font-weight: 600;
}
#toc .outline-link[data-depth="1"] { padding-left: 40px; }
#toc .outline-link[data-depth="2"] { padding-left: 54px; }

/* ---- Sidebar search --------------------------------------------------- */
#toc-search {
  position: sticky;
  top: -16px; /* cancel #toc's top padding so it pins flush */
  z-index: 2;
  margin: -4px 2px 12px;
  padding: 4px 2px 8px;
  background: var(--panel);
}
#toc-search-input {
  width: 100%;
  box-sizing: border-box;
  padding: 7px 30px 7px 10px;
  font: inherit;
  font-size: 13px;
  color: var(--text);
  background: var(--panel-2);
  border: 1px solid var(--border-2);
  border-radius: 8px;
  outline: none;
}
#toc-search-input:focus { border-color: var(--link); }
#toc-search-input::placeholder { color: var(--muted); }
#toc-search-icon {
  position: absolute;
  right: 6px;
  top: 8px;
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  color: var(--muted);
  background: none;
  border: 0;
  cursor: pointer;
}
#toc-search-icon:hover { color: var(--text); }
#toc-search-icon svg { width: 15px; height: 15px; display: block; }
#toc-search .icon-clear { display: none; }
#toc-search.has-text .icon-search { display: none; }
#toc-search.has-text .icon-clear { display: block; }

#toc-results .search-summary {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  padding: 2px 8px 8px;
}
a.search-result {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 8px;
  border-radius: 8px;
  color: var(--muted);
  text-decoration: none;
  font-size: 13px;
}
a.search-result:hover { color: var(--text); background: var(--panel-2); }
a.search-result.active { color: var(--text); background: var(--panel-2); font-weight: 600; }
.search-result-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.search-result-count {
  flex: 0 0 auto;
  font-size: 11px;
  color: var(--muted);
  background: var(--panel);
  border: 1px solid var(--border-2);
  border-radius: 999px;
  padding: 0 7px;
}

/* Matches highlighted in an opened document (search hit). */
mark.search-hit {
  background: color-mix(in srgb, var(--st-proposal) 42%, transparent);
  color: inherit;
  border-radius: 2px;
  padding: 0 1px;
}
mark.search-hit.search-hit-first {
  background: color-mix(in srgb, var(--st-proposal) 70%, transparent);
  outline: 1px solid var(--st-proposal);
}

/* Status token mapping — usable on any element via [data-status]. */
[data-status="implemented"] { --st: var(--st-implemented); }
[data-status="planned"]     { --st: var(--st-planned); }
[data-status="proposal"]    { --st: var(--st-proposal); }
[data-status="reference"]   { --st: var(--st-reference); }

/* ---- Status legend chips (used on the index page) --------------------- */
.legend { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 4px; padding: 0; list-style: none; }
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--muted);
  border: 1px solid var(--border-2);
  border-radius: 999px;
  padding: 3px 10px;
}
.chip::before {
  content: "";
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--st, var(--muted));
}

/* ---- Inline editing --------------------------------------------------- */
/* The textarea that replaces a block while it's being edited (see design.js).
   Sized to roughly match the surrounding text so editing feels in-place. */
.doc-edit {
  display: block;
  width: 100%;
  box-sizing: border-box;
  margin: 6px 0;
  padding: 8px 10px;
  font: inherit;
  line-height: 1.55;
  color: var(--text);
  background: var(--panel-2);
  border: 1px solid var(--link);
  border-radius: 8px;
  outline: none;
  resize: vertical;
  overflow: hidden;
  white-space: pre-wrap;
}
/* Only where editing is on (see the authoring flag in design.js). */
body.authoring main.page :where(p, li, h1, h2, h3, h4, h5, h6, blockquote):hover {
  cursor: text;
}

/* ---- Page content typography ------------------------------------------ */
main.page > h1 {
  display: flex;
  align-items: baseline;
  gap: 12px;
  font-size: 27px;
  margin: 4px 0 18px;
}
/* A page's own maturity: <main class="page" data-status> renders a badge.
   The label text is set per status rather than via attr(): the ::after sits on
   the <h1>, which carries no data-status, so attr(data-status) would be empty. */
main.page[data-status] > h1::after {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--st);
  border: 1px solid var(--st);
  border-radius: 999px;
  padding: 2px 9px;
  align-self: center;
}
main.page[data-status="implemented"] > h1::after { content: "implemented"; }
main.page[data-status="planned"]     > h1::after { content: "planned"; }
main.page[data-status="proposal"]    > h1::after { content: "proposal"; }
main.page[data-status="reference"]   > h1::after { content: "reference"; }
main.page h2 { font-size: 19px; margin: 30px 0 10px; }
main.page h3 { font-size: 15px; margin: 22px 0 8px; }
/* Clear the sticky topbar when an outline link jumps to a heading. */
main.page h2, main.page h3, main.page h4 { scroll-margin-top: 16px; }
main.page p, main.page li { color: var(--text); }
main.page .lede { font-size: 17px; color: var(--muted); }
main.page a { color: var(--link); }
main.page code {
  background: var(--code-bg);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 1px 5px;
  font-size: 0.9em;
}
main.page hr { border: none; border-top: 1px solid var(--border); margin: 28px 0; }
main.page { overflow-wrap: break-word; }
main.page pre {
  background: var(--code-bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  overflow-x: auto;
}
main.page pre code { background: none; border: none; padding: 0; }
main.page blockquote {
  margin: 12px 0;
  padding: 2px 14px;
  border-left: 3px solid var(--border-2);
  color: var(--muted);
}
/* Wide tables scroll inside a .table-scroll wrapper (added by the importer)
   instead of forcing page overflow. */
main.page .table-scroll { overflow-x: auto; margin: 12px 0; }
main.page table { border-collapse: collapse; width: 100%; margin: 12px 0; font-size: 14px; }
main.page .table-scroll > table { margin: 0; }
main.page th, main.page td { border: 1px solid var(--border); padding: 7px 10px; text-align: left; vertical-align: top; }
main.page th { background: var(--panel); }

/* Definition lists (the glossary). Each term is an anchor target with a
   self-link; scroll-margin keeps it clear of the top when jumped to. */
main.page dl { margin: 8px 0; }
main.page dt { font-weight: 700; margin-top: 24px; scroll-margin-top: 16px; }
main.page dd { margin: 4px 0 0; color: var(--text); }
main.page .term-self { color: inherit; }
/*main.page .term-self { text-decoration: underline; text-decoration-style: dotted; }*/
/*main.page dt:target { color: var(--link); }*/

a {
  text-decoration: underline;
  text-decoration-style: dotted;
  color: inherit;
}

/* Inline status tag for a single term/row, e.g. <span class="tag" data-status>. */
.tag {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--st, var(--muted));
  border: 1px solid var(--st, var(--border-2));
  border-radius: 999px;
  padding: 1px 8px;
}

/* Banner on pages imported verbatim from Markdown, pending reconciliation. */
.import-note {
  border: 1px solid var(--st-proposal);
  color: var(--muted);
  background: color-mix(in srgb, var(--st-proposal) 10%, transparent);
  border-radius: 8px;
  padding: 8px 12px;
  margin: 0 0 18px;
  font-size: 13px;
}

/* ---- Responsive ------------------------------------------------------- */
@media (max-width: 820px) {
  body.enhanced {
    grid-template-columns: 1fr;
    grid-template-areas: "topbar" "content";
  }
  body.enhanced #topbar .nav-toggle { display: inline-block; }
  body.enhanced #toc {
    position: fixed;
    top: 49px; bottom: 0; left: 0;
    width: min(80vw, var(--sidebar-w));
    transform: translateX(-100%);
    transition: transform 0.18s ease;
    z-index: 30;
  }
  body.enhanced .layout-splitter { display: none; }
  body.enhanced.nav-open #toc { transform: none; }
  /* On narrow screens the graph column overlays the content instead of sitting
     beside it (there isn't room for three columns). */
  body.enhanced.graph-open #graph-panel {
    position: fixed;
    inset: 49px 0 0 0;
    z-index: 40;
  }
}

@media (prefers-color-scheme: light) {
  :root {
    --bg: #f7f8fa;
    --panel: #ffffff;
    --panel-2: #eef1f5;
    --text: #1c2530;
    --muted: #5b6673;
    --border: #e2e6ec;
    --border-2: #d3d9e0;
    --link: #1a73e8;
    --code-bg: #f0f2f5;
  }
}
