/* =============================================================================
   Laira Coaching & Consulting — Core Stylesheet
   Mobile-first. See responsive.css for breakpoint overrides.

   Design language: minimal, editorial. The palette is taken directly from the
   Laira logo: a deep teal ink and a gold accent on the logo's warm cream.
   Restraint is the point — the gold appears as rules, marks, borders and the
   primary button, never as large fields of colour. A muted sage (the
   watercolour wash in the logo artwork) survives for quiet utility states
   (success messages, advisory boxes).
   ========================================================================== */

/* ---------------------------------------------------------------------------
   1. CSS Custom Properties (design tokens)
   ------------------------------------------------------------------------- */
:root {
    /* Colour palette — sampled from assets/images/laira-logo-lockup.png: the
       wordmark teal (#194747 averaged), the crescent gold (#c08e39 at its most
       saturated), and the cream ground (#f7f2ee).

       The gold is decorative, not a text colour: #be9042 on cream is only
       2.7:1, so anything that must *read* uses --color-accent-deep (a darkened
       gold, 5.3:1) or the teal ink. --color-accent-soft is the pale gold used
       for accent text on teal surfaces. */
    --color-ink: #14484a;
    --color-ink-deep: #0b2e30;
    --color-ink-soft: #55696b;
    --color-paper: #faf6ef;
    --color-paper-alt: #f2ead9;
    --color-white: #ffffff;
    --color-line: #e4dccd;

    --color-accent: #be9042;
    --color-accent-deep: #7e611f;
    --color-accent-soft: #f2e4c6;

    --color-sage: #7f9a92;
    --color-sage-deep: #3f5a55;
    --color-sage-soft: #dee9e4;

    /* Semantic colours */
    --color-bg: var(--color-paper);
    --color-bg-alt: var(--color-paper-alt);
    --color-text: var(--color-ink);
    --color-text-muted: var(--color-ink-soft);
    --color-border: var(--color-line);
    --color-link: var(--color-accent-deep);
    /* Teal, not gold: a focus ring has to hit 3:1 against what surrounds it,
       and the gold accent manages 2.7:1 on cream. */
    --color-focus: var(--color-ink);
    /* Red is not in the brand palette at all now, which is exactly what makes
       it usable for validation — an error border can never be mistaken for
       ordinary accent styling. */
    --color-error: #c62828;
    --color-success: var(--color-sage-deep);

    /* Typography — Roboto for every heading, Poppins for paragraph/body copy. */
    --font-heading: 'Roboto', 'Helvetica Neue', Arial, sans-serif;
    --font-body: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif;

    /* Spacing scale */
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.5rem;
    --space-6: 2rem;
    --space-7: 3.25rem;
    --space-8: 5rem;
    --space-9: 7rem;

    /* Layout */
    --container-max: 1180px;
    --container-pad: var(--space-5);
    --radius-sm: 4px;
    --radius-md: 10px;
    --radius-lg: 18px;

    /* Shadows — quiet by default, a touch more present on hover/elevation */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
    --shadow-md: 0 10px 30px rgba(0, 0, 0, 0.08);
    --shadow-lg: 0 24px 60px rgba(0, 0, 0, 0.14);

    /* Motion */
    --transition-fast: 150ms ease;
    --transition-base: 250ms ease;
    --transition-slow: 500ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* ---------------------------------------------------------------------------
   2. Reset & base
   ------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }

/* The closed mobile nav drawer is parked off-canvas with a transform, which
   Chrome counts towards the document's scrollable width — so on phones the
   page could be dragged sideways to reveal the shut menu. `clip` (rather than
   `hidden`) kills that sideways scroll without turning the root into a scroll
   container, which would break the sticky site header. */
html, body { overflow-x: clip; }

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }
}

body {
    margin: 0;
    font-family: var(--font-body);
    font-size: 1rem;
    line-height: 1.7;
    color: var(--color-text);
    background: var(--color-bg);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

img, picture, svg { max-width: 100%; display: block; height: auto; }

/* Scroll lock while the mobile drawer is open. Set as a class rather than an
   inline style so it cannot be clobbered by anything else writing to
   body.style, and so the state is inspectable from CSS. */
body.nav-open { overflow: hidden; }

/* The site's own email address (SITE_EMAIL, currently
   info@lairacoachingandconsulting.com) runs to ~35 characters with no break
   opportunity in it. Left alone it sets the
   min-content width of whatever holds it, which at 320-375px dragged the
   contact card to 411px, the footer's single-column track to 345px and pushed
   the closing CTA's mailto link off both edges — all of it silently chopped by
   the `overflow-x: clip` above rather than showing as a scrollbar. Letting long
   strings break, and letting grid/flex items shrink past min-content, fixes
   every one of those at once. */
body { overflow-wrap: break-word; }
a[href^="mailto:"], a[href^="tel:"] { overflow-wrap: anywhere; }
.grid > *,
.site-footer__grid > *,
.form-grid > *,
.hero__inner > * { min-width: 0; }

/* Roboto only ships 400/500/700/900 on Google Fonts, so every heading weight
   below is one of those four — asking for 600 would make the browser
   synthesise a fake bold and headings would render unevenly. */
h1, h2, h3, h4 {
    font-family: var(--font-heading);
    color: var(--color-ink);
    line-height: 1.18;
    font-weight: 700;
    letter-spacing: -0.015em;
    margin: 0 0 var(--space-4);
}
h1 { font-size: clamp(2rem, 4.3vw, 3.15rem); font-weight: 700; letter-spacing: -0.03em; }
h2 { font-size: clamp(1.55rem, 2.9vw, 2.15rem); font-weight: 700; letter-spacing: -0.025em; }
h3 { font-size: clamp(1.15rem, 2vw, 1.35rem); font-weight: 700; }
h4 { font-size: 1.05rem; font-weight: 500; }

/* No explicit color here on purpose — paragraphs must inherit from their
   section (dark sections set a light color on themselves); a hardcoded
   color here would silently win over that inheritance and go invisible
   on dark backgrounds. Only components with their own override (e.g.
   .section--navy p, .cta-band p) should set color on <p> directly. */
p { margin: 0 0 var(--space-4); max-width: 68ch; }
p.no-max { max-width: none; }

a { color: var(--color-link); text-decoration-thickness: 1px; text-underline-offset: 3px; }
/* Hover goes darker, never lighter: the base gold accent is 2.7:1 on cream, so
   using it as a hover colour made hovered links harder to read than resting
   ones. Note this rule is (0,1,1) and beats a bare .btn--x (0,1,0) — every
   button variant therefore has to set its own hover colour explicitly, or its
   label gets recoloured to this value mid-hover. */
a:hover { color: var(--color-ink); text-decoration-thickness: 2px; }

ul, ol { padding-left: 1.25rem; }

button { font-family: inherit; }

/* Focus visibility (WCAG 2.2) */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
    outline: 2px solid var(--color-focus);
    outline-offset: 3px;
    border-radius: 2px;
}

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

.skip-link {
    position: absolute;
    left: var(--space-4);
    top: -100px;
    background: var(--color-ink);
    color: var(--color-paper);
    padding: var(--space-3) var(--space-5);
    border-radius: var(--radius-sm);
    z-index: 1000;
    transition: top var(--transition-base);
    text-decoration: none;
}
.skip-link:focus { top: var(--space-4); }

/* ---------------------------------------------------------------------------
   3. Layout helpers
   ------------------------------------------------------------------------- */
.container {
    max-width: var(--container-max);
    margin-inline: auto;
    padding-inline: var(--container-pad);
}

.section { padding-block: var(--space-8); }
.section--alt { background: var(--color-bg-alt); }
/* The intro's own section-head still carries its normal margin-bottom (for
   pages that stack more content in the same section), but page-intro is
   always immediately followed by another .section with its own space-8
   top padding — so without this override, the gap between the intro copy
   and the next section's content compounds to head-margin + intro-padding
   + next-section-padding (~184px) and reads as a dead gap. Collapsing the
   head's own margin here and trimming the intro's padding leaves a single,
   normal-sized gap driven mostly by the next section's top padding. */
.page-intro { background: var(--color-bg-alt); padding-bottom: var(--space-5); }
.page-intro .section-head { margin-bottom: 0; }

/* Page intros run to 80% of the container rather than the 720px reading cap
   .section-head uses inside content sections: an intro is one centred
   statement at the top of a page, not a lead-in to a column of body copy, and
   at 720px the headings broke across three lines with the lede in a narrow
   ribbon. The lede's own 50ch cap has to come off too or it holds the old
   width. Percentage widths only apply once there is width to give away —
   below 768px the container is already narrower than the cap. */
@media (min-width: 768px) {
    .page-intro .section-head { max-width: 80%; }
    .page-intro .section-head .hero__lede { max-width: none; }
}

/* About page intro: a tinted photo backdrop instead of a flat fill. The
   overlay is a heavy tint of the same paper-alt color (not a separate
   design), so body text keeps the same contrast ratio it has everywhere
   else on the site — only a hint of the photograph shows through.
   Path is relative to this stylesheet (assets/css/), which keeps it valid
   whether the site is served from a domain root or a subfolder — CSS
   url() has no equivalent to the PHP BASE_PATH constant used in markup. */
.page-about .page-intro {
    background-image: linear-gradient(rgba(242, 234, 217, 0.8), rgba(242, 234, 217, 0.8)), url('../images/karachi-skyline-pakistan-rooted-methodology.jpg');
    background-size: cover;
    background-repeat: no-repeat;
    background-position: center 30%;
}
/* Let the intro heading/lede span the full container instead of the
   720px reading-width cap .section-head uses everywhere else — this
   section is a wide photo backdrop, not a block of body copy. */
.page-about .page-intro .section-head { max-width: none; }
.page-about .page-intro .hero__lede { max-width: none; }
.section--navy { background: var(--color-ink); color: rgba(250, 246, 239, 0.86); }
.section--navy h2, .section--navy h3 { color: var(--color-paper); }
.section--navy p { color: rgba(250, 246, 239, 0.72); }
.section--teal-soft { background: var(--color-sage-soft); }

.section-head { max-width: 720px; margin: 0 0 var(--space-7); }
.section-head--center { margin-inline: auto; text-align: center; }
.eyebrow {
    display: inline-block;
    font-family: var(--font-body);
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    font-size: 0.74rem;
    color: var(--color-accent-deep);
    margin-bottom: var(--space-3);
}
.section--navy .eyebrow { color: var(--color-accent-soft); }

/* Delicate centred rule beneath the eyebrow on centred section heads — a
   quiet editorial marker instead of relying on colour/weight alone. */
.section-head--center .eyebrow { position: relative; padding-bottom: var(--space-3); }
.section-head--center .eyebrow::after {
    content: '';
    position: absolute;
    left: 50%; bottom: 0;
    width: 32px; height: 2px;
    background: var(--color-accent);
    transform: translateX(-50%);
}
.section--navy .section-head--center .eyebrow::after,
.trust-strip .section-head--center .eyebrow::after { background: var(--color-accent-soft); }

.grid { display: grid; gap: var(--space-6); }
.grid-2 { grid-template-columns: repeat(1, 1fr); }
.grid-3 { grid-template-columns: repeat(1, 1fr); }
.grid-4 { grid-template-columns: repeat(1, 1fr); }
.grid-5 { grid-template-columns: repeat(1, 1fr); }

.visually-reveal {
    opacity: 0;
    transform: translateY(16px);
    transition: opacity var(--transition-slow), transform var(--transition-slow);
}
.visually-reveal.is-visible { opacity: 1; transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
    .visually-reveal { opacity: 1; transform: none; }
}

/* ---------------------------------------------------------------------------
   4. Buttons
   ------------------------------------------------------------------------- */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: 0.8rem 1.65rem;
    border-radius: var(--radius-sm);
    font-weight: 600;
    font-size: 0.96rem;
    letter-spacing: 0.01em;
    text-decoration: none;
    border: 1.5px solid transparent;
    cursor: pointer;
    transition: transform var(--transition-fast), box-shadow var(--transition-fast), background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast);
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

/* Every variant restates `color` on :hover. The generic `a:hover` rule above is
   more specific than a single button class, so a variant that only changes its
   background on hover has its label silently repainted the link-hover colour —
   which is how the primary CTA ended up with near-invisible text on hover. */

/* Gold fill takes the deepest teal as its label (4.6:1); cream on gold is only
   3:1. Hover flips the whole button to teal, so the state change is unmissable
   and the label lands at 9.4:1. */
.btn--gold {
    background: var(--color-accent);
    color: var(--color-ink-deep);
    box-shadow: var(--shadow-sm);
}
.btn--gold:hover {
    background: var(--color-ink);
    color: var(--color-paper);
    border-color: var(--color-ink);
    box-shadow: var(--shadow-md);
}

.btn--navy {
    background: var(--color-ink);
    color: var(--color-paper);
}
/* Deepening teal-on-teal is a subtle change on its own, so the gold rim does
   the signalling here. */
.btn--navy:hover {
    background: var(--color-ink-deep);
    color: var(--color-paper);
    border-color: var(--color-accent);
}

.btn--outline {
    background: transparent;
    border-color: var(--color-ink);
    color: var(--color-ink);
}
.btn--outline:hover { background: var(--color-ink); color: var(--color-paper); border-color: var(--color-ink); }

.btn--outline-light {
    background: transparent;
    border-color: rgba(250, 246, 239, 0.45);
    color: var(--color-paper);
}
.btn--outline-light:hover {
    background: rgba(250, 246, 239, 0.12);
    color: var(--color-paper);
    border-color: var(--color-paper);
}

.btn--sm { padding: 0.5rem 1rem; font-size: 0.86rem; }
.btn--lg { padding: 1rem 2.1rem; font-size: 1.02rem; }
.btn:disabled { opacity: 0.55; cursor: not-allowed; transform: none; }

/* ---------------------------------------------------------------------------
   5. Header & navigation
   ------------------------------------------------------------------------- */
/* The translucent blur lives on a pseudo-element, not on .site-header itself,
   and this is load-bearing rather than stylistic: a non-`none` backdrop-filter
   makes an element the containing block for every position:fixed descendant.
   With the filter on the header, the off-canvas drawer inside it resolved
   `inset: 0` against the ~75px header box instead of the viewport and opened
   as a 160px band across the top of the page. Painting the blur into ::before
   keeps the exact same appearance while leaving the header a normal ancestor,
   so the drawer measures itself against the viewport again. */
.site-header {
    position: sticky;
    top: 0;
    z-index: 500;
    border-bottom: 1px solid var(--color-line);
}
.site-header::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    background: rgba(250, 246, 239, 0.9);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
}
.site-header__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-block: var(--space-3);
}

.site-logo {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    text-decoration: none;
}
.site-logo__mark { width: 46px; height: 46px; flex-shrink: 0; }
.site-logo__text { display: flex; flex-direction: column; line-height: 1.1; }
.site-logo__name { font-family: var(--font-heading); font-weight: 700; font-size: 1.9rem; letter-spacing: -0.03em; color: var(--color-ink); }
.site-logo__sub { font-size: 0.66rem; font-weight: 500; letter-spacing: 0.16em; text-transform: uppercase; color: var(--color-text-muted); }
/* The tagline rides with the logo everywhere it appears (header + footer),
   which is the only place it lives now — the standalone tagline line that
   used to sit under the footer blurb has been removed. */
.site-logo__tagline {
    margin-top: 0.28rem;
    font-size: 0.66rem;
    font-weight: 500;
    letter-spacing: 0.09em;
    color: var(--color-accent-deep);
}

/* 44x44 is the WCAG 2.2 target size; the bars themselves are only ~15px tall,
   so the button needs an explicit box rather than padding around the icon. */
.nav-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    flex-shrink: 0;
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    position: relative;
    z-index: 60;
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
}
.nav-toggle__box { display: flex; flex-direction: column; gap: 5px; width: 24px; }
.nav-toggle__bar {
    height: 1.5px; background: var(--color-ink); border-radius: 2px;
    transition: transform var(--transition-base), opacity var(--transition-base), background var(--transition-base);
}
/* Open state: the three bars fold into a cross. The button sits above the
   drawer (z-index 60 vs 50) and lands inside its top-right corner, so this is
   the drawer's close control — but the bars inherit --color-ink, which is the
   exact colour of the drawer behind them (#14484a on #14484a). The cross was
   being drawn, perfectly invisible. It has to flip to the paper tone the rest
   of the drawer's text uses, and the bars need a colour transition or they
   snap while the rest of the icon animates. */
.nav-toggle[aria-expanded="true"] .nav-toggle__bar { background: var(--color-paper); }
.nav-toggle[aria-expanded="true"]:hover .nav-toggle__bar { background: var(--color-accent-soft); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }
/* Keeps the cross clear of the drawer's own focus ring colour when tabbed to. */
.nav-toggle[aria-expanded="true"]:focus-visible { outline-color: var(--color-accent-soft); }

/* Dimmed backdrop behind the open drawer. It is a real element rather than a
   pseudo so it can carry its own click handler (tap-outside-to-close). */
.nav-scrim {
    position: fixed;
    inset: 0;
    z-index: 40;
    background: rgba(11, 46, 48, 0.55);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--transition-base), visibility 0s linear 250ms;
    border: none;
    padding: 0;
    cursor: pointer;
}
.nav-scrim.is-open {
    opacity: 1;
    visibility: visible;
    transition: opacity var(--transition-base), visibility 0s;
}

/* Off-canvas drawer. Width is capped so it does not become an 800px slab on a
   tablet, and the height uses dvh so mobile browser chrome collapsing does not
   leave the bottom of the menu (the CTA) under the address bar. */
.primary-nav {
    position: fixed;
    top: 0;
    right: 0;
    width: min(86vw, 380px);
    height: 100vh;
    height: 100dvh;
    z-index: 50;
    background: var(--color-ink);
    display: flex;
    flex-direction: column;
    justify-content: center;
    /* Second declaration, so browsers without `safe` keep the plain centring.
       With the About sub-links the drawer's content can now exceed a mid-size
       phone's height, and plain centred overflow pushes the first rows past
       the top edge where they cannot be scrolled back into view. */
    justify-content: safe center;
    padding: var(--space-8) var(--space-6);
    transform: translateX(100%);
    /* `visibility` rather than the old pointer-events approach: pointer-events
       still left every link in the tab order and exposed to screen readers
       while the drawer sat off-canvas. visibility:hidden removes it from both,
       and the 0s-delayed transition holds it visible until the slide finishes. */
    visibility: hidden;
    transition: transform var(--transition-slow), visibility 0s linear 500ms;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
}
.primary-nav.is-open {
    transform: translateX(0);
    visibility: visible;
    transition: transform var(--transition-slow), visibility 0s;
}
.primary-nav__list { list-style: none; margin: 0 0 var(--space-6); padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.primary-nav__link {
    display: block;
    color: rgba(250, 246, 239, 0.82);
    text-decoration: none;
    font-weight: 500;
    font-family: var(--font-heading);
    font-size: 1.3rem;
    /* Keeps each row at/above the 44px WCAG 2.2 target in the drawer. */
    padding: var(--space-3) 0;
    border-bottom: 1px solid rgba(250, 246, 239, 0.08);
}
.primary-nav__link:hover, .primary-nav__link.is-active { color: var(--color-accent-soft); }
.nav-cta { align-self: flex-start; }

/* Dropdown parent (About). In the drawer there is no dropdown to open: the
   sub-links simply sit indented under their parent, always visible, so the
   chevron button has nothing to do and is hidden. It comes back — along with
   the collapsed panel — in the desktop block in responsive.css. */
.primary-nav__item { display: flex; flex-direction: column; }
.primary-nav__toggle { display: none; }
.primary-nav__submenu {
    list-style: none;
    margin: 0;
    padding: 0 0 var(--space-2) var(--space-4);
    display: flex;
    flex-direction: column;
}
.primary-nav__sublink {
    display: block;
    color: rgba(250, 246, 239, 0.66);
    text-decoration: none;
    font-family: var(--font-heading);
    font-size: 1.02rem;
    /* Same 44px minimum target as the top-level rows. */
    padding: var(--space-3) 0;
    border-bottom: 1px solid rgba(250, 246, 239, 0.06);
}
.primary-nav__sublink:hover,
.primary-nav__sublink.is-active { color: var(--color-accent-soft); }

/* Landscape phones and short windows: centring 8 links plus a CTA inside a
   ~380px-tall drawer pushed the first and last items past the edges, and the
   5rem block padding made it worse. Anchor to the top and scroll instead. */
@media (max-width: 1199px) and (max-height: 620px) {
    .primary-nav {
        justify-content: flex-start;
        padding-block: var(--space-6);
    }
    .primary-nav__link { font-size: 1.12rem; padding: var(--space-2) 0; }
}

/* ---------------------------------------------------------------------------
   6. Hero
   ------------------------------------------------------------------------- */
.hero {
    position: relative;
    padding-block: var(--space-8) var(--space-9);
    background: var(--color-paper);
    overflow: hidden;
}
.hero__inner {
    display: grid;
    gap: var(--space-7);
    align-items: center;
}
.hero__eyebrow { color: var(--color-accent-deep); }
.hero__lede { font-size: 1.15rem; color: var(--color-text-muted); max-width: 50ch; }
.hero__actions { display: flex; flex-wrap: wrap; gap: var(--space-4); margin-top: var(--space-6); }
.hero__media {
    position: relative;
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-lg);
    /* Stretch to match the height of its paired text column instead of
       collapsing to the image's own aspect-ratio height — the previous
       behaviour left large empty gaps above/below shorter images whenever
       they sat next to taller text (align-items: center on the parent grid
       centred a short box instead of filling the row). */
    align-self: stretch;
    min-height: 260px;
}

/* Any grid pairing .hero__media with a text column: stretch both sides to
   match (rather than centering whichever is shorter, which left empty gaps
   above/below that side — this happened in both directions depending on
   whether the image or the text block was taller) and vertically centre
   the text column's own content within its now-equal-height box. */
.grid:has(> .hero__media) { align-items: stretch; }
.grid > .hero__media + div,
.grid > div:has(+ .hero__media) {
    display: flex;
    flex-direction: column;
    justify-content: center;
}
/* Turning that text column into a flex column stretches every direct child to
   the full column width — right for paragraphs and cards, wrong for a button,
   which should stay the width of its own label. */
.grid > .hero__media + div > .btn,
.grid > div:has(+ .hero__media) > .btn { align-self: flex-start; }
.hero__media img { width: 100%; height: 100%; object-fit: cover; aspect-ratio: 4 / 3; }

/* Portrait variant, for the founder photographs on the Founders and Portfolio
   pages. The stretch behaviour above is right for scene photography but wrong
   for a person: beside a long biography column it stretched a 4:5 portrait to
   roughly 1:2.8, and object-fit: cover then cropped the subject down to a
   narrow vertical strip. Fixed ratio, aligned to the top of the row. */
.hero__media--portrait { align-self: start; }
.hero__media--portrait img { aspect-ratio: 4 / 5; height: auto; }

/* A 4:5 portrait in an equal-width column stands ~690px tall beside a
   biography that runs much longer, so the bottom of the photo column read as
   dead space. Narrowing the portrait column shortens the photo and widens the
   prose, closing most of the gap; sticky carries the portrait down alongside
   whatever text is left rather than parking it at the top. */
@media (min-width: 768px) {
    .hero__media--portrait { position: sticky; top: 6.5rem; }
}
/* Only from 1024px: at tablet width the same ratio cut the portrait down to
   ~257px, which is too small to read as a professional headshot — there the
   equal split is the better trade. */
@media (min-width: 1024px) {
    .grid-2:has(> .hero__media--portrait) { grid-template-columns: minmax(0, 0.62fr) minmax(0, 1fr); }
    /* A row that puts the portrait on the right (u-order-2) has to swap the
       narrow column over with it. No section uses this today — the Founders
       page's second founder has no published photograph — but it keeps the
       alternating-portrait layout available. */
    .grid-2:has(> .hero__media--portrait.u-order-2) { grid-template-columns: minmax(0, 1fr) minmax(0, 0.62fr); }
}
.hero__badge {
    position: absolute;
    left: var(--space-5);
    bottom: var(--space-5);
    background: rgba(250, 246, 239, 0.96);
    backdrop-filter: blur(6px);
    padding: var(--space-4) var(--space-5);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    max-width: 250px;
}
.hero__badge strong { display: block; color: var(--color-ink); font-family: var(--font-heading); font-size: 1.3rem; font-weight: 600; }
.hero__badge span { font-size: 0.83rem; color: var(--color-text-muted); }

/* ---------------------------------------------------------------------------
   7. Trust / credentials
   ------------------------------------------------------------------------- */
.trust-strip { background: var(--color-ink); color: rgba(250, 246, 239, 0.88); }
.trust-strip h2, .trust-strip h3 { color: var(--color-paper); }
.trust-strip .eyebrow { color: var(--color-accent-soft); }
.trust-grid { display: grid; gap: var(--space-6); grid-template-columns: repeat(1, 1fr); }
.trust-item {
    display: flex;
    gap: var(--space-4);
    align-items: flex-start;
    padding-block: var(--space-2);
}
/* Base styles assume a light background (this component is reused on plain
   content pages, e.g. the About page's "Our Values"). The two homepage
   sections that place it on a dark background (.trust-strip, .section--navy)
   get their own override below so text stays readable in both contexts. */
.trust-item__icon {
    flex-shrink: 0;
    width: 34px; height: 34px;
    display: grid; place-items: center;
    border-radius: 50%;
    border: 1.5px solid var(--color-accent);
    color: var(--color-accent-deep);
    font-family: var(--font-heading);
    font-weight: 600;
    font-size: 0.9rem;
}
.trust-item p { margin: 0; font-size: 0.95rem; color: var(--color-text-muted); }

.trust-strip .trust-item__icon, .section--navy .trust-item__icon { color: var(--color-accent-soft); }
.trust-strip .trust-item p, .section--navy .trust-item p { color: rgba(250, 246, 239, 0.78); }

.trust-note { font-size: 1.05rem; color: rgba(250, 246, 239, 0.6); margin-top: var(--space-7); max-width: none; text-align: center; }

/* ---------------------------------------------------------------------------
   8. Cards (services / audiences / founders / process)
   ------------------------------------------------------------------------- */
.card {
    background: var(--color-white);
    border: 1px solid var(--color-line);
    border-radius: var(--radius-lg);
    padding: var(--space-6);
    box-shadow: none;
    transition: transform var(--transition-base), box-shadow var(--transition-base), border-color var(--transition-base);
    height: 100%;
    display: flex;
    flex-direction: column;
}
.card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: transparent; }

.service-card__icon {
    width: 50px; height: 50px;
    display: grid; place-items: center;
    border-radius: 50%;
    border: 1.5px solid var(--color-accent-soft);
    color: var(--color-accent-deep);
    margin-bottom: var(--space-4);
    flex-shrink: 0;
}
.service-card__icon svg { width: 24px; height: 24px; }

/* Full-bleed photo at the top of a service card, above the icon/title. */
.service-card { overflow: hidden; }
.service-card__photo {
    aspect-ratio: 16/10;
    margin: calc(var(--space-6) * -1) calc(var(--space-6) * -1) var(--space-4);
    background: var(--color-paper-alt);
    overflow: hidden;
}
.service-card__photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.card__title { margin-bottom: var(--space-3); }
.card__body { flex-grow: 1; }
.card__link {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font-weight: 600;
    text-decoration: none;
    margin-top: var(--space-4);
}
.card__link::after { content: '\2192'; transition: transform var(--transition-fast); }
.card__link:hover::after { transform: translateX(4px); }

.audience-card { border-top: 2px solid var(--color-accent); }
.audience-card h3 { margin-bottom: var(--space-2); }
.audience-card .audience-label { font-size: 0.76rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--color-sage-deep); font-weight: 700; }

.founder-card {
    display: flex;
    flex-direction: column;
    background: var(--color-white);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: none;
    border: 1px solid var(--color-line);
}
.founder-card__photo { aspect-ratio: 4/5; background: var(--color-paper-alt); overflow: hidden; }
.founder-card__photo img { width: 100%; height: 100%; object-fit: cover; }
.founder-card__body { padding: var(--space-6); }
.founder-card__role { color: var(--color-accent-deep); font-weight: 600; margin-bottom: var(--space-3); display: block; }
.founder-card__credentials { list-style: none; padding: 0; margin: var(--space-4) 0; font-size: 0.9rem; color: var(--color-text-muted); }
.founder-card__credentials li { padding-left: 1.25rem; position: relative; margin-bottom: var(--space-2); }
.founder-card__credentials li::before { content: '\2013'; position: absolute; left: 0; color: var(--color-accent); font-weight: 700; }

/* Generic version of the same dash-list treatment, for credential/feature
   lists outside the founder-profile context. */
.credential-list { list-style: none; padding: 0; margin: var(--space-4) 0; color: var(--color-text-muted); }
.credential-list li {
    padding: var(--space-3) 0 var(--space-3) 1.5rem;
    position: relative;
    border-bottom: 1px solid var(--color-line);
}
.credential-list li:first-child { padding-top: 0; }
.credential-list li:last-child { border-bottom: none; padding-bottom: 0; }
.credential-list li::before {
    content: '';
    position: absolute;
    left: 0; top: 1.05rem;
    width: 6px; height: 6px;
    border-radius: 50%;
    background: var(--color-accent);
}

/* Small icon-in-a-ring used for value/foundation cards (mirrors .service-card__icon). */
.value-icon {
    width: 50px; height: 50px;
    display: grid; place-items: center;
    border-radius: 50%;
    border: 1.5px solid var(--color-accent-soft);
    color: var(--color-accent-deep);
    margin-bottom: var(--space-4);
    flex-shrink: 0;
}
.value-icon svg { width: 24px; height: 24px; }

/* Minimal, centred treatment for short single-line feature/offering lists
   (service sub-items, workshop topics) that previously rendered as bare
   cards with just a heading and a lot of empty padding. */
.feature-card { text-align: center; align-items: center; }
.feature-card__icon {
    width: 40px; height: 40px;
    margin: 0 auto var(--space-3);
    border-radius: 50%;
    display: grid; place-items: center;
    background: var(--color-accent-soft);
    color: var(--color-accent-deep);
    flex-shrink: 0;
}
.feature-card__icon svg { width: 18px; height: 18px; }
.feature-card h3 { font-size: 1.02rem; margin: 0; }

/* "Why Laira" teaser banner: an accented callout card rather than plain text. */
.teaser-card {
    background: var(--color-white);
    border: 1px solid var(--color-line);
    border-left: 4px solid var(--color-accent);
    border-radius: var(--radius-lg);
    padding: var(--space-6) var(--space-7);
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}
.teaser-card .eyebrow { margin-bottom: 0; }
.teaser-card h2 { margin-bottom: 0; }
.teaser-card p { margin-bottom: 0; }
.teaser-card__actions { margin-top: var(--space-3); }

.process-step { text-align: center; padding: var(--space-5); }
.process-step__number {
    display: grid; place-items: center;
    width: 56px; height: 56px;
    margin: 0 auto var(--space-4);
    border-radius: 50%;
    border: 1.5px solid var(--color-accent);
    color: var(--color-ink);
    font-family: var(--font-heading);
    font-weight: 600;
    font-size: 1.3rem;
}

/* ---------------------------------------------------------------------------
   8b. Photography components
   Shared building blocks for the imagery that runs through every page, so
   individual templates stay free of style="" attributes (a strict CSP is a
   goal here) and no page needs its own one-off background-image rule.
   ------------------------------------------------------------------------- */

/* Full-bleed photographic band with an ink scrim and copy laid over it.
   The scrim is a fixed ink overlay rather than image-dependent, so the
   text contrast ratio is the same no matter which photograph is used. */
.photo-band { position: relative; overflow: hidden; background: var(--color-ink); isolation: isolate; }
.photo-band__img {
    position: absolute;
    inset: 0;
    width: 100%; height: 100%;
    object-fit: cover;
    opacity: 0.34;
    z-index: -1;
}
.photo-band__inner { position: relative; padding-block: var(--space-8); }
.photo-band h2, .photo-band h3 { color: var(--color-paper); }
.photo-band p { color: rgba(250, 246, 239, 0.8); }
.photo-band .eyebrow { color: var(--color-accent-soft); }
.photo-band .section-head--center .eyebrow::after { background: var(--color-accent-soft); }
.photo-band .trust-item__icon { color: var(--color-accent-soft); border-color: var(--color-accent-soft); }
.photo-band .trust-item p { color: rgba(250, 246, 239, 0.82); }

/* Row of supporting photographs — visual texture for sections that are
   otherwise a wall of lists or body copy. */
.media-strip { display: grid; gap: var(--space-4); grid-template-columns: 1fr; margin-block: var(--space-6); }
.media-strip figure {
    margin: 0;
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-md);
    background: var(--color-paper-alt);
}
.media-strip img { width: 100%; height: 100%; aspect-ratio: 4 / 3; object-fit: cover; }

/* Single wide photograph used to break up a long text page. */
.media-figure {
    margin: var(--space-6) 0 0;
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-md);
    background: var(--color-paper-alt);
}
.media-figure img { width: 100%; aspect-ratio: 21 / 9; object-fit: cover; }
.media-figure figcaption {
    padding: var(--space-3) var(--space-5);
    font-size: 0.83rem;
    color: var(--color-text-muted);
    background: var(--color-white);
    border-top: 1px solid var(--color-line);
}

/* Generic version of .service-card__photo, so audience/portfolio cards can
   carry a photo without pretending to be service cards. */
.card--photo { overflow: hidden; }
.card__photo {
    aspect-ratio: 16 / 10;
    margin: calc(var(--space-6) * -1) calc(var(--space-6) * -1) var(--space-5);
    background: var(--color-paper-alt);
    overflow: hidden;
}
.card__photo img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---------------------------------------------------------------------------
   9. Testimonials
   ------------------------------------------------------------------------- */
/* Featured (real, consented) testimonial: the client's own photograph on the
   left, quote and credit on the right. The photograph is a real person
   published with consent — never substitute stock imagery here while the
   credit line reads as a real client. Quotes with no photograph simply omit
   the media column (see the :has() rule below) and run full width. */
.testimonial-feature {
    display: grid;
    gap: var(--space-5);
    background: var(--color-white);
    border: 1px solid var(--color-line);
    border-left: 4px solid var(--color-accent);
    border-radius: var(--radius-lg);
    padding: var(--space-6);
    margin-bottom: var(--space-7);
}
/* Portrait (4:5) rather than square, which uses more of the supplied photo and
   fills the height beside a long quote. Display width is still capped below
   the source's native 460px — a client phone snapshot scaled past 1:1 would
   look soft next to the professionally shot imagery elsewhere on the site. */
.testimonial-feature__media { margin: 0; width: 180px; }
.testimonial-feature__media img {
    width: 100%;
    aspect-ratio: 4 / 5;
    object-fit: cover;
    border-radius: var(--radius-md);
    border: 2px solid var(--color-accent-soft);
}
.testimonial-feature__body { margin: 0; }
.testimonial-feature__quote {
    position: relative;
    font-size: 1.05rem;
    line-height: 1.75;
    font-style: italic;
    font-weight: 400;
    color: var(--color-ink);
    max-width: 68ch;
    margin: 0 0 var(--space-5);
    padding-top: var(--space-5);
}
.testimonial-feature__quote::before {
    content: '\201C';
    position: absolute;
    left: -0.02em; top: -0.15em;
    font-size: 3.4rem;
    line-height: 1;
    font-style: normal;
    color: var(--color-accent);
    opacity: 0.5;
}
.testimonial-feature__author {
    font-style: normal;
    padding-top: var(--space-4);
    border-top: 1px solid var(--color-line);
}
.testimonial-feature__credit {
    font-weight: 600;
    font-size: 0.9rem;
    color: var(--color-text-muted);
}

/* Quote cards sit three to a row and the quotes are of unequal length. .card
   already makes them full-height column flexboxes, so the credit line below
   only needs margin-top:auto to sit flush with the bottom of every card. */
.testimonial-card {
    background: var(--color-white);
    border-radius: var(--radius-lg);
    padding: var(--space-6);
    box-shadow: none;
    border: 1px solid var(--color-line);
    position: relative;
}
/* Quote/pull-quote copy stays in Poppins: only Poppins ships an italic in the
   loaded font set, so setting these in the heading face would give a
   browser-synthesised oblique instead of a real italic. */
.testimonial-card__quote {
    font-family: var(--font-body);
    font-size: 1.02rem;
    line-height: 1.65;
    color: var(--color-ink);
    font-weight: 400;
    font-style: italic;
    margin: 0;
}
.testimonial-card__quote p { margin: 0 0 var(--space-4); }
.testimonial-card__quote p:first-child {
    font-weight: 500;
    font-size: 1.08rem;
}
.testimonial-card__quote p:last-child { margin-bottom: 0; }

/* Generic small muted note — used outside form fields too (e.g. service
   session-format asides). Keep in sync with .form-field .hint above. */
.hint { font-size: 0.86rem; color: var(--color-text-muted); }

/* Editorial pull-quote — oversized decorative quotation mark, set in the
   heading serif so it reads as a considered accent, not stray punctuation. */
.pull-quote {
    position: relative;
    font-family: var(--font-body);
    font-size: 1.22rem;
    font-weight: 500;
    line-height: 1.55;
    font-style: italic;
    color: var(--color-ink);
    padding-left: var(--space-6);
    margin-bottom: var(--space-5);
}
.pull-quote::before {
    content: '\201C';
    position: absolute;
    left: -0.1em;
    top: 0.15em;
    font-size: 2.6rem;
    line-height: 1;
    font-style: normal;
    color: var(--color-accent);
    opacity: 0.55;
}
.testimonial-card__author {
    margin-top: auto;
    padding-top: var(--space-4);
    border-top: 1px solid var(--color-line);
    font-style: normal;
    display: flex;
    align-items: center;
    gap: var(--space-3);
}
/* Only some clients supply a photograph, so the avatar is optional and the
   credit block sits in its own wrapper — the row collapses cleanly to just
   the name and role when there is no image. */
.testimonial-card__avatar {
    width: 52px; height: 52px;
    flex-shrink: 0;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid var(--color-accent-soft);
}
.testimonial-card__credit { min-width: 0; }
.testimonial-card__name {
    display: block;
    font-weight: 700;
    color: var(--color-ink);
    font-size: 0.98rem;
}
.testimonial-card__role {
    display: block;
    margin-top: 0.15rem;
    font-weight: 500;
    color: var(--color-text-muted);
    font-size: 0.84rem;
}

/* ---------------------------------------------------------------------------
   10. Accordion (FAQ)
   ------------------------------------------------------------------------- */
.accordion { border-top: 1px solid var(--color-line); }
.accordion-item { border-bottom: 1px solid var(--color-line); }
.accordion-trigger {
    width: 100%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-4);
    background: none;
    border: none;
    text-align: left;
    padding: var(--space-5) var(--space-2);
    font-family: var(--font-heading);
    font-size: 1.08rem;
    font-weight: 600;
    color: var(--color-ink);
    cursor: pointer;
}
.accordion-trigger__icon {
    flex-shrink: 0;
    width: 26px; height: 26px;
    border-radius: 50%;
    border: 1.5px solid var(--color-accent);
    display: grid; place-items: center;
    position: relative;
    transition: transform var(--transition-base);
}
.accordion-trigger__icon::before, .accordion-trigger__icon::after {
    content: '';
    position: absolute;
    background: var(--color-accent);
}
.accordion-trigger__icon::before { width: 11px; height: 1.5px; }
.accordion-trigger__icon::after { width: 1.5px; height: 11px; transition: transform var(--transition-base); }
.accordion-trigger[aria-expanded="true"] .accordion-trigger__icon::after { transform: scaleY(0); }

.accordion-panel {
    max-height: 0;
    overflow: hidden;
    transition: max-height var(--transition-slow);
}
.accordion-panel__inner { padding: 0 var(--space-2) var(--space-5); color: var(--color-text-muted); }

/* ---------------------------------------------------------------------------
   11. CTA bands
   ------------------------------------------------------------------------- */
.cta-band { background: var(--color-ink); color: var(--color-paper); }
/* Institutional variant — the darkened brand gold, so the two CTA bands read
   as one family (teal and gold, the two logo colours) rather than introducing
   a third hue. The deep gold rather than the bright one because this band
   carries body copy: cream on #7e611f is 5.4:1, cream on #be9042 is 3:1. */
.cta-band--teal { background: var(--color-accent-deep); }
.cta-band__inner {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
    align-items: flex-start;
    padding-block: var(--space-7);
}
.cta-band h2 { color: var(--color-paper); margin-bottom: var(--space-2); }
.cta-band p { color: rgba(250, 246, 239, 0.78); margin: 0; }

.cta-final {
    position: relative;
    overflow: hidden;
    isolation: isolate;
    background: linear-gradient(135deg, var(--color-ink) 0%, var(--color-ink-deep) 100%);
    color: var(--color-paper);
}
/* Photograph sits behind the gradient at low opacity — enough to stop the
   closing band reading as a flat colour block, not enough to compete with
   the headline. */
.cta-final__img {
    position: absolute;
    inset: 0;
    width: 100%; height: 100%;
    object-fit: cover;
    opacity: 0.2;
    z-index: -1;
}
.cta-final__inner { position: relative; padding-block: var(--space-9); text-align: center; max-width: 740px; margin-inline: auto; }
.cta-final h2 { color: var(--color-paper); }
.cta-final p { color: rgba(250, 246, 239, 0.78); margin-inline: auto var(--space-6); }
.cta-final__actions { display: flex; flex-wrap: wrap; gap: var(--space-4); justify-content: center; align-items: center; }
.cta-final__email { color: var(--color-accent-soft); font-weight: 600; }

/* ---------------------------------------------------------------------------
   12. Forms
   ------------------------------------------------------------------------- */
.form-panel {
    background: var(--color-white);
    border: 1px solid var(--color-line);
    border-radius: var(--radius-lg);
    padding: var(--space-6);
    box-shadow: none;
}
.form-grid { display: grid; gap: var(--space-5); grid-template-columns: 1fr; }
.form-field { display: flex; flex-direction: column; gap: var(--space-2); }
.form-field label { font-weight: 600; font-size: 0.9rem; color: var(--color-ink); }
.form-field .hint { font-size: 0.8rem; color: var(--color-text-muted); font-weight: 400; }
.form-field input[type="text"],
.form-field input[type="email"],
.form-field input[type="tel"],
.form-field input[type="date"],
.form-field input[type="time"],
.form-field input[type="number"],
.form-field select,
.form-field textarea {
    font-family: var(--font-body);
    font-size: 1rem;
    padding: 0.7rem 0.9rem;
    border: 1.5px solid var(--color-line);
    border-radius: var(--radius-sm);
    background: var(--color-paper);
    color: var(--color-text);
    width: 100%;
}
.form-field input:focus,
.form-field select:focus,
.form-field textarea:focus { border-color: var(--color-accent); }
.form-field textarea { resize: vertical; min-height: 120px; }
.form-field input:invalid:not(:placeholder-shown) { border-color: var(--color-error); }
.form-field--checkbox { flex-direction: row; align-items: flex-start; gap: var(--space-3); }
/* 24px is the WCAG 2.2 (2.5.8, AA) minimum target; at the previous 18px the
   consent box was the hardest thing on the booking form to hit on a phone. */
.form-field--checkbox input { margin-top: 0.15rem; width: 24px; height: 24px; flex-shrink: 0; }
.form-field--checkbox label { font-weight: 400; }

.form-error { color: var(--color-error); font-size: 0.85rem; font-weight: 600; }
.form-status { padding: var(--space-4) var(--space-5); border-radius: var(--radius-md); margin-bottom: var(--space-6); font-weight: 600; }
.form-status--error { background: #fbeaea; color: var(--color-error); border: 1px solid #e6b3af; }
.form-status--success { background: var(--color-sage-soft); color: var(--color-sage-deep); border: 1px solid var(--color-sage); }

.hp-field { position: absolute; left: -9999px; top: -9999px; opacity: 0; height: 0; overflow: hidden; }

.form-toggle { display: flex; gap: var(--space-3); margin-bottom: var(--space-7); flex-wrap: wrap; }
.form-toggle a {
    text-decoration: none;
    padding: var(--space-3) var(--space-5);
    border-radius: var(--radius-sm);
    border: 1.5px solid var(--color-ink);
    color: var(--color-ink);
    font-weight: 600;
}
.form-toggle a:hover { background: var(--color-paper-alt); color: var(--color-ink); border-color: var(--color-accent); }
.form-toggle a.is-active { background: var(--color-ink); color: var(--color-paper); }
.form-toggle a.is-active:hover { background: var(--color-ink-deep); color: var(--color-paper); border-color: var(--color-accent); }

/* ---------------------------------------------------------------------------
   13. Footer
   ------------------------------------------------------------------------- */
.site-footer { background: var(--color-ink-deep); color: rgba(250, 246, 239, 0.7); padding-top: var(--space-8); }
.site-footer a { color: rgba(250, 246, 239, 0.7); text-decoration: none; }
.site-footer a:hover { color: var(--color-accent-soft); }
.site-footer__grid { display: grid; gap: var(--space-7); grid-template-columns: 1fr; padding-bottom: var(--space-7); }
.footer-col h3 { color: var(--color-paper); font-size: 0.86rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: var(--space-4); }
/* Footer copy sits a step below body size. At the inherited 1rem/1.7 the three
   link columns read as loudly as the page content above them, and the longer
   service names and the address each wrapped to two and three lines. Dropping
   the size and tightening the leading pulls the block back to secondary
   weight; the gap between items carries the separation instead. */
.footer-col ul { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: var(--space-3); font-size: 0.86rem; line-height: 1.5; }
.footer-col--about p { font-size: 0.86rem; line-height: 1.6; }
/* Footer sits on ink, so the shared logo styles need light-on-dark values. */
.site-logo--footer { margin-bottom: var(--space-5); }
.site-logo--footer .site-logo__name { color: var(--color-paper); }
.site-logo--footer .site-logo__sub { color: rgba(250, 246, 239, 0.6); }
.site-logo--footer .site-logo__tagline { color: var(--color-accent-soft); }
.footer-social { display: flex; gap: var(--space-3); margin: var(--space-4) 0; }
.social-icon {
    width: 34px; height: 34px;
    display: grid; place-items: center;
    border-radius: 50%;
    border: 1px solid rgba(250, 246, 239, 0.18);
    font-size: 0.76rem;
    font-weight: 700;
    text-transform: uppercase;
}
.social-icon--placeholder { opacity: 0.35; }
.footer-newsletter__row { display: flex; gap: var(--space-2); margin-top: var(--space-2); }
.footer-newsletter input { flex-grow: 1; padding: 0.6rem 0.8rem; border-radius: var(--radius-sm); border: 1px solid rgba(250, 246, 239, 0.18); background: rgba(250, 246, 239, 0.04); color: rgba(250, 246, 239, 0.55); }
.footer-newsletter__note { font-size: 0.76rem; color: rgba(250, 246, 239, 0.4); margin-top: var(--space-2); }

.site-footer__bottom { border-top: 1px solid rgba(250, 246, 239, 0.1); padding-block: var(--space-5); }
.site-footer__bottom-inner { display: flex; flex-direction: column; gap: var(--space-3); align-items: center; text-align: center; font-size: 0.83rem; }
.site-footer__bottom p { margin: 0; }
.footer-legal { list-style: none; display: flex; gap: var(--space-5); padding: 0; margin: 0; }

/* ---------------------------------------------------------------------------
   14. Breadcrumbs
   ------------------------------------------------------------------------- */
.breadcrumbs { padding-block: var(--space-4); font-size: 0.84rem; }
.breadcrumbs ol { list-style: none; display: flex; flex-wrap: wrap; padding: 0; margin: 0; gap: var(--space-2); color: var(--color-text-muted); }
.breadcrumbs li::after { content: '/'; margin-left: var(--space-2); color: var(--color-line); }
.breadcrumbs li:last-child::after { content: ''; }
/* .breadcrumbs a and the generic a:hover have equal specificity, and this rule
   comes later — so without an explicit hover the crumbs give no feedback at all. */
.breadcrumbs a { color: var(--color-text-muted); }
.breadcrumbs a:hover { color: var(--color-ink); }

/* ---------------------------------------------------------------------------
   15. Utility page layout (legal / 404 / thank-you)
   ------------------------------------------------------------------------- */
.prose { max-width: 74ch; }
.prose h2 { margin-top: var(--space-7); }
.prose ul, .prose ol { max-width: 68ch; }
.legal-updated { color: var(--color-text-muted); font-size: 0.9rem; }
.disclaimer-box {
    background: var(--color-sage-soft);
    border-left: 3px solid var(--color-sage);
    padding: var(--space-5);
    border-radius: var(--radius-sm);
    margin-block: var(--space-6);
}

.error-page { text-align: center; padding-block: var(--space-9); }
.error-page__code { font-family: var(--font-heading); font-weight: 500; font-size: clamp(4rem, 12vw, 8rem); color: var(--color-accent); margin: 0; line-height: 1; }

.thank-you { text-align: center; padding-block: var(--space-9); max-width: 620px; margin-inline: auto; }
.thank-you__icon {
    width: 84px; height: 84px;
    margin: 0 auto var(--space-6);
    border-radius: 50%;
    border: 1.5px solid var(--color-sage);
    color: var(--color-sage-deep);
    display: grid; place-items: center;
    font-size: 2.2rem;
}

/* ---------------------------------------------------------------------------
   15b. Gallery (/gallery)
   Real photographs of Laira's own work, so the treatment is deliberately
   plainer than the stock imagery elsewhere: a quiet card, a printed caption,
   and no gradient or duotone laid over a real room.
   ------------------------------------------------------------------------- */
.gallery-filter {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-2);
    margin-block: var(--space-6) var(--space-7);
}
.gallery-filter__btn {
    font-family: var(--font-body);
    font-size: 0.86rem;
    line-height: 1.2;
    padding: 0.6rem 1.1rem;
    border: 1px solid var(--color-line);
    border-radius: 999px;
    background: var(--color-white);
    color: var(--color-text-muted);
    cursor: pointer;
    transition: color var(--transition-fast), border-color var(--transition-fast), background var(--transition-fast);
}
.gallery-filter__btn:hover { color: var(--color-ink); border-color: var(--color-accent); }
.gallery-filter__btn.is-active {
    background: var(--color-ink);
    border-color: var(--color-ink);
    color: var(--color-paper);
}
.gallery-filter__count {
    display: inline-block;
    margin-left: 0.35rem;
    font-size: 0.74rem;
    opacity: 0.7;
}
.gallery-filter__btn.is-active .gallery-filter__count { color: var(--color-accent-soft); opacity: 1; }

.gallery-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-5);
}
.gallery-item {
    margin: 0;
    background: var(--color-white);
    border: 1px solid var(--color-line);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
    transition: box-shadow var(--transition-base), transform var(--transition-base);
}
.gallery-item:hover { box-shadow: var(--shadow-md); transform: translateY(-3px); }
.gallery-item.is-filtered-out { display: none; }

.gallery-item__link {
    position: relative;
    display: block;
    aspect-ratio: 4 / 3;
    background: var(--color-paper-alt);
    overflow: hidden;
}
/* object-fit crops every tile to one shape. The sources are a mix of squares,
   portraits and landscapes straight off a phone, and a ragged grid of
   different heights reads as broken rather than as editorial. The lightbox
   shows each photograph uncropped. */
.gallery-item__link img {
    width: 100%; height: 100%;
    object-fit: cover;
    /* Biased above centre: several sources are phone portraits of someone
       standing, and a dead-centre crop to 4:3 takes the head off. */
    object-position: center 35%;
    display: block;
    transition: transform var(--transition-slow);
}
.gallery-item__link:hover img,
.gallery-item__link:focus-visible img { transform: scale(1.04); }

/* Magnifier hint, drawn in CSS so no icon font or extra request is needed. */
.gallery-item__zoom {
    position: absolute;
    right: var(--space-3); bottom: var(--space-3);
    width: 34px; height: 34px;
    border-radius: 50%;
    background: rgba(11, 46, 48, 0.78);
    opacity: 0;
    transition: opacity var(--transition-base);
}
.gallery-item__zoom::before,
.gallery-item__zoom::after {
    content: '';
    position: absolute;
    background: var(--color-paper);
}
.gallery-item__zoom::before {
    left: 9px; top: 16px;
    width: 16px; height: 1.5px;
}
.gallery-item__zoom::after {
    left: 16.25px; top: 9px;
    width: 1.5px; height: 16px;
}
.gallery-item__link:hover .gallery-item__zoom,
.gallery-item__link:focus-visible .gallery-item__zoom { opacity: 1; }

.gallery-item__caption {
    padding: var(--space-4) var(--space-5) var(--space-5);
    font-size: 0.86rem;
    line-height: 1.6;
    color: var(--color-text-muted);
}

/* --- Lightbox ------------------------------------------------------------ */
/* `hidden` is what closes it, so every rule here assumes it is open. */
.lightbox {
    position: fixed;
    inset: 0;
    z-index: 200;
    display: grid;
    place-items: center;
    padding: var(--space-5);
    background: rgba(11, 46, 48, 0.94);
}
.lightbox[hidden] { display: none; }
body.lightbox-open { overflow: hidden; }

.lightbox__figure {
    margin: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-4);
    max-width: min(1100px, 100%);
}
.lightbox__img {
    max-width: 100%;
    /* Room for the caption below and the close button above on short
       viewports; without the cap a 4:5 photograph pushes both off screen. */
    max-height: 74vh;
    width: auto; height: auto;
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    background: var(--color-ink-deep);
}
.lightbox__caption {
    text-align: center;
    color: rgba(250, 246, 239, 0.86);
    font-size: 0.9rem;
    line-height: 1.6;
    max-width: 62ch;
}
.lightbox__count {
    display: block;
    font-family: var(--font-heading);
    font-size: 0.74rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--color-accent-soft);
    margin-bottom: var(--space-2);
}

.lightbox__close,
.lightbox__nav {
    position: absolute;
    display: grid;
    place-items: center;
    border: 1px solid rgba(242, 228, 198, 0.35);
    border-radius: 50%;
    background: rgba(11, 46, 48, 0.6);
    color: var(--color-paper);
    cursor: pointer;
    line-height: 1;
    transition: background var(--transition-fast), border-color var(--transition-fast);
}
.lightbox__close:hover,
.lightbox__nav:hover { background: var(--color-ink); border-color: var(--color-accent); }
.lightbox__close {
    top: var(--space-4); right: var(--space-4);
    width: 44px; height: 44px;
    font-size: 1.7rem;
}
.lightbox__nav {
    top: 50%;
    transform: translateY(-50%);
    width: 46px; height: 46px;
    font-size: 2rem;
    padding-bottom: 0.25rem;
}
.lightbox__nav--prev { left: var(--space-3); }
.lightbox__nav--next { right: var(--space-3); }
.lightbox__nav[hidden] { display: none; }

.lightbox__close:focus-visible,
.lightbox__nav:focus-visible {
    outline: 2px solid var(--color-accent-soft);
    outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
   16. Utility classes
   Small, single-purpose helpers used instead of inline styles so pages can
   stay free of style="" attributes (keeps a strict CSP viable).
   ------------------------------------------------------------------------- */
.u-pt-sm { padding-top: var(--space-5); }
.u-mx-auto { margin-inline: auto; }
.u-mt-0 { margin-top: 0; }
.u-mt-md { margin-top: var(--space-5); }
.u-mt-lg { margin-top: var(--space-6); }
.u-mt-xl { margin-top: var(--space-7); }
.u-mb-0 { margin-bottom: 0; }
.u-mb-lg { margin-bottom: var(--space-6); }
.u-mb-xl { margin-bottom: var(--space-7); }
.u-mb-xxl { margin-bottom: var(--space-8); }
.u-m-0 { margin: 0; }
.u-items-center { align-items: center; }
.u-items-start { align-items: start; }
.u-center { text-align: center; }
.u-justify-center { justify-content: center; }
.u-order-1 { order: 1; }
.u-order-2 { order: 2; }
.u-max-52 { max-width: 52ch; }
.u-max-74 { max-width: 74ch; }
.u-max-640 { max-width: 640px; }
.u-max-800 { max-width: 800px; }
.u-max-840 { max-width: 840px; }
.u-role-lg { font-size: 1.05rem; }
.u-inherit-size { font-size: inherit; }
.u-list-plain { list-style: none; padding: 0; display: flex; flex-direction: column; gap: var(--space-3); }
