/* ==========================================================================
   style.css — this page's layout, measures and copy styling.

   The last of three layers: brand-kit.css → theme.css → style.css. Anything
   here is specific to THIS page. Shared components (card surface, sliders,
   the big figure, page shell) live in theme.css — put new shared pieces
   there, not here. There is no dollar figure anywhere in this product.

   Typography/color values below were merged in from import/hours-breakdown-
   final.css (2026-08-10) — see DEVLOG for the full diff against that file:
   what was adopted, what was reverted (the .restate.flag distinction and
   the zero gap between .hero-stat/.restate, both explicit prior decisions),
   and what was left out as either dead code (an unused --space-* scale,
   ::-webkit-slider-runnable-track rules that don't apply given this page's
   appearance:none + gradient-background slider technique) or a likely
   unintended value (.bar-track's border-radius, which stayed at this
   page's usual 999px pill rather than that file's 1px).
   ========================================================================== */

:root {
    color-scheme: light;
    /* Base measure for prose inside the answer card (see .answer-text) —
       everything wider than the paragraph itself (the card, then the whole
       two-column grid at desktop) is derived FROM this single value via
       calc(), not chosen as a separate, independently-guessed number. See
       DEVLOG for the full reasoning. */
    --answer-measure: 70ch;
    /* Same idea as --answer-measure above, for the other side of the
       page: .fn's own natural reading measure. Shared here rather than
       left as .fn's own private literal, since the ≥1024px fix below
       needs the identical value and a second hand-typed number would be
       one more place to forget to update if this ever changes. */
    --scenario-measure: 52ch;
    --card-padding-x: 1.75rem;
}

/* ── Ranked bar chart ──
   Grid, not flex: .bars is the grid container and each .bar-row is
   display:contents, so its three children (name/track/num) become direct
   grid items sharing .bars's own column tracks across every row. That's
   what makes this robust against the card narrowing to the answer measure:
   the "auto" name/num columns size themselves to the WIDEST label/number
   across all 5 rows (not a fixed % or px guess that can be too narrow for
   the longest one, "Scheduling and handovers"), white-space:nowrap
   guarantees neither ever wraps regardless, and because the column widths
   are computed from the full set of rows rather than per-row, re-sorting
   which bar is .lead (first) never changes any column's width — the
   layout can't lose its balance when the order changes. */
.bars {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    column-gap: 0.75rem;
    row-gap: 0.55rem;
    font-size: 0.875rem;
    line-height: 1.3;
}

.bar-row {
    display: contents;
}

.bar-name {
    white-space: nowrap;
    font-family: var(--font-family--heading);
    font-weight: 400;
    color: var(--calc-ink-soft);
}
.bar-row.lead .bar-name {
    color: var(--calc-ink);
    font-weight: 500;
}

.bar-track {
    height: 6px;
    border-radius: 999px;
    background: var(--calc-accent-soft);
    overflow: hidden;
}
.bar-fill {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: var(--color-electric-blue);
    opacity: 0.35;
}
.bar-row.lead .bar-fill {
    opacity: 1;
}

.bar-num {
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    font-size: 0.75rem;
    color: var(--calc-ink-faint);
    text-align: right;
}

/* ── Hero number ──
   Switched to the heading font + real weight so it reads as the page's one
   genuine display moment, rather than inheriting the same body font/weight
   as everything else at a bigger size. line-height 1.5 — an earlier, much
   tighter value (0.95) read as cramped. One clamp() for both mobile and
   desktop now (was two separate ones) — simpler, and close enough to both
   prior values that the extra breakpoint-specific override wasn't earning
   its keep. */
.hero-stat {
    font-family: var(--font-family--heading);
    font-weight: 500;
    line-height: 1.5;
    letter-spacing: -0.03em;
    /* Per request: bigger, not chunkier — weight stays 500. Floor/ceiling
       raised (2.75rem→3rem, 3.5rem→4rem) and the preferred slope steepened
       (4vw→4.5vw) so growth actually starts around the 1024px two-column
       breakpoint rather than ~1100px — at the old 4vw slope, the number
       sat pinned at its floor value across almost the entire practical
       viewport range and only grew close to the ceiling above ~1400px. */
    font-size: clamp(3rem, 4.5vw, 4rem);
}

/* Trailing annotation ("10.5 hours each week") — brand-preview's .hero-stat
   is always a bare number by default, this is the one new shape this page
   needed. inline-block + its own line-height/letter-spacing keep it from
   inheriting .hero-stat's display-type values. */
.hero-stat .unit {
    display: inline-block;
    vertical-align: baseline;
    margin-left: 0.5rem;
    font-family: var(--font-family--body);
    font-weight: 400;
    font-size: 1.125rem;
    line-height: 1;
    letter-spacing: 0;
    color: var(--calc-ink-soft);
}

/* ── "Answer card" internal hierarchy ──
   Everything on the results side lives in one .calc-card (see index.html)
   instead of four separately-styled pieces — a plain hero block, a white
   card, a blue .insight callout, a plain closing paragraph. Hierarchy
   inside the single card is typographic — size, weight, color, spacing —
   rather than background color or a border (see the DEVLOG entry for this
   change for the design-hierarchy sources). Read top to bottom, loudest to
   quietest: .hero-stat → .restate → .bars →
   .answer-cta / .answer-insight (the reply-invitation → expert-insight
   sequence added per import/Results Section — Copy & Visual Hierarchy
   Specification.md — see the rules themselves, below, for how each one is
   styled; the spec's third stage, result interpretation, was dropped —
   see DEVLOG 2026-08-19) → .answer-shift (the "some of this should stay"
   concession), now the card's closing note instead of sitting right
   after the bars — see DEVLOG (2026-08-18). */

/* clamp(), not a fixed value — on taller viewports these three margins (and
   .calc-card's own bottom padding, below) grow toward their ceiling, so the
   card naturally uses more of its column's available height instead of
   leaving empty space under it; on shorter viewports they compress toward
   the floor instead of forcing a scroll. All three stay matched to each
   other (same clamp), same reasoning as when they were a fixed 2rem. */
.layout__results .calc-card > .bars {
    margin-top: clamp(2rem, 5vh, 3rem);
}

/* No margin between .hero-stat and .restate — deliberate: they read as one
   continuous unit (the number, then its restatement), not two separate
   ideas. Needs zeroing on both sides — .hero-stat has no margin-bottom of
   its own to begin with, but style.css's shared .restate sets
   margin-top: 14px, which this overrides. */
p.restate {
    margin-top: 0;
    margin-bottom: 0;
    font-size: 1.25rem;
    font-weight: 500;
    line-height: 1.4;
    color: var(--calc-ink);
}

/* The one moment on the page designed to stand out: the five scenes add up
   to the visitor's whole week, or more than it. Only overrides color/weight
   — font-size stays inherited from p.restate above. */
.restate.flag {
    color: var(--color-electric-blue);
    font-weight: 600;
}

/* Now a single running paragraph (like .answer-cta/.answer-insight below,
   not a heading + separate body line) — .answer-text supplies its
   typography, this only adds the margin-top shared by every other major
   internal break in the card. Only "P.S." itself stays bold (via the
   plain <strong> in index.html, given its own font-weight below since the
   rest of the page's bold text is 600, not the browser's default 700 for
   <strong>) — everything else in the sentence reads as plain body copy. */
.answer-shift {
    margin-top: clamp(2rem, 5vh, 3rem);
}
.answer-shift strong {
    font-weight: 600;
}

/* Shared by .answer-shift and .answer-insight below — both read as the
   same kind of text (same size, same weight, same muted color), so they
   share one class instead of two near-duplicate rules. */
.answer-text {
    max-width: var(--answer-measure);
    font-size: 1rem;
    line-height: 1.6;
    color: var(--calc-ink-soft);
}

/* ── Results-section hierarchy (import/Results Section — Copy & Visual
   Hierarchy Specification.md) ──
   .answer-cta and .answer-insight, below, each read as one running
   paragraph — see each rule for why. Both share the same
   clamp(2rem, 5vh, 3rem) margin-top used everywhere else in the card for a
   major register shift. (.answer-interpret, the spec's first stage —
   result interpretation — was removed; see DEVLOG 2026-08-19.) */

/* .answer-cta-lede/.answer-cta-value are <span>s now, not <p>s — the reply
   invitation and the "why it's useful" follow-up read as one continuous
   sentence flowing together, not two stacked lines, so the parent
   <p class="answer-cta"> carries the shared size/color and only the value
   half keeps its own font-weight on top of that. */
.answer-cta {
    margin-top: clamp(2rem, 5vh, 3rem);
    max-width: var(--answer-measure);
    font-size: 1rem;
    line-height: 1.6;
    color: var(--calc-ink-soft);
}
.answer-cta-value {
    font-weight: 500;
}

/* The mailto link on "reply" — resting state (weight 500, electric blue,
   no underline) is its own rule rather than brand-kit.css's shared `a`
   default (color: inherit, i.e. .answer-cta's ink), since this link needs
   to read as a link even before it's hovered. The hover state is left
   entirely to brand-kit.css's own `a:hover` (already loaded on this page)
   rather than repeated here — same electric-blue underline, offset 5px
   from the text (text-underline-offset), not flush against the
   descenders like a default underline. */
.answer-link {
    /* font-weight: 500; */
    color: var(--color-electric-blue);
}

/* .answer-insight is now a single <p class="answer-insight answer-text"> —
   the expert-insight line, its explanation, and the closing sentence used
   to be three separate lines (one of them an .answer-heading, one an
   .answer-closing), reworked into one flowing paragraph in plain body-copy
   styling per request, so .answer-text supplies all of its typography and
   this rule only adds the margin-top the other two major blocks also get. */
.answer-insight {
    margin-top: clamp(2rem, 5vh, 3rem);
}

/* ── Left column (sliders) ──
   Scoped to .layout__inputs / specific elements rather than edited in the
   shared style.css or brand-preview/theme.css — this-page-only
   adjustments, not changes to the brand system or the production
   calculator. */

/* width was calc(100% - 25px) — a purely stylistic request from earlier in
   this page's history, not a technical constraint. Removed: it made the
   slider's right edge fall short of the label/caption text above it,
   which spans the row's full width — visible on mobile especially, where
   there's no second column to distract from the mismatch. Full width now
   matches every other element in this row. */
.layout__inputs input[type="range"] {
    height: 6px;
}

/* .control-group is applied to both the outer wrapper (the 5 scene
   sliders + the anchor slider block, as siblings) and to #scenes itself
   (the 5 scene sliders' own container) — the only two elements on this
   page that used to carry the shared .fields class, both fully
   overridden to the same values anyway (gap, margin-bottom), so .fields
   was buying nothing here beyond the display:flex/flex-direction it
   restates below directly. One class, one rule, both elements — instead
   of .fields (shared) + .control-group (page-specific) + a separate
   #scenes override all converging on the same computed style. */
.control-group {
    display: flex;
    flex-direction: column;
    gap: 2rem;
    margin-bottom: 0;
}

/* .fn is defined only here, and deliberately as a complete rule rather than
   a patch. It inherited a px-based definition (font-size: 12px; color:
   var(--text-3); margin-top: 4px) from the original calculator's stylesheet,
   which this page overrode property-for-property; when that stylesheet was
   dropped, the override became the whole definition. The rule below sets every property
   style.css sets for .fn, in rem — a complete, self-contained definition
   for this page, not a partial patch on top of the shared px-based one. */
.fn {
    margin-top: 0.25rem;
    margin-bottom: 0.25rem;
    max-width: var(--scenario-measure);
    color: #6B7280;
    font-size: 0.9375rem;
    line-height: 1.5;
}

/* theme.css's shared .calculator sets padding: 2.25rem 1.25rem 3rem —
   bottom tightened here (3rem → 1.5rem), left/right untouched. top gets
   its own override too, but it's mobile-only (further down, inside the
   max-width: 1023.98px block) — at 1024px and up, .calculator's top
   padding falls back through to theme.css's own 2.25rem unchanged; this
   comment previously (and incorrectly) called that a desktop override.

   max-width override, per request: theme.css also sets max-width: var(
   --calc-width) (30rem) on .calculator, capping it to a narrow reading
   column below the desktop breakpoint — the desktop block further down
   already drops this to none. Overridden here rather than by changing
   --calc-width in theme.css, so theme.css keeps a sensible general default
   for anything reusing that layer — the page-specific decision stays on
   the page-specific layer. Net effect
   is the same either way for this page: none, at every width, not just
   desktop. */
.calculator {
    padding-bottom: 1.5rem;
    max-width: none;
}

/* Per request: max-width stays `none` below 600px (phones — full width is
   fine, there's no room for it to matter) and at 1024px+ (the 2-column
   grid manages its own width via .calculator's padding, not a centered
   cap). In between — mostly iPad mini/Air/Pro portrait — full width made
   the sliders read as too long. min(80vw, 40rem): 80vw scaling (tuned up
   from an initial 75vw per follow-up feedback) for the narrower end of
   this range, capped at 40rem (640px) so it doesn't grow long again
   approaching 1024px — pure 80vw would still reach 819px wide right below
   that boundary. theme.css's own `margin: 0 auto` on .calculator (never
   overridden) is what centers it once max-width is finite again here. */
@media (min-width: 600px) and (max-width: 1023.98px) {
    .calculator {
        max-width: min(80vw, 40rem);
    }

    /* Second half of the header/.calculator left-alignment fix (see
       .site-header__inner's padding-inline override in the mobile-stack
       block further down for the padding half). Once .calculator gets a
       finite max-width here, theme.css's own `margin: 0 auto` centers it —
       giving .site-header__inner the identical max-width + auto-centering
       makes it resolve to the exact same box, at every width in this
       range, rather than computing a matching offset by hand (which would
       silently drift out of sync if .calculator's own width formula ever
       changes again). */
    .site-header__inner {
        max-width: min(80vw, 40rem);
        margin-inline: auto;
    }

    /* Same range, same reasoning as the two rules below it in the mobile-
       stack block further down (.sub's max-width, .site-footer__* matching
       brand-kit.css's mismatched 600px breakpoint): style.css's shared .sub
       sets max-width: 430px, a fixed value that reads arbitrarily narrow
       once .calculator itself is fluid (min(80vw, 40rem) above) rather than
       full-width. 90% of .calculator's own width scales with it instead.
       Scoped here rather than style.css so the other pages sharing .sub are
       untouched — same pattern as the ≥1024px .sub override further down. */
    .sub {
        max-width: 90%;
    }
}

/* .site-footer's own padding (brand-kit.css: 2rem 1.5rem) overridden here
   rather than at the source, same reasoning as .fn above — brand-kit.css
   is shared with other pages. Horizontal padding (1.5rem) untouched. */
.site-footer {
    padding-top: 1rem;
    padding-bottom: 1rem;
}

/* brand-kit.css's gradient line fades to #050909 (near-black) — correct on
   the real site's dark navy background, wrong on this page's light one.
   Fading all the way to --bg (tried first) turned out too literal: the
   line and the page become the exact same color, so the last stretch
   before the copyright text reads as not there at all, leaving the text
   feeling detached rather than connected by a fading line. Fades to
   --border instead — the same subtle gray-over-white tint this page
   already uses for visible-but-quiet dividers — so the line stays
   faintly present the whole way through rather than disappearing. Only
   ever visible at ≥1024px on this page (hidden below that per the
   earlier fix), but left unscoped here rather than nested in that media
   query — harmless either way, and simpler. */
.site-footer__gradient-line {
    background-image: linear-gradient(90deg, var(--color-electric-blue), var(--border));
}

/* Per request: one size everywhere, not just through the mobile-stack range
   (the other three brand-kit.css 600px overrides above stay scoped to that
   range, since they only matter for matching this page's own 1024px
   breakpoint — this one's simpler, a flat "always 0.85rem" with no
   breakpoint-matching logic needed). Unconditional, so it also overrides
   brand-kit.css's own >=600px `font-size: unset` at 1024px and up, where
   nothing was overriding it before. */
.site-footer__copyright {
    font-size: 0.85rem;
}

/* brand-kit.css's .site-header__logo img sets height:2rem (32px) — bigger
   than the live site's own header logo, which renders at 27px. Overridden
   here rather than at the source for the usual reason (shared file). */
.site-header__logo img {
    height: 1.6875rem;
}

/* .site-footer__logo has no display override in brand-kit.css (unlike
   .site-header__logo, which is display:flex — flex items get blockified
   automatically, so this issue never shows up there), so its <img> stays a
   genuine inline-replaced element: its line box is governed by the
   surrounding line-height, not just the image's own pixel height, leaving
   invisible space below it that isn't part of the image at all. At mobile
   (.site-footer__inner is a flex column below brand-kit.css's own 600px
   breakpoint), that extra space reads as a bigger gap before the copyright
   line than the deliberate row-gap: 0.35rem actually calls for. display:
   block is the standard fix — takes the image out of inline layout
   entirely, so its box is exactly its own rendered height. */
.site-footer__logo img {
    display: block;
    /* Not a layout bug — the flex centering above is correct by
       calculation. appx-solutions-logo-dark.svg's own artwork has a
       chevron sitting above the wordmark, offset from it by design, baked
       into the file as part of the image's bounding box — so the
       wordmark's own visual weight isn't centered within that box the way
       the box itself is centered in the footer. Per request: a negative
       margin-top on the image pulls it up against the SVG's own
       asymmetry to compensate (tuned to -6px after an initial -2px
       undershot it). Pixel value, not rem — this corrects one specific
       asset's own geometry, not something on the page's type scale. */
    margin-top: -6px;
}

/* Second half of the same gap: .site-footer__logo itself (the <a>) was
   still missing what .site-header__logo gets in brand-kit.css directly
   (display: flex; align-items: center;) — without it, the anchor's own
   box wraps its now-block img with no internal centering reference of its
   own. At the row breakpoints (.site-footer__inner is flex row, per
   request its items should be vertically centered against each other),
   this is what was reading as the logo sitting lower than the gradient
   line/copyright text next to it. Matches .site-header__logo's own
   pattern exactly rather than inventing a different fix for the same
   underlying gap. */
.site-footer__logo {
    display: flex;
    align-items: center;
}

/* font-size/font-weight set on the row; the label <span> picks both up
   through inheritance, but <strong> needs its own explicit font-weight: 500
   even though it matches the row's value — browsers bold <strong> by
   default (a UA rule, not just "no weight set"), so without this it would
   render bold regardless of what the row declares. font-size does inherit
   normally, so it's left off .scenario-slider-row strong on purpose.
   tabular-nums keeps the live-updating value from shifting width as its
   digits change. */
.scenario-slider-row {
    gap: 1rem;
    font-size: 1rem;
    font-weight: 500;
}
.scenario-slider-row strong {
    flex: none;
    font-weight: 500;
    color: var(--calc-ink-soft);
    font-variant-numeric: tabular-nums;
}

/* Mobile only — the sliders sit directly on .calculator's own padding
   (no wrapping card of their own), so the value's right edge lands flush
   with .calculator's content boundary, exactly where .calc-card's border
   sits too, further down the same stacked column. That flush alignment
   read as too tight next to the card's border — this pulls the value in
   slightly. Not needed at desktop, where sliders and the card are in
   separate grid columns with their own spacing already.

   The slider <input> itself is .scenario-slider-row's sibling, not its
   child, so that 0.5rem doesn't reach it — full-width (restored above) ran
   the track out past where the now-inset value sits, undoing the alignment
   this was meant to fix. Matched here with the same 0.5rem rather than a
   separate guessed value, so the two line up exactly instead of
   approximately. */
/* "Mobile only" here means max-width just below the 2-column breakpoint
   above (1024px) — kept as its own literal number rather than reusing a
   variable so it self-documents at a glance, same as every other
   media-query boundary in this file. Catch: this was still `859px` from
   an earlier breakpoint iteration (860px) until this pass — with the
   2-column breakpoint since moved to 1024px, that stale ceiling would
   have left 860–1023px unstyled by every rule below (wrong .calculator
   padding-top, missed .sub/slider spacing fixes) despite still being
   inside the mobile stack. */
@media (max-width: 1023.98px) {
    .scenario-slider-row {
        padding-right: 0.5rem;
    }

    .layout__inputs input[type="range"] {
        width: calc(100% - 0.5rem);
    }

    /* H1 and .sub read as too far apart — .calculator's own flex gap
       (1.5rem/24px, the spacing between every top-level element in the
       mobile stack) applies here too, stacking on top of the H1's own
       margin-bottom (12px) for 36px total. Negative margin-top cancels
       exactly the flex-gap contribution, leaving just the H1's own 12px —
       not a smaller-but-arbitrary gap, the flex gap's precise inverse.

       margin-bottom: 1rem for the same reason on the other side — style.css's
       shared .sub sets margin-bottom: 40px, written for the original
       calculator's pre-flex-gap design, where margins were the only
       spacing mechanism. Here it was stacking with .calculator's own
       1.5rem gap for 64px total after the lede — too much. Zeroing it
       outright (tried first) turned out too tight against the first
       slider below; 1rem adds to the 1.5rem flex gap for 2.5rem (40px)
       total — deliberately picked, not the original's incidental 64px.
       .sub is only used once on this page, so this doesn't create any
       inconsistency. theme.css keeps the original 40px as the base value,
       which is still what applies at desktop widths. */
    .sub {
        margin-top: -1.5rem;
        margin-bottom: 1rem;
    }

    /* theme.css's shared .calculator sets padding: 2.25rem 1.25rem 3rem —
       top padding tightened here (2.25rem → 1.5rem, after a first pass at
       2rem still left too much space), left/right/bottom untouched. */
    .calculator {
        padding-top: 1.5rem;
    }

    /* Left-edge alignment against the header logo, per request — .calculator
       stays centered (theme.css's own `margin: 0 auto`, untouched); the
       header is made to match ITS box instead of the other way around
       (a same-direction attempt — .calculator's own margin/padding pulled
       left to meet the header — was tried first and reverted: it broke the
       centering this page otherwise relies on).

       brand-kit.css's .site-header__inner is 1.5rem padding with no
       effective centering below its own 1200px max-width (viewport is
       always narrower than that here, so the box just fills the container
       and 1.5rem is the whole story) — .calculator's own padding-inline is
       theme.css's 1.25rem, not 1.5rem, so matched here rather than picking
       a value to split the difference. Below 600px this is the whole fix:
       both boxes are full-width with matching padding, so their left edges
       already coincide. */
    .site-header__inner {
        padding-inline: 1.25rem;
    }

    /* The opposite problem, same cause: .calculator's flex gap (1.5rem)
       is what separates .control-group (the sliders, ending with the
       anchor slider) from .calc-card — smaller than .control-group's own
       2rem gap between individual sliders, so the last slider sat closer
       to the card than the sliders sit to each other. margin-top here adds
       to that 1.5rem flex gap for a 2.5rem total — a bit more than the
       2rem inter-slider gap, not just equal to it. */
    .calc-card {
        margin-top: 1rem;
    }

    /* brand-kit.css's own breakpoint for this is 600px (.site-footer__gradient-line
       goes display:block above it) — a mismatch on this page, where 600–1023px is
       still the single-column mobile stack (per the 1024px breakpoint this whole
       block is scoped to), not the two-column desktop arrangement the gradient
       line was designed to sit inside. Forcing it back to none for the entire
       "mobile means max-width: 1023.98px" range so every stacked width gets the
       same footer, matching phone. */
    .site-footer__gradient-line {
        display: none;
    }

    /* Same mismatch, same fix, for the row the gradient line sits in: brand-kit.css
       switches .site-footer__inner from column to row at its own 600px breakpoint.
       Stays column through the full 600–1023px stacked range here, row only once
       this page itself goes two-column at 1024px (brand-kit.css's own >=600px rule
       handles that, unchanged). */
    .site-footer__inner {
        flex-direction: column;
    }

}

/* ── Solid brand-navy header, light logo ──
   Per request — the actual brand-kit navy instead of the light theme, no
   blur/transparency, resting and scrolled both the same solid color.
   --color-bg is brand-kit.css's own page-background navy (#060c1a) — "the
   solid navy" most directly, not a derived/semi-transparent value like
   the blur experiments above (now superseded by this rule; .is-scrolled
   no longer needs its own separate treatment since resting and scrolled
   are identical now). Not media-query-scoped — applies at every width,
   including the ≥1024px default (below), where <header> stays visible
   rather than being replaced by a grid-based logo. .site-footer was part
   of this experiment too (same navy background, light logo) but was
   reverted back to no background per request — its logo stays dark
   (index.html), unlike the header's light-on-navy. */
.site-header {
    background-color: var(--color-bg);
}

/* ── Accessibility ── */
.calculator input[type="range"]:focus-visible {
    outline: 2px solid var(--color-electric-blue);
    outline-offset: 4px;
}

@media (prefers-reduced-motion: reduce) {
    * {
        transition: none !important;
        animation: none !important;
    }
}

/* ── DESKTOP LAYOUT: sliders left, results right ──
   Below the breakpoint, .layout/.layout__title/.layout__inputs/
   .layout__results use display:contents — they exist only to label the
   two halves in markup, not to affect layout — so .calculator's own flex
   column + gap applies directly to their children exactly as if these
   wrappers didn't exist. That keeps the mobile experience byte-for-byte
   unchanged regardless of what the desktop grid below does. */
.layout,
.layout__title,
.layout__inputs,
.layout__results {
    display: contents;
}

/* ── DEFAULT LAYOUT ≥1024px: two columns, header carries the logo ──
   Per request, simplified back down to one breakpoint: below 1024px,
   stacked (mobile default, above); at 1024px and up, this two-column grid
   — no orientation check, no upper bound. <header> stays visible and
   carries the logo at every width, including this range; there's no
   separate grid-based logo column. 1024px chosen to match iPad Pro
   12.9" portrait (the widest iPad portrait width) — everything narrower
   stacks, that width and up gets this grid regardless of device or
   orientation. */
@media (min-width: 1024px) {
    /* --card-cap / --calculator-max-width are used here and by
       .site-header__inner / .site-footer__inner further down — same
       values, not separately guessed numbers per element.

       Earlier version of --calculator-max-width solved for "the width at
       which the results column exactly equals --card-cap," which fixed
       the results column but, per feedback, left the *inputs* column
       oversized relative to its own content: at that width, the 1fr:1.25fr
       split gives the inputs column more room than --scenario-measure
       actually needs, and since .layout__inputs is independently capped
       at --scenario-measure (below), that extra room becomes unused slack
       sitting between the sliders and the gap — which is what was reading
       as "too much space between the slider and the card." Investigated
       whether some single width could make both columns land exactly on
       their own content caps simultaneously: it can't, in general — that
       would require the grid's fixed 1:1.25 ratio to equal the actual
       ratio between --scenario-measure and --card-cap, which there's no
       reason to expect and isn't the case here. Per request, not
       touching column-gap or the 1fr:1.25fr ratio to force that; instead
       --calculator-max-width is now literally the sum of both content
       measures plus the fixed overhead between them (2rem padding × 2 +
       4rem column-gap = 8rem) — a direct "combination of the card width
       and the slider width," per request, rather than extrapolated from
       only one of them. This doesn't give either column a perfect
       zero-slack fit (the 1:1.25 split still doesn't match the two
       measures' own ratio), but it's the closest a single shared width
       can get to both without changing the ratio or the gap, and it's
       already visibly tighter than the card-only version above. */
    :root {
        --card-cap: calc(var(--answer-measure) + var(--card-padding-x) * 2);
        --calculator-max-width: calc(var(--scenario-measure) + var(--card-cap) + 8rem);
    }

    .calculator {
        max-width: var(--calculator-max-width);
        width: 100%;
        /* Investigated per request: between 1024px and --calculator-max-width,
           .calculator was refusing to shrink smoothly with the viewport —
           staying pinned near its capped width while .site-header__inner/
           .site-footer__inner (which have almost no content of their own)
           shrank freely, breaking the alignment between them. Cause: flex
           and grid items default to min-width: auto, not 0 — meaning a
           flex/grid item won't shrink below its own content's min-content
           size unless told otherwise, regardless of an explicit width/
           max-width saying it should be able to. .calculator is a flex
           item of body (the sticky-footer fix above), .layout is in turn a
           flex item of .calculator (theme.css's own display:flex on
           .calculator), and .layout__inputs/.calc-card are grid items of
           .layout with plain 1fr/1.25fr tracks — every one of those is
           subject to the same default, and .calc-card's own big number
           (a large, unbreakable font-size) is a plausible source of a
           real min-content floor worth several hundred px. min-width: 0
           here removes .calculator's own link in that chain; .layout and
           the grid tracks get the same fix just below. */
        min-width: 0;
        /* Centered per request — theme.css's own .calculator already sets
           margin: 0 auto; restated here only as documentation that it's
           deliberate now that max-width is finite (it was inert, doing
           nothing, back when max-width was none). .site-header__inner and
           .site-footer__inner below match this same max-width and
           centering, so all three stay mutually aligned — left edges
           coincide because they're all centered boxes of the same width
           in the same containing block (<body>), not because any of them
           is pinned to a fixed inset from the viewport edge. */
        margin-inline: auto;
        padding-inline: 2rem;
        gap: 0;
        /* `ch` inside --calculator-max-width resolves against whatever
           font-size the element USING the property has, not .calc-card's
           own — .calc-card is a real descendant of .calculator so it
           inherits this correctly once it's set here; without it,
           --answer-measure's 70ch was resolving against the browser's
           16px default instead of the 0.9375rem the card's own text
           actually renders at (see DEVLOG). Matches .site-header__inner/
           .site-footer__inner below, which need the identical fix for the
           same reason. */
        font-size: 0.9375rem;
        /* Sticky-footer half 1 of 3 (with body and .site-footer below) —
           per request: on a tall/short-content combination (an iPad Pro
           12.9" portrait viewport is 1024×1366, right at this
           breakpoint's own width floor, and tall relative to how little
           vertical space the 2-column content needs at that width),
           .site-footer was rendering right after .calculator's natural
           height, with the rest of the tall viewport left as visible
           empty space below it — instead of at the bottom of the screen
           the way it already does at wider/shorter (landscape) viewports,
           where content naturally exceeds the viewport height and there's
           nothing to fill. flex: 1 1 auto lets .calculator grow to absorb
           that leftover space, pushing the footer down to the true
           bottom. */
        flex: 1 1 auto;
    }

    /* Sticky-footer half 2 of 3 — min-height (not height) is what keeps
       normal scrolling intact when content genuinely is taller than the
       viewport: it's a floor, not a cap, so body still grows past 100vh
       and scrolls exactly as before whenever content needs more room;
       this only changes what happens when content needs less. See
       .calculator above for the full reasoning. */
    body {
        display: flex;
        flex-direction: column;
        min-height: 100vh;
    }

    /* Sticky-footer half 3 of 3 — flex: none so .site-footer neither
       grows to share the leftover space with .calculator nor shrinks
       below its own natural height; it just sits at whatever height its
       content needs, pushed to the bottom by .calculator's growth above.
       See .calculator above for the full reasoning.

       padding-top/bottom: per request, doubled to 2rem at this width —
       the 1rem override further up this file (scoped to no width, i.e.
       mobile too) stays as the mobile value; this just re-overrides it
       back up for ≥1024px. */
    .site-footer {
        flex: none;
        padding-top: 2rem;
        padding-bottom: 2rem;
    }

    /* Two columns (inputs / results) — 1fr:1.25fr per request (was
       1fr:1.5fr, closer to even now).

       min-width: 0 — same reasoning as .calculator's own comment above:
       .layout is a flex item of .calculator (theme.css's display:flex),
       so it has the same default min-width: auto floor to remove.

       minmax(0, 1fr) / minmax(0, 1.25fr) — the same default applies one
       level down, to grid tracks and the items in them: a bare `1fr`
       track has an implicit `auto` minimum, so .layout__inputs/.calc-card
       (below) wouldn't shrink past their own content's min-content either,
       no matter what min-width: 0 is set on .layout itself. minmax(0, …)
       keeps the exact same 1:1.25 proportion (not a ratio change, just
       lets each track go below its content size when there isn't room) —
       .layout__inputs and .calc-card's own max-width caps still set the
       upper bound as before; this only changes the lower one. */
    .layout {
        display: grid;
        grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr);
        grid-template-rows: auto auto;
        column-gap: 4rem;
        row-gap: 1.25rem;
        min-width: 0;
    }

    .layout__title {
        display: block;
        grid-column: 1 / -1;
        grid-row: 1;
    }

    /* style.css's shared .sub sets max-width: 430px, a fixed value from the
       original single-column design. In the 2-column grid the title spans
       the full row (grid-column: 1 / -1 above), so a fluid measure reads
       better than a fixed one — scoped here rather than in style.css so
       the other pages sharing .sub are untouched. */
    .layout__title .sub {
        max-width: 45%;
    }

    /* max-width: the other half of the same regression as .calc-card's —
       .fn already caps itself at --scenario-measure independently, but
       the sliders next to it are width: 100% of .layout__inputs (via
       .control-group, which adds no width constraint of its own), and
       .layout__inputs itself had nothing capping IT — so it stretched to
       fill the full 1fr grid column regardless of what .fn was doing,
       leaving the slider tracks visibly wider than the text line next to
       them. Capped here at the same measure, the same way .calc-card is
       capped independently of its own (1.25fr) column — this column no
       longer stretches to fill whatever the grid ratio happens to give
       it. Default grid alignment (stretch, but bounded by max-width) puts
       it flush-left within the column on its own, matching .calc-card's
       side, so no explicit margin override is needed here the way
       .calculator/.site-header__inner/.site-footer__inner needed one.
       font-size: 0.9375rem for the same reason those three needed it —
       --scenario-measure's `ch` must resolve in the same context .fn's
       own does, not whatever this element would otherwise inherit. */
    .layout__inputs {
        display: block;
        grid-column: 1;
        grid-row: 2;
        max-width: var(--scenario-measure);
        font-size: 0.9375rem;
    }

    .layout__results {
        display: flex;
        flex-direction: column;
        grid-column: 2;
        grid-row: 2;
    }

    /* brand-kit.css's .site-header__inner has its own container (max-width:
       1200px, padding: 0 1.5rem, margin: 0 auto), independent of
       .calculator's above.

       max-width matches .calculator's own --calculator-max-width exactly
       (was --content-right-edge, a value computed to track .calc-card's
       actual right edge specifically — dropped along with .calculator's
       own centering: now that .calculator, .site-header__inner, and
       .site-footer__inner are all centered boxes of the identical width
       in the same containing block, they stay mutually aligned on both
       edges automatically, so there's no need for a card-specific
       tracking formula on top of that). margin-inline: auto (brand-kit.css
       already sets this — restated as documentation, same as
       .calculator's own) is what does the actual centering; padding-inline
       is this box's own internal breathing room around the logo, unrelated
       to the centering/alignment question. */
    .site-header__inner {
        max-width: var(--calculator-max-width);
        margin-inline: auto;
        padding-inline: 2rem;
        /* `ch` inside --calculator-max-width resolves against whatever
           font-size the element using the property has — needs 0.9375rem
           here for the same reason .calculator does (see its comment).
           Safe: .site-header__logo sets its own explicit font-size
           (1.25rem, in brand-kit.css), so nothing here actually renders at
           this size. */
        font-size: 0.9375rem;
    }

    /* The actual bug, found by comparing brand-kit.css's two rules
       directly rather than guessing: .site-header has no padding of its
       own, so .site-header__inner's max-width/centering resolves against
       the full viewport width. .site-footer, unlike .site-header, still
       carries brand-kit.css's own padding: 2rem 1.5rem — the 1.5rem
       horizontal half was never overridden (only padding-top/bottom were,
       above) — so .site-footer__inner's max-width/centering was resolving
       against a containing block 3rem narrower than .site-header__inner's.
       Above --calculator-max-width this was invisible (both containers had
       far more room than the cap needed either way, so both simply landed
       on the cap) — below it, .site-footer__inner had less room to work
       with and came out narrower, which is what was actually breaking the
       alignment between 1024px and the cap. Zeroed here so both containers
       give their __inner box the identical amount of room. */
    .site-footer {
        padding-inline: 0;
    }

    /* Same as .site-header__inner above, same reasoning, for the footer.
       .site-footer__copyright already sits at .site-footer__inner's own
       right edge via brand-kit.css's justify-content: space-between, so
       capping+centering this box is what actually moves the copyright
       text into alignment — unlike the header's cap, which is invisible
       with only a logo in the box. padding-inline is new here: brand-kit.css
       gives .site-footer__inner none of its own (its inset used to come
       from .site-footer, the parent, instead) — added directly on this
       element now so its own internal breathing room matches .calculator's
       and .site-header__inner's 2rem exactly, the same way each of those
       two carries its own rather than relying on an ancestor's. */
    .site-footer__inner {
        max-width: var(--calculator-max-width);
        margin-inline: auto;
        padding-inline: 2rem;
        gap: 0.5rem;
        /* Same fix as .site-header__inner above — see its comment. Safe
           here too: .site-footer__copyright sets its own explicit
           font-size (0.85rem, unconditional rule earlier in this file), so
           nothing in this box actually renders at 0.9375rem either. */
        font-size: 0.9375rem;
    }

    /* Card content-width = --answer-measure, plus its own horizontal
       padding on each side — the card is sized to comfortably hold the
       paragraph's measure, not the other way around.

       Padding is asymmetric on purpose: .hero-stat already sits close to
       the top border and reads fine that way (it's the anchor of the
       card), so padding-top only got a small bump. padding-bottom is the
       one that's fluid (clamp) — letting the card breathe more into its
       column's available height on taller viewports, rather than leaving
       empty space below it. */
    .layout__results .calc-card {
        padding-top: 1.35rem;
        padding-inline: var(--card-padding-x);
        padding-bottom: clamp(1.75rem, 5vh, 2.75rem);
        max-width: calc(var(--answer-measure) + var(--card-padding-x) * 2);
    }

    /* Downsize from mobile's 1rem. */
    .answer-cta,
    .answer-text {
        font-size: 0.9375rem;
    }
}

