/* Sattvam AI — Lean division. Deliberately close to paper: this is a tool for
   reading maps, and the maps are line drawings. */

:root {
  --ink: #1b1b1b;
  --ink-2: #555;
  --ink-3: #888;
  --line: #dedbd4;
  --paper: #fbfbf9;
  --panel: #fff;
  --accent: #0b6b3a;
  --warn: #b26a00;
  --bad: #b3261e;
  --ok: #0b6b3a;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
}

code, pre { font-family: "SF Mono", Menlo, Consolas, monospace; }

/* ── header ─────────────────────────────────────────────────────────── */

.top {
  display: flex; align-items: center; gap: 24px;
  padding: 12px 22px;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 20;
}
.brand { font-weight: 600; letter-spacing: -0.01em; }
.brand .div { color: var(--ink-3); margin: 0 6px; }
.brand .unit { color: var(--accent); }
.top nav { display: flex; gap: 16px; }
.top nav a {
  color: var(--ink-2); text-decoration: none; font-size: 13px;
  padding: 4px 2px; border-bottom: 2px solid transparent;
}
.top nav a:hover { color: var(--ink); }
.top nav a.on { color: var(--ink); border-bottom-color: var(--accent); }
.engine { margin-left: auto; font-size: 11.5px; color: var(--ink-3); }

/* ── layout ─────────────────────────────────────────────────────────── */

main { display: grid; grid-template-columns: 330px 1fr; gap: 0; align-items: start; }
body.single main, main.map-page { display: block; }

.panel.controls {
  padding: 22px;
  border-right: 1px solid var(--line);
  background: var(--panel);
  position: sticky; top: 49px;
  height: calc(100vh - 49px);
  overflow-y: auto;
}
h1 { font-size: 19px; margin: 0 0 8px; letter-spacing: -0.01em; }
.lede { font-size: 12.5px; color: var(--ink-2); margin: 0 0 20px; }

.form .row { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.form .row.col { flex-direction: column; align-items: stretch; gap: 5px; }
.form label { font-size: 12px; color: var(--ink-2); min-width: 74px; }
.form .hint { color: var(--ink-3); font-weight: 400; }
.form input, .form select, .form textarea {
  flex: 1; padding: 6px 8px; font-size: 13px; font-family: inherit;
  border: 1px solid var(--line); border-radius: 3px; background: #fff; color: var(--ink);
}
.form textarea { resize: vertical; }
.form input:focus, .form select:focus, .form textarea:focus { outline: 2px solid #cfe3d7; border-color: var(--accent); }

button { font: inherit; cursor: pointer; border-radius: 3px; }
button.primary {
  width: 100%; margin-top: 8px; padding: 9px 14px;
  background: var(--accent); color: #fff; border: none; font-size: 13.5px; font-weight: 500;
}
button.primary:hover { background: #095c31; }
button.primary:disabled { background: var(--ink-3); cursor: progress; }
button.ghost { padding: 6px 9px; background: #fff; border: 1px solid var(--line); color: var(--ink-2); }

.legend { margin-top: 26px; padding-top: 18px; border-top: 1px solid var(--line); }
.legend h3 { font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-3); margin: 0 0 8px; }
.legend ul { margin: 0; padding-left: 16px; font-size: 12px; color: var(--ink-2); }
.legend li { margin-bottom: 4px; }

/* ── output ─────────────────────────────────────────────────────────── */

.output { padding: 22px; min-width: 0; }
.output .empty { color: var(--ink-3); padding: 60px 0; text-align: center; }

.verdict {
  padding: 12px 16px; border-radius: 4px; margin-bottom: 18px;
  border: 1px solid var(--line); background: var(--panel);
}
.verdict-main { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.verdict .badge {
  font-size: 11px; font-weight: 700; letter-spacing: 0.06em;
  padding: 3px 8px; border-radius: 3px; background: #eee; color: var(--ink-2);
}
.verdict.committed { border-left: 3px solid var(--ok); }
.verdict.committed .badge { background: #e3f0e8; color: var(--ok); }
.verdict.escalated { border-left: 3px solid var(--warn); }
.verdict.escalated .badge { background: #fdf1dd; color: var(--warn); }
.verdict.rejected, .verdict.declined { border-left: 3px solid var(--bad); }
.verdict.rejected .badge, .verdict.declined .badge { background: #fbe6e4; color: var(--bad); }
.verdict.review { border-left: 3px solid var(--warn); }
.verdict.review .badge { background: #fdf1dd; color: var(--warn); }
/* The badge is keyed on the published status's tone now rather than on the
   machine verdict, because the two no longer coincide: a map the engine is
   perfectly happy with is still only a recommendation until it is signed. */
.verdict.ok { border-left: 3px solid var(--ok); }
.verdict.ok .badge { background: #e3f0e8; color: var(--ok); }
.verdict.warn { border-left: 3px solid var(--warn); }
.verdict.warn .badge { background: #fdf1dd; color: var(--warn); }
.verdict.bad { border-left: 3px solid var(--bad); }
.verdict.bad .badge { background: #fbe6e4; color: var(--bad); }
.verdict .prob, .verdict .timing { font-size: 12px; color: var(--ink-2); }
.verdict-actions { margin-left: auto; display: flex; gap: 12px; font-size: 12px; }
.verdict-actions a { color: var(--accent); }
.verdict .thr { color: var(--ink-3); margin-left: 6px; }
/* Sign-off state, deliberately given the same visual weight as the badge it
   qualifies. A committed map with nobody's signature on it is not a green
   light, and the reader should not have to look for that. */
.verdict .signoff {
  font-size: 11px; font-weight: 600; letter-spacing: 0.02em;
  padding: 3px 8px; border-radius: 3px; border: 1px solid transparent;
}
.verdict .signoff.ok { background: #e3f0e8; color: var(--ok); border-color: #c9e2d3; }
.verdict .signoff.warn { background: #fdf1dd; color: var(--warn); border-color: #f0dcb8; }
.verdict .archetype { font-size: 12px; color: var(--ink-2); margin-top: 7px; }

.compare { margin-bottom: 22px; }
.compare h2 { font-size: 13px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-3); margin: 0 0 10px; }
.metrics { display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); gap: 10px; }
.metric { background: var(--panel); border: 1px solid var(--line); border-radius: 4px; padding: 9px 11px; }
.metric.better { border-left: 2px solid var(--ok); }
.mlabel { font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.03em; color: var(--ink-3); margin-bottom: 4px; }
.mvals { font-size: 13px; }
.mvals .from { color: var(--ink-3); }
.mvals .arrow { color: var(--ink-3); margin: 0 4px; }
.mvals .to { font-weight: 600; }
.mvals .unit { font-size: 10.5px; color: var(--ink-3); margin-left: 4px; }
.mshift { font-size: 11px; color: var(--ink-3); margin-top: 2px; }
.mshift.good { color: var(--ok); }

.state { background: var(--panel); border: 1px solid var(--line); border-radius: 4px; margin-bottom: 22px; overflow: hidden; }
.state-head {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 11px 16px; border-bottom: 1px solid var(--line); background: #fcfcfa;
}
.state-head h2 { font-size: 14px; margin: 0; }
.chips { display: flex; gap: 6px; flex-wrap: wrap; margin-left: auto; }
.chip {
  font-size: 10.5px; padding: 2px 7px; border-radius: 10px;
  background: #f0efeb; color: var(--ink-2); text-decoration: none;
}
.chip.ok { background: #e3f0e8; color: var(--ok); }
.chip.bad { background: #fbe6e4; color: var(--bad); }
.chip.link { background: transparent; color: var(--accent); border: 1px solid var(--line); }
.chip.cat-convention, .tag.cat-convention { background: #eef1f7; color: #3b5480; }
.chip.cat-discipline, .tag.cat-discipline { background: #f7eef5; color: #7d3b6b; }
.chip.cat-design, .tag.cat-design { background: #fbe6e4; color: var(--bad); }
.chip.cat-improvement, .tag.cat-improvement { background: #fdf6e3; color: var(--warn); }

.svg-wrap { overflow-x: auto; padding: 10px 0; background: #fff; }
.svg-wrap svg { display: block; }
.svg-wrap.wide { padding: 20px; }

details { border-top: 1px solid var(--line); }
summary {
  padding: 9px 16px; font-size: 12.5px; cursor: pointer; color: var(--ink-2);
  user-select: none;
}
summary:hover { background: #fcfcfa; color: var(--ink); }
summary .warn { color: var(--warn); }

.kpi-table, .doc-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.kpi-table th, .doc-table th {
  text-align: left; padding: 6px 16px; font-size: 10.5px; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--ink-3); border-bottom: 1px solid var(--line); font-weight: 500;
}
.kpi-table td, .doc-table td { padding: 5px 16px; border-bottom: 1px solid #f2f0ec; vertical-align: top; }
.kpi-table td.n { text-align: right; font-family: "SF Mono", Menlo, monospace; }
.kpi-table td.u, .kpi-table td.sc, .kpi-table td.s { color: var(--ink-3); font-size: 11px; }
.kpi-table tr.oob td.n { color: var(--bad); font-weight: 600; }
.unresolved { padding: 8px 16px; font-size: 11px; color: var(--ink-3); margin: 0; }

.findings ul { margin: 0; padding: 4px 16px 12px 34px; font-size: 12px; }
.findings li { margin-bottom: 7px; }
.findings code { font-size: 11px; background: #f4f3ef; padding: 1px 5px; border-radius: 3px; }
.findings .msg { color: var(--ink-2); margin-top: 2px; font-size: 11.5px; }
.findings.errors code { background: #fbe6e4; color: var(--bad); }
.findings .evidence { padding-left: 14px; margin-top: 3px; }
.findings .evidence .thr { color: var(--ink-3); }

.tag {
  font-size: 10px; padding: 1px 6px; border-radius: 9px; background: #f0efeb;
  color: var(--ink-2); margin-left: 5px;
}
.tag.primary { background: #fbe6e4; color: var(--bad); }
.tag.sev-error { background: #fbe6e4; color: var(--bad); }
.tag.sev-warn { background: #fdf1dd; color: var(--warn); }
.tag.sev-info { background: #eef1f7; color: #3b5480; }
.tag.band { font-family: "SF Mono", Menlo, monospace; }

.text-view pre {
  margin: 0; padding: 14px 16px; font-size: 11px; line-height: 1.45;
  background: #fcfcfa; overflow-x: auto; color: var(--ink);
}

.notes { background: var(--panel); border: 1px solid var(--line); border-radius: 4px; padding: 12px 16px; }
.notes h3 { font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-3); margin: 0 0 6px; }
.notes ul { margin: 0; padding-left: 18px; font-size: 12px; color: var(--ink-2); }

.error { color: var(--bad); padding: 20px; }

/* ── substrate browser ──────────────────────────────────────────────── */

.substrate-page { display: grid; grid-template-columns: 220px 1fr; }
.families {
  padding: 20px; border-right: 1px solid var(--line); background: var(--panel);
  position: sticky; top: 49px; height: calc(100vh - 49px); overflow-y: auto;
}
.families h2 { font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-3); margin: 0 0 10px; }
.families ul { list-style: none; margin: 0; padding: 0; }
.families a {
  display: flex; justify-content: space-between; padding: 5px 8px; border-radius: 3px;
  color: var(--ink-2); text-decoration: none; font-size: 12.5px;
}
.families a:hover { background: #f4f3ef; color: var(--ink); }
.families a.on { background: #e3f0e8; color: var(--accent); font-weight: 500; }
.families .n { color: var(--ink-3); font-size: 11px; }
.families .src { font-size: 11px; color: var(--ink-3); margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--line); }

.docs { padding: 20px 0; min-width: 0; }
.docs h1 { padding: 0 16px; }
.docs .count { color: var(--ink-3); font-weight: 400; font-size: 14px; }
.doc-table code.formula { display: block; font-size: 11px; color: #3b5480; margin-bottom: 3px; }
.doc-table .intent { font-size: 11.5px; color: var(--ink-2); margin-top: 3px; }
.doc-table .aliases { font-size: 11px; color: var(--ink-3); max-width: 260px; }

.error-page { padding: 60px 22px; }
.error-page a.primary { display: inline-block; width: auto; padding: 8px 16px; color: #fff; text-decoration: none; background: var(--accent); border-radius: 3px; }

@media (max-width: 980px) {
  main, .substrate-page { grid-template-columns: 1fr; }
  .panel.controls, .families { position: static; height: auto; border-right: none; border-bottom: 1px solid var(--line); }
}

/* ── the mapping conversation ────────────────────────────────────────── */

.chat-main { grid-template-columns: 420px 1fr; }
.panel.chat {
  padding: 20px 20px 16px;
  border-right: 1px solid var(--line);
  background: var(--panel);
  position: sticky; top: 49px;
  height: calc(100vh - 49px);
  display: flex; flex-direction: column; gap: 12px;
  /* The column is taller than the viewport once the understood panel and
     narrative are open — scroll the whole chat side, don't clip it. */
  overflow-x: hidden;
  overflow-y: auto;
  min-height: 0;
  -webkit-overflow-scrolling: touch;
}

/* One tab per value stream. A tab strip rather than a sidebar, because these are
   several readings of one job, not several jobs. */
.streams {
  display: flex; align-items: center; gap: 8px;
  border-bottom: 1px solid var(--line); padding-bottom: 8px;
}
.stream-tabs { display: flex; gap: 4px; overflow-x: auto; flex: 1 1 auto; min-width: 0; }
.history-actions { display: flex; align-items: center; gap: 4px; flex: 0 0 auto; }
.history-btn:disabled {
  opacity: 0.4; cursor: not-allowed; border-color: var(--line); color: var(--ink-3);
}
.stream-tab {
  display: inline-flex; align-items: center;
  border: 1px solid var(--line); border-radius: 3px; background: #fbfbf9;
  max-width: 190px; flex: 0 0 auto;
}
.stream-tab.on { border-color: var(--accent); background: #fff; }
button.stream-pick {
  padding: 5px 8px; font: inherit; font-size: 12px; line-height: 1.2;
  background: none; border: 0; color: var(--ink-2); cursor: pointer;
  max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.stream-tab.on button.stream-pick { color: var(--ink); font-weight: 500; }
button.stream-close {
  padding: 3px 6px 4px; font: inherit; font-size: 13px; line-height: 1;
  background: none; border: 0; color: var(--ink-3); cursor: pointer;
}
button.stream-close:hover { color: var(--bad); }
button.ghost.small {
  flex: 0 0 auto; padding: 5px 10px; font-size: 12px;
  background: #fff; border: 1px solid var(--accent); color: var(--accent);
}

/* ── the worked example ──────────────────────────────────────────────────
   First-run furniture, so it is offered rather than imposed: closed, one line
   tall, and gone for good once the stream has a conversation in it. */

.example-wrap { flex: 0 0 auto; margin-bottom: 14px; }
.example-nudge {
  margin: 0 0 6px; font-size: 12.5px; line-height: 1.45; color: var(--ink-2);
}
.example-blink {
  flex: 0 0 auto;
  width: 8px; height: 8px; border-radius: 50%;
  background: #d32f2f;
  box-shadow: 0 0 0 0 rgba(211, 47, 47, 0.55);
  animation: exampleBlink 1.2s ease-out infinite;
}
@keyframes exampleBlink {
  0%   { transform: scale(1);   box-shadow: 0 0 0 0 rgba(211, 47, 47, 0.55); }
  70%  { transform: scale(1.15); box-shadow: 0 0 0 7px rgba(211, 47, 47, 0); }
  100% { transform: scale(1);   box-shadow: 0 0 0 0 rgba(211, 47, 47, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .example-blink { animation: none; }
}

.example {
  border: 1px solid #cfe3d7; border-radius: 4px; background: #f7faf8;
}
.example > summary {
  padding: 8px 11px; cursor: pointer; list-style: none;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.example > summary:focus {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.example > summary::-webkit-details-marker { display: none; }
.example > summary::before {
  content: '+'; font-size: 13px; line-height: 1; color: var(--accent); font-weight: 600;
}
.example[open] > summary::before { content: '\2212'; }
.example-open { font-size: 12.5px; font-weight: 600; color: var(--accent); }
.example-why { font-size: 11.5px; color: var(--ink-3); }

.example-body { padding: 0 11px 11px; }
.example-lede { font-size: 12px; color: var(--ink-2); margin: 0 0 9px; }
.example-parts { margin: 0 0 11px; padding-left: 18px; }
.example-parts li { font-size: 11.5px; color: var(--ink-2); margin-bottom: 4px; }
.example-parts li b { color: var(--ink); }
.example-actions { display: flex; gap: 8px; margin-bottom: 10px; flex-wrap: wrap; align-items: center; }
.example-actions .primary { width: auto; margin-top: 0; padding: 7px 13px; font-size: 12px; }

/* Choosing a stream. The two fields share a row on a desk and stack on a phone,
   where a dropdown wants the full width to show a long stream name. */
.example-pick { display: flex; gap: 9px; margin-bottom: 10px; flex-wrap: wrap; }
.pick-field { display: flex; flex-direction: column; gap: 3px; flex: 1 1 190px; min-width: 0; }
/* An author display rule outranks the browser's own rule for [hidden], so
   without this the field the script hides stays on screen. */
.pick-field[hidden] { display: none; }
.pick-field > span { font-size: 11px; color: var(--ink-3); text-transform: uppercase; letter-spacing: .04em; }
.pick-field select {
  width: 100%; padding: 7px 8px; font: inherit; font-size: 12.5px; color: var(--ink);
  background: #fff; border: 1px solid var(--line); border-radius: 3px;
}
.pick-field select:focus { outline: 2px solid var(--accent); outline-offset: -1px; }

.example-state { font-size: 11.5px; color: var(--ink-3); }

/* What the selected stream is. One line on a desk, wrapping on a phone. */
.example-what { margin: 0 0 9px; font-size: 12px; display: flex; gap: 7px; flex-wrap: wrap; align-items: baseline; }
.example-what b { color: var(--ink); }
.example-meta { font-size: 11.5px; color: var(--ink-3); }
.example-headline { flex: 1 1 100%; font-size: 11.5px; color: var(--ink-2); }

/* The teaching notes, folded away. They are what a first-time user needs and
   what a returning one has already read, and a returning one is who is here to
   pick a stream and press Generate. */
.example-teaches { margin: 0 0 10px; }
.example-teaches > summary {
  cursor: pointer; font-size: 11.5px; color: var(--accent); padding: 2px 0;
}
.example-teaches[open] > summary { margin-bottom: 6px; }
.example-text {
  margin: 0; padding: 9px 10px; max-height: 26vh; overflow-y: auto;
  font: inherit; font-size: 11.5px; line-height: 1.5; color: var(--ink-2);
  white-space: pre-wrap; background: #fff;
  border: 1px solid var(--line); border-radius: 3px;
}

/* Cap the turn log so it does not push the editors off-screen; the chat
   column itself scrolls to reach narrative and actions below. */
.thread {
  flex: 0 1 auto;
  overflow-y: auto;
  min-height: 72px;
  max-height: 22vh;
  padding-right: 4px;
}
.turn { margin-bottom: 12px; }
.turn .who {
  display: block; font-size: 10.5px; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--ink-3); margin-bottom: 3px;
}
.turn p { margin: 0; padding: 8px 10px; border-radius: 4px; font-size: 13px; white-space: pre-wrap; }
.turn.lnse p { background: #f4f6f4; border-left: 2px solid var(--accent); }
.turn.user p { background: #fff; border: 1px solid var(--line); }

/* What the engine understood — editable after the first map. */
.understood {
  border-top: 1px solid var(--line); padding-top: 10px;
  display: flex; flex-direction: column;
  flex: 0 0 auto;
}
.understood-head { flex-shrink: 0; }
.understood-head h3 { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--ink-3); margin: 0 0 4px; }
.understood-lede { font-size: 11.5px; color: var(--ink-3); margin: 0 0 10px; }
.understood-body { flex: 0 0 auto; }
.understood-actions {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  flex-shrink: 0; margin-top: 8px; padding-top: 8px;
  border-top: 1px solid var(--line); background: var(--paper, #faf9f6);
  position: sticky; bottom: 0; z-index: 2;
}
.understood-actions .primary.small,
.narrative-actions .primary.small { width: auto; margin-top: 0; padding: 7px 12px; font-size: 12px; }
.u-section { margin-bottom: 12px; }
.u-section-head {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin-bottom: 6px;
}
.u-section-title {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--ink-3); margin: 0; font-weight: 600;
}
.u-section-head .ghost.small {
  flex-shrink: 0; padding: 4px 8px; font-size: 11px;
  border: 1px solid var(--line); background: #fff;
}
button.u-remove {
  white-space: nowrap; color: var(--warn, #a14a2a);
  border: 1px solid #e2c4b8; background: #fff; padding: 4px 8px; font-size: 11px;
}
.u-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin-bottom: 0; }
.u-stream { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin-bottom: 0; }
.u-field { display: flex; flex-direction: column; gap: 3px; font-size: 11px; color: var(--ink-3); }
.u-field input,
.u-field select,
.u-edit input,
.u-edit select {
  width: 100%; padding: 5px 6px; font: inherit; font-size: 12px;
  border: 1px solid var(--line); border-radius: 3px; background: #fff; color: var(--ink);
}
.u-edit input.u-name { min-width: 9rem; }
.u-edit input[type="number"] { min-width: 4.2rem; }
.u-edit select.u-pos,
.u-edit select.u-before { min-width: 7rem; }
/* Eighteen columns of figures do not fit a phone, so the table pans instead of
   crushing its columns. */
.u-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.u-table { width: 100%; border-collapse: collapse; font-size: 11.5px; margin-bottom: 8px; }
.u-table th { text-align: left; font-weight: 500; color: var(--ink-3); border-bottom: 1px solid var(--line); padding: 2px 4px; }
.u-table td { padding: 2px 4px; border-bottom: 1px solid #f0efea; vertical-align: middle; }
/* The rest of what can be said about one operation.
   Folded shut, because it is thirty fields and almost nobody has all of them —
   open, it is a panel rather than a row, so it breaks out of the cell it lives
   in and lays itself out in labelled groups. */
.u-more { vertical-align: top; }
.u-detail > summary {
  cursor: pointer; font-size: 11px; color: var(--accent);
  padding: 4px 6px; white-space: nowrap; list-style: none;
}
.u-detail > summary::-webkit-details-marker { display: none; }
.u-detail > summary::after { content: ' ▾'; }
.u-detail[open] > summary::after { content: ' ▴'; }
.u-detail[open] {
  position: relative; display: block; background: #fbfaf7;
  border: 1px solid var(--line); border-radius: 4px; padding: 6px 8px 8px;
  min-width: 22rem;
}
.u-detail-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 12px; }
.u-detail-group { min-width: 0; }
.u-detail-title {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--ink-3); margin: 2px 0 4px;
}
.u-detail-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
.u-field.small { font-size: 10.5px; }
.u-field.small input, .u-field.small select { font-size: 11.5px; padding: 3px 5px; }
@media (max-width: 700px) {
  .u-detail-grid, .u-detail-fields { grid-template-columns: minmax(0, 1fr); }
}

.u-note { font-size: 11.5px; color: var(--ink-2); margin: 4px 0; }
.u-note.warn { color: var(--warn); }
.u-hint { font-size: 11px; color: var(--ink-3); margin: 5px 0 0; }
.chat-closed {
  border-top: 1px solid var(--line); padding-top: 10px;
  font-size: 12px; color: var(--ink-3); margin: 0;
}
.narrative-lede { font-size: 11.5px; color: var(--ink-3); margin: 0 0 8px; }
@media (max-width: 720px) {
  .u-stream, .u-grid { grid-template-columns: 1fr; }
}

.say { border-top: 1px solid var(--line); padding-top: 10px; }
.say textarea {
  width: 100%; padding: 8px; font: inherit; font-size: 13px; resize: vertical;
  border: 1px solid var(--line); border-radius: 3px; background: #fff; color: var(--ink);
}
.say textarea:focus { outline: 2px solid #cfe3d7; border-color: var(--accent); }
.say-actions { display: flex; gap: 8px; margin-top: 8px; }
.say-actions .primary { width: auto; flex: 1; margin-top: 0; }
button.mic {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 9px 13px; font-size: 13px;
  background: #fff; color: var(--ink); border: 1px solid var(--line);
}
button.mic .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ink-3); }
button.mic.on { border-color: var(--bad); color: var(--bad); }
button.mic.on .dot { background: var(--bad); animation: pulse 1.1s infinite; }
button.mic:disabled { opacity: 0.5; cursor: not-allowed; }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.25; } }
.say-hint { font-size: 11px; color: var(--ink-3); margin: 7px 0 0; }

.narrative-box {
  border-top: 1px solid var(--line); padding-top: 10px; margin-top: 4px;
  flex: 0 0 auto; padding-bottom: 8px;
}
.narrative-box summary { font-size: 11.5px; color: var(--ink-3); cursor: pointer; }
.narrative-edit {
  display: block; width: 100%; margin: 8px 0 0; min-height: 10rem; max-height: none;
  padding: 8px; font: inherit; font-size: 12px; line-height: 1.45; resize: vertical;
  border: 1px solid var(--line); border-radius: 3px; background: #fff; color: var(--ink);
}
.narrative-edit:focus { outline: 2px solid #cfe3d7; border-color: var(--accent); }
.narrative-actions { display: flex; align-items: center; gap: 8px; margin-top: 8px; }

/* ── future-state options ────────────────────────────────────────────── */

.future-head { padding: 16px 20px 0; }
.future-title { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.future-title h2 { margin: 0; font-size: 16px; }
.option-count { font-size: 11px; color: var(--ink-3); }
.future-summary { font-size: 13px; color: var(--ink-2); margin: 6px 0 0; max-width: 78ch; }
.future-cost { font-size: 12.5px; color: var(--warn); margin: 4px 0 0; max-width: 78ch; }
.future-diff { font-size: 12.5px; color: var(--ink-2); margin: 4px 0 0; max-width: 78ch; }
.metrics.tight { margin: 10px 0; }
.metric.cost .mlabel { color: var(--accent); }
.cost-savings {
  margin: 12px 0 4px; padding: 10px 12px; border: 1px solid var(--line);
  background: linear-gradient(135deg, #f7faf7 0%, #f3f6fb 100%); max-width: 78ch;
}
.cs-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink-3); }
.cs-score { font-size: 22px; font-weight: 650; margin-top: 2px; color: var(--ink); }
.cs-unit { font-size: 12px; font-weight: 500; color: var(--ink-3); margin-left: 4px; }
.cs-headline { font-size: 12.5px; color: var(--ink-2); margin: 4px 0 0; }
.cs-grid { display: flex; flex-wrap: wrap; gap: 12px 18px; margin-top: 8px; font-size: 12px; color: var(--ink-2); }
.cs-grid b { color: var(--ink); }
/* An unpriced saving is a real result with no currency attached. It keeps the
   panel and loses the gradient, so it cannot be mistaken at a glance for the
   priced case. */
.cost-savings.unpriced { background: #f8f8f6; }
.cs-basis {
  display: inline-block; margin-left: 6px; padding: 1px 6px;
  border: 1px solid var(--line); border-radius: 9px;
  font-size: 10px; letter-spacing: 0.02em; text-transform: none; color: var(--ink-3);
}
.cs-disclosure, .cs-missing {
  font-size: 11.5px; color: var(--ink-3); margin: 8px 0 0; max-width: 72ch;
}
.cs-missing { color: var(--ink-2); }
.gantt-controls {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 14px 0 6px; font-size: 13px;
  padding: 10px 12px;
  border: 1px solid rgba(34, 211, 238, 0.18);
  background:
    linear-gradient(135deg, rgba(7, 13, 24, 0.04), rgba(34, 211, 238, 0.06)),
    #f7fafb;
}
.gantt-controls label {
  color: #0e7490;
  font-weight: 650;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-size: 11px;
}
.gantt-controls select {
  padding: 6px 10px; border: 1px solid rgba(14, 116, 144, 0.35);
  background: #fff; font: inherit; color: var(--ink);
}
.gantt-controls #drawGantt,
.gantt-controls #drawHeijunka {
  border-color: #0891b2; color: #0e7490; background: rgba(34, 211, 238, 0.08);
}
.gantt-controls #drawGantt:hover,
.gantt-controls #drawHeijunka:hover { background: rgba(34, 211, 238, 0.16); }
.gantt-pane {
  margin: 8px 0 8px; padding: 12px;
  border: 1px solid rgba(34, 211, 238, 0.28);
  background:
    radial-gradient(1200px 240px at 10% -10%, rgba(34, 211, 238, 0.16), transparent 55%),
    radial-gradient(900px 220px at 90% 0%, rgba(52, 211, 153, 0.1), transparent 50%),
    #070d18;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.04),
    0 12px 40px rgba(7, 13, 24, 0.18);
  border-radius: 16px;
}
.gantt-pane .gantt-msg {
  font-size: 11px; color: #67e8f9; margin: 0 0 10px;
  font-family: "IBM Plex Mono", "SF Mono", ui-monospace, monospace;
  letter-spacing: 0.08em; text-transform: uppercase;
}

/* What the levelled plan cannot promise, and what it had to assume to promise
   the rest. Both sit inside the dark pane under the chart, because a check read
   away from the plan it belongs to is a check nobody acts on. The left rule
   carries the severity: red blocks the plan, amber costs it headroom. */
.hy-checks, .hy-assumptions {
  list-style: none; margin: 12px 0 0; padding: 0;
  display: grid; gap: 6px; max-width: 96ch;
}
.hy-checks li {
  font-size: 12.5px; line-height: 1.45; color: #cbd5e1;
  padding: 6px 10px; border-left: 2px solid rgba(148, 163, 184, 0.4);
  background: rgba(148, 163, 184, 0.06);
}
.hy-checks li.error { border-left-color: #f43f5e; color: #fecdd3; background: rgba(244, 63, 94, 0.08); }
.hy-checks li.warn { border-left-color: #fbbf24; color: #fde68a; background: rgba(251, 191, 36, 0.07); }
.hy-checks li.info { border-left-color: #4ade80; }
.hy-assumptions {
  margin-top: 8px; padding-top: 8px;
  border-top: 1px solid rgba(148, 163, 184, 0.18);
}
.hy-assumptions li { font-size: 11.5px; line-height: 1.45; color: #94a3b8; }
.hy-assumptions li::before { content: "assumed · "; color: #64748b; letter-spacing: 0.06em; }
/* The cell layout. It shares the dark pane the Gantt and the levelled plan use,
   because the three are the same kind of thing — what the future state above
   implies once somebody has to act on it — and giving the layout its own visual
   language would suggest it came from somewhere else. */
.cell-pane {
  margin: 8px 0; padding: 12px;
  border: 1px solid rgba(34, 211, 238, 0.28);
  background:
    radial-gradient(1200px 240px at 10% -10%, rgba(34, 211, 238, 0.16), transparent 55%),
    radial-gradient(900px 220px at 90% 0%, rgba(167, 139, 250, 0.1), transparent 50%),
    #070d18;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.04),
    0 12px 40px rgba(7, 13, 24, 0.18);
  border-radius: 16px;
}

/* The three drawings a future state implies — the cell, the kaizen schedule and
   the levelled year — all scroll the same way.

   A drawing is sized by what it has to say: a fourteen-station cell or a
   twenty-four-month plan is wider than any column it will ever sit in. Scaling it
   down to fit made the words too small to read, so the drawing keeps its own size
   and the pane scrolls in both directions instead. min-width: 0 is what allows
   that — without it the pane is stretched by its own content, the grid column
   grows with it, and the card's rounded corners quietly clip the right-hand side
   with no scrollbar anywhere to reach it.

   The height cap is per pane rather than on the page: three panes tall enough to
   need a cap would otherwise put the findings under the future state a full
   screen further down than the map they belong to. */
.cell-pane, .gantt-pane {
  overflow: auto;
  min-width: 0; max-width: 100%;
  max-height: 78vh;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-x pan-y pinch-zoom;
}
/* Natural size, but never narrower than the pane: a small drawing fills the
   space it is given, a large one overflows it and is scrolled to. */
.cell-pane svg, .gantt-pane svg {
  display: block;
  width: auto; height: auto;
  min-width: 100%; max-width: none;
}
.cell-head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px; margin-bottom: 4px;
}
.cell-shape {
  font: 700 11px "IBM Plex Mono", "SF Mono", ui-monospace, monospace;
  letter-spacing: 0.16em; text-transform: uppercase; color: #22d3ee;
}
.cell-facts {
  font: 500 11px "IBM Plex Mono", "SF Mono", ui-monospace, monospace;
  color: #94a3b8; letter-spacing: 0.04em;
}
.cell-msg { margin: 0 0 10px; font-size: 12.5px; line-height: 1.5; color: #cbd5e1; }

/* The citations, folded away by default. A reader who wants the book and the
   page will open it; a reader who does not should still be able to see the
   drawing without scrolling past fifteen references to get there. */
.cell-sources { margin-top: 12px; }
.cell-sources summary {
  cursor: pointer; font: 600 11px "IBM Plex Mono", "SF Mono", ui-monospace, monospace;
  letter-spacing: 0.08em; text-transform: uppercase; color: #67e8f9;
}
.cell-sources ul { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 6px; }
.cell-sources li { font-size: 11.5px; line-height: 1.45; color: #94a3b8; }
.cell-sources code { color: #a5f3fc; background: rgba(34, 211, 238, 0.08); padding: 0 4px; }
.cell-sources .msg { display: block; color: #64748b; }
.cell-sources .pages { color: #fbbf24; }

button.ghost.wide {
  width: 100%; margin: 12px 0 4px; padding: 9px 14px; font-size: 13px;
  background: #fff; border: 1px solid var(--accent); color: var(--accent);
}
button.ghost.wide:disabled { opacity: 0.55; cursor: wait; }

.assumptions { padding: 16px 20px; border-top: 1px solid var(--line); }
.assumptions h3 { font-size: 13px; margin: 0 0 4px; }
.assumptions ul { margin: 8px 0 0; padding-left: 18px; }
.assumptions li { font-size: 12.5px; margin-bottom: 4px; }
.assumptions code { font-size: 11.5px; color: var(--ink-2); }
.assumed-val { margin-left: 6px; }
.muted { color: var(--ink-3); }

/* ── phones and tablets ──────────────────────────────────────────────────
   These rules live at the end of the file on purpose. The desktop chat layout
   is `.chat-main`, a class, and it out-specifies the bare `main` in the earlier
   980px query — which is why the builder never actually collapsed to one column
   on a phone. It kept a 420px chat beside a 44px sliver of map, the panel pinned
   to the viewport height with its conversation clipped inside and no way to
   reach the rest of it. Ordering these last, against the same selectors, is what
   makes the override hold.

   The shape on a small screen is: one column, the page itself scrolls, and each
   thing that can be wider or taller than the screen — the conversation, the
   drawings, the tables — is its own scroll box rather than a clipped one. */

/* A drawing is the one thing here that is genuinely bigger than a phone. Give it
   two axes and a ceiling, so it can be panned in place instead of stretching the
   page to the width of a value stream map. Scroll chaining is left at its
   default: reaching the bottom of a map should carry on down the page rather
   than trapping the finger. */
.svg-wrap {
  overflow: auto;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-x pan-y pinch-zoom;
  overscroll-behavior-x: contain;
}

@media (max-width: 900px) {
  main.chat-main { grid-template-columns: 1fr; }

  /* Static, not sticky: on a phone the panel has the whole page to be as tall as
     it needs, and pinning it to 100vh was what cut the conversation off. */
  .chat-main .panel.chat {
    position: static;
    height: auto;
    border-right: none;
    border-bottom: 1px solid var(--line);
    padding: 16px 14px 14px;
  }

  /* The conversation keeps its own scroll box so the composer stays within reach
     of the thumb, but a tall one is capped by the screen rather than by a figure
     picked for a laptop. */
  .thread {
    min-height: 140px;
    max-height: 58vh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* The panel already scrolls with the page here, so capping it only made a
     second scroll box inside one that was long enough already. */
  .understood { max-height: none; }

  .svg-wrap { max-height: 72vh; }

  .output { padding: 14px; }
  .future-head, .assumptions { padding-left: 14px; padding-right: 14px; }

  /* The engine line is a footnote on a laptop and a wall of text on a phone. */
  .top { gap: 12px; padding: 10px 14px; flex-wrap: wrap; }
  .engine { display: none; }

  h1 { font-size: 17px; }
  .lede { font-size: 12px; }

  /* Both of these are pre-formatted and will not wrap, so they get to scroll
     sideways instead of widening the page. */
  .example-text, .text-view pre { overflow-x: auto; }
}

/* A tablet keeps the two-column reading layout, but iOS reports 100vh as taller
   than the visible area, which hid the composer under the browser's own chrome.
   dvh is the visible height; the vh line stays as the fallback. */
@media (min-width: 901px) {
  .chat-main .panel.chat { height: calc(100dvh - 49px); }
}

/* Coarse pointer, any width: nothing here is small enough to hit reliably with a
   thumb at 12px. iOS also zooms the page when a font under 16px takes focus, and
   that zoom does not undo itself. */
@media (pointer: coarse) {
  .say textarea { font-size: 16px; }
  /* Same reason as the textarea: iOS zooms in on a control with a font under
     16px and does not zoom back out, which leaves the page half off-screen after
     picking an industry. */
  .pick-field select { font-size: 16px; padding: 10px 8px; }
  button.mic, .say-actions .primary { padding: 11px 14px; }
  button.stream-pick { padding: 8px 10px; }
  button.stream-close { padding: 6px 9px; }
  summary { padding: 11px 16px; }
}
