/* Zombie A.C.R.E.S. — v2: drive-in poster horror.
   Bebas Neue for display type, Special Elite (typewriter) for labels,
   system sans for body. Palette: near-black, bone, blood, toxic green. */

:root {
  --bg: #0a0a08;
  --bg-deep: #050504;
  --bg-panel: #141410;
  --bg-panel-2: #1b1b13;
  --bone: #e8e3d3;
  --bone-dim: #b8b2a0;
  --blood: #b3202a;
  --blood-bright: #e03540;
  --toxic: #7fae3f;
  --toxic-bright: #a4d65e;
  --line: #2c2c22;
  --maxw: 68rem;
  --font-display: "Bebas Neue", "Arial Narrow", "Franklin Gothic Medium", sans-serif;
  --font-type: "Special Elite", "Courier New", Courier, monospace;
}

* { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: 4.75rem;
}

body {
  margin: 0;
  background:
    radial-gradient(ellipse 80% 50% at 50% -10%, rgba(127, 174, 63, 0.07), transparent 60%),
    radial-gradient(ellipse 60% 40% at 50% 110%, rgba(179, 32, 42, 0.05), transparent 60%),
    var(--bg);
  color: var(--bone);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 1.0625rem;
  line-height: 1.65;
  overflow-x: hidden;
}

/* Film grain — a faint dot-register over everything, like old stock. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 90;
  pointer-events: none;
  background-image:
    radial-gradient(rgba(232, 227, 211, 0.05) 1px, transparent 1.4px),
    radial-gradient(rgba(0, 0, 0, 0.16) 1px, transparent 1.4px);
  background-size: 3px 3px, 5px 5px;
  background-position: 0 0, 2px 3px;
  opacity: 0.55;
}

/* Vignette — the edges of the frame fall off into black. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 89;
  pointer-events: none;
  background: radial-gradient(ellipse 105% 90% at 50% 45%, transparent 58%, rgba(0, 0, 0, 0.5) 100%);
}

::selection { background: var(--blood); color: #fff; }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--blood);
  color: #fff;
  padding: 0.5rem 1rem;
  z-index: 100;
}
.skip-link:focus { left: 0; }

a { color: var(--toxic-bright); }
a:hover, a:focus { color: var(--blood-bright); }
a:focus-visible, .btn:focus-visible {
  outline: 2px solid var(--toxic-bright);
  outline-offset: 2px;
}

h3 { line-height: 1.25; }

/* ---------- Header / nav ---------- */
.site-header {
  position: sticky;
  top: 0;
  background: rgba(5, 5, 4, 0.92);
  border-bottom: 1px solid var(--line);
  backdrop-filter: blur(4px);
  z-index: 50;
}
.nav {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0.55rem 1rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem 1.5rem;
}
.nav-brand {
  font-family: var(--font-display);
  color: var(--bone);
  font-size: 1.55rem;
  letter-spacing: 0.08em;
  text-decoration: none;
  text-transform: uppercase;
  padding-top: 0.2rem;
  /* v4.2: the sign over the gate has a loose wire — one brief flicker
     inside a long 11s cycle, opacity only. Off under reduced motion. */
  animation: brand-flicker 11s linear infinite;
}
@keyframes brand-flicker {
  0%, 61.9% { opacity: 1; }
  62.4% { opacity: 0.45; }
  62.9% { opacity: 1; }
  63.5% { opacity: 0.7; }
  64.1%, 100% { opacity: 1; }
}
.nav-brand:hover { color: var(--blood-bright); }
.nav-links {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1.1rem;
}
.nav-links a {
  color: var(--bone-dim);
  text-decoration: none;
  font-size: 0.92rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.nav-links a:hover, .nav-links a:focus { color: var(--toxic-bright); }

/* ---------- Hero — full-bleed poster ---------- */
.hero {
  position: relative;
  min-height: min(96vh, 62rem);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  text-align: center;
  overflow: hidden;
  padding: 7rem 1rem 4rem;
}
.hero-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 35%;
}
/* Dark grade over the art, dissolving into fog and page-black at the bottom. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(180deg, rgba(5, 5, 4, 0.62) 0%, rgba(5, 5, 4, 0.18) 34%, rgba(5, 5, 4, 0.30) 58%, rgba(10, 10, 8, 0.90) 84%, var(--bg) 100%);
}
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    radial-gradient(ellipse 95% 34% at 50% 90%, rgba(196, 208, 178, 0.13), transparent 70%),
    radial-gradient(ellipse 60% 22% at 22% 96%, rgba(127, 174, 63, 0.10), transparent 70%);
}
.hero-inner {
  position: relative;
  z-index: 2;
  max-width: 62rem;
}
.hero-kicker {
  font-family: var(--font-type);
  color: var(--toxic-bright);
  letter-spacing: 0.14em;
  font-size: 0.95rem;
  margin: 0 0 0.6rem;
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.9);
}
.hero h1 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(4.2rem, 15vw, 11rem);
  line-height: 0.92;
  margin: 0;
  text-transform: uppercase;
  letter-spacing: 0.015em;
  color: var(--bone);
  text-shadow:
    0 0 34px rgba(179, 32, 42, 0.45),
    0 0 90px rgba(0, 0, 0, 0.65),
    0 4px 0 rgba(0, 0, 0, 0.55),
    0 10px 34px rgba(0, 0, 0, 0.85);
}
.hero-acronym {
  font-family: var(--font-type);
  color: var(--bone);
  font-size: clamp(0.95rem, 2.6vw, 1.25rem);
  letter-spacing: 0.1em;
  margin: 0.9rem 0 1.3rem;
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.95);
}
.hero-lede {
  max-width: 42rem;
  margin: 0 auto 2rem;
  color: var(--bone);
  font-size: 1.12rem;
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.95), 0 0 26px rgba(0, 0, 0, 0.7);
}
.hero-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
  justify-content: center;
  margin: 0 0 1.1rem;
}
.hero-note {
  font-family: var(--font-type);
  color: var(--bone-dim);
  margin: 0;
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.95);
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-block;
  font-family: var(--font-display);
  font-size: 1.22rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 0.62rem 1.7rem 0.45rem;
  border: 1px solid var(--line);
  border-radius: 3px;
  transition: transform 0.08s ease, background 0.15s ease, color 0.15s ease;
}
.btn:hover { transform: translateY(-1px); }
.btn-blood {
  background: linear-gradient(180deg, #c22a33, var(--blood));
  color: #fff;
  border-color: #6d1218;
  box-shadow: 0 8px 26px rgba(0, 0, 0, 0.55);
}
.btn-blood:hover, .btn-blood:focus { background: var(--blood-bright); color: #fff; }
.btn-bone {
  background: rgba(20, 20, 16, 0.88);
  color: var(--bone);
  border-color: #3a3a2c;
  box-shadow: 0 8px 26px rgba(0, 0, 0, 0.55);
}
.btn-bone:hover, .btn-bone:focus { color: var(--toxic-bright); border-color: var(--toxic); }
.btn-small { font-size: 1.05rem; padding: 0.5rem 1.15rem 0.32rem; }

/* ---------- Layout / sections ---------- */
.section {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 3rem 1rem;
}

/* Section headers are weathered signs: a nailed-up plank, hung slightly crooked. */
.section h2 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.7rem, 6.5vw, 4.1rem);
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: 0.045em;
  color: var(--bone);
  display: inline-block;
  position: relative;
  margin: 0 0 1.4rem;
  padding: 0.34em 0.65em 0.16em;
  background:
    linear-gradient(180deg, rgba(232, 227, 211, 0.045), rgba(0, 0, 0, 0.22)),
    linear-gradient(180deg, #20201a, #12120d);
  border: 1px solid #34342a;
  border-left: 7px solid var(--toxic);
  border-radius: 2px;
  box-shadow: 0 14px 30px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(232, 227, 211, 0.07);
  transform: rotate(-1.3deg);
  transform-origin: left center;
}
.section h2::before,
.section h2::after {
  content: "";
  position: absolute;
  top: 0.45rem;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #55554a, #1b1b15 75%);
  box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.9);
}
.section h2::before { left: 0.5rem; }
.section h2::after { right: 0.5rem; }
/* Alternate sign edges: blood for the rooms that bite. */
#books h2, #world h2, #elsewhere h2 { border-left-color: var(--blood); }
#books h2, #shop h2 { transform: rotate(1.1deg); transform-origin: right center; }

.section-lede { color: var(--bone-dim); max-width: 44rem; margin-top: 0.2rem; }

/* Fog bank between sections — the corn only survives in the kickers now. */
.fog {
  height: 5.5rem;
  max-width: var(--maxw);
  margin: 0 auto;
  background:
    radial-gradient(ellipse 55% 90% at 50% 55%, rgba(196, 208, 178, 0.075), transparent 70%),
    radial-gradient(ellipse 34% 70% at 26% 60%, rgba(127, 174, 63, 0.06), transparent 70%),
    radial-gradient(ellipse 38% 75% at 74% 45%, rgba(232, 227, 211, 0.05), transparent 70%);
  filter: blur(1px);
  user-select: none;
}

/* ---------- Cards ---------- */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: 1.2rem;
  margin-top: 1.6rem;
}
.card {
  background:
    linear-gradient(180deg, rgba(232, 227, 211, 0.035), rgba(0, 0, 0, 0.18)),
    linear-gradient(180deg, var(--bg-panel-2), var(--bg-panel));
  border: 1px solid var(--line);
  border-top: 3px solid var(--toxic);
  border-radius: 3px;
  padding: 1.4rem 1.3rem 1.2rem;
  display: flex;
  flex-direction: column;
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.45);
}
.card-featured { border-top-color: var(--blood); }
.card h3 {
  font-family: Georgia, "Times New Roman", Times, serif;
  margin: 0.35rem 0 0.7rem;
  font-size: 1.35rem;
  color: var(--bone);
}
.card-sub { font-size: 1.05rem; color: var(--bone-dim); font-weight: normal; }
.card p { margin: 0 0 0.9rem; color: var(--bone); }
.card-tag {
  font-family: var(--font-type);
  color: var(--toxic-bright);
  font-size: 0.82rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  margin: 0;
}
.card-featured .card-tag { color: var(--blood-bright); }
.card-links { margin-top: auto; }
.card-alt {
  display: block;
  margin-top: 0.6rem;
  color: var(--bone-dim);
  font-size: 0.92rem;
  font-style: italic;
}

/* The Library: the saga gets the big shelf. */
@media (min-width: 62rem) {
  .book-grid { grid-template-columns: 1.65fr 1fr 1fr; align-items: stretch; }
  .book-grid .card-featured { padding: 2rem 1.9rem 1.6rem; }
  .book-grid .card-featured h3 { font-size: 2.05rem; }
  .book-grid .card-featured p { font-size: 1.09rem; }
}

/* ---------- Inside the Acres — the gates ---------- */
.section-world { position: relative; z-index: 0; }
.section-world::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100vw;
  z-index: -1;
  background:
    linear-gradient(180deg, var(--bg) 0%, rgba(10, 10, 8, 0.55) 14%, rgba(10, 10, 8, 0.62) 86%, var(--bg) 100%),
    url("images/acres-gates.webp") center 42% / cover no-repeat,
    #0d0d0a;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.world-panel {
  background: rgba(8, 8, 6, 0.82);
  border: 1px solid var(--line);
  border-left: 4px solid var(--blood);
  border-radius: 3px;
  padding: 1.6rem 1.7rem 1.2rem;
  max-width: 46rem;
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(2px);
}
.world-panel p { margin: 0 0 1rem; }
.world-hook {
  font-family: Georgia, "Times New Roman", Times, serif;
  font-style: italic;
  font-size: 1.3rem;
  color: var(--blood-bright);
  margin-bottom: 0.4rem !important;
}

/* ---------- Shop ---------- */
.shop-status {
  font-family: var(--font-type);
  font-size: 1.15rem;
  letter-spacing: 0.02em;
  color: var(--bone);
  background: var(--bg-panel);
  border: 1px dashed var(--toxic);
  border-radius: 3px;
  padding: 1rem 1.2rem;
  max-width: 46rem;
}
.shop-routes { max-width: 46rem; padding-left: 1.2rem; }
.shop-routes li { margin-bottom: 0.8rem; }

/* ---------- About ---------- */
#about p { max-width: 46rem; }

/* ---------- Link hub ---------- */
.link-list {
  list-style: none;
  margin: 1.4rem 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: 1rem;
}
.link-list a {
  display: block;
  height: 100%;
  background:
    linear-gradient(180deg, rgba(232, 227, 211, 0.03), rgba(0, 0, 0, 0.16)),
    var(--bg-panel);
  border: 1px solid var(--line);
  border-left: 3px solid var(--toxic);
  border-radius: 3px;
  padding: 1rem 1.1rem;
  text-decoration: none;
  box-shadow: 0 10px 22px rgba(0, 0, 0, 0.4);
}
.link-list a:hover, .link-list a:focus { border-left-color: var(--blood); background: var(--bg-panel-2); }
.link-name {
  display: block;
  font-family: var(--font-display);
  font-size: 1.32rem;
  letter-spacing: 0.055em;
  text-transform: uppercase;
  padding-top: 0.15rem;
  color: var(--bone);
}
.link-list a:hover .link-name { color: var(--toxic-bright); }
.link-desc { display: block; color: var(--bone-dim); font-size: 0.94rem; margin-top: 0.25rem; }

/* ---------- Footer ---------- */
.site-footer {
  border-top: 1px solid var(--line);
  margin-top: 2rem;
  padding: 2.4rem 1rem 2.8rem;
  text-align: center;
  color: var(--bone-dim);
  background:
    radial-gradient(ellipse 70% 100% at 50% 0%, rgba(127, 174, 63, 0.05), transparent 65%),
    linear-gradient(180deg, transparent, rgba(179, 32, 42, 0.06));
}
.footer-brand {
  font-family: var(--font-display);
  color: var(--bone);
  font-size: 1.7rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  margin: 0 0 0.6rem;
}
.site-footer p { margin: 0.25rem 0; }
.footer-note { font-family: var(--font-type); }

/* ---------- Trailer Park — the drive-in lot ---------- */
.section-park { position: relative; z-index: 0; padding-top: 4.2rem; padding-bottom: 3.6rem; }
/* The lot: deeper black than anywhere else on the page. */
.section-park::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100vw;
  z-index: -1;
  background:
    radial-gradient(ellipse 75% 46% at 50% 0%, rgba(127, 174, 63, 0.06), transparent 65%),
    linear-gradient(180deg, #070706, var(--bg-deep) 22%, var(--bg-deep) 82%, #070706);
  border-top: 1px solid #1e1e15;
  border-bottom: 1px solid #1e1e15;
}
/* String lights strung across the top of the lot. */
.section-park::after {
  content: "";
  position: absolute;
  top: 0.65rem;
  left: 50%;
  transform: translateX(-50%);
  width: 100vw;
  height: 30px;
  pointer-events: none;
  background-image:
    radial-gradient(circle at 16px 12px, rgba(232, 227, 211, 0.95) 0 3px, rgba(232, 227, 211, 0.20) 7px, transparent 12px),
    radial-gradient(circle at 16px 18px, rgba(164, 214, 94, 0.9) 0 3px, rgba(164, 214, 94, 0.18) 7px, transparent 12px),
    radial-gradient(circle at 16px 12px, rgba(224, 53, 64, 0.9) 0 3px, rgba(224, 53, 64, 0.18) 7px, transparent 12px);
  background-size: 144px 30px;
  background-repeat: repeat-x;
  background-position: 0 0, 48px 0, 96px 0;
  opacity: 0.9;
}
.trailer-feature { margin-top: 1.6rem; }
.trailer-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: 1.2rem;
  margin-top: 1.2rem;
}
/* Screens glow like projected light. */
.trailer-slot {
  aspect-ratio: 16 / 9;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  background:
    radial-gradient(ellipse 72% 92% at 50% 42%, rgba(232, 227, 211, 0.09), transparent 72%),
    linear-gradient(180deg, #131309, #060604);
  border: 1px solid #38382a;
  border-top: 3px solid var(--blood);
  border-radius: 3px;
  padding: 0.55rem;
  box-shadow:
    0 0 34px rgba(232, 227, 211, 0.13),
    0 0 90px rgba(127, 174, 63, 0.10),
    0 22px 44px rgba(0, 0, 0, 0.65);
}
.trailer-feature .trailer-slot {
  box-shadow:
    0 0 52px rgba(232, 227, 211, 0.17),
    0 0 130px rgba(127, 174, 63, 0.13),
    0 26px 54px rgba(0, 0, 0, 0.7);
}
.trailer-slot iframe {
  width: 100%;
  height: 100%;
  border: 0;
  border-radius: 2px;
}
.trailer-caption {
  color: var(--bone-dim);
  font-size: 0.96rem;
  font-style: italic;
  margin: 0.65rem 0 0;
}
.trailer-caption strong { color: var(--bone); }
.trailer-submit { max-width: 46rem; margin-top: 1.5rem; }

/* ---------- Small screens ---------- */
@media (max-width: 36rem) {
  .hero { min-height: 88vh; padding: 5rem 1rem 3rem; }
  .hero-buttons .btn { width: 100%; text-align: center; }
  .nav { justify-content: center; text-align: center; }
  .nav-links { justify-content: center; }
  .section h2 { transform: rotate(-1deg); }
  .world-panel { padding: 1.2rem 1.1rem 0.9rem; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .btn { transition: none; }
  .nav-brand { animation: none; }
}

/* ================= v3/v4 — the cul-de-sac (multi-page, enterable stage) ================= */

/* Current page in the nav. */
.nav-links a[aria-current="page"] { color: var(--toxic-bright); }

/* Homepage header: a slim bar floating over the stage — on the homepage
   the neighborhood is the first thing you meet, not a wall of nav.
   Inner pages keep the standard sticky header.
   v4.1 pattern: the brand NEVER wraps (flex: none + nowrap, clamp-sized)
   and the links live in a single horizontally scrollable strip whose
   items never shrink (li { flex: none }) — nothing clips mid-word.
   min-width: 0 on the strip is what lets it actually scroll instead of
   pushing past the screen edge.
   v4.2 hardening: at ≤40rem the layout is a COLUMN BY STRUCTURE — the
   brand is a block-level flex item alone on its row and the strip gets
   its own full-width row beneath it, fully specified in the media
   query below (nothing left to cascade luck). The wrapped-brand /
   clipped-nav failure cannot occur: the brand has no inline sibling
   to squeeze against, nowrap forbids a break, and the strip scrolls
   horizontally instead of overflowing. (v4.1's phone test still
   rendered the v4 header because the phone had heuristically cached
   the old stylesheet — hence the ?v= stamps on every page, see
   README.) */
.home .site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  background: linear-gradient(180deg, rgba(5, 5, 4, 0.9), rgba(5, 5, 4, 0.52) 72%, rgba(5, 5, 4, 0));
  border-bottom: none;
  backdrop-filter: blur(3px);
}
.home .nav {
  max-width: none;
  flex-wrap: nowrap;
  padding: 0.4rem 0.9rem;
  gap: 0.4rem 1rem;
}
.home .nav-brand {
  flex: none;
  white-space: nowrap;
  font-size: clamp(1.02rem, 4.6vw, 1.3rem);
}
.home .nav-links {
  flex: 1 1 auto;
  min-width: 0;
  flex-wrap: nowrap;
  justify-content: flex-start;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  /* A fade at the strip's right edge hints it scrolls. */
  mask-image: linear-gradient(90deg, #000 93%, transparent);
  -webkit-mask-image: linear-gradient(90deg, #000 93%, transparent);
}
.home .nav-links::-webkit-scrollbar { display: none; }
.home .nav-links li { flex: none; }
.home .nav-links a { font-size: 0.8rem; white-space: nowrap; }
@media (max-width: 40rem) {
  /* Column by structure, fully specified: brand row on top (block,
     nowrap, left-aligned, sized by the .home clamp), then the strip
     on its own full-width row — single line, items never shrink,
     horizontal scroll with the scrollbar hidden. */
  .home .nav {
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: stretch;
    justify-content: flex-start;
    gap: 0.15rem;
    padding-bottom: 0.6rem;
  }
  .home .nav-brand {
    display: block;
    flex: none;
    align-self: flex-start;
    white-space: nowrap;
    text-align: left;
  }
  .home .nav-links {
    flex: 0 0 auto;
    width: 100%;
    min-width: 0;
    flex-wrap: nowrap;
    justify-content: flex-start;
    overflow-x: auto;
  }
}

/* ---------- Fog intro (homepage only) ----------
   The layer is INVISIBLE and inert by default — with no JS there is no fog
   at all. The head script adds .fog-pending to <html> before first paint
   (and skips it entirely under prefers-reduced-motion), which raises the
   fog; the body script then adds .fog-cleared to lift it. */
.fog-intro {
  position: fixed;
  inset: 0;
  z-index: 80;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 3s ease, visibility 0s linear 3.1s;
  background:
    radial-gradient(ellipse 90% 70% at 25% 30%, rgba(233, 238, 222, 0.92), transparent 70%),
    radial-gradient(ellipse 90% 75% at 75% 65%, rgba(212, 222, 196, 0.92), transparent 70%),
    radial-gradient(ellipse 120% 95% at 50% 50%, rgba(196, 208, 178, 0.88), transparent 78%),
    linear-gradient(180deg, #c6d0b4, #a3b28f);
}
/* Two soft banks drift while the fog sits — the only motion in the intro. */
.fog-intro::before,
.fog-intro::after {
  content: "";
  position: absolute;
  inset: -12%;
  background:
    radial-gradient(ellipse 45% 32% at 30% 45%, rgba(242, 246, 232, 0.55), transparent 70%),
    radial-gradient(ellipse 40% 30% at 68% 60%, rgba(228, 235, 216, 0.5), transparent 70%);
  animation: fog-drift 24s ease-in-out infinite alternate;
}
.fog-intro::after { animation-duration: 33s; animation-direction: alternate-reverse; opacity: 0.7; }
@keyframes fog-drift {
  from { transform: translateX(-2.5%); }
  to   { transform: translateX(2.5%); }
}
html.fog-pending .fog-intro {
  opacity: 1;
  visibility: visible;
  /* Blocks stray clicks for the few seconds the fog is up; the first tap
     anywhere skips the intro, and pointer-events is none once it clears. */
  pointer-events: auto;
  transition: opacity 0.3s ease, visibility 0s;
}
.fog-intro.fog-cleared {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

/* ---------- The cul-de-sac stage (homepage) ----------
   A full-viewport stage you step INTO, not a banner you scroll past.
   The painting lives in .stage-world; enter.js renders it larger than
   the stage and pans/zooms it with a transform. Without JS (or under
   reduced motion) .enter-on is never added: the world fits the page
   width, the painting shows whole, and the houses are plain links. */
.stage {
  position: relative;
  overflow: hidden;
  background: var(--bg-deep);
  touch-action: pan-y; /* vertical swipes scroll on; horizontal drags look around */
  -webkit-user-select: none;
  user-select: none;
}
.stage.enter-on { height: 100vh; height: 100dvh; cursor: grab; }
.stage.enter-on:active { cursor: grabbing; }
.stage-world { position: relative; }
.stage.enter-on .stage-world {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
  will-change: transform;
}
.stage-world.zooming { transition: transform 0.82s cubic-bezier(0.25, 0.6, 0.2, 1); }
/* Legibility shade at the top; the street melts into the page at the bottom. */
.stage::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background:
    linear-gradient(180deg, rgba(5, 5, 4, 0.45) 0%, transparent 22%),
    linear-gradient(0deg, var(--bg) 0%, transparent 13%);
}
.scene-img { display: block; width: 100%; height: auto; }
.stage.enter-on .scene-img { height: 100%; }

/* Ambient fog — banks of mist drifting over the lower streets, forever.
   They live inside the world, so they pan and zoom with the painting.
   v4.1: retuned after "no fog moves" on a real phone — the travel is
   now ±6–7.5% of a 150%-wide bank (well over 100px on the rendered
   world), the cycles are 30–45s, the mist runs denser, and every bank
   BREATHES (opacity rides the same keyframes), so the motion registers
   within seconds even where a bank is thin. Transform/opacity only.
   Per-bank class opacity is the no-animation fallback value. */
.fog-bank {
  position: absolute;
  left: -25%;
  width: 150%;
  z-index: 1;
  pointer-events: none;
}
.fog-bank-1 {
  top: 46%; height: 36%; opacity: 0.8;
  background:
    radial-gradient(ellipse 52% 88% at 30% 50%, rgba(226, 234, 214, 0.64), transparent 70%),
    radial-gradient(ellipse 42% 82% at 72% 45%, rgba(196, 208, 178, 0.54), transparent 70%);
  animation: bank-drift-a 30s ease-in-out infinite alternate;
}
.fog-bank-2 {
  top: 58%; height: 30%; opacity: 0.75;
  background:
    radial-gradient(ellipse 48% 88% at 62% 50%, rgba(232, 227, 211, 0.56), transparent 70%),
    radial-gradient(ellipse 36% 80% at 20% 55%, rgba(196, 208, 178, 0.5), transparent 70%);
  animation: bank-drift-b 38s ease-in-out infinite alternate;
}
.fog-bank-3 {
  top: 70%; height: 29%; opacity: 0.85;
  background:
    radial-gradient(ellipse 56% 92% at 45% 50%, rgba(233, 240, 222, 0.66), transparent 72%);
  animation: bank-drift-a 45s ease-in-out infinite alternate-reverse;
}
@keyframes bank-drift-a {
  from { transform: translateX(-7.5%); opacity: 0.45; }
  to   { transform: translateX(7.5%);  opacity: 0.85; }
}
@keyframes bank-drift-b {
  from { transform: translateX(6%);  opacity: 0.8; }
  to   { transform: translateX(-6%); opacity: 0.45; }
}

/* Stage fog — one wide mist band FIXED TO THE STAGE, not the world
   (a sibling of .stage-world), so it drifts through the frame no
   matter where the world is panned. It paints above the world unit
   (the transformed world is a single stacking context, so a stage
   layer softens the whole frame equally — signs stay readable
   through it) and below the hint and the door veil. A second, slower
   sheet rides in ::before for depth. Transform/opacity only.
   v4.2: the band drops to STREET level (top 52%, height 46%) — in
   v4.1 it sat at 34% and read on a phone as a gray smudge across the
   moon. Colors are the site's pale mist palette only (the
   rgba(196,208,178,…) family + bone tints — never dark gray), the
   gradient falloff is longer (82%), a light blur softens the edges,
   and the sweep widens to ±11% of the 160%-wide band so the drift
   is unmistakable within seconds. */
.fog-stage {
  position: absolute;
  top: 52%;
  left: -30%;
  width: 160%;
  height: 46%;
  z-index: 2;
  pointer-events: none;
  opacity: 0.65;
  filter: blur(7px);
  background:
    radial-gradient(ellipse 44% 78% at 26% 55%, rgba(226, 234, 214, 0.6), transparent 82%),
    radial-gradient(ellipse 40% 72% at 68% 45%, rgba(196, 208, 178, 0.5), transparent 82%);
  animation: stage-fog-drift 30s ease-in-out infinite alternate;
}
.fog-stage::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 36% 64% at 52% 60%, rgba(232, 227, 211, 0.5), transparent 82%),
    radial-gradient(ellipse 32% 58% at 88% 40%, rgba(206, 218, 188, 0.42), transparent 82%);
  animation: stage-fog-slide 38s ease-in-out infinite alternate-reverse;
}
@keyframes stage-fog-drift {
  from { transform: translateX(-11%); opacity: 0.45; }
  to   { transform: translateX(11%);  opacity: 0.8; }
}
@keyframes stage-fog-slide {
  from { transform: translateX(7%); }
  to   { transform: translateX(-7%); }
}

/* ---------- Ambience (v4.2) — the street is occupied ----------
   Both layers are gated on .enter-on, which only enter.js adds (and
   never under prefers-reduced-motion): with JS off they simply do
   not exist. Transform/opacity only. To disable either, delete its
   animation line (or the element in index.html). */

/* A resident crosses the far street. The wrapper spans the whole
   world, so its translateX sweep carries the little figure at its
   left edge from one end of the painting to the other. One crossing
   (~14s of the 36s cycle), then the street is empty again. The
   figure bobs as it shambles; the reaching arm sways. It rides
   inside the world (pans/zooms with the painting), under the
   houses' signs (hotspots are z-index 2), and never takes a tap. */
.wanderer {
  display: none;
  position: absolute;
  top: 29.5%;
  left: 0;
  width: 100%;
  height: 4.6%;
  z-index: 1;
  pointer-events: none;
}
.stage.enter-on .wanderer {
  display: block;
  animation: wander-cross 36s linear infinite;
}
.wanderer-fig {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: auto;
  fill: rgba(8, 9, 7, 0.82);
  animation: wander-bob 0.85s ease-in-out infinite alternate;
}
.wanderer-arm {
  transform-box: fill-box;
  transform-origin: 15% 15%;
  animation: wander-sway 1.7s ease-in-out infinite alternate;
}
@keyframes wander-cross {
  0%       { transform: translateX(-4%);  opacity: 0; }
  4%       { opacity: 1; }
  40%      { transform: translateX(103%); opacity: 1; }
  44%, 100% { transform: translateX(103%); opacity: 0; }
}
@keyframes wander-bob {
  from { transform: translateY(0) rotate(-1deg); }
  to   { transform: translateY(-7%) rotate(1.2deg); }
}
@keyframes wander-sway {
  from { transform: rotate(-6deg); }
  to   { transform: rotate(9deg); }
}

/* Distant lightning — heat lightning over the desert, far away.
   A 47s cycle that is dark for ~89% of its length, then a pale
   green-white double-flicker (peak opacity 0.14) and gone. The
   flash window is under 2% of the cycle. */
.lightning {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(ellipse 130% 95% at 50% -10%, rgba(233, 242, 220, 0.95), rgba(198, 222, 180, 0.4) 55%, transparent 78%);
}
.stage.enter-on .lightning { animation: lightning-cycle 47s linear infinite; }
@keyframes lightning-cycle {
  0%, 88.9%   { opacity: 0; }
  89.4%       { opacity: 0.13; }
  89.8%       { opacity: 0.02; }
  90.2%       { opacity: 0.14; }
  90.7%, 100% { opacity: 0; }
}

/* The way in, written on the fog at the bottom of the stage. */
.stage-hint {
  display: none; /* only true once enter.js has made the street pannable */
  position: absolute;
  left: 0;
  right: 0;
  bottom: 1.05rem;
  z-index: 3;
  margin: 0;
  padding: 0 1rem;
  text-align: center;
  font-family: var(--font-type);
  font-size: 0.92rem;
  letter-spacing: 0.06em;
  color: var(--bone);
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.95), 0 0 24px rgba(0, 0, 0, 0.8);
  pointer-events: none;
}
.stage.enter-on .stage-hint { display: block; }

/* Mist that thickens for a breath as you step through a door. */
.fog-veil {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.8s ease;
  background:
    radial-gradient(ellipse 95% 72% at 50% 62%, rgba(226, 234, 214, 0.5), transparent 75%),
    linear-gradient(180deg, rgba(196, 208, 178, 0.16), rgba(196, 208, 178, 0.38));
}
.stage.entering .fog-veil { opacity: 1; }

/* Screen-reader/SEO only — the homepage's one H1 lives here. v4.1
   removed the painted title overlay from the stage (it duplicated the
   header and stranded stray words over the art in the mobile crop);
   the stage shows painting, doors, fog, and the hint line only. */
.visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Houses you can knock on. The box follows the painted house; the sign
   hangs over the door; hover/focus is a porch light switching on. */
.hotspot {
  position: absolute;
  z-index: 2;
  display: block;
  border-radius: 6px;
  text-decoration: none;
  transition: box-shadow 0.25s ease, background 0.25s ease;
}
/* The porch light is already on: a warm glow breathes over every door,
   staggered house to house, so the street reads as lived-in — and the
   doors read as doors — before anyone touches anything. */
.hotspot::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 6px;
  background: radial-gradient(ellipse 80% 80% at 50% 58%, rgba(255, 183, 92, 0.34), transparent 72%);
  opacity: 0.35;
  pointer-events: none;
  animation: porch-pulse 3.4s ease-in-out infinite alternate;
}
.hs-field-notes::before  { animation-delay: -0.9s; }
.hs-inside::before       { animation-delay: -1.7s; }
.hs-about::before        { animation-delay: -0.5s; }
.hs-shop::before         { animation-delay: -2.4s; }
.hs-trailer-park::before { animation-delay: -2.9s; }
@keyframes porch-pulse {
  from { opacity: 0.2; }
  to   { opacity: 0.55; }
}
.hotspot:hover,
.hotspot:focus-visible {
  outline: none;
  background: radial-gradient(ellipse 82% 82% at 50% 55%, rgba(255, 183, 92, 0.15), transparent 75%);
  box-shadow:
    inset 0 0 46px rgba(255, 178, 84, 0.38),
    inset 0 0 0 2px rgba(255, 196, 110, 0.55),
    0 0 34px rgba(255, 178, 84, 0.22);
}
.hotspot-sign {
  position: absolute;
  top: -0.45rem;
  left: 50%;
  transform: translateX(-50%) rotate(-1.5deg);
  transform-origin: top center; /* it hangs — swings and scales from its nail */
  font-family: var(--font-type);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  white-space: nowrap;
  color: var(--bone);
  background:
    linear-gradient(180deg, rgba(232, 227, 211, 0.05), rgba(0, 0, 0, 0.2)),
    linear-gradient(180deg, #23231b, #12120d);
  border: 1px solid #3a3a2c;
  border-left: 4px solid var(--toxic);
  padding: 0.28rem 0.55rem 0.16rem;
  border-radius: 2px;
  box-shadow: 0 6px 14px rgba(0, 0, 0, 0.55);
  pointer-events: none;
  transition: transform 0.2s ease, color 0.2s ease;
}
.hotspot:hover .hotspot-sign,
.hotspot:focus-visible .hotspot-sign {
  transform: translateX(-50%) rotate(-1.5deg) scale(1.22);
  color: var(--toxic-bright);
}

/* The knock (v4.2): enter.js adds .knocked the moment a door is
   chosen, in step with the zoom — the hanging sign swings on its
   nail (~0.34s) and the porch light flares once as you step in.
   (The class only ever arrives via enter.js, so reduced-motion and
   no-JS visitors get the plain walk-through as before.) */
.hotspot.knocked .hotspot-sign { animation: sign-swing 0.34s ease-in-out; }
@keyframes sign-swing {
  0%   { transform: translateX(-50%) rotate(-1.5deg); }
  30%  { transform: translateX(-50%) rotate(4.5deg); }
  65%  { transform: translateX(-50%) rotate(-4deg); }
  100% { transform: translateX(-50%) rotate(-1.5deg); }
}
.hotspot.knocked::before { animation: porch-flare 0.85s ease-out; }
@keyframes porch-flare {
  0%   { opacity: 1; transform: scale(1.18); }
  100% { opacity: 0.4; transform: scale(1); }
}

/* === CUL-DE-SAC HOTSPOT MAP — edit positions here ===
   One line per house, matched to the .hs-* classes on the homepage scene
   links in index.html. Positions are % of the scene container (the
   painting's own box), so they track the scene image at any screen size.
   WHEN THE PAINTING IS SWAPPED: remap these six lines and the one scene
   <img> src in index.html — nothing else needs to change. */
.hs-library      { left: 13%; top: 39%; width: 16%; height: 15%; } /* teal house, left — locked pulp painting */
.hs-field-notes  { left: 2%;  top: 53%; width: 15%; height: 14%; } /* purple house, bottom-left */
.hs-inside       { left: 35%; top: 37%; width: 12%; height: 13%; } /* pink house, center-back */
.hs-about        { left: 53%; top: 48%; width: 17%; height: 16%; } /* green house, center */
.hs-shop         { left: 59%; top: 38%; width: 13%; height: 11%; } /* yellow adobe, right-back */
.hs-trailer-park { left: 80%; top: 44%; width: 20%; height: 15%; } /* trailer cluster, right */

/* ---------- Welcome + street directory (homepage) ---------- */
.welcome { text-align: center; padding-top: 2.2rem; }
.welcome .hero-lede, .welcome .hero-note { text-shadow: none; }
.scene-hint {
  font-family: var(--font-type);
  color: var(--toxic-bright);
  letter-spacing: 0.05em;
  margin: 1.7rem 0 0;
}
.directory {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0.5rem 1rem 1.5rem;
  text-align: center;
}
.directory-title {
  font-family: var(--font-type);
  font-weight: 400;
  color: var(--bone-dim);
  font-size: 0.95rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  margin: 0 0 1.1rem;
}
.directory-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem;
  justify-content: center;
}
.directory-list a {
  display: inline-block;
  font-family: var(--font-display);
  font-size: 1.3rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--bone);
  text-decoration: none;
  padding: 0.55rem 1.2rem 0.35rem;
  background:
    linear-gradient(180deg, rgba(232, 227, 211, 0.045), rgba(0, 0, 0, 0.22)),
    linear-gradient(180deg, #20201a, #12120d);
  border: 1px solid #34342a;
  border-top: 4px solid var(--toxic);
  border-radius: 2px;
  box-shadow: 0 10px 22px rgba(0, 0, 0, 0.5);
  transform: rotate(-0.6deg);
  transition: transform 0.12s ease, color 0.15s ease;
}
.directory-list li:nth-child(even) a { border-top-color: var(--blood); transform: rotate(0.6deg); }
.directory-list a:hover, .directory-list a:focus { color: var(--toxic-bright); transform: rotate(0deg) translateY(-2px); }

/* ---------- Inner pages ---------- */
.back-row {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 1.1rem 1rem 0;
}
.back-link {
  font-family: var(--font-type);
  font-size: 0.95rem;
  letter-spacing: 0.04em;
  color: var(--bone-dim);
  text-decoration: none;
}
.back-link:hover, .back-link:focus { color: var(--toxic-bright); }
.page-banner { max-width: 110rem; margin: 0 auto; position: relative; }
.page-banner img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 46vh;
  object-fit: cover;
  object-position: center 40%;
}
.page-banner::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg, transparent 52%, var(--bg) 100%);
}

/* ---------- Small screens ---------- */
@media (max-width: 40rem) {
  /* v4: the houses stay tappable at every size — on a phone the world is
     rendered large, so the painted doors are honest tap targets. Signs
     shrink a step; the street directory still waits below the stage. */
  .hotspot-sign { font-size: 0.62rem; padding: 0.22rem 0.42rem 0.12rem; }
  .stage-hint { font-size: 0.8rem; bottom: 0.8rem; }
  .directory-list a { font-size: 1.15rem; }
}

@media (prefers-reduced-motion: reduce) {
  /* The fog never forms for reduced-motion visitors (the head script also
     skips arming it) — belt and suspenders. enter.js also sits out
     entirely, so the stage stays the static fit-width scene. */
  .fog-intro { display: none !important; }
  .fog-intro::before, .fog-intro::after { animation: none; }
  .fog-bank { animation: none; }
  .fog-stage, .fog-stage::before { animation: none; }
  .nav-brand { animation: none; }
  /* v4.2 ambience: also unreachable in practice (enter-on is never
     added under reduced motion) — belt and suspenders. */
  .lightning { animation: none; }
  .wanderer, .wanderer-fig, .wanderer-arm { animation: none; }
  .hotspot::before { animation: none; }
  .stage-world, .fog-veil { transition: none; }
  .hotspot, .hotspot-sign, .directory-list a { transition: none; }
}
