/**
 * The hidden attribute has to actually hide.
 *
 * There was no rule for it anywhere in this stylesheet, so `hidden` only worked on elements nothing
 * else gave a display to -- and any element with one silently ignored it. Marking something hidden
 * and watching it stay on screen is a bug with no visible cause: the attribute is right there in the
 * DOM, and the element is right there on the page.
 *
 * Found on the composer's "All databases" switch, which is meant to appear only on an installation
 * licensed for more than one database. `.assist-toggle` sets display: inline-flex, so the switch was
 * offered to everybody -- a control that is present and permanently inert, which the comment beside
 * the Casey switch already warns is worse than one that is absent. That switch has the same class and
 * the same latent fault; it escapes today only because assist happens to be enabled.
 *
 * !important because that is the point: nothing should out-specify "this is not here".
 */
[hidden] { display: none !important; }

/**
 * Boundaries you can actually see.
 *
 * `--surface-soft` was #f7f9fc, which is one and a half percent off white -- a tint that exists in
 * the stylesheet and not on the screen. `--line` was #dfe5ee, a hairline against white at roughly
 * 1.2:1. Both fall far below the 3:1 that a non-text boundary needs to be reliably visible, so every
 * section on every screen ran into the next one and the page read as a single undifferentiated
 * expanse. Reported plainly: "it's just hard for me to see where things start and end".
 *
 * This is not a preference. Faint boundaries are the first thing to disappear on a projector or
 * through compressed video, so a demonstration is where a stylesheet like this fails worst, in front
 * of the people it can least afford to fail in front of.
 *
 * Deepened rather than redrawn. The palette keeps its hue and its quietness -- these are the same
 * blue-greys, moved far enough from white to do the job they were already meant to be doing.
 */
:root {
  /* How far down the page anything pinned must start, because the topbar is itself sticky and owns
     the space above. A number rather than a guess: tab strips pinned to 0 slid underneath it and
     vanished, which is the opposite of what pinning them was for. */
  --topbar-h: 102px;
  --bg: #e8edf5;
  --surface: #ffffff;
  --surface-soft: #eef3f9;
  --ink: #182235;
  --muted: #657187;
  --line: #ccd6e5;
  --navy: #15243d;
  --navy-2: #213654;
  --accent: #2f6fed;
  --accent-dark: #1e56c9;
  /* Casey's own colour: the round C mark wherever Casey is offered (Tom, 24 Sep 2026). */
  --casey: #7c3aed;
  --accent-soft: #eaf1ff;
  /**
   * The blue used on large filled areas: a primary button, the question read back, the answer
   * table's header.
   *
   * --accent is right on small marks -- a link, a focus ring, a three-pixel progress segment -- and
   * wrong spread across a header or a row of buttons, where it stops being an accent and becomes the
   * loudest thing on a screen somebody reads all day. This is the same hue with the saturation taken
   * out, and it is deliberately not paler: white sits on it at about 4.7:1, above the 4.5 needed for
   * normal text, and a gentler blue would have looked kinder here and been unreadable on a laptop in
   * a bright room.
   */
  --blue-soft: #4a72b8;
  --blue-soft-dark: #3f63a1;
  --green: #138a62;
  --green-soft: #e9f8f2;
  --amber: #a96900;
  --amber-soft: #fff5df;
  --red: #c84242;
  --red-soft: #ffeded;
  --shadow: 0 10px 30px rgba(30, 45, 70, .12);
  --radius: 16px;
  --radius-sm: 10px;
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 14px;
}
button, input, textarea, select { font: inherit; }
button { cursor: pointer; }
.hidden { display: none !important; }

.app-shell { min-height: 100%; display: grid; grid-template-columns: 248px 1fr; }
.sidebar {
  position: fixed;
  inset: 0 auto 0 0;
  width: 248px;
  padding: 24px 18px;
  background: linear-gradient(180deg, var(--navy), #0f1b2e);
  color: white;
  display: flex;
  flex-direction: column;
  z-index: 10;
}
.brand { display: flex; gap: 12px; align-items: center; padding: 0 8px 24px; }
.brand-mark {
  width: 40px; height: 40px; border-radius: 12px;
  display: grid; place-items: center;
  background: linear-gradient(145deg, #6f96d6, var(--blue-soft));
  box-shadow: 0 8px 22px rgba(74, 114, 184, .32);
}
.brand-mark svg { display: block; overflow: visible; }

/* The mark: five nodes, and a signal crossing from the question side to the answer side.
   Slow on purpose. This runs for as long as the application is open, in the corner of somebody's
   eye for a working day, so the cycle is over three seconds and the movement is opacity and a
   short dash rather than anything that travels far enough to catch the eye on its own. */
.mark-edge { stroke: rgba(255, 255, 255, .34); stroke-width: 1.4; fill: none; stroke-linecap: round; }
.mark-spark {
  stroke: #fff; stroke-width: 1.8; fill: none; stroke-linecap: round;
  stroke-dasharray: 5 46; animation: mark-flow 3.2s linear infinite;
}
.mark-spark.is-late { animation-delay: 1.4s; }
@keyframes mark-flow { from { stroke-dashoffset: 51; } to { stroke-dashoffset: 0; } }
.mark-node { fill: #fff; animation: mark-beat 3.2s ease-in-out infinite; }
.mark-node.n2 { animation-delay: .4s; }
.mark-node.n3 { animation-delay: .8s; }
.mark-node.n4 { animation-delay: 1.2s; }
.mark-node.n5 { animation-delay: 1.6s; }
@keyframes mark-beat { 0%, 100% { opacity: .55; } 45% { opacity: 1; } }

/* Still a network, just a still one. The dash is dropped rather than frozen mid-travel, which would
   leave a stub of a line sitting across the mark looking like a rendering fault. */
@media (prefers-reduced-motion: reduce) {
  .mark-spark, .mark-node { animation: none; }
  .mark-spark { stroke-dasharray: none; opacity: .45; }
}
.brand-title { font-weight: 750; font-size: 15px; }
/* The datasheet accent, so the sidebar and the paper a buyer was sent agree with each other.
   Taken from the palette of AI CaseQuery-Datasheet-v3.pdf, where it is the dominant non-neutral. */
.brand-accent { color: #51c7b6; }
.brand-subtitle { color: #9fb0c8; font-size: 12px; margin-top: 2px; }
.nav-list { display: grid; gap: 6px; }
.nav-group { display: grid; gap: 4px; }
.nav-item {
  border: 0; background: transparent; color: #b7c5d7;
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px; border-radius: 10px; text-align: left;
  transition: .16s ease;
}
.nav-item:hover { background: rgba(255,255,255,.06); color: white; }
.nav-item.active { background: rgba(85, 139, 255, .18); color: white; box-shadow: inset 3px 0 0 #6c99ff; }
.nav-group-toggle {
  width: 100%; border: 0; background: transparent; color: #b7c5d7;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 14px; border-radius: 10px; text-align: left; transition: .16s ease;
}
.nav-group-toggle:hover, .nav-group-toggle.active { background: rgba(255,255,255,.06); color: white; }
.nav-group-label { display: flex; align-items: center; gap: 12px; }
.nav-caret { font-size: 12px; transition: transform .16s ease; }
.nav-group-toggle[aria-expanded="false"] .nav-caret { transform: rotate(-90deg); }
.nav-submenu { display: grid; gap: 3px; margin: 0 0 2px 26px; padding-left: 10px; border-left: 1px solid rgba(255,255,255,.13); }
.nav-submenu.collapsed { display: none; }
.nav-subitem { padding: 9px 10px; font-size: 12px; gap: 9px; }
.nav-subitem.active { box-shadow: none; background: rgba(85,139,255,.17); }
.nav-submarker { width: 5px; height: 5px; border-radius: 50%; background: currentColor; opacity: .65; }
/* Marks the one item that leaves this application, so a new tab is expected rather than a surprise. */
.nav-external { margin-left: auto; font-size: 11px; opacity: .55; }
.nav-icon { width: 18px; text-align: center; font-size: 17px; }
.sidebar-status { min-width: 0; margin-top: 14px; border-top: 1px solid rgba(255,255,255,.1); padding: 18px 10px 0; display: grid; gap: 10px; color: #aebbd0; font-size: 12px; }

.sidebar-lower { margin-top: auto; }
.history-launch-button {
  width: 100%; border: 1px solid rgba(255,255,255,.12); background: rgba(255,255,255,.055); color: #d7e2f0;
  display: grid; grid-template-columns: 20px 1fr auto; align-items: center; gap: 9px;
  padding: 11px 12px; border-radius: 10px; text-align: left; transition: .16s ease;
}
.history-launch-button:hover, .history-launch-button[aria-expanded="true"] { background: rgba(85,139,255,.18); border-color: rgba(123,164,255,.3); color: white; }
.history-launch-icon { font-size: 17px; text-align: center; }
.history-count { min-width: 24px; padding: 2px 7px; border-radius: 999px; background: rgba(255,255,255,.1); color: #bfcde0; font-size: 11px; text-align: center; }

/* The publish step is the one an administrator must not miss: until it runs, everything configured
   above works on this machine only, and once the folder is read-only it can no longer be set. */
.final-step { margin-top: 4px; padding: 18px 20px 20px; border: 1px solid #c9d9f5; border-left: 4px solid var(--accent);
              border-radius: var(--radius-sm); background: var(--accent-soft); }
.final-step h3 { margin: 6px 0 10px; }
.final-step .field-help { color: #40506b; }
.final-step-flag { display: inline-block; font-size: 11px; font-weight: 750; letter-spacing: .09em;
                   text-transform: uppercase; color: var(--accent-dark); background: white;
                   border: 1px solid #bcd0f6; border-radius: 999px; padding: 3px 10px; }

/*
 * One line per light, always.
 *
 * These were free to wrap, so a long connection description or a licence line turned a two-line
 * block into five and pushed the sidebar wider than the chat beside it. A status light that
 * reflows is worse than a shorter sentence: the eye reads the shape of this block, not the words,
 * and the shape has to be the same every time it is glanced at.
 *
 * The full text is never lost -- each label carries it as a tooltip, so truncation costs nothing.
 */
.status-row { display: flex; gap: 8px; align-items: center; min-width: 0; }
/* The dot must not be squashed by a long name, and the text truncates rather than wraps -- a
   database path or a company name can be arbitrarily long, and the full text stays in the tooltip. */
.status-row > .status-dot { flex: 0 0 auto; }
.status-row > span:not(.status-dot) { min-width: 0; flex: 1 1 auto; line-height: 1.4;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.status-dot { width: 8px; height: 8px; border-radius: 50%; background: #e4a63d; box-shadow: 0 0 0 3px rgba(228,166,61,.13); }
.status-dot.connected, .status-dot.secure { background: #39c88a; box-shadow: 0 0 0 3px rgba(57,200,138,.12); }
.status-dot.error { background: #ff6f6f; box-shadow: 0 0 0 3px rgba(255,111,111,.12); }

.main-area { grid-column: 2; min-width: 0; padding: 0 30px 34px; }
.topbar {
  height: var(--topbar-h); display: flex; align-items: center; justify-content: space-between;
  gap: 20px; position: sticky; top: 0; z-index: 8;
  background: rgba(238,242,247,.92); backdrop-filter: blur(12px);
}
.topbar h1 { margin: 0; font-size: 24px; letter-spacing: -.35px; }
.topbar p { margin: 6px 0 0; color: var(--muted); }
.topbar-actions { display: flex; gap: 8px; align-items: center; }
/* Board #27: at narrower widths the title shrank to one word per line and the badges pushed the page
   sideways. The title keeps a readable width and the badges wrap within their own box instead. */
.topbar > div:first-child { min-width: 0; flex: 1 1 14rem; }
.topbar-actions { flex-wrap: wrap; justify-content: flex-end; min-width: 0; }
/* inline-flex and a stated line-height, so the text is centred by the box rather than by whatever
   the font's metrics happen to do inside a pill. */
.badge { display: inline-flex; align-items: center; justify-content: center; white-space: nowrap;
  background: white; border: 1px solid var(--line); padding: 6px 12px; border-radius: 999px;
  color: #4f5c71; font-size: 12px; line-height: 1; box-shadow: 0 4px 12px rgba(27,43,67,.04); }
/* The switcher to a firm's companion app: this app highlighted, the other one click away. */
.suite-switch { display: inline-flex; padding: 3px; gap: 2px; border-radius: 999px; background: white; border: 1px solid var(--line);
  box-shadow: 0 4px 12px rgba(27,43,67,.04); }
.suite-link { font-size: 12px; font-weight: 600; line-height: 1; padding: 5px 11px; border-radius: 999px; color: #4f5c71; text-decoration: none; white-space: nowrap; }
.suite-link.current { background: var(--accent); color: white; }
a.suite-link:hover, a.suite-link:focus-visible { background: var(--accent-soft); color: var(--accent-dark); }
a.suite-link::after { content: " \2192"; opacity: .7; }
.badge-safe { background: var(--green-soft); color: var(--green); border-color: #ccecdf; }
.badge-unsafe { background: var(--amber-soft); color: var(--amber); border-color: #f0dcad; }

.page { display: none; }
.active-page { display: block; }
.card { background: var(--surface); border: 1px solid rgba(216,224,235,.9); border-radius: var(--radius); box-shadow: var(--shadow); }
.chat-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 58px;
  gap: 16px;
  align-items: start;
  min-height: calc(100vh - 136px);
  transition: grid-template-columns .22s ease;
}
.chat-layout.safeguards-open { grid-template-columns: minmax(0, 1fr) 320px; }
.chat-main { display: flex; flex-direction: column; overflow: hidden; min-height: 680px; }
.chat-messages { flex: 1; min-height: 0; padding: 28px; overflow-y: auto; }
.welcome-panel { max-width: 760px; margin: 66px auto 30px; text-align: center; }
.welcome-icon { width: 58px; height: 58px; margin: 0 auto 18px; display: grid; place-items: center; border-radius: 18px; background: var(--accent-soft); color: var(--accent); font-size: 25px; }
.welcome-panel h2 { margin: 0 0 8px; font-size: 24px; }
/* 710px because the line it has to hold measures 698px at 14px Inter, and 630px broke it in two.
   The panel is 884px, so this fits inside it with room and still stops well short of a full-width
   measure. Below about 710px of chat column it wraps, which is unavoidable without shrinking the
   text or letting it overflow — balance makes that wrap even rather than leaving an orphan word. */
.welcome-panel p { color: var(--muted); line-height: 1.6; max-width: 710px; margin: 0 auto; text-wrap: balance; }
.example-grid { margin-top: 26px; display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 10px; }
.example-chip { background: var(--surface-soft); border: 1px solid var(--line); border-radius: 12px; padding: 13px 14px; color: #3d4a60; text-align: left; line-height: 1.35; }
.example-chip:hover { border-color: #a9c1f9; background: var(--accent-soft); color: #214eae; }
/* Tightened (Tom, 30 Sep 2026): the hint row sits close under the box, and less room before the border. */
.composer-wrap { border-top: 1px solid var(--line); padding: 12px 18px 8px; background: #fbfcfe; }
.composer-wrap textarea { width: 100%; resize: vertical; min-height: 78px; max-height: 220px; border: 1px solid #cfd8e6; border-radius: 12px; padding: 13px 14px; outline: none; color: var(--ink); background: white; }
.composer-wrap textarea:focus, .text-input:focus, .text-area:focus { border-color: #7aa2fa; box-shadow: 0 0 0 3px rgba(47,111,237,.12); }
.composer-footer { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-top: 4px; }
.composer-hint { color: #8a94a6; font-size: 12px; }

.control-panel { padding: 0; align-self: start; overflow: hidden; min-width: 0; }
.safeguard-panel {
  display: grid;
  grid-template-columns: 58px 262px;
  width: 100%;
  min-height: 310px;
  transition: box-shadow .2s ease;
}
.safeguard-toggle {
  width: 58px; min-height: 310px; height: 100%; border: 0; border-right: 1px solid var(--line);
  background: linear-gradient(180deg, #fbfcfe, #f2f5f9); color: #4f5d73;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 14px;
  padding: 16px 0 14px; user-select: none;
}
.safeguard-toggle:hover { background: var(--accent-soft); color: var(--accent-dark); }
.safeguard-toggle:focus-visible { outline: 3px solid rgba(47,111,237,.24); outline-offset: -3px; }
.safeguard-toggle-icon { width: 30px; height: 30px; display: grid; place-items: center; border-radius: 9px; background: white; border: 1px solid var(--line); font-size: 16px; }
.safeguard-toggle-label { writing-mode: vertical-rl; transform: rotate(180deg); font-size: 12px; font-weight: 750; letter-spacing: .55px; }
.safeguard-toggle-arrow { margin-top: auto; font-size: 22px; line-height: 1; transition: transform .2s ease; }
.safeguard-panel:not(.is-collapsed) .safeguard-toggle-arrow { transform: rotate(180deg); }
.safeguard-content {
  width: 262px; padding: 18px 20px 22px; opacity: 1; visibility: visible;
  transform: translateX(0); transition: opacity .16s ease, transform .2s ease, visibility 0s;
}
.safeguard-panel.is-collapsed .safeguard-content { opacity: 0; visibility: hidden; pointer-events: none; transform: translateX(16px); transition: opacity .12s ease, transform .2s ease, visibility 0s .2s; }
.safeguard-heading { padding-bottom: 13px; border-bottom: 1px solid var(--line); }
.safeguard-heading strong { display: block; font-size: 14px; }
.safeguard-heading small { display: block; color: var(--muted); margin-top: 3px; font-size: 11px; line-height: 1.35; }
.control-panel h3, .designer-output h3 { margin: 0 0 14px; font-size: 15px; }
.switch-row { display: grid; grid-template-columns: minmax(10rem, 1fr) auto; gap: 12px; align-items: center; margin: 16px 0; position: relative; }
.switch-row input { position: absolute; opacity: 0; pointer-events: none; }
.switch-row strong { display: block; font-size: 13px; }
.switch-row small { display: block; color: var(--muted); margin-top: 3px; line-height: 1.35; }
.switch { width: 42px; height: 24px; border-radius: 999px; background: #c7cfda; position: relative; transition: .16s; }
.switch::after { content: ""; position: absolute; width: 18px; height: 18px; top: 3px; left: 3px; border-radius: 50%; background: white; box-shadow: 0 2px 6px rgba(0,0,0,.2); transition: .16s; }
.switch-row input:checked + .switch { background: var(--accent); }
.switch-row input:checked + .switch::after { transform: translateX(18px); }
.switch-row.compact { margin: 14px 0; }
.divider { height: 1px; background: var(--line); margin: 22px 0; }
.field-label { display: block; color: #49566a; font-weight: 650; font-size: 12px; margin: 16px 0 7px; }
.required { color: var(--red); font-weight: 500; }

/* Expected, not required. Quieter than the red asterisk beside a mandatory field, because this one
   can be left empty and the form will still save -- it says "you will regret skipping this", not
   "you cannot continue". */
.expected {
  font-size: 10px; letter-spacing: .04em; text-transform: uppercase; font-weight: 500;
  color: var(--muted); border: 1px solid var(--line); border-radius: 3px;
  padding: 1px 5px; margin-left: 6px; vertical-align: 1px;
}
.text-input, .text-area { width: 100%; border: 1px solid #d2dae6; border-radius: 10px; padding: 10px 11px; color: var(--ink); background: white; outline: none; }
.text-area { resize: vertical; line-height: 1.45; }
.field-help { color: var(--muted); font-size: 12px; margin-top: 6px; }
/* Board #65: a help line that needs acting on, such as a connection now opening a different database. */
.field-help.is-warning { color: #8a5a00; font-weight: 600; }
/* Board #63: the client money review. One block per accounting database, nothing collapsed. */
.accounting-review { display: block; margin-bottom: 14px; }
.accounting-review .table-choice { margin-top: 2px; }
.accounting-review .switch-inline { display: flex; align-items: flex-start; gap: 8px; margin: 12px 0 6px; font-size: 13px; }
.accounting-review .switch-inline input { width: auto; margin-top: 3px; }
/* A heading for a group of objects, said as a suggestion rather than as the answer itself. */
.accounting-review .section-title { font-size: 11.5px; color: var(--muted); text-transform: uppercase; letter-spacing: .06em; font-weight: 700; margin: 16px 0 4px; }
/* Board #45: how a database writes its case numbers, folded away until somebody needs it. */
.key-format { margin-top: 14px; border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; background: var(--surface-soft); }
.key-format > summary { cursor: pointer; font-weight: 650; }
.key-format-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 10px 14px; margin: 10px 0; }
.key-format-grid .switch-inline { display: flex; align-items: center; gap: 7px; font-size: 13px; }
.key-format-grid .switch-inline input { width: auto; }
.key-format-result { margin-top: 10px; }
.key-format-result .note.warn { color: #8a5a00; font-weight: 600; margin: 6px 0 0; }
/* Every way into this installation, one per row. Deliberately plain: it is a statement of fact
   somebody reads once, not a control, and anything that looked pressable would invite the click
   this panel cannot answer. */
.authority-table { width: 100%; border-collapse: collapse; margin-top: 12px; }
.authority-table td { padding: 8px 12px 8px 0; border-top: 1px solid var(--line); font-size: 13px;
                      vertical-align: top; }
.authority-table tr:first-child td { border-top: none; }
.authority-how { white-space: nowrap; width: 1%; color: var(--muted); padding-right: 24px; }
/* Work already done that the application cannot see. Loud, because the person reading it believes
   they have configured something and the screen appears to disagree. */
.authority-stranded { background: var(--amber-soft); border: 1px solid #f0dcad; border-radius: 6px;
                      padding: 12px 14px; margin-top: 12px; font-size: 13px; color: #6b4e00; }
.authority-stranded div { margin-top: 6px; color: #7a5f14; }
#authorityChange { margin-top: 18px; border-top: 1px solid var(--line); padding-top: 14px; }
#authorityChange summary { cursor: pointer; font-weight: 650; font-size: 13px; color: var(--accent-dark); }
#authorityChange[open] summary { margin-bottom: 10px; }
#authorityJson { font-family: Consolas, monospace; font-size: 12.5px; }
.field-checkbox { display: flex; align-items: flex-start; gap: 8px; margin-top: 12px; font-size: 13px;
                  cursor: pointer; }
.field-checkbox input { margin-top: 2px; }
.info-box { margin-top: 20px; padding: 14px; border-radius: 11px; background: #f3f6fb; color: #4c5a70; font-size: 12px; line-height: 1.45; }
/* Tom, 30 Sep 2026: the live 'only you have these settings' warning, outside the folded cards. */
.installation-bar { padding: 14px 16px; border-radius: 10px; border: 1px solid #f0c36d; border-left: 5px solid #d18b00; background: #fff8e8; color: #5a4200; font-size: 12.5px; line-height: 1.5; }
.installation-bar strong { display: block; font-size: 13.5px; margin-bottom: 4px; color: #4a3500; }
.installation-bar p, .installation-bar ul { margin: 4px 0 8px; }
.installation-bar ul { padding-left: 18px; }
.installation-bar .button-row { margin-top: 6px; }
/* Tom, 30 Sep 2026: the draft a view recommendation opens, and the two decisions it asks. */
.view-draft { border-left: 4px solid var(--accent, #2f6fdb); }
.view-draft-step { margin: 12px 0; }
.view-draft-step > strong { display: block; margin-bottom: 4px; }
.view-draft-option { display: flex; gap: 8px; align-items: flex-start; margin: 6px 0; font-size: 12.5px; cursor: pointer; }
.view-draft-option input { margin-top: 3px; }
.info-box strong { color: #334158; }
.info-box p { margin: 5px 0 0; }
/* A second heading in the same box starts a new point, so it gets room above it. */
.info-box p + strong { display: block; margin-top: 12px; }
/* Where the provider key lives, for the person from IT who asks.
   A table because it is a comparison — two places, two different things protecting them — and a
   paragraph would make the reader hold both halves in their head to do the comparing themselves. */
.key-storage { width: 100%; border-collapse: collapse; margin: 18px 0 4px; font-size: 12.5px; }
.key-storage th, .key-storage td { text-align: left; vertical-align: top; padding: 10px 12px; border-bottom: 1px solid var(--line); }
.key-storage th { color: var(--muted); font-weight: 650; font-size: 11.5px; text-transform: uppercase; letter-spacing: .06em; }
.key-storage td { color: #4c5a70; line-height: 1.5; }
.key-storage td:first-child { width: 34%; color: #334158; }
.key-storage code { font-size: 11.5px; }
.key-storage-notes { margin: 10px 0 0; padding-left: 18px; }
.key-storage-notes li { margin-bottom: 5px; line-height: 1.5; }

/* A command meant to be copied rather than retyped. The button sits with it, because a command
   somebody retypes by eye is a command somebody gets wrong. */
.code-line { display: flex; align-items: center; gap: 10px; margin: 8px 0 0; padding: 10px 12px;
             border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface-soft); }
.code-line code { flex: 1 1 auto; min-width: 0; overflow-x: auto; white-space: nowrap; font-size: 12px; color: #334158; }
.code-line .secondary-button { flex: 0 0 auto; padding: 5px 12px; font-size: 12px; }

.policy-guidance { margin: 0 0 16px; }
.policy-guidance p + p { margin-top: 8px; }
.policy-guidance b { color: #334158; font-weight: 650; }

.primary-button, .secondary-button, .icon-button, .copy-inline {
  border-radius: 9px; border: 1px solid transparent; padding: 10px 15px; font-weight: 650; transition: .15s ease;
}
.primary-button { background: var(--blue-soft); color: white; box-shadow: 0 5px 14px rgba(74,114,184,.18); }
.primary-button:hover { background: var(--blue-soft-dark); }
.primary-button:disabled { opacity: .55; cursor: not-allowed; }
.secondary-button { background: white; color: #435066; border-color: #ced7e4; }
.secondary-button:hover:not(:disabled) { border-color: #a9b8cc; background: #f8fafc; }
/* Only .primary-button had this, so every disabled secondary button looked live: full opacity, a
   pointer cursor, and a hover state that responded. Somebody clicking one got nothing and no reason
   -- which is how "the filter doesn't work" gets reported for a filter that works. */
.secondary-button:disabled { opacity: .55; cursor: not-allowed; }

/* What is left where a button was once it has been pressed. Not a disabled button: a disabled
   button still asks to be clicked and then refuses, and dimming it says "you cannot do this" where
   what this has to say is "you already did". Full contrast for the same reason. */
.applied-note { display: inline-flex; align-items: center; background: var(--green-soft);
  color: var(--green); border: 1px solid #ccecdf; border-radius: 9px; padding: 10px 15px;
  font-size: 13px; font-weight: 600; }
.icon-button { padding: 8px 10px; background: white; color: #536078; border-color: var(--line); }
.full-width { width: 100%; }
.small { padding: 7px 10px; font-size: 12px; }
.button-row { display: flex; gap: 9px; align-items: center; flex-wrap: wrap; }

.message { margin: 0 0 22px; }
.message.user { display: flex; justify-content: flex-end; }
.message.user .bubble { max-width: 74%; background: var(--blue-soft); color: white; border-radius: 16px 16px 4px 16px; padding: 12px 15px; line-height: 1.5; box-shadow: 0 5px 15px rgba(74,114,184,.16); white-space: pre-wrap; }
.message.assistant .assistant-head { display: flex; gap: 10px; align-items: center; margin-bottom: 9px; }
.ai-avatar { width: 30px; height: 30px; display: grid; place-items: center; border-radius: 9px; background: var(--accent-soft); color: var(--accent); font-weight: 800; }
.assistant-title { font-weight: 750; }
.assistant-body { margin-left: 40px; color: #344057; line-height: 1.58; }
.assistant-body p { margin: 0 0 10px; }
.assistant-body ul { margin: 8px 0 12px; padding-left: 20px; }
.answer-meta { margin-left: 40px; display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.meta-pill { border: 1px solid var(--line); background: #f7f9fc; color: #69758a; padding: 5px 8px; border-radius: 999px; font-size: 11px; }
/* min-width:0 so a wide table scrolls inside its own wrapper instead of pushing this box wider and
   being clipped by the overflow:hidden that rounds the corners. Without it the last column simply
   disappeared and no scrollbar appeared to get it back. */
.disclosure { margin: 12px 0 0 40px; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; min-width: 0; }
.disclosure-content { min-width: 0; }
/* The same disclosure inside a settings card, without the indent that aligns the chat one under an
   answer. For a step that is the whole point of the screen once and a rarity ever afterwards. */
.settings-disclosure { margin: 12px 0 0; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; min-width: 0; }
.settings-disclosure summary { padding: 10px 12px; background: #f8fafc; color: #536078; font-weight: 650; cursor: pointer; }
.disclosure summary { padding: 10px 12px; background: #f8fafc; color: #536078; font-weight: 650; cursor: pointer; }
.disclosure-content { padding: 12px; }
.loading-message { display: flex; align-items: center; gap: 10px; margin: 12px 0 20px 40px; color: var(--muted); }
.spinner { width: 17px; height: 17px; border: 2px solid #d8e2f4; border-top-color: var(--accent); border-radius: 50%; animation: spin .8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* Where the question has got to, in place of a spinner.
   A spinner says only "not finished", which is the one thing the reader already knows. These carry
   the stage the server is actually in, so a question that is slow shows WHERE it is slow. */
.progress-steps { display: inline-flex; gap: 4px; align-items: center; flex-shrink: 0; }
.progress-steps i { width: 16px; height: 3px; border-radius: 2px; background: var(--line); display: block;
                    transition: background .25s ease; }
.progress-steps i.is-done { background: var(--accent); }
/* The one in progress pulses. Only one ever does, so the movement means "here", not "working". */
.progress-steps i.is-now { background: var(--accent); animation: step-pulse 1.3s ease-in-out infinite; }
@keyframes step-pulse { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }
/* Tabular, so the line does not shift a pixel each time the count ticks over. */
.progress-elapsed { font-variant-numeric: tabular-nums; font-size: 12px; color: var(--muted); flex-shrink: 0; }

/* Movement is the decoration; the position is the information. Someone who has asked for less
   motion keeps every bit of what this says and loses only the pulse. */
@media (prefers-reduced-motion: reduce) {
  .progress-steps i.is-now { animation: none; opacity: .7; }
  .spinner { animation: none; }
}

/* Kept as `auto` on both axes rather than split: the sticky header below positions itself against
   this element as its scroll container, and taking that away makes headers stick to the page. */
/* max-width and a reserved gutter. On Windows 11 the scrollbar is an overlay that fades out, so a
   table that scrolled looked identical to one that was simply cut off -- reported twice as "no
   horizontal scroll and a column out of view". The gutter keeps the bar in the layout, and the
   height cap turns a long answer into something scrollable rather than a page nobody can leave. */
.table-wrap { width: 100%; max-width: 100%; overflow: auto; border: 1px solid var(--line);
              border-radius: 10px; background: white; position: relative;
              max-height: 62vh; scrollbar-gutter: stable; }

/* Only when the columns actually overrun. A permanent bar and a permanent edge shadow on a table
   that fits are pure clutter, so `is-scrollable` is set by measurement (see watchHorizontalOverflow)
   and removed the moment the window is wide enough again. */
.table-wrap.is-scrollable { scrollbar-color: #b6c2d6 #eef2f8; }
.table-wrap.is-scrollable::-webkit-scrollbar { height: 12px; }
.table-wrap.is-scrollable::-webkit-scrollbar-track { background: #eef2f8; border-radius: 0 0 10px 10px; }
.table-wrap.is-scrollable::-webkit-scrollbar-thumb { background: #b6c2d6; border-radius: 6px; border: 2px solid #eef2f8; }
.table-wrap.is-scrollable::-webkit-scrollbar-thumb:hover { background: #92a2bd; }

/* A shadow on whichever edge has content beyond it, so it is obvious there is more and which way to
   go. Both classes come off at the ends, which is what makes them read as "more this way". */
.table-wrap.overflow-right { box-shadow: inset -14px 0 12px -12px rgba(24, 34, 53, 0.28); }
.table-wrap.overflow-left { box-shadow: inset 14px 0 12px -12px rgba(24, 34, 53, 0.28); }
.table-wrap.overflow-left.overflow-right { box-shadow: inset 14px 0 12px -12px rgba(24, 34, 53, 0.28), inset -14px 0 12px -12px rgba(24, 34, 53, 0.28); }
table { width: 100%; border-collapse: collapse; font-size: 12px; }
th { position: sticky; top: 0; background: #f4f7fb; text-align: left; color: #536078; font-weight: 700; border-bottom: 1px solid var(--line); }

/* The answer table, given a header that reads as a heading rather than as another row.
   Softer than --accent (#2f6fed), which across a full-width header shouts; dark enough that white
   sits on it at about 4.7:1, which is above the 4.5 needed for normal text. A paler blue would have
   looked gentler and failed anybody reading it on a laptop screen in a bright room.
   Scoped to this table: the schema explorer, the mapping panes and the rules guide keep the quiet
   grey header, because they are reference material rather than the answer somebody asked for. */
.is-result-table th {
  background: var(--blue-soft); color: #fff; border-bottom-color: var(--blue-soft-dark);
}
/* The sticky header sits over scrolling rows, so it needs its own top corners inside the wrapper. */
.is-result-table th:first-child { border-top-left-radius: 9px; }
.is-result-table th:last-child { border-top-right-radius: 9px; }
th, td { padding: 9px 10px; border-right: 1px solid #edf0f5; border-bottom: 1px solid #edf0f5; white-space: nowrap; max-width: 360px; overflow: hidden; text-overflow: ellipsis; }
tr:last-child td { border-bottom: 0; }
tr:hover td { background: #fafcff; }
/* Suspicions about an answer. Understated on purpose — see buildSignalPanel. */
.signal-box { margin: 12px 0 0 40px; border: 1px solid var(--line); border-radius: 10px; padding: 8px 12px; background: var(--surface-soft); font-size: 12px; }

/* The disclosure control, deliberately not subtle.
 *
 * This was a 12px grey text triangle, which is the same weight as the sentence beside it -- so the
 * panel read as a statement rather than something with more behind it, and the detail that names the
 * two readings went unopened. Understating the panel (see buildSignalPanel) is about not shouting
 * when it fires; it was never meant to hide the fact that it opens.
 *
 * Three things carry it now: a filled chip the glyph sits in, so the control has an edge; the
 * rotation on open, so it reads as a hinge rather than two unrelated characters; and a worded
 * affordance on the right, because an icon alone cannot say what opening it gets you. */
.signal-box summary {
  cursor: pointer; color: var(--muted); font-weight: 600; list-style: none;
  display: flex; align-items: center; gap: 9px;
  margin: -2px -4px; padding: 3px 4px; border-radius: 7px;
}
.signal-box summary::-webkit-details-marker { display: none; }
.signal-box summary:hover { background: rgba(30, 45, 70, .045); }
.signal-box summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.signal-box summary::before {
  content: '\25B8';
  flex: 0 0 auto; width: 19px; height: 19px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 6px; background: #dde4ee; color: var(--navy-2);
  font-size: 13px; line-height: 1;
  transition: transform .16s ease;
}
.signal-box[open] summary::before { transform: rotate(90deg); }
.signal-box summary::after {
  content: 'Show details'; margin-left: auto;
  font-size: 11px; font-weight: 600; color: var(--accent); text-decoration: underline;
}
.signal-box[open] summary::after { content: 'Hide'; }
@media (prefers-reduced-motion: reduce) { .signal-box summary::before { transition: none; } }

.signal-warning { border-color: #f0e0c4; background: #fdf8ee; }
.signal-warning summary { color: #8a5a12; }
.signal-warning summary::before { background: #f2e0bd; color: #8a5a12; }
.signal-warning summary:hover { background: rgba(138, 90, 18, .07); }
.signal-item { margin-top: 10px; padding-top: 10px; border-top: 1px solid #edf0f5; }
.signal-item:first-of-type { border-top: 0; }
.signal-item p { margin: 4px 0 0; color: #3d4a60; line-height: 1.45; }
/* What actually differed between the two askings. Set apart from the prose because it is the only
   part somebody can act on, and it is usually two table names. */
.signal-difference {
  margin: 7px 0 0 !important; padding: 7px 10px;
  border-left: 2px solid var(--amber); border-radius: 0 6px 6px 0;
  background: rgba(169, 105, 0, .06);
  color: #6b4a12 !important; font-size: 11.5px; line-height: 1.5 !important;
}
.signal-suggests { color: var(--muted) !important; font-style: italic; }
.signal-action { margin-top: 8px; background: none; border: 0; padding: 0; color: var(--accent); font-size: 12px; cursor: pointer; text-decoration: underline; }
.signal-action:hover { color: var(--accent-dark); }
/* Board #53: the panel's actions sit together under it, one per thing to sort out. */
.signal-actions { display: flex; flex-wrap: wrap; gap: 4px 16px; }

/* The proposal review. Wide, because the whole point is showing two answers side by side. */
/**
 * The wide modal, written with enough specificity to actually win.
 *
 * `.modal-card-wide { width: 92vw }` sat above `.modal-card { width: min(540px, 100%) }` in this
 * file. Same specificity, later rule wins — so the "wide" modal had been 540px since the day it was
 * written, which is what made the proposal cramped. Two classes now, so order stops mattering.
 */
.modal-card.modal-card-wide { width: min(1240px, 94vw); max-width: none; }

/* Writing on the left, consequences on the right. */
.proposal-layout { display: grid; grid-template-columns: minmax(300px, 400px) minmax(0, 1fr); gap: 20px; align-items: start; }
.proposal-edit { min-width: 0; }
.proposal-preview { min-width: 0; }
.proposal-placeholder { margin: 12px 0 0; font-size: 12px; color: var(--muted); border: 1px dashed var(--line); border-radius: 10px; padding: 14px; text-align: center; }
.proposal-diff:not(:empty) + .proposal-placeholder { display: none; }
/* One column below the width where two would each be too narrow to read a query in. */
@media (max-width: 940px) { .proposal-layout { grid-template-columns: 1fr; } }
.proposal-kind { display: flex; gap: 8px; flex-wrap: wrap; margin: 0 0 12px; }
/* Available, but not yet: a locked padlock says "there is a step first", where a missing button
   says "this does not exist". */
/* A control you can see and cannot yet use.
   One convention for both tiers: .needs-admin was here for the draft-a-rule button on a chat answer,
   and .needs-key now says the same thing for everything on Fine-tuning that wants the leads' key.
   Both stay pressable — pressing one is how you are offered the key — so this is a statement about
   what will happen, not a disabled control. */
.needs-admin::after, .needs-key::after { content: " 🔒"; font-size: 11px; }
.needs-admin, .needs-key { opacity: .78; }
.needs-key:hover { opacity: 1; }
.proposal-badge { font-size: 11px; font-weight: 700; padding: 4px 9px; border-radius: 999px; background: var(--accent-soft); color: #214eae; }
.proposal-badge.note { background: #eaf7ee; color: #1d6b35; }
.proposal-badge.caution { background: #fdf2e2; color: #8a5a12; }
.proposal-reason { margin: 8px 0 0; font-size: 12px; color: var(--muted); }
.proposal-related { margin: 12px 0 0; font-size: 12px; color: #8a5a12; background: #fdf8ee; border: 1px solid #f0e0c4; border-radius: 10px; padding: 10px 12px; }
.proposal-related:empty { display: none; }
.proposal-related ul { margin: 6px 0 0; padding-left: 18px; }
.proposal-note { font-size: 11px; color: var(--muted); }
.proposal-diff:empty { display: none; }
/* Bounded so the comparison cannot push the modal to an absurd height. The two result tables scroll
   within their own panes, which keeps the accept and discard buttons close to hand. */
/**
 * No scroll region of its own.
 *
 * The card scrolls, this scrolled, and the query inside it scrolled — three nested scrollbars, so
 * reaching the bottom of the comparison meant finding the right one first. The card is the only
 * scroller now, and the two-column layout is what makes it short enough for one to be enough.
 */
.proposal-diff { margin-top: 12px; }
.proposal-compare { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.proposal-side { border: 1px solid var(--line); border-radius: 10px; padding: 10px; min-width: 0; }
.proposal-side-count { margin: 4px 0 8px; font-size: 12px; color: var(--muted); }
.proposal-side-error { margin: 4px 0 8px; font-size: 12px; color: #a3282f; }
/* Room for a real query now that there is width to hold one; capped so a monster cannot own the
   whole modal, and the cap is high enough that the ordinary case never meets it. */
.proposal-sql { margin: 8px 0 0; font-size: 11px; background: #f6f8fc; border-radius: 8px; padding: 9px 10px; max-height: 260px; overflow: auto; white-space: pre-wrap; word-break: break-word; line-height: 1.5; }
.proposal-nochange { margin: 0 0 10px; font-size: 12px; color: #8a5a12; }
@media (max-width: 780px) { .proposal-compare { grid-template-columns: 1fr; } }

/* Whether questions that were read two ways have settled — the glossary's only feedback signal. */
.rules-effect { margin-top: 16px; }
.rules-effect:empty { display: none; }
.effect-heading { display: block; font-size: 12px; color: var(--ink); margin-bottom: 8px; }
.effect-group { border-left: 3px solid var(--line); padding: 2px 0 2px 10px; margin-bottom: 10px; }
.effect-group.effect-settled { border-left-color: #4c9a67; }
.effect-group.effect-unsettled { border-left-color: #d8a13c; }
.effect-group-title { font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: 0.03em; }
.effect-group ul { list-style: none; margin: 6px 0 0; padding: 0; }
.effect-group li { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px; align-items: baseline; font-size: 12px; padding: 3px 0; }
/* Second row of the same item: what the two readings were. `order` puts it last whatever position
   it holds in the markup, and the full basis forces the wrap rather than squeezing the question. */
.effect-change {
  order: 1; flex: 0 0 100%; margin: 2px 0 4px;
  padding: 5px 9px; border-left: 2px solid var(--amber); border-radius: 0 6px 6px 0;
  background: rgba(169, 105, 0, .06); color: #6b4a12; font-size: 11px; line-height: 1.45;
  white-space: normal;
}
.effect-question { color: #3d4a60; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.effect-meta { color: var(--muted); font-size: 11px; white-space: nowrap; flex-shrink: 0; }
.effect-dismiss { background: none; border: 0; padding: 0 2px; color: var(--muted); font-size: 12px; cursor: pointer; flex-shrink: 0; line-height: 1; }
.effect-dismiss:hover { color: #a3282f; }
.effect-caveat { margin: 8px 0 0; font-size: 11px; color: var(--muted); font-style: italic; }

.backup-list { list-style: none; margin: 6px 0 0; padding: 0; border: 1px solid var(--line); border-radius: 10px; max-height: 210px; overflow-y: auto; }
.backup-list li { display: flex; justify-content: space-between; gap: 12px; align-items: center; padding: 6px 11px; border-bottom: 1px solid #edf0f5; font-size: 12px; }
.backup-list li:last-child { border-bottom: 0; }
.backup-label { color: #3d4a60; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.backup-restore { background: none; border: 1px solid var(--line); border-radius: 7px; padding: 3px 10px; font-size: 11px; color: var(--accent); cursor: pointer; flex-shrink: 0; }
.backup-restore:hover { border-color: #a9c1f9; background: var(--accent-soft); }

/* Where each rule came from, and what the set costs on every question. */
.rules-provenance { margin-top: 14px; }
/* What the glossary is missing, beside what it costs. Same quiet register as the cost line: a fact
   an administrator can act on, not a warning demanding they act now. */
.rules-naming-gap {
  font-size: 12px; color: var(--muted); line-height: 1.45; margin-top: 6px;
}

.rules-cost { margin: 0 0 10px; font-size: 12px; color: var(--muted); }
/* The readable view of the rules. Rows rather than text, so each rule has a visible start and
   end -- which the editing box above cannot give, because a wrapped line looks like two rules. */
.rules-history { list-style: none; margin: 0; padding: 0; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.rules-history li { display: flex; gap: 12px; align-items: flex-start; padding: 9px 12px;
  border-bottom: 1px solid #edf0f5; font-size: 12px; }
.rules-history li:last-child { border-bottom: 0; }
/* Banding as well as a rule between rows: with the text now wrapping to two or three lines, a
   hairline alone is not enough to tell one entry from the next at a glance. */
.rules-history li:nth-child(even) { background: var(--surface-soft); }
/* The number is what the eye lands on to find the start of an entry. */
.rules-history-number { color: var(--muted); font-variant-numeric: tabular-nums; font-size: 11px;
  min-width: 1.6em; text-align: right; flex-shrink: 0; padding-top: 1px; }
/* Wraps now, and is shown in full: this is where somebody reads their rules, so cutting one at 90
   characters hid the half that usually carries the condition. */
.rules-history-text { color: #3d4a60; min-width: 0; flex: 1; line-height: 1.5; white-space: normal;
  overflow-wrap: anywhere; }
.rules-history-meta { color: var(--muted); font-size: 11px; white-space: nowrap; flex-shrink: 0; padding-top: 1px; }
/* A rule a scan measured, rather than one somebody typed. Two of these arrived a fortnight apart
   saying nearly the same thing, and nothing on the screen distinguished them from the reader's own
   sentences -- so they read as rules he could not remember writing. The stripe carries down the
   left edge so they can be counted at a glance; the chip says what wrote it. */
.rules-history li.is-machine-written { box-shadow: inset 3px 0 0 var(--accent, #6b7fd7); }

/* A rule the floor voted in, distinguishable at a glance from one a scan measured.
   Green rather than the accent blue: several colleagues agreeing is a decision that held, and it
   should not be confused with a finding that becomes stale when the database changes. */
.rules-history li.is-floor-voted { box-shadow: inset 3px 0 0 var(--good, #3f9d6d); }
.rules-history-origin.is-vote {
  color: var(--good, #3f9d6d);
  border-color: color-mix(in srgb, var(--good, #3f9d6d) 45%, transparent);
  background: color-mix(in srgb, var(--good, #3f9d6d) 10%, transparent);
}
.rules-history-origin {
  font-size: 10px; letter-spacing: .05em; text-transform: uppercase; font-weight: 500;
  color: var(--muted); border: 1px solid var(--line); background: var(--surface-soft);
  border-radius: 3px; padding: 2px 7px; white-space: nowrap; flex-shrink: 0; align-self: flex-start;
}

/* A cell holding an address. The trailing glyph is what tells a viewer it is clickable at a glance,
   since the cell is ellipsised and the underline alone can be scrolled out of sight. */
/* A button styled as a link, because a case number opens a panel rather than navigating. Reset the
   button chrome or it arrives grey, boxed and centred inside a table cell. */
/* Full width beneath the schema browser. Fifteen fields across several tracks is a wide job, and the
   360px object column it started in made it a scroll nobody finishes. */
.table-more { display: flex; align-items: center; gap: 10px; padding: 8px 2px 0; font-size: 12px; color: var(--muted); }
.details-picker { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding-bottom: 12px;
                  border-bottom: 1px solid var(--line); }
.details-picker select { width: auto; min-width: 200px; }
.file-details-config { margin-top: 20px; padding: 18px 22px; }
.file-details-config .panel-heading { align-items: flex-start; }
.details-entity { border-top: 1px solid var(--line); padding-top: 14px; margin-top: 14px; }
.details-entity:first-child { border-top: 0; margin-top: 6px; }
/* auto-fill rather than a fixed count: on a wide screen the ticks use the whole width, and on a
   narrow one they fall back to fewer tracks without a media query per breakpoint. */
.details-fields { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
                  gap: 2px 18px; margin: 10px 0 8px; }
.details-fields .field-checkbox { margin-top: 4px; }
button.cell-link { background: none; border: 0; padding: 0; font: inherit; text-align: left; }
.file-details { margin-top: 14px; padding: 16px 18px; }
.file-details h3 { margin: 0 0 10px; font-size: 15px; font-family: Consolas, monospace; }
.file-details-body { max-height: 420px; overflow-y: auto; }
.cell-link { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
.cell-link:hover { color: var(--accent-dark); }
.cell-link::after { content: ' \2197'; font-size: 10px; opacity: 0.65; text-decoration: none; display: inline-block; }
.table-toolbar { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin: 0 0 8px; color: var(--muted); font-size: 12px; }

.schema-layout { display: grid; grid-template-columns: 360px minmax(0,1fr); gap: 20px; min-height: calc(100vh - 136px); }
.schema-list, .schema-detail { padding: 22px; min-height: 660px; }
.panel-heading { display: flex; justify-content: space-between; gap: 12px; align-items: flex-start; margin-bottom: 16px; }

/* The badge and the Show/Hide control, kept together on the right of the worklist heading so the
   heading itself stays one line however long the summary underneath it runs. */
.worklist-heading-actions { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }

/* A control that is a control and not a call to action. Used for Show/Hide steps, where a button
   styled like the primary and secondary ones would compete with the work on the page. */
.link-button {
  background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--accent); font: inherit; font-size: 12.5px; text-decoration: underline;
  text-underline-offset: 2px;
}
.link-button:hover { color: var(--navy); }
.link-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
.panel-heading h2, .detail-heading h2, .settings-card h2 { margin: 0; font-size: 18px; }
.panel-heading p, .detail-heading p, .settings-card > p { color: var(--muted); margin: 5px 0 0; line-height: 1.45; }
.segmented { display: grid; grid-template-columns: repeat(3, 1fr); margin: 12px 0; padding: 3px; border-radius: 9px; background: #eef2f7; }
.segment { border: 0; padding: 7px; border-radius: 7px; background: transparent; color: #6b778a; font-size: 12px; }
.segment.active { background: white; color: #334158; box-shadow: 0 2px 7px rgba(29,43,64,.08); font-weight: 650; }
.object-list { display: grid; gap: 4px; max-height: calc(100vh - 325px); overflow-y: auto; padding-right: 3px; }
.object-item { border: 1px solid transparent; background: transparent; border-radius: 9px; padding: 10px; text-align: left; display: grid; grid-template-columns: 1fr auto; gap: 8px; }
.object-item:hover { background: #f7f9fc; }
.object-item.active { background: var(--accent-soft); border-color: #bfd2ff; }
.object-name { font-weight: 650; color: #35425a; overflow: hidden; text-overflow: ellipsis; }
.object-sub { color: #8791a2; font-size: 11px; margin-top: 3px; }
.object-kind { font-size: 10px; color: #748096; background: #eef2f7; border-radius: 999px; padding: 4px 6px; align-self: start; }
.curated-star { color: #2f6fed; }
.empty-state { text-align: center; max-width: 430px; margin: 170px auto 0; color: var(--muted); }
.empty-state h3 { color: var(--ink); margin: 12px 0 6px; }
.empty-state p { line-height: 1.5; }
.empty-icon { width: 56px; height: 56px; margin: auto; display: grid; place-items: center; border-radius: 17px; background: #f0f4fa; font-size: 23px; color: #728199; }
.detail-heading { display: flex; justify-content: space-between; gap: 18px; align-items: flex-start; }
.object-type { display: inline-block; color: var(--accent); background: var(--accent-soft); font-size: 10px; font-weight: 800; padding: 5px 7px; border-radius: 6px; margin-bottom: 8px; letter-spacing: .4px; }
.tab-strip { display: flex; gap: 18px; border-bottom: 1px solid var(--line); margin-top: 20px; }
.detail-tab { border: 0; background: transparent; color: #6d788b; padding: 10px 1px; border-bottom: 2px solid transparent; }
.detail-tab.active { color: var(--accent); border-bottom-color: var(--accent); font-weight: 700; }
.detail-pane { display: none; padding-top: 18px; }
.detail-pane.active-pane { display: block; }
.column-list { display: grid; gap: 6px; }
.column-row { display: grid; grid-template-columns: minmax(160px, 1fr) 130px 120px; gap: 12px; padding: 10px 11px; border: 1px solid #edf0f5; border-radius: 9px; align-items: center; }
.column-row strong { overflow: hidden; text-overflow: ellipsis; }
.column-type { color: #657187; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; }
.column-flags { color: #8993a4; font-size: 11px; text-align: right; }
.code-block { margin: 0; padding: 15px; border-radius: 10px; background: #101a2b; color: #d7e4f7; font: 12px/1.55 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; white-space: pre-wrap; overflow: auto; max-height: 420px; }

.designer-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; align-items: start; }
.designer-form, .designer-output { padding: 24px; min-height: 0; }
.designer-source-grid { display: grid; grid-template-columns: minmax(300px, .9fr) minmax(360px, 1.1fr); gap: 18px; align-items: start; margin-bottom: 18px; }
.designer-source-panel { min-width: 0; }
.designer-output-bottom { width: 100%; scroll-margin-top: 116px; }
.designer-output-bottom .code-block { max-height: 520px; }
.object-picker { max-height: 190px; overflow-y: auto; border: 1px solid var(--line); border-radius: 10px; padding: 7px; margin-top: 8px; }
.picker-item { display: flex; gap: 9px; align-items: flex-start; padding: 8px; border-radius: 7px; }
.picker-item:hover { background: #f6f8fb; }
.picker-item input { margin-top: 2px; }
.picker-item strong { font-size: 12px; display: block; }
.picker-item small { color: var(--muted); display: block; margin-top: 2px; }
.two-column-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.warning-note { color: #8a6420; background: var(--amber-soft); border: 1px solid #f1ddb0; border-radius: 9px; padding: 10px; font-size: 11px; line-height: 1.4; }
.metric-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin: 18px 0; }
.metric-card { background: #f6f8fb; border: 1px solid #e6ebf2; border-radius: 10px; padding: 11px; min-width: 0; }
.metric-card span { color: var(--muted); display: block; font-size: 11px; }
.metric-card strong { display: block; margin-top: 5px; font-size: 13px; overflow: hidden; text-overflow: ellipsis; }
.code-heading { display: flex; justify-content: space-between; align-items: center; margin: 20px 0 8px; }
.code-heading h3 { margin: 0; }
.copy-inline { padding: 6px 8px; border-color: var(--line); background: white; color: #59667a; font-size: 11px; }
.notes-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin-top: 20px; }
.notes-grid ul { color: #526076; padding-left: 19px; line-height: 1.5; }


.recommendation-panel { margin: 16px 0 0; border: 1px solid #dbe5f5; border-radius: 12px; background: #f8fbff; overflow: hidden; }
.recommendation-heading { display: flex; justify-content: space-between; gap: 12px; align-items: center; padding: 12px; border-bottom: 1px solid #e4ebf5; }
.recommendation-heading strong { display: block; font-size: 13px; }
.recommendation-heading small { display: block; color: var(--muted); margin-top: 3px; line-height: 1.35; }
.recommendation-list { display: grid; gap: 8px; padding: 9px; max-height: 270px; overflow-y: auto; }
.recommendation-card { border: 1px solid #e0e7f1; background: white; border-radius: 9px; padding: 10px; }
.recommendation-card-top { display: flex; justify-content: space-between; gap: 10px; align-items: flex-start; }
.recommendation-card-top > div { min-width: 0; }
.recommendation-card-top strong { display: block; overflow: hidden; text-overflow: ellipsis; }
.recommendation-card p { color: #69758a; font-size: 11px; line-height: 1.45; margin: 7px 0 0; }
.recommendation-card code { display: block; margin-top: 7px; padding: 6px 7px; border-radius: 6px; background: #f3f6fa; color: #44526a; font-size: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.confidence-badge, .mini-recommended-badge { display: inline-block; margin: 4px 0 0 7px; border-radius: 999px; padding: 3px 6px; font-size: 9px; font-style: normal; font-weight: 750; vertical-align: middle; }
.confidence-high { background: var(--green-soft); color: var(--green); }
.confidence-medium { background: var(--amber-soft); color: var(--amber); }
.confidence-low, .confidence-starter { background: #eef2f7; color: #69758a; }
.mini-recommended-badge { background: var(--accent-soft); color: var(--accent); margin-top: 0; }
.picker-item.recommended-source { background: #f7faff; }
.button-row { display: flex; gap: 7px; align-items: center; flex-wrap: wrap; justify-content: flex-end; }
.text-button { border: 0; background: transparent; color: var(--accent); font-size: 10px; padding: 3px 5px; }
.text-button:hover { text-decoration: underline; }

.column-dropdown { border: 1px solid #cfd8e6; border-radius: 10px; background: white; }
.column-dropdown[open] { border-color: #9bb8f6; box-shadow: 0 0 0 3px rgba(47,111,237,.09); }
.column-dropdown summary { list-style: none; cursor: pointer; display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 11px 12px; color: #3f4c62; font-weight: 650; }
.column-dropdown summary::-webkit-details-marker { display: none; }
.column-dropdown summary::after { content: '\25BE'; color: #7a879a; margin-left: auto; }
.column-dropdown[open] summary::after { content: '\25B4'; }
.selection-count { color: var(--accent); background: var(--accent-soft); border-radius: 999px; padding: 4px 8px; font-size: 10px; font-weight: 750; white-space: nowrap; }
.column-dropdown-panel { border-top: 1px solid var(--line); padding: 10px; }
.column-groups { max-height: 310px; overflow-y: auto; margin-top: 9px; display: grid; gap: 9px; }
.column-group { border: 1px solid #e4e9f0; border-radius: 9px; overflow: hidden; }
.column-group-heading { position: sticky; top: 0; z-index: 1; display: flex; justify-content: space-between; align-items: center; gap: 8px; background: #f4f7fb; border-bottom: 1px solid #e4e9f0; padding: 7px 9px; }
.column-group-heading strong { font-size: 11px; color: #44526a; }
.column-option { display: grid; grid-template-columns: auto 1fr; gap: 8px; align-items: center; padding: 7px 9px; border-bottom: 1px solid #f0f2f6; }
.column-option:last-child { border-bottom: 0; }
.column-option:hover { background: #fafcff; }
.column-option input { margin: 0; }
.column-option strong { display: block; font-size: 11px; }
.column-option small { display: block; color: #8993a4; font-size: 9px; margin-top: 1px; }
.selected-column-mappings { display: grid; gap: 6px; margin: 9px 0 0; }
.mapping-header, .mapping-row { display: grid; grid-template-columns: minmax(150px, 1fr) minmax(120px, .8fr) 34px; gap: 8px; align-items: center; }
.mapping-header { color: #7b8799; font-size: 10px; padding: 0 6px; }
.mapping-row { border: 1px solid #e6ebf2; border-radius: 8px; padding: 6px; background: #fbfcfe; }
.mapping-row code { font-size: 10px; color: #46546b; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.compact-input { padding: 7px 8px; min-width: 0; }
.remove-column { width: 30px; height: 30px; color: var(--red); }

.settings-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 20px; }
/* Board #27: two cards side by side left each label column the width of its longest word once the
   window was narrowed, so Safeguards read one word per line. One column well before that point. */
@media (max-width: 1200px) { .settings-grid { grid-template-columns: minmax(0, 1fr); } }
.settings-card { padding: 24px; }

/* Settings cards that fold to their heading (initCollapsibleCards in app.js, 24 September 2026).
   The heading's text sits inside a full-width button, so the whole heading row is the target and it
   is reachable from the keyboard. A folded card hides every child except the one holding the
   heading; nothing is removed or moved, so ids, listeners and typed values all survive a fold. */
.card-toggle { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; margin: 0; padding: 0; border: 0; background: none; color: inherit; font: inherit;
  text-align: left; cursor: pointer; }
.card-toggle:hover { color: var(--accent); }
.card-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 4px; }
.card-toggle-chevron { flex: none; font-size: 14px; color: var(--muted); transition: transform .15s ease; }
.settings-card.is-collapsed .card-toggle-chevron { transform: rotate(-90deg); }
.settings-card.is-collapsed { padding-block: 16px; align-self: start; }
.settings-card.is-collapsed > :not(.card-collapse-head) { display: none !important; }
/* In a provider card the heading shares a row with its status badge; the badge stays in view. */
.provider-head h2 { flex: 1; min-width: 0; }
@media (prefers-reduced-motion: reduce) { .card-toggle-chevron { transition: none; } }

/* Answer speed. Laid out as a column of full-width choices rather than a row: each option carries a
   sentence explaining when to pick it, and three of those side by side become unreadable columns. */
.effort-levels { display: flex; flex-direction: column; gap: 10px; margin-top: 14px; }
.effort-level { display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px;
  border: 1px solid var(--line); border-radius: var(--radius-sm); cursor: pointer; }
.effort-level:hover { border-color: var(--accent); }
/* Accent, not amber: amber is this stylesheet's warning colour, and a chosen setting is not one. */
.effort-level:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); }
.effort-level input { margin-top: 3px; }
.effort-level b { font-size: 14px; }
/* The measured cost of the choice, kept beside its name so the two are read together. */
.effort-seconds { color: var(--muted); font-size: 12px; margin-left: 8px; font-variant-numeric: tabular-nums; }
.effort-level .note { display: block; color: var(--muted); font-size: 12px; margin-top: 4px; line-height: 1.45; }
.full-span { grid-column: 1 / -1; }

/* The wrapper takes no layout of its own, so each provider card becomes a direct grid item and the
   two sit side by side exactly as the hand-written cards above them do. */
.provider-panels { display: contents; }
.provider-card.is-active { border-color: var(--accent, #2f6feb); box-shadow: 0 0 0 1px var(--accent, #2f6feb) inset; }
.provider-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
.provider-active-tag { font-size: 11px; font-weight: 650; letter-spacing: .03em; text-transform: uppercase; color: var(--green); white-space: nowrap; padding-top: 4px; }
.provider-active-tag.idle { color: var(--muted); }
.model-list-editor { margin-top: 14px; }
.model-list-editor summary { cursor: pointer; font-size: 12px; color: var(--muted); }
.model-list-editor textarea { width: 100%; min-height: 108px; margin-top: 10px; padding: 10px; border-radius: 9px; border: 1px solid #d6dde8; font-family: ui-monospace, Consolas, monospace; font-size: 12px; resize: vertical; box-sizing: border-box; }
.model-list-hint { color: var(--muted); font-size: 11px; margin: 8px 0 0; line-height: 1.5; }
.connection-result { margin-top: 14px; min-height: 20px; color: var(--muted); }
.connection-result.success { color: var(--green); }
.connection-result.error { color: var(--red); }
/* A change that was saved AND is worth a second thought -- amber rather than red, because red here
   has always meant "this did not happen" and a warning that looks like a failure gets read as one. */
.connection-result.warn { color: var(--amber); }

/* A provider shown but not yet selectable. Quietened rather than hidden: it is a planned addition,
   and a client asking about it should find it listed and labelled instead of absent. */
.provider-card.is-planned { opacity: .72; }
.provider-card.is-planned input,
.provider-card.is-planned select,
.provider-card.is-planned textarea,
.provider-card.is-planned button { cursor: not-allowed; }
.provider-active-tag.planned { background: var(--surface-soft); color: var(--muted); border-color: var(--line); }
.password-field { display: grid; grid-template-columns: 1fr auto; gap: 8px; }
/* .safeguard-grid and .step-number went with the four-step grid they styled. */


/* Casey. The launcher sits with the other two in the sidebar footer, so the sidebar has one
   convention for "this opens something" rather than a third look for the newest thing in it. */
.casey-launch-button { display: flex; align-items: center; gap: 9px; width: 100%; text-align: left;
  border: 1px solid #3f63a1; background: var(--navy-2); border-radius: 11px; padding: 9px 11px;
  color: white; font-family: inherit; cursor: pointer; transition: .15s ease; }
.casey-launch-button:hover { border-color: var(--accent); background: #27405f; }
.casey-launch-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.casey-launch-mark { flex: none; width: 22px; height: 22px; border-radius: 50%; background: var(--casey);
  color: white; font-size: 11px; font-weight: 700; display: flex; align-items: center; justify-content: center; }
.casey-launch-text { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; flex: 1; min-width: 0; }
.casey-launch-name { font-size: 13px; }
/* The shortcut, shown rather than discovered. The people who use this most will use it constantly. */
.casey-launch-hint { font-size: 10px; color: #8fa0bd; letter-spacing: .3px; }

/* Overlays from the right and does not push the page: whatever this was opened about must stay
   visible beside the answer. Same slide and timing as the history drawer, mirrored. */
/**
 * Above the modal scrim, at 120 against its 100.
 *
 * It sat at 88, which put it under every dialog in the product -- so the one place somebody most
 * obviously needs help, stopped mid-task by a box asking them a question, was the one place Casey
 * could not be reached. Worse, Ctrl+K still opened it: invisible behind the scrim, so the shortcut
 * looked dead while actually toggling.
 *
 * This does partly retract what a backdrop promises, which is that nothing else is available. That
 * is the right trade here: Casey is help with the task in the box, not a rival to it, and help
 * should never be behind the thing you need help with. Every other control in the dialog stays as
 * modal as it was.
 */
.casey-panel {
  position: fixed; z-index: 120; inset: 0 0 0 auto; width: min(400px, 100vw);
  background: white; border-left: 2px solid var(--accent); box-shadow: -20px 0 55px rgba(12,23,39,.18);
  display: flex; flex-direction: column;
  transform: translateX(108%); visibility: hidden; transition: transform .22s ease, visibility 0s .22s;
}
.casey-panel.open { transform: translateX(0); visibility: visible; transition: transform .22s ease, visibility 0s; }
.casey-header { display: flex; align-items: center; gap: 10px; padding: 14px 16px; background: var(--navy); }
.casey-header-text { flex: 1; min-width: 0; }
.casey-header h2 { margin: 0; font-size: 15px; color: white; }
.casey-header p { margin: 2px 0 0; font-size: 11px; color: #8fa0bd; }
.casey-mark { flex: none; width: 26px; height: 26px; border-radius: 50%; background: var(--casey);
  color: white; font-size: 12px; font-weight: 700; display: flex; align-items: center; justify-content: center; }
.casey-close { border: 0; background: transparent; color: #8fa0bd; font-size: 20px; line-height: 1;
  padding: 2px 6px; cursor: pointer; font-family: inherit; }
.casey-close:hover { color: white; }
/* Quieter than Close, and beside it. Clearing is the rarer act and the one with a consequence, so
   it does not compete with the control people reach for constantly. */
.casey-clear { border: 0; background: transparent; color: #8fa0bd; font-size: 12px; line-height: 1;
  cursor: pointer; font-family: inherit; padding: 4px 8px; border-radius: 6px; }
.casey-clear:hover { color: white; background: rgba(255,255,255,.1); }

/* What Casey can see. Quiet, permanent, and it changes with the screen. */
.casey-context { padding: 7px 16px; background: var(--surface-soft); border-bottom: 1px solid var(--line);
  color: var(--muted); font-size: 11px; line-height: 1.5; }

.casey-thread { flex: 1; min-height: 0; overflow-y: auto; padding: 14px 16px;
  display: flex; flex-direction: column; gap: 10px; }
.casey-turn { border-radius: 12px; padding: 9px 11px; font-size: 13px; line-height: 1.55; max-width: 94%; white-space: pre-wrap; }
.casey-turn.is-asked { background: var(--accent-soft); color: var(--navy); align-self: flex-end; }
.casey-turn.is-said { background: var(--surface-soft); color: var(--ink); }
.casey-turn.is-failed { background: var(--red-soft); color: var(--red); }
/* The briefing a "Help me resolve this" opens with, set apart from the conversation: it is what was
   sent on the reader's behalf, and they should be able to see that it is not something they typed. */
.casey-turn.is-brief { background: white; border: 1px solid var(--line); border-left: 3px solid var(--amber);
  border-radius: 0; color: var(--muted); font-size: 12px; align-self: stretch; max-width: 100%; }
/* A wording Casey has offered, set apart from the answer it came in: it is the one thing in this
   panel that can leave it, so it does not look like more conversation. */
.casey-turn-group { display: flex; flex-direction: column; gap: 6px; align-self: stretch; max-width: 100%; }
.casey-proposal { background: white; border: 1px solid var(--green); border-left: 3px solid var(--green);
  border-radius: 0 9px 9px 0; padding: 10px 12px; }
.casey-proposal-label { font-size: 10.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--green); margin-bottom: 5px; }
.casey-proposal-text { margin: 0 0 9px; font-size: 13px; line-height: 1.55; color: var(--ink); }
.casey-proposal-actions { display: flex; gap: 8px; }
.casey-proposal-note { margin: 8px 0 0; font-size: 11.5px; line-height: 1.5; color: var(--muted); }
/* Drafting declined: the reason, and the two doors still open. */
.declined-reason { margin: 0 0 8px; }
.declined-doors { display: flex; gap: 8px; flex-wrap: wrap; }
.declined-note { margin: 8px 0 0; font-size: 12px; color: var(--muted); }
/* What the query shows, when a decline cited a rule. Set apart from the model's reason, because it
   is a measurement rather than a judgement. */
.declined-finding { margin: 8px 0 0; padding: 8px 10px; background: var(--amber-soft);
  border-left: 3px solid var(--amber); color: var(--ink); font-size: 12.5px; line-height: 1.5; }
.casey-empty { color: var(--muted); font-size: 12px; line-height: 1.6; }
.casey-empty p { margin: 0 0 10px; }
.casey-empty-heading { color: var(--navy); font-weight: 600; margin: 14px 0 6px !important; }
/* The assistant's own question bank, as starting points. Stacked rather than wrapped into a cloud:
   these are whole sentences, and a chip cloud of sentences is unreadable at this width. */
.casey-starters { display: flex; flex-direction: column; gap: 6px; }
.casey-starter { text-align: left; background: var(--surface-soft); color: var(--navy);
  border: 1px solid var(--line); border-radius: 9px; padding: 8px 10px; font-family: inherit;
  font-size: 12px; line-height: 1.45; cursor: pointer; }
.casey-starter:hover { border-color: var(--accent); background: var(--accent-soft); color: #2b5cbf; }

.casey-composer { border-top: 1px solid var(--line); padding: 11px 16px 14px; }
.casey-composer textarea { width: 100%; resize: none; border: 1px solid var(--line); border-radius: 10px;
  padding: 9px 11px; font-family: inherit; font-size: 13px; color: var(--ink); }
.casey-composer textarea:focus-visible { outline: 2px solid var(--accent); outline-offset: -1px; border-color: var(--accent); }
.casey-composer-footer { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 8px; }
.casey-composer-hint { color: var(--muted); font-size: 11px; }
.casey-send { padding: 7px 18px; font-size: 13px; }

/**
 * The dialog makes room rather than being covered.
 *
 * A modal centres on the whole viewport, so a 400px panel on the right lands on top of it. Reserving
 * the panel's width as right padding re-centres the card on what is left, and capping the card's
 * width stops the wide ones -- the table viewer, the spot-check -- from growing back under it.
 *
 * Only where there is room to give. Below 980px the panel is most of the screen anyway, so the split
 * would leave two unusable halves instead of one usable one; there it simply overlays.
 */
@media (min-width: 980px) {
  body.casey-open .modal-backdrop { padding-right: calc(min(400px, 100vw) + 24px); }
  body.casey-open .modal-card { max-width: calc(100vw - 448px); }
  body.casey-open .modal-card.modal-card-wide { width: min(1240px, calc(100vw - 448px)); }
}

/* Help from inside the dialog, and it earns its place only where the task is genuinely hard: what a
   measurement claims, why a question was refused, what a drafted rule will do, how to judge an
   answer. Never on a name box, a confirmation, or the key prompt. */
.modal-casey { margin-right: auto; background: transparent; color: #2b5cbf;
  border: 1px solid var(--line); border-radius: 999px; padding: 6px 13px; font-size: 12px;
  font-family: inherit; cursor: pointer; display: inline-flex; align-items: center; gap: 7px; }
.modal-casey:hover { border-color: var(--accent); background: var(--accent-soft); }
.modal-casey-mark { width: 17px; height: 17px; border-radius: 50%; background: var(--casey);
  color: white; font-size: 9px; font-weight: 700; display: flex; align-items: center; justify-content: center; }

/* What the firm's own view already says. Green because it is corroboration rather than a warning:
   the item is easier than it looks, which is the opposite of what an amber note would imply. */
.reference-row-confirms { background: var(--green-soft); border-left: 2px solid var(--green);
  border-radius: 0 6px 6px 0; padding: 7px 9px; margin-top: 4px; color: var(--ink);
  font-size: 11.5px; line-height: 1.55; }
/* The option that view agrees with. Marked, never pre-pressed: a screen arriving with an answer
   already chosen would collect agreement nobody gave, and the name on it would be a fiction. */
.reference-choice.is-confirmed { background: var(--green-soft); color: var(--green); border-color: #bfe6d6; }
.reference-choice.is-confirmed:hover { border-color: var(--green); }
.reference-choice.is-confirmed::before { content: '✓ '; }

/* The wording the assistant is actually given, under the reading it belongs to. Secondary to the
   count, which is what the choice turns on, but present so the written door and the pressed door
   can be seen to offer the same words. */
.reading-sentence { display: block; margin-top: 4px; font-size: 12px; line-height: 1.35; color: var(--muted); white-space: normal; }
.reference-choice.is-confirmed .reading-sentence { color: var(--green); }

/* The act that unlocks recording, sized like it. It was a quiet secondary button beside the box and
   people walked past it, which is how an unread sentence reached everybody's answers. */
.resolve-validate { align-self: flex-start; padding: 10px 20px; font-size: 14px; }
/* Disabled Record is disabled, not hidden — a control that vanishes is one somebody hunts for. */
.resolve-actions .primary-button:disabled { opacity: .45; cursor: not-allowed; }

/* Room for four readings and their counts above the box. At 540px the list scrolled, which put the
   thing being described off screen while somebody wrote about it. */
.modal-card.modal-card-correct { width: min(720px, 94vw); max-width: none; }

/* A textarea in a flex column shrinks to nothing unless told otherwise, which is why the box people
   write their definition in arrived one line tall. */
.resolve-body textarea, .modal-card-correct textarea { flex: none; min-height: 104px; }

/* The guided flow. Wider than a confirmation and narrower than the table viewer: it holds a
   paragraph, three readings and a writing box, and none of those want a 1240px line length. */
.modal-card.modal-card-resolve { width: min(680px, 94vw); max-width: none; text-align: left;
  transition: width .18s ease; }
/* Opened out once a check has produced something, and only then. Tom, 23 September 2026: at 680px
   single-column the preview was appended below the readings and the writing box inside 56vh of
   scroll, so the half of it that mattered was never seen. The empty state keeps its old width --
   a dialog that starts this wide with nothing in the second column is just a wall. */
.modal-card.modal-card-resolve.has-result { width: min(1100px, 95vw); }
.resolve-split { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0; }
.has-result .resolve-split { grid-template-columns: minmax(0, 360px) minmax(0, 1fr); gap: 20px;
  align-items: start; }
/* Each column carries its own scroll so the preview can never push the writing box out of reach --
   the whole point of the dialog is editing the sentence while looking at what it did. */
.resolve-split-main { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.has-result .resolve-split-main { max-height: 72vh; overflow-y: auto; padding-right: 4px; }
.has-result .resolve-body { max-height: none; overflow: visible; }
/* Below this the two columns have nothing useful to say side by side, so they stack and the card
   goes back to one scroll. */
@media (max-width: 900px) {
  .has-result .resolve-split { grid-template-columns: minmax(0, 1fr); gap: 14px; }
  .has-result .resolve-split-main { max-height: none; overflow: visible; }
  .modal-card.modal-card-resolve.has-result { width: min(680px, 94vw); }
  .has-result .resolve-body { max-height: 72vh; overflow-y: auto; }
  .has-result .resolve-split-result .write-result { border-left: 0; padding-left: 0;
    border-top: 1px solid var(--line); padding-top: 12px; max-height: none; }
}
.resolve-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; }
.resolve-head h2 { margin: 0 0 3px; font-size: 19px; }

/* Four steps, shown as progress rather than as navigation. They are not clickable: skipping the
   explanation to reach the writing box is exactly the behaviour this replaced. */
.resolve-steps { display: flex; gap: 6px; list-style: none; margin: 14px 0 0; padding: 0; }
.resolve-step { flex: 1; font-size: 10.5px; color: var(--muted); text-transform: uppercase;
  letter-spacing: .05em; border-top: 3px solid var(--line); padding-top: 6px; }
.resolve-step.is-done { border-top-color: var(--green); color: var(--green); }
.resolve-step.is-current { border-top-color: var(--accent); color: var(--accent); font-weight: 700; }

.resolve-body { display: flex; flex-direction: column; gap: 10px; margin-top: 16px;
  max-height: 56vh; overflow-y: auto; }
.resolve-lead { margin: 0; font-size: 14px; line-height: 1.55; color: var(--ink); }
.resolve-detail { margin: 0; font-size: 12.5px; line-height: 1.55; color: var(--muted); }
.resolve-heading { font-size: 10px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted); margin-top: 4px; }
.resolve-ask { align-self: flex-start; background: transparent; color: #2b5cbf; border: 1px solid var(--line);
  border-radius: 999px; padding: 6px 13px; font-size: 12px; font-family: inherit; cursor: pointer; }
.resolve-ask:hover { border-color: var(--accent); background: var(--accent-soft); }

/* The one question the reader can actually answer, with the consequence of each written under it. */
.resolve-choices { display: flex; flex-direction: column; gap: 8px; }
.resolve-choice { text-align: left; background: var(--surface); border: 1px solid var(--line);
  border-radius: 10px; padding: 11px 13px; font-family: inherit; cursor: pointer;
  display: flex; flex-direction: column; gap: 3px; }
.resolve-choice:hover { border-color: var(--accent); background: var(--accent-soft); }
.resolve-choice strong { font-size: 13.5px; color: var(--navy); }
.resolve-choice span { font-size: 12px; color: var(--muted); line-height: 1.5; }
.resolve-choice.is-primary { border-color: #adc2ef; }
.resolve-choice.is-quiet strong { color: var(--muted); font-weight: 600; }
.resolve-actions { justify-content: space-between; }

/* The arbiter's verdict on a draft rule. Green for agreement and amber for a split — never red,
   because a split is not an error: it is the check doing its job while the rule is still editable. */
.resolve-arbiter { display: flex; flex-direction: column; gap: 4px; border-radius: 0 8px 8px 0;
  border: 1px solid var(--line); border-left: 3px solid var(--line); padding: 9px 11px; }
.resolve-arbiter strong { font-size: 13px; color: var(--navy); }
.resolve-arbiter span { font-size: 12px; line-height: 1.55; color: var(--muted); }
.resolve-arbiter.is-agreed { background: var(--green-soft); border-color: #bfe6d6; border-left-color: var(--green); }
.resolve-arbiter.is-agreed strong { color: var(--green); }
.resolve-arbiter.is-split { background: var(--amber-soft); border-color: #f0dcad; border-left-color: var(--amber); }
.resolve-arbiter.is-split strong { color: var(--amber); }
.resolve-arbiter.is-unknown { background: var(--surface-soft); }

/* The readings being compared, shown rather than described. The one that produced the answer on
   screen is marked, because "which of these am I looking at" is the first question. */
.signal-readings { display: flex; flex-direction: column; gap: 5px; margin: 7px 0 2px; }
.signal-reading { background: var(--surface); border: 1px solid var(--line); border-left: 3px solid var(--line);
  border-radius: 0 6px 6px 0; padding: 6px 9px; display: flex; flex-direction: column; gap: 2px; }
.signal-reading.is-current { border-left-color: var(--accent); background: var(--accent-soft); }
.signal-reading strong { font-size: 11.5px; color: var(--navy); }
.signal-reading span { font-size: 11.5px; color: var(--muted); line-height: 1.5; }


/* "Guide me through this", on an open worklist row. Quiet on purpose: the answer buttons beside it
   are the work, and this is the step before it for somebody who cannot yet choose. */
.reference-guide { align-self: flex-start; margin-top: 5px; background: transparent; color: var(--muted);
  border: 0; padding: 0; font-family: inherit; font-size: 11.5px; cursor: pointer; text-decoration: underline;
  text-underline-offset: 2px; }
.reference-guide:hover { color: #2b5cbf; }


.drawer-backdrop { position: fixed; inset: 0; z-index: 78; background: rgba(11,20,34,.34); backdrop-filter: blur(2px); }
.chat-history-drawer {
  position: fixed; z-index: 90; inset: 0 auto 0 248px; width: min(370px, calc(100vw - 248px));
  background: white; border-right: 1px solid var(--line); box-shadow: 20px 0 55px rgba(12,23,39,.2);
  padding: 24px; display: flex; flex-direction: column; gap: 16px;
  transform: translateX(-108%); visibility: hidden; transition: transform .22s ease, visibility 0s .22s;
}
.chat-history-drawer.open { transform: translateX(0); visibility: visible; transition: transform .22s ease, visibility 0s; }
.history-drawer-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 15px; padding-bottom: 14px; border-bottom: 1px solid var(--line); }
.history-drawer-header h2 { margin: 8px 0 4px; font-size: 21px; }
.history-drawer-header p { margin: 0; color: var(--muted); font-size: 12px; }
.history-list-heading { display: flex; align-items: center; justify-content: space-between; gap: 12px; color: #526077; font-size: 12px; font-weight: 750; text-transform: uppercase; letter-spacing: .45px; }
.text-button { border: 0; background: transparent; color: var(--accent); padding: 4px; font-size: 11px; font-weight: 700; text-transform: none; letter-spacing: 0; }
.text-button:hover { color: var(--accent-dark); text-decoration: underline; }
.chat-history-list { flex: 1; min-height: 0; overflow-y: auto; display: grid; align-content: start; gap: 8px; padding-right: 3px; }
.history-empty { border: 1px dashed #cad4e1; border-radius: 12px; padding: 22px 16px; text-align: center; color: var(--muted); font-size: 12px; line-height: 1.5; }
.history-item { display: grid; grid-template-columns: minmax(0,1fr) 34px; gap: 6px; align-items: stretch; }
.history-open-button { min-width: 0; border: 1px solid var(--line); background: #fbfcfe; border-radius: 11px; padding: 11px 12px; text-align: left; color: var(--ink); transition: .15s ease; }
.history-open-button:hover { border-color: #adc2ef; background: var(--accent-soft); }
.history-item.active .history-open-button { border-color: #8cacfa; background: var(--accent-soft); box-shadow: inset 3px 0 0 var(--accent); }
.history-title { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; font-weight: 750; }
.history-meta { display: block; margin-top: 5px; color: var(--muted); font-size: 10px; }
.history-delete-button { border: 1px solid transparent; border-radius: 9px; background: transparent; color: #8b96a8; font-size: 17px; }
.history-delete-button:hover { color: var(--red); background: var(--red-soft); border-color: #f5caca; }
.history-storage-note { margin: 0; padding-top: 12px; border-top: 1px solid var(--line); color: var(--muted); font-size: 10px; line-height: 1.45; }

.modal-backdrop { position: fixed; inset: 0; background: rgba(11,20,34,.56); z-index: 100; display: grid; place-items: center; padding: 20px; backdrop-filter: blur(3px); }
/* The card scrolls rather than the page behind it. Without a ceiling a modal that grows -- the rule
   preview gains two result tables when it runs -- extends past the viewport with no way to reach the
   rest of it, buttons included. The 40px matches the backdrop's padding above and below. */
.modal-card { width: min(540px, 100%); background: white; border-radius: 18px; box-shadow: 0 30px 80px rgba(12,23,39,.3); padding: 26px; max-height: calc(100vh - 40px); overflow-y: auto; }

/* Kept in view while the content above it scrolls, so "Accept" and "Discard" are always one click
   away rather than at the end of a long scroll. The negative offsets pull it into the card's own
   padding so it sits flush against the bottom edge instead of floating above a white gap. */
.modal-card > .modal-actions { position: sticky; bottom: -26px; background: white; padding: 12px 0; margin-bottom: -26px; }
.modal-icon { width: 45px; height: 45px; display: grid; place-items: center; border-radius: 13px; background: var(--accent-soft); color: var(--accent); font-size: 22px; font-weight: 800; }
.modal-card h2 { margin: 15px 0 5px; }
.modal-card > p { color: var(--muted); line-height: 1.45; }
.token-summary { display: grid; grid-template-columns: 1fr 1fr; border: 1px solid var(--line); border-radius: 12px; overflow: hidden; margin: 18px 0 12px; }
.token-summary > div { padding: 14px; background: #f8fafc; }
.token-summary > div:first-child { border-right: 1px solid var(--line); }
.token-summary .total { grid-column: 1 / -1; border-top: 1px solid var(--line); background: white; }
.token-summary span { color: var(--muted); display: block; font-size: 11px; }
.token-summary strong { display: block; font-size: 20px; margin-top: 4px; }
.risk-notice { padding: 10px 12px; border-radius: 9px; font-size: 12px; line-height: 1.4; }
.risk-notice.low { background: var(--green-soft); color: var(--green); }
.risk-notice.medium { background: var(--amber-soft); color: var(--amber); }
.risk-notice.high { background: var(--red-soft); color: var(--red); }
.modal-card details { margin-top: 12px; color: #58657a; }
.modal-card summary { cursor: pointer; font-weight: 650; font-size: 12px; }
.breakdown-list { display: grid; gap: 6px; margin-top: 10px; }
.breakdown-item { display: flex; justify-content: space-between; gap: 12px; padding: 6px 0; border-bottom: 1px solid #edf0f5; font-size: 12px; }
.modal-note { font-size: 11px; }
/* The break between what the business knows and what the database knows, on the term form. A rule
   with a caption rather than a heading: it separates two groups of fields, it is not a new section
   of the form, and anything heavier read as "you are now somewhere else". */
.term-divider { display: flex; align-items: center; gap: 10px; margin: 22px 0 0; }
.term-divider::before, .term-divider::after { content: ""; flex: 1; height: 1px; background: #e2e7ef; }
.term-divider-label { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
                      color: var(--muted); white-space: nowrap; }
.term-divider-note { margin: 8px 0 4px; font-size: 12px; color: var(--muted); }

/* The two-line answer to "which of these am I writing?", at the top of both tabs. Boxed because it
   is a reference somebody returns to, not an introduction they read once and scroll past. */
.term-rule-key { border: 1px solid #dbe3ef; border-left: 3px solid var(--accent-dark); border-radius: 8px;
                 background: #f7f9fc; padding: 12px 14px; margin: 0 0 16px; }
.term-rule-key p { margin: 0 0 6px; font-size: 13px; }
.term-rule-key p:last-child { margin-bottom: 0; }
.term-rule-key em { color: var(--muted); }

/* The single-rule and single-term entry forms. Boxed off from the list they write into, or the
   draft box reads as the first row of the list. */
.term-form, .rule-form { border: 1px solid #e2e7ef; border-radius: 8px; padding: 14px; margin-bottom: 18px; }
/* The daily copies: one row per day, the day first, its details quiet, the action at the end. */
.daily-export-list { display: flex; flex-direction: column; gap: 6px; margin: 8px 0 4px; }
.daily-export-row { display: flex; align-items: center; gap: 12px; padding: 8px 12px; border: 1px solid var(--line); border-radius: 8px; background: white; }
.daily-export-day { font-size: 13px; color: var(--navy); font-weight: 600; min-width: 190px; }
.daily-export-meta { flex: 1; font-size: 12px; color: var(--muted); }
/* Add a rule stands out from the list under it (Tom, 24 Sep 2026): a firmer edge and a tint. */
.rule-form { border-color: #a9b6ca; background: #f7f9fc; }
.rules-cost { white-space: nowrap; overflow-x: auto; }

/* The offer to move a rule that is really a definition. Quiet: it is a suggestion attached to
   something already valid, and anything that looked like an error would say the rule is wrong. */
.rule-nudge { display: flex; gap: 10px; align-items: flex-start; flex-wrap: wrap; margin-top: 8px;
              padding-top: 8px; border-top: 1px dashed #dfe5ee; font-size: 12px; color: var(--muted); }

.rules-bulk { margin: 18px 0 4px; border: 1px solid #e2e7ef; border-radius: 8px; padding: 10px 14px; }
.rules-bulk > summary { cursor: pointer; font-weight: 650; font-size: 12px; color: var(--accent-dark); }
.rules-bulk-body { padding-top: 10px; }
.modal-actions { display: flex; justify-content: flex-end; gap: 9px; margin-top: 20px; }
.toast { position: fixed; right: 24px; bottom: 24px; z-index: 200; background: #14233b; color: white; border-radius: 10px; padding: 11px 14px; box-shadow: 0 12px 30px rgba(10,20,35,.2); }

@media (max-width: 1180px) {
  .chat-layout.safeguards-open { grid-template-columns: minmax(0, 1fr) 300px; }
  .safeguard-panel { grid-template-columns: 56px 244px; }
  .safeguard-toggle { width: 56px; }
  .safeguard-content { width: 244px; padding-left: 16px; padding-right: 16px; }
  .designer-layout { grid-template-columns: 1fr; }
  .designer-source-grid { grid-template-columns: 1fr; }
  .recommendation-list { max-height: 350px; }
  .designer-form, .designer-output { min-height: auto; }
}
@media (max-width: 900px) {
  .app-shell { display: block; }
  .sidebar { position: static; width: 100%; height: auto; flex-direction: row; align-items: center; padding: 12px 16px; }
  .brand { padding: 0; margin-right: 20px; }
  .brand-subtitle, .sidebar-status { display: none; }
  .sidebar-lower { margin: 0 0 0 auto; }
  /* Board #27: New chat, Ask Casey and Chat history stacked full-width here, a column taller than the
     navigation beside it. In a row they sit in the bar instead of hanging below it. */
  .sidebar-lower { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; justify-content: flex-end; }
  .sidebar-lower .new-chat-button, .sidebar-lower .casey-launch-button { width: auto; margin: 0; white-space: nowrap; }
  .history-launch-button { width: auto; grid-template-columns: 18px auto auto; white-space: nowrap; }
  .chat-history-drawer { left: 0; width: min(370px, 100vw); }
  .nav-list { display: flex; overflow-x: auto; align-items: center; }
  .nav-group { display: flex; align-items: center; gap: 4px; }
  .nav-group-toggle { width: auto; white-space: nowrap; }
  .nav-submenu { display: flex; margin: 0; padding: 0; border: 0; gap: 4px; }
  .nav-submenu.collapsed { display: none; }
  .nav-item { white-space: nowrap; }
  .main-area { padding: 0 16px 24px; }
  /* The topbar grows to fit its content here, so anything pinned below it follows the minimum
     rather than the fixed height. Set on :root and not on .topbar, because the tab strips read the
     variable and are not inside it. */
  :root { --topbar-h: 88px; }
  .topbar { height: auto; min-height: var(--topbar-h); }
  .schema-layout, .settings-grid { grid-template-columns: 1fr; }
  .schema-list, .schema-detail { min-height: auto; }
  .object-list { max-height: 330px; }
  .full-span { grid-column: auto; }
}
@media (max-width: 620px) {
  .brand-title { display: none; }
  .nav-icon { display: none; }
  .nav-item { padding: 9px; font-size: 12px; }
  .topbar-actions { display: none; }
  .example-grid, .two-column-fields, .notes-grid, .metric-grid { grid-template-columns: 1fr; }
  .chat-layout { grid-template-columns: minmax(0, 1fr) 52px; gap: 10px; }
  .chat-layout.safeguards-open { grid-template-columns: minmax(0, 1fr) min(300px, 52vw); }
  .safeguard-panel { grid-template-columns: 52px 248px; }
  .safeguard-toggle { width: 52px; }
  .safeguard-content { width: 248px; padding-left: 14px; padding-right: 14px; }
  .message.user .bubble { max-width: 90%; }
  .assistant-body, .answer-meta, .disclosure { margin-left: 0; }
  .column-row { grid-template-columns: 1fr; }
  .mapping-header { display: none; }
  .mapping-row { grid-template-columns: 1fr 1fr 34px; }
  .column-flags { text-align: left; }
  .history-launch-button > span:nth-child(2) { display: none; }
  .history-count { display: none; }
}
@media (max-width: 520px) {
  .chat-layout { display: block; position: relative; }
  .chat-main { margin-right: 48px; }
  .safeguard-panel { position: absolute; top: 0; right: 0; z-index: 9; width: 52px; box-shadow: var(--shadow); }
  .chat-layout.safeguards-open .safeguard-panel { width: min(300px, calc(100vw - 32px)); }
  .chat-layout.safeguards-open .chat-main { margin-right: 0; }
}

/* --- Clarification choices ------------------------------------------------- */

/* Flat, full-width choices rather than pills: each one is a whole question, so it has to read as a
   line of text the user can scan, not as a tag. */
.clarify-options { display: grid; gap: 8px; margin: 14px 0 8px 40px; }
.clarify-option {
  display: block;
  width: 100%;
  text-align: left;
  padding: 11px 14px;
  font: inherit;
  font-size: 13.5px;
  line-height: 1.45;
  color: var(--ink);
  background: var(--surface-soft);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background .14s ease, border-color .14s ease;
}
.clarify-option:hover { background: var(--accent-soft); border-color: var(--accent); }
.clarify-option:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.clarify-hint { font-size: 11.5px; color: var(--muted); margin: 0 0 4px 40px; }

/* Refinements follow a completed answer, so they are quieter than a blocking clarification: they
   are an offer, not a question the user has to deal with. */
/* Tightened vertically. Three of these follow every answer, so at the previous height they were
   taller than most of the answers they followed and pushed the numbers off the screen. The text size
   is unchanged -- these are questions somebody reads before clicking, and shrinking the words to
   save height would trade the wrong thing. The room comes from the padding, the leading and the gap,
   which is about a quarter off the stack. */
.refine-options { margin: 10px 0 0 40px; gap: 5px; }
.refine-options .clarify-option {
  background: #f2f6fd;
  border-color: #dbe6f7;
  border-left-color: #9db8e4;
  font-size: 12.5px;
  line-height: 1.3;
  padding: 5px 11px;
}
.refine-options .clarify-option:hover {
  background: var(--accent-soft);
  border-color: #b9cdf0;
  border-left-color: var(--accent);
}

/* --- New chat ------------------------------------------------------------- */

.new-chat-button {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 11px 12px;
  margin-bottom: 8px;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(123,164,255,.32);
  background: rgba(85,139,255,.16);
  color: white;
  font: inherit;
  font-size: 13px;
  font-weight: 650;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease;
}
.new-chat-button:hover { background: rgba(85,139,255,.28); border-color: rgba(123,164,255,.5); }
.new-chat-button:focus-visible { outline: 2px solid #7ba4ff; outline-offset: 2px; }
.new-chat-icon { font-size: 15px; line-height: 1; width: 18px; text-align: center; }

/* --- Longer starter questions --------------------------------------------- */

/* Ten full-sentence prompts, five across in two rows. The type is stepped down so a whole question
   fits a narrow column without the block growing tall enough to push the composer off screen. */
.welcome-panel { max-width: 100%; margin: 26px auto 22px; }
.example-grid { margin-top: 20px; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 8px; }
.example-chip {
  white-space: normal;
  text-align: left;
  font-size: 11.5px;
  line-height: 1.35;
  padding: 10px 11px;
  min-height: 0;
  height: 100%;
  border-radius: 10px;
}
@media (max-width: 1500px) { .example-chip { font-size: 11px; padding: 9px 10px; } }
@media (max-width: 1180px) { .example-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 760px)  { .example-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* --- Keep the composer on screen ------------------------------------------ */

/* min-height: 680px made the card taller than the visible area on a 768px-tall laptop, so the
   Estimate & Run button sat below the fold on first load. Sizing to the viewport instead pins the
   composer to the bottom of the card and lets the message list scroll inside it. */
.chat-main { min-height: 0; height: calc(100vh - 132px); }
@media (max-height: 700px) { .chat-main { height: calc(100vh - 110px); } }

/* --- Chat is now full width; safeguards moved into Settings ---------------- */

.chat-layout,
.chat-layout.safeguards-open,
.chat-layout.safeguards-collapsed { grid-template-columns: minmax(0, 1fr); }
.safeguard-panel, .safeguard-toggle, .safeguard-content { display: none !important; }

/* --- Administrator lock ---------------------------------------------------- */

.nav-lock { font-size: 11px; opacity: .75; line-height: 1; }
#adminGate .modal-card { max-width: 420px; }
#adminGate .text-input { margin-top: 4px; letter-spacing: 1px; }
#adminGate .connection-result:empty { display: none; }

.version-row { color: #8c9ab2; font-size: 10.5px; letter-spacing: .2px; padding-left: 16px; }

/* --- Partner mark ---------------------------------------------------------- */

.partner-mark {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid rgba(255,255,255,.08);
  display: grid;
  gap: 5px;
  justify-items: start;
}
.partner-mark-lead {
  font-size: 9px;
  letter-spacing: .4px;
  text-transform: uppercase;
  color: #9fb0c8;
  opacity: .8;
}
/* The supplied artwork is very wide (roughly 2:1), so width is what needs constraining. */
.partner-logo {
  width: 100%;
  max-width: 150px;
  height: auto;
  display: block;
  opacity: .85;
}
.partner-mark-name { font-size: 12px; font-weight: 700; color: #d7e2f2; letter-spacing: .2px; }

/* --- Sensitive-column policy ---------------------------------------------- */

.classify-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  margin: 0 0 18px;
  padding: 12px 16px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--amber);
  border-radius: var(--radius-sm);
  background: var(--amber-soft);
}
.classify-bar.is-locked { border-left-color: var(--green); background: var(--green-soft); }
.classify-bar-text strong { display: block; font-size: 13px; }
.classify-bar-text small { display: block; color: var(--muted); margin-top: 3px; font-size: 11px; line-height: 1.4; }

.column-row.policy-row {
  display: grid;
  /* tick · name · type · flags · restriction tier · badge */
  grid-template-columns: 22px minmax(0, 1.3fr) minmax(0, .9fr) minmax(0, .9fr) auto auto;
  align-items: center;
  gap: 10px;
}
.column-row.policy-row.is-blocked { background: var(--red-soft); }
.column-row.policy-row.is-blocked strong { text-decoration: line-through; opacity: .7; }
.policy-tick { width: 15px; height: 15px; accent-color: var(--red); cursor: pointer; }
.policy-tick:disabled { cursor: not-allowed; opacity: .55; }

.sensitive-badge {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .3px;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 999px;
  white-space: nowrap;
}
.sensitive-badge.blocked { background: var(--red); color: white; }

  display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 10px; padding: 9px 12px; border-radius: var(--radius-sm);
  border: 1px solid #e6d8bd; background: #fdf7ea;
}

/* Request trace */
.starter-input { font-family: inherit; line-height: 1.6; resize: vertical; }
.trace-stats { display: flex; gap: 20px; flex-wrap: wrap; margin: 16px 0 4px; font-size: 12px; color: var(--muted); }
.trace-stats strong { display: block; color: var(--ink, #1d2b40); font-size: 15px; font-weight: 650; }
.trace-stats .is-full { color: var(--red); }
.trace-output {
  margin-top: 16px; max-height: 60vh; overflow: auto; padding: 14px;
  background: #101725; color: #d7e0ee; border-radius: var(--radius-sm);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11px; line-height: 1.5; white-space: pre-wrap; word-break: break-word;
}
.sensitive-badge.suggested { background: var(--amber-soft); color: var(--amber); border: 1px solid var(--amber); }

/* Column notes.
   A distinct accent from the amber policy bar: blocking a column and explaining one are unrelated
   decisions, and colouring them alike would imply otherwise. */
.annotation-bar { border-left-color: var(--accent, #2f6feb); background: #eef4ff; }
.annotation-bar.is-clear { border-left-color: var(--green); background: var(--green-soft); }
.annotation-bar.is-filtering { border-left-color: #6b3fd4; background: #f1ecfe; }

/* The note sits on its own line beneath the column it describes, spanning the whole row -- a sixth
   grid column would leave it too narrow to type a sentence into. */
.column-note { grid-column: 1 / -1; display: grid; grid-template-columns: 1fr auto; gap: 8px; align-items: center; }
.column-note input {
  width: 100%; padding: 7px 9px; border: 1px solid #dfe5ee; border-radius: 7px;
  font-size: 12px; background: white; box-sizing: border-box;
}
.column-note input:focus { outline: none; border-color: var(--accent, #2f6feb); box-shadow: 0 0 0 3px rgba(47,111,235,.12); }
.column-note input.has-note { border-color: var(--green); background: #f6fdf8; }
.column-note-why { color: var(--muted); font-size: 11px; max-width: 46%; text-align: right; line-height: 1.35; }

.note-badge {
  font-size: 10px; font-weight: 700; letter-spacing: .3px; text-transform: uppercase;
  padding: 3px 8px; border-radius: 999px; white-space: nowrap;
}
.note-badge.high { background: #6b3fd4; color: white; }
.note-badge.medium { background: #f1ecfe; color: #5a32b8; border: 1px solid #c9b6f2; }
.note-badge.done { background: var(--green-soft); color: var(--green); border: 1px solid var(--green); }

/* Review mode: hide everything already understood so the reviewer sees only outstanding work. */
.column-row.is-hidden-by-filter { display: none; }

@media (max-width: 900px) {
  .column-row.policy-row { grid-template-columns: 22px minmax(0, 1fr) auto; }
  .column-row.policy-row .column-flags, .column-row.policy-row .column-type { display: none; }
  .tier-select { grid-column: 2 / -1; max-width: none; }
  .column-note { grid-template-columns: 1fr; }
  .column-note-why { max-width: 100%; text-align: left; }
}

/* --- Multi-database connection provisioning ------------------------------- */

.badge-dialect { background: var(--accent-soft); color: var(--accent-dark); border-color: rgba(47,111,237,.25); }
.badge-dialect.badge-disconnected { background: var(--red-soft); color: var(--red); border-color: rgba(200,66,66,.25); }

.dialect-summary {
  display: grid;
  gap: 6px;
  margin: 12px 0 4px;
  padding: 12px 14px;
  background: var(--surface-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-size: 12px;
}
.dialect-summary > div { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.dialect-summary span { color: var(--muted); }
.dialect-summary code {
  background: white;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 2px 7px;
  font-size: 11px;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 60%;
}

.connection-fields { display: grid; gap: 12px; margin-top: 14px; }
.connection-field { display: grid; gap: 5px; }
.connection-field .field-help { margin: 0; }
.connection-checkbox { width: 16px; height: 16px; accent-color: var(--accent); justify-self: start; }

.saved-connection-list { display: grid; gap: 8px; margin-top: 12px; }
.saved-connection {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-soft);
}
.saved-connection.active { border-color: var(--accent); background: var(--accent-soft); }
.saved-connection-open {
  display: grid;
  gap: 3px;
  text-align: left;
  padding: 11px 14px;
  background: none;
  border: 0;
  cursor: pointer;
  font: inherit;
  color: inherit;
  min-width: 0;
}
.saved-connection-open strong { font-size: 13px; }
.saved-connection-open span {
  color: var(--muted);
  font-size: 11px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.saved-connection .icon-button { margin-right: 8px; }

@media (max-width: 620px) {
  .dialect-summary > div { flex-direction: column; align-items: flex-start; gap: 2px; }
  .dialect-summary code { max-width: 100%; }
}

/* Rules that were not sent with a question. Folded shut and quiet: on a firm with a large glossary
   this appears on most answers, and it must inform without competing with the answer above it. */
.withheld-box { margin: 10px 0 0 40px; font-size: 12px; }
.withheld-summary { color: var(--muted); cursor: pointer; line-height: 1.4; }
.withheld-summary:hover { color: var(--navy); }
.withheld-summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; border-radius: 3px; }
.withheld-why { color: var(--muted); margin: 5px 0 6px; line-height: 1.45; }
.withheld-list { margin: 0; padding-left: 18px; color: var(--navy); line-height: 1.45; }
.withheld-list li { margin-bottom: 3px; }

.measurement-box { margin: 14px 0 0 40px; padding: 12px 14px; border-left: 3px solid #d9e2f0; background: #fafbfe; border-radius: 0 9px 9px 0; }
.measurement-heading { display: block; font-size: 12px; color: #49566a; margin-bottom: 7px; }
.measurement-list { margin: 0; padding-left: 18px; }
.measurement-list li { font-size: 13px; line-height: 1.5; color: var(--ink); margin-bottom: 6px; }
.measurement-list li:last-child { margin-bottom: 0; }
/* Quiet on purpose: this is not a rating prompt, and it must not compete with the answer. */
/*
 * The way somebody tells us an answer is wrong, so it has to be seen.
 *
 * It was --muted at 55% opacity in 11px, which lands near 2.5:1 against white — under the 4.5:1
 * small text needs to be read at all. The instinct was right (an answer should not be cluttered with
 * controls) and it overshot: this is the entry point to the entire improvement loop, and it was the
 * faintest thing on the screen.
 *
 * Full opacity and a size that can be read. Still quiet, still secondary to the answer, no longer
 * something you have to already know is there.
 */
.measurement-correct { margin-left: 8px; padding: 0; border: 0; background: none; color: var(--muted); font-size: 11.5px; text-decoration: underline; cursor: pointer; transition: .15s ease; }
.measurement-correct:hover { opacity: 1; color: var(--accent); }
.measurement-sent { margin-left: 8px; font-size: 11px; color: #5d8a5d; }
.feedback-quote { margin: 14px 0 4px; padding: 11px 13px; border-radius: 9px; background: #f3f6fb; color: #4c5a70; font-size: 12px; line-height: 1.5; font-style: italic; }
.feedback-error { min-height: 16px; margin-top: 8px; color: var(--red); font-size: 12px; }

.table-actions { display: flex; gap: 8px; align-items: center; }
.chart-panel { margin: 0 0 12px; padding: 14px; border: 1px solid var(--line); border-radius: 11px; background: var(--surface-soft); }
.chart-controls { display: flex; gap: 8px; align-items: center; margin-bottom: 10px; }
/* The chart's own labels are drawn at 12px, and these pickers sat above them inheriting the body's
   14px -- close enough to look like a mistake rather than a hierarchy. Matched to the surrounding
   secondary text, with the house border and radius so they read as part of the panel. */
.chart-controls .tier-select {
  font-size: 12px;
  padding: 5px 8px;
  border: 1px solid #d2dae6;
  border-radius: 8px;
  background: white;
  color: var(--ink);
  max-width: 260px;
}
.chart-canvas { overflow-x: auto; }
.chart-canvas svg { display: block; max-width: 100%; height: auto; }

.warn-list { margin: 14px 0 4px; padding-left: 18px; }
.warn-list li { margin-bottom: 8px; color: #6b4a12; background: var(--amber-soft); border-radius: 7px; padding: 9px 11px; list-style: none; font-size: 13px; line-height: 1.45; }

.setup-progress { margin: 4px 0 18px; padding: 11px 14px; border-radius: 9px; background: var(--wash, #f6f8fc); color: #46536a; font-size: 13px; }
.setup-progress.done { background: var(--green-soft); color: var(--green); font-weight: 620; }
.setup-list { margin: 0; padding: 0; list-style: none; counter-reset: setup; }
.setup-step { display: grid; grid-template-columns: 30px 1fr auto; gap: 13px; align-items: start; padding: 14px 0; border-top: 1px solid var(--line); }
.setup-step:first-child { border-top: 0; }
.setup-mark { width: 24px; height: 24px; border-radius: 50%; border: 2px solid #c7cfda; display: grid; place-items: center; font-size: 13px; color: transparent; margin-top: 1px; }
.setup-step.is-done .setup-mark { background: var(--green); border-color: var(--green); color: white; }
.setup-step.is-manual .setup-mark { cursor: pointer; }
/* The confirmable tick is a button (board #21): no browser button padding or face, same circle. */
button.setup-mark { padding: 0; background: transparent; font: inherit; font-size: 13px; line-height: 1; }
.setup-step.is-done button.setup-mark { background: var(--green); }
button.setup-mark:focus-visible { outline: 2px solid var(--blue, #2f6fed); outline-offset: 2px; }
.setup-step h4 { margin: 0 0 4px; font-size: 13.5px; color: var(--ink); font-weight: 650; }
/* pre-wrap, because a step whose answer is a command puts it on its own line. Without this the
   newline collapsed and the command ran into the prose around it, which is where it gets mistyped. */
.setup-step p { margin: 0; font-size: 12.5px; color: var(--muted); line-height: 1.5; white-space: pre-wrap; }
.setup-kind { font-size: 10px; text-transform: uppercase; letter-spacing: .05em; padding: 2px 7px; border-radius: 999px; background: #eef2f8; color: #64728a; white-space: nowrap; }
.setup-kind.verify { background: var(--accent-soft); color: #2b5cbf; }
.setup-step.is-last { border-top: 2px solid var(--navy); margin-top: 6px; padding-top: 16px; }
.setup-goto { margin-left: 8px; font-size: 12px; color: var(--accent); background: none; border: 0; padding: 0; text-decoration: underline; }

/* --- Reference ------------------------------------------------------------------------------ */
/* Prose on this page is read, not scanned, so it gets a measure and a line height that suit
   reading. The rest of the application is dense on purpose; this one section is not. */
.reference-copy { max-width: 78ch; color: #43506b; line-height: 1.65; margin: 0 0 12px; }
.reference-list { max-width: 78ch; color: #43506b; line-height: 1.6; margin: 0 0 16px; padding-left: 20px; }
.reference-list li { margin-bottom: 8px; }
#page-tuning h3 { font-size: 15px; color: var(--navy); margin: 22px 0 8px; }

.reference-findings { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
.reference-group { margin-bottom: 18px; }
.reference-group-title { font-size: 12px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); margin: 14px 0 8px; }

/* Set aside, folded, at the foot. Quieter than a live section on purpose: it is a record of what a
   firm has already decided does not concern them, not a list anybody is working through. */
.reference-setaside { margin: 22px 0 4px; border-top: 1px solid var(--line); padding-top: 12px; }
.reference-setaside > summary { cursor: pointer; font-size: 12px; text-transform: uppercase;
  letter-spacing: .06em; color: var(--muted); padding: 4px 0; list-style-position: outside; }
.reference-setaside > summary:hover { color: var(--text); }
.reference-setaside[open] > summary { margin-bottom: 8px; }
/* Rows inside read as archived rather than as awaiting an answer. */
.reference-setaside .reference-row { opacity: .78; }

/* Right-aligned, so the one action above the list reads as an action rather than as a heading. */
.bank-actions { justify-content: flex-end; margin: 4px 0 12px; }

/* What each outcome does, under the question it applies to. A definition list because that is what
   it is -- three terms and what each one means -- and the term stays with its own text when the
   modal narrows. */
.outcome-guide { margin: 10px 0 0; display: grid; grid-template-columns: auto 1fr; gap: 4px 12px; align-items: baseline; }
.outcome-guide dt { font-weight: 600; color: var(--navy); white-space: nowrap; }
.outcome-guide dd { margin: 0; font-size: 13px; line-height: 1.5; color: var(--muted); }
.outcome-guide-note { margin: 10px 0 0; font-size: 12px; color: var(--muted); }

/* Where a committing action lands, said before it is pressed rather than in a toast afterwards.
   One class everywhere so the sentence is recognisable as the same kind of statement wherever it
   appears -- caption weight, never competing with the button it describes. */
.action-destination { margin: 8px 0 0; font-size: 11.5px; line-height: 1.45; color: var(--muted); }
.action-destination strong { color: inherit; font-weight: 600; }

/* The agreed case, demoted. It is a receipt rather than a finding, so it reads at caption weight
   below the answer instead of as a panel above it. Still present, because a check that goes silent
   when it passes cannot be told apart from one that never ran. */
.second-opinion-quiet { margin: 6px 0 0; font-size: 12px; color: var(--muted); }

/* Coming back from Chat. A scroll on its own leaves somebody scanning for which row moved, so the
   row says so for a moment and then stops. Fades rather than blinks: the point is to be found, not
   to demand anything. */
.reference-row.is-returned { box-shadow: 0 0 0 2px var(--accent, #2b5cbf); transition: box-shadow .4s ease; }
@media (prefers-reduced-motion: reduce) {
  .reference-row.is-returned { transition: none; }
}
/* Five outcomes will not sit on one line on a narrow modal, and a button that wraps mid-label reads
   as broken. The row wraps as a row, keeping the three judgements together at the end. */
.spot-outcomes { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; justify-content: flex-end; }
@media (max-width: 620px) {
  .outcome-guide { grid-template-columns: 1fr; gap: 2px; }
  .outcome-guide dd { margin-bottom: 8px; }
}

/* Export: eight lists carry one of these, so it has to disappear until it is wanted.
   No border, no fill, muted until hover -- the weight of a caption rather than of a control. The
   arrow is the only ornament, and it is what makes it findable when somebody is looking for it. */
.list-export { display: flex; justify-content: flex-end; margin: 0 0 8px; }
.export-link { background: none; border: 0; padding: 2px 0; cursor: pointer;
  font-size: 12px; color: var(--muted); letter-spacing: .02em; }
.export-link::before { content: "\2193"; margin-right: 5px; opacity: .7; }
.export-link:hover { color: var(--navy); text-decoration: underline; }
.export-link:focus-visible { outline: 2px solid var(--accent, #2b5cbf); outline-offset: 3px; border-radius: 4px; }

/* The section heading carries its own run control, so the title and the control share a baseline
   and the control keeps its width when a long area name wraps. */
.reference-group-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }

/* The whole heading is the fold control: a caret alone is a target people miss, and the name is
   what they are actually reaching for. */
.reference-group-toggle { display: flex; align-items: center; gap: 8px; background: none; border: 0;
  padding: 0; margin: 0; cursor: pointer; text-align: left; min-width: 0; }
.reference-group-toggle .reference-group-title { margin: 0; }
.reference-group-caret { color: var(--muted); font-size: 10px; width: 10px; flex: none; }
.reference-group-count { font-size: 12px; color: var(--muted); white-space: nowrap; }
.reference-group-toggle:hover .reference-group-title { color: var(--navy); }
.reference-group-toggle:focus-visible { outline: 2px solid var(--accent, #2b5cbf); outline-offset: 3px; border-radius: 4px; }
.section-run { display: flex; align-items: center; gap: 10px; flex: none; }
.section-run-state { font-size: 12px; color: var(--muted); white-space: nowrap; }
/* Fixed width rather than a share of the row: a bar that resized as the percentage climbed would
   read as progress going backwards whenever the label beside it grew a digit. */
.section-run-bar { width: 120px; height: 6px; border-radius: 999px; background: var(--line); overflow: hidden; }
.section-run-fill { height: 100%; background: var(--accent, #2b5cbf); transition: width .3s ease; }

.reference-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  background: white; border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px; }
/* Definitions to settle: the panels sit close together and each is a separate decision, so the edge
   between them is a step darker than the page's hairline (Tom, 24 Sep 2026). */
#decisionList .reference-row { border-color: #a9b6ca; }
#decisionList .reference-row.is-reviewed { border-color: #9fd4bd; }
#decisionList .reference-row.is-raised { border-color: #d9b766; }
#decisionList .reference-row.is-raised.is-handover,
#decisionList .reference-row.is-raised.is-floor { border-color: #9fb6e6; }
.reference-row-main { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.reference-row-title { color: var(--navy); font-size: 14px; }
.reference-row-detail { color: var(--muted); font-size: 12px; line-height: 1.5; }
.reference-row-options { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
/* The settle list stacks instead of wrapping. Once a reading carries the sentence it would produce,
   the buttons are two lines tall, and a wrapped row put "We do not do this" alongside the second
   reading -- where it read as a qualifier on that reading rather than as its own answer. */
.reference-row-options.is-stacked { flex-direction: column; align-items: stretch; gap: 8px; }
/* One width for every answer in the column, and not the page's. Full width, a reading ran edge to
   edge on a wide screen beside pill-sized buttons in the next row -- Tom, 24 Sep 2026: "some short some
   across the entire width of the page". Capped, the answers read as one set of equal choices; text
   aligned left, because a two-line sentence centred is harder to read. */
.reference-row-options.is-stacked { max-width: 680px; }
.reference-row-options.is-stacked .reference-choice { width: 100%; border-radius: 10px; padding: 8px 12px; text-align: left; }
/* The badge carries a number and must not be squeezed to two lines by a long question beside it. */
.reference-row > .badge, .reference-row-end > .badge { flex: none; white-space: nowrap; }
.reference-tag { background: var(--accent-soft); color: #2b5cbf; border-radius: 999px;
  padding: 3px 9px; font-size: 11px; white-space: nowrap; }

/* Fine-tuning rows carry actions, so the row becomes two columns rather than text plus a badge. */
.reference-row-actions { display: flex; align-items: center; gap: 10px; flex: none; }
.reference-run { padding: 6px 14px; font-size: 12px; }
.reference-check { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); white-space: nowrap; cursor: pointer; }
.reference-check input { margin: 0; }

/* Three conclusions, equally weighted. A reviewer who has just read a wrong number should not have
   to hunt for where to say so, and "Wrong" sitting quieter than "Right" would encourage the tick
   that costs nothing over the report that is worth something. */
.reference-outcomes { display: flex; gap: 4px; }
/* --surface, not --panel: the latter has never existed here, so these buttons have been rendering
   with no background at all. Found by the guard added for the scope menu (18 Sep 2026). */
.outcome-button { background: var(--surface); color: var(--muted); border: 1px solid var(--line);
  border-radius: 999px; padding: 5px 11px; font-size: 12px; cursor: pointer; font-family: inherit;
  white-space: nowrap; }
.outcome-button:hover { border-color: var(--accent); color: var(--navy); }
.outcome-button.is-chosen { background: var(--green-soft); color: var(--green); border-color: #ccecdf; }
/* Only the chosen state is coloured by meaning: an unpressed "Wrong" is not a warning about
   anything, and colouring it would make every unreviewed question look like a problem. */
.reference-outcomes .outcome-button:nth-child(2).is-chosen { background: var(--amber-soft); color: var(--amber); border-color: #f0dcad; }
.reference-outcomes .outcome-button:nth-child(3).is-chosen { background: var(--surface); color: var(--muted); border-color: var(--line); }

/* What somebody wrote, kept looking like something somebody wrote. */
.reference-row-note { color: var(--navy); font-size: 12px; line-height: 1.5; font-style: italic; }
/* Reviewed and settled rows recede rather than disappear: the reviewer needs to see what they have
   done, and a finding claimed to be settled must stay checkable by the person it was claimed for. */
.reference-row.is-reviewed { background: var(--green-soft); border-color: #ccecdf; }
.reference-row.is-settled { opacity: .7; }
/* A reported wrong answer sits above the derived definitions and looks unlike them, because it is
   the one item on the list somebody has already proven is a problem. */
.reference-row.is-raised { background: var(--amber-soft); border-color: #f0dcad; }
.badge-warn { background: var(--amber-soft); color: var(--amber); border-color: #f0dcad; }
/* A handover is not a fault. Amber says something broke; this says a decision is owed, which is
   ordinary work rather than an alarm. */
.reference-row.is-raised.is-handover { background: var(--accent-soft); border-color: #cfdcf7; }
/* A contested definition is work owed, not a fault found: people disagreed, which is the system
   doing its job. So it borrows the raised row's prominence and the handover's calmer colour. */
.reference-row.is-raised.is-floor { background: var(--accent-soft); border-color: #cfdcf7; }
/* Both camps, side by side. A lead has to weigh them against each other, so they read as one line of
   comparison rather than as a list where the first looks like the recommendation. */
.floor-camps { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
.floor-camp { background: white; border: 1px solid var(--line); border-radius: 999px;
  padding: 3px 10px; font-size: 11.5px; color: var(--navy); }
/* Separates the two lists on the Leads tab. Quiet, because it is a divider and not a section. */
.reference-heading { color: var(--navy); font-size: 13px; font-weight: 600; margin: 14px 0 2px; }
.reference-settled { color: var(--green); font-size: 12px; }
.reference-warning { color: var(--amber); font-size: 12px; }

/* The spot-check modal. Wider than a dialog because an answer with a table in it is the point, and
   a number squeezed into a 540px column is not a number anybody will judge confidently. */
.spot-question { font-size: 15px; color: var(--navy); font-weight: 600; line-height: 1.4; }
.spot-answer { line-height: 1.55; margin: 10px 0; }

/* Open on the page rather than behind a disclosure, because this is the screen where somebody
   decides whether the number is right, and what it assumed is how that decision gets made. */
.spot-reasoning { background: #f6f8fb; border: 1px solid var(--line); border-left: 3px solid var(--accent, #2b5cbf);
  border-radius: 8px; padding: 10px 12px; margin: 12px 0; }
.spot-reasoning-heading { font-size: 12px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); margin-bottom: 6px; }
.spot-rationale { font-size: 13px; line-height: 1.55; margin: 0 0 8px; }
.spot-reasoning strong { font-size: 12px; }
.spot-assumptions { margin: 4px 0 0; padding-left: 18px; font-size: 13px; line-height: 1.6; color: var(--muted); }
.spot-loading, .spot-idle { color: var(--muted); padding: 18px 0; }
.spot-sql { background: #f6f8fb; border: 1px solid var(--line); border-radius: 8px; padding: 10px;
  font-size: 12px; overflow-x: auto; white-space: pre-wrap; }
#spotCheckRests { background: var(--amber-soft); border: 1px solid #f0dcad; border-radius: 10px;
  padding: 11px 13px; margin: 10px 0; color: var(--amber); }
#spotCheckRests p { margin: 4px 0 0; font-size: 12px; line-height: 1.45; }
/* Close on the left, conclusions on the right: leaving is not one of the three answers. */
.spot-actions { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.spot-outcomes { display: flex; gap: 6px; }

/* Six stages of one exercise, so the strip reads as a sequence rather than a set of destinations.
   It scrolls sideways rather than wrapping: a second row of tabs stops looking like an order. */
/*
 * A segmented control rather than bare text on a rule.
 *
 * They were plain words in a row with a two-pixel underline on the selected one, and against a white
 * card they read as a sentence rather than as controls — "How this works Rules Terms History Has it
 * worked?" is a line of prose until you know it is not. Tom, looking at it: "can you get me some
 * colour or borders, something that doesn't make them all blend in."
 *
 * The container is what does the work. Once the group sits in its own tinted well, the selected one
 * can be a plain white chip and the whole thing reads instantly — no colour needed to carry the
 * structure, so the accent is spent on the selection alone.
 *
 * Chosen from four treatments side by side. This is the shape that matches the cards and pills used
 * everywhere else, with the accent-blue selection from a flatter alternative that read better.
 *
 * Still scrolls sideways rather than wrapping: a second row of tabs stops looking like an order.
 */
/* Tabs stay put while their contents scroll.
   —
   On the long screens — Fine-tuning, Settings, Security, DB Tuning — the strip scrolled away within
   a screenful, and from then on nothing said which tab you were on. Getting back meant scrolling to
   the top to look, which is the same cost as losing your place. Sticky keeps the answer to "where am
   I" permanently on screen for the price of one line.
   —
   `inline-flex` cannot stick: a sticky element resolves its offsets against its containing block,
   and an inline-level box shrink-wrapped to its labels leaves the row beside it uncovered, so
   content scrolls through the gap. It becomes a flex row that fills the width, with the pills still
   packed left by justify-content. The background must be opaque for the same reason — a transparent
   strip shows the text passing underneath it. */
.tuning-tabs { display: flex; width: fit-content; justify-content: flex-start; gap: 2px;
  overflow-x: auto; max-width: 100%;
  background: var(--surface-soft); border: 1px solid var(--line); border-radius: 10px;
  padding: 3px; margin-bottom: 18px;
  position: sticky; top: var(--topbar-h); z-index: 5; }
/**
 * No full-bleed band behind the pills, and the reason is worth keeping.
 *
 * A shrink-wrapped pinned bar only masks what passes under IT, so content scrolls up in full view
 * beside it. The obvious cure is an absolutely-positioned pseudo-element stretching `right: -100vw`
 * to paint an opaque band to the window edge. It was tried and it broke every tab strip in the
 * product: this element has `overflow-x: auto`, and an absolutely-positioned child extending past
 * its content box EXTENDS ITS SCROLLABLE AREA. Each strip gained exactly one viewport width of
 * horizontal scroll, so `max-width: 100%` then clipped the tabs -- "Schema rules" arrived on screen
 * as "...ules", on all seven strips at once.
 *
 * A band would have to live on a non-scrolling wrapper, which means new markup in seven places for a
 * cosmetic gain. Content passing beside a pinned pill bar is what every pinned pill bar does.
 */
.tuning-tab { background: none; border: 1px solid transparent; border-radius: 7px; color: var(--muted);
  font-family: inherit; font-size: 13px; padding: 8px 13px; cursor: pointer; white-space: nowrap;
  transition: .12s ease; }
.tuning-tab:hover { color: var(--navy); }
.tuning-tab.is-active { background: var(--surface); border-color: var(--line); color: var(--accent);
  font-weight: 600; box-shadow: 0 1px 2px rgba(30,45,70,.10); }
.tuning-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* The record of what is settled. Colour tracks how overdue a review is, and nothing here means
   "not applied" except withdrawn -- everything else is in force whatever its shade. */
.reference-row.record-stale { border-left: 3px solid var(--amber); }
.reference-row.record-archived { border-left: 3px solid var(--red); }
.reference-row.record-active { border-left: 3px solid var(--green); }
.reference-row.record-withdrawn { opacity: .6; }

/* What the firm has not stood behind yet, pinned above the rest of the record. The heading carries
   the count, so the rule below it separates two lists rather than decorating one. */
.record-waiting-heading { color: var(--navy); font-size: 14px; font-weight: 600; margin: 0; }
.record-waiting-note { margin: -2px 0 2px; }
.record-rest-heading { color: var(--muted); font-size: 12px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .06em; margin: 10px 0 0; padding-top: 12px; border-top: 1px solid var(--line); }

/* Clearing one answer. Quiet until reached for: it undoes somebody's work, so it should never be
   the thing the eye lands on, and it must be unmistakable once the pointer is on it. */
.reference-row-end { display: flex; align-items: center; gap: 8px; flex: none; }
.reference-row-clear { background: none; border: 1px solid transparent; border-radius: 50%;
  width: 24px; height: 24px; line-height: 1; padding: 0; color: var(--muted); font-size: 16px;
  font-family: inherit; cursor: pointer; flex: none; transition: .12s ease; }
.reference-row-clear:hover { background: var(--red-soft); border-color: #f5caca;
  color: var(--red); }
.reference-row-clear:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Ratified: shown, and shown to be unavailable, because "why is there no X on this one" is the
   question the hover answers. */
.reference-row-clear.is-spent { opacity: .3; cursor: not-allowed; }
.reference-row-clear.is-spent:hover { background: none; border-color: transparent; color: var(--muted); }

/* A choice, not a form. Each button is a complete answer to the question above it. */
.reference-choice { background: var(--accent-soft); color: #2b5cbf; border: 1px solid transparent;
  border-radius: 999px; padding: 5px 12px; font-size: 12px; cursor: pointer; font-family: inherit; }
.reference-choice:hover { border-color: var(--accent); }
.reference-choice.is-chosen { background: var(--green-soft); color: var(--green); border-color: #ccecdf; }
/* Deliberately the quietest control in the row. Setting a question aside is the right answer for a
   firm that does not do that work, and the wrong one for a firm avoiding a hard question -- so it
   sits beside the readings rather than competing with them. */
.reference-choice.is-quiet { background: transparent; color: var(--muted); border-color: var(--line); }
/* An answer like the readings beside it, and deliberately not one of them: it carries no row count,
   because nothing measured it. Dashed rather than quieter -- setting a question aside is the muted
   act, and writing your firm's own definition is not. */
.reference-choice.reference-choice-write { border-style: dashed; border-color: var(--accent); }
.reference-choice.is-quiet:hover { border-color: var(--muted); color: #4f5c71; }
.badge-quiet { color: var(--muted); background: var(--panel-soft, #f6f7f9); }
.reference-settled.is-overdue { color: var(--amber); }

/* The header indicator. Quiet while the review is timely; harder to ignore once it is not. */
.badge-provisional { cursor: pointer; background: var(--accent-soft); color: #2b5cbf; border-color: #cddcf5; }
.badge-provisional.is-stale { background: var(--amber-soft); color: var(--amber); border-color: #f0dcad; }
.badge-provisional.is-archived { background: #fdecec; color: #b3261e; border-color: #f3c9c6; }

/* Who may record a decision, said before the attempt rather than after the refusal. */
.tuning-access { display: flex; align-items: center; justify-content: space-between; gap: 16px;
  background: var(--surface-soft, #f7f9fc); border: 1px solid var(--line); border-radius: 10px;
  padding: 10px 14px; margin: 14px 0 4px; font-size: 13px; color: #43506b; }

/* A definition this answer rested on that nobody has settled. Quiet enough to ignore while reading
   the number, present enough that the person who knows the answer can give it in one click. */
.unsettled-panel { margin: 12px 0 0 40px; padding: 9px 12px; border: 1px solid #f0dcad;
  background: var(--amber-soft); border-radius: 10px; }
/* Tightened throughout. Four stacked lines of prose above three buttons made this the tallest thing
   on the screen, and it is a question with three answers -- not an article. The words are unchanged;
   the room came from the leading and the gaps between them. */
.unsettled-title { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--amber); margin-bottom: 3px; }
.unsettled-question { font-size: 13.5px; color: var(--navy); line-height: 1.35; }
.unsettled-evidence { font-size: 12px; color: #6b5a33; margin-top: 1px; line-height: 1.35; }
/* .unsettled-instruction was the how-to line between the question and the buttons. The line is gone
   and so is its rule; the class name survives only in the comment explaining why, in app.js. */
/* Who may settle it. Set apart from the instruction so it is not read as part of the how-to, and
   quieter than a warning -- it is a fact about the decision, not something going wrong. */
.unsettled-permission {
  font-size: 12px; color: var(--muted); margin-top: 8px; line-height: 1.45;
  padding-top: 8px; border-top: 1px solid rgba(169, 105, 0, .22);
}
.unsettled-choices { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 7px; }
/* Stacked, so the way out is not read as attached to the reading beside it. */
.unsettled-choices.is-stacked { flex-direction: column; align-items: stretch; gap: 8px; }
.unsettled-choices.is-stacked { max-width: 680px; }
.unsettled-choices.is-stacked .reference-choice { width: 100%; border-radius: 10px; padding: 8px 12px; text-align: left; }
/* Collapsed by default. The marker and the pointer are what say it opens; without them a summary
   reads as a heading somebody forgot to make clickable. */
.unsettled-panel > .unsettled-title { cursor: pointer; list-style: none; }
.unsettled-panel > .unsettled-title::-webkit-details-marker { display: none; }
.unsettled-panel > .unsettled-title::before { content: '\25B8'; display: inline-block; margin-right: 6px; transition: transform .15s ease; }
.unsettled-panel[open] > .unsettled-title::before { transform: rotate(90deg); }

/**
 * Every option in this row is one chip, and they all look the same.
 *
 * They were three different things: two tinted readings, a transparent "Neither", and a "Walk me
 * through this…" with no rule at all, which rendered as a raw browser button with a black border.
 * Four ways to answer one question, dressed as four unrelated controls.
 *
 * `.unsettled-open` and `.unsettled-neither` now carry `.reference-choice` and add nothing, so the
 * row is uniform by construction rather than by three rules agreeing. The hooks stay because the
 * markup and the tests name them.
 */
.unsettled-open, .unsettled-neither { /* styling comes from .reference-choice */ }
.unsettled-open:focus-visible { outline: 2px solid var(--amber); outline-offset: 1px; }

/**
 * The other definitions behind the same answer, folded away until asked for.
 *
 * The rows inside were the last raw browser buttons in this panel: black borders, no spacing, butted
 * against each other under a summary that had no room around it either. The comment on the sibling
 * control noted the problem and fixed only itself, so the fix is carried across here -- the rows now
 * take `.reference-choice` like every other way of answering this panel, and this rule supplies the
 * layout the chip class cannot know about.
 */
.unsettled-others { margin-top: 9px; padding-top: 8px; border-top: 1px solid rgba(169, 105, 0, .22); }
.unsettled-others > summary {
  font-size: 12px; color: var(--amber); cursor: pointer; line-height: 1.4;
  list-style: none; padding-left: 13px; position: relative;
}
.unsettled-others > summary::-webkit-details-marker { display: none; }
/* Own marker, so it turns with the disclosure rather than depending on the browser's. */
.unsettled-others > summary::before {
  content: '\25B8'; position: absolute; left: 0; font-size: 10px; top: 1px;
  transition: transform .12s ease; display: inline-block;
}
.unsettled-others[open] > summary::before { transform: rotate(90deg); }
.unsettled-others > summary:focus-visible { outline: 2px solid var(--amber); outline-offset: 1px; border-radius: 3px; }
/* Stacked, not a chip row: each entry carries its evidence on a second line, and a chip cannot hold
   two lines. The questions are close to full width anyway, so a row is the honest container. */
.unsettled-other-list { display: flex; flex-direction: column; gap: 4px; margin-top: 7px; }
.unsettled-other {
  display: block; width: 100%; text-align: left; cursor: pointer; font-family: inherit;
  background: rgba(255, 255, 255, .5); border: 1px solid rgba(169, 105, 0, .22); border-radius: 6px;
  padding: 6px 9px;
}
.unsettled-other:hover { border-color: var(--amber); background: rgba(255, 255, 255, .75); }
.unsettled-other:focus-visible { outline: 2px solid var(--amber); outline-offset: 1px; }
.unsettled-other-question { display: block; font-size: 12.5px; color: var(--navy); line-height: 1.35; }
/* Same treatment the current definition's evidence gets above, one step quieter. */
.unsettled-other-evidence { display: block; font-size: 11.5px; color: #6b5a33; line-height: 1.35; margin-top: 1px; }
/* The way out of the panel, separated from the ways to answer it. */
.unsettled-others .unsettled-open { margin-top: 8px; }

/* The ordered worklist. Three steps, a count that goes down, and a finish. */
.worklist { display: flex; flex-direction: column; gap: 8px; margin: 6px 0 4px; }
.worklist-step { display: flex; align-items: flex-start; gap: 12px; padding: 12px 14px;
  background: white; border: 1px solid var(--line); border-radius: 10px; }
.worklist-step.is-done { background: var(--green-soft); border-color: #ccecdf; }
.worklist-mark { flex: none; width: 24px; height: 24px; border-radius: 50%; display: grid;
  place-items: center; font-size: 12px; background: var(--accent-soft); color: #2b5cbf; }
.worklist-step.is-done .worklist-mark { background: var(--green); color: white; }
.worklist-main { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.worklist-title { color: var(--navy); font-size: 14px; }
.worklist-detail { color: var(--muted); font-size: 12px; line-height: 1.5; }

/* The Leads / DBA split inside the settle list.
   Same tab idiom again, sitting between the scan button and the list it filters, so the count on
   each label is read as belonging to the rows below rather than to the card as a whole. */
/* A nested strip sticks BELOW the page-level one rather than on top of it. Both share a scrolling
   ancestor, so two strips pinned to 0 would occupy the same line and the inner would cover the outer
   — losing exactly the "which screen am I on" the outer is pinned to preserve. */
.settle-tabs { margin: 14px 0 4px; top: calc(var(--topbar-h) + 46px); }

/* Business rules tabs.
   Reuses .tuning-tab styling so the two screens do not teach two different tab idioms, with its own
   panel class because these are sections of one card rather than whole screens. */
/* Pinned directly under the topbar, NOT offset like the settle tabs.
   —
   It is the only strip on page-rules, so the 46px reserved for a strip above it was reserving space
   for nothing — and a gap between the topbar and a pinned bar is a window the page scrolls through,
   which is what "the image goes behind and up past it" was describing. .settle-tabs keeps the offset
   because it genuinely sits beneath the Fine-tuning strip. */
.rules-tabs { margin: 18px 0 0; top: var(--topbar-h); }
.rules-panel { padding-top: 16px; }

/* Settings tabs.
   Same idiom again, sat above the grid rather than inside a card, because here the tabs divide the
   whole screen. The screen had grown to eight stacked cards and somebody after the licence key was
   scrolling past the database connection to reach it. */
.settings-tabs { margin: 0 0 18px; flex-wrap: wrap; }
/* Board #5: on the screens under the Settings strip, a strip of their own (Security, DB Tuning, Trace
   & Support) was pinned to the same offset and z-index, so once the page scrolled it sat on top of
   the Settings tabs and hid them. The Settings strip wraps to a height no fixed offset can predict,
   so these scroll with their section instead of pinning. Fine-tuning and Business Rules are not under
   the Settings strip and keep pinning. */
#page-settings .tuning-tabs:not(.settings-tabs),
#page-trace .tuning-tabs:not(.settings-tabs) { position: static; }
/* The count on a label, quieter than the label so the word is still what is read first. */
.tab-count { color: var(--muted); font-weight: 400; font-variant-numeric: tabular-nums; }
/* Says where a tab's contents came from, before the contents. Sized as help text because that is
   what it is -- the group heading is the tab itself. */
.rules-tab-note { color: var(--muted); font-size: 12.5px; line-height: 1.5; margin: 0 0 14px; }

/* The flow diagram and the guide table on the Business rules "How this works" tab.
   Every colour comes from a variable already defined for this stylesheet, so the drawing follows
   the rest of the interface rather than carrying its own palette. */
/* The Business Rules flow diagram.
 *
 * Two sections on one grid: what an answer can put in front of you, then where every
 * instruction comes from. Each box in a column is the same height and every line of text
 * sits at the same offset from that box's top, so the columns read as set rather than drawn.
 * Connectors are straight lines into a vertical rail -- there is not one curve in the SVG,
 * because the elbows in the previous version were what made it look sketched.
 *
 * The role badges come from LEAD_PATHS and ADMIN_ONLY_PATHS in admin-session.mjs. If a route
 * moves between those sets, the badge here is wrong and nothing will say so.
 */
.rules-flow { margin: 6px 0 0; }
.rules-flow svg {
  width: 100%; height: auto; max-width: 940px; display: block;
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  text-rendering: geometricPrecision;
}
.rules-flow figcaption {
  margin: 14px auto 0; max-width: 720px; text-align: center;
  font-size: 12.5px; line-height: 1.65; color: var(--muted);
}
.rules-flow figcaption b { color: var(--navy); font-weight: 600; }

/* One type scale, used everywhere. */
.rf-section { fill: var(--navy); font-size: 10px; font-weight: 700; letter-spacing: .14em; }
.rf-section-note { fill: var(--muted); font-size: 10px; font-weight: 500; letter-spacing: 0; }
.rf-colhead { fill: var(--muted); font-size: 8.5px; font-weight: 700; letter-spacing: .13em; }
.rf-colhead-mid { fill: var(--blue-soft-dark); }
.rf-eyebrow { font-size: 8.5px; font-weight: 700; letter-spacing: .1em; }
.rf-title { fill: var(--navy); font-size: 12px; font-weight: 650; }
.rf-sub { fill: var(--muted); font-size: 10px; }
.rf-item { fill: var(--navy-2); font-size: 11px; font-weight: 500; }
.rf-quiet { fill: var(--muted); font-size: 10px; }

.rf-rule { stroke: var(--line); stroke-width: 1; }
.rf-rule-mid { stroke: var(--blue-soft); stroke-width: 2; }

.rf-box { stroke-width: 1.25; }
.rf-act   { fill: var(--green-soft); stroke: var(--green); }
.rf-hold  { fill: var(--accent-soft); stroke: var(--blue-soft); stroke-width: 1.75; }
.rf-watch { fill: var(--surface-soft); stroke: var(--line); }
.rf-eyebrow-act { fill: var(--green); }
.rf-eyebrow-watch { fill: var(--muted); }

/* The label the instruction actually wears in the In force list. */
.rf-tag-plate { fill: #ffffff; stroke: var(--green); stroke-width: .9; }
.rf-tag { fill: var(--green); font-size: 8.5px; font-weight: 650; }

/* Straight lines and one rail per side. No curves anywhere. */
.rf-line { stroke: var(--muted); stroke-width: 1.3; fill: none; opacity: .8; }
.rf-rail { stroke: var(--muted); stroke-width: 1.6; opacity: .55; }
.rf-node { fill: var(--muted); opacity: .8; }
.rf-arrowhead { fill: var(--muted); opacity: .85; }
.rf-tick { fill: var(--blue-soft); }
.rf-divide { stroke: var(--blue-soft); stroke-width: 1; opacity: .28; }

/* The panels an answer can carry, in the panels' own colours. */
.rf-chip { stroke-width: 1.1; }
.rf-chip-vote      { fill: #f4f8f3; stroke: #d7e6d4; }
.rf-edge-green { stroke: var(--green); stroke-width: 2.5; }
.rf-role-vote  { fill: var(--green); }
.rf-chip-clarify   { fill: var(--surface-soft); stroke: var(--line); }
/* Kept in step with .refine-options above. This diagram says it shows the panels in their own
   colours, so it is wrong the moment one of them changes and nobody looks here. */
.rf-chip-refine    { fill: #f2f6fd; stroke: #dbe6f7; }
.rf-chip-signal    { fill: #fdf8ee; stroke: #f0e0c4; }
.rf-chip-measure   { fill: #fafbfe; stroke: #d9e2f0; }
.rf-chip-unsettled { fill: var(--amber-soft); stroke: #f0dcad; }
.rf-edge-blue  { stroke: var(--accent); stroke-width: 2.5; }
.rf-edge-cyan  { stroke: #7fd4d4; stroke-width: 2.5; }
.rf-edge-amber { stroke: var(--amber); stroke-width: 2.5; }
.rf-edge-grey  { stroke: #d9e2f0; stroke-width: 2.5; }
.rf-role-block { fill: var(--accent-dark); }
.rf-role-offer { fill: #3f8a8a; }
.rf-role-warn  { fill: #8a5a12; }
.rf-role-tell  { fill: #49566a; }
.rf-role-ask   { fill: var(--amber); }
.rf-chip-name { fill: var(--navy); font-size: 11px; font-weight: 650; }
.rf-chip-sub  { fill: #556174; font-size: 9px; }

/* Who can respond. Anyone and Lead are marked everywhere they apply; Administrator is marked
   only where it is exclusive -- an administrator can do everything a lead can, so putting the
   badge on those too would say the opposite of what it means. Taken from LEAD_PATHS and
   ADMIN_ONLY_PATHS in admin-session.mjs, which is where the decision actually lives. */
.rf-who { font-size: 7.5px; font-weight: 700; letter-spacing: .09em; }
.rf-who-anyone-plate { fill: #e9edf4; stroke: #d3dbe8; stroke-width: .9; }
.rf-who-anyone { fill: #5a6678; }
.rf-who-lead-plate { fill: var(--green-soft); stroke: var(--green); stroke-width: .9; }
.rf-who-lead { fill: var(--green); }
.rf-who-admin-plate { fill: var(--navy); stroke: var(--navy); stroke-width: .9; }
.rf-who-admin { fill: #ffffff; }

/* Cross-reference, carried on both ends instead of a line drawn between them. */
.rf-link-plate { fill: var(--green); }
.rf-link { fill: #ffffff; font-size: 8px; font-weight: 700; letter-spacing: .08em; }

.rf-legend { fill: var(--muted); font-size: 10px; }
.rf-legend-key { fill: var(--navy); font-size: 10px; font-weight: 650; }

.rules-guide { border-collapse: collapse; width: 100%; font-size: 13px; margin: 6px 0 18px; }
.rules-guide th, .rules-guide td { text-align: left; padding: 9px 10px; border-bottom: 1px solid var(--line); vertical-align: top; }
.rules-guide th { font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.rules-guide td:first-child { white-space: nowrap; }
/* Act versus read, as a chip, so the column can be scanned without reading it. */
.guide-act, .guide-watch { display: inline-block; font-size: 10.5px; letter-spacing: .06em;
  text-transform: uppercase; padding: 2px 8px; border-radius: 3px; border: 1px solid; white-space: nowrap; }
.guide-act { color: var(--green); border-color: var(--green); background: var(--green-soft); }
.guide-watch { color: var(--muted); border-color: var(--line); background: var(--surface-soft); }

/* The In force tab: two labelled groups under one cost line. */
.rules-inforce-lede { color: var(--ink); font-size: 13.5px; margin: 0 0 4px; }
/* The cost of everything sent, standing alone rather than heading the history beneath it. */
.rules-cost { color: var(--muted); font-size: 12.5px; font-variant-numeric: tabular-nums; margin: 0 0 20px; }
.rules-group-heading {
  font-size: 14px; font-weight: 600; color: var(--navy);
  margin: 26px 0 10px; display: flex; align-items: baseline; gap: 10px;
}
.rules-group-heading:first-of-type { margin-top: 0; }
/* Said once on the group rather than on every row, where it crowded out the name and date. */
.rules-group-tag {
  font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase; font-weight: 500;
  color: var(--muted); border: 1px solid var(--line); background: var(--surface-soft);
  border-radius: 3px; padding: 2px 8px;
}
.rules-group-note { color: var(--muted); font-size: 12.5px; line-height: 1.5; margin: 0 0 12px; }
/* Tom, 28 Sep 2026: the two collapsed sections on Business Rules › Rules, headed like the groups above. */
.rules-section { margin: 22px 0 6px; border: 1px solid #e2e7ef; border-radius: 8px; padding: 12px 16px; }
.rules-section > summary { cursor: pointer; font-size: 14px; font-weight: 600; color: var(--navy); }
.rules-section[open] > summary { margin-bottom: 10px; }
.rules-section-body { padding-top: 2px; }
.rules-pending { color: var(--warn-text, #8a5a00); font-weight: 500; font-size: 12.5px; }
/* Subordinate to the box above it: this is a history of those lines, not a second list of them. */
.rules-subheading {
  font-size: 12px; font-weight: 600; letter-spacing: .04em; color: var(--muted);
  margin: 22px 0 8px;
}
/* Grown to its content by fitRulesEditor, and draggable past the cap. */
.rules-editor { resize: vertical; min-height: 240px; }


/* Wildcards in a rule. A disclosure, not a permanent block: most rules need no pattern at all, and
   a syntax table sitting open above the editor would suggest they do. */
.rules-wildcards { margin: 10px 0 0; border: 1px solid var(--line); border-radius: 9px; background: var(--surface-soft); }
.rules-wildcards summary {
  cursor: pointer; list-style: none; padding: 8px 12px;
  font-size: 12px; font-weight: 600; color: var(--navy-2);
  display: flex; align-items: center; gap: 8px; border-radius: 9px;
}
.rules-wildcards summary::-webkit-details-marker { display: none; }
.rules-wildcards summary::before {
  content: '\25B8'; width: 17px; height: 17px; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 5px; background: #dde4ee; color: var(--navy-2); font-size: 12px; line-height: 1;
  transition: transform .16s ease;
}
.rules-wildcards[open] summary::before { transform: rotate(90deg); }
.rules-wildcards summary:hover { background: rgba(30, 45, 70, .045); }
.rules-wildcards summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.rules-wildcards-body { padding: 2px 14px 13px; font-size: 12px; line-height: 1.55; color: #3d4a60; }
.rules-wildcards-body p { margin: 0 0 8px; }
.rules-wildcards-body ul { margin: 0 0 8px; padding-left: 18px; }
.rules-wildcards-body li { margin-bottom: 5px; }
.rules-wildcards-body code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11.5px; background: #eef2f8; border-radius: 4px; padding: 1px 5px; }
.rules-wildcard-table { border-collapse: collapse; margin: 0 0 10px; width: 100%; }
.rules-wildcard-table td { padding: 5px 10px 5px 0; vertical-align: top; border-top: 1px solid var(--line); }
.rules-wildcard-table tr:first-child td { border-top: 0; }
.rules-wildcard-table td:first-child { width: 34px; }
.rules-wildcards-note { color: var(--muted); font-size: 11.5px; margin-top: 4px !important; }
@media (prefers-reduced-motion: reduce) { .rules-wildcards summary::before { transition: none; } }

/* "Neither of those" used to be dashed and transparent, quieter than the measured options on the
   reasoning that it is the right answer less often. Made uniform with the rest of the row at the
   product owner's direction: four ways to answer one question, dressed four different ways, read as
   four unrelated controls rather than as a choice. The styling now comes from .reference-choice. */

/* What the rule has to do, under the thing being corrected. Not a quote: the sentence above is the
   firm's problem, this is our advice about it, and they should not read as one block. */
.feedback-guidance {
  margin: 8px 0 0; padding: 8px 11px;
  border-left: 2px solid var(--accent); border-radius: 0 6px 6px 0;
  background: var(--accent-soft); color: #2b4a80; font-size: 12px; line-height: 1.5;
}

/* The definition box. Wider than a name field because it holds prose that reaches the AI verbatim,
   and far narrower than .modal-card-wide, which is the 1240px table viewer -- reusing that class put
   a four-line textarea across the whole screen. Specificity matches the rule it sits beside; see the
   note above .modal-card-wide about what happens when it does not. */
.modal-card.modal-card-write { width: min(580px, 94vw); max-width: none; text-align: left;
  transition: width .18s ease; }
/* Grown only when a check has produced something. The width is on the CARD rather than the column so
   the dialog stays centred as it opens out, instead of the writing box sliding left under the
   pointer somebody has just clicked with. */
.modal-card.modal-card-write.has-result { width: min(1060px, 94vw); }
.write-columns { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0; }
.has-result .write-columns { grid-template-columns: minmax(0, 300px) minmax(0, 1fr); gap: 20px; }
.write-main { min-width: 0; }
/* The result column carries its own rule and its own scroll: a long list of dropped records must not
   push Cancel and Record it off the bottom of the writing column beside it.
   Tom, 23 September 2026: "the screen scrolls and the user doesn't know there is more answer below."
   The card is already horizontal at 1060px and the content is tall rather than wide, so widening it
   further would not have helped. What was missing is any sign that the column scrolls at all -- so:
   more of it visible, a fade at the cut, and a marker that goes away at the end (see .write-more). */
.has-result .write-result { border: 0; border-left: 1px solid var(--line); border-radius: 0;
  background: transparent; margin-top: 0; padding: 0 0 0 20px; max-height: 72vh; overflow-y: auto;
  scroll-behavior: smooth; }
/* The wrapper exists only to carry the fade and the marker, which must NOT scroll with the content. */
.has-result .write-result-wrap { position: relative; min-width: 0; }
.write-result-fade { position: absolute; left: 0; right: 0; bottom: 0; height: 56px; pointer-events: none;
  background: linear-gradient(to bottom, transparent, var(--surface) 82%); opacity: 0;
  transition: opacity .15s ease; border-radius: 0 0 9px 0; }
.write-result-wrap.is-scrollable .write-result-fade { opacity: 1; }
.write-more { position: absolute; left: 50%; bottom: 10px; transform: translateX(-50%);
  display: none; align-items: center; gap: 5px; font-size: 11px; font-weight: 600; color: var(--navy);
  background: var(--surface); border: 1px solid var(--line); border-radius: 999px; padding: 4px 11px;
  box-shadow: 0 2px 8px rgba(20, 54, 90, .14); cursor: pointer; font-family: inherit; }
.write-result-wrap.is-scrollable .write-more { display: inline-flex; }
.write-more:hover { border-color: var(--accent); }

/* A preview where one of the two runs produced no result. Deliberately not the red problem box: a
   query that was stopped is not a fault in the sentence somebody just wrote, and colouring it as one
   is how a person comes to rewrite a definition that was never the problem. */
.write-unfinished { display: flex; flex-direction: column; gap: 6px; font-size: 12px; line-height: 1.55;
  color: var(--navy); background: var(--amber-soft, #fdf6e7); border-left: 2px solid var(--amber, #c98a1b);
  border-radius: 0 7px 7px 0; padding: 10px 12px; }
.write-unfinished strong { font-size: 12.5px; }
.write-unfinished .write-result-note { margin-top: 2px; }
.modal-card.modal-card-write .modal-icon { margin-bottom: 6px; }

/* The optional checks on the definition box, and what they report. */
/* Somewhere to start. Above the box, because a blank box after a warning about two readings is
   where people guess — and a guess here applies to everyone's answers from the next question on. */
.write-suggestions { display: flex; flex-direction: column; gap: 5px; margin: 4px 0 8px; }
.write-suggestions-heading { font-size: 11px; color: var(--muted); }
.write-suggestion { text-align: left; background: var(--surface-soft); border: 1px solid var(--line);
  border-radius: 8px; padding: 7px 9px; font-family: inherit; cursor: pointer;
  display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.write-suggestion:hover { border-color: var(--accent); background: var(--accent-soft); }
.write-suggestion-text { font-size: 12.5px; color: var(--navy); line-height: 1.45; }
/* The count that makes it a choice on evidence rather than on which sentence reads best. */
.write-suggestion-note { font-size: 11px; color: var(--muted); white-space: nowrap; flex: none;
  font-variant-numeric: tabular-nums; }

.write-checks { display: flex; gap: 8px; margin-top: 10px; }
.write-checks .secondary-button { font-size: 12px; padding: 5px 11px; }
.write-result { margin-top: 10px; border: 1px solid var(--line); border-radius: 9px; background: var(--surface-soft); padding: 11px 13px; }
.write-result-body { display: flex; flex-direction: column; gap: 8px; }
.write-result-label { font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
.write-result-instruction { font-size: 12.5px; line-height: 1.5; color: var(--navy); background: var(--surface); border: 1px solid var(--line); border-radius: 7px; padding: 8px 10px; }
.write-result-use { align-self: flex-start; font-size: 12px; padding: 5px 11px; }
/* A value that does not exist is the finding, not a footnote: it is the one that returns nothing. */
.write-result-problem { font-size: 12px; line-height: 1.5; color: #7a3030; background: var(--red-soft); border-left: 2px solid var(--red); border-radius: 0 6px 6px 0; padding: 8px 10px; }
.write-result-ok { font-size: 11.5px; line-height: 1.5; color: var(--green); }
.write-result-note { font-size: 11.5px; line-height: 1.5; color: var(--muted); }
.write-preview-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.write-preview-side { background: var(--surface); border: 1px solid var(--line); border-radius: 7px; padding: 8px 10px; }
.write-preview-count { font-size: 17px; font-weight: 650; color: var(--navy); font-variant-numeric: tabular-nums; margin-top: 2px; }

/* The delta, not two numbers side by side. "142 fewer" is the fact; making somebody subtract 239
   from 381 to find it is work the screen should have done. */
/* What the rule did, in words (24 Sep 2026). The stripe says which kind of verdict it is at a glance:
   changed is the accent, "can't tell" amber, nothing moved muted. */
.write-verdict { display: flex; flex-direction: column; gap: 6px; font-size: 12.5px; line-height: 1.55;
  color: var(--navy); background: var(--surface-soft); border-left: 3px solid var(--line);
  border-radius: 0 7px 7px 0; padding: 10px 12px; }
.write-verdict > strong { font-size: 14px; }
.write-verdict.is-changed { border-left-color: var(--accent); }
.write-verdict.is-varies, .write-verdict.is-not-comparable { border-left-color: var(--amber, #c98a1b); background: var(--amber-soft, #fdf6e7); }
.write-verdict .write-section-heading { margin-top: 6px; }
.write-dba-details > summary, .proposal-sql-details > summary { cursor: pointer; font-size: 12px; color: var(--muted); }
.write-dba-details[open] { display: flex; flex-direction: column; gap: 10px; }
.proposal-sql-details { margin-top: 8px; }
/* What's been settled, in three folding sections (24 Sep 2026). The summary is the heading. */
.record-section { border: 1px solid var(--line); border-radius: 10px; padding: 8px 12px; margin: 10px 0; background: var(--surface); }
.record-section-summary { cursor: pointer; font-size: 13.5px; font-weight: 650; color: var(--navy); padding: 2px 0; }
.record-section[open] > .record-section-summary { margin-bottom: 8px; }
.record-section-waiting { border-color: #f0dcad; background: var(--amber-soft, #fdf6e7); }

/* Part C: a query in plain English. Reads as prose rather than as code, and says what it is. */
.sql-explanations { display: flex; flex-direction: column; gap: 8px; }
.sql-explanation { background: var(--surface-soft, #f7f9fc); border: 1px solid var(--line); border-radius: 8px;
  padding: 8px 11px; margin: 6px 0; font-size: 12.5px; line-height: 1.55; color: var(--navy); }
.sql-explanation-heading { font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); margin-bottom: 3px; }
.sql-explanation-text { margin: 0; }
.sql-explanation.is-pending .sql-explanation-text { color: var(--muted); font-style: italic; }
.sql-explanation.is-error .sql-explanation-text { color: var(--muted); }
.sql-explanation-label { margin: 5px 0 0; font-size: 11px; color: var(--muted); }
.write-delta { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
.write-delta-figure { font-size: 22px; font-weight: 650; color: var(--navy); font-variant-numeric: tabular-nums; }
.write-delta-figure.is-fewer { color: var(--amber); }
.write-delta-figure.is-more { color: var(--accent); }
.write-delta-detail { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }

.write-section { display: flex; flex-direction: column; gap: 6px; }
.write-section-heading { font-size: 10px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--muted); }
.write-assumptions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.write-assumption { background: var(--surface); border: 1px solid var(--line); border-radius: 7px; padding: 8px 10px; }
.write-assumption.is-draft { border-color: var(--accent); }
.write-assumption-label { font-size: 10px; color: var(--muted); }
.write-assumption.is-draft .write-assumption-label { color: #2b5cbf; }
.write-assumption ul { margin: 4px 0 0; padding-left: 15px; }
.write-assumption li { font-size: 11.5px; line-height: 1.5; color: var(--ink); }
.write-assumption-none { font-size: 11.5px; line-height: 1.5; color: var(--muted); margin-top: 4px; }

/* Added and dropped read differently at a glance, which a sentence cannot do — that is the whole
   reason the shape difference is structured rather than prose. */
.write-shape { background: var(--surface); border: 1px solid var(--line); border-radius: 7px;
  padding: 8px 10px; font-size: 11.5px; line-height: 1.7; color: var(--ink); }
.write-chip { border-radius: 5px; padding: 1px 5px; font-size: 11px; white-space: nowrap;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.write-chip.is-added { background: var(--green-soft); color: var(--green); }
.write-chip.is-dropped { background: var(--red-soft); color: var(--red); }

.write-rows { width: 100%; border-collapse: collapse; background: var(--surface);
  border: 1px solid var(--line); border-radius: 7px; overflow: hidden; font-variant-numeric: tabular-nums; }
.write-rows th { background: var(--surface-soft); color: var(--muted); font-size: 10px; font-weight: 700;
  text-align: left; padding: 5px 8px; white-space: nowrap; }
.write-rows td { font-size: 11.5px; color: var(--ink); padding: 5px 8px; border-top: 1px solid var(--surface-soft); white-space: nowrap; }
.write-rows-scroll { overflow-x: auto; }
/* Said under the table, every time. These rows are on this machine and stay on it; the claim is
   cheap to make here and expensive to have omitted. */
.write-rows-note { font-size: 10.5px; line-height: 1.5; color: var(--muted); }

/* A column's real values, read on this machine so an administrator can decide whether to write them
   into its note. Shown beside the note box because that is the decision they inform. */
.column-note-values { margin-top: 5px; background: none; border: 0; padding: 0; color: var(--accent); font-size: 11.5px; cursor: pointer; text-decoration: underline; font-family: inherit; }
.column-note-values:hover { color: var(--accent-dark); }
.column-values { margin-top: 7px; padding: 9px 11px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface-soft); }
.column-values-list { display: flex; flex-wrap: wrap; gap: 6px; }
.column-value { display: inline-flex; align-items: baseline; gap: 6px; background: var(--surface); border: 1px solid var(--line); border-radius: 6px; padding: 3px 8px; font-size: 11.5px; }
.column-value-text { color: var(--navy); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
/* The count is what makes this data rather than a list -- 44 in one bucket and 7 in another is a
   different column from one evenly spread. */
.column-value-count { color: var(--muted); font-size: 10.5px; font-variant-numeric: tabular-nums; }
.column-values-note { font-size: 11.5px; line-height: 1.5; color: var(--muted); margin-top: 6px; }
.column-values-use { margin-top: 8px; font-size: 12px; padding: 5px 11px; }
.column-values-added { display: inline-block; margin-top: 8px; font-size: 11.5px; color: var(--green); font-weight: 600; }

/* Business terms. Cards rather than lines, because a term has parts and the parts are the point --
   somebody scanning should see at a glance which terms carry a SQL reading and which do not. */
.terms-list { display: flex; flex-direction: column; gap: 9px; margin: 8px 0 10px; }
.terms-empty { margin: 6px 0 10px; font-size: 12.5px; line-height: 1.55; color: var(--muted); }
/*
 * Room on the right for the pinned action, so it does not sit on top of the sentence.
 *
 * `.term-remove` is absolutely positioned in the corner, which keeps it out of the reading line —
 * but the text underneath had no idea it was there and ran straight beneath it. Rules are whole
 * sentences, so the collision landed mid-word on every card long enough to reach the corner.
 */
.term-card { position: relative; border: 1px solid var(--line); border-left: 3px solid var(--blue-soft); border-radius: 9px; background: var(--surface-soft); padding: 10px 13px; padding-right: 84px; }
.term-head { display: flex; align-items: baseline; gap: 9px; }
.term-name { font-size: 13px; font-weight: 650; color: var(--navy); }
/* Said quietly and said anyway: a term without one is the term still being translated each time. */
.term-flag { font-size: 10px; font-weight: 600; letter-spacing: .04em; color: var(--amber); background: var(--amber-soft); border-radius: 999px; padding: 2px 8px; }
.term-definition { font-size: 12.5px; line-height: 1.5; color: #3d4a60; margin-top: 4px; }
.term-sql { display: block; margin-top: 6px; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11.5px; color: var(--navy); background: var(--surface); border: 1px solid var(--line); border-radius: 6px; padding: 6px 9px; overflow-x: auto; }
.term-meta { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 7px; font-size: 11px; color: var(--muted); }
/* Board #71: the "Always apply" switch on a rule card. */
.rule-always { display: inline-flex; align-items: center; gap: 4px; cursor: pointer; }
/*
 * One pinned action per card, and only one.
 *
 * "Make this a term" reused this class and was therefore pinned to the same coordinates as "Remove",
 * so the two rendered on top of each other — both illegible, and neither reliably clickable. It
 * belongs in the flow of the nudge that explains it, which is where `.term-convert` puts it.
 */
.term-remove { position: absolute; top: 9px; right: 11px; background: none; border: 0; padding: 0; font-family: inherit; font-size: 11.5px; color: var(--muted); cursor: pointer; text-decoration: underline; }
.term-remove:hover { color: var(--red); }
/* The same look, in the flow, beside the sentence that suggests it. */
.term-convert { background: none; border: 0; padding: 0; font-family: inherit; font-size: 11.5px;
  color: var(--accent); cursor: pointer; text-decoration: underline; white-space: nowrap; }
.term-convert:hover { color: var(--accent-dark); }

/* A second, independent plan. Shown on agreement as well as disagreement: silence when the two
   agreed would leave a reader unable to tell "checked and agreed" from "never checked", and the
   first is most of what somebody about to press Right is looking for. */
.second-opinion { margin: 12px 0 0 40px; padding: 8px 11px; border-radius: 9px; border: 1px solid var(--line); font-size: 12px; line-height: 1.5; }
.second-opinion strong { display: inline; font-size: 12px; }
.second-opinion strong::after { content: " \2014 "; opacity: .55; }
.second-opinion p { display: inline; }
.second-opinion p { margin: 0; }
.second-opinion.is-agreed { background: var(--green-soft); border-color: #cceadd; color: #2b5f4a; }
.second-opinion.is-agreed strong { color: var(--green); }
.second-opinion.is-split { background: var(--amber-soft); border-color: #f0dcad; color: #6b5a33; }
.second-opinion.is-split strong { color: var(--amber); }

/* --- Preparing a database: what it will do, and what it is doing ------------------ */
.primer-plan { border:1px solid var(--line); border-radius:8px; padding:12px 14px; margin:10px 0 4px;
               background:var(--surface-soft); }
.plan-head { display:flex; align-items:baseline; justify-content:space-between; gap:12px; }
.plan-sub { margin:12px 0 2px; }
/* Board #72: a small heading inside a settings card. */
.settings-subhead { margin: 18px 0 0; font-size: 12px; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.table-choices { max-height:260px; overflow-y:auto; border:1px solid var(--line); border-radius:6px;
                 margin:8px 0 6px; background:var(--surface); }
.table-choice { display:grid; grid-template-columns:auto minmax(0,14rem) minmax(0,1fr); gap:10px;
                align-items:baseline; padding:6px 10px; border-bottom:1px solid var(--line);
                font-size:12.5px; cursor:pointer; }
.table-choice:last-child { border-bottom:0; }
.table-choice:hover { background:var(--surface-soft); }
.choice-name { font-family:ui-monospace, Consolas, monospace; font-size:12px; overflow-wrap:anywhere; }
.choice-why { opacity:.75; }

.primer-progress { border:1px solid var(--line); border-radius:8px; padding:12px 14px; margin:10px 0;
                   background:var(--surface-soft); }
.progress-head { display:flex; align-items:center; justify-content:space-between; gap:12px;
                 margin-bottom:8px; }
.progress-track { height:8px; border-radius:99px; background:var(--line); overflow:hidden; }
/* Width transitions, so a jump between stages reads as movement rather than a redraw. */
.progress-fill { height:100%; width:0; border-radius:99px; background:var(--accent);
                 transition:width .4s ease; }
.primer-actions { align-items:center; gap:14px; flex-wrap:wrap; }
.primer-actions .depth { display:flex; align-items:center; gap:6px; font-size:12.5px; }
.depth-note { margin-top:-2px; }

/* The documentation box.
   It had no width at all, so the browser fell back to its default of about twenty characters --
   a box for a sentence, offered for a data dictionary. Examples moved out of the placeholder for
   the same reason: sample text inside the field reads as content somebody has to clear first. */
.doc-input { display:block; width:100%; box-sizing:border-box; min-height:220px; resize:vertical;
             font-family:ui-monospace, Consolas, "Cascadia Mono", monospace; font-size:12.5px;
             line-height:1.5; padding:10px 12px; border:1px solid var(--line); border-radius:6px;
             background:var(--surface); color:inherit; }
.doc-input:focus { outline:2px solid var(--accent-soft); outline-offset:1px; border-color:var(--accent); }
#documentationBox { margin-top:10px; }
#documentationBox .button-row { margin-top:8px; align-items:center; }
/* Examples as their own lines, so they read as samples rather than as a paragraph of prose. */
.example { display:block; font-family:ui-monospace, Consolas, monospace; font-size:12px;
           opacity:.8; margin:3px 0 0 2px; }

/* A question about which table a document means. Shown before the findings, because answering it
   produces more of them. */
.map-question { border-left:3px solid var(--accent); padding:8px 0 8px 12px; margin:10px 0; }
.map-choice { width:100%; max-width:640px; font:inherit; font-size:12.5px; padding:5px 8px;
              border:1px solid var(--line); border-radius:5px; background:var(--surface);
              color:inherit; margin-top:4px; }

/* --- AI Expert Assistant -----------------------------------------------------------------------
   A different colour for a different mode, because a toggle position is not enough to tell somebody
   which of two things just answered them. Purple rather than the product's blue: far enough away to
   be unmistakable at a glance and on a projector, and reserved for this one purpose so it never
   competes with the accent colour that means "this is actionable".
*/
:root {
  --assist: #6b4ea8;
  --assist-soft: #7d5fbe;
  --assist-wash: #f2eefb;
  --assist-line: #d6c9ef;
}

.assist-toggle { display: inline-flex; align-items: center; gap: 7px; margin-right: auto;
  font-size: 13px; color: var(--muted); cursor: pointer; user-select: none; }
.assist-toggle input { accent-color: var(--assist); width: 15px; height: 15px; cursor: pointer; }
.assist-toggle.on { color: var(--assist); font-weight: 600; }

/* The composer itself carries the mode, so it is visible while somebody is typing rather than only
   after they have sent something. */
.composer-wrap.assist textarea { border-color: var(--assist-line); background: var(--assist-wash); }
.composer-wrap.assist .primary-button { background: var(--assist); border-color: var(--assist); }

/* Their question, in assistant mode. Same shape as an ordinary question so nothing moves; only the
   colour changes, which is the whole point. */
.message.user.assist .bubble { background: var(--assist-soft); color: #fff;
  box-shadow: 0 5px 15px rgba(107,78,168,.18); }

/* And the answer, which is prose rather than a table and should not pretend otherwise. */
.assist-answer { background: var(--assist-wash); border: 1px solid var(--assist-line);
  border-left: 3px solid var(--assist); border-radius: 10px; padding: 13px 16px; line-height: 1.55;
  white-space: pre-wrap; }
.assist-answer .assist-mark { display: block; font-size: 11px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--assist); margin-bottom: 6px; }

.example-chip.assist { border-color: var(--assist-line); background: var(--assist-wash); color: var(--assist); }

/* --- Fine-tuning readiness ---------------------------------------------------------------------
   Amber rather than red. This is not an error and the product is not broken -- it is running without
   the guidance that makes it good, which is a different thing and should not look like a failure.
*/
/* Stacked and centred rather than a row with the button pushed to one end: at the top of the panel
   the button is the thing to act on, and a control tucked against the right edge reads as a dismiss
   rather than as an invitation. */
.readiness-ribbon { margin: 0 0 14px; padding: 13px 16px 15px; border-radius: 10px;
  background: #fdf6e8; border: 1px solid #efd9a8; border-left: 3px solid #c98a1c; text-align: center; }
.readiness-text { font-size: 13px; line-height: 1.5; }
.readiness-text strong { display: block; color: #7a5410; margin-bottom: 3px; }
.readiness-text span { color: var(--muted); }
.readiness-ribbon .secondary-button { margin-top: 11px; }

.report-page { background: var(--surface-soft); border: 1px solid var(--line); border-radius: 8px;
  padding: 14px 16px; font: 12.5px/1.6 ui-monospace, Consolas, monospace; white-space: pre-wrap;
  max-height: 46vh; overflow: auto; color: var(--ink); }

/* The quiet state: same control, no accusation. A firm doing well still gets to see how far they
   have got, which is the thing that makes somebody finish. */
.readiness-ribbon.quiet { background: var(--surface-soft); border-color: var(--line);
  border-left-color: var(--line); padding: 9px 16px 11px; }
.readiness-ribbon.quiet .readiness-text strong { display: none; }
.readiness-ribbon.quiet .readiness-text span { color: var(--muted); font-size: 12.5px; }
.readiness-ribbon.quiet .secondary-button { margin-top: 8px; }

/* Sits with the other status badges. Amber only when the reading is being ignored -- the badge
   itself carries the state, so the panel below does not have to exist just to hold a button. */
/* The one badge that is a way in rather than a status, so it carries the sidebar's navy and reads as
   something to press. The amber state below still overrides it: when the reading is being ignored,
   that is the more urgent thing to say. */
.badge-readiness { cursor: pointer; background: var(--navy); color: white; border-color: var(--navy); }
.badge-readiness:hover { background: var(--navy-2); border-color: var(--navy-2); color: white; }
.badge-readiness.needs-attention { background: var(--amber-soft); color: var(--amber); border-color: #f0dcad; }

/* ── Two doors, weighted the same ────────────────────────────────────────────
 *
 * Used where the product genuinely does not know which way somebody should go: a split between the
 * two models, and an offer of a question somebody else settled. Both buttons carry identical
 * weight on purpose. Styling one as primary would be the product making a judgement it has just
 * admitted it cannot make. */
.resolve-doors {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 0.75rem;
  margin-top: 1rem;
}

.resolve-door {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding: 0.85rem 1rem;
  text-align: left;
  font: inherit;
  color: inherit;
  background: var(--surface-raised, #fff);
  border: 1px solid var(--border, #d7dbe2);
  border-radius: 10px;
  cursor: pointer;
  transition: border-color 120ms ease, background 120ms ease;
}

.resolve-door:hover { border-color: var(--accent, #2f6feb); background: var(--surface-hover, #f5f7fb); }
.resolve-door:focus-visible { outline: 2px solid var(--accent, #2f6feb); outline-offset: 2px; }
.resolve-door strong { font-size: 0.95rem; }
.resolve-door span { font-size: 0.82rem; opacity: 0.78; line-height: 1.4; }

/* ── A question somebody already settled, under other words ───────────────── */
.stabilised-offer {
  padding: 1rem 1.15rem;
  border: 1px solid var(--border, #d7dbe2);
  border-radius: 12px;
  background: var(--surface-raised, #fff);
}

.stabilised-offer-head { font-weight: 600; margin-bottom: 0.85rem; }

.stabilised-offer-pair {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 0.75rem;
}

.stabilised-offer-side {
  padding: 0.7rem 0.85rem;
  border-radius: 8px;
  background: var(--surface-sunken, #f4f6f9);
}

/* The settled one is marked, not favoured: the reader must be able to see at a glance which sentence
 * is theirs and which is the firm's, without that difference arguing for either answer. */
.stabilised-offer-side.settled { box-shadow: inset 3px 0 0 var(--accent, #2f6feb); }

.stabilised-offer-label {
  display: block;
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  opacity: 0.65;
  margin-bottom: 0.3rem;
}

.stabilised-offer-side p { margin: 0; line-height: 1.45; }
.stabilised-offer-note { margin: 0.7rem 0 0; font-size: 0.85rem; opacity: 0.8; }
.stabilised-offer-stale { margin: 0.5rem 0 0; font-size: 0.85rem; color: var(--warning-text, #8a5a00); }


/* The mark on an answer that came from a query somebody wrote and stood behind, rather than one
 * planned a moment ago. Quiet by design: it is a provenance note, not a quality claim about the
 * number, and an answer that shouts is an answer people stop reading. */
.stabilised-mark {
  margin-left: auto;
  padding: 0.15rem 0.55rem;
  font-size: 0.72rem;
  letter-spacing: 0.02em;
  border-radius: 999px;
  color: var(--accent-text, #1f4fa8);
  background: var(--accent-soft, #e8f0fe);
  border: 1px solid var(--accent-border, #c3d6f7);
  white-space: nowrap;
}

/* Ninety days without anyone looking. The database can be unchanged while what the firm means by
 * the question has moved, and no fingerprint can catch that -- so the mark stops vouching. */
.stabilised-mark.is-stale {
  color: var(--warning-text, #8a5a00);
  background: var(--warning-soft, #fdf3e0);
  border-color: var(--warning-border, #f0d9a8);
}


/* ── The DBA's bench ─────────────────────────────────────────────────────────
 *
 * Three additions only. Everything else on this card uses the form and row vocabulary the rest of
 * the product already has, which is what a new screen should do -- inventing a parallel set of
 * classes is how two screens in one product stop looking like one product. */

/* A query is code, and code in a proportional face is code somebody misreads. Tall enough to hold a
   real query without scrolling, because the whole job here is reading one before standing behind
   it. */
.sql-editor {
  min-height: 220px;
  font-family: 'Cascadia Mono', Consolas, 'SF Mono', Menlo, monospace;
  font-size: 12.5px;
  line-height: 1.55;
  tab-size: 2;
  white-space: pre;
  overflow-x: auto;
}

/* The same query, stored and being read back. Scrolls rather than wrapping, so the shape of a long
   SELECT stays legible. */
.settled-sql {
  margin: 6px 0 2px;
  padding: 8px 10px;
  max-height: 190px;
  overflow: auto;
  font-family: 'Cascadia Mono', Consolas, 'SF Mono', Menlo, monospace;
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink);
  background: var(--surface-sunken, #f5f7fb);
  border: 1px solid #e2e8f2;
  border-radius: 8px;
  white-space: pre;
}

/* Something a person needs to act on: a query written against a schema that has moved, or one
   nobody has re-checked in ninety days. */
.reference-row-warn {
  color: #8a5a00;
  font-size: 12px;
  line-height: 1.5;
}


/* Used in nine places across the markup and never defined, so all nine rendered as plain body text.
   Same role as .field-help -- a quiet line under something -- so it is given the same treatment
   rather than a second look that means the same thing. */
.muted-note { color: var(--muted); font-size: 12px; line-height: 1.5; margin-top: 6px; }

/* "No AI tokens" (board #77). Said where it is TRUE and nowhere else: these are the features that
   read the firm's own database with SQL and never call a provider, and until now the product never
   claimed it -- so an administrator weighing whether to re-run something had no way to know it was
   free. Quiet, not a badge: it is a fact about the feature, not a reason to use it. */
.no-tokens { color: var(--muted); font-size: 12px; line-height: 1.5; margin-top: 8px; }
.no-tokens strong { color: var(--ink); font-weight: 600; }

/* Naming the tables a question is about (board #77). Anchored above the composer rather than below
   it, because the composer sits at the bottom of the screen and a menu under it would be off-page. */
.composer-wrap { position: relative; }
/* --surface and --ink, not --panel and --text: those two do not exist in this stylesheet, so the
   menu rendered with NO background at all and the chat behind it showed through the options. A
   var() that names nothing falls back to nothing rather than failing loudly, which is why it looked
   deliberate. Reported by Tom, 18 Sep 2026. */
.scope-menu {
  position: absolute; bottom: calc(100% + 6px); left: 0; right: 0; z-index: 40;
  max-height: 320px; overflow-y: auto;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--radius, 8px);
  box-shadow: var(--shadow, 0 10px 30px rgba(0, 0, 0, .18));
}
.scope-option { padding: 9px 12px; cursor: pointer; border-bottom: 1px solid var(--line); background: var(--surface); }
.scope-option:last-child { border-bottom: none; }
.scope-option.is-active, .scope-option:hover { background: var(--accent-soft); }
.scope-option-name { font-weight: 650; font-size: 13.5px; display: block; color: var(--ink); }
.scope-option-meta { font-size: 11.5px; color: var(--muted); }
.scope-option-related { margin-top: 6px; display: flex; flex-wrap: wrap; gap: 6px; align-items: baseline; }
.scope-option-related-lead { font-size: 11.5px; color: var(--muted); }
.scope-related-chip {
  font-size: 11.5px; padding: 2px 8px; border-radius: 999px; cursor: pointer;
  background: var(--surface); border: 1px solid var(--line); color: var(--accent-dark);
}
.scope-related-chip:hover { border-color: var(--accent); background: var(--accent-soft); }

/* What the answer actually read, against what was asked for. Quiet where the scope was honoured;
   it only needs to be noticed when something was added, missed or not understood. */
.scope-report { font-size: 12px; color: var(--muted); margin-top: 8px; line-height: 1.55; }
.scope-report b { color: var(--ink); font-weight: 600; }
.scope-report.is-notable { color: #6b4e00; background: var(--amber-soft); border: 1px solid #f0dcad;
                           border-radius: var(--radius-sm, 6px); padding: 8px 10px; }


/* The line that reconciles the readings with the number of askings. Quiet, because it is an
   explanation of an arithmetic gap rather than a finding -- but present, because a panel showing
   two numbers that contradict each other has told the reader its figures cannot be trusted. */
.signal-footnote { margin: 6px 0 0; font-size: 12px; line-height: 1.5; color: var(--muted); }


/* Questions a firm has said do not apply to them. Set apart and quietened, because they are not
   work waiting to be done -- but still legible, because they are still questions the product
   would ask and a firm may want one back. */
.reference-group.is-inactive {
  margin-top: 26px;
  padding-top: 18px;
  border-top: 1px solid var(--line, #dfe4ea);
}

.reference-group.is-inactive .reference-row { opacity: .62; }
.reference-group.is-inactive .reference-row:hover,
.reference-group.is-inactive .reference-row:focus-within { opacity: 1; }


/* The unlock control with no card behind it. It used to sit inside the progress card and inherit
   its padding; standing alone it needs its own, or it hangs off the top of the tabs. */
.tuning-access-bare {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}


/* A finding about the DATABASE, sitting among decisions about the firm. Tinted rather than amber:
   amber on this screen means somebody reported a wrong answer, and this is not that -- nobody has
   been misled yet, and the whole point is to reach it before they are. */
.reference-row.is-data {
  background: var(--accent-soft);
  border-color: rgba(47, 111, 237, .22);
}


/* What today's answers cost. Green because it is good news and the only badge on that row that is
   -- the others report state, this one reports a saving. */
.badge-free { background: var(--green-soft); color: var(--green); border-color: #ccecdf; }


/* A heading row carrying only a count.
   .panel-heading is space-between, built for a heading on the left and a badge on the right. With
   the heading deliberately removed -- the screen header already says Business Rules -- the badge was
   the only child, so it sat hard left with the width of the card empty beside it and read as
   something that had lost its label. On the right it reads as what it is: a count for the card. */
.panel-heading.is-count-only { justify-content: flex-end; margin-bottom: 12px; }


/* What authority this browser holds. Amber rather than green: it is not an achievement, it is a
   state somebody should notice and be able to end. Pressable, because it is also the control that
   ends it -- the only way to lock again used to be closing the browser. */
.badge-role {
  background: var(--amber-soft);
  color: var(--amber);
  border-color: #f0dcad;
  cursor: pointer;
}
.badge-role:hover { filter: brightness(.97); }
.badge-role:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
.badge-role.is-admin { background: var(--red-soft); color: var(--red); border-color: rgba(200,66,66,.25); }
/* A role from the directory sign-in: a label, not a lock button. */
.badge-role.is-static, .badge-role:disabled { cursor: default; filter: none; opacity: 1; }

/* The three Trace & Support panels. Layout comes from settings-grid; this is the hook the tab
   switcher toggles, and it exists so the switcher has one class to look for. */
.trace-panel { }

/* The provider key card: which key wins, then one section per audience. */
/* A named group inside a settings card: a heading, its state, and the controls that act on it.
   Separated from the card's flow so the two provisioning steps read as one thing to do rather than
   as two buttons that happen to be adjacent. */
.settings-block { margin: 18px 0 4px; }
.settings-block > h3 { margin: 0 0 8px; }

.key-precedence { background: var(--surface-soft); border-radius: 10px; padding: 12px 14px; margin: 14px 0 20px; }
.key-precedence-head { margin: 0 0 8px; font-size: 12px; color: var(--muted); letter-spacing: 0.03em; }
.key-precedence-row { display: flex; align-items: center; gap: 10px; padding: 5px 0; font-size: 13px; }
.key-precedence-rank { width: 16px; color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }
.key-precedence-what { flex: 1; color: var(--muted); }
.key-precedence-state { color: var(--muted); font-size: 12px; white-space: nowrap; }
/* The key itself, as far as it is ever shown: prefix and last four, in the same face the provider's
   own console prints them in, so the two can be compared character by character. */
/* Spelled out, like every other monospace rule here: --mono was never defined, so this rendered in
   the body font and the marks it exists to line up did not line up. */
.key-precedence-mark { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; color: var(--muted); white-space: nowrap; }
/* The one actually in force reads as a statement of fact, so it is the only coloured thing here. */
.key-precedence-state.is-live { color: var(--green); font-weight: 600; }
/* Set, but something above it wins. Distinct from absent, and deliberately not green: it is a fact
   worth seeing — "yes, the provisioning took" — and not a state to be reassured by, because it is
   not the credential being used. */
.key-precedence-state.is-held { color: var(--text); font-weight: 500; }
.key-precedence-row:has(.is-live) .key-precedence-what { color: var(--ink); }
.key-precedence-note { margin: 10px 0 0; padding-top: 10px; border-top: 1px solid var(--line);
  font-size: 12px; color: var(--muted); line-height: 1.5; }
.key-section { margin: 0 0 18px; }
.key-section + .key-section { padding-top: 16px; border-top: 1px solid var(--line); }
.key-section-title { margin: 0 0 2px; font-size: 13px; font-weight: 600; color: var(--ink); }
/* Named but not built. Quiet on purpose: it must not compete with the boxes that do something. */
.key-federated { margin: 12px 0 0; font-size: 12px; color: var(--muted); line-height: 1.55; }
.key-federated-tag { display: inline-block; margin-right: 8px; padding: 2px 8px; border-radius: 999px;
  background: var(--surface-soft); border: 1px solid var(--line); font-size: 11px; color: var(--muted); }

/* Grant guidance beside the connection form, folded away until somebody needs it. */
.grant-help { margin: 14px 0 4px; }
.grant-help > summary { cursor: pointer; font-size: 13px; color: var(--accent); padding: 4px 0; }
.grant-sql { margin: 6px 0 10px; padding: 10px 12px; background: var(--surface-soft);
  border: 1px solid var(--line); border-radius: 8px; font-family: ui-monospace, Consolas, monospace;
  font-size: 12px; line-height: 1.6; white-space: pre; overflow-x: auto; }

/* Restoring a configuration export: what would change, before it changes. */
.import-plan { margin: 12px 0; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.import-row { display: flex; align-items: baseline; gap: 12px; padding: 8px 12px; font-size: 13px;
  border-bottom: 1px solid var(--line); }
.import-row:last-child { border-bottom: none; }
.import-action { width: 74px; flex: none; font-size: 11px; text-transform: uppercase;
  letter-spacing: 0.05em; font-weight: 600; }
.import-row.is-replace .import-action { color: var(--amber); }
.import-row.is-add .import-action { color: var(--green); }
.import-row.is-unchanged .import-action { color: var(--muted); }
.import-name { font-family: ui-monospace, Consolas, monospace; font-size: 12px; color: var(--ink); }
.import-what { color: var(--muted); font-size: 12px; }

/* Rules the save refused, shown back in full because the box no longer holds them. */
.rules-refused { margin: 8px 0 0; padding-left: 18px; display: flex; flex-direction: column; gap: 10px; }
.rules-refused li { color: var(--ink); }
.refused-why { display: block; font-size: 12px; color: var(--amber); margin-bottom: 3px; }
.refused-text { display: block; font-size: 12px; color: var(--muted); line-height: 1.5;
  background: var(--surface-soft); border: 1px solid var(--line); border-radius: 6px; padding: 6px 8px;
  white-space: pre-wrap; word-break: break-word; }
.refused-head { margin: 10px 0 4px; font-size: 13px; color: var(--amber); font-weight: 600; }
/* The two DB Tuning jobs: reading the database, and the hand-written query list. */
.dbtuning-panel { display: contents; }
.dbtuning-panel.hidden { display: none; }

/* The personal answer-detail control, beside the button it affects.
   `margin-left: auto` rather than a change to the footer's own justification: it pushes this and
   everything after it -- which is only the send button -- to the right edge, so the two stay
   together without disturbing where the hint and the mode switches already sit. */
.answer-level-bar {
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 0 auto; font-size: 12px; color: var(--muted);
}
.answer-level-bar select { width: auto; padding: 4px 8px; font-size: 12px; }
.answer-level-bar .personal-choice { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
/* Three personal choices beside the button are wider than a laptop composer: the footer wraps to a
   second row rather than folding each label onto four lines and the button onto two. */
.composer-footer { flex-wrap: wrap; }
.composer-footer > .primary-button { white-space: nowrap; margin-left: auto; padding-top: 7px; padding-bottom: 7px; }
.answer-level-bar { flex-wrap: wrap; justify-content: flex-end; }
.answer-level-bar .assist-toggle { margin-right: 0; white-space: nowrap; font-size: 12px; }
.answer-level-bar small { color: var(--muted); }

/* The answer in words. Sized above the body text because on a plain view it IS the answer, not a
   caption for the table beneath it. */
/* The sentence that answers the question, which is the thing most people actually read.
   —
   It sat flush against whatever came before it in body-text grey, so on a screen carrying a table,
   assumptions and a row count it read as one more line of apparatus rather than as the answer.
   Space above it separates it from what precedes; the darker navy lifts it off the surrounding grey
   without shouting. Deliberately not bold and not larger: it should be the first thing found, not
   the loudest thing present. */
/* Blue since 24 Sep 2026 (Tom): the navy read as black, and this sentence should stand out from
   everything around it. Only this sentence -- not the query, the table or the notes. The darker
   accent blue keeps well above the 4.5:1 contrast normal text needs on white. */
.answer-prose {
  margin: 16px 0 12px; font-size: 15px; line-height: 1.6; color: var(--accent-dark);
}

/* A settings row whose control is a select rather than a switch. Same two-column shape as
   .switch-row, which is the row it sits beside; without this the label and control stacked. */
.field-row { display: grid; grid-template-columns: minmax(10rem, 1fr) auto; gap: 12px; align-items: center; margin: 16px 0; }
.field-row strong { display: block; font-size: 13px; }
.field-row small { display: block; color: var(--muted); margin-top: 3px; line-height: 1.35; }
.field-row select { width: auto; max-width: 16rem; }

/* How a vote turns into a business rule, said where the numbers are set. An administrator who has to
   be told verbally what "stop asking after" does will configure it wrong once and distrust it
   afterwards, so the explanation lives beside the controls rather than in a manual. Set apart from
   the fields by a rule and a tint, because it is reference rather than something to change. */
.voting-explainer {
  margin: 16px 0;
  padding: 14px 16px;
  border-left: 3px solid var(--accent, #6b7f9e);
  background: var(--surface-2, rgba(127, 127, 127, 0.06));
  border-radius: 0 8px 8px 0;
  color: var(--muted);
  line-height: 1.5;
  font-size: 13px;
}
/* Folded shut: it explains a feature that is off until an administrator turns it on. */
.voting-explainer > summary { cursor: pointer; font-weight: 700; color: var(--text, inherit); }
.voting-explainer[open] > summary { margin-bottom: 10px; }
.voting-explainer p { margin: 0 0 8px; }
.voting-explainer p strong { color: var(--text, inherit); }
.voting-explainer ul { margin: 0 0 12px; padding-left: 18px; }
.voting-explainer li { margin: 6px 0; }
.voting-explainer li strong { color: var(--text, inherit); }

/* The offer under an answer: which reading was used, and the chance to say it should be another.
   Quiet by default -- it sits below a number somebody came for, and must read as an aside rather
   than as a demand before they may believe what they are looking at. */
.ballot {
  margin: 10px 0 4px; padding: 10px 12px;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--surface-soft); font-size: 13px;
}
.ballot-asked { margin: 0 0 8px; color: var(--muted); }
/* Who sees this answer. Quieter and smaller than the question, because it must be READ BEFORE
   voting without competing with the thing being asked. */
.ballot-seen-by { margin: -4px 0 8px; font-size: 11px; line-height: 1.4; color: var(--muted); }
.ballot-said { margin: 0; color: var(--muted); }
.ballot-choices { display: flex; flex-wrap: wrap; gap: 6px; }
.ballot-choice {
  font: inherit; font-size: 12px; padding: 4px 10px; cursor: pointer;
  border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface); color: var(--text, inherit);
}
.ballot-choice:hover:not(:disabled) { border-color: var(--accent, #6b7fd7); }
.ballot-choice:disabled { opacity: .5; cursor: default; }
/* "Not sure" is a real answer and must not look like giving up -- if it reads as the coward's
   option, people guess instead, and a guess is indistinguishable from agreement. */
.ballot-choice.is-unsure { font-style: italic; }
.ballot-choice.is-chosen { border-color: var(--good, #3f9d6d); color: var(--good, #3f9d6d); }
/* Board #41: the reading used, for somebody who switched asking off. A line, not a question. */
.ballot.is-informational .ballot-asked { margin: 0; }
.ballot-stop { margin-top: 8px; font-size: 11px; }

/* What went wrong, as pickable chips. Quiet until chosen, so the required correction below stays
   the visible obligation -- the buttons are for counting, the sentence is for understanding. */
.symptom-list { display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0 14px; }
.symptom {
  font: inherit; font-size: 12px; padding: 5px 10px; cursor: pointer; text-align: left;
  border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface); color: var(--muted);
}
.symptom:hover { border-color: var(--accent, #6b7fd7); }
.symptom.is-picked {
  border-color: var(--accent, #6b7fd7); color: var(--text, inherit);
  background: color-mix(in srgb, var(--accent, #6b7fd7) 12%, transparent);
}

/* Ground Truth ------------------------------------------------------------
   A results table and three states. Three rather than two on purpose: a case the judge could not
   decide has not been shown to be wrong, and painting it the same red as a genuinely wrong answer
   is the same false confidence pointed the other way. */
.gt-results { margin-top: 16px; }
.gt-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.gt-table th { text-align: left; font-weight: 650; color: #6b7a91; padding: 8px 10px; border-bottom: 1px solid var(--line); }
.gt-table td { padding: 10px; border-bottom: 1px solid var(--line); vertical-align: top; }
/* A question taken up but not yet saved, marked as such: a row that looks stored and is not would be
   the worst of both. The tint is the same one used elsewhere for "in hand, not finished". */
.gt-draft > td { background: var(--surface-soft); }
/* The table default is one clipped line per cell. A draft cell is a small form: its help ran off as
   "does activ…" and a question of the firm's own hid its "not saved yet" mark behind an ellipsis. */
.gt-draft > td { white-space: normal; max-width: none; }
.gt-draft .field-label { margin-top: 10px; }
.gt-suggestions { margin-top: 22px; border-top: 1px solid var(--line); padding-top: 14px; }
.gt-suggestion { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; padding: 9px 0; }
.gt-suggestion .gt-question { margin: 0; }
.gt-table td:first-child { width: 44%; }
.gt-expected { font-variant-numeric: tabular-nums; color: #4c5a70; }
/* Board #58: collapsed under the Leads list; figures line up, and withheld cells read as a note. */
.floor-scorecard { margin-top: 18px; border-top: 1px solid var(--line); padding-top: 12px; }
.floor-scorecard > summary { cursor: pointer; font-weight: 650; }
.floor-scorecard .gt-table td { font-variant-numeric: tabular-nums; }
.gt-mark { display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 11px; font-weight: 650; }
.gt-mark.is-clean { background: #e6f5ee; color: #1c6b4a; }
.gt-mark.is-wrong { background: #fdeaea; color: var(--red); }
.gt-mark.is-mixed { background: var(--amber-soft); color: var(--amber); }
/* Not a verdict. The planner is not deterministic and the judge refuses rather than guessing, so
   "could not judge" has to look unlike both of the answers above it. */
.gt-mark.is-unknown { background: #eef1f6; color: #5c6a80; }
.gt-changed { color: var(--amber); }
.gt-attempts { display: inline-flex; align-items: center; gap: 6px; }
.gt-editor { margin-top: 20px; }
.gt-editor summary { cursor: pointer; font-size: 12px; font-weight: 650; color: #4c5a70; }

/* The figure boxes, inside the grid. Every box carries the name of what it counts. */
.gt-question { font-size: 13px; color: #2b3648; }
.gt-pairs { display: grid; gap: 6px; }
.gt-field { display: flex; align-items: center; gap: 8px; }
.gt-field label { font-size: 12px; color: #4c5a70; min-width: 96px; }
/* Tabular figures so a column of numbers lines up and a transposed digit is visible. */
.gt-number { width: 104px; padding: 5px 8px; border: 1px solid var(--line); border-radius: 7px;
  font-size: 13px; font-variant-numeric: tabular-nums; text-align: right; }
.gt-number:focus { outline: 2px solid #6c99ff; outline-offset: 1px; }
.gt-footer { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); }
/* Board #52: when the figures were true, and where they came from, above the grid. */
.gt-pack-details { display: flex; flex-wrap: wrap; gap: 8px 18px; align-items: center; margin: 4px 0 2px; }
.gt-pack-details label { display: flex; align-items: center; gap: 8px; margin: 0; }
.gt-pack-details input[type="text"] { min-width: min(100%, 18rem); }

/* Spacing that used to be written inline in index.html. The cloud version serves this same page under
   a Content-Security-Policy that refuses inline styles, so they are named here instead; the page looks
   exactly as it did (CLOUD-POC.md, one page for both). */
.gap-below { margin-bottom: 16px; }
.flush-top { margin-top: 0; }
.gap-above { margin-top: 18px; }
.modal-actions.start { justify-content: flex-start; margin-top: 12px; }
.fill { flex: 1; }

/* The two panels only the cloud service shows (its sign-in, and the page that could not learn which
   host it is on). On the desktop they stay hidden; they wear the sidebar's navy so the first screen
   of the cloud is plainly the same product. */
.host-page { min-height: 100vh; display: grid; place-items: center; padding: 24px; background: linear-gradient(180deg, var(--navy), #0f1b2e); }
.host-card { width: 100%; max-width: 420px; padding: 30px 32px 32px; }
.host-card h1 { margin: 6px 0 10px; font-size: 22px; }
.host-card .brand-on-light { padding: 0 0 18px; }
.host-card .brand-on-light .brand-subtitle { color: var(--muted); }
.host-message { margin: 12px 0 0; color: var(--red); }
/* The user guides under Chat history (Tom, 1 Oct 2026): the same launcher look, folding open to a list. */
.guides-nav { margin-top: 6px; }
.guides-nav > summary { list-style: none; cursor: pointer; }
.guides-nav > summary::-webkit-details-marker { display: none; }
.guides-nav-list { display: grid; gap: 2px; margin: 4px 0 0 34px; }
.guides-nav-list a { color: rgba(255,255,255,.78); font-size: 12.5px; text-decoration: none; padding: 3px 6px; border-radius: 6px; }
.guides-nav-list a:hover, .guides-nav-list a:focus-visible { color: #fff; background: rgba(255,255,255,.08); outline: none; }
