/* High Corn Mill — shared styles */

/* Fonts are served from this origin, latin subset only. Nothing is fetched
   from a font CDN, so there is no third party in the critical path. */
@font-face {
  font-family: 'Quicksand'; font-style: normal; font-weight: 300 700; font-display: swap;
  src: url('../fonts/quicksand-var.woff2') format('woff2');
}

:root {
  /* Green and gold are sampled straight from the logo artwork so the nav mark
     and the page never disagree: #016831 wordmark, #c7a52e wheel. */
  --green: #016831;
  --green-dark: #015327;
  --green-deep: #013d1f;
  --gold: #c7a52e;
  --gold-dark: #a88820;
  /* Logo gold darkened until it clears 4.5:1 on white — for small accent text */
  --gold-deep: #8a6d15;
  /* And lifted the other way until it clears 3:1 on the green panel — for a
     graphic that has to read against the dark ground rather than sit in it */
  --gold-light: #d8b743;
  --cream: #faf8f2;
  --cream-deep: #f1ece0;
  /* The green at the tint the nav pill and the menu use */
  --green-soft: #e7f0e9;
  --ink: #1f2620;
  --muted: #5b6459;
  --line: #e2ded3;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }
/* Quicksand throughout — the rounded-terminal match for the lettering ringing
   the badge. Prose is set normally; the caps-and-tracking treatment belongs to
   headings, menus and labels, where it reads as lettering rather than text. */
body {
  font-family: 'Quicksand', -apple-system, sans-serif;
  color: var(--ink);
  background: var(--cream);
  line-height: 1.72;
  font-size: 1rem; font-weight: 500;
}
h1, h2, h3, h4 { font-family: 'Quicksand', -apple-system, sans-serif; line-height: 1.14; }

/* ===== Weight scale =====
   Quicksand runs 300-700, so 700 is the ceiling and only one tier gets it at
   display size: the H1. Everything else steps down. Small type steps back UP —
   700 on a 12px tracked label carries about the same presence as 600 on a 40px
   heading, so a label being numerically bolder than the heading above it is
   correct rather than an inversion. Within a tier, size does the separating. */
h1                                        { font-weight: 700; }  /* thickest, display only */
h2, h3, h4, .title, .cta-band h2,
.tile span, .social-head h2, .bee-panel h3,
.footer .discover                         { font-weight: 600; }  /* headings, a step under H1 */
.stat b, .timeline b, .explore-card span  { font-weight: 600; }  /* display numerals and tile labels */
.nav-links a, .panel-pages a, .btn        { font-weight: 700; }  /* navigation and controls */
.kicker, .title .thin, .dir-tag,
.stat span, .field label, .panel-extra h5,
.footer .discover .thin,
.footer-right h4, .notice h4              { font-weight: 700; }  /* small tracked labels */
p, li                                     { font-weight: 500; }  /* running text */
p.lead                                    { font-weight: 600; }
/* Display headings, same treatment as everything else — kept as its own rule
   so the sizes and weights below have something to hang off. */
h1, .title, .cta-band h2, .panel-rows h2, .soon h2 {
  text-transform: uppercase; letter-spacing: .16em;
}
/* Kept explicit rather than left to inherit, so these survive any later
   change to the body rule. */
h3, h4, .crumbs, .tile span, .explore-card span, .panel-extra a,
.social-head .handle, .footer-bottom, .dir-links a,
.timeline b, .nav-panel .panel-extra a {
  text-transform: uppercase; letter-spacing: .16em;
}
/* Where the visible text IS an email or a web address, leave it as typed —
   capitalising one makes it harder to read and harder to trust. Links whose
   text is a label ("Email the practice") take the caps like everything else. */
.panel-extra a[href^="mailto:"],
.phero-facts a[href^="mailto:"], .dir-links a[href^="http"] {
  text-transform: none; letter-spacing: .01em;
}
img { max-width: 100%; height: auto; display: block; }
a { color: var(--green); }
.wrap { max-width: 1200px; margin: 0 auto; padding: 0 28px; }

/* Gold wave flourish */
.wave { display: block; width: 110px; height: 14px; margin: 18px 0 0; }
.wave path { stroke: var(--gold); stroke-width: 3.6; fill: none; stroke-linecap: round; }

/* ===== Top utility bar =====
   Solid green, the way the site started. No rule underneath: the change of
   colour from the green bar to the white nav is the edge. */
.topbar {
  background: var(--green); color: #fff; font-size: 1.02rem;
}
.topbar-inner {
  max-width: 1200px; margin: 0 auto; padding: 12px 28px;
  display: flex; align-items: center; justify-content: flex-end; gap: 30px;
}
/* Set exactly like the main nav below it, a size down so the row still fits */
.topbar a {
  color: #fff; text-decoration: none;
  font-family: 'Quicksand', sans-serif; font-weight: 600; font-size: .76rem;
  letter-spacing: .16em; text-transform: uppercase;
  transition: color .2s ease;
}
.topbar a:hover { color: var(--gold); }
.topbar .socials { display: flex; gap: 20px; align-items: center; margin-left: 44px; }
.topbar .socials svg { width: 21px; height: 21px; fill: #fff; display: block; }
.topbar .socials a:hover svg { fill: var(--gold); }

.topbar-inner, .nav-inner { position: relative; }

/* ===== Main nav ===== */
.nav {
  background: #fff; position: sticky; top: 0; z-index: 130;
  box-shadow: 0 1px 0 var(--line), 0 20px 40px -34px rgba(48, 56, 46, .18);
}
.nav-inner {
  max-width: 1200px; margin: 0 auto; padding: 18px 28px;
  display: flex; align-items: center; gap: 26px;
}
/* Never let the logo be a flex casualty. It was shrinking to fit the row, and
   because img{max-width:100%} clamps the picture to its parent while the height
   stays pinned, the wordmark came out 17.6% narrower than it should be — a
   squashed logo rather than a smaller one. flex-shrink pins the box; max-width
   none means even a mis-sized box could not distort the artwork again. */
.nav-logo { margin-right: auto; flex-shrink: 0; }
.nav-logo img { height: 68px; width: auto; max-width: none; }
/* The pill is why the gap is 4px and not 32: the padding round each label is
   doing the spacing now, and 32 on top of it pushed the row off the end. */
.nav-links { display: flex; align-items: center; gap: 3px; list-style: none; }
/* A pill rather than an underline. Same shape language as the buttons and the
   cards, and it gives the menu a friendlier hit area than a 2px rule. */
.nav-links a {
  color: var(--ink); text-decoration: none;
  font-family: 'Quicksand', sans-serif; font-weight: 700;
  font-size: .86rem; letter-spacing: .12em; text-transform: uppercase;
  padding: 10px 11px; border-radius: 999px;
  /* Two-word labels must not break in half. Adding What's On took the row past
     the width where flex would rather wrap the words inside each pill than
     admit the row is full — which reads as seven broken labels, not a menu. */
  white-space: nowrap;
  transition: background .2s ease, color .2s ease;
}
.nav-links a:hover, .nav-links a.active { background: var(--green-soft); color: var(--green); }

/* ===== About, with a submenu =====
   The label stays a real link to the About page and the chevron is a separate
   button beside it. That way someone who wants the page gets the page and
   someone who wants the list gets the list — rather than the common pattern
   where the top item does nothing and the first submenu entry repeats it.
   The pill highlight lives on the pair so the two read as one control. */
.nav-drop { position: relative; display: flex; align-items: center; border-radius: 999px; transition: background .2s ease; }
.nav-drop > a { padding-right: 3px; }
.nav-drop-btn {
  display: grid; place-items: center; width: 24px; align-self: stretch;
  padding: 0 7px 0 0; border: 0; background: none; cursor: pointer;
  color: var(--ink); border-radius: 999px;
  transition: color .2s ease;
}
.nav-drop-btn svg { transition: transform .25s ease; }
.nav-drop:hover, .nav-drop.is-open, .nav-drop:not(.is-js):focus-within { background: var(--green-soft); }
.nav-drop:hover > a, .nav-drop.is-open > a, .nav-drop:not(.is-js):focus-within > a { background: none; color: var(--green); }
.nav-drop:hover .nav-drop-btn, .nav-drop.is-open .nav-drop-btn, .nav-drop:not(.is-js):focus-within .nav-drop-btn { color: var(--green); }
.nav-drop.is-open .nav-drop-btn svg { transform: rotate(180deg); }
/* The page you are on still marks the pill, open or not */
.nav-drop.has-active { background: var(--green-soft); }
.nav-drop.has-active > a { color: var(--green); }
.nav-drop.has-active .nav-drop-btn { color: var(--green); }

.nav-drop-menu {
  /* Anchored to the pill's right edge, not its left. About sits second from the
     end of the row, so a left-anchored panel hangs 3px past the viewport at
     1200px wide — and a hidden absolute box still counts towards scrollWidth,
     so that showed up as a horizontal scrollbar on a menu nobody had opened. */
  position: absolute; top: 100%; right: 0; z-index: 60;
  min-width: 224px; margin: 12px 0 0; padding: 8px; list-style: none;
  background: #fff; border-radius: 22px; border: 1px solid var(--line);
  box-shadow: 0 26px 52px -24px rgba(35, 40, 31, .34);
  opacity: 0; visibility: hidden; transform: translateY(-7px);
  transition: opacity .18s ease, transform .18s ease, visibility .18s;
}
/* Bridges the gap between pill and panel so the menu does not shut while the
   pointer is crossing it. */
.nav-drop-menu::before { content: ""; position: absolute; left: 0; right: 0; top: -12px; height: 12px; }
/* focus-within is the fallback that keeps the submenu reachable by tab if
   js/site.js never loads. Once the script is running it adds .is-js and takes
   the keyboard over via the chevron button, because otherwise Escape cannot
   close the menu: returning focus to the button, which sits inside .nav-drop,
   would re-satisfy focus-within and open it straight back up. */
.nav-drop:not(.is-js):focus-within .nav-drop-menu,
.nav-drop.is-open .nav-drop-menu { opacity: 1; visibility: visible; transform: none; }
@media (hover: hover) and (pointer: fine) {
  .nav-drop:hover .nav-drop-menu { opacity: 1; visibility: visible; transform: none; }
}
.nav-drop-menu li { list-style: none; }
.nav-links .nav-drop-menu a {
  display: block; padding: 11px 15px; border-radius: 15px;
  font-size: .82rem; letter-spacing: .085em; white-space: nowrap;
}
.nav-links .nav-drop-menu a:hover { background: var(--cream-deep); color: var(--green); }
.nav-links .nav-drop-menu a[aria-current="page"] { background: var(--green-soft); color: var(--green); }
@media (prefers-reduced-motion: reduce) {
  .nav-drop-menu, .nav-drop-btn svg { transition: none; }
}
/* Burger is the small-screen nav only — the inline links cover desktop */
.nav-burger { display: none; background: none; border: 0; cursor: pointer; padding: 6px 0 6px 4px; }
.nav-burger span {
  display: block; width: 34px; height: 4.5px; background: var(--green);
  margin: 6px 0; border-radius: 3px; transition: transform .25s ease, opacity .25s ease;
}
.nav-burger:hover span { background: var(--green-dark); }
.nav-burger.open span:nth-child(1) { transform: translateY(10.5px) rotate(45deg); }
.nav-burger.open span:nth-child(2) { opacity: 0; }
.nav-burger.open span:nth-child(3) { transform: translateY(-10.5px) rotate(-45deg); }

/* ===== Skip link =====
   First thing in the tab order on every page, and the only reason it is not
   visible is that it has nothing to say until it is focused. */
.skip {
  position: absolute; left: 12px; top: -60px; z-index: 300;
  background: var(--green); color: #fff; text-decoration: none;
  font-weight: 700; font-size: .8rem; letter-spacing: .16em; text-transform: uppercase;
  padding: 12px 20px; border-radius: 999px;
  transition: top .2s ease;
}
.skip:focus { top: 12px; }
#main:focus { outline: none; }

/* ===== Mobile menu =====
   Was a dropdown of small links hanging off the header. It is now a drawer:
   full height, off the right edge, with the three things somebody standing in
   Skipton actually wants — directions, phone, email — above the page list
   rather than buried under it. Rows are 52px so they can be hit with a thumb.

   It slides on transform alone, which the compositor handles. visibility is
   what keeps the closed panel out of the tab order; display:none would do that
   too but cannot be transitioned, so it is delayed by the length of the slide
   on the way out and immediate on the way in. */
.nav-scrim {
  position: fixed; inset: 0; z-index: 190;
  background: rgba(20, 26, 18, .5);
  opacity: 0; pointer-events: none; transition: opacity .26s ease;
}
.nav-scrim.open { opacity: 1; pointer-events: auto; }

.nav-panel {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 200;
  width: min(87vw, 396px);
  background: #fff; display: flex; flex-direction: column;
  overflow-y: auto; overscroll-behavior: contain;
  box-shadow: -22px 0 60px rgba(20, 26, 18, .3);
  visibility: hidden; transform: translateX(101%);
  transition: transform .28s cubic-bezier(.4, 0, .2, 1), visibility 0s .28s;
}
.nav-panel.open { visibility: visible; transform: translateX(0); transition-delay: 0s, 0s; }

.panel-head {
  position: sticky; top: 0; z-index: 2; background: #fff;
  display: flex; align-items: center; justify-content: space-between;
  padding: 17px 20px 15px; border-bottom: 1px solid var(--line);
}
.panel-title {
  font-size: .74rem; font-weight: 700; letter-spacing: .2em;
  text-transform: uppercase; color: var(--gold-deep);
}
.panel-close {
  width: 46px; height: 46px; margin-right: -8px; border-radius: 50%;
  border: 1.5px solid var(--line); background: #fff; color: var(--green);
  display: grid; place-items: center; cursor: pointer;
}
.panel-close:hover { border-color: var(--green); }

/* Directions, call, email. The point of the whole rebuild. */
.panel-acts { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; padding: 18px 20px 14px; }
.pact {
  display: grid; place-items: center; gap: 9px; min-height: 90px; padding: 16px 6px;
  background: var(--green-soft); border-radius: 22px; color: var(--green);
  text-decoration: none; font-size: .66rem; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; text-align: center;
  transition: background .18s ease;
}
.pact:hover, .pact:active { background: #d8e7dc; }

.panel-pages { display: flex; flex-direction: column; padding: 4px 10px 10px; }
.panel-pages a {
  display: flex; align-items: center; min-height: 52px; padding: 13px 12px;
  border-radius: 16px; color: var(--ink); text-decoration: none;
  font-family: 'Quicksand', sans-serif; font-size: 1rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase;
}
.panel-pages a::after {
  content: ""; width: 8px; height: 8px; margin-left: auto;
  border-top: 2px solid currentColor; border-right: 2px solid currentColor;
  transform: rotate(45deg); opacity: .3;
}
.panel-pages a:hover { background: var(--cream-deep); }
/* The page you are on, marked in the markup rather than worked out in script */
.panel-pages a[aria-current="page"] { background: var(--green-soft); color: var(--green); }
.panel-pages a[aria-current="page"]::after { opacity: .6; }

/* The drawer has no room for hover menus, so About's children are simply shown
   nested under it. Indent, a smaller size and a quieter colour all say the same
   thing, so the relationship survives even if one of the three is missed. */
.panel-sub { display: flex; flex-direction: column; padding-left: 20px; margin: 0 0 6px; }
.panel-pages .panel-sub a {
  min-height: 46px; padding: 10px 12px;
  font-size: .84rem; letter-spacing: .13em; color: var(--muted);
}
.panel-pages .panel-sub a::after { width: 6px; height: 6px; }
.panel-pages .panel-sub a[aria-current="page"] { color: var(--green); }

.panel-extra {
  margin-top: auto; display: grid; gap: 12px; align-content: start;
  padding: 20px 22px calc(24px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
}
.panel-extra h5 {
  font-size: .72rem; letter-spacing: .2em; text-transform: uppercase;
  color: var(--gold-deep); font-family: 'Quicksand', sans-serif; margin-bottom: 2px;
}
.panel-extra a { color: var(--muted); text-decoration: none; font-weight: 600; font-size: .95rem; }
.panel-extra a:hover { color: var(--green); }

/* ===== Quick action bar =====
   Phones only, and fixed, because "how do I get there" and "can I ring them"
   are the two questions this site exists to answer for somebody holding a phone
   in Skipton — neither should cost a scroll to the footer. Body padding below
   reserves its height so it never sits on top of the last line of the page. */
.quickbar { display: none; }
@media (max-width: 700px) {
  .quickbar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 120;
    display: grid; grid-template-columns: repeat(3, 1fr);
    background: rgba(255, 255, 255, .97);
    border-top: 1px solid var(--line);
    box-shadow: 0 -8px 26px rgba(35, 40, 31, .09);
    padding-bottom: env(safe-area-inset-bottom);
  }
  .quickbar a {
    display: grid; place-items: center; gap: 4px; min-height: 58px; padding: 9px 4px 10px;
    color: var(--green); text-decoration: none;
    font-size: .62rem; font-weight: 700; letter-spacing: .11em; text-transform: uppercase;
  }
  .quickbar a + a { border-left: 1px solid var(--line); }
  .quickbar a:active { background: var(--green-soft); }
  /* Two navigations on screen at once is one too many, so the bar drops out
     of the way while the drawer is open rather than stacking under it. */
  body.menu-open .quickbar { transform: translateY(100%); pointer-events: none; }
  .quickbar { transition: transform .26s cubic-bezier(.4, 0, .2, 1); }
  body { padding-bottom: 68px; }
}

/* ===== Hero film =====
   All that survives of the old full-bleed hero. The home page frames the film
   in a card now, and this makes the video fill whatever box it is given; the
   rest of that hero — the dark scrim, the watermark, the scroll arrow — went
   with the layout it belonged to. js/site.js still finds the element by this
   class, so the name stays. */
.hero-video {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; z-index: 0;
}

/* ===== Marquee ===== */
.marquee { background: var(--green); overflow: hidden; padding: 13px 0; }
.marquee-track { display: flex; width: max-content; animation: marquee 36s linear infinite; }
.marquee-track span {
  color: rgba(255, 255, 255, .92); font-size: .82rem; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase; white-space: nowrap; padding-right: 26px;
}
/* Separator is the wheel off the logo rather than a stray dingbat */
.marquee-track span::after {
  content: ""; display: inline-block; vertical-align: -3px;
  width: 15px; height: 15px; margin: 0 26px 0 26px;
  background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%23c7a52e" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><circle cx=%2212%22 cy=%2212%22 r=%228.6%22/><circle cx=%2212%22 cy=%2212%22 r=%222.4%22/><path d=%22M12 3.4v6.2M12 14.4v6.2M3.4 12h6.2M14.4 12h6.2%22/><path d=%22M5.9 5.9l4.4 4.4M13.7 13.7l4.4 4.4M18.1 5.9l-4.4 4.4M10.3 13.7l-4.4 4.4%22/></svg>') center/contain no-repeat;
}
@keyframes marquee { to { transform: translateX(-50%); } }

/* ===== Buttons ===== */
.btn {
  display: inline-block; font-family: 'Quicksand', sans-serif; font-weight: 700;
  font-size: .86rem; letter-spacing: .16em; text-transform: uppercase;
  padding: 16px 34px; border-radius: 999px; text-decoration: none; cursor: pointer;
  transition: background .2s ease, color .2s ease;
}
.btn::after { content: "→"; display: inline-block; margin-left: 12px; transition: transform .2s ease; }
.btn:hover::after { transform: translateX(5px); }
/* Green primary, logo gold on hover. Text flips to deep green on the gold
   because white on gold is nowhere near enough contrast. */
.btn-primary { background: var(--green); color: #fff; }
.btn-primary:hover { background: var(--gold); color: var(--green-deep); }
.btn-green { background: var(--green); color: #fff; }
.btn-green:hover { background: var(--green-dark); }
.btn-outline { border: 2px solid #fff; color: #fff; }
.btn-outline:hover { background: #fff; color: var(--green); }
.btn-outline-green { border: 2px solid var(--green); color: var(--green); }
.btn-outline-green:hover { background: var(--green); color: #fff; }
.btn-row { display: flex; gap: 14px; flex-wrap: wrap; }

/* ===== Sections ===== */
section { padding: 100px 0; }
.kicker {
  color: var(--gold-deep); font-weight: 700; letter-spacing: .2em;
  text-transform: uppercase; font-size: .8rem; margin-bottom: 14px;
}
.title { font-size: clamp(1.75rem, 3.1vw, 2.5rem); margin-bottom: 22px; }
/* Section eyebrows are set like the ones on the hero cards, which in turn take
   after the lettering ringing the badge: caps, wide tracking, gold. */
.title .thin {
  display: block; font-family: 'Quicksand', -apple-system, sans-serif;
  font-weight: 700; font-style: normal; text-transform: uppercase;
  letter-spacing: .2em; font-size: .8rem; line-height: 1.5;
  color: var(--gold-deep); margin-bottom: 14px;
}

/* Arched image — Saratoga signature */
/* Photo frames all share one rounded-corner radius — no arches */

/* Welcome */
.welcome { background: #fff; }
.welcome-grid { display: grid; grid-template-columns: 1fr 1.05fr; gap: 70px; align-items: center; }
.welcome-grid .copy > p { color: var(--muted); margin-bottom: 22px; max-width: 34em; }
.welcome-grid .copy > p.lead { color: var(--ink); font-size: 1.16rem; font-weight: 600; }
.welcome-grid .btn { margin-top: 6px; }
.map-fig { background: var(--cream); border-radius: 38px; padding: 30px 22px; }
.map-fig img { width: 100%; height: auto; }
.stats { display: flex; gap: 44px; margin: 34px 0 36px; flex-wrap: wrap; }
.stat b { font-family: 'Quicksand', sans-serif; font-size: 2.3rem; color: var(--green); display: block; line-height: 1.1; }
.stat span { font-size: .8rem; color: var(--muted); letter-spacing: .16em; text-transform: uppercase; font-weight: 600; }

/* Tiles */
.tiles { background: #fff; padding-top: 0; }
.tiles-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 20px; margin-bottom: 32px;
}
.tiles-head .title { margin-bottom: 0; }
.tiles-head .wave { margin-top: 14px; }
.tile-arrows { display: none; }
.tile-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
.tile {
  position: relative; aspect-ratio: 1 / 1; border-radius: 34px; overflow: hidden;
  display: flex; align-items: flex-end; justify-content: center; text-decoration: none;
}
.tile img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  transition: transform .6s ease;
}
.tile::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(23, 33, 14, .05) 35%, rgba(23, 33, 14, .72));
  transition: background .3s ease;
}
.tile span {
  position: relative; z-index: 2; color: #fff; font-family: 'Quicksand', sans-serif;
  font-size: clamp(1.5rem, 2.6vw, 2rem); font-weight: 600; letter-spacing: .03em;
  text-align: center; padding: 0 16px 26px;
  text-shadow: 0 2px 14px rgba(0, 0, 0, .5);
}
.tile span::after {
  content: "→"; display: block; font-family: 'Quicksand', sans-serif; font-size: .55em;
  width: 40px; height: 40px; line-height: 40px; margin: 12px auto 0;
  border: 1.5px solid rgba(255, 255, 255, .8); border-radius: 50%;
  opacity: 0; transform: translateY(8px); transition: opacity .3s ease, transform .3s ease;
}
.tile:hover span::after { opacity: 1; transform: translateY(0); }
.tile:hover img { transform: scale(1.07); }
.tile:hover::after { background: linear-gradient(180deg, rgba(46, 100, 23, .15) 30%, rgba(28, 63, 11, .8)); }

/* Things to do */
.things { background: var(--cream); }
.things-grid { display: grid; grid-template-columns: 1.02fr .98fr; gap: 80px; align-items: center; }
.things-grid .copy p { color: var(--muted); margin-bottom: 22px; max-width: 36em; }
.things-grid .btn { margin-top: 8px; }
.things-art { position: relative; padding: 30px 30px 0 0; }
.things-art .photo img { width: 100%; aspect-ratio: 4 / 4.6; object-fit: cover; border-radius: 34px; box-shadow: 0 24px 60px rgba(35, 40, 31, .2); }
.things-art .badge {
  position: absolute; top: 0; right: 0; width: 168px; height: auto;
  transform: rotate(9deg); z-index: 2;
}

/* Green panels */
.panels { background: var(--green); color: #fff; }
.panels-grid { display: grid; grid-template-columns: 1.08fr .92fr; gap: 80px; align-items: center; }
.panel-rows h2 { font-size: clamp(1.9rem, 3.4vw, 2.6rem); margin-bottom: 8px; }
.panel-rows h2 + p { color: rgba(255, 255, 255, .85); margin-bottom: 26px; }
.panel-row {
  display: grid; grid-template-columns: 138px 1fr; gap: 24px; align-items: center;
  padding: 24px 0; border-bottom: 1px solid rgba(255, 255, 255, .22);
}
.panel-row:last-child { border-bottom: 0; }
.panel-row img { width: 138px; height: 104px; object-fit: cover; border-radius: 24px; }
.panel-row h3 { font-size: 1.45rem; margin-bottom: 5px; }
.panel-row p { color: rgba(255, 255, 255, .88); font-size: .97rem; margin-bottom: 8px; }
.panel-row a { color: var(--gold); font-weight: 600; font-size: .92rem; text-decoration: none; }
.panel-row a:hover { text-decoration: underline; text-underline-offset: 4px; }
.bee-panel { text-align: center; }
.bee-panel .bee-photo {
  width: min(340px, 80%); aspect-ratio: 4 / 4.2; object-fit: cover; margin: 0 auto 30px;
  border-radius: 34px; box-shadow: 0 20px 50px rgba(0, 0, 0, .25);
}
.bee-panel h3 { font-family: 'Quicksand', sans-serif; font-size: 2rem; margin-bottom: 14px; }
.bee-panel p { color: rgba(255, 255, 255, .9); margin-bottom: 28px; max-width: 30em; margin-left: auto; margin-right: auto; }

/* Social strip */
.social { background: #fff; }
.social-head { display: flex; align-items: flex-end; gap: 20px; flex-wrap: wrap; margin-bottom: 36px; }
.social-head h2 {
  font-size: clamp(1.7rem, 2.9vw, 2.3rem); color: var(--green);
  text-transform: uppercase; letter-spacing: .16em; font-weight: 600;
}
.social-head p { color: var(--muted); padding-bottom: 6px; }
.social-head .handle {
  margin-left: auto; display: flex; align-items: center; gap: 10px;
  color: var(--ink); font-weight: 600; text-decoration: none; padding-bottom: 6px;
}
.social-head .handle svg { width: 26px; height: 26px; color: var(--green); }
.social-head .handle:hover { color: var(--green); }
.social-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; align-items: end; }
.social-grid img {
  width: 100%; aspect-ratio: 4 / 4.4; object-fit: cover; border-radius: 34px;
  transition: transform .3s ease, box-shadow .3s ease;
}
.social-grid img:hover { transform: translateY(-8px); box-shadow: 0 18px 40px rgba(35, 40, 31, .18); }

/* ===== Inner page heroes =====
   One treatment, used on every inner page: a photograph running flush under the
   nav with a white card lapping over its lower edge. Light ground, ink type,
   gold rule along the top of the card. */

/* The generic `section` rule puts 100px of air top and bottom. On a hero that
   reads as a dead band under the nav, so heroes opt out and set their own. */
.phero { position: relative; overflow: hidden; padding: 0; }
.phero h1 {
  font-size: clamp(1.95rem, 3.6vw, 2.85rem); color: var(--ink);
  letter-spacing: -.005em;
}
.phero .kicker { color: var(--gold-deep); }
.phero-lede { color: var(--muted); margin-top: 18px; font-size: 1.1rem; max-width: 34em; }
.phero .btn-row { margin-top: 30px; }
.phero .wave { margin: 16px 0 0; }

.phero-band { background: var(--cream); padding-bottom: 64px; }
.phero-band .band-photo { height: clamp(280px, 36vw, 460px); }
.phero-band .band-photo img { width: 100%; height: 100%; object-fit: cover; }
.phero-band .band-card { max-width: 1200px; margin: -104px auto 0; padding: 0 28px; position: relative; }
.phero-band .band-card > div {
  background: #fff; border-radius: 44px; padding: 44px 52px 46px; max-width: 790px;
  border-top: 4px solid var(--gold);
  box-shadow: 0 30px 66px rgba(35, 40, 31, .18);
}

/* ===== Bees =====
   Only on the beekeeping hero, and only over the photograph of the hives —
   a page about bees can carry a few, but motion loose over the reading is
   just noise. They sit under the card, so one drifting across passes behind
   it rather than over the words, and they never take a click.

   Four paths rather than one shared one: bees that all move the same way at
   the same time read as a screensaver, and the point is that they do not.  */
.phero-band .band-photo { position: relative; }
/* Bounded by the photograph itself, so this cannot drift out of step with the
   band height the way a copied clamp did. */
.bees { position: absolute; inset: 0; z-index: 1; pointer-events: none; }
.phero-band .band-card { z-index: 2; }

.bee {
  position: absolute; left: 0; top: 0; will-change: transform;
  /* Sized by height, so the ratio has to be stated here: the inline drawing
     carries no width or height of its own, and without this it falls back to
     the 300px default every SVG gets and swamps the picture. */
  aspect-ratio: 22 / 16;
  /* The photograph behind them runs from bright sky to dark stonework, so they
     need to carry their own edge or they vanish over half of it. */
  filter: drop-shadow(0 1px 2px rgba(20, 24, 16, .5));
}
.bee-jig { display: block; width: 100%; height: 100%; animation: bee-jig 1.9s ease-in-out infinite; }
.bee-art { display: block; width: 100%; height: 100%; }
/* Fast enough to read as a blur rather than as a flap. */
.bee-wing { transform-origin: 11.5px 6px; animation: bee-wing .14s ease-in-out infinite alternate; }
.bee--rev .bee-art { transform: scaleX(-1); }

@keyframes bee-wing { from { transform: scaleY(1); } to { transform: scaleY(.55); } }
@keyframes bee-jig {
  0%, 100% { transform: translate(0, 0); }
  25% { transform: translate(3px, -4px); }
  50% { transform: translate(-2px, 3px); }
  75% { transform: translate(4px, 2px); }
}

/* The beekeepers' heads start about a quarter of the way down the picture, and
   they stay there at every width because the photograph is cropped at the sides
   rather than top and bottom. So both the size of each bee and how high it sits
   are shares of the band: the same sky keeps the same bees in it whether the
   band is 460px tall or 190px, and nothing needs re-checking per breakpoint.
   The floor stops the smallest turning into a speck on a phone. Lowest any of
   them reaches is 17% plus its rise, against a face line at 25%. */
.bee--a { top: 3%;  height: max(13px, 7%);   animation: bee-a 32s linear infinite; }
.bee--b { top: 9%;  height: max(11px, 5.4%); opacity: .92; animation: bee-b 41s linear infinite -6s; }
.bee--c { top: 6%;  height: max(10px, 4.4%); opacity: .86; animation: bee-c 19s ease-in-out infinite -3s; }
.bee--d { top: 10%; height: max(12px, 6%);   animation: bee-d 47s linear infinite -14s; }

/* The rise and dip in the paths is in pixels, so it has to come down with the
   band. Same 920px the band itself shortens at — using a different breakpoint
   here is how four full-size bees ended up in a short band on a tablet. */
@media (max-width: 920px) { .bees { --wob: .34; } }

@keyframes bee-a {
  0%   { transform: translate(-8vw, 0); }
  25%  { transform: translate(20vw, calc(var(--wob, 1) * -22px)); }
  50%  { transform: translate(48vw, calc(var(--wob, 1) * 14px)); }
  75%  { transform: translate(76vw, calc(var(--wob, 1) * -18px)); }
  100% { transform: translate(108vw, calc(var(--wob, 1) * 6px)); }
}
@keyframes bee-b {
  0%   { transform: translate(106vw, 0); }
  30%  { transform: translate(70vw, calc(var(--wob, 1) * 22px)); }
  60%  { transform: translate(34vw, calc(var(--wob, 1) * -16px)); }
  100% { transform: translate(-10vw, calc(var(--wob, 1) * 10px)); }
}
/* This one never leaves — it works the top corner of the picture and stays. */
@keyframes bee-c {
  0%, 100% { transform: translate(72vw, 0); }
  20% { transform: translate(79vw, calc(var(--wob, 1) * -22px)); }
  45% { transform: translate(85vw, calc(var(--wob, 1) * 8px)); }
  70% { transform: translate(74vw, calc(var(--wob, 1) * 26px)); }
}
@keyframes bee-d {
  0%   { transform: translate(-6vw, calc(var(--wob, 1) * 22px)); }
  35%  { transform: translate(26vw, calc(var(--wob, 1) * -14px)); }
  70%  { transform: translate(58vw, calc(var(--wob, 1) * 18px)); }
  100% { transform: translate(104vw, calc(var(--wob, 1) * -8px)); }
}

/* The wanderers. Fixed to the viewport rather than to the document, because a
   bee pinned to a spot two screens down is a bee nobody ever sees. Sits above
   the page but under the header, the menu and the lightbox, so it can cross the
   reading without ever getting in front of a control. */
.bee-sky {
  position: fixed; inset: 0; z-index: 100;
  pointer-events: none; overflow: hidden;
}
.bee-rover {
  position: absolute; left: 0; top: 0;
  aspect-ratio: 22 / 16; will-change: transform;
  filter: drop-shadow(0 1px 2px rgba(20, 24, 16, .45));
}
@media (prefers-reduced-motion: reduce) { .bee-sky { display: none; } }

/* Asked for less motion, they are gone rather than frozen — four bees stopped
   dead in mid-air over a photograph looks like a fault, not a still. */
@media (prefers-reduced-motion: reduce) { .bees { display: none; } }

/* Contact details sitting inside the hero card as pills */
.phero-facts { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 28px; }
.phero-facts .ico { color: var(--green); flex: 0 0 auto; }
.phero-facts a, .phero-facts span {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--cream); border: 1px solid var(--line); border-radius: 999px;
  padding: 9px 18px; font-size: .92rem; font-weight: 600;
  color: var(--ink); text-decoration: none; transition: border-color .2s ease, color .2s ease;
}
.phero-facts a:hover { border-color: var(--green); color: var(--green); }

/* Breadcrumb — one tap back to the section above */
.crumbs { font-size: .8rem; color: var(--muted); padding: 16px 28px 0; }
.crumbs a { color: var(--muted); text-decoration: none; }
.crumbs a:hover { color: var(--green); text-decoration: underline; text-underline-offset: 3px; }
.crumbs span { padding: 0 8px; opacity: .55; }
.crumbs b { font-weight: 600; color: var(--ink); }

/* ===== Generic image + copy split ===== */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: 70px; align-items: center; }
.split.narrow-art { grid-template-columns: 1.1fr .9fr; }
.split.flip .split-art { order: 2; }
.split-copy p { color: var(--muted); margin-bottom: 20px; max-width: 36em; }
.split-copy p.lead { color: var(--ink); font-size: 1.15rem; font-weight: 600; }
.split-copy .btn-row { margin-top: 30px; }
.split-art img { width: 100%; border-radius: 34px; box-shadow: 0 24px 60px rgba(35, 40, 31, .18); }
.split-art figcaption { color: var(--muted); font-size: .87rem; margin-top: 12px; text-align: center; }

/* ===== Info cards (address, hours, parking, prices) ===== */
.card-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
.card-grid.two { grid-template-columns: repeat(2, 1fr); }
.card {
  background: #fff; border: 1px solid var(--line); border-radius: 34px; padding: 32px 30px;
  transition: transform .25s ease, box-shadow .25s ease;
}
.cream-bg .card, .card.on-cream { background: #fff; }
.card h3 { font-size: 1.4rem; margin-bottom: 10px; color: var(--green); }
.card p { color: var(--muted); font-size: .97rem; }
.card p + p { margin-top: 12px; }
/* :not(.btn) matters — .card a is more specific than .btn-green, so without it
   a filled button inside a card renders green text on a green pill. */
.card a:not(.btn) { color: var(--green); font-weight: 600; text-decoration: none; }
.card a:not(.btn):hover { text-decoration: underline; text-underline-offset: 3px; }
.card .card-icon {
  width: 46px; height: 46px; border-radius: 20px; background: var(--cream-deep);
  display: grid; place-items: center; margin-bottom: 18px; color: var(--green);
}
a.card { display: block; text-decoration: none; color: inherit; }
a.card:hover { transform: translateY(-5px); box-shadow: 0 18px 40px rgba(35, 40, 31, .13); }

/* ===== Checklist ===== */
.checks { list-style: none; display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px 30px; margin: 8px 0 0; }
.checks li { position: relative; padding-left: 30px; color: var(--muted); font-size: .98rem; }
.checks li::before {
  content: "✓"; position: absolute; left: 0; top: -1px;
  color: var(--green); font-weight: 700;
}
.checks.one-col { grid-template-columns: 1fr; }

/* ===== Notice strip ===== */
.notice {
  display: flex; gap: 16px; align-items: flex-start;
  background: #fff; border: 1px solid var(--line); border-left: 5px solid var(--gold);
  border-radius: 28px; padding: 22px 26px; margin-top: 30px;
}
.notice .n-mark { color: var(--gold-dark); display: grid; place-items: center; padding-top: 2px; }
.notice h4 { font-size: 1.05rem; letter-spacing: .16em; text-transform: uppercase; color: var(--green); margin-bottom: 5px; }
.notice p { color: var(--muted); font-size: .95rem; }

/* ===== Business directory ===== */
.dir-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 26px; }
.dir-card {
  background: #fff; border: 1px solid var(--line); border-radius: 34px; overflow: hidden;
  display: flex; flex-direction: column; transition: transform .25s ease, box-shadow .25s ease;
}
.dir-card:hover { transform: translateY(-6px); box-shadow: 0 22px 48px rgba(35, 40, 31, .15); }
.dir-card > img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.dir-body { padding: 26px 26px 28px; display: flex; flex-direction: column; flex: 1; }
.dir-body h3 { font-size: 1.35rem; margin-bottom: 4px; }
.dir-tag {
  font-size: .72rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--gold-deep); font-weight: 700; margin-bottom: 12px;
}
.dir-body p { color: var(--muted); font-size: .95rem; margin-bottom: 18px; }
.dir-links { margin-top: auto; display: flex; flex-wrap: wrap; gap: 8px; }
.dir-links a {
  font-size: .84rem; font-weight: 600; text-decoration: none;
  color: var(--green); border: 1.5px solid var(--line); border-radius: 999px; padding: 7px 15px;
  transition: background .2s ease, color .2s ease, border-color .2s ease;
}
.dir-links a:hover { background: var(--green); border-color: var(--green); color: #fff; }
/* One shared sprite per page carries the brand glyphs; the symbols are only
   ever referenced with <use>, so the sprite itself takes no room. */
.icon-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.dir-social { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.dir-social a {
  width: 38px; height: 38px; border: 1.5px solid var(--line); border-radius: 50%;
  display: flex; align-items: center; justify-content: center; color: var(--green);
  transition: background .2s ease, color .2s ease, border-color .2s ease;
}
.dir-social a:hover { background: var(--green); border-color: var(--green); color: #fff; }
/* Green, not the site's gold: the gold ring is 2.4:1 on white, under the 3:1 a focus indicator needs */
.dir-social a:focus-visible, .dir-links a:focus-visible { outline: 2px solid var(--green); outline-offset: 3px; }
.dir-social svg { width: 18px; height: 18px; fill: currentColor; display: block; }

/* ===== Timeline ===== */
.timeline { list-style: none; position: relative; margin-top: 10px; }
.timeline::before { content: ""; position: absolute; left: 8px; top: 10px; bottom: 10px; width: 2px; background: var(--line); }
.timeline li { position: relative; padding: 0 0 34px 44px; }
.timeline li:last-child { padding-bottom: 0; }
.timeline li::before {
  content: ""; position: absolute; left: 0; top: 8px; width: 18px; height: 18px;
  border-radius: 50%; background: var(--gold); border: 3px solid #fff; box-shadow: 0 0 0 2px var(--gold);
}
.timeline b {
  display: block; font-family: 'Quicksand', sans-serif; font-size: 1.55rem;
  color: var(--green); line-height: 1.2; margin-bottom: 4px;
}
.timeline p { color: var(--muted); font-size: .97rem; }

/* ===== Heraldry =====
   The banner and its caption sit side by side rather than stacked, because the
   blazon needs three lines and a 160px-wide caption under a 160px flag would
   set them as a column of two-word lines. Below 620px the column is too narrow
   to hold both, so it stacks. */
.arms {
  display: flex; gap: 18px; align-items: flex-start;
  margin: 4px 0 18px;
}
.arms svg {
  flex: 0 0 auto; width: clamp(96px, 15vw, 132px); height: auto;
  /* A flag is an object, not a pattern printed on the page — the shadow is what
     says so on a flat sand ground. */
  filter: drop-shadow(0 2px 5px rgba(31, 38, 32, .18));
}
.arms figcaption {
  color: var(--muted); font-size: .88rem; line-height: 1.65;
}
.arms figcaption i { font-style: italic; }
@media (max-width: 620px) {
  .arms { flex-direction: column; gap: 12px; }
  .arms svg { width: 116px; }
}

/* Source note. Deliberately quieter than the timeline it follows — it is there to
   be checked, not read, so it sits a size down behind a hairline. */
.sources {
  margin-top: 26px; padding-top: 16px; border-top: 1px solid var(--line);
  color: var(--muted); font-size: .84rem; line-height: 1.8;
}
.sources b {
  display: block; font-weight: 700; font-size: .72rem;
  letter-spacing: .16em; text-transform: uppercase;
  /* Muted, not the gold the kickers on this page use: at 11.5px that gold
     measures 4.1:1 on sand, under the 4.5 small text needs. This one is muted
     at 5.1:1 — size, weight and tracking already separate it from the note. */
  color: var(--muted); margin-bottom: 4px;
}
.sources a { color: var(--green); text-decoration: none; border-bottom: 1px solid rgba(1, 104, 49, .28); }
.sources a:hover { border-bottom-color: var(--green); }

/* ===== Expandable history =====
   Built on <details>, not script. Three reasons that matters here: it is
   keyboard operable without a line of JavaScript, the closed text still sits in
   the page so a search engine reads all of it, and the site keeps its one small
   script. The row is the whole hit area; the chevron only shows which way it is
   about to go. */
.timeline--open li { padding-bottom: 0; }
.timeline--open details { border-bottom: 1px solid var(--line); padding-bottom: 20px; margin-bottom: 20px; }
.timeline--open li:last-child details { border-bottom: 0; }
.timeline--open summary {
  cursor: pointer; list-style: none; display: flex; align-items: baseline;
  gap: 14px; flex-wrap: wrap; padding-right: 34px; position: relative;
}
/* Safari draws its own triangle unless both of these are set */
.timeline--open summary::-webkit-details-marker { display: none; }
.timeline--open summary::marker { content: ""; }
.timeline--open summary b { margin-bottom: 0; }
.timeline--open summary span {
  font-family: 'Quicksand', sans-serif; font-weight: 600; font-size: .95rem;
  color: var(--muted); letter-spacing: .01em;
}
/* Chevron, drawn from two borders so there is no second SVG to load */
.timeline--open summary::after {
  content: ""; position: absolute; right: 6px; top: .55em;
  width: 9px; height: 9px; border-right: 2.2px solid var(--gold-dark);
  border-bottom: 2.2px solid var(--gold-dark); transform: rotate(45deg);
  transition: transform .22s ease;
}
.timeline--open details[open] summary::after { transform: rotate(-135deg); }
.timeline--open summary:hover span { color: var(--green); }
.timeline--open summary:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; border-radius: 6px; }
.timeline--open details > p { margin-top: 12px; max-width: 44em; }
.timeline--open details > p + p { margin-top: 10px; }
@media (prefers-reduced-motion: reduce) {
  .timeline--open summary::after { transition: none; }
}

/* ===== Gallery strip ===== */
.gallery { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.gallery figure { margin: 0; }
.gallery img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: 34px;
  transition: transform .3s ease, box-shadow .3s ease;
}
.gallery img:hover { transform: translateY(-6px); box-shadow: 0 18px 40px rgba(35, 40, 31, .18); }
.gallery figcaption { color: var(--muted); font-size: .87rem; margin-top: 10px; }

/* ===== Gallery page =====
   One grid, four rhythms. The photographs arrive in four native shapes — 3:2
   press scans of the royal visit, 4:3 snapshots, 3:4 portraits of the hives,
   and square 540px web thumbnails that are the only copies left of a few mill
   events. Forcing all four into one aspect would crop the heads off the
   portraits and blow the thumbnails up past what they hold, so each section
   states its own ratio and column count, and the columns narrow where the
   source files are thin. That is why the events row is four across: at 270px
   a 540px file is a clean 2x, and at 370px it would not be. */
.gal { display: grid; gap: 22px; grid-template-columns: repeat(3, 1fr); }
.gal figure { margin: 0; }
.gal .shot, .egal .shot {
  display: block; overflow: hidden; border-radius: 26px; position: relative;
  background: var(--cream-deep);
  transition: transform .3s ease, box-shadow .3s ease;
}
/* The listing strip sizes its cells off the grid row rather than a ratio, so
   they finish flush with the tall photograph beside them. */
.gal .shot { aspect-ratio: 4 / 3; }
.gal .shot img, .egal .shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gal .shot:hover, .gal .shot:focus-visible,
.egal .shot:hover, .egal .shot:focus-visible { transform: translateY(-6px); box-shadow: 0 18px 40px rgba(35, 40, 31, .18); }
.gal figcaption { color: var(--muted); font-size: .88rem; margin-top: 11px; }

.gal--wide .shot { aspect-ratio: 3 / 2; }
.gal--tall { grid-template-columns: repeat(4, 1fr); }
.gal--tall .shot { aspect-ratio: 3 / 4; }
.gal--sq { grid-template-columns: repeat(4, 1fr); }
.gal--sq .shot { aspect-ratio: 1 / 1; }
.gal--pair { grid-template-columns: repeat(2, 1fr); max-width: 780px; }
.gal--pair .shot { aspect-ratio: 3 / 4; }

.gal-note { color: var(--muted); max-width: 40em; margin: -18px 0 30px; }

/* ===== A listing gallery =====
   The Eller Beck comes with thirty two photographs, and as a captioned grid
   they ran four thousand pixels down a page whose job is to get somebody to
   book. So the set opens the way a holiday let listing opens: one large
   photograph, a strip of six beside it, and the rest a click away. Nothing is
   lost with JavaScript off, because the other twenty five are still plain
   links to their full size files inside the details element below. */
.egal { display: grid; grid-template-columns: 1.68fr 1fr; gap: 14px; }
.egal-lead { aspect-ratio: 4 / 3; }
.egal-strip {
  display: grid; grid-template-columns: repeat(2, 1fr);
  grid-template-rows: repeat(3, 1fr); gap: 14px;
}
.egal-strip .shot { border-radius: 18px; }

/* In the half width column of a split the strip goes underneath rather than
   beside, three across and two deep. That is also what squares the two
   columns up: the photograph on its own left about 250px of empty sand next
   to the copy, and the strip is very close to the height that fills it. The
   lead keeps the radius and the shadow the single photograph had, so the
   block still reads as part of the same page. */
.egal--stack { grid-template-columns: 1fr; gap: 10px; }
.egal-main { position: relative; }
.egal--stack .egal-lead {
  border-radius: 34px;
  box-shadow: 0 24px 60px rgba(35, 40, 31, .18);
}

/* The arrows that page the main photograph. Built in js/site.js on the set it
   finds, so with that file blocked there are none and the photograph is still
   a plain link to its full size file. The scrim is the same .62 as the count
   badge, which holds 5:1 for the chevron against the lightest frame that
   could end up underneath it. */
.egal-go {
  position: absolute; top: 50%; margin-top: -22px;
  width: 44px; height: 44px; padding: 0;
  border: 0; border-radius: 50%; cursor: pointer;
  background: rgba(18, 24, 16, .62); color: #fff;
  display: grid; place-items: center;
  transition: background .2s ease;
}
.egal-go:hover, .egal-go:focus-visible { background: rgba(18, 24, 16, .82); }
.egal-prev { left: 14px; }
.egal-next { right: 14px; }
.egal--stack .egal-strip {
  grid-template-columns: repeat(3, 1fr); grid-template-rows: auto; gap: 10px;
}
.egal--stack .egal-strip .shot { aspect-ratio: 4 / 3; border-radius: 14px; }

/* The count sits on the photograph the way it does on a listing, so the size
   of the set is known before anything is clicked. */
.egal-n {
  position: absolute; right: 16px; bottom: 16px;
  padding: 7px 14px; border-radius: 999px;
  background: rgba(18, 24, 16, .62); color: #fff;
  font-size: .72rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
}
/* The scrim has to hold 4.5:1 against whatever photograph ends up behind it,
   so it is set for the worst case of a white frame: at .64 the small label
   still measures 5.4:1. Hover lightening it would drop that under the line,
   so the hover affordance is the lift the card already has. */
.egal-more span {
  position: absolute; inset: 0; display: grid; place-content: center; gap: 2px;
  background: rgba(18, 24, 16, .64); color: #fff;
  font-weight: 700; font-size: 1.5rem; line-height: 1;
}
.egal-more span small { font-size: .7rem; letter-spacing: .16em; text-transform: uppercase; }

/* Opening the rest is a native disclosure rather than a script, so the button
   works whether or not site.js loaded. */
.egal-all { margin-top: 24px; }
.egal-all summary { list-style: none; display: inline-block; }
.egal-all summary::-webkit-details-marker { display: none; }
.egal-all summary::marker { content: ''; }
.egal-all[open] summary { background: var(--green); color: #fff; }
.gal--sheet {
  grid-template-columns: repeat(5, 1fr); gap: 12px; margin-top: 24px;
}
.gal--sheet .shot { border-radius: 14px; }

/* Lightbox. It is built on the click that asks for it — see js/site.js — so a
   visitor who never opens a photograph downloads none of the large files, and
   with JavaScript off every thumbnail is still a plain link to the full image. */
.lbox {
  position: fixed; inset: 0; z-index: 120; display: grid; place-items: center;
  padding: 24px; background: rgba(18, 24, 16, .93);
}
.lbox img {
  max-width: min(100%, 1400px); max-height: calc(100vh - 140px);
  width: auto; height: auto; border-radius: 12px; display: block;
}
.lbox figure { margin: 0; display: grid; justify-items: center; gap: 14px; }
.lbox figcaption { color: #eae6da; font-size: .95rem; text-align: center; max-width: 44em; }
.lbox-close, .lbox-prev, .lbox-next {
  position: absolute; width: 52px; height: 52px; border: 0; cursor: pointer;
  border-radius: 50%; background: rgba(255, 255, 255, .12); color: #fff;
  display: grid; place-items: center;
  transition: background .2s ease;
}
.lbox-close:hover, .lbox-prev:hover, .lbox-next:hover { background: rgba(255, 255, 255, .26); }
.lbox-close { top: 18px; right: 18px; }
.lbox-prev { left: 18px; top: 50%; margin-top: -26px; }
.lbox-next { right: 18px; top: 50%; margin-top: -26px; }
body.lbox-open { overflow: hidden; }
@media (max-width: 620px) {
  .lbox { padding: 12px; }
  .lbox-prev { left: 8px; }
  .lbox-next { right: 8px; }
  .lbox img { max-height: calc(100vh - 190px); }
}

/* ===== A document offered inside the prose =====
   The leaflet is a thing to open, not a page to read, so it sits in the history
   as a card with its own cover showing rather than as a line of link text. The
   whole card is the link; the arrow is there to say so. */
.doc-card {
  display: grid; grid-template-columns: 150px 1fr; gap: 26px; align-items: center;
  max-width: 860px; margin: 46px auto 0; padding: 20px;
  background: var(--cream); border: 1px solid var(--line); border-radius: 26px;
  text-decoration: none; color: inherit;
  transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease;
}
.doc-card:hover, .doc-card:focus-visible {
  transform: translateY(-4px); border-color: rgba(1, 104, 49, .28);
  box-shadow: 0 20px 40px -24px rgba(35, 40, 31, .34);
}
.doc-card img {
  width: 100%; height: auto; display: block; border-radius: 14px;
  border: 1px solid var(--line); background: #fff;
}
.doc-card h3 { font-size: 1.1rem; margin-top: 5px; }
.doc-card p { color: var(--muted); font-size: .93rem; margin-top: 8px; }
.doc-meta {
  display: block; font-size: .74rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--gold-deep);
}
.doc-go {
  display: inline-flex; align-items: center; gap: 8px; margin-top: 15px;
  font-weight: 700; font-size: .82rem; letter-spacing: .13em;
  text-transform: uppercase; color: var(--green);
}
.doc-card:hover .doc-go svg { transform: translateX(3px); }
.doc-go svg { transition: transform .25s ease; }
@media (max-width: 620px) {
  .doc-card { grid-template-columns: 1fr; gap: 18px; padding: 16px; margin-top: 34px; }
  .doc-card img { max-width: 220px; }
}
@media (prefers-reduced-motion: reduce) {
  .doc-card, .doc-go svg { transition: none; }
}

/* ===== Pricing ===== */

/* ===== Form ===== */
.form-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; }
.field { display: grid; gap: 7px; }
.field.full { grid-column: 1 / -1; }
.field label { font-size: .82rem; font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: var(--green); }
.field input, .field select, .field textarea {
  font-family: 'Quicksand', sans-serif; font-size: 1rem; color: var(--ink);
  background: #fff; border: 1.5px solid var(--line); border-radius: 34px; padding: 14px 16px;
  transition: border-color .2s ease, box-shadow .2s ease;
}
.field textarea { resize: vertical; min-height: 140px; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: var(--green); box-shadow: 0 0 0 3px rgba(1, 104, 49, .13);
}
.field input[aria-invalid="true"], .field textarea[aria-invalid="true"] { border-color: #a3392f; }
.field input[aria-invalid="true"]:focus, .field textarea[aria-invalid="true"]:focus {
  box-shadow: 0 0 0 3px rgba(163, 57, 47, .13);
}
.form-note { color: var(--muted); font-size: .87rem; margin-top: 16px; }
.form-note a { color: var(--green); }

/* The status line the fetch-driven submit fills in: "Sending…", then the
   result. Same green/muted as the rest of the form until it fails. */
/* One box recipe shared by both: the fetch-driven .form-status that appears
   without a page reload, and .form-banner, the pure CSS/HTML fallback for a
   visitor with no JavaScript (PHP redirects to #sent-ok or #sent-err, and
   :target is what reveals the matching one there). Same light green or light
   red panel either way, so which path fired is not something a visitor could
   tell from looking. */
.form-status, .form-banner {
  margin-top: 20px; padding: 16px 20px; border-radius: 16px;
  font-size: .95rem; font-weight: 600; line-height: 1.5;
}
.form-status:not(.is-err), .form-banner--ok { background: var(--green-soft); color: var(--green); }
.form-status.is-err, .form-banner--err { background: #fbecea; color: #a3392f; }
.form-banner--err a { color: inherit; text-decoration: underline; }
.form-banner { display: none; }
.form-banner:target { display: block; }

/* ===== Explore more (bottom of every inner page) ===== */
.explore { background: var(--cream); }
.explore-head { text-align: center; margin-bottom: 38px; }
.explore-head .wave { margin: 16px auto 0; }
.explore-sub { color: var(--muted); margin-top: 14px; }
.explore-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; }
.explore-card {
  position: relative; aspect-ratio: 4 / 3.4; border-radius: 34px; overflow: hidden;
  display: flex; align-items: flex-end; text-decoration: none;
}
.explore-card img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform .55s ease; }
.explore-card::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(23, 33, 14, .04) 30%, rgba(23, 33, 14, .8));
  transition: background .3s ease;
}
.explore-card span {
  position: relative; z-index: 2; color: #fff; font-family: 'Quicksand', sans-serif;
  font-size: 1.35rem; padding: 0 20px 20px; text-shadow: 0 2px 14px rgba(0, 0, 0, .55);
}
.explore-card span small { display: block; font-family: 'Quicksand', sans-serif; font-size: .78rem; opacity: .88; margin-top: 4px; }
.explore-card:hover img { transform: scale(1.07); }
.explore-card:hover::after { background: linear-gradient(180deg, rgba(1, 104, 49, .18) 25%, rgba(1, 61, 31, .85)); }

/* ===== Call to action band ===== */
.cta-band { background: var(--green); color: #fff; text-align: center; }
.cta-band h2 { font-size: clamp(1.65rem, 2.9vw, 2.3rem); margin-bottom: 14px; }
.cta-band p { color: rgba(255, 255, 255, .9); max-width: 40em; margin: 0 auto 30px; }
.cta-band .btn-row { justify-content: center; }
.cta-band .btn-outline { border-color: rgba(255, 255, 255, .85); }

.cream-bg { background: var(--cream); }
.white-bg { background: #fff; }
.section-head { max-width: 46em; margin-bottom: 40px; }
.section-head p { color: var(--muted); margin-top: 6px; }

/* ===== Colour blocks =====
   Panels of flat colour that hold the content column on one side and run off
   the edge of the screen on the other, then lap over each other so the joins
   never line up. The offsets are what make it read as blocks rather than
   stripes, so a run of them always alternates sides. */
.blocks { padding: 0; overflow: hidden; }
.block {
  position: relative;
  padding: 78px 56px;
  background: var(--block-bg, var(--cream-deep));
}
/* Held at the content column on the left, running off the right edge */
.block--right {
  margin-left: max(20px, calc((100vw - 1200px) / 2 + 28px));
  padding-right: max(56px, calc((100vw - 1200px) / 2 + 28px));
  border-radius: 50px 0 0 50px;
}
/* Mirrored */
.block--left {
  margin-right: max(20px, calc((100vw - 1200px) / 2 + 28px));
  padding-left: max(56px, calc((100vw - 1200px) / 2 + 28px));
  border-radius: 0 50px 50px 0;
}
.block-inner { max-width: 1144px; }
/* Pull the next block up under the one above. The block that laps has to sit
   over its neighbour, so it gets the higher stacking order. */
.block--lap { margin-top: -56px; z-index: 1; }
.block--lap-deep { margin-top: -96px; z-index: 1; }

.block--sand { --block-bg: #f4ead3; }
.block--sage { --block-bg: #e8efe7; }
.block--cream { --block-bg: var(--cream-deep); }
.block--green { --block-bg: var(--green); color: #fff; }
.block--green .title, .block--green h2, .block--green h3, .block--green .stat b { color: #fff; }
.block--green .title .thin { color: rgba(255, 255, 255, .82); }
.block--green p, .block--green .split-copy p, .block--green .stat span { color: rgba(255, 255, 255, .88); }
.block--green .split-copy p.lead { color: #fff; }
.block--green .wave path { stroke: var(--gold); }
.block--green .stat { border-color: rgba(255, 255, 255, .3); }
.block--green a:not(.btn) { color: #fff; }
/* A checklist on the green ground was inheriting muted ink on dark green, and
   its ticks were drawn in the same green as the panel — so the list read as
   faint smudges and the ticks were not there at all. */
.block--green .checks li { color: rgba(255, 255, 255, .9); }
.block--green .checks li::before { color: var(--gold); }

/* ===== Footer ===== */
.footer { background: #fff; color: var(--ink); padding: 90px 0 0; border-top: 1px solid var(--line); }
.footer-grid { display: grid; grid-template-columns: 1.35fr 1fr; gap: 50px; align-items: end; padding-bottom: 56px; }
.footer .discover {
  font-family: 'Quicksand', sans-serif; font-size: clamp(1.45rem, 2.6vw, 2.35rem);
  line-height: 1.16; letter-spacing: .16em; text-transform: uppercase;
  margin-bottom: 34px; color: var(--green);
}
/* Poppins ships upright only here, so the eyebrow takes the caps treatment
   the rest of the site uses rather than a faked italic */
.footer .discover .thin {
  display: block; font-weight: 700; font-style: normal; text-transform: uppercase;
  letter-spacing: .2em; font-size: .8rem; color: var(--gold-deep); margin-bottom: 14px;
}
/* Inner pages put the address above the wordmark; the tight display line-height
   lets ascenders collide with it, so give it clearance when it follows content */
address + .discover { margin-top: 30px; }
/* Deliberately NOT in the caps list above. The block holds an email address,
   which has to stay as typed to be readable — so capitalising the rest left
   EMAIL: butted against a lowercase gmail address on the same line. This is a
   postal address and a phone number: things to be read, not decoration. */
.footer address { font-style: normal; color: var(--muted); line-height: 1.9; }
/* The ceiling, not the 600 the scale would suggest for body size. The values
   beside these are green links, and at 600 the label gave way to the colour
   instead of introducing it — which is the whole job of a label. */
.footer address b { font-weight: 700; }
.footer address a { color: var(--green); text-decoration: none; }
.footer address a:hover { text-decoration: underline; text-underline-offset: 3px; }
.footer-right { text-align: right; display: grid; gap: 20px; justify-items: end; }
.footer-right .badge { width: 150px; height: auto; }
.footer-right h4 { font-size: 1rem; letter-spacing: .16em; text-transform: uppercase; color: var(--green); }
.footer-socials { display: flex; gap: 14px; }
.footer-socials a {
  width: 42px; height: 42px; border-radius: 50%;
  background: var(--green); color: #fff;
  display: flex; align-items: center; justify-content: center;
  transition: background .2s ease;
}
.footer-socials a:hover { background: var(--gold); color: var(--green-deep); }
.footer-socials svg { width: 18px; height: 18px; fill: currentColor; stroke: currentColor; }
.footer-bottom {
  border-top: 1px solid var(--line); padding: 18px 0;
  font-size: .85rem; color: var(--muted);
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: 10px;
}

/* Coming soon block */
.soon { text-align: center; background: var(--cream); }
.soon .badge { width: 140px; margin: 0 auto 26px; }
.soon h2 { font-size: 2.1rem; margin-bottom: 14px; }
.soon p { color: var(--muted); max-width: 34em; margin: 0 auto 30px; }

/* Poppins carries several weights, and the badge lettering sits at about a
   semibold, so display type is set there rather than at its natural 400 */

/* ===== Responsive ===== */
@media (max-width: 1050px) {
  .dir-grid, .card-grid, .gallery { grid-template-columns: repeat(2, 1fr); }
  .explore-grid { grid-template-columns: repeat(2, 1fr); }
  .split { gap: 46px; }
  .gal { grid-template-columns: repeat(2, 1fr); }
  .gal--tall, .gal--sq { grid-template-columns: repeat(3, 1fr); }
  /* Twenty five divides into five columns exactly and into four, three or two
     with one left over, so away from the five-up desktop layout the last
     photograph takes the rest of its row rather than sitting there as an
     orphan cell. */
  .gal--sheet { grid-template-columns: repeat(4, 1fr); }
  .gal--sheet .shot:last-child { grid-column: 1 / -1; aspect-ratio: 3 / 1; }
}
/* Measured, not guessed, and re-measured every time an item moves. Folding
   Gallery and the leaflet into a submenu put the row back to seven: logo 335 +
   gap 26 + seven pills 753 = 1114px, which fits a 1181px viewport once padding
   is counted. Below that the burger takes over rather than the row squeezing
   something — which is how the logo came to be distorted when What's On made
   it seven items on the old metrics. */
@media (max-width: 1180px) {
  .nav-links { display: none; }
  .nav-burger { display: block; }
}

@media (max-width: 920px) {
  .topbar-inner { gap: 18px; font-size: .9rem; padding: 10px 20px; overflow-x: auto; white-space: nowrap; justify-content: flex-start; }
  .nav-inner { padding: 12px 20px; }
  .nav-logo img { height: 46px; }
  .welcome-grid, .things-grid, .panels-grid { grid-template-columns: 1fr; gap: 46px; }
  .things-art { padding: 26px 12px 0 0; }
  .things-art .badge { width: 120px; }
  .tile-grid { grid-template-columns: repeat(2, 1fr); gap: 14px; }
  .social-grid { grid-template-columns: 1fr; gap: 18px; }
  .social-grid img { aspect-ratio: 4 / 3; }
  .social-head .handle { margin-left: 0; }
  .stats { gap: 28px; }
  .footer-grid { grid-template-columns: 1fr; align-items: start; }
  .footer-right { text-align: left; justify-items: start; }
  section { padding: 64px 0; }
  /* Colour blocks go full width on a phone. There is no room to hold a column
     on one side and bleed off the other, and the lap shrinks with the padding */
  .blocks { padding: 0; }
  .block { padding: 52px 20px; }
  .block--right, .block--left {
    margin-left: 0; margin-right: 0; padding-left: 20px; padding-right: 20px;
    border-radius: 0;
  }
  .block--lap, .block--lap-deep { margin-top: -28px; border-radius: 34px 34px 0 0; }
  /* Shallower band, and the card laps less far over it, on a phone */
  .phero-band { padding-bottom: 46px; }
  .phero-band .band-photo { height: clamp(190px, 44vw, 270px); }
  .phero-band .band-card { margin-top: -50px; padding: 0 20px; }
  .phero-band .band-card > div { padding: 30px 26px 32px; border-radius: 34px; }
  .phero-lede { font-size: 1.02rem; }
  /* One column everywhere the two-up would squeeze */
  .split, .split.narrow-art { grid-template-columns: 1fr; gap: 36px; }
  .split.flip .split-art { order: 0; }
  .dir-grid, .card-grid, .card-grid.two, .gallery, .form-grid { grid-template-columns: 1fr; }
  /* A thumb needs more than 38px to land on one of these reliably */
  .dir-social { gap: 10px; }
  .dir-social a { width: 44px; height: 44px; }
  .checks { grid-template-columns: 1fr; }
  .card { padding: 26px 24px; }
  .explore-card { aspect-ratio: 4 / 2.6; }
  /* Photographs stay two-up on a phone. One-up would show three of a
     thirty-four photograph page per screen, which is a lot of scrolling for a
     set people browse rather than read. */
  .gal, .gal--tall, .gal--sq { grid-template-columns: repeat(2, 1fr); gap: 14px; }
  .gal--sheet { grid-template-columns: repeat(3, 1fr); gap: 8px; }
  .gal--sheet .shot:last-child { aspect-ratio: 2 / 1; }
  .gal .shot { border-radius: 18px; }
  .gal figcaption { font-size: .82rem; margin-top: 8px; }
}
@media (max-width: 560px) {
  .explore-grid { grid-template-columns: 1fr; }
  .timeline li { padding-left: 38px; }
}
/* Tile carousel on phones */
@media (max-width: 700px) {
  /* On a phone the strip goes under the big photograph and runs three across.
     Kept beside it at this width the strip cells come out barely larger than
     the thumbnails on the sheet below, and stacking it two across makes the
     whole block taller than the grid it replaced. */
  .egal { grid-template-columns: 1fr; gap: 8px; }
  .egal-strip { grid-template-columns: repeat(3, 1fr); grid-template-rows: auto; gap: 8px; }
  .egal-strip .shot { aspect-ratio: 4 / 3; border-radius: 12px; }
  .egal-lead { border-radius: 18px; }
  .egal-n { right: 10px; bottom: 10px; padding: 5px 11px; }
  /* Smaller and tighter in, because a swipe is the main way through on a
     phone and the arrows are the fallback rather than the handle. */
  .egal-go { width: 38px; height: 38px; margin-top: -19px; }
  .egal-prev { left: 8px; }
  .egal-next { right: 8px; }
  .egal-more span { font-size: 1.15rem; }
  .egal-all { margin-top: 18px; }
  .egal-all summary { padding: 14px 26px; font-size: .78rem; }

  .tiles-head { margin-bottom: 18px; }
  .tiles-head .wave { display: none; }
  .tile-arrows { display: flex; gap: 10px; flex: 0 0 auto; }
  .tile-arrows button {
    width: 46px; height: 46px; border-radius: 50%;
    border: 2px solid var(--green); background: #fff; color: var(--green);
    font-size: 1.15rem; cursor: pointer; transition: background .2s ease, color .2s ease;
  }
  .tile-arrows button:hover, .tile-arrows button:active { background: var(--green); color: #fff; }
  .tile-grid {
    display: flex; overflow-x: auto; scroll-snap-type: x mandatory;
    gap: 14px; padding-bottom: 8px;
    scrollbar-width: none; -webkit-overflow-scrolling: touch;
  }
  .tile-grid::-webkit-scrollbar { display: none; }
  .tile { flex: 0 0 80%; aspect-ratio: 1 / 1; scroll-snap-align: start; }
  .topbar .tb-more { display: none; }
  .topbar-inner { overflow: visible; white-space: normal; justify-content: flex-start; }
  .topbar .socials { margin-left: auto; }
}

/* ===== What's on =====
   Two different kinds of thing share this page and they should not look alike.
   The tours are ours and they repeat, so they get a card and a standing
   invitation. The Elsworth evenings are dated, ticketed and they sell out, so
   they get a list you can scan down by month — the shape you already know from
   a listings page, because that is what it is. */
/* ===== Calendar =====
   One grid holding every source — the mill's own tours, Heritage Open Days and
   Elsworth's ticketed nights — because a visitor picks a date first and only
   then cares whose event it is. The grid answers "is anything on that day"; the
   list under it answers "what, when and how much", which no cell this size can.

   Every month is in the page. The script hides all but one and builds the month
   buttons; with no script they simply stack, which is the whole calendar in
   reading order and costs a scroll rather than a feature. */
.cal { margin-top: 30px; }
.cal-key {
  list-style: none; margin: 0 0 26px; padding: 0;
  display: flex; flex-wrap: wrap; gap: 8px 26px;
  font-size: .86rem; color: var(--muted);
}
.cal-key li { display: flex; align-items: center; gap: 9px; }

/* Two tinctures, not three: green is ours and free, gold is Elsworth's and
   ticketed, and that is the distinction a visitor is actually making. Open Days
   is still ours, so it stays green and takes the solid dot — it is the one that
   only happens once. */
.cal-dot { width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto; }
.cal-dot--tour { background: #fff; border: 2px solid var(--green); }
.cal-dot--hod  { background: var(--green); }
.cal-dot--els  { background: var(--gold); }

.cal-bar {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin-bottom: 26px;
}
.cal-tab {
  font: inherit; font-size: .78rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--green); background: none; cursor: pointer;
  border: 1.5px solid var(--line); border-radius: 999px;
  padding: 9px 17px; transition: background .18s ease, color .18s ease, border-color .18s ease;
}
.cal-tab:hover { border-color: var(--green); }
.cal-tab[aria-selected="true"] { background: var(--green); border-color: var(--green); color: #fff; }
.cal-tab[disabled] { color: var(--muted); cursor: default; opacity: .55; }

.cal-title {
  font-family: 'Quicksand', -apple-system, sans-serif;
  font-weight: 700; text-transform: uppercase; letter-spacing: .2em;
  font-size: .78rem; color: var(--muted);
  margin: 44px 0 14px;
}
.cal-month:first-of-type .cal-title { margin-top: 0; }

/* The 1px gap over a line-coloured ground IS the ruling — drawing borders on the
   cells instead doubles them at every shared edge. */
.cal-grid {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 1px; background: var(--line);
  border: 1px solid var(--line); border-radius: 10px; overflow: hidden;
}
.cal-dow {
  background: var(--cream); color: var(--muted);
  font-size: .68rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  text-align: center; padding: 9px 2px;
}
.cal-dow i { font-style: normal; }
.cal-pad { background: var(--cream); }
.cal-day {
  background: #fff; padding: 7px 8px 8px;
  min-height: clamp(58px, 8.6vw, 106px);
}
.cal-day > b {
  display: block; font-size: .92rem; font-weight: 700;
  color: var(--ink); line-height: 1.2; margin-bottom: 5px;
}
.cal-day--bare > b { font-weight: 500; color: var(--muted); }
.cal-day.is-past { background: var(--cream); }
.cal-day.is-past > b { color: var(--muted); }
.cal-day.is-past .cal-marks { opacity: .5; }
/* Today is a ring inside the cell rather than a fill, so it marks the date
   without pretending something is on. */
.cal-day.is-today > b {
  display: inline-block; margin-left: -3px;
  color: var(--green); box-shadow: 0 0 0 2px var(--gold);
  border-radius: 4px; padding: 0 4px;
}

.cal-marks { list-style: none; margin: 0; padding: 0; display: grid; gap: 3px; }
.cal-mark {
  display: flex; align-items: baseline; gap: 6px;
  font-size: .72rem; line-height: 1.35; color: var(--muted);
}
.cal-mark .cal-dot { align-self: center; width: 8px; height: 8px; }
.cal-mark--tour .cal-dot { background: #fff; border: 2px solid var(--green); }
.cal-mark--hod  .cal-dot { background: var(--green); }
.cal-mark--els  .cal-dot { background: var(--gold); }
.cal-mark-t { font-weight: 700; color: var(--ink); }
.cal-mark-n { margin-left: 4px; }
/* Off by default. A cell is a seventh of the width, and below the breakpoint
   there is not enough of it left over for a picture AND the words. */
.cal-pic { display: none; }
@media (min-width: 900px) {
  /* 44px is where the wheel stops being a brown smudge and starts being a
     wheel, and it is small enough that a day holding two events grows the row
     by about forty pixels rather than a hundred. */
  .cal-pic {
    display: block; width: 44px; height: 33px; object-fit: cover;
    border-radius: 4px; flex: 0 0 auto;
  }
  /* Grid, not flex-wrap: the picture has to span both text rows, and a wrapped
     flex line starts back at the left edge, under the picture rather than
     beside it. */
  .cal-mark {
    display: grid; grid-template-columns: 44px minmax(0, 1fr);
    gap: 0 8px; align-items: center;
  }
  .cal-mark .cal-dot { display: none; }
  .cal-pic { grid-column: 1; grid-row: 1 / span 2; }
  .cal-mark-t { grid-column: 2; grid-row: 1; align-self: end; }
  .cal-mark-n { grid-column: 2; grid-row: 2; align-self: start; margin-left: 0; }
}
.cal-day.is-past .cal-pic { filter: grayscale(1); }

.cal-list { list-style: none; margin: 20px 0 0; padding: 0; }
.cal-none { color: var(--muted); font-size: .95rem; padding: 20px 2px; }
.ev-price--free { color: var(--green); }

@media (max-width: 720px) {
  /* A cell this narrow holds a number and a dot and nothing else — the labels
     move to the list underneath, which is where the detail already lives. */
  .cal-dow i { display: none; }
  .cal-day { padding: 5px 4px 6px; }
  .cal-marks { display: flex; flex-wrap: wrap; gap: 3px; justify-content: center; }
  /* display, not font-size:0 — a 0px label is still a label to anything that
     measures text, and the point here is that it is not shown at all. */
  .cal-mark-t, .cal-mark-n { display: none; }
  .cal-mark { gap: 0; }
  .cal-mark .cal-dot { width: 7px; height: 7px; }
  .cal-day > b { text-align: center; margin-bottom: 4px; }
  .cal-day.is-today > b { margin-left: 0; }
}

/* Heritage Open Days: six fixed dates, which is a table of two columns and no
   more, so it is set as one rather than dressed up as cards. */
.hod-dates {
  list-style: none; margin: 22px 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); gap: 1px;
  background: var(--line); border: 1px solid var(--line); border-radius: 10px; overflow: hidden;
}
.hod-dates li {
  background: var(--cream); padding: 12px 14px;
  display: flex; flex-direction: column; gap: 2px;
}
.hod-dates b { font-size: .96rem; color: var(--green); font-weight: 700; }
.hod-dates span { font-size: .86rem; color: var(--muted); }
.hod-access { color: var(--muted); font-size: .92rem; }
/* Sized off its own artwork rather than the type around it — a borrowed mark
   has fixed proportions and shrinking it to fit a kicker slot is how a logo
   ends up illegible. */
.hod-logo { width: clamp(126px, 15vw, 168px); height: auto; margin-bottom: 20px; }
/* Keeps a date range whole. "11–20 September" breaking after the dash reads as
   two different things. */
.nb { white-space: nowrap; }

/* Date column, then what it is, then what it costs and how to book. Deliberately
   not a card each: fourteen cards is a wall, fourteen rows is a calendar. */
.ev {
  display: grid; grid-template-columns: 76px 104px minmax(0, 1fr) auto;
  gap: 6px 24px; align-items: start;
  padding: 22px 2px; border-bottom: 1px solid var(--line);
}
/* Illustrative, not informative — the row already names the event, so the
   picture carries an empty alt rather than repeating the heading twenty-three
   times to a screen reader. */
.ev-pic {
  width: 104px; height: 78px; object-fit: cover;
  border-radius: 8px; align-self: start;
}
/* Sold out is greyed rather than hidden, and the picture follows the row. */
.ev--gone .ev-pic { filter: grayscale(1); opacity: .65; }
.ev-when { text-align: center; padding-top: 2px; }
.ev-when b {
  display: block; font-size: 1.6rem; font-weight: 600;
  color: var(--green); line-height: 1.05;
}
.ev-when span {
  display: block; font-size: .7rem; font-weight: 700;
  letter-spacing: .13em; text-transform: uppercase; color: var(--muted);
}
.ev-what h4 { font-size: 1.08rem; margin: 0 0 5px; line-height: 1.35; }
.ev-what p { color: var(--muted); font-size: .95rem; margin: 0; }
.ev-go { text-align: right; white-space: nowrap; padding-top: 3px; }
.ev-price { display: block; font-weight: 700; color: var(--ink); margin-bottom: 9px; }
.ev-book {
  display: inline-block; font-size: .76rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; text-decoration: none;
  color: var(--green); border: 1.5px solid var(--green);
  border-radius: 999px; padding: 9px 18px; transition: background .18s ease, color .18s ease;
}
.ev-book:hover, .ev-book:focus-visible { background: var(--green); color: #fff; }
/* Sold out is a real state, not a missing button — the row stays readable so
   people can still see what they missed and what is like it. */
.ev--gone .ev-when b, .ev--gone .ev-what h4 { color: var(--muted); }
.ev-gone {
  display: inline-block; font-size: .72rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted); border: 1.5px solid var(--line);
  border-radius: 999px; padding: 9px 16px;
}
.agenda-note { color: var(--muted); font-size: .92rem; margin-top: 24px; }

/* The standing invitation. Green because it is the one thing on this page that
   is ours, free, and available every week. */
.standing { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 30px; align-items: center; }
.standing-day { text-align: center; }
.standing-day b {
  display: block; font-size: 2.5rem; font-weight: 600; line-height: 1; color: #fff;
}
.standing-day span {
  display: block; font-size: .74rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--gold);
  margin-top: 6px;
}

/* ===== Fundraising =====
   A total is only meaningful next to the thing it is heading for, so the figure
   and the goal are shown together and the bar is the same statement drawn. */
/* Held to a measure rather than the full panel: a progress bar a metre wide
   stops reading as a proportion and the two end labels end up a screen apart. */
.raise { margin: 26px 0 30px; max-width: 42em; }
.raise-figs { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.raise-figs b {
  font-size: clamp(2.3rem, 6.4vw, 3.5rem); font-weight: 600;
  color: var(--green); line-height: 1;
}
.raise-figs span { color: var(--muted); font-size: 1.02rem; }
.raise-bar {
  height: 14px; border-radius: 999px; background: var(--cream-deep);
  overflow: hidden;
}
.raise-fill { height: 100%; border-radius: 999px; background: var(--gold); width: var(--at, 0%); }

/* The road. The bar was already the journey drawn; this puts the mill's van on
   it, so the gold behind it reads as ground covered rather than as a value.
   --at is set once on the track and moves the fill and the van together, which
   is what stops the picture and the figure ever disagreeing. */
.raise-track { position: relative; padding-top: 42px; margin: 20px 0 12px; }
.raise-van {
  position: absolute; bottom: 14px; color: var(--gold-dark); line-height: 0;
  /* Centred on the point it has reached, but never hanging off either end. */
  left: clamp(0px, calc(var(--at, 0%) - var(--van) / 2), calc(100% - var(--van)));
  --van: clamp(46px, 7vw, 58px);
}
.raise-van svg { width: var(--van); height: auto; display: block; }
/* A gentle judder while it is going, and dead still once it has parked — that
   difference is the whole reason it reads as travelling rather than sliding. */
.raise-track.is-driving .raise-van { animation: van-bob .36s ease-in-out infinite; }
@keyframes van-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-1.5px); }
}
@media (prefers-reduced-motion: reduce) {
  .raise-track .raise-van { animation: none; }
}
.raise-meta {
  display: flex; justify-content: space-between; gap: 16px;
  font-size: .8rem; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: var(--muted);
}
.raise-asat { color: var(--muted); font-size: .88rem; margin-top: 18px; }
.block--green .raise-figs b { color: #fff; }
.block--green .raise-figs span,
.block--green .raise-meta,
.block--green .raise-asat { color: rgba(255, 255, 255, .82); }
.block--green .raise-bar { background: rgba(255, 255, 255, .2); }
.block--green .raise-van { color: var(--gold-light); }

/* Two lives, given as dates, because that is how a memorial reads. */
.inmem {
  display: flex; gap: 12px 40px; flex-wrap: wrap;
  margin: 30px 0 4px; padding-top: 26px; border-top: 1px solid var(--line);
}
.inmem .inmem-head {
  flex: 1 0 100%; margin: 0 0 6px;
  font-weight: 700; font-size: .78rem; letter-spacing: .16em;
  text-transform: uppercase; color: var(--gold-deep);
}
.inmem div b { display: block; font-size: 1.12rem; color: var(--ink); }
.inmem div span { color: var(--muted); font-size: .95rem; }

@media (max-width: 700px) {
  /* Price and button drop under the title rather than squeezing a third column
     into a phone. The date column stays — it is what makes this scannable. */
  /* Picture takes the left column and everything else stacks beside it. Keeping
     the date as its own column too would leave the title about 150px, which is
     not enough for "Yorkshire Dales Cheese Festival — cheese and wine pairing". */
  .ev { grid-template-columns: 84px minmax(0, 1fr); gap: 4px 16px; padding: 20px 0; }
  .ev-pic { grid-row: 1 / span 3; grid-column: 1; width: 84px; height: 63px; }
  .ev-when { grid-column: 2; text-align: left; display: flex; align-items: baseline; gap: 8px; }
  .ev-when b { font-size: 1.15rem; }
  .ev-when span { display: inline; }
  .ev-what { grid-column: 2; }
  .ev-go { grid-column: 2; text-align: left; margin-top: 12px; }
  .ev-price { display: inline-block; margin: 0 14px 0 0; }
  .standing { grid-template-columns: 1fr; gap: 18px; text-align: center; }
  .standing-day b { font-size: 2.1rem; }
  .inmem { gap: 22px; }
}

/* Names a control for a screen reader without repeating the text on screen —
   fourteen buttons all reading "Book" is fine visually, because the row above
   them says which one, and useless read out of context. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ===== Film =====
   A YouTube iframe drags well over a megabyte of Google's JavaScript into the
   page on load, whether or not anybody presses play — more weight than the
   whole of the rest of this site put together. So the page ships a poster frame
   and a button, and the real player is only fetched by the click that asks for
   it. Nothing third-party is touched until then, and nocookie means no cookie
   is set even after. */
.vid-fig { margin: 0 auto; max-width: 860px; }
.vid {
  position: relative; aspect-ratio: 16 / 9; overflow: hidden;
  border-radius: 30px; background: var(--cream-deep);
  box-shadow: 0 30px 56px -30px rgba(48, 56, 46, .3);
}
.vid img, .vid iframe { display: block; width: 100%; height: 100%; border: 0; }
.vid img { object-fit: cover; }
.vid-play {
  position: absolute; inset: 0; width: 100%; height: 100%;
  display: grid; place-items: center; cursor: pointer;
  padding: 0; border: 0; background: rgba(23, 33, 14, .26);
  transition: background .22s ease;
}
.vid-play:hover, .vid-play:focus-visible { background: rgba(23, 33, 14, .42); }
.vid-disc {
  display: grid; place-items: center;
  width: 84px; height: 84px; border-radius: 50%;
  background: rgba(255, 255, 255, .95); color: var(--green);
  box-shadow: 0 12px 30px -8px rgba(0, 0, 0, .45);
  transition: transform .22s ease;
}
.vid-play:hover .vid-disc, .vid-play:focus-visible .vid-disc { transform: scale(1.07); }
.vid-fig figcaption {
  margin-top: 16px; text-align: center;
  color: var(--muted); font-size: .95rem;
}
@media (prefers-reduced-motion: reduce) {
  .vid-disc, .vid-play { transition: none; }
  .vid-play:hover .vid-disc { transform: none; }
}
@media (max-width: 700px) {
  .vid { border-radius: 22px; }
  .vid-disc { width: 64px; height: 64px; }
}

/* Somebody's own words about their grandparents. Set apart from the page's
   voice so it reads as theirs — indented off a hairline rather than boxed,
   because a memorial in a card with a drop shadow reads as a pull quote in a
   brochure. No coloured rail: the indent and the type do the work. */
.told {
  margin: 26px 0 0; padding-left: 26px;
  border-left: 1px solid var(--line);
}
.told p { color: var(--muted); }
.told p + p { margin-top: 14px; }
@media (max-width: 700px) {
  .told { padding-left: 18px; }
}

/* Build credit. The wordmark is sized to the cap height of the words beside
   it, not to the font size: the lockup carries a monogram taller than its own
   letters, so matching the whole box would leave the name reading small. */
.footer-bottom .built a {
  display: inline-block; vertical-align: middle;
  /* `middle` centres on the x-height, and every word on this line is
     uppercase — so the mark needs lifting onto the cap band. */
  transform: translateY(-1px);
  transition: opacity .2s ease;
}
.footer-bottom .built a:hover { opacity: .62; }
.footer-bottom .built img { display: block; height: 15px; width: auto; }
