/* Shared shell: reset, type, buttons, header, footer, reveals, forms. Page styles live in css/pages/. */

* { box-sizing: border-box; }
html { scroll-behavior: smooth; overflow-x: clip; }
body {
  margin: 0; background: var(--canvas); color: var(--ink);
  font: 400 var(--t-18) / 1.55 var(--sans);
  -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; overflow-x: clip;
}
img, picture, svg, canvas, video { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
h1, h2, h3, h4, p, ul, ol, figure { margin: 0; }
ul, ol { padding: 0; }
:focus-visible { outline: 2px solid var(--leaf); outline-offset: 3px; border-radius: 2px; }
.skip { position: absolute; left: 12px; top: -60px; z-index: 300; background: var(--forest); color: #fff; padding: 10px 14px; border-radius: 8px; }
.skip:focus { top: 12px; }
.wrap { width: min(var(--wrap), 100% - 2 * var(--gutter)); margin-inline: auto; }
.wrap-narrow { width: min(760px, 100% - 2 * var(--gutter)); margin-inline: auto; }

/* Type */
.display { font-family: var(--display); font-weight: 500; line-height: 1.02; letter-spacing: -.012em; text-wrap: balance; font-variant-numeric: lining-nums; }
/* The scale, set once. Page stylesheets load after this and override where a section
   genuinely differs. Before this existed, any heading a page stylesheet forgot fell back
   to the browser default (32 / 24 / 19px), which is what broke About and Corporate. */
:where(h1.display) { font-size: var(--t-88); }
:where(h2.display) { font-size: var(--t-64); }
:where(h3.display) { font-size: var(--t-36); }
:where(h2.display, h3.display) em { font-style: italic; }
body { font-variant-numeric: lining-nums; }
.display em { font-style: italic; font-weight: 500; color: var(--moss); }
.eyebrow { font: 500 var(--t-12) / 1 var(--sans); letter-spacing: .14em; text-transform: uppercase; color: var(--moss); }
.lede { font-size: var(--t-22); line-height: 1.45; color: var(--stone); max-width: 34em; text-wrap: pretty; }
.small { font-size: var(--t-14); color: var(--stone); }
/* Figures. Amounts and counts are always sans with lining, tabular numerals, whatever
   typeface surrounds them. This lives here, not in a page stylesheet, so every page gets it. */
.money { font: 500 1em / 1 var(--sans); font-variant-numeric: tabular-nums lining-nums; letter-spacing: -.02em; }
.money > span { font: inherit; }
.money .cur { font-weight: 400; opacity: .6; margin-right: .06em; color: inherit; }
.prose { max-width: 66ch; }
.prose p + p { margin-top: 1.1em; }
/* Prose sizing is for body copy only: a heading explicitly marked .display keeps the page scale. */
.prose h2:not(.display) { font-family: var(--display); font-weight: 500; font-size: var(--t-36); line-height: 1.1; margin: 2.2em 0 .6em; color: var(--forest); }
.prose h3:not(.display) { font-size: var(--t-22); font-weight: 600; margin: 1.8em 0 .5em; }
.prose ul, .prose ol { padding-left: 1.2em; margin: .8em 0; }
.prose li + li { margin-top: .35em; }
.prose a { color: var(--moss); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }

/* Page head (used by inner pages) */
.page-head { padding: calc(var(--header-h) + clamp(56px, 9vw, 120px)) 0 clamp(40px, 6vw, 80px); }
.page-head h1 { font-size: var(--t-64); max-width: 16ch; margin-top: 18px; color: var(--forest); }
.page-head .lede { margin-top: 22px; }

/* Buttons */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 10px; height: 52px; padding: 0 26px; border-radius: 8px; font-weight: 500; font-size: var(--t-16); white-space: nowrap; transition: background-color .3s, color .3s, border-color .3s; }
.btn-primary { background: var(--forest); color: #fff; }
.btn-primary:hover { background: var(--moss); }
.btn-ghost { border: 1px solid var(--line-strong); color: var(--forest); }
.btn-ghost:hover { border-color: var(--forest); }
.btn-light { background: #fff; color: var(--forest); }
.btn-light:hover { background: var(--mist); }
.btn-outline-light { border: 1px solid rgba(255,255,255,.55); color: #fff; }
.btn-outline-light:hover { border-color: #fff; background: rgba(255,255,255,.08); }
.btn-sm { height: 42px; padding: 0 18px; font-size: 15px; }
.btn .arrow { width: 16px; height: 16px; transition: transform .5s var(--ease); }
.btn:hover .arrow { transform: translateX(3px); }

/* Chips and tags */
.tag { display: inline-flex; align-items: center; gap: 8px; font: 500 12px / 1 var(--sans); letter-spacing: .1em; text-transform: uppercase; padding: 8px 12px; border-radius: 4px; background: var(--mist); color: var(--forest); }
.tag-dark { background: rgba(6,18,12,.55); color: #fff; }
.tag i { width: 7px; height: 7px; border-radius: 50%; background: var(--leaf); }

/* ---------- Header ---------- */
.site-header {
  position: fixed; inset: 0 0 auto 0; z-index: 100;
  /* fixed height: the bar used to squeeze 16px on scroll, which shunted the logo up the page */
  height: var(--header-h);
  display: flex; align-items: center;
  color: color-mix(in oklab, #fff calc(100% - 100% * var(--hdr)), var(--forest) calc(100% * var(--hdr)));
  background: rgba(251, 252, 249, calc(.92 * var(--hdr)));
  backdrop-filter: blur(calc(16px * var(--hdr))) saturate(1.2);
  -webkit-backdrop-filter: blur(calc(16px * var(--hdr))) saturate(1.2);
  box-shadow: 0 10px 40px -24px rgba(18, 56, 42, calc(.5 * var(--hdr)));
  transition: background-color .3s, box-shadow .3s;
}
.site-header > .wrap { display: flex; align-items: center; justify-content: space-between; gap: 32px; }
/* ---------- Logo lockups ----------
   One mark, two lockups: horizontal for the desktop header, stacked for the footer and mobile.
   Clear space on every side is the diameter of the filled circle, about 0.65 of the mark's height. */
.logo { display: flex; align-items: center; gap: 22px; text-decoration: none; color: var(--forest); }
.logo__mark { display: flex; flex: none; }
.logo__svg { display: block; width: auto; }
/* the mark's stroke has to thicken as it shrinks, so it is set per lockup rather than on the file */
.logo__svg circle { stroke-width: var(--mark-stroke, 2.4); }
.logo__text { display: flex; flex-direction: column; gap: 6px; }
.logo__word { font-family: var(--display); font-weight: 500; font-size: 50px; line-height: .8; color: var(--forest); }
.logo__rule { display: block; width: 100%; height: 1px; background: var(--rule); }
.logo__sub { font-family: var(--sans); font-weight: 500; font-size: 12px; letter-spacing: .06em; color: var(--stone); white-space: nowrap; }

/* Stacked: footer and mobile. 64px mark sits above the 48px stroke step, so 2.4. */
.logo--stacked { --mark-stroke: 2.4; }
.logo--stacked .logo__svg { height: 64px; }

/* Reverse, for the forest footer */
.logo--reverse { color: var(--sprout); }
.logo--reverse .logo__word { color: var(--canvas); }
.logo--reverse .logo__rule { background: var(--moss); }
.logo--reverse .logo__sub { color: var(--sprout); }

/* Horizontal: desktop header. The header already shrinks on scroll through --hdr, so the lockup
   rides the same value from its full step (40px mark, 34px word) to the compact one (28px, 24px)
   instead of snapping between them. Both ends sit in the 28-48px band, hence 2.7. */
/* The compact step, held constant. The header is fixed on every page, which is what the compact
   variant is for, and at 28px the mark keeps its full clear space inside a 68px bar. It does not
   scale with scroll: a logo that resizes under you is the one thing a lockup must never do. */
.logo--inline { --mark-stroke: 2.7; gap: 12px; }
.logo--inline .logo__svg { height: 28px; }
.logo--inline .logo__text { flex-direction: row; align-items: center; gap: 11px; }
.logo--inline .logo__word { font-size: 24px; line-height: 1; }
.logo--inline .logo__rule { width: 1px; height: 16px; }
.logo--inline .logo__sub { font-size: 9px; letter-spacing: .07em; }

/* In the header the lockup inherits the bar's own colour, which crossfades from all-canvas over a
   photo hero to forest on the solid bar. Both are approved colourways. */
.site-header .logo, .site-header .logo__word, .site-header .logo__sub { color: inherit; }
.site-header .logo__sub { opacity: .74; }
.site-header .logo__rule { background: currentColor; opacity: .34; }
.nav { display: flex; align-items: center; gap: 34px; font-weight: 500; font-size: 15px; }
.nav a { position: relative; padding: 6px 0; opacity: .92; }
.nav a::after { content: ""; position: absolute; left: 0; right: 100%; bottom: 0; height: 1.5px; background: currentColor; transition: right .5s var(--ease); }
.nav a:hover::after, .nav a[aria-current]::after { right: 0; }
.nav .btn { height: 44px; padding: 0 20px; }
.nav .btn::after { display: none; }
.nav .btn-donate {
  background: color-mix(in oklab, #fff calc(100% - 100% * var(--hdr)), var(--forest) calc(100% * var(--hdr)));
  color: color-mix(in oklab, var(--forest) calc(100% - 100% * var(--hdr)), #fff calc(100% * var(--hdr)));
}
/* Menu button: three rules that fold into a cross. The middle bar is the element itself, so the
   two pseudo bars only ever have to travel to it. */
.menu-btn { display: none; width: 44px; height: 44px; margin-right: -10px; align-items: center; justify-content: center; -webkit-tap-highlight-color: transparent; }
.menu-bars { width: 22px; height: 1.5px; background: currentColor; position: relative; transition: background .2s .18s; }
.menu-bars::before, .menu-bars::after { content: ""; position: absolute; left: 0; right: 0; height: 1.5px; background: currentColor; transition: transform .34s var(--ease), top .28s var(--ease) .12s; }
.menu-bars::before { top: -6.5px; } .menu-bars::after { top: 6.5px; }
.menu-btn[aria-expanded="true"] .menu-bars { background: transparent; transition-delay: 0s; }
.menu-btn[aria-expanded="true"] .menu-bars::before { top: 0; transform: rotate(45deg); transition: top .2s var(--ease), transform .34s var(--ease) .14s; }
.menu-btn[aria-expanded="true"] .menu-bars::after { top: 0; transform: rotate(-45deg); transition: top .2s var(--ease), transform .34s var(--ease) .14s; }

/* Mobile menu: a sheet that slides out from under the bar, over a dimmed page.
   It sits outside .site-header in the markup - see the note in partials/header.njk. */
.menu-scrim { position: fixed; inset: 0; z-index: 89; background: rgba(6, 18, 12, .44); opacity: 0; transition: opacity .42s var(--ease); }
.menu-scrim[hidden] { display: none; }
.menu-scrim.is-open { opacity: 1; }

.mobile-nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 95;
  max-height: 100svh; overflow-y: auto; overscroll-behavior: contain;
  padding: calc(var(--header-h) + 4px) var(--gutter) 24px;
  background: var(--canvas); color: var(--forest);
  border-radius: 0 0 24px 24px;
  box-shadow: 0 32px 64px -34px rgba(6, 18, 12, .55);
  transform: translateY(-101%);
  transition: transform .5s cubic-bezier(.22, 1, .32, 1);
}
.mobile-nav[hidden] { display: none; }
.mobile-nav.is-open { transform: none; }
.mobile-nav-inner { display: grid; }
.mobile-nav a {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 16px 2px; border-top: 1px solid var(--line);
  font-family: var(--display); font-weight: 500; font-size: 27px; line-height: 1.1;
  color: var(--forest); -webkit-tap-highlight-color: transparent;
}
.mobile-nav a:first-child { border-top: 0; }
.mobile-nav a[aria-current] { color: var(--leaf); }
.mn-chev { width: 16px; height: 16px; flex: none; opacity: .3; transition: transform .4s var(--ease), opacity .3s; }
.mobile-nav a:active .mn-chev, .mobile-nav a[aria-current] .mn-chev { opacity: .75; transform: translateX(3px); }
.mobile-nav .mn-give { justify-content: center; width: 100%; height: 54px; margin-top: 20px; border-top: 0; font-family: var(--sans); font-size: 16px; color: #fff; }
.mn-foot { margin: 18px 0 0; font-size: 12px; letter-spacing: .04em; color: var(--stone); }
/* Rows arrive just behind the sheet, and only on the way in - closing takes everything at once. */
.mobile-nav-inner > * { opacity: 0; transform: translateY(-10px); transition: opacity .3s var(--ease), transform .3s var(--ease); }
.mobile-nav.is-open .mobile-nav-inner > * { opacity: 1; transform: none; }
.mobile-nav.is-open .mobile-nav-inner > :nth-child(1) { transition-delay: .11s; }
.mobile-nav.is-open .mobile-nav-inner > :nth-child(2) { transition-delay: .16s; }
.mobile-nav.is-open .mobile-nav-inner > :nth-child(3) { transition-delay: .21s; }
.mobile-nav.is-open .mobile-nav-inner > :nth-child(4) { transition-delay: .26s; }
.mobile-nav.is-open .mobile-nav-inner > :nth-child(5) { transition-delay: .31s; }
.mobile-nav.is-open .mobile-nav-inner > :nth-child(n+6) { transition-delay: .36s; }

body.menu-open { overflow: hidden; }
/* The bar goes solid so the sheet reads as coming out of it, and drops its shadow so no line
   crosses the panel. */
body.menu-open .site-header { --hdr: 1; box-shadow: none; }
@media (min-width: 901px) { .mobile-nav, .menu-scrim { display: none !important; } }
@media (max-width: 900px) {
  .nav { display: none; }
  .menu-btn { display: flex; }
}

/* ---------- Footer ---------- */
.site-footer { position: relative; background: var(--forest); color: rgba(255,255,255,.82); padding: 88px 0 40px; overflow: hidden; isolation: isolate; }
.footer-bg { position: absolute; inset: 0; z-index: -1; }
.footer-bg img { width: 100%; height: 100%; object-fit: cover; opacity: .7; }
.footer-bg::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to bottom, rgba(18,56,42,.35), rgba(18,56,42,.9) 75%); }
.footer-top { display: grid; grid-template-columns: 1.5fr 1fr 1fr 1fr; gap: 40px; }

.site-footer p { max-width: 30em; margin-top: 18px; font-size: 15px; line-height: 1.6; }
.site-footer h4 { margin: 0 0 14px; font: 500 12px / 1 var(--sans); letter-spacing: .14em; text-transform: uppercase; color: var(--sprout); }
.site-footer ul { list-style: none; display: grid; gap: 10px; font-size: 15px; }
.site-footer ul a:hover { color: #fff; }
.footer-bottom { margin-top: 64px; padding-top: 22px; border-top: 1px solid rgba(255,255,255,.16); display: flex; justify-content: space-between; gap: 20px; font-size: 13px; color: rgba(255,255,255,.6); flex-wrap: wrap; }
.footer-social { display: flex; gap: 12px; margin-top: 14px; }
.footer-social-link { display: flex; align-items: center; justify-content: center; width: 34px; height: 34px; border-radius: 50%; border: 1px solid rgba(255,255,255,.28); color: rgba(255,255,255,.82); transition: color .3s, border-color .3s, background-color .3s; }
.footer-social-link svg { width: 18px; height: 18px; }
.footer-social-link:hover { color: #fff; border-color: rgba(255,255,255,.6); background: rgba(255,255,255,.08); }
@media (max-width: 900px) { .footer-top { grid-template-columns: 1fr 1fr; } }
@media (max-width: 520px) { .footer-top { grid-template-columns: 1fr; } }

/* ---------- Reveals ---------- */
.reveal { opacity: 0; transform: translateY(18px); transition: opacity .9s var(--ease), transform .9s var(--ease); transition-delay: var(--d, 0s); }
.reveal.in { opacity: 1; transform: none; }
.no-js .reveal { opacity: 1; transform: none; }

/* ---------- Forms ---------- */
.field { display: grid; gap: 8px; }
.field label { font-weight: 500; font-size: 15px; }
.input { height: 52px; padding: 0 16px; border: 1px solid var(--line-strong); border-radius: 10px; background: #fff; font: inherit; color: var(--ink); width: 100%; }
.input:focus { outline: 2px solid var(--leaf); outline-offset: 1px; border-color: transparent; }

/* ---------- CTA band (shared) ---------- */
.cta-band { position: relative; color: #fff; padding: clamp(96px, 14vw, 200px) 0; isolation: isolate; text-align: center; }
.cta-band .bg { position: absolute; inset: 0; z-index: -1; }
.cta-band .bg img { width: 100%; height: 100%; object-fit: cover; }
.cta-band .bg::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to top, rgba(6,18,12,.72), rgba(6,18,12,.35)); }
.cta-band h2 { font-size: var(--t-64); margin: 0 auto; max-width: 16ch; }
.cta-band h2 em { color: var(--sprout); }
.cta-band .lede { color: rgba(255,255,255,.82); margin: 20px auto 0; }
.cta-band .actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; margin-top: 32px; }
/* Left variant: same band, read as a column against the photograph rather than centred on it. */
.cta-band--left { text-align: left; }
.cta-band--left .wrap > * { margin-inline: 0; }
.cta-band--left h2 { margin-inline: 0; max-width: 18ch; }
.cta-band--left .lede { margin-inline: 0; }
.cta-band--left .actions { justify-content: flex-start; }
.cta-band--left .bg::after { background: linear-gradient(to right, rgba(6,18,12,.82), rgba(6,18,12,.5) 45%, rgba(6,18,12,.15)); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; animation-delay: 0s !important; transition-duration: .01ms !important; }
  .reveal { opacity: 1; transform: none; }
}

/* ---------- Pictograms ---------- */
.ico { width: 24px; height: 24px; flex: none; color: var(--leaf); }
.ico-lg { width: 32px; height: 32px; }
.ico-ring { width: 48px; height: 48px; border-radius: 50%; display: grid; place-items: center; background: var(--mist); color: var(--forest); flex: none; }
.ico-ring .ico { width: 22px; height: 22px; color: inherit; }
.ico-ring.on-dark { background: rgba(255,255,255,.1); color: var(--sprout); }

/* ---------- Motion utilities ---------- */
.reveal-stagger > * { opacity: 0; transform: translateY(16px); transition: opacity .8s var(--ease), transform .8s var(--ease); }
.reveal-stagger.in > * { opacity: 1; transform: none; }
.reveal-stagger.in > :nth-child(1) { transition-delay: 0s; } .reveal-stagger.in > :nth-child(2) { transition-delay: .08s; } .reveal-stagger.in > :nth-child(3) { transition-delay: .16s; } .reveal-stagger.in > :nth-child(4) { transition-delay: .24s; } .reveal-stagger.in > :nth-child(5) { transition-delay: .32s; } .reveal-stagger.in > :nth-child(n+6) { transition-delay: .4s; }
.zoom-img { overflow: hidden; }
.zoom-img img { transition: transform 1.4s var(--ease); }
.zoom-img:hover img, a:hover .zoom-img img { transform: scale(1.04); }
.draw path[pathLength] { stroke-dasharray: 1; stroke-dashoffset: 1; }
.draw.in path[pathLength] { transition: stroke-dashoffset 1.8s var(--ease); stroke-dashoffset: 0; }

/* ---------- Page transitions (cross-document) ---------- */
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: 260ms var(--ease) both vt-out; }
::view-transition-new(root) { animation: 420ms var(--ease) both vt-in; }
@keyframes vt-out { to { opacity: 0; } }
@keyframes vt-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
.site-header { view-transition-name: header; }

/* Patch photograph morph. The card you click and the hero you land on are the same picture, so
   the box does the travelling and both ends fill it with object-fit: cover: what you watch is one
   photograph being re-cropped from a card to the full screen.
   Set up by partials/transition-head.njk, which names the two ends across the navigation. */
.vt-morph { --morph: 700ms; --morph-ease: cubic-bezier(.4, 0, .2, 1); }
/* The card being handed over stops hovering first: see the note in partials/transition-head.njk. */
.vt-handoff { transform: none !important; transition: none !important; }
.vt-morph::view-transition-group(patch-media) { animation-duration: var(--morph); animation-timing-function: var(--morph-ease); }
/* The two ends are different crops of one photograph, so the old one is held at full opacity
   underneath and the new one is brought up over it. Fading both at once would dip through the
   page behind them; swapping outright shows the crop change as a jump. */
.vt-morph::view-transition-image-pair(patch-media) { isolation: none; }
.vt-morph::view-transition-old(patch-media),
.vt-morph::view-transition-new(patch-media) { mix-blend-mode: normal; width: 100%; height: 100%; object-fit: cover; }
.vt-morph::view-transition-old(patch-media) { animation: none; opacity: 1; }
.vt-morph::view-transition-new(patch-media) { animation: 380ms var(--morph-ease) both vt-hold-in; }
/* The page being left is held at full opacity rather than faded out: the photograph lifts off it
   and grows over it, so there is never a moment of bare canvas showing through two half-faded
   pages. The page being entered rises underneath the photograph on the same curve and the same
   clock, so the vignette deepens as the picture grows instead of stepping in once it lands. */
.vt-morph::view-transition-old(root) { animation: none; opacity: 1; }
.vt-morph::view-transition-new(root) { animation: var(--morph) var(--morph-ease) both vt-hold-in; }
@keyframes vt-hold-in { from { opacity: 0; } to { opacity: 1; } }
/* Only the words wait: they rise as the photograph settles. */
.vt-morph-in::view-transition-old(patch-copy) { animation: none; opacity: 0; }
.vt-morph-in::view-transition-new(patch-copy) { animation: 500ms var(--ease) 540ms both vt-copy-rise; }
.vt-morph::view-transition-old(patch-copy) { animation: 200ms linear both vt-out; }
@keyframes vt-copy-rise { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; } .reveal-stagger > * { opacity: 1; transform: none; } .draw path[pathLength] { stroke-dashoffset: 0; } }

/* Photo heroes on inner pages: keep the header legible over bright sky */
.page-about [data-hero]::before, .page-support-index [data-hero]::before, .page-supporter [data-hero]::before, .page-corporate [data-hero]::before, .page-patch [data-hero]::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 240px; z-index: 0; pointer-events: none; background: linear-gradient(to bottom, rgba(6,18,12,.55), transparent); }

/* Partners band (shared) */
.partners-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 24px 40px; padding: 34px 44px; border-radius: var(--r-20); background: var(--forest); color: #fff; }
.partners-label { font-family: var(--display); font-style: italic; font-size: var(--t-22); color: var(--sprout); }
.partners-row img { height: 52px; width: auto; opacity: .95; }
.partners-word { font-family: var(--display); font-weight: 600; font-size: var(--t-36); }
@media (max-width: 700px) { .partners-row { justify-content: start; } }

/* ---------- Thread link: the animated connection between a patch and its match ---------- */
.thread-link { position: relative; width: clamp(160px, 22vw, 320px); height: 80px; align-self: center; justify-self: center; flex: none; }
.thread-link svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; fill: none; }
.thread-link .tl-base { stroke: var(--line-strong); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.thread-link .tl-flow { stroke: var(--leaf); stroke-width: 3; stroke-linecap: round; stroke-dasharray: 10 14; vector-effect: non-scaling-stroke; animation: tlflow 1.8s linear infinite; }
@keyframes tlflow { to { stroke-dashoffset: -24; } }
.thread-link .tl-dot { position: absolute; top: 50%; width: 12px; height: 12px; border-radius: 50%; transform: translate(-50%, -50%); }
.thread-link .tl-dot-a { left: 3%; background: var(--sprout); box-shadow: 0 0 0 2.5px #fff, 0 0 0 4px var(--leaf); }
.thread-link .tl-dot-b { left: 97%; background: var(--canvas); box-shadow: 0 0 0 2.5px var(--leaf); }
.thread-link .tl-pill { position: absolute; left: 50%; top: -10px; transform: translate(-50%, -100%); white-space: nowrap; font: 500 12.5px / 1 var(--sans); letter-spacing: .02em; color: var(--forest); background: var(--mist); padding: 8px 14px; border-radius: 4px; }
.thread-link.on-dark .tl-base { stroke: rgba(255,255,255,.22); }
.thread-link.on-dark .tl-flow { stroke: var(--sprout); }
.thread-link.on-dark .tl-dot-a { box-shadow: 0 0 0 2.5px var(--void), 0 0 0 4px var(--sprout); }
.thread-link.on-dark .tl-dot-b { background: var(--void); box-shadow: 0 0 0 2.5px var(--sprout); }
.thread-link.on-dark .tl-pill { background: rgba(6,18,12,.7); color: #fff; }
@media (max-width: 900px) {
  .thread-link { width: 80px; height: 120px; margin: 0 auto; }
  .thread-link svg { width: 120px; height: 80px; inset: auto; left: 50%; top: 50%; transform: translate(-50%, -50%) rotate(90deg); }
  .thread-link .tl-dot { left: 50%; }
  .thread-link .tl-dot-a { top: 3%; } .thread-link .tl-dot-b { top: 97%; }
  .thread-link .tl-pill { top: 50%; left: calc(50% + 28px); transform: translateY(-50%); }
}
@media (prefers-reduced-motion: reduce) { .thread-link .tl-flow { animation: none; } }

/* Under 760px the horizontal lockup gives way to the stacked one at its 25px step, and the footer
   lockup drops to the 36px step so it does not dominate a phone screen. */
@media (max-width: 760px) {
  .logo--inline { --mark-stroke: 2.7; gap: 14px; }
  .logo--inline .logo__svg { height: 34px; }
  .logo--inline .logo__text { flex-direction: column; align-items: flex-start; gap: 4px; }
  .logo--inline .logo__word { font-size: 25px; line-height: .85; }
  .logo--inline .logo__rule { width: 100%; height: 1px; }
  .logo--inline .logo__sub { font-size: 8px; letter-spacing: .07em; }
  .logo--stacked { --mark-stroke: 2.7; gap: 16px; }
  .logo--stacked .logo__svg { height: 47px; }
  .logo--stacked .logo__word { font-size: 36px; }
  .logo--stacked .logo__text { gap: 4px; }
}

/* Visually hidden, kept in the accessibility tree. The map page carried its own copy of this;
   nav markers need it everywhere. */
.vh { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* Preview build: a nav item whose page is not finished yet. Quietened, with a small marker, so it
   reads as work in progress rather than a link that failed. */
.nav a.is-soon, .mobile-nav a.is-soon { opacity: .55; }
.nav a.is-soon::after, .mobile-nav a.is-soon .mn-label::after { content: ""; display: inline-block; width: 4px; height: 4px; margin-left: 7px; border-radius: 50%; background: currentColor; vertical-align: .35em; }
.nav a.is-soon:hover, .mobile-nav a.is-soon:hover { opacity: .8; }

/* The site says out loud that its place pictures are illustrations. Quiet, but on every page. */
.footer-imagery { margin-top: 56px; max-width: 62ch; font-size: 13px; line-height: 1.6; color: rgba(255,255,255,.62); }
.footer-imagery a { color: var(--sprout); text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
.footer-imagery a:hover { color: #fff; }

/* ---------- Kind label: plain uppercase tag, urban on leaf, wild on forest ---------- */
.tag-kind { background: var(--leaf); color: #fff; }
.tag-kind-wild { background: var(--forest); color: var(--sprout); }

/* ---------- Leaf glyph on primary actions ---------- */
/* Jess's buttons carry a leaf after the label. Use: <a class="btn btn-primary">Label {{ leaf | safe }}</a>
   where leaf is the same svg the arrow is, with class "leaf": {% set icon = 'leaf' %}{% set iconClass = 'leaf' %}{% include "partials/icons.njk" %} */
.btn .leaf { width: 17px; height: 17px; color: inherit; opacity: .9; transition: transform .5s var(--ease); }
.btn:hover .leaf { transform: translateY(-2px) rotate(-8deg); }
.btn-primary .leaf, .btn-donate .leaf { color: var(--sprout); }
.btn-light .leaf { color: var(--leaf); }
/* The Whole Wild World mark is round, so it needs more height than a wordmark to read at the same weight. */
.partners-row img[alt="Whole Wild World"] { height: 84px; }
