/* ------------------------------------------------------------------
   LXP — page-level styles on top of the design system.
   Tokens, primitives, base reset → css/tokens.css.
   ------------------------------------------------------------------ */

/* ============================ CARD IMAGE HOVER ====================
   DS rule: every <img> inside a `.card` animates the SAME way on hover.
   ONE selector. No per-component overrides. Values live in tokens.css
   as --card-img-hover-scale / --card-img-hover-duration / --card-img-hover-easing.

   To make a new component participate, just add the `.card` class to
   the outer element. Don't add component-specific transition/hover rules
   for the image — they'll diverge from the canon.
   =================================================================== */
.card img {
    transition: transform var(--card-img-hover-duration) var(--card-img-hover-easing);
}
.card:hover img,
.card:focus-within img {
    transform: scale(var(--card-img-hover-scale));
}

/* ============================ CARD LIFT ON HOVER ==================
   DS rule: any card that should lift + cast a softer shadow on hover
   opts in with `.card--liftable`. ONE rule, ONE transition. Used by
   article cards, case-study cards/entries, review cards and the editorial
   destination anchor. Don't add per-component :hover rules for the same
   thing — they drift in duration/easing/shadow and the site loses rhythm.
   =================================================================== */
.card--liftable {
    transition: transform 220ms var(--ease), box-shadow 220ms var(--ease);
}
.card--liftable:hover,
.card--liftable:focus-within {
    transform: translateY(-2px);
    box-shadow: var(--shadow-3);
}

/* ============================ PANEL (SET-OFF SURFACE) =============
   DS rule: the ONE way to lift a block of content off the page ground —
   the warm --accent-faint tint, soft --r-lg radius, clamped padding. No
   border, no shadow. This is the sanctioned alternative to running copy;
   it is NOT the general `.card` class (that is deliberately chrome-less,
   a behaviour/typography hook for photo tiles — see tokens.css).

   The recipe lives here ONCE. Opt a new surface in by adding `.panel` to
   its markup. Existing surfaces are grouped in by their own class name so
   there are no markup changes — retune the tint/radius/padding here and
   every panel follows. Don't redeclare these three properties per
   component; that's how the surfaces drift apart.

   Members:
     .reviews__featured              — homepage featured Google review
     .content-element__content.card  — editorial content block (Style: Card)
   Component-specific layout (flex column, line-clamp, author-to-bottom)
   stays on the component's own rules. */
.panel,
.reviews__featured,
.content-element__content.card {
    background: var(--accent-faint);
    border-radius: var(--r-lg);
    padding: clamp(var(--s-6), 4vw, var(--s-8));
}
/* Content sits flush to the panel padding — kill stray outer margins on
   the first/last child (e.g. a leading <h2> or trailing <p> of prose). */
.panel > :first-child,
.reviews__featured > :first-child,
.content-element__content.card > :first-child { margin-top: 0; }
.panel > :last-child,
.reviews__featured > :last-child,
.content-element__content.card > :last-child { margin-bottom: 0; }

:root {
    --measure:   64ch;
    --rail:      1px solid var(--hairline);
    --rail-soft: 1px solid var(--hairline-soft);
}

html {
    /* 103.125% of the 16px browser default = the same 16.5px — but as a
       percentage it still honours a user-raised default font size, which
       a px value silently ignores for every rem on the site. */
    font-size: 103.125%;
    /* Anchor/focus scrolls clear the 71px sticky masthead. */
    scroll-padding-top: 88px;
    line-height: 1.58;
    font-feature-settings: "kern" 1, "liga" 1;
    /* Horizontal-overflow guard for full-bleed (100vw) sections lives in a gated
       rule just below — NOT here on the bare `html`, because overflow on the root
       makes iOS Safari clip position:fixed children (the Lexi bubble + back-to-top
       were getting cut off at the bottom). */
    /* The ROOT background paints the canvas — including iOS Safari's overscroll
       rubber-band past the footer. Match it to the footer's white ground
       (--surface) instead of letting <body>'s bone (--bg) propagate, so an
       over-scroll bounce at the bottom doesn't flash bone below the white footer.
       <body> keeps --bg for the page itself (bone vs white is a hair's
       difference, so the top is visually unchanged). NB: the PERSISTENT bottom
       gap is fixed elsewhere — by the hero using svh, not dvh (see the hero
       stage rule); this rule only tidies the transient over-scroll edge. */
    background: var(--surface);
}

/* Full-bleed (100vw) sections overflow by the vertical-scrollbar gutter (~8–15px)
   on classic-scrollbar browsers, triggering a horizontal scrollbar. `clip` (not
   `hidden`) prevents it without establishing a scroll container, so position:
   sticky keeps working. GATED to NON-touch devices: on iOS/iPadOS Safari, overflow
   on the root element clips position:fixed children (it was cutting off the Lexi
   bubble + back-to-top). Touch browsers use overlay scrollbars (no gutter), so the
   guard isn't needed there anyway — verified there's no horizontal overflow on
   mobile without it. */
@media not all and (any-pointer: coarse) {
    html { overflow-x: clip; }
}

h1, h2, h3, .serif {
    font-feature-settings: "kern" 1, "liga" 1, "onum" 1;
}

/* Structural elements opt out of the body default (Garamond) and use the
   sans stack — nav, breadcrumb, locale switcher, pagination, footer nav.
   Targets the leaf elements (a / li) directly so tokens.css's `p, li`
   serif rule loses to specificity. */
.site-header, .site-header *,
.site-locale__link,
.site-subnav, .site-subnav li, .site-subnav a, .site-subnav h3,
.breadcrumb, .breadcrumb li, .breadcrumb a,
.pagination, .pagination a, .pagination li,
.site-footer, .site-footer li, .site-footer a {
    font-family: var(--sans);
}

/* Brand wordmark stays serif italic (overrides the .site-header * blanket).
   Brand is absolutely positioned within .site-header__inner so its
   navy plate can hang below the nav row without growing the header.
   The grid template reserves a min-width on column 1 so the nav
   stays viewport-centered (won't slide left under the brand). The
   plate is 1.5× the header height; the wordmark is anchored to its
   bottom edge via flex-end + a small bottom padding. */
.site-header__inner {
    position: relative;
    grid-template-columns: minmax(260px, 1fr) auto 1fr;
}
.site-header__brand {
    position: absolute;
    top: 0;
    left: var(--gutter);
    height: calc(var(--site-header-h, 73px) * 1.5);
    display: block;
    text-decoration: none;
    z-index: 1;
    transition: transform 260ms var(--ease);
    will-change: transform;
}
/* Slide the brand plate up while the visitor is scrolling DOWN past
   the masthead. Scrolling back up restores it to fully visible —
   header-scroll.js toggles .site-header--folded on direction change. */
.site-header--folded .site-header__brand {
    transform: translateY(-30px);
}
.site-header__logo {
    display: block;
    height: 100%;
    width: auto;
}

a {
    color: var(--accent);
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
}
a:hover { color: var(--accent-deep); }

/* Headline-in-link: ink color stays, tonal underline wipes L→R on hover/focus.
   Covers both <a><h?> and <h?><a> markup shapes site-wide. */
a :is(h1, h2, h3, h4),
:is(h1, h2, h3, h4):has(a) {
    color: inherit;
    text-decoration: none;
    width: fit-content;
    max-width: 100%;
    background-image: linear-gradient(currentColor, currentColor);
    background-repeat: no-repeat;
    background-position: 0 100%;
    background-size: 0% 0.08em;
    padding-bottom: 0.15em;
    transition: background-size 420ms cubic-bezier(0.65, 0, 0.35, 1);
}
a:hover :is(h1, h2, h3, h4),
a:focus-visible :is(h1, h2, h3, h4),
:is(h1, h2, h3, h4):has(a:hover),
:is(h1, h2, h3, h4):has(a:focus-visible) {
    background-size: 100% 0.08em;
}

.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    padding: var(--s-2) var(--s-4);
    background: var(--accent);
    color: #fff;
}
.skip-link:focus { left: var(--s-4); top: var(--s-4); z-index: 100; }

/* Back-to-top — mobile only. Hidden on desktop entirely; on phones it
   fades in once to-top.js adds .is-visible (past ~0.8 viewport scrolled).
   Espresso disc, design-system rounding + shadow, safe-area aware. */
.to-top { display: none; }
@media (max-width: 720px) {
    .to-top {
        position: fixed;
        /* Bottom-LEFT — the Lexi chat bubble owns the bottom-right corner. */
        left: var(--s-4);
        /* No env(safe-area-inset-bottom) here on purpose: iOS Safari toggles that
           inset 0↔34px as the bottom toolbar collapses/expands on scroll, which
           made the button jump up ~34px (reading as "barely visible") while
           scrolling down. A constant 16px keeps it pinned in every toolbar state. */
        bottom: var(--s-4);
        z-index: 60;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 44px;
        height: 44px;
        padding: 0;
        border: none;
        border-radius: var(--r-pill);
        background: var(--accent);
        color: var(--accent-ink, #fff);
        box-shadow: var(--shadow-2);
        cursor: pointer;
        opacity: 0;
        transform: translateY(8px);
        pointer-events: none;
        transition: opacity 200ms var(--ease), transform 200ms var(--ease), background 160ms ease;
    }
    .to-top.is-visible { opacity: 1; transform: none; pointer-events: auto; }
    .to-top:hover, .to-top:focus-visible { background: var(--accent-deep); }
    .to-top:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
}
/* Hidden while the first-visit consent banner covers the bottom of the screen. */
html.cc-banner-open .to-top { display: none !important; }

/* ---------- Site header -------------------------------------------- */

/* Header bar is full-viewport-width (background + border edge-to-edge).
   Content stays max-width via .site-header__inner. The mega-menu
   dropdown anchors to this sticky element so it bleeds full-width too;
   its inner children carry their own max-width + margin: 0 auto. */
.site-header {
    /* Transparent at the top of the page (brand box, CTA + chrome pill
       carry the visual weight as floating elements); takes a solid sand
       skin once scrolled — see `body.is-scrolled .site-header` below. */
    background: transparent;
    border-bottom: 0;
    position: sticky;
    top: 0;
    z-index: 20;
}
/* Three-column grid: brand | nav | utilities. The 1fr / auto / 1fr
   pattern keeps the nav cell exactly in the row's horizontal center
   regardless of brand or utilities width — so when the logo collapses
   to the X mark, the nav doesn't shift. Inner spans full viewport
   width with gutter padding; brand and utilities anchor to the
   viewport edges. Inner is intentionally NOT position: relative so
   the mega-menu dropdown anchors up to the sticky .site-header. */
.site-header__inner {
    max-width: var(--maxw);
    margin: 0 auto;
    padding: var(--s-4) var(--gutter);
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    column-gap: var(--s-5);
}
.site-header__inner > .site-header__brand   { justify-self: start; }
/* Brand is position: absolute (see top of file), which removes it
   from auto-placement. Pin nav and utilities to their tracks so the
   reserved col 1 stays empty for the brand to overlay. */
.site-header__inner > .site-subnav--inline  {
    grid-column: 2;
    justify-self: center;
}
.site-header__inner > .site-header__utilities {
    grid-column: 3;
    justify-self: end;
    display: flex;
    align-items: center;
    gap: var(--s-5);
}

/* TEST — chrome controls (search + locale + hamburger) clustered into
   a frosted charcoal pill. CTA stays its own button to the left. */
.site-header__controls {
    display: inline-flex;
    align-items: center;
    gap: var(--s-3);
    padding: 0 var(--s-3);
    /* Default ("on paper") state: the pill takes the page's own paper tone
       (--bg bone), so it blends into the page and is defined only by the
       hairline + faint shadow — lighter than a white lozenge, far lighter
       than the old dark blob. Over a fullwidth hero it flips to dark glass
       (override further down): dark glass on imagery, paper on paper. */
    background: var(--bg);
    border: 1px solid var(--hairline);
    border-radius: var(--r-pill);
    box-shadow: var(--shadow-1);
    color: var(--ink);
    transition: background 220ms var(--ease), color 220ms var(--ease),
                border-color 220ms var(--ease), box-shadow 220ms var(--ease);
}
.site-header__controls .site-search-trigger,
.site-header__controls .site-locale__current,
.site-header__controls .site-contact-trigger,
.site-header__controls .site-menu-trigger {
    color: var(--ink);
}
/* Half-pill CTA inside the controls pill — rounded on the left so its
   curve merges with the outer pill's left edge, flat on the right so
   it sits flush against the search/locale/menu chrome. Reads as one
   continuous shape with the chrome rather than a separate pill. */
.site-header__controls .site-header__cta {
    border-radius: var(--r-pill) 0 0 var(--r-pill);
    font-size: 12px;
    align-self: stretch;
    display: inline-flex;
    align-items: center;
    /* Pull CTA flush to the pill's left edge — its left curve merges
       with the pill's left curve so they read as one shape. */
    margin-left: calc(-1 * var(--s-3));
}
/* a:hover (generic) wins over .btn-primary on specificity — pin
   the CTA text white so it stays legible on the deep navy hover bg. */
.site-header__controls .site-header__cta,
.site-header__controls .site-header__cta:hover,
.site-header__controls .site-header__cta:focus-visible {
    color: var(--accent-ink);
}
/* 2026-06-09 — primary CTA unified to espresso. The previous orange
   (--feature) variant put white text on #f39200 (2.35:1, fails WCAG AA);
   the CTA now inherits .btn-primary's espresso background (var(--accent),
   white text = 13:1). One primary-action colour sitewide; orange is
   reserved for small non-text accents only (pills, announcement bar). */
.site-header__inner > .site-subnav--inline {
    margin: 0;
    padding: 0;
    background: transparent;
    border: 0;
}
.site-subnav--inline .site-subnav__links--global {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    gap: var(--s-4);
    white-space: nowrap;
}
/* Hover bridge for the inline nav: the li hit area is extended below
   the visible link by padding-bottom + an equal negative margin-bottom.
   The padding adds invisible hit area; the negative margin keeps the
   margin-box height equal to the link height so flex's align-items:
   center still vertically aligns the link text correctly. */
.site-subnav--inline .site-subnav__links--global > li {
    display: inline-flex;
    align-items: center;
    padding-bottom: 0;
}
.site-subnav--inline .site-subnav__links--global > li.has-dropdown {
    padding-bottom: var(--s-5);
    margin-bottom: calc(var(--s-5) * -1);
}
/* TEST — inline mega-menu nav off; the off-canvas drawer carries navigation
   at all widths (the original "drawer carries all" behaviour). */
.site-header__inner > .site-subnav--inline { display: none; }

.site-locale {
    position: relative;
    font-size: 0.85rem;
}
.site-locale__current {
    appearance: none;
    background: transparent;
    border: 1px solid transparent;
    color: var(--ink);
    cursor: pointer;
    padding: var(--s-1) var(--s-2);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    font: inherit;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
/* Globe affordance so the bare EN/DE/ES reads as a language control.
   Inherits currentColor, matching the search icon's stroke weight. */
.site-locale__globe { flex: 0 0 auto; opacity: 0.85; }
.site-locale__current::after {
    content: "";
    width: 6px;
    height: 6px;
    border-right: 1px solid currentColor;
    border-bottom: 1px solid currentColor;
    transform: rotate(45deg) translate(-1px, -1px);
    transition: transform 200ms var(--ease);
}
.site-locale:hover .site-locale__current::after,
.site-locale:focus-within .site-locale__current::after {
    transform: rotate(-135deg) translate(-1px, -1px);
}
.site-locale__panel {
    position: absolute;
    top: 100%;
    right: 0;
    background: #ffffff;
    border: 1px solid var(--hairline);
    border-radius: var(--r-sm);
    box-shadow: var(--shadow-2);
    padding: var(--s-2);
    margin-top: var(--s-2);
    display: flex;
    flex-direction: column;
    min-width: 80px;
    opacity: 0;
    pointer-events: none;
    transform: translateY(-4px);
    transition: opacity 160ms var(--ease), transform 160ms var(--ease);
    z-index: 30;
}
/* Hover bridge: extend the .site-locale hover area down past the
   button so the cursor can travel to the panel without the gap
   killing the hover state. The ::after sits in the same space the
   panel's margin-top occupies — invisible, no layout impact. */
.site-locale::after {
    content: "";
    position: absolute;
    top: 100%;
    right: 0;
    left: 0;
    height: var(--s-2);
}
.site-locale:hover .site-locale__panel,
.site-locale:focus-within .site-locale__panel {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0);
}
.site-locale__link {
    color: var(--ink-soft);
    text-decoration: none;
    padding: var(--s-2);
    border-radius: var(--r-xs);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    transition: background 140ms var(--ease), color 140ms var(--ease);
}
.site-locale__link:hover {
    color: var(--ink);
    background: var(--stone-100);
}
.site-locale__link--current {
    color: var(--ink);
    background: var(--stone-100);
}
.site-locale__link--invalid {
    opacity: 0.35;
    pointer-events: none;
}

/* Header CTA — primary conversion button living next to the locale switcher.
   Uses tokens.css .btn .btn-primary .btn-sm; this rule only handles header-
   specific spacing. The button is hidden <=720px (it moves into the drawer);
   the single hide rule lives in the .site-header__controls 720px block below. */
.site-header__cta { margin-left: var(--s-2); }

/* ---------- Hamburger menu trigger ----------------------------------
   Three-bar icon. Sits at the right edge of the header, opens the
   off-canvas drawer holding the full navigation. */
.site-menu-trigger {
    appearance: none;
    background: transparent;
    border: 0;
    padding: 8px;
    margin-left: var(--s-2);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 36px;
}
/* The visible word beside the icon — NN/g: an unlabelled hamburger is
   the weakest form of the pattern, and with the desktop nav deliberately
   drawer-only this label is the cheapest compensating measure. */
.site-menu-trigger__label {
    font-family: var(--sans);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: currentColor;
    line-height: 1;
}
.site-menu-trigger__bars {
    display: inline-flex;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
}
/* Integer pixel height — 1.5px rendered each bar at a different sub-
   pixel anti-aliasing pattern depending on its y-position, making the
   middle bar look heavier than the outer two on non-retina displays. */
.site-menu-trigger__bar {
    display: block;
    width: 22px;
    height: 1px;
    background: currentColor;
    transition: transform 200ms ease, opacity 200ms ease;
}
.site-menu-trigger[aria-expanded="true"] .site-menu-trigger__bar:nth-child(1) {
    transform: translateY(6.5px) rotate(45deg);
}
.site-menu-trigger[aria-expanded="true"] .site-menu-trigger__bar:nth-child(2) {
    opacity: 0;
}
.site-menu-trigger[aria-expanded="true"] .site-menu-trigger__bar:nth-child(3) {
    transform: translateY(-6.5px) rotate(-45deg);
}
/* TEST — hamburger always visible (drawer is the unified menu now). */
@media (max-width: 720px) {
    .site-header__rails { display: none; }
    /* Mobile chrome is just the hamburger. CTA, search and the language
       selector all move into the drawer (see Header.ss → .site-drawer__cta
       / __search / __locale) so the masthead is logo + hamburger only. */
    .site-header__controls .site-header__cta,
    .site-header__controls .site-search-trigger,
    .site-header__controls .site-locale { display: none; }
    /* With those three gone, the frosted chrome pill wrapped a lone
       hamburger and read as an orphaned lozenge. Strip the pill on mobile
       so the hamburger stands alone as a clean icon on the transparent
       header, inheriting the header ink instead of the pill's forced white
       (dark over content; white over a hero via the not(.is-scrolled)
       rules). */
    .site-header__controls {
        background: none;
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        border: 0;
        box-shadow: none;
        padding: 0;
        color: inherit;
    }
    .site-header__controls .site-menu-trigger { color: inherit; }
    /* Smaller brand plate so the logo doesn't crowd the right-side
       chrome pill on narrow viewports. */
    .site-header__brand { height: calc(var(--site-header-h, 73px) * 1.1); }
    /* Auto-hide the whole masthead on mobile — industry-standard
       "Headroom" pattern. header-scroll.js already toggles
       .site-header--folded on scroll direction (down past the masthead
       hides it, any upward scroll reveals it, always open near the top
       via REVEAL_AT with an ±8px direction deadband to kill jitter), so
       this is purely the CSS payoff: slide the bar up off-screen.
       The masthead moves as ONE rigid unit — brand plate, logo and chrome
       all travel together at the same speed. -120% (not -100%) because the
       brand plate is 1.1× the header height (position:absolute top:0, so it
       hangs ~10% below the bar); the extra 20% clears that overhang — and
       the logo nested inside it — instead of leaving a navy sliver peeking.
       .page-subnav is display:none on mobile, so nothing sticks below the
       header to leave a gap. */
    .site-header { transition: transform 280ms var(--ease); will-change: transform; }
    .site-header--folded { transform: translateY(-120%); }
    .site-header--folded .site-header__brand { transform: none; }
}

/* ---------- Off-canvas drawer ---------------------------------------
   Hosts the full navigation. Right-side panel (max 480px) over a
   translucent dark backdrop; full-bleed below 720px. Closed by ESC,
   backdrop click, or close button. JS adds .is-open / removes hidden. */
.site-drawer {
    position: fixed;
    inset: 0;
    z-index: 100;
}
.site-drawer[hidden] { display: none; }
.site-drawer__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(15, 14, 10, 0.55);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    opacity: 0;
    transition: opacity 280ms ease;
}
.site-drawer.is-open .site-drawer__backdrop { opacity: 1; }
.site-drawer__panel {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: min(480px, 100%);
    background: var(--bg);
    color: var(--ink);
    padding: var(--s-7) var(--s-7) calc(var(--s-9) + env(safe-area-inset-bottom, 0px));
    overflow-y: auto;
    transform: translateX(100%);
    transition: transform 320ms cubic-bezier(.22,.61,.36,1);
    box-shadow: var(--shadow-drawer);
}
.site-drawer.is-open .site-drawer__panel { transform: translateX(0); }
.site-drawer__top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-5);
    margin-bottom: var(--s-7);
}
.site-drawer__close {
    appearance: none;
    background: transparent;
    border: 0;
    font-size: 32px;
    line-height: 1;
    padding: 4px 10px;
    margin: 0 0 0 -10px;
    color: var(--ink);
    cursor: pointer;
}
.site-drawer__content {
    display: flex;
    flex-direction: column;
    gap: var(--s-8);
}
/* CTA inside the drawer top bar — sits opposite the close button at the
   same vertical position. Orange pill matches the header CTA treatment. */
/* Drawer CTA matches the unified espresso primary (was orange --feature,
   which failed WCAG AA white-on-orange at 2.35:1). */
.site-drawer__cta {
    background: var(--accent);
    color: var(--accent-ink);
    border-radius: var(--r-pill);
    padding: 12px 22px;
    font-family: var(--sans);
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
    letter-spacing: 0.02em;
}
.site-drawer__cta:hover,
.site-drawer__cta:focus-visible {
    background: var(--accent-deep);
    color: var(--accent-ink);
}
.site-drawer__nav ul {
    list-style: none;
    padding: 0;
    margin: 0;
}
.site-drawer__nav > ul > li {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    border-top: 1px solid var(--hairline);
}
.site-drawer__nav > ul > li:last-child {
    border-bottom: 1px solid var(--hairline);
}
.site-drawer__nav > ul > li > a {
    display: block;
    padding: var(--s-4) 0;
    font-family: var(--sans);
    font-size: clamp(17px, 2vw, 19px);
    font-weight: 700;
    letter-spacing: -0.005em;
    color: var(--ink);
    text-decoration: none;
    transition: color 150ms ease;
}
.site-drawer__nav > ul > li > a:hover { color: var(--accent); }
.site-drawer__nav > ul > li > a.is-current { color: var(--ink); }
/* Chevron toggle — sits in column 2, only expands the inline children
   list; the parent link still navigates to its overview page. */
.site-drawer__nav-toggle {
    appearance: none;
    background: transparent;
    border: 0;
    padding: var(--s-4) 0 var(--s-4) var(--s-4);
    margin: 0;
    cursor: pointer;
    color: var(--ink-muted);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: color 150ms ease;
}
.site-drawer__nav-toggle:hover,
/* A color-only change is invisible to many low-vision users — give the
   chevron the same 2px ring every other control uses. */
.site-drawer__nav-toggle:focus-visible {
    color: var(--accent);
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.site-drawer__nav-toggle svg { transition: transform 200ms ease; }
.site-drawer__nav > ul > li.is-expanded .site-drawer__nav-toggle svg {
    transform: rotate(180deg);
}
.site-drawer__nav-children {
    grid-column: 1 / -1;
    list-style: none;
    padding: 0;
    margin: 0;
    display: none;
}
.site-drawer__nav > ul > li.is-expanded > .site-drawer__nav-children {
    display: block;
    margin: 0 0 var(--s-3);
}
.site-drawer__nav-grandchildren {
    list-style: none;
    padding: 0;
    margin: var(--s-1) 0 var(--s-2);
}
.site-drawer__nav-children > li,
.site-drawer__nav-grandchildren > li { margin: 0; }

/* Drawer-only utilities — search field (top of content) + language row
   (bottom). They surface ONLY on mobile, where the header is pared back to
   logo + hamburger; the drawer is also the desktop menu, so they default to
   display:none there (the header still carries search + locale ≥721px). */
.site-drawer__search,
.site-drawer__locale { display: none; }

@media (max-width: 720px) {
    .site-drawer__search { display: block; margin: 0; }
    .site-drawer__search-label {
        display: block;
        font-family: var(--sans);
        font-size: 12px;
        font-weight: 600;
        letter-spacing: 0.14em;
        text-transform: uppercase;
        color: var(--ink-muted);
        margin-bottom: var(--s-2);
    }
    .site-drawer__search input[type="search"] {
        display: block;
        width: 100%;
        font-family: var(--sans);
        font-size: 1.1rem;
        padding: var(--s-3) 0;
        background: transparent;
        color: var(--ink);
        border: 0;
        border-bottom: 1px solid var(--hairline);
        border-radius: 0;
    }
    .site-drawer__search input[type="search"]::placeholder { color: var(--ink-muted); }
    .site-drawer__search input[type="search"]:focus-visible {
        outline: none;
        border-bottom-color: var(--accent);
    }

    /* Quiet uppercase row — reads as a set-once preference, not nav. The
       generous .site-drawer__content gap above already separates it. */
    .site-drawer__locale { display: flex; gap: var(--s-5); }
    .site-drawer__locale-link {
        font-family: var(--sans);
        font-size: 14px;
        letter-spacing: 0.04em;
        text-transform: uppercase;
        color: var(--ink-soft);
        text-decoration: none;
        transition: color 150ms ease;
    }
    .site-drawer__locale-link:hover { color: var(--accent); }
    .site-drawer__locale-link--current { color: var(--ink); font-weight: 600; }
    .site-drawer__locale-link--invalid { opacity: 0.4; pointer-events: none; }
}
.site-drawer__nav-children > li > a {
    display: block;
    padding: var(--s-2) 0 var(--s-2) var(--s-4);
    font-family: var(--sans);
    font-size: 16px;
    color: var(--ink-soft);
    text-decoration: none;
    transition: color 150ms ease;
}
.site-drawer__nav-children > li > a:hover,
.site-drawer__nav-children > li > a.is-current { color: var(--accent); }
.site-drawer__nav-grandchildren > li > a {
    display: block;
    padding: var(--s-1) 0 var(--s-1) var(--s-8);
    font-family: var(--sans);
    font-size: 14px;
    color: var(--ink-muted);
    text-decoration: none;
    transition: color 150ms ease;
}
.site-drawer__nav-grandchildren > li > a:hover,
.site-drawer__nav-grandchildren > li > a.is-current { color: var(--accent); }
/* Body scroll lock while drawer is open */
body.is-drawer-open { overflow: hidden; }

/* ---------- Page sub-nav (inline, after hero) -----------------------
   Renders directly under the hero on pages with a section context.
   Sticky on scroll so the page-level nav stays in reach. Distinct from
   the global header sub-nav (which lives in the site-header rails).
   Hidden on mobile — drawer handles it. */
.page-subnav {
    /* Inline sticky sibling-nav. Surfaces the section's peer pages
       (e.g. the Mallorca disciplines: Incentives, Meetings, Team
       Building…) so you can move between them without digging into the
       hamburger drawer. Hidden on mobile (<720px) — the drawer covers
       that case. */
    display: block;
    position: sticky;
    /* Sticks right below the site-header. The actual rendered header
       height is published as --site-header-h by js/header-scroll.js
       (ResizeObserver-tracked), so this stays correct if the header's
       padding/font/border ever changes. Fallback used pre-JS / SSR. */
    top: var(--site-header-h, 73px);
    z-index: 15;
    background: var(--bg);
    border-bottom: 1px solid var(--hairline);
}
.page-subnav__inner {
    max-width: var(--maxw);
    margin: 0 auto;
    /* Left padding clears the brand plate, which hangs into the
       subnav row by ~37px (1.5x header height). gutter (brand left
       offset) + --brand-w (published live by header-scroll.js) +
       small gap keeps the first link past the brand right edge. */
    padding: var(--s-5) var(--gutter) var(--s-3) calc(var(--gutter) + var(--brand-w, 220px) + var(--s-5));
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--s-5);
    font-family: var(--sans);
    font-size: 0.9rem;
}
.page-subnav__label {
    font-family: var(--sans);
    font-size: 0.9rem;
    font-weight: 500;
    color: var(--ink);
    letter-spacing: 0.01em;
}
.page-subnav__label::after {
    content: " ·";
    color: var(--ink-muted);
    margin-left: 4px;
}
/* Parent label is a link back UP to the section root (destination
   landing / pillar page). Inherits the label's weight + colour so it
   reads as the section name, not a button. Underline only on hover —
   restrained back affordance, no icon clutter. */
.page-subnav__label a {
    color: inherit;
    text-decoration: none;
    transition: color 120ms ease;
}
.page-subnav__label a:hover,
.page-subnav__label a:focus-visible {
    color: var(--accent);
    text-decoration: underline;
    text-underline-offset: 3px;
}
.page-subnav__links {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-5);
}
.page-subnav__links li,
.page-subnav__links a {
    font-family: var(--sans);
}
.page-subnav__links a {
    color: var(--ink-soft);
    text-decoration: none;
    font-size: 0.9rem;
    letter-spacing: 0.03em;
    transition: color 120ms ease;
}
.page-subnav__links a:hover,
.page-subnav__links a.is-current { color: var(--accent); }
.page-subnav__links a.is-current {
    border-bottom: 1px solid var(--accent);
    padding-bottom: 2px;
}
@media (max-width: 720px) {
    .page-subnav { display: none; }
}

/* Inline variant — sits BELOW the hero as a solid sticky bar (vs the
   top-placed bar that floats over the hero). It lives inside the
   maxw-constrained article, so it breaks out to span the viewport while
   __inner re-applies the rail; and it drops the brand-plate offset since
   it's no longer beside the masthead. Solid skin always — the over-hero
   transparent treatment below is scoped to the top bar only. */
.page-subnav--inline {
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    /* Always hold a breathing band below the bar so the first section
       never butts against it. The first block can't be relied on for
       this: most carry the universal s-11 section padding, but its
       eyebrow is absolutely anchored to the section top (~s-4) and a
       `.has-section-rule` block zeroes its top padding outright — both
       leave the heading/eyebrow crowding the bar (e.g. "Ibiza in Zahlen"
       on the DMC pages). The margin lives at the bar's flow position, so
       sticky docking is unaffected — content still scrolls flush under
       the stuck bar. */
    margin-bottom: var(--s-6);
    /* Bar is full-bleed (so the background sits under the docked header),
       but the hairline belongs to the content rail — drop the full-width
       border and redraw it inside __inner, gutter-inset, below. */
    border-bottom: 0;
}
.page-subnav--inline .page-subnav__inner {
    padding-left: var(--gutter);
    padding-right: var(--gutter);
    position: relative;
}
/* Hairline matched to the content rail (maxw minus gutters), so it lines
   up with the page body and the subnav links above it — not the viewport. */
.page-subnav--inline .page-subnav__inner::after {
    content: "";
    position: absolute;
    left: var(--gutter);
    right: var(--gutter);
    bottom: 0;
    border-bottom: 1px solid var(--hairline);
}

/* ---------- Sub-nav ------------------------------------------------ */

.site-subnav {
    background: transparent;
    border-bottom: none;
}

/* Mega-menu hover dropdowns on Global nav items.
   Each dropdown spans the full subnav width (anchored to .site-subnav)
   and uses an auto-fill grid so children flow into multiple columns
   when there are more than ~4 items. Pure CSS reveal via hover /
   focus-within. Mobile uses the off-canvas drawer (this whole bar is
   display:none below 720px). */
.site-subnav--combined {
    position: relative;
}
/* Inline variant — dropdown anchors to the sticky .site-header so it
   spans the full row width below the header instead of the narrow
   nav width. */
.site-subnav--inline { position: static; }
/* Hover bridge: each <li> carries the bottom padding that used to live
   on the subnav's __inner. This extends the <li>:hover hit-area down to
   the very bottom of the subnav, eliminating the dead zone between the
   link text and the dropdown. Visually identical (padding has no bg). */
.site-subnav__links--global > li {
    padding-bottom: var(--s-4);
}
.site-subnav__links--global > li.has-dropdown > a::after {
    content: "";
    display: inline-block;
    width: 6px;
    height: 6px;
    border-right: 1px solid currentColor;
    border-bottom: 1px solid currentColor;
    transform: translateY(-2px) rotate(45deg);
    margin-left: 6px;
    opacity: 0.55;
    transition: transform 200ms ease, opacity 200ms ease;
}
.site-subnav__links--global > li.has-dropdown:hover > a::after,
.site-subnav__links--global > li.has-dropdown:focus-within > a::after {
    transform: translateY(0) rotate(225deg);
    opacity: 1;
}
.site-subnav__dropdown {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: #ffffff;
    border-top: 1px solid var(--hairline);
    border-bottom: 1px solid var(--hairline);
    box-shadow: var(--shadow-3);
    padding: var(--s-7) var(--gutter) var(--s-8);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: opacity 220ms ease, transform 220ms ease, visibility 0ms 220ms;
    z-index: 30;
}
.site-subnav__links--global > li.has-dropdown:hover > .site-subnav__dropdown,
.site-subnav__links--global > li.has-dropdown:focus-within > .site-subnav__dropdown,
.site-subnav__dropdown:hover {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    transition: opacity 220ms ease, transform 220ms ease, visibility 0ms 0ms;
}
.site-subnav__dropdown-eyebrow {
    margin: 0 0 var(--s-5);
    font-family: var(--sans);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ink-muted);
}
.site-subnav__dropdown-grid {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: var(--s-6) var(--s-5);
}
.site-subnav__dropdown a {
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
    text-decoration: none;
    color: var(--ink);
    transition: color 150ms ease;
}
/* Thumb: 16:10 frame with FocusFill image inside. Image inherits size
   from the FocusFill output; we just constrain the wrapper aspect. */
.site-subnav__dropdown-thumb {
    display: block;
    width: 100%;
    aspect-ratio: 16 / 10;
    background: var(--bg-soft);
    overflow: hidden;
    border-radius: var(--r-sm);
    transition: transform 350ms cubic-bezier(.22,.61,.36,1);
}
.site-subnav__dropdown-thumb img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform var(--card-img-hover-duration) var(--card-img-hover-easing);
}
.site-subnav__dropdown-label {
    font-family: var(--sans);
    font-size: 0.78rem;
    letter-spacing: 0.03em;
}
.site-subnav__dropdown a:hover { color: var(--accent); }
.site-subnav__dropdown a:hover .site-subnav__dropdown-thumb img {
    transform: scale(var(--card-img-hover-scale));
}
.site-subnav__links {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-5);
}
.site-subnav__links a {
    color: var(--ink-soft);
    text-decoration: none;
    font-size: 0.9rem;
    letter-spacing: 0.03em;
}
.site-subnav__links a:hover,
.site-subnav__links a.is-current {
    color: var(--accent);
}
.site-subnav__links a.is-current {
    border-bottom: 1px solid var(--accent);
    padding-bottom: 2px;
}

/* ---------- Breadcrumb -------------------------------------------- */

.breadcrumb {
    max-width: var(--maxw);
    margin: 0 auto;
    padding: var(--s-5) var(--gutter) 0;
    font-size: 0.8rem;
    color: var(--ink-soft);
}
.breadcrumb ol {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2);
}
.breadcrumb li + li::before {
    content: "/";
    margin-right: var(--s-2);
    color: var(--hairline);
}
.breadcrumb a {
    color: var(--ink-soft);
    text-decoration: none;
}
.breadcrumb a:hover { color: var(--accent); }
.breadcrumb li[aria-current="page"] span { color: var(--ink); }

/* Full-bleed layouts (Home / DMC) hide the breadcrumb — their heroes
   sit directly below the header rail by design. */
.t-App\\PageType\\HomePage .breadcrumb,
.t-App\\PageType\\DMCPage .breadcrumb { display: none; }

/* ---------- Page layout -------------------------------------------- */

main {
    max-width: var(--maxw);
    margin: 0 auto;
    padding: var(--s-9) var(--gutter) var(--s-10);
}

.page__head {
    margin-bottom: var(--s-8);
    max-width: var(--measure);
}

.page__title {
    font-size: var(--t-display);
    line-height: 1.05;
    margin: 0 0 var(--s-5);
}

/* ---------- Lead typography (single source of truth) ----------------
   Two tiers, both sans. Contrast vs body is carried by size + weight +
   line-height, not family/style — the serif-italic lede was readable
   but felt like a second voice arguing with the headline above it.

   .lead-editorial — sans 300 (Light), full ink, generous size. Default
   lead voice for page subtitles, ledes, taglines, prose .lead. Sister
   classes (.page__subtitle, .article__tagline, .why-us__lead, etc.)
   compose onto this via the grouped selectors so existing templates
   do not need markup changes. The 300 weight creates the editorial
   triad: bold 700 headline → light 300 lede → regular 400 body.
   Mirrors the <em>-in-headline rule (also 300 against 700). */
.lead-editorial,
.page__subtitle,
.page__lead,
.contact-page__lead,
.service__lead,
.why-us__lead,
.sister-brands__lead,
.icon-grid-block__lead,
.newsletter-block__lead,
.product__subtitle,
.product__tagline,
.article__tagline,
.prose .lead,
.prose p.lead,
.prose .copy .lead,
.lead {
    font-family: var(--sans);
    font-weight: 300;
    font-style: normal;
    font-size: clamp(1.2rem, 1.9vw, 1.35rem);
    line-height: 1.4;
    letter-spacing: 0;
    color: var(--ink);
    text-wrap: balance;
    margin: 0 0 var(--s-6);
}

/* .page__subtitle sits directly under the page__head H1 and is the only
   lead surface designed to be pulled tight against the heading above.
   Other lead surfaces (taglines, ledes in body context) keep neutral
   top spacing from the shared rule. */
.page__subtitle {
    margin-top: calc(var(--s-5) * -1);
}

.key-facts {
    list-style: none;
    padding: 0;
    margin: var(--s-6) 0 var(--s-8);
    max-width: var(--measure);
    display: flex;
    flex-direction: column;
    gap: var(--s-4);
}
.key-facts__item {
    display: flex;
    align-items: flex-start;
    gap: var(--s-5);
    font-size: 1.05rem;
    line-height: 1.45;
    color: var(--ink);
}
.key-facts__tick {
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--accent);
    margin-top: 0.2em;
}
.key-facts__tick svg { display: block; }
.key-facts__value {
    flex: 1 1 auto;
}

.page__byline {
    font-size: 0.9rem;
    color: var(--ink-soft);
    margin: var(--s-2) 0 var(--s-5);
}

.page__body,
.prose {
    max-width: var(--measure);
    /* The reading/prose tier. Was inherited silently from body (17px/1.55);
       made explicit so a future body-size change can't move every article. */
    font-size: var(--t-body-lg);
    line-height: var(--lh-body);
}
.prose h2 {
    font-family: var(--sans);
    font-size: var(--t-h2);
    margin-top: var(--s-8);
}
.prose h3 {
    font-family: var(--sans);
    font-size: var(--t-h3);
    margin-top: var(--s-6);
}
.prose p { margin: 0 0 var(--s-5); }
.prose ul, .prose ol { padding-left: var(--s-5); margin: 0 0 var(--s-5); }
.prose li { margin: var(--s-2) 0; }
/* Imported rich text can force horizontal scroll on phones two ways:
   a <pre> (e.g. the legal pages' <pre class="AHinweis">) whose default
   white-space:pre never wraps — an ordinary paragraph pasted into one ran
   ~2400px wide — and bare long URLs/words that don't break. Wrap both;
   covers ElementContent and editorial prose. */
.prose,
.content-element__content {
    overflow-wrap: break-word;
}
.prose pre,
.content-element__content pre {
    white-space: pre-wrap;
    overflow-wrap: break-word;
    word-break: break-word;
}

/* Content block as a card — opt-in via the CMS "Style variation → Card"
   dropdown (config: ElementContent.styles in elemental-canvas.yml). The
   block then carries `.card` and reads as a distinct panel rather than
   running copy. Primary use: the "So arbeiten wir" beat on a ServicePage
   ("was wir tun" subpage). The surface treatment is the shared PANEL
   canon at the top of this file — no per-component declarations here. */

/* Legacy SS3 elemental-block wrappers that arrive inside Page.Content.
   The legacy site rendered these as 2-col grids via heavy nested div
   markup (block-colum/block-column with .copy children). lxp6 just lets
   them flow as a single editorial column — `display: contents` makes
   the wrappers transparent to layout so the prose typography reaches
   the inner h2 / p / ul / li directly. */
.prose .element[class*="Block_"],
.prose .block-colum,
.prose .block-column,
.prose .copy,
.prose .copy .Text,
.prose .copy .Ohne {
    display: contents;
}
.prose .no-margin-top { margin-top: 0; }

/* ---------- Elemental blocks (App\Element\*) -----------------------
   ===================================================================
   THE CONTAINER CONTRACT (general site pattern)
   ===================================================================

   Default: <main> owns the rail. It applies `max-width: var(--maxw)`
   and horizontal `padding: var(--gutter)`. Everything inside —
   including .page__elements and every elemental block — lives in
   that bounded content box. Blocks must NOT redeclare maxw or gutter
   themselves; doing so produces a one-gutter double-indent that
   silently breaks alignment with sibling grids on the same page (e.g.
   .team-grid → text block offset right by ~48px at desktop).

   Exception (THREE pages only): HomePage, DMCPage, ContactPage strip
   <main> via `.t-App\PageType\<X> main { max-width: none; padding: 0 }`
   so heroes can run viewport-wide. On those pages — and ONLY those
   pages — each block must self-bound (own maxw + auto margins + own
   gutter padding). Anywhere else, self-bound = double-indent bug.

   Rule of thumb when writing a new block / debugging alignment:
     • Inside .page__elements?  →  Stay BARE by default.
     • Used on a stripped-main page?  →  Restore bounds inside a
       page-scoped selector (`.t-App\PageType\HomePage .my-block { ... }`)
     • Need a 12-col rail for partial-width?  →  Use `.element.is-partial`
       at line ~1118; it already follows this contract.

   Fixed in line with this contract:
     – .element.is-partial   (this file, ~1118)
     – .element-textext      (this file, ~1258)
     – .element-imgtext      (this file, ~1258)

   Known older blocks that still self-bound (work today only because
   they live exclusively on stripped-main pages — homepage chrome).
   If reused on a bounded-main page they'll need the same conversion:
     .home-hero, .home-destinations, .home-section, .why-us, .affiliation,
     .case-rail-wrap, .sister-brands, .editorial-intro, .key-figures,
     .trusted-by-row, .home-rfp-cta, .rfp, .faq, .page-slides,
     .case-study--editorial, .contact-page__head/__body, .article,
     .newsletter-block, .article-holder__head.
   =================================================================== */
.page__elements { /* intentionally bare per the contract above */ }

/* ---- Page-level partial-width blocks ------------------------------
   Activates per-block on any `.element.is-partial` (marker class set
   by ElementPageLayoutExtension when LayoutSpan != 12 or LayoutOffset
   != 0). Sibling full-width blocks are NOT affected — they keep their
   existing internal layout, gutters, and full-bleed behaviour. The
   partial block lives inside a maxw-constrained rail and positions
   its inner content on a 12-column sub-grid via inline custom
   properties (`--layout-span` / `--layout-offset`).

   This deliberately gives up automatic side-by-side pairing of two
   partial siblings — each partial sits on its own row. The trade-off
   buys us total non-interference with existing full-width block
   styling. When real editorial demand surfaces for paired rows,
   revisit with a proper grid container + explicit gutter tracks. */
.element.is-partial {
    box-sizing: border-box;
}
/* Self-bound only on pages that strip <main> (HomePage / DMCPage /
   ContactPage). On every other page <main> already provides maxw +
   gutter, so adding them here would double-indent the inner content
   by one gutter and break alignment with sibling grids (e.g. team-grid). */
.t-App\\PageType\\HomePage .element.is-partial,
.t-HomePage .element.is-partial,
.t-App\\PageType\\DMCPage .element.is-partial,
.t-App\\PageType\\ContactPage .element.is-partial {
    max-width: var(--maxw);
    margin-left: auto;
    margin-right: auto;
    padding-left: var(--gutter);
    padding-right: var(--gutter);
}
.element.is-partial > * {
    /* --col-w wird HIER definiert (nicht auf .is-partial selbst), damit
       100% die Content-Box des Wrappers referenziert — das ist die
       tatsächliche verfügbare Breite. Vorher rechnete die Formel mit
       --maxw (fest 1440px), wodurch bei Viewports < 1440px der Inhalt
       um die Differenz nach rechts aus dem Grid lief. */
    --col-w: calc((100% - 11 * var(--gap-m, var(--s-6))) / 12);
    box-sizing: border-box;
    max-width: none;
    padding-left: 0;
    padding-right: 0;
    margin-left: calc(var(--layout-offset, 0) * (var(--col-w) + var(--gap-m, var(--s-6))));
    margin-right: 0;
    width: calc(var(--layout-span, 12) * var(--col-w) + (var(--layout-span, 12) - 1) * var(--gap-m, var(--s-6)));
}
/* Mobile: partial blocks stack full-width — column math on phones
   looks broken regardless of design taste. */
@media (max-width: 800px) {
    .element.is-partial > * {
        width: 100%;
        margin-left: 0;
    }
}

/* ---- Side-by-side pair: Affiliation + Testimonial -----------------
   On the homepage the TOURVEST announcement and the testimonial slider
   sit as one row instead of two beats. Four-column grid: outer 1fr
   spacers absorb extra viewport so the pair caps at `--maxw` centered
   (matching the main-content width), inner cells host the two blocks.
   Other elements span 1 / -1 (full-bleed) and keep their own widths.
   Stacks vertically on narrow viewports. */
@media (min-width: 900px) {
    .page__elements:has(> .app__element__elementaffiliation + .app__element__elementtestimonial) {
        display: grid;
        grid-template-columns:
            1fr
            minmax(0, calc((var(--maxw) - var(--s-6)) / 2))
            minmax(0, calc((var(--maxw) - var(--s-6)) / 2))
            1fr;
        column-gap: var(--s-6);
        align-items: start;
    }
    .page__elements:has(> .app__element__elementaffiliation + .app__element__elementtestimonial) > .element {
        grid-column: 1 / -1;
    }
    /* :has(> A + B) has specificity (0,2,0) because both class-selectors
       inside the compound count — so the half-cell rules need an extra
       class qualifier (`.element.app__...`) to land at (0,4,0), matching
       the full-width rule above. */
    .page__elements > .element.app__element__elementaffiliation:has(+ .app__element__elementtestimonial) {
        grid-column: 2 / 3;
    }
    .page__elements > .element.app__element__elementaffiliation + .element.app__element__elementtestimonial {
        grid-column: 3 / 4;
    }
    /* The paired blocks share a row — drop their full-width centering so
       they fill the half-cell instead. */
    .page__elements > .element.app__element__elementaffiliation:has(+ .app__element__elementtestimonial) .affiliation {
        max-width: none;
    }
}

/* Grid layout container (App\Element\ElementGridList).
   `--cols` and `--gap` come from inline style set by the template;
   defaults match the design-system tokens. Children render as cells
   with `grid-column: span N` (or `1 / -1` when GridSpan is 0). */
.lxp-grid {
    display: grid;
    grid-template-columns: repeat(var(--cols, 12), minmax(0, 1fr));
    gap: var(--gap, var(--gap-l));
    margin: var(--s-9) 0;
}
.lxp-grid__cell { min-width: 0; }
@media (max-width: 720px) {
    /* Collapse to a single column on narrow viewports — declared spans
       become noise on phones. */
    .lxp-grid { grid-template-columns: 1fr; }
    .lxp-grid__cell { grid-column: 1 / -1 !important; }
}

/* Split mode (App\Element\ElementGridList.Split). The container fixes a
   two-column ratio via the inline `--split` custom property (e.g.
   "1fr 2fr"); children auto-flow into the two tracks by source order and
   their own GridSpan is ignored. `align-items: start` keeps a short
   column (e.g. key facts) from stretching beside a tall one (body copy).
   The mobile override is declared AFTER the desktop rule so it wins over
   it on narrow viewports. */
.lxp-grid--split {
    grid-template-columns: var(--split, 1fr 2fr);
    align-items: start;
}
@media (max-width: 720px) {
    .lxp-grid--split { grid-template-columns: 1fr; }
}
/* Key facts in a grid cell sit flush with the top of their column —
   drop the standalone block's top margin (it keeps it below a hero). */
.lxp-grid__cell .key-facts { margin-top: 0; }

/* Icon grid block (App\Element\ElementIconGrid). N-up grid of
   centered icon + title + description cards. Icon is whatever the
   editor uploads (SVG preferred). Auto-collapses to single column
   on phones. */
.icon-grid-block { margin: var(--s-9) 0; }
.icon-grid-block__head { text-align: center; margin: 0 auto var(--s-7); }
.icon-grid-block__title { margin: 0 0 var(--s-3); }
.icon-grid-block__lead { color: var(--ink-2, var(--ink)); margin-left: auto; margin-right: auto; }

.icon-grid {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(var(--cols, 3), minmax(0, 1fr));
    gap: var(--s-9) var(--s-7);
    text-align: center;
}
.icon-grid__card {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 0 var(--s-3);
}
/* Icons render as a CSS mask of the SVG so the colour is set via
   `background-color`, not by whatever fill the SVG ships with. The
   block sets `--icon-color` (defaulting to var(--accent)); each card
   sets `--icon-url` inline from the IconCard's Icon URL. */
.icon-grid__icon {
    display: block;
    margin: 0 0 var(--s-4);
    width: 80px;
    height: 80px;
    background-color: var(--icon-color, var(--accent));
    -webkit-mask: var(--icon-url) center / contain no-repeat;
            mask: var(--icon-url) center / contain no-repeat;
}
.icon-grid__title {
    font-family: var(--sans);
    font-size: var(--t-h4);
    font-weight: 600;
    margin: 0 0 var(--s-2);
    /* Inherit body ink — the icon already carries the accent. If you
       want titles tinted to match the icons (legacy LXP behaviour),
       set `color: var(--icon-color, var(--accent));` on this rule. */
}
.icon-grid__desc {
    font-size: 0.95rem;
    line-height: 1.5;
    color: var(--ink-2, var(--ink));
    margin: 0;
}
@media (max-width: 720px) {
    /* 2-up on phones/narrow tablets instead of a single-column stack —
       compact icon+title+desc cards pair cleanly and halve the section
       height on mobile (was 1-col pre-2026-06-05). */
    .icon-grid { grid-template-columns: 1fr 1fr; gap: var(--s-7) var(--s-5); }
    .icon-grid__desc { max-width: none; }
    .icon-grid__icon { width: 56px; height: 56px; }
    /* Defensive overflow guard: flex card child defaults to min-width:auto,
       so a long unbroken title could push the 2-up track past the viewport.
       overflow-wrap breaks any over-long word so it can never out-size the
       track. No visual change at normal content. (2026-06-05) */
    .icon-grid__card { min-width: 0; }
    .icon-grid__title,
    .icon-grid__desc { overflow-wrap: anywhere; }
}
@media (max-width: 380px) {
    /* Genuinely tiny screens fall back to a single column so the icon
       cards don't get crushed. */
    .icon-grid { grid-template-columns: 1fr; }
}

/* Bare inside .page__elements per the contract at line ~1092:
   <main> already applies max-width and gutter. Adding either here
   would double-indent the block relative to siblings (e.g. .team-grid)
   that correctly use main's bounds only. */
.element-textext,
.element-imgtext {
    margin: var(--s-9) 0;
}
/* Wrapping selector adds an extra class to win specificity against
   `.prose h2` (the headline now sits inside the .prose lead column).
   Without this, prose's `margin-top: var(--s-8)` would push the
   headline down — we want it flush at the top of the column. */
.element-textext .element-textext__headline,
.element-imgtext .element-imgtext__headline {
    font-size: var(--t-h2);
    line-height: 1.15;
    margin: 0 0 var(--s-5);
    max-width: 28ch;
}
.element-textext__cols {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--s-6);
    align-items: start;
}
/* Body track is capped to the body's own `.prose` measure (64ch) plus one
   gutter, instead of a free-growing 1.4fr. The old fractional track was
   wider than the 64ch body cap, so every block left a permanent ~148px
   void on the right edge (the "unfinished" look). `minmax(0, …)` lets the
   body track shrink on narrow desktop widths without overflow.
   The left lead column carries a `min(100%, 30ch)` floor so it can't be
   crushed by the body's near-fixed track in the 820–1100px band (without
   the floor a pure 1fr collapsed to ~130px). On wide screens the 1fr grows
   the lead past the floor; for the body-only variant the single grid item
   still fills the row; padded/bg variants keep their own padding rules. */
@media (min-width: 820px) {
    .element-textext__cols {
        grid-template-columns: minmax(min(100%, 30ch), 1fr) minmax(0, calc(var(--measure) + var(--s-8)));
        gap: var(--s-8);
    }
}
/* Padding only when a column has a background colour. The `--padded`
   class is added by the template when LeftBgColor / BodyBgColor is
   non-empty; without a bg, columns stay flush against the page grid. */
.element-textext__left--padded,
.element-textext__body--padded {
    padding: var(--s-7);
}
@media (min-width: 820px) {
    .element-textext__left--padded,
    .element-textext__body--padded {
        padding: var(--s-8);
    }
}
/* Flip ink when a dark bg token is picked (Deep navy / Accent). Mirrors
   .section--deep so prose, headlines, and hairlines stay readable. */
.element-textext__left--inverse,
.element-textext__body--inverse {
    --ink:           #f4f1ea;
    --ink-soft:      rgba(244, 241, 234, 0.72);
    --ink-muted:     rgba(244, 241, 234, 0.55);
    --hairline:      rgba(244, 241, 234, 0.18);
    --hairline-soft: rgba(244, 241, 234, 0.08);
    color:           var(--ink);
    font-weight:     400;   /* light-on-dark: stay regular (base sans is 300) */
}

.element-imgtext {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--s-6);
    align-items: start;
}
@media (min-width: 820px) {
    .element-imgtext { grid-template-columns: 1fr 1fr; gap: var(--s-8); }
}
.element-imgtext__figure { margin: 0; }
.element-imgtext__figure img { width: 100%; height: auto; display: block; }

/* ---------- Team member bio (single page) -------------------------- */

.team-bio__back,
.article__back {
    margin: 0 0 var(--s-6);
    font-family: var(--sans);
    font-size: 0.78rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--ink-soft);
}
.team-bio__back a,
.article__back a {
    color: inherit;
    text-decoration: none;
    border-bottom: 1px solid transparent;
    transition: color 120ms ease, border-color 120ms ease;
}
.team-bio__back a:hover,
.article__back a:hover {
    color: var(--accent);
    border-bottom-color: var(--accent);
}
.team-bio__back span,
.article__back span { margin-right: 0.35em; }

/* Editorial 2-track header: name in left rail column, portrait in
   right body column. Shares 2fr/4fr geometry with .team-bio__grid
   below so vertical rhythm runs name→role and photo→body cleanly. */
.team-bio__head-grid {
    display: grid;
    /* minmax(0, …) so an unbreakable long word in the name cannot
       force the rail track to expand past its 2fr share. */
    grid-template-columns: minmax(0, 2fr) minmax(0, 4fr);
    gap: var(--s-9);
    align-items: start;
    margin: 0 0 var(--s-9);
}
@media (max-width: 860px) {
    .team-bio__head-grid {
        grid-template-columns: 1fr;
        gap: var(--s-7);
    }
}

.team-bio__head {
    grid-column: 1;
    margin: 0;
}
.team-bio__name {
    font-size: var(--t-display);
    line-height: 1.05;
    margin: 0;
    overflow-wrap: anywhere;
}

.team-bio__head-grid .team-bio__banner {
    grid-column: 2;
    margin: 0;
}
@media (max-width: 860px) {
    .team-bio__head-grid .team-bio__banner { grid-column: 1; }
}
.team-bio__banner img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 9;
    object-fit: cover;
}

/* Rail + body share the banner-grid's column geometry (2fr 4fr) so
   the body's leading edge aligns with the photo's leading edge above. */
.team-bio__grid {
    display: grid;
    grid-template-columns: 2fr 4fr;
    gap: var(--s-9);
    align-items: start;
}
@media (max-width: 860px) {
    .team-bio__grid {
        grid-template-columns: 1fr;
        gap: var(--s-7);
    }
}

.team-bio__rail {
    position: sticky;
    top: var(--s-9);
}
@media (max-width: 860px) {
    .team-bio__rail { position: static; }
}

.team-bio__role {
    font-family: var(--serif);
    font-weight: 400;
    font-style: italic;
    font-size: clamp(1.15rem, 1.6vw, 1.4rem);
    line-height: 1.3;
    color: var(--ink-soft);
    margin: var(--s-4) 0 0;
}

.team-bio__contact {
    margin: 0;
    padding-top: var(--s-5);
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--s-3) var(--s-5);
}
.team-bio__contact dt {
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--ink-soft);
    align-self: center;
}
.team-bio__contact dd { margin: 0; }
.team-bio__contact a {
    color: var(--ink);
    text-decoration: none;
    border-bottom: 1px solid var(--hairline);
    transition: border-color 120ms ease, color 120ms ease;
}
.team-bio__contact a:hover {
    color: var(--accent);
    border-bottom-color: var(--accent);
}

.team-bio__body { max-width: var(--measure); }
.team-bio__body .page__elements > * + * { margin-top: var(--s-7); }

/* Prev/next layout via Bootstrap .row + .col-sm-6 on the children.
   Spans full main width (lives outside team-bio__grid). Gutter overridden
   to match editorial spacing; y-gutter kicks in below sm when cols stack. */
.team-bio__nav {
    margin: var(--s-9) 0 0;
    padding-top: var(--s-6);
    border-top: var(--rail-soft);
    --bs-gutter-x: var(--s-6);
    --bs-gutter-y: var(--s-5);
}
.team-bio__nav-link {
    display: flex;
    flex-direction: column;
    gap: var(--s-2);
    text-decoration: none;
    color: inherit;
}
/* Right-align only when prev/next sit side-by-side (sm and up).
   Below sm they stack and read left-aligned. */
@media (min-width: 576px) {
    .team-bio__nav-link--next { text-align: right; }
}
.team-bio__nav-label {
    font-family: var(--sans);
    font-size: 0.72rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ink-soft);
}
.team-bio__nav-title {
    font-family: var(--serif);
    font-style: italic;
    font-size: 1.1rem;
    line-height: 1.3;
    color: var(--ink);
}
/* ---------- Product detail — typography + facts -------------------- */

/* Section split: typographic primitives + facts list live here; the
   editorial grid (Bootstrap rail, row rhythm) is owned by the
   "Product detail (editorial layout)" block lower in this file. */

.product__back {
    margin: 0 0 var(--s-5);
    font-size: 0.9rem;
    letter-spacing: 0.02em;
}
.product__back a {
    color: var(--ink-soft);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    padding-bottom: 2px;
    transition: color 150ms ease, border-color 150ms ease;
}
.product__back a:hover {
    color: var(--ink);
    border-bottom-color: var(--accent);
}
.product__title {
    font-family: var(--sans);
    font-weight: 700;
    font-size: var(--t-hero);
    line-height: 1.05;
    margin: 0 0 var(--s-5);
    letter-spacing: -0.015em;
    max-width: 28ch;
    text-wrap: balance;
}
.product__hero img {
    width: 100%;
    height: auto;
    aspect-ratio: 16/9;
    object-fit: cover;
    display: block;
}

.responsibility {
    list-style: none;
    padding: 0 0 var(--s-6);
    margin: 0 0 var(--s-6);
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--s-5) var(--s-6);
    border-bottom: 1px solid var(--hairline);
}
.responsibility__item {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--s-2);
}
.responsibility__icon {
    width: 72px;
    height: 72px;
    display: block;
}
.responsibility__label {
    font-size: 0.78rem;
    line-height: 1.25;
    letter-spacing: 0.02em;
    color: var(--ink-soft);
    max-width: 100%;
    margin-top: var(--s-2);
}

.product-facts {
    list-style: none;
    padding: 0;
    margin: 0 0 var(--s-6);
    display: flex;
    flex-direction: column;
    gap: var(--s-5);
    padding-bottom: var(--s-6);
    border-bottom: 1px solid var(--hairline);
}
.product-facts__item {
    display: flex;
    align-items: flex-start;
    gap: var(--s-5);
    font-size: 1rem;
    line-height: 1.4;
    color: var(--ink);
}
.product-facts__icon {
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--accent);
    margin-top: 0.15em;
}
.product-facts__icon svg { display: block; }
.product-facts__value { flex: 1 1 auto; }

.product__location {
    margin: 0;
    padding-top: var(--s-5);
    font-size: 0.9rem;
}
.product__location-label {
    color: var(--ink-soft);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-size: 0.75rem;
    margin-right: var(--s-2);
}
.product__location-value { color: var(--ink); }

/* ---------- Page-level slideshow ---------------------------------- */

/* Cross-fading hero used on every non-home page via <% include PageSlides %>.
   Matches the homepage hero keyframes (homeHeroCycle) — first slide is
   eager-loaded with priority hint, rest are low-priority so they load
   without blocking LCP but are present before they fade in. Sits inside
   the content column (no full-bleed escape). */
.page-slides {
    max-width: var(--maxw);
    margin: var(--s-6) auto var(--s-8);
    padding: 0 var(--gutter);
}
/* On the generic Page layout (<article class="page">) the surrounding
   <main> already provides max-width + gutter padding — re-applying them
   here would double-indent the hero versus other sections on the page.
   DMCPage / ArticlePage use different wrappers and zero out main's
   gutter, so they keep .page-slides' own constraints. */
article.page > .page-slides {
    max-width: none;
    margin-inline: 0;
    padding-inline: 0;
}
.page-slides__hero { margin: 0; }
.page-slides__hero img {
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    display: block;
    border-radius: var(--r-lg);
}
.page-slides__hero figcaption {
    font-size: 1rem;
    color: var(--ink-soft);
    margin-top: var(--s-2);
    font-family: var(--serif);
    font-style: italic;
}

.page-slides__stage {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    max-height: 72vh;
    overflow: hidden;
    background: var(--surface);
    border-radius: var(--r-lg);
}
.page-slides__frame {
    position: absolute;
    inset: 0;
    margin: 0;
    opacity: 0;
    animation: homeHeroCycle 60s infinite;
    animation-fill-mode: both;
    animation-timing-function: ease-in-out;
    will-change: opacity, transform;
}
.page-slides__frame:nth-child(1) { animation-delay:  0s; }
.page-slides__frame:nth-child(2) { animation-delay: 12s; }
.page-slides__frame:nth-child(3) { animation-delay: 24s; }
.page-slides__frame:nth-child(4) { animation-delay: 36s; }
.page-slides__frame:nth-child(5) { animation-delay: 48s; }
.page-slides__frame img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* ---------- Product detail slideshow ------------------------------ */

/* Gallery layout is owned by the editorial block — .product__gallery
   uses the same Bootstrap .row > col-12 col-sm-6 col-lg-4 grid as
   .article__gallery, with .article-slide__trigger handling the
   image + zoom-in cursor. Caption styles live in the editorial
   block alongside the row rhythm. */

/* ---------- Product grid (listing) --------------------------------- */

.product-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: var(--s-8) var(--s-6);
    margin-top: var(--s-8);
}

.product-card {
    display: flex;
    flex-direction: column;
    text-decoration: none;
    color: inherit;
}

.product-card__image {
    margin: 0 0 var(--s-4);
    aspect-ratio: 8 / 5;
    overflow: hidden;
    background: var(--hairline-soft);
    transition: opacity 200ms ease;
}
.product-card__image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.product-card__image--empty {
    background: var(--hairline-soft);
    position: relative;
}
.product-card__image--empty::after {
    content: "";
    position: absolute;
    inset: 40% 45% 40% 45%;
    border: 1px solid var(--hairline);
    border-radius: 50%;
}

/* Mobile density — on phones the catalogue collapses to one full-width
   column; a shorter image ratio + tighter row gap keeps it scannable
   instead of an exhausting single-column scroll. (Sticky filter bar is a
   separate change — it needs to reconcile with the fold-on-scroll header.) */
@media (max-width: 540px) {
    .product-card__image { aspect-ratio: 16 / 9; }
    .product-grid { gap: var(--s-6) var(--s-5); }
}

.product-card__body {
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--s-1);
    flex: 1;
}
.product-card__title {
    font-size: var(--t-h3);
    line-height: 1.2;
    margin: 0;
    letter-spacing: -0.005em;
}
.product-card__summary {
    line-height: 1.45;
    color: var(--ink-soft);
    margin: var(--s-1) 0 0;
    flex: 1;
}

.product-card[hidden] { display: none; }

/* Featured-grid variant — homepage version of the product grid. 4-col
   asymmetric: 1st and 6th cards span 2 cols (diagonal weight, two
   featured slots). Same pattern as the services tiles. */
.product-grid--featured {
    grid-template-columns: repeat(4, 1fr);
}
.product-grid--featured > :first-child,
.product-grid--featured > :nth-child(6) {
    grid-column: span 2;
}
@media (max-width: 900px) {
    .product-grid--featured { grid-template-columns: repeat(2, 1fr); }
    .product-grid--featured > :first-child,
    .product-grid--featured > :nth-child(6) { grid-column: span 2; }
}
@media (max-width: 540px) {
    /* Stay 2-up on phones rather than collapsing to a single column —
       keeps the featured-activities strip compact. The two featured
       slots (1st + 6th) span both columns so they still read as hero
       tiles (was 1-col pre-2026-06-05). */
    .product-grid--featured { grid-template-columns: 1fr 1fr; gap: var(--s-5) var(--s-4); }
    .product-grid--featured > :first-child,
    .product-grid--featured > :nth-child(6) { grid-column: span 2; }
    /* Defensive overflow guard: card child defaults to min-width:auto, so a
       wide product image / long title could push a column past the viewport.
       overflow-wrap breaks any over-long word so the title can never out-size
       the column. No visual change at normal content. (2026-06-05) */
    .product-grid--featured .product-card { min-width: 0; }
    .product-grid--featured .product-card__title,
    .product-grid--featured .product-card__summary { overflow-wrap: anywhere; }
}
/* Defensive overflow guard for the base catalogue grid (auto-fill
   minmax(300px,1fr)). On phones the cards collapse to one column; min-width:0
   stops a wide image / long title from forcing the track past the viewport.
   No visual change at normal content. (2026-06-05) */
@media (max-width: 540px) {
    .product-grid .product-card { min-width: 0; }
    .product-grid .product-card__title,
    .product-grid .product-card__summary { overflow-wrap: anywhere; }
}
.product-grid--featured .product-card__body { padding-top: var(--s-1); }

/* ---------- Catalogue Filter Bar -----------------------------------
   Slim chip row above the product grid. Single-select category chips +
   independent "Sustainable only" toggle. Filtering is client-side
   (filter-catalogue.js) — no form submit, no reload. */

.catalogue-filters {
    margin: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-5);
    flex-wrap: wrap;
}
/* When a filter bar is present, the grid's own margin-top provides the
   separation below it — no extra margin needed on the bar itself. */
.catalogue-filters + .product-grid { margin-top: var(--s-6); }

.catalogue-filters__chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2);
    align-items: center;
}

.catalogue-filters__sep {
    display: inline-block;
    width: 1px;
    height: 18px;
    background: var(--hairline);
    margin: 0 var(--s-2);
}

.catalogue-filters__count {
    font-family: var(--sans);
    font-size: 12px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-muted);
    margin: 0;
    font-feature-settings: "tnum";
}

/* Sustainable toggle — distinct from category chips:
   accent-coloured when active to read as a modifier, not a category. */
.chip--toggle .chip__icon {
    width: 14px;
    height: 14px;
    flex: 0 0 auto;
    margin-left: -2px;
}
.chip--toggle[aria-pressed="true"],
.chip--toggle.is-active {
    background: var(--accent-faint);
    color: var(--accent-deep);
    border-color: var(--accent-soft);
}

.product-grid[hidden] { display: none; }

.catalogue-empty {
    padding: var(--s-9) 0;
    text-align: center;
    color: var(--ink-muted);
    font-family: var(--serif);
    font-style: italic;
    font-size: 1.1rem;
}
.catalogue-empty[hidden] { display: none; }

@media (max-width: 600px) {
    .catalogue-filters { gap: var(--s-3); }
    .catalogue-filters__sep { display: none; }
    .catalogue-filters__count { font-size: 11px; }
}

/* ---------- Homepage ---------------------------------------------- */

.home { padding: 0; }

/* Homepage main doesn't want the container padding from generic pages.
   Hero is the first element and starts at y=0 — the site header floats
   over it transparently (see .t-App\\PageType\\HomePage .site-header
   overrides further down). */
.t-HomePage main,
.t-App\\PageType\\HomePage main {
    padding: 0;
    max-width: none;
}

/* 60s cycle = 5 slides × 12s slot. The 7%/27% keyframes are timed so
   each slide is fully opaque from 7% to 27% — but the next slide's
   fade-in (its 0%→7%) starts at this slide's 20% mark. That 7% overlap
   = ~4s of true crossfade where the incoming slide rises from 0→1 over
   the outgoing slide held at 1, sitting on top in DOM order so it
   gradually replaces it. After 27% the outgoing slide fades out behind
   the incoming one, invisibly. A subtle Ken-Burns scale 1.02 → 1.07
   across the visible window adds gentle motion. */
@keyframes homeHeroCycle {
    0%   { opacity: 0; transform: scale(1.02); }
    7%   { opacity: 1; }
    27%  { opacity: 1; }
    34%  { opacity: 0; transform: scale(1.07); }
    100% { opacity: 0; transform: scale(1.02); }
}

/* ElementHero — reusable hero block. Three layouts:
   - .element-hero--fullwidth → full-bleed image with overlay scrim + text
   - .element-hero--boxed     → image fits within site container with overlay text
   - .element-hero--split     → text col + media col, 50/50 above 820px
   Fullwidth and boxed share the same internal structure (stage + plate);
   only the outer container constraint differs.
   Slide cycling uses elementHeroCycle10 (70s = 10 slides × 7s each).
   Distinct from homeHeroCycle (60s/5 slides) used by .home-hero and
   .page-slides — keeps each system independent so changes here don't
   ripple through the other two. */
.element-hero__stage,
.element-hero__media {
    position: relative;
    overflow: hidden;
    /* Dark navy fallback (matches --accent-deep / hero plate) so
       any moment a frame is mid-fade or an image hasn't loaded yet,
       the gap reads as part of the hero rather than a flash of
       white. Per-image element overrides on top still work. */
    background: var(--accent-deep);
}
.element-hero__frame {
    position: absolute;
    inset: 0;
    margin: 0;
    opacity: 0;
    animation: elementHeroCycle10 20s infinite;
    animation-fill-mode: both;
}
.element-hero__frame:nth-child(1)  { animation-delay:  0s; }
.element-hero__frame:nth-child(2)  { animation-delay:  2s; }
.element-hero__frame:nth-child(3)  { animation-delay:  4s; }
.element-hero__frame:nth-child(4)  { animation-delay:  6s; }
.element-hero__frame:nth-child(5)  { animation-delay:  8s; }
.element-hero__frame:nth-child(6)  { animation-delay: 10s; }
.element-hero__frame:nth-child(7)  { animation-delay: 12s; }
.element-hero__frame:nth-child(8)  { animation-delay: 14s; }
.element-hero__frame:nth-child(9)  { animation-delay: 16s; }
.element-hero__frame:nth-child(10) { animation-delay: 18s; }

/* 20s cycle = 10 slides × 2s each. Fade in over 1% (~0.2s), hold through
   9% (~1.6s), fade out over 1% (~0.2s), stay hidden until next cycle. */
@keyframes elementHeroCycle10 {
    0%   { opacity: 0; }
    1%   { opacity: 1; }
    9%   { opacity: 1; }
    10%  { opacity: 0; }
    100% { opacity: 0; }
}
.element-hero__image {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
/* Single-slide special case — no animation, frame stays visible. */
.element-hero__stage[data-slides="1"] .element-hero__frame,
.element-hero__media[data-slides="1"] .element-hero__frame {
    animation: none;
    opacity: 1;
}

/* Fullwidth — port of legacy .home-hero--image */
.element-hero--fullwidth,
.element-hero--boxed {
    position: relative;
    background: transparent;
}
/* Boxed = same structure as fullwidth, just constrained to site container. */
.element-hero--boxed {
    max-width: var(--maxw);
    margin: 0 auto;
    padding: 0 var(--gutter);
}
.element-hero--fullwidth .element-hero__stage,
.element-hero--boxed .element-hero__stage {
    width: 100%;
    aspect-ratio: 16 / 9;
    max-height: 82vh;
}
.element-hero--boxed .element-hero__stage {
    border-radius: var(--r-md);
}
/* Plate is in the normal flow (not absolute) and is pulled up 100px so it
   overlaps the bottom of the stage. The block's content-driven height
   then naturally hangs below the image — magazine-cover caption that
   straddles the photo edge. The next section starts right after the
   plate's true bottom so there's no overlap with the following block. */
.element-hero--fullwidth .element-hero__plate,
.element-hero--boxed .element-hero__plate {
    /* Plate sits INSIDE the hero, anchored to the bottom-left of the
       stage. Image stays full size; block overlays the lower-left
       corner without overhanging the image edge. */
    position: absolute;
    inset: auto 0 var(--s-7) 0;
    z-index: 2;
    padding: 0 var(--gutter);
    background: transparent;
    color: #fff;
}
.element-hero--boxed .element-hero__plate {
    padding: 0 var(--gutter);
}
.element-hero--fullwidth .element-hero__inner,
.element-hero--boxed .element-hero__inner {
    display: inline-block;
    max-width: min(100%, 64rem);
    padding: var(--s-6) var(--s-7);
    background: var(--accent-deep);
    color: #fff;
    border-radius: 0;
}
.element-hero--fullwidth .element-hero__eyebrow,
.element-hero--fullwidth .element-hero__title,
.element-hero--fullwidth .element-hero__subtitle,
.element-hero--boxed .element-hero__eyebrow,
.element-hero--boxed .element-hero__title,
.element-hero--boxed .element-hero__subtitle {
    color: #fff;
}
.element-hero__subtitle {
    font-family: var(--sans);
    font-weight: 300;
    font-size: clamp(1.2rem, 1.9vw, 1.35rem);
}
.element-hero--fullwidth .element-hero__title,
.element-hero--boxed .element-hero__title {
    max-width: 22ch;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
}
.element-hero--fullwidth .element-hero__eyebrow,
.element-hero--boxed .element-hero__eyebrow { opacity: 0.85; }

/* Mobile-only in-hero CTA. The header "Request a proposal" button is
   hidden below 720px (it moves into the drawer), leaving the mobile hero
   fold with no visible action. A single white underlined text-link
   restores one clear next step without putting a coloured button on the
   editorial plate. Desktop keeps the header CTA, so this is hidden ≥720px. */
.element-hero__cta { display: none; }
@media (max-width: 720px) {
    .element-hero__cta {
        display: inline-flex;
        align-items: center;
        gap: 6px;
        margin-top: var(--s-4);
        color: #fff;
        font-family: var(--sans);
        font-weight: 500;
        font-size: 15px;
        text-decoration: none;
        border-bottom: 1px solid currentColor;
        padding-bottom: 2px;
    }
    .element-hero__cta .arrow { transition: transform 220ms var(--ease); }
    .element-hero__cta:hover .arrow,
    .element-hero__cta:focus-visible .arrow { transform: translateX(4px); }
}

/* Plate variant — gradient scrim. Drops the solid block; the plate
   becomes a full-width container at the bottom of the hero, and a
   bounded ::before paints a soft dark-to-transparent scrim that's
   roughly the height of the headline (clamped responsive band).
   Text sits above the scrim; eyebrow and the upper part of the
   title may extend above the gradient — text-shadow carries
   readability where the scrim doesn't reach. */
.element-hero--plate-gradient.element-hero--fullwidth .element-hero__plate,
.element-hero--plate-gradient.element-hero--boxed .element-hero__plate {
    inset: auto 0 0 0;
    /* Bottom padding lifts the headline ~60px off the hero edge so
       it doesn't hug the bottom; gradient stays anchored to the
       hero bottom regardless of where the text sits. */
    padding: var(--s-7) 0 var(--s-10);
    background: transparent;
}
.element-hero--plate-gradient.element-hero--fullwidth .element-hero__plate::before,
.element-hero--plate-gradient.element-hero--boxed .element-hero__plate::before {
    content: "";
    position: absolute;
    inset: auto 0 0 0;
    /* Scrim runs higher than the headline — covers the text block
       and keeps fading well above it so the photo darkens softly
       toward the lower third of the hero. */
    height: clamp(9rem, 22vh, 18rem);
    background: linear-gradient(to top,
        rgba(15, 14, 10, 0.65) 0%,
        rgba(15, 14, 10, 0.30) 55%,
        rgba(15, 14, 10, 0)    100%);
    pointer-events: none;
    z-index: 0;
}
.element-hero--plate-gradient.element-hero--fullwidth .element-hero__inner,
.element-hero--plate-gradient.element-hero--boxed .element-hero__inner {
    position: relative;
    z-index: 1;
    display: block;
    background: transparent;
    padding: 0 var(--gutter);
    max-width: var(--maxw);
    margin: 0 auto;
}
.element-hero--plate-gradient.element-hero--fullwidth .element-hero__eyebrow,
.element-hero--plate-gradient.element-hero--fullwidth .element-hero__title,
.element-hero--plate-gradient.element-hero--fullwidth .element-hero__subtitle,
.element-hero--plate-gradient.element-hero--boxed .element-hero__eyebrow,
.element-hero--plate-gradient.element-hero--boxed .element-hero__title,
.element-hero--plate-gradient.element-hero--boxed .element-hero__subtitle {
    text-shadow: 0 2px 8px rgba(0, 0, 0, 0.45);
}

/* Split — text left, media right; padding only when bg colour is set */
.element-hero--split .element-hero__cols {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0;
    align-items: stretch;
}
@media (min-width: 820px) {
    .element-hero--split .element-hero__cols {
        grid-template-columns: 1fr 1fr;
    }
}
.element-hero--split .element-hero__text {
    padding: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
}
.element-hero--split .element-hero__text--padded {
    padding: var(--s-7);
    border-radius: var(--radius-m, 4px);
}
@media (min-width: 820px) {
    .element-hero--split .element-hero__text--padded {
        padding: var(--s-8);
    }
}
/* Flip ink when a dark bg token is picked (Deep navy / Accent) so the
   eyebrow, headline and subtitle stay readable. Mirrors
   .element-textext__left--inverse / .section--deep. */
.element-hero--split .element-hero__text--inverse {
    --ink:           #f4f1ea;
    --ink-soft:      rgba(244, 241, 234, 0.72);
    --ink-muted:     rgba(244, 241, 234, 0.55);
    --hairline:      rgba(244, 241, 234, 0.18);
    --hairline-soft: rgba(244, 241, 234, 0.08);
    color:           var(--ink);
    font-weight:     400;   /* light-on-dark: stay regular (base sans is 300) */
}
.element-hero--split .element-hero__media {
    /* No aspect-ratio on phones. The media's frame is absolutely positioned
       (contributes no height), so a 4/3 ratio plus the 320px min-height
       transferred a 427px minimum *width* onto this grid cell — wider than
       the 335px column, a ~72px horizontal scroll that min-width:0 can't
       undo (the minimum comes from the ratio, not auto). Let min-height
       define the box and the width fill the column. The >=820px rule below
       restores a fluid full-height media in the 2-col layout. */
    min-height: 320px;
}
@media (min-width: 820px) {
    .element-hero--split .element-hero__media {
        aspect-ratio: auto;
        height: 100%;
        min-height: 420px;
    }
}

/* Shared text-plate typography (used by both layouts) */
.element-hero__eyebrow {
    font-family: var(--sans);
    font-size: var(--t-eyebrow);
    font-weight: 500;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ink-muted);
    margin: 0;
}
.element-hero__title {
    font-size: var(--t-hero);
    line-height: 1.1;
    letter-spacing: -0.018em;
    margin: var(--s-3) 0 0;
}
/* ---------- Fullscreen hero + transparent header overlay ----------
   When a page leads with a full-width hero, the hero fills the
   viewport and the masthead floats over it transparently with white
   text. As soon as the visitor scrolls past the masthead, the
   header restores to its solid background + dark ink state. Driven
   by body.is-scrolled (set by js/header-scroll.js at scrollY > 24)
   and CSS :has() so no PHP/template changes are needed.
   ------------------------------------------------------------------ */

/* Hero stage fills the viewport. Use svh (small viewport height), NOT dvh.
   dvh tracks iOS Safari's dynamic bottom toolbar, so a full-height hero at the
   TOP of the page grows/shrinks by ~70px every time the toolbar shows/hides.
   Because the hero drives layout, that reflows the WHOLE document by ~70px —
   and at the bottom of a long page it leaves a ~70px strip of the page ground
   (bone) below the footer: the iOS-only "content doesn't reach the bottom" bug.
   svh is a STATIC value (the toolbar-expanded height): the hero never tracks the
   toolbar, the document height never changes, so there is no bottom gap.
   Trade-off: when the toolbar is retracted, ~70px of the next section peeks
   below the hero — harmless. 100vh is the pre-svh fallback. */
.element-hero--fullwidth .element-hero__stage {
    aspect-ratio: auto;
    height: 100vh;
    height: 100svh;
    max-height: none;
}
/* Pull the hero up under the sticky chrome (header + optional
   page-subnav) so the image starts at the top edge of the viewport.
   Three selectors cover the layouts that route through here:
     1. Elemental-wrapped block (HomePage, generic Page) — hero is
        nested in .page__elements > .element
     2. DMCPage — hero is rendered directly inside <article class="dmc">
        via $forTemplate, no .element wrapper
     3. Generic fallback — any first-child .element-hero--fullwidth
        directly under an article in main
   --site-header-h and --page-subnav-h are published live by
   js/header-scroll.js (subnav var falls back to 0 when absent). */
.page__elements > .element:first-child:has(> .element-hero--fullwidth),
main > article > .element-hero--fullwidth:first-child {
    margin-top: calc(-1 * (var(--site-header-h, 73px) + var(--page-subnav-h, 0px)));
    /* Escape main's max-width + horizontal padding so the hero spans
       the full viewport even on page types where main is constrained
       (HomePage + DMCPage already drop the constraint themselves). */
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
}
/* Drop main's padding-top on pages with a fullwidth hero so the
   negative margin above can pull the hero cleanly to viewport top.
   Horizontal padding stays so the rest of the page keeps its gutter. */
body:has(.element-hero--fullwidth) main {
    padding-top: 0;
}
/* Subtle top scrim on hoisted heroes so the white nav text stays
   readable on bright photos (sky, sand) without darkening the whole
   image. Sits above the photo, below the .element-hero__plate
   (which is z-index: 2). Height covers chrome + ~100px fade tail. */
.page__elements > .element:first-child:has(> .element-hero--fullwidth) .element-hero__stage::before,
main > article > .element-hero--fullwidth:first-child .element-hero__stage::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: calc(var(--site-header-h, 73px) + var(--page-subnav-h, 0px) + 100px);
    z-index: 1;
    background: linear-gradient(to bottom,
        rgba(0, 0, 0, 0.28) 0%,
        rgba(0, 0, 0, 0.14) 55%,
        rgba(0, 0, 0, 0)    100%);
    pointer-events: none;
}
/* Hide the breadcrumb above a fullwidth hero — the masthead already
   floats over the image and a wayfinding strip would clutter the
   top of the frame. (Same pattern as Home / DMC landings.) */
body:has(.element-hero--fullwidth) .breadcrumb { display: none; }

/* Smooth handoff between transparent and solid header states. */
.site-header,
.site-header .site-subnav__links--global a,
.site-header .site-locale__current,
.site-header .site-search-trigger,
.site-header .site-contact-trigger,
.site-header .site-menu-trigger {
    transition: background 220ms var(--ease), color 220ms var(--ease), border-color 220ms var(--ease);
}

/* Transparent header while body has fullwidth hero AND visitor is at
   the top of the page. The :not(.is-scrolled) flips off as soon as
   header-scroll.js detects scroll past 24px, restoring the default
   header skin. */
body:has(.element-hero--fullwidth):not(.is-scrolled) .site-header {
    background: transparent;
    border-bottom-color: transparent;
}
body:has(.element-hero--fullwidth):not(.is-scrolled) .site-header .site-subnav__links--global a,
body:has(.element-hero--fullwidth):not(.is-scrolled) .site-header .site-locale__current,
body:has(.element-hero--fullwidth):not(.is-scrolled) .site-header .site-search-trigger,
body:has(.element-hero--fullwidth):not(.is-scrolled) .site-header .site-contact-trigger,
body:has(.element-hero--fullwidth):not(.is-scrolled) .site-header .site-menu-trigger {
    color: #fff;
}
/* Over the hero (top of a fullwidth-hero page) the controls keep the dark
   frosted glass — it reads on the photo. Once scrolled onto content the
   default white pill takes over (the chrome adapts to its backdrop).
   Desktop only: on mobile the pill is stripped entirely (≤720px block above),
   and this override out-specifies that strip, so it must not reach mobile. */
@media (min-width: 721px) {
    body:has(.element-hero--fullwidth):not(.is-scrolled) .site-header__controls {
        background: rgba(33, 28, 25, 0.7);
        backdrop-filter: blur(24px) saturate(1.4);
        -webkit-backdrop-filter: blur(24px) saturate(1.4);
        border-color: transparent;
        box-shadow: none;
        color: #fff;
    }
}
/* Soft shadow under the white nav text so it stays readable on light
   areas of the hero photo (sky, sand) without needing a scrim. */
body:has(.element-hero--fullwidth):not(.is-scrolled) .site-header__inner {
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.28);
}

/* Sand skin is reserved for the moment a sticky sub-nav DOCKS beneath the
   header (see the is-subnav-docked rule below) — that's the only time the
   band earns its keep: header + sub-nav merge into one continuous sand band
   with no gap showing through. On plain scroll, and on every page without a
   sub-nav, the header stays transparent the whole way down, letting the
   floating brand plate + chrome carry it. (Previously body.is-scrolled
   turned the header sand on every page once you scrolled past the masthead;
   removed so the sand is tied strictly to docking.) */

/* Pages with an inline sub-nav (bar sits below the hero) solidify the
   header in lockstep with the DOCKING bar, not merely on scroll: the
   header stays ghosted over the hero — transparent + white chrome — no
   matter how far you scroll, until the bar reaches the header (body gets
   .is-subnav-docked from header-scroll.js); then both take sand together.
   These win over the is-scrolled rules above on specificity, so leaving
   the masthead alone no longer flips the header early. The white/over-hero
   treatment is gated on a fullwidth hero so a no-hero inline page (rare —
   base Page without a hero) keeps its normal dark chrome. */
body:has(.element-hero--fullwidth):has(.page-subnav--inline):not(.is-subnav-docked) .site-header {
    background: transparent;
    border-bottom-color: transparent;
}
body:has(.element-hero--fullwidth):has(.page-subnav--inline):not(.is-subnav-docked) .site-header .site-subnav__links--global a,
body:has(.element-hero--fullwidth):has(.page-subnav--inline):not(.is-subnav-docked) .site-header .site-locale__current,
body:has(.element-hero--fullwidth):has(.page-subnav--inline):not(.is-subnav-docked) .site-header .site-search-trigger,
body:has(.element-hero--fullwidth):has(.page-subnav--inline):not(.is-subnav-docked) .site-header .site-contact-trigger,
body:has(.element-hero--fullwidth):has(.page-subnav--inline):not(.is-subnav-docked) .site-header .site-menu-trigger {
    color: #fff;
}
@media (min-width: 721px) {
    body:has(.element-hero--fullwidth):has(.page-subnav--inline):not(.is-subnav-docked) .site-header__controls {
        background: rgba(33, 28, 25, 0.7);
        backdrop-filter: blur(24px) saturate(1.4);
        -webkit-backdrop-filter: blur(24px) saturate(1.4);
        border-color: transparent;
        box-shadow: none;
        color: #fff;
    }
}
body:has(.element-hero--fullwidth):has(.page-subnav--inline):not(.is-subnav-docked) .site-header__inner {
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.28);
}
body:has(.page-subnav--inline).is-subnav-docked .site-header {
    background: var(--bg);
}
/* Mobile: the header NEVER takes the sand skin. The floating navy brand
   plate + frosted chrome pill carry the weight on their own, and the bar
   auto-hides on scroll anyway, so a solid sand band would only add noise.
   Keep it transparent in every scroll/dock state. Placed after the
   is-scrolled / is-subnav-docked sand rules above so it wins the
   same-specificity tie on source order; scoped to ≤720px so desktop keeps
   its solid scrolled band. */
@media (max-width: 720px) {
    .site-header,
    body.is-scrolled .site-header,
    body:has(.page-subnav--inline).is-subnav-docked .site-header {
        background: transparent;
        border-bottom-color: transparent;
    }
}
/* The locale-switcher panel itself stays its normal white card — it
   only opens on hover/focus and shouldn't inherit the white ink. */
body:has(.element-hero--fullwidth):not(.is-scrolled) .site-locale__panel {
    text-shadow: none;
}

/* PageSubNav gets the same transparent-over-hero treatment as the
   header — both pieces of chrome float together over the hero, then
   restore in lockstep when the visitor scrolls. The current-link
   underline switches to white so the active state stays visible. */
.page-subnav,
.page-subnav__label,
.page-subnav__links a {
    transition: background 220ms var(--ease), color 220ms var(--ease), border-color 220ms var(--ease);
}
body:has(.element-hero--fullwidth):not(.is-scrolled) > .page-subnav {
    background: transparent;
    border-bottom-color: transparent;
}
body:has(.element-hero--fullwidth):not(.is-scrolled) > .page-subnav .page-subnav__label,
body:has(.element-hero--fullwidth):not(.is-scrolled) > .page-subnav .page-subnav__label a,
body:has(.element-hero--fullwidth):not(.is-scrolled) > .page-subnav .page-subnav__links a {
    color: #fff;
}
body:has(.element-hero--fullwidth):not(.is-scrolled) > .page-subnav .page-subnav__links a.is-current {
    border-bottom-color: #fff;
}
body:has(.element-hero--fullwidth):not(.is-scrolled) > .page-subnav .page-subnav__inner {
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.28);
}

/* Mega-menu dropdown over a fullwidth hero — frosted-glass panel.
   Translucent dark scrim (0.32 alpha) plus a strong backdrop-blur
   so the hero shows through softly while the labels stay legible.
   White link text, muted-white eyebrow, no drop shadow. */
.site-subnav__dropdown,
.site-subnav__dropdown a,
.site-subnav__dropdown-eyebrow,
.site-subnav__dropdown-thumb {
    transition: background 220ms var(--ease), color 220ms var(--ease), border-color 220ms var(--ease), box-shadow 220ms var(--ease), backdrop-filter 220ms var(--ease);
}
body:has(.element-hero--fullwidth):not(.is-scrolled) .site-subnav__dropdown {
    background: rgba(15, 14, 10, 0.32);
    backdrop-filter: blur(24px) saturate(1.2);
    -webkit-backdrop-filter: blur(24px) saturate(1.2);
    border-top-color: rgba(255, 255, 255, 0.12);
    border-bottom-color: rgba(255, 255, 255, 0.12);
    box-shadow: none;
}
body:has(.element-hero--fullwidth):not(.is-scrolled) .site-subnav__dropdown a { color: #fff; }
body:has(.element-hero--fullwidth):not(.is-scrolled) .site-subnav__dropdown-eyebrow {
    color: rgba(255, 255, 255, 0.65);
}
body:has(.element-hero--fullwidth):not(.is-scrolled) .site-subnav__dropdown-thumb {
    background: rgba(255, 255, 255, 0.06);
}
body:has(.element-hero--fullwidth):not(.is-scrolled) .site-subnav__dropdown a:hover {
    color: var(--accent-soft);
}

/* Key figures — own row, full-width band on --bg-elev, hairlines top+bottom.
   The numbers are the "wow" content; mixing them with memberships diluted
   them. Now they get their own breathing room. */
.key-figures {
    background: transparent;
    padding: var(--s-11) 0;
}
.key-figures__head {
    max-width: var(--maxw);
    margin: 0 auto var(--s-7);
    padding: 0 var(--gutter);
}
.key-figures__row {
    list-style: none;
    padding: 0 var(--gutter);
    max-width: var(--maxw);
    margin: 0 auto;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--s-8) var(--s-6);
}
.key-figures .stat {
    gap: var(--s-3);
    align-items: center;
    text-align: center;
}
.key-figures .t-micro { font-size: 13px; letter-spacing: 0.14em; }
@media (max-width: 720px) {
    .key-figures__row { grid-template-columns: repeat(2, 1fr); }
    .key-figures { padding: var(--s-8) 0; }
}

/* Trusted-by row — own band, sits below memberships with internal hairline. */
.trusted-by-row {
    max-width: var(--maxw);
    margin: 0 auto;
    padding: var(--s-7) var(--gutter) var(--s-9);
}
.stat {
    display: flex;
    flex-direction: column;
    align-items: baseline;
    gap: 6px;
}
.stat-num {
    font-family: var(--sans);
    font-size: clamp(1.875rem, 4.5vw, 4rem);
    font-weight: 400;
    line-height: 0.95;
    letter-spacing: -0.025em;
    color: var(--feature);
}

.cert-row {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-5) var(--s-7);
    align-items: center;
}

/* Cert chip — two variants:
   - default (logo): bare, no chrome, logo gets room to breathe
   - .cert-chip--text: small pill for memberships without a logo */
.cert-chip {
    display: inline-flex;
    align-items: center;
    line-height: 1;
}
.cert-chip img {
    height: 64px;
    width: auto;
    max-width: 180px;
    object-fit: contain;
    display: block;
}
.cert-chip--text {
    height: 36px;
    padding: 0 14px;
    border: 1px solid var(--hairline);
    border-radius: var(--r-pill);
    background: var(--surface);
    gap: 8px;
    font-family: var(--sans);
    font-size: 13px;
    color: var(--ink);
    letter-spacing: 0.02em;
    white-space: nowrap;
}
.cert-chip--text .badge-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--accent);
    flex: 0 0 auto;
}

/* Logo strip — endless marquee. Two identical tracks sit side-by-side and
   translate -50% in a loop, so the seam between them is invisible. Edges
   fade out via mask. Pauses on hover. */
.muted { color: var(--ink-muted); }
.logo-strip {
    overflow: hidden;
    display: flex;
    width: 100%;
    -webkit-mask-image: linear-gradient(to right, transparent, #000 6%, #000 94%, transparent);
            mask-image: linear-gradient(to right, transparent, #000 6%, #000 94%, transparent);
}
.logo-strip__track {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex: 0 0 auto;
    animation: logo-strip-scroll 60s linear infinite;
    will-change: transform;
}
.logo-strip:hover .logo-strip__track { animation-play-state: paused; }
@keyframes logo-strip-scroll {
    from { transform: translate3d(0, 0, 0); }
    to   { transform: translate3d(-100%, 0, 0); }
}
.logo-tile {
    flex: 0 0 auto;
    width: clamp(150px, 18vw, 200px);
    aspect-ratio: 5 / 3;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--s-3);
}
.logo-tile img {
    height: clamp(36px, 4.2vw, 52px);
    width: auto;
    max-width: 85%;
    object-fit: contain;
}

/* Destination tiles — photographic squares, typography below the image.
   No overlay text, no hover darken. Minimal Bauhaus treatment: photo as
   photo, label as label. */
.home-destinations {
    max-width: var(--maxw);
    margin: 0 auto;
    padding: var(--s-11) var(--gutter);
}
.home-destinations__head {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--s-3);
}
.home-destinations__title {
    font-family: var(--sans);
    font-weight: 700;
    /* size owned by .h--display (--t-section); don't set font-size here */
    line-height: 1.1;
    letter-spacing: -0.018em;
    color: var(--ink);
    margin: 0;
}
.destination-grid {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: 1fr 1fr 1fr 1fr;
    grid-auto-rows: minmax(0, auto);
    gap: var(--s-5);
}
/* Mallorca anchors the grid at ~2× size — reflects operational reality
   (HQ, longest tenure, most venues). Spans cols 1-2 of the 4-col grid
   so the right two columns share their track positions with the case
   study rail below. */
.destination--anchor {
    grid-row: 1 / span 2;
    grid-column: 1 / span 2;
}
@media (max-width: 820px) {
    .destination-grid { grid-template-columns: 1fr 1fr; }
    .destination--anchor { grid-column: 1 / -1; grid-row: auto; }
}
@media (max-width: 540px) {
    .destination-grid { grid-template-columns: 1fr; }
}
.destination__link {
    display: block;
    text-decoration: none;
    color: inherit;
}
.destination__figure {
    position: relative;
    margin: 0;
    overflow: hidden;
    background: var(--surface);
    aspect-ratio: 8 / 5;
}
.destination__figure img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.destination__figure--empty {
    display: block;
    width: 100%;
    height: 100%;
    background: var(--hairline-soft);
}
/* Gradient mask sits behind the caption to keep the title legible against
   any photo. Bottom 55% of the figure; transparent at top, ink at base. */
.destination__figure::after {
    content: "";
    position: absolute;
    inset: 45% 0 0 0;
    background: linear-gradient(to bottom, rgba(33, 28, 25, 0) 0%, rgba(33, 28, 25, 0.55) 100%);
    pointer-events: none;
}
.destination__title {
    font-family: var(--sans);
    font-weight: 400;
    font-size: var(--t-h2);
    line-height: 1.05;
    letter-spacing: -0.01em;
    color: #fff;
    margin: 0;
}
.destination__body { padding: var(--s-4); }
.destination__pitch {
    color: var(--ink-soft);
    margin: 0;
    max-width: 32em;
}

/* Homepage Destinations strip: 4×2 grid with a 2×2 anchor.
   Layout:
       Mallorca  Mallorca  Ibiza      Formentera
       Mallorca  Mallorca  Menorca    Malta
   Image edges align across the strip: row-1 image-tops at y0,
   row-1 image-bottoms at y(HBild), row-2 image-tops at y(row-1 +
   gap), row-2 image-bottoms at y(2·row + gap). The anchor's
   image stretches from top to row-2 image-bottom by absorbing
   the body-height of row 1 + the inter-row gap via flex-grow on
   the figure. Bodies have fixed height so row alignment can't
   drift with copy length.
   Scoped under .home-destinations so the DestinationsPage index
   (which uses its own .destination-wall overlay layout) stays
   untouched. */
.home-destinations .destination-grid {
    grid-template-columns: repeat(4, 1fr);
    grid-template-rows: 1fr 1fr;
}
.home-destinations .destination--anchor {
    grid-column: 1 / span 2;
    grid-row: 1 / span 2;
}
.home-destinations .destination__link {
    display: flex;
    flex-direction: column;
    height: 100%;
}
.home-destinations .destination__figure {
    flex: 1 1 auto;
    min-height: 0;
}
.home-destinations .destination__figure img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.home-destinations .destination__figure::after { display: none; }
.home-destinations .destination__body {
    padding: var(--s-4) 0 0;
    flex: 0 0 auto;
    height: 5.5rem;
    overflow: hidden;
}
.home-destinations .destination__region {
    font-family: var(--sans);
    font-size: 0.78rem;
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ink-soft);
    margin: 0 0 var(--s-2);
}
.home-destinations .destination__title {
    font-family: var(--sans);
    font-weight: 700;
    font-size: clamp(1.2rem, 1.5vw, 1.5rem);
    line-height: 1.15;
    letter-spacing: -0.015em;
    color: var(--ink);
    margin: 0;
    text-wrap: balance;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.home-destinations .destination--anchor .destination__title {
    font-size: clamp(1.6rem, 2.2vw, 2.2rem);
}
.home-destinations .destination__pitch { display: none; }
@media (max-width: 1024px) {
    /* Phones & narrow tablets: Mallorca anchors full-width on top, the
       remaining destinations flow into a 2-up grid below. Stops the strip
       from becoming a long vertical scroll on phones (was a single-column
       stack pre-2026-06-05). The anchor is the first child and spans both
       columns, so it stays first and full-width without markup changes.
       Figures regain a fixed 8:5 aspect since flex-grow no longer has a
       fixed-height row to absorb extra space into. */
    .home-destinations .destination-grid {
        grid-template-columns: 1fr 1fr;
        grid-template-rows: auto;
        gap: var(--s-5);
    }
    .home-destinations .destination--anchor {
        grid-column: 1 / -1;
        grid-row: auto;
    }
    /* Overflow guard: CSS grid items (and flex children) default to
       min-width:auto, so a long/unbroken title or an intrinsically wide
       figure can blow a 1fr track past the content rail and push the whole
       page wider than the viewport (horizontal scroll on phones). min-width:0
       lets every card — including the 1/-1 anchor — shrink to its track, and
       overflow-wrap breaks any long word instead of forcing extra width. */
    .home-destinations .destination {
        min-width: 0;
    }
    .home-destinations .destination__figure {
        flex: 0 0 auto;
        aspect-ratio: 8 / 5;
        min-width: 0;
    }
    .home-destinations .destination__title {
        overflow-wrap: break-word;
    }
    /* Narrower 2-up tiles need a touch more room for the (now wrapping)
       title; the fixed body height keeps the two columns bottom-aligned. */
    .home-destinations .destination__body {
        height: 4.5rem;
    }
    .home-destinations .destination--anchor .destination__body {
        height: 5.5rem;
    }
    .home-destinations .destination--anchor .destination__title {
        font-size: clamp(1.4rem, 4vw, 1.8rem);
    }
}
/* Very narrow phones (~360px): the 2-up tiles get cramped; let the
   non-anchor destinations breathe with a tighter gap but keep 2 columns
   so the section stays compact rather than reverting to a long stack. */
@media (max-width: 400px) {
    .home-destinations .destination-grid { gap: var(--s-4); }
    .home-destinations .destination__title {
        font-size: clamp(1rem, 4.5vw, 1.2rem);
    }
}

/* Negative-space rhythm: sections sit on one ground (sand body) and
   are separated by generous vertical breathing room rather than bg
   alternation or hairlines. The space IS the section break. */
.home-section {
    padding: var(--s-11) var(--gutter);
    max-width: var(--maxw);
    margin: 0 auto;
}

/* Full-bleed panel modifier — sand band runs to the viewport edges, but
   the inner content (header, lists, cards) stays inside --maxw so it
   tracks the rest of the page's column. Top + bottom hairlines mark the
   panel's vertical extent. Used for blocks that benefit from a visual
   "section break" without boxing the content into a card (Google Reviews,
   Partner strip). */
/* Panel modifier kept for layout purposes (full-bleed instead of maxw)
   but bg matches the body — negative-space rhythm, no visual bands. */
.home-section--panel {
    background: transparent;
    max-width: none;
    padding: var(--s-11) var(--gutter);
}
.home-section--panel > * {
    /* Match the effective content width of non-panel sections, which sit
       inside .home-section's maxw box AND have gutter padding inside it
       (effective content = maxw − 2·gutter). Without subtracting the
       gutter the panel's children would be 2·gutter wider than the rest
       of the page, making destinations/cases/reviews stand out as wider. */
    max-width: calc(var(--maxw) - 2 * var(--gutter));
    margin-left: auto;
    margin-right: auto;
}

/* Section rule — thick horizontal anchor pinned to the top-left corner of
   the .element wrapper, which spans the full viewport width regardless of
   the inner section's max-width. That keeps the rule at the viewport's
   left edge for every section type (panel or maxw-constrained) without
   per-section CSS. Rendered from ElementHolder.ss when the editor toggles
   ShowSectionRule on a block. Animates in from the left when scrolled
   into view — driven by .is-in-view set by js/section-rule.js. */
.element { position: relative; }

.section-rule {
    position: absolute;
    top: 0;
    left: 0;
    width: clamp(160px, 28%, 320px);
    max-width: none;
    height: 4px;
    background: var(--accent-a-600);
    border: 0;
    margin: 0;
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform 900ms cubic-bezier(0.22, 0.61, 0.36, 1);
    will-change: transform;
}
.section-rule.is-in-view { transform: scaleX(1); }
.element.has-section-rule { padding-top: 0; }

/* ElementContent rendert ohne inneres <section>, also greift die globale
   .element > section { padding: var(--s-11) ... } Regel (siehe unten)
   nicht. Steht ein ElementContent als eigenständiger Beat zwischen
   anderen Sections (z.B. Homepage-Intro nach dem Hero), kollabiert er
   ohne eigenes Padding auf 0 und wird von den 128px-lauten Nachbarn
   plattgedrückt. 96px (--s-10) gibt ihm einen ruhigeren Beat als die
   Loud Sections — Text soll nicht so schwer wirken wie ein 4-Kachel-
   Grid. Greift nur als direktes Kind von .page__elements, nicht bei
   verschachtelten ElementContent-Blöcken innerhalb anderer Wrapper. */
.page__elements > .element.dnadesign__elemental__models__elementcontent {
    padding-top: var(--s-10);
    padding-bottom: var(--s-10);
    /* Wichtig: KEIN padding-Shorthand. Die is-partial-Regel (oben)
       setzt padding-left/right: var(--gutter) auf stripped-main Pages
       — ein Shorthand hier wischt das mit 0 weg und der Block driftet
       um einen Gutter nach links aus dem Grid. Siehe memory
       css_margin_shorthand_trap (gleicher Mechanismus, padding statt
       margin). */
}

/* Uniform generous top padding across every Elemental section, plus
   `position: relative` so the eyebrow (always the section's direct first
   child — see template refactor across all Element blocks) can absolute-
   position itself at top-left without disturbing the section's flow.
   Overrides per-section padding variations (s-9 on testimonial-wrap/
   affiliation/case-rail/home-rfp-cta/sister-brands, s-10 on why-us, s-7
   on trusted-by-row) for one consistent rhythm. */
.element > section { position: relative; padding-top: var(--s-11); }
.element > section.element-hero { padding-top: 0; }

/* Eyebrow anchored as a top-left editorial mark, flush with the
   section's CONTENT column (not its outer box). Absolute positioning
   decouples it from the section's generous flow padding so it sits at
   top:0 + 8px while title/lede sit ~128px below in normal flow.

   The left value handles both section flavours with one formula:
   - capped sections (.home-section, .why-us, .testimonial-wrap, etc.
     have max-width:maxw + padding:gutter) → section width == maxw, so
     (100% - maxw)/2 + gutter == gutter → eyebrow at left:gutter, flush
     with the inner padded content.
   - full-bleed sections (.home-section--panel, .newsletter-block,
     .home-rfp-cta, .key-figures — section width == viewport) → the
     formula pushes the eyebrow inward by the centering offset PLUS
     gutter so it lands at the centered content column's left edge.
   max() clamps to var(--gutter) on narrow viewports where the offset
   goes negative (vw < maxw). */
section > .t-eyebrow {
    position: absolute;
    top: var(--s-4);
    left: max(var(--gutter), calc((100% - var(--maxw)) / 2 + var(--gutter)));
    margin: 0;
}

.home-section__head {
    margin-bottom: var(--s-8);
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--s-5);
}
.home-section__title {
    font-family: var(--sans);
    font-weight: 500;
    font-size: var(--t-eyebrow);
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ink-muted);
    margin: 0;
}
.home-section__lead {
    font-family: var(--serif);
    font-size: 1.05rem;
    font-style: italic;
    color: var(--ink-soft);
    margin: 0;
}

/* ---------- Case study rail (homepage) -----------------------------
   Asymmetric two-column layout: title + lede + arrow controls on the
   left, horizontally-scrolling card rail on the right. The rail uses
   scroll-snap for snappy stops at each card. Arrows are wired up via
   js/case-rail.js (data-rail-prev / data-rail-next / data-rail-scroller). */
.case-rail-wrap {
    max-width: var(--maxw);
    margin: 0 auto;
    /* padding-top comes from the universal `.element > section` rule
       (var(--s-11)) for uniform section rhythm — do not set it here. */
    padding: 0 0 var(--s-10);
    /* Let the rail itself bleed past the right gutter into the viewport
       edge so cards visually continue off-screen — strong scroll affordance. */
    overflow: hidden;
}
/* When the case rail is rendered inside a full-bleed sand panel, the
   wrap's own maxw + side padding fight the panel — undo them so the
   panel handles framing and the rail bleeds inside the panel band. */
.case-rail-wrap.home-section--panel {
    max-width: none;
    padding-left: var(--gutter);
    padding-right: var(--gutter);
    padding-bottom: var(--s-8);
}
/* Track layout mirrors .destination-grid (1fr 1fr 1fr 1fr, gap var(--s-5))
   so head sits in col 1 and the three visible cards land exactly on
   cols 2-4 of the destination grid above. */
.case-rail__layout {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr 1fr;
    gap: var(--s-5);
    align-items: start;
}
.case-rail__head {
    grid-column: 1;
    display: flex;
    flex-direction: column;
    gap: var(--s-4);
    align-self: start;
    padding-bottom: var(--s-4);
}
.case-rail__title {
    font-family: var(--sans);
    font-weight: 700;
    font-size: var(--t-h1);
    line-height: 1.05;
    letter-spacing: -0.02em;
    color: var(--ink);
    margin: 0;
}
.case-rail__lead {
    font-family: var(--sans);
    font-size: 1rem;
    line-height: 1.5;
    color: var(--ink-soft);
    margin: 0;
}
.case-rail__controls {
    display: flex;
    gap: var(--s-2);
    margin-top: var(--s-3);
}
.case-rail__arrow {
    appearance: none;
    background: transparent;
    border: 1px solid var(--hairline);
    border-radius: 999px;
    width: 44px;
    height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--ink);
    cursor: pointer;
    transition: background 150ms ease, border-color 150ms ease, color 150ms ease, transform 150ms ease;
}
.case-rail__arrow:hover {
    background: var(--ink);
    border-color: var(--ink);
    color: #fff;
}
.case-rail__arrow:active { transform: scale(0.95); }
.case-rail__arrow[disabled] {
    opacity: 0.3;
    cursor: not-allowed;
    background: transparent;
    color: var(--ink);
    border-color: var(--hairline);
}

/* The scroller — overflow-x with scroll-snap. No visible scrollbar
   on macOS/iOS; on Windows we leave the native scrollbar. */
.case-rail__scroller {
    grid-column: 2 / -1;
    /* min-width:0 lets the scroller stay within its grid tracks instead
       of expanding to its (much wider) flex-content width. */
    min-width: 0;
    overflow-x: auto;
    overflow-y: visible;
    scroll-snap-type: x mandatory;
    scroll-padding-left: 0;
    -webkit-overflow-scrolling: touch;
    /* Hide scrollbar visually — keyboard / wheel still works */
    scrollbar-width: none;
}
.case-rail__scroller::-webkit-scrollbar { display: none; }

.case-rail {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    gap: var(--s-5);
}
/* Three cards per viewport, sized to one destination-grid 1fr track each
   so they line up with cols 2-4 of .destination-grid. */
.case-rail__item {
    flex: 0 0 calc((100% - 2 * var(--s-5)) / 3);
    scroll-snap-align: start;
}
.case-rail__card {
    display: flex;
    flex-direction: column;
    gap: var(--s-4);
    text-decoration: none;
    color: inherit;
    height: 100%;
}
.case-rail__body { padding: var(--s-4) 0 0; }
.case-rail__photo {
    margin: 0;
    aspect-ratio: 8 / 5;
    overflow: hidden;
    background: var(--bg-soft);
}
.case-rail__photo img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.case-rail__body {
    display: flex;
    flex-direction: column;
    gap: var(--s-2);
    /* Stretch to fill the rest of the card so all cards reach the same
       height (specs sit at the bottom via margin-top: auto below). */
    flex: 1 1 auto;
    padding: var(--s-4);
}
.case-rail__name {
    font-family: var(--sans);
    font-weight: 700;
    font-size: 1.125rem;
    line-height: 1.2;
    letter-spacing: -0.01em;
    margin: 0;
    color: var(--ink);
}
.case-rail__type {
    font-family: var(--sans);
    font-size: 0.95rem;
    line-height: 1.35;
    color: var(--ink-soft);
    margin: 0;
}
.case-rail__specs {
    list-style: none;
    padding: 0;
    /* margin-top: auto keeps cards bottom-aligned across the rail
       even though shorter titles leave more whitespace above. */
    margin: auto 0 0;
    display: flex;
    flex-wrap: wrap;
    gap: 6px var(--s-2);
    font-family: var(--sans);
    font-size: 13px;
    font-style: normal;
    color: var(--ink-muted);
    letter-spacing: 0.02em;
}
.case-rail__specs li { font-family: var(--sans); font-style: normal; }
.case-rail__specs li:not(:last-child)::after {
    content: " · ";
    margin-left: var(--s-2);
    color: var(--ink-muted);
}

/* Mobile: single-column stack — head on top, scroller below full-width. */
@media (max-width: 720px) {
    .case-rail__layout {
        grid-template-columns: 1fr;
        gap: var(--s-5);
    }
    .case-rail__head {
        grid-column: 1 / -1;
        position: static;
        padding-right: var(--gutter);
    }
    .case-rail__scroller {
        grid-column: 1 / -1;
    }
    .case-rail__item {
        flex: 0 0 80%;
    }
}
.case-study-card__specs {
    list-style: none;
    padding: var(--s-3) 0 0;
    margin: auto 0 0;
    border-top: 1px solid var(--hairline);
    display: flex;
    flex-wrap: wrap;
    gap: 6px var(--s-3);
    font-family: var(--sans);
    font-size: var(--t-eyebrow);
    font-weight: 500;
    color: var(--ink-muted);
    letter-spacing: 0.18em;
    text-transform: uppercase;
}
.case-study-card__specs li { font-family: var(--sans); font-weight: 500; }
.case-study-card__specs li:not(:last-child)::after {
    content: " · ";
    margin-left: var(--s-3);
    color: var(--hairline);
}

/* ---------- Case study INDEX page (/case-studies) ----------------------
   Hero entry on top (2-col split, image left + copy right), then 5
   smaller entries in 2-up below. Same logic as the homepage deck but
   stretched to fill the index page's content column. */

.case-study-index-grid {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--s-7) var(--s-5);
}
.case-study-entry { margin: 0; }
.case-study-entry--hero { grid-column: span 2; }
@media (max-width: 900px) {
    .case-study-index-grid { grid-template-columns: 1fr; gap: var(--s-7); }
    .case-study-entry--hero { grid-column: auto; }
}

.case-study-entry__link {
    display: flex;
    flex-direction: column;
    text-decoration: none;
    color: inherit;
    background: var(--surface);
    border: 1px solid var(--hairline);
    border-radius: var(--r-md);
    overflow: hidden;
    transition: transform 220ms var(--ease), box-shadow 220ms var(--ease);
    height: 100%;
}
.case-study-entry--hero .case-study-entry__link {
    flex-direction: row;
    align-items: stretch;
}
.case-study-entry--hero .case-study-entry__photo {
    flex: 1 1 50%;
    min-height: 100%;
}
.case-study-entry--hero .case-study-entry__body {
    flex: 1 1 50%;
    padding: var(--s-7);
    gap: var(--s-4);
    justify-content: center;
}
@media (max-width: 900px) {
    .case-study-entry--hero .case-study-entry__link { flex-direction: column; }
    .case-study-entry--hero .case-study-entry__photo { aspect-ratio: 8 / 5; flex: none; min-height: 0; }
}

/* No-photo fallback — imageless case studies degrade to a text-led card
   (eyebrow + title + specs) instead of an empty grey frame, so the index
   reads as an intentional editorial list. Remove once every published
   case study carries a PrimaryImage. */
.case-study-entry--no-photo .case-study-entry__link { flex-direction: column; }
.case-study-entry--no-photo .case-study-entry__body { flex: 1 1 auto; }

.case-study-entry__photo {
    margin: 0;
    background: var(--stone-200);
    overflow: hidden;
}
.case-study-entry__photo[data-ratio="wide"]   { aspect-ratio: 8 / 5; }
.case-study-entry__photo[data-ratio="square"] { aspect-ratio: 8 / 5; }
.case-study-entry__photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.case-study-entry__body {
    padding: var(--s-5);
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
    flex: 1;
}
.case-study-entry__title {
    font-size: var(--t-h2);
    line-height: 1.18;
    margin: 0;
    color: var(--ink);
}
.case-study-entry--hero .case-study-entry__title {
    font-size: var(--t-h1);
    line-height: 1.15;
}
.case-study-entry__summary {
    color: var(--ink-soft);
    margin: 0;
}

/* ---------- Case study DETAIL page (/case-studies/{slug}/{id}) --------- */

.case-study {
    max-width: var(--maxw-text);
    margin: 0 auto;
}
.case-study__head {
    margin-bottom: var(--s-7);
}
.case-study__back {
    margin: 0 0 var(--s-6);
    font-family: var(--sans);
    font-size: 13px;
}
.case-study__back a {
    color: var(--ink-muted);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    padding-bottom: 1px;
}
.case-study__back a:hover {
    color: var(--ink);
    border-bottom-color: var(--ink);
}
.case-study__eyebrow {
    margin: 0 0 var(--s-3);
}
.case-study__title {
    font-family: var(--sans);
    font-weight: 700;
    font-size: var(--t-display);
    line-height: 1.05;
    letter-spacing: -0.022em;
    margin: 0 0 var(--s-5);
    color: var(--ink);
    text-wrap: balance;
}
.case-study__summary {
    font-family: var(--sans);
    font-size: 1.2rem;
    line-height: 1.5;
    color: var(--ink-soft);
    margin: 0 0 var(--s-7);
}

/* Specs row — small "Destination / Group size / Duration / Programme"
   data block, displayed as a 4-column key/value list with hairline. */
.case-study__specs {
    list-style: none;
    margin: 0 0 var(--s-7);
    padding: var(--s-5) 0;
    border-top: 1px solid var(--hairline);
    border-bottom: 1px solid var(--hairline);
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--s-5) var(--s-4);
}
@media (max-width: 720px) {
    .case-study__specs { grid-template-columns: repeat(2, 1fr); }
}
.case-study__specs li { display: flex; flex-direction: column; gap: 4px; }
.case-study__spec-label {
    font-family: var(--sans);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--ink-muted);
}
.case-study__spec-value {
    font-family: var(--sans);
    font-size: 15px;
    font-weight: 500;
    color: var(--ink);
}

.case-study__photo {
    margin: 0 0 var(--s-8);
    aspect-ratio: 16 / 9;
    overflow: hidden;
    background: var(--stone-200);
    border-radius: var(--r-md);
    /* break out beyond the reading column for visual impact */
    width: calc(100% + 2 * var(--s-9));
    margin-left: calc(-1 * var(--s-9));
}
@media (max-width: 900px) {
    .case-study__photo { width: 100%; margin-left: 0; }
}
.case-study__photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.case-study__body {
    margin: 0 0 var(--s-7);
}

/* Pull quote — italic Garamond, indented from a thick accent rule. */
.case-study__quote {
    margin: var(--s-8) 0;
    padding: 0 0 0 var(--s-5);
    border-left: 3px solid var(--accent);
    font-family: var(--serif);
    font-style: italic;
    font-size: clamp(1.15rem, 1.6vw, 1.45rem);
    line-height: 1.45;
    color: var(--ink);
}

.case-study__what-worked {
    margin: var(--s-8) 0 0;
    padding: var(--s-7) 0 0;
    border-top: 1px solid var(--hairline);
}
.case-study__h2 {
    font-family: var(--sans);
    font-weight: 700;
    font-size: 1.5rem;
    letter-spacing: -0.015em;
    margin: 0 0 var(--s-5);
    color: var(--ink);
}

/* Testimonial — design system pattern (components.html). Big serif
   blockquote + 48px avatar circle + name/role/company. Hand-curated
   quotes only; the .review__* widget renders Google Reviews separately. */
.testimonial {
    margin: 0 auto;
    padding: var(--s-6) 0;
    display: grid;
    grid-template-columns: minmax(180px, 240px) minmax(0, 1fr);
    gap: var(--s-8);
    align-items: start;
    text-align: left;
}
.testimonial__meta {
    display: flex;
    flex-direction: column;
    gap: var(--s-5);
    padding-right: var(--s-6);
    border-right: 1px solid var(--hairline);
}
.testimonial__body {
    min-width: 0;
}
.testimonial__quote {
    font-family: var(--serif);
    font-size: clamp(1.25rem, 2vw, 1.75rem);
    line-height: 1.4;
    font-style: italic;
    color: var(--ink);
    margin: 0 0 var(--s-5);
    text-wrap: balance;
}
.testimonial__quote p {
    font-family: inherit;
    font-style: inherit;
    font-size: inherit;
    margin: 0;
    color: inherit;
}
.testimonial__source {
    display: inline-flex;
    align-items: center;
    gap: var(--s-3);
}
.testimonial__avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: var(--accent);
    color: var(--accent-ink);
    font-family: var(--sans);
    font-size: 14px;
    font-weight: 500;
    letter-spacing: 0.04em;
    flex: 0 0 auto;
}
.testimonial__cite {
    text-align: left;
    display: flex;
    flex-direction: column;
}
.testimonial__name {
    font-family: var(--sans);
    font-size: 14px;
    font-weight: 500;
    color: var(--ink);
}
.testimonial__role {
    font-family: var(--sans);
    font-size: 12px;
    color: var(--ink-muted);
    letter-spacing: 0.02em;
}
.testimonial__logo {
    display: flex;
    align-items: center;
    min-height: 40px;
}
.testimonial__logo img {
    max-height: 48px;
    width: auto;
    max-width: 100%;
    object-fit: contain;
    object-position: left center;
    /* Multiply blend drops white logo backgrounds onto the page ground —
       works for SVG (e.g. built-in <rect fill="white">) and raster
       (JPG/PNG with a white card around the mark). */
    mix-blend-mode: multiply;
}
.testimonial__facts {
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--s-4);
}
.testimonial__fact {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: 0;
}
.testimonial__fact-label {
    font-family: var(--sans);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ink-muted);
    margin: 0;
}
.testimonial__fact-value {
    font-family: var(--sans);
    font-size: 14px;
    font-weight: 500;
    color: var(--ink);
    margin: 0;
}
@media (max-width: 720px) {
    .testimonial {
        grid-template-columns: 1fr;
        gap: var(--s-6);
    }
    .testimonial__meta {
        padding-right: 0;
        border-right: 0;
        border-bottom: 1px solid var(--hairline);
        padding-bottom: var(--s-5);
    }
}

/* Testimonial slider — stack of figures, only [is-active] visible.
   Arrows sit beside the quote; on narrow screens they tuck under it. */
.testimonial-wrap {
    overflow: hidden;
    /* Paired with .affiliation in the elements grid — tighter padding
       than the default home-section rhythm so the editorial pair reads
       as one row, not two stadiums of whitespace. */
    padding: var(--s-9) var(--gutter);
}
/* Match the affiliation eyebrow margins so the paired blocks' eyebrows
   line up exactly at the row's baseline (negative-space alignment). */
.testimonial-wrap__eyebrow {
    margin: 0 0 var(--s-4);
}
.testimonial-slider {
    position: relative;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--s-3);
    max-width: 1080px;
    margin: 0 auto;
    padding: 0 var(--s-3);
}
.testimonial-slider__stage {
    position: relative;
    display: grid;
}
.testimonial-slider__slide {
    grid-area: 1 / 1;
    opacity: 0;
    visibility: hidden;
    transition: opacity 240ms ease;
    pointer-events: none;
}
.testimonial-slider__slide.is-active {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
}
.testimonial-slider__arrow {
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: 1px solid var(--rule);
    color: var(--ink);
    width: 44px;
    height: 44px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    flex: 0 0 auto;
    transition: border-color 160ms ease, color 160ms ease, background 160ms ease;
}
.testimonial-slider__arrow:hover,
.testimonial-slider__arrow:focus-visible {
    border-color: var(--ink);
    color: var(--ink);
    outline: none;
}
.testimonial-slider__arrow:disabled {
    opacity: 0.35;
    cursor: default;
}
@media (max-width: 720px) {
    .testimonial-slider {
        grid-template-columns: auto auto;
        grid-template-rows: auto auto;
        justify-content: center;
        gap: var(--s-4);
    }
    .testimonial-slider__stage {
        grid-column: 1 / -1;
        grid-row: 1;
    }
    .testimonial-slider__arrow--prev {
        grid-column: 1;
        grid-row: 2;
        justify-self: end;
        margin-right: var(--s-2);
    }
    .testimonial-slider__arrow--next {
        grid-column: 2;
        grid-row: 2;
        justify-self: start;
        margin-left: var(--s-2);
    }
}

/* "Read full testimonial" link — sits below the figcaption inside the
   slide. Sans, small, neutral; the slide that has it (Chargebee)
   visually matches the height of the short quotes around it. */
.testimonial__more-trigger {
    appearance: none;
    -webkit-appearance: none;
    display: block;
    margin: 0 0 var(--s-7);
    background: transparent;
    border: 0;
    padding: 0;
    font-family: var(--sans);
    font-size: var(--t-small);
    color: var(--ink-soft);
    letter-spacing: 0.02em;
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 4px;
    text-decoration-thickness: 1px;
    text-decoration-color: var(--rule-band);
    transition: color 160ms ease, text-decoration-color 160ms ease;
}
.testimonial__more-trigger:hover,
.testimonial__more-trigger:focus-visible {
    color: var(--ink);
    text-decoration-color: var(--ink);
    outline: none;
}

/* Modal overlay for the full quote. One per testimonial that has
   QuoteExpanded. [hidden] for initial a11y state; .is-open fades in
   the scrim + card (CSS transition). Body locks scroll while open. */
.testimonial-modal {
    position: fixed;
    inset: 0;
    z-index: 200;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--gutter);
    opacity: 0;
    transition: opacity 200ms ease;
}
/* [hidden] must beat display:flex above so the closed modal doesn't
   sit over the page and swallow clicks (scrim is position:absolute
   inset:0 inside it). */
.testimonial-modal[hidden] {
    display: none;
}
.testimonial-modal.is-open {
    opacity: 1;
}
.testimonial-modal__scrim {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    cursor: pointer;
}
.testimonial-modal__card {
    position: relative;
    background: var(--surface);
    border: 1px solid var(--rule-band);
    max-width: 720px;
    width: 100%;
    max-height: 80vh;
    overflow-y: auto;
    padding: var(--s-8) var(--s-7);
    transform: translateY(8px);
    transition: transform 200ms ease;
}
.testimonial-modal.is-open .testimonial-modal__card {
    transform: translateY(0);
}
.testimonial-modal__close {
    position: absolute;
    top: var(--s-3);
    right: var(--s-3);
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: 0;
    padding: var(--s-2);
    font-family: var(--sans);
    font-size: 24px;
    line-height: 1;
    color: var(--ink-muted);
    cursor: pointer;
    transition: color 160ms ease;
}
.testimonial-modal__close:hover,
.testimonial-modal__close:focus-visible {
    color: var(--ink);
    outline: none;
}
.testimonial-modal__quote {
    margin: 0;
    padding: 0;
    font-family: var(--serif);
    font-size: var(--t-body-lg);
    line-height: 1.55;
    font-style: italic;
    color: var(--ink);
}
.testimonial-modal__quote p {
    font-family: inherit;
    font-style: inherit;
    margin: 0 0 var(--s-4);
}
.testimonial-modal__quote p:last-child {
    margin-bottom: 0;
}
.testimonial-modal__cite {
    margin-top: var(--s-6);
    padding-top: var(--s-4);
    border-top: 1px solid var(--rule-band);
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.testimonial-modal__name {
    font-family: var(--sans);
    font-size: 14px;
    font-weight: 500;
    color: var(--ink);
}
.testimonial-modal__role {
    font-family: var(--sans);
    font-size: 12px;
    color: var(--ink-muted);
    letter-spacing: 0.02em;
}
body.is-testimonial-modal-open {
    overflow: hidden;
}
@media (max-width: 720px) {
    .testimonial-modal__card {
        padding: var(--s-6) var(--s-5);
    }
}

/* ---------- DMC landing ------------------------------------------- */

.dmc { padding: 0; }

/* DMCPage overrides the generic main padding (same trick as HomePage) */
.t-App\\PageType\\DMCPage main {
    padding: 0 0 var(--s-10);
    max-width: none;
}

/* Process strip — 5-step timeline. Connecting hairline runs through the
   centre of all circles via ::before; circles sit on top with surface
   background to break the line cleanly. First step is active (accent fill). */
.process-strip {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: var(--s-5);
    position: relative;
}
.process-strip::before {
    content: "";
    position: absolute;
    top: 18px;
    left: 6%;
    right: 6%;
    height: 1px;
    background: var(--hairline);
    z-index: 0;
}
@media (max-width: 800px) {
    .process-strip { grid-template-columns: 1fr; gap: var(--s-5); }
    .process-strip::before { display: none; }
}
.process-step {
    position: relative;
    z-index: 1;
    text-align: left;
}
.process-step__circle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--bg);
    border: 1px solid var(--ink);
    font-family: var(--sans);
    font-size: 14px;
    font-weight: 500;
    color: var(--ink);
    margin-bottom: var(--s-3);
    font-feature-settings: "tnum";
}
.process-step.is-active .process-step__circle {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--accent-ink);
}
.process-step__title {
    font-size: var(--t-h4);
    color: var(--ink);
    margin: 0 0 4px;
}
.process-step__text {
    font-family: var(--sans);
    font-size: 13px;
    line-height: 1.5;
    color: var(--ink-soft);
    margin: 0;
}

/* ---------- Google Reviews — Featured + supporting ----------------
   Editorial hierarchy, not a row of equal cards: one lead review set
   large in a subtly tinted block, up to two supporting reviews stacked
   beside it. Markup: themes/lxp/templates/Includes/GoogleReviews.ss.
   The floating eyebrow is positioned by the site-wide `section >
   .t-eyebrow` rule; the head carries the section h2 + the aggregate. */

.reviews__head { flex-wrap: wrap; align-items: baseline; }
.reviews__heading {
    /* section tier — matches other homepage section titles (= --t-h1
       clamp). NOT hero tier (see type-hierarchy invariant). */
    font-size: var(--t-section);
    line-height: 1.1;
    margin: 0;
    /* No measure cap: a 22ch cap was tuned to the English default
       ("What our clients say", 20 chars) and forced longer locales to break
       awkwardly — German "Was unsere Kunden sagen" (23) wrapped a lone "sagen",
       Spanish "Lo que dicen nuestros clientes" (30) is longer still. It's a
       short section title, so let it size to content and stay on one line; the
       flex head (justify-content: space-between) keeps it clear of the summary. */
}

/* Aggregate summary — stars + numeric rating + the Google mark + count.
   The numeric rating (not five painted stars) carries the headline
   trust; the multicolour G names the source. */
.reviews__summary {
    display: flex;
    align-items: baseline;
    gap: var(--s-3);
    margin: 0;
    font-size: 0.95rem;
    color: var(--ink-soft);
    white-space: nowrap;
}
.reviews__stars {
    color: var(--feature-500);
    letter-spacing: 2px;
    font-size: 1rem;
    line-height: 1;
}
.reviews__rating {
    font-family: var(--sans);
    font-weight: 700;
    font-size: 1.6rem;
    letter-spacing: -0.02em;
    line-height: 1;
    color: var(--ink);
}
.reviews__gmark { display: inline-flex; align-self: center; }
.reviews__gmark svg { width: 15px; height: 15px; display: block; }
.reviews__count { letter-spacing: 0.02em; color: var(--ink-muted); }

/* Featured + supporting grid. Lead review ≈ 1.6× the supporting column;
   collapses to a single column on tablet/mobile. */
.reviews__layout {
    display: grid;
    grid-template-columns: 1.6fr 1fr;
    gap: var(--s-6);
    align-items: stretch;
}

.reviews__featured {
    /* Surface treatment (tint, radius, padding) comes from the shared
       PANEL canon at the top of this file. Only the lead review's own
       layout lives here: a flex column so __by can be pushed to the
       bottom via margin-top:auto. */
    margin: 0;
    display: flex;
    flex-direction: column;
}
.reviews-featured__stars {
    color: var(--feature-500);
    letter-spacing: 3px;
    font-size: 1.15rem;
    line-height: 1;
    margin-bottom: var(--s-4);
}
.reviews-featured__quote {
    margin: 0;
    /* The lead review reads as a true editorial pull quote — Garamond
       italic, the one sanctioned accent use (set explicitly so it does
       not merely ride the global blockquote rule in tokens.css). */
    font-family: var(--serif);
    font-style: italic;
    font-weight: 400;
    font-size: clamp(1.5rem, 2.6vw, 2.1rem);
    line-height: 1.32;
    letter-spacing: -0.005em;
    color: var(--ink);
    /* cap very long reviews so the block keeps a sane height */
    display: -webkit-box;
    -webkit-line-clamp: 8;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.reviews-featured__by {
    margin-top: auto;
    padding-top: var(--s-6);
    font-size: var(--t-body);
    color: var(--ink-soft);
}

.reviews__side {
    display: flex;
    flex-direction: column;
    gap: var(--s-5);
}
.reviews-mini {
    margin: 0;
    border-top: 1px solid var(--hairline);
    padding-top: var(--s-5);
}
.reviews-mini:first-child { border-top: 0; padding-top: 0; }
.reviews-mini__stars {
    color: var(--feature-500);
    letter-spacing: 2px;
    font-size: 0.85rem;
    line-height: 1;
}
/* Per-review stars are honest (★ filled = score, ☆ empty = remainder).
   The filled run inherits the orange; the empty run is a warm grey so the
   filled-vs-empty distinction is carried by COLOUR, not a low-contrast
   glyph outline (≈4.6:1 on bone and on the featured tint). Invisible on
   the common 5-star case — only a sub-5 review shows a grey star. */
.reviews-featured__stars .reviews__stars-off,
.reviews-mini__stars .reviews__stars-off { color: var(--stone-500); }
.reviews-mini__text {
    /* Supporting copy, not a feature pull quote — Helvetica, overriding
       the global blockquote serif/italic (tokens.css). Small italic serif
       reads too soft at this size. */
    font-family: var(--sans);
    font-style: normal;
    margin: var(--s-3) 0;
    font-size: var(--t-body);
    line-height: 1.5;
    color: var(--ink);
    display: -webkit-box;
    -webkit-line-clamp: 5;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.reviews-mini__by { font-size: var(--t-small); color: var(--ink-muted); }

/* Shared author + time treatment across featured and mini. */
.reviews__author { color: var(--ink); font-weight: 600; }
.reviews__time { color: var(--ink-muted); }
.reviews__time::before { content: " · "; }

.reviews__more {
    margin-top: var(--s-7);
    padding-top: var(--s-5);
    border-top: 1px solid var(--hairline);
    font-size: 0.9rem;
    text-align: right;
}
.reviews__more a {
    color: var(--ink);
    text-decoration: none;
    border-bottom: 1px solid var(--accent);
    padding-bottom: 2px;
}
.reviews__more a:hover { border-bottom-color: var(--feature-500); }

@media (max-width: 860px) {
    .reviews__layout { grid-template-columns: 1fr; gap: var(--s-5); }
    .reviews-featured__quote { -webkit-line-clamp: 10; }
    .reviews__side { margin-top: var(--s-2); }
}

/* ---------- Article detail (long-read editorial) ------------------ */

/* GRID RHYTHM
   ────────────────────────────────────────────────────────────────
   ONE rail, ONE rhythm. Every block on this page is a Bootstrap
   `.row` direct child of `.article`, using a single page-wide
   gutter override: `--bs-gutter-x: var(--s-8)` (52px). Set once
   on `.article .row` so every row inherits — no per-block overrides.

   `.article` lives inside <main>, which provides the rail via
       max-width: var(--maxw); padding: 0 var(--gutter)
   That rail is identical to the site-header brand-to-controls
   rail (both anchor at var(--gutter) from the viewport edges).

   Because the gutter is uniform across every row, the col-5
   grid line stays consistent: hero LEFT == body LEFT == gallery
   tile-2 LEFT. Bumping the gutter widens the visible gap between
   header↔hero, between gallery tiles, and between prev↔next,
   without breaking that alignment.

   Below lg the editorial row collapses to col-12 (header then hero stack).
   sm-md: gallery + nav split col-sm-6 (50/50 inside rail).
   Below sm: everything stacks col-12. */
.article {
    max-width: var(--maxw);
    margin: 0 auto;
}

/* Page-wide column gutter override. MUST be scoped to the `.row`
   element itself — Bootstrap's `.row` rule sets `--bs-gutter-x: 1.5rem`
   on the row, which shadows any parent declaration. Higher specificity
   here (`.article .row` = 0,2,0 vs Bootstrap's `.row` = 0,1,0) wins.

   Capped to 2× the rail padding: the row's negative outdent is
   gutter/2, and it must never exceed <main>'s --gutter or the row
   spills past the viewport. Below ~650px --gutter hits its 20px floor
   while the fixed s-8 (52px) outdent stayed 26px — a ~6px horizontal
   scroll on phones. min() keeps the full s-8 gutter wherever the rail
   is wide enough (>=650px) and shrinks it to a flush fit below that. */
.article .row {
    --bs-gutter-x: min(var(--s-8), calc(var(--gutter) * 2));
}

/* Vertical rhythm — every row separated by --s-9. Keep the rhythm on
   block-level margin (not row gutter-y) so it composes with main's
   padding box cleanly. */
.article__editorial,
.article__body-row,
.article__gallery {
    margin-bottom: var(--s-9);
}
.article > .row { --bs-gutter-y: 0; }

/* Header + hero share row 1 from md+ (≥768px): header col-md-4
   (cols 1-4), hero col-md-8 (cols 5-12). Below md both stack col-12.
   Editorial split kicks in earlier than the body/gallery/nav offset
   layouts (lg+) so the page reads as a wide editorial header even on
   smaller desktops. */
.article__head { margin: 0; }
.article__hero { margin: 0; }

.article__title {
    font-family: var(--sans);
    font-weight: 700;
    font-size: var(--t-hero);
    line-height: 1.05;
    letter-spacing: -0.015em;
    margin: 0 0 var(--s-5);
    max-width: 28ch;
    text-wrap: balance;
}

.article__byline {
    font-family: var(--sans);
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--ink-soft);
    margin: 0;
}

.article__hero img {
    width: 100%;
    height: auto;
    object-fit: cover;
    display: block;
}

.article__external {
    margin-top: var(--s-8);
    padding-top: var(--s-5);
    border-top: var(--rail-soft);
    font-size: 0.95rem;
}
.article__external a { text-decoration: none; border-bottom: 1px solid var(--hairline); }
.article__external a:hover { border-bottom-color: var(--accent); }

/* Gallery: ul.row with li.col tiles. Same Bootstrap default gutter
   as every other row on the page, so tile-2 LEFT edge sits flush
   with body LEFT edge (both at the col-5 grid line at lg+). */
.article-slides {
    list-style: none;
    padding-left: 0;
    margin-block: 0;
    --bs-gutter-y: var(--s-6);
}
.article-slide__trigger {
    display: block;
    width: 100%;
    padding: 0;
    border: 0;
    background: transparent;
    cursor: zoom-in;
    overflow: hidden;
}
.article-slide__trigger img {
    width: 100%;
    height: auto;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    display: block;
    transition: transform var(--card-img-hover-duration) var(--card-img-hover-easing);
}
.article-slide__trigger:hover img,
.article-slide__trigger:focus-visible img {
    transform: scale(var(--card-img-hover-scale));
}
.article-slide__trigger:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
}

/* ---------- Lightbox -------------------------------------------- */
/* Gallery-wall treatment — sand background (--bg-soft) so photos read
   like prints on a wall, not the usual Instagram black void. Controls
   in dark stone for contrast. The ::backdrop dims the page behind so
   the transition into the lightbox feels like entering a quiet room. */
.lightbox {
    width: 100vw;
    height: 100vh;
    max-width: none;
    max-height: none;
    margin: 0;
    padding: 0;
    border: 0;
    background: var(--bg-soft);
    color: var(--ink);
    overflow: hidden;
}
.lightbox::backdrop {
    background: rgba(15, 14, 10, 0.45);
}
.lightbox[open] {
    display: flex;
    align-items: center;
    justify-content: center;
}
.lightbox__image {
    max-width: min(90vw, 1600px);
    max-height: 86vh;
    object-fit: contain;
    display: block;
    box-shadow: var(--shadow-4);
}
.lightbox__btn {
    position: absolute;
    background: transparent;
    border: 0;
    color: var(--ink-soft);
    cursor: pointer;
    padding: var(--s-3);
    line-height: 0;
    transition: color 0.15s ease, transform 0.15s ease;
}
.lightbox__btn:hover,
.lightbox__btn:focus-visible {
    color: var(--ink);
}
.lightbox__btn:focus-visible {
    outline: 1px solid var(--ink-soft);
    outline-offset: 2px;
}
.lightbox__btn--close {
    top: var(--s-4);
    right: var(--s-4);
}
.lightbox__btn--prev,
.lightbox__btn--next {
    top: 50%;
    transform: translateY(-50%);
}
.lightbox__btn--prev { left: var(--s-4); }
.lightbox__btn--next { right: var(--s-4); }
.lightbox__btn--prev:hover { transform: translateY(-50%) translateX(-3px); }
.lightbox__btn--next:hover { transform: translateY(-50%) translateX(3px); }
.lightbox__counter {
    position: absolute;
    bottom: var(--s-5);
    left: 50%;
    transform: translateX(-50%);
    margin: 0;
    font-family: var(--sans);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.18em;
    color: var(--ink-soft);
}

@media (max-width: 560px) {
    .lightbox__btn--prev { left: 0; }
    .lightbox__btn--next { right: 0; }
    .lightbox__image { max-width: 96vw; }
}

/* Nav rides the same single rail. Prev in cols 5-8 (matches body's
   col-lg-8 offset-lg-4 left edge), next in cols 9-12. Below lg falls
   back to col-sm-6 (50/50 side-by-side); below sm fully stacks. Shares
   Bootstrap's default gutter with every other row on the page. */
.article__nav {
    margin-top: var(--s-9);
    padding-top: var(--s-6);
    border-top: var(--rail-soft);
    --bs-gutter-y: var(--s-5);
}

/* When only one direction exists, push it to the right side of the row.
   Margin-left auto in a flex container takes all available space as left
   margin, anchoring the single link at the right edge — keeps "only next"
   visually correct (and "only prev" already sits at offset-lg-4). */
.article__nav-link:only-child {
    margin-left: auto;
}
.article__nav-link {
    display: flex;
    flex-direction: column;
    gap: var(--s-2);
    text-decoration: none;
    color: inherit;
}
/* Right-align only when prev/next sit side-by-side (Bootstrap sm and up).
   Below sm they stack and read left-aligned. */
@media (min-width: 576px) {
    .article__nav-link--next { text-align: right; }
}
.article__nav-label {
    font-family: var(--sans);
    font-size: 0.72rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ink-soft);
}
.article__nav-title {
    font-family: var(--serif);
    font-style: italic;
    font-size: 1.1rem;
    line-height: 1.3;
    color: var(--ink);
}

/* News-index intro lede. The intro paragraph is an .element-textext block
   (migrated by `migrate-article-holder-intro`) sitting as the first child
   of .page__elements, directly under the page__head. As an Elemental
   <section> it inherited the universal section rhythm padding — `.element >
   section { padding-top: var(--s-11) }` (128px, ~line 3258) — on top of its
   own s-9 (72px) block margin, opening a ~200px void below the "News"
   headline. That generous rhythm is for sections deep in a page, not the
   lede right under the title. Strip both on the first block so the lede
   reads as the title's subtitle: title → lede → list flows tight, the gap
   below the headline becoming just the page__head's own margin. */
.article-holder .page__head {
    margin-bottom: var(--s-6);
}
/* Same lede-tightening for the activity catalogue (ProductGroupPage): its
   intro text block is also the first .page__elements child and carried the
   same s-11 void — here below the inline sub-nav rather than the head. The
   sub-nav already supplies the breathing band, so just strip the block's
   own top rhythm. */
.article-holder .page__elements > .element:first-child,
.article-holder .page__elements > .element:first-child > section,
.t-App\\PageType\\ProductGroupPage .page__elements > .element:first-child,
.t-App\\PageType\\ProductGroupPage .page__elements > .element:first-child > section {
    margin-top: 0;
    padding-top: 0;
}

/* ---------- Article list ------------------------------------------ */

/* News index — featured article on top (image left, copy right magazine
   spread), then 2-up grid below with thumbnail + body. Articles' first
   PageSlide image is used as the thumbnail (706 slides exist across 110
   articles in the legacy import). */
.article-holder .article-list {
    margin-top: var(--s-8);
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--s-7) var(--s-6);
    max-width: none;
}
.article-holder .article-card {
    display: flex;
    flex-direction: column;
    text-decoration: none;
    color: inherit;
    border: 1px solid var(--hairline);
    border-radius: var(--r-md);
    overflow: hidden;
    background: var(--surface);
    padding: 0;
    transition: transform 220ms var(--ease), box-shadow 220ms var(--ease);
}
.article-holder .article-card--featured {
    grid-column: span 2;
    flex-direction: row;
    align-items: stretch;
}
.article-holder .article-card--featured .article-card__photo {
    flex: 1 1 55%;
    margin: 0;
    aspect-ratio: auto;
    min-height: 100%;
}
.article-holder .article-card--featured .article-card__body {
    flex: 1 1 45%;
    padding: var(--s-7);
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: var(--s-3);
}
.article-holder .article-card--featured .article-card__title {
    font-size: var(--t-h1);
    line-height: 1.05;
    letter-spacing: -0.02em;
    max-width: 22ch;
}
.article-holder .article-card--featured .article-card__summary {
    font-size: 1.1rem;
    line-height: 1.5;
}

.article-card__photo {
    margin: 0;
    aspect-ratio: 8 / 5;
    overflow: hidden;
    background: var(--stone-200);
}
.article-card__photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.article-holder .article-card__body {
    padding: var(--s-5);
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
    flex: 1;
}

@media (max-width: 800px) {
    .article-holder .article-list { grid-template-columns: 1fr; gap: var(--s-7); }
    .article-holder .article-card--featured { grid-column: auto; flex-direction: column; }
    .article-holder .article-card--featured .article-card__photo { aspect-ratio: 8 / 5; flex: none; min-height: 0; }
    /* Tighter inner padding on full-width mobile cards (was 24px / 36px featured). */
    .article-holder .article-card__body,
    .article-holder .article-card--featured .article-card__body { padding: var(--s-4); }
}

/* Article-related sidebars (article detail page) keep the simple
   single-column flow — overrides on the holder only. */
.article-list {
    margin-top: var(--s-8);
    display: flex;
    flex-direction: column;
    gap: var(--s-8);
    max-width: var(--measure);
}

.article-card {
    padding-bottom: var(--s-6);
    border-bottom: var(--rail);
}
.article-holder .article-card { border-bottom: none; padding-bottom: 0; }
.article-list .article-card:last-child { border-bottom: none; }

.article-card__date {
    font-family: var(--sans);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--accent);
}
.article-card__title {
    font-size: var(--t-h2);
    line-height: 1.15;
    margin: var(--s-3) 0 var(--s-3);
    letter-spacing: -0.01em;
    text-wrap: balance;
}
.article-card__title a {
    color: inherit;
    text-decoration: none;
}
.article-card__byline {
    font-size: 0.85rem;
    color: var(--ink-soft);
    margin: 0 0 var(--s-4);
}
.article-card__summary {
    margin: 0;
    color: var(--ink-soft);
}
.article-card__more {
    margin-top: var(--s-4);
    font-size: 0.9rem;
}
.article-card__more a {
    text-decoration: none;
    color: var(--ink);
    border-bottom: 1px solid var(--hairline);
    padding-bottom: 1px;
}
.article-card__more a:hover { border-bottom-color: var(--accent); color: var(--accent); }

/* ---------- Team grid --------------------------------------------- */

.team-grid {
    margin-top: var(--s-8);
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    gap: var(--s-6);
}

.team-card {
    grid-column: span 12;
    display: flex;
    flex-direction: column;
    text-decoration: none;
    color: inherit;
}
@media (min-width: 820px) {
    .team-card { grid-column: span 6; }
}
@media (min-width: 1200px) {
    .team-card { grid-column: span 3; }
}
/* DMC team block (ElementLocalTeam, nested in .home-section) becomes a
   horizontal scroll-snap rail on mobile, faithfully matching the
   .service-tiles / .sister-brands rails. Scoped via `.home-section` so the
   standalone team page (TeamMemberHolder.ss — .team-grid sits in .page with
   NO .home-section ancestor) is left as the desktop->single-column stack and
   is NOT turned into a horizontal scroller. The rail bleeds to the section
   edge by cancelling .home-section's own --gutter padding with a negative
   margin-inline; a sliver of the next card hints at scrollability. The
   desktop grid (min-width:820px) is untouched. (2026-06-05) */
@media (max-width: 819px) {
    .home-section .team-grid {
        grid-template-columns: none;
        grid-auto-flow: column;
        grid-auto-columns: 64%;
        gap: var(--s-5);
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        scroll-padding-left: var(--gutter);
        margin-inline: calc(-1 * var(--gutter));
        padding: 0 var(--gutter) var(--s-4);
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }
    .home-section .team-grid::-webkit-scrollbar { display: none; }
    .home-section .team-card {
        grid-column: auto;
        scroll-snap-align: start;
        min-width: 0;
    }
    .home-section .team-card__photo { min-width: 0; }
    .home-section .team-card__name { overflow-wrap: anywhere; }
}
@media (max-width: 540px) {
    .home-section .team-grid { grid-auto-columns: 82%; gap: var(--s-4); }
}

/* Standalone team page (TeamMemberHolder.ss): .team-grid is a direct child
   of <article class="page"> — NOT inside .home-section — so the rail rules
   above never reach it. It must still collapse to a single column on mobile,
   otherwise the desktop repeat(12,1fr) grid with grid-column:span 12 stacks
   11 column-gaps inside one card and overflows the viewport. This restores
   the pre-2026-06-05 single-column fix, now scoped to .page > .team-grid so
   it cannot touch the DMC rail. (2026-06-05) */
@media (max-width: 819px) {
    .page > .team-grid { grid-template-columns: 1fr; }
    .page > .team-grid .team-card {
        grid-column: auto;
        min-width: 0;
    }
    .page > .team-grid .team-card__photo { min-width: 0; }
    .page > .team-grid .team-card__name { overflow-wrap: break-word; }
}

.team-card__photo {
    margin: 0 0 var(--s-4);
    aspect-ratio: 3 / 2;
    overflow: hidden;
    background: var(--hairline-soft);
}
.team-card__photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.team-card__photo--empty {
    width: 100%;
    height: 100%;
    background: var(--hairline-soft);
}

.team-card__body {
    padding: var(--s-4) 0;
}
.team-card__name {
    font-size: 1.25rem;
    line-height: 1.2;
    margin: 0;
}
.team-card__role {
    font-size: 0.85rem;
    color: var(--ink-soft);
    margin: var(--s-1) 0 0;
}

/* ---------- Pagination -------------------------------------------- */

.pagination {
    margin-top: var(--s-8);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--s-5);
    flex-wrap: wrap;
    font-size: 0.9rem;
}
.pagination__pages {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    gap: var(--s-2);
}
.pagination__page {
    padding: var(--s-2) var(--s-4);
    border: 1px solid transparent;
    color: var(--ink-soft);
}
.pagination__page a {
    color: var(--ink-soft);
    text-decoration: none;
}
.pagination__page a:hover { color: var(--accent); }
.pagination__page--current {
    border-color: var(--accent);
    color: var(--ink);
}
.pagination__page--gap { border: none; padding: 0 var(--s-1); }
.pagination__link {
    color: var(--ink);
    text-decoration: none;
    padding: var(--s-2) var(--s-4);
    border: 1px solid var(--hairline);
}
.pagination__link:hover { border-color: var(--accent); }

.empty {
    margin-top: var(--s-8);
    color: var(--ink-soft);
    text-align: center;
    font-style: italic;
}

/* ---------- FAQ accordion ----------------------------------------- */

.faq {
    max-width: var(--maxw);
    margin: var(--s-9) auto 0;
    padding: var(--s-6) var(--gutter) var(--s-9);
    border-top: var(--rail);
}
.faq__cols {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--s-6);
}
@media (min-width: 820px) {
    .faq__cols {
        grid-template-columns: 1fr 1.4fr;
        gap: var(--s-8);
        align-items: start;
    }
}
.faq__title {
    font-family: var(--sans);
    font-size: var(--t-h2);
    margin: 0;
    letter-spacing: -0.005em;
}
.faq__list {
    display: flex;
    flex-direction: column;
}
.faq__item {
    border-bottom: var(--rail);
}
.faq__question {
    list-style: none;
    padding: var(--s-4) 0;
    cursor: pointer;
    font-family: var(--sans);
    font-weight: 500;
    font-size: 1rem;
    color: var(--ink);
    position: relative;
    padding-right: var(--s-6);
}
.faq__question::-webkit-details-marker { display: none; }
.faq__question:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
    border-radius: var(--r-xs);
}
.faq__question::after {
    content: "+";
    position: absolute;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    font-family: var(--sans);
    font-size: 1.5rem;
    font-weight: 300;
    color: var(--ink-soft);
    transition: transform 150ms ease;
}
.faq__item[open] > .faq__question::after {
    content: "\2212"; /* minus */
}
.faq__answer {
    padding: 0 0 var(--s-5);
    color: var(--ink-soft);
}
.faq__answer p:last-child { margin-bottom: 0; }

/* Scope the full-bleed section wrapper inside DMCPage so FAQ sits in gutter */
.dmc .home-section .faq { margin-top: 0; padding-top: 0; border-top: 0; }

/* ---------- RFP form (ContactPage dark-surface pattern) -------------
   Per design system patterns.html (Inquiry / RFP form). Full-bleed
   --accent-deep section, two-column inner: copy left + form card
   (white surface) right. The form fields keep their existing
   .contact-form styles inside .rfp__card; only colors & padding
   change to suit the white surface within a dark frame. */

/* Neutralise main on ContactPage so .rfp fills viewport edge-to-edge. */
.t-App\\PageType\\ContactPage main {
    max-width: none;
    padding: 0;
}
.rfp {
    background: var(--accent-deep);
    color: #fff;
    padding: var(--s-9) 0 var(--s-10);
    --ink:       #f4f1ea;
    --ink-soft:  rgba(244, 241, 234, 0.78);
    --ink-muted: rgba(244, 241, 234, 0.55);
    font-weight: 400;   /* light-on-dark: stay regular (base sans is 300) */
}
.rfp__inner {
    max-width: var(--maxw);
    margin: 0 auto;
    padding: 0 var(--gutter);
    display: grid;
    grid-template-columns: 1fr 1.2fr;
    gap: var(--s-9);
    align-items: start;
}
@media (max-width: 900px) {
    .rfp__inner { grid-template-columns: 1fr; gap: var(--s-7); }
}

.rfp__copy > .t-eyebrow {
    margin: 0 0 var(--s-4);
}
.rfp__title {
    color: #fff;
    margin: 0 0 var(--s-4);
    max-width: 18ch;
    font-size: clamp(28px, 3.2vw, 40px);
    line-height: 1.1;
    letter-spacing: -0.02em;
}
.rfp__lead {
    font-family: var(--serif);
    font-size: clamp(1.15rem, 2vw, 1.4rem);
    font-style: italic;
    line-height: 1.4;
    color: rgba(255, 255, 255, 0.92);
    margin: 0 0 var(--s-5);
    /* Hold the lede to a reading measure so it doesn't run the full copy
       column on desktop. Only bites >~480px-wide columns, so the narrower
       mobile column is unaffected. */
    max-width: 20em;
}
/* Step list — numbered serif, hairline above each step. */
.rfp__steps {
    list-style: none;
    padding: 0;
    margin: var(--s-6) 0 0;
    display: flex;
    flex-direction: column;
    gap: 0;
}
.rfp__step {
    display: grid;
    grid-template-columns: 60px 1fr;
    gap: var(--s-4);
    align-items: baseline;
    padding: var(--s-4) 0;
    border-top: 1px solid rgba(255, 255, 255, 0.18);
}
.rfp__step:last-child { border-bottom: 1px solid rgba(255, 255, 255, 0.18); }
.rfp__step-num {
    font-family: var(--sans);
    font-size: 22px;
    font-feature-settings: "tnum", "lnum";
    color: var(--feature);
}
.rfp__step-text {
    font-size: 14px;
    line-height: 1.5;
    color: rgba(255, 255, 255, 0.92);
}

/* Trust signal under the step list — small Travelife seal + one-line
   factual context. Hairline above is implied by the .rfp__step:last-child
   bottom border. No background, no card; the logo is a self-contained
   stamp on the dark band. */
/* Google rating — quiet numeric proof on the dark band, above the
   Travelife badge. Star is the one small logo-orange accent. */
.rfp__rating {
    display: flex;
    align-items: baseline;
    gap: 6px;
    margin: var(--s-6) 0 0;
    font-family: var(--sans);
    font-size: 0.95rem;
    color: rgba(255, 255, 255, 0.82);
}
.rfp__rating-star { color: var(--feature); }
.rfp__rating-value { font-weight: 600; color: #fff; }
.rfp__rating-count { color: rgba(255, 255, 255, 0.6); }

.rfp__trust {
    display: flex;
    align-items: center;
    gap: var(--s-4);
    margin: var(--s-5) 0 0;
    padding: 0;
    text-decoration: none;
    color: inherit;
}
.rfp__trust:hover .rfp__trust-text,
.rfp__trust:focus-visible .rfp__trust-text {
    color: #fff;
}
.rfp__trust-logo {
    flex: 0 0 auto;
    width: 120px;
    height: auto;
    display: block;
}
.rfp__trust-text {
    font-size: 13px;
    line-height: 1.5;
    color: rgba(255, 255, 255, 0.7);
    transition: color 160ms var(--ease);
}
@media (max-width: 480px) {
    .rfp__trust { gap: var(--s-3); }
    .rfp__trust-logo { width: 96px; }
}

/* Form card — white surface, generous padding, design-system rounding.
   Reset the ink tokens here: the parent .rfp block flips them to cream
   for the dark band, which would render cream-on-white inside this card. */
.rfp__card {
    background: var(--surface);
    --ink:       #211c19;            /* PROVISIONAL warm near-black — was #0f2236 */
    --ink-soft:  rgba(33, 28, 25, 0.78);
    --ink-muted: rgba(33, 28, 25, 0.55);
    color: var(--ink);
    border-radius: var(--r-lg);
    padding: var(--s-7) var(--s-7);
    box-shadow: var(--shadow-2);
}
@media (max-width: 720px) {
    .rfp__card { padding: var(--s-5) var(--s-4); }
}

/* ---------- Homepage proposal CTA ---------------------------------
   Conversion endpoint at the homepage tail. Teaser variant of the
   .rfp pattern: full-bleed --accent-deep, single-column copy + steps
   + primary CTA → ContactPage. No form (the form lives on the RFP
   page itself). DS reference: homepage.html · formSec section. */
.home-rfp-cta {
    background: var(--bg-deep);
    color: #fff;
    padding: var(--s-9) 0 var(--s-10);
    margin-top: var(--s-8);
    --ink:       #f4f1ea;
    --ink-soft:  rgba(244, 241, 234, 0.78);
    --ink-muted: rgba(244, 241, 234, 0.55);
    font-weight: 400;   /* light-on-dark: stay regular (base sans is 300) */
}
.home-rfp-cta__inner {
    max-width: var(--maxw);
    margin: 0 auto;
    padding: 0 var(--gutter);
}
.home-rfp-cta__eyebrow {
    margin: 0 0 var(--s-4);
}
.home-rfp-cta__title {
    font-family: var(--sans);
    font-size: var(--t-display);
    line-height: 1.08;
    letter-spacing: -0.018em;
    color: #fff;
    margin: 0 0 var(--s-5);
    max-width: 18ch;
}
.home-rfp-cta__lead {
    font-size: 1.125rem;
    line-height: 1.6;
    color: rgba(255, 255, 255, 0.92);
    margin: 0 auto var(--s-7);
    /* Hold the centred lede to a reading measure — it was running the full
       ~1344px band width edge-to-edge. */
    max-width: 42rem;
}
.home-rfp-cta__steps {
    list-style: none;
    padding: 0;
    margin: 0 0 var(--s-7);
    display: flex;
    flex-direction: column;
    gap: 0;
}
.home-rfp-cta__step {
    display: grid;
    grid-template-columns: 60px 1fr;
    gap: var(--s-4);
    align-items: baseline;
    padding: var(--s-4) 0;
    border-top: 1px solid rgba(255, 255, 255, 0.18);
}
.home-rfp-cta__step:last-child { border-bottom: 1px solid rgba(255, 255, 255, 0.18); }
.home-rfp-cta__step-num {
    font-family: var(--sans);
    font-size: 22px;
    font-feature-settings: "tnum", "lnum";
    color: var(--feature);
}
.home-rfp-cta__step-text {
    font-size: 14px;
    line-height: 1.5;
    color: rgba(255, 255, 255, 0.92);
}
.home-rfp-cta__btn { align-self: start; }
@media (max-width: 720px) {
    .home-rfp-cta { padding: var(--s-7) 0 var(--s-8); }
    .home-rfp-cta__step { grid-template-columns: 44px 1fr; gap: var(--s-3); }
}

/* Centered variant — used at the homepage tail where the band stands
   alone (no left-aligned page rhythm to follow). Title, lede and steps
   align to the center axis; step rows keep the number + text pair but
   collapse to auto columns so the pair centers within its hairline row.
   Button centers via inline-block + text-align on the inner. */
.home-rfp-cta--center { text-align: center; }
.home-rfp-cta--center .home-rfp-cta__title,
.home-rfp-cta--center .home-rfp-cta__lead,
.home-rfp-cta--center .home-rfp-cta__steps { margin-inline: auto; }
.home-rfp-cta--center .home-rfp-cta__title {
    max-width: 24ch;
    line-height: 1.15;
}
.home-rfp-cta--center .home-rfp-cta__step {
    grid-template-columns: auto auto;
    justify-content: center;
    text-align: left;
}

/* ---------- DMC local office (Ibiza / Malta) ---------------------- */
/* Quiet grounding band shown only on DMC pages whose Location carries a
   registered office address. Light, type-driven; sits directly above the
   dark RFP CTA so the page reads office -> brief-us. Self-bound because
   DMC pages run on a stripped (full-bleed) main. */
.dmc-office {
    padding: var(--s-8) 0 0;
}
.dmc-office__inner {
    max-width: var(--maxw);
    margin: 0 auto;
    padding: 0 var(--gutter);
}
.dmc-office__eyebrow { margin: 0 0 var(--s-3); }
.dmc-office__place {
    font-family: var(--sans);
    font-size: var(--t-h2);
    font-weight: 700;
    line-height: var(--lh-snug);
    letter-spacing: -0.005em;
    color: var(--ink);
    margin: 0 0 var(--s-3);
}
.dmc-office__address {
    font-style: normal;
    font-size: var(--t-body-lg);
    line-height: var(--lh-loose);
    color: var(--ink-soft);
}

/* ---------- Contact page — regional offices list ------------------ */
/* Offices with a registered address (Ibiza, Malta). Palma head office
   shows in the global footer, so it is not repeated. Bootstrap row > cols.
   Self-bound — contact runs on a stripped main. */
.contact-offices {
    padding: 0 0 var(--s-9);
}
.contact-offices__inner {
    max-width: var(--maxw);
    margin: 0 auto;
    padding: 0 var(--gutter);
}
.contact-offices__eyebrow { margin: 0 0 var(--s-3); }
.contact-offices__title {
    font-family: var(--sans);
    font-size: var(--t-h1);
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -0.015em;
    color: var(--ink);
    margin: 0 0 var(--s-6);
    max-width: 18ch;
}
.contact-offices__grid { row-gap: var(--s-6); }
.contact-offices__place {
    font-family: var(--sans);
    font-size: var(--t-h3);
    font-weight: 700;
    line-height: var(--lh-snug);
    color: var(--ink);
    margin: 0 0 var(--s-2);
}
.contact-offices__address {
    font-style: normal;
    font-size: var(--t-body-lg);
    line-height: var(--lh-loose);
    color: var(--ink-soft);
}

/* ---------- Contact page (head + body wrapper) -------------------- */
/* Page-level editorial frame ABOVE the RfpForm partial. The partial
   carries its own dark band + form card, so this block stays light
   and type-driven — eyebrow / hero-level title / supporting lede /
   breathing room. */
.contact-page__head {
    padding: var(--s-9) 0 var(--s-8);
    margin: 0 auto;
    max-width: var(--maxw);
}
.contact-page__eyebrow {
    margin: 0 0 var(--s-4);
}
.contact-page__title {
    font-family: var(--sans);
    font-size: var(--t-hero);
    font-weight: 700;
    line-height: 1.04;
    letter-spacing: -0.02em;
    color: var(--ink);
    margin: 0 0 var(--s-5);
    max-width: 14ch;
}
.contact-page__body {
    max-width: var(--maxw);
    margin: 0 auto var(--s-8);
}
.contact-page.page--has-hero .contact-page__body { margin-top: var(--s-7); }
@media (max-width: 720px) {
    .contact-page__head { padding: var(--s-7) 0 var(--s-6); }
}

/* ---------- Contact form ------------------------------------------ */

.contact-form { max-width: var(--measure); margin-inline: auto; }
.contact-form form { margin-top: var(--s-6); }

/* SilverStripe wraps the whole form in <fieldset>; browsers give that a
   default border + inset padding. Strip both so the form sits flush
   against the surrounding card. */
.contact-form fieldset {
    border: 0;
    margin: 0;
    padding: 0;
    min-width: 0;
}

/* Hide the honeypot field — legitimate users never see it */
.contact-form #ContactForm_ContactForm_Website_Holder,
#ContactForm_ContactForm input[name="Website"] { position: absolute; left: -9999px; }

.contact-form .field {
    margin-bottom: var(--s-6);
    display: flex;
    flex-direction: column;
}
.contact-form label.left,
.contact-form label {
    font-family: var(--sans);
    font-size: 0.875rem;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
    color: var(--ink-soft);
    margin-bottom: var(--s-2);
}
.contact-form input[type="text"],
.contact-form input[type="email"],
.contact-form textarea,
.contact-form select {
    font-family: var(--sans);
    font-size: 0.875rem;
    padding: var(--s-4) 0;
    border: none;
    border-bottom: 1px solid var(--hairline-strong);
    background: transparent;
    color: var(--ink);
    width: 100%;
    transition: border-color 150ms ease;
}
.contact-form input:focus,
.contact-form textarea:focus,
.contact-form select:focus {
    outline: none;
    border-bottom-color: var(--ink);
    /* Doubles the underline to 2px without shifting layout — a darker
       1px line alone is too small a delta to read as "focused". */
    box-shadow: 0 1px 0 var(--ink);
}
.contact-form textarea { resize: vertical; min-height: 8rem; }

/* Native <select> — strip browser chrome, replace with editorial caret. */
.contact-form select {
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%2336302c' stroke-width='1.4' stroke-linecap='round'><path d='M1 1.5l5 5 5-5'/></svg>");
    background-repeat: no-repeat;
    background-position: right 4px center;
    background-size: 12px 8px;
    padding-right: var(--s-6);
    cursor: pointer;
}

/* Two-column field rows — wraps a FieldGroup in PHP. SS6's FieldGroup
   nests its children inside `.middleColumn.fieldgroup`, so the grid
   lives on that inner element, not the outer .field-row wrapper. */
.contact-form .field-row { margin-bottom: var(--s-6); }
.contact-form .field-row > .middleColumn.fieldgroup {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--s-4) var(--s-6);
}
.contact-form .field-row .fieldgroup-field { margin: 0; }
.contact-form .field-row .fieldholder-small { margin: 0; display: flex; flex-direction: column; }
@media (max-width: 600px) {
    .contact-form .field-row > .middleColumn.fieldgroup { grid-template-columns: 1fr; }
}

/* Chip multi-select — styles each <input type="checkbox"> + <label>
   pair inside a CheckboxSetField as a borderless toggle button. The
   real input is hidden; the label carries the visible state. */
.contact-form .chip-set { margin-bottom: var(--s-6); }
.contact-form .chip-set > label {
    /* The fieldset legend / outer label */
    display: block;
    margin-bottom: var(--s-3);
}
.contact-form .chip-set ul.checkboxset {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--s-2);
}
@media (max-width: 600px) {
    .contact-form .chip-set ul.checkboxset { grid-template-columns: repeat(2, 1fr); }
}
.contact-form .chip-set ul.checkboxset li { margin: 0; }
.contact-form .chip-set ul.checkboxset input[type="checkbox"] {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}
.contact-form .chip-set ul.checkboxset label {
    display: block;
    text-align: center;
    padding: var(--s-3) var(--s-4);
    font-family: var(--sans);
    font-size: 0.875rem;
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    color: var(--ink);
    background: #fff;
    border: 1px solid var(--ink);
    border-radius: var(--r-sm);
    cursor: pointer;
    transition: background 150ms ease, color 150ms ease, border-color 150ms ease;
    margin: 0;
}
.contact-form .chip-set ul.checkboxset label:hover {
    background: var(--bg-soft);
}
.contact-form .chip-set ul.checkboxset input[type="checkbox"]:checked + label {
    background: var(--accent);
    color: var(--accent-ink, #fff);
    border-color: var(--accent);
}
.contact-form .chip-set ul.checkboxset input[type="checkbox"]:focus-visible + label {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.contact-form .field.checkbox {
    flex-direction: row;
    gap: var(--s-4);
    align-items: flex-start;
    padding-top: var(--s-4);
}
.contact-form .field.checkbox input { margin-top: 0.3rem; }
.contact-form .field.checkbox label {
    font-family: var(--sans);
    font-size: 0.875rem;
    text-transform: none;
    letter-spacing: 0;
    color: var(--ink-soft);
    /* SS adds .right to checkbox labels (framework CSS sets text-align:
       right); force left so the consent text reads ragged-right, esp.
       when the longer DE string wraps. */
    text-align: left;
}
.contact-form .field.checkbox label a { color: var(--ink); text-underline-offset: 3px; }

/* Privacy-policy link sits below the checkbox as its own field. Plain
   serif size, accent-blue link, sits with the same indent as the
   checkbox label so it reads as belonging to the consent block. */
.form-terms-link {
    margin: calc(-1 * var(--s-3)) 0 var(--s-5);
    padding-left: 1.6rem;
    font-family: var(--sans);
    font-size: 0.875rem;
    color: var(--ink-soft);
}
.form-terms-link a {
    color: var(--accent);
    text-decoration: none;
    border-bottom: 1px solid var(--accent-soft);
    padding-bottom: 1px;
}
.form-terms-link a:hover { border-bottom-color: var(--accent); }

.contact-form .message {
    padding: var(--s-4) var(--s-5);
    margin: 0 0 var(--s-5);
    border-left: 2px solid var(--accent-deep);
    background: var(--hairline-soft);
    font-family: var(--sans);
    font-size: 0.875rem;
    color: var(--ink);
}
.contact-form .message.bad { border-left-color: var(--accent); }

/* Zero layout shift on validation. Per-field messages (client- or
   server-side) are pulled out of flow and floated into the gap below
   their field, so showing/hiding an error never reflows the form while
   the user is filling it in. The form-level .message banner is a direct
   child of <form> (not inside a .field), so it keeps its boxed style. */
.contact-form .field,
.contact-form .fieldholder-small { position: relative; }
.contact-form .field .message,
.contact-form .field .error,
.contact-form .field .validation {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    margin: 3px 0 0;
    padding: 0;
    border: 0;
    background: none;
    font-family: var(--sans);
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1.3;
    color: var(--error);
}
/* Invalid field: tint the underline to match its message. .has-error is
   added by contact-validation.js to the field holder. */
.contact-form .has-error input,
.contact-form .has-error textarea,
.contact-form .has-error select { border-bottom-color: var(--error); }

/* ---------- Enquiry modal shell -----------------------------------
   Shared by BOTH enquiry dialogs (contact-panel.js initModal): #contact-modal
   (.contact-modal — WhatsApp/Call + quick message) and #rfp-modal (.rfp-modal —
   the proposal brief, RfpModal.ss). Both selector groups are LOAD-BEARING — do
   not drop `.rfp-modal`. The contact modal's channels live in contact-panel.css. */
.rfp-modal,
.contact-modal {
    width: min(560px, calc(100vw - var(--s-6)));
    max-height: calc(100dvh - var(--s-8));
    padding: 0;
    border: none;
    border-radius: var(--r-lg);
    background: var(--surface);
    color: var(--ink);
    box-shadow: var(--shadow-4);
    overflow: auto;
    overscroll-behavior: contain;
}
.rfp-modal::backdrop,
.contact-modal::backdrop {
    background: rgba(20, 16, 14, 0.55);
    backdrop-filter: blur(2px);
}
.rfp-modal__panel,
.contact-modal__panel { position: relative; padding: var(--s-7); }
.rfp-modal__close,
.contact-modal__close {
    position: absolute;
    top: var(--s-4);
    right: var(--s-4);
    width: 40px;
    height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    border-radius: var(--r-pill);
    color: var(--ink-soft);
    cursor: pointer;
    transition: background 150ms ease, color 150ms ease;
}
.rfp-modal__close:hover,
.rfp-modal__close:focus-visible,
.contact-modal__close:hover,
.contact-modal__close:focus-visible { background: var(--bg-elev); color: var(--ink); }
.rfp-modal__close:focus-visible,
.contact-modal__close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.rfp-modal__title,
.contact-modal__title {
    font-size: clamp(24px, 4vw, 32px);
    line-height: 1.1;
    letter-spacing: -0.02em;
    margin: var(--s-2) var(--s-8) var(--s-3) 0;
}
.rfp-modal__lede,
.contact-modal__lede { color: var(--ink-soft); margin: 0 0 var(--s-5); max-width: 46ch; }
.rfp-modal .contact-form,
.contact-modal .contact-form { max-width: none; }
.rfp-modal .contact-form form,
.contact-modal .contact-form form { margin-top: 0; }
.rfp-modal__thanks,
.contact-modal__thanks { padding: var(--s-6) 0; }
.rfp-modal__thanks-title,
.contact-modal__thanks-title { font-size: clamp(22px, 3.5vw, 28px); line-height: 1.15; margin: 0 0 var(--s-3); }
.rfp-modal__thanks-lede,
.contact-modal__thanks-lede { color: var(--ink-soft); margin: 0 0 var(--s-6); max-width: 42ch; }
@media (max-width: 600px) {
    .rfp-modal,
    .contact-modal {
        /* Full-screen sheet. Use 100% (not 100vw): a top-layer <dialog>'s
           containing block IS the viewport, so 100% fills it exactly, while
           100vw counts the scrollbar gutter and spills ~8–15px wider. Because
           the root overflow-x:clip guard is intentionally OFF on touch devices
           (see top of file), that spill has nothing to contain it and the whole
           page scrolls sideways on iOS/Android with the modal open. margin:0
           overrides the UA dialog's centring auto-margins so the sheet stays
           flush at the top-left. */
        width: 100%;
        max-width: 100%;
        height: 100dvh;
        max-height: 100dvh;
        margin: 0;
        border-radius: 0;
    }
    .rfp-modal__panel,
    .contact-modal__panel {
        padding: var(--s-8) var(--s-5) var(--s-6);
        /* Full-screen sheet (100dvh) under viewport-fit=cover: keep the submit
           button above the iOS home indicator. */
        padding-bottom: calc(var(--s-6) + env(safe-area-inset-bottom, 0px));
    }
}

.contact-form .Actions { margin-top: var(--s-8); }
.contact-form button,
.contact-form input[type="submit"] {
    font-family: var(--sans);
    font-size: 0.875rem;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
    padding: var(--s-4) var(--s-8);
    background: var(--accent);
    color: var(--accent-ink);
    border: none;
    border-radius: var(--r-sm);
    cursor: pointer;
    transition: background 200ms ease, transform 180ms var(--ease);
}
.contact-form button:hover,
.contact-form input[type="submit"]:hover {
    background: var(--accent-deep);
    transform: translateY(-1px);
}
/* Mirror the prototype's "Send brief →" — append an arrow glyph
   after the action text via a pseudo-element so editors don't have
   to type it into the FormAction title. */
.contact-form .btn-with-arrow::after {
    content: " →";
    display: inline-block;
    margin-left: 0.4em;
    transition: transform 180ms var(--ease);
}
.contact-form .btn-with-arrow:hover::after {
    transform: translateX(2px);
}

/* Field-level validation output from the SS form system */
.contact-form .message.required { content: ""; }
/* Quiet required marker so planners see which fields matter BEFORE they
   submit (it was previously blanked). SS marks required via the input's
   [required] attribute, not a wrapper class, so target the label that
   immediately precedes a required control. Monochrome — info, not colour.
   The textarea/select variants need the `.middleColumn` hop because SS
   wraps those controls (the label is the wrapper's sibling, not the
   control's); the checkbox renders its label AFTER the input. */
.contact-form label:has(~ input[required])::after,
.contact-form label:has(~ textarea[required])::after,
.contact-form label:has(~ select[required])::after,
.contact-form label:has(~ .middleColumn input[required])::after,
.contact-form label:has(~ .middleColumn textarea[required])::after,
.contact-form label:has(~ .middleColumn select[required])::after,
.contact-form input[type="checkbox"][required] ~ label::after {
    content: "*";
    margin-left: 4px;
    color: var(--ink-muted);
    font-weight: 500;
}
/* Per-field error styling (burgundy, AA on the light --surface card) is
   handled by the consolidated zero-shift float rule above, which also
   covers .error / .validation. */

/* Mobile: keep the form compact. The underline fields are airy on a phone,
   so tighten field padding and inter-field spacing without touching the
   desktop rhythm. Placed at the end of the section so these overrides win
   on source order over the equal-specificity base rules above. */
@media (max-width: 720px) {
    .contact-form form { margin-top: var(--s-4); }
    .contact-form .field { margin-bottom: var(--s-5); }
    .contact-form .field-row { margin-bottom: var(--s-5); }
    /* Stacked groups: 24px row-gap leaves room for a floated 1-line error
       under the first field without it touching the next label. */
    .contact-form .field-row > .middleColumn.fieldgroup { gap: var(--s-5); }
    .contact-form label { margin-bottom: var(--s-1); }
    /* ≥16px controls — anything smaller makes iOS Safari zoom-jump the
       whole page the moment a field is focused. */
    .contact-form input[type="text"],
    .contact-form input[type="email"],
    .contact-form textarea,
    .contact-form select { padding: var(--s-3) 0; font-size: 1rem; }
    .contact-form textarea { min-height: 6rem; }
    .contact-form .chip-set { margin-bottom: var(--s-5); }
    .contact-form .Actions { margin-top: var(--s-6); }
}

/* ---------- Search ------------------------------------------------ */

.visually-hidden {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0,0,0,0);
    white-space: nowrap; border: 0;
}

/* Header search: icon trigger + full-screen centered <dialog> modal.
   Replaces the old inline input. Native <dialog> handles focus trap +
   ESC; JS in themes/lxp/js/search-modal.js wires the opener + backdrop
   close + focus restoration. */
.site-search-trigger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    background: transparent;
    border: 0;
    color: var(--ink-soft);
    cursor: pointer;
    transition: color 120ms ease;
}
.site-search-trigger:hover,
.site-search-trigger:focus-visible { color: var(--ink); }
.site-search-trigger:focus-visible { outline: 1px solid var(--accent); outline-offset: 2px; }
.site-search-trigger svg { display: block; }

.search-modal {
    margin: auto;
    padding: var(--s-8);
    border: 0;
    background: var(--surface);
    color: var(--ink);
    max-width: 680px;
    width: calc(100vw - var(--s-6));
}
.search-modal[open] { animation: searchModalIn 180ms ease-out both; }
/* Touch users have no ESC key and the backdrop tap is undiscoverable —
   same thin-stroke ✕ as the RFP modal. */
.search-modal__close {
    position: absolute;
    top: var(--s-3);
    right: var(--s-3);
    width: 40px;
    height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    border-radius: var(--r-pill);
    color: var(--ink-soft);
    cursor: pointer;
    transition: background 150ms ease, color 150ms ease;
}
.search-modal__close:hover,
.search-modal__close:focus-visible { background: var(--bg-soft); color: var(--ink); }
.search-modal__close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@keyframes searchModalIn {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}
.search-modal::backdrop {
    background: rgba(26, 24, 19, 0.35);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}
.search-modal form { margin: 0; }
.search-modal input[type="search"] {
    width: 100%;
    font-family: var(--sans);
    font-size: 1.4rem;
    line-height: 1.4;
    padding: var(--s-4) 0;
    background: transparent;
    color: var(--ink);
    border: 0;
    border-bottom: 1px solid var(--hairline);
    border-radius: 0;
    -webkit-appearance: none;
    appearance: none;
}
.search-modal input[type="search"]:focus {
    outline: none;
    border-bottom-color: var(--ink);
}
.search-modal input[type="search"]::-webkit-search-cancel-button { display: none; }
.search-modal__hint {
    margin: var(--s-5) 0 0;
    font-family: var(--sans);
    font-size: 0.72rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ink-soft);
}
.search-modal__hint kbd {
    font-family: var(--sans);
    font-size: 0.72rem;
    letter-spacing: 0.08em;
    color: var(--ink);
    background: transparent;
    border: 1px solid var(--hairline);
    padding: 1px 6px;
    border-radius: 0;
}

.search-form {
    display: flex;
    gap: var(--s-2);
    margin: var(--s-5) 0;
    max-width: var(--measure);
}
.search-form__label { display: none; }
.search-form input[type="search"] {
    flex: 1;
    font-family: var(--sans);
    font-size: 1.25rem;
    padding: var(--s-4) var(--s-5);
    border: 1px solid var(--hairline);
    background: var(--surface);
    color: var(--ink);
}
.search-form input[type="search"]:focus {
    outline: none;
    border-color: var(--accent);
}
.search-form button {
    font-family: var(--sans);
    font-size: 0.85rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 0 var(--s-6);
    background: var(--accent);
    color: var(--accent-ink);
    border: none;
    border-radius: var(--r-sm);
    cursor: pointer;
    transition: background 200ms ease;
}
.search-form button:hover { background: var(--accent-deep); }

.search-section + .search-section {
    margin-top: var(--s-9);
    padding-top: var(--s-8);
    border-top: var(--rail);
}

.search-pages {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: var(--s-6);
}
.search-pages__item a {
    display: block;
    text-decoration: none;
    color: inherit;
    padding-bottom: var(--s-5);
    border-bottom: var(--rail);
}
.search-pages__item:last-child a { border-bottom: none; }
.search-pages__item h3 {
    font-family: var(--sans);
    font-size: 1.25rem;
    margin: 0 0 var(--s-2);
}
.search-pages__item p {
    color: var(--ink-soft);
    margin: 0 0 var(--s-2);
}
.search-pages__url {
    font-size: 0.75rem;
    color: var(--accent-deep);
    letter-spacing: 0.02em;
}

@media (max-width: 900px) {
    .search-modal {
        padding: var(--s-6);
    }
    .search-modal input[type="search"] {
        font-size: 1.15rem;
    }
}

/* ---------- Footer ------------------------------------------------- */

.site-footer {
    border-top: var(--rail-soft);
    background: var(--surface);
    /* Fill the iOS home-indicator safe area with the footer's white ground
       (viewport-fit=cover is set) so no beige canvas shows below the footer.
       __inner keeps its own bottom padding, so footer content still clears it. */
    padding-bottom: env(safe-area-inset-bottom, 0px);
}
.site-footer__inner {
    max-width: var(--maxw);
    margin: 0 auto;
    padding: 0 var(--gutter);
    font-size: 0.9rem;
}
.site-footer__grid {
    display: grid;
    grid-template-columns: 1.5fr repeat(3, 1fr);
    gap: var(--s-8) var(--s-6);
    padding-bottom: var(--s-8);
    border-bottom: var(--rail-soft);
}
.site-footer__col h3 {
    font-family: var(--sans);
    font-size: 0.72rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ink-soft);
    margin: 0 0 var(--s-4);
}
.site-footer__col ul {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: var(--s-2);
}
.site-footer__col a {
    color: var(--ink);
    text-decoration: none;
}
.site-footer__col a:hover { color: var(--accent); }

.site-footer__brand {
    font-family: var(--serif);
    font-size: 1.35rem;
    font-style: italic;
    margin: 0 0 var(--s-4);
    color: var(--ink);
}
.site-footer__address {
    font-style: normal;
    color: var(--ink-soft);
    line-height: 1.6;
    font-size: 0.9rem;
}
/* Contact links sit directly under the address as one cluster — a small
   top gap separates them, no heading (the brand column carries no heading
   by design). Colours/hover come from .site-footer__col a. */
.site-footer__contact {
    margin-top: var(--s-4);
}
/* FOLLOW column — brand icons, always visible, never an accordion. A single
   row of glyphs that inherit ink via currentColor and shift to accent on
   hover (matching the other footer links). Each link is a 44×44 touch target;
   the row is pulled left by half a target's padding so the first glyph's
   optical edge lines up with the heading and column above it. Higher
   specificity (.site-footer__col .site-footer__social) is needed to beat the
   .site-footer__col ul column-flex rule. */
.site-footer__col .site-footer__social {
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0;
    margin-left: -11px;
}
.site-footer__social-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    color: var(--ink);
    transition: color 160ms var(--ease);
}
.site-footer__social-link svg {
    width: 22px;
    height: 22px;
    display: block;
}
.site-footer__social-link:hover { color: var(--accent); }
.site-footer__social-link:focus-visible {
    color: var(--accent);
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 2px;
}

.site-footer__base {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-5);
    justify-content: space-between;
    align-items: baseline;
    padding-top: var(--s-5);
    font-size: 0.8rem;
    color: var(--ink-soft);
}
.site-footer__meta {
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-2);
}
.site-footer__ownership {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
}
.site-footer__ownership-sep {
    color: var(--ink-muted);
}
.site-footer__ownership-mark {
    display: inline-flex;
    align-items: center;
    line-height: 0;
}
.site-footer__ownership-mark img {
    height: 56px;
    width: auto;
    display: block;
    opacity: 0.85;
    transition: opacity 160ms var(--ease);
}
.site-footer__ownership-mark:hover img,
.site-footer__ownership-mark:focus-visible img {
    opacity: 1;
}
.site-footer__pledge {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
}
.site-footer__pledge-sep {
    color: var(--ink-muted);
}
.site-footer__pledge a {
    color: var(--ink-soft);
    text-decoration: none;
    transition: color 160ms var(--ease);
}
.site-footer__pledge a:hover,
.site-footer__pledge a:focus-visible {
    color: var(--accent);
}
.site-footer__legal {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-5);
}
.site-footer__legal a { color: var(--ink-soft); text-decoration: none; }
.site-footer__legal a:hover { color: var(--accent); }

/* Mobile: stack the base. The inline `·` separators only make sense in
   a row — on a narrow viewport they'd land at line-start and read as a
   visual bug. Each component gets its own line, separators hidden, and
   the TOURVEST logo shrinks so it stops dominating the row. */
@media (max-width: 720px) {
    .site-footer__base {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--s-4);
    }
    .site-footer__meta {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--s-3);
    }
    .site-footer__ownership-sep,
    .site-footer__pledge-sep {
        display: none;
    }
    .site-footer__ownership-mark img {
        height: 40px;
    }
}

@media (max-width: 900px) {
    .site-footer__grid {
        grid-template-columns: 1fr 1fr;
        gap: var(--s-6);
    }
    .site-footer__col--brand { grid-column: 1 / -1; }
}
@media (max-width: 560px) {
    .site-footer__grid { grid-template-columns: 1fr; }
}

/* ---------- FOOTER LINK COLUMNS — phone accordions -----------------
   Each link column is wrapped in <details class="site-footer__group">
   with the <h3> heading inside <summary>. Desktop must look identical
   to the old plain h3 + ul: summary acts as a transparent passthrough
   (display:contents) so the h3 sits exactly where it did. The <details>
   is authored `open` (see Footer.ss) so the ul shows natively on desktop
   AND with JS off (graceful baseline — every panel expanded, natively
   tappable). The marker triangle is suppressed everywhere; the +/- toggle
   affordance is added on phone only.

   Flash-free collapse: the phone-collapsed state is established by CSS at
   first paint, gated on .js (set render-blocking in Head.ss). Below 720px
   with JS, the ul is display:none by default — which overrides the `open`
   attribute's rendering — and revealed by [data-open] which phone-accordions.js
   toggles. So the page paints collapsed on the first frame; JS only adds
   interactivity, never mutates the painted layout (no expand→collapse CLS). */
.site-footer__group {
    margin: 0;
}
.site-footer__group-summary {
    list-style: none;
    cursor: default;
}
.site-footer__group-summary::-webkit-details-marker { display: none; }
.site-footer__group-summary::marker { content: ""; }
.site-footer__group-summary h3 { margin: 0 0 var(--s-4); }

/* Desktop (>=721px): transparent — column reads as h3 + ul, always open
   (the [open] attribute keeps the ul visible). */
@media (min-width: 721px) {
    .site-footer__group { display: contents; }
    .site-footer__group-summary { display: contents; }
    .site-footer__group > ul { display: flex; }
}

/* Phone (<=720px): collapsible. Summary is a real tappable row with a
   +/- toggle (+ collapsed, - open). */
@media (max-width: 720px) {
    .site-footer__group-summary {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: var(--s-3);
        min-height: 44px;
        cursor: pointer;
        border-top: var(--rail-soft);
        padding: var(--s-2) 0;
    }
    .site-footer__group-summary h3 { margin: 0; }
    .site-footer__group-summary::after {
        content: "+";
        font-size: 1.1em;
        line-height: 1;
        color: var(--ink-soft);
        flex: 0 0 auto;
    }
    .site-footer__group-summary:focus-visible {
        outline: 2px solid var(--accent);
        outline-offset: 2px;
    }
    .site-footer__group > ul { padding: var(--s-2) 0 var(--s-4); }

    /* With JS: collapsed by default (display:none overrides the `open`
       attribute so first paint is collapsed — no flash), revealed by
       [data-open] which the script toggles. The +/- mark tracks [data-open].
       Without JS (.js absent) this rule never matches, so the `open`
       attribute keeps the ul visible — graceful, natively tappable. */
    .js .site-footer__group > ul { display: none; }
    .js .site-footer__group[data-open] > ul { display: flex; }
    .js .site-footer__group[data-open] .site-footer__group-summary::after {
        content: "\2212"; /* − minus */
    }
}

/* Phone: the Follow column is not an accordion, so it has no <summary> row
   to carry the top hairline the collapsible columns get. Add a matching
   divider + tap-friendly spacing so it sits in the same stacked rhythm. */
@media (max-width: 720px) {
    .site-footer__col--follow {
        border-top: var(--rail-soft);
        padding-top: var(--s-3);
    }
    .site-footer__col--follow h3 {
        margin-bottom: var(--s-2);
    }
}

/* ---------- NEWSLETTER ---------------------------------------------
   Both surfaces (footer row + Elemental block) share the contact-form
   visual vocabulary — underlined input, sentence-case label, accent
   submit with arrow — so the signup feels like part of the same site,
   not a bolted-on widget.

   Hide the honeypot reliably — must be position:absolute (not
   display:none) so well-behaved bots still fill it. */
.newsletter-form #Form_NewsletterForm_Website_Holder,
.newsletter-form input[name="Website"] { position: absolute; left: -9999px; }

/* SS6 wraps the whole form in <fieldset> with default UA chrome —
   neutralise it the same way .contact-form does. */
.newsletter-form fieldset { border: 0; margin: 0; padding: 0; min-width: 0; }
.newsletter-form .clear { display: none; }

/* Suppress the empty error <p> SS6 always renders unless populated. */
.newsletter-form > .message[style*="display: none"] { display: none !important; }
.newsletter-form .message {
    padding: var(--s-3) var(--s-4);
    margin: 0 0 var(--s-4);
    border-left: 2px solid var(--accent-deep);
    background: var(--hairline-soft);
    font-family: var(--sans);
    font-size: 0.875rem;
    color: var(--ink);
}
.newsletter-form .message.bad { border-left-color: var(--accent); }

/* Shared field treatment — underlined input, sentence-case bold
   label. Matches .contact-form so editors / Daddy never see two form
   languages on the same site. */
.newsletter-form .field {
    margin-bottom: var(--s-5);
    display: flex;
    flex-direction: column;
}
.newsletter-form label.form-label,
.newsletter-form label {
    font-family: var(--sans);
    font-size: 0.875rem;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
    color: var(--ink-soft);
    margin-bottom: var(--s-2);
}
.newsletter-form input[type="email"],
.newsletter-form input[type="text"] {
    font-family: var(--sans);
    font-size: 1rem;
    padding: var(--s-3) 0;
    border: none;
    border-bottom: 1px solid var(--hairline);
    background: transparent;
    color: var(--ink);
    width: 100%;
    border-radius: 0;
    transition: border-color 150ms ease;
}
.newsletter-form input[type="email"]:focus,
.newsletter-form input[type="text"]:focus {
    outline: none;
    border-bottom-color: var(--ink);
}
.newsletter-form input::placeholder { color: var(--ink-muted); }

/* Explicit consent row (inline variant only). Checkbox on the left,
   single-line label on the right, slightly smaller type. */
.newsletter-form .field.checkbox {
    flex-direction: row;
    gap: var(--s-3);
    align-items: flex-start;
    padding-top: var(--s-3);
    margin-bottom: var(--s-5);
}
.newsletter-form .field.checkbox input { margin-top: 0.3rem; accent-color: var(--accent); }
.newsletter-form .field.checkbox label {
    font-family: var(--sans);
    font-size: 0.85rem;
    text-transform: none;
    letter-spacing: 0;
    color: var(--ink-soft);
    margin: 0;
    text-align: left; /* override SS .right on checkbox labels */
}

/* Submit — accent rectangle with arrow glyph, exactly like the RFP
   "Send brief →". Keeps the form actions cohesive site-wide. */
.newsletter-form .Actions,
.newsletter-form .btn-toolbar { margin-top: var(--s-4); }
.newsletter-form button[type="submit"],
.newsletter-form input[type="submit"] {
    font-family: var(--sans);
    font-size: 0.875rem;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
    padding: var(--s-3) var(--s-7);
    background: var(--accent);
    color: var(--accent-ink);
    border: none;
    border-radius: var(--r-sm);
    cursor: pointer;
    transition: background 200ms ease, transform 180ms var(--ease);
}
.newsletter-form button[type="submit"]:hover,
.newsletter-form input[type="submit"]:hover {
    background: var(--accent-deep);
    transform: translateY(-1px);
}
.newsletter-form .btn-with-arrow::after {
    content: " →";
    display: inline-block;
    margin-left: 0.4em;
    transition: transform 180ms var(--ease);
}
.newsletter-form .btn-with-arrow:hover::after { transform: translateX(2px); }

/* Field-level validation output from SS */
.newsletter-form .field .error,
.newsletter-form .field .validation {
    font-size: 0.85rem;
    color: var(--accent);
    margin-top: var(--s-2);
}

/* ===== Footer variant — single inline row =========================== */

/* One sand card binding pitch + form into a single cohesive object,
   spanning the standard content width (parent .site-footer__inner is
   already capped at --maxw + gutter padding). Two columns inside:
   pitch on the left, form on the right, both sharing the sand surface
   so they read as one unit rather than two detached islands on
   different surfaces. */

/* Pre-footer trust band — passive credibility, site-wide.
   Three labelled sub-rows: partners, certifications, initiatives.
   Each row gets a small uppercase Helvetica label above a centered
   chip row; hairline separators between rows; whole band closes
   with a hairline before the footer column grid. */
/* Ambient pre-footer trust strip — partner memberships only, no label,
   no row frame. Monochrome + low opacity so the row reads as background
   texture; hover restores colour for the small cohort that knows what
   the logos mean. See Footer.ss + MembershipsFooter.ss for the
   destination strategy decided 2026-05-27. */
.site-footer__trust {
    padding: var(--s-5) 0;
    border-bottom: 1px solid var(--hairline);
    margin-bottom: var(--s-7);
}
.site-footer__trust-row {
    justify-content: center;
    gap: var(--s-5) var(--s-6);
    margin: 0;
    padding: 0;
    list-style: none;
}
.site-footer__trust .cert-chip {
    display: inline-flex;
    align-items: center;
}
.site-footer__trust .cert-chip img {
    height: 40px;
    width: auto;
    max-width: 180px;
    filter: grayscale(1);
    opacity: 0.75;
    transition: filter 200ms var(--ease), opacity 200ms var(--ease);
}
.site-footer__trust .cert-chip:hover img,
.site-footer__trust .cert-chip a:focus-visible img {
    filter: grayscale(0);
    opacity: 1;
}
.site-footer__trust .cert-chip--text {
    font-size: 13px;
    color: var(--ink-muted);
    gap: var(--s-2);
}

.site-footer__newsletter {
    /* Full-bleed sand band that butts directly against the dark/blue
       RFP-CTA above. Outer: vertical padding only, bg runs viewport-wide.
       Inner: maxw + gutter padding, matching the RFP-CTA content column. */
    background: var(--bg-soft);
    padding: var(--s-9) 0 var(--s-7);
}
.site-footer__newsletter-inner {
    max-width: var(--maxw);
    margin: 0 auto;
    padding: 0 var(--gutter);
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--s-7);
    align-items: start;
}
/* Title is calmer here than a page hero — it's the heading of a
   small form card, not the headline of an editorial section. Drop
   the size to sit closer to the body chrome and override the global
   h2 weight=700 rule (this class beats the element selector) so it
   doesn't shout at the rest of the card. */
.site-footer__newsletter-title {
    font-family: var(--sans);
    font-weight: 600;
    font-size: clamp(1.2rem, 1.6vw, 1.5rem);
    line-height: 1.25;
    letter-spacing: -0.01em;
    margin: 0 0 var(--s-3);
    color: var(--ink);
    text-transform: none;
    max-width: 28ch;
}
/* Body chrome — lede, fineprint, and the Email label (overridden
   inside the form below) all share one treatment: 0.875rem sans
   regular ink-soft. Pulls them into a single "small text" voice
   so the card reads as title + body, not title + N variants. */
.site-footer__newsletter-lead {
    margin: 0;
    font-family: var(--sans);
    font-weight: 400;
    font-size: 0.875rem;
    line-height: 1.55;
    color: var(--ink-soft);
}

/* Email label is the only emphasis in the form column — bold (600)
   to mark it clearly as a field label, ink-soft so it doesn't fight
   the title for attention. */
.newsletter-form--footer label.form-label {
    font-weight: 600;
    color: var(--ink-soft);
}
.site-footer__newsletter-thanks {
    margin: 0;
    font-family: var(--serif);
    font-style: italic;
    font-size: 1.2rem;
    color: var(--ink);
}

/* Footer form — single-column stack: Email, Consent, Submit.
   SS6 wraps form fields in a <fieldset>, so we need
   display:contents on the fieldset to let its children
   (Email, Consent) participate in the form grid as direct
   children alongside the btn-toolbar sibling. */
.newsletter-form--footer {
    display: grid;
    grid-template-columns: 1fr;
    row-gap: var(--s-4);
}
.newsletter-form--footer fieldset { display: contents; }
.newsletter-form--footer .field { margin-bottom: 0; }
.newsletter-form--footer #Form_NewsletterForm_Email_Holder {
    grid-row: 1;
}
.newsletter-form--footer #Form_NewsletterForm_Consent_Holder,
.newsletter-form--footer .field.checkbox {
    grid-row: 2;
    padding-top: 0;
    margin-bottom: 0;
}
.newsletter-form--footer .Actions,
.newsletter-form--footer .btn-toolbar {
    grid-row: 3;
    margin-top: 0;
    justify-self: start;
}
/* Input + placeholder match the body chrome (lede / fineprint /
   label) — 0.875rem sans, ink-soft. Typed value uses the darker
   --ink so user input still reads as definite, but the static
   placeholder is visually identical to surrounding prose. */
.newsletter-form--footer input[type="email"] {
    font-size: 0.875rem;
    padding-bottom: var(--s-3);
}
.newsletter-form--footer input::placeholder {
    color: var(--ink-soft);
    opacity: 1;
}

@media (max-width: 900px) {
    .site-footer__newsletter {
        padding: var(--s-7) 0 var(--s-6);
    }
    .site-footer__newsletter-inner {
        grid-template-columns: 1fr;
        gap: var(--s-5);
    }
    .site-footer__newsletter-title,
    .site-footer__newsletter-lead { max-width: none; }
}
@media (max-width: 520px) {
    .newsletter-form--footer {
        row-gap: var(--s-3);
    }
}
/* Phone (<=720px): the sand band ate too much vertical space at 375px.
   Builds on the 900px stack above — cuts band padding further, tightens
   the pitch->form gap and the title/lead rhythm. Form stays fully
   usable (input, consent, submit all comfortably tappable). Desktop and
   the 721-900 tablet band are untouched. */
@media (max-width: 720px) {
    .site-footer__newsletter {
        padding: var(--s-6) 0 var(--s-5);
    }
    .site-footer__newsletter-inner {
        gap: var(--s-4);
    }
    .site-footer__newsletter-title {
        font-size: clamp(1.15rem, 5vw, 1.3rem);
        margin-bottom: var(--s-2);
    }
    .site-footer__newsletter-pitch {
        display: flex;
        flex-direction: column;
        gap: var(--s-2);
    }
    .site-footer__newsletter-lead { line-height: 1.5; }
}
@media (max-width: 600px) {
    /* Footer newsletter submit: the tightened phone row-gap pulls the
       button too close to the consent line — add separation above it only
       (the .Actions base rule sets margin-top:0 and relies on row-gap). */
    .newsletter-form--footer .Actions,
    .newsletter-form--footer .btn-toolbar {
        margin-top: var(--s-3);
    }
    /* Trust / affiliation logo strip: the base 28px (--s-5) top padding
       reads as too much on phones. Trim the top only — bottom padding and
       the desktop band stay as-is. */
    .site-footer__trust {
        padding-top: var(--s-3);
    }
}

/* ===== Block variant — full surface with pitch + form ============== */

.newsletter-block {
    /* Sand band bleeds to viewport edges even when a maxw parent (main, page)
       would normally constrain it. Inner stays at maxw via __inner. */
    width: 100vw;
    margin-inline: calc(50% - 50vw);
    padding: 0 var(--gutter) var(--s-10);
    background: var(--bg-soft);
    border-bottom: 1px solid var(--rule-band);
}
.newsletter-block__inner {
    max-width: var(--maxw);
    margin: 0 auto;
    padding-top: var(--s-9);
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
    gap: var(--s-9);
    align-items: start;
}
.newsletter-block__eyebrow {
    margin: 0 0 var(--s-4);
}
.newsletter-block__title {
    font-family: var(--serif);
    font-style: italic;
    font-weight: 400;
    font-size: clamp(1.9rem, 3vw, 2.6rem);
    line-height: 1.15;
    letter-spacing: -0.01em;
    margin: 0 0 var(--s-5);
    color: var(--ink);
}
.newsletter-block__lead {
    color: var(--ink-soft);
    font-size: 1rem;
    line-height: var(--lh-body);
}
.newsletter-block__lead p { margin: 0 0 var(--s-3); }
.newsletter-block__lead p:last-child { margin-bottom: 0; }
.newsletter-block__fineprint {
    margin: var(--s-6) 0 0;
    font-family: var(--sans);
    font-size: 0.85rem;
    color: var(--ink-muted);
    padding-top: var(--s-5);
    border-top: 1px solid var(--hairline);
}
.newsletter-block__fineprint a {
    color: var(--ink-soft);
    text-decoration: none;
    border-bottom: 1px solid var(--hairline);
}
.newsletter-block__fineprint a:hover {
    color: var(--accent);
    border-bottom-color: var(--accent);
}

/* The form surface inside the block — quiet card on bg-elev to lift
   the form off the sand background, no shadow per Daddy's brief
   (clean, minimal, no heavy shadow). Generous interior padding so the
   underlined inputs have room to breathe. */
.newsletter-block__form {
    background: var(--bg-elev);
    border-radius: var(--r-lg);
    padding: var(--s-7);
}
.newsletter-block__thanks-title {
    font-family: var(--serif);
    font-style: italic;
    font-weight: 400;
    font-size: clamp(1.4rem, 2vw, 1.7rem);
    line-height: 1.2;
    margin: 0 0 var(--s-3);
    color: var(--ink);
}
.newsletter-block__thanks-lead {
    margin: 0;
    color: var(--ink-soft);
    line-height: var(--lh-body);
    font-size: 0.95rem;
}

@media (max-width: 900px) {
    .newsletter-block { padding: 0 var(--gutter) var(--s-8); }
    .newsletter-block__inner {
        padding-top: var(--s-7);
        grid-template-columns: 1fr;
        gap: var(--s-7);
    }
    .newsletter-block__form { padding: var(--s-6); }
}

/* ---------- Responsive nav (very basic) ---------------------------- */

@media (max-width: 800px) {
    .site-header__inner {
        flex-wrap: wrap;
        gap: var(--s-4);
    }
    .site-locale { justify-content: center; }
}

/* ---------- SERVICES PILLAR (five service-line cards) ---------------- */
/* Editorial photo-led tiles. Same vocabulary as .sister-brands__card:
   no card chrome, photo-driven, sans bold title + serif description,
   small-caps CTA. 3+2 layout (last row left-aligned, trailing cell empty). */

.services-pillar { margin: 0 0 var(--s-10); }
.home-services__head {
    margin: 0 0 var(--s-7);
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
    align-items: flex-start;
}
.home-services__title {
    font-family: var(--sans);
    font-weight: 700;
    /* size owned by .h--display (--t-section); don't set font-size here */
    line-height: 1.1;
    letter-spacing: -0.018em;
    color: var(--ink);
    margin: 0;
}
.service-tiles {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--s-6);
    align-items: stretch;
    justify-items: stretch;
}
/* Below 900px the 3-col grid switches to a horizontal scroll-snap rail.
   Bleeds to the viewport edge with negative margins so the first card
   sits flush with the rest of the page's column, and a sliver of the
   next card hints at scrollability. */
@media (max-width: 900px) {
    .service-tiles {
        grid-template-columns: none;
        grid-auto-flow: column;
        grid-auto-columns: 64%;
        gap: var(--s-5);
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        scroll-padding-left: var(--gutter);
        margin-inline: calc(-1 * var(--gutter));
        padding: 0 var(--gutter) var(--s-4);
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }
    .service-tiles::-webkit-scrollbar { display: none; }
}
@media (max-width: 540px) {
    .service-tiles { grid-auto-columns: 82%; gap: var(--s-4); }
}
.service-tile { margin: 0; display: flex; scroll-snap-align: start; }
.service-tile__link {
    display: flex;
    flex-direction: column;
    width: 100%;
    text-decoration: none;
    color: inherit;
}

.service-tile__photo {
    margin: 0;
    aspect-ratio: 8 / 5;
    overflow: hidden;
    background: var(--bg-soft);
    position: relative;
}
.service-tile__photo-img {
    display: block;
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
/* Gradient mask for caption legibility — same pattern as destinations. */
.service-tile__photo:has(.service-tile__photo-img)::after {
    content: "";
    position: absolute;
    inset: 45% 0 0 0;
    background: linear-gradient(to bottom, rgba(33, 28, 25, 0) 0%, rgba(33, 28, 25, 0.55) 100%);
    pointer-events: none;
}
.service-tile__caption {
    position: absolute;
    left: var(--s-4);
    right: var(--s-4);
    bottom: var(--s-3);
    z-index: 1;
}
.service-tile__caption .service-tile__title {
    color: #fff;
}
/* No-photo fallback — when a ServicePage has no hero image, drop the empty
   bone frame and render the title in ink as a text card (otherwise the
   white caption is invisible on the bone panel). Remove once every
   ServicePage carries a hero image. */
.service-tile--no-photo .service-tile__photo {
    aspect-ratio: auto;
    background: transparent;
}
.service-tile--no-photo .service-tile__caption {
    position: static;
    inset: auto;
}
.service-tile--no-photo .service-tile__caption .service-tile__title {
    color: var(--ink);
}

.service-tile__icon-wrap {
    width: 56px;
    height: 56px;
    border-radius: 999px;
    background: var(--surface);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--ink);
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}
.service-tile__icon { display: block; }

.service-tile__body {
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
    flex: 1 1 auto;
    padding: var(--s-4);
}
.service-tile__title {
    font-family: var(--sans);
    font-weight: 700;
    font-size: 1.25rem;
    line-height: 1.2;
    letter-spacing: -0.01em;
    margin: 0;
    color: var(--ink);
}
.service-tile__thesis {
    font-style: normal;
    color: var(--ink-soft);
    margin: 0;
}
/* Small-caps "Read more" line under the thesis — same vocabulary as
   article-card__more / sister-brand link affordances. */
.service-tile__more {
    font-family: var(--sans);
    font-size: 0.72rem;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--ink-muted);
    margin-top: var(--s-3);
    display: inline-block;
    transition: color 200ms var(--ease);
}
.service-tile__link:hover .service-tile__more { color: var(--ink); }

/* ---------- SERVICE SIBLING RAIL (foot of operational service pages) --
   "Services in {Destination}" — reuses the .service-tiles grid above so
   the foot rail reads as the same family as the destination service
   strip. Separated from the page body by a hairline + generous space. */
.service-rail {
    margin-top: var(--s-10);
    padding-top: var(--s-8);
    border-top: 1px solid var(--hairline);
}
.service-rail__head { margin-bottom: var(--s-6); }
.service-rail__title { margin: 0; }
/* The tile for the page you're already on: an accent ring marks "you are
   here", the pointer reverts (it links to self), and the hover lift is
   suppressed so it reads as a static marker, not a destination. */
.service-tile.is-current .service-tile__link { cursor: default; }
.service-tile.is-current .service-tile__photo {
    box-shadow: inset 0 0 0 2px var(--accent);
}

/* Pillar grid wrapper — generous breathing room above the tiles when
   the page chrome above is the editorial page__head fallback. When a
   leading ElementHero precedes the grid, page--has-hero compresses
   that gap so the hero sits cleanly above the inventory. */
.services-pillar__grid { margin-top: var(--s-9); }
.services-pillar.page--has-hero .services-pillar__grid { margin-top: var(--s-8); }

/* ---------- SERVICE PAGE (single service-line root) ------------------ */

.service { margin: 0 0 var(--s-10); }
.service__thesis {
    font-family: var(--serif);
    font-weight: 400;
    font-style: italic;
    font-size: var(--t-h2);
    line-height: 1.15;
    color: var(--ink-soft);
    margin: 0;
    max-width: var(--maxw-text);
}
.service__lead {
    max-width: var(--maxw-text);
    margin: 0 0 var(--s-9);
    font-size: var(--t-body-lg);
}
.service__how, .service__where {
    margin: var(--s-9) 0;
    padding-top: var(--s-7);
    border-top: 1px solid var(--hairline);
}
.service__section-title {
    font-family: var(--sans);
    font-size: var(--t-eyebrow);
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ink-muted);
    font-weight: 500;
    margin: 0 0 var(--s-5);
}

.service-destinations {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--s-5);
}
@media (max-width: 900px) { .service-destinations { grid-template-columns: 1fr 1fr; } }
@media (max-width: 540px) { .service-destinations { grid-template-columns: 1fr; } }
.service-destination { margin: 0; }
.service-destination__link {
    display: block;
    padding: var(--s-5) 0;
    border-top: 1px solid var(--ink);
    text-decoration: none;
    color: inherit;
    transition: opacity 200ms var(--ease);
}
.service-destination__link:hover { opacity: 0.75; }
.service-destination__region {
    font-family: var(--sans);
    font-size: 0.7rem;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--ink-muted);
    margin: 0 0 var(--s-2);
    font-weight: 500;
}
.service-destination__title {
    font-family: var(--sans);
    font-weight: 400;
    font-size: var(--t-h2);
    line-height: 1.15;
    margin: 0 0 var(--s-3);
    color: var(--ink);
}
.service-destination__pitch {
    color: var(--ink-soft);
    margin: 0;
}

/* Photo-led variant of the destination card. When DestinationTiles()
   resolved a HeroImage from the linked DMCPage we render the figure
   ABOVE the text block; the photo leads with the body sitting directly
   beneath it (no hairline divider) to match the site's other photo-led
   cards (article, case-study, team). Card stays text-only when no image. */
.service-destination__link:has(.service-destination__photo) {
    padding: 0;
    border-top: 0;
}
.service-destination__photo {
    margin: 0;
    aspect-ratio: 4 / 3;
    overflow: hidden;
    background: var(--bg-soft);
}
.service-destination__photo-img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 400ms var(--ease);
}
.service-destination__link:hover .service-destination__photo-img { transform: scale(1.02); }
.service-destination__link:has(.service-destination__photo) .service-destination__body {
    padding: var(--s-4) 0 0;
}
.service-destination__link:has(.service-destination__photo) .service-destination__title {
    font-size: 1.4rem;
    line-height: 1.18;
}



/* =============================================================
   DESIGN SYSTEM PAGE  ( /design-system/* )
   All rules scoped under .ds-page so this scaffolding cannot
   leak onto regular site pages. Live tokens.css + app.css are
   the source of truth — these are doc-page utilities only.
   ============================================================= */

.ds-page { display: block; }

/* ---------- TOC SUBNAV ---------- */
.ds-toc {
    position: sticky;
    top: 0;
    z-index: 40;
    background: rgba(247, 244, 238, 0.92);
    backdrop-filter: saturate(140%) blur(10px);
    -webkit-backdrop-filter: saturate(140%) blur(10px);
    border-bottom: 1px solid var(--hairline);
    margin-bottom: var(--s-7);
}
.ds-toc__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-5);
    height: 56px;
}
.ds-toc__brand {
    text-decoration: none;
    color: var(--ink);
    white-space: nowrap;
}
.ds-toc__links {
    display: flex;
    gap: 2px;
    flex-wrap: wrap;
}
.ds-toc__link {
    padding: 8px 12px;
    font-family: var(--sans);
    font-size: 13px;
    color: var(--ink-soft);
    text-decoration: none;
    border-radius: var(--r-sm);
    transition: color 140ms var(--ease), background 140ms var(--ease);
}
.ds-toc__link:hover { color: var(--ink); }
.ds-toc__link.is-current {
    color: var(--ink);
    background: var(--stone-100);
}
@media (max-width: 720px) {
    .ds-toc__row { height: auto; padding: var(--s-3) 0; flex-wrap: wrap; }
    .ds-toc__brand { width: 100%; }
}

.ds-page__body {
    padding-bottom: var(--s-10);
}

/* ---------- SHARED LAYOUT HELPERS ---------- */
.ds-page .ds-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s-5); }
.ds-page .ds-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-4); }
@media (max-width: 800px) {
    .ds-page .ds-grid-2,
    .ds-page .ds-grid-3 { grid-template-columns: 1fr; }
}

/* ---------- OVERVIEW HERO (DesignSystemHero) ---------- */
.ds-page .ds-overview-hero {
    padding: var(--s-9) 0 var(--s-8);
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--s-8);
    align-items: end;
    border-bottom: 1px solid var(--hairline);
}
.ds-page .ds-overview-hero__photos {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--s-3);
}
.ds-page .ds-overview-hero__photos > *:nth-child(2) {
    margin-top: var(--s-7);
}
@media (max-width: 800px) {
    .ds-page .ds-overview-hero { grid-template-columns: 1fr; }
}

.ds-page .ds-direction-card {
    padding: var(--s-6);
    display: flex;
    flex-direction: column;
    gap: var(--s-4);
}
.ds-page .ds-direction-card__swatches {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 6px;
}
.ds-page .ds-direction-card__swatches > div {
    aspect-ratio: 1;
    border-radius: var(--r-sm);
}

.ds-page .ds-principles {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--s-7) var(--s-8);
}
@media (max-width: 720px) {
    .ds-page .ds-principles { grid-template-columns: 1fr; }
}

.ds-page .ds-map {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--s-4);
}
.ds-page .ds-map__card {
    padding: var(--s-6);
    text-decoration: none;
    color: inherit;
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
}
.ds-page .ds-map__open { margin-top: auto; }
@media (max-width: 720px) {
    .ds-page .ds-map { grid-template-columns: 1fr; }
}

/* ---------- FOUNDATIONS (DesignSystemFoundations) ---------- */
.ds-page .colorRamp {
    display: grid;
    grid-template-columns: repeat(10, 1fr);
    gap: 4px;
}
.ds-page .colorRamp .step {
    aspect-ratio: 1;
    border-radius: 3px;
    position: relative;
}
.ds-page .colorRamp .step span {
    position: absolute;
    bottom: 4px;
    left: 6px;
    font-family: var(--sans);
    font-size: 9px;
    letter-spacing: 0.06em;
    color: rgba(255, 255, 255, 0.85);
}
.ds-page .colorRamp .step.dark span { color: rgba(0, 0, 0, 0.6); }

.ds-page .ds-direction-stack {
    display: flex;
    flex-direction: column;
    gap: var(--s-7);
}

.ds-page .ds-token-swatch {
    width: 28px;
    height: 28px;
    background: var(--surface);
    border: 1px solid var(--hairline);
    border-radius: 4px;
}

.ds-page .typeRow {
    display: grid;
    grid-template-columns: 180px 1fr 120px;
    align-items: baseline;
    gap: var(--s-5);
    padding: var(--s-4) 0;
    border-bottom: 1px solid var(--hairline);
}
.ds-page .typeRow .meta {
    font-family: var(--sans);
    font-size: 11px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ink-muted);
}
.ds-page .typeRow .num {
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
    font-size: 12px;
    color: var(--ink-muted);
    text-align: right;
}
@media (max-width: 800px) {
    .ds-page .typeRow {
        grid-template-columns: 1fr;
        gap: var(--s-2);
    }
    .ds-page .typeRow .num { text-align: left; }
}

.ds-page .spaceRow {
    display: grid;
    grid-template-columns: 80px 80px 1fr;
    align-items: center;
    gap: var(--s-4);
    padding: 10px 0;
    border-bottom: 1px solid var(--hairline);
    font-family: var(--sans);
    font-size: 13px;
}
.ds-page .spaceRow code {
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
    background: var(--stone-100);
    padding: 2px 6px;
    border-radius: 3px;
}
.ds-page .spaceBar {
    height: 16px;
    background: var(--accent-soft);
    border-radius: 2px;
}

.ds-page .ds-radius-row {
    display: flex;
    gap: var(--s-6);
    align-items: flex-end;
    flex-wrap: wrap;
}
.ds-page .ds-radius-row .t-micro { margin-top: 8px; }
.ds-page .radiusDemo {
    width: 64px;
    height: 64px;
    background: var(--ink);
    display: inline-block;
}

.ds-page .ds-shadow-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--s-5);
}
.ds-page .shadowDemo {
    width: 100%;
    aspect-ratio: 16 / 9;
    background: var(--surface);
    border-radius: var(--r-md);
    display: grid;
    place-items: center;
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
    font-size: 12px;
    color: var(--ink-muted);
}
.ds-page .ds-shadow-grid .t-micro { margin-top: 8px; }
@media (max-width: 720px) {
    .ds-page .ds-shadow-grid { grid-template-columns: repeat(2, 1fr); }
}

.ds-page .gridCols {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    gap: var(--s-4);
    height: 80px;
}
.ds-page .gridCols > div {
    background: var(--accent-soft);
    border-radius: 2px;
}

/* ---------- COMPONENTS (DesignSystemComponents) ---------- */
.ds-page .compo {
    display: grid;
    grid-template-columns: 240px 1fr;
    gap: var(--s-7);
    padding: var(--s-7) 0;
    border-bottom: 1px solid var(--hairline);
}
.ds-page .compo h3 {
    font-family: var(--sans);
    font-size: 24px;
    margin: 0 0 8px;
}
.ds-page .compo .meta {
    font-family: var(--sans);
    font-size: 12px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ink-muted);
}
.ds-page .compo .desc {
    font-size: 14px;
    color: var(--ink-soft);
    margin-top: 8px;
    line-height: 1.55;
}
@media (max-width: 800px) {
    .ds-page .compo { grid-template-columns: 1fr; }
}

.ds-page .demo {
    background: var(--surface);
    border: 1px solid var(--hairline);
    border-radius: var(--r-md);
    padding: var(--s-6);
    display: flex;
    flex-direction: column;
    gap: var(--s-5);
}
.ds-page .demo + .demo { margin-top: var(--s-3); }
.ds-page .demo .row {
    display: flex;
    gap: var(--s-3);
    align-items: center;
    flex-wrap: wrap;
    margin: 0;
}
.ds-page .demo .label {
    font-family: var(--sans);
    font-size: 11px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ink-muted);
    margin-bottom: 6px;
}

.ds-page .ds-form-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--s-4);
}
@media (max-width: 600px) {
    .ds-page .ds-form-grid { grid-template-columns: 1fr; }
    .ds-page .ds-form-grid > .field[style*="span 2"] { grid-column: auto !important; }
}

.ds-page .ds-radio-row {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--s-3);
    width: 100%;
}
.ds-page .ds-radio {
    display: flex;
    gap: 10px;
    align-items: center;
    padding: 14px;
    border: 1px solid var(--hairline);
    border-radius: var(--r-sm);
    cursor: pointer;
    font-family: var(--sans);
    font-size: 14px;
}
.ds-page .ds-radio.is-on {
    border-color: var(--accent);
    background: var(--accent-faint);
}
.ds-page .ds-radio__mark {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    border: 1px solid var(--stone-300);
    background: transparent;
    flex-shrink: 0;
}
.ds-page .ds-radio__mark.is-on {
    border: 4px solid var(--accent);
    background: var(--surface);
}
@media (max-width: 600px) {
    .ds-page .ds-radio-row { grid-template-columns: 1fr; }
}

.ds-page .ds-checkbox {
    display: flex;
    gap: 12px;
    align-items: flex-start;
}
.ds-page .ds-checkbox__box {
    width: 18px;
    height: 18px;
    border: 1px solid var(--accent);
    background: var(--accent);
    border-radius: 3px;
    display: grid;
    place-items: center;
    margin-top: 2px;
    flex-shrink: 0;
}

.ds-page .ds-card-service {
    padding: var(--s-6);
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
}
.ds-page .ds-card-destination {
    display: flex;
    flex-direction: column;
}
.ds-page .ds-card-destination__body { padding: var(--s-5); }
.ds-page .ds-card-activity {
    display: flex;
    overflow: hidden;
}
.ds-page .ds-card-activity__photo {
    width: 96px;
    flex-shrink: 0;
    background: var(--stone-100);
}
.ds-page .ds-card-activity__photo .photo {
    border-radius: 0;
    height: 100%;
}
.ds-page .ds-card-activity__body {
    padding: var(--s-4);
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.ds-page .ds-card-activity__title {
    font-family: var(--sans);
    font-size: 17px;
    margin: 0;
}

.ds-page .ds-stat-row { gap: var(--s-7); }
.ds-page .ds-stat {
    display: flex;
    align-items: baseline;
    gap: 8px;
}
.ds-page .ds-stat__num {
    font-family: var(--sans);
    font-size: 44px;
    line-height: 1;
}
.ds-page .ds-stat__plus {
    font-size: 22px;
    vertical-align: top;
}

.ds-page .ds-faq {
    border-bottom: 1px solid var(--hairline);
    padding: var(--s-5) var(--s-6);
}
.ds-page .ds-faq.ds-faq--last { border-bottom: 0; }
.ds-page .ds-faq summary {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-family: var(--sans);
    font-size: 22px;
    cursor: pointer;
    list-style: none;
}
.ds-page .ds-faq summary::-webkit-details-marker { display: none; }
.ds-page .ds-faq__sign {
    font-family: var(--sans);
    font-size: 28px;
    font-weight: 300;
    color: var(--ink-muted);
}

.ds-page .ds-testimonial-quote {
    margin: 0;
    font-family: var(--sans);
    font-size: 32px;
    line-height: 1.3;
    letter-spacing: -0.01em;
}
.ds-page .ds-testimonial-source {
    display: flex;
    gap: var(--s-3);
    align-items: center;
    margin-top: var(--s-5);
    font-family: var(--sans);
}
.ds-page .ds-testimonial-source__avatar {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: var(--stone-200);
    border: 1px solid var(--hairline);
}

/* ---------- PATTERNS (DesignSystemPatterns) ---------- */
.ds-page .ds-pattern-section { margin: var(--s-7) 0; }

.ds-page .patternFrame {
    background: var(--surface);
    border: 1px solid var(--hairline);
    border-radius: var(--r-md);
    overflow: hidden;
}
.ds-page .patternHead {
    padding: var(--s-5) var(--s-6);
    border-bottom: 1px solid var(--hairline);
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--s-4);
    flex-wrap: wrap;
}
.ds-page .patternHead h3 {
    font-family: var(--sans);
    font-size: 24px;
    margin: 0;
}
.ds-page .patternHead .meta {
    font-family: var(--sans);
    font-size: 11px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ink-muted);
}
.ds-page .patternBody { padding: 0; }
.ds-page .patternBody.padded { padding: var(--s-7); }
.ds-page .patternNote {
    padding: var(--s-4) var(--s-6);
    background: var(--bg);
    border-top: 1px solid var(--hairline);
    font-family: var(--sans);
    font-size: 13px;
    color: var(--ink-soft);
    line-height: 1.55;
}

/* Hero pattern */
.ds-page .ds-hero-pattern {
    position: relative;
    aspect-ratio: 16 / 8;
    overflow: hidden;
}
.ds-page .ds-hero-pattern__bg { position: absolute; inset: 0; }
.ds-page .ds-hero-pattern__bg .photo { border-radius: 0; height: 100%; }
.ds-page .ds-hero-pattern__scrim {
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(15,14,10,0.32) 0%, rgba(15,14,10,0) 40%, rgba(15,14,10,0.55) 100%);
}
.ds-page .ds-hero-pattern__content {
    position: relative;
    height: 100%;
    padding: var(--s-7);
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    color: #fff;
}
.ds-page .ds-hero-pattern__top {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--s-4);
    flex-wrap: wrap;
}
.ds-page .ds-hero-pattern__eyebrow {
    font-family: var(--sans);
    font-size: 11px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    opacity: 0.85;
}
.ds-page .ds-hero-pattern__tag { opacity: 0.85; color: inherit; }
.ds-page .ds-hero-pattern__title {
    font-family: var(--sans);
    font-size: clamp(36px, 5vw, 88px);
    line-height: 1.02;
    letter-spacing: -0.02em;
    margin: 0;
    max-width: 14ch;
    color: #fff;
}
.ds-page .ds-hero-pattern__lead {
    margin-top: var(--s-4);
    font-size: 19px;
    line-height: 1.55;
    opacity: 0.92;
    color: inherit;
}
.ds-page .ds-hero-pattern__cta {
    display: flex;
    gap: var(--s-3);
    margin-top: var(--s-5);
    align-items: center;
    flex-wrap: wrap;
}
.ds-page .ds-hero-pattern__inline {
    color: #fff;
    border-bottom-color: rgba(255, 255, 255, 0.6);
}

/* Trust bar */
.ds-page .ds-trust-row {
    display: grid;
    grid-template-columns: 1.4fr 1fr;
    gap: var(--s-7);
    align-items: center;
}
.ds-page .ds-trust-stats {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--s-5);
}
.ds-page .ds-trust-num {
    font-family: var(--sans);
    font-size: 44px;
    line-height: 1;
    letter-spacing: -0.01em;
}
.ds-page .ds-trust-plus {
    font-size: 22px;
    vertical-align: top;
}
.ds-page .ds-trust-certs {
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
    align-items: flex-start;
}
.ds-page .certRow {
    display: flex;
    gap: var(--s-2);
    flex-wrap: wrap;
    align-items: center;
}
.ds-page .certChip-bare {
    padding: 6px 12px;
    background: transparent;
    border: 1px solid var(--hairline);
    border-radius: 999px;
    font-family: var(--sans);
    font-size: 12px;
    color: var(--ink-soft);
    display: inline-flex;
    align-items: center;
    gap: 8px;
    white-space: nowrap;
}
.ds-page .certChip-bare .badge-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--accent);
    display: inline-block;
}
@media (max-width: 800px) {
    .ds-page .ds-trust-row { grid-template-columns: 1fr; }
    .ds-page .ds-trust-stats { grid-template-columns: repeat(2, 1fr); }
}

/* Destination grid */
.ds-page .ds-dest-grid {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr;
    grid-template-rows: auto auto;
    gap: var(--s-4);
}
.ds-page .ds-dest-grid a {
    text-decoration: none;
    color: inherit;
    display: flex;
    flex-direction: column;
    gap: var(--s-2);
}
.ds-page .ds-dest-grid__hero {
    grid-row: span 2;
    gap: var(--s-3) !important;
}
.ds-page .ds-dest-grid__caption {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--s-4);
    flex-wrap: wrap;
}
.ds-page .ds-dest-grid__title-lg {
    font-family: var(--sans);
    font-size: 32px;
    margin: 4px 0 0;
    letter-spacing: -0.01em;
}
.ds-page .ds-dest-grid__caption-sm {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--s-3);
}
.ds-page .ds-dest-grid__caption-sm h4 {
    font-family: var(--sans);
    font-size: 22px;
    margin: 0;
}
@media (max-width: 800px) {
    .ds-page .ds-dest-grid {
        grid-template-columns: 1fr;
        grid-template-rows: auto;
    }
    .ds-page .ds-dest-grid__hero { grid-row: auto; }
}

/* Case study */
.ds-page .ds-case-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--s-4);
    margin-bottom: var(--s-7);
}
.ds-page .ds-case-card { display: flex; flex-direction: column; }
.ds-page .ds-case-card__body {
    padding: var(--s-5);
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
}
.ds-page .ds-case-card__top {
    display: flex;
    justify-content: space-between;
    gap: var(--s-3);
}
.ds-page .ds-case-card__title {
    font-family: var(--sans);
    font-size: 24px;
    margin: 0;
    line-height: 1.18;
}
.ds-page .ds-case-card__specs {
    display: flex;
    gap: var(--s-3);
    font-family: var(--sans);
    font-size: 13px;
    color: var(--ink-soft);
    padding-top: var(--s-3);
    border-top: 1px solid var(--hairline);
    flex-wrap: wrap;
}

.ds-page .ds-case-expanded {
    background: var(--bg-elev);
    border-radius: var(--r-md);
    padding: var(--s-7);
    display: grid;
    grid-template-columns: 1.2fr 1fr;
    gap: var(--s-7);
    align-items: start;
}
.ds-page .ds-case-expanded__title {
    font-family: var(--sans);
    font-size: clamp(28px, 3.4vw, 44px);
    line-height: 1.1;
    letter-spacing: -0.018em;
    margin: var(--s-3) 0 0;
}
.ds-page .ds-case-expanded__stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--s-5);
    margin-top: var(--s-6);
    padding-top: var(--s-5);
    border-top: 1px solid var(--hairline);
}
.ds-page .ds-case-expanded__num {
    font-family: var(--sans);
    font-size: 32px;
    line-height: 1;
}
@media (max-width: 800px) {
    .ds-page .ds-case-grid { grid-template-columns: 1fr; }
    .ds-page .ds-case-expanded { grid-template-columns: 1fr; }
}

/* RFP form */
.ds-page .ds-rfp {
    background: var(--accent-deep);
    color: #fff;
}
.ds-page .ds-rfp__cols {
    display: grid;
    grid-template-columns: 1fr 1.2fr;
    gap: var(--s-7);
}
.ds-page .ds-rfp__step { color: rgba(255, 255, 255, 0.7); }
.ds-page .ds-rfp__title {
    font-family: var(--sans);
    font-size: clamp(28px, 3.4vw, 44px);
    line-height: 1.08;
    letter-spacing: -0.018em;
    margin: var(--s-3) 0 0;
    color: #fff;
}
.ds-page .ds-rfp__lead {
    margin-top: var(--s-5);
    color: rgba(255, 255, 255, 0.78);
    font-size: 17px;
    line-height: 1.6;
}
.ds-page .ds-rfp__steps {
    margin-top: var(--s-7);
    padding-top: var(--s-5);
    border-top: 1px solid rgba(255, 255, 255, 0.15);
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
    font-family: var(--sans);
}
.ds-page .ds-rfp__step-row {
    display: flex;
    gap: var(--s-3);
    font-size: 14px;
}
.ds-page .ds-rfp__step-num {
    color: rgba(255, 255, 255, 0.5);
    font-family: var(--sans);
    width: 22px;
}
.ds-page .ds-rfp__form {
    display: flex;
    flex-direction: column;
    gap: var(--s-4);
    background: var(--surface);
    color: var(--ink);
    padding: var(--s-6);
    border-radius: var(--r-md);
}
.ds-page .ds-rfp__form-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--s-3);
}
.ds-page .ds-rfp__chips {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
}
@media (max-width: 800px) {
    .ds-page .ds-rfp__cols { grid-template-columns: 1fr; }
    .ds-page .ds-rfp__chips { grid-template-columns: repeat(2, 1fr); }
}

/* Process strip */
.ds-page .ds-process {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: var(--s-4);
    position: relative;
}
.ds-page .ds-process__line {
    position: absolute;
    top: 14px;
    left: 8%;
    right: 8%;
    height: 1px;
    background: var(--hairline);
}
.ds-page .ds-process__step { position: relative; }
.ds-page .ds-process__num {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--surface);
    border: 1px solid var(--ink);
    color: var(--ink);
    display: grid;
    place-items: center;
    font-family: var(--sans);
    font-size: 13px;
    font-weight: 500;
    position: relative;
    z-index: 1;
}
.ds-page .ds-process__num.is-current {
    background: var(--accent);
    color: var(--accent-ink);
    border-color: transparent;
}
.ds-page .ds-process__step h4 {
    font-family: var(--sans);
    font-size: 20px;
    margin: var(--s-3) 0 6px;
}
.ds-page .ds-process__step p { margin: 0; }
@media (max-width: 800px) {
    .ds-page .ds-process { grid-template-columns: repeat(2, 1fr); }
    .ds-page .ds-process__line { display: none; }
}

/* ---------- PHOTOGRAPHY (DesignSystemPhotography) ---------- */
.ds-page .ds-subject-grid {
    display: grid;
    grid-template-columns: 1.4fr 1fr 1fr 1fr;
    gap: var(--s-3);
}
@media (max-width: 800px) {
    .ds-page .ds-subject-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
    .ds-page .ds-subject-grid { grid-template-columns: 1fr; }
}

.ds-page .ds-ratio-grid {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: var(--s-3);
}
.ds-page .ratioBox {
    aspect-ratio: var(--ratio);
    border: 1px dashed var(--stone-300);
    border-radius: 4px;
    display: grid;
    place-items: center;
    color: var(--ink-muted);
    font-family: var(--sans);
    font-size: 12px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
}
@media (max-width: 800px) {
    .ds-page .ds-ratio-grid { grid-template-columns: repeat(2, 1fr); }
}

.ds-page .doDont {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--s-5);
}
.ds-page .ddCol {
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
}
.ds-page .ddCol .head {
    display: flex;
    gap: 10px;
    align-items: center;
    padding-bottom: var(--s-3);
    border-bottom: 1px solid var(--hairline);
}
.ds-page .pill {
    font-family: var(--sans);
    font-size: 11px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    padding: 4px 10px;
    border-radius: 999px;
}
.ds-page .pillDo {
    background: var(--accent-faint);
    color: var(--accent);
    border: 1px solid var(--accent-soft);
}
.ds-page .pillDont {
    background: #f8eeea;
    color: #8b3a26;
    border: 1px solid #f0d4cb;
}
@media (max-width: 720px) {
    .ds-page .doDont { grid-template-columns: 1fr; }
}

/* ---------- TWEAKS PANEL (mounted by ds-init.js) ---------- */
.ds-tweaks {
    position: fixed;
    right: 20px;
    bottom: 20px;
    z-index: 100;
    width: 280px;
    background: var(--surface);
    border: 1px solid var(--hairline);
    border-radius: var(--r-md);
    box-shadow: var(--shadow-3);
    font-family: var(--sans);
    font-size: 13px;
    overflow: hidden;
}
.ds-tweaks__head {
    padding: 12px 16px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-bottom: 1px solid var(--hairline);
}
.ds-tweaks__head h4 {
    margin: 0;
    font-family: var(--sans);
    font-size: 18px;
}
.ds-tweaks__close {
    font-size: 20px;
    color: var(--ink-muted);
    line-height: 1;
}
.ds-tweaks__body {
    padding: 14px 16px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}
.ds-tweaks__row {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.ds-tweaks__label {
    font-size: 11px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ink-muted);
}
.ds-tweaks__seg {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    border: 1px solid var(--hairline);
    border-radius: var(--r-sm);
    overflow: hidden;
}
.ds-tweaks__seg button {
    padding: 8px 6px;
    font-size: 12px;
    color: var(--ink-soft);
    background: var(--surface);
    border-right: 1px solid var(--hairline);
    transition: background 140ms var(--ease), color 140ms var(--ease);
}
.ds-tweaks__seg button:last-child { border-right: 0; }
.ds-tweaks__seg button.is-on {
    background: var(--ink);
    color: var(--bg);
}
.ds-tweaks-toggle {
    position: fixed;
    right: 20px;
    bottom: 20px;
    z-index: 100;
    padding: 10px 16px;
    font-family: var(--sans);
    font-size: 12px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    background: var(--ink);
    color: var(--bg);
    border-radius: var(--r-pill);
    box-shadow: var(--shadow-3);
}

/* ---------- Micro-animations --------------------------------------- */
/* Three subtle motion treatments. JS toggles classes; CSS owns the
   transitions. */

/* 1. Image fade-in on load */
.img-fade { opacity: 0; transition: opacity 250ms ease; }
.img-fade.is-loaded { opacity: 1; }

/* 2. Section reveal on scroll (IntersectionObserver in microanim.js) */
.reveal-on-scroll {
    opacity: 0;
    transform: translateY(12px);
    transition: opacity 500ms ease, transform 500ms ease;
}
.reveal-on-scroll.is-revealed {
    opacity: 1;
    transform: none;
}

/* 3. Hero text stagger on first paint — eyebrow → title → subtitle */
@keyframes heroStaggerFade {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: none; }
}
.element-hero__eyebrow,
.element-hero__title,
.element-hero__subtitle {
    animation: heroStaggerFade 600ms ease both;
}
.element-hero__eyebrow  { animation-delay:   0ms; }
.element-hero__title    { animation-delay:  80ms; }
.element-hero__subtitle { animation-delay: 160ms; }

/* ---------- PAGE CHILD DIRECTORY ------------------------------------
   Auto-rendered cards listing the current page's published in-menu
   children. Used on category-style pages whose children would otherwise
   be hidden from the DMC sub-nav (which only shows direct DMC children).
   See themes/lxp/templates/Includes/PageChildDirectory.ss. */
/* Child-page directory (services umbrella overview etc.). The tiles use
   the shared .service-tiles / .service-tile photo-card grid — identical to
   the foot ServiceSiblingRail — so the wrapper only owns vertical rhythm;
   <main> already provides the maxw + gutter rail (re-applying it here would
   double-pad the grid narrower than the sibling rail on sub-pages). */
.page-children {
    margin: var(--s-8) 0 var(--s-10);
}

/* ---------- Sister brands (homepage / cross-link) ------------------
   3-up teaser row pointing to sibling brands (LuxuryTravelSpain,
   HeliXperiences, YachtXperiences). Each card is a single anchor;
   image hover-zooms, the CTA arrow nudges right. Collapses to one
   column on mobile. */
.sister-brands {
    max-width: var(--maxw);
    margin: 0 auto;
    padding: var(--s-9) var(--gutter) var(--s-10);
}
.sister-brands__head {
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
    margin: 0 0 var(--s-7);
}
.sister-brands__title {
    font-family: var(--sans);
    font-weight: 700;
    /* size owned by .h--display (--t-section); don't set font-size here */
    line-height: 1.1;
    letter-spacing: -0.018em;
    color: var(--ink);
    margin: 0;
}
.sister-brands__lead {
    font-family: var(--sans);
    font-size: 1rem;
    line-height: 1.5;
    color: var(--ink-soft);
    margin: 0;
}
.sister-brands__grid {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--s-6);
}
.sister-brands__item { margin: 0; }
.sister-brands__card {
    display: flex;
    flex-direction: column;
    text-decoration: none;
    color: inherit;
    height: 100%;
}
.sister-brands__photo {
    margin: 0;
    aspect-ratio: 8 / 5;
    overflow: hidden;
    background: var(--bg-soft);
}
.sister-brands__photo img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.sister-brands__body {
    display: flex;
    flex-direction: column;
    gap: var(--s-2);
    flex: 1 1 auto;
    padding: var(--s-4);
}
.sister-brands__name {
    font-family: var(--sans);
    font-weight: 700;
    font-size: 1.25rem;
    line-height: 1.2;
    letter-spacing: -0.01em;
    margin: 0;
    color: var(--ink);
}
.sister-brands__summary {
    /* Match the section intro (.sister-brands__lead): light 300, 1rem/1.5 — so
       the card copy and the lead read as one consistent voice. */
    font-size: 1rem;
    line-height: 1.5;
    font-weight: 300;
    color: var(--ink-soft);
    margin: 0;
}
/* Below 900px the 3-col grid switches to a horizontal scroll-snap rail —
   identical behaviour to the .service-tiles "six disciplines" strip so the
   homepage reads consistently. Bleeds to the viewport edge with negative
   margins so the first card sits flush with the page column and a sliver of
   the next card hints at scrollability. Replaces the old single-column
   stack (was a long vertical scroll on phones pre-2026-06-05). */
@media (max-width: 900px) {
    .sister-brands__grid {
        grid-template-columns: none;
        grid-auto-flow: column;
        grid-auto-columns: 64%;
        gap: var(--s-5);
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        scroll-padding-left: var(--gutter);
        margin-inline: calc(-1 * var(--gutter));
        padding: 0 var(--gutter) var(--s-4);
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }
    .sister-brands__grid::-webkit-scrollbar { display: none; }
    /* Defensive overflow guard: keep the scroll-rail items + cards from
       forcing their auto-column wider than 64% on a long localized title
       (grid/flex children default to min-width:auto). overflow-wrap breaks
       any over-long word in the name/summary. The rail's overflow-x:auto
       already clips, so this is belt-and-suspenders. No visual change at
       normal content. (2026-06-05) */
    .sister-brands__item { scroll-snap-align: start; min-width: 0; }
    .sister-brands__card { min-width: 0; }
    .sister-brands__name,
    .sister-brands__summary { overflow-wrap: anywhere; }
}
@media (max-width: 540px) {
    .sister-brands__grid { grid-auto-columns: 82%; gap: var(--s-4); }
}

/* ---------- Why us — strict typographic / Bauhaus -----------------------
   Two distinct modes share the .why-us shell:

   1. STRICT TYPOGRAPHIC (homepage) — when the template renders a
      .why-us__list (reasons exist). Single rigorous hairline grid;
      metrics + reasons share one numeric sequence (00–09). No icons,
      no orange. Index on the left, content on the right.

   2. INTRO-ONLY (DMC pages) — when no reasons exist. Side-by-side
      narrative + stats via the .why-us--intro grid (ExtraClass on the
      outer .element wrapper from ElementHolder.ss, NOT on the .why-us
      section itself — scope from outer wrapper, never inner).
   ---------------------------------------------------------------------- */
.why-us {
    max-width: var(--maxw);
    margin: 0 auto;
    padding: var(--s-10) var(--gutter) var(--s-9);
}

/* ---- Mode 1: strict typographic (when reasons exist) ---- */
.why-us:has(.why-us__list) .why-us__head {
    padding-bottom: var(--s-6);
    margin-bottom: var(--s-7);
}
.why-us__cluster {
    font-family: var(--sans);
    font-size: var(--t-eyebrow);
    letter-spacing: 0.18em;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--ink-muted);
    margin: 0 0 var(--s-4);
}
.why-us:has(.why-us__list) .why-us__title {
    font-family: var(--sans);
    font-weight: 700;
    font-size: var(--t-h1);
    line-height: 1.05;
    letter-spacing: -0.02em;
    color: var(--ink);
    margin: 0;
}
.why-us:has(.why-us__list) .why-us__title em {
    font-family: var(--sans);
    font-style: normal;
    font-weight: 300;
    color: var(--ink-muted);
}
.why-us:has(.why-us__list) .why-us__metrics {
    list-style: none;
    margin: 0;
    padding: 0;
    border: 0;
    display: block;
    column-gap: 0;
    row-gap: 0;
    grid-template-columns: none;
}
.why-us:has(.why-us__list) .why-us__metric {
    display: grid;
    grid-template-columns: 1fr 4fr 7fr;
    column-gap: var(--s-7);
    align-items: center;
    padding: var(--s-6) 0;
    border-top: 1px solid var(--hairline);
    border-bottom: 0;
    margin: 0;
    text-align: left;
}
.why-us:has(.why-us__list) .why-us__metric:first-child {
    border-top: 1px solid var(--ink);
}
.why-us__metric-index,
.why-us__row-index {
    font-family: var(--sans);
    font-weight: 700;
    font-size: clamp(2rem, 3vw, 3rem);
    line-height: 0.95;
    letter-spacing: -0.022em;
    color: var(--ink);
    font-feature-settings: "tnum","lnum";
}
.why-us:has(.why-us__list) .why-us__metric-head {
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
}
.why-us:has(.why-us__list) .why-us__metric-label {
    font-family: var(--sans);
    font-size: var(--t-eyebrow);
    letter-spacing: 0.18em;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--ink-muted);
    line-height: 1.2;
    margin: 0;
    max-width: none;
}
.why-us:has(.why-us__list) .why-us__metric-num {
    font-family: var(--sans);
    font-weight: 700;
    font-size: clamp(1.25rem, 1.6vw, 1.625rem);
    line-height: 1.1;
    letter-spacing: -0.018em;
    color: var(--ink);
    font-feature-settings: "tnum","lnum";
}
.why-us__list {
    list-style: none;
    margin: 0;
    padding: 0;
}
.why-us__row {
    display: grid;
    grid-template-columns: 1fr 4fr 7fr;
    column-gap: var(--s-7);
    align-items: center;
    padding: var(--s-6) 0;
    border-top: 1px solid var(--hairline);
    margin: 0;
}
.why-us__row-cat {
    font-family: var(--sans);
    font-size: var(--t-eyebrow);
    letter-spacing: 0.18em;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--ink-muted);
    margin: 0 0 var(--s-3);
}
.why-us__row-name {
    font-family: var(--sans);
    font-weight: 700;
    font-size: clamp(1.25rem, 1.6vw, 1.625rem);
    line-height: 1.1;
    letter-spacing: -0.018em;
    color: var(--ink);
    margin: 0;
}
.why-us__row-body {
    font-family: var(--sans);
    font-size: var(--t-body-lg);
    line-height: 1.55;
    color: var(--ink-soft);
    margin: 0;
    max-width: 64ch;
}
@media (max-width: 900px) {
    .why-us:has(.why-us__list) .why-us__metric {
        grid-template-columns: 1fr 4fr;
        row-gap: var(--s-2);
    }
    .why-us:has(.why-us__list) .why-us__metric-label {
        grid-column: 1 / -1;
        padding-top: var(--s-2);
    }
    .why-us__row {
        grid-template-columns: 1fr 11fr;
        row-gap: var(--s-3);
        padding: var(--s-5) 0;
    }
    .why-us__row-body { grid-column: 2 / -1; }
}
@media (max-width: 600px) {
    .why-us { padding: var(--s-9) var(--gutter) var(--s-8); }
}

/* ---- Mode 1 reasons — phone accordion -----------------------------
   Each reason row is wrapped in <details class="why-us__row-fold">; the
   index + head live in <summary>, the body is the collapsible panel.
   The <details> is authored `open` (see ElementWhyUs.ss) so the body
   shows on desktop AND with JS off (graceful baseline). Desktop (>=721px):
   the fold + summary are display:contents so index, head and body re-enter
   the existing .why-us__row grid (1fr 4fr 7fr, then 1fr 11fr <=900) exactly
   as before. The hairline grid look is preserved because .why-us__row still
   owns the grid + border-top.
   Phone (<=720px): summary becomes the visible 2-col row (index + head)
   with a +/- toggle. Flash-free collapse: gated on .js (set render-blocking in
   Head.ss), the body is display:none by default — overriding the `open`
   attribute so the page paints collapsed on the first frame — and revealed
   by [data-open], which phone-accordions.js toggles. JS only adds
   interactivity; it never mutates the painted layout (no expand→collapse
   CLS). Without JS the `open` attribute keeps the body visible. */
.why-us__row-fold { margin: 0; }
.why-us__row-summary { list-style: none; }
.why-us__row-summary::-webkit-details-marker { display: none; }
.why-us__row-summary::marker { content: ""; }

@media (min-width: 721px) {
    .why-us__row-fold,
    .why-us__row-summary { display: contents; }
    .why-us__row-fold > .why-us__row-body { display: block; }
}

@media (max-width: 720px) {
    /* The grid now lives on the summary (the always-visible row); the
       <li>/<details> are transparent so the body can drop below it. */
    .why-us__row { display: block; }
    /* Fixed index column (defined on the fold so both the summary grid and
       the body below it inherit it). A 1fr index column can't shrink below
       the 2-digit number's min-content (~35px at the 2rem index size), so
       the head column started ~10px further right than the body's
       (100%/12)-based indent assumed — the body sat short of the title.
       A known column width makes the title and body indents identical. */
    .why-us__row-fold { display: block; --why-idx-col: 2.5rem; }
    .why-us__row-summary {
        display: grid;
        grid-template-columns: var(--why-idx-col) 1fr;
        column-gap: var(--s-7);
        align-items: center;
        cursor: pointer;
        min-height: 44px;
        position: relative;
    }
    /* The +/- mark sits at the end of the head cell. */
    .why-us__row-summary .why-us__row-head {
        display: flex;
        flex-direction: column;
        gap: var(--s-3);
    }
    .why-us__row-summary::after {
        content: "+";
        position: absolute;
        right: 0;
        top: 50%;
        transform: translateY(-50%);
        font-size: 1.25rem;
        line-height: 1;
        color: var(--ink-soft);
    }
    .why-us__row-summary:focus-visible {
        outline: 2px solid var(--accent);
        outline-offset: 2px;
    }
    /* Keep room for the +/- mark so it never overlaps the title. */
    .why-us__row-name { padding-right: var(--s-5); }
    /* Body drops below, indented to the head column start (index col +
       gap) so its left edge lines up exactly with the title above. */
    .why-us__row-fold > .why-us__row-body {
        margin-top: var(--s-3);
        margin-left: calc(var(--why-idx-col) + var(--s-7));
    }

    /* With JS: collapsed by default (display:none overrides `open` so first
       paint is collapsed — no flash), revealed by [data-open]. The +/- mark tracks
       [data-open]. Without JS the rule never matches, so `open` keeps the body
       visible — graceful, natively tappable. */
    .js .why-us__row-fold > .why-us__row-body { display: none; }
    .js .why-us__row-fold[data-open] > .why-us__row-body { display: block; }
    .js .why-us__row-fold[data-open] .why-us__row-summary::after {
        content: "\2212"; /* − minus */
    }
}

/* ---- Mode 2: intro-only (.why-us--intro) — DMC narrative + stats ---- */
.why-us--intro .why-us__intro {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas:
        "head    metrics"
        "lead    metrics";
    column-gap: var(--s-9);
    row-gap: var(--s-4);
    align-items: center;
    margin-bottom: 0;
}
.why-us--intro .why-us__intro-row { display: contents; }
.why-us--intro .why-us__head { max-width: none; margin: 0; grid-area: head; align-self: end; }
.why-us--intro .why-us__lead { grid-area: lead; align-self: start; max-width: none; margin: 0; }
.why-us--intro .why-us__title {
    font-family: var(--sans);
    font-weight: 700;
    font-size: var(--t-h2);
    line-height: 1.1;
    letter-spacing: -0.018em;
    color: var(--ink);
    margin: 0 0 var(--s-5);
}
.why-us--intro .why-us__metrics {
    grid-area: metrics;
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--s-5);
    row-gap: var(--s-5);
}
/* A 3-metric intro strip stacks as a single column — a 2×2 grid with three
   items leaves an unbalanced empty cell. Count-scoped via :has() so 4-metric
   strips (the other islands) keep their 2×2. The nth-child(-n+2) borders below
   then read as clean dividers between the stacked stats. */
.why-us--intro .why-us__metrics:has(.why-us__metric:nth-child(3):last-child) {
    grid-template-columns: minmax(0, 1fr);
}
/* A 2-metric strip is a single balanced row of two — drop the 2×2 top-row
   divider so the underlines don't dangle with nothing beneath them. */
.why-us--intro .why-us__metrics:has(.why-us__metric:nth-child(2):last-child) .why-us__metric {
    padding-bottom: 0;
    border-bottom: 0;
}
.why-us--intro .why-us__metric {
    margin: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    text-align: left;
    gap: var(--s-2);
    padding-bottom: 0;
    border-bottom: 0;
}
.why-us--intro .why-us__metric:nth-child(-n+2) {
    padding-bottom: var(--s-4);
    border-bottom: 1px solid var(--ink);
}
.why-us--intro .why-us__metric-num {
    font-family: var(--sans);
    font-size: clamp(2.75rem, 5vw, 4.25rem);
    font-weight: 700;
    line-height: 0.95;
    letter-spacing: -0.025em;
    color: var(--feature);
}
.why-us--intro .why-us__metric-label { color: var(--ink-soft); }
@media (max-width: 900px) {
    .why-us--intro .why-us__intro {
        grid-template-columns: 1fr;
        grid-template-areas: "head" "lead" "metrics";
        row-gap: var(--s-5);
    }
    .why-us--intro .why-us__head,
    .why-us--intro .why-us__lead { align-self: stretch; }
}
@media (max-width: 560px) {
    .why-us--intro .why-us__metrics { grid-template-columns: 1fr; }
    .why-us--intro .why-us__metric:nth-child(-n+2) { padding-bottom: 0; border-bottom: 0; }
    .why-us--intro .why-us__metric {
        padding-bottom: var(--s-4);
        border-bottom: 1px solid var(--ink);
    }
    .why-us--intro .why-us__metric:last-child { padding-bottom: 0; border-bottom: 0; }
}

/* ---------- Affiliation block (group-membership announcement) ----------
   Single-column editorial section: eyebrow → heading → logo → body
   stacked vertically. Top hairline marks the section boundary; right
   hairline acts as the vertical divider against the paired Testimonial
   block. No bottom border — content flows down into whatever follows.
   Used for the TOURVEST membership announcement. */
.affiliation {
    max-width: var(--maxw);
    margin: 0 auto;
    padding: var(--s-9) var(--gutter);
}
.affiliation__row--media {
    margin-top: var(--s-6);
}
.affiliation__logo {
    margin: 0;
    max-width: 360px;
    width: 100%;
}
.affiliation__eyebrow {
    margin: 0 0 var(--s-4);
}
.affiliation__heading {
    font-family: var(--sans);
    font-weight: 700;
    font-size: clamp(22px, 1.8vw, 30px);
    line-height: 1.15;
    letter-spacing: -0.018em;
    color: var(--ink);
    margin: 0;
}
.affiliation__logo img {
    display: block;
    width: 100%;
    height: auto;
}
.affiliation__body {
    font-family: var(--sans);
    font-size: 1.0625rem;
    line-height: var(--lh-body);
    color: var(--ink-soft);
}
/* Below lg the cols stack via Bootstrap; tighten the row spacing so
   logo and body don't float too far below the heading. */
@media (max-width: 991px) {
    .affiliation__row--media {
        margin-top: var(--s-5);
    }
    .affiliation__logo {
        margin-bottom: var(--s-4);
    }
}

/* Newsletter unsubscribe page — kept type-only. Confirm button sits
   next to a quiet cancel link so the destructive action has a visible
   escape; nothing reads as a "form" so the page stays calm. */
.page--unsubscribe .unsubscribe-form {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-5);
    margin-top: var(--s-6);
}
.page--unsubscribe .unsubscribe-form__cancel {
    color: var(--ink-soft);
    text-decoration: underline;
    text-underline-offset: 3px;
    font-family: var(--sans);
    font-size: 0.875rem;
}
.page--unsubscribe .unsubscribe-form__cancel:hover {
    color: var(--ink);
}


/* ================================================================== */
/* Wave 2 — case-study detail, product detail, destinations            */
/* anchor card. Editorial uplift modeled on ArticlePage (the gold      */
/* standard). All new rules are scoped to `--editorial` modifiers so   */
/* the existing rule blocks above keep their current behavior for any  */
/* surface that hasn't moved to the new layout yet.                    */
/* ================================================================== */

/* ---------- Case study detail (editorial layout) ------------------- */

/* Outer wrapper opts out of .case-study's 720px text-cap so the hero +
   specs row can use the full article width. main already owns the
   maxw + gutter rail (see container contract) — do NOT re-apply
   max-width or gutter padding here or the content double-paddings
   and renders narrower than the rest of the site. */
.case-study--editorial {
    max-width: none;
}

.case-study--editorial .case-study__back {
    margin: 0 0 var(--s-5);
}

.case-study--editorial .case-study__hero {
    margin: 0 0 var(--s-7);
}
.case-study--editorial .case-study__hero img {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    display: block;
}

.case-study--editorial .case-study__specs {
    margin: 0 0 var(--s-8);
}

/* The editorial column. Built as a 2-track CSS Grid (1fr left margin
   rail / 2fr editorial column) so children explicitly nominate a track
   via grid-column. Head / body / what-worked / nav all live in column 2.
   Pull-quote opts into column 1 to sit alongside the body's opening. */
.case-study__column {
    display: grid;
    grid-template-columns: 1fr 2fr;
    column-gap: var(--s-6);
    row-gap: 0;
    align-items: start;
}
@media (max-width: 800px) {
    /* Collapse to one column. grid-template-columns:1fr alone is NOT enough:
       the children explicitly nominate tracks (head/body/what-worked/nav →
       grid-column:2, pullquote → grid-column:1), so a single explicit track
       just spawns an implicit second column for the col-2 items and the
       layout stays two-up. Dropping to block flow neutralises every
       grid-column pick so they stack in source order. */
    .case-study__column {
        display: block;
    }
}

.case-study--editorial .case-study__head {
    grid-column: 2;
    margin-bottom: var(--s-6);
}
.case-study--editorial .case-study__title {
    /* Display-tier headline. Bold sans, matching .article__title and the
       site-wide h1-h4 700 default declared in tokens.css. Do NOT lower the
       weight — headlines are bold on lxp6. */
    font-weight: 700;
    font-size: var(--t-display);
    line-height: 1.05;
    letter-spacing: -0.015em;
    margin: 0 0 var(--s-5);
    max-width: 28ch;
    text-wrap: balance;
}
.case-study--editorial .case-study__eyebrow {
    margin: 0 0 var(--s-3);
}
.case-study--editorial .case-study__summary {
    font-family: var(--serif);
    font-style: italic;
    font-size: clamp(1.1rem, 1.8vw, 1.35rem);
    line-height: 1.4;
    color: var(--ink);
    margin: 0 0 var(--s-5);
    max-width: none;
}

/* Pull-quote sits in the LEFT track of the editorial column grid,
   spanning whatever vertical space its content needs. align-self: start
   anchors it to the top so it reads alongside the body's first
   paragraphs rather than centering vertically in the column. */
.case-study__pullquote {
    grid-column: 1;
    align-self: start;
    margin: var(--s-2) 0 var(--s-6);
}
.case-study__pullquote blockquote {
    margin: 0;
    padding: 0 0 0 var(--s-4);
    border-left: 3px solid var(--accent);
    font-family: var(--serif);
    font-style: italic;
    font-size: clamp(1.15rem, 1.8vw, 1.45rem);
    line-height: 1.35;
    color: var(--ink);
    text-wrap: balance;
}
@media (max-width: 800px) {
    .case-study__pullquote {
        grid-column: 1;
        margin: var(--s-6) 0;
    }
}

/* Body in the editorial variant — 64ch reading measure inside the
   2-fr right column. */
.case-study--editorial .case-study__body {
    grid-column: 2;
    max-width: 64ch;
    margin: 0 0 var(--s-7);
}

.case-study--editorial .case-study__what-worked {
    grid-column: 2;
    margin: var(--s-8) 0 0;
    padding: var(--s-7) 0 0;
    border-top: 1px solid var(--hairline);
    max-width: 64ch;
}

/* Prev/next nav inside the editorial column. Mirrors .article__nav. */
.case-study__nav {
    grid-column: 2;
    margin-top: var(--s-9);
    padding-top: var(--s-6);
    border-top: var(--rail-soft);
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--s-6);
    max-width: 64ch;
}
.case-study__nav-link {
    display: flex;
    flex-direction: column;
    gap: var(--s-2);
    text-decoration: none;
    color: inherit;
}
.case-study__nav-link--next { text-align: right; }
.case-study__nav-label {
    font-family: var(--sans);
    font-size: 0.72rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ink-soft);
}
.case-study__nav-title {
    font-family: var(--serif);
    font-style: italic;
    font-size: 1.1rem;
    line-height: 1.3;
    color: var(--ink);
}
@media (max-width: 560px) {
    .case-study__nav { grid-template-columns: 1fr; gap: var(--s-5); }
    .case-study__nav-link--next { text-align: left; }
}

/* Suppress the older "break-out beyond reading column" trick on the
   editorial variant — full-width hero already does that job. */
.case-study--editorial .case-study__photo {
    width: 100%;
    margin-left: 0;
}

/* ---------- Product detail (editorial layout) ---------------------- */

/* GRID RHYTHM — mirrors .article (see "Article detail" block above).
   ONE rail, ONE rhythm. Every row is a Bootstrap `.row` direct child
   of `.product`, with default 24px gutter. No per-block gutter overrides.

   `.product` lives inside <main>, which provides the rail via
       max-width: var(--maxw); padding: 0 var(--gutter)

   Row map at lg+:
     Row 1 (editorial):  header col-md-4 + hero col-md-8  → md split
     Row 2 (main):       aside col-lg-4 (specs) +
                         .product__body col-lg-8           → body LEFT
                         lines up with hero LEFT at col-5
     Row 3 (gallery):    ul.row > li col-12 col-sm-6 col-lg-4
     Row 4 (nav):        a col-12 col-sm-6 prev + next
*/
.product {
    max-width: var(--maxw);
    margin: 0 auto;
}

/* Page-wide column gutter override — same scoping + 2×-rail cap
   rationale as `.article .row` above (prevents the row outdent from
   overflowing the viewport on phones; keeps full s-8 gutter >=650px). */
.product .row {
    --bs-gutter-x: min(var(--s-8), calc(var(--gutter) * 2));
}

.product__editorial,
.product__main-row,
.product__gallery,
.product__nav {
    margin-bottom: var(--s-9);
}
.product > .row { --bs-gutter-y: 0; }

.product__head { margin: 0; }
.product__hero { margin: 0; }

/* Below md the editorial row stacks (header over hero). The row's
   gutter-y is 0 (vertical rhythm is carried on block margins), so without
   this the title/tagline would sit flush against the hero. Add a breathing
   gap under the head only while stacked; at md+ they're side by side and
   need no top offset. */
@media (max-width: 767.98px) {
    .product__hero { margin-top: var(--s-6); }
}

/* .product__tagline typography is owned by the global lead-cluster
   rule (see .lead group). Keep this layout-only — zero its margin so
   it sits flush under the title in the head column. */
.product__tagline { margin: 0; }

/* Specs rail anchors at cols 1-4 of the main row, with the body
   slot to its right (cols 5-12). The body LEFT edge therefore lines
   up with the hero LEFT edge in Row 1. Inner typography
   (responsibility grid, product-facts list, location) is owned by
   the standalone .responsibility / .product-facts / .product__location
   rules higher up — keep this rule scoped to layout only. */
.product__specs-rail {
    margin: 0;
}
.product__specs-rail .responsibility { margin-bottom: var(--s-5); }
.product__specs-rail .product-facts  { margin: 0 0 var(--s-5); }
.product__specs-rail .product__location { margin: 0; }

/* Subtitle (h2) acts as lede, not section heading — intentional exception
   to the site-wide h1-h4 bold rule (tokens.css). The `.product__subtitle`
   class (0,1,0) beats the element-level tokens `h2 { font-weight: 700 }` by
   specificity. See memory feedback_product_subtitle_is_lead. */
.product__subtitle {
    font-weight: 300;
    line-height: 1.3;
    margin: var(--s-3) 0 0;
    text-wrap: balance;
}
.product__prose { max-width: 64ch; }

/* Gallery — shares .article-slides utility row + .article-slide__trigger
   button/image rules with the article gallery (see "Article detail"
   block above). The .row class on <ul> activates Bootstrap; the
   col-* classes on <li> handle the 3-up grid. */
.product__gallery {
    padding-top: var(--s-6);
    border-top: var(--rail-soft);
}
/* No margin reset here on purpose: the shared .article-slides base already
   zeroes the block-axis margin while keeping Bootstrap's horizontal row
   outdent, so the tiles align to the rail like the hero/body. A blanket
   `margin: 0` here used to clobber the outdent too, insetting every gallery
   image ~one gutter (~20px) inside the rail — narrower than the hero. */

/* Prev/next nav — same anatomy as .article__nav. Prev in cols 1-6 of
   the row (Bootstrap sm+); only-child case anchors to the right via
   margin-left: auto so a single direction sits at the row's right
   edge instead of orphaning at the left. */
.product__nav {
    padding-top: var(--s-6);
    border-top: var(--rail-soft);
    --bs-gutter-y: var(--s-5);
}
.product__nav-link:only-child { margin-left: auto; }
.product__nav-link {
    display: flex;
    flex-direction: column;
    gap: var(--s-2);
    text-decoration: none;
    color: inherit;
}
@media (min-width: 576px) {
    .product__nav-link--next { text-align: right; }
}
.product__nav-label {
    font-family: var(--sans);
    font-size: 0.72rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ink-soft);
}
.product__nav-title {
    font-family: var(--serif);
    font-style: italic;
    font-size: 1.1rem;
    line-height: 1.3;
    color: var(--ink);
}

@media (max-width: 560px) {
    .product__nav { --bs-gutter-y: var(--s-5); }
    .product__nav-link--next { text-align: left; }
}

/* ---------- Destinations index: photographic panels ----------------
   Stacked destination panels down the pillar page. Deliberately
   rail-BOUND, not full-bleed: on this site viewport-wide imagery is
   the vocabulary of single hero moments on the rail-stripped pages
   (Home/DMC/Contact); five stacked panels at hero width would shout.
   Bounded, the stack stays in rhythm with the H1, CTA and FAQs around
   it, and panel proportions hold on very wide monitors. Panels
   separate with the standard tile gap (--s-5): as rail-bound plates,
   the scrim-base of one butting the photo-top of the next read muddy
   — the bone seam keeps each island its own surface (gapless belonged
   to the parked full-bleed wall idea). Captions inset from the panel
   edge like the small overlay tiles. Image hover scale comes from the
   central .card rule — no per-component hover. */
.destination-wall {
    list-style: none;
    padding: 0;
    margin: var(--s-7) 0 0;
    display: grid;
    gap: var(--s-5);
}
.destination-wall__panel { margin: 0; }
.destination-wall__link {
    position: relative;
    display: block;
    height: min(62vh, 580px);
    overflow: hidden;
    text-decoration: none;
    color: #fff;
}
.destination-wall__panel--lead .destination-wall__link {
    height: min(80vh, 760px);
}
.destination-wall__figure {
    position: absolute;
    inset: 0;
    margin: 0;
}
.destination-wall__figure img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.destination-wall__figure--empty {
    display: block;
    width: 100%;
    height: 100%;
    background: var(--accent-a-600);
}
/* Legibility scrim — ink-toned like the tile scrim, but deeper and
   stronger: these panels run bright Mediterranean photography behind
   white display type, so the base needs more weight than the small
   tiles' 0.55. Mid-stop keeps the ramp soft instead of a hard band. */
.destination-wall__link::after {
    content: "";
    position: absolute;
    inset: 30% 0 0 0;
    background: linear-gradient(
        to bottom,
        rgba(33, 28, 25, 0) 0%,
        rgba(33, 28, 25, 0.35) 45%,
        rgba(33, 28, 25, 0.78) 100%
    );
    pointer-events: none;
}
.destination-wall__caption {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1;
    padding: 0 var(--s-6) var(--s-6);
}
.destination-wall__eyebrow {
    color: rgba(255, 255, 255, 0.85);
    margin: 0 0 var(--s-2);
}
/* Names sit on the site's hero tier (--t-hero), NOT above it: these
   are h2s on an index page, and the h1 hero of the DMC page each panel
   links to uses the same scale — so the click-through reads as a
   seamless handoff, not a step down. */
.destination-wall__name {
    font-family: var(--sans);
    font-weight: 700;
    font-size: var(--t-hero);
    line-height: 1.08;
    letter-spacing: -0.018em;
    color: #fff;
    margin: 0;
}
.destination-wall__lede {
    color: rgba(255, 255, 255, 0.92);
    font-family: var(--sans);
    font-weight: 300;
    font-size: clamp(1rem, 1.5vw, 1.2rem);
    line-height: 1.4;
    max-width: 44ch;
    margin: var(--s-3) 0 0;
}
.destination-wall__more {
    display: inline-block;
    margin-top: var(--s-4);
    font-family: var(--sans);
    font-size: 0.9rem;
    color: #fff;
    border-bottom: 1px solid rgba(255, 255, 255, 0.55);
    padding-bottom: 2px;
}
.destination-wall__link:hover .destination-wall__more,
.destination-wall__link:focus-visible .destination-wall__more {
    border-bottom-color: #fff;
}

@media (max-width: 820px) {
    .destination-wall__link { height: min(52vh, 440px); }
    .destination-wall__panel--lead .destination-wall__link { height: min(62vh, 540px); }
    .destination-wall__caption { padding-bottom: var(--s-6); }
    .destination-wall__lede { display: none; }
}

/* ---------- Sustainability credentials block ----------------------
   Definition-list of trust signals: title-left, body-right, one
   credential per row separated by hairlines. Distinct from the
   earlier `.why-us` shell so the type weight, optional logo, and
   Meta sub-label are first-class — not borrowed scaffolding.

   Two styles share the same structure; only the ground changes:

     .sustainability--certifications  bone ground, hairline rows.
                                      Third-party audits — institutional
                                      voice.

     .sustainability--commitments     soft sand band running edge-to-edge.
                                      Self-commitments — quieter register,
                                      visually distinct from the section
                                      above without changing the layout.

   The block stays bare per the container contract (main owns the
   maxw + gutter rail on bounded-main pages like /nachhaltigkeit/).
   ------------------------------------------------------------------ */
.sustainability {
    padding: var(--s-9) 0 var(--s-8);
}

/* Self-bound only on the THREE pages that strip <main>'s rail
   (HomePage / DMCPage / ContactPage — heroes run viewport-wide there).
   Without this the block spans the full viewport on the DMC landing
   pages instead of lining up with its siblings (.why-us, service strip).
   MUST stay page-scoped: on bounded-main pages like /nachhaltigkeit/
   <main> already owns maxw + gutter, so an unscoped rule would
   double-indent. Mirrors .element.is-partial (~line 1205). */
.t-App\\PageType\\HomePage .sustainability,
.t-App\\PageType\\DMCPage .sustainability,
.t-App\\PageType\\ContactPage .sustainability {
    max-width: var(--maxw);
    margin-left: auto;
    margin-right: auto;
    padding-left: var(--gutter);
    padding-right: var(--gutter);
}

.sustainability__intro {
    margin-bottom: var(--s-8);
    align-items: baseline;
}

.sustainability__eyebrow {
    margin: 0 0 var(--s-4);
}

.sustainability__title {
    margin: 0;
    text-wrap: balance;
}

.sustainability__lead {
    font-family: var(--sans);
    font-weight: 300;
    font-size: clamp(1.1rem, 1.6vw, 1.3rem);
    line-height: 1.45;
    color: var(--ink);
    margin: 0;
    text-wrap: balance;
}

.sustainability__list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.sustainability__row {
    align-items: center;
    padding: var(--s-6) 0;
    border-top: 1px solid var(--ink);
    margin: 0;
}
.sustainability__row + .sustainability__row {
    border-top: 1px solid var(--hairline);
}
.sustainability__row:last-child {
    border-bottom: 1px solid var(--hairline);
}

.sustainability__logo {
    display: block;
    /* Logo sits in its own column, name beside it. Logos vary wildly in
       aspect ratio — Carboncero / 2020_C are portrait, the CleanWave
       lockup is a wide wordmark (454×34). Cap by BOTH height and width so
       the wide one fills the column without the portrait ones blowing up:
       height wins for portrait marks, width wins for wordmarks. */
    height: auto;
    max-height: clamp(72px, 8vw, 112px);
    max-width: 100%;
    width: auto;
    margin: 0;
}

.sustainability__name {
    font-family: var(--sans);
    font-weight: 700;
    font-size: clamp(1.25rem, 1.6vw, 1.5rem);
    line-height: 1.2;
    letter-spacing: -0.018em;
    color: var(--ink);
    margin: 0;
}

.sustainability__meta {
    margin: var(--s-2) 0 0;
    color: var(--ink-muted);
}

.sustainability__body {
    font-family: var(--sans);
    font-size: var(--t-body-lg);
    line-height: 1.55;
    color: var(--ink-soft);
    margin: 0;
}

/* Commitments variant — soft sand band that runs edge-to-edge.
   Uses the same shadow + clip-path trick as .section--soft so the
   block stays bare (main owns the rail) while the colour bleeds. */
.sustainability--commitments {
    position: relative;
    background: var(--stone-100);
    box-shadow: 0 0 0 100vmax var(--stone-100);
    clip-path: inset(0 -100vmax);
    padding: var(--s-10) 0 var(--s-9);
    margin: var(--s-8) 0;
}

@media (max-width: 991px) {
    .sustainability__intro {
        margin-bottom: var(--s-6);
    }
    .sustainability__lead-wrap {
        margin-top: var(--s-4);
    }
    .sustainability__body-col {
        margin-top: var(--s-3);
    }
}

@media (max-width: 600px) {
    .sustainability {
        padding: var(--s-8) 0 var(--s-7);
    }
    .sustainability--commitments {
        padding: var(--s-9) 0 var(--s-8);
    }
    .sustainability__logo {
        max-height: 64px;
    }
    .sustainability__name-col {
        display: flex;
        flex-direction: column;
        justify-content: center;
    }
    .sustainability__body-col {
        flex: 0 0 100%;
        max-width: 100%;
    }
    .sustainability__row {
        padding: var(--s-5) 0;
    }
}

/* ---------- Sustainability page pull-quote ------------------------
   Sits between the two ElementSustainability blocks via the
   SustainabilityPage layout override. Garamond italic, centered on
   the 12-col grid, narrow measure to keep it as a deliberate pause
   between sections. No quote-mark trash.

   Cancels the Bootstrap .row negative margins inside the block so
   the quote text doesn't leak past the main gutter on mobile. */
.sustainability-quote {
    padding: var(--s-9) 0;
}
.sustainability-quote .row {
    margin-left: 0;
    margin-right: 0;
}
.sustainability-quote .row > [class*="col-"] {
    padding-left: 0;
    padding-right: 0;
}

.sustainability-quote__text {
    font-family: var(--serif);
    font-style: italic;
    font-weight: 400;
    font-size: clamp(1.4rem, 2.4vw, 2rem);
    line-height: 1.4;
    letter-spacing: -0.005em;
    color: var(--ink);
    /* Reset UA blockquote margins (default ~1em 40px) — they were
       letting the quote leak past the main gutter on mobile. */
    margin: 0;
    padding: 0;
    text-align: center;
    text-wrap: balance;
}

@media (max-width: 600px) {
    .sustainability-quote {
        padding: var(--s-8) 0;
    }
    .sustainability-quote__text {
        text-align: left;
    }
}

/* ---------- Job listing — structured open-position cards ----------------
   Replaces the legacy ad-hoc ElementTextText job ads on /jobs. A two-up
   grid of bordered cards: location + type as small UI labels, role title,
   plain-text intro lede, responsibilities, then a clear two-action footer
   (full flip-book description + apply-by-email). Bootstrap .row/.col owns
   the column math; everything else is token-driven. */
.job-listing {
    padding: var(--s-9) 0 var(--s-10);
}
.job-listing__head {
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
    margin: 0 0 var(--s-7);
    max-width: var(--maxw-text);
}
.job-listing__title {
    margin: 0;
    color: var(--ink);
}
.job-listing__lead {
    font-size: var(--t-body-lg);
    line-height: var(--lh-loose);
    color: var(--ink-soft);
    margin: 0;
}
.job-listing__grid {
    list-style: none;
    padding: 0;
    /* Reset only the block-axis list margin. The inline-axis margins are
       Bootstrap's `.row` negative outdent (calc(-.5 * --bs-gutter-x)) — a
       blanket `margin: 0` here clobbered them, insetting the card columns
       ~12px inside the page rail so they no longer aligned with the head,
       sub-nav and sibling blocks. Keep the outdent so the cards land on
       the same maxw+gutter rail as the rest of the page body. */
    margin-top: 0;
    margin-bottom: 0;
    row-gap: var(--s-6);
}
.job-listing__item { margin: 0; }

.job-listing__card {
    display: flex;
    flex-direction: column;
    gap: var(--s-4);
    height: 100%;
    padding: var(--s-6);
    background: var(--surface);
    border: 1px solid var(--hairline);
    border-radius: var(--r-md);
    transition: border-color 220ms var(--ease);
}
.job-listing__card:hover { border-color: var(--stone-300); }

.job-listing__meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2);
}
.job-listing__tag {
    display: inline-flex;
    align-items: center;
    font-family: var(--sans);
    font-size: var(--t-micro);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    font-weight: 500;
    color: var(--ink-muted);
    padding: var(--s-1) var(--s-3);
    border: 1px solid var(--hairline);
    border-radius: var(--r-pill);
}
.job-listing__tag--type {
    color: var(--accent);
    border-color: var(--accent-soft);
}

.job-listing__role {
    font-family: var(--sans);
    font-weight: 700;
    font-size: var(--t-h3);
    line-height: var(--lh-snug);
    letter-spacing: -0.01em;
    color: var(--ink);
    margin: 0;
}
.job-listing__intro {
    font-size: var(--t-body-lg);
    line-height: var(--lh-body);
    color: var(--ink-soft);
    margin: 0;
}
.job-listing__body {
    font-size: var(--t-body);
}
.job-listing__body p,
.job-listing__body ul,
.job-listing__body li {
    font-size: var(--t-body);
}

.job-listing__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-4);
    margin-top: auto;
    padding-top: var(--s-4);
    border-top: 1px solid var(--hairline-soft);
}
.job-listing__link { font-size: var(--t-small); }

@media (max-width: 800px) {
    .job-listing__card { padding: var(--s-5); }
}
