/* ==========================================================================
   Sondertilgung vs ETF

   Light only, by design — there is no dark mode and no theme toggle, so the
   page stores nothing on the visitor's device.

   Palette: the dataviz reference instance. The diverging heatmap ramp is
   derived and checked by build/palette.py — do not hand-edit the --div-* values.

   Layout goal: the inputs and the headline result share the first screen. The
   left column is sticky, so the inputs stay put while the charts scroll past.
   ========================================================================== */

:root {
  color-scheme: light;

  --plane:        #f9f9f7;
  --surface:      #fcfcfb;
  --surface-sunk: #f2f1ee;

  --ink:          #0b0b0b;
  --ink-2:        #52514e;
  --ink-muted:    #898781;

  --rule:         #e1e0d9;
  --axis:         #c3c2b7;
  --border:       rgba(11, 11, 11, 0.10);

  /* identity: blue is always Sondertilgung, orange is always ETF */
  --sond:         #2a78d6;
  --etf:          #eb6834;

  --warning:      #fab219;
  --critical:     #d03b3b;
  --success-text: #006300;

  /* diverging ramp — generated by build/palette.py */
  --div-etf-1: #9f3600; --div-etf-2: #cb4801; --div-etf-3: #f85a02;
  --div-etf-4: #ff9067; --div-etf-5: #ffbfa9;
  --div-mid:   #f0efec;
  --div-sond-5: #b7d3f6; --div-sond-4: #86b6ef; --div-sond-3: #5598e7;
  --div-sond-2: #2a78d6; --div-sond-1: #1c5cab;

  /* UI chrome. Deliberately neither blue nor orange -- those two carry meaning
     everywhere else on the page, and a control is not a strategy. */
  --control: #3a3a42;

  --focus: #2a78d6;
  --sans: system-ui, -apple-system, "Segoe UI", sans-serif;
  --maxw: 1220px;
  --radius: 10px;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--plane);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.5;
}

h1, h2, h3 { line-height: 1.25; margin: 0 0 .35em; font-weight: 620; letter-spacing: -0.011em; }
h1 { font-size: 1.3rem; }
h2 { font-size: 1.02rem; }
h3 { font-size: .93rem; }
p  { margin: 0 0 .8em; }
a  { color: var(--sond); }

.de { color: var(--ink-muted); font-weight: 400; }
.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 20px; }

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

header.site {
  border-bottom: 1px solid var(--rule);
  background: var(--surface);
  padding: 11px 0 10px;
}
header.site h1 { margin: 0; }
header.site .tagline {
  color: var(--ink-2); font-size: .85rem; margin: 2px 0 0; max-width: 78ch;
}

/* ---------- layout ---------- */

.layout {
  display: grid;
  grid-template-columns: 330px minmax(0, 1fr);
  gap: 20px;
  align-items: start;
  padding: 14px 0 60px;
}
@media (max-width: 900px) {
  .layout { grid-template-columns: 1fr; }
  .controls { position: static !important; }
}

.col-title {
  font-size: 1.15rem; font-weight: 700; letter-spacing: -0.015em;
  color: var(--ink);
  margin: 0 0 9px; padding-bottom: 6px;
  border-bottom: 2px solid var(--axis);
}

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 13px 15px;
  margin-bottom: 14px;
}
.card > h2 { margin-bottom: 1px; }
/* A sub-heading for one chart inside a card that holds two. */
.chart-h {
  font-size: .82rem; font-weight: 660; color: var(--ink-2);
  margin: 4px 0 2px; letter-spacing: -0.01em;
}
.chart-h .sub { font-weight: 400; color: var(--ink-muted); }
.card > .card-note { color: var(--ink-2); font-size: .82rem; margin: 0 0 11px; }

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

/* The controls stay put while the results and charts scroll past. The card --
   not the column -- is the scroll container, so the "Inputs" heading stays
   pinned and only the fields move. The cap only bites when the advanced panel
   is open; collapsed, the card is shorter than this and never scrolls. */
.controls { position: sticky; top: 12px; }
.controls .card {
  margin-bottom: 0;
  max-height: calc(100vh - 66px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
@media (max-width: 900px) {
  .controls .card { max-height: none; overflow-y: visible; }
}

/* A section is a box with its heading INSIDE it, on its own tinted strip.
   <legend> cannot do this -- the browser positions it in the border gap, which
   is what left the old headings floating half outside their boxes. A div with
   role="group" plus aria-labelledby names the group just as a legend did. */
.grp {
  border: 1px solid var(--rule); border-radius: 10px;
  background: var(--plane); margin: 0 0 10px; overflow: hidden;
}
.grp-h {
  margin: 0; padding: 9px 12px;
  font-size: .95rem; font-weight: 660; color: var(--ink); letter-spacing: -0.01em;
  background: var(--surface-sunk); border-bottom: 1px solid var(--rule);
}
.grp-h .de { font-weight: 400; font-size: .82rem; }
.grp-body { padding: 11px 12px 3px; }

/* Two-line label: English first in ink, the German term under it in grey. The
   field itself carries the value -- there is no separate read-out. */
.field { display: grid; grid-template-columns: 1fr auto; align-items: center;
         column-gap: 10px; margin-bottom: 9px; }
.field > label, .field > .seg-lbl { display: block; min-width: 0; line-height: 1.25; }
.field > label .lbl, .field > .seg-lbl {
  display: block; font-size: .82rem; color: var(--ink);
}
.field > label .de, .field > .seg-lbl + .seg .de { display: block; }
.field > label .de { font-size: .73rem; color: var(--ink-muted); }
.field .field-error { grid-column: 1 / -1; }
.field .card-note { grid-column: 1 / -1; margin-top: 4px; }

/* The unit sits inside the box, so the box shows one value and one unit and
   nothing else. Padding-right is reserved for it via --unit-w. */
.input-wrap { position: relative; justify-self: end; }
.input-wrap .unit {
  position: absolute; right: 9px; top: 50%; transform: translateY(-50%);
  font-size: .74rem; color: var(--ink-muted); pointer-events: none;
}
.input-wrap.has-unit input { padding-right: var(--unit-w, 26px); }
#fixed_years-field .input-wrap.has-unit input { --unit-w: 44px; }

input[type="text"], input[type="number"], select {
  font: inherit; font-size: .84rem; font-variant-numeric: tabular-nums;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--border); border-radius: 7px;
  padding: 4px 8px; width: 100%;
}
.field > .input-wrap input { width: 122px; text-align: right; }
.field > select { justify-self: end; width: auto; min-width: 122px; }

/* A switch and the field it governs are one unit: the pills form the head of
   the box, and the field the switch selects sits in the body directly under
   them. Without this the switch reads as just another control in the list, with
   nothing to say which input it acts on. */
.pair {
  border: 1px solid var(--rule); border-radius: 9px; background: var(--surface);
  margin: 0 0 9px; overflow: hidden;
}
.pair > .seg {
  border: 0; border-radius: 0; border-bottom: 1px solid var(--rule);
  background: var(--surface-sunk);
}
.pair-body { padding: 9px 10px 0; }
.pair-body > .field:last-of-type { margin-bottom: 9px; }

/* Segmented control. One row of pills, the chosen one filled. */
.field:has(> .seg) { grid-template-columns: 1fr; row-gap: 5px; }
.seg {
  display: flex; border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface); padding: 2px; gap: 2px;
}
.seg button {
  flex: 1 1 0; min-width: 0; border: 0; border-radius: 6px; background: none;
  font: inherit; font-size: .78rem; line-height: 1.2; color: var(--ink-2);
  padding: 4px 6px; cursor: pointer; text-align: center;
}
.seg button .de { display: block; font-size: .68rem; color: var(--ink-muted); }
.seg button:hover { background: var(--surface-sunk); }
.seg button[aria-checked="true"] { background: var(--control); color: #fff; }
.seg button[aria-checked="true"] .de { color: rgba(255, 255, 255, .72); }

:is(input, select, button, [tabindex]):focus-visible {
  outline: 2px solid var(--focus); outline-offset: 2px;
}

.check { display: flex; align-items: center; gap: 8px; font-size: .82rem; color: var(--ink-2); margin-bottom: 7px; }
.check input { accent-color: var(--sond); width: 15px; height: 15px; }

details.advanced > summary {
  cursor: pointer; font-size: .68rem; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--ink-muted); padding: 6px 0 2px;
  border-top: 1px solid var(--rule); margin-top: 4px;
}
details.advanced[open] > summary { margin-bottom: 9px; }
details.advanced .grp { margin-bottom: 12px; }

.btn {
  border: 1px solid var(--border); background: var(--surface); color: var(--ink-2);
  border-radius: 7px; padding: 5px 10px; font: inherit; font-size: .8rem; cursor: pointer;
}
.btn:hover { background: var(--surface-sunk); }

/* a control that has no choice to offer, shown rather than hidden so the
   reason stays visible */
.field.disabled > label, .field.disabled select { opacity: .5; }
.field.disabled select { cursor: not-allowed; }
.field[hidden] { display: none; }

.field-error { color: var(--critical); font-size: .77rem; margin-top: 3px; }
input.invalid, select.invalid { border-color: var(--critical); }

/* ---------- verdict + result block ---------- */

/* One flowing sentence, not a row of boxes. As a flex container each span was
   an unbreakable item, so the tail wrapped whole and always broke right after
   the amount. Inline, it breaks wherever the line runs out. */
.verdict { line-height: 1.5; max-width: 74ch; }
.verdict .who {
  display: inline-block; vertical-align: baseline;
  font-size: .7rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  padding: 3px 8px; border-radius: 999px; color: #fff; white-space: nowrap;
}
.verdict .who.sond { background: var(--sond); }
.verdict .who.etf  { background: var(--etf); }
.verdict .who.tie  { background: var(--ink-muted); }
.verdict .lead,
.verdict .with { font-size: .88rem; color: var(--ink-2); }
.verdict .with[hidden], .verdict .amount[hidden] { display: none; }
.verdict .amount {
  font-size: 1.15rem; font-weight: 700; letter-spacing: -0.01em; white-space: nowrap;
}
.verdict .unit { font-size: .88rem; color: var(--ink-2); }

.block { border-top: 1px solid var(--rule); margin-top: 11px; padding-top: 11px; }

.cmp .mlink {
  display: inline-flex; align-items: center; justify-content: center;
  width: 14px; height: 14px; margin-left: 5px; vertical-align: 1px;
  border: 1px solid var(--axis); border-radius: 50%;
  font-size: .62rem; font-weight: 600; line-height: 1; text-decoration: none;
  color: var(--ink-muted); flex: none;
}
.cmp .mlink:hover, .cmp .mlink:focus-visible {
  color: #fff; background: var(--sond); border-color: var(--sond);
}

#cmp-note { color: var(--ink-2); font-size: .81rem; margin: 9px 0 0; }
#cmp-note[hidden] { display: none; }

.more-cue {
  color: var(--ink-muted); font-size: .78rem; margin: 11px 0 0;
  border-top: 1px solid var(--rule); padding-top: 9px;
}

/* ---------- comparison table ---------- */

table.cmp { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; font-size: .85rem; }
table.cmp th, table.cmp td { padding: 4px 8px; text-align: right; border-bottom: 1px solid var(--rule); }
table.cmp th:first-child, table.cmp td:first-child { text-align: left; font-variant-numeric: normal; }
table.cmp thead th {
  font-size: .7rem; letter-spacing: .05em; text-transform: uppercase;
  color: var(--ink-muted); font-weight: 660; padding-bottom: 5px;
}
table.cmp thead th .swatch {
  display: inline-block; width: 8px; height: 8px; border-radius: 2px;
  margin-right: 5px; vertical-align: baseline;
}
table.cmp thead th .swatch.sond { background: var(--sond); }
table.cmp thead th .swatch.etf  { background: var(--etf); }
/* Same header strip as the input sections on the left. */
table.cmp tr.sect th {
  text-align: left; font-size: .92rem; font-weight: 660; letter-spacing: -0.01em;
  color: var(--ink); background: var(--surface-sunk);
  padding: 8px 10px; border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
table.cmp tbody tr.sect:first-child th { border-top: 0; }
table.cmp tr.total td { border-top: 2px solid var(--axis); border-bottom: 0; font-weight: 700; padding-top: 6px; }
table.cmp td.win { color: var(--success-text); }
table.cmp .sub { display: block; font-size: .73rem; color: var(--ink-muted); font-variant-numeric: normal; line-height: 1.3; }

/* ---------- stat tiles ---------- */

.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 10px; }
.tile { background: var(--surface-sunk); border-radius: 8px; padding: 8px 11px; }
.tile .k { font-size: .73rem; color: var(--ink-2); margin-bottom: 1px; }
.tile .v { font-size: 1.2rem; font-weight: 660; font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.tile .v.none { color: var(--ink-muted); }
.tile .n { font-size: .72rem; color: var(--ink-muted); margin-top: 1px; line-height: 1.35; }

/* ---------- warnings ---------- */

.warnings { margin: 0 0 12px; padding: 0; list-style: none; }
.warnings:empty { margin: 0; }
.warnings li {
  display: flex; gap: 9px; align-items: flex-start;
  background: var(--surface); border: 1px solid var(--border);
  border-left: 3px solid var(--warning);
  border-radius: 8px; padding: 9px 12px; margin-bottom: 7px;
  font-size: .83rem; color: var(--ink-2);
}
.warnings li.critical { border-left-color: var(--critical); }
.warnings li .icon { flex: 0 0 auto; font-weight: 700; color: var(--ink); }

/* ---------- charts ---------- */

.chart { position: relative; }
.chart svg { display: block; width: 100%; height: auto; overflow: visible; }
.chart .gridline { stroke: var(--rule); stroke-width: 1; }
.chart .axisline { stroke: var(--axis); stroke-width: 1; }
.chart .tick { fill: var(--ink-muted); font-size: 11px; font-variant-numeric: tabular-nums; }
.chart .serie { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart .serie.sond { stroke: var(--sond); }
.chart .serie.etf  { stroke: var(--etf); }
/* Bars sit behind the lines and share their colour, muted enough that the line
   stays the thing you read first. */
.chart .bar { stroke: none; }
.chart .bar.sond { fill: var(--sond); opacity: .22; }
.chart .bar.etf  { fill: var(--etf);  opacity: .22; }
/* On a chart of their own there is no line to defer to. */
.chart .bar.solo { opacity: .85; }
.chart .marker { stroke: var(--surface); stroke-width: 2; }
.chart .marker.sond { fill: var(--sond); }
.chart .marker.etf  { fill: var(--etf); }
.chart .refline { stroke: var(--ink-muted); stroke-width: 1; stroke-dasharray: 3 3; }
.chart .reflabel { fill: var(--ink-muted); font-size: 10.5px; }
/* The break-even line is an answer, not an annotation, so it reads darker. */
.chart .refline.be { stroke: var(--ink-2); stroke-dasharray: 5 3; }
.chart .reflabel.be { fill: var(--ink-2); font-weight: 640; }

.legend { display: flex; gap: 15px; flex-wrap: wrap; font-size: .8rem; color: var(--ink-2); margin: 0 0 9px; }
.legend .item { display: flex; align-items: center; gap: 6px; }
.legend .key { width: 11px; height: 11px; border-radius: 3px; flex: 0 0 auto; }
.legend .key.line { height: 3px; border-radius: 2px; }
.legend .key.swatch { height: 11px; border-radius: 3px; }
.legend .key.sond { background: var(--sond); }
.legend .key.etf  { background: var(--etf); }

.tip {
  position: absolute; pointer-events: none; opacity: 0; transition: opacity .08s;
  background: var(--surface); border: 1px solid var(--border);
  box-shadow: 0 4px 14px rgba(0, 0, 0, .13);
  border-radius: 8px; padding: 7px 10px; font-size: .78rem; z-index: 5;
  min-width: 150px; font-variant-numeric: tabular-nums; color: var(--ink);
}
.tip.on { opacity: 1; }
.tip .th { font-weight: 660; margin-bottom: 3px; }
.tip .tr { display: flex; justify-content: space-between; gap: 14px; }
.tip .tr .k { color: var(--ink-2); display: flex; align-items: center; gap: 6px; }
.tip .tr .k i { width: 9px; height: 9px; border-radius: 2px; display: inline-block; }
.tip .tr .k i.sond { background: var(--sond); }
.tip .tr .k i.etf  { background: var(--etf); }

/* heatmap */
.heat { border-collapse: separate; border-spacing: 2px; font-size: .73rem; font-variant-numeric: tabular-nums; }
.heat td.cell { width: 46px; height: 28px; text-align: center; border-radius: 3px; color: var(--ink); cursor: default; }
.heat td.cell.on { outline: 2px solid var(--ink); outline-offset: -2px; }
.heat th { font-weight: 600; color: var(--ink-muted); font-size: .71rem; padding: 2px 5px; }
.heat th.rowhead { text-align: right; }
/* overflow-x:auto alone leaves overflow-y computing to auto as well, which is
   where the stray vertical scrollbar came from. Say hidden explicitly. */
.heat-scroll { overflow-x: auto; overflow-y: hidden; position: relative; }
.heat-legend { display: flex; align-items: center; gap: 8px; font-size: .77rem; color: var(--ink-2); margin-top: 9px; flex-wrap: wrap; }
.heat-legend .ramp { display: flex; }
.heat-legend .ramp i { width: 21px; height: 11px; display: block; }
.heat-legend .ramp i:first-child { border-radius: 3px 0 0 3px; }
.heat-legend .ramp i:last-child { border-radius: 0 3px 3px 0; }

.heat td.cell.c-s1 { background: var(--div-sond-1); }
.heat td.cell.c-s2 { background: var(--div-sond-2); }
.heat td.cell.c-s3 { background: var(--div-sond-3); }
.heat td.cell.c-s4 { background: var(--div-sond-4); }
.heat td.cell.c-s5 { background: var(--div-sond-5); }
.heat td.cell.c-mid { background: var(--div-mid); }
.heat td.cell.c-e5 { background: var(--div-etf-5); }
.heat td.cell.c-e4 { background: var(--div-etf-4); }
.heat td.cell.c-e3 { background: var(--div-etf-3); }
.heat td.cell.c-e2 { background: var(--div-etf-2); }
.heat td.cell.c-e1 { background: var(--div-etf-1); }
/* the darkest two steps of each arm need light text on top */
.heat td.cell.c-s1, .heat td.cell.c-s2,
.heat td.cell.c-e1, .heat td.cell.c-e2 { color: #fff; }

.heat-legend .ramp i.c-s1 { background: var(--div-sond-1); }
.heat-legend .ramp i.c-s2 { background: var(--div-sond-2); }
.heat-legend .ramp i.c-s3 { background: var(--div-sond-3); }
.heat-legend .ramp i.c-s4 { background: var(--div-sond-4); }
.heat-legend .ramp i.c-s5 { background: var(--div-sond-5); }
.heat-legend .ramp i.c-mid { background: var(--div-mid); }
.heat-legend .ramp i.c-e1 { background: var(--div-etf-1); }
.heat-legend .ramp i.c-e2 { background: var(--div-etf-2); }
.heat-legend .ramp i.c-e3 { background: var(--div-etf-3); }
.heat-legend .ramp i.c-e4 { background: var(--div-etf-4); }
.heat-legend .ramp i.c-e5 { background: var(--div-etf-5); }

/* table view — the accessibility channel for every chart */
.tableview { width: 100%; border-collapse: collapse; font-size: .8rem; font-variant-numeric: tabular-nums; margin-top: 10px; }
.tableview th, .tableview td { padding: 3px 8px; border-bottom: 1px solid var(--rule); text-align: right; }
.tableview th:first-child, .tableview td:first-child { text-align: left; }
.tableview thead th { color: var(--ink-muted); font-weight: 640; }
details.datatable > summary { cursor: pointer; font-size: .78rem; color: var(--ink-2); padding: 5px 0; }

/* ---------- status / prose ---------- */

.status {
  display: flex; align-items: center; gap: 9px;
  font-size: .81rem; color: var(--ink-2);
  background: var(--surface-sunk); border-radius: 8px; padding: 7px 11px; margin-bottom: 12px;
}
.status.hidden { display: none; }
.status .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--warning); flex: 0 0 auto; }
.status.err { background: #fdecec; color: #7a1f1f; }
.status.err .dot { background: var(--critical); }

.prose { max-width: 76ch; }
.prose h3 { margin-top: 1.4em; }
.prose ul { padding-left: 1.15em; margin: 0 0 .85em; }
.prose li { margin-bottom: .3em; }
.prose code { background: var(--surface-sunk); padding: 1px 5px; border-radius: 4px; font-size: .88em; }
.prose table { width: 100%; border-collapse: collapse; font-size: .85rem; margin: 0 0 1em; }
.prose table th, .prose table td { text-align: left; padding: 5px 9px; border-bottom: 1px solid var(--rule); vertical-align: top; }
.prose table thead th { color: var(--ink-muted); font-size: .76rem; text-transform: uppercase; letter-spacing: .05em; }

.disclaimer {
  border: 1px solid var(--border); border-left: 3px solid var(--critical);
  background: var(--surface); border-radius: 8px; padding: 13px 16px; margin: 0 0 14px;
}
.disclaimer.warn { border-left-color: var(--warning); }
.disclaimer h2 { font-size: .93rem; margin-bottom: .35em; }
.disclaimer p { font-size: .84rem; color: var(--ink-2); margin-bottom: .55em; }
.disclaimer p:last-child { margin-bottom: 0; }

footer.site {
  border-top: 1px solid var(--rule); background: var(--surface);
  padding: 16px 0; font-size: .83rem; color: var(--ink-2);
}
footer.site .wrap { display: flex; gap: 18px; flex-wrap: wrap; align-items: center; }
footer.site .spacer { flex: 1; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- utilities (no inline style attributes: the CSP forbids them) ---- */

.wide    { width: 100%; }
.block-btn, .btn.block { width: 100%; margin-top: 6px; }
.tight   { margin: 6px 0 0; }
.pad-top { padding-top: 20px; }
.top-gap { margin-top: 22px; }
.center  { text-align: center; }
.muted   { color: var(--ink-muted); }

@media print {
  .controls, .status { display: none; }
  .layout { grid-template-columns: 1fr; }
  body { background: #fff; }
}
