/* ============================================================================
   Typefaces. Self-hosted: the stylesheet asked for Inter for months while no
   font file existed anywhere, so every customer saw their own system font and
   the product looked different on every machine. Both faces are variable
   (one file covers every weight) and latin-subset. Served from our own origin
   because the Content-Security-Policy is font-src 'self' — and because it
   means no customer's browser contacts Google to render our pages.
   Inter — SIL Open Font License 1.1 — https://rsms.me/inter/
   Newsreader — SIL Open Font License 1.1 — https://github.com/productiontype/Newsreader
   ========================================================================= */
@font-face {
  font-family: "Inter var";
  src: url("/web/assets/fonts/inter-var-latin.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Newsreader var";
  src: url("/web/assets/fonts/newsreader-var-latin.woff2") format("woff2");
  font-weight: 400 500;
  font-style: normal;
  font-display: swap;
}

:root {
  --font-sans: "Inter var", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  /* Page titles only. A serif at weight 400 is what stops a heading reading as
     a slab — the old h1 set no weight at all, so it inherited bold at 50px. */
  --font-serif: "Newsreader var", ui-serif, Georgia, "Times New Roman", serif;

  /* The left rail. Hardcoded before, which is why light mode
     lightened the page and left the rail dark. */
  --sidebar-bg: #ffffff;
  --sidebar-fg: #0e1116;
  --sidebar-line: color-mix(in srgb, var(--sidebar-fg) 11%, transparent);
  --sidebar-hover: color-mix(in srgb, var(--sidebar-fg) 5%, transparent);
  --navy: #0e1116;
  --navy-2: #2b3340;
  /* Sampled from the logo file. The accent was #2f55ff — a different hue from
     the mark it sat beside, so the app never quite matched its own brand. */
  --accent: #0668fc;
  --accent-dark: #0a53c4;
  --ink: #0e1116;
  --muted: #71798a;
  --soft: #f6f7f9;
  --surface: #fff;
  --border: #e8eaee;
  --success: #0f7a52;
  --danger: #b42318;
  --warning: #8f5a12;
  /* THE MARKER INKS ON A SHEET (18 Sep 2026): the dots the browser draws
     and the discs the server prints on the download share these three, so
     a dot on screen matches its finding on paper in either theme. */
  --marker-high: #dc2626; --marker-medium: #d97706; --marker-low: #16a34a;
  --marker-ring: #fff;
  --accent-soft: #e8f1ff;
  --page-backdrop: #eceef2;
  --main-bg: #ffffff;
  --surface-raised: #fff;
  --surface-subtle: #f6f7f9;
  --control-bg: #fff;
  /* The padlock on a tab a plan does not include. Defined ONCE, as a mask,
     so it is painted in the brand's ink rather than an operating system's
     coloured emoji - and so it matches the stroke weight of #i-lock in the
     sprite, which is the same drawing for use inside markup. */
  --icon-lock: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='11' width='18' height='11' rx='2'/%3E%3Cpath d='M7 11V7a5 5 0 0 1 10 0v4'/%3E%3C/svg%3E");
  --radius: 8px;
  /* One elevation value applied to everything meant depth signified nothing.
     Structure is carried by 1px borders; shadow is reserved for things that
     genuinely float above the page, and even then it is quiet. */
  --shadow: 0 1px 2px rgba(14,17,22,.05);
  --shadow-pop: 0 8px 24px rgba(14,17,22,.10);
  --btn-primary-start: var(--accent);
  --btn-primary-end: color-mix(in srgb, var(--accent) 78%, #fff);
  font-family: var(--font-sans);
  color: var(--ink);
  background: var(--main-bg);
}

* { box-sizing: border-box; }
html { font-size: 15px; }
body { margin: 0; min-width: 320px; color: var(--ink); background: var(--main-bg); overflow-x: hidden; }
button, input, textarea { font: inherit; }
button { cursor: pointer; }
button:disabled { cursor: not-allowed; opacity: .48; }
[hidden] { display: none !important; }

.auth-view { min-height: 100vh; display: grid; place-items: center; padding: 2rem; background: radial-gradient(circle at 20% 10%, #fff 0, var(--soft) 50%); }
.auth-card { width: min(456px, 100%); padding: 2.4rem; background: var(--surface); border: 1px solid var(--border); border-radius: 10px; box-shadow: var(--shadow-pop); }
.auth-brand { display: inline-flex; align-items: center; gap: .48rem; margin-bottom: 1.15rem; color: var(--navy); font-size: 1.12rem; font-weight: 600; letter-spacing: -.035em; }
.auth-brand img { display: block; width: 32px; height: 32px; object-fit: contain; }
.auth-brand-logo { border-radius: 8px; background: var(--accent); }
.brand-dot { color: var(--accent); }
.brand-mark { display: grid; place-items: center; width: 44px; height: 44px; border-radius: 10px; background: var(--navy); color: #fff; font-size: .77rem; font-weight: 600; letter-spacing: .06em; }
.brand-mark.small { width: 34px; height: 34px; border-radius: 8px; font-size: .77rem; flex: 0 0 auto; }
.brand-logo-small { display: block; width: 34px; height: 34px; flex: 0 0 auto; border-radius: 8px; background: var(--accent); object-fit: contain; }
.eyebrow { margin: 0 0 .35rem; color: var(--accent); font-size: .77rem; font-weight: 600; letter-spacing: .14em; }
h1, h2, h3, p { margin-top: 0; }
/* Weight 400, not the browser's default bold. A 50px heading at weight 700 is
   the single thing that made the app read as heavy; the serif carries the
   authority instead of the weight doing it. Tracking is eased off to match —
   -.045em was tuned for a bold face and opens gaps under a light one. */
h1 {
  margin-bottom: .9rem; font-family: var(--font-serif); font-weight: 400;
  font-size: clamp(1.9rem, 4.4vw, 2.9rem); line-height: 1.14;
  letter-spacing: -.018em; color: var(--navy); text-wrap: balance;
}
h2 {
  margin-bottom: 0; font-family: var(--font-serif); font-weight: 400;
  font-size: 1.42rem; line-height: 1.25; letter-spacing: -.014em; text-wrap: balance;
}
h3 { margin-bottom: .55rem; font-size: 1.02rem; font-weight: 600; letter-spacing: -.006em; }
.lede { color: var(--muted); line-height: 1.6; margin-bottom: 1.45rem; }
.stack { display: grid; gap: .9rem; }
label { display: grid; gap: .38rem; font-size: .77rem; font-weight: 700; color: var(--ink); }
/* Inputs inherited 1rem (15px) from the body while every label, note and
   button around them sat at .68-.78rem. So the text an engineer TYPED was
   half again the size of the interface holding it, which is why a pasted
   context note read as enormous. On the same scale as everything else,
   one step up from a label because it is content rather than chrome. */
input, textarea, select, .paragraph-editor { width: 100%; border: 1px solid var(--border); border-radius: 8px; background: #fff; color: var(--ink); padding: .72rem .78rem; font-size: .82rem; line-height: 1.55; outline: none; }
input:focus, textarea:focus, select:focus, .paragraph-editor:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(0,104,248,.16); outline: none; }
textarea { resize: vertical; line-height: 1.5; }
.button { display: inline-flex; align-items: center; justify-content: center; min-height: 36px; border: 1px solid transparent; border-radius: 8px; padding: .55rem .85rem; font-weight: 550; line-height: 1.1; transition: .16s ease; }
.button.primary { background: var(--accent); color: #fff; }
.button.primary:hover { background: var(--accent-dark); }
.button.secondary { background: var(--navy); color: #fff; }
.button.secondary:hover { background: var(--navy-2); }
.button.ghost { color: var(--ink); background: transparent; border-color: var(--border); }
.button.ghost:hover { background: var(--soft); }
.button.small { min-height: 30px; padding: .35rem .62rem; font-size: .77rem; }
.text-button { background: none; border: 0; color: var(--muted); padding: .25rem; font-size: .77rem; }
.text-button:hover { color: var(--accent); }
/* Every icon in the product is drawn through this ONE rule. Stroke width and
   linecaps live here rather than on each <svg>, so the whole set can be
   retuned in a single place — and so no icon can drift out of the family.
   currentColor means an icon always matches the text it sits beside.
   The previous icons were typewriter characters (‹ › ⌁ ⋮ ⌘ ▤), which took
   their weight from the font and never aligned to the baseline. */
.icon {
  width: 1em; height: 1em; flex: 0 0 auto; vertical-align: -.135em;
  fill: none; stroke: currentColor; stroke-width: 1.75;
  stroke-linecap: round; stroke-linejoin: round;
  pointer-events: none;
}
.icon.lg { width: 1.25em; height: 1.25em; }
.icon-button { display: inline-grid; place-items: center; width: 28px; height: 28px; border: 1px solid var(--border); border-radius: 6px; color: var(--navy); background: #fff; font-size: .95rem; }
.icon-button:hover { border-color: var(--accent); color: var(--accent); }
.inline-actions { display: flex; gap: .45rem; }
.inline-error { margin: 0; color: var(--danger); font-size: .78rem; }
.auth-notice { margin: 0 0 1rem; padding: .7rem .8rem; border: 1px solid color-mix(in srgb, var(--accent) 26%, transparent); border-radius: 8px; color: var(--accent-dark); background: var(--accent-soft); font-size: .78rem; line-height: 1.45; }
.auth-captcha { min-height: 65px; margin: 0 0 1rem; }
.auth-captcha iframe { max-width: 100%; }
.auth-password-visibility { margin-top: -.35rem; font-size: .78rem; }
.auth-outcome { display: grid; gap: .8rem; margin: 0 0 1rem; padding: 1rem; border: 1px solid var(--accent); border-radius: 10px; background: var(--accent-soft); }
.auth-outcome .eyebrow { margin: 0; }
.auth-outcome h2, .auth-outcome p { margin: 0; }
.auth-outcome h2 { font-size: 1.15rem; }
.auth-outcome p:not(.eyebrow) { color: var(--muted); font-size: .84rem; line-height: 1.5; }
.auth-outcome .button { width: 100%; }
.auth-register-cta { display: grid; gap: .55rem; margin-top: 1.35rem; padding-top: 1.2rem; border-top: 1px solid var(--border); color: var(--muted); font-size: .78rem; text-align: center; }
.register-button { width: 100%; min-height: 42px; border-color: var(--accent); color: var(--accent); background: var(--accent-soft); font-size: .88rem; }
.register-button:hover { color: #fff; background: var(--accent); }

.app-shell { min-height: 100vh; }
#workspace-view { min-height: 100vh; display: grid; grid-template-columns: var(--sidebar-width, 265px) minmax(0, 1fr) var(--rail-width, 0px); }
/* The drag handle on the sidebar's edge (owner, 2 Sep: "resize both
   side panels as much as I like"). Same pattern as the review rail —
   but VISIBLE: a 6px invisible strip is a control nobody can find, and
   he could not (2 Sep: "the sidebar width slider is not visible"). A
   faint grip line sits on the edge at rest and brightens on hover. */
.sidebar-resizer { position: absolute; top: 0; right: -5px; width: 12px;
  height: 100%; cursor: col-resize; z-index: 220; touch-action: none; }
.sidebar-resizer::after { content: ""; position: absolute; top: 50%;
  right: 3px; transform: translateY(-50%); width: 3px; height: 44px;
  border-radius: 3px;
  background: color-mix(in srgb, var(--sidebar-fg) 28%, transparent); }
.sidebar-resizer:hover::after,
body.resizing-sidebar .sidebar-resizer::after {
  background: var(--accent); height: 72px; }
.sidebar { position: relative; }
body.resizing-sidebar { cursor: col-resize; user-select: none; }
.sidebar { display: flex; flex-direction: column; min-height: 100vh; padding: 1.05rem .85rem .8rem; background: var(--sidebar-bg); color: var(--sidebar-fg); }
.sidebar-head { display: flex; align-items: center; gap: .65rem; padding: .3rem .35rem 1.35rem; }
.sidebar-head strong { display: block; font-size: .92rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sidebar-head { min-width: 0; }
.sidebar-head > div, .sidebar-head > span { min-width: 0; }
.sidebar-head .muted { display: block; color: color-mix(in srgb, var(--sidebar-fg) 56%, transparent); font-size: .77rem; margin-top: .12rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sidebar-toggle { display: inline-grid; place-items: center; margin-left: auto; width: 30px; height: 30px; flex: 0 0 30px; border: 1px solid var(--sidebar-line); border-radius: 8px; color: var(--sidebar-fg); background: var(--sidebar-hover); font-size: 1.05rem; line-height: 1; }
.sidebar-toggle:hover { background: var(--sidebar-hover); filter: brightness(.95); }
.sidebar-section { padding: 1.15rem .35rem 1rem; border-top: 1px solid color-mix(in srgb, var(--sidebar-fg) 20%, transparent); }
.section-label { display: flex; justify-content: space-between; align-items: center; color: color-mix(in srgb, var(--sidebar-fg) 82%, transparent); font-size: .77rem; font-weight: 650; letter-spacing: .12em; text-transform: uppercase; margin-bottom: .55rem; }
.section-label .icon-button { width: 25px; height: 25px; background: color-mix(in srgb, var(--sidebar-fg) 7%, transparent); border-color: color-mix(in srgb, var(--sidebar-fg) 17%, transparent); color: var(--sidebar-fg); }
.project-list, .document-list { display: grid; gap: .2rem; }
.project-item, .document-item { display: flex; align-items: center; gap: .5rem; width: 100%; border: 0; border-radius: 6px; padding: .34rem .55rem; text-align: left; color: color-mix(in srgb, var(--sidebar-fg) 80%, transparent); background: transparent; font-size: .78rem; }
.project-item:hover, .document-item:hover { background: color-mix(in srgb, var(--sidebar-fg) 8%, transparent); color: var(--sidebar-fg); }
.project-item.active, .document-item.active { background: var(--accent); color: #fff; }
.document-item { color: color-mix(in srgb, var(--sidebar-fg) 68%, transparent); font-size: .77rem; }
.document-item .file-icon { opacity: .65; }

/* A row is the name plus its delete. The delete stays out of the way until
   the row is hovered, then arms on the first click and commits on the second. */
.document-row { display: flex; align-items: center; width: 100%; border-radius: 6px; }
.document-row .document-item { flex: 1 1 auto; min-width: 0; }
.document-row .document-item span:last-child {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.document-delete {
  flex: 0 0 auto; border: 0; background: transparent; cursor: pointer;
  padding: .25rem .45rem; border-radius: 5px; font-size: .78rem; line-height: 1;
  color: color-mix(in srgb, var(--sidebar-fg) 45%, transparent);
  /* Always visible (owner, 27 Aug): a control that appears only on hover
     reads as "no way to delete" to anyone who has not discovered it. */
  opacity: .55; transition: opacity .12s ease;
}
.document-row:hover .document-delete, .document-delete:focus-visible { opacity: 1; }
.document-delete:hover { color: var(--danger); }
.document-delete.is-armed {
  opacity: 1; font-size: .77rem; font-weight: 700; color: #fff;
  background: var(--danger);
}
.muted { color: var(--muted); }
.sidebar .muted { color: color-mix(in srgb, var(--sidebar-fg) 46%, transparent); }
.empty-copy { padding: .45rem .5rem; font-size: .77rem; line-height: 1.45; }
.project-form { display: grid; gap: .55rem; }
.project-form input { padding: .55rem .6rem; font-size: .77rem; }
.project-form .button.ghost { border-color: color-mix(in srgb, var(--sidebar-fg) 34%, transparent); color: var(--sidebar-fg); background: color-mix(in srgb, var(--sidebar-fg) 8%, transparent); }
.project-form .button.ghost:hover { background: color-mix(in srgb, var(--sidebar-fg) 16%, transparent); }
.file-section { flex: 1; min-height: 140px; overflow-y: auto; overflow-x: hidden; }
.sidebar-usage { margin: .35rem; padding: .75rem; border: 1px solid var(--sidebar-line); border-radius: 8px; background: var(--sidebar-hover); }
.usage-meter-head { display: flex; align-items: center; justify-content: space-between; gap: .6rem; color: color-mix(in srgb, var(--sidebar-fg) 90%, transparent); font-size: .77rem; }
.usage-meter-head span { color: color-mix(in srgb, var(--sidebar-fg) 66%, transparent); font-variant-numeric: tabular-nums; }
.usage-meter-track { width: 100%; height: 5px; margin: .62rem 0 .55rem; overflow: hidden; border-radius: 999px; background: color-mix(in srgb, var(--sidebar-fg) 13%, transparent); }
/* STARTS EMPTY, NOT FULL. This was `width: 100%`, and the script that sets the
   real width was unreachable, so every customer saw a full bar whatever they
   had left. An unmeasured allowance must never look like a healthy one. */
.usage-meter-track span { display: block; width: 0; height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--btn-primary-start), var(--btn-primary-end)); transition: width .25s ease; }
.sidebar-usage p { margin: 0; color: color-mix(in srgb, var(--sidebar-fg) 48%, transparent); font-size: .77rem; line-height: 1.4; }
.sidebar-usage .text-button { margin-top: .45rem; padding: 0; color: color-mix(in srgb, var(--sidebar-fg) 72%, transparent); font-size: .77rem; font-weight: 700; }
.sidebar-usage .text-button:hover { color: var(--sidebar-fg); }  /* was #fff - white-on-white on today's light sidebar */
.sidebar-settings { margin: .35rem .35rem .7rem; border-top: 1px solid color-mix(in srgb, var(--sidebar-fg) 12%, transparent); padding-top: .7rem; }
.sidebar-settings summary { cursor: pointer; color: color-mix(in srgb, var(--sidebar-fg) 72%, transparent); font-size: .77rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.settings-stack { display: grid; gap: .65rem; margin-top: .7rem; }
.settings-stack label { color: color-mix(in srgb, var(--sidebar-fg) 75%, transparent); font-size: .77rem; }
.settings-stack input, .settings-stack select { width: 100%; min-width: 0; border: 1px solid color-mix(in srgb, var(--sidebar-fg) 18%, transparent); border-radius: 6px; padding: .48rem .5rem; color: var(--sidebar-fg); background: color-mix(in srgb, var(--sidebar-fg) 8%, transparent); font-size: .77rem; }
.settings-stack select option { color: var(--ink); background: #fff; }
.settings-stack .check-row { display: flex; grid-template-columns: none; align-items: center; gap: .4rem; }
.settings-stack .check-row input { width: auto; }
.settings-note { margin: 0; color: var(--muted); font-size: .77rem; line-height: 1.45; }
.sidebar .settings-note { color: color-mix(in srgb, var(--sidebar-fg) 46%, transparent); }
.sidebar-foot { display: flex; justify-content: space-between; align-items: center; padding: .85rem .35rem .1rem; border-top: 1px solid color-mix(in srgb, var(--sidebar-fg) 12%, transparent); }
.sidebar-foot .text-button { color: color-mix(in srgb, var(--sidebar-fg) 56%, transparent); }
.status-dot { display: inline-flex; align-items: center; gap: .35rem; color: color-mix(in srgb, var(--sidebar-fg) 56%, transparent); font-size: .77rem; }
.status-dot::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--danger); }
.status-dot.online::before { background: #62c58e; }

.main-shell { min-width: 0; min-height: 100vh; overflow-x: hidden; padding: 1.45rem 2.1rem 3rem; }
.subscription-test-banner { display: flex; align-items: center; justify-content: center; gap: .7rem; max-width: 1500px; margin: -.35rem auto 1rem; padding: .55rem .8rem; border: 1px solid #df6479; border-radius: 8px; color: #fff; background: #9f2441; font-size: .77rem; letter-spacing: .01em; }
.subscription-test-banner strong { font-size: .77rem; letter-spacing: .1em; }
.subscription-engine-note { padding: .55rem; border: 1px solid rgba(255,255,255,.18); border-radius: 6px; color: rgba(255,255,255,.78) !important; background: rgba(177,60,87,.22); }
.topbar { display: flex; justify-content: space-between; align-items: flex-end; gap: 1rem; max-width: 1500px; margin: 0 auto 1.2rem; }
.topbar-actions { display: flex; align-items: center; gap: .75rem; }
.download-liability { max-width: 30rem; color: var(--muted); font-size: .77rem; line-height: 1.25; text-align: right; }
.liability-notice { padding-top: .55rem; border-top: 1px solid var(--border); }
.save-state { color: var(--muted); font-size: .77rem; }
.surface-nav { display: flex; gap: .25rem; max-width: 1500px; margin: 0 auto 1.25rem; padding-bottom: .6rem; border-bottom: 1px solid var(--border); overflow-x: auto; }
.surface-tab { border: 0; border-bottom: 2px solid transparent; padding: .45rem .7rem; background: transparent; color: var(--muted); font-size: .78rem; font-weight: 550; white-space: nowrap; }
.surface-tab:hover, .surface-tab.active { color: var(--navy); border-bottom-color: var(--accent); }
.surface { min-width: 0; max-width: 1500px; margin: 0 auto; }
.empty-state { min-height: 62vh; display: grid; place-items: center; align-content: center; gap: .55rem; text-align: center; padding: 3rem; }
.empty-state h3 { margin: .2rem 0 0; font-size: 1.25rem; }
.empty-state p { max-width: 390px; margin-bottom: 1rem; color: var(--muted); line-height: 1.55; }
.empty-icon { display: grid; place-items: center; width: 54px; height: 54px; border: 1px solid var(--border); border-radius: 10px; color: var(--accent); font-size: 2rem; background: #fff; }
.document-workspace { display: grid; grid-template-columns: minmax(0, 1fr) 6px minmax(320px, var(--review-rail-width, 350px)); gap: .4rem; align-items: start; min-width: 0; }
.document-workspace.review-rail-expanded { grid-template-columns: minmax(0, 1fr) 8px minmax(300px, var(--review-rail-width, 470px)); }
/* Two columns, never `1fr 0 40px`: the resizer is `display: none` when collapsed,
   so the rail was the SECOND grid item and sat in the zero-width column with its
   reopen button clipped (17 Sep 2026 - the same fault as the writer's layout). */
.document-workspace.review-rail-collapsed { grid-template-columns: minmax(0, 1fr) 40px; gap: .25rem; }
.document-workspace.review-rail-collapsed > .review-rail { grid-column: 2; overflow: visible; }
.review-rail-resizer { position: relative; align-self: stretch; min-height: calc(100vh - 10rem); cursor: col-resize; touch-action: none; }
.review-rail-resizer::after { content: ""; position: sticky; top: 1rem; display: block; width: 2px; height: calc(100vh - 12rem); margin: 1rem auto; border-radius: 999px; background: #9ba7b7; transition: background .15s ease; }
.review-rail-resizer:hover::after, .review-rail-resizer:focus::after, .resizing-review-rail .review-rail-resizer::after { width: 4px; background: var(--accent); }
.resizing-review-rail { cursor: col-resize; user-select: none; }
.review-rail-collapsed .review-rail-resizer { display: none; }
/* THE CONTROLS SIT AT THE VERY TOP, STUCK, NO GAP (owner, 5 Sep 2026: "there's
   a gap at the top that's kinda weird... our options should be at the very top
   stuck"). The stage carries no top padding; the sticky bar is the top edge,
   opaque, and the page starts beneath it. */
.document-stage { min-width: 0; min-height: 380px; height: calc(100dvh - 8.5rem); max-height: calc(100dvh - 8.5rem); padding: 0 1.3rem 1.3rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--page-backdrop); overflow: auto; overscroll-behavior: contain; }
.document-stage.pdf-active { overflow: auto; }
.document-stage::-webkit-scrollbar { width: 10px; height: 10px; }
.document-stage::-webkit-scrollbar-track { background: transparent; }
.document-stage::-webkit-scrollbar-thumb { border: 2px solid transparent; border-radius: 999px; background: #9ba7b7; background-clip: padding-box; }
.document-controls { position: sticky; z-index: 4; top: 0; display: flex; align-items: center; gap: .35rem; min-height: 36px; margin: 0 -1.3rem .8rem; padding: .35rem 1.3rem; border: 0; border-bottom: 1px solid rgba(14,14,14,.16); border-radius: 0; background: #fff; }
.document-controls-spacer { flex: 1 1 auto; }
.document-controls .icon-button { width: 27px; height: 27px; }
.zoom-label { min-width: 38px; color: var(--navy); font-size: .77rem; font-weight: 550; text-align: center; }
.docx-preview { min-height: 0; min-width: 0; overflow: visible; }
.pdf-preview { display: grid; align-content: start; justify-items: center; gap: 1rem; width: max-content; min-width: 100%; min-height: 0; background: var(--page-backdrop); }
.pdf-page-shell { position: relative; flex: 0 0 auto; background: #fff; box-shadow: 0 2px 12px rgba(14,17,22,.12); }
.pdf-page { display: block; max-width: none; }
.textLayer { position: absolute; inset: 0; z-index: 2; overflow: hidden; opacity: 1; line-height: 1; text-align: initial; text-size-adjust: none; transform-origin: 0 0; forced-color-adjust: none; }
.textLayer :is(span, br) { position: absolute; color: transparent; white-space: pre; cursor: text; user-select: text; transform-origin: 0 0; }
.textLayer span { font-size: calc(var(--scale-factor) * var(--font-height)); transform: rotate(var(--rotate, 0deg)) scaleX(var(--scale-x, 1)); }
.textLayer span.markedContent { top: 0; height: 0; }
.textLayer ::selection { color: transparent; background: rgba(0,104,248,.26); }
.textLayer br::selection { background: transparent; }
.persistent-selection-highlight { position: absolute; z-index: 1; pointer-events: none; border-radius: 2px; background: rgba(0,104,248,.24); mix-blend-mode: multiply; }
.textLayer span.inline-document-editing { z-index: 8; min-width: 1ch; color: #111827; background: #fff; outline: 1px solid rgba(0,104,248,.65); outline-offset: 2px; caret-color: #111827; user-select: text; white-space: pre; }
.textLayer span.inline-document-saving { opacity: .55; pointer-events: none; }
/* Why Edit is off, beside the buttons that are on. */
.selection-why { flex-basis: 100%; margin-top: .3rem; color: var(--muted); font-size: .78rem; line-height: 1.4; }
.selection-toolbar { position: absolute; z-index: 12; display: flex; gap: .25rem; padding: .28rem; border: 1px solid var(--border); border-radius: 8px; background: #fff; box-shadow: var(--shadow-pop); }
.selection-toolbar .button { min-height: 27px; padding: .28rem .5rem; font-size: .77rem; }
.selection-toolbar.selection-comment-editor { display: grid; width: min(280px, calc(100% - 12px)); }
.selection-comment-editor textarea { min-height: 74px; padding: .5rem; font-size: .77rem; resize: vertical; }
.selection-comment-editor .inline-actions { justify-content: flex-end; }
.docx-preview .docx-wrapper { padding: 1rem 0 !important; background: transparent !important; }
.docx-preview .docx-page-shell { position: relative; margin: 0 auto 1rem; }
.docx-preview section.docx { box-shadow: 0 2px 12px rgba(14,17,22,.12); margin: 0 !important; transform-origin: top left; }
.docx-preview ins { background: rgba(38,115,77,.16); text-decoration: underline; text-decoration-color: var(--success); text-decoration-thickness: 2px; }
.docx-preview del { background: rgba(169,63,57,.14); text-decoration: line-through; text-decoration-color: var(--danger); }
.notice { margin-top: .8rem; padding: .7rem .8rem; border: 1px solid #e6d59b; border-radius: 8px; color: #6f5410; background: #fff9df; font-size: .77rem; line-height: 1.45; }
.review-rail { position: sticky; top: 1rem; display: flex; flex-direction: column; gap: .8rem; min-width: 0; max-width: 100%; height: calc(100vh - 10rem); max-height: calc(100vh - 10rem); min-height: 380px; overflow: hidden; padding: 1rem; border: 1px solid var(--border); border-radius: var(--radius); background: #fff; }
.review-rail-body { display: grid; grid-template-columns: minmax(0, 1fr); gap: .8rem; min-height: 0; overflow-x: hidden; overflow-y: auto; padding-right: .2rem; overscroll-behavior: contain; scrollbar-gutter: stable; }
.review-rail-body > * { min-width: 0; max-width: 100%; }
.review-detail-block { display: grid; gap: .8rem; min-width: 0; }
.review-detail-block.is-collapsed { display: none; }
.rail-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .55rem; align-items: center; flex: 0 0 auto; }
.editor-head { display: flex; justify-content: space-between; gap: .5rem; align-items: flex-start; flex: 0 0 auto; }
.rail-title { min-width: 0; }
.rail-head-actions { display: flex; align-items: center; justify-content: flex-end; gap: .35rem; flex: 0 0 auto; }
.review-rail-collapsed .review-rail { align-items: center; width: 40px; height: 40px; min-height: 40px; padding: 0; border: 0; background: transparent; }
.review-rail-collapsed .review-rail-body, .review-rail-collapsed .rail-title, .review-rail-collapsed .count-badge, .review-rail-collapsed #review-rail-expand-toggle, .review-rail-collapsed #review-details-toggle { display: none; }
.review-rail-collapsed .rail-head, .review-rail-collapsed .rail-head-actions { width: 100%; justify-content: center; }
.review-rail-collapsed #review-rail-collapse-toggle { border-color: var(--border); background: var(--surface-raised); box-shadow: var(--shadow); }
.rail-head h3 { margin-bottom: 0; font-size: .9rem; line-height: 1.15; }
/* THE CHANGES-AND-COMMENTS LIST IS A FOLD (owner, 7 Sep 2026: "remove this
   activity bar, its horrible"). It keeps every control it had - accept all,
   reject all, the change list, the version history - and opens only when he
   asks for it, so the passage tools are what greets him. */
.rail-activity-fold { min-width: 0; border-top: 1px solid var(--border); padding-top: .55rem; }
.rail-activity-fold > summary { display: flex; align-items: center; gap: .45rem; cursor: pointer; list-style: none; font-size: .78rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.rail-activity-fold > summary::-webkit-details-marker { display: none; }
.rail-activity-fold > summary::before { content: "\203a"; display: inline-block; font-size: 1rem; line-height: 1; transition: transform .12s ease; }
.rail-activity-fold[open] > summary::before { transform: rotate(90deg); }
.rail-activity-fold > summary:hover { color: var(--ink); }
.rail-activity-fold > summary .count-badge { margin-left: auto; }
.rail-activity-fold .review-detail-block { margin-top: .7rem; }
/* ONE SOURCE OF TRUTH for whether the list is shown: the fold itself. The
   `is-collapsed` class stays as the marker other code reads, but it must not
   also hide the block - a fold that opened onto `display: none` would look
   broken if the toggle event were ever missed. */
.rail-activity-fold .review-detail-block.is-collapsed { display: grid; }
.count-badge { display: inline-grid; place-items: center; min-width: 24px; height: 24px; padding: 0 .35rem; border-radius: 999px; background: var(--soft); color: var(--navy); font-size: .77rem; font-weight: 600; }
.summary-strip { display: flex; flex-wrap: wrap; gap: .45rem; min-width: 0; color: var(--muted); font-size: .77rem; }
.history-details { border-top: 1px solid var(--border); padding-top: .65rem; }
.history-details summary { cursor: pointer; color: var(--navy); font-size: .77rem; font-weight: 550; }
.history-list { display: grid; gap: .25rem; max-height: 150px; overflow: auto; margin-top: .45rem; }
.history-item { display: flex; justify-content: space-between; gap: .5rem; align-items: center; border: 0; border-radius: 6px; padding: .42rem .45rem; color: var(--muted); background: var(--soft); text-align: left; font-size: .77rem; }
.history-item:hover { color: var(--navy); background: #eaf0f4; }
.rail-actions { display: flex; flex-wrap: wrap; gap: .4rem; }
.rail-actions .button { min-width: 0; white-space: nowrap; }
.change-list { display: grid; gap: .5rem; overflow: visible; padding-right: .15rem; }
.change-card { border: 1px solid var(--border); border-left: 3px solid var(--accent); border-radius: 8px; padding: .7rem; background: #fff; }
.change-card .change-meta { display: flex; justify-content: space-between; gap: .4rem; color: var(--muted); font-size: .77rem; }
.change-card p { margin: .45rem 0; font-size: .77rem; line-height: 1.45; }
.change-card p, .change-card .change-meta { min-width: 0; overflow-wrap: anywhere; }
.change-card del { color: var(--danger); text-decoration: line-through; }
.change-card ins { color: var(--success); text-decoration: underline; }
.change-card .inline-actions { justify-content: flex-end; }
.comment-card details summary { cursor: pointer; color: var(--muted); font-size: .77rem; font-weight: 550; }
.comment-card details p { max-height: 190px; overflow: auto; padding-right: .2rem; white-space: pre-wrap; }
.comment-jump { width: 100%; border: 0; padding: 0; color: inherit; background: transparent; text-align: left; font: inherit; }
.comment-jump > span:last-child { display: block; margin-top: .35rem; color: var(--ink); line-height: 1.45; }
.comment-jump:hover > span:last-child { color: var(--accent); }
.comment-details summary, .writer-comment-item summary { cursor: pointer; list-style: none; }
.comment-details summary::-webkit-details-marker, .writer-comment-item summary::-webkit-details-marker { display: none; }
.comment-details summary::after, .writer-comment-item summary::after { content: "⌄"; float: right; color: var(--muted); font-size: .77rem; }
.comment-details[open] summary::after, .writer-comment-item[open] summary::after { content: "⌃"; }
.comment-excerpt { display: block; margin-top: .35rem; color: var(--ink); font-size: .77rem; line-height: 1.42; overflow-wrap: anywhere; }
.comment-detail-body, .writer-comment-detail { display: grid; gap: .45rem; margin-top: .55rem; padding-top: .55rem; border-top: 1px solid var(--border); }
.comment-detail-body p, .writer-comment-detail p { margin: 0; color: var(--ink); font-size: .77rem; line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere; }
.comment-inline-editor { display: grid; gap: .4rem; }
.comment-inline-editor textarea { min-height: 76px; padding: .5rem; font-size: .77rem; resize: vertical; }
.comment-inline-editor .inline-actions { justify-content: flex-end; }
.danger-action { color: var(--danger) !important; }
.selection-workbench { display: grid; gap: .6rem; padding: .75rem; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-subtle); }
.selection-workbench[hidden] { display: none; }
.selection-workbench .editor-head strong { display: block; font-size: .78rem; }
.selection-workbench textarea { min-height: 82px; max-height: 160px; resize: vertical; font-size: .77rem; }
.selection-actions, .review-quick-actions { display: flex; flex-wrap: wrap; gap: .4rem; }
/* The secondary routes - reading the wording first, typing the correction
   yourself - are links under the one button, never buttons beside it
   (owner, 7 Sep 2026: "if i highlight and press shorten i dont need to do
   anything else"). */
.selection-alt-row { display: flex; flex-wrap: wrap; gap: .8rem; margin: -.15rem 0 0; justify-content: flex-end; }
.selection-alt-row .text-button { font-size: .77rem; color: var(--muted); }
.selection-alt-row .text-button:hover:not(:disabled) { color: var(--ink); }
.selection-alt-row .text-button:disabled { opacity: .45; cursor: default; }
.selection-toolbar .selection-alt-row { justify-content: flex-end; padding: 0 .1rem .1rem; }
.selection-actions { justify-content: flex-end; }
.selection-actions .button { min-width: 104px; }
.selection-scope-note { margin: -.1rem 0 0; color: var(--muted); font-size: .77rem; line-height: 1.4; }
.review-quick-actions .button { flex: 0 1 auto; }
.comment-composer { padding-top: .55rem; border-top: 1px solid var(--border); }
.comment-composer summary { cursor: pointer; color: var(--navy); font-size: .77rem; font-weight: 550; }
.comment-composer textarea { margin-top: .55rem; }
.comment-composer .button { width: 100%; margin-top: .45rem; }
.comment-box, .edit-box { display: grid; grid-template-columns: minmax(0, 1fr); gap: .5rem; padding-top: .75rem; border-top: 1px solid var(--border); }
.comment-box { padding-top: 0; border-top: 0; }
.selected-passage-preview { max-height: 84px; overflow: auto; padding: .55rem .65rem; border: 1px solid var(--border); border-radius: 8px; color: var(--muted); background: var(--soft); font-size: .77rem; line-height: 1.45; overflow-wrap: anywhere; }
.edit-box select { width: 100%; min-width: 0; }
.comment-box .button, .edit-box .button { width: 100%; min-width: 0; white-space: nowrap; }
.comment-box label, .edit-box label { font-size: .77rem; }
.comment-box textarea { font-size: .77rem; }
.paragraph-editor { min-height: 100px; max-height: 190px; overflow: auto; font-size: .77rem; line-height: 1.5; }
.paragraph-editor:empty::before { content: attr(data-placeholder); color: #a8b0b6; }
.format-toolbar { display: flex; gap: .3rem; }
.format-toolbar button { width: 27px; height: 27px; border: 1px solid var(--border); border-radius: 6px; background: #fff; color: var(--navy); }
.format-toolbar button:hover { border-color: var(--accent); color: var(--accent); }
.tool-surface { min-height: 62vh; display: grid; place-items: start center; padding-top: 1rem; }
.tool-card { width: min(820px, 100%); padding: 1.5rem; border: 1px solid var(--border); border-radius: var(--radius); background: #fff; }
.tool-card p { line-height: 1.5; }
.tool-result { margin-top: 1.1rem; padding-top: 1rem; border-top: 1px solid var(--border); white-space: pre-wrap; line-height: 1.55; font-size: .82rem; }
.tool-result pre { white-space: pre-wrap; font: inherit; margin: 0; }
.review-report-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin-bottom: .8rem; }
.review-report-head strong { font-size: 1rem; }
.review-report-head span { color: var(--muted); font-size: .77rem; }
/* COMPACT (owner, 18 Sep 2026: "there's so much white space... not compact"):
   a slim summary row, tight body, short leading. */
.review-report-card { border: 1px solid var(--border); border-radius: 10px; background: var(--surface-raised); margin: .3rem 0; white-space: normal; }
.review-report-card summary { cursor: pointer; display: flex; align-items: center; gap: .5rem; padding: .38rem .6rem; line-height: 1.3; }
.review-report-card > div { padding: 0 .6rem .5rem; border-top: 1px solid var(--border); font-size: .82rem; line-height: 1.4; }
.review-report-card p { margin: .3rem 0 0; }
.severity { border-radius: 999px; padding: .12rem .42rem; font-size: .77rem; font-weight: 600; text-transform: uppercase; background: var(--surface-subtle); }
.severity-high, .severity-critical { color: var(--danger); }
.severity-low { color: var(--success); }
.review-report-raw { margin-top: .9rem; white-space: normal; }
.review-report-raw pre { margin-top: .55rem; padding: .8rem; border-radius: 10px; background: var(--surface-subtle); overflow: auto; white-space: pre-wrap; }
.context-card { display: grid; gap: .45rem; margin: 1rem 0; padding: .8rem .9rem; border: 1px solid var(--border); border-radius: 10px; background: var(--soft); }
.context-card-head { display: flex; align-items: center; justify-content: space-between; gap: .6rem; }
.context-card-head strong { color: var(--navy); font-size: .77rem; }
.context-badge { display: inline-flex; align-items: center; width: fit-content; padding: .24rem .45rem; border-radius: 999px; color: var(--accent-dark); background: var(--accent-soft); font-size: .77rem; font-weight: 600; white-space: nowrap; }
.feature-settings { margin: .9rem 0 1rem; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); padding: .75rem 0; }
.feature-settings summary { cursor: pointer; color: var(--navy); font-size: .77rem; font-weight: 600; }
.settings-grid { display: grid; gap: .7rem; margin-top: .75rem; }
.settings-grid label { font-size: .77rem; }
.settings-grid select, .settings-grid input, .settings-grid textarea { font-size: .77rem; }
.check-row { display: flex; grid-template-columns: none; align-items: center; gap: .45rem; }
.check-row input { width: auto; }
.mode-switch { display: flex; gap: .35rem; margin: 1rem 0 .25rem; padding: .25rem; border-radius: 8px; background: var(--soft); }
.mode-button { flex: 1; border: 1px solid transparent; border-radius: 6px; padding: .58rem .65rem; color: var(--muted); background: transparent; font-size: .77rem; font-weight: 600; }
.mode-button.active { border-color: var(--border); color: var(--navy); background: #fff; box-shadow: var(--shadow); }
.strategy-question-panel { display: grid; gap: .65rem; margin-top: .8rem; padding: .8rem; border: 1px solid #e6d59b; border-radius: 8px; color: #6f5410; background: #fff9df; font-size: .77rem; line-height: 1.45; }
.strategy-question-panel ul { margin: 0; padding-left: 1.1rem; }
/* The section plan: one row per section, read top to bottom like the report
   it describes. An unticked row stays visible and dimmed rather than
   disappearing, so removing a section is reversible at a glance. */
/* ONE place to add files, in the map header beside the zoom control. It has to
   READ as a drop target — a bordered box with a plus and two lines of text —
   or it looks like a caption and nobody drops on it. `drop-active` is the
   class the app's one drop-zone system sets. */
.project-canvas-tools { display: flex; gap: .6rem; align-items: center; }
.project-dropzone { display: flex; gap: .5rem; align-items: center; padding: .5rem .7rem; border: 1.5px dashed var(--line, #cfc8b8); border-radius: 8px; cursor: pointer; transition: border-color .12s ease, background .12s ease, color .12s ease; }
.project-dropzone:hover, .project-dropzone:focus-visible { border-color: var(--accent, #b8651a); background: rgba(184, 101, 26, .05); }
.project-dropzone.drop-active { border-color: var(--accent, #b8651a); border-style: solid; background: rgba(184, 101, 26, .1); }
.project-dropzone-icon { display: grid; place-items: center; width: 1.5rem; height: 1.5rem; border: 1.5px dashed var(--line, #cfc8b8); border-radius: 50%; font-size: .95rem; line-height: 1; }
.project-dropzone:hover .project-dropzone-icon, .project-dropzone.drop-active .project-dropzone-icon { border-color: var(--accent, #b8651a); }
.project-dropzone-text { display: grid; line-height: 1.25; }
.project-dropzone-text strong { font-size: .78rem; }
.project-dropzone-text span { font-size: .77rem; opacity: .72; }
:root[data-theme="dark"] .project-dropzone { border-color: #4a4438; }
:root[data-theme="dark"] .project-dropzone-icon { border-color: #4a4438; }
#project-dropzone-status[data-tone="error"] { color: #a8320f; }
:root[data-theme="dark"] .project-dropzone.is-over { background: rgba(184, 101, 26, .14); }
:root[data-theme="dark"] #project-dropzone-status[data-tone="error"] { color: #ff9f86; }

.strategy-plan { display: grid; gap: .5rem; }
.plan-row { display: grid; gap: .35rem; padding: .55rem .65rem; border: 1px solid #e6d59b; border-radius: 6px; background: #fffdf3; }
.plan-row-off { opacity: .45; }
.plan-row-head { display: flex; gap: .5rem; align-items: center; }
.plan-heading { flex: 1 1 auto; min-width: 0; padding: .25rem .4rem; border: 1px solid transparent; border-radius: 4px; background: transparent; color: inherit; font-weight: 600; font-size: .78rem; }
.plan-heading:hover, .plan-heading:focus { border-color: #e6d59b; background: #fff; }
.plan-chips { display: flex; flex-wrap: wrap; gap: .3rem; }
.plan-note { width: 100%; padding: .25rem .4rem; border: 1px dashed #e6d59b; border-radius: 4px; background: transparent; color: inherit; font-size: .77rem; }
.plan-controls { display: flex; flex-wrap: wrap; gap: .3rem; }
.plan-add { display: flex; gap: .4rem; align-items: center; }
.plan-add input { flex: 1 1 auto; min-width: 0; padding: .3rem .45rem; border: 1px solid #e6d59b; border-radius: 4px; background: #fff; color: inherit; font-size: .77rem; }
.strategy-question-actions { display: flex; justify-content: flex-end; margin-top: .6rem; }
:root[data-theme="dark"] .plan-row { border-color: #5c4b1d; background: #241e0f; }
:root[data-theme="dark"] .plan-heading:hover, :root[data-theme="dark"] .plan-heading:focus { border-color: #5c4b1d; background: #2c2512; }
:root[data-theme="dark"] .plan-note, :root[data-theme="dark"] .plan-add input { border-color: #5c4b1d; background: #2c2512; }
.drawing-result-image { display: block; width: 100%; max-height: 62vh; object-fit: contain; background: #f2f0eb; border: 1px solid var(--border); border-radius: 10px; margin-bottom: 1rem; }
.tool-result .drawing-review, .tool-result .drawing-questions { white-space: normal; }
.drawing-review { display: grid; gap: .9rem; }
/* COMPACT, NOT EDGE-TO-EDGE (owner, 2 Sep 2026: "1 check pass and 1
   warning as sooo far apart from each other, the tools are massively far
   apart... not corporate grade"). space-between pushed the actions to
   the far window edge on a wide screen; the cluster now sits directly
   after the title block with a fixed gap, so the whole header reads as
   one bounded strip whatever the window width. */
.drawing-review-summary, .drawing-sheet-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1.4rem; flex-wrap: wrap; }
/* The title block keeps a readable floor and the buttons wrap UNDER it —
   before this, .drawing-actions was flex:0 0 auto and refused to shrink,
   so narrowing the window crushed "15 findings across 1 sheet" into a
   one-word-per-line sliver (owner's screenshot, 2 Sep 2026). */
.drawing-review-summary > div:first-child,
.drawing-sheet-head > div:first-child { flex: 0 1 auto; min-width: 240px; }
.drawing-review-summary h2, .drawing-sheet-head h3 { margin: .15rem 0 .35rem; }
.drawing-review-summary p { margin: 0; color: var(--muted); }
.drawing-actions { display: flex; flex-wrap: wrap; gap: .45rem; flex: 0 0 auto; margin-left: auto; justify-content: flex-end; align-items: center; min-width: 0; }
/* Inside a sheet card the Download menu sits at the card's right edge —
   floating beside "Page 1" read as misplaced (owner, 2 Sep 2026: "the
   download button is awkwardly positioned there"). */
.drawing-sheet-head .drawing-actions,
.drawing-sheet-head .download-menu { margin-left: auto; }
.drawing-actions .download-liability { flex: 1 1 100%; min-width: 0; }
.drawing-sheet .trust-panel { margin: .15rem 0 .5rem; }
.drawing-sheet, .drawing-cross-sheet { padding: 1rem; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); }
.drawing-overview { margin: 0 0 1rem; padding: .75rem .85rem; border-left: 3px solid var(--accent); border-radius: 4px; background: var(--soft); }
.drawing-findings { display: grid; gap: .45rem; }
.drawing-findings > h3, .drawing-cross-sheet > h3 { margin: .2rem 0; }
/* COMPACT CARDS (owner, 2 Sep 2026: "the comments are still massive").
   Tighter padding, smaller type, less air between lines. */
.drawing-finding { padding: .55rem .65rem; border: 1px solid var(--border); border-radius: 9px; background: var(--background); }
.drawing-finding header { display: flex; gap: .55rem; align-items: flex-start; }
.drawing-finding h4 { margin: .1rem 0 .2rem; font-size: .82rem; }
.drawing-finding p { margin: .3rem 0 0; line-height: 1.45; font-size: .78rem; }
.drawing-marker { display: inline-grid; place-items: center; min-width: 1.75rem; height: 1.75rem; padding: 0 .3rem; border-radius: 50%; color: #fff; background: var(--accent); font-weight: 600; }
.drawing-guidance, .drawing-support { margin-top: .75rem; }
.drawing-guidance summary, .drawing-support summary { cursor: pointer; font-weight: 700; color: var(--accent); }
.drawing-guidance-page { margin-top: .65rem; }
.drawing-guidance-image img { display: block; width: 100%; max-height: 70vh; object-fit: contain; margin-top: .65rem; border: 1px solid var(--border); border-radius: 8px; background: #fff; }
.drawing-support pre { margin-top: .65rem; padding: .75rem; max-height: 22rem; overflow: auto; border-radius: 8px; background: var(--soft); white-space: pre-wrap; }
.drawing-questions { display: grid; gap: .85rem; padding: 1rem; border: 1px solid #e6d59b; border-radius: 10px; background: #fff9df; color: #5e470c; }
.drawing-questions h3, .drawing-questions p { margin: 0; }
.drawing-question { display: grid; gap: .4rem; }
.drawing-question select, .drawing-question input { width: 100%; }
@media (max-width: 720px) {
  .drawing-review-summary, .drawing-sheet-head { display: grid; }
}
.writer-surface { place-items: stretch; padding-top: 0; }
/* The Write feature sat at the full 1500px surface while every other
   feature is a .tool-card at min(820px, 100%), so the same layout looked
   like a different one. It matches them now, and widens ONLY while a
   document is open - the two-pane editing layout needs a readable page
   beside a 300px rail, which does not fit in 820px. */
.writer-shell { container: writer / inline-size; display: grid; gap: 1rem; width: min(820px, 100%); margin: 0 auto; min-width: 0; max-width: none; padding: 0; border: 0; background: transparent; }
.writer-shell > * { min-width: 0; }
.writer-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; padding: 1rem 1.1rem; border: 1px solid var(--border); border-radius: var(--radius); background: #fff; }
.writer-header > div:first-child { min-width: 0; }
.writer-header .mode-switch { flex: 0 0 auto; width: min(360px, 42%); max-width: 100%; margin: 0; }
.writer-document-context { display: flex; align-items: center; justify-content: space-between; gap: .8rem; margin: 0 0 .75rem; padding: .7rem .85rem; border: 1px solid var(--border); border-radius: 10px; background: #fff; }
.writer-document-context strong { display: block; max-width: 100%; overflow: hidden; color: var(--navy); font-size: .8rem; text-overflow: ellipsis; white-space: nowrap; }
.writer-document-context .eyebrow { margin-bottom: .2rem; font-size: .77rem; }
.writer-document-context .settings-note { margin: .25rem 0 0; color: var(--muted); }
.fidelity-badge { display: inline-flex; align-items: center; padding: .28rem .5rem; border-radius: 999px; color: var(--success); background: #ecf8f2; font-size: .77rem; font-weight: 600; white-space: nowrap; }
.writer-shell:has(#writer-edit-panel:not([hidden])) { width: min(1400px, 100%); }
.writer-edit-layout { display: grid; grid-template-columns: minmax(460px, 1fr) 6px minmax(300px, var(--writer-rail-width, 360px)); gap: .4rem; align-items: start; }
/* NO VOID WHERE THE TOOLS ARE NOT (owner, 14 Sep 2026: "there is still plenty
   of empty white margin"). The third track is sized for the passage tools. If
   they are not in it, the engineer met 360 px of nothing beside his report,
   and the report was squeezed to pay for it. The page takes the width back. */
.writer-edit-layout:has(> #writer-rail-mount[hidden]):has(> .writer-command-pane[hidden]) {
  grid-template-columns: minmax(0, 1fr); }
.writer-edit-layout:has(> #writer-rail-mount[hidden]):has(> .writer-command-pane[hidden]) > .writer-rail-resizer { display: none; }
/* THE WAY BACK GETS A COLUMN OF ITS OWN (owner, 17 Sep 2026: "when I minimise
   the side panel there's no way to bring it back"). The collapsed grid was
   `1fr 0 34px` for [page][resizer][old pane]. The passage tools now live in
   `#writer-rail-mount`, and with the resizer gone the mount fell into the
   ZERO-width column: the reopen button was there, 28 px wide, inside a box
   0 px wide with its overflow hidden. Two columns, and the last one is the
   button's. */
.writer-edit-layout.writer-rail-collapsed { grid-template-columns: minmax(0, 1fr) 40px; gap: .25rem; }
.writer-edit-layout.writer-rail-collapsed > .writer-rail-mount,
.writer-edit-layout.writer-rail-collapsed > .writer-command-pane { grid-column: 2; }
.writer-rail-mount.review-rail-collapsed { width: 40px; min-width: 40px; }
.writer-rail-mount.review-rail-collapsed .review-rail { overflow: visible; }
.writer-preview-pane, .writer-command-pane { min-width: 0; }
.writer-preview-pane { display: grid; gap: .55rem; min-width: 0; }
.writer-pane-head { display: flex; align-items: flex-start; justify-content: space-between; gap: .7rem; }
.writer-pane-head strong { display: block; color: var(--navy); font-size: .8rem; }
/* THE PAGE GETS THE SCREEN (owner, 13 Sep 2026, with a screenshot: *"there's
   so much empty space... I want the document editing area to be as big as
   possible. At the top and at the bottom and on the sides when you maximise.
   So try to find ways to make the document area as big as possible."*).
   It was `clamp(480px, 100dvh - 17rem, 780px)`: 17rem of reserved chrome and
   a hard 780px ceiling, so on his 1080px screen the pages stopped well short
   of the window and the space below them was empty. The reserve is now the
   chrome that is really above it, and there is no ceiling - a taller window
   is a taller page, which is the whole point of maximising one. */
.writer-document-stage { height: calc(100dvh - 9.5rem); max-height: none; min-height: 480px; padding: .8rem .8rem .4rem; scrollbar-color: #9ba7b7 transparent; }
/* The tools beside it grow with it, or the panel ends halfway down a page. */
.writer-command-pane { max-height: calc(100dvh - 11.5rem); }
/* THE ZOOM BAR SITS AT THE VERY TOP (owner, 12 Sep 2026: "the fit width, it's
   not even at the very top. There's a gap now apart... it should be at the
   very top"). The bar is `position: sticky; top: 0`, and a sticky element
   inside a padded scroll container sticks at the PADDING edge - so the
   stage's own .8rem of top padding stayed above it as a strip of page
   backdrop. The stage no longer pads its top; the bar's negative inline
   margins take it to both edges, and the padding it removed is put back
   under the bar so the first page is not against it. */
.writer-document-stage { padding-top: 0; }
.writer-document-stage .document-controls {
  margin: 0 -.8rem .55rem; padding-inline: .8rem;
}
.document-stage { padding-top: 0; }
.writer-rail-resizer { position: relative; align-self: stretch; min-height: 480px; cursor: col-resize; touch-action: none; }
.writer-rail-resizer::before { content: ""; position: absolute; inset: 0 2px; border-radius: 999px; background: #9ba7b7; transition: background .15s ease; }
.writer-rail-resizer:hover::before, .writer-rail-resizer:focus::before, .resizing-writer-rail .writer-rail-resizer::before { background: var(--accent); }
.writer-rail-resizer span { position: sticky; z-index: 1; top: 50%; display: grid; place-items: center; width: 10px; height: 22px; margin-left: -2px; border: 1px solid var(--border); border-radius: 999px; color: var(--muted); background: #fff; font-size: .77rem; }
.writer-rail-collapsed .writer-rail-resizer { display: none; }
.writer-rail-collapsed .writer-command-pane { width: 34px; height: 40px; min-height: 40px; padding: 0; overflow: hidden; border: 0; background: transparent; }
.writer-rail-collapsed .writer-command-pane > :not(.writer-command-head) { display: none; }
/* AND THE WAY BACK MUST STAY ON SCREEN (owner, 13 Sep 2026: *"if you minimise
   the right side panel on the editor, then there's no way to bring it back,
   which is super annoying"*). The collapsed pane is 34px wide with
   `overflow: hidden`, and the head it keeps holds a title, a status badge and
   THEN the toggle - so the one control that reopens the panel was pushed out
   of the box and clipped. Collapsed, the head is the button and nothing else. */
.writer-rail-collapsed .writer-command-head { display: block; padding: 0; border: 0; }
.writer-rail-collapsed .writer-command-head > :not(.writer-command-actions) { display: none; }
.writer-rail-collapsed .writer-command-actions > :not(#writer-rail-collapse-toggle) { display: none; }
.writer-rail-collapsed #writer-rail-collapse-toggle {
  display: grid; place-items: center; width: 34px; height: 40px;
  border: 1px solid var(--border); border-radius: 6px; background: var(--surface);
}
.writer-rail-collapsed #writer-rail-collapse-toggle:hover { border-color: var(--ink); }
/* The review rail, docked beside the writer or on its own surface, has the
   same shape and the same fault: its head is `.rail-head`, with the title
   first and the toggle last. */
.review-rail-collapsed .rail-head { display: block; padding: 0; border: 0; }
.review-rail-collapsed .rail-head > :not(.rail-head-actions) { display: none; }
.review-rail-collapsed .rail-head-actions > :not(#review-rail-collapse-toggle) { display: none; }
.review-rail-collapsed #review-rail-collapse-toggle {
  display: grid; place-items: center; width: 34px; height: 40px;
  border: 1px solid var(--border); border-radius: 6px; background: var(--surface);
}
.writer-rail-collapsed .writer-command-head { display: flex; justify-content: center; width: 34px; padding: 0; border: 0; }
.writer-rail-collapsed .writer-command-head > div:first-child, .writer-rail-collapsed .writer-command-head .context-badge { display: none; }
.writer-command-actions { display: flex; align-items: center; gap: .35rem; }
.writer-command-pane { position: sticky; top: .75rem; display: flex; flex-direction: column; gap: .6rem; height: clamp(480px, calc(100dvh - 17rem), 780px); min-height: 480px; overflow-x: hidden; overflow-y: auto; padding: .8rem; border: 1px solid var(--border); border-radius: 10px; background: #fff; scrollbar-gutter: stable; }
.writer-command-head { display: flex; align-items: flex-start; justify-content: space-between; gap: .65rem; padding-bottom: .65rem; border-bottom: 1px solid var(--border); }
.writer-command-head strong { display: block; color: var(--navy); font-size: .8rem; }
.writer-selection-text { min-height: 46px; max-height: 112px; overflow: auto; padding: .55rem .6rem; border: 1px solid var(--border); border-radius: 8px; color: var(--ink); background: #f8faff; font-size: .77rem; line-height: 1.45; white-space: pre-wrap; overflow-wrap: anywhere; scrollbar-gutter: stable; }
.writer-quick-actions { display: flex; flex-wrap: wrap; gap: .35rem; }
.writer-quick-actions .button { flex: 0 1 auto; }
.writer-comment-composer { display: grid; gap: .4rem; padding: .55rem; border: 1px solid var(--border); border-radius: 8px; background: var(--surface-subtle); }
.writer-comment-composer textarea { min-height: 66px; padding: .55rem; font-size: .77rem; }
.writer-comment-composer .inline-actions { justify-content: flex-end; }
.writer-composer { flex: 0 0 auto; }
.writer-composer > textarea { min-height: 94px; padding: .78rem; font-size: .77rem; }
.writer-composer .composer-footer { align-items: flex-end; padding: .45rem .5rem; }
.writer-composer .composer-submit { width: auto; min-width: 82px; min-height: 30px; padding: .35rem .65rem; border-radius: 8px; font-size: .77rem; }
.writer-composer .selection-actions .button { min-width: 68px; }
.writer-suggestion { display: grid; gap: .35rem; padding: .75rem; border: 1px solid var(--border); border-radius: 8px; color: var(--ink); background: var(--surface-subtle); font-size: .77rem; line-height: 1.45; }
.writer-suggestion p { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.writer-suggestion textarea { width: 100%; min-height: 4.5rem; max-height: 12rem; resize: vertical; font: inherit; line-height: 1.45; }
.suggestion-actions { display: flex; flex-wrap: wrap; gap: .45rem; align-items: center; }
.apply-suggestion { align-self: flex-start; width: auto; }
.writer-comments { display: grid; gap: .45rem; padding-top: .6rem; border-top: 1px solid var(--border); }
.writer-comments-head { display: flex; align-items: center; justify-content: space-between; }
.writer-comments-head strong { color: var(--navy); font-size: .77rem; }
.writer-comment-list { display: grid; gap: .4rem; }
.writer-comment-item { width: 100%; padding: .5rem .55rem; border: 1px solid var(--border); border-radius: 6px; color: var(--ink); background: var(--surface-subtle); text-align: left; font-size: .77rem; line-height: 1.4; }
.writer-comment-item summary strong, .writer-comment-item summary span { display: block; padding-right: 1rem; }
.writer-comment-item summary span { margin-top: .25rem; color: var(--muted); }
.writer-comment-item:hover { border-color: var(--accent); background: var(--soft); }
.generate-panel { width: min(900px, 100%); margin: 0 auto; padding: 1.2rem; border: 1px solid var(--border); border-radius: var(--radius); background: #fff; }
.generate-panel .task-composer { margin-top: 1rem; }

/* 819, NOT 820. The writer shell is `width: min(820px, 100%)`, so outside
   edit mode its container is EXACTLY 820px - and a `max-width: 820px`
   container query matches its own boundary. One pixel of arithmetic decided
   whether the passage tools had a column or were stacked off the bottom of
   the page. */
@container writer (max-width: 819px) {
  .writer-header { align-items: stretch; flex-direction: column; }
  .writer-header .mode-switch { width: 100%; }
  .writer-edit-layout { grid-template-columns: minmax(0, 1fr); }
  .writer-rail-resizer { display: none; }
  .writer-document-stage { height: 62vh; min-height: 500px; }
  .writer-command-pane { position: static; height: auto; min-height: 0; max-height: none; }
}
.citation { display: inline-block; margin: .35rem .35rem 0 0; padding: .22rem .4rem; border-radius: 999px; color: var(--navy); background: #eef2f5; font-size: .77rem; }

.feature-card { display: grid; gap: 1.1rem; }
.feature-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; }
.feature-card-head h3, .writer-header h3 { margin-bottom: .35rem; font-size: 1.16rem; }
.feature-card-head p, .writer-header p { max-width: 650px; margin-bottom: 0; }
.document-context-strip { display: flex; align-items: center; gap: .5rem; min-width: 0; padding: .7rem .8rem; border: 1px solid var(--border); border-radius: 8px; color: var(--muted); background: var(--soft); font-size: .77rem; }
.document-context-strip strong { min-width: 0; overflow: hidden; color: var(--navy); text-overflow: ellipsis; white-space: nowrap; }
.context-status { margin: -.35rem 0 0; color: var(--muted); font-size: .77rem; line-height: 1.45; }
.task-composer { overflow: visible; border: 1px solid var(--border); border-radius: 8px; background: #fff; transition: border-color .16s ease, box-shadow .16s ease; }
.task-composer:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(0,104,248,.13); }
.task-composer > textarea { display: block; min-height: 132px; border: 0; border-radius: 8px 13px 0 0; padding: 1rem; resize: vertical; box-shadow: none; }
.task-composer > textarea:focus { border-color: transparent; box-shadow: none; }
.composer-footer { display: flex; align-items: center; justify-content: space-between; gap: .75rem; min-height: 54px; padding: .55rem .65rem; border-top: 1px solid var(--border); background: #fafbfe; border-radius: 0 0 13px 13px; }
.composer-options { display: flex; align-items: center; flex-wrap: wrap; gap: .4rem; min-width: 0; }
.option-pill, .select-pill, .compact-options > summary { display: inline-flex; grid-template-columns: none; align-items: center; gap: .38rem; min-height: 32px; width: auto; border: 1px solid var(--border); border-radius: 999px; padding: .32rem .58rem; color: var(--muted); background: #fff; font-size: .77rem; font-weight: 700; white-space: nowrap; }
.option-pill:has(input:checked) { border-color: var(--accent); color: var(--accent-dark); background: var(--accent-soft); }
.option-pill input { width: auto; margin: 0; }
.select-pill select { width: auto; min-width: 0; border: 0; padding: 0 1.05rem 0 0; color: var(--ink); background: transparent; font-size: .77rem; box-shadow: none; }
.compact-options { position: relative; }
.compact-options > summary { cursor: pointer; list-style: none; }
.compact-options > summary::-webkit-details-marker { display: none; }
.compact-options > summary::after { content: "⌄"; color: var(--muted); font-size: .8rem; }
.compact-options[open] > summary { border-color: var(--accent); color: var(--accent-dark); background: var(--accent-soft); }
.compact-options-menu { position: absolute; z-index: 12; left: 0; bottom: calc(100% + .45rem); display: grid; gap: .65rem; width: max-content; min-width: 230px; max-width: 320px; padding: .8rem; border: 1px solid var(--border); border-radius: 10px; background: #fff; box-shadow: var(--shadow-pop); }
.compact-options-menu label { font-size: .77rem; }
.composer-submit { min-width: 112px; border-radius: 999px; }
.upload-zone { display: grid; gap: .65rem; padding: 1.15rem; border: 1px dashed var(--border); border-radius: 10px; background: var(--soft); }
.upload-zone label { gap: .2rem; cursor: pointer; }
.upload-zone label strong { color: var(--navy); }
.upload-zone label span { color: var(--muted); font-size: .77rem; font-weight: 500; }
.upload-zone input { padding: .55rem; background: #fff; font-size: .77rem; }
.compact-composer > textarea { min-height: 100px; }

:root[data-theme="dark"] {
  color-scheme: dark;
  /* Neutral near-black, not navy. The light theme's ground is a true white,
     so a blue-cast dark theme read as a different product rather than the
     same one after dark. */
  --sidebar-bg: #0e1116;
  --sidebar-fg: #e8eaee;
  --sidebar-line: color-mix(in srgb, var(--sidebar-fg) 13%, transparent);
  --sidebar-hover: color-mix(in srgb, var(--sidebar-fg) 8%, transparent);
  --navy: #e8eaee;
  --navy-2: #b9c0cc;
  /* #0068f8 is too dark to read on a near-black ground, so the accent lifts
     rather than being reused verbatim. Same hue, more light. */
  --accent: #5a9dff;
  --accent-dark: #4a8bf0;
  --ink: #e8eaee;
  --muted: #8d96a6;
  --soft: #161a21;
  --surface: #14181f;
  --border: #272d38;
  --success: #4bbd8a;
  --danger: #ff8a7a;
  --warning: #e0a253;
  --accent-soft: #11233d;
  --page-backdrop: #1b2029;
  --main-bg: #0b0e13;
  --surface-raised: #14181f;
  --surface-subtle: #11151b;
  --control-bg: #11151b;
  --shadow: 0 1px 2px rgba(0,0,0,.4);
  --shadow-pop: 0 8px 24px rgba(0,0,0,.5);
  --btn-primary-start: var(--accent);
  --btn-primary-end: color-mix(in srgb, var(--accent) 72%, #fff);
}
:root[data-theme="dark"] .auth-view { background: radial-gradient(circle at 20% 10%, #161b24 0, var(--main-bg) 52%); }
:root[data-theme="dark"] .auth-notice { color: #cfe0ff; border-color: #24406b; background: #101b2e; }

:root[data-theme="dark"] .brand-mark { color: #fff; background: var(--accent); }
:root[data-theme="dark"] .button.secondary { color: var(--main-bg); background: var(--ink); }
:root[data-theme="dark"] :is(.auth-card, .tool-card, .writer-header, .writer-document-context, .writer-command-pane, .generate-panel, .review-rail, .task-composer, .mode-button.active, .icon-button, .option-pill, .select-pill, .compact-options > summary, .compact-options-menu, .upload-zone input, input, textarea, select, .paragraph-editor) { color: var(--ink); border-color: var(--border); background: var(--surface-raised); }
:root[data-theme="dark"] :is(.change-card, .history-item, .empty-icon, .format-toolbar button, .citation) { color: var(--ink); border-color: var(--border); background: var(--surface-subtle); }
:root[data-theme="dark"] :is(.change-card p, .change-card .change-meta, .history-item, .selected-passage-preview) { color: var(--muted); }
:root[data-theme="dark"] .history-item:hover { color: var(--ink); background: #1b212b; }
:root[data-theme="dark"] :is(.composer-footer, .document-controls) { border-color: var(--border); background: rgba(14,23,40,.94); }
:root[data-theme="dark"] :is(.context-badge, .writer-suggestion) { color: var(--navy-2); background: var(--accent-soft); }
:root[data-theme="dark"] .writer-selection-text { color: var(--ink); border-color: #2b3646; background: #131922; }
:root[data-theme="dark"] .fidelity-badge { color: var(--success); background: #0f241d; }
:root[data-theme="dark"] .strategy-question-panel { color: #f0cf75; border-color: #5c4b1d; background: #2c2512; }
:root[data-theme="dark"] .drawing-questions { color: #f0cf75; border-color: #5c4b1d; background: #2c2512; }
:root[data-theme="dark"] .notice { color: #f0cf75; border-color: #5c4b1d; background: #2c2512; }
:root[data-theme="dark"] .button.ghost { color: var(--ink); background: transparent; }
:root[data-theme="dark"] .button.ghost:hover { background: #1a2740; }
:root[data-theme="dark"] .selection-toolbar { color: var(--ink); border-color: var(--border); background: var(--surface-raised); }
:root[data-theme="dark"] .selection-toolbar .button.ghost { color: var(--ink); border-color: var(--border); background: var(--surface-subtle); }
:root[data-theme="dark"] .selection-toolbar .button.ghost:hover { background: #263758; }
:root[data-theme="dark"] .settings-stack select option { color: var(--ink); background: var(--surface-raised); }
:root[data-theme="dark"] .pdf-page-shell { background: #fff; }
:root[data-theme="dark"] .theme-toggle { min-width: 86px; }

.admin-grid { display: grid; gap: 1rem; }
.admin-settings { display: grid; grid-template-columns: repeat(2, minmax(220px, 1fr)); gap: .9rem 1.2rem; align-items: end; }
.admin-settings .settings-note { grid-column: 1 / -1; margin: 0; }
.admin-columns { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr); gap: 1rem; margin-top: 1rem; }
.admin-columns h4 { margin: 0 0 .6rem; }
.admin-list { display: grid; gap: .65rem; max-height: 440px; overflow: auto; }
.admin-card { padding: .8rem; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-subtle); }
.admin-card p { margin: .35rem 0; color: var(--muted); white-space: pre-wrap; overflow-wrap: anywhere; }
.admin-card .change-meta { display: flex; justify-content: space-between; gap: .6rem; }
.admin-card .inline-actions { margin-top: .65rem; }
.safety-flag { display: inline-block; margin: .15rem .2rem 0 0; padding: .12rem .38rem; border-radius: 999px; background: var(--accent-soft); color: var(--navy-2); font-size: .77rem; }

/* THE OWNER'S OPERATING SCREENS. A customer list and a job list are read across,
   not down a column, so they span the whole two-column admin grid. */
.admin-settings .platform-block { grid-column: 1 / -1; display: grid; gap: .55rem; }
.admin-settings .platform-block h4 { margin: .4rem 0 0; }
.platform-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
.platform-toolbar .settings-note { flex: 1 1 auto; min-width: 0; }
.platform-filter { display: inline-flex; align-items: center; gap: .4rem; color: var(--muted); font-size: .77rem; }
.platform-filter select { width: auto; }
/* The list rows. `.admin-card` already draws the box; these add the facts row
   and the state stripe. */
.platform-facts { display: flex; flex-wrap: wrap; gap: .2rem .75rem; margin: .35rem 0 0; color: var(--muted); font-size: .77rem; }
.platform-facts b { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
.platform-tag { display: inline-flex; align-items: center; padding: .1rem .4rem; border-radius: 999px; background: var(--accent-soft); color: var(--navy-2); font-size: .77rem; font-weight: 600; white-space: nowrap; }
.platform-tag.is-suspended { background: color-mix(in srgb, var(--danger) 16%, transparent); color: var(--danger); }
.platform-tag.is-failed { background: color-mix(in srgb, var(--danger) 16%, transparent); color: var(--danger); }
.platform-tag.is-running { background: color-mix(in srgb, var(--warning) 18%, transparent); color: var(--warning); }
/* A SUSPENDED WORKSPACE MUST BE OBVIOUS AT A GLANCE. It is the one state the
   owner scans this list for, and a row that reads like every other row hides it. */
.admin-card.is-suspended { border-color: var(--danger); border-left-width: 4px; background: color-mix(in srgb, var(--danger) 7%, var(--surface-subtle)); }
.admin-card.is-suspended .change-meta strong { color: var(--danger); }
.platform-error { color: var(--danger); }
.platform-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: .75rem; margin: 14px 0 10px; }
.platform-form label { display: grid; gap: .3rem; color: var(--muted); font-size: .77rem; }
.platform-form select, .platform-form input { border: 1px solid var(--border); border-radius: 6px; padding: .4rem .5rem; color: var(--ink); background: var(--control-bg); }
.platform-reason { display: grid; gap: .3rem; margin: 12px 0 4px; color: var(--muted); font-size: .77rem; }
.platform-reason textarea { border: 1px solid var(--border); border-radius: 6px; padding: .45rem .5rem; color: var(--ink); background: var(--control-bg); font: inherit; font-size: .8rem; }
.platform-table { display: grid; gap: .3rem; margin: 0 0 14px; font-size: .77rem; font-variant-numeric: tabular-nums; }
.platform-table .platform-row { display: flex; justify-content: space-between; gap: .8rem; padding: .28rem 0; border-bottom: 1px solid var(--border); }
.platform-table .platform-row span:last-child { color: var(--ink); font-weight: 600; white-space: nowrap; }

/* THE OWNER'S PRICE AND ALLOWANCE. The catalogue price sits beside the override
   on every row, so a changed price is always readable against what it was.
   `.pricing-apply` is drawn apart from Save on purpose: it is the only control
   that reduces what a customer who has already paid may spend. */
.pricing-table { display: grid; gap: .2rem; margin: .2rem 0 .4rem; }
.pricing-row {
  display: grid; grid-template-columns: minmax(72px, .6fr) minmax(96px, .8fr) auto minmax(150px, 1.4fr);
  gap: .4rem .8rem; align-items: center; padding: .34rem 0;
  border-bottom: 1px solid var(--border); color: var(--muted);
  font-size: .77rem; font-variant-numeric: tabular-nums;
}
.pricing-row strong { color: var(--ink); text-transform: capitalize; }
.pricing-row label { display: inline-flex; align-items: center; gap: .3rem; }
.pricing-row input { width: 6.2rem; border: 1px solid var(--border); border-radius: 6px; padding: .28rem .4rem; color: var(--ink); background: var(--control-bg); }
.pricing-apply { margin-top: .5rem; padding: .6rem .7rem; border: 1px dashed var(--danger); border-radius: 8px; }
.pricing-apply .settings-note { margin-bottom: .5rem; }

/* THE CUSTOMER'S OWN DATA CONTROLS. Read across the whole firm-settings grid:
   an export, a grace window, and the one irreversible button in the product.

   NOTE WHAT IS NOT HERE. The two owner-gated blocks below carry
   `data-owner-only` and are `hidden` as authored, so neither may be given a
   display declaration: it outweighs the browser's own rule for a hidden
   element and would draw the delete control for every member of the firm. The
   same trap is written up over the operator's dialog wrapper further down.

   And do not name that wrapper's id in a comment here. The guard over it reads
   the raw stylesheet, so a selector id mentioned in prose immediately above an
   unrelated rule is read as a rule ON it. That cost one failing run. */
.admin-settings .data-block { grid-column: 1 / -1; display: grid; gap: .55rem; }
.admin-settings .data-block h4 { margin: .4rem 0 0; }
.admin-settings .data-block input[type="number"] { width: 8rem; }
.admin-settings .data-block .inline-actions { align-items: center; }
#data-delete-block {
  gap: .5rem; margin-top: .3rem; padding: .75rem .85rem;
  border: 1px solid var(--danger); border-radius: 10px;
  background: color-mix(in srgb, var(--danger) 6%, transparent);
}
#data-delete-block h4 { margin: 0 0 .35rem; color: var(--danger); }
.data-delete-list { margin: .1rem 0 .7rem 1.1rem; padding: 0; color: var(--muted); font-size: .77rem; line-height: 1.5; }
.data-delete-list li { margin: .12rem 0; }
.data-receipt-table { display: grid; gap: .3rem; margin: 0 0 14px; font-size: .77rem; font-variant-numeric: tabular-nums; }
.data-receipt-row { display: flex; justify-content: space-between; gap: .8rem; padding: .28rem 0; border-bottom: 1px solid var(--border); }
.data-receipt-row span:last-child { color: var(--ink); font-weight: 600; white-space: nowrap; }

@media (max-width: 1000px) {
  #workspace-view { grid-template-columns: 220px minmax(0, 1fr) var(--rail-width, 0px); }
  .main-shell { padding: 1.2rem 1.1rem 2rem; }
  .document-workspace, .document-workspace.review-rail-expanded, .document-workspace.review-rail-collapsed { grid-template-columns: minmax(0, 1fr); }
  .review-rail-resizer { display: none; }
  .document-stage, .review-rail { height: 60vh; max-height: 60vh; }
  .review-rail { position: static; }
  .review-rail-collapsed .review-rail { height: auto; min-height: 0; }
  .review-rail-collapsed .review-rail-body { display: none; }
  .writer-header { align-items: stretch; flex-direction: column; }
  .writer-header .mode-switch { width: 100%; }
  .writer-edit-layout { grid-template-columns: minmax(0, 1fr); }
  .writer-document-stage { height: 60vh; max-height: 60vh; }
  .admin-columns, .admin-settings { grid-template-columns: 1fr; }
}

/* EVERY grid variant carries the rail column - a two-column override
   wrapped the right panel to a second row, which is the "chat drags to
   the bottom of the main central panel" bug (owner, 2 Sep 2026). */
#workspace-view.sidebar-collapsed { grid-template-columns: 58px minmax(0, 1fr) var(--rail-width, 0px); }
#workspace-view.sidebar-collapsed .sidebar { padding-left: .45rem; padding-right: .45rem; }
#workspace-view.sidebar-collapsed .sidebar-head { justify-content: center; padding-left: 0; padding-right: 0; }
#workspace-view.sidebar-collapsed .sidebar-head > div:not(.brand-mark):not(.brand-logo-small),
#workspace-view.sidebar-collapsed .sidebar-section,
#workspace-view.sidebar-collapsed .sidebar-settings,
/* The usage panel was NOT in this list, so at 58px wide its words wrapped one
   letter per line and the rail became a column of stacked characters. A
   collapsed rail shows icons, never text. */
#workspace-view.sidebar-collapsed .sidebar-usage,
#workspace-view.sidebar-collapsed .sidebar-foot > :not(.status-dot) { display: none; }
/* Belt and braces: anything that slips through must not be rendered as a
   letter-per-line column. Whatever is left is clipped, not squeezed. */
#workspace-view.sidebar-collapsed .sidebar { overflow-x: hidden; }
#workspace-view.sidebar-collapsed .sidebar * { white-space: nowrap; }
/* Head: logo and toggle share the row, both squared, evenly spaced. */
#workspace-view.sidebar-collapsed .sidebar-head {
  display: flex; flex-direction: column; align-items: center; gap: .5rem;
}
#workspace-view.sidebar-collapsed .sidebar-toggle { margin-left: 0; }
#workspace-view.sidebar-collapsed .sidebar-foot { justify-content: center; padding-left: 0; padding-right: 0; border-top: 0; }
#workspace-view.sidebar-collapsed .sidebar-foot .status-dot { width: 8px; overflow: hidden; white-space: nowrap; color: transparent; }

@media (max-width: 680px) {
  #workspace-view { display: block; }
  .sidebar { min-height: 0; height: auto; }
  .file-section { max-height: 180px; }
  .sidebar-foot { margin-top: .5rem; }
  .topbar { align-items: flex-start; flex-direction: column; }
  .topbar-actions { width: 100%; justify-content: space-between; }
  .document-stage { padding: .5rem; }
  .document-stage, .review-rail { height: 62vh; max-height: 62vh; }
  .writer-document-context { align-items: flex-start; flex-direction: column; }
  .document-controls { justify-content: center; }
  .composer-footer { align-items: stretch; flex-direction: column; }
  .composer-submit { width: 100%; }
  .compact-options-menu { right: 0; left: auto; max-width: min(300px, 80vw); }
  .auth-card { padding: 1.5rem; }
}

.local-email-preview {
  margin-top: 18px;
  padding: 16px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface-subtle);
}
.local-email-preview strong,
.local-email-preview p { display: block; margin: 6px 0 12px; }
.local-email-preview .button { width: 100%; text-align: center; }

[data-upgrade-required].is-locked { opacity: .72; }
.surface-tab.is-locked::after {
  content: ""; display: inline-block; width: .82em; height: .82em;
  margin-left: .38em; vertical-align: -.08em; background: currentColor;
  -webkit-mask: var(--icon-lock) center / contain no-repeat;
  mask: var(--icon-lock) center / contain no-repeat;
}
.locked-copy { color: var(--muted); font-size: .78rem; line-height: 1.45; margin: 8px 4px; }

.upgrade-dialog {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: grid;
  place-items: center;
  padding: 24px;
  background: rgba(3, 12, 27, .68);
  backdrop-filter: blur(6px);
}
.upgrade-dialog[hidden] { display: none; }
.upgrade-card {
  position: relative;
  width: min(460px, 100%);
  padding: 30px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  box-shadow: 0 24px 70px rgba(0, 0, 0, .28);
}
.upgrade-card h2 { margin: 8px 0 10px; }
.upgrade-card > p:not(.eyebrow) { color: var(--muted); line-height: 1.55; }
.upgrade-close { position: absolute; top: 14px; right: 14px; }
.upgrade-actions { display: flex; gap: 10px; margin-top: 22px; }
.upgrade-actions .button { flex: 1; }


/* Job progress — one bar, used by every long-running feature. */
.job-progress { display: flex; flex-direction: column; gap: .45rem; width: 100%; }
.job-progress-track {
  /* 6px was invisible against a light page, and the track took its colour from
     `currentColor` at 12% — inside a muted panel that is nearly the background.
     The owner could not see the bar at all in light mode. Taller, and a real
     colour rather than a tint of whatever text happens to sit around it. */
  height: 8px; border-radius: 999px; overflow: hidden;
  background: var(--border, #d5d9e0);
}
.job-progress-fill {
  /* SOLID INK, not a gradient of two blues that both wash out on white. This
     is the one element on the page whose job is to be seen from across a desk. */
  height: 100%; border-radius: 999px;
  background: var(--text, #111827);
  transition: width 1.4s cubic-bezier(.22, .61, .36, 1);
}
@media (prefers-reduced-motion: reduce) {
  .job-progress-fill { transition: none; }
}
.job-progress-text {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 1rem; font-size: .82rem; opacity: .8;
}
.job-progress-text b { font-variant-numeric: tabular-nums; opacity: .95; }


/* H3 — long words (a document reference, a scheme name) pushed past their
   container instead of wrapping. Nothing in the rail may spill its border. */
.sidebar, .sidebar * { min-width: 0; overflow-wrap: anywhere; }
.settings-row { display: flex; align-items: center; justify-content: space-between; gap: .75rem; }


/* The brand mark had no bounding box of its own, so it floated against the
   toggle beside it. Give both the same footprint and they line up. */
.sidebar-head { display: flex; align-items: center; gap: .6rem; padding: .1rem .25rem .6rem; }
.brand-mark, .brand-logo-small {
  display: inline-grid; place-items: center;
  width: 30px; height: 30px; flex: 0 0 30px; border-radius: 8px;
}


.review-apply-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  margin: .6rem 0 .9rem; padding: .7rem .85rem; border-radius: 8px;
  border: 1px solid var(--border); background: var(--soft); font-size: .82rem;
}


/* Applied and dismissed must never look alike. One means the change is in the
   document; the other means it never will be. Drawing them the same way is how
   an engineer ships a report believing a correction was made. */
.finding-actions { display: flex; align-items: center; gap: .5rem; margin-top: .4rem; }
.finding-state { font-size: .77rem; opacity: .8; }
.review-report-card[data-state="applied"] {
  border-left: 3px solid var(--success);
  background: color-mix(in srgb, var(--success) 6%, transparent);
}
.review-report-card[data-state="dismissed"] { opacity: .5; }
.review-report-card[data-state="dismissed"] summary strong { text-decoration: line-through; }
.review-apply-bar .bar-actions { display: flex; gap: .5rem; }


/* A settings drawer holding three people's settings at once is why it read as
   nonsense. Group headings make whose is whose visible at a glance. */
.settings-group {
  margin: .9rem 0 .1rem; font-size: .77rem; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase; opacity: .62;
}


/* Two different reasons to hide one element must not share one attribute:
   `hidden` belongs to the plan gate, this class to "no project open yet". */
.is-hidden { display: none !important; }
/* display:block, NOT grid — a <details> laid out as a grid renders its content
   whether it is open or closed, so the fold silently does nothing. The grid
   belongs on the body inside it. */
.project-settings { display: block; margin: .35rem .35rem .2rem; border: 1px solid var(--sidebar-line); border-radius: 8px; background: var(--sidebar-hover); }
.project-settings > summary {
  display: flex; align-items: center; gap: .4rem; cursor: pointer; list-style: none;
  padding: .5rem .55rem; font-size: .77rem; font-weight: 600; letter-spacing: .04em;
  color: color-mix(in srgb, var(--sidebar-fg) 76%, transparent);
}
.project-settings > summary::-webkit-details-marker { display: none; }
.project-settings > summary:hover { color: var(--sidebar-fg); }
.project-settings > summary .icon { transition: transform .16s ease; opacity: .7; }
.project-settings[open] > summary .icon { transform: rotate(180deg); }
.project-settings[open] > summary { border-bottom: 1px solid var(--sidebar-line); }
.project-settings-body { display: grid; gap: .55rem; padding: .6rem .55rem .7rem; }
/* The guidance picker. A native multiple-select gave no sign it took more than
   one choice, needed a modifier key nobody guesses, and reported its options in
   document order - so the engineer could neither see nor set which document
   was read in full. These are plain rows: click to include, and the role each
   document plays is written next to it. */
.guidance-field { display: grid; gap: .3rem; }
.guidance-field-label { font-size: .77rem; font-weight: 600; color: var(--sidebar-fg); }
.guidance-picker { display: grid; gap: 2px; margin-top: .2rem; }
.guidance-row { display: flex; align-items: stretch; gap: 3px; }
.guidance-pick {
  flex: 1; min-width: 0; display: flex; align-items: center; gap: .45rem;
  font: inherit; font-size: .77rem; text-align: left; cursor: pointer;
  padding: .4rem .45rem; border: 1px solid transparent; border-radius: 6px;
  color: color-mix(in srgb, var(--sidebar-fg) 74%, transparent); background: transparent;
}
.guidance-pick:hover { background: var(--sidebar-hover); color: var(--sidebar-fg); }
.guidance-pick .icon { opacity: .5; }
.guidance-text { display: grid; gap: 1px; min-width: 0; flex: 1; }
.guidance-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.guidance-role {
  font-size: .77rem; letter-spacing: .02em; line-height: 1.25;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: color-mix(in srgb, var(--sidebar-fg) 52%, transparent);
}
.guidance-role:empty { display: none; }
.guidance-row.is-chosen .guidance-pick {
  color: var(--sidebar-fg); border-color: var(--sidebar-line); background: var(--sidebar-hover);
}
.guidance-row.is-chosen .guidance-pick .icon { opacity: 1; color: var(--accent); }
/* Primary is the one read cover to cover, so it is the one that carries the
   accent. Everything else is present but quiet. */
.guidance-row.is-primary .guidance-pick { border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.guidance-row.is-primary .guidance-role { color: var(--accent); font-weight: 600; }
.guidance-promote {
  flex: 0 0 auto; display: grid; place-items: center; width: 26px; cursor: pointer;
  font-size: .8rem; border: 1px solid var(--sidebar-line); border-radius: 6px;
  color: color-mix(in srgb, var(--sidebar-fg) 55%, transparent); background: transparent;
}
.guidance-promote:hover { color: var(--accent); border-color: var(--accent); }
.guidance-summary { margin: .4rem 0 0; }
/* The ADB version questions. Present only when an ADB volume is chosen, so
   they read as a consequence of the guidance choice above them. */
.adb-regime { display: grid; gap: .5rem; margin-top: .75rem; padding-top: .7rem; border-top: 1px solid var(--sidebar-line); }
.adb-question { display: grid; gap: .28rem; font-size: .77rem; font-weight: 500; line-height: 1.4; color: color-mix(in srgb, var(--sidebar-fg) 82%, transparent); }
.adb-question select { width: 100%; min-width: 0; font-size: .77rem; padding: .35rem .4rem; border-radius: 6px; }
.adb-question .settings-note { font-size: .77rem; line-height: 1.4; }
#adb-regime-outcome { margin: 0; font-size: .77rem; line-height: 1.45; }

/* Context pills: what a job will actually use, shown before it is started.
   Semantic colour is separate from the accent - the accent says "this is the
   document being read in full", amber says "a decision is missing". */
.context-pills { display: flex; flex-wrap: wrap; gap: .35rem; margin: .7rem 0 0; }
.context-pill {
  display: inline-flex; align-items: center; gap: .3rem; max-width: 100%;
  padding: .22rem .5rem; border: 1px solid var(--border); border-radius: 999px;
  color: var(--muted); background: var(--surface-subtle);
  font-size: .77rem; line-height: 1.35;
}
.context-pill > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.context-pill .icon { opacity: .75; }
.context-pill.is-strong {
  color: var(--accent-dark); border-color: color-mix(in srgb, var(--accent) 32%, transparent);
  background: var(--accent-soft); font-weight: 550;
}
.context-pill.is-strong .icon { color: var(--accent); opacity: 1; }
.context-pill.is-warn {
  color: var(--warning); border-color: color-mix(in srgb, var(--warning) 38%, transparent);
  background: color-mix(in srgb, var(--warning) 10%, transparent);
}
.context-pill.is-warn .icon { color: var(--warning); opacity: 1; }


/* Measured in the browser on 2026-08-05: the rail's secondary text sat at 46%
   of the ink on white, which reads as disabled rather than quiet. Light needs
   more weight than dark for the same apparent contrast. */
:root:not([data-theme="dark"]) .sidebar .muted,
:root:not([data-theme="dark"]) .sidebar .settings-note,
:root:not([data-theme="dark"]) .sidebar .empty-copy {
  color: color-mix(in srgb, var(--sidebar-fg) 66%, transparent);
}
:root:not([data-theme="dark"]) .section-label,
:root:not([data-theme="dark"]) .status-dot {
  color: color-mix(in srgb, var(--sidebar-fg) 78%, transparent);
}

/* Beta badge. The pilot is real work on real projects, so the label is a
   statement of fact rather than a disclaimer: this will keep changing. Small,
   quiet, and beside the name rather than over it. */
.beta-badge {
  display: inline-block; margin-left: .4em; vertical-align: .12em;
  padding: .1em .42em; border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  color: var(--accent); background: var(--accent-soft);
  font-family: var(--font-sans); font-size: .62em; font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase; line-height: 1.5;
}

/* ── Rendered answer markdown ─────────────────────────────────────────────
   A lookup answer is usually a TABLE. It used to arrive as pipe characters
   because the answer was drawn as escaped plain text. */
.answer-body > :first-child { margin-top: 0; }
.answer-body > :last-child { margin-bottom: 0; }
.answer-body p { margin: 0 0 .7rem; line-height: 1.55; }
.answer-body h3, .answer-body h4, .answer-body h5, .answer-body h6 {
  margin: 1.1rem 0 .5rem; line-height: 1.3;
}
.answer-body ul, .answer-body ol { margin: 0 0 .7rem; padding-left: 1.25rem; }
.answer-body li { margin: .2rem 0; line-height: 1.5; }
/* TOKENS, NOT A LITERAL. `#eef2f5` is a light grey, so in dark mode a cited
   clause number inside an answer was near-black text on near-white — the one
   run of characters in the paragraph that could not be read. */
.answer-body code {
  padding: .1rem .3rem; border-radius: 4px;
  color: var(--ink); background: var(--surface-subtle);
  border: 1px solid var(--border);
  font-size: .88em;
}
:root[data-theme="dark"] .answer-body code {
  color: var(--ink); background: color-mix(in srgb, var(--ink) 12%, transparent);
}
/* Wide tables scroll inside their own box; the page never scrolls sideways. */
.md-table-wrap { overflow-x: auto; margin: 0 0 .85rem; }
.md-table { border-collapse: collapse; width: 100%; font-size: .86rem; }
.md-table th, .md-table td {
  padding: .42rem .6rem; border: 1px solid var(--border); text-align: left;
  vertical-align: top;
}
.md-table thead th { background: var(--surface-subtle, #eef2f5); font-weight: 700; white-space: nowrap; }
.md-table tbody tr:nth-child(even) td { background: color-mix(in srgb, var(--border) 18%, transparent); }

/* Sources sit below the answer, closed by default. A citation chip after every
   value is what made these unreadable. */
.answer-sources { margin-top: .9rem; }
.answer-sources summary {
  cursor: pointer; font-weight: 600; font-size: .78rem; color: var(--accent);
}
.answer-sources-list { margin-top: .35rem; }

/* ── Guidance page viewer ─────────────────────────────────────────────────
   One image visible immediately with prev/next, as the Streamlit app had it.
   Clicking a button per page meant the engineer never looked at any of them. */
.guidance-viewer { margin-top: .65rem; }
.guidance-viewer-bar {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  margin-bottom: .5rem;
}
.guidance-viewer-caption { font-size: .78rem; font-weight: 600; flex: 1 1 auto; }
.guidance-viewer-count { font-size: .77rem; color: var(--muted); }
.guidance-viewer-stage img {
  display: block; width: 100%; max-height: 70vh; object-fit: contain;
  border: 1px solid var(--border); border-radius: 8px; background: #fff;
}
.guidance-viewer-stage .guidance-viewer-loading {
  padding: 1.2rem; text-align: center; font-size: .8rem; color: var(--muted);
}

/* ── Finding card: two levels ─────────────────────────────────────────────
   The fix is the line the engineer acts on, so it is on the card. The
   reasoning, the clause references and the verification note sit behind one
   toggle — 86 findings with five fields each took an hour to read. */
.drawing-finding-fix { margin: .45rem 0 0; font-weight: 600; line-height: 1.5; }
.drawing-finding-detail { margin-top: .55rem; }
.drawing-finding-detail summary {
  cursor: pointer; font-size: .78rem; font-weight: 600; color: var(--accent);
}
.drawing-finding-detail p { margin: .5rem 0 0; font-size: .86rem; line-height: 1.5; }
/* A finding with no pin says so, rather than borrowing a number. */
.drawing-marker-none { background: var(--muted); opacity: .65; }

/* ── D5 look: findings and sources ────────────────────────────────────────
   From docs/DESIGN_DIRECTION_D.html, the direction the owner chose. Three
   things carry the look: a monospaced number in its own column, a severity
   colour on the LEFT EDGE rather than a coloured pill shouting at you, and
   tighter type so a list of findings reads as a list. */
.drawing-findings { gap: .5rem; }
.drawing-finding {
  display: grid; grid-template-columns: auto 1fr; gap: 2px .8rem;
  padding: .7rem .9rem; border: 1px solid var(--border);
  border-left: 3px solid var(--muted); border-radius: 8px;
}
.drawing-finding:has(.severity-high), .drawing-finding:has(.severity-critical) {
  border-left-color: var(--danger);
}
.drawing-finding:has(.severity-low) { border-left-color: var(--success); }
.drawing-finding header {
  display: contents;                 /* the number becomes its own column */
}
.drawing-finding header > div { grid-column: 2; }
.drawing-finding h4 {
  margin: 0; font-size: .875rem; font-weight: 600; line-height: 1.35;
}
.drawing-finding > *:not(header) { grid-column: 2; }
.drawing-finding-fix {
  margin: .3rem 0 0; font-size: .84rem; font-weight: 500; line-height: 1.55;
}
.drawing-finding-detail p {
  margin: .4rem 0 0; font-size: .8rem; line-height: 1.55; color: var(--muted);
}
/* The marker number: quiet, monospaced, tabular so the column lines up. */
.drawing-marker {
  grid-row: span 4; align-self: start; min-width: 0; height: auto;
  padding: 0; border-radius: 0; background: none; color: var(--muted);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .77rem; font-weight: 500; font-variant-numeric: tabular-nums;
  padding-top: .12rem;
}
.drawing-marker-none { opacity: .45; }
/* The severity word sits above the headline, small and quiet. */
.drawing-finding .severity {
  display: inline-block; margin-bottom: .15rem; padding: 0; background: none;
  font-size: .77rem; letter-spacing: .06em;
}

/* An inline page reference inside an answer — the mock-up's `.cite` chip. */
.cite {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .77rem; color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border-radius: 3px; padding: 1px 5px; white-space: nowrap;
}

/* Sources as one bordered list, page number right-aligned in mono. */
.answer-sources-list { display: grid; gap: 1px; background: var(--border);
  border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.answer-sources-list .citation {
  display: flex; align-items: center; margin: 0; padding: .55rem .75rem;
  border-radius: 0; background: var(--background); font-size: .8rem;
}
.answer-sources-list .citation .pg {
  margin-left: auto; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .77rem; color: var(--muted); font-variant-numeric: tabular-nums;
}

/* ── Tick-table question ──────────────────────────────────────────────────
   Which guidance governs which part of a mixed building. The recommended
   column is pre-ticked, so agreeing costs no clicks and disagreeing costs one. */
.drawing-question-table { display: block; margin: .9rem 0; }
.question-why { margin: .25rem 0 .5rem; font-size: .78rem; color: var(--muted); }
.split-table-wrap { overflow-x: auto; }
.split-table { border-collapse: collapse; width: 100%; font-size: .82rem; }
.split-table th, .split-table td {
  padding: .4rem .55rem; border: 1px solid var(--border); text-align: left;
}
.split-table thead th { background: var(--surface-subtle); font-weight: 600; white-space: nowrap; }
.split-table .split-tick { text-align: center; }
.split-table .split-other { width: 100%; min-width: 7rem; font-size: .8rem; }

/* Verification status, in words. "unverified" is our word for "the zoom check
   did not run on this one", not "this may be wrong". */
.finding-check { margin: .5rem 0 0; font-size: .77rem; font-weight: 600; }
.finding-check-ok { color: var(--success); }
.finding-check-warn { color: var(--danger); }
.finding-check-muted { color: var(--muted); font-weight: 500; }
.finding-check-note { margin-top: .2rem; }
.finding-check-note summary { cursor: pointer; font-size: .77rem; color: var(--muted); }
.finding-check-note p { font-size: .77rem; line-height: 1.5; color: var(--muted); }

/* Where the measured overlay and the finding's words disagree. On the card,
   never behind a toggle: the finding above it is the thing being doubted. */
.finding-measured {
  margin: .55rem 0 0; padding: .5rem .65rem; border-radius: 8px;
  font-size: .78rem; line-height: 1.5;
  border-left: 3px solid var(--muted); background: var(--surface-2, rgba(127,127,127,.08));
}
.finding-measured-understated { border-left-color: var(--danger); }
.finding-measured-overstated { border-left-color: var(--warning, #b7791f); }

/* Where the finished review went. A review that was filed and one that was
   lost used to look identical on this page. */
.drawing-filed { margin: .4rem 0 0; font-size: .78rem; color: var(--muted); }
.drawing-filed-warn { color: var(--danger); font-weight: 600; }

/* A citation whose page will not open. Said out loud, because no link at all
   reads exactly like a finding that never cited anything. */
.finding-noref { margin: .4rem 0 0; font-size: .77rem; color: var(--muted); }

/* ── Annotated sheet with switchable measured layers ──────────────────────
   The base image and one transparent PNG per overlay class were produced all
   along and thrown away in the browser, which drew the flattened image instead
   — so every measured route was baked in whether it mattered or not. */
/* ONE COLUMN (owner, 28 Aug: "the canvas gets cut on the side"): the sheet
   takes the full width; the layer panel floats OVER it and folds, so only
   the panel ever gives way, never the drawing. */
.drawing-canvas-wrap { display: block; }
.cc-body { position: relative; }
/* A STRIP UNDER THE TOOLBAR, NOT A CARD OVER THE SHEET (owner, 6 Sep 2026:
   "this area looks horrible on the right side"). Closed by default; open, its
   toggles run in one wrapped line. */
.cc-body .layer-panel {
  position: absolute; left: .6rem; right: .6rem; top: .5rem; z-index: 6;
  max-width: none; max-height: 40%; overflow: auto;
  padding: .3rem .7rem; border: 1px solid var(--border); border-radius: 6px;
  background: color-mix(in srgb, var(--surface-raised) 92%, transparent);
  box-shadow: none; backdrop-filter: blur(6px);
}
.cc-body .layer-panel .eyebrow { display: inline; margin: 0; font-size: .77rem; }
.cc-body .layer-panel .layer-toggle { display: inline-flex; margin: .1rem .8rem .1rem 0; font-size: .82rem; }
.cc-body .layer-panel .geom-kind { font-size: .82rem; }
.cc-body .layer-panel .geom-controls, .cc-body .layer-panel .layer-controls { display: flex; flex-wrap: wrap; gap: .1rem .6rem; align-items: center; margin-top: .25rem; }
.cc-body .layer-panel > summary { cursor: pointer; list-style: none; }
.cc-body .layer-panel > summary::after {
  content: " ▾"; font-size: .77rem; color: var(--muted);
}
.cc-body .layer-panel:not([open]) > summary::after { content: " ▸"; }
/* The measured-geometry overlay scales with the sheet, exactly like the
   overlay PNGs - one canvas, every layer on it. */
.drawing-canvas .geom-overlay {
  position: absolute; inset: 0; width: 100%; height: 100%;
}
.drawing-canvas .geom-overlay .hidden { display: none; }
/* The native note form: the product's black-and-white voice, at the point
   clicked, unscaled by the canvas zoom. */
.cc-note-form {
  position: absolute; z-index: 7; width: 240px; display: grid; gap: .4rem;
  padding: .55rem; border: 1px solid var(--ink); border-radius: 10px;
  background: var(--surface-raised);
  box-shadow: 3px 3px 0 color-mix(in srgb, var(--ink) 18%, transparent);
}
.cc-note-form textarea {
  width: 100%; padding: .45rem .5rem; border: 1px solid var(--border);
  border-radius: 8px; font: inherit; font-size: .77rem; resize: vertical;
}
.cc-note-form div { display: flex; gap: .4rem; }
/* The right-click menu on the canvas - same card grammar. */
.cc-menu {
  position: absolute; z-index: 8; min-width: 170px; display: grid;
  padding: .25rem; border: 1px solid var(--ink); border-radius: 10px;
  background: var(--surface-raised);
  box-shadow: 3px 3px 0 color-mix(in srgb, var(--ink) 18%, transparent);
}
.cc-menu button {
  padding: .45rem .6rem; border: 0; border-radius: 7px; background: none;
  color: var(--ink); font: inherit; font-size: .77rem; text-align: left;
  cursor: pointer;
}
.cc-menu button:hover { background: var(--surface-subtle); }
.drawing-canvas { position: relative; line-height: 0; }
/* THE PICTURE'S BOX IS THE PICTURE (owner, 17 Sep 2026: "the annotations are
   totally wrong... everything is misaligned"). Every shape, marker layer and
   pin on this canvas is stretched edge to edge over the canvas box. The
   generic picture rule above caps a result image at 62vh and letter-boxes it
   (`object-fit: contain`), so on a large screen the box stayed full width
   while the drawing inside it shrank - and every room, wall and route landed
   about a tenth too wide, off the building. It never showed on a small
   window, where the cap does not bite. On the canvas the picture takes its
   own proportions and nothing else; the viewport's Fit does the fitting. */
.drawing-canvas .drawing-result-image {
  display: block; width: 100%; height: auto; max-height: none;
  object-fit: fill; margin: 0; border: 0; border-radius: 0;
}
.drawing-canvas .drawing-layer {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none;
}
.drawing-canvas .drawing-layer[hidden] { display: none; }
.layer-panel {
  min-width: 15rem; max-width: 18rem; padding: .75rem .85rem;
  border: 1px solid var(--border); border-radius: 8px; background: var(--background);
}
.layer-panel .eyebrow { display: block; margin-bottom: .5rem; }
.layer-toggle {
  display: grid; grid-template-columns: auto 1fr; gap: .1rem .5rem;
  align-items: center; margin: 0 0 .55rem; font-size: .82rem; cursor: pointer;
}
.layer-toggle .layer-count {
  grid-column: 2; font-size: .77rem; color: var(--muted);
}
.layer-swatch {
  display: inline-block; width: .85rem; height: .2rem;
  margin-right: .4rem; border-radius: 2px; vertical-align: middle;
}
@media (max-width: 900px) {
  .drawing-canvas-wrap { grid-template-columns: 1fr; }
  .layer-panel { max-width: none; }
}

/* Completed reviews sit under the uploads in the Documents panel. */
.document-group-heading {
  margin: .8rem 0 .35rem; font-size: .77rem; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; color: var(--muted);
}

/* The project's own settings, confirmed where they are changed. `setSaveState`
   writes to a bar at the top of the page and the engineer is in the sidebar
   with the panel open — he saw nothing at all when it worked. */
.settings-note.is-ok { color: var(--success); font-weight: 600; }
.settings-note.is-error { color: var(--danger); font-weight: 600; }

/* Which sheets this review will read, chosen from what the project holds.
   Uploading in the sidebar and choosing here are the same list. */
.drawing-pick { margin: .6rem 0 0; display: block; }
.drawing-picker {
  display: flex; flex-direction: column; align-items: stretch;
  gap: .2rem; margin-top: .3rem;
}
/* Checkbox first, name beside it. Without the explicit start alignment the
   label inherits the card's centring and the two ends of one row drift apart. */
.drawing-choice {
  display: flex; align-items: center; justify-content: flex-start;
  gap: .45rem; font-size: .78rem; text-align: left;
  padding: .2rem .3rem; border-radius: 5px; cursor: pointer;
}
/* The app styles form inputs full-width, so a bare `flex: 0 0 auto` left the
   checkbox 764px wide and pushed its own label off the end of the row. A
   checkbox needs its size stated. */
.drawing-choice input[type="checkbox"] {
  flex: 0 0 auto; width: 14px; height: 14px; margin: 0;
}
.drawing-choice span { flex: 1 1 auto; min-width: 0; }
.drawing-choice:hover { background: color-mix(in srgb, currentColor 6%, transparent); }

/* The paperclip on a composer. Adding a file meant going to the sidebar, which
   is a different part of the screen from the question being asked. */
.composer-attach {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 7px; cursor: pointer;
  color: var(--muted); border: 1px solid transparent;
}
.composer-attach:hover {
  color: var(--fg); background: color-mix(in srgb, currentColor 8%, transparent);
}
.composer-attach .icon { width: 15px; height: 15px; }

/* ── The review as named checks ─────────────────────────────────────────────
   A flat list of thirty-five findings could not tell the engineer what had
   been looked at and found satisfactory from what had never been looked at.
   The count comes first, because that is what he reads before anything else. */
.checks-panel { margin: 1rem 0; }
.checks-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: .75rem; flex-wrap: wrap;
}
.checks-head h3 { margin: 0; }
.check-counts { display: flex; gap: .4rem; flex-wrap: wrap; }
.check-count {
  font-size: .77rem; font-weight: 700; padding: .12rem .45rem;
  border-radius: 999px; white-space: nowrap;
}
.check-count-fail { color: var(--danger); background: color-mix(in srgb, var(--danger) 12%, transparent); }
.check-count-warn { color: var(--warning, #b7791f); background: color-mix(in srgb, var(--warning, #b7791f) 14%, transparent); }
.check-count-ok { color: var(--success); background: color-mix(in srgb, var(--success) 12%, transparent); }
.check-count-muted { color: var(--muted); background: color-mix(in srgb, currentColor 8%, transparent); }

.check-row { border-top: 1px solid color-mix(in srgb, currentColor 10%, transparent); }
.check-row summary {
  display: flex; align-items: center; gap: .5rem; cursor: pointer;
  padding: .42rem .1rem; font-size: .82rem; list-style: none;
}
.check-row summary::-webkit-details-marker { display: none; }
.check-row[data-empty] summary { cursor: default; opacity: .62; }
.check-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
.check-dot-fail { background: var(--danger); }
.check-dot-warn { background: var(--warning, #b7791f); }
.check-dot-ok { background: var(--success); }
.check-dot-muted { background: color-mix(in srgb, currentColor 32%, transparent); }
.check-name { flex: 1 1 auto; min-width: 0; }
.check-state { font-size: .77rem; color: var(--muted); white-space: nowrap; }
.check-about { margin: 0 0 .3rem 1rem; font-size: .77rem; color: var(--muted); }
.check-list { margin: 0 0 .5rem 1rem; padding-left: 1rem; font-size: .78rem; }
.check-list li { margin: .12rem 0; }
.check-marker {
  display: inline-block; min-width: 1.1rem; text-align: center;
  font-size: .77rem; font-weight: 700; border-radius: 4px; padding: 0 .2rem;
  background: color-mix(in srgb, currentColor 12%, transparent);
}
.check-measure-pass { color: var(--success); }
.check-measure-fail { color: var(--danger); }

/* A finding whose citation does not land on the page it names. Checked on every
   review, free, and it used to end at a log line. */
.finding-badcite {
  margin: .45rem 0 0; padding: .45rem .6rem; border-radius: 8px;
  font-size: .77rem; line-height: 1.5; color: var(--danger);
  border-left: 3px solid var(--danger);
  background: color-mix(in srgb, var(--danger) 8%, transparent);
}

/* The clause and the page, last and small — checked after he has decided the
   finding matters, not before he has read it. */
.finding-basis { margin: .25rem 0 0; font-size: .77rem; color: var(--muted); }

/* REPLY TO ONE COMMENT. The thread stays on the finding, so the reasoning can
   be read again later. Disagreeing with one finding used to mean re-running
   the whole review. */
.finding-reply { margin-top: .4rem; border-top: 1px solid var(--border); padding-top: .35rem; }
.finding-reply .reply-text { width: 100%; font: inherit; font-size: .82rem;
  padding: .4rem .5rem; border: 1px solid var(--border); border-radius: 6px;
  background: var(--surface); color: inherit; resize: vertical; }
.reply-actions { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; margin-top: .25rem; }
.reply-actions .feedback-status { display: inline; min-height: 0; margin: 0; }
.reply-state { font-size: .77rem; color: var(--muted); }
.finding-thread p { margin: .2rem 0; font-size: .82rem; line-height: 1.4; }
.thread-you { color: var(--muted); }
.thread-ask { font-weight: 600; }
.thread-warn { color: var(--danger); font-weight: 600; }
/* The revised wording is the thing he acts on, so it is set apart from the
   reasoning above it. */
.thread-wording { margin: .5rem 0 .2rem; padding: .5rem .6rem; border-radius: 6px;
  background: var(--surface-2, rgba(127, 127, 127, .08)); }
.thread-wording p { margin: .3rem 0 .45rem; }

/* A project row: open it, rename it, delete it. It could be created and then
   never touched again — renaming existed in the API with no door, and deleting
   did not exist at all, so a typo in a name was permanent. */
.project-row { display: flex; align-items: center; gap: 2px; }
.project-row > .project-item { flex: 1 1 auto; min-width: 0; }
.project-row.active > .project-item {
  background: var(--accent); color: #fff;
}
.project-action {
  flex: 0 0 auto; width: 22px; height: 22px; border: 0; background: none;
  color: var(--muted); border-radius: 5px; cursor: pointer; font-size: .8rem;
  line-height: 1; opacity: 0; transition: opacity .12s ease;
}
.project-row:hover .project-action,
.project-row:focus-within .project-action { opacity: 1; }
.project-action:hover { color: var(--fg); background: color-mix(in srgb, currentColor 12%, transparent); }
.project-action.is-armed {
  opacity: 1; width: auto; padding: 0 .35rem; font-size: .77rem;
  font-weight: 700; color: #fff; background: var(--danger);
}

/* The guidance page viewer. Arrows together, height held while a page loads,
   and click the page to read it full size. */
.guidance-viewer-nav { display: inline-flex; align-items: center; gap: .3rem; margin-left: auto; }
.guidance-viewer-bar { display: flex; align-items: center; gap: .5rem; }
.guidance-viewer-caption { flex: 1 1 auto; min-width: 0; }
.guidance-viewer-stage img { cursor: zoom-in; }

/* Three ways out: click anywhere, the cross, or Escape. A viewer that traps the
   reader is worse than no viewer. */
.lightbox {
  position: fixed; inset: 0; z-index: 9999; display: flex;
  align-items: center; justify-content: center; padding: 2rem;
  background: rgba(0, 0, 0, .82); cursor: zoom-out;
}
.lightbox img {
  max-width: 100%; max-height: 100%; object-fit: contain; cursor: default;
  background: #fff; border-radius: 6px; box-shadow: 0 20px 60px rgba(0,0,0,.5);
}
.lightbox-close {
  position: absolute; top: 1rem; right: 1.25rem; width: 38px; height: 38px;
  border: 0; border-radius: 50%; background: rgba(255,255,255,.14);
  color: #fff; font-size: 1.4rem; line-height: 1; cursor: pointer;
}
.lightbox-close:hover { background: rgba(255,255,255,.26); }
body.has-lightbox { overflow: hidden; }

/* ── What the product knows about its own answer ───────────────────────────
   Drawn ABOVE the answer, never under it: a warning the reader meets after he
   has already believed four paragraphs is a warning that arrived too late.
   Two levels only. "warn" is something unchecked or wrong; "info" is the basis
   the answer rests on. A third level would invite a fourth, and the panel's
   whole value is that a warn line means one thing. */
/* COMPACT (owner, 2 Sep 2026: "why so much gap between warnings notes etc,
   these should be compact notes"). The strips sit shoulder to shoulder;
   each summary is one slim line. */
.trust-panel { display: flex; flex-direction: column; gap: .1rem; margin: 0 0 .15rem; }
.trust-panel + .trust-panel { margin-top: 0; }
.trust-panel .trust-fold > summary,
.geometry-panel .trust-fold > summary { padding: .05rem .1rem; font-size: .77rem; line-height: 1.25; }
.trust-panel .trust-fold-body,
.geometry-panel .trust-fold-body { padding: .1rem 0 .25rem; gap: .3rem; }
.trust-note {
  display: flex; flex-direction: column; gap: .18rem;
  padding: .55rem .7rem; border-radius: 8px; font-size: .77rem; line-height: 1.45;
  border: 1px solid color-mix(in srgb, currentColor 26%, transparent);
  background: color-mix(in srgb, currentColor 8%, transparent);
}
.trust-note b { font-size: .78rem; }
.trust-note span { opacity: .88; }
.trust-note-warn { color: var(--warning, #b7791f); }
.trust-note-info { color: var(--muted); }
.trust-detail { margin-top: .3rem; }
.trust-detail summary { cursor: pointer; font-size: .77rem; }
.trust-detail pre {
  margin: .35rem 0 0; padding: .5rem .6rem; border-radius: 6px;
  background: color-mix(in srgb, currentColor 8%, transparent);
  white-space: pre-wrap; font-size: .77rem;
}

/* The knock-on effects an edit triggers — bought on every edit, drawn on none
   of them until 14 Aug 2026. */
.ripple-panel { margin: .8rem 0 0; }
.ripple-panel h4 { margin: 0 0 .35rem; font-size: .78rem; }
.ripple-panel ul { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: .35rem; }
.ripple-item {
  display: flex; flex-direction: column; gap: .15rem;
  padding: .5rem .65rem; border-radius: 8px; font-size: .77rem; line-height: 1.45;
  border-left: 3px solid var(--muted);
  background: color-mix(in srgb, currentColor 6%, transparent);
}
.ripple-item em { font-style: normal; opacity: .85; }
.ripple-high { border-left-color: var(--danger); }
.ripple-medium { border-left-color: var(--warning, #b7791f); }
.ripple-low { border-left-color: var(--muted); }

/* ==========================================================================
   MONOCHROME PRACTICE — AUGUST 2026

   The public site moved from generic blue SaaS chrome to an editorial black
   and white identity. This final presentation layer brings the working product
   into the same family without touching its structure or behaviour.

   Colour is evidence, never decoration:
     cyan  = source / reference
     green = checked / complete
     amber = coordination / judgement
     red   = risk / destructive action
   Everything else is paper, ink and rules.
   ========================================================================== */
:root {
  --sidebar-bg: #0b0b0a;
  --sidebar-fg: #f4f4f0;
  --sidebar-line: rgba(255,255,255,.15);
  --sidebar-hover: rgba(255,255,255,.075);
  --navy: #0e0e0d;
  --navy-2: #3f3f3b;
  --accent: #0e0e0d;
  --accent-dark: #292927;
  --accent-soft: #edede9;
  --ink: #0e0e0d;
  --muted: #656560;
  --soft: #f0f0ec;
  --surface: #ffffff;
  --border: #cecec7;
  --success: #197251;
  --danger: #b83e4c;
  --warning: #9b681b;
  --detail-info: #126d80;
  --detail-info-soft: #e5f2f4;
  --detail-pass: #197251;
  --detail-pass-soft: #e8f3ed;
  --detail-warn: #9b681b;
  --detail-warn-soft: #f6eedf;
  --detail-risk: #b83e4c;
  --detail-risk-soft: #f8e9eb;
  --page-backdrop: #deded8;
  --main-bg: #f4f4f0;
  --surface-raised: #ffffff;
  --surface-subtle: #f0f0ec;
  --control-bg: #ffffff;
  --autofill-bg: #ffffff;
  --autofill-ink: #0e0e0d;
  --background: #ffffff;
  --fg: #0e0e0d;
  --radius: 4px;
  --shadow: 0 1px 0 rgba(14,14,13,.07);
  --shadow-pop: 0 18px 50px rgba(14,14,13,.14);
  --btn-primary-start: #0e0e0d;
  --btn-primary-end: #343431;
}

body { background: var(--main-bg); }

:where(a, button, input, textarea, select, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* Sign-in is the dark opening chapter; the workspace itself remains bright. */
.auth-view {
  background-color: var(--sidebar-bg);
  background-image:
    radial-gradient(circle at 76% 18%, rgba(255,255,255,.09), transparent 30%),
    linear-gradient(rgba(255,255,255,.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.035) 1px, transparent 1px);
  background-size: auto, 54px 54px, 54px 54px;
}
.auth-card {
  border-color: rgba(255,255,255,.28);
  border-radius: 4px;
  box-shadow: 18px 18px 0 rgba(255,255,255,.075), var(--shadow-pop);
}
.auth-brand-logo, .brand-logo-small {
  border: 1px solid currentColor;
  border-radius: 4px;
  background: var(--accent);
}
.auth-brand .brand-dot, .eyebrow { color: var(--detail-info); }
.auth-card h1 { line-height: 1.02; }
.auth-notice, .auth-outcome {
  color: var(--detail-info);
  border-color: color-mix(in srgb, var(--detail-info) 36%, transparent);
  background: var(--detail-info-soft);
}
.register-button {
  color: var(--ink);
  border-color: var(--ink);
  background: transparent;
}
.register-button:hover { color: #fff; background: var(--ink); }

/* The dark rail is the product's persistent brand anchor. */
#workspace-view { background: var(--main-bg); }
.sidebar {
  border-right: 1px solid rgba(255,255,255,.13);
  background: var(--sidebar-bg);
}
.sidebar-head strong { color: #fff; letter-spacing: -.02em; }
.sidebar-head .brand-logo-small {
  border-color: rgba(255,255,255,.32);
  background: var(--sidebar-bg);
}
.sidebar .beta-badge {
  color: #8bd5e0;
  border-color: rgba(139,213,224,.42);
  background: rgba(22,124,145,.16);
}
.sidebar .icon-button, .sidebar-toggle {
  color: var(--sidebar-fg);
  border-color: rgba(255,255,255,.18);
  background: rgba(255,255,255,.06);
}
.sidebar .icon-button:hover, .sidebar-toggle:hover {
  color: #fff;
  border-color: rgba(255,255,255,.45);
  background: rgba(255,255,255,.11);
}
.project-row.active > .project-item,
.project-item.active,
.document-item.active {
  color: var(--ink);
  background: #f4f4f0;
}
.project-row.active .project-action { color: rgba(255,255,255,.74); }
.sidebar-usage { border-radius: 3px; background: rgba(255,255,255,.055); }
.usage-meter-track { height: 3px; border-radius: 0; }
.usage-meter-track span { border-radius: 0; background: #f4f4f0; }
.status-dot.online::before { background: var(--detail-pass); }
.section-label, .eyebrow { font-size: .77rem; font-weight: 700; }
.sidebar-head .muted, .sidebar .empty-copy { font-size: .77rem; }
.project-settings-body > label,
.project-settings-body .guidance-field-label,
.project-settings-body .adb-question {
  color: color-mix(in srgb, var(--sidebar-fg) 88%, transparent);
}
.project-settings-body :is(select, textarea) {
  color: var(--sidebar-fg);
  font-weight: 400;
  border-color: color-mix(in srgb, var(--sidebar-fg) 22%, transparent);
  background: color-mix(in srgb, var(--sidebar-fg) 8%, transparent);
}
.project-settings-body :is(select, textarea):focus {
  border-color: color-mix(in srgb, var(--sidebar-fg) 64%, transparent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--sidebar-fg) 10%, transparent);
}
.project-settings-body textarea::placeholder { color: color-mix(in srgb, var(--sidebar-fg) 60%, transparent); }
.project-settings-body select option { color: var(--ink); background: #fff; }
.project-settings-body .settings-note { color: color-mix(in srgb, var(--sidebar-fg) 65%, transparent); }
.drawing-pick > .guidance-field-label { color: var(--ink); }

/* Editorial hierarchy and sharper work surfaces. */
.main-shell { background: var(--main-bg); }
.topbar { align-items: center; }
.topbar h2 { font-size: 1.65rem; }
.surface-nav { gap: 1.3rem; padding-bottom: 0; border-color: var(--border); }
.surface-tab {
  margin: 0;
  padding: .6rem 0 .7rem;
  border-bottom-width: 2px;
  color: var(--muted);
  font-size: .77rem;
}
.surface-tab:hover, .surface-tab.active {
  color: var(--ink);
  border-bottom-color: var(--ink);
}
.surface-tab:focus-visible { outline-offset: -2px; }
.tool-card, .writer-header, .writer-document-context,
.writer-command-pane, .generate-panel, .review-rail,
.upgrade-card, .admin-card {
  border-color: var(--border);
  border-radius: 4px;
  background: var(--surface-raised);
  box-shadow: none;
}
.tool-card, .generate-panel { border-top: 2px solid var(--ink); }
.feature-card-head h3, .writer-header h3, .generate-panel > h3,
.review-report-head strong {
  font-family: var(--font-serif);
  font-weight: 400;
  letter-spacing: -.014em;
}
.feature-card-head h3, .writer-header h3 { font-size: 1.35rem; }
.feature-card-head p, .writer-header p, .tool-card > p { color: var(--muted); }

/* Controls use black for action; status colours keep their literal meaning. */
input, textarea, select, .paragraph-editor,
.task-composer, .selection-toolbar {
  border-color: var(--border);
  border-radius: 4px;
  color: var(--ink);
  background: #fff;
}
input::placeholder, textarea::placeholder { color: #777771; opacity: 1; }
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--autofill-ink);
  -webkit-box-shadow: 0 0 0 1000px var(--autofill-bg) inset;
  caret-color: var(--autofill-ink);
}
input:focus, textarea:focus, select:focus, .paragraph-editor:focus,
.task-composer:focus-within {
  border-color: var(--ink);
  box-shadow: 0 0 0 3px rgba(14,14,13,.11);
}
.button { border-radius: 4px; }
.button.primary { color: #fff; background: var(--ink); }
.button.primary:hover { background: #30302d; }
.button.secondary {
  color: var(--ink);
  border-color: var(--ink);
  background: #fff;
}
.button.secondary:hover { color: #fff; background: var(--ink); }
.button.ghost, .icon-button { border-color: var(--border); background: #fff; }
.button.ghost:hover, .icon-button:hover { color: var(--ink); border-color: var(--ink); background: var(--soft); }
.text-button:hover, .answer-sources summary, .drawing-guidance summary,
.drawing-support summary, .drawing-finding-detail summary { color: var(--detail-info); }

.task-composer { overflow: hidden; }
.task-composer > textarea { border-radius: 0; }
.composer-footer {
  border-color: var(--border);
  border-radius: 0;
  background: var(--surface-subtle);
}
/* THE ASK BUTTON, decided once (owner, 2 Sep: "the ask button is still
   bad"). Two rules used to fight - a 999px pill up top, this 4px square
   winning by order - so Ask rendered as a flat grey box. One deliberate
   shape: a firm primary button with real presence. */
.composer-submit { border-radius: 8px; min-width: 96px; min-height: 38px;
  font-size: .82rem; font-weight: 650; letter-spacing: .01em; }
.option-pill, .select-pill, .compact-options > summary {
  border-radius: 4px;
  color: var(--muted);
  background: #fff;
}
.option-pill:has(input:checked), .compact-options[open] > summary {
  color: var(--ink);
  border-color: var(--ink);
  background: var(--soft);
}
.upload-zone { border-radius: 4px; background: var(--surface-subtle); }
.mode-switch { border-radius: 4px; background: var(--surface-subtle); }
.mode-button { border-radius: 3px; }
.mode-button.active { color: var(--ink); border-color: var(--border); background: #fff; }

/* D5 colour details: source, checked, coordination and risk. */
.context-badge, .context-pill.is-strong, .cite, .citation,
.answer-sources summary, .guidance-row.is-primary .guidance-role {
  color: var(--detail-info);
}
.context-badge, .context-pill.is-strong, .cite {
  border-color: color-mix(in srgb, var(--detail-info) 30%, transparent);
  background: var(--detail-info-soft);
}
.guidance-row.is-primary .guidance-pick { border-color: var(--detail-info); }
.guidance-row.is-chosen .guidance-pick .icon { color: var(--detail-info); }
.fidelity-badge { color: var(--detail-pass); background: var(--detail-pass-soft); }
.notice, .strategy-question-panel, .drawing-questions {
  color: var(--detail-warn);
  border-color: color-mix(in srgb, var(--detail-warn) 38%, transparent);
  background: var(--detail-warn-soft);
}
.change-card, .drawing-overview { border-left-color: var(--detail-info); }
.severity-high, .severity-critical, .finding-check-warn { color: var(--detail-risk); }
.severity-low, .finding-check-ok { color: var(--detail-pass); }
.drawing-finding:has(.severity-high), .drawing-finding:has(.severity-critical) { border-left-color: var(--detail-risk); }
.drawing-finding:has(.severity-low) { border-left-color: var(--detail-pass); }
.review-report-card[data-state="applied"] { border-left-color: var(--detail-pass); }
.check-dot-fail { background: var(--detail-risk); }
.check-dot-warn { background: var(--detail-warn); }
.check-dot-ok { background: var(--detail-pass); }
.check-count-fail { color: var(--detail-risk); background: var(--detail-risk-soft); }
.check-count-warn { color: var(--detail-warn); background: var(--detail-warn-soft); }
.check-count-ok { color: var(--detail-pass); background: var(--detail-pass-soft); }

.context-card, .document-context-strip, .selected-passage-preview,
.selection-workbench, .writer-selection-text, .writer-suggestion,
.writer-comment-composer, .review-report-raw pre {
  border-radius: 4px;
  background: var(--surface-subtle);
}
.review-report-card, .drawing-sheet, .drawing-cross-sheet,
.drawing-finding, .layer-panel, .history-item,
.writer-comment-item, .project-settings { border-radius: 4px; }
.count-badge, .context-pill, .beta-badge, .severity,
.check-count, .safety-flag { border-radius: 999px; }
.upgrade-dialog { background: rgba(7,7,6,.78); }

/* Explicit dark mode: the same monochrome system inverted, not a blue skin. */
:root[data-theme="dark"] {
  --sidebar-bg: #080808;
  --sidebar-fg: #f2f2ef;
  --navy: #f2f2ef;
  --navy-2: #c4c4bd;
  --accent: #f2f2ef;
  --accent-dark: #d8d8d2;
  --accent-soft: #242421;
  --ink: #f2f2ef;
  --muted: #aaa9a2;
  --soft: #191918;
  --surface: #131312;
  --border: #393936;
  --success: #55bd8c;
  --danger: #ff8494;
  --warning: #e7b260;
  --detail-info: #64c1d2;
  --detail-info-soft: #10292e;
  --detail-pass: #55bd8c;
  --detail-pass-soft: #10261d;
  --detail-warn: #e7b260;
  --detail-warn-soft: #2b2315;
  --detail-risk: #ff8494;
  --detail-risk-soft: #31191d;
  --page-backdrop: #20201e;
  --main-bg: #0b0b0a;
  --surface-raised: #141413;
  --surface-subtle: #1a1a18;
  --control-bg: #141413;
  --autofill-bg: #141413;
  --autofill-ink: #f2f2ef;
  --background: #141413;
  --fg: #f2f2ef;
  --btn-primary-start: #f2f2ef;
  --btn-primary-end: #ccccc6;
}
:root[data-theme="dark"] .auth-card { background: var(--surface-raised); }
:root[data-theme="dark"] .auth-view {
  background-color: var(--sidebar-bg);
  background-image:
    radial-gradient(circle at 76% 18%, rgba(255,255,255,.08), transparent 30%),
    linear-gradient(rgba(255,255,255,.03) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.03) 1px, transparent 1px);
  background-size: auto, 54px 54px, 54px 54px;
}
:root[data-theme="dark"] .auth-notice {
  color: var(--detail-info);
  border-color: color-mix(in srgb, var(--detail-info) 38%, transparent);
  background: var(--detail-info-soft);
}
:root[data-theme="dark"] :is(.auth-brand-logo, .brand-logo-small, .brand-mark) {
  color: #f2f2ef;
  background: #0e0e0d;
}
:root[data-theme="dark"] .button.primary { color: #0e0e0d; background: #f2f2ef; }
:root[data-theme="dark"] .button.primary:hover { background: #d8d8d2; }
:root[data-theme="dark"] .button.secondary { color: #f2f2ef; border-color: #f2f2ef; background: transparent; }
:root[data-theme="dark"] .button.secondary:hover { color: #0e0e0d; background: #f2f2ef; }
:root[data-theme="dark"] .button.ghost:hover,
:root[data-theme="dark"] .selection-toolbar .button.ghost:hover,
:root[data-theme="dark"] .history-item:hover { background: var(--surface-subtle); }
:root[data-theme="dark"] :is(input, textarea, select, .paragraph-editor,
  .task-composer, .selection-toolbar, .mode-button.active, .option-pill,
  .select-pill, .compact-options > summary, .compact-options-menu,
  .upload-zone input, .icon-button) {
  color: var(--ink);
  border-color: var(--border);
  background: var(--surface-raised);
}
:root[data-theme="dark"] input::placeholder,
:root[data-theme="dark"] textarea::placeholder { color: #9a9992; }
:root[data-theme="dark"] .composer-footer,
:root[data-theme="dark"] .document-controls { background: rgba(20,20,19,.94); }
:root[data-theme="dark"] .project-row.active > .project-item,
:root[data-theme="dark"] .project-item.active,
:root[data-theme="dark"] .document-item.active { color: #0e0e0d; background: #f2f2ef; }

/* ==========================================================================
   PAPER RAIL — ACTIVE BRAND SYSTEM

   The paper-first treatment is the default browser workspace. The same DOM,
   events, state and API calls continue underneath; this layer changes only
   presentation.

   In this version teal is evidence, not selection. Black and white carry the
   interface; a slim teal rule identifies only the guidance document read in
   full. The logo is rendered as a single-colour mark so the legacy blue inner
   flame cannot reintroduce the old brand palette.
   ========================================================================== */
:root:not([data-theme="dark"]) {
  --sidebar-bg: #fbfbf8;
  --sidebar-fg: #141413;
  --sidebar-line: rgba(14,14,13,.16);
  --sidebar-hover: rgba(14,14,13,.055);
  --main-bg: #f1f1ed;
  --page-backdrop: #deded7;
  --detail-info: #0d6375;
  --detail-info-soft: #e4eff0;
}

:root:not([data-theme="dark"]) .sidebar {
  border-right-color: var(--border);
  box-shadow: 8px 0 24px rgba(14,14,13,.025);
}
:root:not([data-theme="dark"]) .sidebar-head strong,
:root:not([data-theme="dark"]) .sidebar-head .brand-dot {
  color: var(--sidebar-fg);
}
:root:not([data-theme="dark"]) .sidebar-head .brand-logo-small {
  /* NO FILTER. `brightness(0)` drove the droplet and the inner flame to the
     same black and the mark became a silhouette - the missing "flame within
     the flame". The mark arrives already composited. */
  filter: none;
  border: 0;
  background: transparent;
}
:root:not([data-theme="dark"]) .sidebar .beta-badge {
  color: var(--detail-info);
  border-color: color-mix(in srgb, var(--detail-info) 34%, transparent);
  background: var(--detail-info-soft);
}
:root:not([data-theme="dark"]) .sidebar :is(.icon-button, .sidebar-toggle) {
  color: var(--sidebar-fg);
  border-color: color-mix(in srgb, var(--sidebar-fg) 20%, transparent);
  background: #ffffff;
}
:root:not([data-theme="dark"]) .sidebar :is(.icon-button, .sidebar-toggle):hover {
  color: var(--sidebar-fg);
  border-color: var(--sidebar-fg);
  background: var(--sidebar-hover);
}
:root:not([data-theme="dark"]) :is(
  .project-row.active > .project-item,
  .project-item.active,
  .document-item.active
) {
  color: var(--sidebar-fg);
  background: #ecece7;
  box-shadow: inset 3px 0 0 var(--sidebar-fg);
}
:root:not([data-theme="dark"]) .project-row.active .project-action {
  color: color-mix(in srgb, var(--sidebar-fg) 72%, transparent);
}
:root:not([data-theme="dark"]) .sidebar-usage {
  border: 1px solid var(--sidebar-line);
  background: #f1f1ed;
}
:root:not([data-theme="dark"]) .usage-meter-track {
  background: color-mix(in srgb, var(--sidebar-fg) 13%, transparent);
}
:root:not([data-theme="dark"]) .usage-meter-track span {
  background: var(--sidebar-fg);
}
:root:not([data-theme="dark"]) .guidance-row.is-chosen .guidance-pick {
  color: var(--sidebar-fg);
  border-color: color-mix(in srgb, var(--sidebar-fg) 22%, transparent);
  background: #ecece7;
  box-shadow: inset 3px 0 0 var(--sidebar-fg);
}
:root:not([data-theme="dark"]) .guidance-row.is-chosen .guidance-pick .icon {
  color: var(--sidebar-fg);
}
:root:not([data-theme="dark"]) .guidance-row.is-primary .guidance-pick {
  border-color: color-mix(in srgb, var(--sidebar-fg) 22%, transparent);
  box-shadow: inset 3px 0 0 var(--detail-info);
}
:root:not([data-theme="dark"]) .guidance-row.is-primary .guidance-role {
  color: var(--detail-info);
}

/* Dark mode keeps a dark rail, but lifts it one layer above the canvas so it
   is graphite rather than an undifferentiated black-on-black block. */
:root[data-theme="dark"] {
  --sidebar-bg: #171716;
  --main-bg: #090909;
  --surface: #171716;
  --surface-raised: #191918;
  --surface-subtle: #20201e;
  --control-bg: #191918;
  --background: #191918;
  --border: #41413d;
  --detail-info: #72c4d1;
  --detail-info-soft: #112b30;
}
:root[data-theme="dark"] .sidebar {
  border-right-color: #373733;
  box-shadow: 8px 0 26px rgba(0,0,0,.2);
}
:root[data-theme="dark"] .sidebar-head .brand-logo-small {
  /* Was an inverting filter, which turned the tile into a solid white block.
     The dark artwork is swapped in by `content:` instead. */
  filter: none;
  border: 0;
  background: transparent;
}
:root[data-theme="dark"] .guidance-row.is-chosen .guidance-pick {
  color: var(--sidebar-fg);
  border-color: color-mix(in srgb, var(--sidebar-fg) 20%, transparent);
  background: #272724;
  box-shadow: inset 3px 0 0 var(--sidebar-fg);
}
:root[data-theme="dark"] .guidance-row.is-chosen .guidance-pick .icon {
  color: var(--sidebar-fg);
}
:root[data-theme="dark"] .guidance-row.is-primary .guidance-pick {
  border-color: color-mix(in srgb, var(--sidebar-fg) 20%, transparent);
  box-shadow: inset 3px 0 0 var(--detail-info);
}

/* ==========================================================================
   PAPER RAIL — FINISHING PASS

   Five measured defects in the layer above, all presentation only. No DOM id,
   event, route or product string is touched.
   ========================================================================== */

/* 1. The sign-in mark still carried the legacy blue inner flame.
      The rail mark was made monochrome; the auth mark was not, so the first
      screen a customer ever sees was the only screen still showing the old
      brand.

      `filter` filters the element's OWN background as well as the image, so
      filtering the mark while it still had the black tile painted on it turned
      tile and flame the same colour and the mark disappeared. The tile is
      dropped and the mark is drawn as a silhouette, exactly as the rail mark
      already is: ink on paper in light, paper on ink in dark. */
.auth-brand-logo {
  /* Was `filter: grayscale(1) brightness(0)` over a raster. The mark is a
     vector now and is painted, not filtered - see the brand rules below. */
  background: transparent;
}
:root[data-theme="dark"] .auth-brand-logo {
  /* Was an inverting filter, which turned the tile into a solid white block.
     The dark palette is applied to the SHAPES below instead. */
  border-color: transparent;
  /* An earlier dark rule repaints the tile at higher specificity, and an
     inverted black tile is a solid white block, not a mark. */
  background: transparent;
}

/* 2. Teal is evidence — and a citation is the evidence element. In dark mode
      an older rule (`:root[data-theme="dark"] :is(…, .citation)`) out-specified
      the evidence colour and painted citations plain white, so the one thing
      the palette exists to mark lost its mark on half the installs. Same
      specificity, later in the file, so this wins without touching that rule. */
:root[data-theme="dark"] :is(.citation, .citation b) { color: var(--detail-info); }
:root[data-theme="dark"] .citation .pg { color: var(--muted); }

/* 3. Quiet is not the same as unreadable. Measured against their own painted
      backgrounds these three fell under WCAG AA (4.5:1) at 9.6–11.1px:
        light  .sidebar-usage p   3.18:1   .sidebar-foot .text-button  4.17:1
        dark   .sidebar-usage p   4.32:1   .empty-copy / .muted        4.27:1
      The mix percentages below are the computed minimum for 4.6:1 plus
      headroom, so the text stays subordinate and still passes. */
:root:not([data-theme="dark"]) .sidebar-usage p {
  color: color-mix(in srgb, var(--sidebar-fg) 64%, transparent);
}
:root:not([data-theme="dark"]) .sidebar-foot .text-button {
  color: color-mix(in srgb, var(--sidebar-fg) 64%, transparent);
}
:root[data-theme="dark"] .sidebar-usage p {
  color: color-mix(in srgb, var(--sidebar-fg) 56%, transparent);
}
:root[data-theme="dark"] :is(
  .sidebar .empty-copy,
  .sidebar-head .muted,
  .sidebar-settings .settings-note
) {
  color: color-mix(in srgb, var(--sidebar-fg) 56%, transparent);
}

/* ==========================================================================
   ONE COLOUR RULE, AND IT COMES FROM THE WEBSITE — 18 August 2026

   THE OWNER, 18 Aug 2026: "You're following different colour patterns when it
   comes to the logo, what gets that oil colour… I want you to be consistent."

   The argument was settled by measuring firestrategy.ai rather than by taste.
   Every piece of text on the marketing page is grey, white or near-black,
   with four exceptions in the entire document:

     petrol teal #1384a8  ×2   both of them "ADB Table 2.1" — a CITATION
     green      #37d99a  ×2   "Review complete", and the money figure
     red        #ff6b8a  ×1
     amber      #a77200  ×1

   The site's own `.ai`, its links and its section eyebrows are white or grey.
   So the rule is not a preference, it is already the brand: TEAL MARKS A
   SOURCE AND NOTHING ELSE. The product had teal on eyebrows, the beta badge,
   notices, change cards and the `.ai` — none of which is a source — which is
   exactly what made it read as decoration.
   ========================================================================== */

/* 0. THE BLACK BOX UNDER THE SIDEBAR.
      `color-scheme: dark` was declared for the dark theme and light was NEVER
      declared, so in light mode the property fell back to `normal` and the
      browser painted the surfaces IT owns — the overscroll canvas, the scroll
      gutter, native controls — from the OS appearance instead of from the
      page. On a Mac set to dark that is a black band appearing below a
      paper-white page and vanishing again with the scroll position, which is
      why it was intermittent. Declaring both ends the guess. */
:root { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

/* 1. THE MARK KEEPS THE FLAME INSIDE THE FLAME.
      THE OWNER: "The logo is missing the white flame within the flame."

      He was right, and it was my doing. The asset is a white outer flame with
      a BLUE inner flame on a transparent ground. `brightness(0)` drove every
      opaque pixel to the same value, so the two flames became one blob — the
      blue was gone, and so was the shape.

      `contrast()` separates them instead of flattening them. After
      `grayscale(1)` the outer flame sits at 224 and the inner at 96; contrast
      pushes the first to white and the second to black, and leaves the black
      tile black. The result is the marketing header's lockup exactly, with the
      blue removed: black tile, white flame, dark flame within it. One mark,
      identical in both themes — no inversion, so no theme can lose it. */
/* The tile is deliberately NOT theme-following: it is the same mark on the
   website, the sign-in card, the rail and the Word pane, in both themes. It
   gets its own tokens so that intent is stated once rather than as a hex
   repeated at four selectors. */
:root {
  --brand-tile: #0e0e0d;
  --brand-flame: #f2f2ef;
}
/* THE MARK IS A VECTOR NOW, SO NOTHING FILTERS IT.
   Every earlier attempt reached for `filter`, and `filter` filters the
   element's OWN background as well as its image - which is how a black tile
   and a black flame became one solid block, twice. The mark is an inline
   <svg> with two named parts, so each is simply PAINTED: no filter, no
   background on the element, and nothing left of the legacy blue flame
   anywhere in the file. Sharp at any size, because there is no raster. */
:root:not([data-theme="dark"]) .sidebar-head .brand-logo-small,
:root[data-theme="dark"] .sidebar-head .brand-logo-small,
:root:not([data-theme="dark"]) .auth-brand-logo,
:root[data-theme="dark"] .auth-brand-logo,
.auth-brand-logo,
.brand-logo-small {
  filter: none;
  background: transparent;
  border: 0;
  border-radius: 0;
}
/* TWO FINISHED PICTURES, ONE PER THEME. The tile, the droplet and the inner
   flame are composited OFFLINE by `scripts/build_brand_mark.py`, so the
   browser is handed a mark that is already right and nothing has to correct
   it on the way to the screen. That is the whole point: every previous
   attempt reached for `filter`, and a filter also filters the element's own
   background - which is how a black tile and a black flame became one solid
   block, twice. */
:root[data-theme="dark"] .auth-brand-logo,
:root[data-theme="dark"] .brand-logo-small {
  content: url("/web/assets/fire-mark-dark.png");
}

/* 2. TEAL MARKS A SOURCE. EVERYTHING ELSE IS INK, GREY OR PAPER.
      Kept teal, because each one answers "where did this come from?":
      .citation / .cite / .answer-sources summary / .context-badge /
      .context-pill.is-strong / .guidance-row.is-primary (the 3px edge and its
      "Read in full" label) / .drawing-finding-detail summary, whose label is
      literally "Why, and the guidance behind it".
      Everything below is a label, a badge, a status or an edit — not a
      source — and had no business wearing the evidence colour. */
.eyebrow { color: var(--muted); }
/* The `.ai` is NOT differentiated on firestrategy.ai — it is drawn in exactly
   the same colour as the rest of the wordmark, in the header and the footer
   both. It was measured, not assumed. So it inherits here too, in all four
   places the lockup appears, rather than being tinted a fourth way. */
.auth-brand .brand-dot,
.sidebar-head .brand-dot,
.brand-dot { color: inherit; }

:root:not([data-theme="dark"]) .sidebar .beta-badge,
:root[data-theme="dark"] .sidebar .beta-badge,
.sidebar .beta-badge {
  color: var(--muted);
  border-color: var(--border);
  background: var(--surface-subtle);
}

:root[data-theme="dark"] .auth-notice,
.auth-notice,
.auth-outcome {
  color: var(--ink);
  border-color: var(--border);
  background: var(--surface-subtle);
}

/* An edit and a raw data dump are not sources. */
.change-card,
.drawing-overview { border-left-color: var(--border); }
.drawing-support > summary,
.drawing-overview > summary { color: var(--muted); }

/* 3. GREEN MEANS CHECKED. A LOW-SEVERITY FINDING IS NOT CHECKED.
      THE OWNER: "with green, we should only have things that have been
      checked, done, complete, are accurate, not things that are wrong even
      though with a low severity."

      Green stays on `.finding-check-ok` and `.fidelity-badge`, which is where
      it means verified. The severity scale becomes honest and monotonic —
      red for risk, amber for judgement, grey for minor — so nothing on the
      scale is ever drawn in the colour that means "cleared". */
.severity-low { color: var(--muted); }
/* The amber token is tuned for body text on paper; on the severity chip's own
   grey fill, at 9.6px, it measured 4.19:1 — under AA. Darkened just enough
   (94%) to clear it at 4.61:1 without becoming a second amber. */
.severity-medium { color: color-mix(in srgb, var(--detail-warn) 94%, #000); }
:root[data-theme="dark"] .severity-medium { color: var(--detail-warn); }
.drawing-finding:has(.severity-low) { border-left-color: var(--border); }
.drawing-finding:has(.severity-medium) { border-left-color: var(--detail-warn); }

/* ==========================================================================
   THE THREE COMPOSER CONTROLS BECOME ONE CONTROL — 18 August 2026

   THE OWNER: "I like how this guidance picker works and is designed, the other
   2 — ask about and detail look different, make the boxes and pop ups the same
   as guidance picker."

   They already shared a base rule, so the pill SHAPE matched. What did not was
   everything the eye actually reads: `Guidance` drew its own quiet chevron and
   lifted on open, while `Ask about` and `Detail` were native <select>s wearing
   the platform's own control — a blue-tinted double arrow in its own inset
   box on macOS, which is why they read as a different family of thing.
   ========================================================================== */
.select-pill {
  position: relative;
  gap: .38rem;
  color: var(--muted);
}
.select-pill > select {
  /* Strip the platform control. Without this the OS draws its own arrow inside
     the pill and no amount of border work makes the three agree. */
  appearance: none;
  -webkit-appearance: none;
  min-height: 0;
  margin: 0;
  /* Room for the chevron drawn below. */
  padding: 0 .95rem 0 0;
  border: 0;
  border-radius: 0;
  color: var(--ink);
  background: transparent;
  font-size: .77rem;
  font-weight: 700;
  line-height: 1.2;
  cursor: pointer;
}
.select-pill > select:focus { outline: none; }
/* The same chevron `.compact-options > summary::after` draws, in the same
   colour, at the same size — so the row reads as three of one thing. */
.select-pill::after {
  content: "⌄";
  position: absolute;
  right: .58rem;
  color: var(--muted);
  font-size: .8rem;
  pointer-events: none;
}
/* And the same lift on open. A <select> has no [open], so the state it does
   have — focus, which is exactly when its menu is showing — carries it. */
.select-pill:focus-within {
  color: var(--accent-dark);
  border-color: var(--accent);
  background: var(--accent-soft);
}
.select-pill:focus-within > select { color: var(--accent-dark); }
.select-pill:focus-within::after { color: var(--accent-dark); }

/* A picker must never be able to hide a row.
   `.compact-options-menu` opens UPWARD with no height cap and no scroll, so a
   list taller than the space above the button loses its FIRST entries off the
   top of the screen with no way to reach them — and the first two entries are
   ADB Vol 1 and Vol 2. Five documents measure 264px today, which fits; a sixth
   document, a shorter window or a zoomed page does not. Bounded and scrollable
   costs nothing now and cannot silently drop a document later. */
.compact-options-menu {
  max-height: min(60vh, 420px);
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* ── MEASURED GEOMETRY, one layer at a time ────────────────────────────────
   The owner asked for this inside the product, not as a file beside a probe
   run. The overlay sizes to the IMAGE and never to the scroll box: an SVG at
   `inset: 0` inside a capped scroller takes the VIEWPORT's height and the
   whole overlay lands shifted, which reads as a rendering glitch and is a
   coordinate-space bug. */
.geometry-panel { margin: 16px 0; padding: 14px 16px; border: 1px solid var(--line, #e3e3e3); border-radius: 10px; }
.geometry-panel h4 { margin: 4px 0 2px; }
.geom-controls { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center; margin: 10px 0; }
.geom-kind { display: inline-flex; align-items: center; gap: 5px; font-size: 13px; white-space: nowrap; }
.geom-dot { width: 11px; height: 11px; border-radius: 2px; display: inline-block; }
.geom-stage { overflow: auto; max-height: 68vh; border: 1px solid var(--line, #e3e3e3); border-radius: 8px; }
.geom-frame { position: relative; width: 100%; }
.geom-frame img { display: block; width: 100%; }
.geom-frame .geom-noimage { width: 100%; padding-top: 66%; background: #fafafa; }
.geom-frame svg { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
.geom-space, .geom-route, .geom-pick { cursor: pointer; }
.geom-space.hidden, .geom-route.hidden { display: none; }
.geom-list { max-height: 24vh; overflow: auto; margin-top: 10px; }
.geom-list table { border-collapse: collapse; width: 100%; font-size: 13px; }
.geom-list th, .geom-list td { text-align: left; padding: 4px 10px; border-bottom: 1px solid var(--line, #eee); }
.geom-list .num { text-align: right; font-variant-numeric: tabular-nums; }
.geom-list tr.faded td { opacity: 0.45; }
.geom-list tr.chosen td { font-weight: 600; background: rgba(37, 99, 235, 0.08); }
.geom-list tr.over td { color: #b91c1c; }

/* ── SMOKE AND HEAT: the zone model beside the measured routes (9 Sep 2026) ── */
.simulation-panel .sim-body { display: flex; flex-direction: column; gap: 12px; margin-top: 8px; }
.simulation-panel h4 { margin: 0 0 2px; font-size: .86rem; }
.simulation-panel .sim-block { min-width: 0; }
.simulation-panel .sim-summary-warn { color: var(--warning, #8f5a12); }
.sim-list { max-height: 34vh; }
.sim-list td.sim-why { font-size: 12px; color: var(--muted); }
.sim-list tr.sim-row { cursor: pointer; }
.sim-list tr.sim-neg td { color: var(--danger, #b42318); font-weight: 600; }
.sim-list tr.sim-pos td.num { color: var(--success, #0f7a52); }
.sim-list tr.sim-neg td.sim-why, .sim-list tr.sim-pos td.sim-why { color: inherit; font-weight: 400; }
.sim-fire-tag { font-style: normal; font-size: .77rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--danger, #b42318); margin-left: .3rem; }
.sim-absent { margin: 0; }
.sim-frames { outline: none; border: 1px solid var(--line, #e3e3e3); border-radius: 8px; padding: 6px; }
.sim-frames:focus-visible { box-shadow: 0 0 0 2px var(--accent, #0668fc); }
.sim-frame-stage { position: relative; width: 100%; background: #fff; }
.sim-frame-stage img { display: block; width: 100%; }
.sim-frame-stage .sim-frame-base + .sim-frame-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.sim-frame-bar { display: flex; align-items: center; gap: 10px; margin-top: 6px; font-size: 13px; }
.sim-frame-bar input[type="range"] { flex: 1 1 auto; min-width: 120px; }
.sim-frame-time { font-variant-numeric: tabular-nums; font-weight: 600; min-width: 4.5em; }
.sim-frame-caption { color: var(--muted); }
.sim-curves-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; font-size: 13px; margin-bottom: 6px; }
.sim-curves-bar select { font-size: 13px; }
.sim-legend { color: var(--muted); display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.sim-key { display: inline-block; width: 18px; height: 0; border-top: 2px solid #2563eb; }
.sim-key-temp { border-top-color: #dc2626; }
.sim-key-crit { border-top: 1px dashed var(--muted); }
.sim-canvas { display: block; width: 100%; max-width: 760px; height: auto; border: 1px solid var(--line, #e3e3e3); border-radius: 8px; background: var(--surface, #fff); }
.sim-charts { display: flex; flex-wrap: wrap; gap: 10px; }
.sim-charts figure { margin: 0; flex: 1 1 300px; }
.sim-charts img { display: block; width: 100%; border: 1px solid var(--line, #e3e3e3); border-radius: 8px; }
.sim-charts figcaption { font-size: 12px; color: var(--muted); margin-top: 3px; }
.sim-questions { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.sim-question p { margin: 0; font-size: .82rem; line-height: 1.45; }
.sim-question-kind { font-style: normal; font-size: .77rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); margin-right: .3rem; }
.sim-question .drawing-feedback-form { margin-top: 4px; }
.sim-assumptions summary { cursor: pointer; font-size: .82rem; font-weight: 600; }
.sim-used, .sim-assumption-list { margin: 6px 0 0; padding-left: 18px; font-size: .8rem; line-height: 1.45; }
.sim-assumed { font-style: normal; font-size: .77rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--warning, #8f5a12); }
.sim-input-grid { display: grid; grid-template-columns: 1fr; gap: 6px; }
.sim-input { display: grid; grid-template-columns: minmax(150px, 1fr) minmax(80px, .6fr) minmax(160px, 2fr) auto; gap: 6px; align-items: center; position: relative; }
.sim-input-label { font-size: .8rem; }
.sim-input input { font-size: .82rem; min-width: 0; }
.sim-input .feedback-status { position: static; }
@media (max-width: 720px) { .sim-input { grid-template-columns: 1fr 1fr; } .sim-input-label { grid-column: 1 / -1; } }

/* The guidance viewer's stage is never blank: when the page cannot be shown
   it says why and names the printed page (9 Sep 2026). */
.guidance-viewer-notice { padding: .9rem 1rem; border: 1px dashed var(--border); border-radius: 8px; font-size: .8rem; line-height: 1.5; color: var(--muted); }
.guidance-viewer-notice p { margin: 0 0 .4rem; }
.guidance-viewer-notice b { color: var(--ink); }

/* ==========================================================================
   A PICKER THAT OPENS OFF THE TOP OF THE SCREEN — 18 August 2026

   THE OWNER: "In the research, I wanna click guidance. ADB volume one and two
   do not appear as an option. They do not show up."

   They were never missing. The manifest holds five, every file is on disk,
   `docs()` returns five, `/api/settings` returns five, the running server's own
   log says `full-context: ADB_Vol1, ADB_Vol2, BS_9991, BS_9999, PAS_9980`, and
   no renderer filters anything. The list was complete and the menu was hiding
   the top of it.

   `.compact-options-menu` was anchored `bottom: calc(100% + .45rem)` — it grows
   UPWARD from the button. Its contents are an intro paragraph, then the five
   documents, then the summary note: 270px. The button sits at the bottom of the
   composer, so on a fresh screen there is just enough room above it and
   everything shows. The moment there is an ANSWER on the page — that is, the
   moment the product has been used once — the composer scrolls up the window,
   and the menu opens through the top of it.

   Measured, scrolled so the button sat 120px down: menu top **-157px**, with
   ADB Vol 1, ADB Vol 2 and BS 9991 above the edge of the screen and
   `scrollHeight === clientHeight`, so nothing could be scrolled to. The two
   documents he could not find are the first two in the list, which is exactly
   why it was those two.

   Opening DOWNWARD removes the failure rather than mitigating it: the button
   is near the bottom of the composer and the answer area below it is the
   tallest space on the screen. The height cap and scroll stay as the backstop
   for a longer list on a short window.
   ========================================================================== */
.compact-options-menu {
  top: calc(100% + .45rem);
  bottom: auto;
}

/* ==========================================================================
   THE COMPOSER WAS CLIPPING ITS OWN MENU — 18 August 2026

   THE OWNER: "There's not even one of the guidance documents. None of them
   appears. I'm clicking on guidance, and nothing happens."

   THE ROOT CAUSE, and it was in the reskin all along.
   `.task-composer` is declared `overflow: visible` at its own rule, and the
   comment history says why: the guidance menu is a child of the composer and
   has to escape the box. The reskin then wrote `.task-composer { overflow:
   hidden; }` — to stop the square-cornered textarea poking out of the rounded
   composer — and that one word put the menu back inside a clipping box.

   It explains BOTH reports exactly. Opening UPWARD, the menu ran off the top
   of the composer, so the rows still inside it — the LAST three — were the
   only ones drawn: "ADB Vol 1 and 2 do not show up". Opening downward, which
   I changed it to, put the whole menu below the composer's bottom edge:
   "none of them appears, nothing happens".

   Both of my earlier attempts treated the position. The position was never the
   problem. A menu cannot be positioned out of a box that clips it.

   The corners are kept the way they were meant to be kept — by rounding the
   pieces, not by clipping the parent.
   ========================================================================== */
.task-composer { overflow: visible; }
.task-composer > textarea { border-radius: var(--radius) var(--radius) 0 0; }
.task-composer > .composer-footer { border-radius: 0 0 var(--radius) var(--radius); }

/* The composer's three pickers, drawn by us so they are the same picker on
   every operating system. See `upgradeSelectPill` in app.js for why the native
   <select> menu could never be made to match: it is drawn by the OS. */
.select-menu > summary { gap: .38rem; }
.select-menu-label { color: var(--muted); }
.select-menu-value { color: var(--ink); }
.select-menu[open] > summary .select-menu-label,
.select-menu[open] > summary .select-menu-value { color: var(--accent-dark); }
.select-menu > .compact-options-menu { min-width: 190px; padding: .35rem; }
.select-menu-list { display: grid; gap: 1px; }
.select-option {
  display: flex;
  align-items: center;
  gap: .4rem;
  width: 100%;
  padding: .42rem .5rem;
  border: 0;
  border-radius: 3px;
  color: var(--ink);
  background: transparent;
  font-size: .77rem;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
}
.select-option:hover { background: var(--surface-subtle); }
.select-option.is-selected { font-weight: 700; background: var(--accent-soft); }
/* The tick sits in its own column so the labels stay on one left edge whether
   or not a row is the chosen one. */
.select-option::before {
  content: "";
  flex: 0 0 auto;
  width: .8rem;
  color: var(--ink);
  font-size: .8rem;
  line-height: 1;
}
.select-option.is-selected::before { content: "✓"; }

/* ==========================================================================
   THE PROJECT'S OWN SCREEN — where a job is MANAGED, not reported on

   THE OWNER, 18 August 2026: "It's not there just to show you what has
   happened. It's actually the tab where you manage the entire project... I
   want you effectively to remove all those options from the sidebar to the
   left. On the left, I only wanna have projects."

   So the controls were MOVED, not copied: the scope form, the guidance picker
   and the four lists are the same elements that used to sit in the rail, with
   their ids and their listeners intact. What changes here is only that they
   are no longer being asked to live in 155px of a navigation bar. Rules below
   undo the rail's own compression, which was the right answer in a rail and
   the wrong one on a full-width screen.
   ========================================================================== */
/* The surface centres its children, so a grid child shrinks to its own
   content unless it is told to fill: the two file lists were stacking at
   531px inside a 937px surface. */
.project-overview {
  display: grid; gap: 1rem; width: 100%; max-width: 1400px;
  margin-inline: auto;
}
/* ==========================================================================
   THE PROJECT MAP.
   A spatial view of ONE job: what is in it, what it produced, what is
   missing. It is a navigation layer — every folder it opens holds the real
   control that has always been there.

   OFF BY DEFAULT. `body[data-project-canvas="off"]` is the product as it
   ships: the map is not drawn, the drawer is an ordinary block, and every
   folder is open on the page. Nothing on this screen is positioned or hidden
   by script in that state, so a broken map cannot cost the engineer a
   control. `?canvas=1` turns it on.
   ========================================================================= */
.project-canvas-header {
  display: flex; align-items: end; justify-content: space-between; gap: 1rem;
}
.project-canvas-header h3 {
  margin: 0; font-family: var(--font-serif); font-size: 1.65rem;
  font-weight: 400; letter-spacing: -.015em;
}
.project-canvas-header p { margin: .2rem 0 0; color: var(--muted); font-size: .78rem; }
.project-canvas-zoom {
  display: flex; align-items: center; gap: .25rem; padding: .25rem;
  border: 1px solid var(--border); border-radius: 8px; background: var(--surface);
}
.project-canvas-zoom .icon-button { border: 0; background: transparent; }
.project-zoom-value {
  min-width: 48px; border: 0; color: var(--muted); background: transparent;
  font-size: .77rem; font-variant-numeric: tabular-nums;
}
.project-canvas {
  position: relative; overflow: hidden;
  border: 1px solid var(--border); border-radius: 12px; background: var(--surface);
  box-shadow: var(--shadow);
}
/* The technical grid. Two rulings, the coarse one every fifth line, so the
   eye reads distance on the sheet the way it reads it on a drawing. */
.project-canvas-viewport {
  position: relative; height: clamp(540px, 70vh, 760px);
  overflow: hidden; cursor: grab; touch-action: none;
  background-color: var(--surface);
  background-image: radial-gradient(
    circle,
    color-mix(in srgb, var(--ink) 13%, transparent) 1px,
    transparent 1.15px
  );
  background-size: 18px 18px;
}
.project-canvas-viewport.is-panning { cursor: grabbing; }
/* Pinned to the middle of the sheet. Script only moves and scales it from
   there, so "reset" is always the whole job, centred. */
.project-canvas-world {
  position: absolute; left: 50%; top: 50%; transform-origin: 50% 50%;
  transition: transform .16s ease;
}
/* While a drag is in flight the world must follow the pointer exactly, so the
   easing that makes a zoom step look smooth is switched off. */
.project-canvas-viewport.is-panning .project-canvas-world { transition: none; }
.project-connections { position: absolute; z-index: 1; inset: 0; overflow: visible; pointer-events: none; }
.project-connection {
  fill: none; stroke: color-mix(in srgb, var(--ink) 38%, transparent);
  stroke-width: 1.25; stroke-dasharray: 5 6; vector-effect: non-scaling-stroke;
}
/* A drawing PRODUCES a drawing review. The accent marks the lines that carry
   a piece of work forward, so the map is read as a sequence, not a star. */
.project-connection-produces { stroke: color-mix(in srgb, var(--accent) 62%, transparent); }
.project-nodes { position: absolute; z-index: 2; inset: 0; }
.project-map-group {
  position: absolute; z-index: 0; pointer-events: none;
  border: 1px solid color-mix(in srgb, var(--accent) 28%, var(--border));
  border-radius: 12px;
  background: color-mix(in srgb, var(--accent) 3%, transparent);
}
.project-map-group > span {
  position: absolute; top: 12px; left: 14px; display: inline-flex;
  align-items: center; gap: .35rem; color: var(--muted);
  font-size: .77rem; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase;
}
.project-map-group > span::before {
  content: ""; width: 10px; height: 8px; border: 1px solid currentColor;
  border-radius: 2px;
}
.project-node {
  position: absolute; z-index: 2; display: grid;
  grid-template-columns: 34px minmax(0, 1fr);
  align-items: center; gap: .7rem; padding: .8rem;
  border: 1px solid color-mix(in srgb, var(--ink) 18%, transparent); border-radius: 9px;
  color: var(--ink); background: color-mix(in srgb, var(--surface-raised) 96%, transparent);
  box-shadow: 0 5px 18px rgba(14,17,22,.07);
  text-align: left; transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.project-node:hover { border-color: var(--ink); box-shadow: 0 7px 20px rgba(14,17,22,.10); transform: translateY(-2px); }
.project-node.is-active { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
/* An empty folder is not a failure and is not styled as one. It is drawn
   quieter, and it says which feature is working with nothing. */
.project-node.is-empty { border-style: dashed; box-shadow: none; }
.project-node.is-empty .project-node-icon { color: var(--muted); }
.project-node-text { min-width: 0; }
.project-node strong, .project-node small { display: block; }
/* Two lines, then an ellipsis: a project name is a sentence more often than a
   word, and "Clapham - dormitory ref..." on one line names nothing. */
.project-node strong {
  display: -webkit-box; overflow: hidden; font-size: .79rem; line-height: 1.25;
  -webkit-box-orient: vertical; -webkit-line-clamp: 2;
}
.project-node small { margin-top: .28rem; color: var(--muted); font-size: .77rem; line-height: 1.35; }
.project-node small b { color: var(--ink); font-weight: 650; }
.project-node-icon {
  display: grid; place-items: center; width: 34px; height: 34px;
  border-radius: 7px; color: var(--ink); background: var(--surface-subtle);
}
.project-node-icon-blue { color: var(--accent); background: var(--accent-soft); }
.project-node-centre { border-color: var(--ink); background: var(--ink); color: var(--surface); }
.project-node-centre .project-node-icon { color: var(--ink); background: var(--surface); }
.project-node-centre small { color: color-mix(in srgb, var(--surface) 72%, transparent); }
.project-node-centre small b { color: var(--surface); }
.project-canvas-drawer {
  position: absolute; z-index: 4; inset: 0 0 0 auto; width: min(450px, 48%); overflow-y: auto;
  border-left: 1px solid var(--border); background: var(--surface-raised);
  box-shadow: -16px 0 34px rgba(14,17,22,.10);
}
.project-drawer-head {
  position: sticky; z-index: 2; top: 0; display: flex; align-items: center;
  justify-content: space-between; gap: 1rem; padding: 1rem 1.1rem;
  border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--surface-raised) 95%, transparent);
  backdrop-filter: blur(8px);
}
.project-drawer-head h3 { margin: 0; font-family: var(--font-serif); font-size: 1.3rem; font-weight: 400; }
.project-drawer-head h3:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.project-pane { padding: .85rem; }
.project-pane .tool-card { border: 0; box-shadow: none; }
.project-index { margin-bottom: .75rem; padding: .9rem; border: 1px solid var(--border); border-radius: 8px; background: var(--surface-subtle); }
.project-index p { margin-bottom: .7rem; color: var(--muted); font-size: .77rem; line-height: 1.45; }
.project-index nav { display: flex; flex-wrap: wrap; gap: .35rem; }
.project-index nav button { padding: .32rem .5rem; border: 1px solid var(--border); border-radius: 6px; color: var(--ink); background: var(--surface); font-size: .77rem; }
.project-index nav button:hover { border-color: var(--accent); color: var(--accent); }
.project-version-panel { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--border); }
.project-version-head { display: grid; gap: .7rem; }
.project-version-head h4 { margin: 0; font-size: .86rem; }
.project-version-actions { display: flex; flex-wrap: wrap; gap: .4rem; }
.project-version-list { display: grid; gap: .35rem; margin: .8rem 0 0; padding: 0; list-style: none; }
.project-version-list li { display: grid; grid-template-columns: auto 1fr; gap: .18rem .55rem; padding: .55rem .6rem; border: 1px solid var(--border); border-radius: 6px; font-size: .77rem; }
.project-version-list time { grid-column: 2; color: var(--muted); font-size: .77rem; }
.document-history {
  flex: 0 0 auto; padding: .25rem .38rem; border: 0; color: var(--muted);
  background: transparent; font-size: .77rem;
}
.document-history:hover { color: var(--accent); }
.project-conversation-list { display: grid; gap: .25rem; }
.project-conversation-list .project-item { border: 1px solid var(--border); }

/* The scope box spans the panel: it is one question, not a fifth column. */
.health-basis-scope { grid-column: 1 / -1; }
.health-basis-scope textarea { width: 100%; min-height: 58px; padding: 9px 10px; border: 1px solid var(--border-strong); border-radius: 3px; color: var(--ink); background: var(--surface-raised); font: inherit; font-size: .8rem; resize: vertical; }

/* ── the revision loop ──────────────────────────────────────────────────── */
.health-loop-bar { display: flex; flex-wrap: wrap; gap: .3rem 1.1rem; padding: .75rem .9rem; margin-bottom: 14px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); }
.health-loop-step { display: flex; align-items: center; gap: .45rem; color: var(--muted); font-size: .77rem; }
.health-loop-dot { display: grid; place-items: center; width: 20px; height: 20px; border: 1px solid var(--border); border-radius: 50%; font-size: .77rem; font-variant-numeric: tabular-nums; }
.health-loop-step.is-done { color: var(--ink); }
.health-loop-step.is-done .health-loop-dot { color: var(--surface); border-color: var(--ink); background: var(--ink); }
.health-loop-step.is-active { color: var(--ink); font-weight: 650; }
.health-loop-step.is-active .health-loop-dot { border-color: var(--ink); border-width: 2px; }
.health-respond { margin-top: .7rem; }
.health-respond-form { display: grid; gap: .5rem; margin-top: .55rem; padding: .7rem; border: 1px solid var(--border); border-left: 2px solid var(--ink); border-radius: 8px; background: var(--surface); }
.health-respond-stances { display: grid; gap: .3rem; }
.health-respond-stances label { display: flex; align-items: center; gap: .45rem; color: var(--ink); font-size: .77rem; }
.health-respond-form textarea, .health-question textarea { width: 100%; min-height: 48px; padding: 8px 10px; border: 1px solid var(--border-strong); border-radius: 3px; color: var(--ink); background: var(--surface-raised); font: inherit; font-size: .78rem; resize: vertical; }
.health-questions { margin-top: clamp(20px, 3vw, 28px); padding-top: 14px; border-top: 2px solid var(--ink); }
.health-questions h4 { margin: 0 0 4px; font-family: var(--font-serif); font-size: 1.12rem; font-weight: 400; }
.health-question { display: grid; gap: .4rem; margin-top: .7rem; padding: .7rem .8rem; border: 1px solid var(--border); border-radius: 8px; background: var(--surface-raised); }
.health-question p { margin: 0; font-size: .8rem; }
.health-question small { color: var(--muted); }
.health-loop-gate { display: grid; gap: .7rem; padding: .9rem; border: 1px solid var(--border); border-left: 2px solid var(--ink); border-radius: 8px; background: var(--surface); }
.health-loop-gate p { margin: 0; font-size: .8rem; line-height: 1.6; }
.health-revise-note { margin: 0 0 .6rem; color: var(--warning); font-size: .78rem; font-weight: 600; }
.health-revise-note.is-closed { color: var(--success); }

/* ── the section census - "what complete strategies carry" ──────────────── */
.section-census { margin-top: clamp(20px, 3vw, 28px); padding-top: 14px; border-top: 2px solid var(--ink); }
.section-census h4 { margin: 0 0 4px; font-family: var(--font-serif); font-size: 1.12rem; font-weight: 400; }
.section-census > .muted { font-size: .77rem; }
.section-census-clear { color: var(--success); font-size: .82rem; }
.section-census-label { margin: 12px 0 6px; font-size: .77rem; font-weight: 650; letter-spacing: .05em; text-transform: uppercase; }
.section-census-list { display: grid; gap: .45rem; margin: 0; padding: 0; list-style: none; }
.section-census-list li {
  position: relative; display: grid; gap: .2rem; padding: .6rem .75rem .6rem 1rem;
  border: 1px solid var(--border); border-radius: 8px; background: var(--surface-raised);
}
/* The same black spine as the assessment basis rows - one family. */
.section-census-list li::before {
  content: ""; position: absolute; top: .7rem; bottom: .7rem; left: 0;
  width: 2px; border-radius: 2px; background: var(--ink);
}
.section-census-list strong { font-size: .8rem; }
.section-census-list span { color: var(--muted); font-size: .77rem; line-height: 1.5; }
.section-census-condition { font-style: italic; }
.section-census-list small { color: var(--detail-info); font-size: .77rem; }
.section-census-more { margin-top: 10px; }
.section-census-more summary { color: var(--muted); font-size: .77rem; cursor: pointer; }
.section-census-more ul { margin-top: 8px; }

/* ── the map switched OFF: the screen the product ships today ────────────── */
body[data-project-canvas="off"] :is(.project-canvas-header, .project-canvas-viewport, .project-drawer-head) { display: none; }
body[data-project-canvas="off"] .project-canvas { overflow: visible; border: 0; background: none; box-shadow: none; }
body[data-project-canvas="off"] .project-canvas-drawer {
  position: static; width: auto; overflow: visible; border: 0; box-shadow: none; background: none;
}
body[data-project-canvas="off"] .project-pane { padding: 0; }
body[data-project-canvas="off"] .project-pane .tool-card { border: 1px solid var(--border); }
body[data-project-canvas="off"] .project-index { display: none; }

/* The drawer already names the folder. The card inside it named it a second
   time, so "Architect drawings" was printed twice, 60px apart. Only the
   title block goes; a control that lives in the same head (Start new) stays. */
body[data-project-canvas="on"] .project-pane .feature-card-head > div:first-child { display: none; }
body[data-project-canvas="on"] .project-pane .feature-card-head { justify-content: flex-end; }
.project-block { padding: 1.15rem 1.3rem; }
.project-block > h3 { margin: .25rem 0 .3rem; }
.project-block > .muted { margin: 0 0 .95rem; font-size: .78rem; }

/* Two lists side by side where there is room; stacked where there is not. */
.project-lists { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1.1rem; }
.project-lists .sidebar-section { margin: 0; padding: 0; }
.project-lists .section-label { margin-bottom: .5rem; font-size: .77rem; }
.project-lists .document-list { display: grid; gap: .3rem; max-height: none; }
.project-lists .empty-copy { margin: 0; padding: .55rem .1rem; font-size: .77rem; font-style: italic; color: var(--detail-warn); }
/* A file row on this screen is a row in a table, not an entry squeezed into a
   rail: full width, readable, and the delete stays where the eye expects it. */
.project-lists .document-row { border: 1px solid var(--border); border-radius: var(--radius); }
.project-lists .document-item { width: 100%; padding: .5rem .6rem; font-size: .8rem; }
.project-lists .document-item span:last-child { white-space: normal; word-break: break-word; }

/* The scope panel was a <details> because the rail could not spare the height.
   The screen can, so it is open and its summary is a heading rather than a
   control that invites folding away the thing the screen exists for. */
#project-surface .project-settings { margin: 0; border: 0; background: none; }
#project-surface .project-settings > summary { display: none; }
#project-surface .project-settings-body { padding: 0; }
#project-surface .project-settings-body > label,
#project-surface .project-settings-body .guidance-field-label,
#project-surface .project-settings-body .adb-question { color: var(--ink); font-size: .78rem; }
#project-surface .project-settings-body :is(select, textarea) {
  color: var(--ink);
  border-color: var(--border);
  background: var(--control-bg);
  font-size: .8rem;
}
#project-surface .project-settings-body :is(select, textarea):focus {
  border-color: var(--ink);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ink) 10%, transparent);
}
#project-surface .project-settings-body textarea::placeholder { color: var(--muted); }
#project-surface .project-settings-body .settings-note { color: var(--muted); }
#project-surface .guidance-picker { display: grid; gap: .3rem; }

/* ── narrow screens: an ORDERED LIST OF FOLDERS, never a shrunken map ─────
   A map read on a phone is a picture of a map. The same nodes, the same
   counts and the same folders become a grid; the connectors go, because a
   line that cannot be followed says nothing. The world's size and each
   node's position are set INLINE by script, so these have to win. */
@media (max-width: 820px) {
  .project-canvas-header { align-items: start; }
  .project-canvas-zoom { display: none; }
  .project-canvas { overflow: visible; border: 0; box-shadow: none; }
  .project-canvas-viewport {
    position: static; height: auto; overflow: visible; cursor: auto;
    background-image: none;
  }
  .project-canvas-world {
    position: static; left: auto; top: auto;
    width: auto !important; height: auto !important;
    margin: 0; transform: none !important;
  }
  .project-connections { display: none; }
  .project-map-group { display: none; }
  .project-nodes {
    position: static; display: grid; gap: .65rem;
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .project-node, .project-node-centre {
    position: static; width: auto !important; min-height: 92px !important;
    transform: none;
  }
  .project-node-centre { grid-column: 1 / -1; }
  .project-canvas-drawer {
    position: static; width: auto; max-height: none; margin-top: .8rem;
    border: 1px solid var(--border); border-radius: 8px; box-shadow: none;
  }
  .project-drawer-head { position: static; }
  .project-lists { grid-template-columns: 1fr; }
}

@media (max-width: 520px) {
  .project-nodes { grid-template-columns: 1fr; }
  .project-node-centre { grid-column: auto; }
}

/* ── dark mode. The grid and the connectors are drawn from --ink, which is
   already inverted by the theme, so only the sheet and the shadows need
   saying: a light-mode shadow on a dark sheet reads as a smudge. */
:root[data-theme="dark"] .project-canvas-viewport { background-color: var(--surface); }
:root[data-theme="dark"] :is(.project-node, .project-canvas-drawer) { box-shadow: none; }
:root[data-theme="dark"] .project-node:hover { box-shadow: 0 7px 20px rgba(0,0,0,.45); }
/* The centre card needs no dark rule: it is painted from --ink on --surface,
   and the theme swaps both. Restating it here is how the two drift apart. */

/* Someone who asked for less motion still gets the map; it just stops
   sliding under them. */
@media (prefers-reduced-motion: reduce) {
  .project-canvas-world { transition: none; }
  .project-node:hover { transform: none; }
}

/* ==========================================================================
   THE RAIL IS A COLUMN OF THE SCREEN, NOT OF THE DOCUMENT — 18 August 2026

   THE OWNER: "the plan usage, the settings, the sign out, they should all be
   at the bottom of the page, not under the projects." And: "at the bottom now,
   you again have that black box that should not be there... It seems like to
   always appear when the page is large and has a lot of content."

   Both are the same fact about the rail. `.sidebar` was a flex column in
   normal flow, so its children stacked from the top — plan usage sat directly
   under the last project — and it had to STRETCH to the height of the whole
   document to keep its background under itself. On a long page that is a
   2,200px tall element whose paint has to keep up with the scroll, and any
   moment it does not is a strip of unpainted canvas at the bottom left.

   The rail now has the height of the SCREEN and stays there. Projects take the
   slack, so usage, settings and sign out sit on the bottom edge where they
   belong, and the list scrolls inside itself rather than growing the page.

   And the rail's colour is painted by the GRID, across the full height of the
   column, so it can no longer depend on one element covering the document. If
   the rail is ever shorter than the page again, the ground under it is already
   painted. `html` is painted for the same reason: the browser's own canvas —
   what shows past the end of a scroll — is then never anything but paper.
   ========================================================================== */
html { background: var(--main-bg); }

/* --rail-w is the LEFT SIDEBAR's painted width (this block predates the
   right-hand chat rail and named the sidebar "rail"). THREE fixes in one,
   all found live on 3 Sep 2026 when clicking a chat from another surface
   blanked the screen:
   1. This rule declared only TWO grid tracks and, being last, beat every
      three-track rule above - so the chat rail wrapped below the sidebar
      (the owner's "it drops me below the settings section").
   2. The engineer's drag writes --sidebar-width, but the winning column
      read --rail-w - so resizing changed nothing on screen even after
      the pointer-capture fix. --rail-w now FOLLOWS --sidebar-width.
   3. The third track is the chat rail, same as every other variant. */
:root { --rail-w: 265px; }
#workspace-view { --rail-w: var(--sidebar-width, 265px); }
@media (max-width: 1000px) {
  :root { --rail-w: 220px; }
  #workspace-view { --rail-w: var(--sidebar-width, 220px); }
}
#workspace-view.sidebar-collapsed { --rail-w: 58px; }

#workspace-view {
  grid-template-columns: var(--rail-w) minmax(0, 1fr) var(--rail-width, 0px);
  background-image: linear-gradient(
    to right,
    var(--sidebar-bg) 0 var(--rail-w),
    var(--main-bg) var(--rail-w));
}

.sidebar {
  position: sticky;
  top: 0;
  align-self: start;
  height: 100vh;
  min-height: 0;
}
/* Projects take the slack. There is one section left in the rail now, and it
   is the one that should grow. */
.sidebar > .sidebar-section {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}
#usage-meter, .sidebar-settings, .sidebar-foot { flex: 0 0 auto; }
#usage-meter { margin-top: auto; }

/* The scope panel, compact. THE OWNER: "maybe be more compact... maybe there's
   a better way to design this." Two changes, both structural rather than
   cosmetic: the rarely-answered ADB question folds away until it is wanted,
   and the building-type fallback is not drawn at all once guidance is pinned,
   so the panel is three fields on a typical job instead of five. */
#project-surface .project-settings-body { display: grid; gap: .75rem; }
#project-surface .project-settings-body > label { display: grid; gap: .25rem; }
#project-surface .project-settings-body .settings-note { margin: 0; font-size: .77rem; line-height: 1.35; }
#project-surface .project-settings-body textarea { min-height: 76px; }

.project-detail { border: 1px solid var(--border); border-radius: var(--radius); }
.project-detail > summary {
  display: flex;
  align-items: center;
  gap: .4rem;
  padding: .5rem .6rem;
  cursor: pointer;
  list-style: none;
}
.project-detail > summary::-webkit-details-marker { display: none; }
.project-detail > summary::after { content: "⌄"; margin-left: auto; color: var(--muted); font-size: .85rem; }
.project-detail[open] > summary::after { content: "⌃"; }
.project-detail[open] > summary { border-bottom: 1px solid var(--border); }
.project-detail-body { display: grid; gap: .6rem; padding: .65rem .6rem .75rem; }
#project-surface .adb-question { display: grid; gap: .25rem; font-size: .78rem; }

/* ==========================================================================
   ONE LEFT EDGE — 18 August 2026

   THE OWNER: "the writer is located in a different location, like slightly
   over compared to the other features... Actually, the project is also not in
   the same place. It's slightly to the left. All these features and their text
   should be at the right place. No a bit left, no a bit to the right because
   that makes it a little unprofessional."

   Measured at 1265px: the page title and the tabs both start at 297px, the
   four feature cards at 363px, the project screen at 303px and Admin at 297px.
   Four edges on one page.

   The cause is `place-items: start center` on `.tool-surface`, which centres
   each surface's content inside a column whose own left edge is already set by
   the title above it. The card was centred against the column while everything
   around it was aligned to the column's start.

   Every surface now begins where the title begins and shares one maximum
   width, so nothing has to be lined up by eye again.
   ========================================================================== */
.tool-surface { place-items: start stretch; }
.tool-surface > * {
  width: 100%;
  max-width: var(--content-w, 940px);
  margin-inline: auto;
}
/* Feature cards stay centred on ultrawide displays while retaining one shared
   content width.  This fixes the large dead strip that appeared on the right. */
.writer-shell, .generate-panel { margin-inline: auto; }
#project-surface > .project-overview { max-width: 1400px; }

/* ==========================================================================
   A DOCUMENT USES THE SCREEN IT IS GIVEN (owner, 12 Sep 2026, reading his own
   Rev 02 in the editor with the sidebar already minimised):

     "there's so much, like, empty space, like, gray empty space that I think
      could be utilised... the text is trying to be squeezed when there's so
      much empty space. I think we can take advantage of the space to give
      more space to the text."

   He was looking at a Word page squeezed into about 600 px beside a 360 px
   rail, with roughly a thousand pixels of grey either side of it. The
   two-pane editing layout was AUTHORED for 1400 px - the rule twelve lines
   above sets exactly that - and the generic 940 px content cap above silently
   beat it, because `max-width` outranks `width`. So the wide layout has never
   once been drawn at the width it was designed for.

   Only the workbenches are released: a document, a review or a drawing is a
   PAGE and wants the space. Prose surfaces (library, calculations, research)
   keep their reading measure, because a 1,500 px line of body text is worse
   to read, not better.
   ========================================================================== */
#write-surface .tool-surface > *,
#review-surface .tool-surface > *,
#document-surface .tool-surface > *,
#drawings-surface .tool-surface > *,
.tool-surface > .writer-shell,
.tool-surface > .drawing-workspace {
  max-width: none;
}
/* The composer on its own is still a form, and a form does not want 1,500 px
   of width - it is only the document beside its rail that does. */
.tool-surface > .writer-shell:not(:has(#writer-edit-panel:not([hidden]))) {
  max-width: min(1100px, 100%);
}
.writer-shell:has(#writer-edit-panel:not([hidden])) { width: 100%; }

/* A disabled action is GREY, not a faded black. `opacity: .48` on a black
   button is still black, just softer, so "you cannot press this" read as
   "this is the main action". The border and the not-allowed cursor carry the
   rest of the message. */
.button.primary:disabled,
.button.primary[disabled] {
  opacity: 1;
  color: var(--muted);
  border-color: var(--border);
  background: var(--surface-subtle);
}
.button.primary:disabled:hover { background: var(--surface-subtle); }

/* THE OWNER: "when I select the project, it has a black kind of line on the
   left side which shows that it's been selected, but it's not really visible.
   You could make projects that are selected a little bit more visible."

   The rail is one list now, so the selected row is the single most important
   piece of state on it: it names the project every other screen is about.
   A 3px rule and a 5% fill was the right weight when it competed with eight
   other sections; on its own it reads as nothing. Three signals instead of
   one — a wider rule, a fill with contrast against the rail, and the name in
   full ink and weight. */
:root:not([data-theme="dark"]) :is(
  .project-row.active > .project-item,
  .project-item.active
) {
  color: var(--sidebar-fg);
  background: #e4e4dd;
  box-shadow: inset 4px 0 0 var(--sidebar-fg);
  font-weight: 700;
}
:root[data-theme="dark"] :is(
  .project-row.active > .project-item,
  .project-item.active
) {
  color: #f6f6f3;
  background: #2e2e2a;
  box-shadow: inset 4px 0 0 #f6f6f3;
  font-weight: 700;
}
.project-row.active { border-radius: var(--radius); }

/* WHICH GUIDANCE THIS ANSWER CAME OUT OF.
   Sits between the safety notices and the answer body, so it is read BEFORE
   the answer rather than discovered under it. The drawing review has always
   shown this; research sent the same field and drew nothing, and an answer
   taken from the wrong volume reads exactly like a correct one. */
.guidance-used {
  display: flex; flex-wrap: wrap; align-items: center; gap: .4rem;
  margin: 0 0 .75rem; font-size: .8125rem; line-height: 1.4;
}
.guidance-used-label { color: var(--muted); }
.guidance-used-doc {
  display: inline-flex; align-items: center; padding: .15rem .5rem;
  border-radius: 999px; font-weight: 600;
  background: var(--accent-soft, rgba(37, 99, 235, .1));
  color: var(--accent, #2563eb);
  border: 1px solid var(--accent-border, rgba(37, 99, 235, .25));
}
/* Routed but NOT read — over the context ceiling. Deliberately not styled as
   an error: it is a narrower answer, not a wrong one, and the engineer needs
   to see that the two differ. */
.guidance-used-omitted {
  color: var(--warn-text, #92400e);
  background: var(--warn-soft, rgba(245, 158, 11, .12));
  border: 1px solid var(--warn-border, rgba(245, 158, 11, .3));
  border-radius: 999px; padding: .15rem .5rem;
}

/* ==========================================================================
   ONE CARD — 19 August 2026

   THE OWNER: "the project uses a different font. It seems like it has
   different fonts altogether... the project, the tabs, all the text is not in
   the right location, and the writer is not in the right location."

   Measured at 1265px, and he was right on every count. The outer cards all
   began at 297, which is what I checked last time and why I thought this was
   done. Inside them nothing agreed:

     card WIDTH      research 940 · review 940 · write 940 · PROJECT 820
     text starts at  research 320 · review 320 · DRAWINGS 320 · WRITE 314 · PROJECT 317
     heading         serif 20.25px everywhere · PROJECT sans 15.3px semibold

   Three causes, one each. The project's cards are nested inside the overview
   grid rather than being the surface's own children, so they kept
   `.tool-card`'s 820px instead of the shared 940. Every card carried its own
   padding — 1.5rem, 1.2rem, 1rem — and padding is what decides where the text
   starts. And the serif heading comes from `.feature-card-head h3`, a wrapper
   the project blocks did not use, so they silently fell back to the body face.

   The fix is not three new values. It is the same value in one place.
   ========================================================================== */
.tool-card,
.generate-panel,
.writer-header,
.admin-card,
.project-block { padding: 1.5rem; }
/* `.writer-shell` also carries `.tool-card`, but it is a WRAPPER around the
   writer's own cards, not a card. Padding it padded the writer twice and put
   its text at 343 against everyone else's 320 — the very fault this block
   exists to remove. */
.writer-shell { padding: 0; }

/* Project and Admin nest their cards one level deeper than the other
   surfaces, so a card there never met `.tool-surface > *` and kept
   `.tool-card`'s own 820px. The shared width has to reach them explicitly. */
.project-overview > .project-block,
#admin-surface .tool-card,
#admin-surface .admin-card { width: 100%; max-width: none; }
.generate-panel { width: 100%; max-width: none; }

/* The last three pixels, and they were not a stylesheet fault. A surface with
   more content brings a vertical scrollbar with it, and the scrollbar takes
   its width out of the page: Project measured 937 where Research measured 940,
   and the whole layout stepped sideways as the tabs were changed. Reserving
   the gutter means the page is the same width whether it scrolls or not. */
html { scrollbar-gutter: stable; }

/* THE OWNER, 19 August 2026: "the whole section is slightly up. That's the only
   difference, literally. All of the other features start at the same point, but
   the writer starts a bit higher up, closer to the features tabs."

   Measured: every surface sits 34px below the tab row; the writer sat at 19px.
   `.writer-surface { padding-top: 0 }` overrode the shared `.tool-surface`
   padding, and because both selectors weigh the same the later one simply won.
   Stated once, for both, so they cannot drift apart again — every horizontal
   number on these screens already agreed while this one did not, which is why
   it read as "slightly off" rather than as anything nameable. */
.tool-surface,
.writer-surface { padding-top: 1rem; }


/* ============================================================================
   ALLOWANCE BANDS, and the billing screen.

   The bar has three states and they must be legible without reading the words
   beside them: normal, "running low" at 20% or less, and "used" at nothing
   left. A customer who goes from a full bar to a hard refusal was never
   warned, and that is what happened here for as long as `renderUsageMeter()`
   was unreachable.

   These are ID selectors on purpose. Two later blocks in this file restate
   `.usage-meter-track span`'s background — once for the editorial dark rail
   and once for `:root:not([data-theme="dark"])` — and a plain class here would
   lose to both. The colours are the existing theme tokens, so both themes
   follow automatically.
   ========================================================================= */
#usage-meter.is-low .usage-meter-track span,
#billing-allowance.is-low .usage-meter-track span { background: var(--warning); }
#usage-meter.is-used .usage-meter-track span,
#billing-allowance.is-used .usage-meter-track span { background: var(--danger); }
#usage-meter.is-low .usage-meter-head span,
#usage-meter.is-used .usage-meter-head span { color: var(--sidebar-fg); font-weight: 700; }
#usage-meter.is-low .text-button,
#usage-meter.is-used .text-button { color: var(--sidebar-fg); }

/* The billing screen is the upgrade dialog's card, wider and scrollable: it
   carries a summary, a plan chooser, a top-up and the portal link, which is
   more than fits a phone screen at any font size. */
.billing-card {
  width: min(680px, 100%);
  max-height: min(88vh, 900px);
  overflow-y: auto;
  padding: 26px;
}
.billing-block {
  margin-top: 20px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
}
.billing-block h3 { margin: 0 0 10px; font-size: .95rem; }
.billing-facts {
  display: grid;
  gap: 10px 18px;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  margin: 0 0 16px;
}
.billing-facts div { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.billing-facts dt { color: var(--muted); font-size: .77rem; letter-spacing: .06em; text-transform: uppercase; }
.billing-facts dd { margin: 0; font-weight: 600; font-variant-numeric: tabular-nums; }
/* ID selectors again, and for the same reason: `:root:not([data-theme="dark"])
   .usage-meter-track span` further up weighs more than any two classes, and it
   paints the bar in the RAIL's foreground colour — right in the dark sidebar,
   wrong on a white dialog. */
#billing-allowance .usage-meter-head { color: var(--ink); }
#billing-allowance .usage-meter-head span { color: var(--muted); }
#billing-allowance .usage-meter-track { background: color-mix(in srgb, var(--ink) 12%, transparent); }
#billing-allowance .usage-meter-track span { background: var(--accent); }
.billing-interval-choice { display: flex; gap: 14px; margin-bottom: 12px; font-size: .8rem; }
.billing-interval-choice label { display: inline-flex; align-items: center; gap: .35rem; cursor: pointer; }
.billing-plan-cards {
  display: grid;
  gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}
.billing-plan-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-subtle);
}
.billing-plan-card.is-current { border-color: var(--accent); }
.billing-plan-card h4 { margin: 0; font-size: .92rem; }
.billing-plan-price { margin: 0; font-weight: 600; font-variant-numeric: tabular-nums; }
.billing-plan-card ul { margin: 0; padding-left: 1.05rem; color: var(--muted); font-size: .77rem; line-height: 1.5; }
.billing-plan-card .button { margin-top: auto; }
.billing-seats { display: flex; align-items: center; gap: .45rem; color: var(--muted); font-size: .77rem; }
.billing-seats input { width: 5.5rem; border: 1px solid var(--border); border-radius: 6px; padding: .35rem .45rem; color: var(--ink); background: var(--control-bg); }
.billing-amount { display: flex; align-items: center; gap: .5rem; margin: 10px 0 6px; font-size: .78rem; }
.billing-amount input { width: 7rem; border: 1px solid var(--border); border-radius: 6px; padding: .45rem .5rem; color: var(--ink); background: var(--control-bg); font-variant-numeric: tabular-nums; }
#billing-topup-quick { flex-wrap: wrap; }
#billing-topup-buy, #billing-portal { margin-top: 8px; }
.billing-card[aria-busy="true"] { opacity: .72; }

/* ========================================================================== 
   FIRE STRATEGY HEALTH CHECK
   A deliberately self-contained acquisition surface. The evidence-cyan
   diamond is the reusable visual asset; the rest follows the product's
   paper/ink system.
   ========================================================================== */
.health-shell {
  display: grid;
  gap: 18px;
  max-width: 1180px;
  margin: 0 auto;
}
.health-hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 168px;
  align-items: center;
  gap: 28px;
  padding: clamp(24px, 4vw, 48px);
  color: #fff;
  border-radius: 4px;
  background:
    linear-gradient(rgba(255,255,255,.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.045) 1px, transparent 1px),
    #0b0b0a;
  background-size: 30px 30px;
  overflow: hidden;
}
.health-hero .eyebrow { color: #fff; }
.health-hero h3 {
  max-width: 760px;
  margin-bottom: 10px;
  font-family: var(--font-serif);
  font-size: clamp(1.65rem, 3vw, 2.65rem);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: -.022em;
}
.health-hero p:last-child { max-width: 760px; margin: 0; color: rgba(255,255,255,.7); line-height: 1.65; }
.health-mini-diamond {
  color: color-mix(in srgb, var(--detail-info) 72%, white);
  filter: drop-shadow(0 8px 18px color-mix(in srgb, var(--detail-info) 24%, transparent));
}
.health-mini-diamond svg { display: block; width: 168px; }
.health-mini-diamond polygon:first-child { fill: none; stroke: rgba(255,255,255,.4); stroke-width: 1.25; }
.health-mini-diamond polygon:last-child { fill: currentColor; fill-opacity: .42; stroke: currentColor; stroke-width: 3.2; }
.health-state {
  padding: clamp(20px, 3vw, 34px);
  border: 1px solid var(--border);
  border-top: 2px solid var(--ink);
  border-radius: 4px;
  background: var(--surface-raised);
}
.health-upload-zone { border: 1px dashed color-mix(in srgb, var(--ink) 34%, transparent); background: var(--surface-subtle); }
.health-upload-zone.is-dragging { border-color: var(--detail-info); box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--detail-info) 18%, transparent); }
.health-upload-button {
  display: grid;
  place-items: center;
  gap: 7px;
  width: 100%;
  min-height: 180px;
  padding: 24px;
  border: 0;
  color: var(--ink);
  background: transparent;
}
.health-upload-button .icon { color: var(--detail-info); }
.health-upload-button strong { font-family: var(--font-serif); font-size: 1.25rem; font-weight: 400; }
.health-upload-button span { color: var(--muted); font-size: .77rem; }
.health-file-choice { display: flex; align-items: center; justify-content: space-between; gap: 18px; min-height: 126px; padding: 24px; }
.health-file-choice strong { display: block; max-width: 680px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.health-file-choice p { margin: 3px 0 0; }
.health-basis-panel { margin-top: 18px; padding: clamp(18px, 3vw, 28px); border: 1px solid var(--border); background: var(--surface-subtle); }
.health-basis-panel .feature-card-head { margin-bottom: 16px; }
.health-basis-panel h3 { margin: 2px 0 5px; font-family: var(--font-serif); font-size: 1.25rem; font-weight: 400; }
.health-basis-panel .feature-card-head p { max-width: 760px; margin: 0; color: var(--muted); font-size: .77rem; line-height: 1.55; }
.health-basis-summary { margin-top: 14px; }
.health-basis-summary p { margin: 0; }
.health-basis-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px; border: 1px solid var(--border); background: var(--border); }
.health-basis-grid > div { display: grid; gap: 4px; min-width: 0; padding: 13px; background: var(--surface-raised); }
.health-basis-grid span { color: var(--muted); font-size: .77rem; letter-spacing: .05em; text-transform: uppercase; }
.health-basis-grid strong { overflow: hidden; font-size: .77rem; text-overflow: ellipsis; }
.health-basis-grid small { color: var(--detail-info); font-size: .77rem; line-height: 1.4; }
/* THE ASSESSMENT BASIS ROWS. Each carries its own provenance line, because
   "ADB Vol 2" alone does not say whether the document stated it or the
   engineer corrected it, and those are different claims. */
.health-basis-row {
  position: relative; display: grid; gap: .3rem; padding: .7rem .8rem .7rem 1rem;
  border: 1px solid var(--border); border-radius: 8px; background: var(--surface);
}
/* A black spine on each row and a black rule over the panel. The owner asked
   for "a few black details" here on 24 Aug 2026: four white boxes on a white
   sheet gave the eye nothing to hold, and black is the brand's own weight. */
.health-basis-row::before {
  content: ""; position: absolute; top: .8rem; bottom: .8rem; left: 0;
  width: 2px; border-radius: 2px; background: var(--ink);
}
.health-basis-row label > span { color: var(--ink); font-weight: 650; }
.health-basis-panel {
  padding-top: 14px; border-top: 2px solid var(--ink);
}
.health-basis-panel .feature-card-head h3 { font-family: var(--font-serif); font-weight: 400; }
.health-basis-row label { display: grid; gap: .3rem; }
.health-basis-row label > span { color: var(--muted); font-size: .77rem; letter-spacing: .02em; text-transform: uppercase; }
.health-basis-origin { color: var(--muted); font-size: .77rem; }
.health-basis-row.is-changed { border-color: var(--accent); }
.health-basis-row.is-changed .health-basis-origin { color: var(--accent); font-weight: 600; }
/* Not an error. Nothing has gone wrong when a strategy does not print its
   own height; it is simply a question only the engineer can answer. */
.health-basis-row.is-missing { border-color: var(--warning); }
.health-basis-row.is-missing .health-basis-origin { color: var(--warning); }
.health-basis-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; margin-top: 16px; }
.health-basis-fields label { display: grid; gap: 7px; color: var(--ink); font-size: .77rem; font-weight: 650; }
.health-basis-fields select, .health-basis-fields input { width: 100%; min-height: 42px; padding: 9px 10px; border: 1px solid var(--border-strong); border-radius: 3px; color: var(--ink); background: var(--surface-raised); font: inherit; }
.health-number-field { display: grid; grid-template-columns: 1fr auto; align-items: center; }
.health-number-field input { grid-area: 1 / 1; padding-right: 54px; }
.health-number-field small { grid-area: 1 / 1; justify-self: end; padding-right: 12px; color: var(--muted); font-weight: 500; pointer-events: none; }
.health-privacy-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; margin-top: 18px; background: var(--border); border: 1px solid var(--border); }
.health-privacy-grid div { display: grid; gap: 5px; padding: 16px; background: var(--surface-raised); }
.health-privacy-grid strong { font-size: .77rem; }
.health-privacy-grid span { color: var(--muted); font-size: .77rem; line-height: 1.5; }
.health-start-row { display: flex; align-items: center; justify-content: space-between; gap: 18px; margin-top: 18px; }
.health-start-row p { margin: 0; }
.health-running { display: grid; grid-template-columns: 150px 1fr; align-items: center; gap: 32px; min-height: 250px; }
.health-running h3 { font-family: var(--font-serif); font-size: 1.65rem; font-weight: 400; }
.health-running-diamond { position: relative; width: 130px; height: 130px; animation: health-turn 12s linear infinite; }
.health-running-diamond span { position: absolute; inset: 18px; border: 1px solid color-mix(in srgb, var(--detail-info) 55%, transparent); transform: rotate(30deg); }
.health-running-diamond span:nth-child(2) { inset: 34px; animation: health-pulse 1.8s ease-in-out infinite alternate; }
.health-running-diamond span:nth-child(3) { inset: 50px; background: var(--detail-info); border: 0; }
@keyframes health-turn { to { transform: rotate(360deg); } }
@keyframes health-pulse { to { inset: 25px; } }
@media (prefers-reduced-motion: reduce) { .health-running-diamond, .health-running-diamond span { animation: none; } }

/* THE GRADE, WHAT IT MEANS, AND THE SCORE. The band name used to be printed
   twice - as the heading and again as a pill below the summary - and the word
   alone ("Developing") told the engineer nothing. */
.health-report-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 24px; padding-bottom: 18px; margin-bottom: 20px;
  border-bottom: 2px solid var(--ink);
}
.health-report-head h3 {
  margin: 2px 0 6px; font-family: var(--font-serif);
  font-size: clamp(1.5rem, 3vw, 2rem); font-weight: 400; letter-spacing: -.015em;
}
.health-band-meaning { max-width: 62ch; color: var(--muted); font-size: .82rem; line-height: 1.55; }

/* THE BRIEF, FULL WIDTH. It arrived as one unbroken block inside a third of
   the page, next to a very large number. It is the first thing he reads. */
.health-summary { max-width: 78ch; margin-bottom: clamp(20px, 3vw, 30px); }
.health-summary p { margin: 0 0 .8em; font-size: .93rem; line-height: 1.72; }
.health-summary p:last-child { margin-bottom: 0; }
.health-summary p:first-child { font-size: 1rem; }
.health-band { display: inline-flex; margin-top: 10px; padding: 5px 8px; color: #fff; background: var(--ink); font-size: .77rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; }
/* The diamond sits beside its own numbers, not beside a tall column of prose:
   the lists ran far below the picture and left "a massive white area". */
.health-report-grid {
  display: grid; grid-template-columns: minmax(300px, 1fr) minmax(280px, 1fr);
  gap: clamp(20px, 4vw, 48px); align-items: center;
}
.health-diamond-wrap { min-width: 0; }
.health-diamond { display: block; width: min(100%, 560px); height: auto; margin: 0 auto; overflow: visible; }
.health-diamond .health-ring { fill: none; stroke: color-mix(in srgb, var(--ink) 15%, transparent); stroke-width: 1; }
.health-diamond .health-axis { stroke: color-mix(in srgb, var(--ink) 13%, transparent); stroke-width: 1; }
.health-diamond .health-shape { fill: var(--detail-info); fill-opacity: .18; stroke: var(--detail-info); stroke-width: 3; stroke-linejoin: round; }
.health-diamond .health-point { fill: var(--surface-raised); stroke: var(--detail-info); stroke-width: 2; }
.health-diamond text { fill: var(--ink); font-family: var(--font-sans); font-size: 11px; font-weight: 600; }
.health-axis-table { width: 100%; margin-top: 14px; border-collapse: collapse; font-size: .77rem; }
.health-axis-table th, .health-axis-table td { padding: 8px 4px; border-bottom: 1px solid var(--border); text-align: left; }
.health-axis-table th { color: var(--muted); font-size: .77rem; letter-spacing: .06em; text-transform: uppercase; }
.health-axis-table td:last-child { text-align: right; font-variant-numeric: tabular-nums; font-weight: 700; }
/* Side by side, so neither list runs down an empty page. */
.health-report-copy {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(20px, 4vw, 48px); margin-top: clamp(22px, 3vw, 32px);
}
.health-report-copy > section { padding-top: 16px; border-top: 2px solid var(--ink); }
.health-report-copy h4 { margin: 0 0 10px; font-family: var(--font-serif); font-size: 1.12rem; font-weight: 400; }
.health-report-copy p { color: var(--muted); line-height: 1.62; }
.health-list { display: grid; gap: 10px; margin: 0; padding: 0; list-style: none; }
.health-list li { padding: 12px 0 12px 14px; border-left: 2px solid var(--border); }
.health-list.actions li { border-left-color: var(--detail-info); }
.health-list strong { display: block; margin-bottom: 3px; font-size: .78rem; }
.health-list span, .health-list q { color: var(--muted); font-size: .77rem; line-height: 1.5; }
.health-list q { display: block; margin-top: 5px; }
.health-basis-report, .health-findings { margin-top: 30px; padding-top: 24px; border-top: 1px solid var(--border); }
.health-section-head { display: flex; align-items: end; justify-content: space-between; gap: 20px; margin-bottom: 16px; }
.health-section-head h4 { margin: 2px 0 0; font-family: var(--font-serif); font-size: 1.3rem; font-weight: 400; }
.health-section-head p:not(.eyebrow) { margin: 5px 0 0; color: var(--muted); font-size: .77rem; }
.health-drawing-notice { display: grid; grid-template-columns: minmax(160px, .35fr) minmax(300px, 1fr) auto; align-items: center; gap: 18px; margin-top: 22px; padding: 16px 18px; border-left: 3px solid var(--detail-info); background: var(--surface-subtle); }
.health-drawing-notice strong { font-family: var(--font-serif); font-size: 1rem; font-weight: 500; }
.health-drawing-notice p { margin: 0; color: var(--muted); font-size: .77rem; line-height: 1.55; }
.health-drawing-notice span { color: var(--detail-info); font-size: .77rem; font-weight: 700; }
.health-review-scope { margin-top: 22px; padding: 16px 18px; border: 1px solid var(--border); background: var(--surface-raised); }
.health-review-scope.incomplete { border-left: 3px solid var(--warning); background: color-mix(in srgb, var(--warning) 7%, var(--surface-raised)); }
.health-review-scope > strong { font-family: var(--font-serif); font-size: 1rem; font-weight: 500; }
.health-review-scope p { margin: 7px 0 0; color: var(--muted); font-size: .77rem; line-height: 1.55; }
.health-review-scope div { display: flex; flex-wrap: wrap; gap: 8px 18px; margin-top: 10px; color: var(--ink); font-size: .77rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; }
.health-review-scope ul { margin: 12px 0 0; padding-left: 20px; color: var(--ink); font-size: .77rem; line-height: 1.5; }
.health-review-scope li + li { margin-top: 6px; }
.health-finding-counts { display: flex; gap: 12px; }
.health-finding-counts span { padding: 7px 9px; border: 1px solid var(--border); color: var(--muted); font-size: .77rem; }
.health-finding-counts strong { color: var(--ink); font-variant-numeric: tabular-nums; }
.health-finding { display: grid; grid-template-columns: 42px minmax(0, 1fr); gap: 14px; padding: 18px 0; border-top: 1px solid var(--border); }
.health-finding-index { color: var(--muted); font-family: var(--font-serif); font-size: 1.05rem; }
.health-finding-meta { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 7px; }
.health-finding-meta span { padding: 3px 6px; color: var(--muted); background: var(--surface-subtle); font-size: .77rem; letter-spacing: .04em; text-transform: uppercase; }
.health-finding-meta .severity-pill { color: var(--ink); border-left: 2px solid var(--border-strong); font-weight: 750; }
.health-finding.severity-high .severity-pill { border-left-color: var(--danger); }
.health-finding.severity-medium .severity-pill { border-left-color: var(--warning); }
.health-finding.severity-low .severity-pill { border-left-color: var(--detail-info); }
.health-finding h5 { margin: 0; font-family: var(--font-serif); font-size: 1.06rem; font-weight: 450; line-height: 1.25; }
.health-finding p { margin: 7px 0 0; color: var(--muted); font-size: .77rem; line-height: 1.55; }
.health-finding .health-location { color: var(--ink); font-size: .77rem; font-weight: 650; }
.health-finding q { display: block; margin-top: 9px; padding: 9px 11px; border-left: 2px solid var(--border-strong); color: var(--muted); background: var(--surface-subtle); font-size: .77rem; line-height: 1.5; }
.health-recommendation { display: grid; gap: 3px; margin-top: 10px; padding: 10px 12px; border-left: 2px solid var(--detail-info); }
.health-recommendation strong { font-size: .77rem; }
.health-recommendation span { color: var(--muted); font-size: .77rem; line-height: 1.5; }
.health-finding .health-citation { color: var(--detail-info); font-size: .77rem; font-weight: 650; }
.health-finding .health-citation-warning { color: var(--warning); font-size: .77rem; font-weight: 650; }
.health-report-footer { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 14px; margin-top: 28px; padding-top: 18px; border-top: 1px solid var(--border); }
.health-report-footer p { flex: 1 1 100%; margin: 0; color: var(--muted); font-size: .77rem; line-height: 1.55; }
.health-expiry { color: var(--warning); font-weight: 600; }
.health-used { min-height: 330px; display: grid; place-items: center; align-content: center; text-align: center; }
.health-used p { max-width: 580px; color: var(--muted); line-height: 1.6; }
.health-used .inline-actions { justify-content: center; }

@media (max-width: 800px) {
  .health-hero { grid-template-columns: 1fr; }
  .health-mini-diamond { display: none; }
  .health-privacy-grid { grid-template-columns: 1fr; }
  .health-start-row, .health-report-head { align-items: stretch; flex-direction: column; }
  .health-start-row .button { width: 100%; }
  .health-running { grid-template-columns: 1fr; justify-items: center; text-align: center; }
  .health-report-grid, .health-report-copy { grid-template-columns: 1fr; }
  .health-basis-grid, .health-basis-fields { grid-template-columns: 1fr; }
  .health-section-head, .health-drawing-notice { align-items: stretch; grid-template-columns: 1fr; flex-direction: column; }
  .health-finding-counts { flex-wrap: wrap; }
}

@media print {
  body.health-printing #workspace-view::before,
  body.health-printing .sidebar,
  body.health-printing .topbar,
  body.health-printing .surface-nav,
  body.health-printing .health-hero,
  body.health-printing .health-report-footer { display: none !important; }
  body.health-printing #workspace-view,
  body.health-printing .main-shell,
  body.health-printing #health-surface { display: block !important; margin: 0; padding: 0; background: #fff; }
  body.health-printing .surface:not(#health-surface) { display: none !important; }
  body.health-printing .health-state { border: 0; }
  body.health-printing .health-report-grid { grid-template-columns: 1fr 1fr; }
  /* THE WHOLE REPORT, NOT THE PICTURE. He pressed Download, got the diamond
     alone, and asked for the report. This is that download: the brief, the
     scores, both lists, the basis and every finding, on paper or as a PDF. */
  body.health-printing .health-report-copy { grid-template-columns: 1fr 1fr; }
  /* THE DIAMOND ARRIVED CUT IN HALF - a page break landed through the middle
     of the report grid. The grid, the diamond and each list keep to one page,
     and the SVG is bounded so no print engine overflows it into the gutter. */
  body.health-printing :is(.health-report-grid, .health-diamond-wrap,
    .health-report-copy > section, .section-census-list li, .health-summary) {
    break-inside: avoid; page-break-inside: avoid;
  }
  body.health-printing .health-report-grid { align-items: start; }
  body.health-printing .health-diamond { width: 100%; max-width: 340px; }
  body.health-printing .health-finding { break-inside: avoid; page-break-inside: avoid; }
  body.health-printing .health-findings { break-before: page; page-break-before: always; }
  body.health-printing :is(.health-section-head, .health-report-head) {
    break-after: avoid; page-break-after: avoid;
  }
  body.health-printing .health-review-scope,
  body.health-printing .health-basis-report { break-inside: avoid; }
  body.health-printing a[href]::after { content: ""; }
  @page { margin: 16mm; }
}

/* A page citation is a reference, not a code token. It was set in the
   monospace face this product uses for code, on a grey block, saying "p.148" —
   so the owner read it as a flag and asked what it meant. It is the most
   important mark in an answer: the thing that sends him to the printed page to
   check the number himself. It now reads as words, in the colour that means
   "this came from a document" everywhere else in the product. */
.cite {
  font-family: inherit;
  font-size: .88em;
  font-variant-numeric: tabular-nums;
  color: var(--detail-info);
  background: transparent;
  border-bottom: 1px dotted color-mix(in srgb, var(--detail-info) 55%, transparent);
  border-radius: 0;
  padding: 0 1px;
  cursor: help;
}

/* THE BLACK BOX, belt and braces. Three surfaces now paint the rail's column
   and one of them cannot be scrolled away or out-sized: a FIXED layer behind
   the app, exactly the rail's width, for the whole height of the viewport
   whatever the document does. If the rail is ever shorter than the page again,
   or a repaint lags a scroll, the ground underneath is already there.
   I have still never reproduced this myself, so this does not claim to have
   found the cause — it removes every surface inside the page that could be it. */
#workspace-view::before {
  content: "";
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  width: var(--rail-w);
  background: var(--sidebar-bg);
  pointer-events: none;
  z-index: -1;
}

/* ==========================================================================
   RESEARCH IS A CONVERSATION — 19 August 2026

   THE OWNER: "the idea is that the conversation should continue. You should
   have the previous answers and I could just continue, like how ChatGPT works
   and Claude works... the textbox then should move at the very end of it."

   The thread reads downward, oldest first, and the composer sits BELOW it, so
   the next question is asked where the last answer ended. Nothing moved in the
   markup to achieve that — the card is a column and the pieces are ordered, so
   every id, listener and form submit stays exactly where it was.
   ========================================================================== */
#research-surface .feature-card { display: flex; flex-direction: column; }
#research-surface .feature-card-head { order: 0; }
#research-surface #research-result { order: 1; margin: 0 0 1.1rem; }
#research-surface #research-form { order: 2; }
#research-surface .context-pills { order: 3; }
#research-surface #research-context-status { order: 4; }

.research-turn + .research-turn { margin-top: 1.6rem; padding-top: 1.4rem; border-top: 1px solid var(--border); }
/* The question, set as the engineer asked it. Quiet, because he already knows
   what he asked — it is there so a long thread can be read back. */
/* YOUR QUESTION, THE WAY A CHAT SHOWS IT. The owner, reading a two-turn
   thread: "it's difficult to find out which one was my question — can we not
   do it the same way ChatGPT does it?" It was a grey line with a thin rule,
   which at a glance looks like a caption on the answer below it rather than
   something he said. A right-aligned bubble is unmistakable at a glance and
   needs no label. */
.research-question-said {
  margin: 0 0 .9rem auto;
  max-width: 82%;
  width: fit-content;
  padding: .55rem .8rem;
  border-radius: .9rem .9rem .2rem .9rem;
  background: var(--accent-soft, rgba(37, 99, 235, .09));
  /* --text and --accent-border were never tokens in this app, so the colour
     fell back to near-black in BOTH themes and the bubble went unreadable the
     moment dark mode arrived. Found on the console preview, 24 Aug 2026. */
  color: var(--ink);
  border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
  font-size: .9rem;
  line-height: 1.45;
  white-space: pre-wrap;
}
.research-thread-foot { margin-top: 1.2rem; padding-top: .8rem; border-top: 1px solid var(--border); }
.research-pending { margin: 0; color: var(--muted); font-size: .85rem; }

/* The version question, asked before the answer. It is a STOP, so it is drawn
   in the colour that means a human decision is owed — never as an error, which
   it is not, and never as a finding, which it is not either. */
.research-version-ask {
  margin: 0 0 1.1rem;
  padding: .9rem 1rem;
  border: 1px solid color-mix(in srgb, var(--detail-warn) 40%, transparent);
  border-left: 3px solid var(--detail-warn);
  border-radius: var(--radius);
  background: var(--detail-warn-soft);
}
.research-version-head { margin: 0 0 .2rem; font-size: .86rem; font-weight: 700; }
.research-version-copy { margin: 0 0 .7rem; font-size: .84rem; }
.research-version-actions { display: flex; flex-wrap: wrap; gap: .4rem; margin-bottom: .7rem; }
.research-version-ask .settings-note { margin: 0 0 .2rem; }

/* A JOB THAT IS ALIVE MUST LOOK ALIVE.
   The percentage stays stage-driven — a bar that creeps on a timer is a lie the
   first time a run really stalls. These two say "working" without claiming
   progress: a shimmer that runs only while the job is live, and a spinner.
   Both stop the moment it completes or fails. */
@keyframes job-progress-shimmer {
  0%   { background-position: 0 0; }
  100% { background-position: 2rem 0; }
}
.job-progress.is-live .job-progress-fill {
  background-image: linear-gradient(
    115deg,
    rgba(255, 255, 255, .28) 25%, transparent 25%,
    transparent 50%, rgba(255, 255, 255, .28) 50%,
    rgba(255, 255, 255, .28) 75%, transparent 75%);
  background-size: 2rem 2rem;
  animation: job-progress-shimmer 1.1s linear infinite;
}
@keyframes job-spin { to { transform: rotate(360deg); } }
.job-spinner {
  width: .8em; height: .8em; flex: 0 0 auto;
  border: 2px solid currentColor; border-right-color: transparent;
  border-radius: 50%; opacity: .55;
  animation: job-spin .8s linear infinite;
}
.job-progress-text { display: flex; align-items: center; gap: .45rem; }
/* Time in the CURRENT stage. Ten minutes on one stage should be visible as
   ten minutes on one stage — that is information, not decoration. */
.job-elapsed { color: var(--muted); font-variant-numeric: tabular-nums; }
/* Respect a reader who has asked for less motion. */
@media (prefers-reduced-motion: reduce) {
  .job-progress.is-live .job-progress-fill { animation: none; }
  .job-spinner { animation: none; opacity: .35; }
}

/* A required answer is flagged where it is asked, not only when it is missed. */
.drawing-question.question-required > strong::after { content: " *"; color: #b91c1c; }
.required-flag { display: block; font-size: 12px; color: #b91c1c; margin: 2px 0 4px; }

/* Drag and drop: behaviour gets one non-layout class. Generated upload cards
   already own their grid/padding; project-map buttons and composers must not
   inherit that geometry merely because they accept a dropped file. */
.universal-drop-target.drop-active { outline: 2px dashed var(--accent, #2563eb); outline-offset: -6px; background: rgba(37, 99, 235, 0.04); }
.universal-drop-target.is-uploading { cursor: progress; }
#drop-notice { position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%);
  background: #111; color: #fff; padding: 10px 16px; border-radius: 8px; font-size: 14px;
  max-width: 70ch; opacity: 0; pointer-events: none; transition: opacity .18s; z-index: 60; }
#drop-notice.visible { opacity: 1; }

/* A QUESTION IS NOT A WARNING. When the printed versions of what the answer
   relied on genuinely disagree, the product asks which regime applies — and
   that is something the engineer can ACT on, unlike a warning he can only
   absorb. Styled as a prompt, not a fault. */
.trust-note-ask {
  color: var(--accent, #2563eb);
  background: var(--accent-soft, rgba(37, 99, 235, .07));
  border-left: 3px solid var(--accent, #2563eb);
  padding: .5rem .7rem; border-radius: .25rem;
}

/* THE FILL SLIDES, IT DOES NOT SNAP. The target is always the stage reached —
   never the clock — but drawing a 45% jump in one frame reads as broken, and
   then the freeze that follows reads as hung. About a second and a half to
   travel, with an ease-out so it settles rather than stops dead. */
.job-progress-fill { transition: width 1.4s cubic-bezier(.22, .61, .36, 1); }
@media (prefers-reduced-motion: reduce) {
  .job-progress-fill { transition: none; }
}

/* ONE QUESTION AT A TIME. A second click starts a second job on a transport
   that serves one call at a time, so both run slower and the thread gains an
   answer to a question nobody meant to ask twice. */
.task-composer.is-busy button[type="submit"],
form.is-busy button[type="submit"] {
  opacity: .45; cursor: not-allowed; pointer-events: none;
}
form.is-busy textarea { opacity: .7; }


/* One exchange, visibly one unit. Without a separator a long thread reads as
   one continuous document and the second question disappears into the first
   answer. */
.research-turn + .research-turn {
  margin-top: 1.6rem; padding-top: 1.4rem;
  border-top: 1px solid var(--border, #e5e7eb);
}
.research-answer { clear: both; }

/* STOP, beside the bar it stops. Refreshing the page does not end a job — the
   work runs on the server — so there has to be something that does. Quiet by
   default: it is not the main action, it is the way out of one. */
.job-stop {
  margin-left: .6rem; padding: .1rem .5rem;
  font: inherit; font-size: .78rem; line-height: 1.6;
  color: var(--muted); background: transparent;
  border: 1px solid var(--border, #d5d9e0); border-radius: 999px;
  cursor: pointer;
}
.job-stop:hover:not(:disabled) { color: var(--danger, #b42318); border-color: currentColor; }
.job-stop:disabled { opacity: .5; cursor: default; }

/* A review that lost its passes must not read as a clean drawing. */
.drawing-empty-warning { border-left: 4px solid #b91c1c; padding: 8px 12px;
  background: rgba(185, 28, 28, 0.06); border-radius: 6px; }

/* SAVED CONVERSATIONS, under Projects in the rail.
   Shares `.project-item` so it cannot drift from the list above it — two lists
   a few pixels apart, styled separately, is how a sidebar starts looking
   assembled rather than designed. */
.conversation-item { display: flex; align-items: center; gap: .25rem; padding: 0; }
/* The chat row IS a project row: same reset, same icon-then-name grammar,
   same hover and current states — one visual family in the rail (owner). */
.conversation-item .project-open {
  display: flex; align-items: center; gap: .5rem;
  flex: 1 1 auto; min-width: 0;
  border: 0; border-radius: 6px; padding: .58rem .6rem;
  background: transparent; color: inherit; font: inherit; font-size: .78rem;
  overflow: hidden; text-align: left;
}
.conversation-item .project-open .icon { flex: 0 0 auto; width: 15px; height: 15px; opacity: .75; }
.conversation-item .project-open span {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.conversation-item:hover { background: color-mix(in srgb, var(--sidebar-fg) 8%, transparent); border-radius: 6px; }
/* The delete stays out of the way until the row is under the cursor. It is
   destructive and permanent, so it should not be the first thing the eye
   lands on — but it must be reachable by keyboard, hence :focus-visible. */
.conversation-delete {
  flex: 0 0 auto; width: 1.4rem; height: 1.4rem; line-height: 1;
  border: 0; border-radius: .3rem; background: transparent;
  color: var(--muted); font-size: 1.05rem; cursor: pointer;
  opacity: 0; transition: opacity .12s ease;
}
.conversation-item:hover .conversation-delete,
.conversation-delete:focus-visible { opacity: 1; }
.conversation-delete:hover { color: var(--danger, #b42318); }
.conversation-item.is-current { background: var(--accent-soft, rgba(37,99,235,.08)); }
.rail-empty {
  margin: .35rem 0 .2rem; padding: 0 .2rem;
  font-size: .78rem; color: var(--muted);
}

/* The fixed desktop rail must become ordinary document flow on a phone.
   Keep only its identity row visible until the user asks for navigation; this
   avoids making every mobile visit scroll through projects before reaching
   the active tool, while preserving every rail control in the expanded menu. */
@media (max-width: 680px) {
  :root, #workspace-view, #workspace-view.sidebar-collapsed { --rail-w: 0px; }
  #workspace-view, #workspace-view.sidebar-collapsed {
    display: block;
    min-height: 100vh;
    background: var(--main-bg);
    background-image: none;
  }
  #workspace-view::before { display: none; }
  #workspace-view .sidebar,
  #workspace-view.sidebar-collapsed .sidebar:is(aside) {
    position: relative;
    top: auto;
    display: flex;
    height: auto;
    min-height: 0;
    padding: .7rem .8rem;
    overflow: visible;
  }
  #workspace-view .sidebar-head,
  #workspace-view.sidebar-collapsed .sidebar-head {
    flex-direction: row;
    justify-content: flex-start;
    width: 100%;
    padding: 0;
  }
  #workspace-view .sidebar-head > div,
  #workspace-view.sidebar-collapsed .sidebar-head > div { display: block; }
  #workspace-view .sidebar-toggle,
  #workspace-view.sidebar-collapsed .sidebar-toggle { margin-left: auto; }
  #workspace-view .sidebar:is(aside) > .sidebar-section,
  #workspace-view .sidebar-usage,
  #workspace-view .sidebar-settings,
  #workspace-view .sidebar-foot { display: none; }
  #workspace-view.mobile-nav-open .sidebar:is(aside) > .sidebar-section,
  #workspace-view.mobile-nav-open .sidebar-usage,
  #workspace-view.mobile-nav-open .sidebar-settings,
  #workspace-view.mobile-nav-open .sidebar-foot { display: flex; }
  #workspace-view.mobile-nav-open .sidebar:is(aside) > .sidebar-section,
  #workspace-view.mobile-nav-open .sidebar-settings { width: 100%; }
  #workspace-view.mobile-nav-open .sidebar-settings { display: block; }
  #workspace-view.mobile-nav-open .sidebar-foot { justify-content: space-between; }
  #workspace-view .main-shell { min-height: 0; padding: .85rem .75rem 2rem; }
}

/* What a review cost, beside what it found. */
.review-cost { color: #555; }

/* A FIELD THAT STILL NEEDS AN ANSWER. Used only after the engineer presses
   Generate — marking fields before he has tried anything reads as scolding. */
.needs-answer { border-color: var(--accent, #b8651a) !important; box-shadow: 0 0 0 2px rgba(184, 101, 26, .18); border-radius: 8px; }
.needs-answer select, .needs-answer textarea { border-color: var(--accent, #b8651a); }

/* ==========================================================================
   THE RESEARCH CONSOLE — 24 August 2026.

   The owner saw the Claude-Code-style mock-up and asked for it by name: the
   run must LOOK alive, and the honest way to look alive is to draw the REAL
   stages the server reports as they happen — never a creeping bar, never a
   ticking timer (refused twice), never an invented stage. A finished stage
   shows the time it really took; the live one pulses and shows none.

   Brand: ink-black controls (the cascade already makes .button.primary ink),
   blue kept for citations only, green reserved for checks that really ran.
   Everything reads from the theme tokens, so dark mode needs no second copy.
   ========================================================================== */

/* The card becomes a console: the thread scrolls inside its own box and the
   composer sits at the bottom like a dock. Heights are viewport-derived; on a
   short window the min-height keeps the composer reachable. */
#research-surface .research-console { height: calc(100vh - 205px); min-height: 480px; gap: .85rem; }
#research-surface .research-console .feature-card-head { padding-bottom: .5rem; border-bottom: 1px solid var(--border); }
#research-surface .research-console .feature-card-head p.muted { display: none; }
#research-surface .research-console .feature-card-head h3 { font-size: 1rem; margin: .1rem 0 0; }
#research-surface #research-result { flex: 1 1 auto; min-height: 0; overflow-y: auto; margin: 0; padding-right: .35rem; scrollbar-gutter: stable; }
/* The composer is a dock, not a page: the THREAD owns the height. The
   product-wide 132px minimum is for one-shot composers; here it starved the
   conversation above it on anything smaller than a tall desktop. */
#research-surface .task-composer > textarea { min-height: 68px; }
/* The project badge follows the brand: ink on light, flipped by the tokens in
   dark. --navy already swaps to a light ink there, so one rule serves both. */
#research-surface .research-console .context-badge { background: var(--navy); border-color: var(--navy); color: var(--main-bg); }
@media (max-width: 900px) {
  #research-surface .research-console { height: auto; min-height: 0; }
  #research-surface #research-result { overflow: visible; }
}

/* The answer, as a card: source strip on top, checks under it, prose below. */
.research-answer { border: 1px solid var(--border); border-radius: 10px; background: var(--surface-raised, #fff); overflow: hidden; }
.research-answer > .guidance-used { margin: 0; padding: .5rem .9rem; border-bottom: 1px solid var(--border); background: var(--surface-subtle, #f6f7f9); }
.research-answer > .trust-panel { margin: 0; padding: .2rem .9rem; border-bottom: 1px solid var(--border); }
.research-answer > .trust-panel:empty { display: none; }
.research-answer > .trust-panel .trust-note-warn { padding: .35rem 0; }
.research-answer > .answer-body { padding: .95rem 1.05rem .3rem; }
.research-answer > .answer-sources, .research-answer > .drawing-guidance { margin: .2rem 1.05rem .9rem; }
.research-answer > .research-version-ask { margin: .8rem .9rem; }

/* Checked and clean, in green — drawn ONLY when safetyNotices says the pass
   completed with nothing wrong. The detail is one click away. */
.trust-note-ok { color: var(--success); }
.trust-note-ok > b::before { content: "✓ "; }
.trust-note-ok .trust-detail summary { color: var(--muted); }

/* The quiet rows fold to one line, the same pattern as the run log's
   "7 stages" line. Warnings never enter this fold. */
.trust-fold { font-size: .8rem; color: var(--muted); }
.trust-fold > summary { display: flex; align-items: center; gap: .5rem; cursor: pointer; list-style: none; padding: .3rem .1rem; font-variant-numeric: tabular-nums; }
.trust-fold > summary::-webkit-details-marker { display: none; }
.trust-fold-hint { margin-left: auto; font-size: .77rem; }
.trust-fold[open] .trust-fold-hint { visibility: hidden; }
.trust-fold-body { display: flex; flex-direction: column; gap: .15rem; padding: .2rem 0 .35rem; }

/* THE CHECKS ARE ONE LINE (owner, 18 Sep 2026: "have the warnings, all this
   stuff, in one section. You click it and then it opens... I don't want them
   to take this much space"). "Checks (N)" reads as the button; the one-line
   summary rides beside it; the drawer lists one SHORT row per check, closed,
   and a row opens to its text on a click. */
.trust-checks-button { display: inline-flex; align-items: center; gap: .3rem; padding: .04rem .5rem;
  border: 1px solid var(--border); border-radius: 999px; color: var(--ink); font-weight: 600; white-space: nowrap; }
.trust-fold[open] .trust-checks-button { background: var(--ink); color: var(--surface, #fff); border-color: var(--ink); }
.trust-fold[open] .trust-checks-button .trust-fold-mark,
.trust-fold[open] .trust-checks-button .runlog-tick { color: inherit; }
.trust-fold-line { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.trust-row { display: block; padding: 0; gap: 0; border-radius: 6px; }
.trust-row > summary { display: flex; align-items: center; gap: .4rem; cursor: pointer; list-style: none;
  padding: .2rem .55rem; line-height: 1.3; }
.trust-row > summary::-webkit-details-marker { display: none; }
.trust-row > summary::before { content: "\25B8"; font-size: .77rem; opacity: .75; }
.trust-row[open] > summary::before { content: "\25BE"; }
.trust-row > summary b { font-size: .77rem; font-weight: 600; }
.trust-note-ok.trust-row > summary b::before { content: "\2713 "; }
.trust-row-body { padding: .05rem .55rem .4rem 1.35rem; }
.trust-row-body > span { display: block; }

/* --- the run log ---------------------------------------------------------- */
.runlog { border: 1px solid var(--border); border-radius: 10px; background: var(--surface-raised, #fff); padding: .6rem .8rem .55rem; }
.research-provisional { margin-top: .65rem; border: 1px solid color-mix(in srgb, var(--warning) 38%, var(--border)); border-radius: 10px; background: color-mix(in srgb, var(--warning) 5%, var(--surface-raised, #fff)); overflow: hidden; }
.research-provisional-head { display: flex; align-items: center; gap: .45rem; padding: .55rem .75rem; border-bottom: 1px solid var(--border); font-size: .78rem; }
.research-provisional-head > span:last-child { color: var(--muted); }
.research-provisional-pulse { width: 8px; height: 8px; border-radius: 50%; background: var(--warning); animation: runlog-beat 1.15s ease-in-out infinite; }
.research-provisional-body { padding: .85rem .9rem; color: var(--ink); font-size: .9rem; line-height: 1.55; white-space: pre-wrap; }
.research-provisional-note { margin: 0; padding: .5rem .75rem; border-top: 1px solid var(--border); color: var(--muted); font-size: .77rem; }
.runlog-head { display: flex; align-items: center; gap: .5rem; font-size: .78rem; color: var(--muted); }
.runlog-head .job-stop { margin-left: auto; }
.runlog-steps { list-style: none; margin: .55rem 0 0; padding: 0; }
.runlog-step { position: relative; display: flex; align-items: baseline; gap: .55rem; padding: .24rem 0 .24rem 1.15rem; font-size: .84rem; color: var(--muted); }
/* The rail the bulbs sit on — one thin line joining the stages. */
.runlog-step::before { content: ""; position: absolute; left: .3rem; top: 0; bottom: 0; width: 2px; background: var(--border); }
.runlog-step:first-child::before { top: .55rem; }
.runlog-step:last-child::before { bottom: auto; height: .55rem; }
.runlog-bulb { position: absolute; left: 0; top: .3rem; width: 9px; height: 9px; border-radius: 50%; border: 2px solid var(--border); background: var(--surface-raised, #fff); }
.runlog-step.is-done { color: var(--ink); }
.runlog-step.is-done .runlog-bulb { border-color: var(--success); background: var(--success); }
.runlog-step.is-live { color: var(--ink); font-weight: 550; }
.runlog-step.is-live .runlog-bulb { border-color: var(--warning); background: var(--warning); animation: runlog-beat 1.15s ease-in-out infinite; }
/* The live label shimmers — movement without a lying percentage. */
.runlog-step.is-live .runlog-label {
  background: linear-gradient(90deg, var(--ink) 25%, var(--accent) 50%, var(--ink) 75%);
  background-size: 220% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: runlog-sweep 1.6s linear infinite;
}
/* A DURATION IS ONE WORD (owner, 14 Sep 2026: "the seconds on the researcher
   look kinda weird in the stages"). In the narrow rail the label took the
   width and "38s" broke down the column one character per line. The time
   keeps its own space and never wraps; the label gives way instead. */
.runlog-time { flex: 0 0 auto; margin-left: auto; padding-left: .5rem;
  font-size: .77rem; color: var(--muted); font-variant-numeric: tabular-nums;
  white-space: nowrap; }
.runlog-label { min-width: 0; overflow-wrap: anywhere; }
@keyframes runlog-beat {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--warning) 45%, transparent); }
  50% { box-shadow: 0 0 0 5px transparent; }
}
@keyframes runlog-sweep { to { background-position: -220% 0; } }

/* The finished run, folded to one line. Native <details> — no listener. */
/* ONE QUIET LINE (owner, 2 Sep 2026, repeatedly: "the text 3 stages 4m
   show the run is so big... bigger than the actual text response").
   Smaller than the answer body everywhere, and slimmer still in the rail. */
.runlog-fold { margin: 0 0 .45rem; font-size: .77rem; color: var(--muted); }
.runlog-fold > summary { display: flex; align-items: center; gap: .4rem; cursor: pointer; list-style: none; padding: .24rem .5rem; border: 1px solid var(--border); border-radius: 7px; background: var(--surface-subtle, #f6f7f9); font-variant-numeric: tabular-nums; }
.runlog-fold > summary::-webkit-details-marker { display: none; }
.runlog-tick { color: var(--success); font-weight: 700; }
.runlog-open-hint { margin-left: auto; font-size: .77rem; }
.runlog-fold[open] .runlog-open-hint { visibility: hidden; }
.runlog-fold[open] > summary { border-radius: 8px 8px 0 0; }
.runlog-fold > .runlog-steps { margin: 0; padding: .5rem .7rem .55rem .95rem; border: 1px solid var(--border); border-top: 0; border-radius: 0 0 8px 8px; }

/* The newest turn arrives rather than appearing. Reopened conversations get
   no class and so no movement. */
@keyframes turn-in { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }
.research-turn.is-new { animation: turn-in .32s ease; }
.research-turn.is-new .research-answer { animation: turn-in .38s ease .06s backwards; }

@media (prefers-reduced-motion: reduce) {
  .runlog-step.is-live .runlog-bulb { animation: none; }
  .runlog-step.is-live .runlog-label { animation: none; background: none; color: var(--ink); -webkit-background-clip: initial; background-clip: initial; }
  .research-turn.is-new, .research-turn.is-new .research-answer { animation: none; }
}

/* THE REVISION JOURNEY (24 Aug 2026). Feedback lives on the card it answers;
   the bar that runs the next revision sits at the top of the review. The bar
   uses the ink-on-paper emphasis the brand reserves for the one control that
   moves work forward - same weight as a primary button, because it starts a
   paid run and must not look like a note. */
.drawing-revision-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  padding: 10px 14px; margin: 10px 0;
  /* Light, not ink: the black bar read as a wall, not a next step
     (owner, 1 Sep evening: "remove the black background"). */
  background: var(--accent-soft); color: var(--ink);
  border: 2px solid var(--ink);
  border-radius: 8px;
}
.drawing-revision-bar span { font-size: .85rem; }
.drawing-feedback { margin-top: 8px; border-top: 1px dashed var(--border); padding-top: 6px; }
.drawing-feedback summary { font-size: .8rem; color: var(--muted); cursor: pointer; }
.drawing-feedback-form { display: flex; gap: 8px; align-items: flex-start; margin-top: 6px; }
.drawing-feedback-form textarea { flex: 1 1 auto; font-size: .85rem; }
.drawing-feedback-note {
  font-size: .82rem; margin: 6px 0; padding: 6px 10px;
  background: color-mix(in srgb, var(--ink) 5%, var(--background)); border-left: 3px solid var(--ink);
  border-radius: 0 6px 6px 0;
}
:root[data-theme="dark"] .drawing-feedback-note { background: color-mix(in srgb, var(--ink) 8%, var(--background)); }
/* Dark theme: --ink flips to light and --background to dark with the palette,
   so the same two tokens keep the bar readable - no per-theme override needed
   beyond this note. */

/* THE CODE-COMPLIANT ROUTE stands apart from the ordinary questions - the
   darker ground the owner asked for, in the palette's own ink. */
.strategy-compliant-route {
  background: color-mix(in srgb, var(--ink) 7%, var(--background));
  border: 1px solid var(--border);
  border-left: 3px solid var(--ink);
  border-radius: 8px;
  padding: 10px 12px;
  margin-bottom: 10px;
}

/* ── THE PROJECT KNOWLEDGE CARD — 25 Aug 2026 ─────────────────────────────
   The map's own corner of the project drawer: per-document read state, the
   build button (spending is a button, never a side effect), and a preview of
   the block a project question will carry. */
.project-map-doclist { display: flex; flex-direction: column; gap: .15rem; margin: .3rem 0 .5rem; }
.project-map-doc { margin: 0; font-size: .8rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.project-map-progress { margin: .4rem 0 .6rem; }
/* The map chip on the "Answered from" strip — the project's own documents
   spoken of in the same voice as the guidance they sat beside. */
.guidance-used-map { border-style: dashed; }

/* ── PROJECT WORKSPACE: compact folders inside the canvas drawer ──────────
   The canvas remains spatial on desktop.  A folder opens in a contained
   drawer, so inspecting a file never turns the whole map into a long page. */
.project-role-primary { margin-bottom: .65rem; }
.project-brief-control { display: grid; gap: .35rem; }
.project-brief-control label { display: grid; gap: .3rem; font-size: .78rem; }
.project-brief-control textarea { width: 100%; min-height: 105px; }
.project-folder-summary-details {
  margin: .65rem 0; padding: .58rem .65rem;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface-subtle);
}
.project-folder-summary-details > summary { cursor: pointer; font-size: .77rem; font-weight: 650; }
.project-folder-summary-details[open] > summary { margin-bottom: .55rem; }
.project-index-links { display: grid; grid-template-columns: 1fr 1fr; gap: .45rem; }
.project-index-link {
  display: grid; grid-template-columns: 30px minmax(0, 1fr) 14px;
  align-items: center; gap: .5rem; min-width: 0; padding: .58rem;
  border: 1px solid var(--border); border-radius: 8px;
  color: var(--ink); background: var(--surface-raised); text-align: left;
}
.project-index-link:hover { border-color: var(--accent); }
.project-index-icon {
  display: grid; place-items: center; width: 30px; height: 30px;
  border-radius: 6px; color: var(--muted); background: var(--surface-subtle);
}
.project-index-link.is-ready .project-index-icon { color: var(--success); }
.project-index-copy { min-width: 0; }
.project-index-copy strong, .project-index-copy small { display: block; }
.project-index-copy strong { overflow: hidden; font-size: .77rem; text-overflow: ellipsis; white-space: nowrap; }
.project-index-copy small { margin-top: .15rem; color: var(--muted); font-size: .77rem; line-height: 1.3; }
.project-index-arrow { width: 13px; color: var(--muted); }
.project-folder-file {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .35rem;
  align-items: center; margin-top: .35rem; padding: .28rem .3rem .28rem .45rem;
  border: 1px solid var(--border); border-radius: 8px; background: var(--surface-raised);
}
.project-folder-file-open {
  display: grid; grid-template-columns: 18px minmax(0, 1fr); align-items: center;
  gap: .45rem; min-width: 0; padding: .22rem 0; border: 0;
  color: var(--ink); background: transparent; text-align: left;
}
.project-folder-file-open > span { min-width: 0; }
.project-folder-file-open strong,
.project-folder-file-open small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.project-folder-file-open strong { font-size: .77rem; }
.project-folder-file-open small { margin-top: .12rem; color: var(--muted); font-size: .77rem; }
.project-folder-file-actions { display: flex; gap: .15rem; }
.project-folder-file-actions .icon-button { width: 30px; height: 30px; }
.project-file-delete { color: var(--danger, #a93838); }
.project-file-mover { grid-column: 1 / -1; padding: .42rem; border-top: 1px dashed var(--border); }
.project-file-mover label { display: flex; align-items: center; gap: .5rem; font-size: .77rem; }
.project-file-mover select { flex: 1; min-width: 0; }
#project-role-notes-block { display: grid; gap: .4rem; padding-top: .1rem; }
#project-role-notes-block label { display: grid; gap: .3rem; font-size: .77rem; font-weight: 650; }
#project-role-notes { min-height: 74px; }
.project-pane .universal-upload-zone { margin: 0 0 .55rem; }

@media (max-width: 520px) {
  .project-index-links { grid-template-columns: 1fr; }
}

/* ── THE ENGINEER'S MARK-UP ON THE SHEET ────────────────────────────────────
   (owner, 10 Sep 2026: "let them draw lines, polygonal lines, and highlight
   polygonal areas, to mark and comment and correct you, and then apply the
   corrections"). His shapes ride the ONE canvas beside the pins and the
   measured layers - never a second copy of the sheet. */
.drawing-canvas .geom-marks {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; z-index: 2;
}
.drawing-canvas .geom-marks .geom-mark { pointer-events: none; }
.drawing-canvas .geom-marks .geom-mark-hit { pointer-events: stroke; cursor: grab; }
.drawing-canvas .geom-marks .geom-mark-hit:active { cursor: grabbing; }
.drawing-canvas .geom-marks .hidden { display: none; }
/* The shape being drawn: the product's ink, dashed, with a dot on every
   point placed so far. */
.cc-draw-live {
  position: absolute; inset: 0; pointer-events: none; z-index: 3;
  color: var(--ink);
}
.cc-draw-live svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.cc-draw-dot {
  position: absolute; width: 7px; height: 7px; margin: -3.5px 0 0 -3.5px;
  border-radius: 50%; background: var(--ink);
  border: 1px solid var(--surface);
}
.cc-stage[data-cc-draw-mode] .cc-viewport,
.cc-stage[data-cc-draw-mode="line"] .cc-viewport,
.cc-stage[data-cc-draw-mode="area"] .cc-viewport { cursor: crosshair; }

/* WHILE THE PENCIL IS DOWN, THE WHOLE SHEET IS DRAWABLE. The owner,
   11 Sep 2026: "when you're trying to draw a line or an area where there is
   an image there, there's a little bit of a glitch. It doesn't allow you to
   create lines where there's already an image... no problems whatsoever in
   the intersection."

   The press was landing on whatever sat over the sheet - an open note card,
   a pin, an attached photo - and `closest("[data-cc-canvas]")` found nothing,
   so the point was simply lost. The JS rule ("while the pencil is down a
   click is a point, never a note pin") was already written; it could not fire
   because the event never reached it. Every overlay stands aside for the
   duration, so a line can be drawn straight across a photo. */
.cc-stage[data-cc-draw-mode] .cc-notes,
.cc-stage[data-cc-draw-mode] .cc-pins,
.cc-stage[data-cc-draw-mode] .cc-pin,
.cc-stage[data-cc-draw-mode] .cc-pin-rect,
.cc-stage[data-cc-draw-mode] .cc-pin-frame,
.cc-stage[data-cc-draw-mode] .cc-band,
.cc-stage[data-cc-draw-mode] .drawing-result-image,
.cc-stage[data-cc-draw-mode] .cc-canvas-photo,
.cc-stage[data-cc-draw-mode] img,
.cc-stage[data-cc-draw-mode] .geom-overlay,
.cc-stage[data-cc-draw-mode] svg { pointer-events: none; }

/* THE CARD THAT ASKS "THIS WALL IS..." IS NOT AN OVERLAY (owner, 11 Sep 2026:
   "you can't actually save, delete or do anything with the window that pops
   up because you're still drawing lines behind it"). The rule above stood
   the note card aside with everything else, so Done, Delete, the periods and
   the text box all passed their clicks through to the sheet and added points
   to the line. Everything on the sheet stands aside for the pencil; the card
   that belongs to the shape takes its own clicks. More specific than the
   rule above on purpose, and it must stay so. */
.cc-stage[data-cc-draw-mode] .cc-note-form,
.cc-stage[data-cc-draw-mode] .cc-note-form * { pointer-events: auto; }
.cc-draw-toggle.is-armed { border-color: var(--accent); color: var(--accent); }
.cc-draw-note { font-size: .78rem; opacity: .8; }
/* A WALL THE ENGINEER RATED reads as his: heavier, with a soft halo, so his
   correction is never mistaken for something we measured. */
.geom-wall.engineer-set { filter: drop-shadow(0 0 4px rgba(0, 0, 0, .35)); }
.geom-space.engineer-set { stroke-dasharray: none; }
/* A ROUTE HE WITHDREW is drawn faint and struck, and one whose space he
   re-kinded is drawn as it was measured with its reason on the tooltip. The
   look lives here, so the first render and the repaint after a save cannot
   drift apart. */
.geom-route.engineer-withdrawn {
  stroke: #9ca3af !important; stroke-dasharray: 20 18 !important; opacity: .5;
}
.geom-route.engineer-stale { opacity: .75; stroke-dasharray: 34 10; }
/* The card that says what a shape means: the note card's own grammar. */
.cc-mark-form { width: 258px; }
.cc-mark-form strong { font-size: .84rem; }
.cc-mark-form .settings-note { margin: 0; font-size: .78rem; }
.cc-mark-form label { display: grid; gap: .2rem; font-size: .78rem; }
.cc-mark-form input[type="text"], .cc-mark-form select {
  width: 100%; padding: .35rem .45rem; border: 1px solid var(--border);
  border-radius: 8px; font: inherit; font-size: .77rem;
}
.cc-mark-periods { display: flex; flex-wrap: wrap; gap: .25rem; }
.cc-mark-periods .button { padding: .22rem .42rem; font-size: .78rem; }
.cc-mark-periods .button.is-selected {
  background: var(--ink); color: var(--surface); border-color: var(--ink);
}
/* THE TICK BOX SITS BESIDE ITS WORDS (owner, 11 Sep 2026, on the "This space
   is..." card). The label inherited the card's grid, and a text-input width
   rule stretched the box, so the tick floated in the middle of the card with
   "Count this space in the areas" wrapped over three lines to its right. */
.cc-mark-form label.cc-mark-check { display: flex; flex-direction: row; align-items: center; justify-content: flex-start; gap: .45rem; text-align: left; font-size: .78rem; }
.cc-mark-form label.cc-mark-check input[type="checkbox"] { width: auto; min-width: 0; flex: 0 0 auto; margin: 0; }
.cc-mark-state { font-size: .78rem; align-self: center; opacity: .8; }
.cc-mark-state.is-ok { color: var(--ok, #16a34a); }
.cc-mark-state.is-error { color: var(--danger); }
/* A wall whose space the engineer re-kinded: the period read from this sheet
   is no longer settled, so the line is drawn broken until it is measured
   again. */
.geom-wall.engineer-stale { stroke-dasharray: 26 14; opacity: .8; }
/* A WALL RE-READ THE MOMENT HE SAID WHAT THE SPACE IS (owner, 10 Sep 2026:
   "we can do live, instant refresh of the actual drawing"). It carries a
   settled period again - worked out by the same reading that rated it - so
   it is drawn solid, with a halo that says the engineer's correction is why
   it changed. Never the broken line of "not decided": it IS decided. */
.geom-wall.engineer-rekinded {
  stroke-dasharray: none; filter: drop-shadow(0 0 3px rgba(0, 0, 0, .28));
}
/* A ROUTE whose printed row was re-read keeps the metres it walked and shows
   them plainly: no dashes, because nothing about it is unsettled. */
.geom-route.engineer-recomputed { opacity: 1; stroke-dasharray: none; }

/* ── THE FEATURE CHAIN — the job map beside every deliverable composer ─────
   25 Aug 2026. The project map's design language, turned vertical: the same
   card (icon chip + two lines), the same dashed relationship line, the same
   quiet dashed border for "empty is information, not failure". One rail per
   feature, sticky beside the composer, collapsing to a slim strip. */
.chain-layout {
  display: flex; flex-wrap: wrap; gap: 1rem; align-items: flex-start;
  width: 100%; max-width: none; margin-inline: auto;
  /* WRAP, NOT SQUEEZE (owner, 28 Aug: "it looked broken and text got
     messed up"): the snake band, the room and the result each carry
     flex-basis 100%, so without wrapping they crushed onto one row the
     moment more than one of them was visible. */
}
/* Document and drawing workbenches use the space released by collapsing
   the sidebar. Reading/composer widths remain owned by their inner views. */
#document-surface, #write-surface, #review-surface, #drawings-surface {
  max-width: none;
}
.chain-main { flex: 1 1 auto; min-width: 0; }
/* The established composers still own the event listeners and result nodes.
   In the new workflow they are a control depot: an open step borrows the real
   control, so there is one implementation but never a second visible UI. */
body[data-feature-chain="on"] .feature-control-depot { display: none; }
body[data-feature-chain="on"] .tool-surface.is-edit-mode .feature-control-depot { display: block; }
.chain-rail {
  position: sticky; top: .75rem; display: flex; flex: 0 0 292px;
  flex-direction: column; gap: .7rem; width: 292px;
  max-height: calc(100vh - 1.5rem); overflow: auto;
  padding: .85rem; border: 1px solid var(--border); border-radius: 12px;
  background: var(--surface-raised); box-shadow: 0 2px 8px rgba(14,17,22,.05);
}
.chain-head { display: flex; align-items: flex-start; justify-content: space-between; gap: .6rem; }
.chain-head h3 { margin: 0; font-family: var(--font-serif); font-size: 1.08rem; font-weight: 400; }
/* The vertical spine: one dashed line down through the icon chips, computed
   nowhere and maintained nowhere — it is a border, so a card added to the
   table lands on it by construction. Chips sit above it (z-index). */
.chain-steps { position: relative; display: flex; flex-direction: column; gap: .55rem; }
.chain-steps::before {
  content: ""; position: absolute; top: 18px; bottom: 18px; left: 24px;
  border-left: 1px dashed color-mix(in srgb, var(--ink) 30%, transparent);
}
.chain-step { position: relative; }
.chain-card {
  display: grid; grid-template-columns: 34px minmax(0, 1fr); gap: .6rem;
  align-items: center; width: 100%; padding: .7rem;
  border: 1px solid color-mix(in srgb, var(--ink) 18%, transparent);
  border-radius: 8px; color: var(--ink); background: var(--surface-raised);
  text-align: left; box-shadow: 0 2px 8px rgba(14,17,22,.05);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.chain-card:hover { border-color: var(--ink); box-shadow: 0 5px 14px rgba(14,17,22,.10); }
.chain-step.is-open > .chain-card { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.chain-node-icon {
  position: relative; z-index: 1; display: grid; place-items: center;
  width: 34px; height: 34px; border-radius: 7px;
  color: var(--ink); background: var(--surface-subtle);
}
.chain-text { min-width: 0; }
.chain-text strong { display: block; font-size: .78rem; line-height: 1.25; }
.chain-text small {
  display: -webkit-box; overflow: hidden; margin-top: .22rem;
  color: var(--muted); font-size: .77rem; line-height: 1.35;
  -webkit-box-orient: vertical; -webkit-line-clamp: 3;
}
/* Empty is information, drawn quieter — the map's own rule. */
.chain-step.is-empty > .chain-card { border-style: dashed; box-shadow: none; }
.chain-step.is-empty .chain-node-icon { color: var(--muted); }
/* A decision still owed (no sheets, no version) reads as a caution, not a
   failure: the job will run, on less than the engineer may think. */
.chain-step.is-warn > .chain-card { border-color: color-mix(in srgb, var(--warning) 55%, transparent); }
.chain-step.is-warn .chain-node-icon { color: var(--warning); background: color-mix(in srgb, var(--warning) 12%, transparent); }
.chain-step.is-warn .chain-text small { color: var(--warning); }
/* Live = the server is working; the words on the card are ITS words. */
.chain-step.is-live > .chain-card { border-color: var(--accent); }
.chain-step.is-live .chain-node-icon { color: var(--accent); background: var(--accent-soft); }
.chain-step.is-done .chain-node-icon { color: var(--success); background: color-mix(in srgb, var(--success) 12%, transparent); }
.chain-body {
  margin: .45rem 0 .2rem 0; padding: .65rem .7rem .7rem;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface-subtle); display: grid; gap: .55rem;
}
.chain-body .settings-note { margin: 0; }
.chain-body .button { justify-self: start; }
/* Prompt is ONE real textarea. With the Run chain on it lives only in the
   Prompt card; `chainBorrowControl` temporarily moves that same node into the
   open body, so the request and the visible field cannot diverge. */
body[data-feature-chain="on"] .chain-owned-prompt { display: none; }
body[data-feature-chain="on"] .chain-body .chain-owned-prompt {
  display: block; width: 100%; min-height: 7rem;
}
.chain-brief-text {
  margin: 0; max-height: 130px; overflow: auto; color: var(--ink);
  font-size: .77rem; line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere;
}
.chain-list { display: grid; gap: .3rem; margin: 0; padding: 0; list-style: none; }
.chain-list li {
  padding: .4rem .5rem; border: 1px solid var(--border); border-radius: 6px;
  background: var(--surface-raised); font-size: .77rem; line-height: 1.35;
  overflow-wrap: anywhere;
}
.chain-note { margin: 0; }
/* Collapsed: the rail folds to a slim labelled strip. Everything else in the
   rail hides; the strip alone shows, and one click brings the map back.
   The fold button itself STAYS visible on the open rail (owner, 28 Aug):
   each side carries a labelled button that maximises the other side. */
.chain-strip { display: none; }
.chain-head-actions { display: flex; align-items: center; gap: .4rem; }
.chain-expand, .chain-collapse {
  display: inline-flex; align-items: center; gap: .35rem; white-space: nowrap;
}
.chain-rail.is-collapsed { flex-basis: 100%; width: 100%; padding: .4rem .7rem; }
.chain-rail.is-collapsed :is(.chain-steps, .chain-note) { display: none; }

/* ── A FOLD: one card for the steps the project already filled (18 Sep 2026,
   owner: "Can we reduce the steps? Make it as simple as possible"). The face
   lists each held step on one short line; a required step still empty ends
   "needed" in the warning colour, so the fold never hides a gate. Open, the
   body shows the held steps' own cards, each opening its own editor. */
.chain-fold-lines {
  display: grid; gap: .12rem; margin: .25rem 0 0; padding: 0; list-style: none;
  color: var(--muted); font-size: .77rem; line-height: 1.35;
}
.chain-fold-lines li { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.chain-fold-lines li.is-needed { color: var(--warning); font-weight: 650; }
.chain-fold-hint {
  display: block; margin-top: .3rem; color: var(--accent); font-size: .77rem; font-weight: 650;
}
.chain-step.is-done .chain-fold-hint { color: var(--muted); }
.chain-substeps { display: grid; gap: .45rem; }
.chain-substep > .chain-card {
  padding: .55rem .6rem; grid-template-columns: 28px minmax(0, 1fr);
  box-shadow: none;
}
.chain-substep .chain-node-icon { width: 28px; height: 28px; }
.chain-substep .chain-text small { -webkit-line-clamp: 2; }
.chain-rail.is-snake .chain-substep > .chain-card {
  border-color: color-mix(in srgb, var(--ink) 35%, transparent); box-shadow: none; height: auto;
}
.chain-rail.is-snake .chain-substep.is-open > .chain-card { border-color: var(--accent); }
.chain-rail.is-snake .chain-substep.is-warn > .chain-card {
  border-color: color-mix(in srgb, var(--warning) 55%, transparent);
}
.chain-rail.is-snake .chain-fold-body { background: var(--surface-subtle); }
.chain-rail.is-snake .chain-substep .chain-body { background: var(--surface-raised); }

/* The brief, editable on the step itself - same field styling as the rest
   of the product, sized for a paste. */
.chain-brief-box {
  width: 100%; padding: .55rem .6rem; border: 1px solid var(--border);
  border-radius: 8px; color: var(--ink); background: var(--surface-raised);
  font: inherit; font-size: .77rem; line-height: 1.5; resize: vertical;
}
.chain-editor-actions, .chain-choice-grid {
  display: flex; flex-wrap: wrap; align-items: center; gap: .45rem;
}
.chain-choice-grid .is-selected {
  border-color: var(--accent); background: var(--accent-soft); color: var(--accent);
}
/* A chosen file says so with a small green tick (owner, 28 Aug: "when a
   file is selected should show a green small tick"), and clicking it
   again unselects - the same button is the whole option set for now. */
.chain-choice-grid .is-selected::before {
  content: "✓ "; color: var(--success); font-weight: 700;
}
.chain-question { display: grid; gap: .3rem; font-size: .77rem; }
.chain-question textarea {
  width: 100%; padding: .5rem; border: 1px solid var(--border);
  border-radius: 7px; background: var(--surface-raised); color: var(--ink);
  font: inherit; resize: vertical;
}
.chain-project-questions { display: grid; gap: .5rem; }
.chain-project-question {
  display: grid; gap: .35rem; padding: .55rem;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface-raised);
}
.chain-project-question > small {
  color: var(--accent); font-size: .77rem; font-weight: 650; line-height: 1.35;
}
.chain-project-question label { display: grid; gap: .3rem; font-size: .77rem; line-height: 1.4; }
.chain-project-question textarea {
  width: 100%; min-height: 54px; padding: .48rem .52rem;
  border: 1px solid var(--border); border-radius: 7px;
  color: var(--ink); background: var(--surface-subtle); font: inherit;
  font-size: .77rem; resize: vertical;
}
.chain-project-question > .button { justify-self: start; }
.question-provenance {
  display: block; margin: .18rem 0 .35rem; color: var(--muted);
  font-size: .77rem; font-weight: 400; line-height: 1.4;
}
.chain-folder-audit {
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface-raised); padding: .45rem .55rem;
}
.chain-folder-audit > summary { cursor: pointer; font-size: .77rem; font-weight: 650; }
.chain-folder-audit[open] > summary { margin-bottom: .45rem; }
.universal-upload-zone {
  display: grid; gap: .15rem; margin-top: .45rem; padding: .65rem;
  border: 1px dashed var(--border); border-radius: 8px; cursor: pointer;
  background: var(--surface-subtle);
}
.universal-upload-zone > strong { color: var(--ink); font-size: .77rem; }
.universal-upload-zone > .settings-note { line-height: 1.35; }
.universal-upload-zone--compact {
  display: inline-grid; min-width: 9.5rem; margin-top: 0; padding: .42rem .55rem;
  text-align: left; text-transform: none; letter-spacing: normal;
}
.universal-upload-zone--compact > strong { font-size: .77rem; }
.universal-upload-zone--compact > .settings-note { font-size: .77rem; }
.composer-options > .universal-upload-zone--compact { min-width: 8.5rem; }
.health-upload-zone.universal-upload-zone { margin-top: 0; padding: 0; }
.project-dropzone.universal-upload-zone { margin-top: 0; }
.universal-upload-zone:hover, .universal-upload-zone.drop-active {
  border-color: var(--accent); background: var(--accent-soft);
}
.universal-upload-zone.is-uploading { opacity: .65; pointer-events: none; }
.chain-declaration { color: var(--warning); }
/* A filed review, openable from the result step - a full-width row, not a
   pill, because the filename is the information. */
.chain-review-open { width: 100%; text-align: left; overflow-wrap: anywhere; }
/* A folder that will catch the file being dragged over it. */
.project-node.drop-active {
  border-color: var(--accent); border-style: solid;
  box-shadow: 0 0 0 3px var(--accent-soft);
}
/* WHAT DICTATION SHOWS WHILE IT LISTENS: pulsing dot, elapsed time, a level
   meter fed by the same stream the recording uses, and the browser's live
   word preview when it has one. The Gemini transcript stays the text of
   record and replaces the preview when it lands. */
.dictation-live {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  margin-top: .45rem; padding: .4rem .55rem;
  border: 1px dashed var(--border); border-radius: 8px;
  background: var(--surface-raised);
}
.dictation-dot {
  width: 9px; height: 9px; border-radius: 50%; background: var(--danger);
  animation: dictation-pulse 1.1s ease-in-out infinite;
}
@keyframes dictation-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: .35; transform: scale(.75); }
}
.dictation-timer {
  font-size: .77rem; font-weight: 650; font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.dictation-meter { display: inline-flex; align-items: flex-end; gap: 2px; height: 14px; }
.dictation-meter i {
  width: 3px; height: 100%; border-radius: 2px; background: var(--accent);
  transform: scaleY(.15); transform-origin: bottom;
  transition: transform .08s linear;
}
.dictation-interim {
  flex: 1 1 100%; font-size: .77rem; line-height: 1.4; color: var(--muted);
  font-style: italic; min-height: 0;
}
.chain-actions .is-recording { color: var(--danger); border-color: var(--danger); }
/* The dot that says a note is saved on this step. */
.chain-step.has-note .chain-node-icon::after {
  content: ""; position: absolute; top: -3px; right: -3px;
  width: 8px; height: 8px; border-radius: 50%;
  border: 1.5px solid var(--surface-raised); background: var(--accent);
}
/* The one-shot flash a chain jump leaves on the real control, so the eye
   lands where the edit happens. */
.chain-flash { animation: chain-flash 1.6s ease; }
@keyframes chain-flash {
  0%, 55% { box-shadow: 0 0 0 3px var(--accent-soft); }
  100% { box-shadow: 0 0 0 0 transparent; }
}
/* Narrow screens: the rail leaves the side and stacks under the composer —
   the composer is the work, the map is the explanation of it. */
@media (max-width: 1100px) {
  .chain-layout { flex-direction: column; }
  .chain-rail { position: static; width: auto; flex-basis: auto; max-height: none; }
  .chain-rail.is-collapsed { width: auto; }
}
@media (max-width: 680px) { .chain-steps { grid-template-columns: 1fr; } }
:root[data-theme="dark"] :is(.chain-rail, .chain-card) { box-shadow: none; }
:root[data-theme="dark"] .chain-card:hover { box-shadow: 0 5px 14px rgba(0,0,0,.45); }
@media (prefers-reduced-motion: reduce) {
  .chain-flash { animation: none; }
  .chain-card { transition: none; }
}

/* ── Upload context: the type-or-dictate box under every upload zone ──────
   The owner's rule (27 Aug): a file never arrives without a place for the
   words about it. Outside the zone, so typing never opens the picker. */
.upload-with-context { display: grid; gap: .4rem; }
.upload-context {
  width: 100%; padding: .5rem .6rem; border: 1px solid var(--border);
  border-radius: 8px; color: var(--ink); background: var(--surface-raised);
  font: inherit; font-size: .77rem; line-height: 1.45; resize: vertical;
  min-height: 2.4rem;
}
.upload-context:focus { outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft); }

/* ── The snake: feature steps on the map's canvas grammar ─────────────────
   Same steps, same logic, same cards — laid as a serpentine over the dotted
   canvas instead of a single column. The rail widens to a full band; the
   dashed spine gives way to per-card connectors laid by layoutSnakeRail().
   `?snake=0` restores the vertical rail. */
.chain-rail.is-snake {
  position: static; order: -1; flex: 1 1 100%; width: 100%;
  max-height: none; overflow: visible;
  background:
    radial-gradient(color-mix(in srgb, var(--ink) 14%, transparent) 1px,
      transparent 1px) 0 0 / 22px 22px,
    var(--surface-subtle);
}
.chain-rail.is-snake .chain-steps { display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .8rem 1.1rem; }
@media (max-width: 900px) {
  .chain-rail.is-snake .chain-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.chain-rail.is-snake .chain-steps::before { content: none; }
.chain-rail.is-snake .chain-step { min-width: 0; }
.chain-rail.is-snake .chain-card { height: 100%; }
/* Connectors: the snake's own line — bold, black, unmissable (the owner:
   "visibly aggressive, black and white, Harvey-inspired"). Solid ink with a
   squared end-cap dot, so the path reads at a glance. */
.chain-rail.is-snake .chain-step::after {
  content: ""; position: absolute; z-index: 0;
  border: 0 solid var(--ink);
}
.chain-rail.is-snake .chain-step::before {
  content: ""; position: absolute; z-index: 0;
  width: 7px; height: 7px; background: var(--ink); display: none;
}
.chain-rail.is-snake .chain-step.snake-right::after {
  top: 50%; right: -1.15rem; width: 1.15rem; border-top-width: 3px;
}
.chain-rail.is-snake .chain-step.snake-right::before {
  display: block; top: calc(50% - 2px); right: -0.7rem;
}
.chain-rail.is-snake .chain-step.snake-left::after {
  top: 50%; left: -1.15rem; width: 1.15rem; border-top-width: 3px;
}
.chain-rail.is-snake .chain-step.snake-left::before {
  display: block; top: calc(50% - 2px); left: -0.7rem;
}
.chain-rail.is-snake .chain-step.snake-down::after {
  left: 50%; bottom: -.85rem; height: .85rem; border-left-width: 3px;
}
.chain-rail.is-snake .chain-step.snake-down::before {
  display: block; bottom: -0.55rem; left: calc(50% - 2px);
}
/* The cards themselves sharpen on the canvas: full-ink border, hard shadow. */
.chain-rail.is-snake .chain-card {
  border-color: var(--ink);
  box-shadow: 3px 3px 0 color-mix(in srgb, var(--ink) 18%, transparent);
}
.chain-rail.is-snake .chain-step.is-empty > .chain-card {
  border-color: color-mix(in srgb, var(--ink) 45%, transparent);
}
/* The open step takes the whole row: the body gets reading width and the
   snake visibly pauses on the step being worked. */
.chain-rail.is-snake .chain-step.is-open {
  grid-column: 1 / -1 !important;
}
.chain-rail.is-snake .chain-step.is-open::after { content: none; }
.chain-rail.is-snake .chain-body { background: var(--surface-raised); }
/* An open snake step grows with its body — height:100% on the card was a
   sizing loop that pushed the body outside the row (measured: body bottom
   610 vs item bottom 444). */
.chain-rail.is-snake .chain-step.is-open .chain-card { height: auto; }

/* ── Mobile: the phone is a first-class client (owner, 27 Aug, from his
   own phone). The faults he photographed: section labels wrapping mid-word
   ("PROJECT S"), the sidebar stacking into a broken band, tabs cramped. ── */
.section-label span { white-space: nowrap; }
@media (max-width: 700px) {
  /* One column on a phone: the rail's painted ground does not apply, so the
     gradient is repainted flat here rather than letting the desktop paint
     bleed under stacked content. Attribute-qualified so the positional
     guard scans still read the desktop block as the last plain rule. */
  #workspace-view[id] {
    display: block;
    background: var(--surface);
  }
  .sidebar[aria-label] {
    display: grid; grid-template-columns: 1fr 1fr; gap: .5rem .8rem;
    width: auto; max-width: none; height: auto; position: static;
    padding: .6rem .8rem;
    border-right: 0; border-bottom: 1px solid var(--border);
  }
  .sidebar .sidebar-head { grid-column: 1 / -1; }
  .sidebar .sidebar-usage, .sidebar .sidebar-settings,
  .sidebar .sidebar-footer { grid-column: 1 / -1; }
  .surface-nav {
    display: flex; overflow-x: auto; -webkit-overflow-scrolling: touch;
    gap: .25rem; padding-bottom: .25rem; scrollbar-width: none;
  }
  .surface-nav::-webkit-scrollbar { display: none; }
  .surface-tab { flex: 0 0 auto; white-space: nowrap; }
  .chain-rail.is-snake .chain-steps { grid-template-columns: 1fr; }
  .chain-rail.is-snake .chain-step::after,
  .chain-rail.is-snake .chain-step::before { content: none; }
  .upload-with-context, .upload-context { width: 100%; }
}
@media (max-width: 560px) {
  .sidebar[aria-label] { grid-template-columns: 1fr; }
}

/* ── The snake folds and expands; the deliverable leads (owner, 27 Aug) ── */
/* Folded (owner, 3 Sep 2026: revert to the previous top-right button):
   the HEAD row alone - title left, the same black New run at the right -
   above the result, in normal flow. */
.chain-rail.is-snake.is-collapsed {
  order: -1; flex-basis: 100%; width: 100%; padding: .35rem .7rem;
  background: none; border: none; max-height: none;
}
.chain-rail.is-collapsed .chain-head { margin: 0; }
.chain-rail.is-snake.is-fullscreen {
  /* A real full-screen room, not a stretched card (owner: "maximise is
     kinda weird"): the canvas fills the viewport with its own backdrop,
     the steps sit in a centred column at reading width, and the same
     button that opened it closes it - highlighted so the way out is
     obvious. */
  position: fixed; inset: 0; z-index: 60; margin: 0; border-radius: 0;
  border: 0; overflow: auto; max-height: none;
  padding: 2.2rem clamp(1.2rem, 6vw, 4rem) 3rem;
}
.chain-rail.is-snake.is-fullscreen .chain-steps,
.chain-rail.is-snake.is-fullscreen .chain-head,
.chain-rail.is-snake.is-fullscreen .chain-note {
  max-width: 1080px; margin-left: auto; margin-right: auto;
}
.chain-rail.is-snake.is-fullscreen .chain-steps { gap: 1rem 1.3rem; }
.chain-rail.is-snake.is-fullscreen .chain-card { padding: .9rem; }
.chain-rail.is-snake.is-fullscreen .chain-expand {
  color: var(--surface); background: var(--ink); border-color: var(--ink);
}

/* ── Mobile corrections from the Codex 390px audit ─────────────────────── */
@media (max-width: 700px) {
  /* Sidebar sections stack; the row layout crushed Projects to 18px. */
  .sidebar[aria-label] .sidebar-section { display: block; min-width: 0; }
  /* Fingers, not cursors: WCAG-sized targets on the controls that matter. */
  .surface-tab, .project-item, .conversation-item .project-open,
  .chain-card, .icon-button, .button { min-height: 44px; }
  .section-label .icon-button { min-height: 36px; min-width: 36px; }
}

/* ── The drawing COMMAND CENTRE: the sheet centre-stage, map grammar ───── */
.cc-stage {
  border: 1px solid var(--ink); border-radius: 12px; overflow: hidden;
  background:
    radial-gradient(color-mix(in srgb, var(--ink) 16%, transparent) 1px,
      transparent 1px) 0 0 / 22px 22px,
    var(--surface-subtle);
}
.cc-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: .6rem; padding: .5rem .7rem;
  border-bottom: 1px solid var(--ink); background: var(--surface-raised);
}
.cc-tools { display: flex; align-items: center; gap: .35rem; }
.cc-viewport {
  position: relative; overflow: hidden; max-height: 74vh; min-height: 320px;
  cursor: grab; touch-action: none;
}
.cc-viewport:active { cursor: grabbing; }
.cc-stage[data-cc-note-mode="1"] .cc-viewport { cursor: crosshair; }
.cc-viewport .drawing-canvas { transform-origin: 0 0; will-change: transform; }
.cc-note-toggle.is-armed { border-color: var(--accent); color: var(--accent); }
.cc-pins { position: absolute; inset: 0; pointer-events: none; }
/* THE FINDINGS LAYER IS DOTS (owner, 18 Sep 2026: "I just want the dot").
   A dot sits at its finding's place, sized as a share of the sheet so it
   scales exactly as the numbered discs did (36 px on a 3,000 px master), in
   the severity colour with a hairline of paper round it; no number. The
   number and the headline are its hover title, and a press opens the
   finding in the queue. The layer itself lets the pointer through, so the
   sheet still pans between the dots. */
.cc-dots { pointer-events: none; }
.cc-dot {
  position: absolute; transform: translate(-50%, -50%);
  width: 1.1%; aspect-ratio: 1 / 1; height: auto; min-width: 0; padding: 0;
  border-radius: 50%; border: 1px solid var(--marker-ring); background: var(--marker-medium);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .18); cursor: pointer;
  pointer-events: auto; font-size: 0; line-height: 0; color: transparent;
}
.cc-dot.severity-high, .cc-dot.severity-critical { background: var(--marker-high); }
.cc-dot.severity-medium { background: var(--marker-medium); }
.cc-dot.severity-low, .cc-dot.severity-advisory { background: var(--marker-low); }
.cc-dot:hover, .cc-dot:focus-visible, .cc-dot.is-active {
  box-shadow: 0 0 0 2px var(--marker-ring), 0 0 0 4px var(--accent); outline: 0;
}
/* The sheet's one line when its routes were not measured: no panel, no
   heading, the reason behind "why". */
.sheet-unmeasured { margin: .35rem 0 .2rem; }
.sheet-unmeasured > summary { padding: .2rem .1rem; font-size: .8rem; }
/* The note pin wears the map's grammar (owner, 28 Aug: "something black
   and white, more to brand... feeling native"): a hard ink square with the
   product's offset shadow, not a generic red balloon. */
.cc-pin {
  /* SMALLER STILL (owner, 2 Sep: "they need to be much smaller in size"),
     glyph dead-centre via grid, and resizable: drag the bottom-right
     corner (a nub appears on hover) between 8 and 40px. */
  position: absolute; transform: translate(-50%, -50%);
  width: 11px; height: 11px; border-radius: 50%;
  border: 1px solid var(--surface); background: var(--ink);
  color: var(--surface); display: grid; place-items: center; padding: 0;
  font-size: 6px; line-height: 1; pointer-events: auto; cursor: help;
  box-shadow: 0 1px 2px color-mix(in srgb, var(--ink) 35%, transparent);
}
.cc-pin:hover::after { content: ""; position: absolute; right: -3px;
  bottom: -3px; width: 6px; height: 6px; border-radius: 2px;
  background: var(--accent); border: 1px solid var(--surface);
  cursor: nwse-resize; }
.cc-pin.is-new { outline: 2px solid var(--accent); outline-offset: 1px; }
/* A FIGURE pin (owner, 2 Sep 2026: two kinds of comments). Square where a
   comment is round, accent where a comment is ink — readable at a glance
   which marks direct the review and which go INTO the written report. */
.cc-pin-figure { border-radius: 3px; background: var(--accent); }
/* The framed figure area: the engineer's own rectangle, outlined on the
   sheet (owner, 3 Sep 2026). The live band shares the look. */
.cc-pin-rect, .cc-band { position: absolute; border: 2px solid var(--accent);
  border-radius: 3px; background: color-mix(in srgb, var(--accent) 12%, transparent);
  transform: none; width: auto; height: auto; min-width: 0; min-height: 0;
  box-shadow: none; color: transparent; font-size: 0; cursor: pointer;
  pointer-events: auto; }
.cc-band { pointer-events: none; border-style: dashed; }
.cc-frame-hint { margin: 0 0 .3rem; font-size: .77rem; }
.cc-note-kinds { display: flex; gap: .3rem; margin-bottom: .35rem; }
.cc-note-kinds .button.is-selected { background: var(--ink);
  color: var(--surface); border-color: var(--ink); }
/* The one main action on a finished review (owner, 28 Aug: "make the rev
   CTA more visible... the comments become the centre piece"). The ink bar
   itself is defined once above; these grow the button to main-CTA weight. */
.drawing-revision-bar span { font-size: .78rem; line-height: 1.5; }
/* Black button, white text (owner, 3 Sep 2026) - the main action reads
   as the main action. */
.drawing-revision-bar .revision-cta {
  flex: 0 0 auto; font-size: .85rem; padding: .65rem 1.1rem;
  background: var(--ink); color: var(--surface); border-color: var(--ink);
}
.drawing-revision-bar .revision-cta:hover {
  background: color-mix(in srgb, var(--ink) 86%, var(--surface));
  color: var(--surface);
}
.drawing-revision-bar .revision-cta:disabled {
  background: var(--surface); color: var(--muted);
  border-color: var(--border);
}
.cc-pin[data-entry-id] { cursor: grab; }
.cc-pin[data-entry-id]:active { cursor: grabbing; }
/* The sheet is a canvas: never let the browser lift the PNG as a drag
   ghost, and never let a drag select text under the cursor. */
.cc-viewport img { -webkit-user-drag: none; user-select: none; }
.cc-viewport { user-select: none; }

/* The autosaving note: quiet status beside the box, green tick on save. */
.drawing-feedback-form { position: relative; }
.feedback-status {
  display: block; min-height: 1rem; margin-top: .15rem;
  font-size: .77rem; color: var(--muted);
}
.feedback-status[data-tone="ok"] { color: var(--success); }
.feedback-status[data-tone="error"] { color: var(--warning); }
.feedback-status.is-ticked { animation: feedback-tick .45s ease; }
@keyframes feedback-tick {
  0% { opacity: 0; transform: translateY(2px) scale(.92); }
  60% { opacity: 1; transform: translateY(0) scale(1.06); }
  100% { transform: scale(1); }
}

/* The folded notices strip: severity stays visible on the closed line. */
.trust-count-warn, .trust-count-ask { color: var(--warning); font-weight: 650; }
.trust-fold-warn > summary { border-color:
  color-mix(in srgb, var(--warning) 55%, transparent); }
.trust-fold-mark { color: var(--warning); }

/* "What was checked" folds closed; the counts live on the summary line. */
.checks-fold > summary { display: flex; align-items: center; gap: .8rem;
  flex-wrap: wrap; cursor: pointer; }
.checks-fold > summary h3 { margin: 0; }

/* Earlier filed runs on the empty room. */
.stage-past { display: flex; align-items: center; justify-content: center;
  gap: .4rem; flex-wrap: wrap; margin-top: .6rem; }

/* Find any file inside any step: the filter box a big step earns. */
.chain-search {
  width: 100%; padding: .45rem .6rem; border: 1px solid var(--border);
  border-radius: 8px; color: var(--ink); background: var(--surface-raised);
  font: inherit; font-size: .77rem;
}
.chain-search:focus { outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft); }
/* The folded strip's second door: start a fresh run without unfolding. */

/* The pre-run checklist: what to finish, each line a door to its step. */
.chain-guide {
  padding: .6rem .75rem; border-radius: 8px; font-size: .77rem;
  border: 1px solid color-mix(in srgb, var(--warning) 55%, transparent);
  background: color-mix(in srgb, var(--warning) 10%, transparent);
}
.chain-guide ol { margin: .35rem 0 0 1.1rem; padding: 0; display: grid; gap: .3rem; }
.chain-guide-step {
  padding: 0; border: 0; background: none; color: var(--accent);
  font: inherit; text-decoration: underline; cursor: pointer;
}

/* ── The forming paper: the writer's document taking shape ─────────────── */
.writer-paper { margin: .8rem 0; }
.paper-head { display: flex; align-items: baseline; gap: .8rem; margin-bottom: .5rem; }
/* One line that says what the list is, in his words, before the first draft. */
.paper-lead { margin: 0 0 .5rem; color: var(--muted); font-size: .8rem; line-height: 1.5; }
.paper-lead b { color: var(--ink); font-weight: 700; }
.paper-page {
  background: var(--surface-raised); border: 1px solid var(--ink); border-radius: 4px;
  box-shadow: 4px 4px 0 color-mix(in srgb, var(--ink) 15%, transparent);
  padding: 1.4rem 1.6rem; max-width: 720px;
}
:root[data-theme="dark"] .paper-page { background: var(--surface-raised); }
.paper-section {
  display: grid; grid-template-columns: 2rem 1fr auto; gap: .8rem;
  align-items: center; padding: .55rem .4rem;
  border-bottom: 1px dashed color-mix(in srgb, var(--ink) 25%, transparent);
}
.paper-section h4 { margin: 0; font-family: var(--font-serif); font-weight: 500; font-size: .95rem; }
.paper-section p { margin: .15rem 0 0; font-size: .77rem; color: var(--muted); }
.paper-no { font-family: var(--font-serif); color: var(--muted); }
.paper-state { font-size: 1rem; width: 1.6rem; text-align: center; }
.paper-section.is-gap { cursor: pointer; }
.paper-section.is-gap:hover { background: color-mix(in srgb, var(--ink) 5%, transparent); }
.paper-section.is-gap .paper-state { color: var(--muted); }
.paper-section.is-ready .paper-state { color: var(--accent); }
.paper-section.is-written .paper-state { color: var(--success); }
.paper-section.is-written p { color: var(--success); }
.paper-section.is-missing .paper-state { color: var(--warning); }
.paper-section.is-missing p { color: var(--warning); }

/* ── The manuscript: the reviewed document with margin comments ────────── */
/* COMPACT (owner, 18 Sep 2026): the quote and the proposal side by side,
   each as tall as its own words and no taller; a small "Open" button. */
.manuscript {
  margin: .5rem 0; border: 1px solid var(--ink); border-radius: 6px;
  background: var(--surface-raised); padding: .5rem .7rem;
}
.ms-head { display: flex; align-items: baseline; gap: .8rem; margin-bottom: .3rem; }
.ms-row {
  display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: .6rem; padding: .35rem 0; align-items: start;
  border-bottom: 1px dashed color-mix(in srgb, var(--ink) 22%, transparent);
}
.ms-row:last-child { border-bottom: 0; }
.ms-quote {
  margin: 0; padding: .3rem .6rem;
  border-left: 3px solid var(--ink); background: var(--surface-raised);
  font-family: var(--font-serif); font-size: .82rem; line-height: 1.4;
}
:root[data-theme="dark"] .ms-quote { background: var(--surface-subtle); }
.ms-bubble {
  align-self: start; padding: .35rem .55rem; border: 1px solid var(--border);
  border-radius: 10px 10px 10px 2px; background: var(--surface-subtle);
  font-size: .77rem;
}
.ms-bubble strong { display: block; margin-bottom: .15rem; font-size: .77rem; }
.ms-bubble p { margin: 0 0 .3rem; line-height: 1.35; }
.ms-bubble .button.small { min-height: 22px; padding: .1rem .45rem; font-size: .77rem; }
.ms-bubble.is-high { border-color: color-mix(in srgb, var(--warning) 60%, transparent); }
@media (max-width: 700px) { .ms-row { grid-template-columns: 1fr; } }

/* The rooms before the work: an honest empty stage is still the stage. */
.stage-default { margin: .8rem 0; }
.stage-default .stage-empty {
  min-height: 200px; display: grid; place-content: center; gap: .8rem;
  text-align: center; padding: 1.6rem;
}
.stage-default .stage-empty p {
  max-width: 460px; margin: 0; color: var(--muted);
  font-size: .8rem; line-height: 1.55;
}
.stage-default .stage-empty .button { justify-self: center; }

/* ── THE KEYSTEP: review our output, hand your marked-up input back ─────
   The door to the final deliverable wears the map's black. When Run 1 is
   done and this still sits empty, it is the loudest thing on the snake. */
/* THE FEEDBACK STEP: emphasised, never a black block. The owner, 1 Sep
   evening: "remove the black background cell, it confuses me each time on
   where the end is" — so this card stays light with a strong border, and
   the END of the chain (Download, .is-endstep below) carries the loudest
   treatment, because the end is what the eye needs to find. */
.chain-step.is-keystep > .chain-card {
  background: var(--accent-soft);
  border: 2px solid var(--ink); color: var(--ink);
}
.chain-step.is-keystep > .chain-card .chain-text strong { color: var(--ink); }
.chain-step.is-keystep > .chain-card .chain-text small { color: var(--muted); }
.chain-step.is-keystep .chain-node-icon {
  background: color-mix(in srgb, var(--ink) 10%, transparent); color: var(--ink);
}
.chain-step.is-keystep.is-done > .chain-card {
  background: var(--surface-raised); color: var(--ink);
  border-color: var(--ink);
}
.chain-step.is-keystep.is-done > .chain-card .chain-text strong { color: var(--ink); }
.chain-step.is-keystep.is-done > .chain-card .chain-text small { color: var(--muted); }
.chain-step.is-keystep.is-done .chain-node-icon {
  color: var(--success);
  background: color-mix(in srgb, var(--success) 12%, transparent);
}
/* THE END OF THE CHAIN. A double-rule border says "this is where it all
   lands" without a drop of black fill. */
.chain-step.is-endstep > .chain-card {
  border: 2px solid var(--ink);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ink) 14%, transparent);
  background: var(--surface);
}
.chain-step.is-endstep .chain-node-icon {
  color: var(--ink);
  background: color-mix(in srgb, var(--ink) 10%, transparent);
}
@keyframes keystep-call { 0%, 100% { box-shadow: 3px 3px 0 color-mix(in srgb, var(--ink) 18%, transparent); } 50% { box-shadow: 0 0 0 6px color-mix(in srgb, var(--ink) 30%, transparent); } }
.chain-step.is-keystep.is-urgent > .chain-card {
  animation: keystep-call 2.2s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .chain-step.is-keystep.is-urgent > .chain-card { animation: none;
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--ink) 30%, transparent); }
}
/* The rooms take a full row beneath the snake in the surface flex. */
.writer-paper, .stage-default { flex: 1 1 100%; min-width: 0; }
/* The relocated result stands where the room stands: full width, beside the
   snake — its birth home inside the hidden depot is display:none. */
.chain-layout > .tool-result { flex: 1 1 100%; min-width: 0; }
/* An upload still in flight: named at once, tickable when stored. */
.drawing-choice.is-pending { opacity: .6; }
.drawing-choice.is-pending .settings-note { margin-left: .35rem; }

/* ── The finding number is a door to its place on the sheet ─────────────
   The owner, 29 Aug 2026: everything internally linked. Clicking a
   finding's number takes the Command Centre to that marker. A finding
   with no located place keeps the plain dash and is not a button. */
.drawing-marker-go {
  cursor: pointer; border: 0; font: inherit;
  transition: transform .12s ease, box-shadow .12s ease;
}
.drawing-marker-go:hover {
  transform: scale(1.12);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.drawing-marker-go:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
/* The landing flash: a ring that says "here", then leaves. */
.cc-goto-flash {
  position: absolute; width: 46px; height: 46px; border-radius: 50%;
  transform: translate(-50%, -50%); pointer-events: none;
  border: 3px solid var(--accent);
  animation: cc-goto-pulse 2.4s ease-out forwards;
}
@keyframes cc-goto-pulse {
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(2.2); }
  18%  { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  70%  { opacity: 1; }
  100% { opacity: 0; }
}

/* THE SECTION ROOM — the writer's answer to the drawing reviewer's pinned
   comments (owner, 30 Aug 2026: "we want similar for writter"). Brand-native
   black and white, the same restraint the drawing comments were asked for.
   Every row of the forming paper opens one; the note box autosaves. */
.paper-section { cursor: pointer; }
.paper-section:hover { background: color-mix(in srgb, var(--ink) 5%, transparent); }
.paper-section:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.paper-notes {
  font-size: .77rem; font-weight: 700; color: var(--muted);
  padding: .1rem .34rem; border: 1px solid var(--border); border-radius: 999px;
}
.section-room {
  position: fixed; inset: 0; z-index: 70; display: grid; place-items: center;
  padding: 1.5rem; background: color-mix(in srgb, var(--ink) 46%, transparent);
  backdrop-filter: blur(2px);
}
.section-room[hidden] { display: none; }
.section-room-card {
  width: min(760px, 100%); max-height: min(84vh, 900px); overflow-y: auto;
  display: grid; gap: .9rem; padding: 1.5rem 1.7rem;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 12px; box-shadow: var(--shadow-pop);
}
.section-room-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  border-bottom: 1px solid var(--border); padding-bottom: .7rem;
}
.section-room-head h3 {
  margin: 0; font-family: var(--font-serif); font-weight: 500; font-size: 1.15rem;
}
.section-room-body {
  max-height: 42vh; overflow-y: auto; padding-right: .4rem;
  font-family: var(--font-serif); font-size: .88rem; line-height: 1.65;
}
.section-room-body p { margin: 0 0 .8rem; }
.section-room-notes { display: grid; gap: .6rem; margin: 0; padding: 0; }
.section-room-notes li {
  list-style: none; padding: .6rem .7rem; border-left: 2px solid var(--ink);
  background: var(--surface-subtle); border-radius: 0 6px 6px 0;
}
.section-room-notes p { margin: 0 0 .2rem; font-size: .8rem; }

/* THE FILED-DRAFT HEADER: its name, and the button that hands over the file.
   The owner, 31 Aug 2026: "when I click on a past fire strategy that's been
   generated, I should be able to download it." */
.record-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap;
  border-bottom: 1px solid var(--border); padding-bottom: .7rem;
  margin-bottom: .2rem;
}
.record-head h3 {
  margin: 0; font-family: var(--font-serif); font-weight: 500; font-size: 1.05rem;
}

/* A rotated guidance page: standards print landscape tables on portrait
   sheets (owner's BS 9991 Table 5 screenshot, 1 Sep 2026). The stage
   scrolls; the turn never crops the page. */
.guidance-viewer-stage { overflow: auto; }
.guidance-viewer-stage img.rot-90 { transform: rotate(90deg); }
.guidance-viewer-stage img.rot-180 { transform: rotate(180deg); }
.guidance-viewer-stage img.rot-270 { transform: rotate(270deg); }
.guidance-viewer-stage img.rot-90,
.guidance-viewer-stage img.rot-270 { margin: 12% auto; max-width: 78vh; }
/* The LIGHTBOX image too. The rules above are scoped to the viewer stage,
   so clicking rotate in the full-size view changed the class and drew
   nothing — "the rotation doesn't work" (owner, 2 Sep 2026). */
#guidance-lightbox img.rot-90 { transform: rotate(90deg); }
#guidance-lightbox img.rot-180 { transform: rotate(180deg); }
#guidance-lightbox img.rot-270 { transform: rotate(270deg); }
#guidance-lightbox img.rot-90,
#guidance-lightbox img.rot-270 { max-width: 88vh; max-height: 92vw; }

/* ── Teamwork: the bell and the project team menu (2 Sep 2026) ─────────── */
.notify-bell { position: relative; }
.notify-bell > summary { list-style: none; position: relative; cursor: pointer; }
.notify-bell > summary::-webkit-details-marker { display: none; }
.notify-count {
  position: absolute; top: -4px; right: -6px; min-width: 16px; height: 16px;
  border-radius: 8px; background: var(--danger); color: var(--sidebar-fg);
  font-size: 10px; line-height: 16px; text-align: center; padding: 0 4px;
  font-variant-numeric: tabular-nums;
}
.notify-menu {
  position: absolute; right: 0; top: calc(100% + 8px); width: 340px;
  max-height: 420px; overflow-y: auto; z-index: 60;
  background: var(--surface);
  border: 1px solid var(--border); border-radius: 10px;
  box-shadow: var(--shadow-pop); padding: 10px;
}
.notify-menu-head { display: flex; justify-content: space-between;
  align-items: center; margin-bottom: 6px; font-weight: 600; }
.notify-list { display: flex; flex-direction: column; gap: 6px; }
.notify-item { display: flex; flex-direction: column; gap: 2px;
  padding: 8px; border-radius: 8px; border: 1px solid transparent;
  font-size: 13px; }
.notify-item.is-unread { background: var(--accent-soft);
  border-color: var(--border); }
.notify-item time { font-size: .77rem; color: var(--muted); }
.notify-actions { display: flex; gap: 12px; margin-top: 2px; }
.project-team { position: relative; }
.project-team > summary { list-style: none; cursor: pointer; }
.project-team > summary::-webkit-details-marker { display: none; }
.project-team-menu {
  position: absolute; right: 0; top: calc(100% + 8px); width: 300px;
  z-index: 55; background: var(--surface);
  border: 1px solid var(--border); border-radius: 10px;
  box-shadow: var(--shadow-pop); padding: 12px;
  display: flex; flex-direction: column; gap: 8px;
}
.project-team-list { display: flex; flex-direction: column; gap: 4px; }
.project-team-row { display: flex; justify-content: space-between;
  font-size: 13px; }
.project-invite-form { display: flex; gap: 6px; }
.project-invite-form input { flex: 1 1 auto; min-width: 0; }

/* ── Calculations surface (2 Sep 2026) ─────────────────────────────────── */
.calcs-layout { display: grid; grid-template-columns: minmax(260px, 380px) 1fr;
  gap: 20px; align-items: start; }
@media (max-width: 760px) { .calcs-layout { grid-template-columns: 1fr; } }
.calcs-finder input[type="search"] { width: 100%; }
.calcs-results { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
.calcs-hit { display: flex; flex-direction: column; gap: 3px; text-align: left;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 10px; padding: 10px 14px; cursor: pointer; }
.calcs-hit:hover { border-color: var(--accent); }
.calcs-hit-title { font-weight: 600; }
.calcs-hit-sub { font-size: 12px; color: var(--muted); }
/* The folded card: ONE line of summary, clipped, never a paragraph (owner,
   18 Sep 2026: "the default of calculations should be minimized"). */
.calcs-hit-summary { display: block; width: 100%; min-width: 0; font-size: 12.5px; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.calcs-badge { align-self: flex-start; font-size: .77rem; font-weight: 700;
  letter-spacing: 0.05em; text-transform: uppercase; border-radius: 4px;
  padding: 1px 7px; background: var(--surface-subtle); color: var(--muted);
  border: 1px solid var(--border); }
.calcs-badge.is-verified { background: var(--accent-soft); color: var(--accent);
  border-color: var(--accent); }
.calcs-panel { background: var(--surface); border: 1px solid var(--border);
  border-radius: 12px; padding: 18px 20px; display: flex;
  flex-direction: column; gap: 10px; }
.calcs-panel header { display: flex; justify-content: space-between;
  gap: 12px; align-items: baseline; flex-wrap: wrap; }
/* ONE COLUMN, ONE INPUT PER ROW (owner, 18 Sep 2026). The two-column grid
   put a fifteen-code label in upper case over the next field at 1366 px:
   `repeat(auto-fit, minmax(220px, 1fr))` gave two 270 px tracks and a
   letter-spaced RESIDENTIAL_OTHER_BEDROOM_CORRIDORS is wider than one. */
#calcs-form { display: grid; grid-template-columns: 1fr; gap: 10px; min-width: 0; }
#calcs-form .calcs-field { min-width: 0; }
#calcs-form .calcs-field label, #calcs-form .calcs-field-help { overflow-wrap: anywhere; }
.calcs-input, .calcs-claimed { display: flex; flex-direction: column; gap: 4px;
  font-size: 13.5px; }
.calcs-card { white-space: pre-wrap; overflow-x: auto;
  background: var(--surface-subtle); border: 1px solid var(--border);
  border-radius: 10px; padding: 12px 14px; font-size: 13px; }

/* ── Rail chat: the RIGHT panel (owner, 2 Sep 2026: "what happened to the
   right side bar, you never created that?"). Third grid column of the
   workspace, resizable from its left edge; the left menu stays put. ── */
.rail-chat { display: flex; flex-direction: column; gap: 8px;
  position: sticky; top: 0; height: 100vh; min-height: 0;
  padding: .8rem .7rem; border-left: 1px solid var(--border);
  background: var(--surface); animation: railchat-in 0.18s ease; }
.rail-resizer { position: absolute; top: 0; left: -5px; width: 12px;
  height: 100%; cursor: col-resize; z-index: 220; touch-action: none; }
.rail-resizer::after { content: ""; position: absolute; top: 50%;
  left: 3px; transform: translateY(-50%); width: 3px; height: 44px;
  border-radius: 3px;
  background: color-mix(in srgb, var(--ink) 22%, transparent); }
.rail-resizer:hover::after,
body.resizing-rail .rail-resizer::after {
  background: var(--accent); height: 72px; }
body.resizing-rail { cursor: col-resize; user-select: none; }
/* NO `position: relative` HERE. It overrode the sticky rule above, so the
   panel scrolled away with the page and only its bottom edge was left at the
   top of the screen (owner, 4 Sep 2026: "when i scroll down, it looks
   sloppy"). A sticky element is positioned, so the resizer's absolute
   placement still works. */
@media (prefers-reduced-motion: reduce) { .rail-chat { animation: none; } }
@keyframes railchat-in { from { opacity: 0.4; transform: translateX(8px); }
  to { opacity: 1; transform: none; } }
.rail-chat-head { display: flex; align-items: center; gap: 8px; }
/* "Open full" is a control, not spare text — it must never be crushed
   into a vertical sliver when the title is long (owner's screenshot,
   2 Sep 2026: the arrow squeezed against the fold). */
.rail-chat-head .link-button,
.rail-chat-head button { flex: 0 0 auto; white-space: nowrap; }
.rail-chat-head strong { flex: 1 1 auto; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.rail-chat-thread { flex: 1 1 auto; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 8px; padding-right: 2px; }
.rail-msg { border-radius: 10px; padding: 8px 10px; font-size: 12.5px;
  line-height: 1.5; overflow-wrap: anywhere; }
.rail-msg-q { background: var(--accent-soft); align-self: flex-end;
  max-width: 92%; }
.rail-msg-a { background: var(--surface); border: 1px solid var(--border); }
.rail-msg-a.is-waiting { color: var(--muted); font-style: italic; }
.rail-msg-a img { max-width: 100%; height: auto; border-radius: 6px; }
.rail-msg-a table { font-size: .77rem; display: block; overflow-x: auto; }
.rail-msg-a h1, .rail-msg-a h2, .rail-msg-a h3 { font-size: 13px; margin: 6px 0 2px; }
.rail-chat-form { display: flex; flex-direction: column; gap: 6px; align-items: stretch; }
.rail-chat-options { display: flex; align-items: center; gap: 6px; min-width: 0; }
.rail-chat-options .button { margin-left: auto; flex: 0 0 auto; }
.rail-chat-options .select-pill { flex: 0 0 auto; }
.rail-chat-guidance { flex: 1 1 auto; min-width: 0; font-size: .77rem; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rail-chat-form textarea { flex: 1 1 auto; min-width: 0; resize: none;
  font-size: 13px; }

/* ── Consistency pass over the 2 Sep additions (owner: "same style across
   the product"). Everything here sits on the product's own scale: 15px
   root, .68-.82rem body copy, .72rem compact controls. The link-button
   class was referenced and never defined, so every "Mark all read",
   Accept/Decline and Open full rendered as a raw system button. ─────── */
.link-button {
  background: none; border: none; padding: 0; cursor: pointer;
  color: var(--accent); font-size: .77rem; font-weight: 600;
  text-decoration: underline; text-underline-offset: 2px;
}
.link-button:hover { color: var(--accent-dark); }
.notify-menu { width: 300px; padding: .55rem .6rem; }
.notify-menu-head { font-size: .77rem; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted); font-weight: 700; }
.notify-item { font-size: .77rem; padding: .45rem .55rem; }
.notify-item time { font-size: .77rem; }
.notify-count { min-width: 14px; height: 14px; border-radius: 7px;
  font-size: 9px; line-height: 14px; top: -3px; right: -5px; }
.project-team-menu { width: 264px; padding: .6rem .65rem; gap: .5rem; }
.project-team-row { font-size: .77rem; }
.project-team-row .settings-note { font-size: .77rem; }
.project-invite-form input { padding: .42rem .55rem; font-size: .77rem; }
.project-team-menu #project-team-note { font-size: .77rem; }
.calcs-hit { padding: .55rem .7rem; }
.calcs-hit-title { font-size: .8rem; }
.calcs-hit-sub { font-size: .77rem; }
.calcs-badge { font-size: .77rem; padding: 1px 6px; }
.calcs-panel { padding: .9rem 1rem; }
.calcs-panel h3 { margin: 0; }
.calcs-card { font-size: .77rem; }
.calcs-input span, .calcs-claimed span { font-size: .77rem; }
.rail-chat-head strong { font-size: .78rem; }
.rail-msg { font-size: .77rem; }
.calcs-cat { display: flex; flex-direction: column; gap: .4rem;
  margin-bottom: .55rem; }
.calcs-cat-head { display: flex; justify-content: space-between;
  align-items: baseline; border-bottom: 1px solid var(--border);
  padding-bottom: .2rem; }
.calcs-cat-head h4 { margin: 0; font-size: .77rem; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.calcs-cat-hits { display: flex; flex-direction: column; gap: .4rem; }

/* Blocked drafts read as what they are, not as more duplicates. */
.project-folder-file.is-blocked { border-left: 3px solid var(--danger); }
.project-folder-file.is-blocked small { color: var(--danger); }
.project-folder-file span strong { overflow-wrap: anywhere; }
.guidance-divider { border-top: 1px solid var(--border); margin: .35rem .1rem; }
.sidebar .guidance-divider { border-top-color: var(--sidebar-line); }
.lightbox-nav { position: fixed; bottom: 18px; left: 50%;
  transform: translateX(-50%); display: flex; gap: .4rem;
  align-items: center; background: var(--surface); border: 1px solid var(--border);
  border-radius: 999px; padding: .3rem .6rem; box-shadow: var(--shadow-pop); }
.lightbox-count { font-size: .77rem; color: var(--muted);
  font-variant-numeric: tabular-nums; padding: 0 .2rem; }

/* The rail is a COMPACT view of the same answer (owner, 2 Sep: "the
   letters should be smaller... you got all the font sizes wrong"). The
   saved HTML carries the big surface's own sizes; inside the rail every
   descendant inherits the rail's scale instead — headings and hierarchy
   still differ, but at rail proportions. */
.rail-chat-thread .rail-msg-a { font-size: .77rem; line-height: 1.5; }
.rail-chat-thread .rail-msg-a :is(p, li, td, th, span, summary, small, b,
  strong, em, div, .settings-note, .trust-fold, .trust-fold-hint, .runlog,
  .answer-body, .answer-fallback-note, .research-pending, button) {
  font-size: inherit !important;
}
/* Bulk, not just letters (owner, 2 Sep: "the stages and show the run in
   the researcher and the guidance document are massive!!"): the run card
   and the Answered-from chips keep big-surface padding unless told
   otherwise, and padding is what reads as size in a 250px rail. */
.rail-chat-thread .rail-msg-a .runlog { padding: .3rem .45rem .25rem; border-radius: 7px; }
.rail-chat-thread .rail-msg-a .runlog-fold { font-size: .77rem; margin: 0 0 .3rem; }
.rail-chat-thread .rail-msg-a .runlog-fold > summary { padding: .16rem .4rem; gap: .3rem; }
.rail-chat-thread .rail-msg-a .runlog-steps { margin-top: .25rem; }
.rail-chat-thread .rail-msg-a .runlog-step { padding: .12rem 0 .12rem .9rem; }
.rail-chat-thread .rail-msg-a .guidance-used { padding: .25rem 0; gap: .25rem; margin: 0 0 .3rem; border: 0; background: none; }
.rail-chat-thread .rail-msg-a .guidance-used-doc { padding: .08rem .4rem; font-size: .77rem !important; }
.rail-chat-thread .rail-msg-a :is(h1, h2, h3, h4) {
  font-size: .78rem !important; margin: .35rem 0 .15rem;
}
.rail-chat-thread .rail-msg-a .eyebrow,
.rail-chat-thread .rail-msg-a .trust-count-ask,
.rail-chat-thread .rail-msg-a .trust-count-warn {
  font-size: .77rem !important;
}
.rail-chat-thread .rail-msg-a .button,
.rail-chat-thread .rail-msg-a .guidance-viewer-bar .button {
  min-height: 22px; padding: .15rem .4rem;
}
.rail-chat-form .button { min-height: 30px; padding: .35rem .62rem;
  font-size: .77rem; }
.download-menu { position: relative; }
.download-menu > summary { list-style: none; cursor: pointer; }
.download-menu > summary::-webkit-details-marker { display: none; }
.download-menu-list { position: absolute; right: 0; top: calc(100% + 6px);
  z-index: 50; min-width: 240px; background: var(--surface);
  border: 1px solid var(--border); border-radius: 10px;
  box-shadow: var(--shadow-pop); padding: .35rem; display: flex;
  flex-direction: column; gap: 2px; }
.download-menu-list .drawing-download { display: flex; flex-direction: column;
  gap: 1px; text-align: left; background: none; border: none;
  border-radius: 7px; padding: .45rem .6rem; cursor: pointer; }
.download-menu-list .drawing-download:hover { background: var(--soft); }
.download-menu-list .drawing-download strong { font-size: .77rem; }
.download-menu-list .drawing-download small { font-size: .77rem;
  color: var(--muted); }
.sheet-nav { position: sticky; top: 0; z-index: 30; display: flex;
  flex-wrap: wrap; gap: .3rem; align-items: center;
  background: var(--main-bg, var(--surface)); padding: .45rem 0;
  border-bottom: 1px solid var(--border); margin-bottom: .6rem; }
.sheet-nav-tab { background: none; border: 1px solid var(--border);
  border-radius: 999px; padding: .22rem .65rem; font-size: .77rem;
  cursor: pointer; color: var(--ink); }
/* The calculator's result card: value first, working underneath, copy in
   the corner (owner, 2 Sep 2026). */
.calc-result-head { display: flex; align-items: baseline; gap: .6rem;
  flex-wrap: wrap; padding: .55rem .7rem; border-radius: 10px 10px 0 0;
  border: 1px solid var(--border); border-bottom: none;
  background: var(--soft); }
.calc-result-value { font-size: 1.05rem;
  font-variant-numeric: tabular-nums; }
.calc-result-note { font-size: .77rem; color: var(--muted);
  flex: 1 1 auto; min-width: 0; }
.calc-result-head .calc-copy { margin-left: auto; flex: 0 0 auto; }
.calc-copy.is-copied { color: var(--success); border-color: var(--success); }
.calc-tone-ok .calc-result-value { color: var(--success); }
.calc-tone-warn .calc-result-value { color: var(--warning); }
.calc-tone-err .calc-result-value { color: var(--danger); }
.calc-working { margin: 0; padding: .7rem .75rem; border-radius: 0 0 10px 10px;
  border: 1px solid var(--border); background: var(--surface);
  font-size: .77rem; line-height: 1.5; white-space: pre-wrap;
  overflow-x: auto; }
/* The filed report row under a finished write (owner, 2 Sep 2026). */
.filed-report-row { display: flex; align-items: center; gap: .55rem;
  flex-wrap: wrap; margin-top: .7rem; padding: .5rem .65rem;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--soft); }
.filed-report-row .filed-report-name { font-size: .77rem; font-weight: 600;
  flex: 1 1 200px; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.sheet-nav-tab.active { background: var(--ink); color: var(--surface);
  border-color: var(--ink); }
.sheet-nav-arrows { margin-left: auto; display: flex; gap: .25rem; }

/* Proposed calculations as readable cards (owner, 3 Sep 2026). */
.proposed-calcs > summary { font-weight: 700; color: var(--accent); cursor: pointer; }
.proposed-calc { margin-top: .6rem; padding: .55rem .65rem;
  border: 1px solid var(--border); border-radius: 9px;
  background: var(--background); }
.proposed-calc-head { display: flex; align-items: center; gap: .6rem;
  flex-wrap: wrap; cursor: pointer; list-style: none; }
.proposed-calc-head::-webkit-details-marker { display: none; }
.proposed-calc-head::before { content: "\25b8"; color: var(--muted);
  font-size: .78rem; transition: transform .12s ease; }
.proposed-calc[open] > .proposed-calc-head::before { transform: rotate(90deg); }
.proposed-calc-head strong { font-size: .78rem; flex: 1 1 12rem; }
/* THE SHUT CARD CARRIES ITS OWN VERDICT. Folded, the summary is the whole
   answer: the method, the pill and the number. */
.proposed-calc-head .calc-verdict-pill { margin: 0; }
.proposed-calc-head .calc-verdict-value { font-weight: 700;
  font-variant-numeric: tabular-nums; font-size: .78rem; }
.calc-head-note { font-size: .78rem; color: var(--muted); }
.proposed-calc-actions { display: flex; flex-wrap: wrap; gap: .4rem;
  margin-top: .5rem; }
.proposed-calc-body { padding-top: .1rem; }
.proposed-calc p { margin: .3rem 0 0; font-size: .77rem; color: var(--muted);
  line-height: 1.45; }
.proposed-calc-inputs { display: flex; flex-wrap: wrap; gap: .3rem;
  margin-top: .4rem; }
.proposed-calc-input { padding: .1rem .45rem; border: 1px solid var(--border);
  border-radius: 999px; font-size: .77rem;
  font-variant-numeric: tabular-nums; background: var(--soft); }

/* THE VERDICT, ON THE PAGE (6 Sep 2026). The maths was run on the server for
   £0 and its answer was drawn nowhere; a mismatch now reads as a mismatch at a
   glance. A FLAG, NEVER A BLOCK (RULING-009): colour and weight only - nothing
   here disables, hides or gates any control. */
.proposed-calc.calc-is-mismatch { border-color: var(--warning); }
.proposed-calc.calc-is-error { border-color: var(--border); }
.calc-verdict { display: flex; align-items: baseline; flex-wrap: wrap;
  gap: .4rem .55rem; margin-top: .45rem; }
.calc-verdict-pill { padding: .1rem .5rem; border-radius: 999px;
  font-size: .77rem; font-weight: 800; letter-spacing: .06em;
  border: 1px solid var(--border); background: var(--soft); color: var(--muted); }
.calc-is-consistent .calc-verdict-pill { color: var(--success);
  border-color: var(--success); }
.calc-is-mismatch .calc-verdict-pill { color: var(--warning);
  border-color: var(--warning); }
.calc-is-error .calc-verdict-pill { color: var(--danger);
  border-color: var(--danger); }
.calc-verdict-value { font-size: 1rem; font-weight: 700;
  font-variant-numeric: tabular-nums; }
.calc-verdict-meaning { font-size: .77rem; color: var(--muted);
  line-height: 1.45; }
.calc-verdict-note { margin: .3rem 0 0; font-size: .8rem; font-weight: 600;
  line-height: 1.45; font-variant-numeric: tabular-nums; }
.calc-is-mismatch .calc-verdict-note { color: var(--warning); }
.calc-is-error .calc-verdict-note { color: var(--danger); }
.calc-flag-note { margin: .5rem 0 0; font-size: .77rem; color: var(--muted);
  line-height: 1.45; }
/* 11.5px is the readable floor on a 15px root (test_web_client_audit). The
   working card is the evidence the engineer signs off — never set it smaller. */
.proposed-calc .calcs-card { margin-top: .5rem; font-size: .77rem; }

/* The one folder-notes block, shared by every drawer. */
.folder-notes-block { margin-top: .8rem; padding-top: .7rem;
  border-top: 1px solid var(--border); }
.folder-notes-block label { display: block; font-size: .77rem;
  font-weight: 650; }
.folder-notes-block textarea { display: block; width: 100%; margin-top: .35rem;
  padding: .5rem .6rem; border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface); color: var(--ink); font: inherit;
  font-size: .77rem; line-height: 1.5; resize: vertical; }
.folder-notes-block .inline-actions { margin-top: .4rem; }

/* ── CLASSES app.js EMITS THAT HAD NO RULE AT ALL ────────────────────────────
   Eleven class names were written into the page by JavaScript and never
   defined here, so each one rendered as unstyled default text: a failure
   panel that read like a stray paragraph, a "spinner" that was an empty span,
   status pills with no pill. Same tokens as their neighbours, so they inherit
   dark mode with everything else — never a literal colour. */

/* A question that was not answered. Amber, not red: the work is retryable. */
.research-failed { display: grid; gap: .35rem; margin: .55rem 0;
  padding: .65rem .75rem; border: 1px solid var(--border); border-left: 3px solid var(--warning);
  border-radius: 9px; background: var(--surface-subtle); }
.research-failed-head { margin: 0; font-size: .8rem; font-weight: 700; color: var(--warning); }
.research-failed p { margin: 0; font-size: .78rem; line-height: 1.5; color: var(--ink); }
.research-failed-detail { margin-top: .2rem; }
.research-failed-detail summary { font-size: .77rem; color: var(--muted); cursor: pointer; }
.research-failed-detail pre { margin: .35rem 0 0; padding: .5rem .6rem; border-radius: 8px;
  background: var(--soft); color: var(--muted); font-size: .77rem;
  white-space: pre-wrap; overflow-wrap: anywhere; }

/* The dictation is being transcribed. A spinner has to actually turn. */
.dictation-spinner { display: inline-block; width: .85rem; height: .85rem;
  border: 2px solid var(--border); border-top-color: var(--accent);
  border-radius: 50%; vertical-align: -.15rem;
  animation: dictation-spin .8s linear infinite; }
@keyframes dictation-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .dictation-spinner { animation-duration: 2.4s; }
}

/* A small standing label — what a job will use, what a file is. */
.pill { display: inline-flex; align-items: center; gap: .3rem;
  padding: .12rem .5rem; border: 1px solid var(--border); border-radius: 999px;
  background: var(--soft); color: var(--muted);
  font-size: .78rem; font-weight: 550; white-space: nowrap; }

/* The quietest button we draw: an "Add" beside a list. */
.button.subtle { border-color: transparent; background: var(--soft); color: var(--ink); font-weight: 550; }
.button.subtle:hover, .button.subtle:focus-visible { border-color: var(--border); background: var(--surface-subtle); }
.btn-quiet { border: 1px solid var(--border); border-radius: 8px;
  padding: .35rem .7rem; background: transparent; color: var(--muted);
  font-size: .78rem; font-weight: 550; }
.btn-quiet:hover, .btn-quiet:focus-visible { color: var(--ink); background: var(--soft); }

/* The product's half of a finding thread, set apart from the engineer's. */
.thread-ai { margin: .3rem 0; padding: .45rem .6rem; border-left: 2px solid var(--accent);
  border-radius: 0 8px 8px 0; background: var(--surface-subtle);
  color: var(--ink); font-size: .78rem; line-height: 1.5; }

/* "This did not load" — one line, where the missing thing should have been. */
.error-copy { display: block; margin: .35rem 0 0; color: var(--warning);
  font-size: .78rem; line-height: 1.45; }

/* A labelled input inside a panel built in JavaScript. */
.field { display: grid; gap: .3rem; margin: .5rem 0; font-size: .78rem; font-weight: 650; color: var(--ink); }
.field > span { font-weight: 650; }
.field textarea, .field input, .field select { font-weight: 400; }

/* Where an apply run writes its progress, beside the button that started it. */
.apply-progress { display: block; min-height: 1rem; margin-top: .25rem;
  color: var(--muted); font-size: .78rem; }

/* One thing the checks were not happy about, in the checks list. */
.check-concern { margin: .15rem 0; color: var(--warning); font-size: .78rem; line-height: 1.45; }

/* 4 Sep 2026, the owner's list: a narrow rail must not break a name mid-word,
   the project list must sit tighter, and a light button turns dark on hover
   (and a dark one light) so every button answers the pointer the same way. */
.project-item > span, .document-item > span { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.project-row + .project-row { margin-top: 1px; }
/* Light buttons (ghost, secondary - white with an ink border) go INK on hover;
   the dark primary goes light. A disabled button answers no pointer. The
   earlier form of this rule sent `.secondary` to paper-on-ink, which is
   the colour it already was, so the Download button "did not change"
   (owner, 4 Sep 2026). */
.button.ghost:not([disabled]):hover,
.button.secondary:not([disabled]):hover { background: var(--ink); color: var(--paper, #fff); border-color: var(--ink); }
/* The download menu's items keep a light hover: an ink hover hid their
   grey hint lines (owner, 4 Sep 2026: "become invisible when hovering"). */
.download-menu-list .drawing-download:hover { background: var(--soft); color: var(--ink); }
.download-menu-list .drawing-download:hover strong, .download-menu-list .drawing-download:hover small { color: inherit; }
.button.primary:not([disabled]):hover { filter: none; background: var(--paper, #fff); color: var(--ink); border-color: var(--ink); }

/* The engineering-judgement card in sections (owner, 4 Sep 2026). */
.trust-note p { margin: 0 0 .55rem; max-width: 78ch; line-height: 1.5; }
.trust-note p:last-child { margin-bottom: 0; }
.trust-note .notice-lead { margin: .35rem 0 .25rem; }
.trust-note .notice-list { margin: 0 0 .55rem; padding-left: 1.2rem; max-width: 78ch; }
.trust-note .notice-list li { margin: 0 0 .3rem; line-height: 1.45; }

/* Dictation on every box (owner, 4 Sep 2026): the recording state reads the
   same everywhere, and the microphone beside a finding's note sits on its
   own line under the box. */
.button.is-recording { color: var(--danger); border-color: var(--danger); }
.drawing-feedback-form .feedback-dictate { margin: .3rem .4rem 0 0; }

/* The closed checks strip names a pending decision (owner, 4 Sep 2026). */
.trust-fold-ask-title { color: var(--ink); font-weight: 500; }

/* The finding's longer read, folded under "More" (owner, 4 Sep 2026). */
.drawing-finding-more { margin: .2rem 0 .35rem; }
.drawing-finding-more > summary { cursor: pointer; font-size: .77rem; color: var(--detail-info); }
.drawing-finding-more > p { margin: .35rem 0 0; font-size: .82rem; line-height: 1.55; max-width: 78ch; }

/* The Command Centre before the run (owner, 4 Sep 2026): the ticked sheets,
   drawn on the same stage a filed review uses, pins and all. */
.drawing-prerun { margin-top: .6rem; display: grid; gap: .6rem; }
.drawing-prerun[hidden] { display: none; }
.cc-stage-prerun .cc-sheet-name { font-size: .77rem; color: var(--muted); margin-left: .5rem;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cc-stage-prerun .cc-viewport { min-height: 380px; }

/* Dictation everywhere, the same way (owner, 4 Sep 2026). The finding's
   comment box keeps its controls on their own row; the live pill spans it;
   Discard sits at the pill's right; the saved tick steps back after a
   moment; a framed area shows it can be moved. */
.drawing-feedback-form { flex-wrap: wrap; }
.drawing-feedback-form textarea { flex: 1 1 100%; }
.drawing-feedback-form .dictation-live { flex: 1 1 100%; margin-top: .3rem; }
.dictation-discard { margin-left: auto; font-size: .77rem; color: var(--muted); }
.dictation-discard:hover { color: var(--danger); }
.feedback-status, [data-folder-notes-status] { transition: opacity .5s ease; }
.feedback-status.is-faded, [data-folder-notes-status].is-faded { opacity: 0; }
.cc-pin-rect { cursor: move; }
.confirm-card h3 { margin: .2rem 0 .4rem; font-size: 1.05rem; }
.confirm-card-body { margin: 0 0 .9rem; color: var(--muted); font-size: .85rem; line-height: 1.5; }
.cc-note-form .danger-action { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, transparent); }

/* The engineering judgement ledger (operator only). */
.learning-entry .learning-context { font-size: .77rem; color: var(--muted); margin: .1rem 0 .4rem; }
.learning-entry del { color: var(--muted); }
.learning-entry ins { text-decoration: none; background: color-mix(in srgb, var(--ok, #2f7d4f) 12%, transparent); }

/* The microphone every box gets (owner, 4 Sep 2026): quiet, after the box. */
.dictate-any { margin: .3rem 0 0; font-size: .77rem; }
.rail-chat-options .dictate-any { margin: 0; }

/* The top of a draft (owner, 4 Sep 2026): Download, open to work on it, run
   the next revision, and the drop for a commented Word file. */
.writer-revision-bar { display: grid; gap: .5rem; margin: .4rem 0 .8rem; padding: .7rem .8rem;
  border: 1px solid var(--border); border-radius: 8px; background: var(--surface-raised); }
.writer-revision-actions { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; }
.writer-revision-actions .revision-cta { margin-left: auto; }
.writer-revision-actions .revision-cta:disabled { background: var(--surface); color: var(--muted); border-color: var(--border); }
.writer-revision-drop .universal-upload-zone--compact { margin: 0; }

/* The note card's grip, and its error line; the rail's fixed mode. */
.cc-note-grip { height: 8px; margin: -4px 0 6px; border-radius: 4px; cursor: move;
  background: repeating-linear-gradient(90deg, var(--border) 0 4px, transparent 4px 8px); }
.cc-note-error { color: var(--danger); margin: .3rem 0 0; }
.rail-chat-mode { font-size: .77rem; color: var(--muted); border: 1px solid var(--border); border-radius: 999px; padding: .2rem .5rem; }
.rail-chat-guidance.link-button { text-align: left; }
/* Chats get room of their own under the projects (owner, 4 Sep 2026). */
.section-label:has(#new-conversation) { margin-top: 1.1rem; padding-top: .9rem; border-top: 1px solid color-mix(in srgb, var(--sidebar-fg) 14%, transparent); }

.chain-source-ticks { display: grid; gap: .25rem; margin: .4rem 0 .6rem; }
.revision-armed { margin-bottom: .6rem; }

/* Recovered dictations: words that outlived their box. */
.recovered-dictations { display: grid; gap: .5rem; margin: .6rem 0; }
.recovered-dictation-text { white-space: pre-wrap; margin: .4rem 0; font-size: .85rem; }

/* THE QUESTIONS, COMPACT (owner, 4 Sep 2026). */
.chain-project-questions { display: grid; gap: .3rem; }
.chain-project-question { border: 1px solid var(--border); border-radius: 8px; padding: .35rem .6rem; background: var(--surface); }
.chain-project-question > summary { list-style: none; cursor: pointer; display: flex; gap: .6rem; align-items: baseline; font-size: .85rem; }
.chain-project-question > summary::-webkit-details-marker { display: none; }
.chain-project-question .chain-question-text { flex: 1 1 auto; }
.chain-project-question .chain-question-answer { flex: 0 1 45%; text-align: right; color: var(--ok, #2f7d4f); font-size: .8rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chain-project-question:not(.is-answered) .chain-question-answer { display: none; }
.chain-question-body { display: grid; gap: .35rem; padding: .35rem 0 .15rem; }
.chain-question-chips { display: flex; flex-wrap: wrap; gap: .3rem; align-items: center; }
.chain-chip.is-selected { background: var(--ink); color: var(--surface); border-color: var(--ink); }
.chain-chip-guidance { border-color: var(--ink); font-weight: 600; }
.chain-chip-guidance:not(.is-selected) { background: color-mix(in srgb, var(--ink) 6%, transparent); }
.chain-question-note-link { font-size: .77rem; margin-left: auto; }
.chain-question-body textarea { min-height: 2.2rem; font-size: .85rem; }

/* THE NOTES: small points, a thin frame, a crosshair while marking. */
.cc-pin { width: 8px; height: 8px; font-size: 5px; }
.cc-pin:hover { transform: translate(-50%, -50%) scale(1.35); }
/* HOVER = BLACK AND WHITE (owner, 5 Sep 2026: "when i hover over it make it
   black and white"): the pin inverts to solid black with white text, so the
   one under the pointer is unmistakable before a click edits or deletes it. */
.cc-pin:hover, .cc-pin:focus-visible { background: var(--ink) !important; color: var(--surface) !important; border-color: var(--ink) !important; box-shadow: 0 0 0 2px var(--surface); }
.cc-pin[data-rect="1"]:hover { background: color-mix(in srgb, var(--ink) 8%, transparent) !important; border-color: var(--ink) !important; }
.cc-pin-rect, .cc-band { border-width: 1.5px; border-radius: 2px; background: color-mix(in srgb, var(--accent) 7%, transparent); }
.cc-pin-rect:hover { background: color-mix(in srgb, var(--accent) 16%, transparent); }
.cc-band { border-style: solid; }
.cc-stage[data-cc-note-mode="1"] [data-cc-canvas] { cursor: crosshair; }

.operator-banner { display: flex; align-items: center; gap: .8rem; margin: .4rem 0 .8rem; padding: .55rem .8rem; border: 1px solid var(--ink); border-radius: 8px; background: color-mix(in srgb, var(--ink) 6%, transparent); font-size: .85rem; }
.operator-banner .button { margin-left: auto; }
.platform-table { width: 100%; border-collapse: collapse; font-size: .8rem; }
.platform-table th, .platform-table td { text-align: left; padding: .3rem .4rem; border-bottom: 1px solid var(--border); }


/* ── THE DISCLAIMER GATE (owner, 5 Sep 2026) ─────────────────────────────── */
.terms-gate { position: fixed; inset: 0; z-index: 400; display: grid; place-items: center; padding: 1.5rem;
  background: color-mix(in srgb, var(--ink) 55%, transparent); backdrop-filter: blur(3px); }
.terms-card { width: min(760px, 100%); max-height: 92vh; display: grid; grid-template-rows: auto 1fr auto;
  background: var(--surface); color: var(--ink); border: 1px solid var(--ink); border-radius: 10px; overflow: hidden;
  box-shadow: 0 30px 80px -30px color-mix(in srgb, var(--ink) 60%, transparent); }
.terms-card header { padding: 1.1rem 1.4rem .6rem; border-bottom: 1px solid var(--border); }
.terms-card header h2 { margin: .2rem 0 0; font-size: 1.15rem; line-height: 1.3; }
.terms-body { overflow-y: auto; padding: 1rem 1.4rem; font-size: .92rem; line-height: 1.55; }
.terms-body h3 { margin: 1rem 0 .3rem; font-size: .95rem; }
.terms-body h3:first-child { margin-top: 0; }
.terms-body p { margin: .35rem 0 .6rem; }
.terms-card footer { display: grid; gap: .6rem; padding: .9rem 1.4rem 1.1rem; border-top: 1px solid var(--border); background: var(--surface-subtle); }
.terms-progress { margin: 0; font-size: .8rem; color: var(--muted); }
.terms-progress.is-done { color: var(--ink); font-weight: 600; }
.terms-accept-line { display: flex; justify-content: flex-start; gap: .55rem; align-items: flex-start; font-size: .86rem; font-weight: 500; }
.terms-accept-line span { flex: 1 1 auto; }
/* THE TICK SITS BESIDE ITS WORDS. The page-wide input rule made this checkbox a
   330 px block, so the box floated a third of the dialog away from the sentence
   it confirms - on the first screen every new account sees (17 Sep 2026). */
.terms-accept-line input { margin-top: .2rem; flex: 0 0 auto; width: auto; }
#terms-accept[disabled] { opacity: .45; cursor: not-allowed; }

/* Calculations run from the question (research answers) */
.calc-results { margin-top: .9rem; display: grid; gap: .6rem; }
.calc-results h4 { margin: 0; font-size: .82rem; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.calc-result { border: 1px solid var(--border); border-radius: 7px; padding: .6rem .75rem; background: var(--surface); }
.calc-result header { display: flex; justify-content: space-between; gap: .8rem; align-items: baseline; font-weight: 600; font-size: .86rem; }
.calc-result-value { font-size: 1.05rem; }


/* ── THE REVIEW QUEUE beside the sheet (owner, 5 Sep 2026: the tour's layout) ── */
.drawing-workspace { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(320px, .9fr); gap: .8rem; align-items: start; margin-top: .5rem; }
@media (max-width: 1100px) { .drawing-workspace { grid-template-columns: 1fr; } }
.drawing-sheet-column { min-width: 0; }
.review-queue { min-width: 0; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); overflow: hidden; position: sticky; top: .5rem; }
.review-queue-head { padding: .7rem .8rem; border-bottom: 1px solid var(--border); }
.review-queue-head > div:first-child { display: flex; align-items: center; justify-content: space-between; }
.review-queue-head small { color: var(--muted); font-size: .77rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
.review-queue-head strong { font-size: .86rem; }
.review-queue-filters { display: flex; flex-wrap: wrap; gap: .35rem; margin-top: .5rem; }
.review-queue-filter { min-height: 26px; border: 1px solid var(--border); border-radius: 999px; padding: 0 .6rem; background: var(--surface); color: var(--muted); font-size: .77rem; font-weight: 650; cursor: pointer; }
.review-queue-filter b { font-weight: 700; margin-left: .15rem; }
.review-queue-filter.is-active { border-color: var(--ink); background: var(--ink); color: var(--surface); }
.review-queue-list { max-height: 300px; overflow-y: auto; border-bottom: 1px solid var(--border); }
.review-queue-item { display: grid; grid-template-columns: 30px minmax(0, 1fr) auto; gap: .5rem; width: 100%; align-items: start; border: 0; border-top: 1px solid var(--border); padding: .6rem .7rem; background: var(--surface); color: var(--ink); text-align: left; cursor: pointer; }
.review-queue-item:first-child { border-top: 0; }
.review-queue-item:hover, .review-queue-item.is-active { background: var(--surface-subtle); }
.review-queue-item.is-active { box-shadow: inset 3px 0 0 var(--ink); }
.review-queue-number { display: inline-grid; place-items: center; width: 22px; height: 22px; border: 1.5px solid var(--ink); border-radius: 50%; font-size: .77rem; font-weight: 700; }
.review-queue-item.is-active .review-queue-number { background: var(--ink); color: var(--surface); }
.review-queue-item span strong { display: block; font-size: .8rem; line-height: 1.3; }
.review-queue-item span small { display: block; margin-top: .15rem; color: var(--muted); font-size: .77rem; line-height: 1.3; }
.review-queue-pill { border-radius: 999px; padding: .15rem .45rem; font-size: .77rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; white-space: nowrap; font-style: normal; border: 1px solid var(--border); color: var(--ink); background: var(--surface); }
.review-queue-pill.is-reviewed { background: var(--ink); color: var(--surface); border-color: var(--ink); }
.review-queue-pill.is-noted { background: var(--surface-subtle); }
.review-queue-detail { padding: .7rem .8rem; }
.review-queue-detail .drawing-finding { border: 0; padding: 0; background: transparent; }


/* ── THE LIBRARY (owner, 5 Sep 2026): the website's guides inside the product ── */
.library-layout { display: grid; grid-template-columns: minmax(220px, 300px) minmax(0, 1fr); gap: 1rem; align-items: start; }
@media (max-width: 900px) { .library-layout { grid-template-columns: 1fr; } }
.library-nav { position: sticky; top: .5rem; display: grid; gap: .8rem; max-height: calc(100vh - 2rem); overflow-y: auto; }
.library-group h4 { margin: 0 0 .3rem; font-size: .77rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.library-link { display: block; width: 100%; border: 0; border-left: 2px solid transparent; padding: .35rem .6rem; background: transparent; color: var(--ink); text-align: left; font-size: .9rem; line-height: 1.35; cursor: pointer; text-decoration: none; }
.library-link:hover { background: var(--surface-subtle); }
.library-link.is-active { border-left-color: var(--ink); background: var(--surface-subtle); font-weight: 600; }
.library-article { max-width: 78ch; padding: 1.2rem 1.4rem 1.6rem; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); }
.library-head h2 { margin: .2rem 0 .5rem; font-size: 1.6rem; line-height: 1.2; letter-spacing: -.01em; }
.library-lede { margin: 0 0 .8rem; font-size: 1.02rem; line-height: 1.55; color: var(--ink); }
.library-block { padding-top: .9rem; margin-top: .9rem; border-top: 1px solid var(--border); }
.library-block h3 { margin: 0 0 .4rem; font-size: 1.08rem; }
.library-block p { margin: .35rem 0 .55rem; line-height: 1.6; }
.library-foot { margin-top: 1.2rem; padding-top: .8rem; border-top: 1px solid var(--border); font-size: .8rem; color: var(--muted); }


/* ── THE CALCULATIONS PAGE in the website tool's shape (owner, 5 Sep 2026) ── */
.calcs-panel { padding: 1.1rem 1.3rem 1.3rem; border-radius: 10px; }
.calcs-panel header h3 { font-size: 1.15rem; line-height: 1.3; }
.calcs-field { display: grid; gap: .3rem; margin: .8rem 0; }
.calcs-field label { font-weight: 600; font-size: .9rem; }
.calcs-input-unit { display: flex; align-items: center; gap: .5rem; }
.calcs-input-unit input[type="number"], .calcs-input-unit input[type="text"], .calcs-input-unit select { flex: 1 1 auto; min-width: 0; max-width: 420px; font-size: 1rem; padding: .5rem .6rem; border: 1px solid var(--border); border-radius: 6px; background: var(--control-bg); color: var(--ink); }
.calcs-input-unit input[type="number"] { max-width: 260px; }
.calcs-input-unit input[type="checkbox"] { width: 18px; height: 18px; margin: .2rem 0; accent-color: var(--ink); }
.calcs-unit { color: var(--muted); font-size: .86rem; white-space: nowrap; }
.calcs-field-help { margin: 0; color: var(--muted); font-size: .8rem; }
.calcs-result { margin-top: 1rem; padding: 1rem 1.1rem; border: 1px solid var(--border); border-left: 4px solid var(--ink); border-radius: 8px; background: var(--surface-subtle); }
.calcs-result.is-warn { border-left-color: var(--warning); }
.calcs-result.is-err { border-left-color: var(--danger); }
.calcs-result-top { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: .6rem; }
.calcs-result-label { font-size: .8rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
.calcs-result-figure { font-family: var(--font-serif); font-size: 2rem; line-height: 1; font-weight: 500; }
.calcs-result-figure small { font-family: var(--font-sans); font-size: .95rem; font-weight: 600; color: var(--muted); }
.calcs-result-note { margin: .6rem 0 0; font-size: .9rem; }
.calcs-result-inputs { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .7rem; }
.calcs-result-basis { margin: .6rem 0 0; font-size: .8rem; color: var(--muted); }
.calcs-working { margin-top: .8rem; }
.calcs-working summary { cursor: pointer; font-size: .86rem; color: var(--muted); }

/* The mark a re-targeted note points at, and THINNER frames (owner, 5 Sep 2026) */
.cc-note-target { position: absolute; z-index: 5; width: 10px; height: 10px; transform: translate(-50%, -50%); border: 1.5px solid #000; border-radius: 50%; background: #fff; pointer-events: none; }
.cc-pin.cc-pin-rect, .cc-pin[data-rect="1"] { border-width: 1px !important; border-style: solid; box-shadow: none; }

/* Editing history rows are buttons: open the document; restore an older save */
.project-version-list > div, .project-version-list > li { display: flex; align-items: center; gap: .5rem; }
.project-version-open { flex: 1 1 auto; display: grid; grid-template-columns: auto 1fr auto; gap: .6rem; align-items: center; width: 100%; border: 1px solid rgba(14,14,14,.16); border-radius: 7px; padding: .5rem .7rem; background: #fff; color: #0e0e0e; text-align: left; cursor: pointer; }
.project-version-open:hover { background: #f2f2ef; border-color: #0e0e0e; }
.project-version-open time { color: #6f706b; font-size: .8rem; }

/* The engineer's own scale (two clicks and a distance) */
.cc-scale-toggle.is-armed { border-color: var(--accent); color: var(--accent); }
.cc-scale-note { font-size: .78rem; opacity: .8; margin-left: .4rem; }
.cc-scale-note .link-button { background: none; border: 0; padding: 0; text-decoration: underline; cursor: pointer; font: inherit; color: inherit; }
.cc-scale-dot { position: absolute; width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: 50%; background: var(--ink); border: 2px solid var(--surface); box-shadow: 0 0 0 1px var(--ink); pointer-events: none; z-index: 6; }
.cc-scale-form { position: absolute; z-index: 7; background: var(--surface); border: 1px solid var(--ink); padding: .5rem .6rem; font-size: .8rem; display: grid; gap: .4rem; min-width: 14rem; }
.cc-scale-form input { width: 100%; margin-top: .2rem; }
.cc-scale-form .row { display: flex; gap: .4rem; }

/* THE AREAS, AS THE OWNER DREW THEM (5 Sep 2026): one thin black line, a
   faint grey fill, the same look while dragging and after. No growth on
   hover; corners you can find; a figure area hatched so it reads apart
   from a comment area. */
.cc-pin.cc-pin-rect, .cc-pin[data-rect="1"], .cc-band {
  border: 1px solid var(--ink) !important; border-radius: 0 !important;
  background: rgba(0, 0, 0, 0.045) !important; box-shadow: none !important;
  transform: none !important; transition: background-color .12s ease;
}
.cc-band { border-style: solid !important; }
.cc-pin[data-rect="1"]:hover, .cc-pin[data-rect="1"]:focus-visible {
  background: rgba(0, 0, 0, 0.09) !important; border-color: var(--ink) !important;
  transform: none !important; outline: none;
}
.cc-pin[data-rect="1"]:hover::after { display: none; }
/* Corner handles: four 6px squares that appear on hover, so the corner is
   where the eye says it is and the cursor says what a drag will do. */
.cc-pin[data-rect="1"]::before, .cc-pin[data-rect="1"]::after {
  content: none;
}
.cc-pin[data-rect="1"]:hover {
  background-image:
    linear-gradient(var(--ink), var(--ink)), linear-gradient(var(--ink), var(--ink)),
    linear-gradient(var(--ink), var(--ink)), linear-gradient(var(--ink), var(--ink)) !important;
  background-size: 6px 6px, 6px 6px, 6px 6px, 6px 6px !important;
  background-position: left top, right top, left bottom, right bottom !important;
  background-repeat: no-repeat !important;
}
/* A figure area: hatched, so it reads as "this goes into the report". */
.cc-pin.cc-pin-figure[data-rect="1"], .cc-pin-figure.cc-pin-rect {
  background: repeating-linear-gradient(45deg, rgba(0, 0, 0, 0.10) 0 1.5px, transparent 1.5px 7px) !important;
}
.cc-pin.cc-pin-figure[data-rect="1"]:hover {
  background: repeating-linear-gradient(45deg, rgba(0, 0, 0, 0.18) 0 1.5px, transparent 1.5px 7px),
    linear-gradient(var(--ink), var(--ink)), linear-gradient(var(--ink), var(--ink)), linear-gradient(var(--ink), var(--ink)), linear-gradient(var(--ink), var(--ink)) !important;
  background-size: auto, 6px 6px, 6px 6px, 6px 6px, 6px 6px !important;
  background-position: 0 0, left top, right top, left bottom, right bottom !important;
  background-repeat: repeat, no-repeat, no-repeat, no-repeat, no-repeat !important;
}
/* The point pin keeps its circle: white centre, black ring. */
.cc-pin:not([data-rect="1"]) { background: var(--surface) !important; border: 1.5px solid var(--ink) !important; color: transparent !important; box-shadow: none !important; }
.cc-pin:not([data-rect="1"]):hover { background: var(--ink) !important; transform: translate(-50%, -50%) !important; }
/* THE OPTIONS CARD SITS STILL: docked at the top-right of the stage, one
   place every time; the grip moves it and the place is remembered. */
.cc-note-form { border-radius: 8px; box-shadow: 0 6px 18px rgba(0, 0, 0, 0.14); }

/* The review steps docked above an open document: one row, scrolls sideways. */
.chain-rail.chain-strip { display: flex; flex-wrap: nowrap; gap: .5rem; overflow-x: auto; padding: .3rem 0 .6rem; margin: 0 0 .5rem; max-width: none; width: auto; }
.chain-rail.chain-strip > * { flex: 0 0 auto; }
.chain-rail.chain-strip [data-chain-step] { flex: 0 0 230px; min-width: 230px; }
.chain-rail.chain-strip .chain-rail-head, .chain-rail.chain-strip h3, .chain-rail.chain-strip .eyebrow { flex-basis: 100%; }

/* Your notes on this sheet: listed beside the findings, click to open the pin's card. */
.cc-notes { display: grid; gap: .3rem; margin: .5rem 0 .3rem; padding: .5rem .6rem; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); }
.cc-notes > small { font-size: .78rem; letter-spacing: .06em; text-transform: uppercase; opacity: .7; }
.cc-note-row { display: grid; grid-template-columns: auto 1fr; gap: .5rem; align-items: start; width: 100%; text-align: left; padding: .35rem .45rem; border: 1px solid var(--border); border-radius: 6px; background: var(--surface); font: inherit; font-size: .8rem; cursor: pointer; }
.cc-note-row:hover { border-color: var(--ink); }
.cc-note-row em { font-style: normal; font-size: .78rem; letter-spacing: .05em; text-transform: uppercase; padding: .1rem .35rem; border: 1px solid var(--ink); border-radius: 4px; }

/* The docked steps strip stays short: one scrolling row, no heading block.
   NOT WHEN IT IS ALSO THE SNAKE'S GRID (owner, 12 Sep 2026: *"on the document
   reviewer I only see just a few of the steps... the steps are cut"*). The
   strip was authored as one horizontal row, where a 170px cap is exactly
   right. On the document-review surface the rail carries `is-snake` as well,
   which lays the steps out as a three-column grid - so the cap cut the second
   and third rows off, and `overflow-y: hidden` meant there was no way to
   scroll to them. Content hidden with no way to reach it is the fault; the
   short strip is not. A grid keeps its height. */
.chain-rail.chain-strip:not(.is-snake) {
  max-height: 170px; overflow-y: hidden; align-items: flex-start;
}
.chain-rail.chain-strip.is-snake { max-height: none; overflow-y: visible; }
.chain-rail.chain-strip .chain-rail-head { display: none; }

/* A comment that has just been added: seen, then settles. */
.comment-card.is-new, .writer-comment-item.is-new { outline: 2px solid var(--ink); outline-offset: 2px; transition: outline-color 1.2s ease; }


/* THE COMMENT MARGIN (owner, 5 Sep 2026: "the comments need to happen where
   this is"). A column beside every selectable page; each comment is a
   bubble level with the words it is on, stacked when they would overlap;
   the composer is a bubble in the same place. */
.pdf-page-shell { overflow: visible; }
.comment-gutter { position: absolute; top: 0; left: 100%; width: 232px; height: 100%; pointer-events: none; }
.comment-bubble { position: absolute; left: 14px; width: 206px; display: grid; gap: .3rem; padding: .45rem .55rem; border: 1px solid var(--border); border-left: 3px solid var(--navy-2); border-radius: 6px; background: var(--surface); box-shadow: 0 2px 8px rgba(14, 17, 22, .08); font-size: .78rem; line-height: 1.4; pointer-events: auto; }
.comment-bubble.is-active { border-left-color: var(--accent); box-shadow: 0 0 0 2px rgba(0, 104, 248, .18); }
.comment-bubble.is-composer { border-left-color: var(--accent); }
.comment-bubble.is-saving { opacity: .6; }
.comment-bubble-head { display: flex; justify-content: space-between; gap: .4rem; padding: 0; border: 0; background: none; font: inherit; font-weight: 600; color: var(--ink); cursor: pointer; text-align: left; }
.comment-bubble-author { font-weight: 600; color: var(--ink); }
.comment-bubble-where { color: var(--muted); font-weight: 500; }
.comment-bubble-text { margin: 0; white-space: pre-wrap; max-height: 9rem; overflow: auto; color: var(--ink); }
.comment-bubble textarea { width: 100%; min-height: 64px; padding: .45rem; font-size: .78rem; resize: vertical; }
.comment-bubble .inline-actions { display: flex; gap: .3rem; justify-content: flex-end; flex-wrap: wrap; }
.comment-bubble .comment-inline-editor { display: grid; gap: .35rem; }


/* THE PIN IS ONE THIN RING (owner, 6 Sep 2026, the "O" he drew): no fill,
   no glyph, no shadow; a figure pin is the same ring squared. Areas sit
   beneath every point so a point can be dragged over a framed area. */
.cc-pin { background: rgba(255, 255, 255, .55) !important; border: 1.5px solid var(--ink) !important;
  color: transparent !important; box-shadow: none !important; width: 12px; height: 12px; z-index: 4; }
.cc-pin.cc-pin-figure { border-radius: 3px; border-color: var(--accent) !important; }
.cc-pin:hover, .cc-pin:focus-visible { background: rgba(255, 255, 255, .85) !important; color: transparent !important; }
.cc-pin.cc-pin-rect, .cc-pin[data-rect="1"] { z-index: 3; background: rgba(0, 0, 0, 0.03) !important; }
.cc-pin.is-new { outline: 1.5px solid var(--accent); outline-offset: 2px; }


/* One toast, bottom centre, with the one action that matters. */
.undo-toast { position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%); z-index: 60; display: flex; align-items: center; gap: .7rem; padding: .55rem .8rem; border: 1px solid var(--ink); border-radius: 6px; background: var(--ink); color: var(--surface); font-size: .82rem; box-shadow: 0 4px 16px rgba(14, 17, 22, .18); }
.undo-toast .button { background: var(--surface); color: var(--ink); border-color: var(--surface); }
/* A structured comment: labelled lines, gaps kept. */
.comment-bubble-text .comment-line { display: block; }
.comment-bubble-text .comment-gap { display: block; height: .35rem; }
.comment-bubble.is-saving::after { content: "saving…"; display: block; margin-top: .25rem; color: var(--muted); font-size: .77rem; }

/* ── CALCULATIONS AND LIBRARY IN THE WEBSITE'S OWN LANGUAGE (owner, 6 Sep 2026:
   "I told you I want those looking like in our website"). Two inks and three
   greys, square corners, hairline rules, serif titles at weight 400, small
   uppercase labels, an inverted block as the only emphasis. ── */
#calcs-surface, #library-surface { --grey-1: var(--muted); --grey-2: color-mix(in srgb, var(--muted) 72%, transparent); --rule: var(--border); }
#calcs-surface .calcs-layout { gap: 2.4rem; }
#calcs-surface .calcs-finder input[type="search"] { border: 0; border-bottom: 1px solid var(--ink); border-radius: 0;
  background: transparent; padding: .7rem 0; font-size: 1.02rem; box-shadow: none; }
#calcs-surface .calcs-finder input[type="search"]:focus { outline: 0; border-bottom-width: 2px; }
#calcs-surface .calcs-results { gap: 0; margin-top: 1.2rem; }
#calcs-surface .calcs-results > .settings-note { color: var(--grey-1); font-size: .9rem; max-width: 34ch; }
#calcs-surface .calcs-cat { gap: 0; margin-bottom: 1.4rem; }
#calcs-surface .calcs-cat-head { border-bottom: 1px solid var(--ink); padding-bottom: .45rem; margin-bottom: .1rem; }
#calcs-surface .calcs-cat-head h4 { font-size: .77rem; font-weight: 600; letter-spacing: .16em; color: var(--grey-2); }
#calcs-surface .calcs-cat-hits { gap: 0; }
#calcs-surface .calcs-hit { border: 0; border-bottom: 1px solid var(--rule); border-radius: 0; background: transparent;
  padding: .7rem .1rem; gap: .2rem; transition: padding-left .15s ease; }
#calcs-surface .calcs-hit:hover { border-color: var(--ink); padding-left: .4rem; }
#calcs-surface .calcs-hit.is-active { border-bottom-color: var(--ink); }
#calcs-surface .calcs-hit-title { font-size: .92rem; font-weight: 500; letter-spacing: -.005em; }
#calcs-surface .calcs-hit-sub { font-size: .78rem; color: var(--grey-1); }
#calcs-surface .calcs-hit-summary { font-size: .8rem; color: var(--grey-1); }
#calcs-surface .calcs-hit .calcs-badge { margin-top: .15rem; }
#calcs-surface .calcs-badge { border-radius: 0; font-size: .77rem; font-weight: 600; letter-spacing: .14em;
  padding: .28rem .5rem; line-height: 1; background: transparent; color: var(--grey-2); border: 1px solid var(--border); }
#calcs-surface .calcs-badge.is-verified { background: var(--ink); color: var(--surface); border-color: var(--ink); }
#calcs-surface .calcs-panel { border-radius: 0; border: 1px solid var(--rule); padding: 1.9rem 2.1rem 2.1rem; gap: .9rem; box-shadow: none; }
#calcs-surface .calcs-panel header { border-bottom: 1px solid var(--rule); padding-bottom: 1rem; margin-bottom: .3rem; }
#calcs-surface .calcs-panel header h3 { font-family: var(--font-serif); font-weight: 400; font-size: 1.9rem; line-height: 1.12;
  letter-spacing: -.02em; text-wrap: balance; max-width: 26ch; }
#calcs-surface #calcs-summary { font-size: 1rem; line-height: 1.55; color: var(--grey-1); max-width: 60ch; }
#calcs-surface #calcs-basis { font-size: .8rem; color: var(--grey-2); letter-spacing: .02em; }
#calcs-surface #calcs-applies { border-top: 1px solid var(--rule); padding-top: .8rem; }
#calcs-surface #calcs-applies summary { font-size: .77rem; font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: var(--grey-2); cursor: pointer; }
#calcs-surface #calcs-applies p { color: var(--grey-1); font-size: .92rem; line-height: 1.55; max-width: 60ch; }
#calcs-surface .calcs-field label, #calcs-surface .calcs-claimed > span { font-size: .77rem; font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: var(--grey-2); }
#calcs-surface .calcs-input-unit input[type="number"], #calcs-surface .calcs-input-unit input[type="text"], #calcs-surface .calcs-input-unit select, #calcs-surface #calcs-claimed { border: 0; border-bottom: 1px solid var(--ink); border-radius: 0;
  background: transparent; padding: .5rem 0; font-size: 1.1rem; font-family: var(--font-serif); box-shadow: none; color: var(--ink); }
#calcs-surface .calcs-input-unit select { padding-right: 1.6rem; cursor: pointer; }
#calcs-surface .calcs-input-unit input:focus, #calcs-surface .calcs-input-unit select:focus, #calcs-surface #calcs-claimed:focus { outline: 0; border-bottom-width: 2px; }
#calcs-surface .calcs-field-help { max-width: 60ch; line-height: 1.5; }
#calcs-surface .calcs-unit { font-size: .8rem; color: var(--grey-2); letter-spacing: .04em; }
#calcs-surface .calcs-field-help { font-size: .82rem; color: var(--grey-1); }
#calcs-surface #calcs-run { border-radius: 0; border: 1px solid var(--ink); background: var(--ink); color: var(--surface);
  padding: .8rem 1.1rem; font-size: .84rem; font-weight: 500; letter-spacing: .01em; align-self: flex-start; transition: .15s ease; box-shadow: none; }
#calcs-surface #calcs-run:hover { background: var(--surface); color: var(--ink); }
#calcs-surface .calcs-result { border-radius: 0; border: 0; background: var(--ink); color: var(--surface); padding: 1.6rem 1.7rem; margin-top: .4rem; }
#calcs-surface .calcs-result-label { color: rgba(255, 255, 255, .62); font-size: .77rem; letter-spacing: .16em; }
#calcs-surface .calcs-result-figure { font-size: 2.6rem; font-weight: 400; color: var(--surface); letter-spacing: -.02em; }
#calcs-surface .calcs-result-figure small { color: rgba(255, 255, 255, .62); font-weight: 500; }
#calcs-surface .calcs-result-note { color: rgba(255, 255, 255, .8); font-size: .95rem; line-height: 1.5; max-width: 60ch; }
#calcs-surface .calcs-result-basis { color: rgba(255, 255, 255, .55); }
#calcs-surface .calcs-result-inputs span, #calcs-surface .calcs-result-inputs .chip { border: 1px solid rgba(255, 255, 255, .28); color: rgba(255, 255, 255, .85);
  background: transparent; border-radius: 0; font-size: .77rem; padding: .28rem .55rem; }
#calcs-surface .calcs-result.is-warn { background: var(--surface); color: var(--ink); border: 1px solid var(--ink); }
#calcs-surface .calcs-result.is-warn .calcs-result-label, #calcs-surface .calcs-result.is-warn .calcs-result-basis { color: var(--grey-2); }
#calcs-surface .calcs-result.is-warn .calcs-result-figure { color: var(--ink); }
#calcs-surface .calcs-result.is-warn .calcs-result-note { color: var(--grey-1); }
#calcs-surface .calcs-result.is-warn .calcs-result-inputs span { border-color: var(--rule); color: var(--grey-1); }
#calcs-surface .calcs-result.is-err { background: var(--surface); color: var(--danger); border: 1px solid var(--danger); }
#calcs-surface .calcs-result.is-err .calcs-result-figure, #calcs-surface .calcs-result.is-err .calcs-result-note { color: var(--danger); }
#calcs-surface .calcs-working summary { font-size: .77rem; font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: var(--grey-2); cursor: pointer; }
#calcs-surface .calcs-card { border-radius: 0; border: 1px solid var(--rule); background: transparent; font-size: .8rem; line-height: 1.5; margin-top: .6rem; }
#library-surface .library-layout { gap: 2.4rem; }
#library-surface .library-nav { gap: 1.3rem; top: 1rem; }
#library-surface .library-group h4 { font-size: .77rem; font-weight: 600; letter-spacing: .16em; color: var(--grey-2); border-bottom: 1px solid var(--ink); padding-bottom: .4rem; margin-bottom: .1rem; }
#library-surface .library-link { border: 0; border-bottom: 1px solid var(--rule); border-radius: 0; padding: .55rem .1rem; font-size: .88rem; color: var(--grey-1); transition: padding-left .15s ease, color .15s ease; }
#library-surface .library-link:hover { background: transparent; color: var(--ink); padding-left: .4rem; border-bottom-color: var(--ink); }
#library-surface .library-link.is-active { background: transparent; color: var(--ink); font-weight: 500; border-bottom-color: var(--ink); }
#library-surface .library-article { border-radius: 0; border: 1px solid var(--rule); padding: 2.2rem 2.4rem 2.4rem; max-width: 84ch; }
#library-surface .library-head .label, #library-surface .library-kicker { font-size: .77rem; font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: var(--grey-2); }
#library-surface .library-head h2 { font-family: var(--font-serif); font-weight: 400; font-size: 2.3rem; line-height: 1.1; letter-spacing: -.02em; text-wrap: balance; }
#library-surface .library-lede { font-size: 1.12rem; line-height: 1.55; color: var(--grey-1); max-width: 60ch; margin-bottom: 1.4rem; }
#library-surface .library-block { border-top: 1px solid var(--rule); padding-top: 1.4rem; margin-top: 1.4rem; }
#library-surface .library-block h3 { font-family: var(--font-serif); font-weight: 400; font-size: 1.45rem; line-height: 1.16; letter-spacing: -.015em; margin-bottom: .6rem; }
#library-surface .library-block p { color: var(--grey-1); font-size: .95rem; line-height: 1.62; max-width: 64ch; }
#library-surface .library-block p strong { color: var(--ink); font-weight: 600; }
#library-surface .library-block ul, #library-surface .library-block ol { color: var(--grey-1); font-size: .93rem; line-height: 1.6; max-width: 64ch; }
#library-surface .library-block li::marker { color: var(--grey-2); }
#library-surface .library-foot { font-size: .78rem; color: var(--grey-2); letter-spacing: .02em; }
#library-surface .library-article > .settings-note { font-family: var(--font-serif); font-size: 1.4rem; color: var(--grey-2); }


/* A tracked change the moment it is asked for: the old words struck, the new words beside them. */
.persistent-selection-highlight.is-pending-delete { background: rgba(220, 38, 38, .12) !important; box-shadow: inset 0 -2px 0 rgba(220, 38, 38, .85); }
.persistent-selection-highlight.is-pending-delete::after { content: ""; position: absolute; left: 0; right: 0; top: 50%; border-top: 1.5px solid rgba(220, 38, 38, .9); }
.pending-insert { position: absolute; z-index: 5; padding: .15rem .4rem; background: rgba(22, 163, 74, .12); color: var(--success); border-left: 2px solid var(--success); font-size: .82rem; line-height: 1.35; white-space: normal; pointer-events: none; animation: pending-insert-in .18s ease-out; }
@keyframes pending-insert-in { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: none; } }
.is-redrawing { transition: opacity .18s ease; opacity: .72; }

/* THE PRESS ANSWERS ON THE WORDS (owner, 7 Sep 2026: "make it smoother, make
   it responsive"). The passage he chose breathes while the job runs, and a
   failure marks the same words and says why - never only a line in a panel
   somewhere else on the screen. */
.persistent-selection-highlight.is-working { background: rgba(6, 104, 252, .30); animation: selection-working 1.1s ease-in-out infinite; }
@keyframes selection-working { 0%, 100% { opacity: .5; } 50% { opacity: 1; } }
.persistent-selection-highlight.is-failed { background: rgba(220, 38, 38, .18); box-shadow: inset 0 -2px 0 rgba(220, 38, 38, .9); animation: none; }
.selection-failure { position: absolute; z-index: 6; padding: .18rem .45rem; background: rgba(220, 38, 38, .10); color: var(--danger); border-left: 2px solid var(--danger); font-size: .78rem; line-height: 1.35; white-space: normal; pointer-events: none; }
@media (prefers-reduced-motion: reduce) {
  .persistent-selection-highlight.is-working { animation: none; opacity: 1; }
}


/* The browser's own selection over the text layer is faint; ours, cut from the glyph boxes, is the highlight. */
.textLayer ::selection { background: rgba(6, 104, 252, .10); color: transparent; }
.persistent-selection-highlight.is-live { background: rgba(6, 104, 252, .26); mix-blend-mode: multiply; pointer-events: none; transition: none; }


/* The tools stand apart from the flow, at the far right of the surface nav. */
.surface-nav { display: flex; align-items: center; flex-wrap: wrap; }
/* THE TOOLS ARE TABS LIKE THE OTHERS (owner, 11 Sep 2026: "I told you you
   need to fix the design of the tools... it looks horrible"). The group was
   packed at a .15rem gap against the main tabs' 1.3rem, so "Calculations",
   "Smoke view", the pill and "Library" ran together into one line of text
   beside a shouting uppercase label. Same rhythm as the tabs to its left, a
   quiet label, and a small tag in place of the pill. */
.surface-nav-tools { margin-left: auto; display: inline-flex; align-items: stretch; gap: 1.3rem; padding-left: 1.3rem; border-left: 1px solid var(--border); }
/* NO NEGATIVE MARGIN: it pulled the first tool under the label, so the active
   tab's black pill butted against "TOOLS" (owner's screenshot, 17 Sep 2026). */
.surface-nav-tools-label { align-self: center; font-size: .77rem; font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: var(--muted); opacity: .7; margin-right: 0; }
.surface-nav-tools .surface-tab { display: inline-flex; align-items: center; gap: .4rem; }
.surface-nav-tools .beta-badge { margin-left: 0; padding: .1em .4em; border: 0; border-radius: 3px; background: color-mix(in srgb, var(--muted) 14%, transparent); color: var(--muted); font-size: .77rem; letter-spacing: .08em; vertical-align: 0; line-height: 1.4; }
.surface-nav-tools .surface-tab.active .beta-badge { background: var(--ink); color: var(--paper, #fff); }
@media (max-width: 760px) { .surface-nav-tools { margin-left: 0; border-left: 0; padding-left: 0; } }

.writer-editor-door { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; margin: 0 0 .9rem; }

/* ── THE FRAME IS THE HANDLE, THE INSIDE IS THE SHEET (owner, 7 Sep 2026:
   "image rectangles must not block comments - comments are the top layer,
   everything clickable / draggable"; "image boxes: 1 line instead of 2").
   A rectangle pin lets the pointer through its middle: only its edge band
   (the frame child, clipped to an 8px ring) answers, so a comment can be
   left inside a framed figure area and the frame still moves, resizes and
   opens from its edge. The ONE line is the frame's; the pin draws none. */
.cc-pin.cc-pin-rect, .cc-pin[data-rect="1"] {
  pointer-events: none !important;
  border: 0 !important;
  box-shadow: none !important;
  z-index: 2 !important;
}
.cc-pin[data-rect="1"] > .cc-pin-frame {
  position: absolute; inset: 0; display: block; box-sizing: border-box;
  border: 1px solid var(--ink); border-radius: 0;
  pointer-events: auto;
  clip-path: polygon(evenodd, 0 0, 100% 0, 100% 100%, 0 100%, 0 0,
    8px 8px, 8px calc(100% - 8px), calc(100% - 8px) calc(100% - 8px),
    calc(100% - 8px) 8px, 8px 8px);
}
.cc-pin.is-new[data-rect="1"] > .cc-pin-frame { border-width: 2px; border-color: var(--accent); }
/* WITH THE PENCIL DOWN THE FRAME STANDS ASIDE TOO (11 Sep 2026, seen in the
   offline harness on his sheet 4). The rule above gives the frame's edge band
   the pointer, and it outranks the draw-mode list by coming later at the same
   weight - so the first corner of an area drawn beside a framed figure grabbed
   the frame, re-filed it where it already was, and the area never started. */
.cc-stage[data-cc-draw-mode] .cc-pin[data-rect="1"] > .cc-pin-frame { pointer-events: none; }
/* Point pins, question pins and the note card sit above every frame. */
.cc-pin:not([data-rect="1"]) { z-index: 6 !important; }
.cc-pin.cc-pin-ask { border-radius: 50%; color: var(--surface) !important;
  background: var(--ink) !important; font-weight: 700; font-size: 7px; }
.cc-pin.cc-pin-ask:hover { background: var(--accent) !important; }
/* A pin drawn before the server has answered: there at once, a shade
   lighter, and it takes its id when the answer comes. */
.cc-pin.is-pending { opacity: .55; }

/* THE NOTES LIST NEVER BURIES THE SHEET (owner, 7 Sep 2026: "many comments
   come down and start hiding the drawing"). Inside a stage the list is a
   short scrolling strip; the sheet keeps its height. */
.cc-stage .cc-notes { max-height: 8.5rem; overflow: auto; margin: .35rem 0 .25rem; }
.cc-stage .cc-notes .cc-note-row { padding: .15rem .3rem; }
.geom-legend { display: block; width: 100%; margin-top: .25rem; opacity: .8; }
.geom-legend i { display: inline-block; width: 1.1rem; height: .25rem; vertical-align: middle; margin: 0 .25rem 0 .5rem; border-radius: 2px; }

/* ==========================================================================
   THE LAYER LIST, TIGHTENED (owner, 12 Sep 2026: *"can you just beautify this
   drawing review section list? It looks so messy... there's a lot of gaps.
   Maybe be more compact, maybe more of a black and white design"*).

   It was a wall of twelve checkboxes at 13px on 14px gaps, each with its own
   coloured square, then two legends of coloured bars. Nothing is removed -
   every layer he could switch he can still switch - but it reads as one
   compact block: a dense two-line wrap, the room kinds as quiet chips whose
   colour is a thin edge rather than a filled dot, and the legends set as one
   small line each. The colours on the DRAWING are untouched; this is the
   list's dress, and on the drawing the colour is the information.
   ========================================================================== */
.geom-controls {
  gap: .25rem .55rem; margin: .5rem 0 .35rem; padding: .45rem .55rem;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface-subtle);
}
.geom-controls > .eyebrow {
  flex-basis: 100%; margin: 0 0 .15rem; font-size: .78rem; letter-spacing: .08em;
}
.geom-kind {
  gap: .3rem; padding: .1rem .38rem .1rem .3rem; border-radius: 999px;
  border: 1px solid transparent; font-size: .78rem; line-height: 1.5;
}
.geom-kind:hover { border-color: var(--border); background: var(--main-bg); }
.geom-kind input { margin: 0; width: .82rem; height: .82rem; accent-color: var(--ink); }
/* The kind's colour, smaller and round: twelve filled SQUARES in a row is
   what made the list read as noise. The colour itself is the key to the
   drawing and stays - it arrives as an inline background, so nothing here
   may override it. */
.geom-dot { width: .58rem; height: .58rem; border-radius: 999px; }
.geom-controls .button.geom-toggle {
  padding: .1rem .45rem; font-size: .78rem; border-radius: 999px;
}
.geom-legend { margin-top: .2rem; font-size: .78rem; line-height: 1.7; opacity: .75; }
.geom-legend i { width: .85rem; height: .2rem; margin: 0 .2rem 0 .4rem; }

/* THE LIVE SELECTION IS THE BROWSER'S OWN, ON THE GLYPHS (owner, 7 Sep
   2026: highlighting must feel native). pdf.js text spans are transparent;
   the selection paint is what the eye follows while dragging. */
#pdf-preview .textLayer ::selection, #writer-pdf-preview .textLayer ::selection, #docx-preview ::selection {
  background: color-mix(in srgb, var(--accent) 38%, transparent);
  color: transparent;
}
#docx-preview ::selection { color: inherit; }
/* A fresh framed area shows its frame thicker, never a second ring. */
.cc-pin.is-new[data-rect="1"] { outline: none !important; }
.comment-bubble .composer-attach { position: relative; cursor: pointer; }
.comment-bubble .composer-attachments { display: block; margin-top: .25rem; opacity: .8; }

/* A CHECK WAITING ON A NUMBER (8 Sep 2026). The product knows a calculation
   applies and knows exactly which figures it lacks. That is a question the
   engineer can answer in seconds, so it is printed plainly and the card is
   marked as ASKING rather than as failed - a question and a failure are not
   the same answer, and colouring them alike teaches the engineer to ignore
   both. A FLAG, NEVER A BLOCK: nothing here gates a control. */
.proposed-calc.calc-asking { border-color: var(--accent, var(--border)); }
.calc-needs-input { margin-top: .45rem; padding: .45rem .55rem;
  border-radius: 7px; background: var(--soft); }
.calc-needs-input p { margin: 0 0 .25rem; font-size: .77rem;
  color: var(--text); }
.calc-needs-input ul { margin: 0; padding-left: 1.05rem; }
.calc-needs-input li { font-size: .77rem; color: var(--muted);
  line-height: 1.5; }
.calc-needs-input .calc-unit { font-variant-numeric: tabular-nums;
  opacity: .8; }

/* THE WALL CARD (8 Sep 2026): what a wall is, what it must resist, the page. */
.geom-wall { cursor: pointer; }
.geom-wall-card { position: absolute; z-index: 40; width: 320px; max-width: calc(100% - 16px); background: var(--surface); color: var(--ink); border: 1px solid var(--border); border-radius: 10px; box-shadow: 0 8px 28px rgba(0, 0, 0, .2); padding: .6rem .8rem .5rem; font-size: .86rem; line-height: 1.35; }
.geom-wall-card strong { display: block; padding-right: 1.6rem; }
.geom-wall-card .geom-wall-class { opacity: .75; font-size: .8rem; margin: .1rem 0 .3rem; }
.geom-wall-card .geom-wall-verdict { font-weight: 600; margin-bottom: .3rem; }
.geom-wall-card .geom-wall-period { display: inline-block; padding: 0 .4rem; border-radius: 4px; background: #dc2626; color: #fff; font-weight: 700; }
.geom-wall-card p { margin: .25rem 0; }
.geom-wall-card .geom-wall-cite { opacity: .75; font-size: .8rem; }
.geom-wall-card .geom-wall-close { position: absolute; top: .3rem; right: .35rem; font-size: 1.1rem; line-height: 1; }

/* ── The passage tools, one component on both surfaces (8 Sep 2026) ──────── */
/* The selected passage is a box he edits; his words go in as a tracked change. */
textarea.selected-passage-preview { min-height: 66px; max-height: 160px; resize: vertical; color: var(--ink); background: var(--surface-raised); font-size: .77rem; line-height: 1.45; }
textarea.selected-passage-preview:disabled { color: var(--muted); background: var(--soft); }
.selection-typed-row { display: flex; align-items: center; justify-content: space-between; gap: .5rem; margin-top: -.2rem; }
.selection-typed-row .settings-note { flex: 1 1 auto; min-width: 0; }
.selection-typed-row .button { flex: 0 0 auto; }
/* A refusal is printed in red beside the button, never in a status line elsewhere. */
.selection-actions { align-items: center; gap: .5rem; }
.passage-refusal { flex: 1 1 auto; min-width: 0; color: var(--danger); font-size: .77rem; line-height: 1.35; text-align: right; overflow-wrap: anywhere; }
.passage-refusal[hidden] { display: none; }
/* Every press is a card that stays until he clears it. */
.passage-jobs { display: grid; gap: .5rem; }
.passage-jobs:empty { display: none; }
.passage-job { position: relative; display: grid; gap: .35rem; padding: .6rem .65rem; border: 1px solid var(--border); border-left: 3px solid var(--accent); border-radius: 8px; background: var(--surface-raised); font-size: .77rem; line-height: 1.45; }
.passage-job.is-running { border-left-color: var(--accent); }
.passage-job.is-done { border-left-color: var(--success); }
.passage-job.is-failed { border-left-color: var(--danger); }
.passage-job.is-stopped { border-left-color: var(--muted); }
.passage-job-head { display: flex; align-items: center; justify-content: space-between; gap: .4rem; }
.passage-job-verb { color: var(--navy); font-weight: 600; font-size: .77rem; letter-spacing: .01em; }
.passage-job.is-running .passage-job-verb::after { content: "…"; }
.passage-job-clear { width: 22px; height: 22px; }
.passage-job-words { margin: 0; color: var(--muted); font-style: italic; overflow-wrap: anywhere; }
.passage-job-words:empty, .passage-job-instruction:empty { display: none; }
.passage-job-instruction { margin: 0; color: var(--ink); overflow-wrap: anywhere; }
.passage-job-body { min-width: 0; overflow-wrap: anywhere; }
.passage-job-body .job-progress { margin-top: .2rem; }
.passage-job-error { color: var(--danger); margin: 0; }
.passage-job-proposal { padding: .5rem .6rem; border: 1px solid var(--border); border-radius: 6px; background: var(--soft); white-space: pre-wrap; }
/* The verdict card of "Check against the guidance": one line, tinted by the
   verdict, then what the page says, the correction and the cited pages. */
.guidance-check { display: grid; gap: .4rem; }
.guidance-check-headline { margin: 0; padding-left: .5rem; border-left: 3px solid var(--muted); }
.guidance-check-ok .guidance-check-headline { border-left-color: var(--success); }
.guidance-check-warn .guidance-check-headline { border-left-color: var(--warning); }
.guidance-check-says { margin: 0; }
.guidance-check-withheld, .guidance-check-unopened { margin: 0; color: var(--warning); }
.guidance-check-correction { display: grid; gap: .3rem; padding: .5rem .6rem; border: 1px solid var(--border); border-radius: 6px; background: var(--soft); }
.guidance-check-correction .settings-note { margin: 0; }
.guidance-check-correction-text { margin: 0; white-space: pre-wrap; }
.guidance-check-correction .inline-actions { justify-content: flex-end; }
.guidance-check-study { margin-top: .2rem; }
.guidance-check-study > summary { cursor: pointer; color: var(--muted); }
.selection-workbench.is-busy .review-quick-actions { opacity: .92; }
/* A follow-up under every answer, carrying the turn it follows. */
.follow-up { display: grid; gap: .35rem; margin-top: .6rem; padding-top: .5rem; border-top: 1px dashed var(--border); }
.follow-up textarea { min-height: 44px; font-size: .77rem; }
.follow-up .inline-actions { justify-content: flex-end; }
.research-thread-foot .research-follow-up { margin-right: .8rem; }
/* The rail on the writer: the same node, docked in the writer's third column. */
.writer-rail-mount { min-width: 0; }
.writer-rail-mount[hidden] { display: none; }
/* THE TOOLS ARE AS TALL AS THE PAGE THEY WORK ON. They were capped at 780 px
   beside a stage that takes the window, so the comment list ran out of room
   while the screen below it was empty. */
.writer-rail-mount .review-rail { height: calc(100dvh - 9.5rem); max-height: none; min-height: 480px; top: .75rem; }
.writer-rail-mount.review-rail-collapsed .review-rail { align-items: center; width: 40px; height: 40px; min-height: 40px; padding: 0; border: 0; background: transparent; }
.writer-rail-mount.review-rail-collapsed .review-rail-body, .writer-rail-mount.review-rail-collapsed .rail-title, .writer-rail-mount.review-rail-collapsed #rail-surface-note { display: none; }
.writer-rail-mount.review-rail-collapsed .rail-head, .writer-rail-mount.review-rail-collapsed .rail-head-actions { width: 100%; justify-content: center; }
#rail-surface-note { margin: .1rem 0 0; }
/* A comment is a marker in the margin; the thread lives in the rail. */
.comment-gutter .comment-marker { display: grid; grid-template-columns: 26px minmax(0, 1fr); align-items: center; gap: .4rem; width: 206px; max-width: calc(100% - 14px); padding: .3rem .4rem; border: 1px solid var(--border); border-radius: 8px; background: var(--surface-raised); color: var(--ink); text-align: left; font-size: .77rem; line-height: 1.3; cursor: pointer; box-shadow: var(--shadow); }
.comment-gutter .comment-marker:hover, .comment-gutter .comment-marker.is-active { border-color: var(--accent); box-shadow: 0 0 0 2px rgba(0,104,248,.18); }
.comment-marker-initials { display: grid; place-items: center; width: 26px; height: 26px; border-radius: 999px; background: var(--navy); color: var(--surface-raised); font-size: .77rem; font-weight: 700; letter-spacing: .02em; }
.comment-marker-line { display: grid; min-width: 0; }
.comment-marker-line b { font-size: .77rem; }
.comment-marker-line .comment-bubble-where { margin-left: .25rem; color: var(--muted); font-weight: 400; }
.comment-marker-text { display: block; overflow: hidden; color: var(--muted); white-space: nowrap; text-overflow: ellipsis; }
.comment-card.is-flash { animation: comment-card-flash 1.6s ease-out; }
@keyframes comment-card-flash { 0% { box-shadow: 0 0 0 3px rgba(0,104,248,.35); } 100% { box-shadow: none; } }
/* The comment composer's attach control is a paperclip, its words in the title. */
.comment-bubble.is-composer .composer-attach { display: inline-grid; place-items: center; width: 28px; height: 28px; padding: 0; border: 1px solid var(--border); border-radius: 6px; background: var(--surface-raised); cursor: pointer; }
.comment-bubble.is-composer .composer-attach:hover { border-color: var(--accent); }
.comment-bubble.is-composer .composer-attach .icon { width: 14px; height: 14px; }
/* The writer's six steps, numbered, each saying its state. */
.writer-stepper { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: .4rem; margin: 0 0 .8rem; }
.writer-stepper[hidden] { display: none; }
.writer-step { display: grid; grid-template-columns: 26px minmax(0, 1fr); grid-template-rows: auto auto; column-gap: .45rem; align-items: start; padding: .5rem .55rem; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-raised); color: var(--ink); text-align: left; cursor: pointer; }
.writer-step:hover { border-color: var(--accent); }
.writer-step-no { grid-row: 1 / span 2; display: grid; place-items: center; width: 26px; height: 26px; border-radius: 999px; border: 1px solid var(--border); font-size: .77rem; font-weight: 700; color: var(--muted); background: var(--soft); }
.writer-step-text { display: grid; min-width: 0; }
.writer-step-text strong { font-size: .78rem; line-height: 1.2; color: var(--navy); }
.writer-step-text small { color: var(--muted); font-size: .77rem; line-height: 1.25; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.writer-step-state { grid-column: 2; font-style: normal; font-size: .77rem; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); margin-top: .2rem; }
.writer-step.is-done .writer-step-no { background: var(--success); border-color: var(--success); color: var(--surface-raised); }
.writer-step.is-done .writer-step-state { color: var(--success); }
.writer-step.is-current { border-color: var(--accent); box-shadow: 0 0 0 2px rgba(0,104,248,.14); }
.writer-step.is-current .writer-step-no { background: var(--accent); border-color: var(--accent); color: var(--surface-raised); }
.writer-step.is-current .writer-step-state { color: var(--accent); }
.writer-step.is-todo { opacity: .78; }
@media (max-width: 900px) { .writer-stepper { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 560px) { .writer-stepper { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* A COMMENT THAT HAS NOT LANDED YET, AND ONE THAT WAS REFUSED (owner, 9 Sep
   2026: "I made a few comments and didn't see them appear close to
   instantly"). The card is drawn at the press; until the server answers it
   is dimmed a little and says "Saving…". If the server refuses, the card
   turns red, keeps his words and carries a Retry. Nothing he wrote is ever
   taken off the screen. */
.change-card.comment-pending { opacity: 0.72; }
.change-card.comment-failed { border-left-color: var(--danger) !important; }
.comment-state-note {
  margin: 6px 0 0;
  font-size: 12px;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 8px;
}
.comment-state-note.is-error { color: var(--danger); }

/* ===========================================================================
   THE SMOKE VIEW (preview surface, 10 Sep 2026)

   THE OWNER, 10 Sep 2026: "I want strong visuals, strong visual identity,
   native experience, and our black and white strong branding."

   Black and white, strong and quiet: every neutral is one of the app's own
   custom properties, so this surface is the same product in light and in
   dark and follows a theme change without a second palette. Colour appears
   in ONE place and carries ONE meaning - the temperature of the smoke -
   drawn from the same stop list src/core/cfast_visuals.py bakes into the
   frames. A red is a failing margin or a printed limit, never decoration.
   =========================================================================== */

/* .tool-surface is `place-items: start center`, which shrink-wraps its
   child, and .tool-card caps at 820px. The plan is 1400px wide, so the
   host states its own width rather than inheriting a card's. */
.smoke-view-host { width: 100%; max-width: 1400px; justify-self: center; }
.smoke-view { display: grid; gap: 1rem; color: var(--ink); }

.sv-head { display: grid; gap: .2rem; }
.sv-head-title { display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap; }
.sv-head h2 { margin: 0; font-family: var(--font-serif); font-weight: 400; font-size: 1.75rem; letter-spacing: -.01em; }
.sv-head-sub { margin: 0; color: var(--muted); font-size: .8rem; }
/* The preview mark is the house .beta-badge (styles.css line 1069), not a
   second badge of its own. */
.sv-head-title .beta-badge { margin-left: 0; vertical-align: .18em; }

/* THE SAMPLE IS NEVER IN DOUBT. A screen of realistic numbers that does not
   say whose they are is the one way this mock-up could mislead. */
.sv-sample-banner {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .5rem;
  padding: .55rem .7rem; border: 1px solid var(--ink); border-radius: var(--radius);
  background: var(--surface-subtle); font-size: .78rem; line-height: 1.45;
}
.sv-sample-banner strong {
  padding: .1rem .4rem; border-radius: 3px; background: var(--ink); color: var(--main-bg);
  font-size: .77rem; letter-spacing: .09em; text-transform: uppercase;
}
.sv-sample-built { color: var(--muted); }
.sv-sample-tag {
  display: inline-block; padding: 0 .28rem; border: 1px solid var(--border); border-radius: 3px;
  background: var(--surface-subtle); color: var(--muted);
  font-size: .77rem; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  vertical-align: .12em;
}

.sv-tabs { display: flex; gap: 0; border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.sv-tab {
  padding: .5rem .85rem; border: 0; border-bottom: 2px solid transparent; background: none;
  color: var(--muted); font: inherit; font-size: .82rem; font-weight: 600; cursor: pointer;
}
.sv-tab:hover { color: var(--ink); }
.sv-tab[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--ink); }
.sv-panel { display: block; }

/* ---- 1. the smoke view --------------------------------------------------- */

.sv-stage { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 1rem; align-items: start; }
@media (max-width: 1100px) { .sv-stage { grid-template-columns: minmax(0, 1fr); } }

.sv-plan-frame { border: 1px solid var(--ink); border-radius: var(--radius); background: #fff; overflow: hidden; }
/* The frames carry a caption strip baked under the plan. The product draws
   its own legend in words, so the strip is clipped rather than shown twice. */
.sv-plan-clip { position: relative; width: 100%; overflow: hidden; }
.sv-plan-img { position: absolute; inset: 0; width: 100%; object-fit: cover; object-position: top left; display: block; }
.sv-plan-img[hidden] { display: none; }
.sv-hit { position: absolute; inset: 0; width: 100%; height: 100%; }
.sv-room-hit { fill: transparent; stroke: transparent; stroke-width: 6; cursor: pointer; }
.sv-room-hit:hover { fill: color-mix(in srgb, var(--ink) 8%, transparent); stroke: var(--ink); }
.sv-room-hit:focus-visible { outline: none; fill: color-mix(in srgb, var(--ink) 8%, transparent); stroke: var(--ink); }
.sv-room-hit.is-on { stroke: var(--ink); stroke-width: 8; fill: color-mix(in srgb, var(--ink) 5%, transparent); }

.sv-transport {
  display: grid; grid-template-columns: auto auto minmax(0, 1fr); gap: .7rem; align-items: center;
  margin-top: .6rem; padding: .6rem .7rem; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-raised);
}
.sv-play {
  display: inline-flex; align-items: center; gap: .4rem; padding: .38rem .7rem;
  border: 1px solid var(--ink); border-radius: 4px; background: var(--ink); color: var(--main-bg);
  font: inherit; font-size: .78rem; font-weight: 600; cursor: pointer;
}
.sv-play:hover { background: var(--navy-2); border-color: var(--navy-2); }
.sv-play-icon {
  width: 0; height: 0; border-style: solid; border-width: 5px 0 5px 8px;
  border-color: transparent transparent transparent currentColor;
}
.sv-play.is-playing .sv-play-icon {
  width: 8px; height: 10px; border: 0; border-left: 3px solid currentColor; border-right: 3px solid currentColor;
  background: none;
}
.sv-clock { display: grid; gap: 0; line-height: 1.05; min-width: 5.5rem; }
.sv-clock-t { font-family: var(--font-serif); font-size: 1.5rem; }
.sv-clock-t b { font-weight: 400; font-variant-numeric: tabular-nums; }
.sv-clock-mm { color: var(--muted); font-size: .77rem; font-variant-numeric: tabular-nums; }
.sv-slider { grid-column: 3; width: 100%; accent-color: var(--ink); }
.sv-ticks { grid-column: 3; display: flex; gap: .25rem; flex-wrap: wrap; }
.sv-tick {
  padding: .1rem .38rem; border: 1px solid var(--border); border-radius: 3px; background: var(--control-bg);
  color: var(--muted); font: inherit; font-size: .77rem; font-variant-numeric: tabular-nums; cursor: pointer;
}
.sv-tick:hover { color: var(--ink); border-color: var(--ink); }
.sv-tick.is-on { background: var(--ink); border-color: var(--ink); color: var(--main-bg); }
.sv-frame-note { margin: .5rem 0 0; color: var(--muted); font-size: .78rem; }
.sv-frame-note b { color: var(--ink); }

.sv-side { display: grid; gap: .8rem; position: sticky; top: .5rem; }
@media (max-width: 1100px) { .sv-side { position: static; } }
.sv-legend { margin-top: .7rem; padding: .75rem .8rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-raised); }
.sv-legend h4 { margin: 0 0 .25rem; font-size: .78rem; }
.sv-legend-lead { margin: 0 0 .5rem; color: var(--muted); font-size: .78rem; line-height: 1.4; }
.sv-keys { list-style: none; margin: 0; padding: 0; display: grid; gap: .22rem 1.4rem;
  grid-template-columns: repeat(auto-fill, minmax(330px, 1fr)); align-items: start; }
.sv-keys-marks { margin-top: .5rem; padding-top: .5rem; border-top: 1px solid var(--border); gap: .35rem 1.4rem; }
.sv-key { display: grid; grid-template-columns: 14px auto minmax(0, 1fr); gap: .4rem; align-items: start; font-size: .77rem; line-height: 1.35; }
.sv-keys-marks .sv-key { grid-template-columns: 14px minmax(0, 1fr); }
.sv-swatch { width: 14px; height: 14px; border: 1px solid var(--border); border-radius: 2px; margin-top: .08rem; }
.sv-key-value { font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.sv-key-words { color: var(--muted); }
/* _ARROW, the closed-door fill and _FIRE in src/core/cfast_visuals.py. A
   key drawn in any other colour would not name the mark on the picture. */
.sv-swatch-hatch { background: repeating-linear-gradient(45deg, var(--ink) 0 1px, transparent 1px 4px); }
.sv-swatch-arrow { border: 0; background: none; position: relative; }
.sv-swatch-arrow::after {
  content: ''; position: absolute; left: 0; top: 6px; width: 12px; height: 0;
  border-top: 2px solid #6d28d9;
}
.sv-swatch-arrow::before {
  content: ''; position: absolute; left: 9px; top: 3px; width: 0; height: 0;
  border-style: solid; border-width: 4px 0 4px 5px; border-color: transparent transparent transparent #6d28d9;
}
.sv-swatch-closed { background: #6b7280; border-color: var(--ink); }
.sv-swatch-fire { background: none; border: 2px solid #dc2626; }

/* ---- 2. the room panel --------------------------------------------------- */

.sv-roomcard { padding: .75rem .8rem; border: 1px solid var(--ink); border-radius: var(--radius); background: var(--surface-raised); display: grid; gap: .6rem; }
.sv-roomcard header { display: grid; gap: .35rem; }
.sv-roomcard h4 { margin: 0; font-size: .88rem; display: flex; gap: .4rem; align-items: baseline; flex-wrap: wrap; }
.sv-firetag {
  padding: .05rem .35rem; border: 1px solid #dc2626; border-radius: 3px; color: #dc2626;
  font-size: .77rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
}
.sv-roompick { width: 100%; padding: .3rem .4rem; border: 1px solid var(--border); border-radius: 4px; background: var(--control-bg); color: inherit; font: inherit; font-size: .78rem; }
.sv-now-lead { margin: 0; color: var(--muted); font-size: .77rem; }
.sv-now { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .4rem; margin: 0; }
.sv-now div { display: grid; gap: .1rem; }
.sv-now dt { color: var(--muted); font-size: .77rem; line-height: 1.25; }
.sv-now dd { margin: 0; font-family: var(--font-serif); font-size: 1.1rem; font-variant-numeric: tabular-nums; }
.sv-aset { display: grid; gap: .18rem; padding: .55rem .6rem; border-left: 3px solid var(--ink); background: var(--surface-subtle); border-radius: 0 4px 4px 0; }
.sv-aset[data-has="false"] { border-left-color: var(--muted); }
.sv-aset-label { font-size: .77rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
.sv-aset-label em { font-weight: 400; letter-spacing: 0; text-transform: none; color: var(--muted); font-style: normal; }
.sv-aset-value { font-family: var(--font-serif); font-size: 1.5rem; font-variant-numeric: tabular-nums; }
.sv-aset-crit, .sv-cite { color: var(--muted); font-size: .77rem; line-height: 1.4; }
.sv-cite { font-weight: 700; color: var(--detail-info); }
.sv-curves { width: 100%; display: block; }
.sv-plainlist { list-style: none; margin: 0; padding: 0; display: grid; gap: .28rem; color: var(--muted); font-size: .77rem; line-height: 1.4; }
.sv-plainlist b { color: var(--ink); }

/* ---- 3. the ASET / RSET board ------------------------------------------- */

.sv-defs { padding: .7rem .8rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-subtle); }
.sv-defs p { margin: 0 0 .3rem; font-size: .78rem; line-height: 1.5; }
.sv-defs p:last-child { margin-bottom: 0; }
.sv-meta { color: var(--muted); font-size: .78rem; }
/* WHERE A NUMBER CAME FROM, when it did not come from us. The RSET side
   is worked from inputs an engineer states with a source; nothing here
   defaults it, and the screen must not let it read as a default. */
.sv-defs-flag { margin: .5rem 0 0; padding: .45rem .6rem; border-left: 3px solid var(--detail-info);
  background: var(--detail-info-soft); font-size: .78rem; line-height: 1.5; }
.sv-boardsum { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .6rem; margin: .8rem 0; }
@media (max-width: 1100px) { .sv-boardsum { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 720px) { .sv-boardsum { grid-template-columns: minmax(0, 1fr); } }
.sv-boardstat { display: grid; gap: .1rem; padding: .6rem .7rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-raised); }
.sv-boardstat b { font-family: var(--font-serif); font-size: 1.8rem; font-weight: 400; line-height: 1; }
.sv-boardstat span { color: var(--muted); font-size: .77rem; line-height: 1.35; }
.sv-boardstat.sv-tone-fail { border-color: var(--detail-risk); background: var(--detail-risk-soft); }
.sv-boardstat.sv-tone-fail b { color: var(--detail-risk); }
.sv-boardstat.sv-tone-pass b { color: var(--detail-pass); }

.sv-routes { display: grid; gap: .7rem; }
.sv-route { padding: .75rem .85rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-raised); }
/* A NEGATIVE MARGIN IS LOUD. People need longer than they have, and that is
   the one thing on this screen a reader must not scroll past. */
.sv-route.sv-tone-fail { border-color: var(--detail-risk); border-left-width: 4px; }
.sv-route.sv-tone-unknown { border-style: dashed; }
.sv-route-head { display: flex; gap: 1rem; justify-content: space-between; align-items: flex-start; flex-wrap: wrap; }
.sv-route-head h4 { margin: 0 0 .1rem; font-size: .92rem; }
.sv-route-sub { margin: 0; color: var(--muted); font-size: .78rem; }
.sv-measured { padding: 0 .25rem; border: 1px solid var(--border); border-radius: 3px; font-size: .77rem; letter-spacing: .06em; text-transform: uppercase; }
.sv-margin { display: grid; gap: .05rem; text-align: right; min-width: 9rem; }
.sv-margin-value { font-family: var(--font-serif); font-size: 2rem; line-height: 1; font-variant-numeric: tabular-nums; }
.sv-margin-word { color: var(--muted); font-size: .77rem; }
.sv-margin[data-tone="fail"] .sv-margin-value { color: var(--detail-risk); font-weight: 600; }
.sv-margin[data-tone="fail"] .sv-margin-word { color: var(--detail-risk); }
.sv-margin[data-tone="unknown"] .sv-margin-value,
.sv-margin[data-tone="window"] .sv-margin-value { color: var(--muted); font-size: 1.1rem; }
.sv-margin[data-tone="pass"] .sv-margin-value { color: var(--detail-pass); }
.sv-route.sv-tone-pass { border-left: 4px solid var(--detail-pass); }
.sv-route.sv-tone-window { border-style: solid; }

.sv-route-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)) minmax(0, 1.4fr); gap: .7rem; margin-top: .6rem; }
@media (max-width: 900px) { .sv-route-grid { grid-template-columns: minmax(0, 1fr); } }
.sv-figure { display: grid; gap: .1rem; align-content: start; }
.sv-figure-label { font-size: .77rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.sv-figure-value { font-family: var(--font-serif); font-size: 1.35rem; font-variant-numeric: tabular-nums; }
.sv-figure-note { color: var(--muted); font-size: .77rem; line-height: 1.35; }
.sv-stack { display: flex; height: 12px; border: 1px solid var(--ink); border-radius: 2px; overflow: hidden; }
.sv-stack-part { display: block; min-width: 1px; }
.sv-part-detection { background: var(--ink); }
.sv-part-alarm { background: repeating-linear-gradient(90deg, var(--ink) 0 1px, transparent 1px 3px); }
.sv-part-pre_movement { background: color-mix(in srgb, var(--ink) 45%, transparent); }
.sv-part-travel { background: color-mix(in srgb, var(--ink) 16%, transparent); }
.sv-stack-legend { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .3rem; color: var(--muted); font-size: .77rem; }
.sv-stack-legend span { display: inline-flex; align-items: center; gap: .25rem; }
.sv-stack-legend i { width: 9px; height: 9px; border: 1px solid var(--ink); border-radius: 2px; }
.sv-verdict { margin: .6rem 0 0; padding: .4rem .55rem; border-left: 3px solid var(--detail-risk); background: var(--detail-risk-soft); font-size: .8rem; line-height: 1.45; }
.sv-tone-pass .sv-verdict, .sv-tone-unknown .sv-verdict, .sv-tone-window .sv-verdict {
  border-left-color: var(--border); background: var(--surface-subtle);
}
.sv-tone-pass .sv-verdict { border-left-color: var(--detail-pass); }
.sv-none { margin: 0; color: var(--muted); font-size: .78rem; line-height: 1.4; }
/* THE SCREEN A MODEL THAT HAS NOT RUN SHOWS. Never an empty chart: a
   plan with no smoke and a curve with no line read as a model that ran
   and found nothing. */
.sv-notrun { padding: 1.6rem 1.4rem; border: 1px dashed var(--border); border-radius: var(--radius);
  background: var(--surface-subtle); text-align: center; }
.sv-notrun h3 { margin: 0 0 .4rem; font-family: var(--font-serif); font-weight: 400; font-size: 1.3rem; }
.sv-notrun p { margin: .3rem auto; max-width: 46rem; font-size: .8rem; line-height: 1.55; }
.sv-notrun ul { display: inline-block; margin: .3rem 0; text-align: left; font-size: .78rem; line-height: 1.5; }
.sv-working { margin-top: .55rem; }
.sv-working summary { cursor: pointer; font-size: .78rem; font-weight: 700; color: var(--muted); }
.sv-working summary:hover { color: var(--ink); }
.sv-working ol { margin: .5rem 0; padding-left: 1.1rem; font-size: .78rem; line-height: 1.6; font-variant-numeric: tabular-nums; }
.sv-inputs { width: 100%; border-collapse: collapse; margin-top: .5rem; font-size: .77rem; }
.sv-inputs th, .sv-inputs td { padding: .22rem .4rem; border-top: 1px solid var(--border); text-align: left; vertical-align: top; }
.sv-inputs th { width: 9rem; font-weight: 600; }
.sv-inputs .sv-src { color: var(--muted); }
.sv-assumed { padding: 0 .25rem; border: 1px solid var(--detail-warn); border-radius: 3px; background: var(--detail-warn-soft); color: var(--detail-warn); font-size: .77rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }

/* ---- 4. what decides the answer ------------------------------------------ */

.sv-sens { display: grid; gap: .7rem; margin: .8rem 0; }
.sv-sensrow { padding: .7rem .8rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-raised); }
.sv-sensrow.is-open { border-left: 4px solid var(--ink); }
.sv-sensrow.is-settled { opacity: .78; }
.sv-sensrow header { display: flex; gap: .8rem; justify-content: space-between; align-items: baseline; flex-wrap: wrap; }
.sv-sensrow h4 { margin: 0; font-size: .86rem; }
.sv-sens-sub { margin: .1rem 0 0; color: var(--muted); font-size: .77rem; }
.sv-sens-sub b { color: var(--ink); font-variant-numeric: tabular-nums; }
.sv-sens-flag { padding: .1rem .4rem; border: 1px solid var(--ink); border-radius: 3px; font-size: .77rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; white-space: nowrap; }
.sv-sensrow.is-settled .sv-sens-flag { border-color: var(--border); color: var(--muted); }
.sv-sensbar { position: relative; height: 38px; margin: .55rem 0 .45rem; border-bottom: 1px solid var(--border); overflow: hidden; }
.sv-sensbar-span { position: absolute; top: 5px; height: 6px; min-width: 2px; background: var(--ink); border-radius: 3px; }
.sv-sensbar-lo, .sv-sensbar-hi { position: absolute; top: 15px; color: var(--muted); font-size: .77rem; font-variant-numeric: tabular-nums; transform: translateX(-50%); white-space: nowrap; }
.sv-sensrows { list-style: none; margin: 0; padding: 0; display: grid; gap: .12rem; font-size: .78rem; }
.sv-sensrows li { display: grid; grid-template-columns: minmax(0, 1fr) 4.5rem minmax(0, 9rem); gap: .5rem; padding: .18rem 0; border-top: 1px solid var(--border); align-items: baseline; }
.sv-sensrows li.is-base { font-weight: 600; }
.sv-sensrow-label i { color: var(--muted); font-weight: 400; font-size: .77rem; }
.sv-sensrow-value { font-variant-numeric: tabular-nums; text-align: right; }
.sv-sensrow-room { color: var(--muted); font-size: .77rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- 5. state of the run, and the questions ------------------------------ */

.sv-statehead { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .6rem; margin-bottom: .9rem; }
@media (max-width: 980px) { .sv-statehead { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.sv-statecard { display: grid; gap: .15rem; align-content: start; padding: .65rem .7rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-raised); }
.sv-statecard b { font-size: .84rem; }
.sv-statecard span { color: var(--muted); font-size: .77rem; line-height: 1.35; }
.sv-statecard.sv-tone-fail { border-color: var(--detail-risk); }
.sv-statecard.sv-tone-fail b { color: var(--detail-risk); }
.sv-statecard.sv-tone-warn { border-color: var(--detail-warn); }
.sv-statecard.sv-tone-warn b { color: var(--detail-warn); }
.sv-statecols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.2rem; }
@media (max-width: 900px) { .sv-statecols { grid-template-columns: minmax(0, 1fr); } }
.sv-statecols h4 { margin: 1rem 0 .35rem; font-size: .78rem; }
.sv-statecols section > h4:first-child { margin-top: 0; }
.sv-table { width: 100%; border-collapse: collapse; font-size: .78rem; }
.sv-table th, .sv-table td { padding: .25rem .4rem; border-top: 1px solid var(--border); text-align: left; }
.sv-table th { width: 10rem; color: var(--muted); font-weight: 600; }
.sv-sourcelist { list-style: none; margin: 0; padding: 0; display: grid; gap: .4rem; }
.sv-sourcelist li { display: grid; gap: .1rem; padding-left: .6rem; border-left: 2px solid var(--border); font-size: .78rem; line-height: 1.45; }
.sv-sourcelist li b { font-size: .78rem; }
.sv-sourcelist li span { color: var(--muted); }
.sv-sourcelist.sv-tone-fail li { border-left-color: var(--detail-risk); }

.sv-questions { margin-top: 1.1rem; padding: .8rem .85rem; border: 1px solid var(--ink); border-radius: var(--radius); background: var(--surface-subtle); }
.sv-questions h4 { margin: 0 0 .2rem; font-size: .82rem; }
.sv-q { display: grid; gap: .25rem; margin-top: .7rem; }
.sv-q-text { font-size: .78rem; line-height: 1.45; }
.sv-q-row { display: flex; gap: .45rem; align-items: center; }
.sv-q-input { flex: 1 1 auto; min-width: 0; padding: .35rem .5rem; border: 1px solid var(--border); border-radius: 4px; background: var(--control-bg); color: inherit; font: inherit; font-size: .8rem; }
.sv-q-input:focus { outline: 2px solid var(--ink); outline-offset: -1px; border-color: var(--ink); }
.sv-q-tick { min-width: 3.4rem; color: var(--detail-pass); font-size: .77rem; font-weight: 700; }
.sv-q-tick.is-saved::before { content: '\2713 '; }

/* ---- the sheet picker, the run controls, and what a run came back with ----
   ADDED 10 Sep 2026, when this screen stopped being a preview over a sample
   and became the place the engineer RUNS the model. The controls are the
   house buttons in the house black; nothing here introduces a second colour
   language, and a failing row is the same red a failing margin already uses. */

.sv-sheetpick { display: inline-flex; align-items: center; gap: .4rem; color: var(--muted); font-size: .78rem; }
.sv-sheetpick-select {
  padding: .25rem .4rem; border: 1px solid var(--border); border-radius: 4px;
  background: var(--control-bg); color: var(--ink); font: inherit; font-size: .78rem; max-width: 26rem;
}

.sv-runbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem;
  padding: .5rem .6rem; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-subtle);
}
.sv-run {
  padding: .38rem .75rem; border: 1px solid var(--ink); border-radius: 4px;
  background: var(--ink); color: var(--main-bg); font: inherit; font-size: .8rem; font-weight: 700; cursor: pointer;
}
.sv-run-all, .sv-run-add { background: none; color: var(--ink); }
/* The chosen fire locations, on the screen until he takes one off. */
.sv-runset-chips { display: flex; flex-wrap: wrap; gap: .3rem; }
.sv-chip {
  padding: .2rem .5rem; border: 1px solid var(--ink); border-radius: 999px;
  background: var(--control-bg); color: var(--ink); font: inherit; font-size: .78rem; cursor: pointer;
}
.sv-chip:hover { background: var(--surface-subtle); }
.sv-chip.is-picked, .sv-plan-room.is-picked { outline: 2px solid var(--ink); }

/* THE FLOOR, BEFORE ANY SMOKE. The sheet's own picture with every modellable
   room drawn over it; a click puts the fire in one. */
.sv-plan { margin: .8rem 0 0; }
.sv-plan-stage { position: relative; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--main-bg); }
.sv-plan-img { display: block; width: 100%; height: auto; }
.sv-plan-boxes { position: absolute; inset: 0; }
.sv-plan-room {
  position: absolute; margin: 0; padding: 0; cursor: pointer; overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--ink) 55%, transparent);
  background: color-mix(in srgb, var(--ink) 6%, transparent);
  color: var(--ink); font: inherit; font-size: .78rem; line-height: 1.1;
  display: flex; align-items: center; justify-content: center; text-align: center;
}
.sv-plan-room span { padding: 0 .2rem; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sv-plan-room:hover { background: color-mix(in srgb, var(--ink) 16%, transparent); }
.sv-plan figcaption { margin-top: .35rem; color: var(--muted); font-size: .78rem; line-height: 1.45; }
.sv-plan-skipped { margin-top: .5rem; font-size: .78rem; color: var(--muted); }
.sv-plan-skipped ul { margin: .3rem 0 0; padding-left: 1.1rem; }
.sv-plan-skipped b { color: var(--ink); }
.sv-run:disabled { opacity: .45; cursor: default; }
.sv-run-note { flex: 1 1 14rem; min-width: 0; color: var(--muted); font-size: .78rem; line-height: 1.4; }
.sv-run-note[data-tone="error"] { color: var(--danger); font-weight: 600; }

.sv-runset { display: grid; gap: .5rem; padding: .6rem; border: 1px solid var(--ink); border-radius: var(--radius); }
.sv-runset h4 { margin: 0; font-size: .9rem; }
.sv-runset h4 small { color: var(--muted); font-weight: 400; }
.sv-runtable { width: 100%; border-collapse: collapse; font-size: .78rem; }
.sv-runtable th, .sv-runtable td { padding: .3rem .45rem; border-bottom: 1px solid var(--border); text-align: left; vertical-align: top; }
.sv-runtable th { color: var(--muted); font-weight: 600; text-transform: uppercase; letter-spacing: .06em; font-size: .78rem; }
.sv-runtable tr.is-fail td { background: color-mix(in srgb, var(--danger) 7%, transparent); }
.sv-runtable tr.is-notrun td { color: var(--muted); }
.sv-runtable i { color: var(--muted); font-size: .78rem; }
.sv-show {
  padding: .2rem .5rem; border: 1px solid var(--border); border-radius: 4px;
  background: var(--control-bg); color: var(--ink); font: inherit; font-size: .78rem; cursor: pointer;
}
.sv-show:hover { border-color: var(--ink); }

.sv-charts { display: grid; gap: .7rem; }
.sv-charts figure { margin: 0; }
.sv-charts img { width: 100%; height: auto; border: 1px solid var(--border); border-radius: var(--radius); }
.sv-charts figcaption { margin-top: .3rem; color: var(--muted); font-size: .77rem; line-height: 1.4; }

.sv-sens-ranges, .sv-sens-verdict { margin: .35rem 0 0; color: var(--muted); font-size: .77rem; line-height: 1.45; }
.sv-sens-verdict { color: var(--ink); }

.sv-tryblock { display: grid; gap: .4rem; margin-top: .9rem; }
.sv-tryblock h4 { margin: 0; font-size: .9rem; }
.sv-trylist { list-style: none; margin: 0; padding: 0; display: grid; gap: .3rem; }
.sv-trylist li { display: flex; align-items: center; gap: .5rem; padding: .3rem .45rem; border: 1px solid var(--border); border-radius: 4px; }
.sv-try-label { flex: 1 1 auto; min-width: 0; font-size: .8rem; }
.sv-try-label i { color: var(--muted); font-size: .78rem; }
.sv-try {
  padding: .22rem .6rem; border: 1px solid var(--ink); border-radius: 4px;
  background: none; color: var(--ink); font: inherit; font-size: .78rem; font-weight: 600; cursor: pointer;
}
.sv-try:disabled { opacity: .4; cursor: default; }

/* ---- your inputs --------------------------------------------------------- */

.sv-ingroup { margin-top: 1rem; }
.sv-ingroup h4 { margin: 0 0 .15rem; font-size: .95rem; }
.sv-ingrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: .55rem; margin-top: .55rem; }
.sv-in { display: grid; gap: .3rem; padding: .5rem .6rem; border: 1px solid var(--border); border-radius: var(--radius); }
.sv-in-head { display: grid; gap: .1rem; }
.sv-in-label { font-size: .82rem; font-weight: 700; }
.sv-in-label small { color: var(--muted); font-weight: 400; }
.sv-in-what { color: var(--muted); font-size: .78rem; line-height: 1.35; }
.sv-in-row { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; }
.sv-in-value { flex: 0 0 7rem; }
.sv-in-source { flex: 1 1 12rem; min-width: 0; }
.sv-in-value, .sv-in-source {
  padding: .3rem .45rem; border: 1px solid var(--border); border-radius: 4px;
  background: var(--control-bg); color: inherit; font: inherit; font-size: .8rem;
}
.sv-in-value:focus, .sv-in-source:focus { outline: 2px solid var(--ink); outline-offset: -1px; border-color: var(--ink); }
.sv-in-tick { min-width: 3.4rem; font-size: .78rem; font-weight: 700; }
.sv-in-printed { margin: 0; color: var(--muted); font-size: .78rem; line-height: 1.4; }
.sv-in-printed b { color: var(--ink); }
.sv-in-printed em { font-style: normal; color: var(--danger); font-weight: 600; }

/* ---- the 3D view (18 Sep 2026) -------------------------------------------- */
/* The building in metres, the layer inside every room, and the assumptions
   the run made beside it. The canvas keeps the app's neutrals; colour on it
   is the temperature scale and nothing else. */
.sv-scene-stage { display: grid; grid-template-columns: minmax(0, 1fr) 380px; gap: 1rem; align-items: start; }
@media (max-width: 1100px) { .sv-scene-stage { grid-template-columns: minmax(0, 1fr); } }
.sv-scene-col { display: grid; gap: .6rem; min-width: 0; }
.sv-scene-host { display: grid; gap: .5rem; }
.sv-scene-tools { display: flex; align-items: center; gap: .3rem; flex-wrap: wrap; }
.sv-scene-preset {
  padding: .3rem .7rem; border: 1px solid var(--border); border-radius: 4px; background: var(--control-bg);
  color: var(--muted); font: inherit; font-size: .78rem; font-weight: 600; cursor: pointer;
}
.sv-scene-preset:hover { color: var(--ink); border-color: var(--ink); }
.sv-scene-preset.is-on { background: var(--ink); border-color: var(--ink); color: var(--main-bg); }
.sv-scene-hint { margin-left: auto; color: var(--muted); font-size: .77rem; }
.sv-scene-canvas-wrap { border: 1px solid var(--ink); border-radius: var(--radius); background: #fff; overflow: hidden; }
.sv-scene-canvas { display: block; width: 100%; height: auto; aspect-ratio: 16 / 10; touch-action: none; cursor: grab; outline: none; }
.sv-scene-canvas:active { cursor: grabbing; }
.sv-scene-canvas:focus-visible { box-shadow: inset 0 0 0 2px var(--ink); }
.sv-scene-transport { margin-top: 0; }
.sv-scene-note { margin: 0; color: var(--muted); font-size: .77rem; }
.sv-scene-legend { margin-top: 0; }
.sv-scene-side { display: grid; gap: .8rem; min-width: 0; }
.sv-shafttag { background: var(--soft); color: var(--muted); border-color: var(--border); }
.sv-now-more { margin-top: .4rem; }
.sv-now-more dd small { display: block; color: var(--muted); font-weight: 400; font-size: .78rem; line-height: 1.3; }
.sv-roomdoors { margin: .4rem 0 0; font-size: .77rem; }
.sv-roomdoors summary { cursor: pointer; color: var(--muted); }
.sv-roomdoors ul { margin: .3rem 0 0; padding-left: 1rem; line-height: 1.4; }

/* The assumptions: one card per thing the model took as given. */
.sv-assume { display: grid; gap: .5rem; padding: .75rem .8rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-raised); }
.sv-as-head h4 { margin: 0 0 .2rem; font-size: .95rem; }
.sv-as-head .sv-meta { margin: 0; }
.sv-as-list { display: grid; gap: .45rem; }
.sv-as-row { display: grid; gap: .25rem; padding: .5rem .6rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--paper, #fff); }
.sv-as-row header { display: flex; align-items: baseline; justify-content: space-between; gap: .5rem; }
.sv-as-row h5 { margin: 0; font-size: .82rem; }
.sv-as-basis { flex: 0 0 auto; padding: 0 .3rem; border: 1px solid var(--border); border-radius: 3px; color: var(--muted); font-size: .78rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; white-space: nowrap; }
.sv-as-basis.is-assumed { border-color: var(--detail-warn); background: var(--detail-warn-soft); color: var(--detail-warn); }
.sv-as-basis.is-asked, .sv-as-basis.is-not-modelled { border-color: var(--danger); color: var(--danger); }
.sv-as-basis.is-printed, .sv-as-basis.is-measured { border-color: var(--ink); color: var(--ink); }
.sv-as-value { margin: 0; font-size: .82rem; font-weight: 600; line-height: 1.35; }
.sv-as-source, .sv-as-note { margin: 0; color: var(--muted); font-size: .78rem; line-height: 1.4; }
.sv-as-question { margin: 0; color: var(--danger); font-size: .78rem; line-height: 1.4; }
.sv-as-edit { display: grid; gap: .35rem; margin-top: .25rem; padding-top: .35rem; border-top: 1px dashed var(--border); }
.sv-as-field { display: grid; grid-template-columns: 7.5rem minmax(0, 1fr); gap: .4rem; align-items: center; font-size: .78rem; }
.sv-as-field > span { color: var(--muted); }
.sv-as-field small { color: var(--muted); }
.sv-as-field input, .sv-as-field select, .sv-as-cell input, .sv-as-mirror, .sv-win-source, .sv-door-at {
  padding: .28rem .45rem; border: 1px solid var(--border); border-radius: 4px; background: var(--control-bg);
  color: inherit; font: inherit; font-size: .78rem; min-width: 0;
}
.sv-as-field input:focus, .sv-as-field select:focus, .sv-as-mirror:focus, .sv-win-source:focus, .sv-door-at:focus, .sv-door-state:focus { outline: 2px solid var(--ink); outline-offset: -1px; border-color: var(--ink); }
.sv-as-cell { padding: 0; border: 0; gap: .3rem; }
.sv-as-cell .sv-in-source, .sv-as-mirrorcell .sv-as-mirror[data-mirror-field="source"] { width: 100%; }
.sv-as-mirrorcell { display: grid; gap: .3rem; }
.sv-as-window { display: grid; gap: .3rem; }
.sv-as-goto { justify-self: start; padding: .22rem .6rem; border: 1px solid var(--ink); border-radius: 4px; background: none; color: var(--ink); font: inherit; font-size: .77rem; font-weight: 600; cursor: pointer; }
.sv-doors { font-size: .78rem; }
.sv-doors summary { cursor: pointer; color: var(--ink); font-weight: 600; }
.sv-doorlist { list-style: none; margin: .4rem 0 0; padding: 0; display: grid; gap: .35rem; }
.sv-doorlist li { display: grid; gap: .15rem; padding: .35rem 0; border-top: 1px solid var(--border); line-height: 1.35; }
.sv-doorlist li > b { font-weight: 600; }
.sv-doorlist small { color: var(--muted); }
.sv-door-now b { font-weight: 600; }
.sv-door-why { display: block; }
.sv-door-edit { display: flex; gap: .3rem; align-items: center; flex-wrap: wrap; margin-top: .15rem; }
.sv-door-state { flex: 1 1 12rem; max-width: 100%; padding: .2rem .3rem; border: 1px solid var(--border); border-radius: 4px; background: var(--control-bg); color: inherit; font: inherit; font-size: .78rem; }
.sv-door-at { width: 4.6rem; }
.sv-door-at[hidden] { display: none; }
.sv-as-run { display: grid; gap: .3rem; margin-top: .3rem; }
.sv-run-again { justify-self: start; }
.sv-as-run-note { color: var(--muted); font-size: .77rem; }
.sv-in-hidden[hidden] { display: none; }

/* A tracked change on the rail is a place on the page: it says so. */
.change-card.is-navigable { cursor: pointer; }
.change-card.is-navigable:hover { border-left-color: var(--accent); }

/* THE SMOKE VIEW WITH NOTHING OF HIS TO SHOW, and what a run means (owner,
   11 Sep 2026). No sample building in either place. */
.sv-empty { max-width: 640px; margin: 2.5rem auto; padding: 1.5rem 1.6rem; border: 1px solid var(--border); border-radius: 8px; background: var(--paper, #fff); }
.sv-empty h3 { margin: 0 0 .4rem; font-family: var(--font-serif, Georgia, serif); }
.sv-empty p { margin: 0 0 1rem; color: var(--muted); font-size: .9rem; line-height: 1.5; }
.sv-meaning { margin: 0 0 1rem; padding: .9rem 1.1rem; border: 1px solid var(--border); border-left: 4px solid var(--ink); border-radius: 6px; background: var(--paper, #fff); }
.sv-meaning.is-pass { border-left-color: var(--ink); }
.sv-meaning.is-fail { border-left-color: var(--danger); }
.sv-meaning h4 { margin: 0 0 .35rem; font-size: .95rem; }
.sv-meaning > p { margin: .15rem 0 .35rem; font-size: .88rem; line-height: 1.5; }
.sv-meaning details { margin-top: .4rem; font-size: .83rem; }
.sv-meaning summary { cursor: pointer; font-weight: 600; }
.sv-meaning ul { margin: .35rem 0 .25rem 1.1rem; padding: 0; line-height: 1.5; }
.sv-meaning details p { margin: .35rem 0 0; color: var(--muted); }

/* The section list's fold sits at the right of its head. */
.paper-head { display: flex; align-items: baseline; gap: .75rem; flex-wrap: wrap; }
.paper-head .paper-fold { margin-left: auto; }

/* THE WRITER'S TWO DOORS, OUTSIDE THE CARD (11 Sep 2026). The header left the
   writer card so the steps cannot hide it; it now spans the surface like the
   steps below it instead of taking the card's centred width. */
#write-surface > .writer-header { width: auto; max-width: none; margin: 0 0 1rem; }

/* A REVIEW OF PART OF A SET SAYS SO. Two sheets on the screen with nothing
   about the other two reads as a review of the whole project (owner, 14 Sep
   2026: "why only 2 floors on this development, im sure there was like 4?"). */
.drawing-unreviewed { margin: .5rem 0 0; padding: .5rem .65rem;
  border-left: 3px solid var(--warning); border-radius: 4px;
  background: var(--soft); font-size: .8rem; line-height: 1.45; }

/* THE WORST CASE IS THE ANSWER, so it is drawn as the answer (owner, 14 Sep
   2026: "find the worst case, measure them, and then show them the worst
   case"). One card above the evidence, in the house black and white, with
   the time as the largest thing on it and what the number is NOT one click
   away - never hidden, never assumed read. */
.sv-worst { margin: 0 0 .9rem; padding: .85rem 1rem; border: 1px solid var(--ink);
  border-left-width: 5px; border-radius: 10px; background: var(--surface-raised, #fff); }
.sv-worst.is-none { border-color: var(--border); border-left-color: var(--muted); }
.sv-worst-eyebrow { display: block; margin-bottom: .2rem; color: var(--muted);
  font-size: .78rem; font-weight: 700; letter-spacing: .08em; }
.sv-worst h4 { margin: 0 0 .35rem; font-size: 1rem; }
.sv-worst p { margin: .25rem 0; font-size: .82rem; line-height: 1.5; }
.sv-worst-time b { font-size: 1.45rem; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.sv-worst-against { color: var(--muted); }
.sv-worst-limits { margin-top: .5rem; }
.sv-worst-limits > summary { color: var(--muted); font-size: .8rem; cursor: pointer; }
.sv-worst-limits ul { margin: .4rem 0 0 1rem; padding: 0; font-size: .8rem; line-height: 1.5; }
.sv-sens { margin: 0 0 .9rem; padding: .55rem .75rem; border: 1px solid var(--border);
  border-radius: 10px; background: var(--soft); }
.sv-sens > summary { font-weight: 700; font-size: .82rem; cursor: pointer; }
.sv-sens > summary small { margin-left: .4rem; color: var(--muted); font-weight: 400; }
.sv-sens ul { margin: .35rem 0 0 1rem; padding: 0; font-size: .8rem; line-height: 1.5; }
.sv-run-worst { font-weight: 700; }

/* CONNECTED AREAS ARE NUMBERED WHERE HE IS LOOKING (owner, 13 Sep 2026: "in
   the smoke view, I didn't see the connected areas idea, like, where you can
   connect different areas one, two, three"). The set existed as a row of name
   chips beside a button, which says nothing about which spaces on the drawing
   are in it. The number is on the plan and on the chip. */
.sv-plan-room.is-inset { outline: 2px solid var(--ink); outline-offset: -2px; }
.sv-plan-room[data-set-number]:not([data-set-number=""])::after {
  content: attr(data-set-number); position: absolute; top: 2px; left: 2px;
  display: grid; place-items: center; width: 1.15rem; height: 1.15rem;
  border-radius: 999px; background: var(--ink); color: var(--paper, #fff);
  font-size: .78rem; font-weight: 700; line-height: 1; }
.sv-chip-n { display: inline-grid; place-items: center; width: 1.05rem; height: 1.05rem;
  margin-right: .3rem; border-radius: 999px; background: var(--ink); color: var(--paper, #fff);
  font-size: .78rem; }


/* THE FIRM ADDS ITS OWN PEOPLE (17 Sep 2026). One row of fields that wraps on a
   narrow card; the button sits on the baseline of the inputs. */
/* The admin card is a two-column grid; the form is a full-width row of it. */
.admin-member-add { margin: 0 0 .9rem; grid-column: 1 / -1; }
.admin-member-add-row { display: flex; flex-wrap: wrap; gap: .6rem; align-items: flex-end; }
.admin-member-add-row label { display: grid; gap: .25rem; font-size: .78rem; min-width: 11rem; flex: 1 1 11rem; }
.admin-member-add-row input, .admin-member-add-row select { width: 100%; }
.admin-member-add-row .button { flex: 0 0 auto; }


/* THE ARCHIVE FOLD (17 Sep 2026): quiet, below the working list. */
.project-archive { margin-top: .6rem; }
.project-archive > summary { cursor: pointer; font-size: .78rem; color: var(--muted); padding: .2rem .1rem; }
.project-row.is-archived .project-item { opacity: .72; }

/* THE "?" THAT HOLDS THE PANEL'S INSTRUCTIONS (17 Sep 2026). A small round
   button in the rail head; its words open as a card under the head and close
   on the next press. */
.panel-help { position: relative; }
.panel-help > summary { list-style: none; display: grid; place-items: center; width: 28px; height: 28px;
  border-radius: 999px; font-weight: 600; font-size: .8rem; cursor: pointer; }
.panel-help > summary::-webkit-details-marker { display: none; }
.panel-help[open] > summary { border-color: var(--ink); }
.panel-help-body { position: absolute; z-index: 30; top: calc(100% + .4rem); right: 0; width: min(320px, 78vw);
  padding: .7rem .8rem; border: 1px solid var(--ink); border-radius: 10px; background: var(--surface-raised);
  box-shadow: 3px 3px 0 color-mix(in srgb, var(--ink) 18%, transparent); }
.panel-help-body p { margin: 0 0 .5rem; font-size: .78rem; line-height: 1.45; color: var(--ink); }
.panel-help-body p:last-child { margin-bottom: 0; }
.review-rail-collapsed .panel-help, .writer-rail-mount.review-rail-collapsed .panel-help { display: none; }

.track-changes-toggle.is-off { border-style: dashed; color: var(--muted); }
/* READABLE ON HOVER, BOTH THEMES (owner, 18 Sep 2026: "when I hover over
   track changes, sometimes the letters appear in gray"). The OFF state's
   muted grey and the generic ghost hover fought; this one rule decides. */
.button.track-changes-toggle:not([disabled]):hover,
.button.track-changes-toggle.is-off:not([disabled]):hover {
  color: #fff; background: var(--ink); border-color: var(--ink); border-style: solid; }
:root[data-theme="dark"] .button.track-changes-toggle:not([disabled]):hover,
:root[data-theme="dark"] .button.track-changes-toggle.is-off:not([disabled]):hover {
  color: var(--surface); background: var(--ink); border-color: var(--ink); }
/* THE SWITCH DECIDES WHAT THE PAGES SHOW. OFF (`.changes-final`): the final
   text - insertions read as plain words, deletions are not drawn. The
   server-rendered pages are fetched again with `changes=final`; this rule
   covers the browser-rendered fallback, which carries <ins>/<del>. */
.docx-preview.changes-final del { display: none; }
.docx-preview.changes-final ins { background: none; text-decoration: none; }

.writer-report-picker { display: block; margin-top: .3rem; max-width: 100%; padding: .3rem .5rem; border: 1px solid var(--border);
  border-radius: 8px; background: var(--surface); color: var(--ink); font: inherit; font-size: .78rem; }
.writer-report-picker[hidden] { display: none; }

/* No 62vh floor under an open document - see `switchSurface` (17 Sep 2026). */
#review-surface.has-document { min-height: 0; }

.account-names { display: grid; gap: .6rem; max-width: 420px; }
.account-names label { display: grid; gap: .25rem; font-size: .8rem; font-weight: 600; }
.account-names input { padding: .45rem .55rem; border: 1px solid var(--border); border-radius: 8px; font: inherit; background: var(--surface); color: var(--ink); }

/* A DELETE GOES WHITE ON RED WHEN HOVERED (owner, 18 Sep 2026: "the delete
   should become white instead of remain red when you hover"). ONE rule for
   every delete and danger control - the project's, a file's, a comment's, a
   conversation's, the workspace's - so no second copy can drift. */
.danger-action:not([disabled]):hover, .danger-action:not([disabled]):focus-visible,
.document-delete:hover, .conversation-delete:hover, .project-file-delete:hover,
.project-action[title="Delete project"]:hover, .dictation-discard:hover {
  color: #fff !important; background: var(--danger) !important; border-color: var(--danger) !important;
}

/* THE REVISION STRIP (22 Sep 2026): every filed revision of a deliverable,
   one press apart, on top of the open one. Pills wear the sheet tabs'
   grammar; the open one is ink. */
.revision-strip { display: flex; align-items: center; flex-wrap: wrap; gap: .3rem; margin: .35rem 0 .1rem; }
.revision-strip .eyebrow { margin-right: .2rem; }
.revision-pill { background: none; border: 1px solid var(--border); border-radius: 999px;
  padding: .12rem .55rem; color: var(--ink); font: inherit; font-size: .78rem; cursor: pointer; }
.revision-pill:hover { border-color: var(--ink); }
.revision-pill.is-open { background: var(--ink); color: var(--surface); border-color: var(--ink); cursor: default; }
#writer-report-strip { margin-top: .25rem; }
