/* Salesforce Lightning visual language, hand-rolled so the page has no build
 * step and no network dependency.
 *
 * Two things a financial statement needs that a generic UI kit does not give
 * you: digits that line up in a column, and a hierarchy where the result line
 * reads louder than the detail lines without shouting. Structure comes from
 * hairlines and weight, not filled boxes. */

:root {
  --brand: #0176d3;
  --brand-dark: #032d60;
  --canvas: #f3f3f3;
  --surface: #fff;
  --surface-sunk: #fafaf9;
  --hairline: #e5e5e5;
  --rule: #c9c9c9;
  --ink: #181818;
  --ink-weak: #5c5c5c;
  --ink-faint: #939393;
  --positive: #2e7d4f;
  --negative: #ba0517;
  --nav-hover: #f5f7fa;
  --nav-active: #f0f6fd;
  --radius: 0.25rem;

  /* The statement's own bands. Kept as tokens because the table is read as a
   * printed document as often as a page, and the fills have to survive the
   * theme without turning into decoration. */
  --stmt-title-bg: #1f3864;
  --stmt-group-bg: #9d7b32;
  --stmt-head-bg: #565656;
  --stmt-band-bg: #dcdcdc;
  --stmt-band-ink: #1f3864;
  --stmt-total-bg: #f0f0f0;
  --stmt-result-bg: #e6efdc;

  /* One categorical ramp, assigned in fixed order, so a category keeps its
   * colour between the donut, its legend, and anywhere else it appears. */
  --cat-1: #0176d3;
  --cat-2: #5eb4ff;
  --cat-3: #2e844a;
  --cat-4: #9d53f2;
  --cat-5: #fe9339;
  --cat-6: #06a59a;
  --cat-7: #b47c00;
  --cat-8: #e16032;
}

:root[data-theme="dark"] {
  --canvas: #16191c;
  --surface: #1c2126;
  --surface-sunk: #22282e;
  --hairline: #2f373e;
  --rule: #444d55;
  --ink: #eaeff3;
  --ink-weak: #a9b4bf;
  --ink-faint: #78848f;
  --brand: #57a3fb;
  --brand-dark: #10161b;
  --positive: #45c65a;
  --negative: #fe5c4c;
  --nav-hover: #232a31;
  --nav-active: #1b2b3d;
  /* The navy and gold survive the switch; the light fills behind bands and
   * totals cannot, so they invert into tints of the surface instead. */
  --stmt-title-bg: #16233c;
  --stmt-group-bg: #6d5522;
  --stmt-head-bg: #333b43;
  --stmt-band-bg: #2b333b;
  --stmt-band-ink: #cfe0f5;
  --stmt-total-bg: #262d34;
  --stmt-result-bg: #23301f;
  --cat-1: #57a3fb;
  --cat-2: #90d0fe;
  --cat-3: #45c65a;
  --cat-4: #c29ef1;
  --cat-5: #fe9339;
  --cat-6: #04e1cb;
  --cat-7: #f5c44e;
  --cat-8: #fe805b;
}

/* The toggle stamps data-theme on <html>; "system" defers to the OS. */
@media (prefers-color-scheme: dark) {
  :root[data-theme="system"] {
    --canvas: #16191c;
    --surface: #1c2126;
    --surface-sunk: #22282e;
    --hairline: #2f373e;
    --rule: #444d55;
    --ink: #eaeff3;
    --ink-weak: #a9b4bf;
    --ink-faint: #78848f;
    --brand: #57a3fb;
    --brand-dark: #10161b;
    --positive: #45c65a;
    --negative: #fe5c4c;
    --nav-hover: #232a31;
    --nav-active: #1b2b3d;
    --cat-1: #57a3fb;
    --cat-2: #90d0fe;
    --cat-3: #45c65a;
    --cat-4: #c29ef1;
    --cat-5: #fe9339;
    --cat-6: #04e1cb;
    --cat-7: #f5c44e;
    --cat-8: #fe805b;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--canvas);
  color: var(--ink);
  font-family: "Salesforce Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
    Roboto, Helvetica, Arial, sans-serif;
  font-size: 13px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, p, table, figure { margin: 0; }

a { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }

/* --- Global header ---------------------------------------------------- */

.hdr {
  background: var(--brand-dark);
  height: 3rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 1.25rem;
  position: sticky;
  top: 0;
  z-index: 20;
}

.hdr__brand { color: #fff; font-weight: 700; font-size: 1rem; letter-spacing: -0.01em; }

.hdr__sub {
  color: rgba(255, 255, 255, 0.7);
  font-size: 0.8125rem;
  margin-left: 0.625rem;
  padding-left: 0.625rem;
  border-left: 1px solid rgba(255, 255, 255, 0.25);
}

.hdr__right { color: rgba(255, 255, 255, 0.7); font-size: 0.75rem; }

.hdr__signout {
  color: #fff;
  margin-left: 0.875rem;
  text-decoration: underline;
  white-space: nowrap;
}

.main { padding: 1.25rem 1.5rem 5rem; }

/* --- Page header ------------------------------------------------------ */

.page-header {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  margin-bottom: 1rem;
}

.page-header__row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.875rem 1.25rem;
}

.page-header__media { display: flex; gap: 0.75rem; align-items: center; min-width: 0; }

.entity-icon {
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--radius);
  background: var(--nav-active);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.125rem;
  flex: none;
}

.page-header__eyebrow {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-weak);
  font-weight: 600;
}

.page-header__title {
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.2;
}

.page-header__meta { color: var(--ink-weak); font-size: 0.8125rem; margin-top: 0.125rem; }

.page-header__actions { display: flex; gap: 0.5rem; align-items: center; flex: none; }

/* --- KPI strip -------------------------------------------------------- */

.kpis {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(155px, 1fr));
  border-top: 1px solid var(--hairline);
}

.kpi { padding: 0.75rem 1.25rem 0.875rem; border-right: 1px solid var(--hairline); }
.kpi:last-child { border-right: none; }

.kpi__label {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-weak);
  font-weight: 600;
}

.kpi__value {
  font-size: 1.4375rem;
  font-weight: 300;
  line-height: 1.2;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  margin-top: 0.1875rem;
}

.kpi__value--na { font-size: 0.9375rem; color: var(--ink-faint); font-weight: 400; }
.kpi__sub { font-size: 0.75rem; color: var(--ink-weak); margin-top: 0.1875rem; }

/* --- Cards ------------------------------------------------------------ */

.stack { display: flex; flex-direction: column; gap: 1rem; }

.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
@media (max-width: 900px) { .two-col { grid-template-columns: 1fr; } }

.card {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
}

.card__header {
  padding: 0.75rem 1.25rem;
  border-bottom: 1px solid var(--hairline);
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
}

.card__title { font-size: 0.9375rem; font-weight: 700; }
.card__sub { font-size: 0.75rem; color: var(--ink-weak); margin-top: 0.125rem; max-width: 78ch; }
.card__body { padding: 1rem 1.25rem 1.25rem; }
.card__body--flush { padding: 0; }

/* --- Badges and buttons ----------------------------------------------- */

.badge {
  display: inline-block;
  padding: 0.125rem 0.5rem;
  border-radius: 0.75rem;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

.badge--success { background: color-mix(in srgb, var(--positive) 18%, transparent); color: var(--positive); }
.badge--warning { background: color-mix(in srgb, #fe9339 20%, transparent); color: #a06000; }
.badge--error   { background: color-mix(in srgb, var(--negative) 18%, transparent); color: var(--negative); }
.badge--quiet   { background: var(--surface-sunk); color: var(--ink-weak); }

.btn {
  display: inline-block;
  padding: 0.25rem 0.75rem;
  border: 1px solid #c9c9c9;
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--brand);
  font-size: 0.8125rem;
  font-weight: 400;
  cursor: pointer;
  line-height: 1.5;
}

.btn:hover { background: var(--surface-sunk); text-decoration: none; }
.btn--active { background: var(--brand); border-color: var(--brand); color: #fff; font-weight: 600; }
.btn--active:hover { background: #014486; }

.btn-row { display: flex; gap: 0.375rem; flex-wrap: wrap; }

/* --- Tables ----------------------------------------------------------- */

table { width: 100%; border-collapse: collapse; }

thead th {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ink-weak);
  font-weight: 600;
  text-align: left;
  padding: 0.5rem 1.25rem;
  border-bottom: 1px solid var(--rule);
  white-space: nowrap;
}

tbody td, tbody th {
  padding: 0.375rem 1.25rem;
  border-bottom: 1px solid var(--hairline);
  text-align: left;
  font-weight: 400;
  vertical-align: baseline;
}

tbody tr:hover td, tbody tr:hover th { background: var(--surface-sunk); }

.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.muted { color: var(--ink-weak); }
.mono { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 0.75rem; color: var(--ink-weak); }

.row-section th {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 700;
  color: var(--ink-weak);
  padding-top: 0.875rem;
  border-bottom: 1px solid var(--hairline);
  background: var(--surface-sunk);
}

.row-subtotal td, .row-subtotal th {
  font-weight: 600;
  border-top: 1px solid var(--rule);
  border-bottom: none;
}

/* The double rule under the result is the accounting convention, and it costs
 * no color. */
.row-result td, .row-result th {
  font-weight: 700;
  font-size: 0.875rem;
  border-top: 3px double var(--rule);
  border-bottom: none;
  padding-top: 0.5rem;
  padding-bottom: 0.625rem;
}

.delta { font-variant-numeric: tabular-nums; font-weight: 600; }
.delta--positive { color: var(--positive); }
.delta--negative { color: var(--negative); }
.delta--neutral { color: var(--ink-faint); }

.code { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-weight: 600; color: var(--brand); }

/* --- Chart ------------------------------------------------------------ */

.chart svg { width: 100%; height: auto; display: block; }
/* A small viewBox stretched across a wide card turns 10px type into 20px. The
 * three-bar charts hold their own size and centre instead. */
.chart--compact svg { max-width: 460px; margin: 0 auto; }
.gridline { stroke: var(--hairline); stroke-width: 1; }
.axis-label { font-size: 10px; fill: var(--ink-faint); }
.bar { fill: var(--cat-2); opacity: .85; }
.bar:hover { opacity: 1; }
.bar--active { fill: var(--brand); }
/* One colour per year in the grouped occupancy chart, taken from the shared
 * categorical ramp so a year keeps its colour wherever it appears. */
.bar--series1 { fill: var(--cat-1); }
.bar--series2 { fill: var(--cat-2); }
.bar--series3 { fill: var(--cat-3); }
.chart-band { fill: var(--nav-active); }
.bar--missing { fill: var(--surface-sunk); stroke: var(--hairline); stroke-dasharray: 2 2; }
.chart-note { margin-top: 0.625rem; color: var(--ink-weak); font-size: 0.75rem; max-width: 72ch; }

/* --- States ----------------------------------------------------------- */

.empty { padding: 0.5rem 0 0.75rem; max-width: 62ch; color: var(--ink-weak); }
.empty__hint { color: var(--ink-faint); font-size: 0.75rem; margin-top: 0.375rem; }
.loading { padding: 3rem 1.25rem; color: var(--ink-faint); }

.alert {
  background: #fedbd8;
  border: 1px solid #ea001e;
  border-radius: var(--radius);
  padding: 0.75rem 1rem;
  color: #8e030f;
}

.footnote { color: var(--ink-faint); font-size: 0.75rem; padding: 0 1.25rem 1rem; }

/* --- Ratios, compare matrix, roll-up ---------------------------------- */

.omitted { margin: 0; padding-left: 1.1rem; color: var(--ink-faint); font-size: 0.75rem; }
.omitted li { margin-bottom: 0.1875rem; }

.formula-hint {
  display: block;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.6875rem;
  color: var(--ink-faint);
  font-weight: 400;
}

/* The leader cell is marked by weight and a hairline underline rather than a
 * fill, so a column of numbers still scans as a column. */
.cell-leader {
  font-weight: 700;
  color: var(--brand-dark);
  box-shadow: inset 0 -2px 0 var(--brand);
}

/* The laggard cell is marked the same way and in the opposite colour: a red
 * hairline underline, and NOTHING ELSE. Deliberately not `--negative` on the
 * number itself -- these cells hold ratios, and a red figure in a financial
 * table reads as a negative VALUE rather than as a worst-in-row, which is a
 * different claim and the one a reader would believe first. The underline is
 * the whole signal; `.cell-leader`'s weight is not mirrored either, because
 * two competing emphases in one row is how neither gets read. */
.cell-laggard { box-shadow: inset 0 -2px 0 var(--negative); }
.band {
  display: inline-block;
  margin-left: 0.375rem;
  padding: 0 0.375rem;
  border-radius: 0.625rem;
  font-size: 0.625rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.band--healthy { background: color-mix(in srgb, var(--positive) 18%, transparent); color: var(--positive); }
.band--watch   { background: color-mix(in srgb, #fe9339 20%, transparent); color: #a06000; }
.band--problem { background: color-mix(in srgb, var(--negative) 18%, transparent); color: var(--negative); }

/* Wide tables scroll inside their own container; the page body never does. */
.scroll-x { overflow-x: auto; }
.scroll-x table { min-width: 720px; }

/* --- Compare picker ---------------------------------------------------- */

.picker__search { margin-bottom: 0.75rem; }
.picker__search input {
  width: 100%;
  max-width: 22rem;
  padding: 0.375rem 0.625rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  font: inherit;
  background: var(--surface);
  color: var(--ink);
}
.picker__search input::placeholder { color: var(--ink-faint); }
.picker__search input:focus {
  outline: 2px solid var(--brand);
  outline-offset: -1px;
  border-color: var(--brand);
}

/* Fifty-four rows in one column would be a scroll of its own. The grid keeps
 * the whole portfolio in view on a wide screen and collapses to one column on
 * a phone. */
.picker {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: 0.125rem 1rem;
  max-height: 21rem;
  overflow-y: auto;
}
/* THE PICKER THAT IS THE WHOLE SCREEN.
 *
 * `.picker` caps itself at 21rem because everywhere it was first used it
 * shares a card with something else -- Compare's own controls, Access
 * Control's grants -- and an uncapped 54-row grid would push that off the
 * page. The quarterly narrative's picker shares its card with nothing: its
 * only job is choosing a property, so the cap hides two thirds of the
 * portfolio behind a scroll for no gain. This lifts it there and nowhere
 * else. */
.picker--full { max-height: none; }
.picker__item {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  padding: 0.3125rem 0.5rem;
  border-radius: var(--radius);
  cursor: pointer;
}
.picker__item:hover { background: var(--nav-hover); }
.picker__item input { margin-top: 0.1875rem; accent-color: var(--brand); }
.picker__item--off { cursor: not-allowed; opacity: 0.55; }
.picker__item--off:hover { background: transparent; }
.picker__body { display: flex; flex-direction: column; min-width: 0; }
.picker__name {
  font-size: 0.8125rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.picker__meta {
  font-size: 0.6875rem;
  color: var(--ink-weak);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.picker__empty { color: var(--ink-faint); font-size: 0.8125rem; padding: 0.5rem 0; }

/* The metric name is what makes a row legible, so it stays put while the
 * property columns scroll under it. Without this a fifty-four column matrix
 * is unreadable past the third property. */
.matrix th[scope="row"], .matrix thead th:first-child {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--surface);
  min-width: 13rem;
}
.matrix tbody tr:hover th[scope="row"] { background: var(--surface-sunk); }

/* A section heading spans every column, which makes the cell itself wider than
 * the viewport: sticky has no room to hold it and the label scrolls off with
 * the table. Pinning the label inside the cell is what actually keeps "Debt"
 * or "Credit" on screen at the fortieth property. The inset matches the cell
 * padding so it stays in line with the metric names below it. */
.matrix .row-section th { position: static; }
.matrix .row-section__label {
  position: sticky;
  left: 1.25rem;
  display: inline-block;
}

/* --- Shell and sidebar ------------------------------------------------ */

.shell { display: flex; align-items: flex-start; }

.sidebar {
  width: 236px;
  flex: none;
  background: var(--surface);
  border-right: 1px solid var(--hairline);
  min-height: calc(100vh - 3rem);
  position: sticky;
  top: 3rem;
  max-height: calc(100vh - 3rem);
  overflow-y: auto;
  padding-bottom: 2rem;
}

.sidebar__search { padding: 0.75rem 0.625rem 0.375rem; }

.sidebar__search input {
  width: 100%;
  padding: 0.375rem 0.625rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  font: inherit;
  background: var(--surface);
  color: var(--ink);
}

.sidebar__search input::placeholder { color: var(--ink-faint); }
.sidebar__search input:focus {
  outline: 2px solid var(--brand);
  outline-offset: -1px;
  border-color: var(--brand);
}

.sidebar__heading {
  font-size: 0.625rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--ink-faint);
  font-weight: 600;
  padding: 0.875rem 0.875rem 0.25rem;
}

.sidebar__empty { padding: 0.5rem 1rem; color: var(--ink-faint); font-size: 0.75rem; }

.nav-item {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  padding: 0.375rem 0.875rem;
  color: var(--ink);
  border-left: 3px solid transparent;
  text-decoration: none;
}

.nav-item:hover { background: var(--nav-hover); text-decoration: none; }

/* The active asset is marked by a rule and weight rather than a fill, so the
 * list still reads as a list. */
.nav-item--active {
  border-left-color: var(--brand);
  background: var(--nav-active);
}

.nav-item--active .nav-item__name { font-weight: 700; color: var(--brand-dark); }
.nav-item--disabled { opacity: 0.45; cursor: default; }
.nav-item--rollup { padding-top: 0.4375rem; padding-bottom: 0.4375rem; }

.nav-item__icon { color: var(--ink-faint); font-size: 0.8125rem; line-height: 1.4; }
.nav-item__body { min-width: 0; }

/* Long legal entity names wrapped to three lines and made the list twice as
 * tall as it needed to be. One line each, ellipsised, with the full value on
 * hover. */
.nav-item__name {
  display: block;
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.35;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.nav-item__meta {
  display: block;
  font-size: 0.6875rem;
  color: var(--ink-faint);
  line-height: 1.35;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.main { flex: 1 1 auto; min-width: 0; max-width: 1600px; margin-right: auto; }

.hdr__toggle {
  display: none;
  background: none;
  border: none;
  color: #fff;
  font-size: 1.125rem;
  cursor: pointer;
  margin-right: 0.75rem;
  padding: 0;
}

@media (max-width: 860px) {
  .sidebar { display: none; }
  .sidebar--open { display: block; position: fixed; z-index: 30; height: 100%; }
  .hdr__toggle { display: block; }
}

/* --- Metric tiles ----------------------------------------------------- */

.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 1px;
  background: var(--hairline);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
}

.tile { background: var(--surface); padding: 0.625rem 0.875rem 0.75rem; }

.tile__label {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ink-weak);
  font-weight: 600;
}

.tile__value {
  font-size: 1.125rem;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  margin-top: 0.1875rem;
  letter-spacing: -0.01em;
}

.band-text--healthy { color: var(--positive); }
.band-text--watch   { color: #a06000; }
.band-text--problem { color: var(--negative); }

/* --- Layout: two columns where the content earns it -------------------- */

/* The statement is tall and narrow; the charts beside it are short and wide.
 * Stacking them wastes half the viewport and pushes the visuals below the
 * fold. */
.split {
  display: grid;
  grid-template-columns: minmax(0, 1.55fr) minmax(320px, 1fr);
  gap: 1rem;
  align-items: start;
}

.split__col { display: flex; flex-direction: column; gap: 1rem; min-width: 0; }

@media (max-width: 1140px) {
  .split { grid-template-columns: 1fr; }
}

/* --- Theme toggle ----------------------------------------------------- */

.theme-toggle {
  display: inline-flex;
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 1rem;
  overflow: hidden;
}

.theme-toggle button {
  background: none;
  border: none;
  color: rgba(255, 255, 255, 0.72);
  font: inherit;
  font-size: 0.6875rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 0.1875rem 0.625rem;
  cursor: pointer;
}

.theme-toggle button[aria-pressed="true"] {
  background: rgba(255, 255, 255, 0.18);
  color: #fff;
  font-weight: 700;
}

.hdr__right { display: flex; align-items: center; gap: 0.875rem; }

/* --- Grouped bar chart (year over year) -------------------------------- */

.chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.875rem;
  margin-top: 0.625rem;
  font-size: 0.75rem;
  color: var(--ink-weak);
}

.chart-legend span { display: inline-flex; align-items: center; gap: 0.375rem; }

.swatch {
  width: 0.625rem;
  height: 0.625rem;
  border-radius: 2px;
  display: inline-block;
  flex: none;
}

.bar-prior   { fill: var(--cat-2); }
.bar-current { fill: var(--cat-1); }
.bar-label   { font-size: 10px; fill: var(--ink-weak); font-variant-numeric: tabular-nums; }
.bar-group   { font-size: 11px; fill: var(--ink); }

/* --- Donut ------------------------------------------------------------ */

.donut-wrap { display: flex; gap: 1.25rem; align-items: center; flex-wrap: wrap; }
.donut { flex: none; }
.donut__hole-value {
  font-size: 13px;
  font-weight: 700;
  fill: var(--ink);
  font-variant-numeric: tabular-nums;
}
.donut__hole-label { font-size: 9px; fill: var(--ink-faint); text-transform: uppercase; }

.donut-legend { flex: 1; min-width: 190px; display: flex; flex-direction: column; gap: 0.1875rem; }

.donut-legend__row {
  display: grid;
  grid-template-columns: 0.625rem 1fr auto;
  gap: 0.5rem;
  align-items: center;
  font-size: 0.75rem;
}

.donut-legend__pct {
  font-variant-numeric: tabular-nums;
  color: var(--ink-weak);
  font-weight: 600;
}

/* --- Ranked bars ------------------------------------------------------ */

.ranked { display: flex; flex-direction: column; gap: 0.3125rem; }

.ranked__row {
  display: grid;
  grid-template-columns: minmax(120px, 190px) 1fr auto;
  gap: 0.75rem;
  align-items: center;
  font-size: 0.8125rem;
}

.ranked__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.ranked__track {
  background: var(--surface-sunk);
  border-radius: 2px;
  height: 0.875rem;
  overflow: hidden;
}

.ranked__fill { height: 100%; border-radius: 2px; }
.ranked__fill--healthy { background: var(--positive); }
.ranked__fill--watch   { background: #fe9339; }
.ranked__fill--problem { background: var(--negative); }
.ranked__value { font-variant-numeric: tabular-nums; font-weight: 600; }

/* --- Scatter ---------------------------------------------------------- */

.dot { cursor: pointer; }
.dot--healthy { fill: var(--positive); }
.dot--watch   { fill: #fe9339; }
.dot--problem { fill: var(--negative); }
.axis-line { stroke: var(--hairline); }

/* A bare property code is an identifier, not a name; set it as one so the eye
 * does not read it as a building. */
.nav-item__name--code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.75rem;
  letter-spacing: 0.01em;
}

/* --- Operating statement table ---------------------------------------- */

.statement { min-width: 860px; }

/* The banded statement: a titled block, then a band naming each period, then
 * the columns. The bands do the work the eye needs at a glance -- which half
 * of the table am I in, and is this a line, a total, or the result. */
.card--statement { overflow: hidden; }

.statement__title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  background: var(--stmt-title-bg);
  color: #fff;
  padding: 0.625rem 1.25rem;
}
.statement__title h2 {
  font-size: 0.9375rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.statement__title span { font-weight: 600; text-transform: none; opacity: 0.85; }

/* Fifteen rows is enough to lose the header on the way down. The sticky rule
 * comes first so the band colours below it win: a later rule of equal weight
 * setting a surface background is what blanked the gold band. */
.statement thead th {
  position: sticky;
  z-index: 2;
}

.statement__groups th {
  background: var(--stmt-group-bg);
  color: #fff;
  text-align: center;
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  border-bottom: none;
  padding: 0.3125rem 1.25rem;
  top: 0;
}

.statement__cols th {
  background: var(--stmt-head-bg);
  color: #fff;
  font-size: 0.6875rem;
  letter-spacing: 0.04em;
  text-transform: none;
  border-bottom: none;
  top: 1.55rem;
}

.col-group-start { border-left: 1px solid var(--hairline); }
.statement__groups .col-group-start,
.statement__cols .col-group-start { border-left: 1px solid rgba(255, 255, 255, 0.35); }

/* On the navy bar the success green is unreadable, so the badge borrows the
 * bar's own contrast instead of the page's. */
.statement__title .badge {
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
}

/* Section band, subtotal, result: three weights of emphasis, each a fill
 * rather than a different type size, so the columns keep one rhythm. */
.statement .row-band th {
  background: var(--stmt-band-bg);
  color: var(--stmt-band-ink);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.4375rem 1.25rem;
  border-bottom: none;
}
.statement .row-gap td { padding: 0.375rem 0; border-bottom: none; }

.statement .row-subtotal td, .statement .row-subtotal th {
  background: var(--stmt-total-bg);
  color: var(--stmt-band-ink);
}
.statement .row-result td, .statement .row-result th {
  background: var(--stmt-result-bg);
  color: var(--stmt-band-ink);
  border-top: 1px solid var(--rule);
}
.statement tbody tr:hover td, .statement tbody tr:hover th { background: var(--nav-hover); }
.statement .row-band:hover th,
.statement .row-subtotal:hover td, .statement .row-subtotal:hover th { background: var(--stmt-total-bg); }
.statement .row-result:hover td, .statement .row-result:hover th { background: var(--stmt-result-bg); }

.statement tbody td,
.statement tbody th { padding-top: 0.3125rem; padding-bottom: 0.3125rem; }

.cell-label { position: relative; overflow: hidden; }
.cell-label__text { position: relative; z-index: 1; }

.delta__arrow {
  font-style: normal;
  font-size: 0.625rem;
  margin-right: 0.1875rem;
  vertical-align: 1px;
}

/* The lifted prior-year label is set quieter so the pair still reads as
 * "prior, then current" once they are no longer on the same line. */
.bar-label--prior { fill: var(--ink-faint); }

/* --- Account drill --------------------------------------------------------
 *
 * The disclosure lives inside the label rather than in a column of its own,
 * because the statement already spends its width on numbers. The caret is the
 * only new affordance on the table; everything else in the panel reuses the
 * type, rules and colour the statement already established.
 */
.drill-toggle {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: baseline;
  gap: 0.375rem;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.drill-toggle:hover .cell-label__text { text-decoration: underline; }
.drill-toggle:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: 2px;
}

/* A CSS triangle rather than a glyph, so it cannot pick up the row's font
 * fallback and land at a different size in each browser. */
.drill-toggle__caret {
  flex: none;
  width: 0;
  height: 0;
  border-left: 4px solid var(--ink-faint);
  border-top: 3.5px solid transparent;
  border-bottom: 3.5px solid transparent;
  transform: translateY(-1px);
  transition: transform 0.12s ease;
}

.drill-toggle[aria-expanded="true"] .drill-toggle__caret {
  border-left: 3.5px solid transparent;
  border-right: 3.5px solid transparent;
  border-top: 4px solid var(--brand);
  border-bottom: 0;
  transform: translateY(1px);
}

@media (prefers-reduced-motion: reduce) {
  .drill-toggle__caret { transition: none; }
}

.drill-row > td {
  padding: 0;
  background: var(--surface-sunk);
  border-bottom: 1px solid var(--hairline);
}

/* The panel is inset from the left so it reads as belonging to the row above
 * it rather than as a new section of the statement. */
.drill {
  padding: 0.625rem 1rem 0.75rem 2rem;
  border-left: 2px solid var(--brand);
}

.drill__table { min-width: 0; }
.drill__table thead th {
  position: static;
  font-size: 0.625rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  background: none;
}
.drill__table tbody th,
.drill__table tbody td {
  padding-top: 0.1875rem;
  padding-bottom: 0.1875rem;
  font-size: 0.75rem;
  border-bottom: none;
}
.drill__table tbody tr:hover th,
.drill__table tbody tr:hover td { background: var(--surface); }

.drill__code { width: 1%; white-space: nowrap; padding-right: 0.75rem; }

.drill__recon {
  margin-top: 0.5rem;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.4375rem;
  font-size: 0.6875rem;
  color: var(--ink-weak);
  max-width: 88ch;
}

.drill__empty {
  font-size: 0.75rem;
  color: var(--ink-weak);
  padding: 0.25rem 0;
}

/* A quiet divider inside a card body, for a second group of tiles that is
 * related to the first but measures something different. */
.subhead {
  margin: 1.125rem 0 0.5rem;
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 700;
  color: var(--ink-weak);
}

/* --- Form fields ------------------------------------------------------------
 *
 * ADDED, NOT PORTED -- deliberately, and this note is here so the next reader
 * takes it for an addition rather than for drift. Every rule above came over
 * verbatim from an app that had no forms in it: two search boxes were the whole
 * of its text input, so there was no rule for a labelled field, and every admin
 * form written since had to improvise one out of `.picker__search` and a
 * `.subhead` label. A <label> is inline by default and `.subhead` sets no
 * display, so each of those labels sat BESIDE its input and the input began
 * wherever the label's text happened to run out. "ISSUER" is short and "EMAIL
 * DOMAINS" is long: that, and nothing else, is why the four fields on the
 * sign-in screen started at four different x positions. What was missing was a
 * primitive, so this is a primitive rather than four spacing fixes.
 *
 * One field is one `.field`: the micro-label on its own line, the control under
 * it on the field's left edge, and the space between fields carried by the
 * wrapper -- which is also what keeps a row of buttons and the button that
 * submits them from reading as one cluster. The label is matched by ELEMENT as
 * well as by class, so a field written later cannot bring the inline label back
 * by forgetting a class name. The control keeps the border, radius and brand
 * focus ring this sheet already had -- those were never the problem -- and the
 * same 22rem measure as the picker's search box, so a field and a search box in
 * one app are one width. */
.field { margin-bottom: 0.875rem; }

.field label,
.field .subhead {
  display: block;
  margin: 0 0 0.25rem;
}

.field input {
  width: 100%;
  max-width: 22rem;
  padding: 0.375rem 0.625rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  font: inherit;
  background: var(--surface);
  color: var(--ink);
}

.field input::placeholder { color: var(--ink-faint); }

.field input:focus {
  outline: 2px solid var(--brand);
  outline-offset: -1px;
  border-color: var(--brand);
}

/* A hint that explains one field belongs to that field, so it sits on the
 * field's left edge rather than on the card inset `.footnote` carries for the
 * notes that sit under a whole card. */
.field .footnote { padding: 0.25rem 0 0; }

/* --- A value that is also its own filter ------------------------------------
 *
 * ADDED, NOT PORTED, and for the same reason as the fields above: this sheet
 * has exactly one control, `.btn`, so a screen that wants a quieter one has to
 * either invent it or shout. The audit log shouted. It drew a bordered `.btn`
 * under the WHO and the WHAT of every row -- fourteen of them on a page of
 * seven entries -- and a ledger whose buttons are read before its entries has
 * stopped being a ledger. The action is worth keeping, since one click narrows
 * the whole log to a person or to a record, so what changes is its weight
 * rather than its existence: the VALUE becomes the control and the row goes
 * back to being text.
 *
 * The affordance is a dotted rule under the value. It is there at rest rather
 * than revealed on hover, because a control found by accident is one most
 * readers never find; it is a RULE and not a colour, so it survives being
 * printed and being read by somebody who does not see the brand blue; and the
 * control stays a <button>, so it is in the tab order with the same
 * `:focus-visible` ring the account drill uses for the same job. */
.cell-filter {
  padding: 0;
  border: 0;
  border-bottom: 1px dotted var(--rule);
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.cell-filter:hover { color: var(--brand); border-bottom-color: var(--brand); }

.cell-filter:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: 2px;
}

/* --- A question typed as prose, and the answer that comes back --------------
 *
 * ADDED, NOT PORTED, and marked as an addition for the reason the two blocks
 * above are: everything before them came over verbatim from an app that had
 * neither forms nor an assistant in it. This block is the assistant's, and the
 * gap it closes is exact. **This sheet styled no <textarea>.** Two search boxes
 * were the whole of that app's text input; `.field` above styles `input` and
 * says so; so a screen that wanted a QUESTION typed had one control available
 * to it, and the Ask screen duly shipped a question box the width of a search
 * field with its label floated off to the left of it. A question is prose. It
 * needs room to be written and read back, and that is a missing primitive
 * rather than a screen to be talked out of wanting one.
 *
 * Everything but the shape is `.field input`'s -- the same border, radius,
 * ground and brand focus ring -- because a field and a question box in one app
 * are one control at two heights and not two controls. Two things do differ.
 * The measure is wider than the 22rem a field carries, because 22rem of a
 * sentence is four words to a line. And it resizes VERTICALLY: a long question
 * grows its box instead of scrolling inside it, and a reader can take it
 * further, while sideways would break the card it sits in. */
.field textarea {
  display: block;
  width: 100%;
  max-width: 46rem;
  min-height: 4.25rem;
  padding: 0.375rem 0.625rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  font: inherit;
  line-height: 1.5;
  background: var(--surface);
  color: var(--ink);
  resize: vertical;
}

.field textarea::placeholder { color: var(--ink-faint); }

.field textarea:focus {
  outline: 2px solid var(--brand);
  outline-offset: -1px;
  border-color: var(--brand);
}

/* THE ANSWER, IN THE PARAGRAPHS ITS RENDERER WROTE.
 *
 * `yardy/assistant/say.py` is the only renderer inside spec §6's
 * no-invented-numbers guarantee, and it now emits the answer in three parts --
 * the report, a line per row of it, then what the report holds -- separated by
 * newlines that are `template` fragments carrying whitespace and nothing else.
 * `pre-line` is what prints them. The alternative was for the client to split
 * the prose up and lay the pieces out, which is a second renderer in a second
 * language reading a structure the first one only implies: the exact defect
 * the guarantee exists to prevent, and it would have bought a margin.
 *
 * The measure is the only other thing here, and it is the same reason
 * `.card__sub` carries one: a hundred-and-forty-character line of a
 * twelve-month grid is a line a reader loses their place in. No type scale of
 * its own -- the answer is read in the same face as the tables it is about,
 * and an assistant that grew its own typography would read as a second product
 * inside this one. */
.answer {
  white-space: pre-line;
  max-width: 88ch;
}

/* ONE CITATION, AND THE FIGURES READ UNDER IT.
 *
 * THE ONE PLACE THIS SCREEN IS ALLOWED TO BE LOUD. A citation is the thing
 * this assistant has that a chat assistant does not, and it was being drawn as
 * the quietest possible thing: a source family, a period and a batch list
 * repeated verbatim beside every figure -- eighty-four cells of identical text
 * on a twenty-eight-figure answer, which a reader stops seeing by the third
 * row. Repetition was not the mistake; a citation belongs to a figure and an
 * answer that ever draws on two queries must never be able to acquire one
 * shared citation by default. So the figures are GROUPED BY THE CITATION THEY
 * CARRY, and each group states it once, in the tile treatment the report
 * screen's own "Source and period" card already uses. Two citations render as
 * two of these; the shared one is derived from the figures rather than assumed
 * of them.
 *
 * The accent rule is `.drill`'s, at the same weight and colour: it is this
 * sheet's existing way of saying "everything to the right of this belongs to
 * one thing", and it is a RULE rather than a fill, so the grouping survives
 * being printed and being read by somebody who does not see the brand blue.
 * The heading above each list is a `.subhead`, which is already the sheet's
 * answer for a second group inside one card body. */
.cite {
  border-left: 2px solid var(--brand);
  padding-left: 1rem;
}

/* Two citations are two blocks, not one long one. The gap is the card body's
 * own rhythm rather than a new spacing token. */
.cite + .cite { margin-top: 1.5rem; }

/* --- The assistant, reachable from every page ------------------------------
 *
 * ADDED, NOT PORTED, and the fourth block in this sheet that is. THIRD SHAPE
 * for this one control: sub-project 11b shipped a header word, the product
 * owner moved it to a floating corner, and this pass moves it again -- a
 * PLACEMENT change each time, never a second implementation of the assistant
 * itself.
 *
 * WHY THE CORNER LEFT. It covered, at most, the corner of a table's last row
 * or two -- accepted at the time as a small and constant cost, but a long
 * holdings table puts exactly that corner under a reader's eye more often
 * than the previous reasoning gave it credit for. The product owner's
 * standard for this revision is not "small enough to accept" but "none",
 * which a corner-anchored control sitting IN FRONT of the page cannot give,
 * whatever its footprint. An edge tab that only ever covers the strip of
 * viewport nearest the edge -- never the table beneath the pointer -- can.
 *
 * THE TAB IS AN EDGE AFFORDANCE, VERTICALLY CENTRED. `.ask-tab` is fixed to
 * `right: 0` and centred on the viewport's height (`top: 50%`, a transform to
 * pull its own height back over that point) rather than pinned to the top or
 * the bottom. Both of those were considered and rejected: the top of the
 * right edge is the header's own territory (`.hdr__right` already carries
 * Sign out and the theme toggle up there, at `top: 0`), and the bottom of a
 * tall page is precisely the table-row problem this revision exists to
 * retire, just moved from the corner to the foot of the edge instead of out
 * of it. The vertical middle is neither: it is clear on every page this
 * control is offered on, it does not compete with the header for the same
 * strip of edge, and it is where a reader's eye returns to after scrolling in
 * either direction, which is also the most legible place for a control meant
 * to be found without hunting for it.
 *
 * NO CHAT CLICHE, STILL. A plain rounded tab in `--brand`, this sheet's one
 * accent colour, rounded at `--radius` on the page-facing corners only -- the
 * same token `.hdr__signout` and every primary control on this sheet already
 * carries -- carrying `LAUNCHER_LABEL` itself ("Ask") rather than an icon this
 * product draws nowhere else. No bounce, no sparkle, no gradient, no pulsing
 * dot.
 *
 * THE PANEL IS NOW AN OVERLAY, AND THAT IS THE OTHER HALF OF THIS REVISION.
 * The product owner's requirement is that the page layout must not move by a
 * pixel when the panel opens -- no reflow, no narrower main column, no
 * shrunk table -- and the only way to guarantee that is for the panel to sit
 * OUTSIDE the page's flow entirely rather than displacing it, which is what
 * `.ask-dock` does now: `position: fixed`, anchored to the same right edge as
 * the tab, stacked above the page rather than inserted into it. It starts
 * below `.hdr`'s own height (`top: 3rem`, the same measure `.sidebar`'s sticky
 * offset already uses) so the header -- and Sign out, the only way back to the
 * login page -- stays reachable and visible while the panel is open, exactly
 * as the product owner asked for "the header stays put". Its width is capped
 * at `calc(100vw - 4rem)` so a narrow viewport always keeps a strip of the
 * page, and the tab that closes it, visible and reachable -- the panel may
 * take most of the width there, but never all of it.
 *
 * WHAT "DOES NOT CHANGE THE LAYOUT" MEANS AT THE EDGES. A fixed-position
 * panel anchored with `right: 0` cannot itself introduce a horizontal
 * scrollbar or shift the body's width the way an inserted-in-flow element
 * could -- it is never counted in the document's scrollable area at all --
 * so no extra rule is needed to prevent that here; the property that makes
 * the panel not displace content is the same property that keeps it from
 * widening the page. `overflow-y: auto` on the panel itself, rather than
 * `overflow: hidden` anywhere on `body`, is the one addition: a long answer
 * scrolls inside the panel instead of growing it past the viewport's height.
 *
 * MOTION, AND WHY IT IS ALLOWED HERE WHEN SUB-PROJECT 11B RULED IT OUT. A
 * panel that simply appeared at the edge, with nothing to say it had just
 * arrived from there, would be a harder panel to place mentally than one that
 * visibly slides in from the tab that opened it -- this is motion that
 * ANSWERS THE CLICK, not decoration, which is the distinction spec's whole
 * posture rests on. `@keyframes ask-dock-in` is an ENTRANCE animation rather
 * than a transition because the dock unmounts on close (`if (!open) return
 * null` in `ask-launcher.tsx`) and a transition needs a stable element to
 * animate FROM; an animation runs once on the element's own arrival, which is
 * exactly the moment there is something to show. It is suppressed under
 * `prefers-reduced-motion: reduce`, below, and the hover states on the tab
 * remain flat colour swaps needing no guard of their own. */
.ask-tab {
  position: fixed;
  top: 50%;
  right: 0;
  transform: translateY(-50%);
  /* Above ordinary page content and above the dock itself (see `.ask-dock`'s
   * z-index below) -- open or closed, this is the control that closes the
   * panel, and it must stay on top of it to keep doing that. Below the
   * narrow-viewport sidebar overlay (`.sidebar--open`, z-index 30): the
   * sidebar is left-anchored and never reaches this edge, but the ordering is
   * correct regardless of that, and cheap to state. */
  z-index: 26;
  padding: 0.625rem 0.75rem;
  background: var(--brand);
  border: 1px solid var(--brand-dark);
  border-right: 0;
  border-radius: var(--radius) 0 0 var(--radius);
  color: #fff;
  font: inherit;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  white-space: nowrap;
  cursor: pointer;
}

.ask-tab:hover { background: var(--brand-dark); }

.ask-tab:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

/* OPEN, THE TAB RIDES THE PANEL'S OWN EDGE rather than staying at `right: 0`
 * and disappearing under it. The offset is the panel's own width, repeated
 * here rather than factored into a custom property because the two rules
 * are five lines apart and a third reader gains nothing a comment does not
 * already say: if `.ask-dock`'s width below changes, this must change with
 * it. The vertical position does not move -- the panel spans from `top: 3rem`
 * to the foot of the viewport, and 50% of the full viewport height is well
 * within that span on every screen this control is offered on. */
.ask-tab--open { right: min(24rem, calc(100vw - 4rem)); }

.ask-dock {
  position: fixed;
  top: 3rem;
  right: 0;
  bottom: 0;
  /* Matches `.ask-tab--open`'s offset exactly -- see the comment there. */
  width: min(24rem, calc(100vw - 4rem));
  overflow-y: auto;
  background: var(--surface-sunk);
  border-left: 1px solid var(--hairline);
  /* The one shadow this sheet carries outside the statement's own inset rows,
   * and it earns its place: an overlay with nothing to say it is above the
   * page rather than inserted into it reads as a layout bug on first glance.
   * A soft, dark, directional shadow -- cast toward the page it sits over --
   * is the plainest possible way to say "this is above", and it costs nothing
   * under `prefers-reduced-motion` because it is not motion. */
  box-shadow: -0.375rem 0 1rem rgba(0, 0, 0, 0.16);
  padding: 1rem 1.25rem 1.25rem;
  /* Above ordinary page content, below its own tab (z-index 26) and below the
   * narrow-viewport sidebar overlay (z-index 30). */
  z-index: 25;
  animation: ask-dock-in 180ms ease-out both;
}

@keyframes ask-dock-in {
  from { transform: translateX(100%); }
  to { transform: translateX(0); }
}

@media (prefers-reduced-motion: reduce) {
  .ask-dock { animation: none; }
}

/* Used only inside `.ask-dock` (see `ask-launcher.tsx`) -- `/ask`'s own full-
 * size page has no element by this name and carries its own measure
 * separately. The 62rem cap this class used to carry made sense when the dock
 * was a full-width band; the panel is narrower than that on every viewport by
 * construction now (see `.ask-dock`'s width, above), so there is nothing left
 * for a max-width to constrain. */
.ask-dock__body { max-width: none; }

/* --- the conversation, folded in from the on-report panel this dock absorbed
 *
 * ADDED, NOT PORTED. The dock used to hold one question and one answer; it now
 * holds a conversation that survives navigation (`lib/ask-history.ts`), and
 * three small rules are what that costs the sheet.
 *
 * `.stack`'s own 1rem gap does the actual layout work for all three -- the
 * question box from the pre-scoped explanation above it, one entry from the
 * next, and a question from its own answer inside one entry -- so what
 * follows is the three places `.stack` alone was not quite enough. */

/* THE PRE-SCOPED EXPLANATION, MOVED HERE VERBATIM FROM `ask-panel.tsx`'s OWN
 * `.card__header`, WITHOUT THE CARD. A second bordered box nested inside a
 * panel already set apart from the page by its own border and shadow would be
 * a box inside a box; a hairline rule under the explanation, the same
 * `.card__header` closes on, says "this is a heading" without saying it
 * twice. */
.ask-dock__intro {
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--hairline);
}

/* EMPTY BEFORE ANYTHING IS ASKED, AND THAT HAS TO COST NOTHING. `.stack`'s
 * `display: flex` gives every child a gap, including an empty one -- so
 * before the first question this element would otherwise hold open a full
 * 1rem of blank space between the question box and the panel's own bottom
 * padding, for a list with nothing in it. `:empty` is exact rather than a
 * guess: the moment one entry exists, the gap it was reserving is doing real
 * work. */
.ask-dock__history:empty { display: none; }

/* THE CITATION TILES, IN A COLUMN 24REM WIDE.
 *
 * `.tiles` auto-fits `minmax(140px, 1fr)`, which is right on a report screen --
 * three tiles across a full-width card, each holding a short value. In this
 * dock the same rule fits TWO, and drops the third into a ~170px cell. That
 * third tile is "Load batches", whose value is every ingest batch behind the
 * figures: a quarter of income statement cites dozens, and at 1.125rem in a
 * 170px column they stack one or two ids to a line and become the tallest
 * thing in the panel, dwarfing the answer they are a footnote to.
 *
 * So: one tile per row, and the value at the body size the rest of the dock
 * uses rather than the display size a short tile value wants. The sentence
 * then wraps as prose across the full width, which is what it is.
 *
 * Scoped to `.ask-dock` and to nothing else -- the report screen's own
 * provenance card is unchanged, and `describeBatches` still writes one wording
 * for both surfaces. No new class name is introduced, which is what the
 * shell suite's anti-drift check is actually about; this is the same
 * "ADDED, NOT PORTED" dock section the rules above belong to.
 *
 * No filename with an extension appears in this comment on purpose: the
 * fidelity harness counts declared classes with a plain dot-word regex over
 * this file, so a spec filename written here with its extensions is counted as
 * a class of that name and shows up forever after as one that never renders. */
.ask-dock .tiles { grid-template-columns: 1fr; }
.ask-dock .tile__value { font-size: 0.9375rem; }

/* ONE ENTRY FROM THE NEXT, DIVIDED RATHER THAN MERELY SPACED -- the same
 * pattern `.cite + .cite` already uses for two citations under one answer,
 * because the shape of the problem is the same one level up: `.stack`'s gap
 * alone reads as one long list, and a conversation is a sequence of distinct
 * exchanges. The rule is on the SECOND and later entries only, so the first
 * one is not divided from the question box above it, which is not part of
 * the conversation. */
.ask-dock__entry + .ask-dock__entry {
  border-top: 1px solid var(--hairline);
  padding-top: 1rem;
}

/* --- Narrow viewports ------------------------------------------------------
 *
 * Two flex rows in the header were laid out with `flex: none` and no wrap, so
 * below roughly 700px they pushed the document wider than the viewport and the
 * whole page scrolled sideways. Wide content is supposed to scroll inside its
 * own container here (see .scroll-x on the statement); the body never should.
 */
/* A table that runs wider than its card scrolls inside the card. Only the
 * operating statement carried an explicit .scroll-x wrapper, so the ratio,
 * holdings and provenance tables pushed the whole document sideways on a
 * phone. Putting it on the container rather than wrapping each table means a
 * table added later inherits the behaviour instead of reintroducing the bug.
 * The statement keeps its own wrapper: it needs one for the sticky header,
 * which binds to the nearest scrolling ancestor. */
.card__body--flush { overflow-x: auto; }

@media (max-width: 700px) {
  .main { padding: 1rem 0.875rem 4rem; }

  /* The tagline is decorative and the first thing that can go. The theme
   * toggle stays: it is a control, not a label. */
  .hdr { padding: 0 0.875rem; }
  .hdr__right > :not(.theme-toggle) { display: none; }
  /* Signing out must survive the narrow layout -- it is the only way back to the
     login page, and there is no other affordance for it anywhere in the UI. */
  .hdr__right > .hdr__signout { display: inline; }
  /* THE LAUNCHER NO LONGER COMPETES FOR THIS ROW, and needs no rule here to say
     so: `.ask-tab` is fixed to the viewport edge, not laid out in
     `.hdr__right`, so narrowing the header cannot clip it and it never had to
     yield. It is vertically centred, opposite `.hdr__toggle` at the header's
     own top-left corner, so the two narrow-viewport controls this header
     carries cannot collide at any width -- and its own width-capping rule
     (`.ask-tab--open`, `.ask-dock`'s `min(24rem, calc(100vw - 4rem))`) already
     keeps the panel it opens from taking the whole screen on a phone, so
     nothing further is needed here either. A reader who opened the dock on a
     wide screen and narrowed the window keeps it, unaffected by anything in
     this block. */
  .ask-dock { padding: 0.875rem; }
  .hdr__sub { display: none; }

  /* A two-word brand is far wider than the one-word mark this row was built for,
     and at 390px it pushed Sign out off the edge. The row gives ground in the
     places that cost nothing: the brand steps down one size and the theme
     toggle drops its letter-spacing and some padding. */
  .hdr__brand { font-size: 0.875rem; }
  .hdr__right { gap: 0.5rem; }
  .hdr__signout { margin-left: 0; }
  .theme-toggle button { padding: 0.1875rem 0.4375rem; letter-spacing: 0; }

  /* Title and actions stack rather than compete for one line. */
  .page-header__row { flex-wrap: wrap; gap: 0.625rem; padding: 0.875rem; }
  .page-header__actions { flex: 1 1 100%; flex-wrap: wrap; }

  /* A KPI at 155px minimum forces three columns onto a 390px screen and the
   * money clips. Two columns keeps the figures whole. */
  .kpis { grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); }
  .kpi { padding: 0.625rem 0.875rem 0.75rem; }

  /* The drill's left inset is a luxury at this width; the accent rule alone
   * still reads as "this belongs to the row above". */
  .drill { padding-left: 0.875rem; }
}

/* On the narrowest phones the brand, the theme toggle and the way out cannot all
 * fit on one 3rem row. The toggle is what yields: the operating system's own
 * light/dark preference still drives the theme through prefers-color-scheme, so
 * nothing becomes unreachable. Losing Sign out would leave no route back to the
 * login page anywhere in the UI. */
@media (max-width: 360px) {
  .theme-toggle { display: none; }

  /* Two columns leave ~144px per KPI here, and a portfolio total needs more than
   * that -- "$10,337,211.23" ran straight into the figure beside it. One column
   * is taller but every number stays whole and unambiguous, which matters more
   * on a financial statement than compactness. */
  .kpis { grid-template-columns: 1fr; }
  .kpi { border-right: none; border-bottom: 1px solid var(--hairline); }
  .kpi:last-child { border-bottom: none; }
}
