/* =================================================================
   The Land Remembered, Wildlife Sanctuary
   A naturalist's field journal of one piece of old Florida.

   House system (one file, in this order):
     1. Tokens          5. Sections, in page order
     2. Base + type     6. Shared components (buttons, focus, viewer)
     3. Small caps      7. Motion contract + reduced motion
     4. Navigation      8. Print (print.css, linked media="print")
   Breakpoints, three only: phone < 600, tablet 600 to 859,
   small desktop 860 to 1023, desktop 1024 and up.
   Paper things are square (--r-paper); screen things are rounded (--r-screen).
   Each later pass rewrites its own section here as one block.
   ================================================================= */

/* ---------- 1. TOKENS ---------- */
:root {
  /* grounds */
  --paper: #fdfaf2;          /* the only section paper */
  --parchment: #efe5d1;      /* sheets and prints only */
  --mat: #f2e8d2;            /* print mats */
  --cypress: #17342b;
  --cypress-deep: #10261f;

  /* text on dark (measured on --cypress) */
  --on-dark: #efe6cf;        /* 10.81:1 */
  --on-dark-dim: #b9c7b4;    /* 7.61:1 */
  --amber: #d9a441;          /* 5.98:1 */
  --amber-press: #d2972a;    /* hover and :active, 6% darker */

  /* text on paper (measured on --paper unless noted) */
  --ink: #1c2a21;            /* 14.35:1 */
  --ink-soft: #44544a;       /* 7.71:1, reading text */
  --brass-ink: #86622a;      /* 5.31:1; never small text on parchment or mat */
  --brass-on-sheet: #7a5824; /* 5.17:1 on parchment, 5.31:1 on mat */
  --muted: #616d5e;          /* 5.22:1, paper only */
  --ink-on-sheet: #56614f;   /* 5.22:1 on parchment, 5.36:1 on mat */
  --sepia-ink: #7d603d;      /* 5.57:1 */

  /* rules and small type */
  --rule-dark: rgba(239, 230, 207, 0.18);
  --rule-light: rgba(23, 52, 43, 0.16);
  --foot-small: #8a9886;     /* 5.24:1 on --cypress-deep */
  --on-deep-head: #9fb3a2;   /* colophon heads and terms, on --cypress-deep */
  --on-deep-warm: #ead9ae;   /* the colophon's visit line, on --cypress-deep */

  /* signal and chart inks */
  --live: #d0483a;
  --chart-on: #b9cdb0;
  --chart-peak: #48684f;

  /* shape */
  --r-paper: 0;
  --r-screen: 6px;

  /* exactly three shadows */
  --lift-print: 0 1px 0 rgba(0, 0, 0, 0.22), 0 24px 44px -26px rgba(0, 0, 0, 0.75);   /* prints and the poster, on dark */
  --lift-plate: 0 1px 0 rgba(110, 86, 52, 0.14), 0 24px 44px -32px rgba(28, 42, 33, 0.55); /* sheets, plates, photos on paper */
  --lift-frame: 0 30px 60px -30px rgba(0, 0, 0, 0.8);                                  /* the camera frame and the viewer */

  /* motion */
  --ease-out: cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-in: cubic-bezier(0.5, 0, 0.75, 0);
  --ease-ink: cubic-bezier(0.3, 0.7, 0.2, 1);
  --t-micro: 150ms;
  --t-ui: 200ms;
  --t-settle: 760ms;
  --ease-settle: cubic-bezier(0.22, 1, 0.36, 1);   /* the poster lay-down */

  /* layout */
  --wrap: 1180px;
  --gutter: max(clamp(16px, 5vw, 28px), env(safe-area-inset-left), env(safe-area-inset-right));

  /* type sizes: the display h1 and h2, the mission thesis and the pull quotes are set on their own. Every
     chapter subhead is --t-h3, every entry title --t-h4; running text --t-body, notes and captions --t-body-s.
     Phones step the two heading sizes down (block 2). */
  --t-h3: 1.6rem;
  --t-h4: 1.35rem;
  --t-body: 1rem;
  --t-body-lh: 1.65;
  --t-body-s: 0.92rem;

  /* type */
  --font-display: "IM Fell English", "IM Fell English Fallback", "Iowan Old Style", "Palatino Linotype", Georgia, serif;
  --font-sc: "IM Fell English SC", "IM Fell English", "IM Fell English Fallback", Georgia, serif;
  --font-body: "Libre Franklin", "Libre Franklin Fallback", "Franklin Gothic Book", "Helvetica Neue", Arial, sans-serif;

  --paper-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.36 0 0 0 0 0.28 0 0 0 0 0.16 0 0 0 0.07 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
}

/* ---------- 2. BASE + TYPOGRAPHY ---------- */
/* Faces, self-hosted (SIL Open Font License 1.1): Google Fonts' latin subsets, byte for byte, with the
   Google version in each filename (build/manifest-fonts.json). IM Fell roman is preloaded in <head>.
   The digit faces at the end of this block must stay the LAST faces declared in the file. */
/* IM Fell English, roman. Preloaded in <head>. (58.5 KB) */
@font-face {
  font-family: "IM Fell English";
  src: url("fonts/im-fell-english-regular-latin-v14.woff2") format("woff2");
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* IM Fell English, italic (56.5 KB) */
@font-face {
  font-family: "IM Fell English";
  src: url("fonts/im-fell-english-italic-latin-v14.woff2") format("woff2");
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* IM Fell English SC (55.6 KB) */
@font-face {
  font-family: "IM Fell English SC";
  src: url("fonts/im-fell-english-sc-regular-latin-v16.woff2") format("woff2");
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* Libre Franklin, variable weight axis, served 400 to 700 (28.6 KB) */
@font-face {
  font-family: "Libre Franklin";
  src: url("fonts/libre-franklin-variable-latin-v20.woff2") format("woff2");
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* Libre Franklin, italic 400 (the only italic the site requests) (17.0 KB) */
@font-face {
  font-family: "Libre Franklin";
  src: url("fonts/libre-franklin-italic-latin-v20.woff2") format("woff2");
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Metric-matched fallbacks: a local system face resized and re-spaced to IM Fell's
   and Libre Franklin's measurements, so the swap barely moves a line. Computed with
   fontTools from site text (staging page, ?noanim, 1440 wide), weighted by font size.
   Chrome, Edge and Firefox honour all four descriptors; Safari honours size-adjust
   (17+) and, at last check, ignores the three overrides, which only move the
   baseline inside each line box because the site sets unitless line-heights. */
/* IM Fell English roman -> Georgia */
@font-face {
  font-family: "IM Fell English Fallback";
  src: local("Georgia");
  font-style: normal;
  font-weight: 400;
  size-adjust: 94.06%;
  ascent-override: 96.25%;
  descent-override: 38.62%;
  line-gap-override: 0.00%;
}
/* IM Fell English italic -> Georgia Italic */
@font-face {
  font-family: "IM Fell English Fallback";
  src: local("Georgia Italic"), local("Georgia-Italic");
  font-style: italic;
  font-weight: 400;
  size-adjust: 78.89%;
  ascent-override: 114.76%;
  descent-override: 46.05%;
  line-gap-override: 0.00%;
}
/* Libre Franklin 400 and 500 -> Arial (Helvetica is width-compatible) */
@font-face {
  font-family: "Libre Franklin Fallback";
  src: local("Arial"), local("ArialMT"), local("Helvetica");
  font-style: normal;
  font-weight: 400;
  size-adjust: 104.29%;
  ascent-override: 92.63%;
  descent-override: 23.59%;
  line-gap-override: 0.00%;
}
/* Libre Franklin 600 and 700 -> Arial Bold */
@font-face {
  font-family: "Libre Franklin Fallback";
  src: local("Arial Bold"), local("Arial-BoldMT"), local("Helvetica Bold"), local("Helvetica-Bold");
  font-style: normal;
  font-weight: 700;
  size-adjust: 100.78%;
  ascent-override: 95.85%;
  descent-override: 24.41%;
  line-gap-override: 0.00%;
}
/* Libre Franklin italic -> Arial Italic */
@font-face {
  font-family: "Libre Franklin Fallback";
  src: local("Arial Italic"), local("Arial-ItalicMT"), local("Helvetica Oblique"), local("Helvetica-Oblique");
  font-style: italic;
  font-weight: 400;
  size-adjust: 104.12%;
  ascent-override: 92.78%;
  descent-override: 23.63%;
  line-gap-override: 0.00%;
}

/* Libre Franklin for paper only: static 400 and 500 instances of the variable file above (same outlines,
   wght pinned; build/scratch/print-brief/print_font.py). Chrome's PDF writer cannot embed a variable font and
   draws its glyphs as Type 3 paths (about 0.9 MB per printed copy). Used only by the print block's body stack
   (print.css), so a screen visitor never downloads them unless app.js warms them; the italic is the same file as above.
   Declared here, not in print.css: a face in a media="print" sheet does not exist on screen, so it could not be
   warmed, and Chrome's print does not wait for a face that only appears with the print media (Type 3 again). (15.5 KB each) */
@font-face { font-family: "Libre Franklin Print"; src: url("fonts/libre-franklin-400-static-latin-v20.woff2") format("woff2"); font-style: normal; font-weight: 400; font-display: swap; unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Libre Franklin Print"; src: url("fonts/libre-franklin-500-static-latin-v20.woff2") format("woff2"); font-style: normal; font-weight: 500 700; font-display: swap; unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Libre Franklin Print"; src: url("fonts/libre-franklin-italic-latin-v20.woff2") format("woff2"); font-style: italic; font-weight: 400; font-display: swap; unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }

/* IM Fell's period figures (a "1" that reads as "I") swapped for EB Garamond's lining digits.
   Same family name + a digits-only unicode-range, declared after the faces above, so these win
   for 0-9 everywhere IM Fell is used. Subset to ten glyphs, about 2 KB each. KEEP THESE LAST.
   The SC family gets the upright face only: it has no italic, and an italic digits-only face
   under that name would make an italic request match a set with no letters in it. */
@font-face { font-family: "IM Fell English"; src: url("fonts/fell-digits.woff2") format("woff2"); font-style: normal; font-weight: 400; font-display: swap; unicode-range: U+0030-0039; }
@font-face { font-family: "IM Fell English"; src: url("fonts/fell-digits-italic.woff2") format("woff2"); font-style: italic; font-weight: 400; font-display: swap; unicode-range: U+0030-0039; }
@font-face { font-family: "IM Fell English SC"; src: url("fonts/fell-digits.woff2") format("woff2"); font-style: normal; font-weight: 400; font-display: swap; unicode-range: U+0030-0039; }

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

html {
  background: var(--cypress-deep);   /* overscroll above the cover and below the footer */
  scroll-behavior: smooth;
  /* anchors and focused controls stop clear of the fixed nav (app.js measures it into --nav-h; it grows with large text) */
  scroll-padding-top: calc(var(--nav-h, 69px) + 5px);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}
body {
  font-family: var(--font-body);
  font-synthesis: none;
  color: var(--ink);
  background: var(--paper);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}
img { max-width: 100%; height: auto; display: block; }
[hidden] { display: none !important; }   /* the attribute always wins over a component's own display */
/* <picture> only chooses a file; the <img> inside keeps every existing layout rule */
picture { display: contents; }
picture > source { display: none; }   /* with contents, a <source> would otherwise become a grid or flex item */
main:focus { outline: none; }   /* the skip link's target, not a control */

h1, h2, h3, h4, h5 { font-family: var(--font-display); font-weight: 400; }
h1, h2, h3 { line-height: 1.12; }
h2 { font-size: clamp(2.35rem, 5vw, 3.8rem); line-height: 1.02; letter-spacing: 0; }
h1, h2, h3, h4, figcaption, blockquote { text-wrap: balance; }
@media (max-width: 599px) { :root { --t-h3: 1.42rem; --t-h4: 1.25rem; } }
/* a word wider than the line breaks instead of scrolling the page (very large text settings) */
h1, h2, h3, h4, p, li, dd, dt { overflow-wrap: anywhere; }
p { max-width: 44em; text-wrap: pretty; }   /* 64ch of Libre Franklin */

/* keeps a hyphenated measure (400-square-foot) on one line */
.nw { white-space: nowrap; }

.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 var(--gutter); }

/* section heads: one title block for every section. Two equal halves meet on the page's
   center line, both hang from a hairline, top-aligned. They stack under 860px. */
.section-head {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 18px 64px; align-items: start;
  margin-bottom: 52px; padding-top: 30px; border-top: 1px solid var(--rule-light);
}
.section-head .section-sub { margin: -4px 0 0; max-width: 42.65em; font-size: 1.04rem; line-height: 1.68; color: var(--ink-soft); }
.cams .section-head, .ledger .section-head, .seasons .section-head, .restoration .section-head { border-top-color: var(--rule-dark); }
.section-head.light h2 { color: var(--on-dark); }
.section-head.light .section-sub { color: var(--on-dark-dim); }
@media (max-width: 859px) {
  .section-head { grid-template-columns: 1fr; padding-top: 24px; }
  .section-head .section-sub { margin-top: 0; }
}

/* dark grounds carry the amber focus ring */
.hero, .nav, .cams, .ledger, .seasons, .restoration, .footer, .viewer { --focus: var(--amber); }

/* ---------- 3. SMALL CAPS: one style, true small caps, no uppercase tracking ---------- */
.now-item dt, .sc-month, .sc-today, .sc-head .sc-note, .badge-rec, .cam-slate p, .cam-plan-zone, .plan-zone, .plan-zone-name, .plan-filter button, .plan-switch button, .support cite, .resto-date, .cover-imprint, .cover-dateline .sc, .viewer-count, .colo-h, .colo-dl dt {
  font-family: var(--font-sc); font-weight: 400; font-style: normal;
  letter-spacing: 0.03em; text-transform: none;
}

/* ---------- 4. NAVIGATION ---------- */
.skip-link {
  position: fixed; top: 12px; left: 12px; z-index: 600;
  padding: 10px 16px; border-radius: var(--r-screen);
  background: var(--on-dark); color: var(--cypress);
  font-weight: 600; font-size: 0.95rem; text-decoration: none;
  transform: translateY(calc(-100% - 24px));
}
.skip-link:focus { transform: none; outline: 2px solid var(--amber); outline-offset: 3px; }

.nav {
  position: fixed; inset: 0 0 auto 0; z-index: 100;
  padding: 10px 0; border-bottom: 1px solid transparent;
  transition: background-color var(--t-ui) var(--ease-out), border-color var(--t-ui) var(--ease-out);
}
.nav.scrolled { background-color: var(--paper); border-bottom-color: var(--rule-light); --focus: var(--brass-ink); }
.nav-inner {
  max-width: var(--wrap); min-height: 48px; margin: 0 auto; padding: 0 var(--gutter);
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
}
.nav-brand { display: flex; align-items: center; min-width: 0; text-decoration: none; color: var(--on-dark); transition: color var(--t-ui) var(--ease-out); }
.nav.scrolled .nav-brand { color: var(--ink); }
.nav-brand-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.15; }
.nav-brand-text strong { font-family: var(--font-display); font-weight: 400; font-size: 1.32rem; }
.nav-brand-text em { font-family: var(--font-display); font-style: italic; font-size: 0.95rem; opacity: 0.8; }
.nav-links { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 8px 26px; }
.nav-links a {
  text-decoration: none; color: var(--on-dark); font-size: 0.93rem; font-weight: 500;
  transition: color var(--t-ui) var(--ease-out), opacity var(--t-ui) var(--ease-out), text-decoration-color var(--t-ui) var(--ease-out);
}
.nav.scrolled .nav-links a { color: var(--ink); }
.nav .nav-links a.nav-cta {
  background: var(--amber); color: var(--cypress); padding: 8px 16px; border-radius: var(--r-paper);
  transition: background-color var(--t-ui) var(--ease-out);
}
.nav .nav-links a.nav-cta:active { background: var(--amber-press); }
.nav-toggle { display: none; }
@media (hover: hover) {
  .nav-links a:hover { opacity: 0.75; }
  .nav .nav-links a.nav-cta:hover { background: var(--amber-press); opacity: 1; }
}

/* desktop: the section on screen is marked with a 1px underline (aria-current, set by app.js) */
@media (min-width: 860px) {
  .nav-links a {
    text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 7px;
    text-decoration-color: transparent;
  }
  .nav-links a[aria-current] { text-decoration-color: currentColor; }
  .nav .nav-links a.nav-cta { text-underline-offset: 4px; }
}

/* small desktop: the full row, a size tighter, so it fits from 860px */
@media (min-width: 860px) and (max-width: 1023px) {
  .nav-brand-text strong { font-size: 1.2rem; }
  .nav-links { column-gap: 16px; }
  .nav-links a { font-size: 0.86rem; }
  .nav .nav-links a.nav-cta { padding: 8px 12px; }
}

/* phone + tablet: a full-screen cypress sheet. Closed it is hidden and inert (app.js), so Tab
   never reaches it; open, the page behind is inert and the sheet holds focus. */
@media (max-width: 859px) {
  .nav-brand { flex: 1 1 auto; min-width: 0; }
  .nav-toggle {
    flex: none; display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 5px;
    position: relative; z-index: 110;
    width: 44px; height: 44px; padding: 0; margin-right: -10px;
    background: none; border: 0; cursor: pointer; color: var(--on-dark);
  }
  .nav-toggle span { width: 24px; height: 2px; background: currentColor; transition: transform var(--t-ui) var(--ease-out), opacity var(--t-ui) var(--ease-out); }
  .nav.scrolled .nav-toggle { color: var(--ink); }
  .nav-toggle.open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .nav-toggle.open span:nth-child(2) { opacity: 0; }
  .nav-toggle.open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

  .nav-links {
    --focus: var(--amber);
    position: fixed; inset: 0; z-index: 105;
    flex-direction: column; flex-wrap: nowrap; justify-content: flex-start; align-items: stretch; gap: 0;
    padding: 96px var(--gutter) 40px; overflow-y: auto;
    background: var(--cypress);
    visibility: hidden; opacity: 0;
    transition: opacity var(--t-ui) var(--ease-out), visibility 0s linear var(--t-ui);
  }
  .nav-links.open { visibility: visible; opacity: 1; transition: opacity var(--t-ui) var(--ease-out), visibility 0s; }
  .nav-links a, .nav.scrolled .nav-links a {
    color: var(--on-dark); font-family: var(--font-display); font-weight: 400; font-size: 1.8rem; line-height: 1.2;
    padding: 14px 0; border-bottom: 1px solid var(--rule-dark);
  }
  .nav-links a:first-child { border-top: 1px solid var(--rule-dark); }
  .nav .nav-links a.nav-cta {
    align-self: flex-start; margin-top: 32px; padding: 14px 24px; border: 0;
    font-family: var(--font-body); font-weight: 600; font-size: 1.05rem; color: var(--cypress);
  }
  .nav.menu-open .nav-brand { position: relative; z-index: 110; color: var(--on-dark); }
  .nav.menu-open .nav-toggle { color: var(--on-dark); }
  html.menu-open, html:has(.nav-links.open) { overflow: hidden; }
}
@media (max-width: 599px) {
  .nav-brand-text strong { font-size: 1.14rem; }
}
/* without app.js (a failed download, scripts off): no menu button; the nav is an ordinary bar at the top of the
   page with its links in a wrapping row under the name below 860px */
html:is(:not(.js), .noapp) .nav { position: relative; background: var(--cypress-deep); }
@media (max-width: 859px) {
  html:is(:not(.js), .noapp) .nav-toggle { display: none; }
  html:is(:not(.js), .noapp) .nav-inner { flex-wrap: wrap; row-gap: 4px; padding-bottom: 4px; }
  html:is(:not(.js), .noapp) .nav-links {
    position: static; inset: auto; flex: 1 0 100%; flex-direction: row; flex-wrap: wrap; justify-content: flex-start; align-items: center; gap: 2px 18px;
    padding: 0; overflow: visible; background: none; visibility: visible; opacity: 1; transform: none;
  }
  html:is(:not(.js), .noapp) .nav-links a { font-family: var(--font-body); font-size: 0.95rem; font-weight: 500; line-height: 1.3; padding: 8px 0; border: 0; }
  html:is(:not(.js), .noapp) .nav .nav-links a.nav-cta { margin-top: 0; padding: 8px 12px; font-size: 0.95rem; }
}

/* ---------- 5. SECTIONS, in page order ---------- */

/* ===== cover: the dusk river, the poster laid down like a print, the place read live ===== */
/* One grid with named areas; .hero-copy is display: contents, so the DOM order (title, sub,
   actions, poster, foot) is also the focus and reading order at every width. The poster holds
   nothing focusable. The photo is a pure crop of the owners' original (no pixels altered). */
.hero { position: relative; overflow: hidden; background: var(--cypress-deep); }
.hero-bg { position: absolute; inset: 0; background-color: var(--cypress-deep); }
.hero-bg-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 70%; }
.hero-bg::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(100deg, rgba(16, 26, 20, 0.86) 0%, rgba(16, 26, 20, 0.7) 40%, rgba(16, 26, 20, 0.6) 55%, rgba(16, 26, 20, 0.18) 100%),
    linear-gradient(to top, rgba(16, 26, 20, 0.7) 0%, rgba(16, 26, 20, 0) 30%);
}
.hero-inner {
  /* the poster's picture height: never taller than the screen leaves room for */
  --poster-h: min(560px, calc(100vh - 260px));
  position: relative; z-index: 2;
  width: 100%; max-width: var(--wrap); min-height: 100vh; margin: 0 auto;
  padding: 112px var(--gutter) 26px;
  display: grid; column-gap: 48px;
  /* the poster column is the poster's own width (390px), so the copy column always holds "Remembered" on one line */
  grid-template-columns: minmax(0, 1fr) minmax(0, 390px);
  grid-template-rows: minmax(0, 1fr) auto auto auto minmax(0, 1fr) auto;
  grid-template-areas: ". poster" "title poster" "sub poster" "actions poster" ". poster" "foot foot";
}
@supports (height: 100svh) {
  .hero-inner { --poster-h: min(560px, calc(100svh - 260px)); min-height: 100svh; }
}
.hero-copy { display: contents; }
.hero h1 {
  grid-area: title;
  /* "Remembered" is about 5.6em wide, so the size is capped to the screen width */
  font-size: min(clamp(3.4rem, 8.4vw, 6.6rem), calc((100vw - 60px) / 5.9));
  line-height: 0.94; letter-spacing: 0; color: var(--on-dark);
}
.h1line { display: block; }
.hero-sub { grid-area: sub; margin-top: 26px; max-width: 30.27em; font-size: 1.12rem; color: var(--on-dark); }
.hero-actions { margin-top: 34px; display: flex; flex-wrap: wrap; align-items: center; gap: 26px; }
.hero .hero-actions { grid-area: actions; }

/* the poster, matted like a print: a screen-sized picture inside a fixed mat */
.hero-poster { grid-area: poster; align-self: center; justify-self: end; container-type: inline-size; width: 100%; display: flex; justify-content: flex-end; }
.hero-poster figure {
  --pw: min(366px, calc(var(--poster-h) * 0.6671));
  position: relative; isolation: isolate; width: calc(var(--pw) + 24px); margin: 0;
  padding: 12px 12px 0; background: var(--mat);
}
@supports (width: 1cqi) { .hero-poster figure { --pw: min(calc(100cqi - 24px), calc(var(--poster-h) * 0.6671)); } }
/* two shadows: ::before is the print at rest, ::after the print held above the page (motion block) */
.hero-poster figure::before, .hero-poster figure::after { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none; }
.hero-poster figure::before { box-shadow: var(--lift-print); }
.hero-poster figure::after { box-shadow: 0 2px 0 rgba(0, 0, 0, 0.16), 0 44px 70px -28px rgba(0, 0, 0, 0.8); opacity: 0; }
.hero-poster img { width: var(--pw); height: auto; aspect-ratio: 1024 / 1535; border-radius: var(--r-paper); background-color: var(--ph); }
.hero-poster figcaption { padding: 10px 2px 12px; text-align: left; font-family: var(--font-display); font-style: italic; font-size: 0.98rem; line-height: 1.4; color: var(--ink-on-sheet); }

/* the cover foot: a hairline, the dateline (app.js; absent without JS) and the imprint */
.cover-foot {
  grid-area: foot; position: relative; margin-top: 44px; padding-top: 13px;
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 390px); column-gap: 48px; row-gap: 6px; align-items: start;
}
.cover-foot::before { content: ""; position: absolute; inset: 0 0 auto; height: 1px; background: rgba(233, 224, 200, 0.26); transform-origin: 0 50%; }
.cover-foot p { max-width: none; margin: 0; line-height: 1.45; }
.cover-dateline { font-family: var(--font-display); font-style: italic; font-size: 1rem; color: var(--on-dark); }
.cover-dateline .sc { font-style: normal; }
.cover-imprint { justify-self: end; text-align: right; text-wrap: balance; font-size: 0.95rem; color: var(--on-dark); }
html:is(:not(.js), .noapp) .cover-dateline { display: none; }
html.app .cover-dateline { min-height: 2.9em; }   /* two lines held, so the tide clause never moves anything */
html:is(:not(.js), .noapp) .hero-inner { padding-top: 56px; }   /* without app.js the nav is a bar above the cover (block 4) */

/* laptop screens (768 to 820px tall): a little less air, so the foot and its dateline stay on the first screen */
@media (min-width: 1024px) and (max-height: 820px) {
  .hero-inner { --poster-h: min(560px, calc(100vh - 304px)); padding-top: 96px; }
  @supports (height: 100svh) { .hero-inner { --poster-h: min(560px, calc(100svh - 304px)); } }
  .cover-foot { margin-top: 32px; }
}

/* below 1024 the copy runs further across the photo: the scrim holds 4.5:1 to the right edge of the text */
@media (max-width: 1023px) {
  .hero-bg::after {
    background:
      linear-gradient(100deg, rgba(16, 26, 20, 0.86) 0%, rgba(16, 26, 20, 0.74) 45%, rgba(16, 26, 20, 0.5) 100%),
      linear-gradient(to top, rgba(16, 26, 20, 0.7) 0%, rgba(16, 26, 20, 0) 30%);
  }
}
/* tablet: the same areas, the poster column at 38% */
@media (min-width: 600px) and (max-width: 1023px) {
  .hero-bg-img { object-position: 68% 70%; }   /* portrait tablets: the trunks part for the sunset */
  .hero-inner { padding-top: 104px; column-gap: 32px; grid-template-columns: minmax(0, 1fr) 38%; }
  .hero h1 { font-size: min(clamp(3rem, 8.4vw, 6.6rem), calc((62vw - 76px) / 5.9)); }
  .hero-sub { margin-top: 18px; font-size: 1.06rem; }
  .hero .hero-actions { margin-top: 28px; column-gap: 22px; row-gap: 4px; }
  .cover-foot { column-gap: 32px; grid-template-columns: minmax(0, 1fr) 38%; }
}

/* phone: title, poster, sub, actions, foot in one column */
@media (max-width: 599px) {
  .hero-inner {
    padding: 88px var(--gutter) 30px;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
    grid-template-areas: "title" "poster" "sub" "actions" "foot";
    align-content: start;
  }
  .hero-bg-img { object-position: 80% 70%; }   /* the tall phone crop finds the sunset over the water */
  .hero h1 { font-size: min(3.1rem, calc((100vw - 40px) / 5.9)); }
  /* the poster on the gutter, its print (mat and caption) never taller than 46% of the screen, so the
     primary button is on the first screen of a 390 by 844 phone */
  .hero-inner { --poster-h: clamp(240px, calc(46vh - 108px), 420px); }
  @supports (height: 100svh) { .hero-inner { --poster-h: clamp(240px, calc(46svh - 108px), 420px); } }
  .hero-poster { margin-top: 18px; justify-self: start; justify-content: flex-start; }
  .hero-poster figure { --pw: min(calc(82vw - 24px), calc(var(--poster-h) * 0.6671)); }
  .hero-sub { margin-top: 18px; font-size: 1.06rem; }
  .hero .hero-actions { margin-top: 18px; flex-direction: column; align-items: stretch; gap: 8px; }
  .hero .hero-actions .btn { justify-content: center; min-height: 48px; }
  .hero .hero-actions .text-link { align-self: flex-start; }
  .cover-foot { margin-top: 40px; grid-template-columns: minmax(0, 1fr); row-gap: 8px; }
  .cover-foot p { font-size: 0.95rem; }
  .cover-imprint { justify-self: start; text-align: left; }
}

/* ===== mission: paper; the site's large-type thesis beside the emblem in one ink ===== */
.mission { background-color: var(--paper); background-image: var(--paper-grain); }
.mission-inner {
  display: grid; grid-template-columns: minmax(0, 1fr); justify-items: start; gap: 36px;
  padding: 80px var(--gutter);
}
/* the Corbetts' emblem, recolored to cypress ink (brand/emblem-scene-ink, 1250x650) */
.mission-emblem { width: min(300px, 78%); height: auto; aspect-ratio: 1250 / 650; }
.mission p {
  max-width: 16.32em;
  font-family: var(--font-display); font-size: clamp(1.55rem, 1.2rem + 1.1vw, 2.1rem); line-height: 1.3;
  color: var(--ink); hanging-punctuation: first last;
}
.mission em { font-style: italic; color: var(--sepia-ink); }
@media (min-width: 600px) { .mission-inner { padding: 96px var(--gutter); gap: 40px; } }
/* desktop: the house split. The emblem in the left half (from the wrap's left edge, 440px at most), centred on
   the thesis, which runs in the right half from the page's centre line, as every section intro does */
@media (min-width: 1024px) {
  .mission-inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 64px; align-items: center;
    padding: 112px var(--gutter);
  }
  .mission-emblem { width: 100%; max-width: 440px; }
  .mission p { max-width: none; font-size: 2.1rem; }
}

/* ===== cameras: cypress ===== */
.cams { padding: 110px 0 64px; background: var(--cypress); color: var(--on-dark); }
.cams .section-head h2 { color: var(--on-dark); }
.cams .section-head .section-sub { color: var(--on-dark-dim); }

/* right now at the sanctuary: sky, weather and the regional nesting season. The cover dateline
   owns the time and the tide. Every slot is held from the first paint (two lines, a dim ellipsis),
   so values arriving never move the page; without JS the strip is not shown at all. */
.now-strip {
  display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: start; column-gap: 40px;
  margin: 0 0 30px; padding: 20px 0 4px;
  border-top: 1px solid var(--rule-dark); border-bottom: 1px solid var(--rule-dark);
  color: var(--on-dark);
}
html:is(:not(.js), .noapp) .now-strip { display: none; }
.cam-print-line { display: none; }   /* the strip's stand-in on paper (print block) */
.now-label { max-width: none; margin: 0; padding-top: 19px; white-space: nowrap; font-family: var(--font-display); font-style: italic; font-size: 1.12rem; line-height: 1.3; color: var(--on-dark); }
.now-items { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 1fr); gap: 10px 32px; margin: 0; }
.now-item { min-width: 0; }
.now-item dt { font-size: 0.95rem; line-height: 1.4; color: var(--on-dark-dim); }
.now-item dd {
  display: grid; min-height: calc(2 * 1.45em); margin: 1px 0 0;
  font-size: 0.95rem; line-height: 1.45; font-weight: 500; color: var(--on-dark); font-variant-numeric: tabular-nums;
}
.now-item dd > span { grid-area: 1 / 1; min-width: 0; }
.now-wait, .now-item.is-none .now-val { color: var(--on-dark-dim); font-weight: 400; }
.now-item.is-none .almanac { display: none; }
.now-item:not(.is-set) .now-val, .now-item.is-set .now-wait { opacity: 0; }
.now-sky .now-val { display: flex; align-items: flex-start; gap: 10px; }
/* the almanac: a hairline arc of the day, the sun's place on it in amber; below the horizon at night */
.almanac { flex: none; width: 64px; height: 22px; margin-top: -1px; overflow: visible; }
.almanac-horizon, .almanac-arc { fill: none; stroke: var(--on-dark-dim); stroke-width: 1; vector-effect: non-scaling-stroke; }
.almanac-arc { stroke-opacity: 0.55; }
.almanac-dot { fill: var(--amber); }
.almanac.is-below .almanac-dot { fill: var(--on-dark-dim); opacity: 0.6; }
@media (max-width: 1023px) {
  .now-strip { grid-template-columns: minmax(0, 1fr); row-gap: 10px; }
  .now-label { padding-top: 0; }
}
/* phone: sky | weather on one row, the season under both */
@media (max-width: 599px) {
  .now-label { white-space: normal; }
  .now-items { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px 18px; }
  .now-season { grid-column: 1 / -1; }
  .now-sky .now-val { flex-direction: column; gap: 4px; }
  /* the arc stacks over its text here, so this row holds the arc plus two lines (three for the weather) */
  .now-sky dd, .now-wx dd { min-height: calc(26px + 2 * 1.45em); }
}

/* the player: a screen thing, rounded. app.js keeps .cam-frame[data-state] (idle | acquiring | locked |
   paused) and [data-picture] (still | video), and #camLayout[data-tune] while the acquire runs (motion
   block). Nothing laid over the picture takes the pointer: a tap anywhere reaches the screen or the button.
   .cam-frame[data-source] is "recorded" for every clip today. When a real stream exists, "live" swaps the
   chip's word for "Live" and gives it the site's only permitted pulse; that is not built until then. */
/* The DOM order is the reading and Tab order at every width: the screen, what the clip shows, the recordings, the
   note, the planned card, the ask. 1024 and up: the screen and its caption on the left with the recordings beside
   them, then the note and the ask on the left with the planned card beside them (its top level with the note).
   The last row takes the slack, so the planned card never pushes the ask down. */
.cam-layout {
  display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); column-gap: 32px; align-items: start;
  grid-template-areas: "frame tiles" "caption tiles" "note plan" "ask plan";
  grid-template-rows: auto auto auto 1fr;
}
.cam-frame { grid-area: frame; }
.cam-caption { grid-area: caption; }
.cam-tiles { grid-area: tiles; }
.cam-demo-note { grid-area: note; }
.cam-plan { grid-area: plan; }
.cam-ask { grid-area: ask; }
.cam-frame {
  position: relative; isolation: isolate; aspect-ratio: 16 / 10; overflow: hidden; cursor: pointer;
  border-radius: var(--r-screen); background: var(--ph, var(--cypress-deep)); box-shadow: var(--lift-frame);
}
html:is(:not(.js), .noapp) .cam-frame { cursor: default; }
.cam-frame > .cam-still, .cam-frame > video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* the still is the picture until the clip has a decoded frame */
.cam-frame > video { opacity: 0; }
.cam-frame[data-picture="video"] > video { opacity: 1; }
.cam-veil, .cam-vignette, .cam-slate, .cam-topbar, .cam-lower, .cam-dip { pointer-events: none; }
/* the acquire's veil: the still at 70% (::before) under a parchment wash (::after); at rest both are 0 */
.cam-veil::before, .cam-veil::after { content: ""; position: absolute; inset: 0; opacity: 0; }
.cam-veil::before { background: #08100c; }
.cam-veil::after { background: var(--parchment); mix-blend-mode: color; }
/* scrims sized so the chips, the lower third and the slate hold 4.5:1 over the brightest clip */
.cam-vignette {
  position: absolute; inset: 0;
  background:
    linear-gradient(to top, rgba(8, 16, 12, 0.84) 0%, rgba(8, 16, 12, 0.56) 22%, rgba(8, 16, 12, 0) 44%),
    linear-gradient(to bottom, rgba(8, 16, 12, 0.45), rgba(8, 16, 12, 0) 26%);
}
/* the slate: the clip's name and its record, in small caps, over the still while the first frame decodes */
.cam-slate {
  position: absolute; inset: 0; z-index: 2; overflow: hidden;   /* very large text: the card clips itself, never the player */
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  padding: 0 10%; text-align: center; color: var(--parchment); opacity: 0;
  background: radial-gradient(closest-side, rgba(8, 16, 12, 0.62), rgba(8, 16, 12, 0)) 50% 50% / 92% 76% no-repeat;
}
.cam-slate p { max-width: 28em; margin: 0; text-wrap: balance; }
.cam-slate-line span { display: inline-block; }   /* breaks between the date and the source, not inside them */
.cam-slate-name { font-size: clamp(1.5rem, 1.1rem + 1.2vw, 2.15rem); line-height: 1.1; }
.cam-slate-name::after { content: ""; display: block; width: 44px; height: 1px; margin: 12px auto 0; background: rgba(239, 229, 209, 0.55); }
.cam-slate-line { font-size: 1rem; line-height: 1.45; }
.cam-topbar { position: absolute; z-index: 3; top: 16px; left: 16px; right: 16px; display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 8px; }
.badge-rec { display: inline-flex; align-items: center; padding: 3px 10px; border-radius: var(--r-screen); background: rgba(8, 16, 12, 0.78); color: var(--on-dark); font-size: 1rem; line-height: 1.4; }
.cam-clock {
  padding: 5px 11px; border-radius: var(--r-screen); background: rgba(8, 16, 12, 0.72);
  color: rgba(255, 255, 255, 0.94); font-size: 0.82rem; font-weight: 600; letter-spacing: 0.04em; font-variant-numeric: tabular-nums;
}
/* the lower third: the clip's name, then the day and time it was recorded */
.cam-lower { position: absolute; z-index: 3; left: 20px; right: 84px; bottom: 18px; color: #fff; }
.cam-lower h3 { font-size: var(--t-h3); line-height: 1.15; }
.cam-when { max-width: none; margin-top: 4px; font-size: 0.82rem; line-height: 1.4; font-variant-numeric: tabular-nums; color: rgba(255, 255, 255, 0.88); }
/* the one control */
.cam-play {
  position: absolute; z-index: 4; right: 16px; bottom: 16px; width: 44px; height: 44px;
  display: grid; place-items: center; padding: 0; border: 1px solid rgba(239, 230, 207, 0.55); border-radius: 50%;
  background: rgba(8, 16, 12, 0.62); color: var(--on-dark); cursor: pointer;
  transition: background-color var(--t-ui) var(--ease-out), border-color var(--t-ui) var(--ease-out);
}
.cam-play:active { background: rgba(8, 16, 12, 0.9); }
/* focus: the amber ring 2px out, on a dark collar, so it holds 3:1 over the brightest water */
.cam-play:focus-visible { background: rgba(8, 16, 12, 0.62); outline-offset: 2px; box-shadow: 0 0 0 6px rgba(8, 16, 12, 0.72); }
.cam-play-i { grid-area: 1 / 1; width: 20px; height: 20px; fill: currentColor; }
.cam-play .is-pause, .cam-play.is-playing .is-play { display: none; }
.cam-play.is-playing .is-pause { display: block; }
html:is(:not(.js), .noapp) .cam-tiles { display: none; }   /* the tiles (hidden in the markup) and the play button only work with app.js */
@media (hover: hover) { .cam-play:hover { background: rgba(8, 16, 12, 0.86); border-color: var(--on-dark); } }
/* a switch: a straight cut through a 120ms dip to cypress */
.cam-dip { position: absolute; inset: 0; z-index: 5; background: var(--cypress); opacity: 0; }
.cam-dip.on { opacity: 1; }
/* under the frame: what the clip shows, where the clips come from, one quiet line about the network */
.cam-caption { margin-top: 16px; max-width: 42.65em; font-size: 1rem; line-height: 1.6; color: var(--on-dark-dim); }
.cam-demo-note { margin-top: 8px; max-width: 44em; font-size: var(--t-body-s); line-height: 1.55; font-style: italic; color: var(--on-dark-dim); }
.cam-ask { margin-top: 18px; padding-top: 14px; max-width: none; border-top: 1px solid var(--rule-dark); font-size: var(--t-body-s); line-height: 1.55; color: var(--on-dark-dim); }
.cam-ask a { color: var(--on-dark); font-weight: 500; text-decoration: underline; text-decoration-color: var(--amber); text-decoration-thickness: 1px; text-underline-offset: 4px; }
@media (hover: hover) { .cam-ask a:hover { text-decoration-color: var(--on-dark); } }

/* the tiles. Desktop: a column of recordings, thumbnail beside the name and its date. Under 860px: a
   strip that scrolls sideways. The active one carries an inset amber hairline (the outline is the focus
   ring's) and, while the tour runs, a 2px hairline under its picture that fills over the dwell. From 1024 to 1179
   the thumbnail narrows with the screen (112px down to about 93px at 1024), so the column of five ends level
   with the screen beside it. */
.cam-tiles { display: grid; gap: 2px; }
.cam-card {
  position: relative; display: grid; grid-template-columns: var(--thumb, 112px) minmax(0, 1fr); align-items: center; column-gap: 16px;
  width: 100%; padding: 7px; border: 0; border-radius: var(--r-screen); background: transparent;
  color: var(--on-dark); font: inherit; text-align: left; cursor: pointer;
  transition: background-color var(--t-ui) var(--ease-out);
}
.cam-card::before { content: ""; position: absolute; inset: 0; z-index: 3; border-radius: inherit; box-shadow: inset 0 0 0 1px var(--amber); opacity: 0; pointer-events: none; }
.cam-card.is-active { background: rgba(239, 230, 207, 0.06); cursor: default; }
.cam-card.is-active::before { opacity: 1; }
.cam-card:not(.is-active):active { background: rgba(239, 230, 207, 0.09); }
.cam-card-thumb { position: relative; display: block; overflow: hidden; aspect-ratio: 16 / 10; border-radius: 4px; background: var(--ph, var(--cypress-deep)); }
.cam-card-thumb img { width: 100%; height: 100%; object-fit: cover; transition: filter var(--t-ui) var(--ease-out); }
.cam-card-dwell { position: absolute; z-index: 2; left: 0; right: 0; bottom: 0; height: 2px; background: var(--amber); transform: scaleX(0); transform-origin: 0 50%; }
.cam-card:not(.is-active) .cam-card-dwell { visibility: hidden; }
.cam-card-text { display: flex; flex-direction: column; min-width: 0; }
.cam-card-name { font-family: var(--font-display); font-size: 1.22rem; line-height: 1.2; color: var(--on-dark); }
.cam-card-date { margin-top: 2px; font-family: var(--font-display); font-style: italic; font-size: 1rem; line-height: 1.3; color: var(--on-dark-dim); }
.cam-card-rec { display: none; }   /* paper only: "Recorded July 14, 2026", written by app.js from data-rec */
@media (hover: hover) {
  .cam-card:not(.is-active):hover { background: rgba(239, 230, 207, 0.04); }
  .cam-card:hover .cam-card-thumb img { filter: brightness(1.14); }
}

/* the planned network: paper, not screen. A square-cornered parchment card with an inner crop of the
   sanctuary map and only the markers the camera plate renders (5, 6, 7, 8, 11, 12); Zone C as its letter */
.cam-plan {
  --focus: var(--brass-ink);
  position: relative; display: grid; grid-template-columns: 112px minmax(0, 1fr); grid-template-rows: 1fr auto 1fr; column-gap: 16px;
  margin-top: 8px; padding: 8px; background-color: var(--parchment); background-image: var(--paper-grain);
  border-radius: var(--r-paper); box-shadow: var(--lift-print); color: var(--ink);
}
.cam-plan-map { grid-row: 1 / -1; position: relative; display: block; aspect-ratio: 1; background: var(--ph); outline: 1px solid rgba(110, 86, 52, 0.3); outline-offset: -1px; }
.cam-plan-map img { width: 100%; height: 100%; }
.cam-plan-pin { position: absolute; left: var(--x); top: var(--y); width: 6px; height: 6px; margin: -3px 0 0 -3px; border-radius: 50%; background: var(--cypress); box-shadow: 0 0 0 1.5px var(--parchment); }
.cam-plan-zone {
  position: absolute; left: var(--x); top: var(--y); transform: translate(-50%, -50%);
  font-size: 0.95rem; line-height: 1; color: var(--cypress);
  text-shadow: 0 0 2px var(--parchment), 0 0 3px var(--parchment);
}
.cam-plan-title { grid-row: 2; align-self: end; max-width: none; margin: 0; text-wrap: balance; font-family: var(--font-display); font-size: 1.2rem; line-height: 1.2; color: var(--cypress); }
.cam-plan-link {
  grid-row: 3; align-self: start; justify-self: start; margin-top: 6px; text-wrap: balance;
  font-size: 0.9rem; font-weight: 500; color: var(--brass-on-sheet);
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px;
}
.cam-plan-link::after { content: ""; position: absolute; inset: 0; }   /* the whole card is the target */
@media (hover: hover) { .cam-plan-link:hover { color: var(--cypress); } }

/* small desktop: the thumbnail narrows with the screen, so the five recordings end level with the screen
   (the screen is (100vw - 88px) x 0.3846 tall; five rows of 0.625 x thumb + 14px, 2px apart, match it) */
@media (min-width: 1024px) and (max-width: 1179px) {
  .cam-tiles { --thumb: clamp(88px, calc((100vw - 88px) * 0.1231 - 25px), 112px); }
}
/* under 1024px, one column in the DOM order: the screen, what the clip shows (right under the picture), the
   recordings as a strip, the note, the planned card, the ask. The strip: 4:3 tiles that scroll sideways under
   860px (148px on phones, the third peeking at 390; tablets show four and a part of the fifth), and from 860px
   the five fill the row */
@media (max-width: 1023px) {
  .cam-layout { grid-template-columns: minmax(0, 1fr); grid-template-areas: "frame" "caption" "tiles" "note" "plan" "ask"; grid-template-rows: none; }
  .cam-caption { margin-top: 14px; }
  .cam-tiles {
    display: flex; gap: 10px; overflow-x: auto; overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory; scroll-padding-inline: var(--gutter);
    margin: 16px calc(-1 * var(--gutter)) 0; padding: 6px var(--gutter);
    scrollbar-width: none;
  }
  .cam-tiles::-webkit-scrollbar { display: none; }
  /* a tile is 4:3 and grows taller (never clips) when its name and date need more room at large text: the
     picture fills the tile behind the words, which sit on its foot in the flow */
  .cam-card {
    flex: 0 0 clamp(148px, calc((100% - 40px) / 4.4), 200px); display: flex; flex-direction: column; justify-content: flex-end; align-items: stretch;
    aspect-ratio: 4 / 3; padding: 0; scroll-snap-align: start; background: var(--ph, var(--cypress-deep));
  }
  .cam-card.is-active { background: var(--ph, var(--cypress-deep)); }
  .cam-card-thumb { position: absolute; inset: 0; aspect-ratio: auto; border-radius: inherit; }
  .cam-card-thumb::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to top, rgba(8, 16, 12, 0.86) 0%, rgba(8, 16, 12, 0.5) 34%, rgba(8, 16, 12, 0) 62%); }
  .cam-card-text { position: relative; z-index: 2; padding: 0 8px 8px 10px; overflow-wrap: anywhere; }
  .cam-card-name { font-size: 1.02rem; line-height: 1.15; color: #fff; }
  .cam-card-date { margin-top: 0; font-size: 0.95rem; color: rgba(255, 255, 255, 0.86); }
  .cam-demo-note { margin-top: 14px; }
  .cam-plan { max-width: 440px; margin-top: 26px; grid-template-columns: 104px minmax(0, 1fr); }
  .cam-ask { margin-top: 22px; }
}
@media (min-width: 860px) and (max-width: 1023px) {
  .cam-card { flex: 1 0 0; min-width: 0; }
}
@media (max-width: 599px) {
  .cam-frame { aspect-ratio: 4 / 3; }
  .cam-topbar { top: 12px; left: 12px; right: 12px; }
  .cam-lower { left: 16px; right: 72px; bottom: 14px; }
  .cam-when-time { display: none; }   /* phones: the name and the date only */
  .cam-play { right: 12px; bottom: 12px; }
  .cam-slate { gap: 8px; padding: 0 8%; }
  .cam-slate-line { font-size: 0.95rem; }
  .cam-caption { font-size: 0.98rem; }
  .cam-plan { grid-template-columns: 96px minmax(0, 1fr); column-gap: 14px; }
}

/* ===== the ledger: cypress, continuing the cameras. Done set apart from planned ===== */
/* A named break: the house head (hairline, title in the left half, no intro), then two ruled
   lists that hang from the head's own centre line. Left, what is on the land today, figures in
   amber. Right, what the camera network would add, marked planned, figures in on-dark at 72%
   (6.37:1 on cypress). Under both, the source line. No motion here. */
.ledger { padding: 0 0 104px; background: var(--cypress); color: var(--on-dark); }
.ledger .section-head { margin-bottom: 40px; }
.ledger-cols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-rows: auto auto; column-gap: 64px; }
/* each column spans both rows on the parent's tracks, so the two lists start on one line
   even when one head wraps */
.ledger-col { display: grid; grid-row: span 2; grid-template-rows: subgrid; row-gap: 0; min-width: 0; }
.ledger-h { align-self: end; margin: 0 0 14px; font-size: var(--t-h3); line-height: 1.2; color: var(--on-dark); }
.ledger-state { font-style: italic; font-size: 1.2rem; color: var(--on-dark-dim); white-space: nowrap; }
.ledger-list { margin: 0; border-top: 1px solid var(--rule-dark); }
.ledger-row { display: flex; align-items: baseline; gap: 14px; padding: 15px 0 13px; border-bottom: 1px solid var(--rule-dark); }
.ledger-row dt { flex: 1; display: flex; align-items: baseline; gap: 14px; font-family: var(--font-display); font-size: 1.28rem; line-height: 1.3; color: var(--on-dark); }
.ledger-row dt::after { content: ""; flex: 1; min-width: 24px; border-bottom: 1px dotted rgba(239, 230, 207, 0.4); transform: translateY(-5px); }
.ledger-row dd { margin: 0; font-family: var(--font-display); font-size: 2rem; line-height: 1; color: var(--amber); white-space: nowrap; }
.ledger-planned .ledger-row dd { color: rgba(239, 230, 207, 0.72); }
.ledger-source { margin: 22px 0 0; max-width: none; font-style: italic; font-size: var(--t-body-s); line-height: 1.5; color: var(--on-dark-dim); }
@media (max-width: 1023px) {
  .ledger-state { font-size: 1.08rem; }
  .ledger-row dt { font-size: 1.12rem; }
  .ledger-row dd { font-size: 1.7rem; }
}
/* phone and tablet: one column, what is done first, 28px above each list head */
@media (max-width: 859px) {
  .ledger { padding-bottom: 80px; }
  .ledger .section-head { margin-bottom: 0; }
  .ledger-cols { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; }
  .ledger-col { grid-row: auto; grid-template-rows: none; }
  .ledger-h { margin-top: 28px; }
}
/* phone: the type, gaps and leader shrink with the screen below about 350px, so the longest
   label ("Cameras on their own solar power") still holds one line at 320 */
@media (max-width: 599px) {
  .ledger { padding-bottom: 72px; }
  .ledger-row { gap: min(14px, 3vw); }
  .ledger-row dt { gap: min(14px, 3vw); font-size: min(1.1rem, 5vw); }
  .ledger-row dt::after { min-width: min(24px, 5vw); }
  .ledger-row dd { font-size: min(1.6rem, 7.2vw); }
}

/* ===== the land: paper. A calm opener, the camera plate with its numbered key, one promise =====
   Opener: the features in columns 1 to 6 beside one photograph in columns 7 to 12, inside the wrap and
   starting on the house centre line (sticky from 1024px); below 1024 the photograph is a 4:3 band under the
   head, within the margins (Oct 3: Josh preferred photos that stop at the page margins, not the screen edge). The plate: the illustrated map on a square parchment mat (500px at most, the 1000px file is its
   2x), two layers over it (the camera plan, the landmarks; the hidden one is inert), a roughened zone
   outline per parcel that only shows while its zone is hovered or chosen, and the key beside it (stacked
   below 1024). Nests, the rookery and the hub are never marked. No motion on entry; interaction is 150ms. */
.sanctuary { padding: 110px 0; overflow-x: clip; background-color: var(--paper); background-image: var(--paper-grain); }

.land-open { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: 24px; align-items: start; }
.land-features { grid-column: 1 / 7; grid-row: 1; }
.feature { padding: 22px 0; border-top: 1px solid var(--rule-light); }
.feature:first-child { border-top: 0; padding-top: 0; }
.feature h3 { margin-bottom: 8px; font-size: var(--t-h4); color: var(--cypress); }
.feature p { font-size: var(--t-body); line-height: var(--t-body-lh); color: var(--ink-soft); }
.land-spread {
  grid-column: 7 / 13; grid-row: 1; position: sticky; top: 96px; align-self: start;
  margin: 6px 0 0 20px;   /* inside the wrap; 20px puts its left edge on the house centre line */
  border-radius: var(--r-paper);
}
.land-spread img { width: 100%; height: auto; aspect-ratio: 4 / 3; max-height: 640px; object-fit: cover; background: var(--ph); }
.land-spread figcaption {
  padding: 12px 20px 13px; background-color: var(--parchment); background-image: var(--paper-grain);
  font-family: var(--font-display); font-style: italic; font-size: 1rem; line-height: 1.4; color: var(--ink-on-sheet);
}

/* the plate spread: the plate in the left half, the key's head and rows in the right half on the house
   centre line (where every section intro starts), top-aligned */
.plan { margin-top: 112px; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-rows: auto 1fr; column-gap: 64px; align-items: start; }
.plan-head { grid-column: 2; grid-row: 1; }
.plan-key { grid-column: 2; grid-row: 2; }
.plan-plate {
  grid-column: 1; grid-row: 1 / 3; justify-self: start; width: min(100%, 528px); margin: 0;
  display: grid; grid-template-columns: minmax(0, 1fr) 220px; grid-template-rows: auto auto 1fr; grid-template-areas: "map map" "cap loc" "tools loc"; column-gap: 20px; align-content: start;
  padding: 14px; background-color: var(--parchment); background-image: var(--paper-grain);
  border-radius: var(--r-paper); box-shadow: var(--lift-plate); color: var(--ink); --focus: var(--brass-on-sheet);
}
.plan-map { grid-area: map; position: relative; aspect-ratio: 2 / 3; background-color: var(--ph); }
.plan-map img { width: 100%; height: 100%; }
.plan-caption { grid-area: cap; margin-top: 14px; font-family: var(--font-display); font-style: italic; font-size: 0.98rem; line-height: 1.45; color: var(--ink-on-sheet); text-wrap: pretty; }
.plan-tools { grid-area: tools; align-self: start; display: flex; flex-direction: column; align-items: flex-start; margin-top: 16px; }   /* right under the caption */
.plate-locator { grid-area: loc; margin: 14px 0 0; }
.plate-locator svg { display: block; width: 100%; height: auto; border: 1px solid var(--sepia-ink); border-radius: var(--r-paper); }
.plate-locator figcaption { margin-top: 7px; font-family: var(--font-display); font-style: italic; font-size: 0.95rem; line-height: 1.4; color: var(--ink-on-sheet); }

/* zones: no wash at rest. Hovering a zone head (desktop) or choosing a zone (phone) washes its parcel at
   18% and draws its boundary as a 1px dashed sepia line */
.plan-zones { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.plan-zone-shape { fill-opacity: 0; stroke: #6d5b3d; stroke-opacity: 0; stroke-width: 1; stroke-dasharray: 4 3; vector-effect: non-scaling-stroke; mix-blend-mode: multiply; transition: fill-opacity var(--t-micro) var(--ease-out), stroke-opacity var(--t-micro) var(--ease-out); }
.plan-zone-shape[data-zone="A"] { fill: #a97f38; }
.plan-zone-shape[data-zone="B"] { fill: #4f6b46; }
.plan-zone-shape[data-zone="C"] { fill: #5b7d8c; }
:is([data-zone-focus="A"], [data-zone-pick="A"]) .plan-zone-shape[data-zone="A"],
:is([data-zone-focus="B"], [data-zone-pick="B"]) .plan-zone-shape[data-zone="B"],
:is([data-zone-focus="C"], [data-zone-pick="C"]) .plan-zone-shape[data-zone="C"] { fill-opacity: 0.18; stroke-opacity: 1; }

/* the two layers: the one not shown is transparent, inert (app.js) and takes no pointer */
.plan-layer, .land-layer { position: absolute; inset: 0; transition: opacity var(--t-micro) var(--ease-out); }
.plan-map[data-layer="plan"] .land-layer, .plan-map[data-layer="landmarks"] .plan-layer { opacity: 0; pointer-events: none; }
.plan-zone {
  position: absolute; left: var(--x); top: var(--y); transform: translate(-50%, -50%); white-space: nowrap;
  font-size: 0.95rem; line-height: 1; color: var(--cypress); pointer-events: none;
  text-shadow: 0 0 2px #efe3c3, 0 0 3px #efe3c3, 0 0 5px #efe3c3;
}
/* the camera markers: buttons, clearly larger than the painted nest glyphs, all one style. The disc is set in em,
   so it grows with the reader's text size (22px at 100%) */
.plan-cam {
  --d: calc(22em / 12); --hit: max(22px, var(--d));
  position: absolute; left: var(--x); top: var(--y); width: var(--hit); height: var(--hit); margin: calc(var(--hit) / -2) 0 0 calc(var(--hit) / -2);
  display: grid; place-items: center; padding: 0; border: 0; border-radius: 50%; background: none; cursor: pointer;
  font-family: var(--font-display); font-size: 0.75rem; line-height: 1; color: var(--parchment);
  transition: opacity var(--t-micro) var(--ease-out);
}
.plan-cam:focus-visible { outline-color: var(--cypress); outline-offset: 2px; }
.plan-cam::before {
  content: ""; position: absolute; left: 50%; top: 50%; width: var(--d); height: var(--d); margin: calc(var(--d) / -2) 0 0 calc(var(--d) / -2);
  border-radius: 50%; background: var(--cypress); border: 1px solid var(--parchment); box-shadow: 0 1px 2px rgba(28, 42, 33, 0.35);
  transition: transform var(--t-micro) var(--ease-out), background-color var(--t-micro) var(--ease-out), border-color var(--t-micro) var(--ease-out);
}
.plan-cam > span { position: relative; transition: color var(--t-micro) var(--ease-out); font-variant-numeric: lining-nums; }
.plan-cam.is-lit::before { background: var(--parchment); border-color: var(--cypress); transform: scale(1.15); }
.plan-cam.is-lit { color: var(--cypress); z-index: 2; }
[data-zone-focus="A"] .plan-cam:not([data-zone="A"]), [data-zone-focus="B"] .plan-cam:not([data-zone="B"]), [data-zone-focus="C"] .plan-cam:not([data-zone="C"]) { opacity: 0.35; }
[data-zone-pick="A"] .plan-cam:not([data-zone="A"]), [data-zone-pick="B"] .plan-cam:not([data-zone="B"]), [data-zone-pick="C"] .plan-cam:not([data-zone="C"]) { opacity: 0.25; }
/* a marker's subject, beside it (below 1024px, where the key is not beside the map) */
.plan-tag {
  position: absolute; z-index: 3; max-width: min(240px, 70%); margin: 0; padding: 6px 10px 7px;
  background: var(--mat); border: 1px solid rgba(110, 86, 52, 0.35); box-shadow: var(--lift-print);
  font-family: var(--font-display); font-size: 0.98rem; line-height: 1.25; color: var(--ink); pointer-events: none;
}
.plan-tag b { font-weight: 400; color: var(--sepia-ink); }

/* the landmarks: static ink key circles; desktop opens the card beside one, phones open the viewer's card */
.map-spot { position: absolute; z-index: 1; left: var(--x); top: var(--y); width: 40px; height: 40px; margin: -20px 0 0 -20px; padding: 0; border: 0; background: none; cursor: pointer; }
.map-spot-dot { position: absolute; inset: 11px; border-radius: 50%; background: var(--paper); border: 1px solid var(--sepia-ink); box-shadow: 0 0 0 2px rgba(253, 250, 242, 0.55); transition: background-color var(--t-micro) var(--ease-out), border-color var(--t-micro) var(--ease-out); }
.map-spot.is-open .map-spot-dot, .map-spot:active .map-spot-dot { background: var(--amber); border-color: var(--cypress); }
@media (hover: hover) { .map-spot:hover .map-spot-dot { background: var(--amber); border-color: var(--cypress); } }
.map-card {
  position: absolute; z-index: 4; width: min(250px, 62%); padding: 12px 14px;
  background: var(--mat); border: 1px solid rgba(110, 86, 52, 0.35); border-radius: var(--r-paper); box-shadow: var(--lift-print);
}
.map-card img { width: 100%; height: 110px; margin-bottom: 9px; object-fit: cover; border-radius: var(--r-paper); }
.map-card h4 { margin: 0 26px 4px 0; font-size: 1.22rem; line-height: 1.25; color: var(--cypress); }
.map-card p { margin: 0; font-size: 0.84rem; line-height: 1.5; color: var(--ink-soft); }
.map-card-x { position: absolute; top: 2px; right: 2px; width: 36px; height: 36px; display: grid; place-items: center; border: 0; background: none; font-size: 1.3rem; line-height: 1; color: var(--ink-on-sheet); cursor: pointer; }

/* the plate's controls: a segmented switch between the layers (small caps, a hairline between the two; the
   layer shown is underlined solid in ink, the other dotted in muted ink, so both read as choices), and the
   full-size view */
.plan-switch { display: inline-flex; flex-wrap: wrap; align-items: stretch; border: 1px solid rgba(110, 86, 52, 0.35); }
.plan-switch button {
  min-height: 44px; padding: 0 14px; border: 0; background: none; cursor: pointer;
  font-size: 1rem; color: var(--muted);
  text-decoration: underline dotted; text-decoration-color: rgba(97, 109, 94, 0.7); text-decoration-thickness: 1px; text-underline-offset: 5px;
  transition: color var(--t-micro) var(--ease-out), background-color var(--t-micro) var(--ease-out), text-decoration-color var(--t-micro) var(--ease-out);
}
.plan-switch button + button { border-left: 1px solid rgba(110, 86, 52, 0.35); }
.plan-switch button[aria-pressed="true"] { color: var(--ink); text-decoration-style: solid; text-decoration-color: currentColor; background-color: rgba(253, 250, 242, 0.55); cursor: default; }
.plan-switch button:not([aria-pressed="true"]):active { color: var(--cypress); background-color: rgba(110, 86, 52, 0.08); }
.plan-full {
  min-height: 40px; padding: 0; border: 0; background: none; cursor: pointer;
  font: 500 0.9rem/1.3 var(--font-body); color: var(--brass-on-sheet);
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px;
}
@media (hover: hover) {
  .plan-switch button:not([aria-pressed="true"]):hover { color: var(--cypress); text-decoration-style: solid; text-decoration-color: currentColor; background-color: rgba(110, 86, 52, 0.06); }
  .plan-full:hover { color: var(--cypress); }
}
/* desktop: the foot column beside the locator is too narrow for the two side by side, so the switch stacks
   (the hairline runs between them across), and the full-size link sits under it */
@media (min-width: 1024px) {
  .plan-switch { flex-direction: column; flex-wrap: nowrap; }
  .plan-switch button { min-height: 40px; padding: 0 14px; text-align: left; }
  .plan-switch button + button { border-left: 0; border-top: 1px solid rgba(110, 86, 52, 0.35); }
  .plan-full { margin-top: 10px; }
}
html:is(:not(.js), .noapp) .plan-tools, html:is(:not(.js), .noapp) .plan-filter { display: none; }

/* the key: a numbered map key, not a table. Rows are not controls: a marker lights its row, a row (mouse)
   lights its marker, a zone head (mouse) washes its zone */
.plan-title { margin-bottom: 14px; font-size: var(--t-h3); line-height: 1.15; color: var(--cypress); }
.plan-intro { font-size: 1rem; line-height: 1.68; color: var(--ink-soft); }
.plan-key { margin-top: 6px; }
.plan-filter { display: none; }
.plan-zone-group { margin-top: 30px; }
.plan-zone-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 2px 14px; font-size: var(--t-h4); line-height: 1.25; color: var(--cypress); }
.plan-zone-count { font-family: var(--font-display); font-style: italic; font-size: 0.98rem; color: var(--muted); }
.plan-zone-land { margin: 4px 0 12px; font-family: var(--font-display); font-style: italic; font-size: 1.02rem; line-height: 1.45; color: var(--ink-soft); }
.plan-rows { list-style: none; border-top: 1px solid var(--rule-light); }
.plan-rows li { display: flex; align-items: center; gap: 12px; padding: 7px 6px; border-bottom: 1px solid var(--rule-light); font-size: 0.97rem; line-height: 1.4; color: var(--ink); transition: background-color var(--t-micro) var(--ease-out); }
.plan-rows li.is-lit { background: rgba(169, 127, 56, 0.1); }
.plan-num {
  flex: none; display: inline-grid; place-items: center; width: 24px; height: 24px; border-radius: 50%;
  border: 1px solid rgba(23, 52, 43, 0.45); font-family: var(--font-display); font-size: 0.8rem; line-height: 1; color: var(--cypress); font-variant-numeric: lining-nums;
}
.is-mapped .plan-num, .plan-num.is-mapped { background: var(--cypress); border-color: var(--cypress); color: var(--parchment); }
.plan-legend { display: flex; align-items: flex-start; gap: 12px; margin-top: 18px; font-size: var(--t-body-s); line-height: 1.5; color: var(--muted); }
.plan-legend .plan-num { margin-top: -1px; }

/* the promise, the chapter's close: on the house split under a hairline like a section head. The title in the left
   half is set as the restoration's field note is (IM Fell italic, large), the words in the right half as an intro */
.free-watch { margin-top: 104px; padding-top: 30px; border-top: 1px solid var(--rule-light); display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 18px 64px; align-items: start; }
.free-watch h3 { font-style: italic; font-size: var(--t-h3); line-height: 1.3; color: var(--ink); }
.free-watch p { margin-top: 2px; max-width: 42.65em; font-size: 1.04rem; line-height: 1.68; color: var(--ink-soft); }

/* below 1024: the photograph is a band under the head, within the margins; the plate stacks above its key */
@media (max-width: 1023px) {
  .land-open { grid-template-columns: minmax(0, 1fr); }
  .land-spread { grid-column: 1; grid-row: 1; position: static; margin: 0 0 44px; }
  .land-spread img { max-height: 620px; }
  .land-features { grid-column: 1; grid-row: 2; }
  .plan { margin-top: 88px; grid-template-columns: minmax(0, 1fr); grid-template-rows: none; }
  .plan-head, .plan-key, .plan-plate { grid-column: 1; grid-row: auto; }
  .plan-head { max-width: 44em; margin-bottom: 28px; }
  .plan-plate { width: min(100%, 628px); }
  .plan-key { max-width: 44em; margin-top: 34px; }
}
/* tablets: the features two by two */
@media (min-width: 600px) and (max-width: 1023px) {
  .land-features { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 40px; }
  .land-features .feature:nth-child(-n+2) { border-top: 0; padding-top: 0; }
}
/* phone and tablet: zone toggles over the key; the promise stacks */
@media (max-width: 859px) {
  .plan-filter { display: flex; flex-wrap: wrap; align-items: center; column-gap: 4px; padding-bottom: 4px; border-bottom: 1px solid var(--rule-light); }
  .plan-filter-label { flex: 1 0 100%; font-family: var(--font-display); font-style: italic; font-size: 0.98rem; color: var(--muted); }
  .plan-filter button {
    min-height: 44px; padding: 0 10px; border: 0; background: none; cursor: pointer; font-size: 1.08rem; color: var(--ink-on-sheet);
    text-decoration: underline; text-decoration-color: transparent; text-decoration-thickness: 1px; text-underline-offset: 5px;
  }
  .plan-filter button:first-of-type { padding-left: 0; }
  .plan-filter button[aria-pressed="true"] { color: var(--cypress); text-decoration-color: currentColor; }
  .plan-key[data-pick="A"] .plan-zone-group:not([data-zone="A"]),
  .plan-key[data-pick="B"] .plan-zone-group:not([data-zone="B"]),
  .plan-key[data-pick="C"] .plan-zone-group:not([data-zone="C"]) { display: none; }
  .plan-zone-group { margin-top: 24px; }
  .free-watch { margin-top: 80px; grid-template-columns: minmax(0, 1fr); padding-top: 24px; }
  .free-watch p { margin-top: 0; }
}
/* phone: one column on the mat, the locator under the caption at 60% (never under 214px, so its labels hold 10px) */
@media (max-width: 599px) {
  .sanctuary { padding: 80px 0; }
  .land-spread figcaption { font-size: 0.95rem; }
  .plan { margin-top: 72px; }
  .plan-plate { padding: 10px; grid-template-columns: minmax(0, 1fr); grid-template-rows: none; grid-template-areas: "map" "cap" "tools" "loc"; }
  .plan-caption { font-size: 0.95rem; }
  .plate-locator { width: clamp(214px, 60%, 260px); margin-top: 16px; }
  .plan-cam { --d: calc(18em / 11); --hit: max(24px, var(--d)); font-size: 0.6875rem; }
  .map-card { padding: 10px 12px; }
  .map-card img { height: 78px; margin-bottom: 7px; }
  .map-card h4 { font-size: 1.04rem; }
  .map-card p { font-size: 0.8rem; line-height: 1.42; }
}
/* narrow phones: the zone labels carry their letter only; a landmark card's short pairs may wrap at large text */
@media (max-width: 479px) {
  .plan-zone-n { display: none; }
  .map-card .nw { white-space: normal; }
}

/* ===== seasons: cypress; one parchment sheet holds the calendar, its legend, the plate cabinet and the credit =====
   A regional calendar ("around Tampa Bay"), static HTML from build/seasons.mjs: the month header, six rows
   (name | track | note) and the six plate buttons. app.js only sets --x-frac (the Today line, drawn on every
   track by .sc-track::after once .has-today is on), the month mark and the month line, and links a plate to
   its row. The chart is aria-hidden; a visually hidden table carries the same facts. Bars are square
   (paper): the season an outlined band, the peak solid. Desktop: name | track | note. 600 to 1023: the
   note under the track. Phone: each species a block, name over a full-width track over its note. */
.seasons { padding: 104px 0; background: var(--cypress); color: var(--on-dark); }
.season-sheet {
  --focus: var(--brass-on-sheet);
  padding: 40px 44px 32px;
  background-color: var(--parchment); background-image: var(--paper-grain);
  border-radius: var(--r-paper); box-shadow: var(--lift-plate); color: var(--ink);
}
.season-top { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 10px 32px; padding-bottom: 14px; }
.season-title { font-style: italic; font-size: var(--t-h4); line-height: 1.2; color: var(--ink); }
.season-legend { display: flex; flex-wrap: wrap; gap: 6px 22px; margin: 0; font-size: 0.8rem; line-height: 1.3; color: var(--ink-on-sheet); }
.lg-item { display: inline-flex; align-items: center; gap: 9px; }
.lg { flex: none; }
.lg { display: inline-block; width: 28px; height: 12px; border-radius: 0; }

/* the bars: the season is a band ruled top and bottom over a light cypress wash; the peak is solid */
.lg.on, .sc-cell.on { background-color: rgba(72, 104, 79, 0.2); border: 1px solid rgba(23, 52, 43, 0.62); }
.lg.peak, .sc-cell.peak { background-color: var(--chart-peak); border: 1px solid var(--chart-peak); }
.sc-cell { height: 16px; border-radius: 0; transition: background-color var(--t-ui) var(--ease-out), border-color var(--t-ui) var(--ease-out); }
.sc-cell.on, .sc-cell.peak { border-left-width: 0; border-right-width: 0; }
.sc-cell.l { margin-left: 2px; border-left-width: 1px; }
.sc-cell.r { margin-right: 2px; border-right-width: 1px; }

.season-chart { position: relative; }
.sc-row {
  display: grid; grid-template-columns: clamp(170px, 16vw, 230px) minmax(0, 1fr) minmax(0, 0.6fr); column-gap: 28px; align-items: center;
  border-top: 1px solid var(--rule-light); transition: background-color var(--t-ui) var(--ease-out);
}
.sc-head { border-top: 0; align-items: end; }
.sc-name { padding: 13px 0; font-family: var(--font-display); font-size: 1.14rem; line-height: 1.2; color: var(--cypress); transition: color var(--t-ui) var(--ease-out); }
.sc-track {
  position: relative; align-self: stretch; display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); align-items: center;
  border-right: 1px solid rgba(23, 52, 43, 0.12);
  background-image: linear-gradient(to right, rgba(23, 52, 43, 0.12) 1px, transparent 1px); background-size: calc(100% / 12) 100%;
}
.sc-note { padding: 11px 0; font-size: var(--t-body-s); line-height: 1.45; color: var(--ink-on-sheet); }
.sc-head .sc-note { padding: 0 0 7px; font-size: 0.95rem; }
.sc-head .sc-track { padding-top: 26px; }
.sc-month { padding-bottom: 7px; text-align: center; font-size: 0.95rem; line-height: 1; color: var(--ink-on-sheet); }
.sc-month.is-now { color: var(--brass-on-sheet); }
.sc-m1 { display: none; }
/* Today: one brass hairline through every track at the date's place in the year; its label over the months */
.sc-today { display: none; position: absolute; top: 2px; left: clamp(0px, calc(var(--x-frac, 0) * 100% - 1.7em), calc(100% - 3.4em)); width: 3.4em; text-align: center; font-size: 0.95rem; line-height: 1.2; color: var(--brass-on-sheet); }
.has-today .sc-today { display: block; }
.has-today .sc-track::after { content: ""; position: absolute; top: 0; bottom: 0; left: calc(var(--x-frac, 0) * 100% - 1px); width: 2px; background: var(--brass-on-sheet); pointer-events: none; }
.has-today .sc-head .sc-track::after { content: none; }   /* the label marks the head; the line starts at the first bird */
/* a plate and its row light together (app.js): the row takes a brass wash, its bars and name go brass */
.sc-row.is-linked { background-color: rgba(122, 88, 36, 0.07); }
.sc-row.is-linked .sc-name { color: var(--brass-on-sheet); }
.sc-row.is-linked .sc-cell.on { background-color: rgba(122, 88, 36, 0.22); border-color: var(--brass-on-sheet); }
.sc-row.is-linked .sc-cell.peak { background-color: var(--brass-on-sheet); border-color: var(--brass-on-sheet); }

.season-foot { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 8px 64px; align-items: start; padding-top: 16px; border-top: 1px solid var(--rule-light); }
.season-now { margin: 0; font-size: 0.98rem; line-height: 1.5; color: var(--ink); }
.season-now:empty { display: none; }
.season-now b { font-family: var(--font-display); font-style: italic; font-size: 1.06rem; font-weight: 400; color: var(--brass-on-sheet); }
.season-source { grid-column: 2; margin: 0; font-size: var(--t-body-s); line-height: 1.5; color: var(--ink-on-sheet); }

/* the cabinet: six plates matted on paper, each with its source and, where the sanctuary has its own record, a line saying so.
   Each plate spans four rows of the cabinet (picture, name, source, record line) on a subgrid, so the source and the
   record lines share one baseline across a row even when a name runs to two lines; without subgrid the name keeps
   two lines' room */
.plate-cabinet { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 24px; margin-top: 40px; padding-top: 30px; border-top: 1px solid var(--rule-light); }
.plate { display: flex; flex-direction: column; align-items: stretch; padding: 0; border: 0; background: none; color: inherit; font: inherit; text-align: left; cursor: zoom-in; }
.plate-img { display: block; padding: 7px; background: linear-gradient(var(--ph, var(--mat)), var(--ph, var(--mat))) content-box, var(--paper); box-shadow: var(--lift-plate); transition: transform var(--t-ui) var(--ease-out); }
.plate-img img { display: block; width: 100%; height: auto; aspect-ratio: 1; object-fit: cover; }
.plate-name { margin-top: 12px; min-height: 2.4em; font-family: var(--font-display); font-size: var(--t-h4); line-height: 1.2; color: var(--ink); }
@supports (grid-template-rows: subgrid) {
  .plate { display: grid; grid-row: span 4; grid-template-rows: subgrid; row-gap: 0; align-content: start; }
  .plate-name { min-height: 0; }
}
.plate-ref { margin-top: 3px; font-size: var(--t-body-s); line-height: 1.35; color: var(--ink-on-sheet); }
.plate-here { margin-top: 5px; font-family: var(--font-display); font-style: italic; font-size: 0.96rem; line-height: 1.25; color: var(--brass-on-sheet); }
.plate.is-linked .plate-img { transform: translateY(-3px); }
@media (hover: hover) { .plate:hover .plate-img { transform: translateY(-3px); } }
.plate-credit { max-width: 56em; margin-top: 30px; font-size: var(--t-body-s); line-height: 1.55; color: var(--ink-on-sheet); }
.plate-credit cite { font-style: italic; }
html:is(:not(.js), .noapp) .plate-cabinet, html:is(:not(.js), .noapp) .plate-credit { display: none; }   /* the plates open only in the viewer (app.js) */

/* below 1024: three-letter months give way to initials; the note runs under the track */
@media (max-width: 1023px) {
  .seasons { padding: 88px 0; }
  .season-sheet { padding: 32px 28px 26px; }
  .sc-m3 { display: none; }
  .sc-m1 { display: inline; }
  .sc-row { grid-template-columns: 170px minmax(0, 1fr); column-gap: 20px; }
  .sc-row:not(.sc-head) .sc-name { grid-row: 1 / span 2; align-self: start; }
  .sc-track { min-height: 40px; }
  .sc-note { grid-column: 2; padding: 0 0 12px; }
  .sc-head .sc-note { display: none; }
  .plate-cabinet { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 30px 22px; }
}
@media (max-width: 859px) {
  .season-foot { grid-template-columns: minmax(0, 1fr); }
  .season-source { grid-column: 1; }
}
/* phone: each species a block, its name over a full-width track (cells 26px and up at 390) over its note */
@media (max-width: 599px) {
  .seasons { padding: 72px 0; }
  .season-sheet { padding: 22px 14px 18px; }
  .season-top { display: block; padding-bottom: 12px; }
  .season-legend { margin-top: 10px; }
  .sc-row { display: block; }
  .sc-head .sc-name { display: none; }
  .sc-row:not(.sc-head) .sc-name { display: block; padding: 12px 0 7px; font-size: 1.05rem; }
  .sc-track { min-height: 24px; }
  .sc-note { display: block; padding: 7px 0 12px; }
  .plate-cabinet { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 26px 14px; margin-top: 30px; padding-top: 24px; }
  .plate-credit { margin-top: 24px; }
}

/* ===== history: paper. The chronicle, with the river of time drawn in the map's ink =====
   Each entry: the era (IM Fell italic, brass ink, lining figures) in the left half, right-aligned and
   baseline-aligned with its heading; the heading and text in the right half, on the house centre line under
   the intro. The 64px gap between them is the river's gutter: two 1px hairlines 3px apart in the map's
   water ink meander down it (app.js builds them), crossing at a 5px sepia station on each era's baseline
   and bending once between stations, and end at an ink dot under Today. Tablet: a 140px era column.
   Phone: the river keeps a 14px lane at the left (6px either side of its centre line) and the entries
   are indented 30px. --tl-x is the river's centre line (app.js reads it; percent of the timeline or px).
   Motion (named place 3) is in block 7. Without app.js a straight double rule stands in the gutter. */
.history { padding: 110px 0 120px; background-color: var(--paper); background-image: var(--paper-grain); }
.timeline {
  --tl-x: 50%; --tl-amp: 15px;
  position: relative; display: grid; grid-template-columns: minmax(0, 1fr); gap: 72px;
  view-timeline: --river block;
}
.timeline-item {
  position: relative; z-index: 1; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: 64px; align-items: baseline;
}
.timeline-era {
  grid-column: 1; grid-row: 1; justify-self: end; text-align: right;
  font-family: var(--font-display); font-style: italic; font-size: clamp(2.1rem, 0.6rem + 2.8vw, 3.2rem); line-height: 1; color: var(--brass-ink);
}
.tl-base { display: inline-block; width: 0; height: 0; vertical-align: baseline; }   /* app.js: marks the era's baseline */
.timeline-item h3 { grid-column: 2; grid-row: 1; margin-bottom: 8px; font-size: var(--t-h4); color: var(--cypress); }
.timeline-item p { grid-column: 2; grid-row: 2; max-width: 42.65em; font-size: var(--t-body); line-height: var(--t-body-lh); color: var(--ink-soft); }
.tl-river { position: absolute; left: 0; top: 0; z-index: 0; overflow: visible; pointer-events: none; }
.tl-river-line { fill: none; stroke: #5b7d8c; stroke-width: 1; stroke-opacity: 0.7; stroke-dasharray: 1 1; stroke-dashoffset: 0; }
.tl-river-line.is-far { stroke-opacity: 0.4; }
.tl-station { fill: var(--sepia-ink); stroke: var(--sepia-ink); stroke-width: 1; }   /* r=2 + 1px ring = 5px */
.tl-nib {
  position: absolute; left: 0; top: 0; z-index: 2; width: 5px; height: 5px; margin: -2.5px 0 0 -2.5px;
  border-radius: 50%; background: var(--cypress); pointer-events: none; offset-rotate: 0deg; offset-distance: 100%;
}
.timeline:not(.has-river)::before {
  content: ""; position: absolute; top: 0; bottom: 0; left: calc(var(--tl-x) - 2px); width: 4px;
  border-left: 1px solid rgba(91, 125, 140, 0.7); border-right: 1px solid rgba(91, 125, 140, 0.4);
}
@media (max-width: 859px) {
  .timeline { --tl-x: 172px; --tl-amp: 14px; }   /* 140px eras + half the 64px gutter */
  .timeline-item { grid-template-columns: 140px minmax(0, 1fr); }
  .timeline-era { font-size: 1.9rem; }
}
@media (max-width: 599px) {
  .timeline { --tl-x: 7px; --tl-amp: 6px; gap: 52px; }
  .timeline-item { grid-template-columns: minmax(0, 1fr); padding-left: 30px; }
  .timeline-era { grid-row: 1; justify-self: start; text-align: left; margin-bottom: 6px; font-size: 1.6rem; }
  .timeline-item h3 { grid-column: 1; grid-row: 2; }
  .timeline-item p { grid-column: 1; grid-row: 3; }
}

/* ===== restoration: cypress. A dated photo essay =====
   The chapter opens on its head (hairline, title, intro), then the essay: the frontispiece (the finished
   floating nest island, cropped 16:9), then nine prints in the order they were taken: pairs of a larger and
   a smaller print, a lead print alone on its row, and the close (the night heron, its caption set large
   beside it as George's field note). Every print keeps its own ratio, uncropped; the frontispiece is the
   only crop. Prints are paper: square mats, an even caption band (app.js measures the tallest band and sets
   --band, so every band matches; the frontispiece keeps its own), the date it was photographed in italic
   under the caption. All fifteen photographs stay one click away in the viewer (app.js; the six not shown
   live in <template id="restoArchive">). No hover transforms.
   Sizes. Phones and tablets: --h units times --k (0.8px on tablets, less on narrow tablets so a pair always
   fits). 1024 and up: by width, on the wrap's own edges. The frontispiece fills the left two-thirds with its
   label in the right third; each pair is a larger print (44% of the wrap) on one edge and a smaller one (32%)
   on the other, set lower, the larger alternating sides; the lead print (48%, never taller than the screen
   leaves room for) stands alone on the centre line. At 1440 the prints span the wrap, 158 to 1282px, and none
   is drawn above 1.3 times its file on a 2x screen.
   Oct 3 revision (desktop): the pairs are justified rows (equal photo heights, captions aligned, 40px gutter,
   centred on the page's centre line) instead of a large and a small print pushed to opposite edges. */
.restoration { --k: 0.8px; --gap: 48px; padding: 80px 0 80px; background: var(--cypress); }
.restoration .section-head h2 { color: var(--on-dark); }
.restoration .section-head .section-sub { color: var(--on-dark-dim); }

/* a print: the photograph on its mat, the caption band under it */
.resto-print {
  margin: 0; width: min-content; padding: 10px 10px 0;
  background: var(--mat); border-radius: var(--r-paper); box-shadow: var(--lift-print); cursor: zoom-in;
}
.resto-ph { position: relative; height: calc(var(--h, 300) * var(--k)); aspect-ratio: var(--ar); overflow: hidden; background-color: var(--ph, var(--cypress-deep)); }
.resto-ph img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.resto-band {
  display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 1px;
  height: var(--band, auto); min-height: 74px; padding: 9px 6px 10px; text-align: center;
}
.resto-cap { display: block; font-family: var(--font-display); font-style: italic; font-size: 0.98rem; line-height: 1.3; color: var(--ink); text-wrap: balance; }
/* the date a photograph was taken: IM Fell small caps (block 3) at 15px or more, lining figures, every width */
.resto-date { display: block; font-size: 0.95rem; line-height: 1.35; color: var(--ink-soft); font-variant-numeric: lining-nums; }
/* the photo is the control (app.js); its ring is drawn around the whole print, out on the cypress */
.resto-ph:focus-visible { outline-offset: -5px; }
@supports selector(:has(*)) {
  .resto-ph:focus-visible { outline: none; }
  :is(.resto-print, .resto-mat):has(.resto-ph:focus-visible) { outline: 2px solid var(--focus); outline-offset: 3px; }
}

/* the essay: the frontispiece first (centred, 820 by 461 at most, until 1024), then the rows */
.resto-essay { display: flex; flex-direction: column; align-items: flex-start; gap: var(--gap); }
.resto-front { width: min(100%, 840px); margin: 0 auto 16px; }
.resto-front .resto-ph { height: auto; aspect-ratio: 16 / 9; }
.resto-pair { display: grid; grid-template-columns: auto auto; justify-content: center; column-gap: 40px; align-items: start; width: 100%; }
.resto-print.is-large { --h: 400; }
.resto-print.is-small { --h: 300; }
.resto-lead { --h: 520; align-self: center; }

/* the close: the heron at the inner edge of the left half, the field note in the right half, George's name under it */
.resto-close { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 40px; align-items: center; width: 100%; margin: 0; }
.resto-mat {
  justify-self: end; width: min(100%, calc(330 * var(--k) + 20px)); padding: 10px;
  background: var(--mat); border-radius: var(--r-paper); box-shadow: var(--lift-print); cursor: zoom-in;
}
.resto-mat .resto-ph { width: 100%; height: auto; }
.resto-close-text { min-width: 0; }
.resto-close-text .resto-cap {
  font-size: 1.4rem; line-height: 1.38; color: var(--on-dark); text-wrap: pretty;
  hanging-punctuation: first last;
}
.resto-close-text .resto-nl { display: block; }   /* the field note's second sentence on its own line */

/* the foot: the house pattern at a small scale. A hairline, the full set left, the credit right */
.resto-foot {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 8px 64px; align-items: baseline;
  margin-top: 52px; padding-top: 14px; border-top: 1px solid var(--rule-dark);
}
.resto-all {
  display: inline-block; justify-self: start; min-height: 48px; padding: 0; border: 0; background: none; cursor: pointer;   /* hidden in the markup until app.js wires it */
  font: 500 0.98rem/1.3 var(--font-body); color: var(--on-dark);
  text-decoration: underline; text-decoration-color: var(--amber); text-decoration-thickness: 1.5px; text-underline-offset: 6px;
  transition: text-decoration-color var(--t-ui) var(--ease-out);
}
.resto-all:active { text-decoration-color: var(--on-dark); }
@media (hover: hover) { .resto-all:hover { text-decoration-color: var(--on-dark); } }
.resto-credit { grid-column: 2; margin: 0; font-family: var(--font-display); font-style: italic; font-size: 1.02rem; line-height: 1.5; color: var(--on-dark-dim); }

/* tablets: the rows at 0.8 scale (less below about 680px, so a pair always fits the wrap), each pair centred */
@media (min-width: 600px) and (max-width: 1023px) {
  .restoration { --k: min(0.8px, (100vw - 156px) / 700); --gap: 40px; padding: 72px 0 72px; }
  .resto-cap { font-size: 0.95rem; }
}
@media (min-width: 600px) and (max-width: 859px) {
  .resto-foot { grid-template-columns: 1fr; }
  .resto-credit { grid-column: 1; }
}

/* desktop: sized by width on the wrap's edges */
@media (min-width: 1024px) {
  .restoration { --gap: 72px; }
  .resto-essay .resto-ph { width: 100%; height: auto; }
  /* the frontispiece: the print in the left two-thirds on its mat, its label in the right third, at its foot */
  .resto-front {
    display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); column-gap: 64px; align-items: end;
    width: 100%; margin: 0 0 8px; padding: 0; background: none; box-shadow: none;
  }
  .resto-essay .resto-front .resto-ph { aspect-ratio: 16 / 9; border: 10px solid var(--mat); box-shadow: var(--lift-print); }
  .resto-front .resto-band { height: auto; min-height: 0; align-items: flex-start; gap: 10px; padding: 0 0 4px; text-align: left; }
  .resto-front .resto-cap { font-size: 1.55rem; line-height: 1.32; color: var(--on-dark); text-wrap: pretty; hanging-punctuation: first last; }
  .resto-front .resto-date { font-size: 1.02rem; color: var(--on-dark-dim); }
  .resto-front:has(.resto-ph:focus-visible) { outline: none; }
  .resto-front .resto-ph:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }
  /* a pair: a justified row. Each print grows by its own aspect ratio (--g, set on the figure) from a basis
     equal to its mat, so both photographs come out exactly the same height and the caption bands line up.
     The row is capped at a 520px photograph height (--sum is the row's summed ratios) and centred on the
     page's centre line; a wide pair fills the wrap. */
  .resto-pair {
    display: flex; justify-content: center; align-items: flex-start; gap: 40px;
    width: 100%; max-width: calc(var(--sum, 1.5) * 520px + 80px); margin-inline: auto;
  }
  .resto-pair > .resto-print { flex: var(--g, 0.75) 1 20px; width: auto; min-width: 0; margin-top: 0; }
  :is(.resto-pair, .resto-lead) .resto-cap { font-size: 1.04rem; }
  /* the lead: alone on the centre line, 48% wide, never taller than a laptop screen leaves room for */
  .resto-lead { width: min(48%, calc((100vh - 230px) * 0.75 + 20px)); }
  @supports (height: 100svh) { .resto-lead { width: min(48%, calc((100svh - 230px) * 0.75 + 20px)); } }
  /* the close on the house halves: the heron (32% of the wrap) at the inner edge of the left half */
  .resto-close { column-gap: 64px; }
  .resto-mat { width: 68%; }
  .resto-close-text .resto-cap { font-size: 1.7rem; }
}

/* phone: pairs two up at equal widths; the frontispiece and the lead fill the column; the close stacks */
@media (max-width: 599px) {
  .restoration { --gap: 28px; padding: 64px 0 64px; }
  .resto-print { width: auto; padding: 6px 6px 0; }
  .resto-ph { height: auto; }
  .resto-band { min-height: 0; padding: 7px 3px 9px; }
  .resto-cap { font-size: 0.95rem; line-height: 1.28; }
  .resto-front { width: auto; margin: 0 0 8px; }
  .resto-front .resto-ph { aspect-ratio: 3 / 2; }
  .resto-front .resto-band { padding: 8px 4px 10px; }
  .resto-essay { align-items: stretch; }
  .resto-pair { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 12px; }
  .resto-lead { align-self: stretch; }
  .resto-close { display: block; }
  .resto-mat { justify-self: start; width: 78%; padding: 6px; }   /* left, on the column edge, like the field note under it */
  .resto-close-text { display: block; margin-top: 20px; }
  .resto-close-text .resto-cap { font-size: 1.3rem; }
  .resto-foot { grid-template-columns: 1fr; margin-top: 44px; padding-top: 0; border-top: 0; }
  .resto-all {
    display: block; width: 100%; padding: 0; text-align: left;
    border-top: 1px solid var(--rule-dark); border-bottom: 1px solid var(--rule-dark);
  }
  .resto-credit { grid-column: 1; margin-top: 14px; }
}

/* ===== stewards: paper. The story beside a ruled record of their work; the memberships as one line of text =====
   1024 and up: the story (with the page's one drop cap) in the left half under the h2, the record in the right
   half under the intro, on the house centre line (64px gap); the memberships close the left column under the
   story. 860 to 1023: one column (story, record, memberships); the record keeps its 88px year column.
   Under 860 each year becomes a small-caps line above its entry. The chapter ends in open paper: Support's own
   head (its hairline) marks the break, so no extra rule is drawn here. No motion. */
.stewards { padding: 110px 0 96px; background-color: var(--paper); background-image: var(--paper-grain); }
.stewards-grid {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-rows: auto 1fr;
  column-gap: 64px; align-items: start;
}
.steward-story { grid-column: 1; grid-row: 1; }
.steward-record { grid-column: 2; grid-row: 1 / span 2; }
.steward-members { grid-column: 1; grid-row: 2; margin-top: 52px; padding-top: 22px; border-top: 1px solid var(--rule-light); }

.steward-story p { max-width: 42.65em; margin-bottom: 22px; font-size: var(--t-body); line-height: 1.7; color: var(--ink-soft); }
.steward-story p:last-child { margin-bottom: 0; }
/* the page's one drop cap */
.steward-story .drop-cap::first-letter {
  -webkit-initial-letter: 3; initial-letter: 3;
  padding-right: 10px; font-family: var(--font-display); font-weight: 400; color: var(--sepia-ink);
}
@supports not ((initial-letter: 3) or (-webkit-initial-letter: 3)) {
  .steward-story .drop-cap::first-letter { float: left; padding: 8px 12px 0 0; font-size: 4.3em; line-height: 0.78; }
}

/* the record: year | place over the Corbetts' own words, a hairline between entries */
.record-h { margin-bottom: 16px; font-size: var(--t-h3); line-height: 1.2; color: var(--cypress); }
.record-list { list-style: none; border-top: 1px solid var(--rule-light); }
.record-entry {
  display: grid; grid-template-columns: 88px minmax(0, 1fr); align-items: baseline;
  padding: 20px 0 22px; border-bottom: 1px solid var(--rule-light);
}
.record-year { grid-column: 1; grid-row: 1; font-family: var(--font-display); font-size: 1.3rem; line-height: 1.2; color: var(--sepia-ink); }
.record-place { grid-column: 2; grid-row: 1; margin-bottom: 6px; font-size: var(--t-h4); line-height: 1.2; color: var(--cypress); }
.record-place a { color: inherit; text-decoration: underline; text-decoration-thickness: 1px; text-decoration-color: rgba(125, 96, 61, 0.55); text-underline-offset: 4px; transition: color var(--t-ui) var(--ease-out); }
@media (hover: hover) { .record-place a:hover { color: var(--brass-ink); } }
.record-text { grid-column: 2; grid-row: 2; font-size: var(--t-body); line-height: var(--t-body-lh); color: var(--ink-soft); }

/* memberships: a plain line of names under an italic head, left-aligned */
.members-h { margin-bottom: 8px; font-style: italic; font-size: var(--t-h4); line-height: 1.2; color: var(--sepia-ink); }
.members-list { font-family: var(--font-display); font-size: 1.14rem; line-height: 1.62; color: var(--cypress); }

@media (max-width: 1023px) {
  .stewards-grid { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; }
  .steward-story, .steward-record, .steward-members { grid-column: 1; grid-row: auto; }
  .steward-record { max-width: calc(88px + 42.65em); margin-top: 56px; }
  .steward-members { margin-top: 36px; padding-top: 0; border-top: 0; }   /* the record's last hairline already rules it off */
}
@media (max-width: 859px) {
  .record-entry { grid-template-columns: minmax(0, 1fr); padding: 18px 0 20px; }
  .record-year { grid-column: 1; grid-row: 1; margin-bottom: 4px; font-family: var(--font-sc); font-size: 1.08rem; letter-spacing: 0.03em; }
  .record-place { grid-column: 1; grid-row: 2; }
  .record-text { grid-column: 1; grid-row: 3; }
}
@media (max-width: 599px) {
  .stewards { padding: 96px 0 72px; }
  .steward-record { margin-top: 48px; }
  .steward-members { margin-top: 32px; }
  .members-list .nw { white-space: normal; }   /* a narrow column: the names run as prose */
  .members-list { font-size: 1.08rem; }
}

/* ===== support: paper. The giving desk, an editorial spread for funders =====
   Opening break: George's photograph of the restored pond and its sanctuary sign opens the section in the
   left half, inside the wrap (Oct 3: no bleed to the screen edge), sticky from 1024px like the land's photo,
   with its caption on a parchment strip. The head and the ways to
   give run in the right half on the house centre line: a hairline, the h2, the intro, then three ruled
   entries, each a head, its words and plain underlined actions in brass ink (no button chrome, 44px tall).
   The mailing address is set on a square mat like an envelope. The foot: the Corbetts' words under a 120px
   rule in the left half, the Foundation's note in the right half. Copy buttons exist only with JS (app.js
   unhides them). Below 1024: head, the photo as a band within the margins, the entries, the foot, one column.
   Below 600 every action is a full-width 48px row between hairlines. Nothing is centred. No motion except
   the copy label's 150ms swap (block 7). */
.support { padding: 110px 0 120px; overflow-x: clip; background-color: var(--paper); background-image: var(--paper-grain); }
.give-spread {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-rows: auto 1fr;
  column-gap: 64px; align-items: start;
}
.give-head { grid-column: 2; grid-row: 1; padding-top: 30px; border-top: 1px solid var(--rule-light); }
.give-head h2 { color: var(--ink); }
.give-intro { margin-top: 22px; max-width: 42.65em; font-size: 1.04rem; line-height: 1.68; color: var(--ink-soft); }

.give-photo {
  grid-column: 1; grid-row: 1 / span 2; position: sticky; top: calc(var(--nav-h, 69px) + 24px); align-self: start;
  margin: 0;
  border-radius: var(--r-paper);
}
.give-photo img { width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; background: var(--ph); }
/* desktop: the photograph travels with the ways to give (sticky), and is as tall as the screen leaves room for
   under the nav (its caption and 24px of air included), from its own 4:3 up to 4:5, cropped around the sign,
   so no empty paper opens up beside the list while it scrolls */
@media (min-width: 1024px) {
  .give-photo { container-type: inline-size; }
  @supports (width: 1cqi) {
    .give-photo img { aspect-ratio: auto; height: clamp(75cqi, calc(100vh - 164px), 125cqi); object-position: 55% 50%; }
    @supports (height: 100svh) { .give-photo img { height: clamp(75cqi, calc(100svh - 164px), 125cqi); } }
  }
}
.give-photo figcaption {
  padding: 12px 20px 13px; background-color: var(--parchment); background-image: var(--paper-grain);
  font-family: var(--font-display); font-style: italic; font-size: 1rem; line-height: 1.4; color: var(--ink-on-sheet);
}

/* the ways to give: three ruled entries */
.give-ways { grid-column: 2; grid-row: 2; margin-top: 60px; }
.give-ways-h { margin-bottom: 16px; font-size: var(--t-h3); line-height: 1.2; color: var(--cypress); }
.give-entry { padding: 24px 0 18px; border-top: 1px solid var(--rule-light); }
.give-entry:last-child { border-bottom: 1px solid var(--rule-light); }
.give-entry h4 { margin-bottom: 8px; font-size: var(--t-h4); line-height: 1.2; color: var(--cypress); }
.give-entry p { font-size: var(--t-body); line-height: var(--t-body-lh); color: var(--ink-soft); }
.give-entry .give-email { margin-top: 4px; font-weight: 500; letter-spacing: 0.01em; color: var(--ink); }
.give-entry .give-credit { margin-top: 14px; max-width: 32em; font-family: var(--font-display); font-style: italic; font-size: 1.1rem; line-height: 1.45; color: var(--sepia-ink); }

/* the envelope: the address on a square mat, as it would be written */
.give-envelope {
  width: min(100%, 26rem); margin-top: 16px; padding: 28px;
  background-color: var(--mat); background-image: var(--paper-grain); border-radius: var(--r-paper); box-shadow: var(--lift-plate);
  font-family: var(--font-display); font-style: normal; font-size: 1.5rem; line-height: 1.34; color: var(--ink);
}
.give-envelope span { display: block; }

/* actions: plain underlined words in brass ink. A mailto says it is email; a copy swaps its label */
.give-actions { display: flex; flex-wrap: wrap; column-gap: 30px; margin-top: 8px; }
.give-act {
  display: inline-flex; align-items: center; min-height: 44px; padding: 0; border: 0; border-radius: 0; background: none;
  font: 500 0.98rem/1.3 var(--font-body); text-align: left; color: var(--brass-ink); cursor: pointer;
  text-decoration: underline; text-decoration-thickness: 1px; text-decoration-color: rgba(134, 98, 42, 0.5); text-underline-offset: 5px;
  transition: color var(--t-ui) var(--ease-out), text-decoration-color var(--t-ui) var(--ease-out);
}
.give-act:active { color: var(--cypress); text-decoration-color: currentColor; }
@media (hover: hover) { .give-act:hover { color: var(--cypress); text-decoration-color: currentColor; } }
.give-copy { display: inline-grid; justify-items: start; align-items: center; text-decoration: none; }
.give-copy > span { grid-area: 1 / 1; text-decoration-line: underline; text-decoration-thickness: 1px; text-decoration-color: rgba(134, 98, 42, 0.5); text-underline-offset: 5px; }
.give-copy-done { opacity: 0; }
.give-copy.is-done .give-copy-label { opacity: 0; }
.give-copy.is-done .give-copy-done { opacity: 1; }
@media (hover: hover) { .give-copy:hover > span { text-decoration-color: currentColor; } }

/* the foot: the Corbetts' words under a short rule (left half), the Foundation's note (right half) */
.give-foot {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 64px; align-items: start;
  margin-top: 96px;
}
.give-note { grid-column: 2; grid-row: 1; padding-top: 30px; max-width: 34em; font-size: var(--t-body-s); line-height: 1.62; color: var(--ink-soft); }
.give-quote { grid-column: 1; grid-row: 1; margin: 0; hanging-punctuation: first last; }
.give-quote::before { content: ""; display: block; width: 120px; margin-bottom: 26px; border-top: 1px solid var(--sepia-ink); }
.give-quote p { font-family: var(--font-display); font-style: italic; font-size: clamp(1.45rem, 1.05rem + 1.1vw, 2rem); line-height: 1.38; color: var(--ink); max-width: 16.5em; text-wrap: pretty; }
.support cite { display: block; margin-top: 16px; font-size: 1.02rem; color: var(--sepia-ink); }

/* below 1024: one column. The head (house halves from 860), the photograph as a band within the margins, the entries */
@media (max-width: 1023px) {
  .give-spread { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; }
  .give-head, .give-photo, .give-ways { grid-column: 1; grid-row: auto; }
  .give-head { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 18px 64px; align-items: start; }
  .give-intro { margin-top: -4px; }
  .give-photo { position: static; margin: 52px 0 0; }
  .give-ways { max-width: 44em; margin-top: 56px; }
  .give-foot { margin-top: 88px; }
}
@media (max-width: 859px) {
  .give-head { grid-template-columns: minmax(0, 1fr); padding-top: 24px; }
  .give-intro { margin-top: 0; }
  .give-foot { grid-template-columns: minmax(0, 1fr); margin-top: 72px; }
  .give-note, .give-quote { grid-column: 1; grid-row: auto; }
  .give-note { padding-top: 0; }
  .give-quote { margin-top: 48px; }
}
/* phone: every action a full-width 48px row between hairlines */
@media (max-width: 599px) {
  .support { padding: 96px 0 88px; }
  .give-photo { margin-top: 40px; }
  .give-photo figcaption { font-size: 0.95rem; }
  .give-ways { margin-top: 48px; }
  .give-entry { padding: 22px 0 0; }
  .give-envelope { width: 100%; padding: 22px 24px; font-size: 1.32rem; }
  .give-actions { flex-direction: column; margin-top: 14px; }
  .give-act { width: 100%; min-height: 48px; border-top: 1px solid var(--rule-light); }   /* the next entry's hairline closes the last row */
  .give-entry:last-child .give-actions { border-bottom: 1px solid var(--rule-light); }
  .give-entry:not(:has(.give-act:not([hidden]))) { padding-bottom: 22px; }   /* no JS: the envelope keeps its air */
  .give-entry:last-child { border-bottom: 0; }
}

/* ===== footer: cypress-deep. The colophon that closes the book =====
   Three rows on the wrap's content box, each hanging from its own 1px rule (the rules sit on inner
   elements, never on the padded .wrap, so at 1440 every one spans 158 to 1282px).
   1. Masthead: the motto set large and, under it, the visit line (quiet, live, unrounded, absent on
      failure; app.js unhides it), the emblem in one cream ink at the right, bottoms aligned.
   2. Three ruled columns: the sanctuary, the Foundation as letterhead, the colophon proper (a dl).
   3. Base line: the novel disclaimer, verbatim, and the imprint.
   The masthead, the columns and the base share one three-column grid, so the emblem, the Colophon
   column and the imprint all start on the same line. Below 860px the masthead and the base stack; the
   columns pair up on tablets and stack on phones. No motion. */
.footer { padding: 96px 0 40px; background: var(--cypress-deep); color: var(--on-dark-dim); }
.footer a {
  color: var(--on-dark); text-decoration: underline; text-decoration-thickness: 1px;
  text-decoration-color: rgba(239, 230, 207, 0.4); text-underline-offset: 3px;
  transition: text-decoration-color var(--t-ui) var(--ease-out);
}
@media (hover: hover) { .footer a:hover { text-decoration-color: currentColor; } }
.footer a:active { text-decoration-color: currentColor; }

.colo-mast, .colo-cols, .colo-base { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: 40px; border-top: 1px solid var(--rule-dark); }

/* 1. masthead */
.colo-mast { align-items: end; padding-top: 52px; }
.colo-words { grid-column: 1 / span 2; padding-bottom: 6px; }
.colo-motto {
  max-width: 11em; font-family: var(--font-display); font-style: italic; font-size: clamp(2.2rem, 4.6vw, 3.6rem);
  line-height: 1.02; color: var(--on-dark); text-wrap: balance;
}
.colo-count {
  max-width: 24em; margin-top: 28px; font-family: var(--font-display); font-size: 1.2rem; line-height: 1.42;
  color: var(--on-deep-warm); font-variant-numeric: tabular-nums lining-nums;
}
.colo-count .colo-clause { display: inline-block; }   /* the clause moves to its own line whole, and still wraps inside at large text */
.colo-emblem { grid-column: 3; width: 100%; max-width: 420px; height: auto; aspect-ratio: 1250 / 650; opacity: 0.88; }

/* 2. three ruled columns */
.colo-cols { row-gap: 40px; margin-top: 64px; padding-top: 30px; }
.colo-h { margin-bottom: 12px; font-size: 1.05rem; line-height: 1.3; color: var(--on-deep-head); }
.colo-col p { font-size: 0.94rem; line-height: 1.62; }
.colo-col p + p { margin-top: 12px; }
.colo-col .colo-note { font-style: italic; }
.colo-dl { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 8px 16px; font-size: 0.94rem; line-height: 1.55; }
.colo-dl > div { display: contents; }
.colo-dl dt { grid-column: 1; padding-top: 1px; font-size: 1rem; line-height: 1.45; color: var(--on-deep-head); }
.colo-dl dd { grid-column: 2; }
.colo-dl dd + dd { margin-top: -2px; }

/* 3. base line */
.colo-base { margin-top: 64px; padding-top: 20px; font-size: 0.84rem; line-height: 1.6; color: var(--foot-small); }
.colo-disclaimer { grid-column: 1 / span 2; max-width: 50em; }
.colo-imprint { grid-column: 3; }
.colo-imprint > span { display: block; }   /* two lines: the Foundation's copyright, then the site credit */
.colo-imprint > .colo-sep { display: none; }

/* small desktop: the colophon's terms sit over their entries in the narrower column */
@media (min-width: 860px) and (max-width: 1023px) {
  .colo-dl { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .colo-dl dt, .colo-dl dd { grid-column: 1; }
  .colo-dl > div + div dt { margin-top: 10px; }
}
/* phone and tablet: one column; the motto, the visit line, the emblem 300px at the left */
@media (max-width: 859px) {
  .footer { padding: 64px 0 36px; }
  .colo-mast, .colo-cols, .colo-base { grid-template-columns: minmax(0, 1fr); }
  .colo-mast { row-gap: 26px; align-items: start; padding-top: 40px; }
  .colo-words, .colo-emblem, .colo-disclaimer, .colo-imprint { grid-column: 1; }
  .colo-words { padding-bottom: 0; }
  .colo-count { margin-top: 18px; font-size: 1.12rem; }
  .colo-emblem { max-width: 300px; margin-top: 6px; }
  .colo-cols { row-gap: 32px; margin-top: 52px; padding-top: 30px; }
  .colo-base { row-gap: 14px; margin-top: 52px; }
}
@media (max-width: 479px) {
  .colo-dl .nw, .colo-count .nw { white-space: normal; }
}
/* tablet: the sanctuary and the Foundation side by side, the colophon across both under them */
@media (min-width: 600px) and (max-width: 859px) {
  .colo-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 40px; }
  .colo-col:last-child { grid-column: 1 / -1; }
}

/* ---------- 6. SHARED COMPONENTS ---------- */

/* buttons: amber with cypress text is the primary; white on brass is retired */
.btn {
  display: inline-flex; align-items: center; gap: 10px; padding: 13px 22px;
  border-radius: var(--r-paper); text-decoration: none;
  font-weight: 600; font-size: 0.95rem; letter-spacing: 0.01em;
  transition: background-color var(--t-ui) var(--ease-out), border-color var(--t-ui) var(--ease-out), color var(--t-ui) var(--ease-out);
}
.btn-primary { background: var(--amber); color: var(--cypress); }
.btn-primary:active { background: var(--amber-press); }
.text-link {
  display: inline-block; padding: 10px 0;
  color: var(--on-dark); font-weight: 500;
  text-decoration: underline; text-decoration-color: var(--amber); text-decoration-thickness: 1.5px; text-underline-offset: 6px;
  transition: text-decoration-color var(--t-ui) var(--ease-out);
}
@media (hover: hover) {
  .btn-primary:hover { background: var(--amber-press); }
  .text-link:hover { text-decoration-color: var(--on-dark); }
}

/* read by screen readers, not shown */
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }

/* one focus ring: 2px, amber on dark grounds, brass ink on paper */
:focus-visible { outline: 2px solid var(--focus, var(--brass-ink)); outline-offset: 3px; }

/* the viewer: one dialog for prints, plates and the map (app.js openViewer). The room is cypress at 94%;
   the picture lies on its mat like the prints on the page, with the label on a parchment strip under it
   (caption in IM Fell italic, date and credit small in --ink-on-sheet). app.js sizes every frame in pixels
   from the item's ratio, never larger than the file. Screen controls are round; paper is square.
   Desktop: the count top left, close top right, prev and next at the sides. Below 860px: close top right,
   a bottom bar of prev, count and next (48px each); a card opens as a bottom sheet. Motion is in block 7. */
dialog.viewer {
  position: fixed; inset: 0; width: 100%; height: 100%; max-width: none; max-height: none;
  margin: 0; padding: 0; border: 0; background: transparent; color: var(--on-dark);
  overflow: hidden; overscroll-behavior: contain;
}
dialog.viewer:not([open]) { display: none; }
dialog.viewer::backdrop { background: rgba(10, 20, 16, 0.94); }
/* the page behind never scrolls (iPhone Safari honours overflow on the root since iOS 16); the gutter
   keeps a classic scrollbar's width, so nothing behind shifts */
html:has(dialog.viewer[open]), html.viewer-open { overflow: hidden; scrollbar-gutter: stable; }
.viewer-shell {
  position: absolute; inset: 0; display: grid;
  grid-template-columns: 104px minmax(0, 1fr) 104px;
  grid-template-rows: 76px minmax(0, 1fr) 32px;
  grid-template-areas: "count count close" "prev stage next" ". . .";
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}
.viewer-stage { grid-area: stage; position: relative; display: grid; place-items: center; min-width: 0; min-height: 0; touch-action: pan-y; }
.viewer-stage[data-kind="diptych"] { place-items: start center; overflow-y: auto; overscroll-behavior: contain; }
.viewer-stage:focus-visible { outline: 2px solid var(--focus); outline-offset: -4px; }
.viewer-nav { display: contents; }
.viewer-count { grid-area: count; align-self: center; margin: 0 0 0 32px; font-size: 1.12rem; line-height: 1; color: var(--on-dark-dim); font-variant-numeric: lining-nums tabular-nums; }
.viewer-btn {
  width: 52px; height: 52px; display: grid; place-items: center; padding: 0;
  border: 1px solid rgba(239, 230, 207, 0.38); border-radius: 50%; background: rgba(239, 230, 207, 0.06);
  color: var(--on-dark); cursor: pointer;
  transition: background-color var(--t-ui) var(--ease-out), border-color var(--t-ui) var(--ease-out);
}
.viewer-btn svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.viewer-btn:active { background: rgba(239, 230, 207, 0.2); }
@media (hover: hover) { .viewer-btn:hover { background: rgba(239, 230, 207, 0.15); border-color: var(--on-dark); } }
.viewer-close { grid-area: close; align-self: center; justify-self: end; margin-right: 24px; }
.viewer-prev { grid-area: prev; place-self: center; }
.viewer-next { grid-area: next; place-self: center; }
.viewer-shell.is-single :is(.viewer-prev, .viewer-next, .viewer-count) { display: none; }

/* the sheet: paper, square, lifted off the room */
.viewer-sheet {
  grid-area: 1 / 1; margin: 0; padding: 10px 10px 0;
  background-color: var(--parchment); background-image: var(--paper-grain);
  border-radius: var(--r-paper); box-shadow: var(--lift-frame); color: var(--ink);
  --focus: var(--brass-ink);
}
.viewer-pic { position: relative; overflow: hidden; background: var(--ph, var(--cypress-deep)) center / cover no-repeat; }   /* app.js may lay the page's loaded thumbnail here until the file lands */
.viewer-img { display: block; width: 100%; height: 100%; object-fit: cover; user-select: none; -webkit-user-select: none; -webkit-user-drag: none; -webkit-touch-callout: none; }
.viewer-label { padding: 12px 4px 15px; }
.viewer-label p { max-width: none; }
.viewer-caption { font-family: var(--font-display); font-style: italic; font-size: 1.05rem; line-height: 1.38; color: var(--ink); }
.viewer-date, .viewer-credit { margin-top: 4px; font-size: 0.82rem; line-height: 1.45; color: var(--ink-on-sheet); }
.viewer-label cite { font-style: italic; }
.viewer-caption cite { font-style: normal; }
.viewer-action {
  display: inline-block; margin-top: 4px; padding: 10px 0; border: 0; background: none; cursor: pointer;
  font: 500 0.88rem/1.3 var(--font-body); color: var(--brass-on-sheet);
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px;
}
@media (hover: hover) { .viewer-action:hover { color: var(--ink); } }

/* diptych: a plate and the sanctuary's own record on one sheet, a 1px sepia rule between them */
.viewer-diptych { display: grid; grid-template-columns: auto 1px auto; column-gap: 16px; align-items: start; padding: 20px 20px 4px; }
.viewer-rule { align-self: stretch; margin-bottom: 16px; background: rgba(125, 96, 61, 0.55); }
.viewer-diptych .viewer-label { padding: 10px 0 14px; }

/* map: the 1000px plate at its own size in a pane that scrolls, the shown layer cloned over it (static spans) */
.viewer-map-pane { overflow: auto; overscroll-behavior: contain; touch-action: pan-x pan-y; background-color: var(--ph, var(--mat)); }
.viewer-map-canvas { position: relative; }
.viewer-map-pic { position: absolute; inset: 0; }
.viewer-map-canvas :is(.plan-layer, .land-layer) { opacity: 1; pointer-events: none; transition: none; }
.viewer-map-canvas .plan-cam { --hit: 32px; --d: 32px; font-size: 17px; }
.viewer-map-canvas .plan-zone { font-size: 1.3rem; }

/* card: a landmark on a parchment card */
.viewer-card-body { padding: 14px 8px 18px; }
.viewer-card-title { margin-bottom: 6px; font-size: 1.55rem; line-height: 1.15; color: var(--cypress); }
.viewer-card-text { font-size: 0.98rem; line-height: 1.6; color: var(--ink-soft); }
.viewer-card .viewer-label { padding: 10px 0 0; }

@media (max-width: 859px) {
  .viewer-shell {
    grid-template-columns: minmax(0, 1fr); grid-template-rows: 64px minmax(0, 1fr) auto;
    grid-template-areas: "close" "stage" "nav";
  }
  .viewer-close { width: 48px; height: 48px; margin-right: max(8px, calc(var(--gutter) - 8px)); }
  .viewer-nav { grid-area: nav; display: flex; justify-content: center; align-items: center; gap: 6px; padding: 10px 16px 12px; }
  .viewer-nav .viewer-btn { width: 48px; height: 48px; }
  .viewer-count { min-width: 6.4em; margin: 0; text-align: center; font-size: 1.06rem; }
  .viewer-shell.is-single .viewer-nav { display: none; }
  .viewer-sheet { padding: 8px 8px 0; }
  .viewer-label { padding: 10px 2px 13px; }
  .viewer-caption { font-size: 1rem; }
  .viewer-diptych { grid-template-columns: auto; justify-items: center; padding: 12px 12px 0; }
  .viewer-rule { width: 100%; height: 1px; margin: 0 0 12px; justify-self: stretch; }
  .viewer-stage[data-kind="card"] { place-items: end stretch; }
  .viewer-card { max-height: calc(100% - 24px); overflow-y: auto; overscroll-behavior: contain; box-shadow: none; }
  .viewer-card-body { padding: 14px 8px 22px; }
}

/* Windows high contrast and other forced-color modes */
@media (forced-colors: active) {
  :focus-visible { outline-color: Highlight; }
  .map-spot-dot { forced-color-adjust: none; background: Canvas; border-color: Highlight; }
  .plan-cam { forced-color-adjust: none; color: Canvas; }
  .plan-cam::before { forced-color-adjust: none; background: CanvasText; border-color: Canvas; }
  .plan-cam.is-lit::before { background: Highlight; }
  .plan-zone-shape { stroke: CanvasText; }
  .is-mapped .plan-num, .plan-num.is-mapped { forced-color-adjust: none; background: CanvasText; color: Canvas; }
  .cam-play-i { fill: ButtonText; }
  .cam-card-dwell, .cam-plan-pin { forced-color-adjust: none; background: Highlight; }
  .almanac-horizon, .almanac-arc { stroke: CanvasText; }
  .almanac-dot { fill: CanvasText; }
  .tl-river-line { stroke: CanvasText; }
  .tl-station { fill: CanvasText; stroke: CanvasText; }
  .tl-nib { forced-color-adjust: none; background: CanvasText; }
  .cam-card.is-active::before { box-shadow: none; border: 2px solid Highlight; }
  dialog.viewer::backdrop { background: Canvas; }
  .viewer-sheet { border: 1px solid CanvasText; }
}

/* ---------- 7. MOTION CONTRACT ----------
   Three named places carry motion: the cover poster lay-down (cover item), the camera
   acquire (cameras item) and the river of time (history-ink: scroll-drawn). Everything else is
   interaction feedback of 340ms or less, using opacity, color or transform: strip value
   crossfades, the almanac dot, viewer crossfades, copy-label swaps, image decode fades, the
   tour dwell hairline and hover states. Nothing loops at rest.
   Hover rules live inside @media (hover: hover). Start states apply only under
   html.js:not(.noanim) and each has a CSS fail-safe that reaches rest about 2.5 s after load,
   so a script error never leaves content hidden. ?noanim sets html.noanim: everything at rest. */
@keyframes lr-rest { to { transform: none; opacity: 1; } }

/* image decode fade: below-the-fold photos rise from their --ph slot colour in 200ms once decoded.
   The head script marks every <img> .is-loaded on load OR error (capture listeners set before any
   <img> parses) and app.js marks img.complete at init, so nothing stays hidden; a photo that never
   arrives leaves its slot colour, never a blank. Motion-safe only; ?noanim and print show them at once. */
@media (prefers-reduced-motion: no-preference) {
  html.js:not(.noanim) img[loading="lazy"] { transition: opacity var(--t-ui) var(--ease-out); }
  html.js:not(.noanim) img[loading="lazy"]:not(.is-loaded) { opacity: 0; }
}

/* the set: the cover poster laid down like a print, once per session (named motion place 1).
   Start: 18px low, turned 1.2 degrees, its shadow that of a print held above the page. It never
   fades. app.js adds .set-go (760ms to rest) as soon as the poster is decoded, or .set-rest; the
   1.6 s fail-safe rests it if app.js never runs. .set-seen (head script) = a repeat view: at rest.
   The foot's hairline draws at 900ms, then the dateline and imprint ink in, all at rest by 1.6 s. */
@keyframes lr-gone { to { opacity: 0; } }
@keyframes lr-draw { from { transform: scaleX(0); } }
@keyframes lr-ink { from { opacity: 0; } }
@keyframes lr-write { to { clip-path: inset(0); } }
@keyframes lr-lit { to { opacity: 1; filter: none; } }
@media (prefers-reduced-motion: no-preference) {
  html.js:not(.noanim):not(.set-seen) .hero-poster figure { transform: translateY(18px) rotate(-1.2deg); animation: lr-rest 1ms linear 1.6s forwards; }
  html.js:not(.noanim):not(.set-seen) .hero-poster figure::before { opacity: 0; animation: lr-rest 1ms linear 1.6s forwards; }
  html.js:not(.noanim):not(.set-seen) .hero-poster figure::after { opacity: 1; animation: lr-gone 1ms linear 1.6s forwards; }
  html.js.set-go:not(.noanim):not(.set-seen) .hero-poster figure { animation: lr-rest var(--t-settle) var(--ease-settle) forwards; }
  html.js.set-go:not(.noanim):not(.set-seen) .hero-poster figure::before { animation: lr-rest var(--t-settle) var(--ease-settle) forwards; }
  html.js.set-go:not(.noanim):not(.set-seen) .hero-poster figure::after { animation: lr-gone var(--t-settle) var(--ease-settle) forwards; }
  html.js.set-rest:not(.noanim):not(.set-seen) .hero-poster figure,
  html.js.set-rest:not(.noanim):not(.set-seen) .hero-poster figure::before { transform: none; opacity: 1; animation: none; }
  html.js.set-rest:not(.noanim):not(.set-seen) .hero-poster figure::after { opacity: 0; animation: none; }
  html.js:not(.noanim):not(.set-seen) .cover-foot::before { animation: lr-draw 500ms var(--ease-out) 900ms both; }
  html.js:not(.noanim):not(.set-seen) .cover-foot p { animation: lr-ink var(--t-ui) var(--ease-out) 1400ms both; }

  /* the acquire (named motion place 2). app.js sets #camLayout[data-tune] to pre when the player nears the
     screen (desktop, motion allowed, once a session; ?tune replays), open when it is half on screen, then
     lift once its first frame has decoded (at least 420ms after open; 1,400ms at most). Start: the still at
     70% under a parchment wash and the slate, the lower third clipped, the tiles unlit. Lift: the veil goes
     in 300ms, the slate in 150ms, the lower third writes on from the left in 220ms, the tiles light in
     order (160ms each, 60ms apart). Opacity, filter and clip-path only. The 4 s net rests every start
     state if the script dies (the script itself never holds one past 3.8 s). */
  html.js:not(.noanim) .cam-layout:is([data-tune="pre"], [data-tune="open"]) .cam-veil::before,
  html.js:not(.noanim) .cam-layout:is([data-tune="pre"], [data-tune="open"]) .cam-veil::after { opacity: 0.3; animation: lr-gone 300ms linear 4s forwards; }
  html.js:not(.noanim) .cam-layout:is([data-tune="pre"], [data-tune="open"]) .cam-slate { opacity: 1; animation: lr-gone 150ms linear 4s forwards; }
  html.js:not(.noanim) .cam-layout:is([data-tune="pre"], [data-tune="open"]) .cam-lower { clip-path: inset(0 100% 0 0); animation: lr-write 220ms linear 4s forwards; }
  html.js:not(.noanim) .cam-layout:is([data-tune="pre"], [data-tune="open"]) :is(.cam-card-thumb, .cam-card-text) { opacity: 0.12; filter: grayscale(1); animation: lr-lit 160ms linear 4s forwards; }
  html.js:not(.noanim) .cam-layout[data-tune="lift"] .cam-veil::before,
  html.js:not(.noanim) .cam-layout[data-tune="lift"] .cam-veil::after { transition: opacity 300ms var(--ease-out); }
  html.js:not(.noanim) .cam-layout[data-tune="lift"] .cam-slate { transition: opacity 150ms var(--ease-out); }
  html.js:not(.noanim) .cam-layout[data-tune="lift"] .cam-lower { transition: clip-path 220ms var(--ease-out) 120ms; }
  html.js:not(.noanim) .cam-layout[data-tune="lift"] :is(.cam-card-thumb, .cam-card-text) {
    transition: opacity 160ms var(--ease-out) calc(200ms + var(--k, 0) * 60ms), filter 160ms linear calc(200ms + var(--k, 0) * 60ms);
  }
  /* a clip's first frame crossfades over its still; a switch dips to cypress for 120ms */
  html.js:not(.noanim) .cam-frame > video { transition: opacity 300ms var(--ease-out); }
  html.js:not(.noanim) .cam-dip { transition: opacity 120ms var(--ease-out); }
  html.js:not(.noanim) .cam-card-thumb img { transition: opacity var(--t-ui) var(--ease-out), filter var(--t-ui) var(--ease-out); }

  /* the giving desk: a copy button's label swaps to "Copied" and back (150ms) */
  html.js:not(.noanim) .give-copy > span { transition: opacity var(--t-micro) var(--ease-out); }

  /* strip values crossfade in; the almanac dot moves on the minute */
  html.js:not(.noanim) .now-item dd > span { transition: opacity var(--t-ui) var(--ease-out); }
  .almanac-dot { transition: transform 600ms var(--ease-out); }
}

/* the river of time (named motion place 3): drawn by the reader's scroll, reversible, its nib held at 70% of
   the screen's height. app.js builds the river and marks the timeline .is-view (CSS view timelines) or .is-scrub
   (its own fallback); without motion it marks neither and the river is drawn complete, every station inked, the
   nib resting as the end dot. View timeline: both hairlines (pathLength 1) draw from the scroll, the nib rides
   the same path (offset-path, set by app.js), each station inks in as the nib reaches it (--at, its place on the
   scroll in px from the timeline top). --tl-a and --tl-b are where the river starts and ends. Nothing is
   measured while scrolling. Fallback: app.js sets the dash offset, moves the nib and marks stations .is-wet. */
@keyframes lr-river { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes lr-nib { from { offset-distance: 0%; } to { offset-distance: 100%; } }
@keyframes lr-wet { from { fill: var(--paper); } to { fill: var(--sepia-ink); } }
@media (prefers-reduced-motion: no-preference) {
  html.js:not(.noanim) .timeline.is-view :is(.tl-river-line, .tl-nib) {
    animation: lr-river linear both; animation-timeline: --river;
    animation-range: cover calc(30vh + var(--tl-a, 0px)) cover calc(30vh + var(--tl-b, 100%));
  }
  html.js:not(.noanim) .timeline.is-view .tl-nib { animation-name: lr-nib; }
  html.js:not(.noanim) .timeline.is-view .tl-station {
    animation: lr-wet linear both; animation-timeline: --river;
    animation-range: cover calc(30vh + var(--at, 0px)) cover calc(30vh + var(--at, 0px) + 3px);
  }
  html.js:not(.noanim) .timeline.is-scrub .tl-station:not(.is-wet) { fill: var(--paper); }
}

/* the viewer (app.js): the sheet waits at opacity 0 until its file is decoded (300ms at most), then crossfades
   in: 180ms from scale .98 on open, a plain 180ms crossfade on browse (a swipe adds a short follow-through in
   its direction). A finger carries the sheet; under 40px it snaps back in 220ms. The backdrop and the controls
   fade in over 200ms; a close fades everything in 160ms. Reduced motion: opacity only, 120ms. ?noanim: instant
   (app.js uses zero durations). The sheet's resting state is set by app.js, never by a timer here: the room is
   dark until the picture is there, and a picture that is late fades up from its slot colour. */
.viewer-sheet { opacity: 0; }
.viewer-sheet.is-in { opacity: 1; }
.viewer-sheet.is-out { opacity: 0; pointer-events: none; }
.viewer-img:not(.is-loaded) { opacity: 0; }
dialog.viewer.is-closing .viewer-shell { opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
  html:not(.noanim) .viewer-sheet { transform: scale(0.98); transition: opacity 180ms var(--ease-out), transform 180ms var(--ease-out); }
  html:not(.noanim) .viewer-sheet.is-browse { transform: translateX(var(--enter-x, 0px)); }
  html:not(.noanim) .viewer-sheet.is-in, html:not(.noanim) .viewer-sheet.is-out { transform: none; }
  html:not(.noanim) .viewer-sheet.is-dragging { transition: none; }
  html:not(.noanim) .viewer-sheet.is-snapping { transition: transform 220ms var(--ease-out); }
  html:not(.noanim) .viewer-img { transition: opacity var(--t-ui) var(--ease-out); }
  html:not(.noanim) dialog.viewer[open]::backdrop,
  html:not(.noanim) dialog.viewer[open] .viewer-shell { animation: lr-ink 200ms var(--ease-out); }
  html:not(.noanim) dialog.viewer .viewer-shell { transition: opacity 160ms var(--ease-in); }
  html:not(.noanim) dialog.viewer.is-closing::backdrop { animation: lr-gone 160ms var(--ease-in) forwards; }
}
@media (prefers-reduced-motion: no-preference) and (max-width: 859px) {
  html:not(.noanim) .viewer-stage[data-kind="card"] .viewer-sheet:not(.is-in) { transform: translateY(24px); }
}
@media (prefers-reduced-motion: reduce) {
  html:not(.noanim) .viewer-sheet, html:not(.noanim) .viewer-img { transition: opacity 120ms linear; }
  html:not(.noanim) dialog.viewer .viewer-shell { transition: opacity 120ms linear; }
  html:not(.noanim) dialog.viewer[open]::backdrop,
  html:not(.noanim) dialog.viewer[open] .viewer-shell { animation: lr-ink 120ms linear; }
  html:not(.noanim) dialog.viewer.is-closing::backdrop { animation: lr-gone 120ms linear forwards; }
}

html.noanim { scroll-behavior: auto; }
html.noanim *, html.noanim *::before, html.noanim *::after { animation: none !important; transition: none !important; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .plan-cam.is-lit::before { transform: none; }
  .plan-cam::before, .map-spot-dot, .plate-img, .nav-toggle span { transition: none; }
  .plate:hover .plate-img, .plate.is-linked .plate-img { transform: none; }
  .almanac-dot { transition: none; }
}
