/* ==========================================================================
   Homepage
   --------------------------------------------------------------------------
   Composition only. Every colour, radius, shadow and type size resolves
   through the tokens in css/design-system.css — there are no raw hex values
   in this file, deliberately, so the system stays the single source of truth.

   Replaces the ~350-line inline <style> block that used to sit in index.php.
   ========================================================================== */

/* Approximate navbar height. The hero subtracts it so "full height" means the
   viewport, not the viewport plus the bar above it. */
:root {
    --nav-h: 5.6rem;
}

/* --------------------------------------------------------------------------
   1. Hero

   Two columns from lg up — the pitch left, the two inputs right — stacking
   below 992px. It was previously a centred single column, the only centred
   block on the site, which also buried the inputs under the headline and lead
   where they fell at or below the fold on a laptop.

   min-height, never height: on a landscape phone the headline, lead, two
   fields and CTA do not fit, and content must grow past the fold rather than
   be clipped.
   -------------------------------------------------------------------------- */

/* A full screen, deliberately.

   This was briefly cut to 78vh to let the next section peek, on the theory
   that it would draw people down into the calculator. It does not: the wizard
   is display:none until toggleWelcome() runs, so what actually shows at the
   fold is Deal Advisory — a different offer competing with the two inputs
   right here. The hero is self-contained now that it is two columns: pitch,
   fields and CTA together, with nothing below it that helps the primary
   action. Keeping the first screen to just this is the point.

   .hero-scroll-cue below already signals there is more page. */
.home-hero {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: calc(100vh - var(--nav-h));
    min-height: calc(100svh - var(--nav-h));
    padding: var(--s6) 0 var(--s8);
    overflow: hidden;
}

/* Legacy hook. The hero is no longer collapsed when the wizard opens, but the
   rule stays defined so nothing that still references the class breaks. */
.home-hero.collapsed,
.welcome-section.collapsed {
    display: none;
}

/* Was a 40rem centred column — the only centred block on the site. Now a full
   width row, left aligned like every other section. */
.hero-stack {
    max-width: none;
    margin: 0;
    text-align: left;
}

/* Holds the measure at a readable length even though the column could be
   wider on a large screen. */
.hero-copy {
    max-width: 34rem;
}

.home-hero .eyebrow {
    margin-bottom: var(--s2);
}

.home-hero h1 {
    margin: 0 0 var(--s3);
}

/* Keeps the compound term whole; it otherwise broke as "rent-to-" / "own"
   at mobile widths. Plain hyphen retained for search and copy-paste. */
.home-hero h1 .nowrap {
    white-space: nowrap;
}

.home-hero .hero-lead {
    font-size: 1.125rem;
    line-height: 1.5;
    color: var(--ink-2);
    max-width: 34rem;
    margin: 0 0 var(--s5);
    /* Prevents the orphaned last word ("commission."). */
    text-wrap: pretty;
}

/* The tutorial link under the lead. Small and quiet: it announces the video
   without competing with the two inputs opposite, which are the hero's job.
   Tightens the lead's bottom margin when it is present, so the pair reads as
   one block rather than two separated paragraphs. Browsers without :has()
   simply get the roomier original spacing. */
.home-hero .hero-lead:has(+ .hero-watch) {
    margin-bottom: var(--s3);
}
.home-hero .hero-watch {
    margin: 0 0 var(--s5);
    font-size: var(--t-small);
}
.home-hero .hero-watch a {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    color: var(--accent);
    font-weight: 500;
    text-decoration: underline;
    text-underline-offset: 0.18em;
    text-decoration-color: var(--rule-strong);
}
.home-hero .hero-watch a:hover {
    text-decoration-color: currentColor;
}
.home-hero .hero-watch i {
    font-size: 1.15rem;
    line-height: 1;
}

/* Capped so the two fields still read as one object rather than stretching
   the full width of a wide column. Left aligned within its column, which puts
   it nearest the text it belongs to. */
.hero-form {
    max-width: 26rem;
    margin: 0;
    text-align: left;
}

.hero-field {
    margin-bottom: var(--s3);
}

.home-hero .form-label {
    font-size: var(--t-small);
    font-weight: 600;
    color: var(--ink);
    margin-bottom: 0.4rem;
}

/* The border lives on the group, not on its two children, so the "$" and the
   input read as a single field with no seam between them. */
.home-hero .input-group {
    background: var(--paper-raised);
    border: 1px solid var(--rule-strong);
    border-radius: var(--r-md);
    transition: border-color .15s ease, box-shadow .15s ease;
}
.home-hero .input-group .input-group-text {
    background: transparent;
    border: 0;
    color: var(--ink-3);
    padding-right: 0.1rem;
}
.home-hero .input-group .form-control {
    background: transparent;
    border: 0;
    color: var(--ink);
    padding-left: 0.3rem;
}
.home-hero .input-group .form-control:focus {
    box-shadow: none;
}
.home-hero .input-group:focus-within {
    border-color: var(--accent);
    box-shadow: var(--focus-ring);
}

/* Invalid state.

   The rules above are .home-hero .input-group .form-control (0-3-0) and beat
   Bootstrap's .form-control.is-invalid (0-2-0), which is why stock validation
   styling never appears here. The hero states its own error styling at
   matching specificity, and sits after :focus-within so a focused invalid
   field still reads as an error. */
.home-hero .input-group.hero-invalid,
.home-hero .input-group.hero-invalid:focus-within {
    border-color: var(--status-neg);
    box-shadow: 0 0 0 4px rgba(143, 31, 58, .16);
}
.home-hero .input-group.hero-invalid .input-group-text {
    color: var(--status-neg);
}
/* Bootstrap paints a warning glyph into the field background; the border and
   message carry the state here without crowding the number. */
.home-hero .input-group .form-control.is-invalid {
    background-image: none;
}
.home-hero .invalid-feedback {
    color: var(--status-neg);
    font-weight: 500;
    font-size: 0.8125rem;
    margin-top: 0.4rem;
}

.hero-cta {
    width: 100%;
    margin-top: var(--s3);
}

.home-hero .hero-secondary-link {
    margin: var(--s3) 0 0;
    font-size: var(--t-small);
    color: var(--ink-3);
    text-align: left;
}
.home-hero .hero-secondary-link a {
    color: var(--accent);
    font-weight: 500;
    text-decoration: underline;
    text-underline-offset: 0.18em;
    text-decoration-color: var(--rule-strong);
}
.home-hero .hero-secondary-link a:hover {
    text-decoration-color: currentColor;
}

/* Scroll cue: a hairline that drifts down its own track. Decorative only. */
.hero-scroll-cue {
    position: absolute;
    left: 50%;
    bottom: var(--s5);
    transform: translateX(-50%);
    width: 1px;
    height: var(--s6);
    overflow: hidden;
    background: var(--rule);
}
.hero-scroll-line {
    display: block;
    width: 1px;
    height: 40%;
    background: var(--ink-3);
    animation: hero-cue 2.4s cubic-bezier(.4, 0, .2, 1) infinite;
}
@keyframes hero-cue {
    0%   { transform: translateY(-100%); }
    60%  { transform: translateY(250%); }
    100% { transform: translateY(250%); }
}

/* Phone: fit the whole hero — headline through CTA — without scrolling.

   Measured before trimming (390px wide): the stack overshot a 620px viewport
   by 94px. The two big blocks were the lead (128px of text plus a 36px margin)
   and the hero's own 48/72 padding; the rest is a few px each.

   What is NOT reduced: the 44px input and 48px CTA minimums under
   `pointer: coarse` below. Those are the touch-target floor and the whole
   point of the hero — shrinking them to win vertical space would trade the
   thing that works for the thing that fits. */
@media (max-width: 767.98px) {
    .home-hero {
        padding: var(--s5) 0 var(--s6);
    }
    .home-hero .eyebrow {
        margin-bottom: var(--s1);
    }
    .home-hero .hero-lead {
        font-size: 1.0625rem;
        margin-bottom: var(--s4);
    }
    .hero-field {
        margin-bottom: var(--s2);
    }
    .home-hero .form-label {
        margin-bottom: 0.3rem;
    }
    .hero-cta {
        margin-top: var(--s2);
    }
    .home-hero .hero-secondary-link {
        margin-top: var(--s2);
    }
    .hero-scroll-cue {
        display: none;
    }
}

/* Short viewports — an SE, or any phone once the browser chrome is showing.
   Keyed to height, because this is a vertical-space problem: a tall phone at
   the same width has room to spare and should keep the fuller typography. */
@media (max-width: 767.98px) and (max-height: 740px) {
    .home-hero {
        padding: var(--s4) 0 var(--s5);
        justify-content: flex-start;
    }
    .home-hero h1 {
        font-size: 1.875rem;
        margin-bottom: var(--s2);
    }
    .home-hero .hero-lead {
        font-size: 1rem;
        line-height: 1.45;
        margin-bottom: var(--s3);
    }
    .home-hero .eyebrow {
        font-size: 0.625rem;
        margin-bottom: var(--s1);
    }
    /* The one line the hero can afford to lose here: the video band is a few
       hundred pixels below and announces itself. The inputs cannot move. */
    .home-hero .hero-watch {
        display: none;
    }
}

/* Keyed to the input method, not the viewport: a touchscreen laptop needs the
   larger target as much as a phone does. Bootstrap's .form-control resolves to
   38px, under the 44px touch minimum, and these two are the first thing anyone
   taps on this site. */
@media (pointer: coarse) {
    .home-hero .input-group .form-control,
    .home-hero .input-group .input-group-text {
        min-height: 44px;
    }
    .hero-cta {
        min-height: 48px;
    }
}

/* --------------------------------------------------------------------------
   1b. Homepage video band (includes/video_band.php)

   A slim band directly under the hero: small thumbnail left, one line of copy
   right. Deliberately not a .home-section — that padding is tuned for the full
   sections further down, and this one has to stay short enough that it reads
   as a footnote to the hero rather than competing with it.

   The thumbnail is a <button>, so it carries focus and keyboard activation for
   free. The play badge sits over it at all times, because touch devices never
   hover and it is the only thing marking the image as a video. Hover lifts the
   whole thumbnail, matching .listing-card:hover on listings.php.
   -------------------------------------------------------------------------- */

.video-band {
    border-top: 1px solid var(--rule);
    padding: var(--s6) 0;
}

.video-band-inner {
    display: grid;
    gap: var(--s4);
    align-items: center;
}
/* The thumbnail column grows with the viewport rather than sitting at one fixed
   width: at 20rem it read as an afterthought on a desktop while filling a phone
   screen. Full width stacked, then a widening column as there is room for one. */
@media (min-width: 768px) {
    .video-band-inner {
        grid-template-columns: minmax(0, 26rem) minmax(0, 1fr);
        gap: var(--s5);
    }
    /* Once playing, the first column grows again to hold a readable player. */
    .video-band-inner.is-playing {
        grid-template-columns: minmax(0, 44rem) minmax(0, 1fr);
        align-items: start;
    }
}
@media (min-width: 1200px) {
    .video-band-inner {
        grid-template-columns: minmax(0, 34rem) minmax(0, 1fr);
    }
    .video-band-inner.is-playing {
        grid-template-columns: minmax(0, 52rem) minmax(0, 1fr);
    }
}

.video-facade {
    position: relative;
    display: block;
    width: 100%;
    padding: 0;
    border: 1px solid var(--rule);
    border-radius: var(--r-md);
    overflow: hidden;
    background: var(--paper-raised);
    box-shadow: var(--lift-sm);
    cursor: pointer;
    /* On the base rule rather than inside :hover, so it eases back down on the
       way out as well as up on the way in. */
    transition: transform .2s ease, box-shadow .2s ease;
}
.video-facade img {
    display: block;
    width: 100%;
    height: auto;
}
/* The same 5px rise as .listing-card:hover. */
.video-facade:hover,
.video-facade:focus-visible {
    transform: translateY(-5px);
    box-shadow: var(--lift);
}

/* The badge, with no wash behind it: the thumbnail was made to be looked at,
   and a grey veil over it is a tax paid by everyone who never clicks. */
.video-play {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}
.video-play svg {
    width: 3.25rem;
    height: 3.25rem;
    padding: .7rem .6rem .7rem .85rem;
    border-radius: 50%;
    background: rgba(253, 252, 250, .92);
    color: var(--accent);
}

/* The player that replaces the thumbnail. */
.video-frame {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    border: 1px solid var(--rule);
    border-radius: var(--r-md);
    overflow: hidden;
    background: #000;
}
.video-frame iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}

.video-band-title {
    font-size: var(--t-h3);
    margin: 0 0 var(--s2);
}
.video-band-blurb {
    color: var(--ink-2);
    margin: 0 0 var(--s2);
    max-width: 46ch;
}
.video-band-meta {
    font-size: var(--t-small);
    color: var(--ink-3);
    margin: 0;
}

@media (prefers-reduced-motion: reduce) {
    .video-facade {
        transition: none;
    }
    .video-facade:hover,
    .video-facade:focus-visible {
        transform: none;
    }
}

/* --------------------------------------------------------------------------
   2. Page sections

   One continuous canvas. Sections are separated by hairlines and whitespace,
   never by alternating background bands.
   -------------------------------------------------------------------------- */

/* Sections carry their own texture (see design-system.css 4c). The sequence
   down the page is deliberate rather than decorative — the ground loosens as
   the content gets less interactive:

     hero + wizard   dot lattice + grain    (document default, tex-both)
     deal advisory   line grid + grain      engineered; it is the structured offer
     marketplace     wide dot lattice       structure recedes so the two choices lead

   The ebook CTA and footer fall back to the document texture, which closes
   the sequence rather than leaving the page ending on bare paper. */
.home-section {
    padding: var(--s9) 0;
    border-top: 1px solid var(--rule);
}

.section-head {
    max-width: 34rem;
    margin: 0 0 var(--s7);
}
.section-head .lead-quiet {
    margin-bottom: 0;
}
.section-head h2 {
    margin: 0 0 var(--s3);
}

/* Steps — hairline-separated columns, not cards. */
.step-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0;
}
.step {
    padding: var(--s5) var(--s5) 0 0;
    border-top: 1px solid var(--ink);
    margin-right: var(--s5);
}
.step:last-child {
    margin-right: 0;
}
.step-n {
    display: block;
    font-family: var(--font-mono);
    font-size: var(--t-caption);
    letter-spacing: 0.08em;
    color: var(--ink-3);
    margin-bottom: var(--s3);
}
.step h3 {
    font-size: var(--t-h3);
    margin: 0 0 var(--s2);
}
.step p {
    color: var(--ink-2);
    margin: 0;
}

@media (max-width: 767.98px) {
    .step-grid {
        grid-template-columns: 1fr;
    }
    .step {
        margin-right: 0;
        padding-right: 0;
        padding-bottom: var(--s5);
    }
}

/* Two-sided comparison — one deal, two readings of it. */
/* A tonal block with a hairline border, so the figures read as one module
   rather than as text sitting loose on the page. */
.sides {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0;
    background-color: var(--paper-tint);
    background-image: var(--tex-diag), var(--tex-grain);
    background-size: var(--tex-diag-size), var(--tex-grain-size);
    border: 1px solid var(--rule);
    border-top: 1px solid var(--ink);
    border-radius: 0 0 var(--r-md) var(--r-md);
    padding: 0 var(--s5);
}
.side {
    padding: var(--s5) var(--s5) var(--s5) 0;
}
.side + .side {
    border-left: 1px solid var(--rule);
    padding-left: var(--s5);
    padding-right: 0;
}

@media (max-width: 767.98px) {
    .sides {
        grid-template-columns: 1fr;
    }
    .side,
    .side + .side {
        padding: var(--s5) 0;
        border-left: 0;
    }
    .side + .side {
        border-top: 1px solid var(--rule);
    }
}


/* Live worked example. The panel holds real output from the real engine, so
   it gets the one elevation in the system. */
/* The chart's viewBox is 300×132 — proportioned for the calculator's narrow
   sidebar. Left to fill this panel it stretches into mostly empty plot, so
   cap it and centre it rather than scaling it up. */

/* --------------------------------------------------------------------------
   3. Calculator wizard
   -------------------------------------------------------------------------- */

#calculatorSection {
    display: none;
}

/* Fills the screen once opened, like the hero.

   A full 100svh here, not `100svh - --nav-h` as in the hero: the navbar is
   not fixed, so by the time toggleWelcome() has scrolled the wizard to the
   top of the viewport the nav has scrolled away and there is nothing to
   subtract. min-height, never height — the form and the snapshot panel are
   taller than the viewport on a short window and must be allowed to grow. */
#calculatorSection.active {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 100vh;
    min-height: 100svh;
    padding: var(--s7) 0;
    border-top: 1px solid var(--rule);
}
#calculatorSection.active > .row {
    width: 100%;
}

/* Scroll snap — the wizard settles centred in the viewport.

   `proximity`, not `mandatory`: mandatory hijacks every scroll gesture on the
   page and makes it impossible to stop anywhere else, which on a page this
   long is worse than no snap at all. Proximity only engages when the reader
   has already come to rest near the wizard.

   Only the wizard carries a snap point. Declaring the snap TYPE on the
   scroller is what arms it; without a matching `scroll-snap-align` on a child,
   nothing snaps — so the hero, the sections and the footer scroll freely.

   `scroll-snap-stop: normal` lets a fast flick pass straight through rather
   than being caught. */
html {
    scroll-snap-type: y proximity;
}
#calculatorSection.active {
    scroll-snap-align: center;
    scroll-snap-stop: normal;
}

/* The page bottom needs a snap point of its own. With only one snap area on
   the page, Chrome pulls the final resting position toward it and the document
   stops 13px short of its true end — measured: 13px with snap on, 0 with it
   off. Anchoring the footer's end makes the very bottom a valid position, so
   the page scrolls all the way. */
body > .site-footer {
    scroll-snap-align: end;
}

/* A snap area taller than the viewport cannot be centred in it, and the spec
   skips the snap rather than clipping — but on mobile the section is far
   taller and the browser's fallback behaviour varies, so take the snap off
   entirely below lg, where the wizard is also no longer full-height. */
@media (max-width: 991.98px) {
    html {
        scroll-snap-type: none;
    }
    #calculatorSection.active {
        scroll-snap-align: none;
    }
}

/* Someone who has asked for reduced motion has asked not to have the page
   moved for them. */
@media (prefers-reduced-motion: reduce) {
    html {
        scroll-snap-type: none;
    }
}

/* Below lg the form and snapshot stack, so the section is already far taller
   than the viewport and the floor only adds dead space above the fields. */
@media (max-width: 991.98px) {
    #calculatorSection.active {
        display: block;
        min-height: 0;
        padding: var(--s7) 0;
    }
}

.wizard-tabs {
    border-bottom: 1px solid var(--rule);
}
.wizard-tabs .nav-link {
    cursor: pointer;
    font-size: var(--t-small);
    font-weight: 500;
    color: var(--ink-3);
    background: none;
    border: none;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    padding: 0.75rem 1rem;
    margin-bottom: -1px;
}
/* Tabs mark where you are, not what to click — ink, not the action colour. */
.wizard-tabs .nav-link:hover {
    color: var(--state-current);
    border-bottom-color: var(--rule-strong);
}
.wizard-tabs .nav-link.active {
    font-weight: 600;
    color: var(--state-current);
    border-bottom-color: var(--state-current);
    background: none;
}

.wizard-tab-pane {
    display: none;
    /* Bottom padding tightened from --s5: equalizePaneHeights() (index.php)
       floors every pane at the tallest, so any pane shorter than that floor
       collects its slack here, at the bottom, above the nav buttons. Trimming
       this shrinks that gap on every tab, since the floor itself is derived
       from these same paddings. Top padding stays at --s5 — that's breathing
       room below the tab strip, not slack. */
    padding: var(--s5) 0 var(--s3);
}
.wizard-tab-pane.active {
    display: block;
}

/* Country choice (Property Details -> Address). The same metaphor as the
   snapshot's Lease / Renewal control in snapshot-charts.css: a sunken track with
   the selection as a raised paper pill in ink, no colour, because choosing a
   country is state, not action. Its own class rather than .snap-toggle, which
   the wizard script binds to the snapshot period on every element that has it.
   The radios stay real inputs (.btn-check), so keyboard and screen readers get
   a native radio group. */
.country-choice {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 3px;
    padding: 3px;
    background: var(--state-track);
    border: 1px solid var(--rule);
    border-radius: var(--r-md);
}
.country-choice-option {
    display: inline-flex;
    align-items: center;
    margin: 0;
    padding: 0.4rem 0.9rem;
    border-radius: calc(var(--r-md) - 2px);
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--ink-3);
    cursor: pointer;
    user-select: none;
    transition: color .15s ease, background-color .15s ease, box-shadow .15s ease;
}
.country-choice-option:hover {
    color: var(--ink);
}
.btn-check:checked + .country-choice-option {
    background: var(--state-raised);
    color: var(--state-current);
    font-weight: 600;
    box-shadow: var(--lift-sm);
}
.btn-check:focus-visible + .country-choice-option {
    box-shadow: var(--focus-ring);
}
@media (prefers-reduced-motion: reduce) {
    .country-choice-option { transition: none; }
}

/* Persistent escape-hatch below the wizard nav buttons (Back/Next/Calculate).
   Carries current wizard values across to /calculator.php via querystring. */
.wizard-secondary-link {
    margin: var(--s3) 0 0;
    text-align: center;
    font-size: var(--t-small);
}
.wizard-secondary-link a {
    color: var(--ink-3);
    text-decoration: none;
    font-weight: 500;
}
.wizard-secondary-link a:hover {
    color: var(--accent);
    text-decoration: underline;
    text-underline-offset: 0.18em;
}

.form-subsection {
    margin-bottom: var(--s3);
}
/* The markup gives #navBar Bootstrap's .mt-3; tightened here rather than
   edited in index.php, since that same class sets the gap-2 between the
   Back/Next/Calculate buttons themselves, which shouldn't change. Bootstrap's
   spacing utilities carry !important on the loaded CDN build (confirmed — the
   unused local css/bootstrap.css copy does not), so an ID selector alone
   doesn't win here without it. */
#navBar {
    margin-top: var(--s2) !important;
}
.form-subsection h6 {
    font-size: var(--t-caption);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-3);
    border-bottom: 1px solid var(--rule);
    padding-bottom: 0.5rem;
    margin-bottom: var(--s3);
}

/* Nav buttons — consistent height */
#navBar .btn {
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding-top: 0;
    padding-bottom: 0;
}
.nav-arrow {
    width: 42px;
}

/* --------------------------------------------------------------------------
   4. Snapshot panel
   -------------------------------------------------------------------------- */

.snapshot-placeholder {
    text-align: center;
    padding: var(--s6) var(--s3);
    color: var(--ink-3);
}
.snapshot-result {
    display: none;
}
.snapshot-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--s2);
    margin-bottom: 0.35rem;
}
.snapshot-row .label {
    color: var(--ink-3);
    font-size: var(--t-small);
}
.snapshot-row .value {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-weight: 400;
    color: var(--ink);
    white-space: nowrap;
}

/* The panel is a stack of short rows; Bootstrap's 1rem rule margins are sized
   for body copy and read as gaps here. */
#snapshotResult hr {
    margin: 0.6rem 0;
    border-top: 1px solid var(--rule);
    opacity: 1;
}

.donut-legend .sq {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 2px;
    margin-right: 0.4rem;
    vertical-align: -1px;
}
.donut-legend .sq.cf { background: var(--series-2); }
.donut-legend .sq.bo { background: var(--series-1); }

@media (max-width: 991.98px) {
    .snapshot-col {
        order: 2;
        margin-top: var(--s4);
    }
    .form-col {
        order: 1;
    }
}

/* Three flex-grow buttons sharing a phone-width row squeezed "Save & Create
   Account" to 177px, where it wrapped to two lines and spilled outside the
   button. Measured: the row is clean at 576px and above, so it stacks only
   below that. Stacking also gives the two primaries a reading order instead of
   sitting them side by side at equal weight. */
@media (max-width: 575.98px) {
    #navBar {
        flex-wrap: wrap;
    }
    #navBar .flex-grow-1 {
        flex: 1 0 100%;
    }
    #navBar .nav-arrow {
        flex: 0 0 auto;
    }
}

/* --------------------------------------------------------------------------
   5. SEO prose
   -------------------------------------------------------------------------- */

#about-calculator {
    border-top: 1px solid var(--rule);
    padding: var(--s9) 0;
}
#about-calculator h2 {
    font-size: var(--t-h3);
    margin: var(--s6) 0 var(--s3);
}
#about-calculator h2:first-of-type {
    margin-top: 0;
}
#about-calculator p {
    color: var(--ink-2);
    max-width: 62ch;
}

/* --------------------------------------------------------------------------
   7. Tonal sections

   A half-step down in tone, so a section reads as a distinct module rather
   than as more of the same continuous ground. Used sparingly — the canvas is
   still continuous, this is a shift in shade, not an inverted band.
   -------------------------------------------------------------------------- */


/* The panel is white and lifted; on the tinted, hatched ground it now has
   something to lift off. Its own edge is the shadow's hairline. */

/* Two-sides figures sit in a tonal block so the numbers read as a unit rather
   than as text on the page. */

@media (max-width: 767.98px) {
    .sides {
        padding: 0 var(--s4);
    }
}

/* --------------------------------------------------------------------------
   8. Deal Advisory

   The report fan beside this section moved to design-system.css (§10c) once
   deal-advisory.php began showing it too. Only the note under the CTA, which
   the event block also borrows, stays here.
   -------------------------------------------------------------------------- */

.advisory-note {
    margin: var(--s3) 0 0;
    font-size: var(--t-small);
    color: var(--ink-3);
    max-width: 34ch;
}

/* --------------------------------------------------------------------------
   9. Marketplace paths

   Reuses .sides / .side from the removed "one deal, two sides" block — the
   two-column grid with a centre hairline was worth keeping rather than
   deleting and rewriting.
   -------------------------------------------------------------------------- */

#marketplace-paths .side h3 {
    font-size: var(--t-h3);
    margin: 0 0 var(--s2);
}
#marketplace-paths .side p {
    color: var(--ink-2);
    margin: 0 0 var(--s4);
    max-width: 44ch;
}

/* --------------------------------------------------------------------------
   10. Homepage event (includes/event_banner.php)

   The portrait is an ink hedcut, so it gets no frame at all — no card, no
   shadow, no radius. Framing an engraving in a white box is the one thing
   that would make it look pasted on.

   The source PNG has an opaque pure-white background and no alpha channel,
   so it cannot simply be made transparent. multiply blends each pixel with
   the page behind it: white becomes the ground and disappears, while the ink
   is unaffected. Exactly the technique the ebook cover uses, and the reason
   the black-and-white file is used here rather than the cream one — the cream
   version carries its own #FBF1D8 ground, which multiply would darken into a
   visible yellow square.
   -------------------------------------------------------------------------- */

/* Appearance lives in css/design-system.css as .portrait / .portrait-byline,
   because the About page uses it too. Only the size is set here. */
#meet-greet .portrait {
    width: 210px;
}

/* The section head's max-width is tuned for a narrow column. Here the text is
   the whole point of the block, so it gets a full editorial measure. */
#meet-greet .section-head {
    max-width: 52rem;
}

.event-audience {
    font-size: var(--t-small);
    color: var(--ink-3);
    max-width: 60ch;
    margin: var(--s3) 0 0;
}

/* Tabular figures so the time reads as data rather than prose. */
.event-when {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: var(--t-body);
    color: var(--ink);
    margin: var(--s5) 0 0;
}

/* The shared .advisory-note measure is 34ch, tuned for the narrow Deal Advisory
   column. Here it forced one short sentence onto two lines. */
#meet-greet .advisory-note {
    max-width: none;
}

/* The registration form took the place of the old Join button, so it keeps
   that button's place in the rhythm. Capped well short of the text measure: a
   full-width email field on a wide screen reads as a search bar rather than a
   one-line sign-up. Inputs and buttons come from design-system.css. */
#meet-greet .event-form {
    margin: var(--s4) 0 0;
    max-width: 30rem;
}

/* Confirmation and failure after the redirect. Both take the form's slot, so
   the block does not jump as it swaps between them. */
.event-msg {
    margin: var(--s4) 0 0;
    max-width: 46ch;
    color: var(--ink);
    border-left: 2px solid var(--accent);
    padding-left: var(--s3);
}
.event-msg-error {
    border-left-color: var(--status-neg);
}

@media (max-width: 767.98px) {
    /* Stacked on a phone the portrait leads the block, so it shrinks and sits
       left with the text rather than centred above it — a byline, not a hero
       image. */
    #meet-greet .portrait {
        width: 132px;
    }
}
