/* ============================================================================
   PORTABILITY FLOOR — every custom property this file consumes, defined here.
   This file is ported into stacks on its own, and stacks vendor dist/tailwind/theme-tokens.css
   plus templates/2040/tokens.css through their OWN Tailwind build — not this stylesheet. Anything
   defined only in those sources therefore resolves to NOTHING once this file is ported alone,
   which is how --header-height shipped collapsed to 40px in v1.3.9.
   The selector is :where(:root) / :where(.dark) on purpose: ZERO specificity, so a real token
   sheet, a tenant theme, or any per-page override always wins when one is present.
   SOURCE OF TRUTH: templates/2040/tokens.css (the design identity) over tokens/tokens.json (the
   shared semantic layer), shipped to stacks as dist/tailwind/theme-tokens.css. The block below is
   a FALLBACK COPY of those values, not their definition. Change one and you must change the other;
   if the two disagree the floor loses, which is the safe direction.
   The var() chains are reproduced VERBATIM from the compiled build this file replaces — including
   --color-primary-soft's #1d4ed8 tail, which is the shared neutral base default showing through
   rather than 2040's own #4674a4. That is the value 2040 renders today; correcting it would be a
   design change hidden inside a mechanical conversion, so it is flagged in
   designs/2040/section-library.md and left alone here.
   ============================================================================ */
:where(:root) {
  --color-primary: var(--brand-primary, #4674a4);
  --color-primary-soft: var(--sem-primary-soft, var(--brand-primary, #1d4ed8));
  --color-secondary: var(--brand-primary-strong, #273656);
  --color-surface: var(--sem-surface, #fff);
  --color-surface-raised: var(--sem-surface-raised, #fff);
  --color-surface-muted: var(--sem-surface-muted, #f5f5f5);
  --color-surface-warm: var(--sem-surface-warm, #fcf7f4);
  --color-heading: var(--sem-heading, #171717);
  --color-ink: var(--sem-ink, #404040);
  --color-edge-strong: var(--sem-edge-strong, #d4d4d4);
  --color-edge-raised: var(--sem-edge-raised, transparent);
  /* the plate the cta-over-image render sits on, so a slow image never flashes white */
  --color-neutral-900: oklch(20.5% 0 none);
  --radius-lg: 0.5rem;
  --radius-xl: 0.75rem;
  --radius-2xl: 1rem;
  --radius-3xl: 1.5rem;
  --radius-hero: 96px;
  --radius-hero-lg: 128px;
  --radius-pill: 999px;
  --shadow-md: 0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a;
  --duration-fast: 150ms;
  --ease-standard: cubic-bezier(.4, 0, .2, 1);
  /* the diagonal wash under the cta-over-image card. Was an inline style="background:…" on the
     fragment; a gradient is a design value, so it lives with the other tokens, not in the markup. */
  --scrim-ctai: linear-gradient(to top right, rgba(23,23,23,.9), rgba(23,23,23,.55) 45%, rgba(23,23,23,.25));
}
/* ---------------------------------------------------------------------------
   DARK — the second half of the portability floor, and a PHASE-1 DELIVERABLE per
   the Owner ruling of 2026-08-02.
   This file is ported ALONE. A dark treatment that lives only in a stack's
   site.css therefore does not travel with it, which is the same failure mode the
   light floor above exists to prevent: before this block, a ported fragment in a
   dark host fell back to #fff surfaces and #171717 headings and rendered a light
   island. Every semantic token the blocks consume now carries its dark flip here.
   Still :where() / ZERO specificity, so a real token sheet, a tenant theme or a
   per-page override always wins. BOTH triggers are listed because the stacks
   differ (.dark on pc/la, [data-theme] on go) — same reasoning as tokens.css.
   MODE-INVARIANT ON PURPOSE (STY-6) — absent below by decision, not omission:
     --color-primary / --color-primary-strong / --color-accent — the brand hues.
       The brand-surface blocks (.ctab-card, .atl-avatar, .atl-year-pill,
       .pstep-num, .sec-btn-brand) sit ON brand colour with #fff on top in BOTH
       themes, which is the same call the reference chrome makes for its header
       and footer.
     --color-neutral-900 / --scrim-ctai — the plate and the diagonal wash under
       cta-over-image. They back a photographic render that is dark in both
       themes; flipping them would put white behind a dark scrim.
     .sec-btn-light / .sec-btn-ghost — the two CTAs that sit on that scrim. See
       .sec-btn-light's own note in the button family below.
   --------------------------------------------------------------------------- */
:where(.dark), :where([data-theme="dark"]) {
  /* 2040's identity flip: content headings set in --color-secondary go navy -> white */
  --color-secondary: var(--sem-heading, #fff);
  --color-surface: var(--sem-surface, #0a0a0a);
  --color-surface-raised: var(--sem-surface-raised, #171717);
  --color-surface-muted: var(--sem-surface-muted, #262626);
  --color-surface-warm: var(--sem-surface-warm, #1c1917);
  --color-heading: var(--sem-heading, #fff);
  --color-ink: var(--sem-ink, #d4d4d4);
  --color-edge-strong: var(--sem-edge-strong, #404040);
  /* transparent in light, a visible hairline in dark — the whole reason this token exists.
     It is what keeps .ctai-card's edge readable once the card and the page are both dark. */
  --color-edge-raised: var(--sem-edge-raised, rgba(255, 255, 255, 0.14));
  /* --color-primary-soft is brand TEXT (.aprof-link, .vprop-icon), per the role dictionary in
     docs/design-generation-contract.md @c926985. #9cbcda is a tint of 2040's own --color-primary.
     The reference's site.css agrees on this role as of c926985 — it had briefly read the same name
     as a surface tint, which is now --color-primary-wash-strong there. No dark rendering of these
     blocks had ever shipped, so no incumbent value changed; the light #1d4ed8 quirk flagged in
     designs/2040/section-library.md is untouched above. */
  --color-primary-soft: var(--sem-primary-soft-dark, #9cbcda);
  /* a light-theme drop shadow is invisible on a dark surface, and .atl-card / .mgal-card are what
     separate a masonry column from the warm band behind it */
  --shadow-md: 0 4px 6px -1px #00000080, 0 2px 4px -2px #00000099;
}
:where([data-design="2040"]) {
/* ============================================================================
   2040 "Airbnb-lift" — section-library block styles.
   PLAIN CSS, per the Owner ruling of 2026-08-02: a fragment renders from THIS FILE ALONE and every
   class it writes is defined here. No Tailwind utilities — a utility in a fragment only resolves
   because some unrelated scanned file happened to use the same one, and when that coincidence
   breaks the block renders unstyled with no error.
   This file REPLACES the compiled-Tailwind sections.css it is named after. That build carried
   Tailwind's preflight scoped under .page-builder, so the blocks silently depended on it for
   border-box sizing, zeroed margins, `img { display: block }` and `a { text-decoration: inherit }`.
   A ported plain-CSS file cannot assume any of that, so the reset below is explicit and every rule
   states its own margin, line-height and weight rather than inheriting one.
   Classes are namespaced PER BLOCK. A second generic vocabulary living in this file would be
   Tailwind again with worse tooling; the shared names below (.sec-inner, .sec-band, .sec-btn,
   .sec-icon) are components — they name a container, a band, a button and an inline icon, not a
   property.
   ============================================================================ */
/* Root of every fragment. Carries the box model the blocks were authored against and nothing else. */
.sec, .sec *, .sec *::before, .sec *::after { box-sizing: border-box; }
/* the centred content column — max-w-7xl with the gutter that widens once at sm */
.sec-inner { margin-inline: auto; max-width: 80rem; padding-inline: 1rem; }
@media (min-width: 640px) { .sec-inner { padding-inline: 1.5rem; } }
/* the standard vertical band five blocks share */
.sec-band { padding-block: 2.5rem; }
@media (min-width: 1024px) { .sec-band { padding-block: 5rem; } }
/* Behaviour hooks, NOT styling. `.main-button` and `.cta-button` are what the template-level script
   binds the enquiry modal to (route 2 of the no-executable-behaviour ruling: the fragment stays
   inert markup, the template wires it). They are defined here so the guard resolves them and so the
   one CTA that is an <a> with no href still reads as clickable — which is what the markup said
   before the conversion. */
.main-button, .cta-button { cursor: pointer; }
/* --- the pill button. Five blocks draw it; five copies would be the coincidence problem again. --- */
.sec-btn { display: inline-flex; align-items: center; gap: 0.5rem; border-radius: var(--radius-pill, 999px); padding: 0.75rem 1.75rem; font-weight: 600; text-decoration: none; transition: background-color var(--duration-fast, 150ms) var(--ease-standard, cubic-bezier(.4,0,.2,1)), color var(--duration-fast, 150ms) var(--ease-standard, cubic-bezier(.4,0,.2,1)), opacity var(--duration-fast, 150ms) var(--ease-standard, cubic-bezier(.4,0,.2,1)); }
.sec-btn-brand { background: var(--color-primary); color: #fff; }
.sec-btn-brand:hover { opacity: 0.9; color: #fff; }
/* STY-5: the LABEL is brand text -> --color-primary-soft. The 1px rule is a stroke, not text, and
   stays on the fill token: #4674a4 on #0a0a0a is 3.4:1, which clears the 3:1 non-text threshold. */
.sec-btn-outline { border: 1px solid var(--color-primary); color: var(--color-primary-soft); }
.sec-btn-outline:hover { background: var(--color-primary); color: #fff; }
/* MODE-INVARIANT (STY-6): this button and .sec-btn-ghost below sit on the cta-over-image scrim,
   which is dark in BOTH themes. The "light" button therefore stays literally light instead of
   following --color-surface-raised, which in dark would turn it near-black on a dark render and
   lose the control entirely. #fff is the value --color-surface-raised already resolves to in
   light, so light rendering is byte-identical. */
/* STY-5 EXCEPTION, and the 4827da0 rule is exactly why: the label stays on --color-primary. The
   button is mode-INVARIANT white, so pairing it with --color-primary-soft — which VARIES to #9cbcda
   in dark — would put a pale blue on white at 1.9:1. An invariant surface takes an invariant ink. */
.sec-btn-light { background: #fff; padding: 0.75rem 1.5rem; font-size: 0.875rem; line-height: 1.25rem; font-weight: 700; color: var(--color-primary); }
.sec-btn-light:hover { background: rgb(255 255 255 / 0.9); color: var(--color-primary); }
.sec-btn-ghost { border: 1px solid rgb(255 255 255 / 0.5); padding: 0.75rem 1.5rem; font-size: 0.875rem; line-height: 1.25rem; color: #fff; }
.sec-btn-ghost:hover { background: rgb(255 255 255 / 0.1); color: #fff; }
/* full-width stacked CTA — the wider padding rides with it, as it did in the markup */
.sec-btn-block { width: 100%; justify-content: center; padding: 0.875rem 2rem; }
/* inline icon inside a button or a card head */
.sec-icon { display: block; width: 1.25rem; height: 1.25rem; flex: none; }
@media (prefers-reduced-motion: reduce) { .sec-btn { transition: none; } }
/* ============================================================================
   agent-profile — portrait right, copy and the two enquiry CTAs left.
   ============================================================================ */
.aprof { display: grid; align-items: center; gap: 2.5rem; }
@media (min-width: 1024px) { .aprof { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 4rem; } }
@media (min-width: 1024px) { .aprof-copy { grid-column: span 2; } .aprof-media { grid-column: span 3; } }
.aprof-title { margin: 0 0 1.5rem; font-size: 1.5rem; line-height: 1.25; font-weight: 700; color: var(--color-secondary); }
@media (min-width: 768px) { .aprof-title { font-size: 1.875rem; } }
.aprof-body { margin: 0; line-height: 1.625; color: var(--color-ink); }
.aprof-strong { font-weight: 600; color: var(--color-heading); }
.aprof-link { font-weight: 600; color: var(--color-primary-soft); text-decoration: none; }
.aprof-link:hover { text-decoration: underline; color: var(--color-primary-soft); }
/* 1.5rem of stack spacing plus the 0.5rem the actions carried on their own */
.aprof-actions { margin-top: 2rem; display: flex; flex-direction: column; gap: 0.75rem; }
.aprof-media { overflow: hidden; border-radius: var(--radius-3xl, 1.5rem); }
/* object-position: top — a portrait crop that keeps the face when the ratio bites */
.aprof-img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; object-position: top; }
/* ============================================================================
   agent-timeline — a dated track record, each year carrying its own masonry set.
   ============================================================================ */
.atl-sec { background: var(--color-surface-warm); padding-block: 4rem; }
@media (min-width: 1024px) { .atl-sec { padding-block: 6rem; } }
.atl-head { margin-bottom: 2.5rem; display: flex; align-items: center; gap: 1rem; }
.atl-avatar { display: flex; width: 3.5rem; height: 3.5rem; align-items: center; justify-content: center; border-radius: var(--radius-pill, 999px); background: var(--color-primary); font-size: 1.125rem; line-height: 1.75rem; font-weight: 600; color: #fff; }
.atl-name { margin: 0; font-size: 1.5rem; line-height: 2rem; font-weight: 700; color: var(--color-heading); }
@media (min-width: 768px) { .atl-name { font-size: 1.875rem; line-height: 2.25rem; } }
.atl-role { margin: 0; line-height: 1.5; color: var(--color-ink); }
/* The rule is the timeline. The 0.5rem indent plus the 2rem inset is what puts the dots ON it. */
.atl-track { margin-left: 0.5rem; border-left: 2px solid var(--color-edge-strong); padding-left: 2rem; }
.atl-entry { position: relative; padding-bottom: 2.5rem; }
.atl-entry:last-child { padding-bottom: 0; }
/* -41px = the 2rem inset + the 2px rule + half the 1rem dot, so it sits centred on the line. The
   ring is drawn as a spread shadow in the band's own fill, which is what erases the rule behind it. */
.atl-dot { position: absolute; left: -41px; top: 0.25rem; width: 1rem; height: 1rem; border-radius: var(--radius-pill, 999px); background: var(--color-primary); box-shadow: 0 0 0 4px var(--color-surface-warm); }
.atl-year { margin-bottom: 1.25rem; }
.atl-year-pill { display: inline-block; border-radius: var(--radius-pill, 999px); background: var(--color-primary); padding: 0.25rem 1rem; font-size: 0.875rem; line-height: 1.25rem; font-weight: 600; color: #fff; }
.atl-cols { columns: 1; column-gap: 1.5rem; }
@media (min-width: 640px) { .atl-cols { columns: 2; } }
@media (min-width: 1024px) { .atl-cols { columns: 3; } }
.atl-card { margin-bottom: 1.5rem; break-inside: avoid; overflow: hidden; border-radius: var(--radius-2xl, 1rem); background: var(--color-surface-raised); box-shadow: var(--shadow-md); }
/* height:auto against the intrinsic ratio — the masonry column length IS the picture's own shape */
.atl-img { display: block; height: auto; width: 100%; }
/* ============================================================================
   content-split — a warm panel of two alternating image / copy rows.
   ============================================================================ */
.csplit-head { margin: 0 auto; max-width: 48rem; text-align: center; }
.csplit-heading { margin: 0 0 0.75rem; font-size: 1.875rem; line-height: 2.25rem; font-weight: 700; color: var(--color-heading); }
@media (min-width: 768px) { .csplit-heading { font-size: 2.25rem; line-height: 2.5rem; } }
.csplit-sub { margin: 0; line-height: 1.5; color: var(--color-ink); }
/* font-weight is set on the PANEL and inherited: the body copy inside is light, the titles set
   their own medium. Moving it onto each paragraph would change which elements a stack can restyle. */
.csplit-panel { margin-top: 1.5rem; overflow: hidden; border-radius: var(--radius-3xl, 1.5rem); background: var(--color-surface-warm); font-weight: 300; }
@media (min-width: 768px) { .csplit-panel { border-radius: var(--radius-hero, 96px); } }
@media (min-width: 768px) { .csplit-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* Below md the second row REVERSES so the picture leads on a phone in both rows; at md the grid
   takes over and source order puts the copy first. */
.csplit-row--flip { display: flex; flex-direction: column-reverse; }
@media (min-width: 768px) { .csplit-row--flip { display: grid; } }
.csplit-media { overflow: hidden; }
@media (max-width: 767.98px) { .csplit-media { aspect-ratio: 4 / 3; } }
.csplit-img { display: block; height: 100%; width: 100%; object-fit: cover; }
.csplit-copy { align-self: center; padding: 2.75rem 2rem; text-align: center; }
@media (min-width: 768px) { .csplit-copy { padding-block: 5rem; } }
.csplit-title { margin: 0 0 0.75rem; font-size: 1.5rem; line-height: 2rem; font-weight: 500; color: var(--color-heading); }
.csplit-text { margin: 0; line-height: 1.5; color: var(--color-ink); }
.csplit-lead { margin: 0 0 0.75rem; font-size: 1.125rem; line-height: 1.75rem; font-weight: 500; color: var(--color-ink); }
/* 0.75rem, not the 0.5rem the markup asked for: the stack spacing below the paragraph won the
   collapse. Reproduced as measured. */
.csplit-cta { margin-top: 0.75rem; }
/* ============================================================================
   cta-banner — a brand card with the two contact routes.
   ============================================================================ */
.ctab-card { border-radius: var(--radius-2xl, 1rem); background: var(--color-primary); padding: 3rem 2rem; text-align: center; color: #fff; }
@media (min-width: 768px) { .ctab-card { padding: 4rem; } }
.ctab-copy { margin: 0 auto; max-width: 36rem; }
.ctab-title { margin: 0 0 1.5rem; font-size: 1.5rem; line-height: 2rem; font-weight: 700; color: #fff; }
@media (min-width: 768px) { .ctab-title { font-size: 1.875rem; line-height: 2.25rem; } }
.ctab-body { margin: 0 0 1.5rem; line-height: 1.5; color: rgb(255 255 255 / 0.8); }
.ctab-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 1rem; }
/* ============================================================================
   cta-over-image — a lifted card on a darkened render, with the 2040 diagonal corner.
   ============================================================================ */
.ctai { position: relative; isolation: isolate; overflow: hidden; background: var(--color-surface); }
.ctai-bg { position: absolute; inset: 0; z-index: -10; background: var(--color-neutral-900); }
.ctai-img { display: block; width: 100%; height: 100%; object-fit: cover; }
.ctai-scrim { position: absolute; inset: 0; background: var(--scrim-ctai); }
.ctai-inner { position: relative; padding-block: 4rem; }
@media (min-width: 768px) { .ctai-inner { padding-block: 8rem; } }
/* The oversized bottom-right corner is 2040's signature, and it is a PAIR: 0.5rem on three corners
   against 64px on one. Scaling to 96px at md keeps the diagonal reading as a device rather than a
   rounding error once the card is wide. */
.ctai-card { max-width: 36rem; border: 1px solid var(--color-edge-raised); border-radius: var(--radius-lg, 0.5rem); border-bottom-right-radius: 64px; background: var(--color-surface-raised); padding: 2rem; }
@media (min-width: 768px) { .ctai-card { border-bottom-right-radius: var(--radius-hero, 96px); padding: 3.5rem 2.75rem; } }
.ctai-title { margin: 0 0 1.25rem; font-size: 1.5rem; line-height: 2rem; font-weight: 500; color: var(--color-heading); }
@media (min-width: 768px) { .ctai-title { font-size: 1.875rem; line-height: 2.25rem; } }
.ctai-body { margin: 0; line-height: 1.5; color: var(--color-ink); }
/* the one square-cornered CTA in the library — it belongs to the card, not to the pill family */
.ctai-btn { margin-top: 2rem; display: inline-flex; align-items: center; border-radius: var(--radius-lg, 0.5rem); background: var(--color-primary); padding: 0.75rem 1.75rem; font-weight: 600; color: #fff; text-decoration: none; transition: opacity var(--duration-fast, 150ms) var(--ease-standard, cubic-bezier(.4,0,.2,1)); }
.ctai-btn:hover { opacity: 0.9; color: #fff; }
@media (prefers-reduced-motion: reduce) { .ctai-btn { transition: none; } }
/* ============================================================================
   lifestyle-collage — one lead frame and two stacked, with the diagonal corner pair.
   ============================================================================ */
.lcol-sec { padding-bottom: 1.5rem; }
@media (min-width: 768px) { .lcol-sec { padding-bottom: 3rem; } }
@media (min-width: 1024px) { .lcol-sec { padding-bottom: 5rem; } }
@media (min-width: 1024px) { .lcol-head { max-width: 48rem; } }
.lcol-title { margin: 0 0 0.75rem; font-size: 1.875rem; line-height: 2.25rem; font-weight: 700; color: var(--color-heading); }
@media (min-width: 768px) { .lcol-title { font-size: 2.25rem; line-height: 2.5rem; } }
@media (min-width: 1024px) { .lcol-title { font-size: 3rem; line-height: 1; } }
.lcol-body { margin: 0; font-weight: 300; line-height: 1.5; color: var(--color-ink); }
/* Stacked and ratio-sized on a phone; a fixed-height row from md, where the frames divide the
   height between them instead of each setting their own. */
.lcol-grid { margin-top: 1.5rem; display: flex; flex-direction: column; gap: 1.25rem; }
@media (min-width: 768px) { .lcol-grid { height: 420px; flex-direction: row; } }
@media (min-width: 1024px) { .lcol-grid { height: 460px; gap: 2rem; } }
/* min-height:0 lets a flex child shrink below its content; without it the absolutely-filled frames
   would push the row past its fixed height. */
.lcol-main { position: relative; min-height: 0; overflow: hidden; border-radius: var(--radius-lg, 0.5rem); border-top-left-radius: var(--radius-hero, 96px); }
@media (max-width: 767.98px) { .lcol-main { aspect-ratio: 16 / 9; } }
@media (min-width: 768px) { .lcol-main { flex-basis: 66.666667%; border-radius: var(--radius-xl, 0.75rem); border-top-left-radius: var(--radius-hero-lg, 128px); } }
.lcol-side { display: flex; gap: 1.25rem; min-height: 0; }
@media (min-width: 768px) { .lcol-side { flex-basis: 33.333333%; flex-direction: column; } }
@media (min-width: 1024px) { .lcol-side { gap: 2rem; } }
.lcol-tile { position: relative; min-height: 0; flex: 1 1 0%; overflow: hidden; border-radius: var(--radius-lg, 0.5rem); }
@media (max-width: 767.98px) { .lcol-tile { aspect-ratio: 4 / 3; } }
/* the diagonal's opposite corner — bottom-right on the last tile answers top-left on the lead frame */
.lcol-tile--br { border-bottom-right-radius: var(--radius-hero, 96px); }
@media (min-width: 768px) { .lcol-tile--br { border-bottom-right-radius: var(--radius-hero-lg, 128px); } }
.lcol-img { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: cover; }
/* ============================================================================
   masonry-gallery — a ratio-varied column flow, one card per picture.
   ============================================================================ */
.mgal-sec { background: var(--color-surface-warm); padding-block: 4rem; }
@media (min-width: 1024px) { .mgal-sec { padding-block: 6rem; } }
.mgal-head { margin: 0 auto 3rem; max-width: 48rem; text-align: center; }
.mgal-title { margin: 0 0 0.75rem; font-size: 1.875rem; line-height: 2.25rem; font-weight: 700; color: var(--color-heading); }
@media (min-width: 768px) { .mgal-title { font-size: 2.25rem; line-height: 2.5rem; } }
.mgal-sub { margin: 0; line-height: 1.5; color: var(--color-ink); }
.mgal-cols { columns: 1; column-gap: 1.5rem; }
@media (min-width: 640px) { .mgal-cols { columns: 2; } }
@media (min-width: 1024px) { .mgal-cols { columns: 3; } }
@media (min-width: 1280px) { .mgal-cols { columns: 4; } }
.mgal-card { margin-bottom: 1.5rem; break-inside: avoid; overflow: hidden; border-radius: var(--radius-2xl, 1rem); background: var(--color-surface-raised); box-shadow: var(--shadow-md); }
/* The frame carries the ratio and the picture fills it, so the column rhythm is set by the LAYOUT
   and not by whatever shape the uploaded file happens to be. */
.mgal-frame--5x6 { aspect-ratio: 5 / 6; }
.mgal-frame--4x3 { aspect-ratio: 4 / 3; }
.mgal-frame--1x1 { aspect-ratio: 1; }
.mgal-frame--3x4 { aspect-ratio: 3 / 4; }
.mgal-frame--5x4 { aspect-ratio: 5 / 4; }
.mgal-frame--4x5 { aspect-ratio: 4 / 5; }
.mgal-img { display: block; height: 100%; width: 100%; object-fit: cover; }
/* ============================================================================
   process-steps — four numbered steps.
   ============================================================================ */
.pstep-head { margin: 0 auto; max-width: 32rem; text-align: center; }
.pstep-heading { margin: 0 0 1rem; font-size: 1.5rem; line-height: 2rem; font-weight: 700; color: var(--color-heading); }
@media (min-width: 768px) { .pstep-heading { font-size: 1.875rem; line-height: 2.25rem; } }
.pstep-sub { margin: 0; line-height: 1.5; color: var(--color-ink); }
.pstep-grid { margin-top: 2.5rem; display: grid; grid-template-columns: 1fr; gap: 1.5rem; }
@media (min-width: 768px) { .pstep-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .pstep-grid { margin-top: 4rem; grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.pstep-item { text-align: center; }
.pstep-num { margin: 0 auto 1rem; display: flex; width: 3.5rem; height: 3.5rem; align-items: center; justify-content: center; border-radius: var(--radius-pill, 999px); background: var(--color-primary); font-size: 1.25rem; line-height: 1.75rem; font-weight: 700; color: #fff; }
.pstep-title { margin: 0 0 1rem; font-size: 1.125rem; line-height: 1.75rem; font-weight: 700; color: var(--color-heading); }
.pstep-body { margin: 0; font-size: 0.875rem; line-height: 1.25rem; color: var(--color-ink); }
/* ============================================================================
   stats-grid — four figures on muted wells.
   ============================================================================ */
.sgrid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.5rem; }
@media (min-width: 1024px) { .sgrid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.sgrid-item { border-radius: var(--radius-xl, 0.75rem); background: var(--color-surface-muted); padding: 1.5rem; text-align: center; }
/* STY-5: a figure is text. It cleared AA on size alone (large text, 3:1) but was the fill token
   doing a text job, which is the thing STY-5 names. */
.sgrid-value { margin-bottom: 0.5rem; font-size: 2.25rem; line-height: 2.5rem; font-weight: 700; color: var(--color-primary-soft); }
.sgrid-label { font-size: 0.875rem; line-height: 1.25rem; font-weight: 600; color: var(--color-ink); }
/* ============================================================================
   value-props — four claim cards over one CTA.
   ============================================================================ */
.vprop-head { margin: 0 auto; max-width: 42rem; text-align: center; }
.vprop-heading { margin: 0; font-size: 1.5rem; line-height: 2rem; font-weight: 700; color: var(--color-heading); }
@media (min-width: 768px) { .vprop-heading { font-size: 1.875rem; line-height: 2.25rem; } }
.vprop-grid { margin: 2rem auto 0; display: grid; max-width: 56rem; grid-template-columns: 1fr; gap: 1.5rem; }
@media (min-width: 768px) { .vprop-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .vprop-grid { margin-top: 3.5rem; } }
.vprop-card { border-radius: var(--radius-xl, 0.75rem); background: var(--color-surface-muted); padding: 1.5rem; }
@media (min-width: 768px) { .vprop-card { padding: 3rem; } }
@media (min-width: 1024px) { .vprop-card { padding: 4rem; } }
.vprop-card-head { margin-bottom: 1.5rem; display: flex; align-items: center; gap: 0.75rem; }
.vprop-icon { display: block; width: 1.75rem; height: 1.75rem; flex: none; color: var(--color-primary-soft); }
.vprop-card-title { margin: 0; font-size: 1.125rem; line-height: 1.75rem; font-weight: 700; color: var(--color-heading); }
.vprop-card-body { margin: 0; line-height: 1.5; color: var(--color-ink); }
.vprop-foot { margin-top: 2rem; text-align: center; }
@media (min-width: 1024px) { .vprop-foot { margin-top: 3.5rem; } }
.vprop-cta { margin-bottom: 1rem; }
.vprop-note { margin: 0; line-height: 1.5; color: var(--color-ink); }
}