/* ==========================================================================
   TRAJECTORY
   Luxe minimal · black / white / jade hairline
   --------------------------------------------------------------------------
   0.  Webfont
   1.  Tokens
   2.  Reset & base
   3.  Typography primitives
   4.  Layout primitives
   5.  Buttons & links
   6.  Reveal system
   7.  Header
   8.  Hero
   9.  Ticker
   10. Events
   11. Idea / manifesto
   12. Join
   12b.Gallery + lightbox
   13. Instagram
   13b.Books
   14. Footer
   15. Message page
   16. Responsive
   ========================================================================== */

/* ---------------------------------------------------------------- Webfont
   Montserrat is self-hosted rather than pulled from the Google Fonts CDN:
   no third-party request on page load (which also keeps the site clear of the
   GDPR complaints that CDN-hosted Google Fonts have attracted in the EU), one
   less thing that can be slow or blocked, and the exact weights we use and
   nothing more. Latin subset, woff2 only — every browser that matters supports it.
   ------------------------------------------------------------------------- */
@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("../fonts/montserrat-latin-300-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/montserrat-latin-400-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/montserrat-latin-500-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/montserrat-latin-600-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/montserrat-latin-700-normal.woff2") format("woff2");
}

/* ------------------------------------------------------------------ 1. Tokens */
:root {
  /* colour */
  --ink:          #000000;
  --ink-raise:    #060606;
  --ink-panel:    #0a0a0a;
  --paper:        #ffffff;
  /* Neutrals carry a faint green bias so they sit with the accent instead of
     reading as generic greys on a black ground. */
  --mute:         #85908c;
  --mute-soft:    #b1bab6;
  --accent:       #009c72;
  --accent-lift:  #00b885;   /* hover / focus brightening only */
  --accent-soft:  rgba(0, 156, 114, .45);
  --accent-ghost: rgba(0, 156, 114, .12);
  --hair:         rgba(255, 255, 255, .12);
  --hair-strong:  rgba(255, 255, 255, .26);

  /* type — one family. Hierarchy comes from weight, size and tracking,
     because there is no second face to carry the contrast. */
  --font-display: "Montserrat", "Helvetica Neue", Arial, sans-serif;
  --font-ui:      "Montserrat", "Helvetica Neue", Arial, sans-serif;

  /* Uppercase runs far wider per character than mixed case, so the display
     sizes sit well below where a sentence-case scale would land. */
  --fs-hero:  clamp(2rem, 4.6vw, 4.5rem);
  --fs-h2:    clamp(1.625rem, 3.4vw, 3rem);
  --fs-h3:    clamp(1.0625rem, 1.6vw, 1.375rem);
  --fs-lead:  clamp(1rem, 1.25vw, 1.1875rem);
  --fs-body:  clamp(.9375rem, 1.05vw, 1.0625rem);
  --fs-label: .6875rem;

  --ls-label: .28em;
  --ls-meta:  .16em;
  --ls-display: .015em;   /* caps set tight look cramped; a hair of air fixes it */

  /* layout */
  --shell:    1480px;
  --gutter:   clamp(1.25rem, 5vw, 6rem);
  --section:  clamp(6rem, 13vh, 11rem);

  /* motion */
  --ease:     cubic-bezier(.22, .61, .36, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --dur:      .7s;
}

/* ------------------------------------------------------- 2. Reset & base */
*, *::before, *::after { box-sizing: border-box; }

/* The `hidden` attribute is only a UA-level `display: none`, so ANY author
   rule that sets display beats it — `.egrid { display: grid }` did exactly
   that, leaving the gallery panel rendering underneath the index list and
   every event on the page twice. This is why normalize.css carries the same
   rule. Anything that must be hidden while keeping layout should use
   visibility or opacity, not this attribute. */
[hidden] { display: none !important; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-ui);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img, svg, video { display: block; max-width: 100%; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }
input, textarea, select { font: inherit; color: inherit; }

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

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

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

.skip-link {
  position: absolute; top: -100px; left: var(--gutter); z-index: 200;
  padding: .9rem 1.4rem; background: var(--paper); color: var(--ink);
  font-size: var(--fs-label); letter-spacing: var(--ls-label); text-transform: uppercase;
}
.skip-link:focus { top: 1rem; }

/* Film grain — barely there, but it kills the flatness of pure black. */
.grain {
  position: fixed; inset: 0; z-index: 3; pointer-events: none;
  opacity: .035; mix-blend-mode: screen;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* --------------------------------------------- 3. Typography primitives */
.label {
  margin: 0;
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--mute);
}
.label--accent { color: var(--accent); }
.label--paper { color: var(--paper); }

.label-dot {
  display: inline-block;
  width: 4px; height: 4px;
  margin-right: .85em;
  vertical-align: middle;
  background: var(--accent);
  border-radius: 50%;
}
.label-dot--pulse { animation: pulse 2.8s var(--ease) infinite; }

@keyframes pulse {
  0%, 100% { opacity: 1;   transform: scale(1); }
  50%      { opacity: .35; transform: scale(.7); }
}

/* All display type is uppercase. Caps carry no descenders, so the leading is
   tighter than mixed case would take, and `balance` stops a short heading
   dropping one orphaned word onto its own line. */
.display {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: var(--ls-display);
  text-transform: uppercase;
  text-wrap: balance;
}
.display--hero { font-size: var(--fs-hero); line-height: 1.06; }
.display--h2   { font-size: var(--fs-h2);   line-height: 1.08; }
.display--h3   { font-size: var(--fs-h3);   line-height: 1.26; letter-spacing: .03em; }

/* Emphasis is carried by colour — italic caps read as a mistake. */
.display em {
  font-style: normal;
  color: var(--accent);
}

.lead {
  font-size: var(--fs-lead);
  line-height: 1.72;
  color: var(--mute-soft);
  font-weight: 300;
}

.meta {
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
  color: var(--mute-soft);
}

/* ------------------------------------------------- 4. Layout primitives */
.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: var(--section); position: relative; }
.section--tight { padding-block: clamp(4rem, 8vh, 7rem); }

.rule {
  height: 1px;
  background: var(--hair);
  border: 0;
  margin: 0;
  transform-origin: left center;
}
.rule--accent { background: var(--accent-soft); }

/* A hairline that draws itself in on reveal. */
.rule--draw { transform: scaleX(0); transition: transform 1.1s var(--ease-out); }
.is-revealed .rule--draw,
.rule--draw.is-revealed { transform: scaleX(1); }

.section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 2rem;
  flex-wrap: wrap;
  margin-bottom: clamp(2.5rem, 5vw, 4.5rem);
}
.section-head__text { max-width: 100%; }
.section-head__text .lead,
.section-head__text p:not(.label) { max-width: 40ch; }
.section-head .label { margin-bottom: 1.4rem; }

/* --------------------------------------------------- 5. Buttons & links */
.btn {
  --btn-fg: var(--paper);
  display: inline-flex;
  align-items: center;
  gap: 1.1em;
  padding: 1.15rem 2.1rem;
  position: relative;
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--btn-fg);
  border: 1px solid var(--hair-strong);
  overflow: hidden;
  transition: color .5s var(--ease), border-color .5s var(--ease);
}
.btn > * { position: relative; z-index: 1; }

/* Gold wipe from the left on hover. */
.btn::before {
  content: "";
  position: absolute; inset: 0;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform .55s var(--ease-out);
}
.btn:hover, .btn:focus-visible { color: var(--ink); border-color: var(--accent); }
.btn:hover::before, .btn:focus-visible::before { transform: scaleX(1); }

.btn svg {
  width: 18px; height: 18px;
  fill: none; stroke: currentColor; stroke-width: 1.1;
  stroke-linecap: round; stroke-linejoin: round;
  transition: transform .5s var(--ease-out);
}
.btn:hover svg { transform: translateX(5px); }

.btn--accent { border-color: var(--accent); }
.btn--ghost { border-color: var(--hair); }
.btn--block { width: 100%; justify-content: center; }
.btn--sm { padding: .85rem 1.5rem; }

/* Understated text link with a rule that grows. */
.tlink {
  display: inline-flex; align-items: center; gap: .8em;
  padding-bottom: .45rem;
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--mute-soft);
  position: relative;
  transition: color .4s var(--ease);
}
.tlink::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 1px; background: var(--hair-strong);
  transform: scaleX(0); transform-origin: right center;
  transition: transform .5s var(--ease-out), background-color .4s var(--ease);
}
.tlink:hover { color: var(--paper); }
.tlink:hover::after { transform: scaleX(1); transform-origin: left center; background: var(--accent-lift); }
.tlink svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.1; }

/* ---------------------------------------------------- 6. Reveal system
   The hidden state is applied only when JS is running (html.js). If the
   script fails to load or throws, every section stays visible instead of
   the page rendering blank. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(26px);
  transition:
    opacity  .95s var(--ease-out) calc(var(--i, 0) * 85ms),
    transform .95s var(--ease-out) calc(var(--i, 0) * 85ms);
  will-change: opacity, transform;
}
.js [data-reveal].is-revealed { opacity: 1; transform: none; }

.js [data-reveal="mask"] {
  opacity: 1;
  transform: none;
  clip-path: inset(0 0 100% 0);
  transition: clip-path 1.15s var(--ease-out) calc(var(--i, 0) * 85ms);
}
.js [data-reveal="mask"].is-revealed { clip-path: inset(0 0 0 0); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .js [data-reveal] { opacity: 1 !important; transform: none !important; clip-path: none !important; }
}

/* ---------------------------------------------------------- 7. Header */
.header {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  transition: background-color .5s var(--ease), backdrop-filter .5s var(--ease);
}
.header::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: var(--hair);
  transform: scaleX(0); transform-origin: center;
  transition: transform .8s var(--ease-out);
}
.header.is-stuck {
  background: rgba(0, 0, 0, .72);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
}
.header.is-stuck::after { transform: scaleX(1); }

.header__inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 2rem;
  height: clamp(76px, 8vh, 104px);
  transition: height .5s var(--ease);
}
.header.is-stuck .header__inner { height: clamp(64px, 6.5vh, 80px); }

.header__logo img {
  width: clamp(132px, 12vw, 176px);
  height: auto;
  transition: width .5s var(--ease), opacity .4s var(--ease);
}
.header__logo:hover img { opacity: .72; }

.nav { display: flex; align-items: center; gap: clamp(1.5rem, 3vw, 3rem); }
.nav__links { display: flex; align-items: center; gap: clamp(1.5rem, 3vw, 3rem); }

.nav__link {
  position: relative;
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--mute-soft);
  padding-block: .4rem;
  transition: color .4s var(--ease);
}
.nav__link::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 1px; background: var(--accent);
  transform: scaleX(0); transform-origin: right center;
  transition: transform .45s var(--ease-out);
}
.nav__link:hover { color: var(--paper); }
.nav__link:hover::after,
.nav__link.is-active::after { transform: scaleX(1); transform-origin: left center; }
.nav__link.is-active { color: var(--paper); }

.nav__cta { margin-left: clamp(.5rem, 2vw, 1.5rem); }

/* Mobile menu */
.burger {
  display: none;
  width: 42px; height: 42px;
  position: relative;
  margin-right: -8px;
}
.burger span {
  position: absolute; left: 9px; right: 9px; height: 1px;
  background: var(--paper);
  transition: transform .45s var(--ease-out), opacity .3s var(--ease);
}
.burger span:nth-child(1) { top: 17px; }
.burger span:nth-child(2) { top: 24px; }
.burger.is-open span:nth-child(1) { transform: translateY(3.5px) rotate(45deg); }
.burger.is-open span:nth-child(2) { transform: translateY(-3.5px) rotate(-45deg); }

.drawer {
  position: fixed; inset: 0; z-index: 99;
  background: var(--ink);
  padding: clamp(120px, 18vh, 180px) var(--gutter) var(--gutter);
  display: flex; flex-direction: column; justify-content: space-between;
  clip-path: inset(0 0 100% 0);
  transition: clip-path .75s var(--ease-out);
  visibility: hidden;
}
.drawer.is-open { clip-path: inset(0 0 0 0); visibility: visible; }

.drawer__nav { display: flex; flex-direction: column; gap: clamp(1rem, 3vh, 2rem); }
.drawer__link {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 6.5vw, 2.5rem);
  font-weight: 600;
  line-height: 1.1;
  text-transform: uppercase; letter-spacing: .03em;
  color: var(--paper);
  opacity: 0; transform: translateY(20px);
  transition: opacity .6s var(--ease-out), transform .6s var(--ease-out), color .3s var(--ease);
}
.drawer.is-open .drawer__link { opacity: 1; transform: none; transition-delay: calc(.18s + var(--i) * .07s); }
.drawer__link:hover { color: var(--accent); }
.drawer__foot { display: flex; gap: 1.5rem; flex-wrap: wrap; padding-top: 2rem; border-top: 1px solid var(--hair); }

body.is-locked { overflow: hidden; }

/* ------------------------------------------------------------ 8. Hero */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: flex-end;
  padding-top: clamp(120px, 16vh, 190px);
  padding-bottom: clamp(2.5rem, 6vh, 5rem);
  overflow: hidden;
}

.hero__bg {
  position: absolute; inset: 0; z-index: 0;
  overflow: hidden;
}
.hero__bg img {
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: .34;
  filter: contrast(1.05) saturate(1.06);
  transform: scale(1.06);
  animation: heroDrift 26s var(--ease) infinite alternate;
}
@keyframes heroDrift {
  from { transform: scale(1.06) translate3d(0, 0, 0); }
  to   { transform: scale(1.14) translate3d(0, -2%, 0); }
}
/* Vignette + floor fade so type always sits on near-black. */
.hero__bg::after {
  content: "";
  position: absolute; inset: 0;
  background:
    linear-gradient(to top, var(--ink) 3%, rgba(0,0,0,.58) 40%, rgba(0,0,0,.3) 100%),
    radial-gradient(115% 88% at 76% 32%, rgba(0,0,0,.1) 0%, rgba(0,0,0,.76) 76%);
}

.hero__inner { position: relative; z-index: 1; width: 100%; }

.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .95fr);
  gap: clamp(2rem, 4.5vw, 4.5rem);
  align-items: end;
}

.hero__eyebrow {
  display: flex; align-items: center; gap: 1.4rem;
  flex-wrap: wrap;
  margin-bottom: clamp(1.5rem, 3vw, 2.25rem);
}
.hero__eyebrow .divider {
  width: 46px; height: 1px; background: var(--accent-soft);
}

.hero__title { margin-bottom: clamp(1.5rem, 3vw, 2.5rem); max-width: 17ch; }

.hero__meta {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: clamp(1rem, 2.4vw, 2.25rem);
  padding-top: 1.6rem;
  border-top: 1px solid var(--hair);
  margin-bottom: clamp(2rem, 4vw, 3rem);
}
.hero__meta-item { display: flex; align-items: center; gap: .7rem; }
.hero__meta-item svg {
  width: 15px; height: 15px; flex: none;
  fill: none; stroke: var(--accent); stroke-width: 1.05;
  stroke-linecap: round; stroke-linejoin: round;
}
.hero__meta-sep { width: 1px; height: 14px; background: var(--hair); }

.hero__actions { display: flex; flex-wrap: wrap; align-items: center; gap: clamp(1rem, 2.5vw, 2rem); }

/* Countdown */
.countdown {
  display: flex;
  gap: clamp(1.25rem, 3vw, 2.75rem);
  padding: clamp(1.25rem, 2.4vw, 1.85rem) 0;
  border-top: 1px solid var(--hair);
  border-bottom: 1px solid var(--hair);
  margin-bottom: clamp(1.75rem, 3.5vw, 2.5rem);
}
.countdown__cell { display: flex; flex-direction: column; gap: .55rem; min-width: 3.4ch; }
.countdown__num {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 3vw, 2.75rem);
  font-weight: 300;
  line-height: .95;
  letter-spacing: -.01em;
  font-variant-numeric: tabular-nums;
}
.countdown__label {
  font-size: .625rem;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--mute);
}
.countdown--done .countdown__num { color: var(--accent); }

/* Framed hero image */
.hero__frame {
  position: relative;
  align-self: center;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--hair);
  padding: 10px;
  overflow: hidden;
}
.hero__frame::after {
  content: "";
  position: absolute; inset: 10px;
  border: 1px solid var(--accent-ghost);
  pointer-events: none;
  z-index: 2;
  transition: border-color .55s var(--ease);
}
.hero__frame:hover::after { border-color: var(--accent-soft); }
.hero__frame img {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: contrast(1.03) saturate(1.04);
  transition: transform 1.4s var(--ease-out);
}
.hero__frame:hover img { transform: scale(1.045); }

.hero__frame-tag {
  position: absolute; left: 10px; bottom: 10px; right: 10px;
  /* The tall top padding is the point: it gives the gradient room to fade out
     over ~150px instead of ending abruptly and drawing a line across the
     photograph. The type then sits on near-solid black rather than on picture. */
  padding: 4rem 1.15rem 1.15rem;
  /* Holds near-solid black across both lines of type, then releases. The small
     accent date line is the one at risk: it is the lightest weight on the page
     and it sits highest in the scrim. */
  background: linear-gradient(
    to top,
    rgba(0, 0, 0, .95) 0%,
    rgba(0, 0, 0, .93) 38%,
    rgba(0, 0, 0, .80) 58%,
    rgba(0, 0, 0, .40) 80%,
    rgba(0, 0, 0, 0) 100%
  );
}

/* Scroll cue */
.scroll-cue {
  display: flex; align-items: center; gap: 1rem;
  margin-top: clamp(1.75rem, 3.5vh, 3rem);
}
.scroll-cue__line { width: 64px; height: 1px; background: var(--hair-strong); position: relative; overflow: hidden; }
.scroll-cue__line::after {
  content: ""; position: absolute; inset: 0;
  background: var(--accent);
  animation: cue 2.6s var(--ease) infinite;
}
@keyframes cue {
  0%   { transform: translateX(-100%); }
  55%  { transform: translateX(0); }
  100% { transform: translateX(100%); }
}

/* Empty hero */
.hero--empty .hero__title { max-width: 20ch; }

/* --------------------------------------------------------- 9. Ticker */
.ticker {
  border-block: 1px solid var(--hair);
  overflow: hidden;
  padding-block: 1.15rem;
}
.ticker__track {
  display: flex;
  width: max-content;
  animation: marquee 46s linear infinite;
}
.ticker:hover .ticker__track { animation-play-state: paused; }
.ticker__item {
  display: flex; align-items: center; gap: 2.5rem;
  padding-inline: 1.25rem;
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--mute);
  white-space: nowrap;
}
.ticker__item b { font-weight: 400; color: var(--paper); }
.ticker__item::after { content: ""; width: 3px; height: 3px; background: var(--accent); border-radius: 50%; }
@keyframes marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* -------------------------------------------------------- 10. Events */
.events__toggle {
  display: inline-flex;
  border: 1px solid var(--hair);
}
.events__toggle button {
  padding: .8rem 1.4rem;
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--mute);
  transition: color .35s var(--ease), background-color .35s var(--ease);
}
.events__toggle button + button { border-left: 1px solid var(--hair); }
.events__toggle button.is-active { color: var(--ink); background: var(--paper); }

.filters { display: flex; flex-wrap: wrap; gap: .6rem; margin-bottom: 2.5rem; }
.filters button {
  padding: .55rem 1.1rem;
  font-size: var(--fs-label);
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
  color: var(--mute);
  border: 1px solid var(--hair);
  transition: color .35s var(--ease), border-color .35s var(--ease);
}
.filters button:hover { color: var(--paper); border-color: var(--hair-strong); }
.filters button.is-active { color: var(--accent); border-color: var(--accent-soft); }

/* --- Index view: editorial rows --------------------------------------- */
.elist { border-top: 1px solid var(--hair); }

.erow {
  position: relative;
  display: grid;
  grid-template-columns: clamp(88px, 9vw, 128px) minmax(0, 1fr) minmax(0, .5fr) 44px;
  align-items: center;
  gap: clamp(1rem, 3vw, 2.5rem);
  padding: clamp(1.6rem, 3vw, 2.4rem) 0;
  border-bottom: 1px solid var(--hair);
  isolation: isolate;
  transition: padding-left .6s var(--ease-out);
}

/* Ghost image that fades in behind the row on hover — the whole trick. */
.erow__ghost {
  position: absolute; inset: 0; z-index: -1;
  overflow: hidden;
  opacity: 0;
  transition: opacity .65s var(--ease);
}
.erow__ghost img {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: contrast(1.04) saturate(1.05);
  transform: scale(1.08);
  transition: transform 1.6s var(--ease-out);
}
.erow__ghost::after {
  content: "";
  position: absolute; inset: 0;
  /* The horizontal curtain is what makes a colour photograph safe to put
     behind body copy: heaviest under the title, lifting through the middle,
     heavy again at the right edge. Measured at 7.7:1 worst case against a
     deliberately blown-out test photo, so real ones have room to spare. */
  background:
    linear-gradient(90deg, rgba(0,0,0,.96) 24%, rgba(0,0,0,.74) 62%, rgba(0,0,0,.94) 100%),
    linear-gradient(rgba(0,0,0,.2), rgba(0,0,0,.2));
}
.erow:hover .erow__ghost { opacity: .72; }
.erow:hover .erow__ghost img { transform: scale(1); }

/* Gold indicator that grows from the left edge. */
.erow::before {
  content: "";
  position: absolute; left: 0; top: 0; bottom: -1px;
  width: 2px; background: var(--accent);
  transform: scaleY(0); transform-origin: bottom center;
  transition: transform .6s var(--ease-out);
}
.erow:hover::before { transform: scaleY(1); transform-origin: top center; }
.erow:hover { padding-left: clamp(1rem, 2vw, 2rem); }

.erow__date { display: flex; flex-direction: column; gap: .25rem; }
.erow__day {
  font-family: var(--font-display);
  font-size: clamp(1.875rem, 3vw, 2.75rem);
  font-weight: 300; line-height: .9;
  letter-spacing: -.01em;
  font-variant-numeric: tabular-nums;
  transition: color .45s var(--ease);
}
.erow:hover .erow__day { color: var(--accent-lift); }
.erow__month { font-size: .625rem; letter-spacing: .24em; text-transform: uppercase; color: var(--mute); }

.erow__body { min-width: 0; }
.erow__title {
  font-family: var(--font-display);
  font-size: clamp(1rem, 1.5vw, 1.3125rem);
  font-weight: 600; line-height: 1.24;
  text-transform: uppercase;
  letter-spacing: .035em;
  margin: 0 0 .6rem;
  transition: transform .6s var(--ease-out);
}
.erow:hover .erow__title { transform: translateX(6px); }
.erow__sub {
  font-size: var(--fs-label);
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
  color: var(--mute);
  display: flex; flex-wrap: wrap; align-items: center; gap: .65rem;
}
.erow__sub .dot { width: 3px; height: 3px; background: currentColor; border-radius: 50%; opacity: .6; }

.erow__where {
  font-size: var(--fs-label);
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
  color: var(--mute-soft);
  text-align: right;
}
.erow__where span { display: block; }
.erow__where .venue { color: var(--paper); margin-bottom: .25rem; }

.erow__go {
  justify-self: end;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border: 1px solid var(--hair);
  border-radius: 50%;
  transition: background-color .45s var(--ease), border-color .45s var(--ease), transform .45s var(--ease-out);
}
.erow__go svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.1; stroke-linecap: round; stroke-linejoin: round; }
.erow:hover .erow__go { background: var(--accent); border-color: var(--accent); color: var(--ink); transform: rotate(-45deg); }

.erow__link { position: absolute; inset: 0; z-index: 2; }

/* --- Gallery view: image cards ---------------------------------------- */
.egrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
  gap: clamp(1.25rem, 2.5vw, 2.25rem);
}

.ecard { position: relative; display: block; }
.ecard__media {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border: 1px solid var(--hair);
  background: var(--ink-panel);
}
.ecard__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transform: scale(1.02);
  transition: transform 1.3s var(--ease-out);
}
.ecard:hover .ecard__media img { transform: scale(1.08); }
.ecard__media::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(0,0,0,.9) 6%, rgba(0,0,0,.34) 40%, transparent 64%);
}

.ecard__stamp {
  position: absolute; top: 0; left: 0; z-index: 2;
  padding: .85rem 1.05rem;
  background: var(--ink);
  border-right: 1px solid var(--hair);
  border-bottom: 1px solid var(--hair);
  text-align: center;
}
.ecard__stamp .d {
  display: block;
  font-family: var(--font-display);
  font-size: 1.5rem; line-height: 1; font-weight: 300;
}
.ecard__stamp .m { display: block; font-size: .625rem; letter-spacing: .22em; text-transform: uppercase; color: var(--accent); margin-top: .3rem; }

.ecard__caption { position: absolute; left: 0; right: 0; bottom: 0; z-index: 2; padding: 1.35rem; }
.ecard__title {
  font-family: var(--font-display);
  font-size: 1.0625rem; font-weight: 600; line-height: 1.28;
  text-transform: uppercase; letter-spacing: .04em;
  margin: 0 0 .55rem;
}
.ecard__meta { font-size: .625rem; letter-spacing: .2em; text-transform: uppercase; color: var(--mute-soft); }

/* --- Loading / empty --------------------------------------------------- */
.skeleton { border-top: 1px solid var(--hair); }
.skel-row {
  display: grid;
  grid-template-columns: clamp(88px, 9vw, 128px) minmax(0, 1fr) minmax(0, .5fr);
  gap: 2rem; align-items: center;
  padding: clamp(1.6rem, 3vw, 2.4rem) 0;
  border-bottom: 1px solid var(--hair);
}
.shimmer {
  height: 12px;
  background: linear-gradient(90deg, rgba(255,255,255,.05) 0%, rgba(255,255,255,.13) 50%, rgba(255,255,255,.05) 100%);
  background-size: 200% 100%;
  animation: shimmer 1.6s linear infinite;
}
.shimmer.tall { height: 34px; }
.shimmer.w60 { width: 60%; }
.shimmer.w40 { width: 40%; }
@keyframes shimmer {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}

.empty {
  padding: clamp(3rem, 8vw, 6rem) 0;
  border-top: 1px solid var(--hair);
  text-align: center;
}
.empty .display { margin-bottom: 1.25rem; }

.notice {
  display: inline-flex; align-items: center; gap: .8rem;
  margin-bottom: 2rem;
  padding: .7rem 1.1rem;
  border: 1px solid var(--accent-soft);
  background: var(--accent-ghost);
  font-size: var(--fs-label);
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
  color: var(--accent);
}

/* ----------------------------------------------------------- 11. Idea */
.idea__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  gap: clamp(2.5rem, 7vw, 7rem);
  align-items: start;
}
.idea__statement { position: sticky; top: clamp(110px, 14vh, 160px); }
.idea__statement .display { margin-bottom: 2rem; max-width: 14ch; }

.principles { border-top: 1px solid var(--hair); }
.principle {
  display: grid;
  grid-template-columns: 2.75rem minmax(0, 1fr);
  gap: clamp(1rem, 2vw, 2rem);
  padding: clamp(1.75rem, 3vw, 2.5rem) 0;
  border-bottom: 1px solid var(--hair);
}
.principle__num {
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0;
  color: var(--accent);
  padding-top: .1rem;
}
.principle__title {
  font-family: var(--font-display);
  font-size: clamp(1rem, 1.35vw, 1.1875rem);
  font-weight: 600; line-height: 1.3;
  text-transform: uppercase; letter-spacing: .045em;
  margin: 0 0 .8rem;
}
.principle__copy { margin: 0; color: var(--mute-soft); font-size: var(--fs-body); }

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: clamp(1.5rem, 4vw, 3rem);
  margin-top: clamp(3rem, 7vw, 5.5rem);
  padding-top: clamp(2rem, 4vw, 3rem);
  border-top: 1px solid var(--hair);
}
.stat__num {
  font-family: var(--font-display);
  font-size: clamp(2rem, 3.8vw, 3.25rem);
  font-weight: 300; line-height: 1;
  letter-spacing: -.015em;
  font-variant-numeric: tabular-nums;
  margin-bottom: .7rem;
}
.stat__num .plus { color: var(--accent); }

/* The closing M.O.V.E. line — the one place the page raises its voice. */
.creed {
  margin-top: clamp(3rem, 7vw, 5.5rem);
  padding-top: clamp(2.5rem, 5vw, 4rem);
  border-top: 1px solid var(--accent-soft);
  text-align: center;
}
.creed p {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.125rem, 2.4vw, 2rem);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: .04em;
  text-transform: uppercase;
  text-wrap: balance;
}
.creed em { font-style: normal; color: var(--accent); }

.mission {
  margin-top: clamp(2rem, 4vw, 3rem);
  padding: clamp(1.5rem, 3vw, 2.25rem);
  border: 1px solid var(--hair);
}
.mission p { margin: 0; color: var(--mute-soft); font-size: var(--fs-body); line-height: 1.75; }
.mission strong { color: var(--paper); font-weight: 500; }

/* ----------------------------------------------------------- 12. Join */
.join__panel--cta { text-align: center; }
.join__assurance--row {
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1.25rem 2.5rem;
  margin-top: 2.5rem;
}

/* --- Join dialog ------------------------------------------------------- */
/* Native <dialog>: focus trapping, Escape and background inertness come from
   the platform rather than from script we would have to get right ourselves. */
.modal {
  width: min(560px, calc(100vw - 2rem));
  max-height: min(90svh, 900px);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--paper);
  overflow: visible;
}
.modal::backdrop {
  background: rgba(0, 0, 0, .82);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.modal[open] { animation: modalIn .4s var(--ease-out) both; }
.modal[open]::backdrop { animation: fadeIn .4s var(--ease) both; }
@keyframes modalIn {
  from { opacity: 0; transform: translateY(14px) scale(.985); }
  to   { opacity: 1; transform: none; }
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

.modal__panel {
  position: relative;
  max-height: min(90svh, 900px);
  overflow-y: auto;
  padding: clamp(1.75rem, 4vw, 2.75rem);
  background: var(--ink-raise);
  border: 1px solid var(--hair);
}
/* The same corner ticks the page panel uses, so the dialog reads as part of it. */
.modal__panel::before,
.modal__panel::after {
  content: "";
  position: absolute;
  width: 20px; height: 20px;
  border: 1px solid var(--accent);
  pointer-events: none;
}
.modal__panel::before { top: -1px; left: -1px; border-right: 0; border-bottom: 0; }
.modal__panel::after  { bottom: -1px; right: -1px; border-left: 0; border-top: 0; }

.modal__close {
  position: absolute; top: .9rem; right: .9rem;
  width: 40px; height: 40px;
  display: grid; place-items: center;
  color: var(--mute);
  transition: color .3s var(--ease), transform .3s var(--ease);
}
.modal__close svg {
  width: 18px; height: 18px;
  fill: none; stroke: currentColor; stroke-width: 1.2; stroke-linecap: round;
}
.modal__close:hover { color: var(--paper); transform: rotate(90deg); }

.modal__intro {
  margin: 0 0 2rem;
  color: var(--mute-soft);
  font-size: var(--fs-body);
  max-width: 42ch;
}
.modal .join__success { padding: 0; }

/* The page section can afford generous rhythm; a dialog cannot. Tightened so
   the submit button lands inside the panel rather than below the scroll. */
.modal .form__rows      { gap: 1.15rem; }
.modal .form__pair      { gap: 1.15rem; }
.modal .field__input    { padding: 1.15rem 0 .65rem; font-size: 1rem; }
.modal .field__label    { top: 1.15rem; font-size: .9375rem; }
.modal .form__consents  { gap: .85rem; }
.modal .check__text     { font-size: .75rem; line-height: 1.55; }
.modal .form__foot      { gap: .85rem; margin-top: .25rem; }
.modal .btn             { padding: 1rem 2rem; }

/* On a phone a centred card leaves the form cramped and the page peeking
   round the edges. A full-height sheet gives the fields the whole screen,
   which is also the pattern people already expect there. */
@media (max-width: 640px) {
  .modal {
    width: 100vw;
    max-width: 100vw;
    max-height: 100svh;
    margin: 0;
  }
  .modal__panel {
    min-height: 100svh;
    max-height: 100svh;
    border: 0;
    padding: clamp(4rem, 12vw, 5rem) 1.5rem 2.5rem;
  }
  .modal__panel::before,
  .modal__panel::after { display: none; }
  .modal__close { top: 1rem; right: 1rem; }
  .modal[open] { animation: sheetIn .4s var(--ease-out) both; }
}
@keyframes sheetIn {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .modal[open], .modal[open]::backdrop { animation: none; }
}

.join { background: var(--ink-raise); }
.join__panel {
  position: relative;
  border: 1px solid var(--hair);
  padding: clamp(2rem, 5vw, 5rem);
}
/* Gold corner ticks — quiet luxury detail. */
.join__panel::before,
.join__panel::after {
  content: "";
  position: absolute;
  width: 22px; height: 22px;
  border: 1px solid var(--accent);
  pointer-events: none;
}
.join__panel::before { top: -1px; left: -1px; border-right: 0; border-bottom: 0; }
.join__panel::after  { bottom: -1px; right: -1px; border-left: 0; border-top: 0; }

.join__grid {
  display: grid;
  grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr);
  gap: clamp(2.5rem, 6vw, 5.5rem);
  align-items: start;
}
.join__intro .display { margin-bottom: 1.75rem; max-width: 11ch; }
.join__intro .lead { max-width: 34ch; }

.join__assurance {
  display: flex; flex-direction: column; gap: .75rem;
  margin-top: 2.5rem; padding-top: 2rem;
  border-top: 1px solid var(--hair);
}
.join__assurance div { display: flex; align-items: center; gap: .8rem; font-size: var(--fs-label); letter-spacing: var(--ls-meta); text-transform: uppercase; color: var(--mute); }
.join__assurance svg { width: 14px; height: 14px; flex: none; fill: none; stroke: var(--accent); stroke-width: 1.2; stroke-linecap: round; stroke-linejoin: round; }

/* --- Form ------------------------------------------------------------- */
.form__rows { display: grid; gap: clamp(1.5rem, 3vw, 2.25rem); }
.form__pair { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1.5rem, 3vw, 2.25rem); }

.field { position: relative; }
.field__input {
  width: 100%;
  padding: 1.4rem 0 .85rem;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--hair);
  color: var(--paper);
  font-size: 1.0625rem;
  font-weight: 300;
  transition: border-color .45s var(--ease);
}
.field__input:focus { outline: none; border-bottom-color: var(--accent); }
.field__input::placeholder { color: transparent; }

.field__label {
  position: absolute; left: 0; top: 1.4rem;
  font-size: 1rem; font-weight: 300; color: var(--mute);
  pointer-events: none;
  transform-origin: left top;
  transition: transform .4s var(--ease-out), color .4s var(--ease), letter-spacing .4s var(--ease);
}
.field__input:focus + .field__label,
.field__input:not(:placeholder-shown) + .field__label {
  transform: translateY(-1.5rem) scale(.66);
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
  color: var(--accent);
}
.field__optional { color: var(--mute); opacity: .6; }

.field__error {
  display: block;
  margin-top: .55rem;
  font-size: .6875rem;
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
  color: #e0755f;
  min-height: 1em;
}
.field.has-error .field__input { border-bottom-color: #e0755f; }

/* Honeypot — visually gone, still focusable-proof for bots. */
.hp {
  position: absolute !important;
  left: -9999px !important;
  width: 1px; height: 1px; opacity: 0;
}

/* Custom checkbox */
.check { display: grid; grid-template-columns: 20px 1fr; gap: 1rem; align-items: start; cursor: pointer; }
.check input { position: absolute; opacity: 0; width: 0; height: 0; }
.check__box {
  width: 20px; height: 20px;
  margin-top: 2px;
  border: 1px solid var(--hair-strong);
  display: grid; place-items: center;
  transition: border-color .35s var(--ease), background-color .35s var(--ease);
}
.check__box svg {
  width: 11px; height: 11px;
  fill: none; stroke: var(--ink); stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 20; stroke-dashoffset: 20;
  transition: stroke-dashoffset .35s var(--ease-out);
}
.check input:checked ~ .check__box { background: var(--accent); border-color: var(--accent); }
.check input:checked ~ .check__box svg { stroke-dashoffset: 0; }
.check input:focus-visible ~ .check__box { outline: 1px solid var(--accent); outline-offset: 3px; }
.check__text { font-size: .8125rem; line-height: 1.65; color: var(--mute-soft); }
.check__text a { color: var(--paper); text-decoration: underline; text-underline-offset: 3px; }
.check.has-error .check__box { border-color: #e0755f; }

.form__consents { display: grid; gap: 1.25rem; }

.form__foot { display: flex; flex-direction: column; gap: 1.25rem; margin-top: .5rem; }
.form__status {
  font-size: var(--fs-label);
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
  color: #e0755f;
  min-height: 1.2em;
}

.btn.is-busy { pointer-events: none; opacity: .6; }
.btn__spinner {
  width: 15px; height: 15px;
  border: 1px solid rgba(255,255,255,.28);
  border-top-color: var(--paper);
  border-radius: 50%;
  animation: spin .7s linear infinite;
  display: none;
}
.btn.is-busy .btn__spinner { display: block; }
.btn.is-busy svg { display: none; }
@keyframes spin { to { transform: rotate(360deg); } }

/* Success state */
.join__success {
  display: none;
  text-align: left;
  padding: clamp(1rem, 3vw, 2rem) 0;
}
.join__success.is-visible { display: block; animation: fadeUp .8s var(--ease-out) both; }
.join__form.is-hidden { display: none; }
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: none; }
}
.join__success-mark {
  width: 56px; height: 56px;
  border: 1px solid var(--accent);
  border-radius: 50%;
  display: grid; place-items: center;
  margin-bottom: 2rem;
}
.join__success-mark svg { width: 22px; height: 22px; fill: none; stroke: var(--accent); stroke-width: 1.2; stroke-linecap: round; stroke-linejoin: round; }

/* ------------------------------------------------------- 12b. Gallery */
/* A deliberately uneven grid: every third tile spans two columns, so a wall of
   event photos reads as a gallery rather than a contact sheet. */
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 220px), 1fr));
  grid-auto-rows: 190px;
  gap: clamp(.5rem, 1vw, .9rem);
}

.gtile {
  position: relative;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--hair);
  background: var(--ink-panel);
  cursor: zoom-in;
  display: block;
}
.gtile:nth-child(6n + 1) { grid-column: span 2; grid-row: span 2; }
.gtile:nth-child(6n + 4) { grid-row: span 2; }

.gtile img {
  width: 100%; height: 100%;
  object-fit: cover;
  transform: scale(1.02);
  transition: transform 1.1s var(--ease-out);
}
.gtile:hover img,
.gtile:focus-visible img { transform: scale(1.07); }

.gtile__date {
  position: absolute; left: 0; bottom: 0;
  padding: .5rem .75rem;
  background: var(--ink);
  border-top: 1px solid var(--hair);
  border-right: 1px solid var(--hair);
  font-size: .5625rem;
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
  color: var(--mute-soft);
  opacity: 0;
  transform: translateY(100%);
  transition: opacity .4s var(--ease), transform .4s var(--ease-out);
}
.gtile:hover .gtile__date,
.gtile:focus-visible .gtile__date { opacity: 1; transform: none; }

@media (max-width: 640px) {
  .gallery { grid-auto-rows: 132px; grid-template-columns: repeat(2, 1fr); }
  .gtile:nth-child(6n + 1) { grid-column: span 2; }
  .gtile:nth-child(6n + 4) { grid-row: span 1; }
}

/* --- Lightbox ---------------------------------------------------------- */
.lightbox {
  width: 100vw; max-width: 100vw;
  height: 100svh; max-height: 100svh;
  margin: 0; padding: 0; border: 0;
  background: transparent;
  overflow: hidden;
}
.lightbox::backdrop { background: rgba(0, 0, 0, .94); }
.lightbox[open] { display: flex; align-items: center; justify-content: center; animation: fadeIn .3s var(--ease) both; }

.lightbox__figure {
  margin: 0;
  max-width: min(1200px, 92vw);
  max-height: 86svh;
  display: flex; flex-direction: column; gap: 1rem;
}
.lightbox__figure img {
  max-width: 100%;
  max-height: 74svh;
  width: auto; height: auto;
  object-fit: contain;
  border: 1px solid var(--hair);
}
.lightbox__caption {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1.5rem; flex-wrap: wrap;
  font-size: var(--fs-label);
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
  color: var(--mute-soft);
}

.lightbox__close {
  position: absolute; top: 1.25rem; right: 1.25rem; z-index: 2;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  color: var(--mute);
  transition: color .3s var(--ease), transform .3s var(--ease);
}
.lightbox__close:hover { color: var(--paper); transform: rotate(90deg); }
.lightbox__close svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.2; stroke-linecap: round; }

.lightbox__nav {
  position: absolute; top: 50%; z-index: 2;
  transform: translateY(-50%);
  width: 52px; height: 52px;
  display: grid; place-items: center;
  border: 1px solid var(--hair);
  color: var(--mute-soft);
  background: rgba(0, 0, 0, .5);
  transition: color .3s var(--ease), border-color .3s var(--ease);
}
.lightbox__nav:hover { color: var(--ink); background: var(--accent); border-color: var(--accent); }
.lightbox__nav svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.2; stroke-linecap: round; stroke-linejoin: round; }
.lightbox__nav--prev { left: clamp(.5rem, 2vw, 2rem); }
.lightbox__nav--next { right: clamp(.5rem, 2vw, 2rem); }

@media (max-width: 640px) {
  .lightbox__nav { width: 44px; height: 44px; }
  .lightbox__figure img { max-height: 62svh; }
}

/* ------------------------------------------------------ 13. Instagram */
.ig__grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: clamp(.5rem, 1vw, 1rem);
}
.ig__tile {
  position: relative;
  aspect-ratio: 1;
  overflow: hidden;
  border: 1px solid var(--hair);
  background: var(--ink-panel);
  display: block;
}
.ig__tile img {
  width: 100%; height: 100%;
  object-fit: cover;
  transform: scale(1.01);
  transition: transform 1.1s var(--ease-out);
}
.ig__tile:hover img { transform: scale(1.09); }

.ig__overlay {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: 1rem;
  background: linear-gradient(to top, rgba(0,0,0,.88) 4%, rgba(0,0,0,.15) 55%, transparent 100%);
  opacity: 0;
  transition: opacity .5s var(--ease);
}
.ig__tile:hover .ig__overlay { opacity: 1; }
.ig__caption {
  font-size: .6875rem; line-height: 1.55; color: var(--mute-soft);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.ig__badge {
  position: absolute; top: .7rem; right: .7rem;
  width: 26px; height: 26px;
  display: grid; place-items: center;
  background: rgba(0,0,0,.6);
  backdrop-filter: blur(6px);
}
.ig__badge svg { width: 13px; height: 13px; fill: none; stroke: var(--paper); stroke-width: 1.2; }

.ig__skel { aspect-ratio: 1; background: var(--ink-panel); border: 1px solid var(--hair); }


/* ---------------------------------------------------------- 13b. Books */
.books-teaser {
  display: grid;
  grid-template-columns: minmax(0, .55fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 5rem);
  align-items: center;
}
.books-teaser__cover {
  display: block;
  border: 1px solid var(--hair);
  padding: 10px;
  overflow: hidden;
}
.books-teaser__cover img {
  width: 100%; height: auto; display: block;
  transition: transform 1.2s var(--ease-out);
}
.books-teaser__cover:hover img { transform: scale(1.04); }
@media (max-width: 860px) {
  .books-teaser { grid-template-columns: 1fr; }
  .books-teaser__cover { max-width: 260px; }
}

.books-hero { padding-bottom: clamp(2rem, 4vw, 3rem); padding-top: clamp(9rem, 16vh, 12rem); }

.book__grid {
  display: grid;
  grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr);
  gap: clamp(2rem, 5vw, 5rem);
  align-items: start;
}

.book__cover {
  position: relative;
  border: 1px solid var(--hair);
  padding: 10px;
  overflow: hidden;
}
.book__cover::after {
  content: "";
  position: absolute; inset: 10px;
  border: 1px solid var(--accent-ghost);
  pointer-events: none;
}
.book__cover img {
  width: 100%; height: auto;
  display: block;
  transition: transform 1.2s var(--ease-out);
}
.book__cover:hover img { transform: scale(1.03); }

.book__placeholder {
  aspect-ratio: 3 / 4;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .9rem;
  background: var(--ink-panel);
  border: 1px dashed var(--hair);
}

.book__eyebrow {
  display: flex; align-items: center; gap: 1.25rem;
  flex-wrap: wrap; margin-bottom: 1.25rem;
}
.pill-live {
  display: inline-flex; align-items: center; gap: .6rem;
  padding: .35rem .85rem;
  font-size: .625rem;
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
  color: var(--accent);
  border: 1px solid var(--accent-soft);
  background: var(--accent-ghost);
}

.book__title { margin-bottom: .85rem; }
.book__subtitle {
  margin: 0 0 1.25rem;
  font-size: var(--fs-label);
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
  color: var(--mute-soft);
  max-width: 46ch;
}
.book__tagline {
  margin: 0 0 1.5rem;
  font-family: var(--font-display);
  font-size: clamp(1rem, 1.5vw, 1.25rem);
  font-weight: 500;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--accent);
}
.book__desc { max-width: 58ch; margin-bottom: 1.75rem; }

.book__facts {
  display: flex; flex-wrap: wrap; gap: 1.5rem;
  padding: 1.1rem 0;
  border-top: 1px solid var(--hair);
  border-bottom: 1px solid var(--hair);
  margin-bottom: 1.75rem;
}

.book__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 1.25rem; }
.book__pending { color: var(--mute); }

.book__authors { margin-top: 2rem; border-top: 1px solid var(--hair); padding-top: 1.25rem; }
.book__authors summary {
  cursor: pointer; list-style: none;
  display: flex; align-items: center; gap: .7rem;
}
.book__authors summary::-webkit-details-marker { display: none; }
.book__authors summary::after {
  content: "+";
  color: var(--accent);
  font-size: 1rem; line-height: 1;
  transition: transform .35s var(--ease);
}
.book__authors[open] summary::after { transform: rotate(45deg); }
.book__authors summary:hover .label { color: var(--paper); }
.book__authors ul {
  list-style: none; margin: 1.25rem 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: .7rem 1.5rem;
}
.book__authors li { font-size: .875rem; color: var(--mute-soft); }

/* Contributor headshots. The supplied images already carry each person's name,
   so the grid adds no captions of its own — the photos are the caption. */
.contributors {
  margin-top: clamp(3rem, 6vw, 5rem);
  padding-top: clamp(2rem, 4vw, 3rem);
  border-top: 1px solid var(--hair);
}
.contributors__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1.5rem; flex-wrap: wrap;
  margin-bottom: clamp(1.5rem, 3vw, 2.25rem);
}
.contributors__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 148px), 1fr));
  gap: clamp(.5rem, 1vw, .9rem);
}
.contributor {
  margin: 0;
  position: relative;
  overflow: hidden;
  border: 1px solid var(--hair);
  background: var(--ink-panel);
}
.contributor img {
  width: 100%; height: auto; display: block;
  transform: scale(1.01);
  transition: transform 1s var(--ease-out);
}
.contributor:hover img { transform: scale(1.05); }

@media (max-width: 860px) {
  .book__grid { grid-template-columns: 1fr; }
  .book__cover { max-width: 340px; }
  .contributors__grid { grid-template-columns: repeat(auto-fill, minmax(min(100%, 116px), 1fr)); }
}

/* --------------------------------------------------------- 14. Footer */
.footer { border-top: 1px solid var(--hair); padding-block: clamp(3.5rem, 7vw, 5.5rem) 2.5rem; }
.footer__top {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) repeat(2, minmax(0, .6fr));
  gap: clamp(2rem, 5vw, 4rem);
  padding-bottom: clamp(2.5rem, 5vw, 4rem);
}
.footer__logo img { width: clamp(150px, 15vw, 200px); margin-bottom: 1.5rem; }
.footer__tag { max-width: 30ch; color: var(--mute); font-size: .875rem; }
.footer__col h3 { margin: 0 0 1.4rem; font-size: var(--fs-label); letter-spacing: var(--ls-label); text-transform: uppercase; font-weight: 400; color: var(--mute); }
.footer__col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .85rem; }
.footer__col a { font-size: .875rem; color: var(--mute-soft); transition: color .35s var(--ease); }
.footer__col a:hover { color: var(--accent); }

.footer__bottom {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 1.25rem;
  padding-top: 2rem;
  border-top: 1px solid var(--hair);
  font-size: .6875rem;
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
  color: var(--mute);
}
.footer__bottom a:hover { color: var(--paper); }

/* --------------------------------------------------- 15. Message page */
.page-message { min-height: 100svh; display: grid; place-items: center; padding: var(--gutter); }
.message { max-width: 46ch; text-align: center; }
.message__logo { display: inline-block; margin-bottom: clamp(2.5rem, 6vh, 4rem); }
.message__logo img { width: 200px; }
.message .label { margin-bottom: 1.5rem; }
.message__heading {
  font-family: var(--font-display);
  font-size: clamp(1.375rem, 3.4vw, 2.125rem);
  font-weight: 600; line-height: 1.2;
  text-transform: uppercase; letter-spacing: .03em;
  text-wrap: balance;
  margin: 0 0 1.5rem;
}
.message__name { color: var(--accent); }
.message__body { color: var(--mute-soft); margin: 0 0 2.5rem; }

/* --------------------------------------------- 15b. Photography & hover */
/* Photographs run in full colour everywhere. That removes the old
   grayscale-to-colour reveal, which was carrying the entire hover state, so
   the response has to come from somewhere other than the picture's own tone.
   Three moves, the same three on every image on the site, so it still reads
   as one system rather than seven separate ideas:

     1. a light sweep travels across the frame once
     2. a hairline settles onto the edge in accent, with a soft accent lift
     3. the image eases forward

   The sweep is a gradient band on ::before rather than a filter on the image,
   so nothing touches the colour. Every container here already sets
   position:relative and overflow:hidden, which is what clips it. */

.hero__frame::before,
.ecard__media::before,
.gtile::before,
.ig__tile::before,
.contributor::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(
    102deg,
    transparent 36%,
    rgba(255, 255, 255, .07) 45%,
    rgba(255, 255, 255, .20) 50%,
    rgba(255, 255, 255, .07) 55%,
    transparent 64%
  );
  transform: translateX(-135%);
  opacity: 0;
  /* On the way out the band is snapped back with the delay rather than
     animated, so it never sweeps backwards across the photo. */
  transition: opacity .25s var(--ease), transform 0s .5s;
}

/* The hero frame has a 10px mat, so its sweep sits inside that. */
.hero__frame::before { inset: 10px; }

.hero__frame:hover::before,
.ecard:hover .ecard__media::before,
.gtile:hover::before,
.gtile:focus-visible::before,
.ig__tile:hover::before,
.ig__tile:focus-visible::before,
.contributor:hover::before {
  opacity: 1;
  transform: translateX(135%);
  transition: opacity .2s var(--ease), transform 1s var(--ease-out);
}

/* The edge response. inset box-shadow rather than a border so nothing
   reflows, plus a low accent-tinted lift to separate the tile from the
   black ground. */
.ecard__media,
.gtile,
.ig__tile,
.contributor {
  transition:
    border-color .5s var(--ease),
    box-shadow .5s var(--ease);
}

.ecard:hover .ecard__media,
.gtile:hover,
.gtile:focus-visible,
.ig__tile:hover,
.ig__tile:focus-visible,
.contributor:hover {
  border-color: var(--accent-soft);
  box-shadow:
    inset 0 0 0 1px var(--accent-ghost),
    0 22px 44px -30px rgba(0, 156, 114, .55);
}

/* Keyboard users get the same treatment as the mouse, not an outline instead
   of it — the tiles are links and buttons. */
.gtile:focus-visible,
.ig__tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) {
  /* A sweep that cannot animate is just a flash of light. */
  .hero__frame::before,
  .ecard__media::before,
  .gtile::before,
  .ig__tile::before,
  .contributor::before { display: none; }
}

/* The index rows have no frame to light, so the same idea plays along the
   rule beneath them: the accent hairline draws left to right under the row,
   meeting the vertical rail that grows on ::before. */
.erow::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform .7s var(--ease-out);
  pointer-events: none;
}
.erow:hover::after,
.erow:focus-within::after { transform: scaleX(1); }

/* Touch has no hover, so the states above never fire. Give the tiles the
   accent edge permanently at low strength rather than leaving them flat. */
@media (hover: none) {
  .gtile,
  .ig__tile,
  .contributor { border-color: rgba(255, 255, 255, .16); }
}

/* ------------------------------------------------ 15c. Events, collapsed */
/* The list shows five and holds the rest back. Everything is in the HTML —
   this only hides it — so the full calendar is still there for search engines
   and for anyone browsing without JavaScript, who simply sees all of it. */
html.js #events-mount[data-collapsed="1"] .is-extra { display: none; }

/* A fade on the last visible row says "there is more" without a scrollbar or
   a shadow, which would both be louder than this page wants. */
html.js #events-mount[data-collapsed="1"] .elist { position: relative; }
html.js #events-mount[data-collapsed="1"] .elist::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 90px;
  pointer-events: none;
  background: linear-gradient(to top, var(--ink) 8%, transparent 100%);
}

.events__more {
  display: flex;
  justify-content: center;
  margin-top: clamp(2rem, 4vw, 3rem);
}
.events__more[hidden] { display: none; }

/* The arrow points down while collapsed and up once opened, so the control
   reads as a direction rather than only as a label. */
.events__more .btn svg { transition: transform .5s var(--ease-out); }
.events__more .btn[aria-expanded="false"] svg { transform: rotate(90deg); }
.events__more .btn[aria-expanded="true"] svg { transform: rotate(-90deg); }

/* ----------------------------------------------------- 16. Responsive */
@media (max-width: 1100px) {
  .hero__grid { grid-template-columns: 1fr; }
  /* The event photo leads on narrow screens rather than being hidden — it is
     the most recognisable thing about the gathering. `order` lifts it above
     the text now that the grid has collapsed to one column. */
  .hero__frame {
    order: -1;
    align-self: stretch;
    margin-bottom: clamp(1.25rem, 4vw, 2rem);
  }
  .hero__frame-tag { padding: .85rem 1rem; }
  /* Reclaim the height the image just took, so the CTA stays reachable. */
  .hero { padding-top: clamp(100px, 13vh, 150px); }
  .scroll-cue { display: none; }
  .idea__grid { grid-template-columns: 1fr; }
  .idea__statement { position: static; }
  .join__grid { grid-template-columns: 1fr; }
  .ig__grid { grid-template-columns: repeat(4, 1fr); }
  .footer__top { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 860px) {
  .nav__links, .nav__cta { display: none; }
  .burger { display: block; }

  .erow {
    grid-template-columns: clamp(70px, 18vw, 96px) minmax(0, 1fr) 38px;
    gap: 1.25rem;
  }
  .erow__where { display: none; }
  .erow__go { width: 38px; height: 38px; }

  .countdown { gap: 1.25rem; }
  .hero__meta-sep { display: none; }
}

@media (max-width: 640px) {
  .form__pair { grid-template-columns: 1fr; }
  .ig__grid { grid-template-columns: repeat(2, 1fr); }
  .footer__top { grid-template-columns: 1fr; }
  .section-head { flex-direction: column; align-items: flex-start; }
  .events__toggle { width: 100%; }
  .events__toggle button { flex: 1; }
  .hero { align-items: center; }
  .countdown__cell { min-width: 2.8ch; }
}

@media print {
  .header, .grain, .join, .ig, .scroll-cue { display: none; }
  body { background: #fff; color: #000; }
}
