/* Save Sundial Park — "Survey"
   Palette sampled from the residents' own photographs of the field:
   shadowed turf, sunlit grass, the chalk of spray-paint survey lines,
   the orange of a surveyor's stake, and the light of an Ajax evening. */

:root {
  --turf:      #14301c;
  --turf-deep: #0b1d11;
  --turf-lift: #1c3d25;
  --field:     #7fa650;
  --chalk:     #f2f0e6;
  --chalk-dim: #a8b3a1;
  --paper:     #e9e7db;
  --paper-2:   #dedbcc;
  --ink:       #101a12;
  --ink-dim:   #4a5a4d;
  --stake:     #e4572e;
  /* Deeper stake, used only as the action band's ground: white body text on
     #e4572e measures 3.68:1, which fails WCAG AA. This clears it at 4.89:1. */
  --stake-deep: #c9431f;
  --dusk:      #e8b04b;

  --rail-w: 96px;
  --gutter: clamp(1.25rem, 4vw, 4rem);
  --measure: 34rem;

  --display: "Archivo", "Helvetica Neue", sans-serif;
  --body: "Newsreader", Georgia, serif;
  --mono: "JetBrains Mono", ui-monospace, "SF Mono", monospace;

  --step--1: clamp(0.78rem, 0.75rem + 0.15vw, 0.86rem);
  --step-0:  clamp(1rem, 0.96rem + 0.2vw, 1.12rem);
  --step-1:  clamp(1.2rem, 1.1rem + 0.5vw, 1.5rem);
  --step-2:  clamp(1.5rem, 1.3rem + 1vw, 2.25rem);
  --step-3:  clamp(2rem, 1.6rem + 2vw, 3.5rem);
  --step-4:  clamp(2.75rem, 1.8rem + 4.5vw, 6.5rem);
  --step-5:  clamp(3.5rem, 1.8rem + 8vw, 10rem);
}

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

html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  background: var(--turf);
  color: var(--chalk);
  font-family: var(--body);
  font-size: var(--step-0);
  line-height: 1.62;
  font-optical-sizing: auto;
  -webkit-font-smoothing: antialiased;
}

img, video { max-width: 100%; display: block; }
a { color: inherit; }

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

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Mark outbound text links, but not buttons — a glyph inside a button reads
   as clutter, and the button label already says what it opens. */
.beyond a[target="_blank"]::after,
.foot a[target="_blank"]::after {
  content: "\2197";
  margin-left: 0.4em;
  opacity: 0.55;
  font-size: 0.9em;
}

.skip {
  position: absolute; left: -9999px;
  background: var(--dusk); color: var(--ink);
  padding: 0.75rem 1.25rem; z-index: 100;
  font-family: var(--mono); font-size: var(--step--1);
}
.skip:focus { left: 1rem; top: 1rem; }

/* ── Gnomon rail ─────────────────────────────────────────────────────────
   A sundial tells time by the length of a shadow. The rail is the page's
   shadow: it lengthens as you scroll, and its ticks are the dates. */

.rail {
  position: fixed;
  inset: 0 auto 0 0;
  width: var(--rail-w);
  z-index: 40;
  pointer-events: none;
  mix-blend-mode: normal;
}

.rail__line {
  position: absolute;
  left: 50%;
  top: 0; bottom: 0;
  width: 1px;
  background: currentColor;
  opacity: 0.22;
}

.rail__shadow {
  position: absolute;
  left: 50%;
  top: 0;
  width: 3px;
  margin-left: -1px;
  height: var(--progress, 0%);
  background: var(--dusk);
  opacity: 0.85;
}

.rail__ticks {
  position: absolute;
  inset: 0;
  margin: 0; padding: 0;
  list-style: none;
}

.rail__tick {
  position: absolute;
  left: 0; right: 0;
  transform: translateY(-50%);
  text-align: center;
  pointer-events: auto;
}

.rail__tick a {
  display: block;
  font-family: var(--mono);
  font-size: 0.5625rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-decoration: none;
  color: currentColor;
  opacity: 0.42;
  padding: 0.3rem 0;
  transition: opacity 0.25s, color 0.25s;
}
.rail__tick a::before {
  content: "";
  display: block;
  width: 9px; height: 1px;
  margin: 0 auto 0.3rem;
  background: currentColor;
}
.rail__tick a:hover { opacity: 1; }
.rail__tick[aria-current="true"] a {
  opacity: 1;
  color: var(--stake);
}
.rail__tick[aria-current="true"] a::before {
  width: 20px; height: 2px;
  background: var(--stake);
}

/* The rail crosses dark and light grounds at the same time, so each tick
   picks its own colour from whatever band it happens to be sitting over. */
.rail { color: var(--chalk); }
.rail__tick { color: var(--chalk); }
.rail__tick.on-light { color: var(--ink); }
/* Dark ink at the dark-ground opacity reads as almost nothing on cream —
   light and dark grounds need different amounts of dimming, not the same one. */
.rail__tick.on-light a { opacity: 0.6; }
.rail__tick.on-light a:hover { opacity: 1; }
.rail__tick.on-act { color: #fff; }
.rail__tick.on-act a { opacity: 0.7; }
.rail__tick.on-act a:hover { opacity: 1; }
.rail__tick.on-act[aria-current="true"] a,
.rail__tick.on-act[aria-current="true"] a::before { color: var(--ink); background: var(--ink); }
.rail__tick.on-act[aria-current="true"] a { background: none; }

/* The rail is a desktop device. On a phone it collapsed to a thin bar pinned
   above the browser's own chrome, which read as clutter and duplicated the
   scrollbar the OS already draws. Dropped entirely below this width. */
@media (max-width: 860px) {
  .rail { display: none; }
}

/* ── Layout ─────────────────────────────────────────────────────────────── */

.page { margin-left: var(--rail-w); }
@media (max-width: 860px) { .page { margin-left: 0; } }

.band { padding: clamp(4rem, 9vw, 8.5rem) var(--gutter); }
.band--paper { background: var(--paper); color: var(--ink); }
.band--deep  { background: var(--turf-deep); }
.band--tight { padding-top: clamp(2rem, 4vw, 3.5rem); }

.wrap { max-width: 72rem; margin-inline: auto; }
.wrap--narrow { max-width: 46rem; }

.eyebrow {
  font-family: var(--mono);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--field);
  margin: 0 0 1.25rem;
}
.band--paper .eyebrow { color: var(--ink-dim); }

h1, h2, h3 {
  font-family: var(--display);
  font-weight: 800;
  font-stretch: 118%;
  line-height: 0.98;
  letter-spacing: -0.02em;
  margin: 0;
  text-wrap: balance;
}

/* ── Hero ───────────────────────────────────────────────────────────────── */

.hero {
  position: relative;
  min-height: min(92vh, 60rem);
  min-height: min(92svh, 60rem);   /* svh: ignore collapsing mobile browser chrome */
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: clamp(2rem, 5vw, 4rem) var(--gutter) clamp(2rem, 4vw, 3rem);
  overflow: hidden;
}

.hero__media { position: absolute; inset: 0; z-index: 0; }
.hero__media picture { display: block; height: 100%; }
.hero__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 50% 62%;
}
.hero__media::after {
  content: "";
  position: absolute; inset: 0;
  background:
    linear-gradient(to top, var(--turf) 4%, rgba(20,48,28,0.86) 32%, rgba(20,48,28,0.28) 68%, rgba(20,48,28,0.55) 100%);
}

.hero__inner { position: relative; z-index: 1; max-width: 60rem; }

.hero__kicker {
  font-family: var(--mono);
  font-size: var(--step--1);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--dusk);
  margin: 0 0 clamp(1rem, 2vw, 1.75rem);
}

.hero h1 {
  font-size: var(--step-5);
  font-weight: 900;
  font-stretch: 125%;
  line-height: 0.88;
  letter-spacing: -0.035em;
  margin-bottom: clamp(1.25rem, 2.5vw, 2rem);
}

.hero__standfirst {
  font-size: var(--step-1);
  line-height: 1.48;
  max-width: 38rem;
  color: color-mix(in srgb, var(--chalk) 88%, transparent);
  margin: 0 0 clamp(1.75rem, 3vw, 2.5rem);
}

.hero__actions { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: stretch; }

.hero__credit {
  position: relative; z-index: 1;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  color: var(--chalk-dim);
  margin: clamp(2rem, 5vw, 4rem) 0 0;
}

/* On a portrait phone the hero is taller than it is wide, so the panorama
   would be scaled to fit the height and show its whole sky. The portrait crop
   swapped in by <picture> is near-square, and this keeps the frame from
   growing so tall that the crop stretches again. */
@media (max-aspect-ratio: 1/1) {
  .hero { min-height: min(78svh, 44rem); }
  .hero__media img { object-position: 50% 78%; }
}

/* Short laptop viewports: at 144px the headline alone is three 127px lines, so
   the hero grows past the fold and "Write to Council" drops out of sight.
   Size the headline against the viewport height and tighten the rhythm. */
@media (min-width: 861px) and (max-height: 840px) {
  .hero h1 { font-size: min(var(--step-5), 13svh); }
  .hero__standfirst { margin-bottom: 1.5rem; }
  .hero__credit { margin-top: 1.75rem; }
  .hero { padding-top: 2.5rem; }
}

/* Narrower still, and the frame would crop most of the field's width away.
   A shorter hero keeps the crop near its own 1.14 aspect — and puts the four
   figures on screen without scrolling, which is where the argument starts. */
@media (max-width: 560px) {
  .hero { min-height: min(64svh, 32rem); }
  .hero__media img { object-position: 50% 68%; }
}

/* ── Buttons ────────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--mono);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 0.95rem 1.6rem;
  border: 1px solid transparent;
  min-height: 44px;
  transition: background 0.2s, color 0.2s, border-color 0.2s;
}
.btn--primary { background: var(--stake); color: #fff; }
.btn--primary:hover { background: #f26a41; }
.btn--ghost { border-color: color-mix(in srgb, currentColor 45%, transparent); }
.btn--ghost:hover { border-color: currentColor; background: rgba(255,255,255,0.07); }
.band--paper .btn--ghost:hover { background: rgba(0,0,0,0.05); }

/* ── Receipts ───────────────────────────────────────────────────────────── */

.receipts {
  display: grid;
  /* 15rem, not 13: at 430px this resolves to a single full-width column so the
     figures keep their scale instead of shrinking to 24px in two cramped cells. */
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1px;
  background: color-mix(in srgb, var(--chalk) 16%, transparent);
  border-block: 1px solid color-mix(in srgb, var(--chalk) 16%, transparent);
}
.receipt {
  background: var(--turf);
  padding: clamp(1.75rem, 3vw, 2.75rem) clamp(1.25rem, 2vw, 2rem);
  container-type: inline-size;
}
.receipt__figure {
  font-family: var(--display);
  font-weight: 800;
  font-stretch: 112%;
  /* "$3,500,000" is ten glyphs of expanded display type. Sized against the
     column rather than the page so it cannot outgrow its cell. */
  font-size: clamp(1.5rem, 12cqi, 3.25rem);
  line-height: 0.94;
  letter-spacing: -0.03em;
  color: var(--dusk);
  display: block;
}
/* Orange is reserved for loss everywhere on this page; amber states a fact.
   Set per item rather than by position, so editing the list cannot invert it —
   which is exactly what happened when the asking-price tile was removed. */
.receipt--loss .receipt__figure { color: var(--stake); }
.receipt--status .receipt__figure { color: var(--dusk); }
.receipt__label {
  display: block;
  font-size: var(--step-0);
  margin-top: 0.75rem;
  color: var(--chalk);
}
.receipt__source {
  display: block;
  font-family: var(--mono);
  font-size: 0.6875rem;
  line-height: 1.5;
  letter-spacing: 0.03em;
  color: var(--chalk-dim);
  margin-top: 0.6rem;
}

/* ── Prose ──────────────────────────────────────────────────────────────── */

.prose p {
  font-size: var(--step-1);
  line-height: 1.58;
  max-width: var(--measure);
  margin: 0 0 1.35em;
}
.prose p:last-child { margin-bottom: 0; }
.prose p:last-child strong {
  font-family: var(--display);
  font-weight: 800;
  font-stretch: 112%;
  font-size: var(--step-2);
  line-height: 1.1;
  display: block;
  letter-spacing: -0.02em;
}

/* Lisa's standing line — set large enough to read as the page's position,
   not as a caption. */
.statement {
  font-family: var(--display);
  font-weight: 700;
  font-stretch: 112%;
  font-size: var(--step-2);
  line-height: 1.15;
  letter-spacing: -0.02em;
  max-width: 26ch;
  margin: 0;
  text-wrap: balance;
  color: var(--dusk);
}

.docs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin: 1.75rem 0 0;
}

.beyond {
  list-style: none;
  margin: 1.75rem 0 0;
  padding: 0;
  max-width: var(--measure);
  border-top: 1px solid color-mix(in srgb, currentColor 20%, transparent);
}
.beyond li { border-bottom: 1px solid color-mix(in srgb, currentColor 14%, transparent); }
.beyond a {
  display: flex;
  align-items: center;
  min-height: 48px;
  padding: 0.5rem 0;
  font-family: var(--mono);
  font-size: var(--step--1);
  line-height: 1.5;
}
.beyond a:hover { color: var(--stake); }

/* ── Timeline ───────────────────────────────────────────────────────────── */

.entry {
  border-top: 1px solid color-mix(in srgb, currentColor 18%, transparent);
  padding-block: clamp(2.5rem, 5vw, 4.5rem);
  display: grid;
  grid-template-columns: 11rem minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 3.5rem);
}
@media (max-width: 760px) {
  .entry { grid-template-columns: 1fr; gap: 1.25rem; }
}

.entry__meta { position: sticky; top: 2rem; align-self: start; }
@media (max-width: 760px) { .entry__meta { position: static; } }

.entry__date {
  font-family: var(--mono);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.06em;
  line-height: 1.45;
  display: block;
}

.tag {
  display: inline-block;
  font-family: var(--mono);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 0.25rem 0.5rem;
  margin-top: 0.85rem;
  border: 1px solid currentColor;
}
.tag--documented { color: var(--field); }
.band--paper .tag--documented { color: #4d7a2a; }
.tag--reported   { color: var(--chalk-dim); }
.band--paper .tag--reported { color: var(--ink-dim); }
.tag--unknown    { color: var(--stake); }

.entry__title {
  font-size: var(--step-2);
  margin-bottom: 0.9rem;
}
.entry__body {
  font-size: var(--step-0);
  line-height: 1.66;
  max-width: var(--measure);
  margin: 0;
}
.entry__source {
  font-family: var(--mono);
  font-size: 0.6875rem;
  line-height: 1.5;
  letter-spacing: 0.03em;
  color: var(--chalk-dim);
  margin: 1.25rem 0 0;
}
.band--paper .entry__source { color: var(--ink-dim); }

/* Key–value strip for the sale facts */
.facts {
  margin: 1.75rem 0 0;
  border-top: 1px solid color-mix(in srgb, currentColor 20%, transparent);
  max-width: var(--measure);
}
.facts div {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.6rem 0;
  border-bottom: 1px solid color-mix(in srgb, currentColor 12%, transparent);
  font-family: var(--mono);
  font-size: var(--step--1);
}
.facts dt { color: var(--chalk-dim); margin: 0; }
.band--paper .facts dt { color: var(--ink-dim); }
.facts dd { margin: 0; font-weight: 500; text-align: right; }

/* Pull quote — the one place the page raises its voice */
.pull {
  margin: clamp(2rem, 4vw, 3rem) 0 0;
  padding-left: clamp(1rem, 2vw, 1.75rem);
  border-left: 3px solid var(--stake);
  max-width: 40rem;
}
.pull blockquote {
  margin: 0;
  font-family: var(--display);
  font-weight: 700;
  font-stretch: 112%;
  font-size: var(--step-2);
  line-height: 1.12;
  letter-spacing: -0.02em;
  text-wrap: balance;
}
.pull figcaption {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  line-height: 1.6;
  color: var(--chalk-dim);
  margin-top: 1rem;
}
.band--paper .pull figcaption { color: var(--ink-dim); }

/* ── Media figures ──────────────────────────────────────────────────────── */

.plates {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(19rem, 100%), 1fr));
  gap: clamp(1rem, 2vw, 1.75rem);
  margin: clamp(1.75rem, 4vw, 2.75rem) 0 0;
}

.plate { margin: 0; }
.plate picture { display: block; }
.plate img, .plate video {
  width: 100%;
  height: auto;
  /* Phone photographs are tall. Without a cap a single portrait shot fills the
     whole viewport and the reader loses the thread of the entry. */
  max-height: 58vh;
  object-fit: contain;
  object-position: center top;
  background: var(--turf-deep);
}
.band--paper .plate img, .band--paper .plate video { background: var(--paper-2); }

/* A lone figure should not span the full measure of the page. */
.plate:only-child { max-width: 34rem; }
.plate--wide:only-child { max-width: none; }
.plate figcaption {
  display: flex;
  gap: 0.85rem;
  align-items: baseline;
  margin-top: 0.7rem;
  font-family: var(--mono);
  font-size: 0.6875rem;
  line-height: 1.55;
  letter-spacing: 0.02em;
  color: var(--chalk-dim);
}
.band--paper .plate figcaption { color: var(--ink-dim); }
.plate time { color: var(--dusk); flex: none; }
.band--paper .plate time { color: var(--stake); }

.plate--wide { grid-column: 1 / -1; }

/* ── Actions taken ──────────────────────────────────────────────────────── */

.done {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(17rem, 100%), 1fr));
  gap: 1px;
  background: color-mix(in srgb, var(--chalk) 15%, transparent);
  border: 1px solid color-mix(in srgb, var(--chalk) 15%, transparent);
  margin-top: clamp(2rem, 4vw, 3rem);
}
.done > div {
  background: var(--turf-deep);
  padding: clamp(1.5rem, 2.5vw, 2.25rem);
}
.done h3 {
  font-size: var(--step-1);
  font-weight: 700;
  margin-bottom: 0.65rem;
}
.done p { margin: 0; font-size: var(--step--1); line-height: 1.62; color: color-mix(in srgb, var(--chalk) 82%, transparent); }

/* ── Gallery ────────────────────────────────────────────────────────────── */

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(15rem, 100%), 1fr));
  gap: clamp(0.75rem, 1.5vw, 1.25rem);
  margin-top: clamp(2rem, 4vw, 3rem);
}
.gallery figure { margin: 0; }
.gallery img, .gallery video {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background: var(--turf-deep);
}
.gallery figcaption {
  margin-top: 0.55rem;
  font-family: var(--mono);
  font-size: 0.625rem;
  line-height: 1.55;
  letter-spacing: 0.02em;
  color: var(--chalk-dim);
}
.gallery time { display: block; color: var(--dusk); }

.is-video { position: relative; }
.is-video::after {
  content: "▶";
  position: absolute;
  top: 0.6rem; left: 0.6rem;
  font-family: var(--mono);
  font-size: 0.625rem;
  padding: 0.25rem 0.45rem;
  background: rgba(11,29,17,0.78);
  color: var(--chalk);
}

/* ── Act ────────────────────────────────────────────────────────────────── */

.band--act { background: var(--stake-deep); color: #fff; }
.band--act .eyebrow { color: rgba(255,255,255,0.88); }
.band--act .btn--primary { background: var(--ink); color: var(--chalk); }
.band--act .btn--primary:hover { background: #000; }
.band--act .btn--ghost { border-color: rgba(255,255,255,0.55); }
.band--act .btn--ghost:hover { background: rgba(255,255,255,0.14); border-color: #fff; }

.act__head { font-size: var(--step-3); max-width: 20ch; margin-bottom: 1.5rem; }
.act__lede { font-size: var(--step-1); max-width: 36rem; margin: 0 0 2rem; }

.asks { counter-reset: ask; list-style: none; margin: 0 0 2.5rem; padding: 0; max-width: 44rem; }
.asks li {
  counter-increment: ask;
  display: grid;
  grid-template-columns: 2.5rem 1fr;
  gap: 0.5rem;
  padding: 0.9rem 0;
  border-top: 1px solid rgba(255,255,255,0.3);
  font-size: var(--step-0);
  line-height: 1.55;
}
.asks li::before {
  content: counter(ask, decimal-leading-zero);
  font-family: var(--mono);
  font-size: var(--step--1);
  opacity: 0.82;
  padding-top: 0.2em;
}

.columns {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
  gap: clamp(1.5rem, 3vw, 2.5rem);
  margin-top: clamp(2rem, 4vw, 3rem);
}
.columns h3 {
  font-size: var(--step--1);
  font-family: var(--mono);
  font-weight: 500;
  font-stretch: normal;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding-bottom: 0.6rem;
  margin-bottom: 0.85rem;
  border-bottom: 1px solid currentColor;
  opacity: 0.8;
}
.contacts { list-style: none; margin: 0; padding: 0; }
.contacts li {
  font-size: var(--step--1);
  line-height: 1.5;
  border-bottom: 1px solid rgba(255,255,255,0.18);
}
.contacts strong { display: block; font-weight: 600; font-family: var(--body); }
/* These are the page's real call to action on a phone — they need to be
   thumb-sized, not 15px of underlined text. */
.contacts a {
  display: block;
  min-height: 44px;
  padding: 0.15rem 0 0.7rem;
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.01em;
  word-break: break-word;
  /* Dimming these any further drops them under 4.5:1 on the action band. */
  opacity: 0.95;
}
.contacts a:hover { opacity: 1; }
.contacts li > strong { padding-top: 0.7rem; }

.letter {
  margin-top: clamp(2rem, 4vw, 3rem);
  background: rgba(0,0,0,0.16);
  padding: clamp(1.25rem, 2.5vw, 2rem);
}
.letter summary {
  font-family: var(--mono);
  font-size: var(--step--1);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  min-height: 44px;
  display: flex;
  align-items: center;
}
.letter pre {
  font-family: var(--mono);
  font-size: 0.75rem;
  line-height: 1.7;
  white-space: pre-wrap;
  margin: 1.25rem 0 0;
  padding-top: 1.25rem;
  border-top: 1px solid rgba(255,255,255,0.25);
}

/* ── Zoomable photographs ────────────────────────────────────────────────
   Every photograph is a button so it is reachable by keyboard as well as by
   tap. The button is invisible — the image is the affordance. */

.zoom {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
  color: inherit;
  font: inherit;
}
.zoom img { transition: opacity 0.2s; }
.zoom:hover img { opacity: 0.88; }
.zoom:focus-visible { outline: 2px solid var(--dusk); outline-offset: 3px; }

/* ── Lightbox ────────────────────────────────────────────────────────────
   Native <dialog>, so focus trapping and Escape come from the platform
   rather than from hand-written key handling. */

.lightbox {
  width: 100vw;
  max-width: 100vw;
  height: 100dvh;
  max-height: 100dvh;
  margin: 0;
  padding: 0;
  border: 0;
  background: rgba(8, 20, 12, 0.96);
  color: var(--chalk);
  overflow: hidden;
}
.lightbox::backdrop { background: rgba(8, 20, 12, 0.9); }

.lightbox__figure {
  margin: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: clamp(1rem, 4vw, 3rem);
}

.lightbox__img {
  /* flex-shrink with min-height:0 is what actually lets the image give up
     space for the caption; a percentage max-height alone does not resolve
     against an indefinite track and the caption gets pushed off screen. */
  flex: 0 1 auto;
  min-height: 0;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
}

.lightbox__cap {
  flex: 0 0 auto;
  font-family: var(--mono);
  font-size: 0.75rem;
  line-height: 1.6;
  letter-spacing: 0.02em;
  color: var(--chalk-dim);
  text-align: center;
  max-width: 46rem;
  display: grid;
  gap: 0.15rem;
}
.lightbox__when { color: var(--dusk); }
.lightbox__count { opacity: 0.6; }

.lightbox__close,
.lightbox__nav {
  position: absolute;
  z-index: 2;
  min-width: 48px;
  min-height: 48px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid color-mix(in srgb, var(--chalk) 35%, transparent);
  background: rgba(8, 20, 12, 0.7);
  color: var(--chalk);
  font-family: var(--mono);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
  transition: background 0.2s, border-color 0.2s;
}
.lightbox__close:hover,
.lightbox__nav:hover { background: var(--turf-lift); border-color: var(--chalk); }
.lightbox__close:focus-visible,
.lightbox__nav:focus-visible { outline: 2px solid var(--dusk); outline-offset: 3px; }

.lightbox__close { top: clamp(0.75rem, 2vw, 1.5rem); right: clamp(0.75rem, 2vw, 1.5rem); }
.lightbox__nav { top: 50%; transform: translateY(-50%); }
.lightbox__nav--prev { left: clamp(0.5rem, 2vw, 1.5rem); }
.lightbox__nav--next { right: clamp(0.5rem, 2vw, 1.5rem); }

@media (max-width: 560px) {
  /* Thumb-reachable on a phone: side arrows sit low rather than mid-screen. */
  .lightbox__nav { top: auto; bottom: clamp(0.75rem, 3vw, 1.5rem); transform: none; }
}

/* ── Floating call to action ─────────────────────────────────────────────
   Shown only between the end of the hero and the start of the action band —
   before that the hero's own button is on screen, after that it would sit on
   top of the thing it points at. Same label as the hero button, because it is
   the same action. */

.fab {
  position: fixed;
  z-index: 45;
  right: clamp(1rem, 2.5vw, 2.5rem);
  bottom: clamp(1rem, 2.5vw, 2.5rem);
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.85rem 1.5rem;
  min-height: 56px;
  justify-content: center;
  background: var(--stake);
  color: #fff;
  text-decoration: none;
  box-shadow: 0 6px 28px rgba(0, 0, 0, 0.4);

  opacity: 0;
  visibility: hidden;          /* also drops it out of the tab order */
  transform: translateY(0.75rem);
  transition: opacity 0.28s ease, transform 0.28s ease, visibility 0.28s;
}

.fab.is-on {
  opacity: 1;
  visibility: visible;
  transform: none;
}

.fab:hover { background: #f26a41; }
.fab:focus-visible { outline: 2px solid var(--dusk); outline-offset: 3px; }

.fab__label {
  font-family: var(--mono);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1.2;
}

.fab__hint {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.06em;
  opacity: 0.82;
  line-height: 1.2;
}

@media (max-width: 860px) {
  /* Full-width bar on a phone, clearing the 3px scroll rail at the bottom. */
  .fab {
    right: 0;
    left: 0;
    bottom: 0;
    flex-direction: row;
    align-items: baseline;
    justify-content: center;
    gap: 0.6rem;
    padding: 1rem 1.25rem;
    min-height: 60px;
    transform: translateY(100%);
    box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.35);
  }
  .fab.is-on { transform: none; }
  .fab__hint { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .fab { transition: opacity 0.01ms, visibility 0.01ms; transform: none; }
  .fab.is-on { transform: none; }
}

/* ── Back to top ─────────────────────────────────────────────────────────
   Appears on upward scroll once you are well down the page — scrolling back
   up is the signal that you want it. */

.totop {
  position: fixed;
  z-index: 46;
  right: clamp(1rem, 2.5vw, 2.5rem);
  bottom: clamp(1rem, 2.5vw, 2.5rem);
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid color-mix(in srgb, var(--chalk) 40%, transparent);
  background: rgba(11, 29, 17, 0.88);
  backdrop-filter: blur(6px);
  color: var(--chalk);
  cursor: pointer;

  opacity: 0;
  visibility: hidden;
  transform: translateY(0.5rem);
  transition: opacity 0.24s ease, transform 0.24s ease, visibility 0.24s,
              background 0.2s, border-color 0.2s;
}

.totop.is-on { opacity: 1; visibility: visible; transform: none; }
.totop:hover { background: var(--turf-lift); border-color: var(--chalk); }
.totop:focus-visible { outline: 2px solid var(--dusk); outline-offset: 3px; }

/* Sit above the action button whenever that one is also on screen. The FAB
   precedes this element in the DOM, so a sibling selector keeps the two
   positions in sync without any JavaScript coordinating them. */
.fab.is-on ~ .totop { bottom: calc(clamp(1rem, 2.5vw, 2.5rem) + 56px + 0.6rem); }

@media (max-width: 860px) {
  .totop { bottom: 1rem; }
  .fab.is-on ~ .totop { bottom: calc(60px + 1rem); }
}

@media (prefers-reduced-motion: reduce) {
  .totop { transition: opacity 0.01ms, visibility 0.01ms; transform: none; }
  .totop.is-on { transform: none; }
}

/* ── Footer ─────────────────────────────────────────────────────────────── */

.foot {
  background: var(--turf-deep);
  padding: clamp(3rem, 6vw, 5rem) var(--gutter);
  font-family: var(--mono);
  font-size: 0.6875rem;
  line-height: 1.8;
  letter-spacing: 0.03em;
  color: var(--chalk-dim);
}
.foot__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
  gap: 2rem;
  max-width: 72rem;
  margin-inline: auto;
}
.foot strong { color: var(--chalk); display: block; margin-bottom: 0.5rem; font-weight: 500; }
/* 11px mono links are a 15px-tall target. WCAG 2.2 (2.5.8) wants 24px minimum
   with a pointer, so pad them everywhere rather than only on touch widths. */
.foot a {
  color: var(--chalk);
  display: inline-block;
  min-height: 24px;
  padding: 0.35rem 0;
}

/* ── Phones ─────────────────────────────────────────────────────────────── */

@media (max-width: 860px) {
  /* Nothing on a phone should be smaller than this and still be worth reading. */
  .gallery figcaption { font-size: 0.75rem; line-height: 1.5; }
  .plate figcaption,
  .entry__source,
  .receipt__source,
  .pull figcaption,
  .hero__credit { font-size: 0.75rem; }
  .tag { font-size: 0.6875rem; }
  .foot { font-size: 0.75rem; line-height: 1.75; }

  /* One column of gallery cards at true phone widths reads better than two
     cropped squares. */
  .gallery { grid-template-columns: repeat(auto-fill, minmax(min(13rem, 100%), 1fr)); }

  /* Clear the fixed action bar so the last line of the footer is readable. */
  .foot { padding-bottom: calc(clamp(3rem, 6vw, 5rem) + 60px); }

  .btn { width: 100%; justify-content: center; }
  .hero__actions { gap: 0.6rem; }
  .hero__actions .btn { width: auto; flex: 1 1 12rem; }

  /* Touch widths take the larger 44px target. */
  .foot a { display: flex; align-items: center; min-height: 44px; }
}

@media (max-width: 420px) {
  .receipt { padding: 1.5rem 1.25rem; }
  .entry__meta { display: flex; align-items: baseline; gap: 0.75rem; flex-wrap: wrap; }
  .tag { margin-top: 0; }
}
