/* Thinkneering — global.css (v2)
   Tokens marked [NEW] are additions proposed on top of the agreed set.
   Nothing outside this file may hardcode a colour, font or spacing value. */

:root {
  /* Colour */
  --color-bg: #f7f8fa;
  --color-surface: #ffffff;
  --color-primary: #2f5fff;
  --color-primary-dark: #1e3fcc;
  --color-accent: #00c2a8;
  --color-text: #14161a;
  --color-text-muted: #5c6270;
  --color-border: #e3e5ea;
  --color-success: #1fa971;
  --color-warning: #e0a100;
  --color-danger: #e0432f;

  /* [NEW] tint + depth values needed by the two-layer access UI */
  --color-surface-sunken: #eef0f5;
  --color-primary-tint: rgba(47, 95, 255, 0.08);
  --color-accent-tint: rgba(0, 194, 168, 0.12);
  --color-warning-tint: rgba(224, 161, 0, 0.12);
  --color-danger-tint: rgba(224, 67, 47, 0.10);
  --color-overlay: rgba(20, 22, 26, 0.45);

  /* Typography */
  --font-heading: 'Sora', sans-serif;
  --font-body: 'Inter', sans-serif;
  --font-mono: 'JetBrains Mono', monospace;

  /* Spacing */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 16px;
  --space-4: 24px;
  --space-5: 32px;
  --space-6: 48px;
  --space-7: 72px;   /* [NEW] section rhythm on marketing pages */

  /* Radius & shadow */
  --radius-sm: 6px;
  --radius-md: 12px;
  --radius-lg: 20px;                                  /* [NEW] hero + reader */
  --shadow-card: 0 2px 8px rgba(20, 22, 26, 0.06);
  --shadow-lifted: 0 10px 28px rgba(20, 22, 26, 0.10); /* [NEW] hover + modal */

  --maxw: 1100px;
  --maxw-wide: 1360px; /* [NEW] the two workbench screens (map, knowledge admin) */
  --maxw-read: 720px; /* [NEW] reader measure */

  /* [NEW] The page side gutter. Three page containers had grown their own
     copy of this value and two of them had drifted to --space-3 on mobile,
     so the knowledge and process-map screens sat 8px tighter than every
     other page. One token, referenced by every container, means they cannot
     drift apart again. The value is --space-4 per the design system. */
  --gutter: var(--space-4);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) { color-scheme: dark; }
}
:root[data-theme='dark'], html[data-theme='dark'] {
  color-scheme: dark;
  --color-bg: #0f1115;
  --color-surface: #171a20;
  --color-surface-sunken: #1f232b;
  --color-text: #eef0f4;
  --color-text-muted: #98a0b0;
  --color-border: #2a2f39;
  --color-primary: #7d9bff;
  --color-primary-dark: #5c7fff;
  --color-primary-tint: rgba(125, 155, 255, 0.14);
  --shadow-card: 0 2px 8px rgba(0, 0, 0, 0.4);
  --shadow-lifted: 0 10px 28px rgba(0, 0, 0, 0.5);
  --color-overlay: rgba(0, 0, 0, 0.6);
}

/* ------------------------------------------------------------ base */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4 { font-family: var(--font-heading); font-weight: 600; line-height: 1.25; margin: 0; }
h1 { font-size: 2rem; letter-spacing: -0.02em; }
h2 { font-size: 1.375rem; letter-spacing: -0.01em; }
h3 { font-size: 1.0625rem; }
p { margin: 0; }
a { color: var(--color-primary); text-decoration: none; }
a:hover { text-decoration: underline; }
img { max-width: 100%; display: block; }
:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; left: var(--space-3); top: -60px; z-index: 100;
  background: var(--color-surface); padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-card);
}
.skip-link:focus { top: var(--space-3); }

.wrap { width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 var(--gutter); }
.stack > * + * { margin-top: var(--space-3); }
.muted { color: var(--color-text-muted); }
.eyebrow {
  font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--color-text-muted);
}

/* ---------------------------------------------------------- header */
.site-header {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--color-surface) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--color-border);
}
.site-header__inner {
  display: flex; align-items: center; gap: var(--space-4);
  height: 60px; max-width: var(--maxw); margin: 0 auto; padding: 0 var(--gutter);
}
.brand {
  display: inline-flex; align-items: center; gap: var(--space-2);
  font-family: var(--font-heading); font-weight: 600; color: var(--color-text);
  letter-spacing: -0.02em; text-decoration: none; flex: none;
}
.brand:hover { text-decoration: none; }
.brand__mark {
  width: 26px; height: 26px; border-radius: var(--radius-sm);
  background: var(--color-primary); color: #fff;
  display: grid; place-items: center; font-size: 0.8125rem;
}
.site-nav { display: flex; gap: var(--space-1); flex: 1; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.site-nav::-webkit-scrollbar { display: none; }
.site-nav a {
  padding: var(--space-1) var(--space-2); border-radius: var(--radius-sm);
  color: var(--color-text-muted); font-size: 0.9375rem; white-space: nowrap;
}
.site-nav a:hover { background: var(--color-surface-sunken); color: var(--color-text); text-decoration: none; }
.site-nav a[aria-current='page'] { color: var(--color-text); background: var(--color-primary-tint); }
.header-actions { display: flex; align-items: center; gap: var(--space-2); flex: none; }

/* ---------------------------------------------------------- footer */
.site-footer {
  margin-top: var(--space-7); border-top: 1px solid var(--color-border);
  background: var(--color-surface); padding: var(--space-5) 0;
}
.site-footer__inner {
  max-width: var(--maxw); margin: 0 auto; padding: 0 var(--gutter);
  display: flex; flex-wrap: wrap; gap: var(--space-4); justify-content: space-between;
  color: var(--color-text-muted); font-size: 0.875rem;
}
.site-footer nav { display: flex; gap: var(--space-3); flex-wrap: wrap; }

/* --------------------------------------------------------- buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  font-family: var(--font-body); font-size: 0.9375rem; font-weight: 500;
  padding: var(--space-2) var(--space-3); min-height: 40px;
  border-radius: var(--radius-md); border: 1px solid transparent;
  background: var(--color-surface-sunken); color: var(--color-text);
  cursor: pointer; text-decoration: none; transition: background .15s, border-color .15s, transform .1s;
}
.btn:hover { text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn[disabled], .btn[aria-disabled='true'] { opacity: .55; cursor: not-allowed; }
.btn--primary { background: var(--color-primary); color: #fff; }
.btn--primary:hover { background: var(--color-primary-dark); }
.btn--ghost { background: transparent; border-color: var(--color-border); }
.btn--ghost:hover { background: var(--color-surface-sunken); }
.btn--quiet { background: transparent; color: var(--color-text-muted); }
.btn--quiet:hover { background: var(--color-surface-sunken); color: var(--color-text); }
.btn--danger { background: var(--color-danger-tint); color: var(--color-danger); }
.btn--sm { min-height: 32px; padding: var(--space-1) var(--space-2); font-size: 0.875rem; }
.btn--block { width: 100%; }
.btn svg { width: 18px; height: 18px; }

/* ----------------------------------------------------------- forms */
.field { display: block; }
.field + .field { margin-top: var(--space-3); }
.field > label, .label {
  display: block; font-size: 0.875rem; font-weight: 500;
  margin-bottom: var(--space-1); color: var(--color-text);
}
.hint { font-size: 0.8125rem; color: var(--color-text-muted); margin-top: var(--space-1); }
input[type='text'], input[type='email'], input[type='password'], input[type='number'],
input[type='url'], input[type='search'], select, textarea {
  width: 100%; font-family: var(--font-body); font-size: 0.9375rem;
  color: var(--color-text); background: var(--color-surface);
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-3); min-height: 40px;
}
textarea { min-height: 120px; resize: vertical; line-height: 1.6; }
input:focus, select:focus, textarea:focus { border-color: var(--color-primary); outline-offset: 0; }
/* Fields laid out side by side. `.field + .field` adds a top margin for the
   normal stacked case; inside a row that same rule pushed every field after
   the first down by one space unit, so Product and Factory sat on different
   baselines. Cancel it here and align on the top edge, so labels of unequal
   length (one wraps, one does not) still leave the inputs level. */
.field-row { display: flex; gap: var(--space-3); flex-wrap: wrap; align-items: flex-start; }
.field-row > * { flex: 1 1 180px; }
.field-row > .field + .field { margin-top: 0; }

.segmented { display: inline-flex; background: var(--color-surface-sunken); border-radius: var(--radius-md); padding: var(--space-1); gap: var(--space-1); }
.segmented button {
  border: 0; background: transparent; color: var(--color-text-muted);
  font-family: var(--font-body); font-size: 0.875rem; font-weight: 500;
  padding: var(--space-1) var(--space-3); min-height: 32px;
  border-radius: var(--radius-sm); cursor: pointer;
}
.segmented button[aria-pressed='true'] { background: var(--color-surface); color: var(--color-text); box-shadow: var(--shadow-card); }

/* ----------------------------------------------------------- cards */
.panel {
  background: var(--color-surface); border: 1px solid var(--color-border);
  border-radius: var(--radius-md); box-shadow: var(--shadow-card); padding: var(--space-4);
}
.panel__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-3); }

.grid { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }

.card {
  position: relative; display: flex; flex-direction: column; gap: var(--space-2);
  background: var(--color-surface); border: 1px solid var(--color-border);
  border-radius: var(--radius-md); box-shadow: var(--shadow-card);
  padding: var(--space-4); color: var(--color-text); text-decoration: none;
  transition: box-shadow .18s, border-color .18s, transform .18s;
}
a.card:hover { text-decoration: none; box-shadow: var(--shadow-lifted); border-color: var(--color-primary); transform: translateY(-2px); }
.card__icon {
  width: 36px; height: 36px; border-radius: var(--radius-sm);
  background: var(--color-primary-tint); color: var(--color-primary);
  display: grid; place-items: center;
}
.card__icon svg { width: 20px; height: 20px; }
.card__title { font-family: var(--font-heading); font-weight: 600; font-size: 1rem; }
.card__desc { color: var(--color-text-muted); font-size: 0.875rem; }
.card__foot { margin-top: auto; padding-top: var(--space-2); display: flex; align-items: center; gap: var(--space-2); }
.card--locked { background: var(--color-surface-sunken); }
.card--locked .card__icon { background: var(--color-warning-tint); color: var(--color-warning); }

/* The access chip is the spine of the two-layer model: every card says
   plainly which layer it belongs to. */
.chip {
  display: inline-flex; align-items: center; gap: var(--space-1);
  font-family: var(--font-mono); font-size: 0.625rem; letter-spacing: 0.08em;
  text-transform: uppercase; padding: 2px var(--space-2);
  border-radius: 999px; border: 1px solid var(--color-border); color: var(--color-text-muted);
  white-space: nowrap;
}
.chip svg { width: 12px; height: 12px; }
.chip--free { color: var(--color-success); border-color: color-mix(in srgb, var(--color-success) 40%, transparent); }
.chip--auth { color: var(--color-warning); border-color: color-mix(in srgb, var(--color-warning) 40%, transparent); }
.chip--restricted { color: var(--color-primary); border-color: color-mix(in srgb, var(--color-primary) 40%, transparent); }
.chip--danger { color: var(--color-danger); border-color: color-mix(in srgb, var(--color-danger) 40%, transparent); }
.chip--solid { background: var(--color-primary); color: #fff; border-color: transparent; }

/* ------------------------------------------------------ page parts */
.page-head { padding: var(--space-6) 0 var(--space-4); }
.page-head h1 { margin-bottom: var(--space-2); }
.page-head p { color: var(--color-text-muted); max-width: 60ch; }
/* One-line restatement of what the page does, sitting between the h1 and the
   longer description. Heavier than body copy, lighter than a heading. */
.page-head__lede {
  font-family: var(--font-heading); font-size: 1.0625rem; font-weight: 500;
  color: var(--color-text); margin-bottom: var(--space-2);
}
main { padding-bottom: var(--space-6); }
.section-block { margin-top: var(--space-6); }
.section-block__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-3); }

/* The hero sits on `.wrap hero`, so it inherits the side gutter from `.wrap`.
   Setting `padding` as a shorthand here would reset left and right to zero —
   same specificity, later in the file — and the whole first screen would run
   edge to edge on a phone. Vertical padding is set on its own axis so the
   gutter survives. The same applies to any future class paired with `.wrap`. */
.hero { padding-top: var(--space-7); padding-bottom: var(--space-5); }
.hero h1 { font-size: clamp(1.75rem, 6vw, 2.75rem); max-width: 18ch; margin-bottom: var(--space-3); }
.hero p { font-size: 1.0625rem; color: var(--color-text-muted); max-width: 56ch; }
.hero__actions { display: flex; gap: var(--space-2); flex-wrap: wrap; margin-top: var(--space-4); }
.layer-strip {
  display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  margin-top: var(--space-5);
}
.layer {
  border: 1px solid var(--color-border); border-radius: var(--radius-lg);
  padding: var(--space-4); background: var(--color-surface);
}
.layer--member { border-color: var(--color-primary); background: var(--color-primary-tint); }
.layer h3 { margin-bottom: var(--space-2); }
.layer ul { margin: var(--space-2) 0 0; padding-left: var(--space-3); color: var(--color-text-muted); font-size: 0.9375rem; }

.notice {
  border: 1px solid var(--color-border); border-left: 3px solid var(--color-primary);
  background: var(--color-surface); border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4); display: flex; gap: var(--space-3); align-items: flex-start;
}
.notice--warning { border-left-color: var(--color-warning); }
.notice--danger { border-left-color: var(--color-danger); }
.notice--success { border-left-color: var(--color-success); }

.empty {
  text-align: center; padding: var(--space-6) var(--space-4);
  border: 1px dashed var(--color-border); border-radius: var(--radius-md); color: var(--color-text-muted);
}

/* ---------------------------------------------------------- tables */
.table-wrap { overflow-x: auto; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); }
table.data { width: 100%; border-collapse: collapse; font-size: 0.9375rem; }
table.data th, table.data td { padding: var(--space-2) var(--space-3); text-align: left; border-bottom: 1px solid var(--color-border); vertical-align: middle; }
table.data th { font-family: var(--font-heading); font-weight: 600; font-size: 0.8125rem; color: var(--color-text-muted); background: var(--color-surface-sunken); position: sticky; top: 0; }
table.data tr:last-child td { border-bottom: 0; }
table.data td.num, table.data th.num { font-family: var(--font-mono); font-size: 0.875rem; }

/* ---------------------------------------------------------- toasts */
#toast-region { position: fixed; right: var(--space-3); bottom: var(--space-3); z-index: 90; display: flex; flex-direction: column; gap: var(--space-2); }
.toast {
  background: var(--color-surface); border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-primary); border-radius: var(--radius-md);
  box-shadow: var(--shadow-lifted); padding: var(--space-3) var(--space-4); font-size: 0.9375rem; max-width: 320px;
}
.toast--error { border-left-color: var(--color-danger); }
.toast--success { border-left-color: var(--color-success); }

/* ---------------------------------------------------------- modals */
dialog.modal {
  border: 1px solid var(--color-border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lifted); background: var(--color-surface); color: var(--color-text);
  padding: var(--space-4); width: min(560px, calc(100vw - var(--space-4) * 2)); max-height: 85vh;
}
dialog.modal::backdrop { background: var(--color-overlay); }
dialog.modal h2 { margin-bottom: var(--space-3); }
.modal__actions { display: flex; gap: var(--space-2); justify-content: flex-end; margin-top: var(--space-4); }

/* ----------------------------------------------------------- admin */
.admin-shell { display: grid; grid-template-columns: 220px 1fr; gap: var(--space-4); align-items: start; padding-top: var(--space-4); }
.admin-nav { position: sticky; top: 76px; display: flex; flex-direction: column; gap: var(--space-1); }
.admin-nav button {
  display: flex; align-items: center; gap: var(--space-2); width: 100%; text-align: left;
  border: 0; background: transparent; color: var(--color-text-muted);
  font-family: var(--font-body); font-size: 0.9375rem; padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md); cursor: pointer; min-height: 40px;
}
.admin-nav button:hover { background: var(--color-surface-sunken); color: var(--color-text); }
.admin-nav button[aria-current='true'] { background: var(--color-primary-tint); color: var(--color-primary); font-weight: 500; }
.admin-nav svg { width: 18px; height: 18px; }
.stat-grid { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.stat { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--space-3) var(--space-4); box-shadow: var(--shadow-card); }
.stat__value { font-family: var(--font-heading); font-size: 1.75rem; font-weight: 600; line-height: 1.1; }
.stat__label { font-family: var(--font-mono); font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--color-text-muted); margin-top: var(--space-1); }
.toolbar { display: flex; gap: var(--space-2); flex-wrap: wrap; align-items: center; margin-bottom: var(--space-3); }
.toolbar input[type='search'], .toolbar select { max-width: 220px; }
.tree-row { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--color-border); }
.tree-row--child { padding-left: var(--space-6); background: var(--color-surface-sunken); }
.tree-row__main { flex: 1; min-width: 0; }
.tree-row__title { font-weight: 500; }
.row-actions { display: flex; gap: var(--space-1); flex: none; }

/* ---------------------------------------------------------- reader */
.reader { display: grid; grid-template-columns: 260px 1fr; gap: var(--space-5); align-items: start; padding-top: var(--space-4); }
.reader__toc { position: sticky; top: 76px; max-height: calc(100vh - 100px); overflow-y: auto; }
.reader__toc ol { list-style: none; margin: var(--space-2) 0 0; padding: 0; counter-reset: ch; }
.reader__toc li { counter-increment: ch; }
.reader__toc a {
  display: flex; gap: var(--space-2); padding: var(--space-2); border-radius: var(--radius-sm);
  color: var(--color-text-muted); font-size: 0.9375rem;
}
.reader__toc a::before { content: counter(ch, decimal-leading-zero); font-family: var(--font-mono); font-size: 0.75rem; padding-top: 3px; opacity: .7; }
.reader__toc a:hover { background: var(--color-surface-sunken); color: var(--color-text); text-decoration: none; }
.reader__toc a[aria-current='true'] { background: var(--color-primary-tint); color: var(--color-primary); }
.reader__body { max-width: var(--maxw-read); font-size: 1.0625rem; line-height: 1.75; }
.reader__body > * + * { margin-top: var(--space-4); }
.reader__body h2 { font-size: 1.5rem; margin-top: var(--space-6); }
.reader__body h3 { font-size: 1.1875rem; margin-top: var(--space-5); }
.reader__body p { color: var(--color-text); }
.reader__body figure { margin: 0; }
.reader__body figcaption { font-size: 0.875rem; color: var(--color-text-muted); margin-top: var(--space-2); }
.reader__body img { border-radius: var(--radius-md); border: 1px solid var(--color-border); }
.reader__body blockquote {
  margin: 0; padding-left: var(--space-4); border-left: 3px solid var(--color-accent);
  font-size: 1.125rem; color: var(--color-text-muted);
}
.reader__body pre {
  background: var(--color-surface-sunken); border-radius: var(--radius-md);
  padding: var(--space-3); overflow-x: auto; font-family: var(--font-mono); font-size: 0.875rem;
}
.reader__body hr { border: 0; border-top: 1px solid var(--color-border); margin: var(--space-6) 0; }
.reader__nav { display: flex; justify-content: space-between; gap: var(--space-3); margin-top: var(--space-6); padding-top: var(--space-4); border-top: 1px solid var(--color-border); }
.chart { width: 100%; }
.chart text { font-family: var(--font-mono); font-size: 10px; fill: var(--color-text-muted); }

.paywall {
  border: 1px solid var(--color-border); border-radius: var(--radius-lg);
  background: var(--color-surface); box-shadow: var(--shadow-card);
  padding: var(--space-5); text-align: center;
}
.paywall .chip { margin-bottom: var(--space-3); }

/* ----------------------------------------------------------- auth pages */
.auth-wrap { max-width: 420px; margin: var(--space-7) auto; padding: 0 var(--gutter); }
.auth-wrap .panel { padding: var(--space-5); }

/* ------------------------------------------------------- sign-in landing
   The only page a signed-out visitor can reach, so it is the whole first
   impression of the site rather than a utility form. It keeps the home
   page's hero treatment — same type scale, same accented headline — with
   the form as the second column instead of a call-to-action button.

   Deliberately no nav and no tool links: there is nothing a signed-out
   visitor may open, and offering doors that all lead back here is worse
   than offering none. */
.auth-landing {
  display: grid; gap: var(--space-6); align-items: center;
  grid-template-columns: 1.1fr minmax(340px, 420px);
  max-width: var(--maxw); margin: 0 auto;
  padding: var(--space-7) var(--gutter) var(--space-6);
  min-height: calc(100vh - 60px);
}
.auth-landing__copy h1 {
  font-size: clamp(1.75rem, 6vw, 2.75rem); max-width: 16ch;
  margin-bottom: var(--space-3);
}
.auth-landing__copy h1 em { font-style: normal; color: var(--color-primary); }
.auth-landing__copy p { font-size: 1.0625rem; color: var(--color-text-muted); max-width: 48ch; }
.auth-landing .panel { padding: var(--space-5); }

/* A bare brand row rather than the site header: the header renders nav from
   /api/catalog, which a signed-out visitor cannot call. */
.auth-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3);
  max-width: var(--maxw); margin: 0 auto;
  padding: var(--space-4) var(--gutter) 0;
}

/* Below this the two columns cannot both keep their minimum width, so the
   form stacks under the copy rather than being squeezed. */
@media (max-width: 900px) {
  .auth-landing {
    grid-template-columns: 1fr; gap: var(--space-5);
    padding-top: var(--space-5); min-height: 0; align-items: start;
  }
  .auth-landing__copy h1 { max-width: none; }
}


/* ------------------------------------------------- reader controls (v3) */
.read-progress {
  position: sticky; top: 60px; z-index: 30; height: 3px;
  background: var(--color-border);
}
.read-progress span { display: block; height: 100%; width: 0; background: var(--color-primary); transition: width .1s linear; }

.reader__bar {
  display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap;
  padding: var(--space-2) 0 var(--space-3); margin-bottom: var(--space-3);
  border-bottom: 1px solid var(--color-border);
}
.reader__bar-group { display: inline-flex; align-items: center; gap: var(--space-1); }
.reader--wide .reader__body { max-width: 900px; }
.reader--no-toc { grid-template-columns: 1fr; }
.reader--no-toc .reader__toc { display: none; }

/* Full screen: drop every piece of site chrome and centre the column. */
body.is-reading .site-header,
body.is-reading .site-footer,
body.is-reading .tab-bar,
body.is-reading .reader__toc { display: none; }

/* The tab bar is fixed and body padding reserves its height. Hiding the bar
   without releasing the padding leaves a strip of dead space at the bottom of
   a full-screen page — which is most of what "full screen" was meant to
   remove. The !important earns its place: .has-tab-bar is set on the same
   element, so specificity alone cannot settle it. */
body.is-reading.has-tab-bar { padding-bottom: 0 !important; }
body.is-reading .read-progress { top: 0; }
body.is-reading .reader { grid-template-columns: 1fr; padding-top: var(--space-4); }
body.is-reading .reader__body { margin: 0 auto; }
body.is-reading main { padding-bottom: var(--space-7); }

/* ------------------------------------------------ markdown editor (v3) */
.md-input {
  width: 100%; min-height: 60vh; resize: vertical;
  font-family: var(--font-mono); font-size: 0.875rem; line-height: 1.7;
  tab-size: 2;
}
.reader__body code {
  font-family: var(--font-mono); font-size: 0.875em;
  background: var(--color-surface-sunken); padding: 1px var(--space-1); border-radius: var(--radius-sm);
}
.reader__body pre code { background: none; padding: 0; }


/* ---------------------------------------------------- home page (v4) */
.hero h1 em {
  font-style: normal; color: var(--color-primary);
}
.hero__lede { font-size: 1.125rem; color: var(--color-text-muted); max-width: 52ch; }
.layer h3 { margin-top: var(--space-2); }
.layer .chip { margin-bottom: var(--space-1); }

/* Flagship block: copy on the left, the three steps as a numbered rail. */
.feature {
  display: grid; gap: var(--space-5); grid-template-columns: 1.1fr 1fr;
  align-items: center; margin-top: var(--space-6);
  background: var(--color-surface); border: 1px solid var(--color-border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-card);
  padding: var(--space-5);
}
.feature h2 { font-size: 1.75rem; margin: var(--space-1) 0 var(--space-2); }
.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.steps li {
  display: grid; grid-template-columns: auto 1fr; gap: var(--space-1) var(--space-3);
  align-items: baseline; padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--color-border);
}
.steps li:last-child { border-bottom: 0; padding-bottom: 0; }
.steps__n {
  grid-row: span 2; font-family: var(--font-mono); font-size: 1.25rem;
  color: var(--color-primary); opacity: .7;
}
.steps__t { font-family: var(--font-heading); font-weight: 600; }
.steps__d { grid-column: 2; color: var(--color-text-muted); font-size: 0.9375rem; }

/* Editorial index — deliberately not the card grid used on section pages. */
.index-list { border-top: 1px solid var(--color-border); }
.index-row {
  display: grid; grid-template-columns: auto 1fr auto auto;
  gap: var(--space-3); align-items: center;
  padding: var(--space-4) var(--space-2);
  border-bottom: 1px solid var(--color-border);
  color: var(--color-text); text-decoration: none;
  transition: background .15s, padding-left .15s;
}
.index-row:hover, .index-row:focus-visible {
  text-decoration: none; background: var(--color-surface); padding-left: var(--space-4);
}
.index-row__n {
  font-family: var(--font-mono); font-size: 0.8125rem;
  color: var(--color-text-muted); opacity: .6;
}
.index-row__main { display: grid; gap: 2px; min-width: 0; }
.index-row__title { font-family: var(--font-heading); font-weight: 600; font-size: 1.25rem; letter-spacing: -0.01em; }
.index-row__desc { color: var(--color-text-muted); font-size: 0.9375rem; }
.index-row__go { color: var(--color-text-muted); opacity: 0; transform: translateX(-4px); transition: opacity .15s, transform .15s; }
.index-row:hover .index-row__go, .index-row:focus-visible .index-row__go { opacity: 1; transform: none; }
.index-row--locked .index-row__title { color: var(--color-text-muted); }

@media (max-width: 720px) {
  .feature { grid-template-columns: 1fr; padding: var(--space-4); }
  .index-row { grid-template-columns: auto 1fr; }
  .index-row__meta { grid-column: 2; }
  .index-row__go { display: none; }
}

/* ------------------------------------------------------- responsive */
@media (max-width: 860px) {
  .admin-shell, .reader { grid-template-columns: 1fr; }
  .admin-nav { position: static; flex-direction: row; overflow-x: auto; }
  .reader__toc { position: static; max-height: none; }
}
@media (max-width: 560px) {
  .site-header__inner { gap: var(--space-2); }
  .site-nav { order: 3; width: 100%; }
  h1 { font-size: 1.625rem; }
  .panel, .card { padding: var(--space-3); }
  /* 72px of dead space above the first line costs a third of a phone screen
     before a word is read. The desktop rhythm is kept; the phone one is not. */
  .hero { padding-top: var(--space-5); padding-bottom: var(--space-4); }
  .page-head { padding-top: var(--space-5); }
}
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ------------------------------------------- HVAC chart tokens (v7) */
/* Categorical series colours for engineering charts. Semantic tokens
   (--color-danger etc.) carry the wrong meaning on a chart series, so
   these are a separate scale. Dark variants mirror the site's existing
   explicit [data-theme='dark'] pattern. */
:root {
  --chart-1: #2f5fff;
  --chart-2: #00c2a8;
  --chart-3: #e0a100;
  --chart-4: #8b5cf6;
  --chart-5: #e0432f;
  --chart-6: #1fa971;
  --chart-7: #ec4899;
  --chart-8: #5c6270;
  --chart-grid: rgba(20, 22, 26, 0.10);
  --chart-sensible: #2f5fff;
  --chart-latent: #00c2a8;
}
:root[data-theme='dark'], html[data-theme='dark'] {
  --chart-1: #7d9bff;
  --chart-2: #3ddbc4;
  --chart-3: #f0be3d;
  --chart-4: #a78bfa;
  --chart-5: #f4705d;
  --chart-6: #4ec894;
  --chart-7: #f472b6;
  --chart-8: #98a0b0;
  --chart-grid: rgba(238, 240, 244, 0.10);
  --chart-sensible: #7d9bff;
  --chart-latent: #3ddbc4;
}


/* ------------------------------------------------------ library grouping
   A shelf of six books needs no grouping; a shelf of sixty is unusable
   without it. Built on <details> so the open/closed state is the browser's
   job and the keyboard works without any script. */
.shelf-bar {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--space-3); flex-wrap: wrap;
  margin: var(--space-5) 0 var(--space-3);
}
.field--inline { display: flex; align-items: center; gap: var(--space-2); }
.field--inline > label { margin: 0; white-space: nowrap; }
.field--inline > select { width: auto; min-width: 160px; }

.shelf-group { border-top: 1px solid var(--color-border); }
.shelf-group:last-of-type { border-bottom: 1px solid var(--color-border); }
.shelf-group__head {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) 0;
  cursor: pointer; list-style: none;
  font-family: var(--font-heading); font-weight: 500;
}
/* Safari draws its own triangle through ::-webkit-details-marker, which the
   standard list-style rule above does not reach. */
.shelf-group__head::-webkit-details-marker { display: none; }
.shelf-group__head::before {
  content: ''; flex: none; width: 8px; height: 8px;
  border-right: 2px solid var(--color-text-muted);
  border-bottom: 2px solid var(--color-text-muted);
  transform: rotate(-45deg); transition: transform .15s ease;
}
.shelf-group[open] > .shelf-group__head::before { transform: rotate(45deg); }
.shelf-group__head:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: 2px; border-radius: var(--radius-sm);
}
.shelf-group__name { flex: 1 1 auto; }
.shelf-group > .book-shelf { padding-bottom: var(--space-4); }

/* =====================================================================
   App shell — what makes this feel like an app rather than a page
   ===================================================================== */

/* Notch and home-indicator insets. viewport-fit=cover lets the page paint
   edge to edge; without these the content then sits under the notch. */
:root {
  --safe-top:    env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left:   env(safe-area-inset-left, 0px);
  --safe-right:  env(safe-area-inset-right, 0px);
  --tab-bar-h: 56px;
}

/* Overscroll on the body is what produces the rubber-band bounce that reveals
   the page background behind a fixed header — the clearest visual tell that
   something is a web page. */
html { overscroll-behavior-y: none; }

body {
  -webkit-tap-highlight-color: transparent;
  padding-left: var(--safe-left);
  padding-right: var(--safe-right);
}

/* Stops the grey flash on every tap without removing the focus ring, which
   keyboard users still need. */
a, button, summary, [role="button"] { -webkit-tap-highlight-color: transparent; }

/* iOS zooms the whole page when a focused input is under 16px, and never
   zooms back out. This is the fix, and it has to be a hard minimum. */
input, select, textarea { font-size: max(16px, 1rem); }

.site-header { padding-top: var(--safe-top); }

/* ------------------------------------------------------- tab bar */
.tab-bar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 40;
  display: none;
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
  padding-bottom: var(--safe-bottom);
}

.tab-bar a {
  flex: 1 1 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px;
  /* 56px, not 44: the Apple and Android minimums are the point at which a
     target stops being missed, not the point at which it feels good. */
  min-height: var(--tab-bar-h);
  padding: var(--space-2) 4px;
  color: var(--color-text-muted);
  text-decoration: none;
  font-size: 0.6875rem;
  line-height: 1.2;
}

.tab-bar a span {
  max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.tab-bar a[aria-current="page"] { color: var(--color-primary); }
.tab-bar a:active { background: var(--color-surface-sunken); }
.tab-bar a:focus-visible {
  outline: 2px solid var(--color-primary); outline-offset: -2px;
}

/* The bar covers the last ~56px of the page, so the footer and anything at
   the end of a long form would otherwise sit underneath it permanently. */
body.has-tab-bar { padding-bottom: calc(var(--tab-bar-h) + var(--safe-bottom)); }

@media (max-width: 640px) {
  .tab-bar { display: flex; }

  /* The header nav is now duplicated by the tab bar. Two navs on a 375px
     screen is one nav too many. */
  .site-nav { display: none; }

  .site-footer { padding-bottom: var(--space-5); }
}

/* ------------------------------------------------------- standalone */
/* Installed to the home screen: there is no URL bar, no back gesture to a
   previous site, and no browser chrome to borrow. */
html[data-standalone="true"] {
  /* Selecting text by accident while scrolling a list is a browser habit that
     reads as broken in an app. Inputs and real prose are exempt below. */
  -webkit-user-select: none;
  user-select: none;
}

html[data-standalone="true"] input,
html[data-standalone="true"] textarea,
html[data-standalone="true"] [contenteditable],
html[data-standalone="true"] .reader__body,
html[data-standalone="true"] pre,
html[data-standalone="true"] code,
html[data-standalone="true"] .kg-act__outcome-text {
  -webkit-user-select: text;
  user-select: text;
}

/* Momentum scrolling inside panes, so a long list in the graph inspector
   behaves the way every other list on the phone does. */
.kg-tabpane, .reader__toc, .admin-nav, #books {
  -webkit-overflow-scrolling: touch;
}

/* ------------------------------------------------------- touch targets */
@media (pointer: coarse) {
  .btn--sm { min-height: 40px; }
  .btn { min-height: 44px; }
  /* A remove link that sits 8px from an open link is a link you tap by
     mistake, and this one deletes a book. */
  .book-card__remove { min-height: 40px; padding-inline: var(--space-3); }
  .shelf-group__head { padding: var(--space-4) 0; }
}

/* ------------------------------------------------------------- dialog
   Native <dialog>, so focus trapping, Escape and the backdrop come from
   the browser rather than from script that has to be kept correct.
   Styled here because the element ships with a white box and a black
   border that belong to no theme. */
dialog {
  width: min(440px, calc(100vw - var(--space-5)));
  padding: var(--space-5);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text);
  box-shadow: var(--shadow-lifted);
}

dialog::backdrop {
  /* Deliberately not a theme token: ::backdrop sits outside the document,
     so custom properties declared on :root do not reach it. */
  background: rgba(10, 12, 16, 0.55);
}

dialog[open] { animation: dialog-in .14s ease-out; }

@keyframes dialog-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  dialog[open] { animation: none; }
}

/* A phone keyboard covers the lower half of the screen, so a centred
   dialog with a text field in it ends up behind the keyboard. */
@media (max-width: 560px) {
  dialog {
    margin-top: var(--space-5);
    margin-bottom: auto;
  }
}

/* =====================================================================
   The desk
   ---------------------------------------------------------------------
   A knowledge base is a deposit system: you put in today and get out in
   eight months, and nobody sustains that on discipline alone. So the
   front door is the place you ASK it something. A graph that visibly
   pays you back is the only kind anyone keeps filling.
   ===================================================================== */

.desk { margin-top: var(--space-5); }

.desk__ask { display: flex; gap: var(--space-2); }
.desk__ask input {
  flex: 1 1 auto;
  min-width: 0;            /* or a long placeholder pushes the button off-screen */
  height: 52px;
  font-size: max(16px, 1.0625rem);
  padding: 0 var(--space-4);
  border-radius: var(--radius-md);
}
.desk__ask .btn { height: 52px; padding-inline: var(--space-5); }

.desk__answer {
  margin-top: var(--space-4);
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-primary);
  border-radius: var(--radius-md);
  background: var(--color-surface);
}
.desk__answer p { margin: 0 0 var(--space-2); }
.desk__answer p:last-child { margin-bottom: 0; }

/* Nothing on file is a legitimate answer, not an error. It gets a neutral
   edge so it does not read as something having gone wrong. */
.desk__answer.is-empty { border-left-color: var(--color-text-muted); }
.desk__answer.is-conflict { border-left-color: var(--color-warning); }
.desk__answer.is-error { border-left-color: var(--color-danger); }

/* The line naming a figure that must not be quoted. Loud on purpose: it is
   the one part of an answer that is a warning rather than information. */
.desk__note {
  color: var(--color-warning);
  font-size: 0.9375rem;
}

.desk__queues {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-3);
  margin-top: var(--space-5);
}

.desk__tile {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text);
  text-decoration: none;
}
.desk__tile:hover { border-color: var(--color-primary); box-shadow: var(--shadow-card); }
.desk__n { font-family: var(--font-heading); font-size: 1.5rem; font-weight: 600; }
.desk__label { color: var(--color-text-muted); font-size: 0.9375rem; }

/* An empty queue should look finished, not broken. */
.desk__tile.is-clear .desk__n { color: var(--color-success); }

@media (max-width: 560px) {
  .desk__ask { flex-wrap: wrap; }
  .desk__ask input { flex: 1 1 100%; }
  .desk__ask .btn { flex: 1 1 100%; }
}

/* The desk, beyond the ask box. A count you have to open three pages to act
   on is not a prompt — so the top of the review queue is shown in full, and
   each map carries its own draft count. */
.desk__h {
  font-size: 1rem;
  color: var(--color-text-muted);
  margin: var(--space-5) 0 var(--space-3);
}

.desk__maprow {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--space-3);
}
.desk__map {
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text);
  text-decoration: none;
}
.desk__map:hover { border-color: var(--color-primary); }
.desk__map-title { font-family: var(--font-heading); font-weight: 500; }
.desk__map-meta { color: var(--color-text-muted); font-size: 0.875rem; }

.desk__nextcard {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-accent);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text);
  text-decoration: none;
}
.desk__nextcard:hover { border-color: var(--color-primary); }
.desk__nexttitle { font-family: var(--font-heading); font-size: 1.125rem; font-weight: 500; }
