/* RoboROI.
 *
 * This file was 73 lines and opened "Deliberately plain. The product's credibility comes from
 * sourced numbers, not decoration." That was right about the risk and wrong about the remedy, and
 * DECISIONS.md D44 records the reversal: the page was not merely plain, it was unreadable in a
 * specific way — the answer sat below the fold under four paragraphs of caveats, and a reader who
 * cannot find the number cannot check it either.
 *
 * The constraint the old comment was protecting is kept, and it is worth stating exactly, because
 * it is narrower than "no styling":
 *
 *   Nothing here may make the model look more certain than it is.
 *
 * So: unverified caveats and refusals get MORE visual weight than they had, not less; ranges are
 * typeset so the span reads as the figure and the base reads as a note inside it, never the other
 * way round; and no colour is load-bearing — every state that matters is also stated in words,
 * because a red border is not a disclosure to a colourblind CFO or a greyscale printout.
 *
 * No external fonts, no CDN, no @import. F01.4 asserts every script and stylesheet reference is
 * same-origin, and a webfont would put a CFO's numbers behind a third party's uptime.
 */

:root {
  color-scheme: light dark;

  --ink: #14181d;
  --ink-soft: #444e59;
  --muted: #67727e;
  --line: #dde2e8;
  --line-strong: #c2cad3;
  --bg: #ffffff;
  --bg-sunk: #f6f8fa;
  --bg-raised: #ffffff;
  --accent: #1f4e79;
  --accent-ink: #ffffff;
  --accent-soft: #eef4fa;

  /* Caution, not alarm. Used for the unverified caveat and the refusal notice, both of which are
     things the tool is being honest about rather than errors it has made. */
  --warn-line: #c8901f;
  --warn-bg: #fdf7ea;
  --warn-ink: #6b4c08;

  --radius: 8px;
  --radius-sm: 5px;
  --measure: 46rem;
  --wide: 64rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    --ink: #e7ebef;
    --ink-soft: #b9c2cc;
    --muted: #8d99a5;
    --line: #2b323a;
    --line-strong: #3d4650;
    --bg: #12151a;
    --bg-sunk: #171b21;
    --bg-raised: #191e25;
    --accent: #6aa9e0;
    --accent-ink: #0b0e12;
    --accent-soft: #172633;

    --warn-line: #b8892b;
    --warn-bg: #241d0e;
    --warn-ink: #e8c98a;
  }
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  padding: 0 1.25rem 4rem;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 1rem;
  line-height: 1.55;
  color: var(--ink);
  background: var(--bg);
}

/* Tabular figures everywhere a number appears. Money in a proportional font makes columns of
   digits fail to line up, and a column that does not line up is a column nobody scans. */
table, .figure, .premium dd, [data-cumulative], [data-annual], [data-total] {
  font-variant-numeric: tabular-nums;
}

header.site, main, footer.site {
  max-width: var(--measure);
  margin-inline: auto;
}

/* The results page carries a three-column table and a chart; the form does not. Widening only the
   page that needs it keeps the form's line length readable. */
body:has(.comparison) header.site,
body:has(.comparison) main,
body:has(.comparison) footer.site { max-width: var(--wide); }

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

header.site {
  padding: 2.25rem 0 1.25rem;
  border-bottom: 1px solid var(--line);
  margin-bottom: 2rem;
}

header.site h1 {
  margin: 0 0 .3rem;
  font-size: clamp(1.5rem, 1.2rem + 1.2vw, 2rem);
  line-height: 1.2;
  letter-spacing: -0.02em;
}

.tagline { margin: 0; color: var(--muted); }
.crumb { margin: .75rem 0 0; font-size: .875rem; }
.crumb a { color: var(--accent); text-decoration: none; }
.crumb a:hover { text-decoration: underline; }

/* ---- form -------------------------------------------------------------- */

.wizard { margin: 0 0 2rem; }

fieldset {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.5rem;
  margin: 0 0 1.5rem;
  background: var(--bg-raised);
}

legend {
  padding: 0 .5rem;
  font-weight: 650;
  letter-spacing: -0.01em;
}

.field { display: grid; gap: .35rem; margin: 0 0 1.5rem; }
.field:last-child { margin-bottom: 0; }

label { font-weight: 600; }

select, input[type="number"] {
  font: inherit;
  padding: .55rem .65rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: inherit;
  max-width: 26rem;
  width: 100%;
}

select:focus-visible,
input:focus-visible,
button:focus-visible,
a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

input[type="checkbox"] { margin-right: .4rem; }
label:has(input[type="checkbox"]) { font-weight: 600; }

.hint {
  display: block;
  color: var(--muted);
  font-size: .875rem;
  line-height: 1.5;
  max-width: var(--measure);
}

button {
  font: inherit;
  font-weight: 650;
  padding: .7rem 1.6rem;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: var(--accent-ink);
  cursor: pointer;
}

button:hover { filter: brightness(1.08); }

/* ---- notices ----------------------------------------------------------- */

/* Deliberately heavier than the old rule, which rendered these as ordinary paragraphs. A caveat
   that reads like body copy is a caveat that gets skimmed, and every one of these is the tool
   telling the reader something that counts against its own answer. */
.notice {
  border: 1px solid var(--warn-line);
  border-left-width: 4px;
  border-radius: var(--radius-sm);
  background: var(--warn-bg);
  color: var(--warn-ink);
  padding: 1rem 1.1rem;
  margin: 0 0 1.5rem;
  font-size: .9375rem;
  line-height: 1.55;
}

.notice strong { color: inherit; }
.notice code { background: rgba(0, 0, 0, .06); color: inherit; }
@media (prefers-color-scheme: dark) { .notice code { background: rgba(255, 255, 255, .1); } }

/* ---- sections ---------------------------------------------------------- */

section { margin: 0 0 2.25rem; }

h2 {
  margin: 0 0 .5rem;
  font-size: 1.25rem;
  letter-spacing: -0.015em;
}

h3 {
  margin: 0 0 .5rem;
  font-size: 1.0625rem;
  letter-spacing: -0.01em;
}

.derivation, .breakeven, .front-loading, .opex, .chart {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.25rem 1.35rem;
  background: var(--bg-raised);
}

.comparison > section { margin-bottom: 1.5rem; }
.comparison > section:last-child { margin-bottom: 0; }

.figure {
  margin: .25rem 0 .35rem;
  font-size: 1.75rem;
  font-weight: 650;
  line-height: 1.15;
  letter-spacing: -0.02em;
}

.figure .hint { display: inline; font-size: .875rem; font-weight: 400; }

.working {
  margin: 0 0 .35rem;
  font-size: .9375rem;
  color: var(--ink-soft);
}

/* ---- the headline figures --------------------------------------------- */

/* The section a reader came for. It is first on the page (D44) and it is the only place given
   this much type — but the numbers in it are ranges, and the typography has to say so: the span
   is the figure, and `base` is a note inside the span rather than a second, competing headline. */
.headline {
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  padding: 1.35rem 1.45rem;
  background: var(--accent-soft);
}

dl.premium {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1rem 1.5rem;
  margin: 1rem 0;
}

dl.premium > div {
  padding: .85rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg-raised);
}

dl.premium dt {
  font-size: .8125rem;
  font-weight: 600;
  color: var(--muted);
  letter-spacing: .01em;
  margin-bottom: .3rem;
}

dl.premium dd {
  margin: 0;
  font-size: 1.25rem;
  font-weight: 650;
  line-height: 1.25;
  letter-spacing: -0.015em;
}

dl.premium dd strong { font-weight: inherit; }

/* The base figure and any band note sit BELOW the span at body weight. F13 forbids collapsing a
   range to a point; presenting `base` at headline size would do it visually while the markup
   stayed honest. */
dl.premium dd .hint {
  display: block;
  margin-top: .3rem;
  font-size: .8125rem;
  font-weight: 400;
  letter-spacing: normal;
}

/* No breakeven within the horizon is a real, quotable answer — MISSION.md invariant 4 forbids
   extrapolating a month past the horizon. Typeset as prose, not as a missing number. */
[data-no-breakeven] {
  font-size: 1rem;
  font-weight: 600;
  color: var(--ink-soft);
}

/* ---- tables ------------------------------------------------------------ */

.comparison-table, .assumptions { width: 100%; border-collapse: collapse; }

/* Only the comparison table scrolls. It is four columns of currency and must not wrap; the
   provenance table is three columns of prose and must.

   `display: block; overflow-x: auto` was briefly applied to BOTH, and on the provenance table it
   was a disaster that no test could see: taking the table out of table layout collapsed the
   caveat column to a sliver, so single caveats wrapped to 818px tall and the page grew to 16,000px
   — five screens of near-empty column. `verify` was 9/9 green throughout, because every assertion
   reads textContent and the text was all present, correctly, in a column one word wide. */
.table-scroll {
  overflow-x: auto;
  max-width: 100%;
  /* Reserved so a row that continues past the edge does not read as the end of the data. */
  scrollbar-gutter: stable;
}

/* The table keeps its natural width inside the scroller and stays a real table. Currency columns
   must not wrap: a figure broken across two lines stops being scannable. */
.table-scroll .comparison-table { min-width: 34rem; }
.comparison-table td, .comparison-table tfoot th { white-space: nowrap; }
.comparison-table td .hint { white-space: normal; }

/* `fixed`, not `auto`. Under auto layout the browser sized the first two columns to their longest
   unbreakable content and left the provenance column 325px of a 1024px table — and the provenance
   column is where the caveats live. The longest of them is 1,903 characters, so it rendered 818px
   tall: a single unverified disclosure occupying more than a screen, in a column a third the width
   it should be.

   The caveats are NOT shortened to fix this. They are the most valuable text on the page — F04
   asserts each is real, visible text — and 18 of them at this length is what "35 of 84 keys are
   unverified" actually looks like when written out honestly. A long page is the correct outcome;
   a narrow column was not. */
.assumptions { table-layout: fixed; }
.assumptions th:nth-child(1) { width: 24%; }
.assumptions th:nth-child(2) { width: 13%; }
.assumptions th:nth-child(3) { width: 63%; }

/* Source URLs and data keys are long, unbreakable tokens, and under fixed layout an overlong token
   overflows its cell rather than widening it.
 *
 * `th` as well as `td`, and that is the whole point of the rule: with `td` alone the page still
 * scrolled sideways at 390px, because the offender was
 * `cost.insurance.general_liability_per_10_unit_fleet_annual` — a 56-character key in the
 * row-header column. Unlabelled keys appear as their own row header (a missing label must never
 * mean a missing source), so the longest unbreakable strings on the page are all in `th`. */
.assumptions th, .assumptions td { overflow-wrap: anywhere; }

.comparison-table th, .comparison-table td,
.assumptions th, .assumptions td {
  text-align: left;
  vertical-align: top;
  padding: .6rem .7rem;
  border-bottom: 1px solid var(--line);
}

.comparison-table thead th, .assumptions thead th {
  font-size: .8125rem;
  letter-spacing: .02em;
  text-transform: uppercase;
  color: var(--muted);
  border-bottom: 1px solid var(--line-strong);
  white-space: nowrap;
}

.comparison-table thead th .hint { display: inline; text-transform: none; letter-spacing: normal; }

.comparison-table tbody tr:nth-child(even) { background: var(--bg-sunk); }

.comparison-table td .hint { display: block; font-size: .8125rem; margin-top: .1rem; }

.comparison-table tfoot th, .comparison-table tfoot td {
  border-top: 2px solid var(--line-strong);
  border-bottom: 0;
  font-size: 1.0625rem;
}

.assumptions { font-size: .9375rem; }
.assumptions td { color: var(--ink-soft); }

/* ---- provenance -------------------------------------------------------- */

/* The unverified caveat. F04 asserts this is real text and not hidden — so this rule may set
   colour and weight, and must never set `display: none`, `visibility`, or a zero font-size. */
.caveat {
  display: block;
  margin-top: .3rem;
  padding: .4rem .55rem;
  border-left: 3px solid var(--warn-line);
  background: var(--warn-bg);
  color: var(--warn-ink);
  font-size: .8125rem;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.source-note {
  display: block;
  margin-top: .3rem;
  font-size: .8125rem;
  color: var(--muted);
}

/* ---- chart ------------------------------------------------------------- */

.chart canvas { max-width: 100%; height: auto; }

/* ---- misc -------------------------------------------------------------- */

a { color: var(--accent); }

/* `code` on this site always holds a data key or a filename, and the keys are long and
   unbreakable — `robot.generic.raas_monthly_fraction_of_price` is 44 characters with no break
   opportunity, and it alone made the page scroll sideways at 320px. Wrapping is set here rather
   than on the two notices that happen to contain one today, because every future key is long too. */
code {
  background: var(--bg-sunk);
  border: 1px solid var(--line);
  padding: .05rem .3rem;
  border-radius: 3px;
  font-size: .875em;
  overflow-wrap: anywhere;
}

footer.site {
  margin-top: 3rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: .875rem;
}

@media (max-width: 40rem) {
  body { padding: 0 1rem 3rem; }
  fieldset { padding: 1.1rem; }
  .derivation, .breakeven, .front-loading, .opex, .chart, .headline { padding: 1rem; }
  dl.premium { grid-template-columns: 1fr; }
}

@media print {
  body { padding: 0; color: #000; background: #fff; }
  .crumb, .chart { display: none; }
  .notice, .caveat { border-color: #000; background: transparent; color: #000; }
  table { display: table; overflow: visible; }
}
