/* =====================================================================
   site.css — ECo Global Consulting layout & section components
   Editorial-luxury, magazine-style. Oversized Century serif display,
   ornamental EC monogram motif, asymmetric grids and gold hairline
   framing from the 2026 brand kit. Works with base.css.
   ===================================================================== */

/* ---- Generic editorial section frame ------------------------------ */
.r-section { position: relative; padding: var(--sp-section) 0; }
.r-eyebrow {
    font-family: var(--font-sans);
    font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .32em; text-transform: uppercase;
    color: var(--accent-strong); display: flex; align-items: center; gap: 14px;   /* AA-safe */
}
/* Brand sparkle where the "/ 01" chapter numbers used to sit. Same masked SVG
   and same --gold as the slide captions carry, so they read as one ornament.
   Drawn from CSS, so no template carries a decorative character for a screen
   reader to read out. */
.r-eyebrow::before {
    content: "";
    width: .78em; height: .78em; flex-shrink: 0;
    background: var(--gold);
    -webkit-mask: var(--icon-sparkle) center / contain no-repeat;
    mask: var(--icon-sparkle) center / contain no-repeat;
}
/* The rule that closes each header now carries the gold sweep that used to run
   in the homepage scroll cue. A 46px gold segment travels the 120px rule, then
   the cycle rests for the back half — every header on the page animates at
   once, and a constant crawl on all of them would read as noise. Animating
   background-position rather than a child element keeps this to one pseudo-
   element and no markup change; the painted area is 1px tall, so the cost of
   not being a composited transform is negligible. */
.r-eyebrow::after {
    content: "";
    flex: 1; height: 1px; max-width: 120px;
    background-color: var(--hairline);
    background-image: linear-gradient(90deg, transparent, var(--gold), transparent);
    background-size: 46px 100%;
    background-repeat: no-repeat;
    animation: eyebrow-sheen 3.6s var(--ease-out) infinite;
}
@keyframes eyebrow-sheen {
    0%   { background-position: -46px 0; }
    45%  { background-position: 166px 0; }
    100% { background-position: 166px 0; }
}

/* Section titles use Raleway (primary type per 2026 brand kit); the italic
   emphasis word stays Century Old Style as an editorial accent. */
.r-display { font-family: var(--font-sans); font-weight: 700; letter-spacing: -0.015em; line-height: 1.1; }
.r-display em { font-family: var(--font-serif); font-weight: 400; font-style: italic; color: var(--accent-strong); }

/* Display type scale (replaces per-page inline font-size overrides) */
.r-display.ds-xl { font-size: var(--fs-d1); }
.r-display.ds-lg { font-size: var(--fs-d2); }
.r-display.ds-md { font-size: var(--fs-d2); }
.r-display.ds-sm { font-size: var(--fs-d3); }
.r-display.ds-xs { font-size: var(--fs-d3); }

/* top hairline frame on major sections */
.framed { border-top: 1px solid var(--hairline); }

/* ---- Hero --------------------------------------------------------- */
/* Height is the viewport less the 76px header, the 180px stat band and a 62px trim — the band was cut 10%
   on 10 Aug 2026, which is what stops the centred text column parking its slack under the header.
   Capped at 684px, the same 10% off the old 760, so a tall monitor gets no field of empty photo.
   The stat figures still clear the fold: 77 header + 562 hero + 180 band = 819 on a 900px window. */
.r-hero {
    position: relative;
    min-height: min(calc(100vh - 338px), 684px);
    min-height: min(calc(100svh - 338px), 684px);
    display: flex; align-items: stretch;
    background: var(--hero-grad);
    overflow: hidden;
    padding: var(--sp-tight) 0 var(--sp-block);
}
.r-hero .container { position: relative; z-index: 2; }
/* Two columns: copy left, capability slideshow right. 1fr .92fr keeps the headline the wider of the two.
   The grid is stretched so the photo column runs the hero's full height; only the copy opts back out, which
   is what keeps the eyebrow 34px under the header instead of floating in the middle. */
/* minmax(0, 1fr) on the row, not the default auto: an auto row sizes to the copy and leaves the rest of the
   stretched container empty below it, which is exactly how the photo column failed to reach the stat band. */
.r-hero-grid {
    display: grid; grid-template-columns: 1fr .92fr; grid-template-rows: minmax(0, 1fr);
    gap: clamp(28px, 4vw, 64px); align-items: stretch;
}
/* No slides in the CMS yet, so there is no second column to hold room for. */
.r-hero-grid.solo { grid-template-columns: 1fr; }
/* Centred against the centred card, and spaced by relationship rather than evenly. An even spread put the
   eyebrow 91px from the heading it labels — the same distance as the lede sits from the buttons — so nothing
   told the reader which blocks belong together. The three margins below rise 1 : 1.4 : 2 as the tie weakens.
   Flex, so the margins cannot collapse into each other; vh terms shrink them all on a short window. */
/* Centred, so the text column and the photo panel beside it share a centre line. The band above was cut 10%
   to stop that centring from parking 113px of slack under the header. */
.r-hero-copy { align-self: center; display: flex; flex-direction: column; }
.r-hero-kicker { margin-bottom: clamp(14px, 2.3vh, 22px); }
/* Set a step up from the section eyebrows — it is the first line on the site, not a chapter marker. */
.r-hero .r-hero-copy .r-eyebrow { font-size: var(--fs-sm); }
/* 13.5em is the measure that breaks after "banking,", giving two lines: it clears that clause (12.7em) and
   stops short of "expertly" (16.9em). Both are em, so the break holds at every size --fs-d1 produces. */
.r-hero h1 {
    font-family: var(--font-serif); font-weight: 400;
    font-size: var(--fs-d1); line-height: 1.04; letter-spacing: -0.02em;
    margin-bottom: clamp(20px, 3.4vh, 32px); max-width: 13.5em;
    overflow-wrap: break-word; word-wrap: break-word;
}
.r-hero h1 em { font-style: italic; color: var(--accent-strong); }
.r-hero .lede { font-size: var(--fs-lede); margin-bottom: clamp(26px, 4.8vh, 46px); }
.r-hero .cta-row { margin-bottom: 0; }
/* The hero scroll cue was removed in Jul 2026; its gold sweep now runs on the
   .r-eyebrow rule above. */

/* ---- Hero capability slideshow ------------------------------------ */
/* Replaced the marquee ticker in Aug 2026. Slides stack in one grid cell so a crossfade is opacity alone —
   no reflow, no layout shift, and the stage keeps the height of the tallest caption. */
.hero-show { position: relative; align-self: stretch; display: flex; flex-direction: column; }
/* No flex:1 — a 0 flex-basis makes Firefox size this to 0, since aspect-ratio does not transfer through it. */
.hs-stage { position: relative; display: grid; min-height: clamp(260px, 34vh, 420px); overflow: hidden; }
.hs-slide {
    grid-area: 1 / 1; position: relative; margin: 0;
    opacity: 0; visibility: hidden;
    transition: opacity .7s var(--ease-out), visibility 0s linear .7s;
}
.hs-slide.on { opacity: 1; visibility: visible; transition: opacity .7s var(--ease-out), visibility 0s; }
.hs-photo { position: absolute; inset: 0; background-size: cover; background-position: center; }
/* Scrim, not a flat tint: the caption sits low, so the darkening is only where the type is. Weighted for the
   brightest slide — a laptop-lit meeting table — since a scrim tuned to the dark skylines fails on that one. */
.hs-photo::after {
    content: ""; position: absolute; inset: 0;
    background: linear-gradient(to top, rgba(42, 11, 40, .92) 0%, rgba(42, 11, 40, .66) 26%, rgba(42, 11, 40, .24) 52%, transparent 78%);
}
.hs-caption { position: absolute; left: 0; right: 0; bottom: 0; padding: 0 clamp(20px, 2.6vw, 34px) clamp(58px, 6vh, 74px); }
/* Full --gold, not --camel-40: that token is 40% alpha and disappears against a photo. */
.hs-caption .r-eyebrow { font-size: var(--fs-2xs); color: var(--gold); }
.hs-caption .r-eyebrow::after { background-color: rgba(255, 255, 255, .34); }
.hs-descriptor {
    margin: 12px 0 0; color: #fff;
    font-family: var(--font-serif); font-size: var(--fs-d3); line-height: 1.16;
}
/* Unlabelled slide — the line is the whole caption, so it takes the eyebrow's space and a step of size with it. */
.hs-caption.solo .hs-descriptor { margin-top: 0; font-size: var(--fs-d2); }
/* Controls ride on the photo's darkest corner, so they need no plate of their own. */
.hs-controls { position: absolute; left: clamp(20px, 2.6vw, 34px); bottom: clamp(18px, 2.2vh, 26px); z-index: 2; display: flex; align-items: center; gap: 16px; }
.hs-pause { width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; opacity: .55; transition: opacity var(--transition); }
.hs-pause:hover, .hs-pause:focus-visible { opacity: 1; }
/* One box drawn two ways: two bars for pause, a right-pointing triangle for play. No icon file either way. */
.hs-glyph { width: 10px; height: 12px; border-left: 3px solid #fff; border-right: 3px solid #fff; }
.hs-pause[data-paused] .hs-glyph {
    width: 0; height: 0; border: 6px solid transparent; border-left: 10px solid #fff; border-right: 0;
    margin-left: 3px;
}
.hs-dots { display: flex; align-items: center; gap: 9px; }
/* 24px hit area around a 7px dot. That is under the 44px touch minimum, so a coarse pointer gets 44px below. */
.hs-dot {
    width: 24px; height: 24px; padding: 0; position: relative;
    display: flex; align-items: center; justify-content: center;
}
/* Finger-sized targets without changing how anything looks: the dot and the glyph keep their drawn size. Both
   conditions, because a touchscreen laptop needs this at any width and a phone needs it whatever it reports. */
@media (pointer: coarse), (max-width: 860px) {
    .hs-dot, .hs-pause { width: 44px; height: 44px; }
    .hs-dots { gap: 0; }
}
.hs-dot::before {
    content: ""; width: 7px; height: 7px; border-radius: 50%;
    background: rgba(255, 255, 255, .42); transition: background var(--transition), transform var(--transition);
}
.hs-dot:hover::before { background: rgba(255, 255, 255, .8); }
.hs-dot[aria-selected="true"]::before { background: var(--gold); transform: scale(1.3); }

/* The panel stays inside the 1280px container, wearing the radius and shadow the statement figure already
   uses, and centres against a top-aligned copy column. Chosen over the two bleeding layouts in Aug 2026. */
.r-hero .hero-show {
    align-self: center; border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow-md);
}
/* 4:3 until it would push the stat figures under the fold on a short window; past 56vh the height caps and
   background-size: cover simply crops a little harder. */
.r-hero .hs-stage { aspect-ratio: 4 / 3; min-height: 0; max-height: 56vh; }

/* ---- Editorial stats ---------------------------------------------- */
/* Four figures across since Aug 2026, when the implementations count was cut.
   "16,000+" is still the widest string, and a quarter of the 1280px container
   (~320px, less 24px of side padding) now holds it with room to spare. nowrap
   on .rs-num keeps a figure from breaking at the thousands comma. */
.r-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0; }
.r-stat { padding: 14px 24px; border-left: 1px solid var(--hairline); }
.r-stat:first-child { border-left: none; padding-left: 0; }
.r-stat .rs-num {
    font-family: var(--font-sans); font-weight: 700;
    font-size: var(--fs-d1); line-height: 1; letter-spacing: -0.02em;
    color: var(--heading); white-space: nowrap;
}
.r-stat .rs-num .unit { color: var(--accent); }
.r-stat .rs-label { margin-top: 12px; font-size: var(--fs-xs); line-height: 1.5; color: var(--text-muted); letter-spacing: .02em; }

/* Full-width band directly under the hero. Padding is tighter than a normal section so the whole band clears
   ~200px, the figure the hero's min-height subtracts to keep the five figures above the fold. */
.r-statband { padding: clamp(24px, 2.6vw, 34px) 0; border-bottom: 1px solid var(--hairline); }
.r-statband .r-stat { padding-block: 6px; }

/* ---- Intro statement ---------------------------------------------- */
.r-statement { display: grid; grid-template-columns: 1fr 1.6fr; gap: clamp(30px, 5vw, 70px); align-items: start; }
.r-statement .rs-head { position: sticky; top: 110px; }
.r-statement .big {
    font-family: var(--font-serif); font-weight: 400;
    font-size: var(--fs-d2); line-height: 1.28; letter-spacing: -0.01em;
    color: var(--heading); margin-bottom: 1.2em;
}
.r-statement .big em { font-style: italic; color: var(--accent-strong); }
.r-statement p { color: var(--text-muted); font-size: var(--fs-body); max-width: 60ch; }

/* ---- Growth champions feature ------------------------------------- */
.r-award { position: relative; background: var(--panel-bg); color: var(--panel-text); overflow: hidden; }
.r-award .ra-mono { position: absolute; left: -6%; bottom: -20%; width: 440px; opacity: .08; }
.r-award .container { position: relative; z-index: 2; }
.r-award-grid { display: grid; grid-template-columns: 1fr 1.3fr; gap: clamp(36px, 6vw, 80px); align-items: center; }
.r-award .ra-year { font-family: var(--font-sans); font-weight: 700; font-size: clamp(5rem, 13vw, 11rem); line-height: .82; letter-spacing: -0.03em; color: var(--gold); }
.r-award .ra-year span { display: block; font-weight: 400; font-size: var(--fs-xs); letter-spacing: .3em; text-transform: uppercase; color: var(--on-panel-muted); margin-top: 18px; }
.r-award h2 { color: var(--panel-heading); font-family: var(--font-sans); font-weight: 700; font-size: var(--fs-d2); letter-spacing: -0.01em; }
.r-award p { color: var(--on-panel-muted); max-width: 56ch; }
.r-award .src { color: var(--gold); font-weight: 600; }
.r-award .ra-rule { width: 70px; height: 2px; background: var(--gold); margin-bottom: 28px; }

/* ---- Services — editorial list ------------------------------------ */
/* Three columns since Jul 2026, when the 01/02/03 marker was dropped from the
   front of each row: title | description | arrow. */
/* Widened from 1.1 : 1.4 — the descriptions carry the old site's full sentences, and "Implementation Services"
   needs a title column that holds it on one line at the 2.2rem the clamp reaches above 1280px. */
.r-services .svc-row {
    display: grid; grid-template-columns: 1.15fr 1.55fr auto; gap: 30px; align-items: center;
    padding: 40px 0; border-top: 1px solid var(--hairline);
    transition: background var(--transition), padding var(--transition);
}
.r-services .svc-row:last-child { border-bottom: 1px solid var(--hairline); }
.r-services .svc-row:hover { background: var(--surface-2); padding-inline: 24px; }
.svc-title { font-family: var(--font-sans); font-weight: 700; font-size: var(--fs-d2); color: var(--heading); line-height: 1.15; letter-spacing: -0.01em; }
.svc-desc { color: var(--text-muted); font-size: var(--fs-sm); }
.svc-go { width: 52px; height: 52px; border-radius: 50%; border: 1px solid var(--hairline); display: flex; align-items: center; justify-content: center; color: var(--accent-strong); transition: background var(--transition), color var(--transition), transform var(--transition); flex-shrink: 0; font-size: 0; }
.svc-go::after { content: ""; width: 20px; height: 20px; background: currentColor; -webkit-mask: var(--icon-arrow-right) center / contain no-repeat; mask: var(--icon-arrow-right) center / contain no-repeat; }
.r-services .svc-row:hover .svc-go { background: var(--gold); color: var(--coffee); transform: rotate(-45deg); border-color: var(--gold); }

/* ---- Solutions — overlapping cards -------------------------------- */
.r-solutions { background: var(--surface-2); border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline); }
/* auto-fit, not repeat(3): the card count is data-driven, and a fixed 3 left an empty column when it dropped to 2. */
.sol-deck { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); gap: 24px; margin-top: 56px; }
.sol-card {
    position: relative; background: var(--surface-inset);
    border: 1px solid var(--border); border-radius: var(--radius-lg);
    padding: 40px 32px 34px; overflow: hidden;
    transition: transform var(--transition), box-shadow var(--transition);
}
.sol-card:hover { transform: translateY(-8px); box-shadow: var(--shadow-lg); }
.sol-card .sol-mark { font-family: var(--font-sans); font-weight: 700; font-size: var(--fs-d2); color: var(--heading); margin-bottom: .2em; letter-spacing: -0.01em; }
.sol-card .sol-kind { font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--accent-strong); margin-bottom: 22px; display: block; }
.sol-card p { color: var(--text-muted); font-size: var(--fs-sm); margin-bottom: 1.4em; }
.sol-card .card-link { font-weight: 700; font-size: var(--fs-xs); color: var(--accent-strong); display: inline-flex; gap: 7px; align-items: center; }
.sol-card::before { content: ""; position: absolute; left: 0; bottom: 0; height: 4px; width: 100%; background: linear-gradient(90deg, var(--gold), var(--camel)); transform: scaleX(0); transform-origin: left; transition: transform var(--transition); }
.sol-card:hover::before { transform: scaleX(1); }

/* ---- Pull-quote full bleed ---------------------------------------- */
.r-quote { position: relative; text-align: center; }
.r-quote .qmark { font-family: var(--font-serif); font-size: 7rem; line-height: .4; color: var(--camel); opacity: .5; }
.r-quote blockquote {
    font-family: var(--font-serif); font-weight: 400; font-style: italic;
    font-size: var(--fs-d1); line-height: 1.3; letter-spacing: -0.01em;
    color: var(--heading); max-width: 20ch; margin: 28px auto 36px; margin-block-start: 0;
}
.r-quote blockquote .hl { color: var(--accent-strong); }
/* About Us quotes a full sentence, not a phrase — at 20ch and 3rem it would run ten lines and swallow the page. */
.r-quote blockquote.q-long { max-width: 34ch; font-size: var(--fs-d2); line-height: 1.34; }
.r-quote .qauthor { display: inline-flex; align-items: center; gap: 14px; }
/* Sans, not serif: the fallback initial is a UI mark, and at serif 700 this one hidden letter pulled the whole
   25KB Century Bold file on every page carrying a quote. */
.r-quote .qavatar { width: 52px; height: 52px; border-radius: 50%; background: linear-gradient(135deg, var(--gold), var(--camel)); color: var(--coffee); display: flex; align-items: center; justify-content: center; font-family: var(--font-sans); font-weight: 700; font-size: var(--fs-d4); }
.r-quote .qmeta { text-align: left; }
.r-quote .qname { font-weight: 700; color: var(--heading); }
.r-quote .qrole { font-size: var(--fs-xs); color: var(--text-muted); }

/* ---- Global reach ------------------------------------------------- */
.r-reach { background: var(--panel-bg); color: var(--panel-text); position: relative; overflow: hidden; }
.r-reach .rr-mono { position: absolute; right: -5%; top: -25%; width: 460px; opacity: .07; }
.r-reach .container { position: relative; z-index: 2; }
.r-reach-grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(36px, 6vw, 80px); align-items: center; }
.r-reach h2 { color: var(--panel-heading); font-family: var(--font-sans); font-weight: 700; letter-spacing: -0.01em; }
.r-reach p { color: var(--on-panel-muted); max-width: 50ch; }
.r-reach .r-eyebrow { color: var(--gold); }
/* background-color, not the `background` shorthand: the shorthand would reset
   background-image/size/repeat and wipe the gold sweep gradient this section's
   eyebrow inherits from .r-eyebrow::after. Only the track colour changes here. */
.r-reach .r-eyebrow::after { background-color: var(--camel-40); }
.reach-cities { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.reach-city { background: transparent; border: 1px solid var(--gold); border-radius: var(--radius-md); padding: 26px 24px; text-align: center; }
.reach-city .rc-name { font-family: var(--font-sans); font-weight: 700; font-size: var(--fs-d3); color: var(--gold); }

/* ---- News strip --------------------------------------------------- */
/* Wraps because the "What we do" heading is a full sentence now — unwrapped it left the h2 165px beside a
   nowrap button on a phone. The link drops under the heading and keeps its own line. */
.r-news-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-end; gap: 24px; margin-bottom: 44px; }
.r-news-head > div { flex: 1 1 340px; min-width: 0; }
.r-news-list { border-top: 1px solid var(--hairline); }
.r-news-item {
    display: grid; grid-template-columns: 96px 116px 1fr auto auto; gap: 28px; align-items: center;
    padding: 22px 0; border-bottom: 1px solid var(--hairline);
    transition: background var(--transition), padding var(--transition);
}
.r-news-item:hover { background: var(--surface-2); padding-inline: 22px; }
.r-news-item .rn-thumb {
    width: 96px; height: 64px; border-radius: 10px; border: 1px solid var(--hairline);
    background: var(--surface-2) center/cover no-repeat;
}
.r-news-item .rn-date { font-size: var(--fs-xs); color: var(--text-subtle); letter-spacing: .04em; }
.r-news-item .rn-title { font-family: var(--font-sans); font-weight: 700; font-size: var(--fs-d3); color: var(--heading); line-height: 1.2; letter-spacing: -0.01em; }
.r-news-item .rn-cat { font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--accent-strong); border: 1px solid var(--hairline); border-radius: var(--radius-pill); padding: 5px 13px; white-space: nowrap; }
.r-news-item .rn-go { color: var(--accent-strong); transition: transform var(--transition); font-size: 0; display: inline-flex; }
.r-news-item .rn-go::after { content: ""; width: 20px; height: 20px; background: currentColor; -webkit-mask: var(--icon-arrow-right) center / contain no-repeat; mask: var(--icon-arrow-right) center / contain no-repeat; }
.r-news-item:hover .rn-go { transform: translateX(5px); }

/* ---- Contact CTA -------------------------------------------------- */
.r-contact { position: relative; text-align: center; overflow: hidden; }
.r-contact .rc-mono { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: 520px; opacity: .06; pointer-events: none; }
.r-contact .container { position: relative; z-index: 2; }
.r-contact h2 { font-family: var(--font-serif); font-weight: 400; font-size: var(--fs-d1); line-height: 1.05; max-width: 18ch; margin: 0 auto .5em; }
.r-contact h2 em { font-style: italic; color: var(--accent-strong); }
.r-contact p { color: var(--text-muted); font-size: var(--fs-lede); max-width: 52ch; margin: 0 auto 2em; }
/* Slogan sign-off above the closing CTA. Serif italic between two gold rules,
   matching the header lockup — the section eyebrow style (uppercase, .32em
   tracking) would have made the slogan read as a label, not as the sign-off.
   Two classes so it outranks `.r-contact p` on specificity. */
.r-contact .r-slogan {
    display: flex; align-items: center; justify-content: center; gap: 18px;
    font-family: var(--font-serif); font-style: italic;
    font-size: var(--fs-lede);
    color: var(--accent-strong);
    max-width: none; margin: 0 auto 22px;
}
.r-contact .r-slogan::before, .r-contact .r-slogan::after {
    content: ""; height: 1px; width: clamp(28px, 6vw, 64px); background: var(--hairline);
}

/* ---- Responsive --------------------------------------------------- */
@media (max-width: 980px) {
    .r-statement, .r-award-grid, .r-reach-grid { grid-template-columns: 1fr; }
    .r-statement .rs-head { position: static; }
    .sol-deck { grid-template-columns: 1fr; }
    .r-services .svc-row { grid-template-columns: 1fr auto; }
    .r-services .svc-row .svc-desc { grid-column: 1 / 2; }
    /* Pinned beside the title. Left to auto-placement it fell to a row of its own under the description. */
    .r-services .svc-row .svc-go { grid-column: 2; grid-row: 1; }
    /* Stats reflow to two rows here and cannot make the fold anyway, so the hero goes back to its own height
       rather than holding a viewport-minus-band reserve that would show as a field of empty photo.
       Padding is left to the tokens on the base rule — there is no slack to fight at this width. */
    .r-hero { min-height: 0; }
    /* One column, slideshow under the buttons. */
    .r-hero-grid { grid-template-columns: 1fr; gap: clamp(38px, 6vw, 56px); }
    /* No font-size override any more: the headline holds --fs-d1 here, the same step every other page's h1 uses. */
    .r-hero .lede { max-width: 640px; }
    /* Wider than the 4:3 it uses beside the copy — full width, a squarer panel would fill most of the screen. */
    .r-hero .hs-stage { aspect-ratio: 7 / 5; }
    /* Top-anchored here: the crop is tighter at one column, and the subject of every hero photo sits high. */
    .r-hero .hs-photo { background-position: top center; }
    /* 4 figures reflow to 2 + 2. Items 1 and 3 open a row, so they drop the divider that would hang at its start. */
    .r-stats { grid-template-columns: repeat(2, 1fr); gap: 32px 0; }
    .r-stat:nth-child(odd) { border-left: none; padding-left: 0; }
}
/* Short desktop window — a 1080p laptop at 125% scaling lands here. Everything above the stat band gives up a
   few pixels so all four figures still clear the fold; taller screens keep the roomier hero above.
   The headline is the one place the scale bends: min() lets a short window shrink it below --fs-d1, and only
   here, because a phone in landscape is short too and would otherwise get a 21px h1. */
@media (min-width: 981px) and (max-height: 800px) {
    .r-hero { padding: 26px 0; }
    .r-hero h1 { font-size: min(var(--fs-d1), 5.6vh); }
    .r-statband { padding: 22px 0; }
    .r-statband .r-stat .rs-label { margin-top: 8px; }
}
@media (max-width: 640px) {
    .r-news-item { grid-template-columns: 1fr auto; gap: 8px 16px; }
    .r-news-item .rn-date { grid-column: 1 / -1; }
    .r-news-item .rn-cat, .r-news-item .rn-thumb { display: none; }
    .reach-cities { grid-template-columns: 1fr; }
    .r-services .svc-row { grid-template-columns: 1fr auto; align-items: start; }
    .r-services .svc-row .svc-desc { grid-column: 1 / -1; }
    /* Still 2 + 2 — one figure per line would push the band past a phone screen on its own. */
    .r-stats { gap: 28px 0; }
    .r-stat { padding-inline: 16px; }
    .r-stat:nth-child(odd) { padding-left: 0; }
}

/* ---- Mockup imagery ----------------------------------------------- */
/* Real photos go in assets/images/photos/. Missing images degrade gracefully
   to the branded gradients/veils below. */

/* Hero background photo behind the serif headline */
.r-hero.has-media .r-hero-photo { position: absolute; inset: 0; z-index: 0; background-size: cover; background-position: center; }
.r-hero.has-media .r-hero-photo::after { content: ""; position: absolute; inset: 0; }
[data-theme="light"] .r-hero.has-media .r-hero-photo::after { background: linear-gradient(105deg, rgba(237, 232, 214, .95) 36%, rgba(226, 220, 195, .80)); }
[data-theme="dark"]  .r-hero.has-media .r-hero-photo::after { background: linear-gradient(105deg, rgba(12, 2, 19, .94) 36%, rgba(63, 19, 60, .80)); }

/* Statement editorial figure in the sticky left column */
.rs-figure {
    margin-top: 30px; aspect-ratio: 4 / 3.1; border-radius: var(--radius-lg);
    background: var(--surface-2) center/cover no-repeat;
    border: 1px solid var(--hairline); box-shadow: var(--shadow-md);
}

/* Solution card band. Replaced the photo banner on 10 Aug 2026: no product artwork exists for every solution, and a
   UI screenshot is unreadable at this height anyway. The category sets in serif italic gold on the violet field, and
   the card drops its .sol-kind line so the category is stated once. Shared with .sol-tile on the Solutions page. */
.sol-card .sol-cat,
.sol-tile .sol-cat {
    height: 96px; margin: -40px -32px 26px;
    display: flex; align-items: center; justify-content: center; padding: 0 22px;
    background: linear-gradient(135deg, var(--violet-deep), var(--violet) 62%, #56204F);
    font-family: var(--font-serif); font-style: italic; font-size: var(--fs-lede);
    line-height: 1.2; text-align: center; color: var(--gold);
}

/* Pull-quote portrait (photo covers the fallback letter) */
.r-quote .qavatar { position: relative; overflow: hidden; }
.r-quote .qavatar img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* Global reach → world-map graphic */
.rr-map {
    position: absolute; right: -3%; top: 50%; transform: translateY(-50%);
    width: min(58vw, 700px); height: 78%;
    background-size: contain; background-position: center right; background-repeat: no-repeat;
    opacity: .5; z-index: 1; pointer-events: none;
}
@media (max-width: 980px) { .rr-map { opacity: .22; } }
