/* ==========================================================================
   Suresh Poduval — Official Site
   Main stylesheet (modern, mobile-first)
   ========================================================================== */

/* ----- Design tokens ----- */
:root {
    /* Colors */
    --bg:            #0a0a0a;
    --bg-elev:       #141414;
    --bg-card:       #1a1a1a;
    --bg-surface:    #1e1e1e;
    --bg-light:      #fafafa;
    --bg-section:    #f7f5f0;

    --text:          #e8e6e0;
    --text-muted:    #9b9890;
    /* was #6b6862 — 3.57:1 on --bg, under AA for the footer's copyright and
       closing line. #8a877f is 5.52:1 and reads as the same quiet grey. */
    --text-dim:      #8a877f;
    --text-dark:     #1a1a1a;
    /* was #6b7280 — 4.44:1 on --bg-section, i.e. just under AA on the cream
       panels, and this token carries most of the body copy on the site
       (.muted, .card-text, .two-col-text p, every *-prose p). #5f6672 is
       5.31:1 on cream / 5.54:1 on white, same slate hue. */
    --text-dark-mut: #5f6672;

    --accent:        #c9a961;
    --accent-hover:  #d4b673;
    --accent-deep:   #a88845;
    --accent-light:  #f0d9a8;
    --accent-pale:   #f5e8cc;
    /* Text-safe gold, for gold TYPE on the LIGHT surfaces only.
       --accent itself is 8.8:1 on the dark background it was designed for but
       only 2.07:1 on --bg-section, so kickers, card meta and the fact chips
       set in it were effectively unreadable on every cream section.
       Chosen to clear 4.5:1 on the darkest light surface it lands on — the
       rgba(0,0,0,.05) fact chips over cream (4.89:1) — which means it also
       clears every lighter one: cream 5.44, --bg-light 5.68, white 5.93.
       Keep using --accent for gold on dark, and for borders/rules/icons,
       where the contrast minimum does not apply. */
    --accent-ink:    #7d5f2a;

    /* Modern champagne-gold gradient (wordmark + premium accents) */
    --gradient-gold: linear-gradient(135deg, #f5e3b8 0%, #d8b97a 28%, #c9a961 55%, #a88845 100%);
    --gradient-gold-soft: linear-gradient(135deg, #f5e8cc 0%, #d4b896 50%, #b8945a 100%);

    --border:        rgba(255, 255, 255, 0.08);
    --border-strong: rgba(255, 255, 255, 0.16);
    --border-light:  rgba(0, 0, 0, 0.08);

    --shadow-sm:     0 2px 8px rgba(0, 0, 0, 0.15);
    --shadow-md:     0 8px 24px rgba(0, 0, 0, 0.25);
    --shadow-lg:     0 20px 60px rgba(0, 0, 0, 0.4);

    /* Typography */
    --font-serif:    'Playfair Display', 'Georgia', serif;
    --font-display:  'Cormorant Garamond', 'Playfair Display', 'Georgia', serif;
    --font-sans:     'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

    --fs-xs:   0.75rem;
    --fs-sm:   0.875rem;
    --fs-base: 1rem;
    --fs-md:   1.125rem;
    --fs-lg:   1.25rem;
    --fs-xl:   1.5rem;
    --fs-2xl:  2rem;
    --fs-3xl:  2.5rem;
    --fs-4xl:  3.5rem;
    --fs-5xl:  4.5rem;

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

    /* Layout */
    --container: 1240px;
    --container-narrow: 880px;
    --radius-sm: 4px;
    --radius:    8px;
    --radius-lg: 16px;
    --radius-xl: 24px;

    /* Motion */
    --ease:    cubic-bezier(0.4, 0, 0.2, 1);
    --ease-in: cubic-bezier(0.4, 0, 1, 1);
    --ease-out:cubic-bezier(0, 0, 0.2, 1);
    --t-fast:  150ms;
    --t-med:   300ms;
    --t-slow:  600ms;

    /* Header (main nav row + utility top bar above it) */
    --header-h: 120px;
}

/* ----- Reset ----- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }

html {
    scroll-behavior: smooth;
    /* Clears the sticky header for every in-page anchor — the browser's own
       fragment navigation, scrollIntoView(), and focus() all honour this, so
       targets like #enquiry and #subscribe no longer land underneath the bar.
       responsive.css only redefines --header-h, so this follows it. */
    scroll-padding-top: calc(var(--header-h) + var(--sp-4));
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

body {
    font-family: var(--font-sans);
    font-size: var(--fs-base);
    line-height: 1.6;
    color: var(--text-dark);
    background: var(--bg-light);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow-x: hidden;
}

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

button, input, textarea, select {
    font: inherit;
    color: inherit;
}

button { background: none; border: none; cursor: pointer; }

a {
    color: inherit;
    text-decoration: none;
    transition: color var(--t-fast) var(--ease);
}

ul, ol { list-style: none; }

::selection {
    background: var(--accent);
    color: var(--bg);
}

/* ----- Typography ----- */
h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-serif);
    font-weight: 500;
    line-height: 1.2;
    letter-spacing: -0.02em;
}

h1 { font-size: var(--fs-4xl); }
h2 { font-size: var(--fs-3xl); }
h3 { font-size: var(--fs-2xl); }
h4 { font-size: var(--fs-xl); }
h5 { font-size: var(--fs-lg); }
h6 { font-size: var(--fs-base); }

p { line-height: 1.7; }

.muted    { color: var(--text-dark-mut); }
.eyebrow  {
    font-family: var(--font-sans);
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    /* Light surfaces are the default (body background is --bg-light), so the
       text-safe gold is the default here and the brighter --accent is restored
       below wherever the surface is dark. At 12px/600 this is small text, so
       the 4.5:1 minimum applies in full. */
    color: var(--accent-ink);
}
/* Dark surfaces: back to the full-brightness gold (8.8:1 on --bg). */
.section-dark .eyebrow,
.hero .eyebrow,
.hero-copy .eyebrow,
.hero-slider .eyebrow,
.cta-band .eyebrow,
.site-footer .eyebrow { color: var(--accent); }

/* Several headings are long transliterated Malayalam titles set as one
   unbreakable word; at 320px they ran past their box. Let them break rather
   than overflow — only affects words that genuinely do not fit. */
h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; }

/* ----- Utilities ----- */
.container {
    width: 100%;
    max-width: var(--container);
    margin: 0 auto;
    padding: 0 var(--sp-5);
}

.container-narrow {
    max-width: var(--container-narrow);
    margin: 0 auto;
    padding: 0 var(--sp-5);
}

.section {
    padding: var(--sp-10) 0;
}

.section-sm {
    padding: var(--sp-8) 0;
}

.section-dark {
    background: var(--bg);
    color: var(--text);
}

.section-dark .muted { color: var(--text-muted); }

.section-light {
    background: var(--bg-section);
}

/* Plain white band — use to separate two sections that would otherwise both
   sit on the cream .section-light and read as one continuous block. */
.section-white {
    background: #fff;
}

.section-title {
    font-size: var(--fs-3xl);
    margin-bottom: var(--sp-4);
}

.section-header {
    text-align: center;
    max-width: 700px;
    margin: 0 auto var(--sp-8);
}

.section-header .eyebrow { margin-bottom: var(--sp-3); display: inline-block; }
.section-header p { color: var(--text-dark-mut); font-size: var(--fs-md); margin-top: var(--sp-3); }

.section-dark .section-header p { color: var(--text-muted); }

.visually-hidden {
    position: absolute !important;
    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;
    top: -100px; left: 0;
    background: var(--accent);
    color: var(--bg);
    padding: var(--sp-3) var(--sp-5);
    z-index: 1000;
    font-weight: 600;
}
.skip-link:focus { top: 0; }

/* Programmatic focus targets — #main-content (skip-link destination) and the
   #enquiry panel the contact handler redirects to. They are only focusable so
   focus can be MOVED there; without this the browser draws a focus ring around
   the entire page or the whole form panel, which reads as a rendering fault. */
[tabindex="-1"]:focus { outline: none; }

/* ----- Buttons ----- */
.btn {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    padding: var(--sp-3) var(--sp-6);
    font-size: var(--fs-sm);
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    border-radius: var(--radius-sm);
    border: 1px solid transparent;
    cursor: pointer;
    transition: all var(--t-med) var(--ease);
    white-space: nowrap;
}

.btn-primary {
    background: var(--accent);
    color: var(--bg);
}
.btn-primary:hover {
    background: var(--accent-hover);
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
}

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

.btn-ghost {
    color: currentColor;
    background: transparent;
    border-color: var(--border-strong);
}
.btn-ghost:hover {
    border-color: var(--accent);
    color: var(--accent);
}

/* Partner to .btn-primary for a pair of buttons over photography. Same shape,
   size and lift as the primary — only the colour differs, so the two read as
   one set with a clear first and second choice. Solid rather than transparent
   like .btn-ghost, because over a bright patch of a hero photo a see-through
   button loses its edges and its label. */
.btn-contrast {
    background: rgba(10, 10, 10, 0.72);
    color: var(--accent-light);
    border-color: var(--accent);
    -webkit-backdrop-filter: blur(6px);
            backdrop-filter: blur(6px);
}
.btn-contrast:hover {
    background: var(--accent-deep);
    border-color: var(--accent-deep);
    color: var(--bg);
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
}

.btn-sm { padding: var(--sp-2) var(--sp-5); font-size: var(--fs-xs); }
.btn-lg { padding: var(--sp-4) var(--sp-7); font-size: var(--fs-base); }

/* ----- Header / Navigation ----- */
.site-header {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 100;
    padding: var(--sp-4) 0;
    background: rgba(10, 10, 10, 0.0);
    backdrop-filter: blur(0);
    transition: background var(--t-med) var(--ease),
                backdrop-filter var(--t-med) var(--ease),
                padding var(--t-med) var(--ease);
}

.site-header.scrolled,
body:not(.page-home) .site-header {
    background: rgba(10, 10, 10, 0.92);
    backdrop-filter: blur(20px);
    padding: var(--sp-3) 0;
    border-bottom: 1px solid var(--border);
}

.header-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-5);
}

/* ----- Brand / Typography Wordmark ----- */
.brand {
    display: inline-flex;
    align-items: center;
    color: var(--text);
    transition: opacity var(--t-fast) var(--ease);
    text-decoration: none;
}
.brand:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 6px;
    border-radius: var(--radius-sm);
}

/* --- Wordmark animation tokens ---
   The whole logo animation is expressed as custom properties so the
   touch/small-screen block in responsive.css can swap it for a different one by
   redefining values rather than by re-declaring (and having to unset) each
   animated property. They live on :root, not on .wordmark: a declaration on the
   element itself would beat anything :root said, and the mobile pass could
   never land. See "Brand wordmark — touch animation" in responsive.css. */
:root {
    /* Champagne gold, even-tempered: the tile that drifts through the letters.
       Its end stops match and it is exactly twice the width of the text, so
       scrolling it by one full tile (wm-flow) loops seamlessly. */
    --wm-gradient: linear-gradient(100deg,
        #a88845 0%, #f5e3b8 25%, #c9a961 50%, #f5e3b8 75%, #a88845 100%);
    --wm-gradient-size: 200% auto;
    --wm-rest-pos: 0% 50%;
    --wm-anim-name: wm-flow 5s linear infinite, wm-glow 4.5s ease-in-out infinite;
    --wm-anim-tag:  wm-flow 7s linear infinite;
    --wm-anim-rule: wm-line-glow 4.5s ease-in-out infinite;
    --wm-sheen: block;   /* the sweeping highlight band; 'none' turns it off */
    --wm-float: none;    /* drawer-brand drift; only the touch pass sets one */
}

.wordmark {
    display: inline-flex;
    flex-direction: column;
    line-height: 1;
    gap: 8px;
    position: relative;
}

/* Specular sweep: a soft band of light that crosses the mark every few seconds
   and then rests, in the same gold as .about-portrait-sheen. It rides the
   element's own background rather than a translated box, so it cannot spill
   past the wordmark into the header bar, and screen blending means it brightens
   the letters it passes over instead of veiling them. */
.wordmark::after {
    content: '';
    position: absolute;
    /* Bleeds sideways so the band enters and leaves well clear of the letters.
       Kept to 20px: the footer wordmark sits one container gutter (24px) from
       the viewport edge, and unlike the fixed header it can widen the document
       if it reaches past it. */
    inset: -8px -20px;
    display: var(--wm-sheen);
    pointer-events: none;
    /* The ramp is transparent for its outer 30% at each end. That margin is not
       decoration: the band is tilted 15deg off vertical, so a stop that only
       reaches zero at 0%/100% still meets the tile's straight left and right
       edges part-way up the ramp — which drew the band as a hard-edged grey
       rectangle sliding over the logo instead of a streak of light. */
    background-image: linear-gradient(105deg,
        rgba(245, 227, 184, 0)    30%,
        rgba(245, 227, 184, 0.28) 44%,
        rgba(255, 255, 255, 0.50) 50%,
        rgba(245, 227, 184, 0.28) 56%,
        rgba(245, 227, 184, 0)    70%);
    background-size: 60% 100%;
    background-repeat: no-repeat;
    background-position: -160% 0;
    /* A background is clipped to its box, so the band would otherwise appear and
       disappear on a straight vertical cut as it crosses the two ends. Fading
       the element's own edges means there is no cut to see at any position —
       the timing below then only has to park the band, not hide the seam. */
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 14%, #000 86%, transparent 100%);
            mask-image: linear-gradient(90deg, transparent 0, #000 14%, #000 86%, transparent 100%);
    mix-blend-mode: screen;
    /* linear, not eased: an ease-out spends the back half of the pass parked at
       the right-hand edge, which is exactly where the clipped edge shows */
    animation: wm-sheen 7s linear infinite;
}

/* --- Primary wordmark: Cormorant Garamond, gradient-gold --- */
.wordmark-name {
    font-family: var(--font-display);
    font-size: 1.75rem;
    font-weight: 500;
    letter-spacing: 0.01em;
    line-height: 1;
    /* Flowing "liquid gold": the gradient above, clipped to the glyphs and kept
       moving — plus a soft breathing glow. Both come from the tokens, so the
       touch pass can substitute its own without touching this rule. */
    background-image: var(--wm-gradient);
    background-size: var(--wm-gradient-size);
    background-position: var(--wm-rest-pos);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
    white-space: nowrap;
    animation: var(--wm-anim-name);
}

/* --- Tagline: tiny tracked sans, preceded by a hairline --- */
.wordmark-tag {
    font-family: var(--font-sans);
    font-size: 0.62rem;
    font-weight: 500;
    letter-spacing: 0.32em;
    text-transform: uppercase;
    padding-left: 22px;
    position: relative;
    white-space: nowrap;
    opacity: 0.92;
    /* same liquid-gold flow as the name — gentler and slower */
    background-image: var(--wm-gradient);
    background-size: var(--wm-gradient-size);
    background-position: var(--wm-rest-pos);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
    animation: var(--wm-anim-tag);
}
.wordmark-tag::before {
    content: '';
    position: absolute;
    left: 0; top: 50%;
    width: 14px;
    height: 1px;
    background: var(--accent);
    transform: translateY(-50%);
    opacity: 0.7;
    transition: width var(--t-med) var(--ease),
                opacity var(--t-med) var(--ease);
    transform-origin: left center;
    animation: var(--wm-anim-rule);
}

/* --- Hover: the tagline hairline grows --- */
.brand:hover .wordmark-tag::before {
    width: 22px;
}

/* --- Variant: footer (slightly larger, generous breathing room) --- */
.wordmark--footer .wordmark-name { font-size: 2.1rem; }
.wordmark--footer .wordmark-tag  { font-size: 0.66rem; letter-spacing: 0.34em; }

/* --- Variant: compact (mobile) --- */
.wordmark--compact .wordmark-name { font-size: 1.35rem; }
.wordmark--compact .wordmark-tag  { display: none; }

/* Brand block inside the mobile slide-in drawer — hidden on desktop (the header
   wordmark already carries the brand there); revealed in responsive.css ≤1240px. */
.nav-drawer-brand { display: none; }

/* Social row at the foot of that drawer — same arrangement: hidden here, styled
   and revealed in responsive.css ≤1240px. Its colours live there too, after
   .social-icons, so the brand fills win the cascade over that rule's gold
   hover state instead of having to out-specify it. */
.nav-social-block { display: none; }

/* --- Wordmark animation: flowing "liquid gold" + soft gold glow (continuous,
   lightweight, and frozen to a rich static gold logo under reduced motion) ---

   Pointer/desktop pass: wm-flow + wm-glow + wm-sheen.
   Touch pass:           wm-shine + wm-line-sweep + wm-float (see responsive.css).
   Both sets are declared here so every wordmark keyframe stays in one place. */
@keyframes wm-flow {
    to { background-position: 200% 50%; }   /* scroll one full tile = seamless loop */
}
@keyframes wm-glow {
    0%, 100% { filter: drop-shadow(0 0 2px rgba(212, 184, 122, 0)); }
    50%      { filter: drop-shadow(0 0 12px rgba(212, 184, 122, 0.55)); }
}
@keyframes wm-line-glow {
    0%, 100% { opacity: 0.7; box-shadow: 0 0 0 rgba(201, 169, 97, 0); }
    50%      { opacity: 1;   box-shadow: 0 0 7px rgba(201, 169, 97, 0.65); }
}
/* The band is narrower than the box it sits in, so -160% parks it clear of the
   left edge and 270% clear of the right: a 2.7s pass, then a 4.3s rest. It
   fades in and out at the ends of the pass because a background is clipped to
   its box — without the fade the band appears and vanishes on a straight
   vertical cut at the edge of the wordmark. */
@keyframes wm-sheen {
    0%        { background-position: -160% 0; opacity: 0; }
    6%, 30%   { opacity: 1; }
    36%, 100% { background-position:  270% 0; opacity: 0; }
}

/* --- Touch variants ---
   wm-shine moves the SAME background one tile-width, like wm-flow, but the tile
   carries a single near-white highlight instead of an even champagne ripple —
   so it reads as one bright pass across the letters and then a rest, rather
   than a permanent drift. Position runs 100%→0% because the tile is wider than
   the text: with an oversized background, a larger percentage sits further
   LEFT, so counting down is what sweeps the highlight left-to-right. */
@keyframes wm-shine {
    0%        { background-position: 100% 50%; }
    55%, 100% { background-position:   0% 50%; }
}
/* Hairline: stretched on transform (compositor) rather than the desktop
   box-shadow bloom (repaint). translateY(-50%) is the static centring from
   .wordmark-tag::before and has to be restated or the rule jumps. */
@keyframes wm-line-sweep {
    0%, 100% { transform: translateY(-50%) scaleX(1);    opacity: 0.7; }
    50%      { transform: translateY(-50%) scaleX(1.85); opacity: 1; }
}
@keyframes wm-float {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-2px); }
}

/* Primary nav */
.primary-nav .nav-list {
    display: flex;
    align-items: center;
    /* No inter-item gap: each .nav-link already carries sp-3 side padding, which
       keeps the items comfortably spaced while leaving room for the larger
       serif so the inline bar still fits beside the logo. */
    gap: 0;
}

.nav-item { position: relative; }

.nav-link {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    /* Horizontal padding trimmed sp-4 → sp-3 → sp-2, and the serif stepped
       1.2rem → 1.15rem. Ten items at the current labels (Television,
       Bibliography) plus the chevron chips measure ~1027px, but the 1240px
       container leaves only ~1192px once the wordmark and its gap are taken
       out. The trims bring the bar back to ~915px — the same headroom it had
       when the labels were shorter. Lengthening a label eats into that. */
    padding: var(--sp-3) var(--sp-2);
    color: var(--text);
    /* Matches the dropdown labels (.dropdown-link-label) so the main menu and
       its panels share one elegant, consistent typeface. */
    font-family: var(--font-display);
    font-size: 1.15rem;
    font-weight: 500;
    /* A two-word label (e.g. "Early Life") must never break across two lines —
       it drags the whole header row taller and strands its chevron. */
    white-space: nowrap;
    letter-spacing: 0.01em;
    border-radius: var(--radius-sm);
    transition: color var(--t-fast) var(--ease);
}
.nav-link:hover,
.nav-item.active > .nav-link { color: var(--accent); }

/* Dropdown-affordance chevron — a bare gold caret, no frame. It reads as an
   editorial mark rather than UI furniture, which suits the serif wordmark and
   the rest of the site's restrained gold-on-black palette. Full accent colour
   (not a dimmed grey) is what makes it legible at rest, so "this item opens a
   menu" is clear before any hover; it rotates to point up while open. */
.chev {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    margin-left: 4px;
    color: var(--accent);
    transition: transform var(--t-med) var(--ease),
                color var(--t-fast) var(--ease);
}
/* Slightly lighter stroke than the markup default reads crisper at this size —
   a 2px stroke on a 12px glyph looks blunt next to the fine serif. */
.chev svg { width: 13px; height: 13px; display: block; stroke-width: 1.75; }

/* Open / hovered / keyboard-focused: brightens and flips to point up. */
.nav-item.has-dropdown:hover .chev,
.nav-item.has-dropdown:focus-within .chev,
.nav-item.has-dropdown.expanded > .nav-link .chev {
    transform: rotate(180deg);
    color: var(--accent-hover);
}

/* ----- Dropdown (mega-menu-lite with branded section heading) ----- */
.dropdown {
    position: absolute;
    top: calc(100% + 8px); left: 0;
    min-width: 320px;
    max-width: 360px;
    background: var(--bg-elev);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 0;
    opacity: 0;
    visibility: hidden;
    transform: translateY(10px);
    transition: opacity var(--t-med) var(--ease),
                visibility var(--t-med) var(--ease),
                transform var(--t-med) var(--ease);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
    background-image:
        radial-gradient(circle at top right, rgba(201, 169, 97, 0.06), transparent 50%),
        linear-gradient(180deg, rgba(255,255,255,0.02), transparent 30%);
}
/* Hover-bridge: invisible safety zone so the dropdown doesn't close
   between the parent link and the dropdown body */
.nav-item.has-dropdown::after {
    content: '';
    position: absolute;
    top: 100%; left: 0;
    width: 100%; height: 12px;
    display: none;
}
.nav-item.has-dropdown:hover::after { display: block; }

.nav-item.has-dropdown:hover > .dropdown,
.nav-item.has-dropdown:focus-within > .dropdown {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

/* Anchor dropdown to the right edge for menu items near the end of the bar.
   The Showcase dropdown sits in the right half — pin it to the right so the
   wider panel doesn't clip the viewport. */
.nav-item.has-dropdown.nav-item-showcase .dropdown { left: auto; right: 0; }

/* --- Dropdown header (the new bit) --- */
.dropdown-header {
    padding: var(--sp-5) var(--sp-5) var(--sp-4);
    border-bottom: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    gap: 6px;
    position: relative;
}
.dropdown-header::after {
    /* small gold accent line at the bottom-left of the header — matches the
       hairline that prefixes the wordmark-tag */
    content: '';
    position: absolute;
    bottom: -1px;
    left: var(--sp-5);
    width: 28px;
    height: 1px;
    background: var(--accent);
    opacity: 0.85;
}

.dropdown-eyebrow {
    font-family: var(--font-sans);
    font-size: 0.65rem;
    font-weight: 600;
    letter-spacing: 0.32em;
    text-transform: uppercase;
    color: var(--accent);
    padding-left: 22px;
    position: relative;
}
.dropdown-eyebrow::before {
    /* matches .wordmark-tag::before for visual rhyme */
    content: '';
    position: absolute;
    left: 0; top: 50%;
    width: 14px;
    height: 1px;
    background: var(--accent);
    transform: translateY(-50%);
    opacity: 0.7;
}

.dropdown-subtitle {
    font-family: var(--font-display);
    font-size: 1rem;
    font-style: italic;
    font-weight: 400;
    line-height: 1.3;
    color: var(--text);
    letter-spacing: 0.005em;
}

/* --- Dropdown link list --- */
.dropdown-list {
    list-style: none;
    margin: 0;
    padding: var(--sp-3);
}

.dropdown-link {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-areas: "label arrow";
    align-items: center;
    column-gap: var(--sp-4);
    padding: var(--sp-3) var(--sp-4);
    color: var(--text);
    border-radius: var(--radius);
    transition: background var(--t-fast) var(--ease),
                color var(--t-fast) var(--ease),
                padding-left var(--t-med) var(--ease);
    position: relative;
}

.dropdown-link-label {
    grid-area: label;
    font-family: var(--font-display);
    font-size: 1.05rem;
    font-weight: 500;
    line-height: 1.2;
    color: var(--text);
    transition: color var(--t-fast) var(--ease);
}

.dropdown-arrow {
    grid-area: arrow;
    font-size: 1.1rem;
    color: var(--accent);
    opacity: 0;
    transform: translateX(-6px);
    transition: opacity var(--t-med) var(--ease),
                transform var(--t-med) var(--ease);
}

.dropdown-link:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
}
.dropdown-link:hover,
.dropdown-link.active,
.dropdown-link:focus-visible {
    background: linear-gradient(90deg, rgba(201, 169, 97, 0.08), transparent);
}
.dropdown-link:hover .dropdown-link-label,
.dropdown-link.active .dropdown-link-label {
    color: var(--accent-hover);
}
.dropdown-link:hover .dropdown-arrow,
.dropdown-link.active .dropdown-arrow,
.dropdown-link:focus-visible .dropdown-arrow {
    opacity: 1;
    transform: translateX(0);
}

/* Active-page indicator: a thin gold rule on the left */
.dropdown-link.active::before {
    content: '';
    position: absolute;
    left: 4px; top: 50%;
    width: 2px; height: 60%;
    background: var(--accent);
    border-radius: 2px;
    transform: translateY(-50%);
}

/* ----- Nested submenu (e.g. FilmoGraphy → Direction → …) ----- */
/* A dropdown that contains a flyout submenu must NOT clip it. The base
   .dropdown uses overflow:hidden for its rounded corners; that would cut off
   the sub-panel which sits at left:100% (outside the box). */
.dropdown.has-nested { overflow: visible; }
.has-subdropdown { position: relative; }
/* The "Direction" trigger never navigates — its arrow points sideways. Like
   the top-level chevrons it is a bare gold caret, and unlike the leaf links
   (whose → only fades in on hover) it stays visible at rest, since that is the
   only cue that this row opens a further menu. */
.has-subdropdown > .dropdown-link .dropdown-arrow {
    opacity: 1;
    transform: none;
    font-size: 1.1rem;
    line-height: 1;
    color: var(--accent);
    transition: color var(--t-fast) var(--ease),
                transform var(--t-fast) var(--ease);
}
.has-subdropdown:hover > .dropdown-link .dropdown-arrow,
.has-subdropdown:focus-within > .dropdown-link .dropdown-arrow {
    color: var(--accent-hover);
}

.dropdown-sublist {
    list-style: none;
    margin: 0;
    padding: var(--sp-3);
    position: absolute;
    top: -1px;
    left: 100%;
    min-width: 260px;
    max-width: 300px;
    background: var(--bg-elev);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    background-image:
        radial-gradient(circle at top right, rgba(201, 169, 97, 0.06), transparent 50%),
        linear-gradient(180deg, rgba(255,255,255,0.02), transparent 30%);
    opacity: 0;
    visibility: hidden;
    transform: translateX(8px);
    transition: opacity var(--t-med) var(--ease),
                visibility var(--t-med) var(--ease),
                transform var(--t-med) var(--ease);
    z-index: 2;
}
.has-subdropdown:hover > .dropdown-sublist,
.has-subdropdown:focus-within > .dropdown-sublist {
    opacity: 1;
    visibility: visible;
    transform: translateX(0);
}

/* ----- Utility top bar (above the main menu): contact + social ----- */
.topbar {
    border-bottom: 1px solid var(--border);
    margin-bottom: var(--sp-3);
    padding-bottom: var(--sp-3);
    max-height: 50px;
    overflow: hidden;
    transition: max-height var(--t-med) var(--ease),
                opacity var(--t-med) var(--ease),
                margin var(--t-med) var(--ease),
                padding var(--t-med) var(--ease),
                border-color var(--t-med) var(--ease);
}
/* Tuck the utility bar away once the user starts scrolling — only the main
   menu stays pinned. (main.js adds .scrolled past 40px of scroll.) */
.site-header.scrolled .topbar {
    max-height: 0;
    opacity: 0;
    margin-bottom: 0;
    padding-bottom: 0;
    border-bottom-color: transparent;
    pointer-events: none;
}
.topbar-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    font-size: 0.8rem;
}
.topbar-contact {
    display: flex;
    align-items: center;
    gap: var(--sp-5);
    min-width: 0;
}
.topbar-item {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    color: var(--text-muted);
    letter-spacing: 0.01em;
    min-width: 0;
    transition: color var(--t-fast) var(--ease);
}
.topbar-item:hover { color: var(--accent); }
/* Focus needs its own visible indicator: hover's colour swap alone is a
   colour-only cue, which does not satisfy WCAG 2.4.11 and disappears entirely
   for anyone who cannot distinguish the two greys. */
.topbar-item:focus-visible {
    color: var(--accent);
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.topbar-item svg { width: 15px; height: 15px; color: var(--accent); flex: none; }
.topbar-item .topbar-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.topbar-social {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-4);
    flex: none;
}
.topbar-social a {
    display: inline-flex;
    color: var(--text-muted);
    transition: color var(--t-fast) var(--ease), transform var(--t-med) var(--ease);
}
.topbar-social a:hover { color: var(--accent); transform: translateY(-2px); }
.topbar-social a:focus-visible {
    color: var(--accent);
    transform: translateY(-2px);
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.topbar-social svg { width: 16px; height: 16px; }

/* Hamburger */
.nav-toggle {
    display: none;
    width: 44px; height: 44px;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 5px;
}
.nav-toggle span {
    width: 24px;
    height: 2px;
    background: var(--text);
    transition: all var(--t-med) var(--ease);
}
.nav-toggle.open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle.open span:nth-child(2) { opacity: 0; }
.nav-toggle.open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* ----- Hero ----- */
.hero {
    position: relative;
    min-height: 100vh;
    display: grid;
    place-items: center;
    color: var(--text);
    background: var(--bg);
    overflow: hidden;
    text-align: center;
    padding: calc(var(--header-h) + var(--sp-6)) var(--sp-5) var(--sp-8);
}

.hero::before {
    content: '';
    position: absolute;
    inset: 0;
    background: radial-gradient(ellipse at center, rgba(201, 169, 97, 0.15), transparent 60%),
                linear-gradient(180deg, rgba(10,10,10,.5) 0%, rgba(10,10,10,.9) 100%);
    z-index: 1;
}

.hero-bg {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
    filter: grayscale(20%) brightness(0.7);
    z-index: 0;
}

.hero-inner {
    position: relative;
    z-index: 2;
    max-width: 880px;
    margin: 0 auto;
}

.hero-eyebrow {
    color: var(--accent);
    margin-bottom: var(--sp-5);
}

.hero-title {
    font-size: clamp(2.5rem, 8vw, 5.5rem);
    font-weight: 600;
    margin-bottom: var(--sp-5);
    line-height: 1.05;
}

.hero-divider {
    width: 60px;
    height: 2px;
    background: var(--accent);
    margin: var(--sp-5) auto;
}

.hero-subtitle {
    font-size: var(--fs-lg);
    color: var(--text-muted);
    margin-bottom: var(--sp-4);
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

.hero-lead {
    font-size: var(--fs-md);
    color: var(--text);
    max-width: 640px;
    margin: 0 auto var(--sp-7);
    line-height: 1.7;
}

.hero-actions {
    display: flex;
    gap: var(--sp-4);
    justify-content: center;
    flex-wrap: wrap;
}

.hero-scroll-cue {
    position: absolute;
    bottom: var(--sp-6);
    left: 50%;
    transform: translateX(-50%);
    color: var(--text-muted);
    font-size: var(--fs-xs);
    letter-spacing: 0.2em;
    text-transform: uppercase;
    z-index: 2;
    animation: bob 2s ease-in-out infinite;
}
@keyframes bob {
    0%, 100% { transform: translate(-50%, 0); opacity: 0.7; }
    50%      { transform: translate(-50%, 8px); opacity: 1; }
}

/* ==========================================================================
   Hero slider (homepage) — cinematic, brand-consistent, fully responsive
   ========================================================================== */
.hero-slider {
    position: relative;
    min-height: 100vh;
    min-height: 100svh;
    color: var(--text);
    overflow: hidden;
    isolation: isolate;
    /* Backdrop for the whole slideshow. The photographs now cover the frame
       edge to edge, so this is no longer the ground they sit on — but it still
       earns its place twice over: it shows through the middle of a crossfade,
       when both the outgoing and incoming photo are part-faded and neither is
       opaque, and it carries the hero on its own if a photo is ever missing. */
    background:
        radial-gradient(120% 90% at 70% 22%, rgba(201,169,97,0.20), transparent 58%),
        linear-gradient(150deg, #17130a 0%, #0c0b08 48%, var(--bg) 100%);
}

/* ----- Background stack -----
   The hero copy is fixed and lives outside the track (see .hero-copy), so the
   track is purely a backdrop: a pile of absolutely-stacked photo layers that
   crossfade one into the next. */
.hero-track {
    position: absolute;
    inset: 0;
    z-index: 0;
}

/* ----- Individual slide -----
   A full-bleed frame for one photograph: the photo covers the hero edge to
   edge, so the slide is simply the viewport-sized box it fills. */
.hero-slide {
    position: absolute;
    inset: 0;
    opacity: 0;
    visibility: hidden;
    z-index: 0;
    transition: opacity var(--t-slow) var(--ease),
                visibility var(--t-slow) var(--ease);
}
.hero-slide.is-active {
    opacity: 1;
    visibility: visible;
    z-index: 1;
}

/* The photograph — filling the frame. `cover` means something has to be cut:
   the sources run from 1.05 to 1.78 in aspect while the hero follows the
   viewport, so on a wide desktop a squarish photo loses height and on a phone
   every photo loses most of its width. Which part survives is what --focus
   decides: it is the subject's position in that particular frame, set per slide
   in data/site.php and written onto the tag by index.php. Without it the crop
   is taken from the centre, which on a phone throws away a subject standing at
   either edge — the opening banner's subject sits at 28% and would be gone. */
.hero-slide-photo {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: var(--focus, 50% 50%);
    /* Holds the photographs together as a set, and takes the edge off the
       brightest frames so the copy over them keeps its contrast. */
    filter: grayscale(12%) brightness(0.88);
    /* Resting state is deliberately the END of the zoom, not the start: when a
       slide goes inactive its animation is dropped, and landing on the value it
       already held means the outgoing photo cannot visibly snap mid-fade. */
    transform: scale(1.08);
}

/* Ken Burns. Transform only — it is composited on the GPU, never triggers
   layout or paint, and touches nothing but this one element, so the copy
   sitting above it is completely unaffected. It runs slightly shorter than the
   slide interval so it has settled before the crossfade begins. */
.hero-slide.is-active .hero-slide-photo {
    animation: heroKenBurns calc(var(--hero-interval, 6500ms) - 250ms) linear forwards;
    will-change: transform;
}
@keyframes heroKenBurns {
    from { transform: scale(1); }
    to   { transform: scale(1.08); }
}
/* Whenever the slideshow itself is not running — paused by the button, or the
   tab is in the background — stop the zoom too, rather than burn frames on an
   animation nobody is watching. */
.hero-slider:not(.is-playing) .hero-slide-photo {
    animation-play-state: paused;
}

/* Cinematic wash — weighted to the RIGHT so the text stays legible while the
   left side of the photo is left bright and highlighted. It sits above the
   whole background stack rather than inside each layer, so it holds steady
   instead of pulsing while two photos crossfade. */
.hero-slider::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background:
        radial-gradient(ellipse at 88% 42%, rgba(201,169,97,0.16), transparent 55%),
        linear-gradient(90deg, rgba(10,10,10,0.04) 0%, rgba(10,10,10,0.22) 38%, rgba(10,10,10,0.66) 66%, rgba(10,10,10,0.88) 100%),
        linear-gradient(180deg, transparent 55%, rgba(10,10,10,0.55) 100%);
}

/* ----- Hero copy -----
   Static: it is written once, above the slideshow, and never re-animates when
   the photo behind it changes. This element also sets the hero's height and
   holds the padding the slides used to carry. */
.hero-copy {
    position: relative;
    z-index: 2;
    min-height: inherit;
    display: grid;
    place-items: center end;
    text-align: right;
    padding: calc(var(--header-h) + var(--sp-7)) clamp(var(--sp-6), 8vw, 7rem) var(--sp-10);
}

.hero-slide-inner {
    max-width: 600px;
    margin: 0;
    /* Reveal once on load. The hidden state lives in the keyframe rather than
       on the element, so if animations are stripped out (reduced motion) the
       copy still renders in its final, visible state. */
    animation: heroContentIn var(--t-slow) var(--ease-out) 180ms both;
}
@keyframes heroContentIn {
    from { transform: translateY(24px); opacity: 0; }
    to   { transform: translateY(0);    opacity: 1; }
}

/* Two-line closing tagline under the subtitle */
.hero-tagline {
    font-family: var(--font-display);
    font-size: clamp(1.5rem, 3.2vw, 2.25rem);
    line-height: 1.28;
    color: var(--text);
    margin: 0 0 var(--sp-7) auto;
}

.hero-slide-eyebrow {
    color: var(--accent);
    margin-bottom: var(--sp-5);
}

.hero-slide-title {
    font-size: clamp(2rem, 5.2vw, 3.75rem);
    font-weight: 600;
    line-height: 1.06;
    margin-bottom: var(--sp-4);
}

.hero-slide-divider {
    display: block;
    width: 60px;
    height: 2px;
    background: var(--gradient-gold);
    margin: var(--sp-5) 0 var(--sp-5) auto;
}

/* Sits over photography, so it is set for legibility rather than as quiet
   secondary text: full-strength colour instead of --text-muted (which was only
   ~3.6:1 against the wash), a heavier weight, wider tracking to open up the
   capitals, and a soft shadow to hold the letters together over a busy frame.
   Neutral rather than gold on purpose — the divider directly above it and the
   Screenplay button below are already gold, and a third gold element between
   them would flatten the hierarchy. */
.hero-slide-subtitle {
    font-size: var(--fs-lg);
    color: var(--text);
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    margin-bottom: var(--sp-4);
    text-shadow: 0 1px 12px rgba(10, 10, 10, 0.55);
}

.hero-slide-lead {
    font-size: var(--fs-md);
    color: var(--text);
    max-width: 540px;
    margin: 0 0 var(--sp-7) auto;
    line-height: 1.7;
}

.hero-slide-actions {
    display: flex;
    gap: var(--sp-4);
    justify-content: flex-end;
    flex-wrap: wrap;
}

/* ----- Arrows -----
   Not rendered by the homepage hero any more: with the copy fixed, prev/next
   would only shuffle the photograph. Kept here so re-enabling them is a
   markup-only change. */
.hero-arrow {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 5;
    width: 56px;
    height: 56px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: rgba(10, 10, 10, 0.32);
    border: 1px solid var(--border-strong);
    color: var(--text);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
    transition: background var(--t-med) var(--ease),
                color var(--t-med) var(--ease),
                border-color var(--t-med) var(--ease),
                transform var(--t-med) var(--ease);
}
.hero-arrow svg { width: 24px; height: 24px; }
.hero-arrow:hover,
.hero-arrow:focus-visible {
    background: var(--accent);
    color: var(--bg);
    border-color: var(--accent);
    outline: none;
}
.hero-arrow-prev { left: var(--sp-6); }
.hero-arrow-next { right: var(--sp-6); }
.hero-arrow-prev:hover { transform: translateY(-50%) translateX(-3px); }
.hero-arrow-next:hover { transform: translateY(-50%) translateX(3px); }

/* ----- Controls cluster (dots + play/pause) ----- */
.hero-controls {
    position: absolute;
    bottom: var(--sp-7);
    left: 50%;
    transform: translateX(-50%);
    z-index: 5;
    display: flex;
    align-items: center;
    gap: var(--sp-4);
}

.hero-dots {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
}

.hero-dot {
    position: relative;
    width: 40px;
    height: 4px;
    border-radius: 4px;
    background: rgba(255, 255, 255, 0.22);
    overflow: hidden;
    transition: background var(--t-fast) var(--ease);
}
.hero-dot:hover { background: rgba(255, 255, 255, 0.4); }
.hero-dot::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: var(--gradient-gold);
    transform: scaleX(0);
    transform-origin: left center;
}
/* Active dot fills over the autoplay interval; pauses with the slideshow */
.hero-dot.is-active::after {
    animation: heroDotFill var(--hero-interval, 6500ms) linear forwards;
}
.hero-slider:not(.is-playing) .hero-dot.is-active::after {
    animation: none;
    transform: scaleX(1);
}
@keyframes heroDotFill {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
}

.hero-playpause {
    width: 34px;
    height: 34px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid var(--border-strong);
    color: var(--text);
    transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.hero-playpause:hover,
.hero-playpause:focus-visible { background: var(--accent); color: var(--bg); outline: none; }
.hero-playpause svg { width: 18px; height: 18px; }
.hero-playpause .icon-play  { display: none; }
.hero-playpause[aria-pressed="true"] .icon-pause { display: none; }
.hero-playpause[aria-pressed="true"] .icon-play  { display: block; }

/* Single-slide fallback: hide chrome */
.hero-slider.is-single .hero-arrow,
.hero-slider.is-single .hero-controls { display: none; }

/* Reposition the scroll cue to the corner so it clears the centered controls */
.hero-slider .hero-scroll-cue {
    left: auto;
    right: var(--sp-6);
    bottom: var(--sp-6);
    transform: none;
    animation: heroBob 2s ease-in-out infinite;
}
@keyframes heroBob {
    0%, 100% { transform: translateY(0);   opacity: 0.7; }
    50%      { transform: translateY(8px); opacity: 1; }
}

/* ----- Inner page hero ----- */
.page-hero {
    /* Top padding must clear the fixed header (--header-h); the extra above and
       below is what sets the band's height. */
    padding: calc(var(--header-h) + var(--sp-6)) var(--sp-5) var(--sp-6);
    background-size: cover;
    background-position: center;
    color: var(--text);
    text-align: center;
}

.page-hero-inner {
    max-width: 880px;
    margin: 0 auto;
}

.breadcrumb {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    color: var(--text-muted);
    font-size: var(--fs-xs);
    letter-spacing: 0.15em;
    text-transform: uppercase;
    margin-bottom: var(--sp-4);
}
.breadcrumb a { color: var(--text-muted); transition: color var(--t-fast); }
.breadcrumb a:hover { color: var(--accent); }
.breadcrumb [aria-current] { color: var(--accent); }

.page-hero-title {
    font-size: clamp(2rem, 6vw, 4rem);
    margin-bottom: var(--sp-3);
}

/* Sits on a photograph, so it is set to be read rather than to recede: it was
   --text-muted at a flat 18px, which measured only ~3.6:1 against the scrim.
   Full-strength colour, a responsive size that grows on wider screens, a touch
   more weight, and a soft shadow to hold the letters together over a busy
   background. Line height is opened up because some pages run to two lines. */
.page-hero-sub {
    color: var(--text);
    font-size: clamp(1.25rem, 2.2vw, 1.75rem);
    font-weight: 500;
    line-height: 1.5;
    letter-spacing: 0.01em;
    text-shadow: 0 1px 14px rgba(10, 10, 10, 0.6);
    max-width: 620px;
    margin: 0 auto;
}

/* Highlighted variant: short standout phrases set in the champagne gold rather
   than plain white. Slightly tracked out and shadowed a touch harder, since the
   gold is a mid-tone and can sit over a bright patch of the photograph. */
.page-hero-sub--accent {
    color: var(--accent-light);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-shadow: 0 1px 16px rgba(10, 10, 10, 0.75);
}

/* Banner variant: the background image is a finished piece with its own title
   artwork. Give it a generous, responsive height and anchor LEFT so the baked-in
   text (which sits on the left of the image) is never cropped on narrow screens.
   The overlaid <h1>/subtitle are visually hidden; only the breadcrumb sits on top. */
.page-hero--banner {
    min-height: clamp(300px, 40vw, 540px);
    background-position: left center;
}

/* ----- Cards & grids ----- */
.grid {
    display: grid;
    gap: var(--sp-5);
}
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }

.card {
    background: var(--bg-light);
    border: 1px solid var(--border-light);
    border-radius: var(--radius-lg);
    overflow: hidden;
    transition: transform var(--t-med) var(--ease),
                box-shadow var(--t-med) var(--ease),
                border-color var(--t-med) var(--ease);
}
.card:hover {
    transform: translateY(-4px);
    box-shadow: 0 16px 40px rgba(0,0,0,.08);
    border-color: var(--accent);
}

.section-dark .card {
    background: var(--bg-card);
    border-color: var(--border);
}
.section-dark .card:hover { border-color: var(--accent); }

.card-img {
    aspect-ratio: 4 / 3;
    background: linear-gradient(135deg, var(--bg-card), var(--bg-elev));
    background-size: cover;
    background-position: center;
    overflow: hidden;
}
.card-img img {
    width: 100%; height: 100%;
    object-fit: cover;
    transition: transform var(--t-slow) var(--ease);
}
.card:hover .card-img img { transform: scale(1.05); }

.card-body { padding: var(--sp-5) var(--sp-5) var(--sp-6); }
.card-title {
    font-size: var(--fs-xl);
    margin-bottom: var(--sp-2);
}
.card-meta {
    font-size: var(--fs-xs);
    letter-spacing: 0.15em;
    text-transform: uppercase;
    /* Text-safe gold on the light card surface; restored to --accent for cards
       inside .section-dark just below. */
    color: var(--accent-ink);
    margin-bottom: var(--sp-3);
}
.card-text { color: var(--text-dark-mut); }
.section-dark .card-text { color: var(--text-muted); }
.section-dark .card-meta { color: var(--accent); }

/* Card call-to-action. Built on .btn-primary so it inherits the site's button
   shape, size and lift, with two hover flourishes on top: the arrow steps
   forward, and a soft highlight sweeps across the face. Both are driven from
   the CARD's hover as well as the button's own, so pointing anywhere at the
   card animates it and the whole tile reads as one target. Transform and a
   single offset only — no layout work, so it stays smooth on mobile. */
.card-cta {
    margin-top: var(--sp-5);
    position: relative;
    overflow: hidden;
    isolation: isolate;
}
.card-cta-arrow {
    display: inline-block;
    transition: transform var(--t-med) var(--ease);
}
.card:hover .card-cta-arrow,
.card-cta:hover .card-cta-arrow,
.card-cta:focus-visible .card-cta-arrow {
    transform: translateX(5px);
}
.card-cta::before {
    content: '';
    position: absolute;
    top: 0;
    left: -140%;
    width: 55%;
    height: 100%;
    background: linear-gradient(100deg, transparent, rgba(255,255,255,0.5), transparent);
    transform: skewX(-18deg);
    transition: left 0.6s var(--ease);
    pointer-events: none;
    z-index: -1;
}
.card:hover .card-cta::before,
.card-cta:hover::before,
.card-cta:focus-visible::before {
    left: 140%;
}

/* ----- About / two-column ----- */
.two-col {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--sp-9);
    align-items: center;
}
.two-col-image {
    aspect-ratio: 4 / 5;
    background: var(--bg-card);
    border-radius: var(--radius-lg);
    background-size: cover;
    background-position: center;
    position: relative;
    overflow: hidden;
}
.two-col-image::after {
    content: '';
    position: absolute;
    inset: 0;
    border: 1px solid var(--border-light);
    border-radius: var(--radius-lg);
    pointer-events: none;
}
.two-col-text h2 { margin-bottom: var(--sp-4); }
.two-col-text p  { color: var(--text-dark-mut); margin-bottom: var(--sp-4); font-size: var(--fs-md); }

/* ----- About portrait (homepage) -----
   A framed photograph rather than the flat .two-col-image tile: the picture
   keeps its own 1113x1600 proportions and a nameplate rides the bottom edge
   over a scrim. Everything decorative is a pseudo-element or a single empty
   span, so the markup stays a plain figure + img. */
.about-portrait {
    position: relative;
    width: 100%;
    max-width: 430px;
    margin: 0 auto;
    isolation: isolate;
}

/* Warm bloom under the frame so the portrait sits on the pale page instead of
   floating on it. */
.about-portrait::after {
    content: '';
    position: absolute;
    inset: auto -10% -7% -10%;
    height: 55%;
    background: radial-gradient(ellipse at 50% 100%, rgba(201, 169, 97, 0.28), transparent 70%);
    z-index: -2;
    pointer-events: none;
}

.about-portrait-frame {
    position: relative;
    overflow: hidden;
    border-radius: var(--radius-lg);
    background: var(--bg-section);
    box-shadow: 0 26px 60px rgba(26, 26, 26, 0.22), 0 2px 8px rgba(26, 26, 26, 0.08);
    transition: transform 700ms var(--ease), box-shadow 700ms var(--ease);
}

.about-portrait-frame img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 1113 / 1600;
    object-fit: cover;
    object-position: center top;
}

/* Scrim for the nameplate + a hairline edge, matching .two-col-image::after. */
.about-portrait-frame::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(to top,
        rgba(10, 10, 10, 0.74) 0%,
        rgba(10, 10, 10, 0.28) 16%,
        rgba(10, 10, 10, 0) 40%);
    pointer-events: none;
    z-index: 1;
}
.about-portrait-frame::after {
    content: '';
    position: absolute;
    inset: 0;
    border: 1px solid var(--border-light);
    border-radius: var(--radius-lg);
    pointer-events: none;
    z-index: 3;
    transition: border-color 700ms var(--ease);
}

/* Band of gold light that crosses the photograph on hover. It is parked off
   the left edge and hidden, so the reset after hover-out is a fade rather than
   a second sweep running backwards: the transform snap is delayed until the
   fade has finished. Over-sized top/bottom so the skewed corners never show. */
.about-portrait-sheen {
    position: absolute;
    top: -20%;
    bottom: -20%;
    left: -40%;
    width: 42%;
    z-index: 2;
    pointer-events: none;
    opacity: 0;
    background: linear-gradient(90deg,
        rgba(245, 227, 184, 0) 0%,
        rgba(245, 227, 184, 0.35) 40%,
        rgba(255, 255, 255, 0.6) 50%,
        rgba(245, 227, 184, 0.35) 60%,
        rgba(245, 227, 184, 0) 100%);
    transform: translateX(-140%) skewX(-14deg);
    transition: opacity 260ms var(--ease), transform 0s 260ms;
}

.about-portrait-plate {
    position: absolute;
    left: var(--sp-5);
    right: var(--sp-5);
    bottom: var(--sp-5);
    z-index: 4;
    display: flex;
    flex-direction: column;
    gap: var(--sp-1);
    padding-left: var(--sp-4);
    border-left: 2px solid var(--accent);
    transition: transform 700ms var(--ease);
}
.about-portrait-name {
    font-family: var(--font-serif);
    font-size: var(--fs-xl);
    line-height: 1.15;
    color: #fff;
}
.about-portrait-role {
    font-family: var(--font-sans);
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--accent-light);
}

/* Hover: the framed photograph lifts off the page on a deeper shadow while a
   band of gold light sweeps across it. */
.about-portrait:hover .about-portrait-frame {
    transform: translateY(-12px);
    box-shadow: 0 44px 84px rgba(26, 26, 26, 0.3), 0 4px 12px rgba(26, 26, 26, 0.1);
}
.about-portrait:hover .about-portrait-frame::after {
    border-color: rgba(201, 169, 97, 0.55);
}
.about-portrait:hover .about-portrait-sheen {
    opacity: 1;
    transform: translateX(420%) skewX(-14deg);
    transition: opacity 200ms var(--ease), transform 1100ms var(--ease-out);
}
.about-portrait:hover .about-portrait-plate { transform: translateY(-4px); }

/* ----- Stats / highlights ----- */
.stats {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--sp-5);
    padding: var(--sp-8) 0;
    border-top: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
}
.stat { text-align: center; }
.stat-number {
    font-family: var(--font-serif);
    font-size: var(--fs-4xl);
    font-weight: 600;
    color: var(--accent);
    margin-bottom: var(--sp-2);
    line-height: 1;
}
.stat-label {
    font-size: var(--fs-xs);
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--text-muted);
}

/* ----- Timeline (awards / news) ----- */
.timeline {
    position: relative;
    padding-left: var(--sp-7);
    max-width: 760px;
    margin: 0 auto;
}
.timeline::before {
    content: '';
    position: absolute;
    left: 8px; top: 0; bottom: 0;
    width: 2px;
    background: var(--border-light);
}
.section-dark .timeline::before { background: var(--border); }

.timeline-item {
    position: relative;
    padding: 0 0 var(--sp-7);
}
.timeline-item::before {
    content: '';
    position: absolute;
    left: calc(-1 * var(--sp-7) + 2px);
    top: var(--sp-2);
    width: 14px; height: 14px;
    border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 0 4px var(--bg-light);
}
.section-dark .timeline-item::before { box-shadow: 0 0 0 4px var(--bg); }

.timeline-year {
    display: inline-block;
    font-size: var(--fs-xs);
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--accent);
    margin-bottom: var(--sp-2);
    font-weight: 600;
}
.timeline-title {
    font-size: var(--fs-lg);
    margin-bottom: var(--sp-2);
}
.timeline-meta {
    color: var(--text-dark-mut);
    font-size: var(--fs-sm);
}
.section-dark .timeline-meta { color: var(--text-muted); }

/* ----- Gallery ----- */
.gallery-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--sp-3);
}
.gallery-item {
    aspect-ratio: 1;
    background: var(--bg-card);
    border-radius: var(--radius);
    overflow: hidden;
    cursor: pointer;
    position: relative;
}
.gallery-item img {
    width: 100%; height: 100%;
    object-fit: cover;
    transition: transform var(--t-slow) var(--ease);
}
.gallery-item::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, transparent 60%, rgba(0,0,0,0.7));
    opacity: 0;
    transition: opacity var(--t-med);
}
.gallery-item:hover img    { transform: scale(1.08); }
.gallery-item:hover::after { opacity: 1; }
.gallery-item:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* ----- Masonry gallery (biography & photo essays) -----
   Mixed-aspect photos shown uncropped in balanced columns. Each tile reuses
   .gallery-item (hover zoom + gradient) and opens in the shared lightbox. */
.masonry {
    column-count: 3;
    column-gap: var(--sp-3);
}
.masonry .gallery-item {
    display: block;
    width: 100%;
    aspect-ratio: auto;
    margin: 0 0 var(--sp-3);
    break-inside: avoid;
    -webkit-column-break-inside: avoid;
}
.masonry .gallery-item img {
    width: 100%;
    height: auto;
    display: block;
}

/* ----- Arts gallery wall (arts.php) -----
   Mixed-aspect artworks shown uncropped in a masonry wall, each set in a
   gold-edged matte frame that lifts under a soft spotlight on hover. The wall
   is auto-populated from images/Arts/ in PHP, so any number of works flows in,
   and each frame opens in the shared lightbox via [data-lightbox]. */
.art-wall {
    column-count: 3;
    column-gap: var(--sp-5);
}
.art-frame {
    display: block;
    position: relative;
    width: 100%;
    margin: 0 0 var(--sp-5);
    break-inside: avoid;
    -webkit-column-break-inside: avoid;
    padding: 10px;
    background: linear-gradient(160deg, #2c2c2c 0%, #1f1f1f 100%);
    border: 1px solid rgba(201, 169, 97, 0.38);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-sm);
    cursor: pointer;
    overflow: hidden;
    transition: transform var(--t-med) var(--ease),
                border-color var(--t-med) var(--ease),
                box-shadow var(--t-med) var(--ease);
}
.art-frame img {
    display: block;
    width: 100%;
    height: auto;
    border-radius: 2px;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.55), 0 6px 16px rgba(0, 0, 0, 0.35);
    transition: transform var(--t-slow) var(--ease);
}
.art-frame:hover {
    transform: translateY(-6px);
    border-color: var(--accent);
    box-shadow: var(--shadow-lg), 0 0 0 1px rgba(201, 169, 97, 0.25);
}
.art-frame:hover img { transform: scale(1.05); }

/* "View full size" magnifier that fades in over the work on hover */
.art-frame__view {
    position: absolute;
    inset: 10px;
    display: grid;
    place-items: center;
    border-radius: 2px;
    background: rgba(10, 9, 7, 0.42);
    opacity: 0;
    transition: opacity var(--t-med) var(--ease);
    pointer-events: none;
}
.art-frame__view svg {
    width: 40px; height: 40px;
    color: var(--accent-light);
    filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.6));
    transform: scale(0.85);
    transition: transform var(--t-med) var(--ease);
}
.art-frame:hover .art-frame__view     { opacity: 1; }
.art-frame:hover .art-frame__view svg { transform: scale(1); }

/* ==========================================================================
   Literature gallery — "Continuous filmstrip" (literature.php)
   A light, modern marquee: the photos scroll horizontally in one endless ribbon
   on the cream section (no dark panel). The set is rendered twice so the loop is
   seamless (translateX(-50%)); a per-image duration keeps the scroll speed
   constant at any photo count. It pauses on hover/focus, dissolves softly at
   both edges, becomes a manual swipe-strip under reduced motion, and every card
   opens the shared lightbox. Variable-width cards (fixed height, natural aspect)
   give it an editorial filmstrip feel.
   ========================================================================== */
/* ---- Open-book frame ----
   The filmstrip sits on the spread of an open book: two warm paper pages meeting
   at a centre crease, stacked page edges down the outer sides, and a soft shadow
   lifting the book off the cream section. Warm tones only — no black. */
.lit-book {
    position: relative;
    padding: clamp(22px, 3.2vw, 52px) clamp(26px, 4vw, 58px);
    border-radius: 8px;
    background: linear-gradient(90deg,
        #efe4cf 0%, #fdfaf2 5%, #fdfaf2 46%,
        #e7dcc2 49%, #d8c9a6 50%, #e7dcc2 51%, #fdfaf2 54%,
        #fdfaf2 95%, #efe4cf 100%);
    box-shadow:
        0 2px 0 rgba(255, 255, 255, 0.7) inset,
        0 22px 48px -22px rgba(60, 45, 20, 0.5),
        0 0 0 1px rgba(201, 169, 97, 0.22);
}
/* Stacked page-edge thickness down the outer sides (>=3px bands so they stay
   crisp at fractional device-pixel ratios) */
.lit-book::before,
.lit-book::after {
    content: '';
    position: absolute;
    top: 10px; bottom: 10px;
    width: 9px;
    z-index: 1;
    background: repeating-linear-gradient(180deg,
        #f0e5d0 0, #f0e5d0 3px, #dccba6 3px, #dccba6 5px);
}
.lit-book::before { left: -6px;  border-radius: 5px 0 0 5px; box-shadow: -3px 5px 9px rgba(60, 45, 20, 0.16); }
.lit-book::after  { right: -6px; border-radius: 0 5px 5px 0; box-shadow:  3px 5px 9px rgba(60, 45, 20, 0.16); }

/* Centre fold — a soft valley crease (light–shadow–light) the photos glide
   across, so it reads as a page fold rather than a flat dark band. It sits in
   front like a real spine; kept subtle so it never muddies the photos. */
.lit-book__gutter {
    position: absolute;
    top: 0; bottom: 0; left: 50%;
    width: 38px;
    transform: translateX(-50%);
    z-index: 2;
    pointer-events: none;
    background: linear-gradient(90deg,
        rgba(70, 52, 24, 0) 0%,
        rgba(255, 251, 242, 0.14) 26%,
        rgba(70, 52, 24, 0.13) 50%,
        rgba(255, 251, 242, 0.14) 74%,
        rgba(70, 52, 24, 0) 100%);
}

.lit-marquee { position: relative; }
.lit-marquee__viewport {
    overflow: hidden;
    padding: clamp(16px, 2vh, 28px) 0;   /* room so the hover lift + its shadow aren't clipped */
    /* Soft dissolve at both edges so cards emerge / leave gracefully. The black
       here is a mask alpha channel, not a visible colour. (On the viewport, not
       the marquee, so the pause button stays fully opaque.) */
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 6%, #000 94%, transparent 100%);
            mask-image: linear-gradient(90deg, transparent 0, #000 6%, #000 94%, transparent 100%);
}
.lit-marquee__track {
    display: flex;
    width: max-content;
    /* Cards carry their own right margin (not flex gap) so translateX(-50%)
       lands exactly on a repeat and the loop is seamless. */
    animation: lit-marquee var(--lit-duration, 50s) linear infinite;
}
.lit-marquee:hover  .lit-marquee__track,
.lit-marquee:focus-within .lit-marquee__track,
.lit-marquee.is-paused .lit-marquee__track {
    animation-play-state: paused;        /* hover / keyboard focus / pause button */
}
@keyframes lit-marquee {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}

/* Pause / play control — always visible, reachable on touch (WCAG 2.2.2) */
.lit-marquee__pause {
    position: absolute;
    top: var(--sp-3); right: var(--sp-3);
    z-index: 4;
    display: grid; place-items: center;
    width: 44px; height: 44px;
    border-radius: 50%;
    color: var(--accent-deep);
    background: rgba(255, 255, 255, 0.92);
    box-shadow: var(--shadow-sm);
    transition: transform var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.lit-marquee__pause:hover { transform: scale(1.08); background: #fff; }
.lit-marquee__pause:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lit-marquee__icon { width: 20px; height: 20px; }
.lit-marquee__icon--play { display: none; }
.lit-marquee.is-paused .lit-marquee__icon--pause { display: none; }
.lit-marquee.is-paused .lit-marquee__icon--play  { display: block; }

/* One photo card — fixed height, natural (variable) width */
.lit-card {
    position: relative;
    flex: none;
    height: clamp(260px, 40vh, 460px);   /* taller cards; width scales up with aspect-ratio */
    aspect-ratio: var(--ar, 4 / 3);      /* reserve width before decode → no reflow, equal halves */
    width: auto;
    min-width: 80px;                     /* last-resort guard if --ar is ever missing */
    margin-right: var(--sp-4);
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--bg-section);       /* matches the section, so any stray edge blends in */
    box-shadow: 0 5px 14px rgba(60, 45, 20, 0.13);   /* light, warm — photos mounted on the page */
    cursor: pointer;
    transition: transform var(--t-med) var(--ease),
                box-shadow var(--t-med) var(--ease);
}
.lit-card__img {
    width: 100%;
    height: 100%;
    object-fit: cover;                   /* fills the aspect-reserved box (no crop when --ar matches) */
    max-width: none;                     /* override the global img max-width */
    display: block;
    transition: transform var(--t-slow) var(--ease);
}

/* Editorial index chip — a light pill with a gold numeral, always legible */
.lit-card__index {
    position: absolute;
    top: var(--sp-3); left: var(--sp-3);
    z-index: 2;
    padding: 3px 11px;
    border-radius: 999px;
    font-family: var(--font-display);
    font-size: var(--fs-lg);
    line-height: 1.25;
    color: #6e5a2b;                      /* darker gold-brown — 4.5:1+ on the white pill */
    background: rgba(255, 255, 255, 0.92);
    box-shadow: var(--shadow-sm);
}

/* Light hover veil so the magnifier reads (no dark overlays) */
.lit-card::after {
    content: '';
    position: absolute; inset: 0; z-index: 1;
    background: rgba(255, 255, 255, 0);
    transition: background var(--t-med) var(--ease);
    pointer-events: none;
}

/* Centered "view full size" magnifier */
.lit-card__view {
    position: absolute; top: 50%; left: 50%;
    z-index: 3;
    display: grid; place-items: center;
    width: 56px; height: 56px;
    border-radius: 50%;
    color: var(--accent-deep);
    background: rgba(255, 255, 255, 0.92);
    box-shadow: var(--shadow-md);
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.8);
    transition: opacity var(--t-med) var(--ease), transform var(--t-med) var(--ease);
    pointer-events: none;
}
.lit-card__view svg { width: 22px; height: 22px; }

/* ---- Hover & keyboard focus: lift the card, zoom the photo, reveal magnifier */
.lit-card:hover,
.lit-card:focus-visible {
    transform: translateY(-5px);
    box-shadow: 0 10px 24px -6px rgba(60, 45, 20, 0.32), 0 0 0 2px var(--accent);
    z-index: 3;                          /* lift above neighbouring cards */
}
/* Keyboard focus ring: gold + a dark warm halo so it clears WCAG 1.4.11 (3:1)
   against the light paper as well as over photos. */
.lit-card:focus-visible {
    outline: none;
    box-shadow: 0 10px 24px -6px rgba(60, 45, 20, 0.32),
                0 0 0 2px var(--accent),
                0 0 0 5px rgba(58, 44, 18, 0.92);
}
.lit-card:hover .lit-card__img,
.lit-card:focus-visible .lit-card__img { transform: scale(1.06); }
.lit-card:hover::after,
.lit-card:focus-visible::after { background: rgba(255, 255, 255, 0.14); }
.lit-card:hover .lit-card__view,
.lit-card:focus-visible .lit-card__view { opacity: 1; transform: translate(-50%, -50%) scale(1); }

/* ---- Smaller screens: shorter strip, gentler pace ---- */
@media (max-width: 768px) {
    .lit-card { height: clamp(210px, 52vw, 340px); margin-right: var(--sp-3); }
    .lit-card__index { font-size: var(--fs-base); }
    /* Slower on phones so a moving photo is easier to take in and tap. */
    .lit-marquee__track { animation-duration: calc(var(--lit-duration, 50s) * 1.5); }
}

/* ---- Touch devices (no hover): surface the "open" affordance, since the
   magnifier would otherwise only appear on hover ---- */
@media (hover: none) {
    .lit-card__view { opacity: 0.9; transform: translate(-50%, -50%) scale(1); }
}

/* ---- Reduced motion: stop the scroll, offer a manual swipe-strip, drop the
   duplicate (clone) set, and hide the now-pointless pause button. ---- */
@media (prefers-reduced-motion: reduce) {
    .lit-marquee__viewport {
        overflow-x: auto;
        -webkit-mask-image: none;
                mask-image: none;
    }
    .lit-marquee__track { animation: none; }
    .lit-card--clone    { display: none; }
    .lit-marquee__pause { display: none; }
    .lit-book__gutter   { display: none; }   /* the fold reads as a crease only while photos glide; static, it's just a smudge */
}

/* ----- Forms ----- */
.form-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--sp-4);
}

.form-field { display: flex; flex-direction: column; gap: var(--sp-2); }
.form-field.full { grid-column: 1 / -1; }

.form-field label {
    font-size: var(--fs-xs);
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: var(--text-dark-mut);
    font-weight: 600;
}
.section-dark .form-field label { color: var(--text-muted); }

.form-field input,
.form-field textarea,
.form-field select {
    width: 100%;
    padding: var(--sp-3) var(--sp-4);
    background: var(--bg-light);
    border: 1px solid var(--border-light);
    border-radius: var(--radius-sm);
    color: var(--text-dark);
    transition: border-color var(--t-fast) var(--ease);
}
.section-dark .form-field input,
.section-dark .form-field textarea,
.section-dark .form-field select {
    background: var(--bg-card);
    border-color: var(--border);
    color: var(--text);
}

.form-field input:focus,
.form-field textarea:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(201, 169, 97, 0.15);
}

.form-field textarea {
    min-height: 160px;
    resize: vertical;
    font-family: inherit;
}

.form-error {
    color: #e57373;
    font-size: var(--fs-sm);
    margin-top: var(--sp-2);
}

/* The confirmation is the single most important sentence on the contact page,
   and at #4caf50 on its own 10% tint it measured 2.53:1 — the least legible
   text on the screen. #2e7d32 on the same tint is 4.67:1. */
.form-success {
    background: rgba(76, 175, 80, 0.1);
    border: 1px solid rgba(76, 175, 80, 0.3);
    color: #2e7d32;
    padding: var(--sp-4);
    border-radius: var(--radius);
    margin-bottom: var(--sp-4);
}

/* Same problem as .form-success: #e57373 measured 2.63:1, #c62828 is 4.96:1. */
.form-alert {
    background: rgba(229, 115, 115, 0.1);
    border: 1px solid rgba(229, 115, 115, 0.3);
    color: #c62828;
    padding: var(--sp-4);
    border-radius: var(--radius);
    margin-bottom: var(--sp-4);
}

/* ----- CTA band ----- */
.cta-band {
    background: var(--bg);
    color: var(--text);
    padding: var(--sp-8) 0;
    border-top: 1px solid var(--border);
}
.cta-band-inner {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--sp-6);
    align-items: center;
}
.cta-text .section-title { color: var(--text); margin-bottom: var(--sp-2); }

/* The subscribe band is the one place these status messages sit on a DARK
   surface, so the light-surface greens/reds set on .form-success/.form-alert
   would be near-invisible here. The original brighter pair measures 6.4:1 and
   6.0:1 against this background, so restore them for this context only. */
.cta-band .form-success { color: #4caf50; }
.cta-band .form-alert   { color: #e57373; }
.cta-text .muted { color: var(--text-muted); }

.subscribe-form {
    display: flex;
    gap: var(--sp-2);
}
.subscribe-form input[type="email"] {
    flex: 1;
    padding: var(--sp-3) var(--sp-4);
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--text);
}
.subscribe-form input[type="email"]:focus {
    outline: none;
    border-color: var(--accent);
}

/* ----- Footer ----- */
.site-footer {
    background: var(--bg-elev);
    color: var(--text);
    padding: var(--sp-9) 0 0;
    border-top: 1px solid var(--border);
}

/* Brand + three link columns + contact. The link columns carry more than one
   headed group each, so the footer reads as a sitemap of the whole nav rather
   than a short selection. The 1024px and 768px rules below collapse this to
   2 columns and then 1, so the extra track only exists on desktop. */
.footer-grid {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr 1fr 1.5fr;
    gap: var(--sp-7);
    padding-bottom: var(--sp-8);
    border-bottom: 1px solid var(--border);
}

.footer-tagline {
    color: var(--text-muted);
    font-size: var(--fs-sm);
    margin: var(--sp-4) 0;
    max-width: 320px;
}

.footer-heading {
    font-family: var(--font-sans);
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--accent);
    margin-bottom: var(--sp-4);
}

/* Second and later groups stacked in the same column need air above them,
   otherwise the heading sits flush against the previous group's last link. */
.footer-links + .footer-heading { margin-top: var(--sp-5); }

.footer-links li     { margin-bottom: var(--sp-2); }
.footer-links a      { color: var(--text-muted); font-size: var(--fs-sm); transition: color var(--t-fast); }
.footer-links a:hover{ color: var(--accent); }

.contact-list li {
    margin-bottom: var(--sp-3);
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.contact-label {
    font-size: var(--fs-xs);
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: var(--text-dim);
}
.contact-list a { color: var(--text); font-size: var(--fs-sm); }
.contact-list a:hover { color: var(--accent); }

/* ----- Contact page: details + enquiry panel -----------------------------
   Details on the left, the form raised on its own panel to the right. The
   column widths live here rather than inline on the element: an inline
   grid-template-columns outranks the stacking rule in responsive.css and
   would hold two cramped columns on a phone. */
.contact-layout {
    display: grid;
    grid-template-columns: 1fr 1.15fr;
    gap: var(--sp-8);
    align-items: start;
}

.contact-cards {
    list-style: none;
    display: grid;
    gap: var(--sp-4);
    margin-top: var(--sp-6);
}

/* One detail per card: a gold chip, a tracked label, then the value(s). */
.contact-card {
    display: flex;
    align-items: flex-start;
    gap: var(--sp-4);
    padding: var(--sp-5);
    background: #fff;
    border: 1px solid var(--border-light);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    transition: border-color var(--t-med) var(--ease),
                box-shadow var(--t-med) var(--ease),
                transform var(--t-med) var(--ease);
}
.contact-card:hover {
    border-color: var(--accent);
    box-shadow: var(--shadow-md);
    transform: translateY(-3px);
}

.contact-card__icon {
    flex: none;
    width: 46px; height: 46px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: var(--gradient-gold);
    color: var(--bg);
}
.contact-card__icon svg { width: 21px; height: 21px; }

.contact-card__body {
    display: flex;
    flex-direction: column;
    gap: var(--sp-1);
    min-width: 0;          /* lets the long addresses wrap instead of stretching the card */
}

.contact-card__label {
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: var(--text-dark-mut);
    margin-bottom: var(--sp-1);
}

.contact-card__value {
    color: var(--text-dark);
    overflow-wrap: anywhere;   /* an email is one long unbreakable word on narrow screens */
    transition: color var(--t-fast) var(--ease);
}
.contact-card__value:hover { color: var(--accent-deep); }

/* The form sits on a raised white panel with a gold hairline along its top
   edge, so it reads as the page's primary action rather than a second column
   of text. White on the cream .section-light band gives the lift its edge. */
.contact-panel {
    position: relative;
    padding: var(--sp-7);
    background: #fff;
    border: 1px solid var(--border-light);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
    overflow: hidden;
}
.contact-panel::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 3px;
    background: var(--gradient-gold);
}

.contact-panel__title {
    font-size: var(--fs-xl);
    margin: var(--sp-2) 0 var(--sp-5);
}

.contact-panel__submit {
    width: 100%;
    justify-content: center;
    margin-top: var(--sp-5);
}

/* ----- Contact: follow tiles -----
   Two columns of named profile tiles closing out the details column. They
   borrow the .contact-card treatment — white, hairline border, lift and gold
   edge on hover — so the whole left column reads as one set rather than cards
   plus a stray icon row. */
.contact-follow { margin-top: var(--sp-6); }
.contact-follow__label { display: block; margin-bottom: var(--sp-4); }

.social-tiles {
    list-style: none;
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--sp-3);
}

.social-tile {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    height: 100%;                 /* equal-height tiles when one caption wraps */
    padding: var(--sp-4);
    background: #fff;
    border: 1px solid var(--border-light);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    transition: border-color var(--t-med) var(--ease),
                box-shadow var(--t-med) var(--ease),
                transform var(--t-med) var(--ease);
}
.social-tile:hover,
.social-tile:focus-visible {
    border-color: var(--accent);
    box-shadow: var(--shadow-md);
    transform: translateY(-3px);
    outline: none;
}

/* Chip rests in pale gold and fills with the full gradient on hover — the same
   reveal the header/footer icon buttons use, in this section's light palette. */
.social-tile__icon {
    flex: none;
    width: 36px; height: 36px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: var(--accent-pale);
    color: var(--accent-deep);
    transition: background var(--t-med) var(--ease),
                color var(--t-med) var(--ease);
}
.social-tile__icon svg { width: 16px; height: 16px; }
.social-tile:hover .social-tile__icon,
.social-tile:focus-visible .social-tile__icon {
    background: var(--gradient-gold);
    color: var(--bg);
}

.social-tile__body {
    display: flex;
    flex-direction: column;
    min-width: 0;                 /* lets the caption ellipsis instead of pushing the tile wide */
}
.social-tile__name {
    color: var(--text-dark);
    font-size: var(--fs-sm);
    font-weight: 600;
    line-height: 1.3;
}
.social-tile__meta {
    color: var(--text-dark-mut);
    font-size: var(--fs-xs);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.social-icons {
    display: flex;
    gap: var(--sp-3);
    flex-wrap: wrap;
}
.social-icons a {
    width: 40px; height: 40px;
    display: grid; place-items: center;
    background: var(--bg-card);
    color: var(--text-muted);
    border-radius: 50%;
    transition: all var(--t-med) var(--ease);
    border: 1px solid var(--border);
}
.social-icons a:hover {
    background: var(--accent);
    color: var(--bg);
    border-color: var(--accent);
    transform: translateY(-2px);
}
.social-icons svg { width: 16px; height: 16px; }

.footer-bottom {
    padding: var(--sp-5) 0;
}
.footer-bottom-inner {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--sp-4);
    flex-wrap: wrap;
}
.footer-bottom .muted { color: var(--text-dim); font-size: var(--fs-xs); letter-spacing: 0.1em; }

/* ----- Scroll-to-top ----- */
.scroll-top {
    position: fixed;
    bottom: var(--sp-6);
    right: var(--sp-6);
    width: 48px; height: 48px;
    display: grid; place-items: center;
    background: var(--accent);
    color: var(--bg);
    border-radius: 50%;
    opacity: 0;
    visibility: hidden;
    transform: translateY(20px);
    transition: all var(--t-med) var(--ease);
    z-index: 90;
    box-shadow: var(--shadow-md);
}
.scroll-top svg { width: 22px; height: 22px; }
.scroll-top:hover { background: var(--accent-hover); transform: translateY(-4px); }
.scroll-top.visible {
    opacity: 1; visibility: visible; transform: translateY(0);
}

/* ----- Reveal-on-scroll ----- */
.reveal {
    opacity: 0;
    transform: translateY(30px);
    transition: opacity var(--t-slow) var(--ease), transform var(--t-slow) var(--ease);
}
.reveal.visible {
    opacity: 1;
    transform: translateY(0);
}

/* ----- Lightbox overlay (custom) ----- */
.lightbox {
    position: fixed;
    inset: 0;
    background: rgba(10, 10, 10, 0.95);
    display: none;
    z-index: 200;
    align-items: center;
    justify-content: center;
    padding: var(--sp-5);
}
.lightbox.open { display: flex; }
.lightbox img {
    max-width: 90vw;
    max-height: 85vh;
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    opacity: 0;
    transition: opacity var(--t-med) var(--ease);
}
.lightbox img.loaded { opacity: 1; }
.lightbox-close,
.lightbox-prev,
.lightbox-next {
    position: absolute;
    background: rgba(255,255,255,.1);
    color: #fff;
    width: 48px; height: 48px;
    display: grid; place-items: center;
    border-radius: 50%;
    cursor: pointer;
    transition: background var(--t-fast);
}
.lightbox-close { top: var(--sp-5); right: var(--sp-5); }
.lightbox-prev  { left: var(--sp-5);  top: 50%; transform: translateY(-50%); }
.lightbox-next  { right: var(--sp-5); top: 50%; transform: translateY(-50%); }
.lightbox-close:hover,
.lightbox-prev:hover,
.lightbox-next:hover { background: var(--accent); color: var(--bg); }
.lightbox-counter {
    position: absolute;
    bottom: var(--sp-5);
    left: 50%; transform: translateX(-50%);
    color: var(--text-muted);
    font-size: var(--fs-sm);
    letter-spacing: 0.1em;
}
/* main.js sets .hidden on the arrows and the counter when a lightbox group holds
   only one image. The author `display: grid` above outranks the UA stylesheet's
   [hidden] { display: none }, so without these the buttons would stay visible and
   clickable — the exact dead controls the JS is trying to remove. */
.lightbox-prev[hidden],
.lightbox-next[hidden],
.lightbox-counter[hidden] { display: none; }

/* Prize records on /arts. This list had no rule anywhere, and the global
   `* { margin: 0; padding: 0 }` reset strips list markers' indent, so the two
   entries ran together as a single unbroken block of text with no bullets.
   Same gold tick as the other lists on the site. */
.arts-prizes {
    list-style: none;
    margin: var(--sp-5) 0;
}
.arts-prizes li {
    position: relative;
    padding-left: var(--sp-5);
    margin-bottom: var(--sp-3);
    color: var(--text-dark-mut);
    line-height: 1.7;
}
.arts-prizes li::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0.65em;
    width: 8px;
    height: 2px;
    background: var(--accent);
}
.arts-prizes li:last-child { margin-bottom: 0; }

/* ----- Misc utilities ----- */
.center { text-align: center; }
.mb-0 { margin-bottom: 0 !important; }
.mt-4 { margin-top: var(--sp-4); }
.mt-5 { margin-top: var(--sp-5); }
.mt-7 { margin-top: var(--sp-7); }
.divider {
    width: 80px; height: 2px;
    background: var(--accent);
    margin: var(--sp-4) auto;
    border: 0;
}

/* ==========================================================================
   Family-tree gallery (family.php)
   Photos hang as framed nodes from horizontal branches off a central golden
   trunk, in generationally widening tiers (the tiers are built in PHP). The
   connector lines are pure CSS pseudo-elements, so any number of photos works.
   Tablet/phone collapse lives in responsive.css.
   ========================================================================== */
.ftree {
    --ftree-stem: 2.5rem;                         /* branch-to-photo drop height */
    --ftree-node: clamp(82px, 13vw, 162px);       /* photo node size (larger on desktop) */
    --ftree-line: rgba(168, 136, 69, 0.55);       /* branch / stem colour        */
    position: relative;
    max-width: 1160px;
    margin-inline: auto;
    padding-top: var(--sp-4);
    text-align: center;
}
/* Central trunk */
.ftree::before {
    content: '';
    position: absolute;
    top: 96px;            /* emerges from beneath the crest */
    bottom: 44px;
    left: 50%;
    width: 2px;
    transform: translateX(-50%);
    background: linear-gradient(180deg,
        var(--accent-deep) 0%, var(--accent) 45%, transparent 100%);
    opacity: 0.6;
    z-index: 0;
}
/* A glowing pulse that drifts down the trunk — the tree's "live" heartbeat */
.ftree::after {
    content: '';
    position: absolute;
    left: 50%;
    margin-left: -5px;
    top: 7%;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: radial-gradient(circle,
        rgba(245, 227, 184, 0.95) 0%, rgba(201, 169, 97, 0.45) 55%, transparent 72%);
    filter: blur(0.5px);
    pointer-events: none;
    z-index: 0;
    animation: ftree-orb 6s ease-in-out infinite;
}
/* Root crest — a portrait medallion the tree grows from. The gradient behind
   the photo shows while it loads and rims the frame with a warm glow. */
.ftree__crest {
    position: relative;
    z-index: 2;
    width: clamp(132px, 16vw, 184px);
    aspect-ratio: 1;
    margin: 0 auto var(--sp-6);
    display: grid;
    place-items: center;
    overflow: hidden;
    border-radius: var(--radius-lg);   /* squared off to match the tree's photo nodes */
    background:
        radial-gradient(circle at 50% 36%, rgba(201, 169, 97, 0.20), transparent 70%),
        var(--bg-card);
    border: 3px solid var(--accent);
    box-shadow: 0 0 0 6px rgba(201, 169, 97, 0.10), var(--shadow-md);
    animation: ftree-crest 4.5s ease-in-out infinite;
}
/* Cropped to the circle. The subject sits high in the frame, so the crop is
   biased upward to keep the head clear of the ring rather than centring on
   the shoulders. */
.ftree__crest-img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center 22%;
    border-radius: var(--radius-lg);
}
/* Tier (one branch of the tree) */
.ftree__tier {
    position: relative;
    z-index: 1;
    margin-bottom: var(--sp-7);
}
.ftree__tier:last-child { margin-bottom: 0; }
/* Row of photos hanging from a branch */
.ftree__row {
    position: relative;
    width: fit-content;
    max-width: 100%;
    margin: var(--ftree-stem) auto 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-wrap: nowrap;
    justify-content: center;
    align-items: flex-start;
    gap: clamp(var(--sp-3), 2vw, var(--sp-5));
}
/* Horizontal branch bus */
.ftree__row::before {
    content: '';
    position: absolute;
    top: calc(var(--ftree-stem) * -1);
    left: 0;
    right: 0;
    height: 2px;
    background: var(--ftree-line);
    z-index: 0;
}
/* Hide the bus for a lone photo (no siblings to bridge) */
.ftree__row:has(> .ftree__node:only-child)::before { display: none; }
/* Junction where the branch meets the trunk */
.ftree__row::after {
    content: '';
    position: absolute;
    top: calc(var(--ftree-stem) * -1);
    left: 50%;
    width: 11px;
    height: 11px;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 0 4px rgba(201, 169, 97, 0.15);
    z-index: 1;
    animation: ftree-pulse 3s ease-in-out infinite;
}
.ftree__node {
    position: relative;
    width: var(--ftree-node);
    list-style: none;
    transform-origin: top center;   /* swing from where the stem meets the branch */
    animation: ftree-sway var(--sway-dur, 5s) ease-in-out var(--sway-delay, 0s) infinite;
    will-change: transform;
}
.ftree__node:hover { animation-play-state: paused; }   /* settle the photo on hover */
/* Drop stem from the branch down to each photo */
.ftree__node::before {
    content: '';
    position: absolute;
    top: calc(var(--ftree-stem) * -1);
    left: 50%;
    width: 2px;
    height: var(--ftree-stem);
    transform: translateX(-50%);
    background: var(--ftree-line);
    z-index: 0;
}
/* Framed photo node (also carries .gallery-item for the shared lightbox) */
.ftree__photo {
    display: block;
    width: 100%;
    aspect-ratio: 1;
    border-radius: var(--radius-lg);
    border: 3px solid rgba(201, 169, 97, 0.40);
    box-shadow: var(--shadow-sm);
    transition: transform var(--t-med) var(--ease),
                border-color var(--t-med) var(--ease),
                box-shadow var(--t-med) var(--ease);
}
.ftree__photo:hover {
    transform: translateY(-6px);
    border-color: var(--accent);
    box-shadow: var(--shadow-lg);
}

/* ----- Family-tree "live" ambient animation -----
   Hanging photos sway, branch joints pulse, a glow drifts down the trunk, and
   the crest softly breathes. Every keyframe rests at its neutral state at
   0%/100%, so prefers-reduced-motion (responsive.css) freezes it cleanly. */
@keyframes ftree-sway {
    0%, 100% { transform: rotate(0deg); }
    25%      { transform: rotate(calc(var(--sway-amp, 1.1) *  1deg)); }
    75%      { transform: rotate(calc(var(--sway-amp, 1.1) * -1deg)); }
}
@keyframes ftree-pulse {
    0%, 100% { box-shadow: 0 0 0 4px rgba(201, 169, 97, 0.15); }
    50%      { box-shadow: 0 0 0 9px rgba(201, 169, 97, 0.03); }
}
@keyframes ftree-crest {
    0%, 100% { box-shadow: 0 0 0 6px rgba(201, 169, 97, 0.10), var(--shadow-md); }
    50%      { box-shadow: 0 0 0 11px rgba(201, 169, 97, 0.05),
                           0 0 28px rgba(201, 169, 97, 0.30), var(--shadow-md); }
}
@keyframes ftree-orb {
    0%   { top: 7%;  opacity: 0; }
    12%  { opacity: 1; }
    88%  { opacity: 1; }
    100% { top: 93%; opacity: 0; }
}
/* Offset alternating joints so they don't all pulse in unison */
.ftree__tier:nth-child(even) .ftree__row::after { animation-delay: -1.5s; }

/* ==========================================================================
   Expanding-panel gallery (orator.php)
   A row of photo panels: hovering one smoothly widens it while its neighbours
   compress and dim, and a caption + zoom reveal on the active panel. Panels
   stagger-fade in on scroll. Touch / small screens fall back to a tidy tile
   grid (see responsive.css). Each panel opens in the shared lightbox.
   ========================================================================== */
.xgallery {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
}
.xrow {
    display: flex;
    gap: var(--sp-3);
    height: clamp(240px, 30vw, 380px);
}
.xpanel {
    position: relative;
    flex: 1 1 0;
    min-width: 0;
    overflow: hidden;
    border-radius: var(--radius-lg);
    background: var(--bg-card);
    cursor: pointer;
    box-shadow: var(--shadow-sm);
    transition: flex-grow var(--t-slow) var(--ease), box-shadow var(--t-med) var(--ease);
}
.xpanel img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform var(--t-slow) var(--ease), filter var(--t-med) var(--ease);
}
.xpanel::after {                 /* legibility veil for the caption */
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    background: linear-gradient(180deg, rgba(10, 10, 10, 0), rgba(10, 10, 10, 0));
    transition: background var(--t-med) var(--ease);
}
.xpanel__cap {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    z-index: 2;
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-5);
    opacity: 0;
    transform: translateY(12px);
    transition: opacity var(--t-med) var(--ease), transform var(--t-med) var(--ease);
    pointer-events: none;
}
.xpanel__cap::before {           /* short gold accent bar */
    content: '';
    flex: none;
    width: 28px; height: 2px;
    background: var(--accent);
}
.xpanel__no {
    font-family: var(--font-display);
    font-size: var(--fs-2xl);
    line-height: 1;
    color: #fff;
    letter-spacing: 0.02em;
}

/* ---- Accordion + reveal interactions on pointer (desktop) devices ---- */
@media (hover: hover) {
    .xrow:hover .xpanel        { flex-grow: 0.75; }                       /* neighbours compress */
    .xrow .xpanel:hover        { flex-grow: 3; box-shadow: var(--shadow-lg); }  /* hovered expands */
    .xrow:hover .xpanel img    { filter: brightness(0.55) saturate(0.8); }      /* neighbours dim   */
    .xrow .xpanel:hover img    { filter: none; transform: scale(1.06); }        /* hovered pops     */
    .xpanel:hover::after       { background: linear-gradient(180deg, rgba(10,10,10,0) 45%, rgba(10,10,10,0.65)); }
    .xpanel:hover .xpanel__cap { opacity: 1; transform: translateY(0); }
}
/* Touch devices: no hover, so keep captions + veil visible as an affordance */
@media (hover: none) {
    .xpanel::after       { background: linear-gradient(180deg, rgba(10,10,10,0) 55%, rgba(10,10,10,0.55)); }
    .xpanel__cap         { opacity: 1; transform: none; }
}

/* ---- Staggered entrance (reuses the .reveal IntersectionObserver) ---- */
.xrow.reveal     { transform: none; }   /* animate panels individually, not the row block */
.xrow .xpanel    { opacity: 0; }
.xrow.visible .xpanel              { animation: xpanel-in 0.6s var(--ease) both; }
.xrow.visible .xpanel:nth-child(1) { animation-delay: 0s; }
.xrow.visible .xpanel:nth-child(2) { animation-delay: 0.08s; }
.xrow.visible .xpanel:nth-child(3) { animation-delay: 0.16s; }
.xrow.visible .xpanel:nth-child(4) { animation-delay: 0.24s; }
.xrow.visible .xpanel:nth-child(5) { animation-delay: 0.32s; }
@keyframes xpanel-in {
    from { opacity: 0; transform: translateY(26px) scale(0.95); }
    to   { opacity: 1; transform: none; }
}

/* ==========================================================================
   Prize showcase — student-life record (Acting & Elocution).
   Tabbed disciplines (only one shown at a time → far less scrolling) over a
   responsive grid of medal-coloured prize cards. Data from the legacy
   Prizes.html. Tabs are JS-enhanced; panels toggle via the [hidden] attribute.
   ========================================================================== */
.prize-tabs { max-width: 1120px; margin: 0 auto; text-align: center; }

/* ----- Tab bar (pill toggle) ----- */
.prize-tablist {
    display: inline-flex;
    gap: var(--sp-2);
    padding: var(--sp-2);
    margin: 0 auto var(--sp-8);
    background: rgba(0, 0, 0, 0.04);
    border: 1px solid var(--border-light);
    border-radius: 999px;
}
.prize-tab {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-4) var(--sp-7);
    border-radius: 999px;
    font-family: var(--font-sans);
    font-size: var(--fs-lg);
    font-weight: 700;
    letter-spacing: 0.02em;
    color: var(--text-dark-mut);
    cursor: pointer;
    transition: color var(--t-fast) var(--ease),
                background var(--t-fast) var(--ease),
                box-shadow var(--t-fast) var(--ease),
                transform var(--t-fast) var(--ease);
}
.prize-tab:not([aria-selected="true"]):hover {
    color: var(--text-dark);
    background: rgba(0, 0, 0, 0.05);
}
.prize-tab__icon {
    display: inline-flex;
    width: 28px;
    height: 28px;
    flex: none;
    opacity: 0.85;
    transition: transform var(--t-fast) var(--ease), opacity var(--t-fast) var(--ease);
}
.prize-tab__icon svg { width: 100%; height: 100%; }
.prize-tab:hover .prize-tab__icon { opacity: 1; }
.prize-tab[aria-selected="true"] .prize-tab__icon {
    opacity: 1;
    transform: scale(1.08);
}
.prize-tab__count {
    font-size: var(--fs-sm);
    font-weight: 700;
    padding: 2px 11px;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.06);
    color: var(--text-dark-mut);
    transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.prize-tab[aria-selected="true"] {
    color: var(--bg);
    background: var(--gradient-gold);
    box-shadow: var(--shadow-md);
}
.prize-tab[aria-selected="true"] .prize-tab__count {
    background: rgba(0, 0, 0, 0.20);
    color: #fff;
}
.prize-tab:focus-visible { outline: 2px solid var(--accent-deep); outline-offset: 2px; }

/* ----- Panels ----- */
.prize-panel { text-align: left; }
.prize-panel[hidden] { display: none; }
.prize-panel:not([hidden]) { animation: prize-fade var(--t-med) var(--ease) both; }
@keyframes prize-fade {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: none; }
}
.prize-panel__sub {
    text-align: center;
    color: var(--text-dark-mut);
    font-style: italic;
    font-size: var(--fs-sm);
    margin: 0 0 var(--sp-6);
}

/* ----- Card grid ----- */
.prize-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
    gap: var(--sp-4);
}

.medal-defs { position: absolute; width: 0; height: 0; overflow: hidden; }

.pcard {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: var(--sp-4);
    padding: var(--sp-5);
    background: #fff;
    border: 1px solid var(--border-light);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    transition: transform var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.pcard:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }

/* 3D medal — domed disc + ribbon, lifted off the card with a drop shadow */
.pcard__medal {
    flex: none;
    width: 46px;
    height: 48px;
    margin-top: 2px;
    filter: drop-shadow(0 3px 3px rgba(0, 0, 0, 0.28));
    transition: transform var(--t-med) var(--ease);
}
.pcard:hover .pcard__medal { transform: translateY(-1px) rotate(-5deg) scale(1.06); }

.pcard__body {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}
.pcard__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--sp-1) var(--sp-3);
}
.pcard__rank {
    font-family: var(--font-sans);
    font-size: var(--fs-xs);
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--medal-ink, var(--accent-deep));
}
.pcard__date {
    font-size: var(--fs-xs);
    color: var(--text-dark-mut);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.pcard__item {
    font-family: var(--font-serif);
    font-size: var(--fs-lg);
    line-height: 1.2;
    margin: 0;
    color: var(--text-dark);
}
.pcard__venue {
    font-size: var(--fs-sm);
    line-height: 1.5;
    color: var(--text-dark-mut);
    margin: 0;
}

/* Medal palette per rank — drives the stripe (--medal) + rank label (--medal-ink) */
.pcard--first  { --medal: #c9a961; --medal-ink: #9c7d2e; }   /* gold   */
.pcard--second { --medal: #9aa3ad; --medal-ink: #6b7280; }   /* silver */
.pcard--third  { --medal: #c08457; --medal-ink: #9c5a32; }   /* bronze */
.pcard--other  { --medal: #b9b3a6; --medal-ink: #7c766a; }   /* camp participation, etc. */

/* ----- Kalaprathibha championship feature card (spans the whole grid) ----- */
.prize-feature {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    gap: var(--sp-4);
    padding: var(--sp-5) var(--sp-6);
    background: var(--gradient-gold-soft);
    border: 1px solid var(--accent);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}
.prize-feature__icon { flex: none; width: 34px; height: 34px; color: var(--accent-deep); }
.prize-feature__text {
    margin: 0;
    font-family: var(--font-serif);
    font-size: var(--fs-md);
    font-weight: 500;
    line-height: 1.4;
    color: #5a4a22;
}

@media (max-width: 600px) {
    .prize-tablist { display: flex; width: 100%; }
    .prize-tab {
        flex: 1;
        justify-content: center;
        gap: var(--sp-2);
        padding: var(--sp-3) var(--sp-2);
        font-size: var(--fs-base);
    }
    .prize-tab__icon { width: 22px; height: 22px; }
    .prize-tab__count { font-size: var(--fs-xs); padding: 1px 8px; }
    .prize-feature { flex-direction: column; text-align: center; gap: var(--sp-3); }
}
