/* ==========================================================================
   The Colony Project — Malone-inspired editorial minimalism
   Big display type · short measures · asymmetrical 12-col grid · whitespace
   ========================================================================== */

/* ---------- Design tokens ---------- */
:root {
  --paper:    #FAF7F2;  /* warm off-white background          */
  --paper-2:  #EFE9DF;  /* tonal block behind images          */
  --ink:      #191613;  /* near-black text                    */
  --ink-soft: #4C463E;  /* body paragraphs                    */
  --ink-2:    #6B6257;  /* muted labels, captions             */
  --line:     #E3DCD0;  /* hairline rules                     */
  --accent:   #B4502E;  /* terracotta — used sparingly        */
  --paw-ink:  #D4A373;  /* warm sand — decorative paw trail   */

  /* Fraunces survives only inside the ransom letter cards; everything
     else is handwritten — Caveat (marker) for headings and accents,
     Patrick Hand (neat print) for body copy. */
  --font-display: "Fraunces", Georgia, "Times New Roman", serif;
  --font-hand: "Caveat", "Segoe Print", "Comic Sans MS", cursive;
  --font-body: "Patrick Hand", "Segoe Print", "Comic Sans MS", cursive;
  --font-ui: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;

  --container: 1280px;
  --space-section: clamp(6rem, 16vh, 11rem);
}

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

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font-body);
  font-weight: 400;
  line-height: 1.65;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

h1, h2, h3 {
  font-family: var(--font-hand);
  font-weight: 600;
  line-height: 1.15; /* Caveat needs more air than the old serif did */
  letter-spacing: 0;
  margin: 0;
}

p { margin: 0 0 1.1rem; color: var(--ink-soft); }
p:last-child { margin-bottom: 0; }

a { color: inherit; }

::selection { background: var(--accent); color: var(--paper); }

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

/* ---------- Layout primitives ---------- */
.container {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 5vw, 3rem);
}

.grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(1.25rem, 3vw, 2.5rem);
}

section { padding-block: var(--space-section); scroll-margin-top: 5rem; }

/* ---------- Accessibility ---------- */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink);
  color: var(--paper);
  padding: 0.6rem 1rem;
  z-index: 100;
}
.skip-link:focus { left: 0; }

/* ---------- Header ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--paper) 90%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}

.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding-block: 0.9rem;
}

.wordmark {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--font-hand);
  font-weight: 600;
  font-size: 1.4rem;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
}

.wordmark-logo {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
}

.nav-links {
  display: flex;
  gap: 2rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav-links a {
  font-size: 0.82rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  text-decoration: none;
  color: var(--ink-2);
  transition: color 0.2s ease;
}
.nav-links a:hover { color: var(--ink); }

/* ---------- Buttons & links ---------- */
.btn {
  display: inline-block;
  background: var(--ink);
  color: var(--paper);
  padding: 0.85rem 1.7rem;
  border-radius: 999px;
  text-decoration: none;
  font-size: 0.9rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  transition: background 0.25s ease, transform 0.25s ease;
  white-space: nowrap;
}
.btn:hover { background: var(--accent); transform: translateY(-1px); }

.btn--small { padding: 0.55rem 1.2rem; font-size: 0.82rem; }

.link-quiet {
  font-size: 0.88rem;
  color: var(--ink-2);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--line);
  transition: color 0.2s ease;
}
.link-quiet:hover { color: var(--ink); }

/* ---------- Section furniture ---------- */
.kicker {
  display: block;
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 1.25rem;
}

.section-title {
  font-size: clamp(2.4rem, 5.5vw, 4.2rem);
  max-width: 16ch;
  margin-bottom: clamp(2.5rem, 6vw, 4.5rem);
}

/* ---------- Image frames ---------- */
.frame {
  margin: 0;
  background: var(--paper-2);   /* graceful surface while images load */
  border-radius: 2px;
  /* clip + margin (where supported) leaves a window around the card
     for scrapbook decoration — the torn outer mat, its drop-shadow,
     and the overhanging tape — while still containing the photo
     itself. Must exceed the mat's full shadow falloff (inset + offset
     + blur tail), or the shadow gets sliced into straight dark edges. */
  overflow: hidden;
  overflow: clip;
  overflow-clip-margin: 64px;
}
.frame img { width: 100%; height: 100%; object-fit: cover; }

.ratio-45 { aspect-ratio: 4 / 5; }
.ratio-32 { aspect-ratio: 3 / 2; }
.ratio-11 { aspect-ratio: 1 / 1; }

/* ---------- 1. Hero ---------- */
.hero { padding-top: clamp(3rem, 9vh, 6rem); }

.hero .grid { align-items: center; }

/* Headline sits alone in the empty left columns; image pinned right (~55%). */
.hero-copy   { grid-column: 1 / 6; }
.hero-figure { grid-column: 7 / 13; max-height: 82vh; }

.hero h1 {
  font-size: clamp(3.2rem, 9vw, 7.5rem);
  line-height: 0.98;
  letter-spacing: -0.03em;
  margin-bottom: 1.75rem;
}

.hero-sub {
  font-size: clamp(1rem, 1.4vw, 1.2rem);
  color: var(--ink-2);
  max-width: 34ch;
  margin-bottom: 2.25rem;
}

.hero-actions {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: wrap;
}

/* ---------- 2. Impact (stat tiles) ---------- */
.stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(2rem, 5vw, 4rem);
  list-style: none;
  margin: 0;
  padding: 0;
}

.stats li { border-top: 1px solid var(--line); padding-top: 1.5rem; }

/* Stat values: sans, semibold, proportional figures (default — no
   tabular-nums; every-digit-width-of-0 looks loose at display sizes). */
.stat-value {
  display: block;
  font-weight: 600;
  font-size: clamp(2.6rem, 6vw, 4.8rem);
  line-height: 1;
  letter-spacing: -0.02em;
}

.stat-label {
  display: block;
  margin-top: 0.6rem;
  font-size: 0.9rem;
  color: var(--ink-2);
}

.stats-note { margin-top: 2.75rem; font-size: 0.8rem; color: var(--ink-2); }
.stats-note a { color: inherit; }

/* ---------- 3. Mission ---------- */
.mission .grid { align-items: center; }

/* Image anchored left (~60%); narrow text column on the right. */
.mission-figure { grid-column: 1 / 8; }
.mission-copy   { grid-column: 9 / 13; font-size: 1.02rem; }

.pillars {
  list-style: none;
  margin: clamp(4rem, 8vw, 6rem) 0 0;
  padding: 0;
}

.pillars li {
  display: grid;
  grid-template-columns: minmax(140px, 240px) 1fr;
  gap: 2rem;
  align-items: baseline;
  padding-block: 1.75rem;
  border-top: 1px solid var(--line);
}
.pillars li:last-child { border-bottom: 1px solid var(--line); }

.pillars h3 { font-size: clamp(1.6rem, 3vw, 2.2rem); }
.pillars p  { margin: 0; font-weight: 300; color: var(--ink-2); }

/* ---------- 4. Projects (staggered, asymmetrical) ---------- */
.project { margin-bottom: clamp(5rem, 10vw, 8rem); }
.project:last-child { margin-bottom: 0; }

.project h3 {
  font-size: clamp(1.8rem, 3.5vw, 2.6rem);
  margin-bottom: 1rem;
}

.project-copy p { max-width: 44ch; }

/* Shelter: full-bleed-feeling image on the left 2/3, caption low right. */
.project--shelter .grid          { align-items: end; }
.project--shelter .project-figure { grid-column: 1 / 9; }
.project--shelter .project-copy   { grid-column: 9 / 13; }

/* Vet: text alone on the left, smaller image offset LOWER on the right. */
.project--vet .grid           { align-items: start; }
.project--vet .project-copy   { grid-column: 1 / 6; align-self: center; }
.project--vet .project-figure { grid-column: 8 / 13; margin-top: clamp(2rem, 6vw, 5rem); }

/* Ops: narrow image floating in negative space, text beneath. */
.project--ops .project-figure { grid-column: 5 / 9; }
.project--ops .project-copy {
  grid-column: 4 / 10;
  margin-top: 2.5rem;
  text-align: center;
}
.project--ops .project-copy p { margin-inline: auto; }

/* ---------- 5. Founder ---------- */
.founder .grid { align-items: center; }

.founder-copy   { grid-column: 1 / 7; font-size: 1.02rem; }
.founder-figure { grid-column: 8 / 13; }

.signature {
  display: block;
  margin-top: 2rem;
  font-family: var(--font-hand);
  font-size: 1.5rem;
  color: var(--ink);
}

/* ---------- Activity log ---------- */
/* A plain dated list — no thumbnails, no cards. The regular rhythm of
   dates down the hairline rules is itself the visual. */
.log-list { list-style: none; margin: 0; padding: 0; }

.log-list li {
  display: grid;
  grid-template-columns: minmax(130px, 180px) 1fr;
  gap: 2rem;
  align-items: baseline;
  padding-block: 2.25rem;
  border-top: 1px solid var(--line);
}
.log-list li:last-child { border-bottom: 1px solid var(--line); }

.log-date {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.log-body h3 { font-size: 1.6rem; margin-bottom: 0.5rem; }
.log-body p  { margin: 0; color: var(--ink-2); max-width: 56ch; }

/* ---------- Testimonials ---------- */
/* Staggered single-column quotes — never equal thirds. Accent hairline
   instead of quotation-mark graphics; handwritten at reading scale. */
.quotes {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  row-gap: clamp(4rem, 8vw, 7rem);
}

.quote {
  margin: 0;
  padding-left: 1.75rem;
  border-left: 2px solid var(--accent);
}

.quote p {
  font-family: var(--font-hand);
  font-size: clamp(1.5rem, 2.6vw, 1.95rem);
  line-height: 1.4;
  color: var(--ink);
  margin-bottom: 1.25rem;
}

.quote cite {
  font-style: normal;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.quote-1 { grid-column: 1 / 8; }
.quote-2 { grid-column: 5 / 12; }
.quote-3 { grid-column: 2 / 9; }

/* ---------- Footer ---------- */
footer {
  border-top: 1px solid var(--line);
  padding-block: clamp(4rem, 10vw, 7rem) 2rem;
}

.footer-cta h2 {
  font-size: clamp(2.2rem, 5vw, 4rem);
  max-width: 18ch;
  margin-bottom: 1.25rem;
}
.footer-cta p { max-width: 40ch; margin-bottom: 2rem; }

/* Split CTA: copy left, form right, one empty column between. */
.footer-copy   { grid-column: 1 / 6; align-self: center; }
.involve-form  { grid-column: 7 / 13; display: flex; flex-direction: column; gap: 1.4rem; }

.footer-alt { font-size: 0.9rem; margin-bottom: 0; }

.form-label {
  display: block;
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin-bottom: 0.45rem;
}

/* Underline-only inputs — no boxes. */
.form-field input,
.form-field textarea {
  width: 100%;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  background: transparent;
  padding: 0.5rem 0;
  font: inherit;
  color: var(--ink);
  resize: vertical;
  transition: border-color 0.25s ease;
}
.form-field input:focus,
.form-field textarea:focus {
  outline: none;
  border-bottom: 2px solid var(--accent);
}

/* Segmented Adopt / Volunteer / Donate pills. */
.involve-roles {
  border: 0;
  margin: 0;
  padding: 0;
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.involve-roles legend { margin-bottom: 0.7rem; }
.involve-roles label { cursor: pointer; }
.involve-roles input {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
}
.involve-roles span {
  display: inline-block;
  padding: 0.5rem 1.15rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.85rem;
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
.involve-roles input:checked + span {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}
.involve-roles input:focus-visible + span {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

.involve-form .btn {
  align-self: flex-start;
  border: 0;
  cursor: pointer;
  font: inherit;
  font-size: 0.9rem;
  font-weight: 500;
}

.footer-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  justify-content: space-between;
  margin-top: clamp(4rem, 8vw, 6rem);
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
  font-size: 0.8rem;
  color: var(--ink-2);
}
.footer-meta a { color: inherit; text-underline-offset: 3px; }

/* ---------- Paw trail (page-long backdrop) ---------- */
/* A zigzag walk down the whole page, one leg per section: it enters at
   the Impact section's top-left, walks down to the right, turns, and
   keeps switching direction through Mission, Projects, and Founder until
   it walks out at the bottom of the footer. js/main.js maps each
   section's scroll progress to how many of its prints are stamped in;
   scrolling back up lifts them again. Prints face their direction of
   travel (≈135° = down-right, ≈225° = down-left) with per-step jitter,
   and alternate sides like a real gait. */
main section, footer { position: relative; }
.page .page-inner { position: relative; z-index: 1; }
.page .container { position: relative; z-index: 1; }

.paws-wrapper {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

.paw {
  position: absolute;
  width: var(--paw-size, 44px);
  height: var(--paw-size, 44px);
  fill: var(--paw-ink);
  opacity: 0;
  /* Enters "mid-step": lifted along its own heading, slightly small. */
  transform: rotate(var(--r, 225deg)) translateY(-28px) scale(0.5);
  transition:
    opacity 0.4s ease-out,
    transform 0.4s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.paw--dog { --paw-size: 54px; }

.paw.visible {
  opacity: 0.22;
  transform: rotate(var(--r, 225deg)) translateY(0) scale(1);
}

/* Leg 1 (Impact): top-left → bottom-right; the last print begins the turn. */
.paw-i1 { top: 6%;  left: 8%;  --r: 128deg; }
.paw-i2 { top: 26%; left: 24%; --r: 143deg; }
.paw-i3 { top: 45%; left: 42%; --r: 131deg; }
.paw-i4 { top: 64%; left: 58%; --r: 146deg; }
.paw-i5 { top: 83%; left: 76%; --r: 158deg; }

/* Leg 2 (Mission): top-right → bottom-left, feet alternating off the line. */
.paw-m1 { top: 4%;  right: 6%;  --r: 233deg; }
.paw-m2 { top: 16%; right: 21%; --r: 217deg; }
.paw-m3 { top: 29%; right: 27%; --r: 229deg; }
.paw-m4 { top: 41%; right: 43%; --r: 214deg; }
.paw-m5 { top: 53%; right: 49%; --r: 236deg; }
.paw-m6 { top: 65%; right: 65%; --r: 220deg; }
.paw-m7 { top: 78%; right: 71%; --r: 231deg; }
.paw-m8 { top: 90%; right: 86%; --r: 216deg; }

/* Legs 3–5 (one per project PAGE): the walk keeps zigzagging page by
   page — shelter L→R, vet R→L, ops L→R — and still steps on each
   page's photo card so the touch-highlight fires. */
.paw-p1 { top: 10%; left: 8%;   --r: 130deg; }
.paw-p2 { top: 45%; left: 30%;  --r: 144deg; } /* steps on: shelter */
.paw-p3 { top: 80%; left: 62%;  --r: 133deg; }
.paw-p4 { top: 8%;  right: 12%; --r: 228deg; }
.paw-p5 { top: 45%; right: 24%; --r: 216deg; } /* steps on: vet */
.paw-p6 { top: 80%; right: 58%; --r: 231deg; }
.paw-p7 { top: 12%; left: 14%;  --r: 136deg; }
.paw-p8 { top: 50%; left: 45%;  --r: 152deg; } /* steps on: ops */

/* Leg 4 (Log): turns and walks top-right → bottom-left. */
.paw-l1 { top: 6%;  right: 8%;  --r: 233deg; }
.paw-l2 { top: 25%; right: 22%; --r: 218deg; }
.paw-l3 { top: 45%; right: 38%; --r: 230deg; }
.paw-l4 { top: 65%; right: 54%; --r: 216deg; }
.paw-l5 { top: 84%; right: 72%; --r: 197deg; }

/* Leg 5 (Founder): top-left → bottom-right, stepping on the portrait. */
.paw-f1 { top: 5%;  left: 7%;  --r: 131deg; }
.paw-f2 { top: 21%; left: 20%; --r: 140deg; }
.paw-f3 { top: 38%; left: 32%; --r: 134deg; }
.paw-f4 { top: 50%; left: 48%; --r: 138deg; }
.paw-f5 { top: 62%; left: 68%; --r: 146deg; } /* steps on: portrait */
.paw-f6 { top: 88%; left: 78%; --r: 158deg; }

/* Leg 6 (Voices): back across, top-right → bottom-left. */
.paw-v1 { top: 6%;  right: 7%;  --r: 231deg; }
.paw-v2 { top: 26%; right: 24%; --r: 219deg; }
.paw-v3 { top: 46%; right: 40%; --r: 233deg; }
.paw-v4 { top: 66%; right: 56%; --r: 217deg; }
.paw-v5 { top: 85%; right: 72%; --r: 200deg; }

/* Leg 7 (Footer): the final stretch, walking out bottom-right. */
.paw-t1 { top: 8%;  left: 10%; --r: 134deg; }
.paw-t2 { top: 34%; left: 30%; --r: 146deg; }
.paw-t3 { top: 60%; left: 52%; --r: 131deg; }
.paw-t4 { top: 84%; left: 72%; --r: 141deg; }

@media (max-width: 860px) {
  .paw { --paw-size: 32px; }
  .paw--dog { --paw-size: 40px; }
}

/* ---------- Scroll-reveal ---------- */
/* Elements fade in and drift up as they enter the viewport. Elements that
   arrive together are staggered: js/main.js sets --reveal-delay per element
   (0ms, 110ms, 220ms, …) so a section's contents enter one after another. */
.js .reveal {
  opacity: 0;
  transform: translateY(40px);
  transition:
    opacity  0.9s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.9s cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: var(--reveal-delay, 0s);
}
.reveal.is-visible { opacity: 1; transform: none; }

/* Writing reveal: body copy is split into word spans (js/main.js), and
   when a page opens the words appear LINE AFTER LINE — each line inks
   in with a quick left-to-right ripple, then the next line starts.
   Line membership is measured at page-open time, so wrapping is always
   respected. Deliberately NOT gated on prefers-reduced-motion — it is
   a gentle fade, and reduced-motion machines would otherwise never see
   the effect at all. */
.js .reveal .w {
  opacity: 0;
  transition: opacity 0.3s ease;
  transition-delay: var(--w-delay, 0s);
}
.js .reveal.is-visible .w { opacity: 1; }

/* Photos grow gently into place while their frame fades in. (The zoom
   settles inward from 0.94 — never outward — so nothing spills through
   the frame's decoration window during the reveal.) */
.js .frame.reveal img {
  transform: scale(0.94);
  transition: transform 1.4s cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: var(--reveal-delay, 0s);
}
.frame.reveal.is-visible img { transform: scale(1); }

/* ---------- 3D tilt cards ---------- */
/* While the pointer is over a frame, js/main.js writes --rx/--ry (the
   tilt, cursor side lifting toward the viewer) and --mx/--my (the glare
   position). This transform rule intentionally comes AFTER the reveal
   block so it takes over from `.reveal.is-visible { transform: none }`
   once a frame has revealed. Hover-capable devices only. */
.frame { position: relative; }

.frame.is-visible,
.frame:not(.reveal) {
  transform: perspective(950px)
             rotateX(var(--rx, 0deg))
             rotateY(var(--ry, 0deg))
             scale(var(--ts, 1))
             rotate(var(--pz, 0deg)); /* scrapbook paste-rotation */
  transition:
    opacity    0.9s cubic-bezier(0.22, 1, 0.36, 1),
    transform  0.9s cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 0.4s ease;
}

/* Hovered: near-instant transform response, slight lift, soft shadow. */
.frame.is-tilting {
  --ts: 1.02;
  transition: transform 0.08s linear, box-shadow 0.4s ease;
  box-shadow: 0 30px 60px -24px rgba(25, 22, 19, 0.3);
  will-change: transform;
}

/* Scrapbook paste — the photos' PERMANENT dress: every card wears the
   torn paper mat and the washi tape at all times, hanging straight.
   When a paw print steps on a card (js/main.js toggles .is-pawed), it
   inclines a little — as if nudged — and rights itself when the print
   lifts.
   All exterior decoration is box-shadow-based so the frame's clipping
   can't cut it off. */
.frame {
  box-shadow:
    0 0 0 8px #FFFDF6,                        /* paper mat */
    0 0 0 9px rgba(25, 22, 19, 0.09),         /* mat's cut edge */
    0 26px 46px -18px rgba(25, 22, 19, 0.35); /* lifted off the page */
}

/* The paw-nudge leans alternate strictly down the book — after a photo
   tips left, the next one tips right: mission ← shelter → vet ← ops →
   founder ←. Magnitudes jitter a little, like a real scrap stash. */
.frame.is-pawed                            { --pz: -1.6deg; }
.mission-figure.is-pawed                   { --pz: -1.6deg; }
.project--shelter .project-figure.is-pawed { --pz:  1.5deg; }
.project--vet .project-figure.is-pawed     { --pz: -1.4deg; }
.project--ops .project-figure.is-pawed     { --pz:  1.8deg; }
.founder-figure.is-pawed                   { --pz: -1.7deg; }

/* Torn-paper edge: an SVG mat with a ragged inner hole laid over the
   photo's perimeter, in the same paper white as the outer mat — so the
   visible photo-to-paper boundary is an irregular rip, not a clean cut.
   The frame's overflow:hidden means the tear must be drawn inward. */
.frame .torn {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1; /* above the photo, below the washi tape */
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 500' preserveAspectRatio='none'%3E%3Cpath fill='%23FFFDF6' fill-rule='evenodd' d='M0 0h400v500H0z M20 16L52 22 88 12 126 20 163 10 198 18 236 11 272 21 308 13 345 19 381 14 386 48 378 86 388 124 380 168 389 210 379 254 387 300 378 342 388 388 381 432 386 470 352 486 315 478 280 488 243 479 207 489 170 480 134 488 98 479 60 487 28 481 14 448 22 410 12 370 21 328 13 288 22 244 12 204 20 162 13 120 22 78 15 40z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
}

/* Torn OUTER mat: a second ragged SVG extending 16px beyond the card
   (through the frame's clip window), so the white paper is irregular
   against the page too — torn on both of its edges. Its drop-shadow
   follows the ragged silhouette, replacing the rectangular box-shadow
   where the clip window is supported. */
.frame .mat {
  position: absolute;
  inset: -16px;
  z-index: -1; /* behind the photo, above the frame's own background */
  pointer-events: none;
  transition: filter 0.35s ease;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 420 520' preserveAspectRatio='none'%3E%3Cpath fill='%23FFFDF6' d='M6 10L44 4 82 12 120 3 158 11 196 5 234 13 272 4 310 12 348 6 386 13 412 8 416 42 409 84 417 128 408 172 416 214 407 258 415 300 408 344 417 386 409 428 415 468 410 506 378 516 340 508 302 517 264 509 226 516 188 508 150 515 112 507 74 516 36 509 10 514 4 478 12 438 3 396 11 354 4 312 12 270 3 228 11 186 4 144 12 102 5 60z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
  filter: drop-shadow(0 18px 18px rgba(25, 22, 19, 0.26));
}
/* Where the clip window exists, the ragged mat carries the whole
   paste look — drop the rectangular fallback shadows entirely. */
@supports (overflow-clip-margin: 1px) {
  .frame,
  .frame.is-tilting {
    box-shadow: none;
  }
}

/* ---------- Paper scraps behind text ---------- */
/* Headlines and quotes sit on torn pastel paper scraps. The ragged
   shape is a MASK, so one asset serves every scrap color. The
   drop-shadow lives on the text element: the paper silhouette casts
   it, while the glyphs' own shadow hides behind the opaque paper. */
.section-title,
.hero h1,
.footer-cta h2,
.quote {
  position: relative;
  filter: drop-shadow(0 8px 9px rgba(25, 22, 19, 0.13));
}

.section-title::before,
.hero h1::before,
.footer-cta h2::before,
.quote::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--scrap, #C9DCEA);
  transform: rotate(var(--scrap-rot, -1deg));
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 120' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M8 10L48 5 92 13 138 6 184 12 228 5 272 13 318 7 362 12 406 5 450 13 494 7 538 12 578 6 592 9 588 34 594 58 587 84 593 108 566 114 522 107 478 115 434 108 390 114 346 107 302 115 258 108 214 114 170 107 126 115 82 108 38 114 12 110 5 88 11 62 4 36 9 14z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 120' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M8 10L48 5 92 13 138 6 184 12 228 5 272 13 318 7 362 12 406 5 450 13 494 7 538 12 578 6 592 9 588 34 594 58 587 84 593 108 566 114 522 107 478 115 434 108 390 114 346 107 302 115 258 108 214 114 170 107 126 115 82 108 38 114 12 110 5 88 11 62 4 36 9 14z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
}

/* Headlines shrink-wrap their scrap; negative margin keeps the type
   optically on the grid line despite the paper's padding. */
.section-title,
.hero h1,
.footer-cta h2 {
  display: inline-block;
  padding: 0.26em 0.55em 0.3em;
  margin-left: -0.55em;
}

/* Quotes get the blockier tear (reuses the mat's squarish shape). */
.quote {
  border-left: 0;
  padding: 1.7rem 2rem 1.6rem;
}
/* Tall, multi-line headline scraps (hero, footer) use the squarish
   tear too — the wide strip stretched over several lines turns its
   jitter into chunky zigzag teeth. */
.hero h1::before,
.footer-cta h2::before,
.quote::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 420 520' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M6 10L44 4 82 12 120 3 158 11 196 5 234 13 272 4 310 12 348 6 386 13 412 8 416 42 409 84 417 128 408 172 416 214 407 258 415 300 408 344 417 386 409 428 415 468 410 506 378 516 340 508 302 517 264 509 226 516 188 508 150 515 112 507 74 516 36 509 10 514 4 478 12 438 3 396 11 354 4 312 12 270 3 228 11 186 4 144 12 102 5 60z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 420 520' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M6 10L44 4 82 12 120 3 158 11 196 5 234 13 272 4 310 12 348 6 386 13 412 8 416 42 409 84 417 128 408 172 416 214 407 258 415 300 408 344 417 386 409 428 415 468 410 506 378 516 340 508 302 517 264 509 226 516 188 508 150 515 112 507 74 516 36 509 10 514 4 478 12 438 3 396 11 354 4 312 12 270 3 228 11 186 4 144 12 102 5 60z'/%3E%3C/svg%3E");
}

/* A little white torn fringe under every scrap: a second, slightly
   larger masked layer. Same tear assets, but MIRRORED and rotated a
   touch more than the pastel above it — so the white border's width
   wanders like a rip through the paper's white core, never a neat
   parallel outline. Sits at z -2, behind the pastel's z -1. */
.section-title::after,
.hero h1::after,
.footer-cta h2::after,
.quote::after {
  content: "";
  position: absolute;
  inset: -11px;
  z-index: -2;
  background: #FFFDF6;
  transform: rotate(calc(var(--scrap-rot, -1deg) * 1.4)) scaleX(-1);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 120' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M8 10L48 5 92 13 138 6 184 12 228 5 272 13 318 7 362 12 406 5 450 13 494 7 538 12 578 6 592 9 588 34 594 58 587 84 593 108 566 114 522 107 478 115 434 108 390 114 346 107 302 115 258 108 214 114 170 107 126 115 82 108 38 114 12 110 5 88 11 62 4 36 9 14z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 120' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M8 10L48 5 92 13 138 6 184 12 228 5 272 13 318 7 362 12 406 5 450 13 494 7 538 12 578 6 592 9 588 34 594 58 587 84 593 108 566 114 522 107 478 115 434 108 390 114 346 107 302 115 258 108 214 114 170 107 126 115 82 108 38 114 12 110 5 88 11 62 4 36 9 14z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
}
.hero h1::after,
.footer-cta h2::after,
.quote::after {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 420 520' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M6 10L44 4 82 12 120 3 158 11 196 5 234 13 272 4 310 12 348 6 386 13 412 8 416 42 409 84 417 128 408 172 416 214 407 258 415 300 408 344 417 386 409 428 415 468 410 506 378 516 340 508 302 517 264 509 226 516 188 508 150 515 112 507 74 516 36 509 10 514 4 478 12 438 3 396 11 354 4 312 12 270 3 228 11 186 4 144 12 102 5 60z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 420 520' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M6 10L44 4 82 12 120 3 158 11 196 5 234 13 272 4 310 12 348 6 386 13 412 8 416 42 409 84 417 128 408 172 416 214 407 258 415 300 408 344 417 386 409 428 415 468 410 506 378 516 340 508 302 517 264 509 226 516 188 508 150 515 112 507 74 516 36 509 10 514 4 478 12 438 3 396 11 354 4 312 12 270 3 228 11 186 4 144 12 102 5 60z'/%3E%3C/svg%3E");
}

/* ---------- Ransom-note headlines ---------- */
/* js/main.js splits display headlines into per-letter .cut cards —
   magazine cutouts pasted onto the big pastel scraps. Eight variants
   cycle deterministically: mixed papers, typefaces, and small
   rotations, mostly cream cards with ink type (like real cutouts)
   plus a few inverted and colored ones for punch. */
/* Ransom headlines carry no big scrap of their own — each LETTER is
   its own irregular paper piece. The doubled class outguns the scrap
   rules' specificity to strip their padding, offset, and shadow. */
.is-ransom.is-ransom {
  letter-spacing: normal;
  line-height: 1.16;
  padding: 0;
  margin-left: 0;
  filter: none;
}
.is-ransom.is-ransom::before,
.is-ransom.is-ransom::after { display: none; }

/* Shadows live on the word: a clipped element's box-shadow is clipped
   away with it, but drop-shadow on the wrapper traces every letter
   card's irregular silhouette. */
.cut-word {
  display: inline-block;
  white-space: nowrap;
  /* Two shadows under the cutouts, tracing each card's irregular
     silhouette: a crisp contact edge right beneath the paper, then a
     soft ambient falloff that lifts the letters off the page. */
  filter:
    drop-shadow(0 0.06em 0.03em rgba(25, 22, 19, 0.30))
    drop-shadow(0 0.16em 0.28em rgba(25, 22, 19, 0.24));
}

.cut {
  display: inline-block;
  padding: 0.06em 0.12em;
  margin: 0.03em 0.015em;
  line-height: 1.08;
}

/* Every variant's card is cut along its own irregular outline — the
   later ones include tag, pennant, and chunky-octagon silhouettes. */
.cut-v1  { clip-path: polygon(4% 7%, 30% 2%, 65% 6%, 96% 1%, 99% 34%, 94% 66%, 98% 95%, 68% 99%, 34% 93%, 3% 97%, 6% 64%, 1% 32%); }
.cut-v2  { clip-path: polygon(2% 4%, 36% 6%, 70% 1%, 98% 5%, 95% 30%, 99% 62%, 94% 97%, 60% 94%, 28% 99%, 4% 95%, 7% 68%, 2% 35%); }
.cut-v3  { clip-path: polygon(5% 2%, 40% 5%, 72% 2%, 97% 6%, 99% 40%, 95% 72%, 97% 98%, 66% 95%, 32% 98%, 2% 94%, 4% 60%, 6% 28%); }
.cut-v4  { clip-path: polygon(1% 6%, 28% 1%, 62% 6%, 99% 3%, 96% 36%, 99% 68%, 95% 94%, 64% 98%, 30% 95%, 5% 99%, 2% 66%, 5% 30%); }
.cut-v5  { clip-path: polygon(6% 3%, 34% 6%, 68% 2%, 95% 5%, 98% 32%, 94% 64%, 99% 96%, 62% 99%, 36% 94%, 6% 98%, 1% 62%, 4% 34%); }
.cut-v6  { clip-path: polygon(3% 5%, 38% 2%, 66% 6%, 98% 2%, 95% 38%, 98% 70%, 96% 97%, 58% 96%, 30% 99%, 2% 96%, 5% 70%, 3% 30%); }
.cut-v7  { clip-path: polygon(2% 8%, 32% 3%, 64% 7%, 97% 4%, 99% 36%, 96% 68%, 98% 94%, 70% 97%, 36% 92%, 4% 98%, 3% 62%, 6% 34%); }
.cut-v8  { clip-path: polygon(5% 4%, 36% 7%, 70% 3%, 96% 7%, 99% 42%, 94% 70%, 98% 98%, 64% 94%, 28% 97%, 3% 93%, 6% 58%, 2% 26%); }
.cut-v9  { clip-path: polygon(2% 6%, 50% 1%, 97% 7%, 99% 68%, 52% 98%, 3% 72%); }
.cut-v10 { clip-path: polygon(4% 8%, 36% 3%, 68% 7%, 97% 3%, 95% 40%, 99% 78%, 94% 96%, 60% 99%, 26% 94%, 3% 98%, 6% 60%, 2% 26%); }
.cut-v11 { clip-path: polygon(3% 12%, 50% 2%, 97% 10%, 99% 96%, 66% 92%, 33% 98%, 1% 93%); }
.cut-v12 { clip-path: polygon(2% 6%, 40% 1%, 74% 6%, 98% 2%, 96% 34%, 99% 66%, 97% 98%, 62% 95%, 30% 99%, 4% 94%, 1% 58%, 5% 28%); }
.cut-v13 { clip-path: polygon(6% 2%, 52% 6%, 94% 1%, 99% 44%, 95% 92%, 55% 99%, 8% 95%, 1% 50%); }
.cut-v14 { clip-path: polygon(2% 10%, 34% 4%, 66% 8%, 98% 4%, 96% 42%, 99% 74%, 95% 97%, 58% 93%, 24% 98%, 5% 92%, 3% 56%, 6% 24%); }
.cut-v15 { clip-path: polygon(4% 4%, 96% 2%, 99% 62%, 78% 97%, 50% 92%, 20% 98%, 1% 60%); }
.cut-v16 { clip-path: polygon(3% 3%, 38% 7%, 70% 2%, 97% 7%, 99% 38%, 94% 70%, 98% 96%, 64% 99%, 32% 93%, 2% 97%, 5% 66%, 1% 34%); }

.cut-v1 { background: #FFFFFF; color: var(--ink); font-family: var(--font-display); font-weight: 600; transform: rotate(-3deg); }
.cut-v2 { background: var(--ink); color: var(--paper); font-family: Impact, "Arial Black", "Franklin Gothic Bold", sans-serif; font-weight: 400; transform: rotate(2deg); }
.cut-v3 { background: #F2D4DA; color: var(--ink); font-family: "Playfair Display", Georgia, serif; font-style: italic; font-weight: 700; transform: rotate(4deg) translateY(-0.03em); }
.cut-v4 { background: #FFFFFF; color: var(--ink); font-family: Oswald, "Arial Narrow", sans-serif; font-weight: 500; transform: rotate(-5deg); }
.cut-v5 { background: var(--accent); color: var(--paper); font-family: var(--font-display); font-weight: 700; transform: rotate(3deg); }
.cut-v6 { background: #C9DCEA; color: var(--ink); font-family: Consolas, "Courier New", monospace; font-weight: 700; transform: rotate(-2deg) translateY(0.04em); }
.cut-v7 { background: #E0D8EC; color: var(--ink); font-family: Caveat, "Segoe Script", cursive; font-weight: 600; font-size: 1.15em; transform: rotate(5deg); }
.cut-v8 { background: #CFE6DA; color: var(--ink); font-family: Inter, sans-serif; font-weight: 600; font-size: 0.95em; transform: rotate(-4deg); }
.cut-v9  { background: #E3B23C; color: var(--ink); font-family: Oswald, "Arial Narrow", sans-serif; font-weight: 600; text-transform: uppercase; font-size: 0.85em; transform: rotate(-5deg) translateY(0.03em); }
.cut-v10 { background: #4E6E58; color: var(--paper); font-family: "Special Elite", "Courier New", monospace; font-weight: 400; transform: rotate(3.5deg); }
.cut-v11 { background: #C24C3F; color: var(--paper); font-family: "Playfair Display", Georgia, serif; font-style: italic; font-weight: 700; transform: rotate(-2.5deg) translateY(-0.04em); }
.cut-v12 { background: #F3E9D7; color: var(--ink); font-family: var(--font-display); font-weight: 400; font-size: 1.06em; transform: rotate(1.5deg); }
.cut-v13 { background: #5E7286; color: var(--paper); font-family: Inter, sans-serif; font-weight: 500; text-transform: uppercase; font-size: 0.8em; transform: rotate(4.5deg) translateY(0.04em); }
.cut-v14 { background: #D4A373; color: var(--ink); font-family: Georgia, "Times New Roman", serif; font-weight: 700; transform: rotate(-3.5deg) translateY(0.05em); }
.cut-v15 { background: #6E5A78; color: var(--paper); font-family: Caveat, "Segoe Script", cursive; font-weight: 600; font-size: 1.18em; transform: rotate(2.8deg); }
.cut-v16 { background: #A8BCA1; color: var(--ink); font-family: Georgia, "Times New Roman", serif; font-style: italic; font-weight: 400; font-size: 1.05em; transform: rotate(-1deg) translateY(-0.05em); }

/* One pastel per scrap, leans alternating — like a real stash. */
.hero h1                 { --scrap: #CBDDEB; --scrap-rot: -0.7deg; }
.impact .section-title   { --scrap: #EFDCD3; --scrap-rot: -1.2deg; }
.mission .section-title  { --scrap: #CFE6DA; --scrap-rot:  0.9deg; }
.projects .section-title { --scrap: #C9DCEA; --scrap-rot: -1deg;   }
.log .section-title      { --scrap: #E0D8EC; --scrap-rot:  1.1deg; }
.founder .section-title  { --scrap: #F2D4DA; --scrap-rot: -0.9deg; }
.voices .section-title   { --scrap: #EFDCD3; --scrap-rot:  1deg;   }
.footer-cta h2           { --scrap: #C9DCEA; --scrap-rot: -0.8deg; }
.quote-1                 { --scrap: #F2D4DA; --scrap-rot: -1.1deg; }
.quote-2                 { --scrap: #C9DCEA; --scrap-rot:  0.9deg; }
.quote-3                 { --scrap: #CFE6DA; --scrap-rot: -0.7deg; }

/* Washi tape strip: torn ends via clip-path, faint diagonal weave.
   Overhangs the top edge slightly, straddling the torn mat. */
.frame::before {
  content: "";
  position: absolute;
  top: -9px;
  left: 50%;
  width: 112px;
  height: 28px;
  transform: translateX(-50%) rotate(-3deg);
  background:
    repeating-linear-gradient(
      115deg,
      rgba(255, 255, 255, 0.25) 0 6px,
      rgba(255, 255, 255, 0) 6px 12px
    ),
    rgba(176, 196, 222, 0.65); /* pastel blue */
  clip-path: polygon(
    3% 0, 100% 0, 96% 20%, 100% 44%, 95% 68%, 100% 100%,
    2% 100%, 6% 72%, 0 46%, 4% 22%
  );
  pointer-events: none;
  z-index: 2;
}

/* Vary the tape color like a real scrap stash. */
.project--vet .project-figure::before,
.founder-figure::before {
  background:
    repeating-linear-gradient(
      115deg,
      rgba(255, 255, 255, 0.25) 0 6px,
      rgba(255, 255, 255, 0) 6px 12px
    ),
    rgba(240, 196, 204, 0.7); /* pastel pink */
}
.project--ops .project-figure::before {
  background:
    repeating-linear-gradient(
      115deg,
      rgba(255, 255, 255, 0.25) 0 6px,
      rgba(255, 255, 255, 0) 6px 12px
    ),
    rgba(203, 235, 214, 0.75); /* pastel mint */
}

/* Glare sheen that follows the cursor across the card. */
.frame::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(
    circle at var(--mx, 50%) var(--my, 50%),
    rgba(255, 253, 248, 0.38),
    rgba(255, 253, 248, 0) 58%
  );
  transition: opacity 0.35s ease;
}
.frame.is-tilting::after { opacity: 1; }

/* ---------- Responsive ---------- */
@media (max-width: 860px) {
  .nav-links { display: none; }

  /* Collapse every asymmetric placement to full width, in source order.
     Selectors must match the specificity of the desktop placements above
     (two classes), or those rules would still win inside this query. */
  .hero-copy, .hero-figure,
  .mission-figure, .mission-copy,
  .founder-copy, .founder-figure,
  .project--shelter .project-figure, .project--shelter .project-copy,
  .project--vet .project-figure,     .project--vet .project-copy,
  .project--ops .project-figure,     .project--ops .project-copy {
    grid-column: 1 / -1;
  }

  .project--vet .project-figure,
  .project--ops .project-copy { margin-top: 0; }

  .stats { grid-template-columns: repeat(2, 1fr); }

  .pillars li { grid-template-columns: 1fr; gap: 0.35rem; }

  .log-list li { grid-template-columns: 1fr; gap: 0.4rem; }

  .quote-1, .quote-2, .quote-3 { grid-column: 1 / -1; }

  .footer-copy, .involve-form { grid-column: 1 / -1; }
}

@media (max-width: 480px) {
  .stats { gap: 1.75rem; }
}

/* ---------- Reduced motion ---------- */
/* Reduced motion: drop every transform (slide, zoom, hover lift) but keep a
   gentle scroll-triggered crossfade — "reduce motion" means no movement,
   not no feedback. Note: Windows maps its "Animation effects" toggle
   (Settings → Accessibility → Visual effects) to this media query. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal {
    transform: none;
    transition: opacity 0.9s ease;
    transition-delay: var(--reveal-delay, 0s);
  }
  .frame.reveal img { transform: none; transition: none; }
  .btn:hover { transform: none; }
  /* Paw prints still fade in/out, but without the step-down movement. */
  .paw,
  .paw.visible { transform: rotate(var(--r, 225deg)); transition: opacity 0.6s ease; }
}

/* ==========================================================================
   Flipbook
   Active only when js/main.js sets body.flipbook-on — without JavaScript
   the pages simply flow as a normal scrolling document. With it, pages
   stack like leaves of an album and turn in 3D around the left edge.
   ========================================================================== */
.book-nav,
.page-indicator { display: none; }

.flipbook-on {
  height: 100dvh;
  overflow: hidden;
}

.flipbook-on .site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
}

/* Full-bleed book: pages fill the viewport; the turn.js fold shading
   and curl lighting carry the book feel during the turns themselves. */
.flipbook-on .book {
  position: fixed;
  inset: 0;
  perspective: 3000px;
}

.flipbook-on .page {
  position: absolute;
  inset: 0;
  padding: 0;
  background: var(--paper);
  /* Book model: the spine is the viewport's RIGHT edge. Pages not yet
     reached wait folded away behind the spine (rotateY(180°)); turning
     forward sweeps the next leaf in from the right and lays it open
     right-to-left across the screen, like a Western book page turn.
     Turning back folds it away again. preserve-3d keeps the leaf's
     paper back face (::after below) oriented with it, so the first
     half of the turn shows paper, then the leaf opens to its front. */
  transform-origin: right center;
  transition: transform 0.95s cubic-bezier(0.33, 0.08, 0.22, 1);
  transform-style: preserve-3d;
  /* Only visible mid-turn: the lifting leaf casts onto the page below. */
  box-shadow: 0 16px 40px -16px rgba(25, 22, 19, 0.38);
}
.flipbook-on .page.flipped { transform: rotateY(180deg); }

/* Fold shading (turn.js style): injected by js/main.js onto every leaf.
   As a leaf folds toward the spine, its face darkens from the fold
   outward; as it lays open, the light returns. Rides the same
   transition as the turn itself. */
.leaf-shade {
  position: absolute;
  inset: 0;
  z-index: 6;
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(
    270deg,
    rgba(25, 22, 19, 0.38),
    rgba(25, 22, 19, 0.10) 42%,
    rgba(25, 22, 19, 0.02) 70%,
    transparent
  );
  transition: opacity 0.95s cubic-bezier(0.33, 0.08, 0.22, 1);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
.flipbook-on .page.flipped .leaf-shade { opacity: 1; }

/* The BACK of each leaf: blank paper, faintly shaded toward the spine.
   It faces away when the page lies open (its backface is hidden), and
   covers the mirrored content once the leaf turns past 90°. The 1px
   translateZ lifts it off the content plane so coplanar 3D painting
   can't bleed through. */
.flipbook-on .page::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 5;
  /* Curl lighting: a bright band beside the fold, deepening toward the
     free edge — reads as paper bending mid-turn. */
  background:
    linear-gradient(
      270deg,
      rgba(255, 255, 255, 0.85) 0%,
      rgba(25, 22, 19, 0.10) 10%,
      rgba(25, 22, 19, 0.02) 24%,
      rgba(25, 22, 19, 0.16) 100%
    ),
    var(--paper);
  transform: rotateY(180deg) translateZ(1px);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  pointer-events: none;
}

/* Set while restoring a deep-linked page on load — no turning animation. */
.no-anim .page { transition: none !important; }

/* Spine shading along the right edge of every leaf. */
.flipbook-on .page::before {
  content: "";
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  width: 46px;
  background: linear-gradient(270deg, rgba(25, 22, 19, 0.06), transparent);
  pointer-events: none;
  z-index: 2;
}

/* A leaf's content scrolls inside it when taller than the screen. */
.flipbook-on .page-inner {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: calc(58px + clamp(1rem, 4vh, 2.5rem)) 0 4.5rem;
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}

/* Compact editorial rhythm inside a fixed page. */
.flipbook-on .page .container { padding-block: clamp(0.5rem, 2vh, 1.5rem); }
.flipbook-on .project { margin-bottom: 0; }

/* Ransom letter cards inflate titles — scale them down and keep them
   to one line so each page's content fits its screen. */
.flipbook-on .section-title {
  font-size: clamp(1.9rem, 3.6vw, 3rem);
  margin-bottom: clamp(1rem, 3vh, 2rem);
  max-width: none;
}

/* Project pages: the whole beat (title, photo, text) stays above the
   fold — photo cards cap their height and crop via object-fit instead
   of pushing the copy below the screen, and text centers beside the
   photo rather than hanging off its bottom edge. */
.flipbook-on .project-figure { max-height: 52vh; }
.flipbook-on .project .grid { align-items: center; }
.flipbook-on .project--vet .project-figure { margin-top: 0; }

/* Cover page: hero vertically centered on the leaf. `safe center`
   falls back to top-aligned when content overflows a short screen, so
   the headline can never be clipped out of reach behind the header. */
.flipbook-on #top .page-inner {
  display: flex;
  align-items: center;
  align-items: safe center;
}
.flipbook-on #top .container { width: 100%; }
.flipbook-on .hero-figure { max-height: 74vh; }

/* The ransom letter cards nearly double the headline's height — scale
   the cover down and widen its column so all four beats (headline,
   sub, buttons, photo) fit one viewport with no scrolling. */
.flipbook-on .hero-copy { grid-column: 1 / 7; }
.flipbook-on .hero h1 {
  font-size: clamp(2.2rem, 4.6vw, 4rem);
  margin-bottom: 1.25rem;
}
.flipbook-on .hero-sub {
  max-width: 42ch;
  margin-bottom: 1.5rem;
}

/* ---------- Book navigation ---------- */
.flipbook-on .book-nav { display: block; }

.page-arrow {
  position: fixed;
  top: 50%;
  transform: translateY(-50%);
  z-index: 60;
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: color-mix(in srgb, var(--paper) 85%, transparent);
  backdrop-filter: blur(6px);
  color: var(--ink);
  font-size: 1.1rem;
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease, opacity 0.2s ease;
}
.page-arrow.prev { left: clamp(0.6rem, 2vw, 1.6rem); }
.page-arrow.next { right: clamp(0.6rem, 2vw, 1.6rem); }
.page-arrow:hover {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}
.page-arrow[disabled] { opacity: 0.25; pointer-events: none; }

.flipbook-on .page-indicator {
  display: block;
  position: fixed;
  left: 50%;
  bottom: 0.9rem;
  transform: translateX(-50%);
  z-index: 60;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  color: var(--ink-2);
}

@media (max-width: 860px) {
  .page-arrow {
    top: auto;
    bottom: 0.7rem;
    transform: none;
    width: 2.6rem;
    height: 2.6rem;
  }
  .page-arrow.prev { left: 1rem; }
  .page-arrow.next { right: 1rem; }
  .flipbook-on .page-indicator { bottom: 1.45rem; }
}

@media (prefers-reduced-motion: reduce) {
  /* Reduced motion: the leaf still turns — it is a direct response to a
     deliberate press, not autonomous motion — but quicker and gentler.
     (Note: Windows' "Animation effects" toggle maps to this query.) */
  .flipbook-on .page,
  .leaf-shade { transition-duration: 0.5s; }
}

/* ---------- Two-voice typography ---------- */
/* The scrapbook's CONTENT is handwritten (Caveat headings, Patrick
   Hand body), but its structural furniture — small uppercase labels,
   navigation, buttons, dates, form controls — stays typeset in Inter,
   like printed labels stuck into a handwritten album. Handwriting
   with wide tracking in small caps reads ragged; this keeps the
   hierarchy crisp. */
.nav-links a,
.btn,
.kicker,
.stat-label,
.stats-note,
.log-date,
.form-label,
.involve-roles span,
.form-field input,
.form-field textarea,
.footer-meta,
.page-indicator,
.page-arrow,
.quote cite,
.link-quiet {
  font-family: var(--font-ui);
}

/* ---------- Readability scale ---------- */
/* Handwriting faces run optically small — content type is scaled up so
   it reads easily. Keep these overrides last so they win the cascade. */
body { font-size: 1.15rem; }                              /* ~18.4px base */
.hero-sub { font-size: clamp(1.15rem, 1.7vw, 1.4rem); }
.mission-copy, .founder-copy { font-size: 1.18rem; }
.log-body h3 { font-size: 1.8rem; }
.kicker { font-size: 0.82rem; }
.nav-links a { font-size: 0.88rem; }
.btn { font-size: 0.95rem; }
.stat-label { font-size: 1rem; }
.stats-note { font-size: 0.9rem; }
.log-date { font-size: 0.85rem; }
.quote cite { font-size: 0.85rem; }
.link-quiet { font-size: 0.95rem; }
.footer-meta { font-size: 0.88rem; }
.form-label { font-size: 0.8rem; }
.involve-roles span { font-size: 0.95rem; }

/* ---------- No-scroll fit ---------- */
/* Every leaf is composed to fit one screen (~700px of content height)
   with no inner scrolling. Photos cap their height and crop via
   object-fit; the dense pages trade a step of type size for fitting
   whole — still larger than the site's original body text. The
   page-inner scrollbar remains only as a safety net for very short
   windows. */
.flipbook-on .page-inner { padding: calc(58px + 1.5vh) 0 3.2rem; }
.flipbook-on .kicker { margin-bottom: 0.6rem; }

/* Impact */
.flipbook-on .stats { gap: clamp(1.5rem, 3vw, 3rem); }
.flipbook-on .stats-note { margin-top: 1.2rem; }

/* Mission: capped photo; pillars fold into one three-column row.
   The photo is left exactly as it is — only the TEXT column moves
   toward it (one grid column left, plus a small pull-in). */
.flipbook-on .mission-figure { max-height: 38vh; }
.flipbook-on .mission-copy {
  font-size: 1.05rem;
  grid-column: 8 / 13;
  margin-left: -1.5rem;
}
.flipbook-on .pillars {
  margin-top: clamp(1.2rem, 3vh, 2rem);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1rem, 2.5vw, 2rem);
}
.flipbook-on .pillars li {
  display: block;
  padding-block: 1rem 0;
  border-top: 1px solid var(--line);
  border-bottom: 0;
}
.flipbook-on .pillars li:last-child { border-bottom: 0; }
.flipbook-on .pillars p { font-size: 1rem; }

/* Ops: pull the centered caption up so the page fits whole. */
.flipbook-on .project--ops .project-copy { margin-top: 1.25rem; }
.flipbook-on .project--ops .project-copy p { font-size: 1.05rem; }

/* Log: tighter rows. */
.flipbook-on .log-list li { padding-block: 1.1rem; gap: 1.5rem; }
.flipbook-on .log-body h3 { font-size: 1.5rem; }
.flipbook-on .log-body p { font-size: 1rem; }

/* Founder: capped portrait, compact statement. */
.flipbook-on .founder-figure { max-height: 60vh; }
.flipbook-on .founder-copy { font-size: 1.05rem; line-height: 1.55; }
.flipbook-on .founder-copy p { margin-bottom: 0.8rem; }
.flipbook-on .signature { margin-top: 0.8rem; font-size: 1.3rem; }

/* Voices: compact staggered quotes. */
.flipbook-on .quotes { row-gap: clamp(1.2rem, 3vh, 2.2rem); }
.flipbook-on .quote p { font-size: clamp(1.2rem, 1.9vw, 1.5rem); margin-bottom: 0.6rem; }

/* Contact: compact form and footer meta. */
.flipbook-on .involve-form { gap: 0.9rem; }
.flipbook-on .form-field textarea { height: 3.4em; }
.flipbook-on .footer-cta h2 { font-size: clamp(1.8rem, 3.4vw, 2.6rem); }
.flipbook-on .footer-copy p { margin-bottom: 1rem; }
.flipbook-on .footer-meta { margin-top: clamp(1rem, 3vh, 2rem); padding-top: 1rem; }

/* Final fit trims: log rows and quote scraps. */
.flipbook-on .log-list li { padding-block: 0.85rem; }
.flipbook-on .quotes { row-gap: 0.9rem; }
.flipbook-on .quote { padding: 0.85em 1.15em 0.95em; }
.flipbook-on .quote p { font-size: clamp(1.05rem, 1.6vw, 1.3rem); margin-bottom: 0.5rem; }

/* ---------- Cursor paw trail ---------- */
/* Prints stamped behind the moving mouse (built by js/main.js). The
   layer sits over the pages but under the header, and never catches
   pointer events. Pointer-driven, so not gated on reduced motion;
   the fade itself is opacity-only. */
.paw-cursor {
  position: fixed;
  inset: 0;
  z-index: 45;
  pointer-events: none;
  overflow: hidden;
}

.paw-step {
  position: absolute;
  width: 26px;
  height: 26px;
  margin: -13px 0 0 -13px; /* center each stamp on its point */
  fill: var(--paw-ink);
  transform: rotate(var(--a, 0deg));
  animation: paw-step-fade 1.1s ease-out forwards;
}

@keyframes paw-step-fade {
  0%   { opacity: 0; }
  12%  { opacity: 0.42; }
  55%  { opacity: 0.3; }
  100% { opacity: 0; }
}
