/* Thurmaston Village — shared stylesheet */

@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/inter-variable.woff2") format("woff2");
}

@font-face {
  font-family: "Manrope";
  font-style: normal;
  font-weight: 500 800;
  font-display: swap;
  src: url("../fonts/manrope-variable.woff2") format("woff2");
}

:root {
  --green-900: #1f4d3a;
  --green-700: #2c6b4f;
  --green-100: #e7efe6;
  --gold-600: #b9822f;
  --gold-100: #f6ead2;
  --cream: #faf6ee;
  --paper: #ffffff;
  --ink: #22281f;
  --ink-soft: #52584c;
  --line: #ddd6c4;
  --radius: 14px;
  --radius-lg: 22px;
  --radius-pill: 999px;
  --shadow: 0 4px 20px rgba(31, 77, 58, 0.08);
  --shadow-lg: 0 20px 50px rgba(31, 77, 58, 0.18);
  --glass-blur: blur(20px) saturate(180%);
  --glass-bg: rgba(255, 255, 255, 0.65);
  --glass-bg-strong: rgba(255, 255, 255, 0.82);
  --glass-border: rgba(255, 255, 255, 0.55);
  --glass-bg-dark: rgba(255, 255, 255, 0.09);
  --glass-border-dark: rgba(255, 255, 255, 0.18);
  /* A second, smaller blur tier — for small/chrome surfaces (chips,
     small overlays) that don't want the full --glass-blur strength.
     Everything bigger (cards, panels, modals, the header) uses the
     original --glass-blur. Added when 4 different components had each
     hardcoded their own one-off blur value instead of sharing a token
     — folding them onto just these two tiers, rather than adding a
     third bespoke value each time, is the actual fix. */
  --glass-blur-sm: blur(12px) saturate(160%);
  /* Translucent green-900 — the dark-glass counterpart to the light
     --glass-bg-* family above, for panels that used to be 100% opaque
     solid --green-900 (the hero cards, the photo facts panel, page
     banners, modals). Same hue, so no text-color/contrast rework
     needed on anything switched over to it — just the fill becomes
     glass instead of flat. */
  --glass-bg-green: rgba(31, 77, 58, 0.82);
  --glass-bg-green-strong: rgba(31, 77, 58, 0.92);
  --font-head: "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-body: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  /* Spacing scale (4px rhythm) — used on new/touched selectors only;
     not retrofitted onto every existing hand-picked padding/margin
     value in the file, that's a separate, deliberately deferred pass. */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 32px;
  --space-8: 40px;
  --space-9: 56px;
  --space-10: 72px;
  /* Type scale — named to match sizes already used around the site
     (so this reads as a naming pass, not a resize), applied only to
     new/touched selectors for the same reason as the spacing scale. */
  --text-xs: 0.75rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-md: 1.125rem;
  --text-lg: 1.25rem;
  --text-xl: 1.5rem;
  --text-2xl: clamp(1.75rem, 1.4rem + 1.5vw, 2.25rem);
  --text-3xl: clamp(1.8rem, 1.2rem + 3vw, 2.8rem); /* = the existing hero h1 clamp */
}

/* Radius/shadow pairing rule (a convention, not a new mechanism):
     pills/chips/inputs      -> --radius-pill + --shadow
     grid cards/tiles        -> --radius + --shadow (--shadow-lg on hover)
     standalone panels/modals/hero cards -> --radius-lg + --shadow-lg
   Stating this explicitly is what makes a stray value (e.g. a button
   using an 8px or 20px radius instead of one of the above) visible as
   a violation to fix, rather than "just another one-off."

   Breakpoint scale already in use across this file (kept as literal
   px values in @media conditions — custom properties can't be read
   inside a media-query condition in any browser): 340 / 480 / 560 /
   640 / 780 / 980. New responsive rules should pick from this list
   rather than inventing another value. */

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font-body);
  /* Ambient colour blobs behind the base cream gradient — the same
     "fixed" layer as before, just with soft green/gold radial tints
     mixed in. Every glass panel below the hero (.card, .callout, form
     cards, the map sidebar, etc.) blurs *this*, which is what makes
     them read as glass rather than flat white boxes on a flat page. */
  background:
    radial-gradient(640px circle at 8% 4%, rgba(185, 130, 47, 0.14), transparent 60%),
    radial-gradient(720px circle at 94% 18%, rgba(44, 107, 79, 0.16), transparent 60%),
    radial-gradient(680px circle at 12% 70%, rgba(31, 77, 58, 0.12), transparent 60%),
    radial-gradient(560px circle at 92% 96%, rgba(185, 130, 47, 0.12), transparent 60%),
    linear-gradient(180deg, #faf6ee 0%, #f2ead9 100%);
  background-attachment: fixed;
  color: var(--ink);
  line-height: 1.6;
}

img { max-width: 100%; display: block; }

a { color: var(--green-700); }
a:hover { color: var(--gold-600); }

/* Visible, consistent keyboard focus everywhere — only for keyboard
   navigation (:focus-visible), so mouse clicks stay visually quiet. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid var(--gold-600);
  outline-offset: 2px;
}

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

h1, h2, h3, h4 {
  font-family: var(--font-head);
  font-weight: 700;
  color: var(--green-900);
  line-height: 1.2;
  letter-spacing: -0.01em;
  margin: 0 0 0.5em;
}

.container {
  max-width: 1120px;
  margin: 0 auto;
  padding: 0 20px;
}

.skip-link {
  position: absolute;
  left: -999px;
  top: 0;
  background: var(--green-900);
  color: #fff;
  padding: 10px 16px;
  z-index: 1000;
  border-radius: 0 0 6px 0;
}
.skip-link:focus { left: 0; }

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

/* ---------- Coming-soon gate (index.html only) ---------- */
/* Hidden-by-default-until-unlocked, not shown-by-default-until-locked —
   fails safe if js/coming-soon.js somehow doesn't run (e.g. blocked),
   the real homepage just never appears rather than briefly flashing. */
#site-real-content { display: none; }
html.unlocked #site-real-content { display: block; }
html.unlocked #coming-soon-gate { display: none; }

#coming-soon-gate {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: linear-gradient(135deg, var(--green-900), var(--green-700));
}
.coming-soon-inner {
  max-width: 420px;
  width: 100%;
  text-align: center;
  color: #fff;
}
.coming-soon-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.15);
  font-weight: 700;
  font-size: 1.4rem;
  margin-bottom: 18px;
}
.coming-soon-inner h1 {
  margin: 0 0 12px;
  font-size: clamp(1.8rem, 1.3rem + 2vw, 2.4rem);
  color: #fff;
}
.coming-soon-inner p { color: rgba(255, 255, 255, 0.85); margin: 0 0 24px; }
#coming-soon-form {
  display: flex;
  gap: 8px;
  justify-content: center;
  flex-wrap: wrap;
}
#coming-soon-password {
  padding: 10px 16px;
  border-radius: var(--radius-pill);
  border: 1px solid rgba(255, 255, 255, 0.4);
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  min-width: 180px;
  font-size: 16px;
}
#coming-soon-password::placeholder { color: rgba(255, 255, 255, 0.6); }
#coming-soon-error { color: #ffb4b4; margin: 14px 0 0; font-size: 0.9rem; }

/* ---------- Header ---------- */

.site-header {
  background: var(--glass-bg-strong);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border-bottom: 1px solid var(--glass-border);
  box-shadow: 0 1px 0 rgba(255,255,255,0.4) inset, 0 8px 24px rgba(31,77,58,0.06);
  position: sticky;
  top: 0;
  z-index: 100;
}

.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-top: 14px;
  padding-bottom: 14px;
  max-width: 1320px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  flex-shrink: 0;
}

.brand-mark {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--green-900);
  color: var(--gold-100);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-head);
  font-weight: bold;
  font-size: 18px;
}

.brand-text {
  font-family: var(--font-head);
  font-size: 1.3rem;
  color: var(--green-900);
  font-weight: bold;
}
.brand-text small {
  display: block;
  font-family: var(--font-body);
  font-size: 0.65rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  font-weight: normal;
}

.main-nav {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
}

.main-nav a {
  text-decoration: none;
  color: var(--ink);
  font-size: 0.9rem;
  padding: 8px 14px;
  border-radius: var(--radius-pill);
  white-space: nowrap;
  transition: background 0.15s ease, color 0.15s ease;
}

.main-nav a:hover,
.main-nav a[aria-current="page"] {
  background: var(--green-100);
  color: var(--green-900);
}

.nav-toggle {
  display: none;
  align-items: center;
  gap: 6px;
  background: rgba(255,255,255,0.5);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-pill);
  padding: 8px 14px;
  font-size: 1.1rem;
  cursor: pointer;
  color: var(--ink);
}

.search-btn {
  background: var(--green-900);
  color: #fff;
  border: none;
  border-radius: var(--radius-pill);
  padding: 9px 16px;
  font-size: 0.9rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  transition: background 0.15s ease;
}
.search-btn:hover { background: var(--gold-600); }

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

.search-overlay {
  position: fixed;
  inset: 0;
  background: rgba(20, 26, 22, 0.35);
  backdrop-filter: var(--glass-blur-sm);
  -webkit-backdrop-filter: var(--glass-blur-sm);
  z-index: 200;
  display: none;
  align-items: flex-start;
  justify-content: center;
  padding: 8vh 16px;
}
.search-overlay.open { display: flex; }

.search-panel {
  background: var(--glass-bg-strong);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  width: 100%;
  max-width: 640px;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 20px;
  max-height: 78vh;
  display: flex;
  flex-direction: column;
}

.search-panel-head {
  display: flex;
  gap: 10px;
  align-items: center;
}

#site-search-input {
  flex: 1;
  font-size: 1.05rem;
  padding: 12px 16px;
  border: 1px solid var(--glass-border);
  background: rgba(255,255,255,0.6);
  border-radius: var(--radius-pill);
  font-family: var(--font-body);
}
#site-search-input:focus {
  outline: 2px solid var(--green-700);
  outline-offset: 1px;
}

.search-close {
  background: none;
  border: none;
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
  color: var(--ink-soft);
  padding: 4px 8px;
}

#site-search-results {
  list-style: none;
  margin: 14px 0 0;
  padding: 0;
  overflow-y: auto;
}

#site-search-results li { border-top: 1px solid var(--line); }
#site-search-results li:first-child { border-top: none; }

#site-search-results a {
  display: block;
  padding: 12px 6px;
  text-decoration: none;
}
#site-search-results a:hover { background: var(--green-100); border-radius: 6px; }

.result-title {
  color: var(--green-900);
  font-weight: 600;
  font-family: var(--font-head);
}
.result-cat {
  display: inline-block;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  background: var(--gold-100);
  color: #7a5a2e; /* darker than gold-600 — that pairing fails WCAG AA (2.8:1) on this background */
  padding: 2px 8px;
  border-radius: 20px;
  margin-left: 8px;
  vertical-align: middle;
}
.result-excerpt {
  color: var(--ink-soft);
  font-size: 0.9rem;
  margin-top: 2px;
}

.search-hint, .search-empty {
  color: var(--ink-soft);
  padding: 12px 6px;
  font-size: 0.9rem;
}

/* ---------- Hero ---------- */
/* Rebuilt as a full-bleed photo backdrop with a green-tinted scrim and
   two floating frosted-glass cards on top (the site's info/search, and
   a Village Chronology teaser) — the "layered translucent panel over
   imagery" look (macOS Control Center, Apple's own marketing pages)
   requested explicitly, in place of the previous fixed-height photo-
   beside-a-solid-green-box split. Makes the photo more prominent
   (full-bleed, not a boxed 3:2 side panel) rather than less, and
   solves what would otherwise be a tight fixed-height budget for
   fitting a second card in — .hero's height is now content-driven
   below 980px and only gets a tall min-height at/above it. */

/* No overflow:hidden here (deliberately) — .hero-media already clips
   its own backdrop image to itself via inset:0 + its own overflow:
   hidden below, so the outer hero doesn't need to as well, and NOT
   clipping here is what lets the search results dropdown
   (#home-search-results, below) float over the "Photo archive"
   section underneath instead of being cut off at the hero's own
   bottom edge. */
.hero {
  position: relative;
  color: #fff;
  display: flex;
  align-items: center;
}

@media (min-width: 980px) {
  .hero { min-height: clamp(560px, 62vh, 720px); }
}

/* Full-bleed backdrop (was a flexed, fixed-aspect side panel) — fills
   the whole .hero regardless of its height. */
.hero-media {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
}

/* Unchanged — still the exact element js/main.js's initHero() targets
   (hero.querySelector(".hero-slide")) to swap in the real photo from
   data/hero.json once one exists. */
.hero-slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 1.2s ease;
  background-size: cover;
  background-position: center;
}
.hero-slide.active { opacity: 1; }

/* Green-tinted, not black/grey — keeps the overlay on-palette while it
   does its actual job (card text staying legible over whatever photo
   is live). Directional so more of the photo reads clearly on the
   right, under the smaller chronology card, than under the denser
   text of the main card on the left. */
.hero-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, rgba(31, 77, 58, 0.82) 0%, rgba(31, 77, 58, 0.55) 45%, rgba(31, 77, 58, 0.2) 100%);
}

.hero-inner {
  position: relative;
  z-index: 1;
  width: 100%;
  padding-top: var(--space-8);
  padding-bottom: var(--space-8);
}

.hero-cards {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: var(--space-7);
  align-items: start;
}

.hero-card {
  background: var(--glass-bg-green);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border-dark);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: clamp(24px, 3vw, 40px);
}

.eyebrow {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--gold-100);
  margin: 0 0 8px;
}

.hero-card-main h1 {
  color: #fff;
  font-weight: 800;
  font-size: clamp(1.8rem, 3vw, 2.8rem);
  margin-bottom: 0.25em;
}

.hero-subtitle {
  font-size: 1.1rem;
  margin: 0 0 12px;
  color: #f2f0e6;
}

.hero-lede {
  font-size: 0.95rem;
  line-height: 1.5;
  max-width: 46em;
  margin: 0 0 18px;
  color: #d9e6db;
}

.hero-search {
  position: relative;
  max-width: 420px;
  margin: 0 0 20px;
}

/* Matches the header's .search-btn (top right) deliberately — same
   solid --green-900 fill, same pill radius, same rough height/font
   size, plus the same magnifying-glass icon — rather than the
   glass/translucent treatment used elsewhere in the hero, so the two
   read as clearly the same search feature rather than two different
   styles that happen to both say "search." */
.hero-search-input {
  width: 100%;
  font-size: 0.9rem;
  padding: 9px 18px 9px 40px;
  border: 1.5px solid rgba(255, 255, 255, 0.7);
  background: var(--green-900);
  border-radius: var(--radius-pill);
  font-family: var(--font-body);
  color: #fff;
  box-shadow: var(--shadow);
}
.hero-search-icon {
  position: absolute;
  left: 16px;
  top: 50%;
  transform: translateY(-50%);
  color: rgba(255, 255, 255, 0.7);
  pointer-events: none;
}
.hero-search-input::placeholder { color: rgba(255, 255, 255, 0.7); }
.hero-search-input:focus {
  outline: 2px solid #fff;
  outline-offset: 1px;
}

/* Same card look as .home-search-results elsewhere (that class is
   still applied, just repositioned here), anchored absolutely since
   it's floating over a glass hero card, not sitting inline in the
   page flow. Targeted by #home-search-results (an ID, not just the
   .hero-search-results class) so these overrides reliably beat
   .home-search-results's own margin/max-width regardless of which
   block happens to come later in this file. z-index raised from the
   original 5 to sit above .hero-card-chronology, which now sits
   directly below this card in normal flow on the stacked mobile
   layout (it didn't need to clear another card before). */
/* Capped and internally scrollable — about 5 results' worth — rather
   than growing to fit every match, now that .hero no longer clips it
   (above): with 20 possible matches (renderResultsInto's own cap) an
   uncapped list would otherwise float a very tall card down over most
   of the "Photo archive" section below it. overscroll-behavior stops
   scrolling through the end of the list from also scrolling the page
   underneath it. */
#home-search-results.hero-search-results {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  right: 0;
  max-width: none;
  margin: 0;
  z-index: 20;
  max-height: 340px;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.hero-cta {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

.hero-chronology-title {
  color: #fff;
  font-size: var(--text-lg);
  margin: 0 0 8px;
}

.hero-chronology-lede {
  font-size: 0.9rem;
  line-height: 1.5;
  color: #d9e6db;
  margin: 0 0 var(--space-4);
}

.hero-chronology-years {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0 0 var(--space-5);
  padding: 0;
}

/* .chip's base look (light bg, dark text/border) is built for a light
   page background — inverted here for the dark glass card it sits on,
   same two states (rest/hover) as everywhere else .chip is used. */
.hero-chronology-years .chip {
  background: rgba(255, 255, 255, 0.14);
  border-color: rgba(255, 255, 255, 0.35);
  color: #fff;
}
.hero-chronology-years .chip:hover {
  background: #fff;
  color: var(--green-900);
  border-color: #fff;
}

@media (max-width: 980px) {
  .hero-cards {
    grid-template-columns: 1fr;
    gap: var(--space-6);
  }
}

@media (max-width: 640px) {
  .hero-inner { padding-top: var(--space-7); padding-bottom: var(--space-7); }
}

.btn {
  display: inline-block;
  padding: 12px 24px;
  border-radius: var(--radius-pill);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.95rem;
  border: 2px solid transparent;
  transition: background 0.2s ease, color 0.2s ease, transform 0.15s ease;
}
.btn:active { transform: scale(0.97); }
.btn-primary { background: var(--gold-600); color: #241a06; }
.btn-primary:hover { background: #d29b46; color: #241a06; }
.btn-outline {
  border-color: rgba(255,255,255,0.6);
  background: rgba(255,255,255,0.12);
  backdrop-filter: var(--glass-blur-sm);
  -webkit-backdrop-filter: var(--glass-blur-sm);
  color: #fff;
}
.btn-outline:hover { background: #fff; color: var(--green-900); }

/* .btn-outline (above) is a translucent glass button designed for the
   dark hero background — used against cemetery.html's ordinary light
   page background it read as a near-invisible white-on-white button.
   A solid fill with a white border reads clearly on light backgrounds
   instead, requested explicitly as "green with white outline". */
.btn-green-outline {
  background: var(--green-900);
  border-color: #fff;
  box-shadow: var(--shadow);
  color: #fff;
}
.btn-green-outline:hover { background: var(--green-700); }

.btn-facebook {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: #1877F2;
  color: #fff;
  border-color: #1877F2;
  box-shadow: 0 2px 8px rgba(24, 119, 242, 0.35);
}
.btn-facebook:hover {
  background: #0d5fd1;
  border-color: #0d5fd1;
  color: #fff;
}
.btn-facebook svg { flex-shrink: 0; }

.footer-fb-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.footer-fb-link svg { flex-shrink: 0; }

.tiles-lede {
  text-align: center;
  color: var(--ink-soft);
  max-width: 560px;
  margin: 0 auto 36px;
}

/* ---------- Generic content sections ---------- */

.page-hero {
  /* Translucent instead of flat — no border/radius added here unlike
     the other converted dark-glass panels below, since this is a
     full-bleed banner spanning the whole viewport width, not an inset
     floating box; a border on it would just draw two stray vertical
     lines at the screen edges. */
  background: var(--glass-bg-green);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  color: #fff;
  padding: 46px 0;
}
.page-hero .container { max-width: 900px; }
.page-hero h1 { color: #fff; margin-bottom: 6px; }
.page-hero p { color: #d9e6db; margin: 0; max-width: 640px; }
/* An inline link inside the hero paragraph (e.g. cemetery-map.html's
   "see the full directory") otherwise inherits the site's default
   link colours (--green-700 normal, --gold-600 on hover) — both were
   built assuming a light page background, so on this dark green glass
   panel the normal state is nearly invisible and gold reads poorly
   against green. White, in both states, actually shows up. */
.page-hero a { color: #fff; }
.page-hero a:hover { color: #fff; opacity: 0.8; }

.breadcrumb {
  font-size: 0.85rem;
  color: #c7d9c9;
  margin-bottom: 10px;
}
.breadcrumb a { color: #e7efe6; }

.place-back-link {
  display: inline-block;
  margin-top: 14px;
  color: #e7efe6;
  font-size: 0.88rem;
  font-weight: 600;
  text-decoration: none;
}
.place-back-link:hover { text-decoration: underline; }

.content-section {
  padding-top: 44px;
  padding-bottom: 44px;
}

.content-section + .content-section {
  border-top: 1px solid var(--line);
}

.content-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 24px;
}

.card {
  background: var(--glass-bg-strong);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius);
  padding: 22px;
  box-shadow: var(--shadow);
  overflow: hidden;
}

/* An optional cover photo (e.g. a Shared Memory with a photo attached)
   — bled out to the card's own edges via a negative margin matching
   the card's own padding, rather than sitting inset inside it like a
   normal image, so it reads as a photo card, not a text card with a
   thumbnail dropped in. `.card`'s own overflow:hidden clips the image's
   square corners to the card's rounded ones. */
.card-photo {
  display: block;
  width: calc(100% + 44px);
  max-width: none;
  height: 160px;
  object-fit: cover;
  margin: -22px -22px 16px;
}

.card h3 { font-size: 1.1rem; }
.card .meta {
  font-size: 0.8rem;
  color: var(--gold-600);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 6px;
}

.info-list { list-style: none; padding: 0; margin: 0; }
.info-list li {
  padding: 12px 0;
  border-bottom: 1px solid var(--line);
  display: flex;
  gap: 14px;
}
.info-list li:last-child { border-bottom: none; }
.info-list .dt { min-width: 76px; font-weight: 600; color: var(--green-900); }

/* ---------- Cemetery directory ---------- */

/* cemetery-map.html — the cemetery's aerial photo (data/cemetery-
   overview.json), full-width and carrying one pin per grave with a
   Position on the cemetery map set (js/cemetery-map.js). Pin markers
   are plain <a> tags positioned by percent
   (admin/pin-grave.html is what produces that x%/y% — see its own
   comment for why a custom CMS widget isn't possible here), same
   "click-to-place, percent-of-image" convention as
   js/place.js's renderNumberedPeople markers. */
.cemetery-map-wrap {
  position: relative;
  display: block;
  line-height: 0;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
}
.cemetery-map-wrap img { width: 100%; display: block; }
.cemetery-map-pin {
  position: absolute;
  width: 16px;
  height: 16px;
  margin-left: -8px;
  margin-top: -8px;
  border-radius: 50%;
  background: var(--gold-600);
  border: 2px solid #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);
  cursor: pointer;
}
.cemetery-map-pin:hover,
.cemetery-map-pin:focus-visible {
  background: var(--green-700);
  outline: none;
}
.cemetery-map-pin-label {
  position: absolute;
  bottom: 130%;
  left: 50%;
  transform: translateX(-50%);
  background: var(--green-900);
  color: #fff;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  font-size: 0.75rem;
  line-height: 1.3;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
  box-shadow: var(--shadow);
}
.cemetery-map-pin:hover .cemetery-map-pin-label,
.cemetery-map-pin:focus-visible .cemetery-map-pin-label {
  opacity: 1;
}
/* Result of typing a name into the "Find a name on the map" search box
   (js/cemetery-map.js) — a plain gold dot is easy to lose among a busy
   real aerial photo full of actual headstones, so a match gets sized
   up, ringed, and its label forced visible (not just on hover) for a
   few seconds rather than relying on the visitor to spot a 16px dot
   themselves. */
.cemetery-map-pin.highlighted {
  width: 26px;
  height: 26px;
  margin-left: -13px;
  margin-top: -13px;
  background: #a33;
  z-index: 2;
  animation: cemetery-pin-pulse 1s ease-in-out 3;
}
.cemetery-map-pin.highlighted .cemetery-map-pin-label {
  opacity: 1;
}
@keyframes cemetery-pin-pulse {
  0%, 100% { box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5), 0 0 0 0 rgba(163, 51, 51, 0.6); }
  50% { box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5), 0 0 0 10px rgba(163, 51, 51, 0); }
}

.cemetery-directory-list { list-style: none; padding: 0; margin: 0; }
.cemetery-directory-list li {
  display: flex;
  align-items: center;
  gap: 8px;
  border-bottom: 1px solid var(--line);
  transition: background 0.3s ease;
}
.cemetery-directory-list li:last-child { border-bottom: none; }
/* A search result without a map pin (js/cemetery.js's jumpToGrave)
   highlights its row here instead — same idea as .cemetery-map-pin.
   highlighted above (a brief, unmissable flash), just for the case
   where there's nothing to show on the map. */
.cemetery-directory-list li.highlighted { background: rgba(185, 130, 47, 0.18); }
.cemetery-directory-list li input[type="checkbox"] {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  accent-color: var(--green-700);
  cursor: pointer;
}
.cemetery-directory-list a {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  padding: 12px 6px;
  text-decoration: none;
  color: inherit;
  border-radius: 8px;
  transition: background 0.15s ease;
}
.cemetery-directory-list a:hover { background: var(--green-100); }
.cemetery-directory-name { font-weight: 600; color: var(--green-900); font-family: var(--font-head); }
.cemetery-directory-meta { color: var(--ink-soft); font-size: 0.85rem; white-space: nowrap; }

.tag-list { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 0; }
.tag {
  background: var(--green-100);
  color: var(--green-900);
  font-size: 0.78rem;
  padding: 4px 10px;
  border-radius: 20px;
}

.callout {
  background: rgba(246, 234, 210, 0.75);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid rgba(230, 201, 138, 0.7);
  border-radius: var(--radius);
  padding: 18px 20px;
}
.callout h3 { margin-bottom: 6px; }

/* The homepage's map teaser — a deliberately smaller, secondary link
   out to the full interactive map on its own page (map.html), rather
   than embedding the map itself here. A small illustration sits
   alongside the text so it reads as "a map" at a glance rather than
   just another text callout — there's no live map on this page for
   the eye to land on any more. */
.callout-map {
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 24px;
}
.callout-map-media {
  flex: 0 0 auto;
  width: 160px;
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
}
.callout-map-media img { display: block; width: 100%; height: auto; }
.callout-map-body { flex: 1 1 auto; }
.callout-map h3 { font-size: 1.25rem; }
.callout-map .btn { margin-top: 10px; }

@media (max-width: 640px) {
  .callout-map { flex-direction: column; text-align: center; }
  .callout-map-media { width: 200px; }
}

.placeholder-photo {
  aspect-ratio: 16/10;
  border-radius: var(--radius);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 0.85rem;
  text-align: center;
  padding: 10px;
  background: linear-gradient(135deg, var(--green-700), var(--green-900));
}

form.stack { display: flex; flex-direction: column; gap: 14px; max-width: 480px; }
form.stack[hidden] { display: none; }
form.stack label { display: block; font-weight: 600; font-size: 0.9rem; margin-bottom: 6px; }
form.stack input, form.stack textarea, form.stack select {
  width: 100%;
  box-sizing: border-box;
  padding: 10px 12px;
  border: 1px solid var(--glass-border);
  border-radius: 8px;
  font-family: var(--font-body);
  font-size: 0.95rem;
  background: var(--glass-bg);
  backdrop-filter: var(--glass-blur-sm);
  -webkit-backdrop-filter: var(--glass-blur-sm);
  transition: border-color 0.15s ease;
}
form.stack input:focus, form.stack textarea:focus, form.stack select:focus {
  border-color: var(--green-700);
}

table.simple { width: 100%; border-collapse: collapse; }
table.simple th, table.simple td {
  text-align: left;
  padding: 10px 12px;
  border-bottom: 1px solid var(--line);
}
table.simple th { color: var(--green-900); font-family: var(--font-head); }

/* ---------- Place page (dedicated per-pin story pages) ---------- */

.place-content {
  max-width: 680px;
  margin: 0 auto;
}
.place-content p {
  margin: 0 0 1.1em;
  line-height: 1.7;
}
.place-content p:last-child { margin-bottom: 0; }

.place-photo-block {
  display: block;
  text-decoration: none;
  margin: 24px 0;
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
  border: 1px solid var(--glass-border);
}
.place-photo-block img {
  width: 100%;
  display: block;
  transition: transform 0.2s ease;
}
.place-photo-block:hover img { transform: scale(1.03); }
.place-photo-caption {
  display: block;
  padding: 10px 14px;
  background: var(--glass-bg-strong);
  color: var(--ink);
  font-size: 0.85rem;
}

.place-not-found {
  color: var(--ink-soft);
  text-align: center;
}

.events-other-link {
  text-align: center;
  margin-top: 20px;
  font-size: 0.9rem;
}

/* ---------- Location timeline (location.html) ---------- */

.location-subheading {
  color: var(--ink-soft);
  font-size: 1.05rem;
  margin: -8px 0 0;
}

/* display: table -- a block-level box that still shrinks to fit its
   content, so margin: 0 auto centers it (like the timeline list below
   it) without stretching the button itself to the full column width. */
.location-download-pdf-btn {
  display: table;
  margin: 0 auto 20px;
}

.location-timeline {
  max-width: 800px;
  margin: 0 auto;
}

.location-timeline-heading {
  color: var(--ink-soft);
  font-size: 1rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 32px 0 16px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
}

.location-entry {
  display: flex;
  gap: 20px;
  padding: 24px 0;
  border-left: 3px solid var(--gold-600);
  padding-left: 24px;
  margin-bottom: 4px;
}
.location-entry + .location-entry { border-top: 1px solid var(--line); }

.location-entry-media {
  flex: 0 0 180px;
  display: block;
  border-radius: var(--radius);
  overflow: hidden;
}
.location-entry-media img {
  width: 100%;
  height: 130px;
  object-fit: cover;
  display: block;
  transition: transform 0.2s ease;
}
.location-entry-media:hover img { transform: scale(1.03); }

.location-entry-body { flex: 1 1 auto; min-width: 0; }

.location-entry-caption {
  display: block;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--green-900);
  text-decoration: none;
  margin-bottom: 4px;
}
.location-entry-caption:hover { text-decoration: underline; }

.location-entry-meta {
  color: var(--ink-soft);
  font-size: 0.88rem;
  margin: 0 0 10px;
}

.location-entry-history p {
  margin: 0 0 10px;
  line-height: 1.6;
}
.location-entry-history p:last-child { margin-bottom: 0; }

@media (max-width: 600px) {
  .location-entry { flex-direction: column; gap: 12px; }
  .location-entry-media { flex: none; }
}

/* ---------- Village Chronology ---------- */

.chronology-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  justify-content: space-between;
  max-width: 800px;
  margin: 0 auto 16px;
}
.chronology-toolbar .photo-search-input { margin-bottom: 0; flex: 1 1 260px; max-width: none; }
.chronology-toolbar .chronology-download-pdf-btn { flex: none; }

#chronology-eras {
  max-width: 800px;
  margin: 0 auto 8px;
}

.chronology-timeline {
  max-width: 800px;
  margin: 0 auto;
}

/* Same left-rail look as .location-entry, minus the photo column —
   a chronology entry is text-only. */
.chronology-entry {
  display: flex;
  align-items: baseline;
  gap: 20px;
  padding: 16px 0 16px 24px;
  border-left: 3px solid var(--gold-600);
}
.chronology-entry + .chronology-entry { border-top: 1px solid var(--line); }

/* A link through to year.html?year=X — "everything from that year"
   (chronology entries, photos, events), not just this one row — so
   it's styled to still read as the bold year label it always was,
   with an underline only on hover as the one added affordance that
   it's now clickable. Entries with no parseable year (`entry.sortYear
   === null`) render a plain, unlinked span instead — see
   js/chronology.js's renderEntry. */
.chronology-year {
  flex: 0 0 100px;
  font-family: var(--font-head);
  font-weight: 700;
  color: var(--green-900);
  font-size: 1.05rem;
  text-decoration: none;
}
a.chronology-year:hover { text-decoration: underline; }

.chronology-body {
  flex: 1 1 auto;
  min-width: 0;
}

.chronology-text {
  margin: 0;
  line-height: 1.6;
}

@media (max-width: 600px) {
  .chronology-entry { flex-direction: column; gap: 4px; padding-left: 16px; }
  .chronology-year { flex: none; }
}

/* ---------- Pick-and-choose PDF pattern ----------
   Shared across every page that lists more than one of something and
   lets a visitor tick which ones to include in a combined PDF: year.html
   (chronology entries/events/photos for one year), category.html
   (photos in one category), events.html (Event Pages), location.html
   (a place's photos) and cemetery.html (graves). One set of classes
   rather than a near-duplicate per page — see js/pdf-helpers.js's
   wireCheckboxSelectAll for the matching shared JS. */

.pick-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  max-width: 900px;
  margin: 0 auto 28px;
  padding-bottom: 20px;
  border-bottom: 1px solid var(--line);
}
.pick-toolbar-actions { display: flex; gap: 8px; }

.pick-list { list-style: none; margin: 12px 0 0; padding: 0; }
.pick-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 0;
  border-bottom: 1px solid var(--line);
}
.pick-item:last-child { border-bottom: none; }
.pick-item input[type="checkbox"] {
  margin-top: 4px;
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  accent-color: var(--green-700);
  cursor: pointer;
}
.pick-item-body { flex: 1 1 auto; min-width: 0; }
.pick-item-title { font-weight: 600; font-family: var(--font-head); }
.pick-item-title a { color: var(--green-900); text-decoration: none; }
.pick-item-title a:hover { text-decoration: underline; }
.pick-item-meta { font-size: 0.85rem; color: var(--ink-soft); margin: 2px 0 0; }
.pick-item-text { margin: 0; line-height: 1.6; }

.pick-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 14px;
  margin-top: 12px;
}
.pick-photo-item { position: relative; }
.pick-photo-item input[type="checkbox"] {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 2;
  width: 20px;
  height: 20px;
  accent-color: var(--green-700);
  cursor: pointer;
}

#year-chronology-section, #year-events-section, #year-photos-section {
  max-width: 900px;
  margin: 0 auto 36px;
}

/* A prominent nudge to a place's timeline page (location.html) when
   more than one photo shares this one's Location — see js/place.js's
   renderLocationBanner. Styled as its own eye-catching callout (not
   just a text link) specifically because a plain link in this spot
   was the thing that turned out to go unnoticed before. */
.place-location-banner {
  display: block;
  max-width: 900px;
  margin: 0 auto 20px;
  padding: 14px 20px;
  background: var(--gold-100);
  border: 1px solid var(--gold-600);
  border-radius: var(--radius);
  color: var(--green-900);
  font-weight: 600;
  text-decoration: none;
  transition: background 0.15s ease;
}
.place-location-banner:hover { background: #efdcb4; }
.place-location-banner strong { color: var(--green-900); }
/* Pre-existing bug, fixed here: this class's own "display: block" was
   overriding the browser's default [hidden] handling, so a photo with
   no location-banner content (most photos) still showed an empty gold
   box — noticed while screenshotting this page for the glass redesign,
   unrelated to it. Applies to both banners sharing this class
   (#place-location-banner and #place-chronology-banner). */
.place-location-banner[hidden] { display: none; }

/* The "facts" card at the top of a story page — the same information
   the photo's lightbox shows (name, date/location, category/credit,
   history, ref), so the story page doesn't make you go find the photo
   again to see it. */
.place-photo-panel {
  display: none;
  max-width: 900px;
  margin: 0 auto 36px;
  background: var(--glass-bg-green);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border-dark);
  color: #fff;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
}
.place-photo-panel.visible { display: flex; align-items: flex-start; }
.place-photo-panel-media {
  position: relative;
  flex: 1 1 320px;
  min-width: 240px;
}
.place-photo-panel-media img {
  width: 100%;
  height: auto;
  max-height: 520px;
  object-fit: cover;
  display: block;
  cursor: zoom-in;
}
/* Visible cue that the photo is clickable to zoom — cursor: zoom-in
   alone isn't enough, since there's no hover state at all on a
   touchscreen, which is exactly where zooming into detail is most
   useful. pointer-events: none so a click on the badge itself still
   falls through to the image underneath rather than needing its own
   click handler. */
.place-photo-panel-zoom-hint {
  position: absolute;
  right: 10px;
  bottom: 10px;
  background: rgba(10, 13, 11, 0.7);
  color: #fff;
  font-size: 0.78rem;
  font-weight: 600;
  padding: 6px 10px;
  border-radius: 20px;
  pointer-events: none;
  display: flex;
  align-items: center;
  gap: 5px;
}
/* Numbered-person markers (js/place.js renderNumberedPeople) — small
   circular buttons positioned by percentage over the photo, one per
   person the tool at admin/number-photo.html was used to click. Each
   opens the "Know more" popup pre-filled with its number rather than
   needing a second submission mechanism. Sized/coloured to read as
   clickable without competing with the zoom-hint badge. */
.place-photo-marker {
  position: absolute;
  width: 28px;
  height: 28px;
  margin-left: -14px;
  margin-top: -14px;
  border-radius: 50%;
  background: var(--gold-600);
  color: #fff;
  font-weight: 700;
  font-size: 0.85rem;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
  cursor: pointer;
  padding: 0;
}
.place-photo-marker:hover,
.place-photo-marker:focus-visible {
  background: var(--green-700);
  outline: none;
}
.place-photo-panel-info {
  flex: 1 1 260px;
  padding: 24px 26px;
}
.place-photo-panel-caption {
  font-family: var(--font-head);
  font-size: 1.15rem;
  margin: 0 0 4px;
}
.place-photo-panel-datelocation {
  color: #e7efe6;
  font-size: 0.88rem;
  font-weight: 600;
  margin: 0 0 4px;
}
.place-photo-panel-meta {
  color: #c7d9c9;
  font-size: 0.72rem;
  margin: 0;
}
.place-photo-panel-ref {
  color: rgba(255, 255, 255, 0.45);
  font-size: 0.72rem;
  font-family: ui-monospace, "SF Mono", "Courier New", monospace;
  margin: 10px 0 0;
}
.place-photo-panel-link {
  display: inline-block;
  margin-top: 14px;
  color: var(--gold-600);
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: none;
}
.place-photo-panel-link:hover { text-decoration: underline; }

/* A small, click-through-only preview map — not meant to be panned or
   zoomed in place, so the cursor/hover treatment reads as "one big
   button" rather than "a map you can't quite use." */
.place-mini-map {
  height: 160px;
  width: 100%;
  border-radius: var(--radius);
  overflow: hidden;
  margin-top: 14px;
  filter: saturate(0.9);
  transition: filter 0.15s ease;
}
.place-mini-map:hover { filter: saturate(1.1) brightness(1.03); }

@media (max-width: 640px) {
  .place-photo-panel { flex-direction: column; }
}

/* History — its own full-width, light, readable section (below the
   photo, above "Know more") rather than crammed into the facts
   panel's narrow dark info column next to the terser caption/date/
   credit/ref facts. */
.place-history {
  display: none;
  max-width: 900px;
  margin: 0 auto 36px;
  background: var(--paper);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg);
  padding: 24px 26px;
  box-shadow: var(--shadow);
}
.place-history.visible { display: block; }
.place-history h2 {
  font-size: 1.05rem;
  color: var(--green-900);
  margin: 0 0 10px;
}
.place-history p {
  margin: 0;
  line-height: 1.7;
  color: var(--ink);
  white-space: pre-wrap;
}

/* "Know more about this photo?" — same dark-card treatment as the
   facts panel above it, but its own full-width section rather than
   squeezed into that panel's narrow info column (see renderSubmitSection
   in js/place.js for why). */
.place-submit {
  display: none;
  max-width: 900px;
  margin: 0 auto 36px;
  background: var(--glass-bg-green);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border-dark);
  color: #fff;
  border-radius: var(--radius-lg);
  padding: 24px 26px;
  box-shadow: var(--shadow-lg);
}
.place-submit.visible { display: block; }
.place-submit form.stack { max-width: 480px; }

/* Other archive photos sharing the same location as this page's photo
   — only shown when there actually are any (relies on those other
   photos having the same Location text set, see CLAUDE.md). */
.place-related {
  display: none;
  max-width: 900px;
  margin: 44px auto 0;
}
.place-related.visible { display: block; }
.place-related h2 { font-size: 1.2rem; }
.place-related-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 16px;
}
.place-related-grid .place-photo-block { margin: 0; }

/* ---------- Historic map ---------- */

.map-layout {
  display: grid;
  grid-template-columns: 1fr 320px;
  gap: 20px;
  align-items: start;
}

.map-canvas-wrap {
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow);
  border: 1px solid var(--glass-border);
  position: relative;
  isolation: isolate;
}

#historic-map {
  height: 520px;
  width: 100%;
  background: var(--green-100);
  font-family: var(--font-body);
}

.map-sidebar {
  background: var(--glass-bg-strong);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: 16px;
  max-height: 520px;
  display: flex;
  flex-direction: column;
}

.map-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 12px;
}

/* A small pill-shaped tag/filter, used wherever the site needs a row
   of short clickable labels — map category filters, chronology era
   jump buttons, the homepage hero's chronology year links. Was
   ".map-filters button" (a parent-scoped descendant selector, with a
   hardcoded 20px radius instead of the shared pill token) — a
   standalone class instead, so the exact same look works on a <button>
   or an <a>, inside a ".map-filters" row or not. */
.chip {
  display: inline-block;
  border: 1px solid var(--glass-border);
  background: var(--glass-bg-strong);
  backdrop-filter: var(--glass-blur-sm);
  -webkit-backdrop-filter: var(--glass-blur-sm);
  color: var(--ink);
  font-size: 0.78rem;
  padding: 5px 11px;
  border-radius: var(--radius-pill);
  text-decoration: none;
  cursor: pointer;
  font-family: var(--font-body);
  transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
}
.chip.active {
  background: var(--green-900);
  border-color: var(--green-900);
  color: #fff;
}
.chip:hover:not(.active) {
  border-color: var(--green-700);
}

#map-list {
  list-style: none;
  margin: 0;
  padding: 0;
  overflow-y: auto;
  flex: 1;
}

.map-list-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 6px;
  border-bottom: 1px solid var(--line);
  border-left: 3px solid var(--pin-color, transparent);
  cursor: pointer;
  border-radius: 6px;
}
.map-list-item:hover { background: var(--green-100); }
.map-list-item:last-child { border-bottom: none; }

.map-list-thumb {
  width: 44px;
  height: 44px;
  border-radius: 8px;
  object-fit: cover;
  flex-shrink: 0;
  display: block;
}

.map-list-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--pin-color, var(--green-700));
  flex-shrink: 0;
}

.map-list-text { min-width: 0; }

.map-list-item strong {
  display: block;
  font-size: 0.9rem;
  color: var(--green-900);
  font-family: var(--font-head);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.map-list-period {
  display: block;
  font-size: 0.78rem;
  color: var(--ink-soft);
}

.map-list-empty {
  color: var(--ink-soft);
  font-size: 0.9rem;
  padding: 10px 6px;
}

/* Leaflet marker (divIcon) */
.map-pin-icon { background: none; border: none; }
.map-pin {
  display: block;
  width: 24px;
  height: 24px;
  border-radius: 50% 50% 50% 0;
  background: var(--pin-color, var(--green-700));
  border: 2px solid #fff;
  box-shadow: 0 2px 6px rgba(0,0,0,0.35);
  transform: rotate(-45deg);
  position: relative;
  top: 4px;
  left: 1px;
}

/* Leaflet popup theming */
.leaflet-popup-content-wrapper {
  border-radius: var(--radius);
  background: var(--glass-bg-strong);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  font-family: var(--font-body);
}
.leaflet-popup-content { margin: 14px 16px; }
.map-popup-cat {
  display: inline-block;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #fff;
  background: var(--pin-color, var(--green-700));
  padding: 3px 9px;
  border-radius: 20px;
  margin-bottom: 8px;
}
.map-popup h3 {
  font-size: 1rem;
  margin: 0 0 4px;
}
.map-popup-period {
  font-size: 0.8rem;
  color: var(--gold-600);
  font-weight: 600;
  margin: 0 0 8px;
}
.map-popup p { margin: 0 0 8px; font-size: 0.88rem; }
.map-popup-page-link {
  display: inline-block;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--green-700);
  text-decoration: none;
}
.map-popup-page-link:hover { color: var(--gold-600); }
.map-popup-photo-btn {
  display: block;
  width: 100%;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  margin: 6px 0 8px;
  text-decoration: none;
}
.map-popup-photo-btn img {
  width: 100%;
  border-radius: 6px;
  display: block;
  transition: opacity 0.15s ease;
}
.map-popup-photo-btn:hover img { opacity: 0.85; }
.map-popup-photo-hint {
  display: block;
  text-align: center;
  font-size: 0.7rem;
  color: var(--ink-soft);
  margin-top: 4px;
}

/* Leaflet tooltip theming — the short hover label shown on a pin
   before it's clicked (see js/map.js's bindTooltip calls). Kept
   deliberately plainer/smaller than the popup — it's a quick "what's
   this" hint, not the full detail. */
.leaflet-tooltip {
  font-family: var(--font-body);
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--green-900);
  background: var(--glass-bg-strong);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  border-radius: 6px;
  padding: 4px 10px;
  box-shadow: var(--shadow);
}
.leaflet-tooltip-top::before { border-top-color: var(--glass-border); }

@media (max-width: 780px) {
  .map-layout { grid-template-columns: 1fr; }
  #historic-map { height: 400px; }
  .map-sidebar { max-height: 300px; }
}

/* ---------- Category search bar ---------- */

.category-search-bar {
  padding-top: 30px;
  padding-bottom: 6px;
}

.category-search-label {
  display: block;
  font-family: var(--font-head);
  font-weight: 700;
  color: var(--green-900);
  font-size: 0.95rem;
  margin-bottom: 8px;
}

.photo-search-input-wide { max-width: none; }

/* The homepage's search box is centred as its own focal point under
   the hero — category.html's otherwise-identical bar stays
   left-aligned above its photo grid, so this only touches the
   homepage's copy via its extra .home-search-section class rather
   than changing .category-search-bar itself. */
.home-search-section { text-align: center; }
.home-search-section .category-search-label { text-align: center; }
.home-search-section .photo-search-input-wide { max-width: 640px; margin: 0 auto; }

/* Results dropdown for the homepage's own search box — empty (no
   query yet) renders no box at all via :not(:empty), same idea as the
   overlay's #site-search-results but inline on the page instead of in
   a modal, so it needs its own container styling. */
.home-search-results {
  list-style: none;
  margin: 10px auto 0;
  padding: 0;
  max-width: 640px;
  text-align: left;
}
.home-search-results:not(:empty) {
  background: var(--glass-bg-strong);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius);
  padding: 6px;
  box-shadow: var(--shadow);
}
.home-search-results li { border-top: 1px solid var(--line); }
.home-search-results li:first-child { border-top: none; }
.home-search-results a { display: block; padding: 12px 10px; text-decoration: none; }
.home-search-results a:hover { background: var(--green-100); border-radius: 6px; }

/* ---------- Photo archive ---------- */

.photo-search-input {
  width: 100%;
  max-width: 420px;
  display: block;
  font-size: 0.95rem;
  padding: 12px 18px;
  border: 1px solid var(--glass-border);
  background: var(--glass-bg);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border-radius: var(--radius-pill);
  font-family: var(--font-body);
  margin-bottom: 14px;
  box-shadow: var(--shadow);
}
.photo-search-input:focus {
  outline: 2px solid var(--green-700);
  outline-offset: 1px;
}

.photo-grid-status {
  color: var(--ink-soft);
  font-size: 0.88rem;
  margin: 0 0 14px;
}

.photo-grid-footer {
  margin-top: 20px;
  text-align: center;
}

/* Extends .btn (js/photos.js adds both classes) — border-radius and
   font-weight now come from there; everything below is a genuine
   override (this button is smaller and its border/transition differ
   from .btn's defaults), kept explicit rather than stripped, so this
   stays pixel-identical to before. Composing onto .btn instead of
   redeclaring from scratch means this now also gets .btn's :active
   press-feedback for free. */
.btn-show-all {
  background: var(--green-100);
  color: var(--green-900);
  border: 1px solid var(--glass-border);
  padding: 10px 22px;
  font-family: var(--font-body);
  font-size: 0.9rem;
  cursor: pointer;
  transition: background 0.15s ease;
}
.btn-show-all:hover { background: #d7e5d3; }

.photo-filters {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
  margin-bottom: 20px;
}
/* Title sits below the photo, not overlaid on top of it — was an
   absolutely-positioned label over the image (plus a darkening
   gradient just so the text stayed legible over an unpredictable
   photo); requested explicitly as clearer to read. Each tile is now a
   flex column: .photo-filter-photo (the aspect-ratio image box —
   js/photos.js sets its background-image, not the <a>'s own anymore)
   above, .photo-filter-label (plain flow text, own solid background)
   below. */
.photo-filters a {
  position: relative;
  display: flex;
  flex-direction: column;
  border: 3px solid transparent;
  border-radius: var(--radius-lg);
  overflow: hidden;
  text-decoration: none;
  font-family: var(--font-body);
  box-shadow: var(--shadow);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.photo-filter-photo {
  aspect-ratio: 3/2;
  background-color: var(--green-100);
  background-size: cover;
  background-position: center;
}
.photo-filter-label {
  color: #fff;
  background: var(--green-900);
  font-weight: 600;
  font-size: 0.85rem;
  text-align: center;
  padding: 10px 12px;
}
.photo-filters a:hover {
  border-color: rgba(255,255,255,0.6);
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
}

.photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 14px;
}

.photo-thumb {
  position: relative;
  display: block;
  border: 1px solid var(--glass-border);
  border-radius: var(--radius);
  overflow: hidden;
  padding: 0;
  cursor: pointer;
  aspect-ratio: 4/3;
  background: var(--green-100);
  box-shadow: var(--shadow);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.photo-thumb:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
}
.photo-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.2s ease;
}
.photo-thumb:hover img { transform: scale(1.05); }

.photo-thumb::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(20,30,22,0) 50%, rgba(17,26,19,0.82) 100%);
  pointer-events: none;
}

.photo-thumb-caption {
  position: absolute;
  z-index: 1;
  left: 8px;
  right: 8px;
  bottom: 7px;
  text-align: left;
  color: #fff;
}
.photo-thumb-caption strong {
  display: block;
  font-family: var(--font-head);
  font-size: 0.78rem;
  font-weight: 700;
  line-height: 1.25;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.photo-thumb-caption span {
  display: block;
  font-size: 0.68rem;
  color: rgba(255,255,255,0.85);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The form itself, reused inside the "Know more" popup on place.html
   (.place-know-more-modal below) — kept under this name since it grew
   up as the lightbox's submit form and every field id/label already
   refers to it that way; only the outer chrome changed. */
.photo-lightbox-submit h4 {
  color: #fff;
  font-family: var(--font-head);
  font-size: 0.95rem;
  margin: 0 0 4px;
}
.photo-lightbox-submit > p {
  color: #c7d9c9;
  font-size: 0.82rem;
  margin: 0 0 12px;
}
.photo-lightbox-submit form.stack { gap: 10px; max-width: none; }
.photo-lightbox-submit form.stack label {
  color: #e7efe6;
  font-size: 0.8rem;
  margin-bottom: 4px;
}
.photo-lightbox-submit form.stack input,
.photo-lightbox-submit form.stack textarea {
  background: rgba(255,255,255,0.92);
  font-size: 0.85rem;
  padding: 8px 10px;
}
.photo-lightbox-submit form.stack input[readonly] {
  background: rgba(255,255,255,0.55);
  color: #52584c;
  cursor: default;
}
.photo-lightbox-submit .btn-primary {
  align-self: flex-start;
  padding: 9px 18px;
  font-size: 0.85rem;
}

/* ---------- Know more modal (place.html) ---------- */

.place-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  max-width: 900px;
  margin: 4px auto 20px;
}
/* Side by side, the two buttons are naturally different widths (their
   labels are different lengths) — fine on a wide screen, but once the
   row is too narrow to fit them both and they stack instead, two
   different-width buttons left-aligned above one another reads as
   lopsided rather than a matched pair. Below that point, make them
   full-width and equal instead of letting them stack at their own
   natural sizes. */
@media (max-width: 480px) {
  .place-actions { flex-direction: column; }
  .place-actions .btn { width: 100%; text-align: center; }
}
/* .btn-outline is styled for the dark hero background — this section
   of the page is light, so the download button gets its own outline
   style rather than reusing that class here. */
.place-download-pdf-btn {
  background: transparent;
  border-color: var(--green-700);
  color: var(--green-700);
}
.place-download-pdf-btn:hover { background: var(--green-700); color: #fff; }
.place-download-pdf-btn:disabled { opacity: 0.6; cursor: default; }

.place-know-more-modal {
  position: fixed;
  inset: 0;
  background: rgba(10, 13, 11, 0.82);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  z-index: 400;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.place-know-more-modal.open { display: flex; }

.place-know-more-inner {
  position: relative;
  width: min(480px, 94vw);
  max-height: 88vh;
  overflow-y: auto;
  /* The stronger glass tier, not the standard one — this card already
     sits over its own dimmed/blurred backdrop (.place-know-more-modal),
     so it needs the extra opacity to stay legible rather than reading
     as blur-on-blur. */
  background: var(--glass-bg-green-strong);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border-dark);
  border-radius: var(--radius-lg);
  padding: 24px;
  box-shadow: var(--shadow-lg);
}

.place-know-more-close {
  position: absolute;
  top: 12px;
  right: 16px;
  background: none;
  border: none;
  color: #fff;
  font-size: 2rem;
  line-height: 1;
  cursor: pointer;
}

/* Full-screen zoom/pan viewer for a photo's own page — click the main
   photo to open. Built on vendor/panzoom (vendored the same way as
   Leaflet/jsPDF/qrcode-generator — a small, no-build-step, MIT library
   rather than hand-rolling pinch-zoom gesture math), which handles
   wheel-zoom, drag-to-pan and touch pinch-zoom on whatever element it's
   given; +/-/Reset buttons exist alongside it since not everyone
   discovers scroll-to-zoom on their own. Same fixed-overlay/.open
   pattern as .place-know-more-modal above, just without the backdrop
   blur (a photo you're trying to examine closely shouldn't sit behind
   a blurred backdrop) and at a higher z-index so it can be opened from
   any photo page state.
   */
.place-zoom-overlay {
  position: fixed;
  inset: 0;
  background: rgba(8, 10, 9, 0.94);
  z-index: 500;
  display: none;
  align-items: center;
  justify-content: center;
}
.place-zoom-overlay.open { display: flex; }

.place-zoom-stage {
  width: 100%;
  height: 100%;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  touch-action: none;
}
.place-zoom-stage img {
  max-width: 90vw;
  max-height: 90vh;
  width: auto;
  height: auto;
  user-select: none;
  -webkit-user-drag: none;
}

/* Shared base for a solid-white circular icon button over a photo
   (needs to stay legible over any colour) — .place-zoom-close and
   .place-zoom-nav used to redeclare the same background/border/color/
   radius/shadow/hover independently; this is that shared look, with
   each keeping only its own position/size on top of it. */
.icon-btn-circle {
  background: #fff;
  border: none;
  color: var(--green-900);
  border-radius: 50%;
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
}
.icon-btn-circle:hover { background: var(--gold-100); }

.place-zoom-close {
  position: absolute;
  top: 16px;
  right: 20px;
  font-size: 1.8rem;
  line-height: 1;
  width: 44px;
  height: 44px;
  z-index: 2;
}

.place-zoom-hint {
  position: absolute;
  top: 22px;
  left: 50%;
  transform: translateX(-50%);
  color: rgba(255, 255, 255, 0.7);
  font-size: 0.85rem;
  margin: 0;
  z-index: 2;
  pointer-events: none;
}

.place-zoom-controls {
  position: absolute;
  bottom: 22px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 10px;
  z-index: 2;
}
.place-zoom-btn {
  background: #fff;
  border: none;
  color: var(--green-900);
  font-size: 1.1rem;
  font-weight: 700;
  min-width: 44px;
  padding: 10px 16px;
  border-radius: var(--radius-pill);
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
}
.place-zoom-btn:hover { background: var(--gold-100); }

/* Prev/Next through a multi-photo gallery (event.html only — place.html's
   overlay shows one fixed photo with no siblings to step through, so it
   never renders these buttons at all). Extends .icon-btn-circle (see
   above) for the same reason .place-zoom-close does: needs to stay
   legible over a photo of any colour. */
.place-zoom-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  font-size: 2rem;
  line-height: 1;
  width: 48px;
  height: 48px;
  z-index: 2;
}
.place-zoom-nav:hover { background: var(--gold-100); }
.place-zoom-nav[hidden] { display: none; }
.place-zoom-prev { left: 16px; }
.place-zoom-next { right: 16px; }

@media (max-width: 560px) {
  /* Cramped next to the close button at this width, and pinch-to-zoom
     is the natural first thing to try on a touchscreen anyway. */
  .place-zoom-hint { display: none; }
  .place-zoom-nav { width: 40px; height: 40px; font-size: 1.6rem; }
  .place-zoom-prev { left: 6px; }
  .place-zoom-next { right: 6px; }
}

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

.site-footer {
  background: var(--green-900);
  color: #d9e6db;
  padding: 40px 0 24px;
  margin-top: 40px;
}
.footer-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 28px;
  margin-bottom: 24px;
}
.site-footer h4 { color: #fff; font-size: 1rem; }
.site-footer a { color: #d9e6db; }
.site-footer a:hover { color: var(--gold-100); }
.site-footer ul { list-style: none; padding: 0; margin: 0; }
.site-footer li { margin-bottom: 8px; }
.footer-bottom {
  border-top: 1px solid rgba(255,255,255,0.15);
  padding-top: 18px;
  font-size: 0.82rem;
  color: #b7cbb9;
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
}

/* ---------- Responsive ---------- */

@media (max-width: 980px) {
  .main-nav {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--glass-bg-strong);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    border-bottom: 1px solid var(--glass-border);
    flex-direction: column;
    align-items: stretch;
    padding: 10px;
    box-shadow: var(--shadow);
  }
  .main-nav.open { display: flex; }
  .main-nav a { padding: 12px; border-radius: var(--radius); }
  .nav-toggle { display: inline-flex; }
}

/* Below ~560px (the full header needs a measured 547px to fit
   everything on one line — checked directly, not assumed), the brand
   text + "Menu" + "Search" buttons together are wider than the
   screen even with .main-nav already collapsed — .brand's
   flex-shrink: 0 keeps the logo from ever compressing, so on a
   narrow phone the two header buttons were being pushed straight off
   the right edge, causing a horizontal scrollbar on every page.
   Dropping the subtitle, shrinking the brand mark/text, and switching
   both buttons to icon-only (font-size: 0 hides their text node; the
   <svg> icons inside have their own explicit width/height, so they're
   unaffected and stay visible) reclaims enough width without touching
   any page's HTML. Tightened further after the first pass still
   overflowed on real 375px and 320px viewports — measure on an actual
   narrow viewport before assuming a fix like this has enough
   headroom, font-metric differences eat the margin fast. */
@media (max-width: 560px) {
  .brand { gap: 6px; }
  .brand-mark { width: 32px; height: 32px; font-size: 15px; }
  .brand-text small { display: none; }
  .brand-text { font-size: 0.9rem; }
  .nav-toggle, .search-btn { font-size: 0; padding: 10px; gap: 0; }
}

/* The smallest common phone width (iPhone SE-class, ~320px) still
   didn't fit after the 480px pass above — checked on an actual 320px
   viewport, not assumed. A bit more off the header's own edge padding
   and gaps, plus the brand mark/text one size down again. */
@media (max-width: 340px) {
  .site-header .container { padding-left: 12px; padding-right: 12px; gap: 6px; }
  .brand-mark { width: 28px; height: 28px; font-size: 13px; }
  .brand-text { font-size: 0.8rem; }
  .nav-toggle, .search-btn { padding: 8px; }
}
