
/* ============================================================================
   ABOVE-THE-FOLD CALCULATOR (standing requirement)
   The interface AND a live result must be usable without scrolling.
   Measured budget on a 1366x768 laptop before this change:
     header 67 + crumb 42 + tool-hd 226 + calc chrome 93 = form at 428,
     result hero at 799 -- 31px BELOW the fold. Nothing was visible.
   Three changes fix it without losing any content:
     1. The masthead block is compressed and the badge strip is deferred
        below the calculator (it is trust furniture, not interface).
     2. Above 1100px the calculator becomes two columns: inputs left,
        live results right. Both sit entirely above the fold.
     3. The action row is no longer a full-width band above the results;
        it sits inside the input column, so it cannot push results down.
   ========================================================================== */
.tool-hd{padding:4px 0 10px}
.tool-hd h1{margin:4px 0 6px}
.tool-hd .lede{margin-bottom:2px}
/* Trust badges are moved out of the fold budget and rendered under the
   calculator by tool_factory; this rule styles them wherever they land. */
.badges{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0 2px}
.badge{font-size:.73rem;font-weight:700;color:var(--muted);background:var(--surface);
border:1px solid var(--stroke);padding:5px 11px;border-radius:99px;display:inline-flex;align-items:center;gap:6px}
.badge b{color:var(--pos)}
.calc{background:var(--surface)}
.layout{display:grid;grid-template-columns:minmax(0,1fr) 312px;gap:28px;align-items:start;min-width:0}
@media(max-width:1000px){.layout{grid-template-columns:minmax(0,1fr)}}
.calc{padding:20px 22px;scroll-margin-top:80px}
@media(max-width:520px){.calc{padding:16px}}
/* Fieldsets stack; the fields INSIDE them do the pairing. Putting two
   fieldsets side by side instead was measurably worse in the 761-1100px
   band: it halved each group's width to ~290px, which forced every group
   back to a single column and left a 7-field group towering beside a
   1-field neighbour (749px tall). Stacking the groups gives each one the
   full 598px and lets auto-fit pair inside it. */
.calc-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:0;min-width:0}
/* Fields pair up only where the column can actually hold two of them.
   Measured input-column widths: 400px beside the sticky result panel
   (>=1101px), ~674px once the panel drops below (761-1100px), 320px on a
   390px handset. A hard two-column rule would be right for exactly one of
   those, so the track floor does the deciding: at a 232px minimum the grid
   yields one column at 400px and below, two once the fieldset clears
   ~480px. No breakpoint list to keep in sync, and no field is ever
   squeezed under 232px, which is where the longest labels (32 chars)
   begin to wrap past two lines. */
.fgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(232px,1fr));
gap:0 16px;min-width:0;align-items:start}
/* The floor is chosen per group at build time from the widest label in it
   (see tool_factory). Short-label groups -- weekday loads, rep counts --
   may pair inside the 400px split column; verbose ones wait for width. */
.fgrid.fg-one{grid-template-columns:minmax(0,1fr)}
.fgrid.fg-tight{grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
.fgrid.fg-mid{grid-template-columns:repeat(auto-fit,minmax(186px,1fr))}
/* Below ~360px two tracks would put a 48px control under 140px, so every
   group drops to one column regardless of how short its labels are. */
@media(max-width:360px){.fgrid,.fgrid.fg-tight,.fgrid.fg-mid{grid-template-columns:minmax(0,1fr)}}
/* Controls that carry chips, a slider or prose help stay full width: their
   natural height already breaks the row rhythm of a paired neighbour. */
.fgrid>.field.wide,.fgrid>.field:has(.chips),.fgrid>.field:has(input[type=range]),
.fgrid>.rng{grid-column:1/-1}
.calc h2{margin:0 0 2px;font-size:1.12rem}
.calc .sub{font-size:.82rem;color:var(--dim);margin-bottom:12px}

/* --- the split: inputs beside results on anything wide enough ----------- */
.calc-split{display:grid;grid-template-columns:minmax(0,1fr);gap:0;min-width:0}
@media(min-width:1101px){
  .layout{grid-template-columns:minmax(0,1fr) 312px}
  .calc-split{grid-template-columns:minmax(0,1.02fr) minmax(0,1fr);gap:0 22px;align-items:start}
  .calc-split>.cs-in{min-width:0}
  .calc-split>.cs-out{min-width:0;position:sticky;top:80px}
  .calc-split .out{margin-top:0}
  /* The result column is roughly half the old full width, so a 4-across card
     row collapses to one word per line. Inside the split the breakdown runs
     two-up, and prose cards (sentence answers) take the full row. */
  .calc-split .cards4{grid-template-columns:repeat(2,minmax(0,1fr))}
  .calc-split .oc{padding:12px 12px;text-align:left}
  .calc-split .oc .v.prose{font-size:.9rem;line-height:1.4}
  .calc-split .oc:has(.v.prose){grid-column:1/-1}
}
/* Below the split breakpoint the inputs come first and the full output
   region follows in document order. The headline answer is kept above the
   fold by a compact live strip (.fold-res) that mirrors the hero value and
   sits directly under the field grid. Promoting the whole output region
   instead would bury the first input under ~3,800px of detail cards on a
   phone, which is worse than scrolling for the breakdown. */
@media(max-width:1100px){
  .calc-split{display:flex;flex-direction:column}
  .calc-split>.cs-in{order:1}
  .calc-split>.cs-out{order:2;min-width:0}
  .calc-split .out{margin-top:16px}
}
/* On the smallest phones (<=430px) the masthead has to give up more room so
   that the answer strip AND the first input both clear a 640px viewport. */
@media(max-width:430px){
  .crumb{padding:8px 0 2px;font-size:.76rem}
  .tool-hd{padding:2px 0 6px}
  .tool-hd h1{margin:2px 0 4px}
  .tool-hd .lede{font-size:.9rem;margin-bottom:0}
  .calc{padding:14px}
  .calc h2{font-size:1rem}
  .calc .sub{margin-bottom:8px;font-size:.78rem}
  .fs legend{margin-bottom:8px}
}
/* A 360x640 handset is the tightest case in the matrix: the answer strip,
   the first legend and the first field must all clear 640px. Measured
   overruns before this block ran 1-46px, so the fold budget is recovered
   from the masthead, the section chrome and the field rhythm rather than
   from the control sizes, which must stay touch-legal (>=44px). */
@media(max-width:380px),(max-height:680px){
  .hdr{position:static}
  .crumb{padding:6px 0 0;font-size:.72rem}
  .tool-hd{padding:0 0 4px}
  .tool-hd .eyebrow{font-size:.64rem;padding:3px 8px}
  .tool-hd h1{margin:2px 0 2px}
  .tool-hd .lede{font-size:.84rem;line-height:1.45;
    display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .calc{padding:12px}
  .calc h2{font-size:.96rem;margin-bottom:0}
  .calc .sub{margin-bottom:6px;font-size:.74rem;
    display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden}
  .fold-res{margin-bottom:10px;padding:9px 11px}
  .fold-res .v{font-size:1.18rem}
  .fs legend{margin-bottom:6px;font-size:.68rem}
  .field{margin-bottom:10px}
  .field label{margin-bottom:3px}
}
/* --- the compact above-the-fold answer strip (narrow screens only) ------ */
.fold-res{display:none}
@media(max-width:1100px){
  .fold-res{display:flex;align-items:baseline;justify-content:space-between;gap:12px;
    margin:0 0 14px;padding:12px 14px;border-radius:var(--r-sm);
    border:1px solid var(--stroke2);background:linear-gradient(160deg,var(--tint),var(--tint-b))}
  .fold-res .k{font-size:.68rem;font-weight:800;letter-spacing:.12em;text-transform:uppercase;
    color:var(--brand2);flex:0 1 auto;min-width:0}
  .fold-res .v{font-family:var(--mono);font-variant-numeric:tabular-nums;font-weight:800;
    font-size:1.32rem;line-height:1.15;color:var(--txt);text-align:right;
    overflow-wrap:anywhere;min-width:0}
  .fold-res .v.prose{font-family:var(--sans);font-size:.95rem;font-weight:600;line-height:1.3}
}
.fs{border:0;padding:0;margin:0 0 4px;min-width:0}
.fs legend{font-size:.72rem;font-weight:800;letter-spacing:.13em;text-transform:uppercase;
color:var(--brand2);margin-bottom:8px;padding:0}
.rng{display:flex;align-items:center;gap:12px;margin:-2px 0 10px}
.rng input[type=range]{flex:1}
.rng output{font-family:var(--mono);font-size:.78rem;color:var(--muted);min-width:52px;text-align:right}
.ip-fmt{position:absolute;left:34px;right:46px;top:50%;transform:translateY(-50%);pointer-events:none;
font-family:var(--mono);font-size:.98rem;color:var(--txt);background:var(--input-bg);
white-space:nowrap;overflow:hidden;line-height:1.4;padding-right:4px}
.ip:not(.has-suf) .ip-fmt{right:14px}
.actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:10px;padding-top:12px;border-top:1px solid var(--stroke)}
/* One button now, so it sizes to its content instead of stretching across
   the whole column and reading like a primary call to action. */
.actions .btn{flex:0 1 auto;min-width:150px}
@media(max-width:420px){.actions .btn{flex:1 1 100%}}
.out{margin-top:22px;border-radius:var(--r);overflow:hidden;border:1px solid var(--stroke2);
background:linear-gradient(160deg,var(--tint),var(--tint-b))}
.out-hero{padding:20px 22px;text-align:center;border-bottom:1px solid var(--stroke)}
.out-hero .k{font-size:.73rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase;color:var(--brand2)}
.out-hero .v{font-family:var(--mono);font-variant-numeric:tabular-nums;font-weight:800;overflow-wrap:break-word;
font-size:var(--fs-hero);line-height:1.12;margin:6px 0 4px;
background:linear-gradient(180deg,var(--grad-a),var(--grad-c));-webkit-background-clip:text;background-clip:text;color:transparent}
.out-hero .m{font-size:.83rem;color:var(--muted)}
.cards4{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:1px;background:var(--stroke)}
@media(max-width:700px){.cards4{grid-template-columns:repeat(2,minmax(0,1fr))}}
.oc{background:var(--surface);padding:14px 13px;text-align:center}
.oc .k{font-size:.68rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--dim);display:block;margin-bottom:5px}
.oc .v{font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:var(--fs-card);font-weight:700;color:var(--txt)}
.oc .v.pos{color:var(--pos)}.oc .v.neg{color:var(--neg)}
.oc .m{display:block;margin-top:5px;font-family:var(--sans);font-variant-numeric:normal;font-size:.78rem;line-height:1.4;color:var(--muted);font-weight:400;text-align:left}
.oc .m:empty{display:none}
.oc:has(.m:not(:empty)){text-align:left}
/* Sentence-length output values: sans face, left-aligned, normal tracking.
   Applied by set() at runtime, so a card that holds a figure keeps the mono
   accounting treatment while a card that holds analysis reads as text. */
.oc .v.prose{font-family:var(--sans);font-variant-numeric:normal;font-size:.875rem;
font-weight:600;line-height:1.5;text-align:left;color:var(--body);letter-spacing:0}
.oc:has(.v.prose){text-align:left}
/* A sentence-length answer must never be squeezed into a quarter track.
   The full-width promotion used to live only inside the >=1101px split, so
   between 701px and 1100px a prose card rendered as a ~150px tower running
   hundreds of pixels down the page. Promote it at every width instead. */
.cards4>.oc:has(.v.prose){grid-column:1/-1}
@media(max-width:700px){.cards4>.oc:has(.v.prose){grid-column:1/-1}}
.oc .v.prose.pos{color:var(--pos)}.oc .v.prose.neg{color:var(--neg)}
.out-hero .v.prose{font-family:var(--sans);font-size:1.24rem;line-height:1.35;
letter-spacing:-.01em}
.split{padding:18px 20px;border-top:1px solid var(--stroke)}
.split h3{margin:0 0 12px;font-size:.75rem;letter-spacing:.13em;text-transform:uppercase;color:var(--dim);font-weight:800}
.bar{display:flex;height:13px;border-radius:99px;overflow:hidden;background:var(--surface2);margin-bottom:11px}
.bar i{display:block;transition:width .5s cubic-bezier(.4,0,.2,1)}
.keys{display:flex;flex-wrap:wrap;gap:7px 18px;font-size:.79rem;color:var(--muted)}
.keys span{display:inline-flex;align-items:center;gap:7px}
.keys u{width:10px;height:10px;border-radius:3px;text-decoration:none}
.legend .ky{display:inline-flex;align-items:center;gap:7px;color:var(--body)}
.legend .ky u{width:10px;height:10px;border-radius:3px;text-decoration:none;display:inline-block;flex:0 0 10px}
.ky-b u{background:var(--brand)}.ky-i u{background:var(--neg)}.ky-e u{background:var(--pos)}
/* The chart legend and the amortisation table must stay inside a 320px
   viewport. Removing the sticky header at that width (fold work, b42)
   reflowed them, so both are explicitly constrained here. */
@media(max-width:380px){
  .legend{flex-wrap:wrap;min-width:0}
  .legend .ky{min-width:0;font-size:.72rem}
  .keys{gap:6px 12px;font-size:.72rem;min-width:0}
  .tbl-w.amort{overflow-x:auto;-webkit-overflow-scrolling:touch}
  .tbl-w.amort table{min-width:0;font-size:.74rem}
  .tbl-w.amort th,.tbl-w.amort td{padding:6px 6px;white-space:nowrap}
}
.chart-w{padding:18px 20px 20px;border-top:1px solid var(--stroke)}
.chart-w canvas{width:100%;height:200px;display:block;max-width:100%}
.tabs{display:flex;gap:6px;margin:26px 0 12px;flex-wrap:wrap}
.tab{font:inherit;font-size:.83rem;font-weight:700;color:var(--muted);background:var(--surface);
border:1px solid var(--stroke);padding:8px 15px;border-radius:99px;cursor:pointer;transition:.18s}
.tab:hover{color:var(--txt);border-color:var(--stroke2)}
/* Free-entry term presets. The number input is the control; these are
   shortcuts. --muted on --surface clears the contrast gate; min-width:0 and
   flex-wrap keep them inside the grid track at every viewport. */
.chips{display:flex;flex-wrap:wrap;gap:6px;margin:7px 0 0;min-width:0}
.chip{font:inherit;font-size:.74rem;font-weight:700;letter-spacing:.01em;
color:var(--muted);background:var(--surface);border:1px solid var(--stroke);
padding:4px 10px;border-radius:99px;cursor:pointer;transition:.16s;white-space:nowrap}
.chip:hover{color:var(--txt);border-color:var(--stroke2)}
.chip:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.chip[aria-pressed=true]{background:var(--tint);border-color:var(--brand);color:var(--txt)}
.tab[aria-selected=true]{background:var(--tint);border-color:var(--brand);color:var(--txt)}
.amort{max-height:430px;overflow-y:auto}
.amort table{min-width:560px}
.amort thead th{position:sticky;top:0;z-index:2;background:var(--sticky)}
.amort tbody tr.yr{background:var(--tint-b);font-weight:700}
aside.rail{position:sticky;top:84px;display:flex;flex-direction:column;gap:16px}
@media(max-width:1000px){aside.rail{position:static}}
.rail section{padding:18px}
.rail h2,.rail h3{font-size:.75rem;letter-spacing:.13em;text-transform:uppercase;color:var(--dim);margin:0 0 12px;font-weight:800}
.rail ul{list-style:none;margin:0;padding:0}
.rail li{margin-bottom:7px}
.rail li a{color:var(--soft);font-size:.86rem;font-weight:600;display:block;padding:2px 0;transition:.15s}
.rail li a:hover{color:var(--brand2);transform:translateX(3px);text-decoration:none}
.author{display:flex;gap:13px;align-items:flex-start;padding:20px;margin:2rem 0}
.author .av{width:50px;height:50px;flex:0 0 50px;border-radius:14px;display:grid;place-items:center;
font-family:var(--mono);font-weight:800;font-size:1.1rem;color:#fff;
background:linear-gradient(135deg,var(--brand),var(--brand3));background-color:#4f46e5;box-shadow:0 8px 20px -8px rgba(99,102,241,.9)}
.author .m{font-size:.85rem;color:var(--muted);margin:0}
.author .n{font-weight:800;color:var(--txt);font-size:.98rem;display:block;margin-bottom:2px}
.author .r{font-size:.73rem;color:var(--dim);display:block;margin-bottom:7px;text-transform:uppercase;letter-spacing:.08em;font-weight:700}
.steps{counter-reset:s;list-style:none;margin:1.1rem 0 1rem;padding:0}
.steps li{counter-increment:s;position:relative;padding-left:42px;margin-bottom:14px;color:var(--body)}
.steps li::before{content:counter(s);position:absolute;left:0;top:-1px;width:28px;height:28px;border-radius:9px;
display:grid;place-items:center;font-family:var(--mono);font-size:.82rem;font-weight:800;color:var(--brand2);
background:var(--tint);border:1px solid var(--stroke2)}
.rel{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:10px;margin-top:16px}
.rel a{display:block;padding:13px 15px;font-size:.88rem;font-weight:600;color:var(--soft);background:var(--surface);
border:1px solid var(--stroke);border-radius:12px;transition:.18s}
.rel a:hover{border-color:var(--brand);background:var(--tint);color:var(--txt);transform:translateY(-2px);text-decoration:none}

.limits{margin:16px 0 0;padding:16px 18px;border:1px dashed var(--stroke);
border-radius:var(--r);background:rgba(127,127,127,.05);min-width:0}
.limits h3{margin:0 0 8px;font-size:.78rem;letter-spacing:.11em;text-transform:uppercase;
color:var(--dim);font-weight:800}
.limits ul{margin:0;padding-left:18px}
.limits li{font-size:.88rem;color:var(--muted);margin-bottom:5px;min-width:0}
.pc-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(280px,100%),1fr));
gap:14px;margin:1.1rem 0}
.pc{min-width:0;padding:18px 20px;border-radius:var(--r);border:1px solid var(--stroke);
background:var(--surface)}
.pc h3{margin:0 0 10px;font-size:.95rem}
.pc ul{margin:0;padding-left:18px}
.pc li{margin-bottom:7px;font-size:.9rem;min-width:0}
.pc-pro{border-left:3px solid var(--pos)}
.pc-con{border-left:3px solid var(--neg)}
.risk-bar{--warn:#f59e0b;--warn-ink:#fbbf24;
display:flex;gap:12px;align-items:flex-start;margin:1.1rem 0;padding:15px 18px;
border-radius:var(--r);border:1px solid var(--stroke);border-left:3px solid var(--warn);
background:rgba(245,158,11,.07)}
/* The amber that reads on a dark surface fails AA on a light one, so the ICON
   colour (which carries text-level contrast) darkens while the 3px rule, which
   is a non-text boundary, keeps the brand amber. */
html[data-theme=light] .risk-bar{--warn-ink:#92400e;--warn:#b45309}
.risk-bar .risk-i{font-size:1.1rem;line-height:1.4;flex:0 0 auto;color:var(--warn-ink)}
.risk-bar p{margin:0;font-size:.89rem;color:var(--muted);min-width:0}
