@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal; font-weight: 500; font-display: swap;
  src: url(fonts/cormorant-garamond-500.woff2) format('woff2');
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal; font-weight: 600; font-display: swap;
  src: url(fonts/cormorant-garamond-600.woff2) format('woff2');
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: italic; font-weight: 500; font-display: swap;
  src: url(fonts/cormorant-garamond-500-italic.woff2) format('woff2');
}
@font-face {
  font-family: 'Caveat';
  font-style: normal; font-weight: 400; font-display: swap;
  src: url(fonts/caveat-400.woff2) format('woff2');
}

:root {
  /* The page handles both themes itself (see the blocks below). Without this,
     Chrome's auto dark mode force-darkens it and strips the nav/scrim backgrounds. */
  color-scheme: light dark;

  --laterite: #8B3A1F;
  --sal: #2D3B26;
  --turmeric: #C8842B;
  --ash: #E8E1D4;
  --indigo: #1F2A3A;

  --text-paper: #23303f;
  --text-muted: #5a5347;
  --panel-bg: rgba(238, 233, 220, 0.86);
  --panel-border: rgba(139, 58, 31, 0.22);
  --accent: var(--laterite);
  --band-bg: var(--ash);

  --font-display: 'Cormorant Garamond', Georgia, 'Palatino Linotype', serif;
  --font-body: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --font-accent: 'Caveat', 'Segoe Script', cursive;

  --text-sm: 0.875rem;
  --text-base: 1.0625rem;
  --text-lg: 1.375rem;
  --text-xl: 1.85rem;
  --text-2xl: clamp(1.6rem, 4vw, 2.4rem);
  --text-3xl: clamp(2.1rem, 5.5vw, 3.4rem);
  --text-hero: clamp(3rem, 11vw, 7rem);

  --content-pad: clamp(1.25rem, 5vw, 3rem);
  --measure: 60ch;

  /* Scrim laid over the backdrop photograph. Light by default so light-mode ink
     has a light ground; the dark block below swaps in the near-black one. */
  --scrim: linear-gradient(rgba(232,225,212,.55), rgba(232,225,212,.65));
}

@media (prefers-color-scheme: dark) {
  :root {
    --text-paper: #E8E1D4;
    --text-muted: #a89c88;
    --panel-bg: rgba(20, 28, 40, 0.82);
    --panel-border: rgba(200, 132, 43, 0.28);
    --accent: var(--turmeric);
    --band-bg: #241C15;
    --scrim: linear-gradient(rgba(10,14,12,.86), rgba(10,14,12,.92));
  }
}

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

html { -webkit-text-size-adjust: 100%; }
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.72;
  color: var(--text-paper);
  background: #0e131f;
  /* clip, not hidden: `overflow-x: hidden` turns body into the scroll container,
     which freezes window.scrollY and kills the parallax, progress bar and nav state. */
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
}

/* --- Living landscape canvas --- */
/* Page backdrop. Replaces the old drawn-hills canvas: every section below the
   header sits on a real photograph of the place, held still and pushed far back
   so it reads as ground rather than as an image. The photograph is attached per
   body class at the bottom of this file; the scrim over it is --scrim. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 0;
  /* The photograph itself is attached per page at the bottom of this file. */
  background-image: var(--scrim);
  background-size: cover;
  background-position: center;
  filter: blur(3px);
  transform: scale(1.04);   /* hides the blur's soft edge */
}

/* --- Grain --- */
.grain {
  position: fixed;
  inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
  opacity: 0.04;
  pointer-events: none;
  z-index: 9998;
  mix-blend-mode: overlay;
}

.progress-bar {
  position: fixed;
  top: 0; left: 0;
  height: 3px; width: 0%;
  background: var(--turmeric);
  z-index: 10000;
  transition: width 90ms linear;
}

main { position: relative; z-index: 1; }

/* --- Typography helpers --- */
.display { font-family: var(--font-display); }
.accent-font { font-family: var(--font-accent); }

h1, h2 { font-family: var(--font-display); line-height: 1.12; text-wrap: balance; font-weight: 600; }
p + p { margin-top: 1.4em; }

/* ==================== HERO ==================== */
.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  align-items: stretch;
  overflow: hidden;
  color: var(--ash);
  /* No background here: the animated landscape canvas shows through by default. */
}
.hero.has-photo {
  background: url("hero.jpg") center 55% / cover no-repeat;
}
/* Art direction, not just a smaller file. The landscape frame is 1.96:1, so a
   390px phone shows 29% of its width — and because the photograph is more than
   half sky, that slice is mostly flat grey. The road, the cyclist and the mist on
   the hills never appear. hero-portrait.jpg is a tall crop of the same frame
   through the part that matters. background-position cannot do this: at phone
   width the full height already fits, so there is no vertical crop to move. */
@media (max-aspect-ratio: 1/1) and (max-width: 820px) {
  .hero.has-photo {
    background-image: url("hero-portrait.jpg");
    background-position: center center;
  }
}
/* Scrim. Darkens top and bottom for the nav and the scroll cue, and pulls a soft
   pool of shadow through the middle so the centred wordmark stays legible. */
.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* This is an overcast monsoon frame — the sky is near-white, so the scrim has to
     work much harder than it would over a dark photograph. */
  background:
    radial-gradient(ellipse 62% 38% at 50% 44%, rgba(10,14,12,.52), rgba(10,14,12,.16) 70%, transparent 100%),
    linear-gradient(to bottom, rgba(10,14,12,.60) 0%, rgba(10,14,12,.14) 20%, rgba(10,14,12,.16) 58%, rgba(10,14,12,.68) 100%),
    linear-gradient(to top, rgba(139,58,31,.20), transparent 38%);
}

.hero-inner {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
  padding: clamp(6.5rem, 15vh, 9.5rem) var(--content-pad) clamp(6rem, 14vh, 8rem);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
}

.hero-kicker {
  font-family: var(--font-body);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(245, 239, 228, 0.82);
  margin-bottom: 1.1rem;
  text-shadow: 0 2px 14px rgba(0,0,0,0.6);
}

.wordmark {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-hero);
  line-height: 0.94;
  letter-spacing: -0.015em;
  text-shadow: 0 4px 40px rgba(0,0,0,0.55), 0 2px 8px rgba(0,0,0,0.5);
}

.hero-lede {
  margin-top: 1.5rem;
  max-width: 46ch;
  margin-inline: auto;
  font-size: clamp(1.05rem, 1.6vw, 1.3rem);
  line-height: 1.6;
  color: rgba(245, 239, 228, 0.92);
  text-shadow: 0 2px 18px rgba(0,0,0,0.6);
}

/* Scroll cue — anchored to .hero, not .hero-inner, so centring the lockup
   does not drag it up off the bottom edge. */
.scroll-cue {
  position: absolute;
  z-index: 1;
  left: 50%;
  transform: translateX(-50%);
  bottom: clamp(1.5rem, 4vh, 2.6rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.7rem;
  padding: 0.5rem 0.75rem;
  color: rgba(245, 239, 228, 0.86);
  text-decoration: none;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  text-shadow: 0 2px 12px rgba(0,0,0,0.6);
  transition: color 0.2s ease;
}
.scroll-cue:hover { color: var(--turmeric); }
.scroll-chevron {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  animation: bob 2.4s ease-in-out infinite;
}
@keyframes bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(6px); }
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 2rem;
}
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 0.8rem 1.6rem;
  border-radius: 3px;
  border: 1px solid transparent;
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  transition: transform 0.2s ease, background 0.2s ease;
}
.btn.primary { background: var(--turmeric); color: var(--indigo); }
.btn.secondary { color: var(--ash); border-color: rgba(245, 239, 228, 0.55); }
.btn:hover { transform: translateY(-2px); }
.btn.primary:hover { background: #d9964a; }

/* ==================== STATUS BAND ====================
   The honest state of the project, on a solid surface directly under the photo.
   Two tokens carry the whole light/dark flip — nothing else in here is themed. */
.status-band {
  --band-ink: var(--text-paper);
  position: relative;
  z-index: 1;
  background: var(--band-bg);
  color: var(--band-ink);
  padding: clamp(2.75rem, 7vw, 4.5rem) 0 clamp(2.25rem, 5vw, 3.25rem);
}
.status-inner {
  max-width: 1180px;
  margin: 0 auto;
  padding-inline: var(--content-pad);
}
.status-lead {
  max-width: 46ch;
  font-family: var(--font-display);
  font-size: var(--text-xl);
  line-height: 1.35;
  margin-bottom: clamp(1.75rem, 4vw, 2.5rem);
}
.hero-ledger {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  border-top: 1px solid color-mix(in srgb, var(--band-ink) 26%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--band-ink) 14%, transparent);
}
.ledger-item {
  padding: 1.15rem 1.35rem 1.1rem 0;
  border-right: 1px solid color-mix(in srgb, var(--band-ink) 14%, transparent);
}
.ledger-item:last-child { border-right: 0; }
.ledger-item span {
  display: block;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--band-ink) 62%, transparent);
}
.ledger-item strong {
  display: block;
  margin-top: 0.55rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.35rem, 2.3vw, 2rem);
  line-height: 1;
  color: var(--accent);
}
.ledger-item small {
  display: block;
  margin-top: 0.55rem;
  font-size: 0.78rem;
  line-height: 1.45;
  color: color-mix(in srgb, var(--band-ink) 78%, transparent);
}
/* Buttons that used to live in the hero. On the band they sit on a solid
   surface, so .btn.secondary needs ink borders rather than the ash ones. */
.status-band .hero-actions { margin-top: clamp(1.75rem, 4vw, 2.25rem); }
.status-band .btn.secondary {
  color: var(--band-ink);
  border-color: color-mix(in srgb, var(--band-ink) 42%, transparent);
}
.status-band .btn.secondary:hover {
  border-color: color-mix(in srgb, var(--band-ink) 75%, transparent);
}

/* ==================== NOTES (side-by-side, click to open) ====================
   Plain <details>. No JS, no accordion library — the browser already does this. */
.notes {
  position: relative;
  z-index: 1;
  max-width: 1100px;
  margin: 0 auto;
  padding: clamp(3rem, 8vw, 5.5rem) var(--content-pad);
}
.notes-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 1rem;
  align-items: start;
}
.note {
  background: var(--panel-bg);
  backdrop-filter: blur(10px) saturate(1.15);
  -webkit-backdrop-filter: blur(10px) saturate(1.15);
  border: 1px solid var(--panel-border);
  border-left: 3px solid var(--accent);
  border-radius: 3px;
  box-shadow: 0 24px 50px -30px rgba(0,0,0,0.6);
  color: var(--text-paper);
}
.note > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.35rem 1.4rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-lg);
  line-height: 1.25;
}
.note > summary::-webkit-details-marker { display: none; }
.note > summary::after {
  content: '+';
  flex: 0 0 auto;
  color: var(--accent);
  font-size: 1.4rem;
  line-height: 1;
}
.note[open] > summary::after { content: '\2013'; }
.note > summary:hover { color: var(--accent); }
.note-body { padding: 0 1.4rem 1.5rem; }
.note-body p + p { margin-top: 1em; }
.note-body em { font-style: italic; }
.note.soon { border-left-color: var(--text-muted); }
.note.soon > summary { color: var(--text-muted); }

.eyebrow {
  font-family: var(--font-accent);
  font-size: var(--text-lg);
  color: var(--accent);
  margin-bottom: 1.6rem;
  display: block;
}

/* ==================== MANIFESTO ==================== */
.manifesto {
  position: relative;
  min-height: 92vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: clamp(4rem, 10vh, 8rem) var(--content-pad);
  color: var(--ash);
}
.manifesto::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(ellipse 66% 52% at 50% 48%, rgba(8,10,18,0.5), rgba(8,10,18,0) 74%);
}
.manifesto-line {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-3xl);
  line-height: 1.16;
  text-wrap: balance;
  text-shadow: 0 3px 44px rgba(0,0,0,0.8);
}
.manifesto-body {
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--text-xl);
  line-height: 1.4;
  max-width: 26ch;
  margin: 2rem auto 3.5rem;
  color: #f0e9db;
  text-shadow: 0 2px 30px rgba(0,0,0,0.8);
}
.manifesto-loc {
  font-size: var(--text-sm);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(232,225,212,0.75);
  line-height: 2.1;
  text-shadow: 0 2px 18px rgba(0,0,0,0.85);
}
.manifesto-coords {
  font-family: var(--font-display);
  letter-spacing: 0.16em;
  font-size: var(--text-lg);
  color: rgba(232,225,212,0.6);
  margin-top: 0.6rem;
  text-shadow: 0 2px 18px rgba(0,0,0,0.85);
}
.manifesto-close {
  font-family: var(--font-accent);
  font-size: var(--text-lg);
  color: var(--turmeric);
  margin-top: 2.6rem;
  text-shadow: 0 2px 20px rgba(0,0,0,0.85);
}

/* The photographer's name, under the caption. Quiet, but never absent when the
   manifest carries one — other people in the village shoot for this now. */
.photo-card figcaption .credit {
  display: block;
  margin-top: 0.2rem;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  opacity: 0.6;
}
.photo-card figcaption .credit::before { content: "Photograph: "; }

/* ==================== REVEAL ==================== */
/* Gated on .js, set by a one-line inline script in <head>. Without that gate the
   page hides its own content by default and only JavaScript can bring it back —
   so a slow, blocked or failed script leaves a blank page. Every .reveal element
   is visible by default now; the animation is what gets added, not the content. */
.js .reveal {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity 0.85s cubic-bezier(.2,.6,.2,1) var(--d,0s), transform 0.85s cubic-bezier(.2,.6,.2,1) var(--d,0s);
}
.js .reveal.visible { opacity: 1; transform: none; }

/* An album's photographs are inside a <details> that is closed on load, so they
   have no box for the observer to intersect. Opening it must not leave them at
   opacity 0 if the observer misses the change. */
.js details[open] .reveal { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .js .reveal { opacity: 1; transform: none; transition: none; }
  .scroll-chevron { animation: none; }
  html { scroll-behavior: auto; }
}

:focus-visible { outline: 2px solid var(--turmeric); outline-offset: 3px; }

/* --- Section anchoring under fixed nav --- */
section[id], header[id] { scroll-margin-top: 84px; }

/* --- Persistent site nav --- */
.site-nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 9000;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 0.85rem clamp(1.2rem, 4vw, 2.6rem);
  color: var(--ash);
  background: linear-gradient(to bottom, rgba(31,42,58,.78), rgba(31,42,58,0));
  transition: background .3s ease, border-color .3s ease;
  border-bottom: 1px solid transparent;
}
/* Solid once the hero photo is gone, so links stay legible over pale panels. */
.site-nav.scrolled {
  background: rgba(20, 28, 40, 0.93);
  backdrop-filter: blur(14px) saturate(1.1);
  -webkit-backdrop-filter: blur(14px) saturate(1.1);
  border-bottom-color: rgba(200, 132, 43, 0.22);
}
.brand-mark {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.35rem;
  line-height: 1;
  color: var(--ash);
  text-decoration: none;
  white-space: nowrap;
}
/* Mark is drawn on a 24 viewBox so its strokes land on whole pixels at icon sizes. */
.brand-logo { width: 38px; height: 38px; flex: 0 0 auto; color: var(--ash); }
.brand-logo .sun { fill: var(--turmeric); }
.brand-logo .frame {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.nav-links {
  display: flex;
  align-items: center;
  gap: 1.4rem;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.nav-links::-webkit-scrollbar { display: none; }
.nav-links a {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(245, 239, 228, 0.82);
  text-decoration: none;
  white-space: nowrap;
  padding: 0.35rem 0;
  border-bottom: 1px solid transparent;
  transition: color .2s ease, border-color .2s ease;
}
.nav-links a:hover { color: var(--turmeric); border-color: var(--turmeric); }
.nav-links a.nav-cta { color: var(--turmeric); }

/* --- Mobile menu -----------------------------------------------------------
   Six links need about 418px; a 390px phone gives the strip roughly 316px, so
   the Pilot CTA sat off the edge. The button below replaces the scrolling strip
   with a panel — but only when JS is available to work the aria state. With JS
   off it never appears and the strip stays as it was. */
.nav-toggle { display: none; }

@media (max-width: 768px) {
  .js .nav-toggle {
    display: grid;
    place-items: center;
    width: 44px;                 /* 44px is the minimum comfortable touch target */
    height: 44px;
    margin: -6px -6px -6px 0;
    padding: 0;
    background: none;
    border: 0;
    color: inherit;
    cursor: pointer;
  }
  .nav-toggle .bars { display: block; width: 22px; }
  .nav-toggle .bars i {
    display: block;
    height: 2px;
    background: currentColor;
    border-radius: 2px;
    transition: transform .25s ease, opacity .2s ease;
  }
  .nav-toggle .bars i + i { margin-top: 5px; }

  /* Three lines fold into a cross. Purely cosmetic, so it goes when the visitor
     asked for less motion — the transition, not the state. */
  .nav-toggle[aria-expanded="true"] .bars i:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .nav-toggle[aria-expanded="true"] .bars i:nth-child(2) { opacity: 0; }
  .nav-toggle[aria-expanded="true"] .bars i:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

  .js .nav-links {
    position: absolute;
    top: 100%;
    right: 0;
    left: 0;
    display: grid;
    gap: 0;
    padding: 0.4rem 0 0.6rem;
    background: rgba(20, 28, 40, 0.97);
    backdrop-filter: blur(14px) saturate(1.1);
    -webkit-backdrop-filter: blur(14px) saturate(1.1);
    border-bottom: 1px solid rgba(200, 132, 43, 0.22);
    /* No mask and no horizontal scroll here — every link has its own row now. */
    mask-image: none;
    padding-right: 0;
    overflow: visible;
    /* Collapsed by default. visibility keeps it out of the tab order while shut. */
    visibility: hidden;
    opacity: 0;
    transform: translateY(-6px);
    transition: opacity .22s ease, transform .22s ease, visibility .22s;
  }
  .js .nav-links.open { visibility: visible; opacity: 1; transform: none; }

  .js .nav-links a {
    font-size: 0.8rem;
    letter-spacing: 0.1em;
    padding: 0.85rem clamp(1.2rem, 5vw, 2rem);
    border-bottom: 0;
  }
  .js .nav-links a:hover,
  .js .nav-links a[aria-current="page"] { background: rgba(200, 132, 43, 0.1); }
  .js .nav-links a.nav-cta { color: var(--turmeric); }

  @media (prefers-reduced-motion: reduce) {
    .nav-toggle .bars i,
    .js .nav-links { transition: none; }
  }
}

@media (max-width: 768px) {
  :root {
    --content-pad: 1.2rem;
    --text-hero: clamp(2.5rem, 11vw, 4.5rem);
    --text-3xl: clamp(1.8rem, 7vw, 2.6rem);
    --text-2xl: clamp(1.4rem, 5vw, 2rem);
  }
  html, body, main, section {
    max-width: 100vw;
    overflow-x: clip;
  }
  .wordmark { font-size: clamp(2.6rem, 12vw, 4.2rem); }
  .site-nav { padding: 0.6rem 0.9rem; gap: 0.8rem; }
  .brand-logo { width: 32px; height: 32px; }
  .brand-mark { font-size: 1.1rem; gap: 0.5rem; }
  /* Six items need ~418px and a 390px phone gives the strip ~316px, so it scrolls.
     Without a cue the last link just stops mid-word and reads as a clipping bug.
     Fade the trailing edge, and pad by the same amount so a fully scrolled strip
     leaves the last link (the Pilot CTA) in the opaque part, not under the fade. */
  .nav-links {
    gap: 0.9rem;
    padding-right: 22px;
    mask-image: linear-gradient(to right, #000 calc(100% - 22px), transparent);
  }
  .nav-links a { font-size: 0.66rem; letter-spacing: 0.07em; }
  .hero-ledger { grid-template-columns: repeat(2, 1fr); }
  .ledger-item { padding-right: 1rem; }
  .ledger-item:nth-child(2n) { border-right: 0; }
  .ledger-item:nth-child(n+3) { border-top: 1px solid color-mix(in srgb, var(--band-ink) 14%, transparent); }
}

@media (max-width: 560px) {
  .brand-mark span { display: none; }
  .hero-actions .btn { flex: 1 1 auto; }
}

/* --- Practical guide / how to reach --- */
.guide { position: relative; z-index: 1; }
.guide::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at 50% 40%, rgba(10,15,25,.55), rgba(10,15,25,.15) 70%);
  z-index: -1;
}
.guide-inner {
  max-width: 68ch;
  margin: 0 auto;
  padding: clamp(4rem, 9vw, 7rem) var(--content-pad);
}
/* --- Journey: four drawn steps instead of a map plate --- */
.journey {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.9rem;
  margin: 1.7rem 0 1rem;
}
/* Lives here rather than in the 768px block above, which sits earlier in the file:
   equal specificity, so the four-column rule directly above would win and did —
   step four rendered 60px past the right edge and `overflow-x: clip` ate it. */
@media (max-width: 768px) {
  .journey { grid-template-columns: repeat(2, 1fr); gap: 0.7rem; }
}
.journey-step {
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: 3px;
  padding: 1.1rem 0.9rem 1.2rem;
  text-align: center;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  transition: transform .3s ease, border-color .3s ease;
}
.journey-step:hover { transform: translateY(-3px); border-color: var(--turmeric); }
.journey-num {
  display: block;
  font-size: 0.6rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--text-muted);
  opacity: .75;
}
.journey-ico {
  width: 60px; height: 60px;
  display: block;
  margin: .5rem auto .55rem;
  color: var(--accent);
}
.journey-ico .j-accent { stroke: var(--turmeric); }
.journey-step h3 {
  font-family: var(--font-accent);
  font-weight: 400;
  font-size: 1.3rem;
  color: var(--accent);
  margin-bottom: .25rem;
}
.journey-step p {
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--text-muted);
}
.journey-cap {
  font-size: 0.72rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-muted);
  text-align: center;
  margin: 0 0 2.4rem;
}
.guide-grid { display: grid; gap: 1.8rem; }
.guide-item {
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-left: 3px solid var(--accent);
  border-radius: 3px;
  backdrop-filter: blur(10px) saturate(1.15);
  -webkit-backdrop-filter: blur(10px) saturate(1.15);
  box-shadow: 0 24px 50px -30px rgba(0,0,0,0.6);
  padding: 1.4rem 1.5rem 1.6rem;
}
.guide-item h3 {
  font-family: var(--font-accent);
  font-weight: 400;
  font-size: 1.5rem;
  color: var(--accent);
  margin-bottom: .35rem;
}
.guide-item p { max-width: var(--measure); color: var(--text-muted); }

/* --- Call to action --- */
.cta { position: relative; z-index: 1; text-align: center; }
.cta::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at 50% 50%, rgba(10,15,25,.5), rgba(10,15,25,.1) 70%);
  z-index: -1;
}
.cta-inner {
  max-width: 640px;
  margin: 0 auto;
  padding: clamp(2.25rem, 6vw, 3.75rem) clamp(1.5rem, 5vw, 3rem);
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: 4px;
  backdrop-filter: blur(10px) saturate(1.15);
  -webkit-backdrop-filter: blur(10px) saturate(1.15);
  box-shadow: 0 24px 50px -30px rgba(0,0,0,0.6);
}
.cta-line {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  line-height: 1.25;
  text-wrap: balance;
  margin-bottom: 1.4rem;
}
.cta-btn {
  display: inline-block;
  font-family: var(--font-body);
  font-size: 0.82rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ash);
  background: var(--laterite);
  text-decoration: none;
  padding: .95rem 2.2rem;
  border-radius: 2px;
  transition: background .2s ease, transform .2s ease;
}
.cta-btn:hover { background: var(--turmeric); transform: translateY(-2px); }
.cta-body {
  max-width: 54ch;
  margin: 0 auto 2rem;
  font-size: var(--text-base);
  color: var(--text-paper);
}
.cta-sub {
  font-family: var(--font-accent);
  font-size: 1.25rem;
  color: var(--text-muted);
  margin-top: 1.2rem;
}

/* --- Raw Photo Gallery --- */
.gallery-wrap {
  position: relative;
  z-index: 1;
  padding: clamp(3.5rem, 8vw, 6rem) var(--content-pad);
}
.gallery-header {
  max-width: 68ch;
  margin: 0 auto 2.8rem;
  padding: clamp(1.5rem, 5vw, 2.75rem);
  text-align: center;
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: 4px;
  backdrop-filter: blur(10px) saturate(1.15);
  -webkit-backdrop-filter: blur(10px) saturate(1.15);
  box-shadow: 0 24px 50px -30px rgba(0,0,0,0.6);
}
.gallery-title {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  color: var(--text-paper);
  margin: 0.4rem 0 0.8rem;
}
.gallery-sub {
  font-size: var(--text-base);
  color: var(--text-muted);
}
/* Editorial mosaic. Cards claim a span instead of all being the same box, so a
   panorama reads as a panorama and a portrait stays upright. `dense` lets the
   browser backfill the gaps that leaves — no masonry library involved. */
.gallery-grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  grid-auto-rows: 165px;
  grid-auto-flow: dense;
  gap: 1rem;
  max-width: 1180px;
  margin: 0 auto;
}

/* Caption sits over the bottom of the photo, Kerala-Tourism style. */
.photo-card {
  position: relative;
  grid-column: span 2;
  overflow: hidden;
  border-radius: 4px;
  background: rgba(0,0,0,0.25);
  display: flex;
  align-items: flex-end;
}
/* Span modifiers come after .photo-card: same specificity, so source order decides. */
.photo-card--feature { grid-column: span 4; grid-row: span 2; }
.photo-card--tall    { grid-column: span 2; grid-row: span 2; }
.photo-card--wide    { grid-column: span 4; grid-row: span 1; }
.photo-card--feature figcaption { font-size: 1.55rem; padding-top: 3.5rem; }

/* Must sit AFTER the span modifiers above, for the same source-order reason: the
   modifiers are one class each, so an equal-specificity rule earlier in the file
   loses. When this block was above them, a --feature card still claimed span 4 in
   a 2-column grid, which forced two implicit columns and squeezed the plain cards
   into 100px slivers with one word per caption line. */
@media (max-width: 700px) {
  .gallery-grid { grid-template-columns: repeat(2, 1fr); grid-auto-rows: 190px; }
  .photo-card--feature,
  .photo-card--wide { grid-column: span 2; grid-row: span 2; }
  .photo-card--tall { grid-column: span 1; grid-row: span 2; }
  .photo-card--feature figcaption { font-size: 1.2rem; padding-top: 2.5rem; }
}

.photo-card img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.5s ease;
}
.photo-card:hover img { transform: scale(1.05); }
.photo-card figcaption {
  position: relative;
  width: 100%;
  padding: 2.5rem 1.2rem 1.1rem;
  font-family: var(--font-display);
  font-size: 1.2rem;
  line-height: 1.25;
  color: #f5efe4;
  background: linear-gradient(to top, rgba(8,10,18,0.85), rgba(8,10,18,0));
}
/* No photo in the frame yet. Uncomment the <img> and this styling drops away
   on its own — nothing else to change. */
.photo-card:not(:has(img)) {
  background: var(--panel-bg);
  border: 1px dashed var(--panel-border);
  align-items: center;
  justify-content: center;
}
.photo-card:not(:has(img)) figcaption {
  background: none;
  padding: 1.2rem;
  text-align: center;
  font-size: 1rem;
  color: var(--text-muted);
}

.gallery-more {
  max-width: 1100px;
  margin: 2rem auto 0;
  padding: clamp(1.5rem, 4vw, 2.25rem);
  text-align: center;
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: 4px;
  backdrop-filter: blur(10px) saturate(1.15);
  -webkit-backdrop-filter: blur(10px) saturate(1.15);
  box-shadow: 0 24px 50px -30px rgba(0,0,0,0.6);
}
.gallery-more a {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  min-height: 48px;
  padding: 0.8rem 1.6rem;
  border: 1px solid var(--panel-border);
  border-radius: 3px;
  color: var(--accent);
  text-decoration: none;
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  transition: border-color 0.2s ease;
}
.gallery-more a:hover { border-color: var(--accent); }
.gallery-more small {
  display: block;
  margin-top: 0.9rem;
  font-size: 0.8rem;
  color: var(--text-muted);
}

/* ==================== WRITING (blog index) ==================== */
.posts {
  position: relative;
  z-index: 1;
  max-width: 1100px;
  margin: 0 auto;
  padding: clamp(3rem, 8vw, 5.5rem) var(--content-pad);
}
.posts-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
  gap: 1rem;
  align-items: start;
}
.post-card {
  display: block;
  padding: 1.35rem 1.4rem 1.5rem;
  background: var(--panel-bg);
  backdrop-filter: blur(10px) saturate(1.15);
  -webkit-backdrop-filter: blur(10px) saturate(1.15);
  border: 1px solid var(--panel-border);
  border-left: 3px solid var(--accent);
  border-radius: 3px;
  box-shadow: 0 24px 50px -30px rgba(0,0,0,0.6);
  color: var(--text-paper);
  text-decoration: none;
  transition: transform 0.2s ease, border-color 0.2s ease;
}
.post-card:hover { transform: translateY(-3px); border-color: var(--accent); }
.post-date {
  display: block;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.6rem;
}
.post-card h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-lg);
  line-height: 1.25;
  margin-bottom: 0.5rem;
}
.post-card p {
  font-size: 0.92rem;
  line-height: 1.55;
  color: var(--text-muted);
}

/* ==================== PAGE HEADER (land.html, visit.html) ====================
   A shorter cousin of .hero: same photograph treatment, half the height, so a
   linked page opens on the place rather than on a wall of text. */
.page-head {
  position: relative;
  z-index: 1;
  min-height: 58vh;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  color: var(--ash);
  background-size: cover;
  background-position: center 55%;
}
.page-head::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(to bottom, rgba(10,14,12,.62) 0%, rgba(10,14,12,.20) 30%, rgba(10,14,12,.78) 100%),
    linear-gradient(to top, rgba(139,58,31,.22), transparent 45%);
}
.page-head-inner {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
  padding: clamp(7rem, 16vh, 10rem) var(--content-pad) clamp(2rem, 5vh, 3rem);
}
.page-head h1 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-3xl);
  line-height: 1;
  text-shadow: 0 4px 30px rgba(0,0,0,.6);
}
.page-head p {
  margin-top: 1rem;
  max-width: 52ch;
  color: rgba(245,239,228,.9);
  text-shadow: 0 2px 16px rgba(0,0,0,.6);
}

/* ==================== UNFOLD CARDS ====================
   The homepage does not scroll through the whole project. It offers doors. */
.unfold {
  position: relative;
  z-index: 1;
  max-width: 1180px;
  margin: 0 auto;
  padding: clamp(3rem, 8vw, 5rem) var(--content-pad);
}
.unfold-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1rem;
  margin-top: 1.5rem;
}
.unfold-card {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 260px;
  padding: 1.4rem;
  border-radius: 4px;
  overflow: hidden;
  color: var(--ash);
  text-decoration: none;
  background-size: cover;
  background-position: center;
  transition: transform .25s ease, box-shadow .25s ease;
}
.unfold-card:hover { transform: translateY(-3px); box-shadow: 0 14px 40px rgba(0,0,0,.4); }
.unfold-card .eyebrow-sm {
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--turmeric);
}
.unfold-card h3 {
  margin-top: 0.5rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-xl);
  line-height: 1.1;
}
.unfold-card p {
  margin-top: 0.5rem;
  font-size: 0.9rem;
  line-height: 1.5;
  color: rgba(245,239,228,.86);
}
.unfold-card .go {
  margin-top: 1rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--turmeric);
}

/* Foot link between pages */
.page-jump {
  position: relative;
  z-index: 1;
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 var(--content-pad) clamp(3rem, 8vw, 5rem);
}

/* ==================== FOOTER ====================
   Same mechanism as .status-band: a solid --band-bg surface directly under the
   photo, so ink and surface flip together in both themes. */
.site-foot {
  position: relative;
  z-index: 1;
  background: var(--band-bg);
  color: var(--text-paper);
  border-top: 1px solid var(--panel-border);
}
.site-foot-inner {
  max-width: 1180px;
  margin: 0 auto;
  padding: clamp(2.5rem, 6vw, 3.5rem) var(--content-pad);
  display: grid;
  gap: 2rem;
}
@media (min-width: 640px) {
  .site-foot-inner { grid-template-columns: 1fr 1fr; }
}
/* .brand-mark / .brand-logo hardcode ash for use over the dark hero photo;
   here the mark sits on the footer's own themed surface, so it needs its
   own ink instead. */
.foot-brand .brand-mark,
.foot-brand .brand-logo { color: var(--text-paper); }
.foot-loc {
  margin-top: 0.9rem;
  max-width: 42ch;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--text-muted);
}
.foot-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 1.2rem;
}
.foot-nav a {
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-paper);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 0.2s ease, border-color 0.2s ease;
}
.foot-nav a:hover { color: var(--accent); border-color: var(--accent); }
.foot-disclaimer {
  margin-top: 1.1rem;
  max-width: 52ch;
  font-size: 0.82rem;
  line-height: 1.55;
  color: var(--text-muted);
}
.foot-mail {
  display: inline-block;
  margin-top: 1rem;
  font-family: var(--font-accent);
  font-size: 1.1rem;
  color: var(--accent);
  text-decoration: none;
  transition: color 0.2s ease;
}
.foot-mail:hover { color: var(--text-paper); }

/* ============ Lightbox ============
   A native <dialog> built by assets/lightbox.js. Esc, the backdrop and the focus
   trap come from the element itself, so there is nothing here but appearance. */
.gallery-grid .photo-card { cursor: zoom-in; }
.gallery-grid .photo-card:focus-visible {
  outline: 2px solid var(--turmeric);
  outline-offset: 3px;
}
.lightbox {
  width: 100vw;
  max-width: 100vw;
  height: 100dvh;
  max-height: 100dvh;
  padding: 0;
  border: 0;
  background: transparent;
  overflow: hidden;
}
.lightbox::backdrop { background: rgba(6, 8, 12, 0.94); }
.lb-frame {
  display: flex;
  flex-direction: column;
  align-items: center;
  /* `safe`, not plain `center`: on a phone a portrait photo plus its caption is
     taller than this box, and centred overflow spills past BOTH ends — the image
     rode up under .lb-close and the corner of the photograph swallowed it. Safe
     centring falls back to flex-start once it overflows, so the top padding that
     reserves room for the close button is always honoured. */
  justify-content: safe center;
  gap: 0.9rem;
  height: 100%;
  margin: 0;
  /* Top padding must clear .lb-close, which ends at 1rem + 2.75rem = 3.75rem.
     At the old 3.2rem a portrait photograph ran under the button. */
  padding: 4.25rem 1rem;
  pointer-events: none;    /* clicks fall through to the dialog, which closes it */
}
.lb-frame img {
  max-width: min(96vw, 1600px);
  max-height: 82dvh;
  object-fit: contain;
  border-radius: 3px;
  pointer-events: auto;
}
.lb-frame figcaption {
  font-family: var(--font-display);
  font-size: 1.15rem;
  color: #f5efe4;
  text-align: center;
}
.lb-close, .lb-nav {
  position: absolute;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(245, 239, 228, 0.22);
  border-radius: 50%;
  background: rgba(8, 10, 18, 0.55);
  color: #f5efe4;
  cursor: pointer;
  line-height: 1;
  transition: border-color 0.2s ease, background 0.2s ease;
}
.lb-close:hover, .lb-nav:hover {
  border-color: var(--turmeric);
  background: rgba(8, 10, 18, 0.85);
}
.lb-close { top: 1rem; right: 1rem; width: 2.75rem; height: 2.75rem; font-size: 1.5rem; }
.lb-nav {
  top: 50%;
  transform: translateY(-50%);
  width: 3rem;
  height: 3rem;
  font-size: 2rem;
  padding-bottom: 0.2rem;
}
.lb-prev { left: 1rem; }
.lb-next { right: 1rem; }
/* On a phone the arrows would sit on top of the photograph. Put them under it. */
@media (max-width: 560px) {
  .lb-nav { top: auto; bottom: 1.1rem; transform: none; }
  .lb-prev { left: 25%; }
  .lb-next { right: 25%; }
  .lb-frame { padding: 4.25rem 0.5rem 5.5rem; }
  /* 82dvh ignores this frame's own padding (4.25 + 5.5rem) plus the gaps, the
     caption and the "also" line, so a portrait photo pushed the caption down into
     the arrow row. 15.5rem is that furniture; subtract it and the stack fits.
     If .lb-close or the arrow row changes size, this number has to follow. */
  .lb-frame img { max-height: calc(100dvh - 15.5rem); }
  /* One line only down here — three related captions wrapping would eat the photo. */
  .lb-also { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
}

/* The photograph slides in from the side it came from, so a swipe has a direction
   and the set feels like a set rather than a slideshow of unrelated frames. */
@keyframes lb-slide-from-right { from { opacity: 0; transform: translateX(4%); } }
@keyframes lb-slide-from-left  { from { opacity: 0; transform: translateX(-4%); } }
.lb-frame img.lb-in-right { animation: lb-slide-from-right 0.22s ease-out; }
.lb-frame img.lb-in-left  { animation: lb-slide-from-left  0.22s ease-out; }
@media (prefers-reduced-motion: reduce) {
  .lb-frame img.lb-in-right, .lb-frame img.lb-in-left { animation: none; }
}

/* "also: <caption> · <caption>" under the open photograph — the other frames that
   share a tag with it. Buttons, not links: they move the lightbox, not the page. */
.lb-also {
  margin: 0;
  font-size: 0.82rem;
  color: var(--text-muted);
  text-align: center;
  pointer-events: auto;
}
.lb-also:empty { display: none; }
.lb-also button {
  padding: 0.35rem 0.15rem;      /* vertical padding keeps the tap target usable */
  border: 0;
  background: none;
  font: inherit;
  color: var(--turmeric);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.lb-also button:hover { color: #f5efe4; }

/* ============ Footer social ============
   Icons are drawn inline so they inherit currentColor and flip with the theme —
   no icon font, no sprite, nothing to fetch. */
.foot-social {
  display: flex;
  gap: 0.5rem;
  margin-top: 1.1rem;
}
.foot-social a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;                   /* a link this small is a touch target first */
  height: 44px;
  border: 1px solid var(--panel-border);
  border-radius: 50%;
  color: var(--text-muted);
  transition: color 0.2s ease, border-color 0.2s ease;
}
.foot-social a:hover { color: var(--accent); border-color: var(--accent); }
.foot-social svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* Shapes that read better filled than outlined at 20px. */
.foot-social svg .solid,
.foot-social svg .dot { fill: currentColor; stroke: none; }

/* The hidden attribute is only `display: none` in the UA stylesheet, so any author
   `display` beats it — and .photo-card sets display:flex. A filtered-out photograph
   therefore stayed on screen while the count said it had gone. Restate it here. */
.photo-card[hidden],
.album[hidden],
.gallery-wrap[hidden] { display: none; }

/* ============ Albums ============
   Each set is a <details>. Closed, the page is seven covers and nothing to scroll
   past; open, one album's grid appears under its own cover. No JavaScript involved —
   the element does the work, and it stays keyboard-operable for free. */
.album {
  max-width: 1180px;
  margin: 0 auto 1rem;
  padding: 0 1rem;
}
.album-cover {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 0.3rem;
  min-height: 210px;
  padding: 1.4rem 3.5rem 1.3rem 1.4rem;
  border-radius: 4px;
  background-size: cover;
  background-position: center;
  cursor: pointer;
  list-style: none;              /* Firefox draws a marker without this */
  transition: transform 0.3s ease;
}
.album-cover::-webkit-details-marker { display: none; }
.album-cover:hover { transform: translateY(-2px); }
.album-cover:focus-visible { outline: 2px solid var(--turmeric); outline-offset: 3px; }
.album-eyebrow {
  font-family: var(--font-accent);
  font-size: 1rem;
  color: var(--turmeric);
}
.album-title {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 5vw, 2.2rem);
  line-height: 1.1;
  color: #f5efe4;
}
.album-sub {
  max-width: 52ch;
  font-size: 0.85rem;
  line-height: 1.5;
  color: rgba(245, 239, 228, 0.72);
}
/* A chevron that turns when the album opens, so the cover reads as a control. */
.album-cue {
  position: absolute;
  top: 1.4rem;
  right: 1.4rem;
  width: 2.75rem;
  height: 2.75rem;
  border: 1px solid rgba(245, 239, 228, 0.3);
  border-radius: 50%;
  background: rgba(8, 10, 18, 0.5);
  transition: transform 0.3s ease, border-color 0.2s ease;
}
.album-cue::after {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 0.6rem;
  height: 0.6rem;
  border-right: 2px solid #f5efe4;
  border-bottom: 2px solid #f5efe4;
  transform: translateY(-20%) rotate(45deg);
}
.album[open] .album-cue { transform: rotate(180deg); }
.album-cover:hover .album-cue { border-color: var(--turmeric); }
.album[open] .gallery-grid { margin-top: 1rem; }
@media (prefers-reduced-motion: reduce) {
  .album-cover, .album-cue { transition: none; }
}

/* ============ Tag bar ============
   Chips above the archive. Each is a plain link to ?tag=…, so it works with
   JavaScript off — the page just does not filter. */
.tag-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  max-width: 1180px;
  margin: 0 auto clamp(1.5rem, 4vw, 2.5rem);
  padding: 0 1rem;
}
.tag-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 44px;              /* a chip is a touch target before it is a label */
  padding: 0 0.85rem;
  border: 1px solid var(--panel-border);
  border-radius: 999px;
  background: var(--panel-bg);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  text-decoration: none;
  transition: border-color 0.2s ease, color 0.2s ease;
}
.tag-chip small { opacity: 0.6; font-size: 0.72rem; }
.tag-chip:hover { border-color: var(--accent); color: var(--text-paper); }
.tag-chip.is-on {
  border-color: var(--accent);
  color: var(--accent);
}

/* Image paths live here, not in inline styles, so the bare filename resolves
   next to this stylesheet.

   These are written as ordinary background-image declarations on purpose. A
   url() carried inside a custom property is NOT resolved against the stylesheet
   that declared it — Chrome resolves it against the document, so `url('road.jpg')`
   was fetched from the site root and 404'd on every page. That is why the
   backdrops rendered as flat dark panels with no photograph in them.
   The scrim stays a custom property: a gradient has no URL to resolve. */
body.bg-hero::before { background-image: var(--scrim), url('hero.jpg'); }
body.bg-land::before { background-image: var(--scrim), url('land.jpg'); }
body.bg-road::before { background-image: var(--scrim), url('road.jpg'); }
.head-land { background-image: url('land.jpg'); }
.head-road { background-image: url('road.jpg'); }
.card-land { background-image: linear-gradient(to top, rgba(10,14,12,.86), rgba(10,14,12,.22)), url('land.jpg'); }
.card-road { background-image: linear-gradient(to top, rgba(10,14,12,.86), rgba(10,14,12,.22)), url('road.jpg'); }

/* --- Filmstrip -------------------------------------------------------------
   A door into photographs.html. Scroll-snap is native: swipe, trackpad, drag and
   arrow keys all work without a line of JavaScript, which is why this replaced
   the 3D ring demo. The ring spun on its own and fought the rest of the site. */
.strip {
  position: relative;
  z-index: 1;
  padding: clamp(2.5rem, 7vw, 4.5rem) 0 clamp(2rem, 5vw, 3rem);
}
/* There is no .inner utility in this stylesheet — every section pads itself. */
.strip-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  max-width: 1180px;
  margin: 0 auto clamp(1rem, 3vw, 1.6rem);
  padding-inline: var(--content-pad);
}
.strip-head h2 { margin: 0; }
.strip-all {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--turmeric);
  text-decoration: none;
  white-space: nowrap;
}
.strip-all:hover { text-decoration: underline; }

.strip-rail {
  display: flex;
  gap: clamp(0.6rem, 2vw, 1rem);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  /* The rail runs full-bleed, but its first card has to line up with the heading
     above it — so the inline padding matches whatever gutter centres a 1180px
     container at this width. */
  /* The heading above carries BOTH the centring margin and the content padding,
     so the rail has to add them together to line up with it. */
  --rail-gutter: calc(max(0px, (100vw - 1180px) / 2) + var(--content-pad));
  padding: 0 var(--rail-gutter) 0.5rem;
  /* Without this the rail scrolls itself on load. scroll-snap-align: start aligns
     a card to the scrollport's edge, which sits INSIDE the padding — so the
     browser snaps the padding away and the first photo ends up flush against the
     screen edge. scroll-padding moves the snap line to where the padding ends. */
  scroll-padding-inline-start: var(--rail-gutter);
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
  scroll-behavior: smooth;
}
.strip-rail::-webkit-scrollbar { height: 6px; }
.strip-rail::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--turmeric) 45%, transparent);
  border-radius: 3px;
}

.strip-shot {
  position: relative;
  flex: 0 0 auto;
  width: clamp(210px, 42vw, 320px);
  aspect-ratio: 3 / 4;
  scroll-snap-align: start;
  overflow: hidden;
  border-radius: 4px;
  background: rgba(0,0,0,.25);
  text-decoration: none;
}
.strip-shot img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The card is one link, so the caption must not eat the pointer or the photo
     will not respond where the text sits. */
  transition: transform .5s cubic-bezier(.2,.6,.2,1);
}
.strip-shot:hover img,
.strip-shot:focus-visible img { transform: scale(1.04); }
.strip-shot span {
  position: absolute;
  inset: auto 0 0 0;
  padding: 2.2rem 0.85rem 0.8rem;
  font-family: var(--font-display);
  font-size: 0.95rem;
  line-height: 1.25;
  color: var(--ash);
  background: linear-gradient(to top, rgba(8,10,18,.9), transparent);
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .strip-rail { scroll-behavior: auto; }
  .strip-shot img { transition: none; }
  .strip-shot:hover img, .strip-shot:focus-visible img { transform: none; }
}
