/* =========================================================================
   ATX WRITING CLUB — COMPONENTS & PAGES
   Built on system.css. Nothing here invents a colour or a duration; it only
   arranges what the system already defines.
   ========================================================================= */

/* -- HERO ---------------------------------------------------------------- */

.hero {
  position: relative;
  min-height: 100svh;
  display: grid;
  align-items: end;
  padding-top: calc(var(--header-h) + 4vh);
  padding-bottom: clamp(2.5rem, 7vh, 6rem);
  overflow: clip;
  isolation: isolate;
}
.hero__bg { position: absolute; inset: -8% 0 -8% 0; z-index: -2; }
/* <picture> is a display:block box with auto height, so once the hero image
   was wrapped in one the img's height:100% resolved against nothing and it
   fell back to its intrinsic ratio — a band at the top instead of a full
   bleed. The wrapper has to carry the height too. */
.hero__bg picture { display: block; width: 100%; height: 100%; }
.hero__bg img { width: 100%; height: 100%; object-fit: cover; }
.hero__scrim {
  position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(180deg, rgba(20,16,11,.42) 0%, rgba(20,16,11,.06) 34%, rgba(20,16,11,.62) 100%),
    radial-gradient(120% 80% at 50% 0%, transparent 40%, rgba(20,16,11,.30) 100%);
}
.hero--paper { background: var(--paper); }
.hero--paper .hero__scrim { display: none; }

.hero__inner { width: 100%; }
.hero__eyebrow { display: flex; align-items: center; gap: .9rem; margin-bottom: clamp(1rem, 2.5vh, 2rem); }
.hero__eyebrow .bar { width: clamp(28px, 5vw, 64px); height: 1px; background: currentColor; opacity: .6; }
.hero__title { max-width: 16ch; }
.hero__foot {
  margin-top: clamp(1.75rem, 5vh, 3.5rem);
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--s-6); flex-wrap: wrap;
}
.hero__sub { max-width: 34ch; }

.hero__scroll {
  display: inline-flex; align-items: center; gap: .7rem;
  font-family: var(--f-label); font-size: var(--t-micro);
  letter-spacing: .2em; text-transform: uppercase; opacity: .75;
}
.hero__scroll .tick {
  width: 1px; height: 34px; background: currentColor; position: relative; overflow: hidden;
}
.hero__scroll .tick::after {
  content: ''; position: absolute; inset: 0; background: var(--rust-night);
  animation: tick 2.6s var(--e-soft) infinite;
}
@keyframes tick { 0% { transform: translateY(-100%); } 55%,100% { transform: translateY(100%); } }

.hero--art { min-height: auto; padding-block: calc(var(--header-h) + clamp(4rem,12vh,9rem)) var(--band); }
.hero--art .hero__title { max-width: 20ch; }

/* -- TICKER BAND --------------------------------------------------------- */

.band-ticker {
  border-block: 1px solid var(--rule);
  padding-block: clamp(.85rem, 1.6vh, 1.3rem);
  background: var(--paper-lo);
}
:is(.night,.ftr,.menu,.tier--feature,.mcard--dark) .band-ticker, .band-ticker.night { background: var(--night-2); border-color: var(--rule-night); }
.ticker__item {
  display: inline-flex; align-items: center; gap: 1.4rem;
  padding-inline: 1.4rem;
  font-family: var(--f-poster);
  font-size: clamp(1.1rem, 2vw, 1.75rem);
  text-transform: uppercase; letter-spacing: .02em;
  white-space: nowrap;
}
.ticker__item .dot { width: 5px; height: 5px; background: var(--rust); border-radius: 50%; flex: none; }
.ticker__item .art { height: clamp(26px, 3.4vw, 40px); width: auto; opacity: .9; }

/* -- STATEMENT ----------------------------------------------------------- */

.statement {
  font-family: var(--f-display);
  font-size: clamp(2.1rem, 5.6vw, 5.4rem);
  line-height: 1.04; letter-spacing: -.026em;
  max-width: 22ch;
}
.statement em { font-style: italic; color: var(--rust); }
:is(.night,.ftr,.menu,.tier--feature,.mcard--dark) .statement em { color: var(--rust-night); }

.statement-block { position: relative; }
.statement-block .mark--a { right: -2%; top: -14%; width: clamp(110px, 17vw, 300px); }
.statement-block .mark--b { left: -6%; bottom: -18%; width: clamp(90px, 12vw, 210px); }

/* -- PILLAR LIST (three-up value props) ---------------------------------- */

.pillars { display: grid; gap: clamp(2rem, 4vw, 3.5rem); grid-template-columns: repeat(3, 1fr); }
@media (max-width: 860px) { .pillars { grid-template-columns: 1fr; } }
.pillar { border-top: 1px solid var(--rule); padding-top: var(--s-5); }
:is(.night,.ftr,.menu,.tier--feature,.mcard--dark) .pillar { border-color: var(--rule-night); }
.pillar__n { display: block; margin-bottom: var(--s-5); }
.pillar__art { height: clamp(70px, 8vw, 104px); width: auto; margin-bottom: var(--s-5); opacity: .95; }
.pillar h3 { font-size: var(--t-d4); margin-bottom: .55rem; }
.pillar p { color: var(--ink-2); font-size: var(--t-small); }
:is(.night,.ftr,.menu,.tier--feature,.mcard--dark) .pillar p { color: var(--on-night-2); }

/* -- PINNED CHAPTERS ----------------------------------------------------- */

.chapters { position: relative; height: var(--ch-h, auto); }
.chapters__sticky {
  position: sticky; top: 0; height: 100svh;
  display: grid; align-items: center; overflow: hidden;
}

.chapters__grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 5vw, 5rem); align-items: center; }
@media (max-width: 900px) { .chapters__grid { grid-template-columns: 1fr; gap: var(--s-6); } }
.chapters__media { position: relative; aspect-ratio: 4/5; overflow: hidden; }
@media (max-width: 900px) { .chapters__media { aspect-ratio: 16/10; } }
.chapters__media img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transform: scale(1.06);
  transition: opacity 700ms var(--e-expo), transform 1400ms var(--e-expo);
}
.chapters__media img.is-active { opacity: 1; transform: scale(1); }
/* The three chapters share one grid cell instead of each being absolutely
   positioned and vertically centred on its own. Centring meant a chapter with
   a longer kicker or a third line of body sat at a different height than its
   neighbours, so the number, the rail and the headline all jumped as you
   scrolled. Stacked in one cell the panel is as tall as the longest chapter
   and every chapter starts at the same top edge. */
.chapters__panel { position: relative; display: grid; min-height: 20rem; }
.chapters__panel > .ch {
  grid-area: 1 / 1;
  display: grid; align-content: start;
  opacity: 0; transform: translateY(18px);
  transition: opacity 620ms var(--e-expo), transform 620ms var(--e-expo);
  pointer-events: none;
}
.chapters__panel > .ch.is-active { opacity: 1; transform: none; pointer-events: auto; }
.ch h3 { font-size: var(--t-d2); margin-block: .6rem .9rem; }
.ch p { color: var(--on-night-2); max-width: 38ch; }

/* Two lines are always reserved for the kicker. One of the three needs both,
   and without the reservation that chapter alone pushed its headline down. */
.ch__kicker { min-height: 2.5em; max-width: 30ch; }

.chapters__rail { display: flex; gap: .5rem; margin-block: var(--s-3) var(--s-5); }
.chapters__rail i { display: block; width: 34px; height: 2px; background: var(--rule-night); }
.chapters__rail i.is-active { background: var(--rust-night); }

/* -- TIERS --------------------------------------------------------------- */

.tiers { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0; border-top: 1px solid var(--rule); }
@media (max-width: 980px) { .tiers { grid-template-columns: 1fr; } }
.tier {
  position: relative;
  padding: clamp(1.75rem, 3vw, 2.75rem) clamp(1.25rem, 2.2vw, 2rem) clamp(2rem, 3.4vw, 3rem);
  border-right: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  display: flex; flex-direction: column;
  transition: background-color 600ms var(--e-expo);
}
.tier:last-child { border-right: 0; }
@media (max-width: 980px) { .tier { border-right: 0; } }
.tier:hover { background: var(--paper-hi); }
.tier--feature { background: var(--night); color: var(--on-night); border-color: var(--rule-night); }
.tier--feature:hover { background: var(--night-2); }
.tier--feature .tier__price small, .tier--feature .tier__best dt { color: var(--on-night-2); }
.tier--feature .tier__incl li { border-color: var(--rule-night); }
.tier__flag {
  position: absolute; top: 0; right: clamp(1.25rem, 2.2vw, 2rem);
  transform: translateY(-50%);
  background: var(--rust-ink); color: #FFF6E6;
  font-family: var(--f-label); font-size: var(--t-micro); font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase; padding: .45em .85em;
}
.tier__name { font-family: var(--f-poster); font-size: clamp(2.2rem, 3.6vw, 3.2rem); line-height: .9; }
.tier__price { font-family: var(--f-display); font-size: clamp(1.9rem, 2.8vw, 2.6rem); letter-spacing: -.02em; margin-top: .45rem; }
.tier__price small { font-family: var(--f-label); font-size: var(--t-label); letter-spacing: .16em; text-transform: uppercase; color: var(--ink-3); margin-left: .5rem; }
.tier__art { position: absolute; right: clamp(.5rem,1.4vw,1.25rem); bottom: clamp(.5rem,1.4vw,1.25rem); width: clamp(74px, 9vw, 128px); opacity: .18; pointer-events: none; }
.tier--feature .tier__art { opacity: .3; }
.tier__best { margin-top: var(--s-5); }
.tier__best dt { margin-bottom: .5rem; }
.tier__best dd { margin: 0; font-size: var(--t-small); color: inherit; }
.tier__best ul { list-style: none; padding: 0; display: flex; flex-wrap: wrap; gap: .4rem; }
.tier__best li {
  font-family: var(--f-label); font-size: var(--t-micro); letter-spacing: .1em;
  text-transform: uppercase; border: 1px solid var(--rule-strong); padding: .35em .6em;
}
.tier--feature .tier__best li { border-color: var(--rule-night); }
.tier__blurb { margin-top: var(--s-5); font-size: var(--t-small); color: var(--ink-2); }
.tier--feature .tier__blurb { color: var(--on-night-2); }
.tier__incl { list-style: none; padding: 0; margin-top: var(--s-5); }
.tier__incl li {
  font-size: var(--t-small); padding: .62rem 0 .62rem 1.4rem; position: relative;
  border-bottom: 1px solid var(--rule);
}
.tier__incl li::before {
  content: '→'; position: absolute; left: 0; top: .62rem;
  color: var(--rust); font-family: var(--f-label); font-size: .8em;
}
.tier--feature .tier__incl li::before { color: var(--rust-night); }
.tier__cta { margin-top: auto; padding-top: var(--s-6); }
.tier__cta .btn { width: 100%; justify-content: center; }

/* -- EVENT CARDS --------------------------------------------------------- */

.ev-list { border-top: 1px solid var(--rule); }
.ev {
  position: relative;
  display: grid; grid-template-columns: 4.5rem 1fr auto;
  gap: clamp(1rem, 3vw, 2.5rem); align-items: center;
  padding-block: clamp(1.4rem, 2.6vw, 2.2rem);
  border-bottom: 1px solid var(--rule);
  text-decoration: none;
  transition: padding-inline 620ms var(--e-expo), background-color 620ms var(--e-expo);
}
.ev:hover { background: var(--paper-hi); padding-inline: clamp(.5rem, 1.6vw, 1.5rem); }
.ev__n { display: block; align-self: start; padding-top: .55rem; }
.ev__t { display: block; font-family: var(--f-display); font-size: var(--t-d3); line-height: 1.06; letter-spacing: -.016em; }
.ev__d { display: block; margin-top: .5rem; color: var(--ink-2); font-size: var(--t-small); max-width: 56ch; }
.ev__facts { display: flex; gap: 1.25rem; margin-top: .85rem; flex-wrap: wrap; }
.ev__go { display: grid; place-items: center; width: 3rem; height: 3rem; border: 1px solid var(--rule-strong); border-radius: 50%; flex: none; transition: background-color 420ms var(--e-expo), color 420ms var(--e-expo), transform 420ms var(--e-expo); }
.ev:hover .ev__go { background: var(--rust); color: var(--paper-hi); border-color: var(--rust); transform: translateX(4px); }
.ev__art {
  position: absolute; right: clamp(3.5rem, 9vw, 9rem); top: 50%;
  width: clamp(90px, 11vw, 170px); translate: 0 -50%;
  opacity: 0; transform: translateX(24px) rotate(-6deg);
  transition: opacity 620ms var(--e-expo), transform 780ms var(--e-expo);
  pointer-events: none;
}
.ev:hover .ev__art { opacity: .95; transform: translateX(0) rotate(0deg); }
@media (max-width: 760px) {
  .ev { grid-template-columns: 1fr; gap: .35rem; }
  .ev__n { padding-top: 0; }
  .ev__go { display: none; }
  .ev__art { display: none; }
}

/* -- HORIZONTAL RAIL ----------------------------------------------------- */

.rail { position: relative; }
.rail__viewport { overflow: hidden; }
.rail__track { display: flex; gap: clamp(1rem, 2.4vw, 2rem); will-change: transform; }
.rail__card { flex: 0 0 clamp(17rem, 26vw, 25rem); }
.rail__card .fig { margin-bottom: var(--s-4); }
/* The pin now runs on phones too. Cards are sized so roughly one and a bit is
   in frame — enough to make it obvious the row continues. The vertical scroll
   needed to cross the rail is damped in JS so it does not take five swipes. */
@media (max-width: 900px) {
  .rail__card { flex-basis: 76vw; }
  .rail--spk .rail__card { flex-basis: 64vw; }
  /* The card has to fit the pinned 100svh box or its tail is clipped, so the
     picture gives up height before the type does. */
  .rail__card .fig { max-height: 46svh; }
  .rail__card .fig img { height: 100%; object-fit: cover; }
}

/* Reduced motion: the pin is the animation, so remove it entirely. Without
   this the track never gets its transform and everything past the second card
   sits behind overflow:hidden, unreachable — which was true on desktop too. */
@media (prefers-reduced-motion: reduce) {
  .rail { height: auto !important; }
  .rail__viewport {
    position: static !important;
    height: auto !important;
    display: block !important;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 1rem;
  }
  .rail__viewport::-webkit-scrollbar { display: none; }
  .rail__viewport > .wrap { max-width: none; padding-inline: 0; }
  .rail__track { transform: none !important; padding-inline: var(--gut); }
  .rail__card { scroll-snap-align: start; }
  .rail__card .fig { max-height: none; }
  .rail::after {
    content: 'Swipe →';
    display: block; padding-inline: var(--gut); padding-top: .5rem;
    font-family: var(--f-label); font-size: var(--t-micro);
    letter-spacing: .18em; text-transform: uppercase; color: var(--ink-3);
  }
}

/* -- SPEAKERS RAIL ------------------------------------------------------- */
/* Narrower than the events rail on purpose. Eight faces at 25rem would be a
   parade; at 18rem they read as a set, and more of them are on screen at once,
   which is the whole point of showing who has taught here. */

.rail--spk .rail__card { flex: 0 0 clamp(14rem, 19vw, 18rem); }
.spk .fig { margin-bottom: 0; }
.spk__taught {
  font-family: var(--f-label); font-size: var(--t-micro); font-weight: 620;
  letter-spacing: .1em; text-transform: uppercase; color: var(--rust-ink);
  line-height: 1.45;
}
:is(.night,.ftr,.menu) .spk__taught { color: var(--rust-night); }
.spk--end { display: grid; align-content: center; }

/* -- POLAROID WALL ------------------------------------------------------- */

.wall {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(clamp(9rem, 15vw, 14rem), 1fr));
  gap: clamp(.85rem, 1.8vw, 1.6rem);
}
.pol {
  background: var(--paper-hi);
  padding: clamp(.5rem, .8vw, .7rem) clamp(.5rem, .8vw, .7rem) clamp(1.6rem, 2.6vw, 2.4rem);
  box-shadow: 0 1px 0 rgba(28,22,16,.10), 0 10px 22px -18px rgba(28,22,16,.55);
  transition: transform 760ms var(--e-expo), box-shadow 760ms var(--e-expo);
  transform: rotate(var(--tilt, 0deg));
  position: relative;
}
.pol img { width: 100%; aspect-ratio: .84; object-fit: cover; background: var(--paper-lo); }
.pol:hover { transform: rotate(0deg) translateY(-6px) scale(1.02); box-shadow: 0 2px 0 rgba(28,22,16,.10), 0 26px 44px -26px rgba(28,22,16,.6); z-index: 2; }
:is(.night,.ftr,.menu,.tier--feature,.mcard--dark) .pol { background: var(--night-3); }

/* -- WRITER CARDS -------------------------------------------------------- */

.writers { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(1.25rem, 2.4vw, 2.25rem); }
@media (max-width: 1000px) { .writers { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px)  { .writers { grid-template-columns: 1fr; } }
.writer__fig { margin-bottom: var(--s-4); }
.writer h3 { font-size: var(--t-d4); }
.writer dl { margin-top: var(--s-4); display: grid; gap: .7rem; }
.writer dt { margin-bottom: .18rem; }
.writer dd { margin: 0; font-size: var(--t-small); line-height: 1.45; }

/* -- FAQ ----------------------------------------------------------------- */

.faq { border-top: 1px solid var(--rule); }
.faq__item { border-bottom: 1px solid var(--rule); }
.faq__q {
  width: 100%; text-align: left; display: flex; gap: var(--s-5);
  align-items: baseline; justify-content: space-between;
  padding-block: clamp(1.15rem, 2.2vw, 1.7rem);
  font-family: var(--f-display); font-size: var(--t-d4); line-height: 1.24; letter-spacing: -.008em;
  transition: color 300ms linear;
}
.faq__q:hover { color: var(--rust-ink); }
.faq__sign { flex: none; width: 16px; height: 16px; position: relative; align-self: center; }
.faq__sign::before, .faq__sign::after {
  content: ''; position: absolute; inset: 50% 0 auto 0; height: 1px; background: currentColor;
  transition: transform 520ms var(--e-expo), opacity 300ms linear;
}
.faq__sign::after { transform: rotate(90deg); }
.faq__item[open] .faq__sign::after { transform: rotate(0deg); opacity: 0; }
.faq__a { overflow: hidden; display: grid; grid-template-rows: 0fr; transition: grid-template-rows 620ms var(--e-expo); }
.faq__item[open] .faq__a { grid-template-rows: 1fr; }
.faq__a > div { min-height: 0; }
.faq__a .inner { padding-bottom: clamp(1.4rem, 2.6vw, 2.2rem); max-width: 58ch; color: var(--ink-2); }
.faq__a h5 { font-family: var(--f-label); font-size: var(--t-label); letter-spacing: .16em; text-transform: uppercase; color: var(--rust-ink); margin-top: 1.4em; margin-bottom: .35em; }
.faq__a p + p { margin-top: .9em; }

/* -- JOURNAL ------------------------------------------------------------- */

.j-index { border-top: 1px solid var(--rule); }
.j-row {
  display: grid; grid-template-columns: 4.5rem 1.2fr 1fr auto; align-items: center;
  gap: clamp(1rem, 3vw, 2.5rem);
  padding-block: clamp(1.3rem, 2.4vw, 2rem);
  border-bottom: 1px solid var(--rule); text-decoration: none;
  transition: background-color 620ms var(--e-expo), padding-inline 620ms var(--e-expo);
}
.j-row:hover { background: var(--paper-hi); padding-inline: clamp(.5rem, 1.6vw, 1.5rem); }
.j-row__t { display: block; font-family: var(--f-display); font-size: var(--t-d3); line-height: 1.08; letter-spacing: -.016em; }
.j-row__by { color: var(--ink-3); }
.j-row__thumb { width: 5.5rem; aspect-ratio: 4/5; object-fit: cover; opacity: 0; transform: translateY(10px); transition: opacity 500ms var(--e-expo), transform 620ms var(--e-expo); }
.j-row:hover .j-row__thumb { opacity: 1; transform: none; }
@media (max-width: 820px) {
  .j-row { grid-template-columns: 3rem 1fr; align-items: start; row-gap: .5rem; }
  .j-row__thumb { display: none; }
  /* Four children into two columns put the byline back in the 3rem number
     gutter, where "Words by Zac Solomon" wrapped one word per line. Pin it
     to the content column so it gets the full width on its own row. */
  .j-row__by { grid-column: 2; }
}

.article__head { padding-top: calc(var(--header-h) + clamp(3rem, 9vh, 7rem)); }
.article__title { max-width: 22ch; }
.article__byline { display: flex; gap: var(--s-6); flex-wrap: wrap; align-items: baseline; margin-top: var(--s-6); }
.article__hero { margin-block: clamp(2.5rem, 6vh, 5rem); }
.article__body { display: grid; grid-template-columns: minmax(0, 1fr); justify-items: center; }
.article__body > * { width: min(100%, var(--measure)); }
.article__body > .wide { width: min(100%, 66rem); }
.article__body > .pull { width: min(100%, 52rem); }
.article__nav { display: flex; justify-content: space-between; gap: var(--s-6); flex-wrap: wrap; padding-top: var(--s-6); border-top: 1px solid var(--rule); }

/* -- MERCH --------------------------------------------------------------- */

.shop { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(1.5rem, 3vw, 3rem); }
@media (max-width: 900px) { .shop { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .shop { grid-template-columns: 1fr; } }
.prod { text-decoration: none; display: block; }
.prod .fig { background: var(--paper-lo); }
.prod__row { display: flex; justify-content: space-between; gap: var(--s-4); margin-top: var(--s-4); align-items: baseline; }
.prod__t { font-family: var(--f-display); font-size: var(--t-d4); line-height: 1.2; }
.prod__p { font-family: var(--f-label); font-size: var(--t-meta); letter-spacing: .08em; }
.prod__flag {
  position: absolute; left: 0; top: 0; z-index: 2;
  background: var(--ink); color: var(--paper);
  font-family: var(--f-label); font-size: var(--t-micro); font-weight: 620;
  letter-spacing: .18em; text-transform: uppercase; padding: .45em .8em;
}

/* Cart drawer. Behaviour lives in shop.js; width override in shop.css. */
.cart-btn { position: relative; display: inline-flex; align-items: center; gap: .4rem; }
.cart-btn__n {
  font-family: var(--f-label); font-size: var(--t-micro); font-weight: 700;
  min-width: 1.35em; height: 1.35em; display: grid; place-items: center;
  border-radius: 50%; background: var(--rust); color: var(--paper-hi);
}
.drawer {
  position: fixed; inset: 0 0 0 auto; width: min(28rem, 100vw); z-index: 950;
  background: var(--paper-hi); color: var(--ink);
  transform: translateX(101%); transition: transform 620ms var(--e-quint);
  display: flex; flex-direction: column; box-shadow: -30px 0 60px -40px rgba(28,22,16,.6);
}
body.cart-open .drawer { transform: none; }
.drawer__scrim { position: fixed; inset: 0; z-index: 940; background: rgba(20,16,11,.42); opacity: 0; pointer-events: none; transition: opacity 500ms var(--e-expo); }
body.cart-open .drawer__scrim { opacity: 1; pointer-events: auto; }
.drawer__head, .drawer__foot { padding: var(--s-5) var(--s-6); border-bottom: 1px solid var(--rule); display: flex; justify-content: space-between; align-items: center; gap: var(--s-4); }
.drawer__foot { border-bottom: 0; border-top: 1px solid var(--rule); display: block; }
.drawer__body { flex: 1; overflow-y: auto; padding: var(--s-5) var(--s-6); }
.cart-line { display: grid; grid-template-columns: 4rem 1fr auto; gap: var(--s-4); padding-block: var(--s-4); border-bottom: 1px solid var(--rule); align-items: center; }
.cart-line img { width: 4rem; aspect-ratio: 1; object-fit: cover; }

/* -- CONTACT ------------------------------------------------------------- */

.contact-grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 6vw, 6rem); align-items: start; }
@media (max-width: 900px) { .contact-grid { grid-template-columns: 1fr; } }

/* -- STYLEGUIDE ---------------------------------------------------------- */

.sg-swatches { display: grid; grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); gap: var(--s-4); }
.sg-swatch { border: 1px solid var(--rule); }
.sg-swatch__chip { height: 7.5rem; }
.sg-swatch__meta { padding: .75rem .85rem 1rem; display: grid; gap: .18rem; }
.sg-row { display: grid; grid-template-columns: 9rem 1fr; gap: var(--s-5); padding-block: var(--s-5); border-bottom: 1px solid var(--rule); align-items: baseline; }
@media (max-width: 700px) { .sg-row { grid-template-columns: 1fr; gap: .5rem; } }
.sg-elements { display: grid; grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); gap: var(--s-5); }
.sg-el { text-align: center; border: 1px solid var(--rule); padding: var(--s-5) var(--s-3) var(--s-4); background: var(--paper-hi); }
.sg-el img { height: 7rem; width: auto; margin: 0 auto var(--s-4); }
.sg-demo { border: 1px solid var(--rule); padding: var(--s-6); background: var(--paper-hi); }
code, .mono {
  font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  font-size: .82em; letter-spacing: 0; color: #8E2E12;
  background: color-mix(in srgb, var(--rust) 9%, var(--paper-hi));
  padding: .12em .35em;
}
:is(.night,.ftr,.menu,.tier--feature,.mcard--dark) code, :is(.night,.ftr,.menu,.tier--feature,.mcard--dark) .mono {
  color: var(--rust-night); background: color-mix(in srgb, var(--rust) 18%, var(--night-2));
}

/* -- MISC ---------------------------------------------------------------- */

.quiet-note { font-size: var(--t-meta); color: var(--ink-3); }
:is(.night,.ftr,.menu,.tier--feature,.mcard--dark) .quiet-note { color: var(--on-night-2); }

.cta-band { position: relative; overflow: clip; }
.cta-band .mark--a { left: -4%; bottom: -22%; width: clamp(140px, 20vw, 340px); opacity: .5; }
.cta-band .mark--b { right: -3%; top: -18%; width: clamp(110px, 15vw, 250px); opacity: .5; }

/* Custom cursor — desktop, fine pointer only */
.cursor {
  position: fixed; top: 0; left: 0; z-index: 9500; pointer-events: none;
  width: 8px; height: 8px; border-radius: 50%; background: var(--rust);
  transform: translate3d(-50%, -50%, 0);
  transition: width 420ms var(--e-expo), height 420ms var(--e-expo),
              background-color 420ms var(--e-expo), opacity 300ms linear;
  mix-blend-mode: normal;
}
.cursor.is-media { width: 84px; height: 84px; background: color-mix(in srgb, var(--rust) 88%, transparent); }
.cursor__label {
  position: absolute; inset: 0; display: grid; place-items: center;
  font-family: var(--f-label); font-size: 9px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--paper-hi);
  opacity: 0; transition: opacity 260ms linear;
}
.cursor.is-media .cursor__label { opacity: 1; }
@media (hover: none), (pointer: coarse) { .cursor { display: none; } }

/* -- ESSAY --------------------------------------------------------------- */

.essay__p { margin-top: 1.15em; }
.essay__p:first-child { margin-top: 0; }
.essay__p--open::first-letter {
  font-family: var(--f-display); float: left; font-size: 4.1em; line-height: .78;
  padding: .06em .1em 0 0; color: var(--rust);
}
.essay__h {
  font-family: var(--f-label); font-size: var(--t-label); letter-spacing: .16em;
  text-transform: uppercase; font-weight: 620; color: var(--rust-ink);
  margin-top: 2.6em; margin-bottom: .1em;
}
.essay__verse {
  font-family: var(--f-display); font-size: var(--t-d4);
  line-height: 1.62; letter-spacing: -.004em; margin-top: 1.9em;
}
.essay__verse:first-child { margin-top: 0; }
.essay__break { margin-block: clamp(3rem, 8vh, 6rem); }
.essay .pull { border-left: 0; padding-left: 0; text-align: center; }
.essay .pull::before {
  content: ''; display: block; width: 40px; height: 1px;
  background: var(--rust); margin: 0 auto clamp(1.5rem, 3vh, 2.5rem);
}


/* -- SEALS & DYNAMIC MARKS ---------------------------------------------- */

.cta-band__dyn { right: 4%; top: 50%; translate: 0 -50%; width: clamp(200px, 26vw, 430px); opacity: .9; }
.cta-band .mark--a { left: -5%; bottom: -26%; width: clamp(140px, 20vw, 320px); opacity: .34; }
.cta-band .mark--b { right: 44%; top: -20%; width: clamp(110px, 14vw, 210px); opacity: .26; }

/* A page seal: the badge that stamps a section, like a wax mark on paper. */
.seal { display: block; width: clamp(96px, 11vw, 168px); height: auto; }
.seal--lg { width: clamp(150px, 20vw, 300px); }


/* A full-width dynamic element used as a section divider. */
.divider-art {
  display: grid; place-items: center;
  padding-block: clamp(2.5rem, 7vh, 6rem);
  position: relative;
}
/* The upper bound used to be 520px on a 30vw curve, which is the right weight
   on a phone and a billboard on a desktop — the break was reading louder than
   the sections it separates. The vw term is unchanged so mobile is untouched;
   only the ceiling comes down. */
.divider-art img { width: clamp(180px, 30vw, 300px); height: auto; }
@media (min-width: 901px) {
  .divider-art { padding-block: clamp(2rem, 5vh, 4rem); }
}
.divider-art::before, .divider-art::after {
  content: ''; position: absolute; top: 50%; width: min(24vw, 300px); height: 1px; background: var(--rule);
}
.divider-art::before { left: var(--gut); }
.divider-art::after { right: var(--gut); }
:is(.night,.ftr,.menu,.tier--feature,.mcard--dark) .divider-art::before, :is(.night,.ftr,.menu,.tier--feature,.mcard--dark) .divider-art::after { background: var(--rule-night); }

.sg-logos { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: var(--s-5); }
.sg-logo { border: 1px solid var(--rule); background: var(--paper-hi); padding: var(--s-6) var(--s-4) var(--s-4); text-align: center; }
.sg-logo img { height: 8.5rem; width: auto; margin: 0 auto var(--s-4); }

/* =========================================================================
   v1.1 — polaroid-first photography, the ledger, the mark taxonomy
   ========================================================================= */

/* -- POLAROID MARQUEE ---------------------------------------------------- */
/* The member wall, moved to the top of the page and set in motion. Two rows
   travelling in opposite directions at different speeds so the band never
   reads as a single sliding strip. */

.pol-marquee {
  padding-block: clamp(1.5rem, 3.5vh, 3rem);
  background: var(--paper-lo);
  border-block: 1px solid var(--rule);
  overflow: hidden;
}
.pol-marquee .ticker + .ticker { margin-top: clamp(.6rem, 1.2vw, 1rem); }
.pol-marquee .ticker__set { gap: clamp(.6rem, 1.2vw, 1rem); padding-right: clamp(.6rem, 1.2vw, 1rem); }
.pol-marquee .pol {
  flex: none;
  width: clamp(104px, 12.5vw, 178px);
  padding: clamp(.35rem, .55vw, .5rem) clamp(.35rem, .55vw, .5rem) clamp(1.1rem, 1.8vw, 1.6rem);
}
.pol-marquee .pol:hover { transform: rotate(0deg) translateY(-5px) scale(1.03); }
.pol-marquee__rev .ticker__track { animation-direction: reverse; }
.pol-marquee__cap {
  display: flex; justify-content: space-between; gap: var(--s-5);
  padding-inline: var(--gut); padding-bottom: clamp(.9rem, 1.8vh, 1.4rem);
}

/* -- THE LEDGER ---------------------------------------------------------- */

.ledger { border-top: 1px solid var(--rule-night); }
.ledger__row {
  display: grid;
  grid-template-columns: minmax(6.5rem, 12ch) 1fr minmax(0, 34ch);
  gap: clamp(1rem, 3vw, 3rem);
  align-items: baseline;
  padding-block: clamp(1.5rem, 3vw, 2.6rem);
  border-bottom: 1px solid var(--rule-night);
  transition: background-color 620ms var(--e-expo), padding-inline 620ms var(--e-expo);
}
.ledger__row:hover { background: var(--night-2); padding-inline: clamp(.5rem, 1.4vw, 1.25rem); }
.ledger__n {
  font-family: var(--f-display);
  font-size: clamp(2.9rem, 6.2vw, 5.6rem);
  line-height: .86; letter-spacing: -.03em;
  font-variant-numeric: lining-nums;
  color: var(--on-night);
}
.ledger__n sup {
  font-family: var(--f-label); font-size: .28em; font-weight: 700;
  vertical-align: super; letter-spacing: .02em; color: var(--rust-night);
}
.ledger__t { font-family: var(--f-display); font-size: var(--t-d3); line-height: 1.1; letter-spacing: -.014em; }
.ledger__d { font-size: var(--t-small); color: var(--on-night-2); }
@media (max-width: 820px) {
  .ledger__row { grid-template-columns: 1fr; gap: .45rem; }
  .ledger__n { font-size: clamp(3.4rem, 17vw, 5rem); }
}

/* -- TIER VALUE TABLE ---------------------------------------------------- */

.tier--feature .tier__value { border-color: var(--rule-night); }
.tier--feature .tier__value .vr dt { color: var(--on-night-2); }
.tier--feature .tier__value .vr dd { color: var(--rust-night); }
.tier--feature .tier__value .vr--total { border-color: var(--rule-night); }
.tier--feature .tier__value .vr--foot { border-color: var(--rule-night); }
.tier__terms {
  margin-top: .5rem;
  font-family: var(--f-label); font-size: var(--t-meta); color: var(--ink-3);
}
.tier--feature .tier__terms { color: var(--on-night-2); }

/* -- MARK TAXONOMY ------------------------------------------------------- */
/* Each event type owns a mark for good. Repeated on the index, the detail
   page, the calendar and the door of the venue, it becomes something members
   read faster than the words. */

.taxonomy {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: clamp(.5rem, 1.4vw, 1.25rem);
}
@media (max-width: 1000px) { .taxonomy { grid-template-columns: repeat(3, 1fr); } }
/* Two across on anything phone-sized. At three the labels wrap to two lines
   and the grid reads as noise rather than a set of marks. */
@media (max-width: 900px)  { .taxonomy { grid-template-columns: repeat(2, 1fr); } }
.tax {
  display: grid; justify-items: center; text-align: center; gap: .6rem;
  padding: clamp(1rem, 1.8vw, 1.5rem) .5rem clamp(.9rem, 1.6vw, 1.25rem);
  border: 1px solid var(--rule); text-decoration: none;
  transition: background-color 520ms var(--e-expo), border-color 520ms var(--e-expo), transform 520ms var(--e-expo);
}
:is(.night,.ftr,.menu,.tier--feature,.mcard--dark) .tax { border-color: var(--rule-night); }
.tax:hover { background: var(--paper-hi); transform: translateY(-3px); }
:is(.night,.ftr,.menu,.tier--feature,.mcard--dark) .tax:hover { background: var(--night-2); }
.tax img { height: clamp(48px, 5.4vw, 74px); width: auto; }
.tax span { font-family: var(--f-label); font-size: var(--t-micro); font-weight: 620;
  letter-spacing: .11em; text-transform: uppercase; line-height: 1.3; }

/* The mark now lives permanently at the head of every event row. */
.ev { grid-template-columns: 3.6rem 4.5rem 1fr auto; }
.ev__mark { width: 3.6rem; height: auto; align-self: center; opacity: .95;
  transition: transform 620ms var(--e-expo); }
.ev:hover .ev__mark { transform: scale(1.09) rotate(-3deg); }
@media (max-width: 760px) {
  .ev { grid-template-columns: 2.6rem 1fr; grid-template-areas: "mark n" "mark body"; column-gap: 1rem; }
  .ev__mark { grid-area: mark; width: 2.6rem; align-self: start; }
  .ev__n { grid-area: n; }
  .ev > span:not(.ev__n):not(.ev__mark):not(.ev__go):not(.ev__art) { grid-area: body; }
}

/* -- MEMBERSHIP CARD ----------------------------------------------------- */

.card-strip { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(1rem, 2.4vw, 2rem); }
@media (max-width: 860px) { .card-strip { grid-template-columns: 1fr; } }
.mcard {
  position: relative; aspect-ratio: 1.586;      /* ISO/IEC 7810 ID-1 — a real card */
  border: 1px solid var(--rule-strong);
  background: var(--paper-hi);
  display: grid; align-content: space-between;
  padding: clamp(.9rem, 1.6vw, 1.35rem);
  overflow: hidden;
  transition: transform 720ms var(--e-expo), box-shadow 720ms var(--e-expo);
}
.mcard:hover { transform: translateY(-5px) rotate(-.6deg); box-shadow: 0 24px 40px -30px rgba(28,22,16,.6); }
.mcard--dark { background: var(--night); color: var(--on-night); border-color: var(--rule-night); }
.mcard__seal { position: absolute; right: -8%; bottom: -18%; width: 52%; opacity: .22; pointer-events: none; }
.mcard--dark .mcard__seal { opacity: .3; }
.mcard__name { font-family: var(--f-poster); font-size: clamp(1.6rem, 2.6vw, 2.4rem); line-height: .9; }
.mcard__no { font-family: var(--f-label); font-size: var(--t-micro); letter-spacing: .22em; }

/* -- LINEAGE BUST ---------------------------------------------------------- */
/* Sunk low enough to sit under the type as a watermark rather than compete
   with it — just legible enough that you notice him on the second look. */
.mark--bust {
  z-index: 0; opacity: .10;
  right: 4%; top: 50%; transform: translateY(-50%);
  width: min(38vw, 620px);
}
@media (min-width: 1400px) { .mark--bust { opacity: .12; } }
/* On a phone the copy fills the column, so he goes behind it rather than
   beside it — bottom-anchored and wider than the viewport so the crop reads
   as a detail rather than a shrunken whole. */
@media (max-width: 900px) {
  /* There is no room beside the copy on a phone — the band is only about one
     screen tall and the text fills the column — and the band clips its own
     overflow, so anything anchored to an edge gets cut in half. He goes
     behind the type instead, centred and oversized: the actual watermark
     treatment rather than a decoration squeezed into a margin. */
  .mark--bust {
    left: 50%; right: auto; top: 50%; bottom: auto;
    transform: translate(-50%, -50%);
    width: min(96vw, 400px); opacity: .20;
  }
}

/* -- SHELF --------------------------------------------------------------- */

/* Fixed column counts rather than auto-fill. With auto-fill the number of
   columns floats with the viewport, so no fixed item count can ever fill the
   last row — at 1440 it landed 7 across and left a four-wide hole. Each
   breakpoint now divides the item count exactly: 18 over 6 or 3, 10 over 2. */
.shelf { display: grid; grid-template-columns: repeat(6, 1fr);
  gap: clamp(.85rem, 1.8vw, 1.5rem); }
@media (max-width: 1099px) { .shelf { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 900px)  { .shelf { grid-template-columns: repeat(2, 1fr); } }
.shelf__item { border: 1px solid var(--rule-night); padding: var(--s-4); display: grid; gap: .4rem;
  align-content: start; min-height: 11rem; }
.shelf__item .num { color: var(--on-night-3); }
.shelf__t { font-family: var(--f-display); font-size: 1.06rem; line-height: 1.22; }
.shelf__m { font-family: var(--f-label); font-size: var(--t-micro); letter-spacing: .1em;
  text-transform: uppercase; color: var(--on-night-2); margin-top: auto; }
/* The grid runs seven across on a wide screen, so ten items left a ragged
   three-wide hole in the second row. Entries 011+ square it off. On a phone
   the grid is two across and ten already lands even, so they are dropped
   rather than rendered and hidden — no point shipping the DOM for them. */
@media (max-width: 900px) { .shelf__item--fill { display: none; } }


/* -- CHAPTERS ON A PHONE ------------------------------------------------- */
/* The pinned three-panel section is a desktop device. On a phone a 400vh
   sticky box that only swaps text is a scroll trap, so it unpacks into three
   ordinary stacked chapters, each with its own picture. Declared here, after
   the desktop rules, so the single-cell stacking is actually overridden. */

@media (max-width: 900px) {
  .chapters { height: auto !important; }
  .chapters__sticky {
    position: static; height: auto; display: block;
    padding-block: var(--band); overflow: visible;
  }
  .chapters__grid { display: block; }
  .chapters__media { display: none; }             /* each chapter carries its own */
  .ch__img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; margin-bottom: var(--s-4); }
  .chapters__panel { position: static; min-height: 0; display: grid; gap: 0; }
  .chapters__panel > .ch {
    grid-area: auto;                              /* one row each, not a stack */
    position: static; inset: auto; opacity: 1; transform: none; pointer-events: auto;
    display: block; padding-block: clamp(1.6rem, 4vh, 2.4rem);
    border-top: 1px solid var(--rule-night);
  }
  .chapters__panel > .ch:first-child { border-top: 0; padding-top: 0; }
  .ch h3 { font-size: var(--t-d3); }
  .ch p { max-width: none; }
  /* Nothing to track when they are all on screen at once, and with the rail
     gone the kicker no longer needs its two reserved lines either. */
  .chapters__rail { display: none; }
  .ch__kicker { min-height: 0; margin-bottom: var(--s-3); }
}

/* -- THE INVITE ---------------------------------------------------------- */
/* Paper card on a dimmed page, one clear way in and three ways out (the ×,
   the line under the form, and the scrim). Deliberately quiet: this is the
   only thing on the site that interrupts anybody, so it should look like a
   card someone handed you rather than a conversion unit. */

.invite {
  position: fixed; inset: 0; z-index: 990;
  display: grid; place-items: center;
  padding: var(--gut);
}
.invite[hidden] { display: none; }

.invite__scrim {
  position: absolute; inset: 0;
  background: rgba(20, 16, 11, .64);
  opacity: 0; transition: opacity 420ms var(--e-expo);
}
.invite.is-open .invite__scrim { opacity: 1; }

.invite__card {
  position: relative;
  width: min(34rem, 100%);
  max-height: calc(100dvh - var(--gut) * 2);
  overflow-y: auto;
  background: var(--paper-hi);
  color: var(--ink);
  padding: clamp(1.75rem, 4vw, 2.75rem);
  box-shadow: 0 40px 90px -50px rgba(20, 16, 11, .85);
  opacity: 0; transform: translateY(14px) scale(.985);
  transition: opacity 460ms var(--e-expo), transform 560ms var(--e-quint);
}
.invite.is-open .invite__card { opacity: 1; transform: none; }
/* Focus is moved here on open so a screen reader lands inside the dialog
   rather than at the top of the page behind it. It is not a control anyone
   tabs to, so it gets no focus ring — the ring belongs on the × and the
   field, which do get one from the system stylesheet. */
.invite__card:focus, .invite__card:focus-visible { outline: none; }

/* The way out. Full 44px target, always in the same corner, never a 10px × */
.invite__x {
  position: absolute; top: .5rem; right: .5rem;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  background: transparent; border: 0; cursor: pointer;
  color: var(--ink-2); border-radius: 50%;
  transition: background 240ms var(--e-expo), color 240ms var(--e-expo);
}
.invite__x svg { width: 20px; height: 20px; }
.invite__x:hover { background: color-mix(in srgb, var(--ink) 8%, transparent); color: var(--ink); }

.invite__title {
  font-family: var(--f-display);
  font-size: var(--t-d3);
  line-height: 1.02;
  letter-spacing: -.012em;
  margin-top: var(--s-3);
}
.invite__body { margin-top: var(--s-4); color: var(--ink-2); }
.invite__form { margin-top: var(--s-5); }
.invite__note { margin-top: var(--s-4); }

.invite__no {
  margin-top: var(--s-5);
  background: transparent; border: 0; padding: .35rem 0; cursor: pointer;
  font-family: var(--f-label); font-size: var(--t-meta);
  color: var(--ink-3); text-decoration: underline; text-underline-offset: 3px;
}
.invite__no:hover { color: var(--ink); }

/* Hold the page still underneath, so closing puts them back exactly where
   they were rather than at the top of the document. */
body.invite-open { overflow: hidden; }

@media (max-width: 560px) {
  .invite__card { width: 100%; }
  .invite__form .btn { width: 100%; justify-content: center; }
}

@media (prefers-reduced-motion: reduce) {
  .invite__scrim, .invite__card { transition: none; }
  .invite__card { transform: none; }
}

/* -- THE ROAD (after you join) ------------------------------------------- */
/* Five stops on one line. Wide screens run it left to right like a highway
   with mile markers; anything narrower stands it up as a spine, which is the
   only honest way to read five steps on a phone. The markup does not change
   between the two — the rail, the fill and the traveller are the same three
   elements rotated. */

.road-intro { margin-bottom: clamp(3rem, 7vh, 5.5rem); }
.road-intro__h { max-width: 20ch; }
@media (max-width: 1080px) { .road-intro { margin-bottom: clamp(2.5rem, 6vh, 4rem); } }

.road {
  --road-inset: 10px;                 /* half a dot, so the line meets centres */
  position: relative;
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: clamp(1.25rem, 2.4vw, 2.5rem);
}

/* The rail itself: one hairline the whole way, one rust line over it that is
   only as long as the reader has travelled. */
/* --road-start and --road-span are measured in journey.js off the first and
   last marker, so the rail begins and ends on a dot rather than on the edge of
   the box. --road-p is a plain 0-1 number, which is what lets the same three
   declarations serve both axes. */
.road__line, .road__fill {
  position: absolute; left: var(--road-start, 0px); top: var(--road-inset);
  height: 1px; pointer-events: none;
}
.road__line { width: var(--road-span, 100%); background: var(--rule-night); }
.road__fill {
  width: calc(var(--road-p, 0) * var(--road-span, 100%));
  background: var(--rust-night);
  transition: width 220ms linear;
}

/* The traveller. A single rust dot that runs the length of the rail as the
   section passes, so the road reads as something you are moving along rather
   than a diagram of one. */
.road__car {
  position: absolute; top: var(--road-inset);
  left: calc(var(--road-start, 0px) + var(--road-p, 0) * var(--road-span, 100%));
  width: 9px; height: 9px; margin: -4px 0 0 -4px;
  border-radius: 50%; background: var(--rust-night);
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--rust-night) 22%, transparent);
  transition: left 220ms linear;
  pointer-events: none;
}

.road__step { position: relative; padding-top: calc(var(--road-inset) * 2 + 1.4rem); }

.road__dot {
  position: absolute; top: calc(var(--road-inset) - 5px); left: 0;
  width: 11px; height: 11px; border-radius: 50%;
  background: var(--night); border: 1px solid var(--rule-night);
  transition: background 380ms var(--e-expo), border-color 380ms var(--e-expo),
              transform 380ms var(--e-expo);
}
.road__step.is-on .road__dot {
  background: var(--rust-night); border-color: var(--rust-night); transform: scale(1.18);
}

.road__n { color: var(--on-night-3); transition: color 380ms var(--e-expo); }
.road__step.is-on .road__n { color: var(--rust-night); }
.road__of { color: var(--on-night-3); }
.road__step.is-on .road__of { color: var(--on-night-3); }

.road__t {
  font-family: var(--f-display);
  font-size: var(--t-d4);
  line-height: 1.12;
  margin: var(--s-3) 0 var(--s-3);
  max-width: 18ch;
}
.road__b { color: var(--on-night-2); font-size: var(--t-small); max-width: 34ch; }

/* Reading a step lifts it very slightly out of the row. Deliberately small —
   this is a road, not a set of cards. */
.road__step { transition: transform 420ms var(--e-expo); }
@media (hover: hover) {
  .road__step:hover, .road__step:focus-within { transform: translateY(-4px); }
  .road__step:hover .road__dot, .road__step:focus-within .road__dot { transform: scale(1.35); }
}

/* -- stood up ------------------------------------------------------------- */
/* Below the width where five columns can hold a sentence, the same road runs
   down the page instead of across it. */
@media (max-width: 1080px) {
  .road {
    grid-template-columns: 1fr;
    gap: 0;
    padding-left: clamp(1.6rem, 5vw, 2.4rem);
  }
  .road__line, .road__fill {
    left: var(--road-inset); top: var(--road-start, 0px);
    width: 1px; height: auto;
  }
  .road__line { height: var(--road-span, 100%); }
  .road__fill {
    width: 1px; height: calc(var(--road-p, 0) * var(--road-span, 100%));
    transition: height 220ms linear;
  }
  .road__car {
    left: var(--road-inset);
    top: calc(var(--road-start, 0px) + var(--road-p, 0) * var(--road-span, 100%));
    margin: -4px 0 0 -4px;
    transition: top 220ms linear;
  }
  .road__step {
    padding: 0 0 clamp(1.75rem, 4.5vw, 2.75rem) clamp(1.6rem, 5vw, 2.4rem);
  }
  .road__step:last-child { padding-bottom: 0; }
  .road__dot { top: .35rem; left: calc(var(--road-inset) * -1 - 5px + var(--road-inset)); }
  .road__t { max-width: 24ch; }
  .road__b { max-width: 46ch; }
  .road__step:hover, .road__step:focus-within { transform: none; }
}

@media (max-width: 1080px) {
  /* The dot has to sit on the spine, which is now at the padding edge. */
  .road__dot { left: -5px; margin-left: 0; }
  .road { padding-left: 0; }
  .road__line, .road__fill, .road__car { left: 0; }
  .road__step { padding-left: clamp(1.75rem, 6vw, 2.75rem); }
}

/* The close. Sized like a decision rather than a link: the price rides inside
   the button so nobody has to scroll back up to check what they are agreeing
   to before they click. */
.road-close {
  margin-top: clamp(2.75rem, 7vh, 4.5rem);
  display: grid; justify-items: start; gap: var(--s-4);
}
.road-close__price {
  font-family: var(--f-label); font-size: var(--t-micro);
  letter-spacing: .14em; opacity: .78; margin-left: .1rem;
}
@media (max-width: 560px) {
  .road-close { justify-items: stretch; }
  .road-close__go { justify-content: center; }
}

@media (prefers-reduced-motion: reduce) {
  .road__fill, .road__car, .road__dot, .road__step { transition: none; }
}

/* -- TERMS --------------------------------------------------------------- */
/* A legal document, set to be read rather than skimmed. The headings keep the
   capitalisation the document itself uses — no text-transform anywhere in
   here, because the page has to show exactly what was signed off. */

.terms__h {
  font-family: var(--f-label);
  font-size: var(--t-meta);
  font-weight: 620;
  letter-spacing: .1em;
  text-transform: none;
  line-height: 1.35;
  color: var(--rust-ink);
  margin-top: var(--s-8);
  margin-bottom: var(--s-4);
  max-width: 44ch;
}
.terms__h:first-child { margin-top: 0; }

.terms p { max-width: 68ch; }

.terms__list {
  margin: var(--s-4) 0 var(--s-5);
  padding-left: 1.4rem;
  max-width: 68ch;
  list-style: disc;
}
.terms__list--num { list-style: decimal; }
.terms__list li { margin-bottom: .55em; padding-left: .25rem; }
.terms__list li::marker { color: var(--ink-4); }

/* -- WHAT YOU GET -------------------------------------------------------- */
/* Six cells welded into one hairline table, built the same way the tier cards
   below are — so the page reads as one ruled system rather than a list
   followed by a table.

   Three things are happening on top of that:

     · a ledger line at the foot of every cell, aligned across the row, so a
       reader who skims the headlines still takes five numbers away with them;
     · a hover that turns the cell into a poster rather than tinting it — the
       mark grows and bleeds off the corner and the index comes up huge in the
       poster face behind the words;
     · the rules draw themselves in reading order as the block arrives, each
       cell's contents following a beat behind its own rule, the way plates
       come off a press.

   The reveal needs no script of its own. motion.js already puts .is-in on
   anything carrying data-anim and writes a --delay from the parent's
   data-stagger, so the cell borrows both and spends them on its own
   choreography. Under prefers-reduced-motion motion.js marks everything in
   view at once and the transitions below are switched off, so the grid simply
   exists. */

.gets-intro { margin-bottom: clamp(2.5rem, 6vh, 4.5rem); }
.gets-intro h2 { max-width: 22ch; }

.gets {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border-top: 1px solid var(--rule);
}
@media (max-width: 1000px) { .gets { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px)  { .gets { grid-template-columns: 1fr; } }

.get {
  position: relative;
  display: flex; flex-direction: column;
  padding: clamp(1.6rem, 2.6vw, 2.4rem) clamp(1.25rem, 2.2vw, 2rem) clamp(1.4rem, 2.2vw, 1.9rem);
  background: transparent;
  overflow: hidden;                       /* the mark bleeds off the corner */
  transition: background 520ms var(--e-expo), color 380ms var(--e-expo);
}
/* Used as a trigger only — the cell must not fade, or the rules it is drawing
   fade in with it and the whole effect collapses into one dissolve. */
.get[data-anim] { opacity: 1; transform: none; }

/* ---- the rules, drawn ---------------------------------------------------- */
.get::before, .get::after {
  content: ''; position: absolute; background: var(--rule);
  transition: transform 700ms var(--e-expo);
  transition-delay: var(--delay, 0ms);
}
.get::before { top: 0; right: 0; width: 1px; height: 100%; transform: scaleY(0); transform-origin: 50% 0; }
.get::after  { left: 0; bottom: 0; height: 1px; width: 100%; transform: scaleX(0); transform-origin: 0 50%; }
.get.is-in::before { transform: scaleY(1); }
.get.is-in::after  { transform: scaleX(1); }

/* The right-hand rule of the last column would double the page gutter. */
.gets .get:nth-child(3n)::before { display: none; }
@media (max-width: 1000px) {
  .gets .get:nth-child(3n)::before { display: block; }
  .gets .get:nth-child(2n)::before { display: none; }
}
@media (max-width: 640px) { .gets .get::before { display: none; } }

/* ---- the contents, a beat behind ---------------------------------------- */
.get__top, .get__t, .get__b, .get__ledger {
  opacity: 0; transform: translateY(10px);
  transition: opacity 620ms var(--e-expo), transform 620ms var(--e-expo);
  transition-delay: calc(var(--delay, 0ms) + 170ms);
}
.get.is-in .get__top,
.get.is-in .get__t,
.get.is-in .get__b,
.get.is-in .get__ledger { opacity: 1; transform: none; }

.get__top {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--s-4);
  margin-bottom: clamp(1.25rem, 2.4vw, 2rem);
}
.get__n { color: var(--ink-3); transition: color 380ms var(--e-expo); }

/* A member's polaroid rather than a mark from the pack. It reuses .pol whole —
   paper edge, drop shadow, tilt — so it is the same object that runs in the
   members marquee further down the page, at a smaller size. The tilt comes in
   per cell from the template so the six do not lean the same way. */
.get__pol {
  flex: none; margin: 0;
  width: clamp(104px, 9vw, 132px);
  transform-origin: 100% 0;
  transition: transform 820ms var(--e-expo), background 520ms var(--e-expo),
              box-shadow 760ms var(--e-expo);
}
/* The window the photograph is cropped into. Fixed ratio, clipped, so a zoom
   pushes the subject up in scale without changing the frame by a pixel. */
.get__shot {
  display: block; overflow: hidden;
  aspect-ratio: .84; background: var(--paper-lo);
}
.get__shot img {
  width: 100%; height: 100%; object-fit: cover;
  transform: scale(var(--zoom, 1));
  transform-origin: var(--pos, 50% 40%);
}

.get__t {
  font-family: var(--f-display);
  font-size: var(--t-d4);
  line-height: 1.1;
  letter-spacing: -.008em;
  margin-bottom: var(--s-3);
  max-width: 20ch;
}
.get__b {
  color: var(--ink-2);
  font-size: var(--t-small);
  max-width: 34ch;
  margin-bottom: clamp(1.5rem, 3vw, 2.25rem);
  transition: color 380ms var(--e-expo), opacity 620ms var(--e-expo), transform 620ms var(--e-expo);
}

/* ---- the ledger line ----------------------------------------------------- */
/* margin-top:auto drops it to the floor of the cell, so all six sit on one
   line across the row and the block reads as an itemised receipt. */
.get__ledger {
  margin-top: auto;
  padding-top: var(--s-3);
  border-top: 1px solid var(--rule);
  font-family: var(--f-label); font-size: var(--t-micro); font-weight: 620;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-3);
  transition: color 380ms var(--e-expo), border-color 380ms var(--e-expo),
              opacity 620ms var(--e-expo), transform 620ms var(--e-expo);
}

/* ---- the poster hover ---------------------------------------------------- */
/* The index, set in the poster face at the size it would be on a bill, ghosted
   behind the words. It only exists on hover, and it is what turns a dark cell
   into a poster for one thing. */
.get__ghost {
  position: absolute; right: -.04em; bottom: -.24em;
  font-family: var(--f-poster);
  font-size: clamp(7rem, 13vw, 11rem);
  line-height: .74; letter-spacing: -.02em;
  color: var(--on-night);
  opacity: 0; transform: translateY(14px);
  pointer-events: none;
  transition: opacity 560ms var(--e-expo), transform 820ms var(--e-expo);
}

/* A rust rule that wipes in across the top — the same wipe the buttons and the
   body links already use, so it is a gesture the page has made before. */
.get__flash {
  position: absolute; left: 0; top: 0; height: 2px; width: 100%;
  background: var(--rust);
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform 620ms var(--e-expo);
}

/* The lit cell. Written twice on purpose: :hover is fenced inside
   (hover: hover) so a touch device cannot get stuck with a cell dark after
   tapping it, and .is-live is what journey.js hands to whichever cell is
   nearest the middle of the screen on a device that has no pointer. Same
   state, two ways in. */
@media (hover: hover) {
  .get:hover { background: var(--night); color: var(--on-night); }
  .get:hover .get__t { color: var(--on-night); }
  .get:hover .get__b { color: var(--on-night-2); }
  .get:hover .get__n { color: var(--rust-night); }
  .get:hover .get__ledger { color: var(--rust-night); border-color: var(--rule-night); }
  .get:hover .get__flash { transform: scaleX(1); }
  .get:hover .get__ghost { opacity: .11; transform: none; }
  /* The frame stays paper on the lit cell on purpose — a white-edged
     polaroid against black is the whole point of the object, and letting it go
     dark turns it back into a plain photograph. */
  .get:hover .get__pol { transform: rotate(0deg) scale(1.22) translate(6%, -5%); }
}

.get.is-live { background: var(--night); color: var(--on-night); }
.get.is-live .get__t { color: var(--on-night); }
.get.is-live .get__b { color: var(--on-night-2); }
.get.is-live .get__n { color: var(--rust-night); }
.get.is-live .get__ledger { color: var(--rust-night); border-color: var(--rule-night); }
.get.is-live .get__flash { transform: scaleX(1); }
.get.is-live .get__ghost { opacity: .11; transform: none; }
.get.is-live .get__pol { transform: rotate(0deg) scale(1.22) translate(6%, -5%); }

/* ---- stacked, on a phone ------------------------------------------------ */
/* One-up, the table construction turns against itself: with a rule under every
   ledger line and another under every cell, the column becomes a ladder of
   near-identical hairlines and nothing tells you where one thing ends and the
   next begins. So on a phone the cell keeps exactly one rule — its own — and
   the separation is carried by weight instead: bigger type, a bigger mark, a
   rust stat on every card, and a lit cell that runs the full width of the
   screen rather than sitting inside the gutter.

   Bleeding the grid out to the screen edges is what makes that last part
   work. The night block reaches both edges, so scrolling the section on a
   phone is a series of full-width plates rather than six boxed paragraphs. */
@media (max-width: 640px) {
  .gets {
    margin-inline: calc(var(--gut) * -1);
    border-top-color: var(--rule);
  }
  .get {
    padding: clamp(2.1rem, 7vw, 2.75rem) var(--gut) clamp(1.9rem, 6vw, 2.4rem);
  }

  /* The second hairline goes. The stat keeps its place at the foot of the
     card and carries rust instead of a rule, so every card has an accent
     whether or not it is the lit one. */
  .get__ledger {
    border-top: 0;
    padding-top: 0;
    margin-top: clamp(1.5rem, 5vw, 2rem);
    color: var(--rust-ink);
  }

  .get__t { font-size: var(--t-d3); max-width: 16ch; }
  .get__b { font-size: var(--t-body); max-width: none; }
  .get__pol { width: clamp(124px, 36vw, 156px); }
  .get__top { margin-bottom: clamp(1.5rem, 5vw, 2rem); }
  .get__ghost { font-size: clamp(9rem, 40vw, 13rem); }
}

@media (prefers-reduced-motion: reduce) {
  .get, .get::before, .get::after, .get__flash, .get__ghost, .get__pol,
  .get__top, .get__t, .get__b, .get__n, .get__ledger { transition: none; }
  .get::before { transform: scaleY(1); }
  .get::after { transform: scaleX(1); }
  .get__top, .get__t, .get__b, .get__ledger { opacity: 1; transform: none; }
}

/* -- WHERE BAND (events) -------------------------------------------------- */
/* Both columns start on the same line. Vertically centring a three-line
   headline against two short paragraphs left them beginning at completely
   different heights, which reads as a mistake rather than a composition. */
.where-band { align-items: start; }
.where-band__col { padding-top: .35rem; }
@media (max-width: 900px) { .where-band__col { padding-top: 0; } }

/* -- FAQ STEPS ------------------------------------------------------------ */
/* A numbered route inside an answer. Only the cancellation answer uses it so
   far, and it exists because three ordered actions read as three ordered
   actions and not as a paragraph with two semicolons in it. */
.faq__steps {
  margin: var(--s-4) 0 var(--s-4);
  padding-left: 1.35rem;
  list-style: decimal;
}
.faq__steps li {
  margin-bottom: .6em;
  padding-left: .3rem;
  max-width: 62ch;
}
.faq__steps li::marker {
  font-family: var(--f-label);
  font-size: var(--t-meta);
  color: var(--rust-ink);
}
.faq__steps b { font-weight: 600; color: var(--ink); }

/* -- LANDING PAGE (join.atxwritingclub.com) -----------------------------
   One page, no navigation, one destination. These rules only ever apply
   under .join-page or to classes that appear nowhere else, so nothing here
   can reach the main site. */

/* Two tiers instead of three. Scoped above the 980px breakpoint so the
   phone rule below it still wins and the cards stack, same as everywhere. */
@media (min-width: 981px) { .tiers--2 { grid-template-columns: repeat(2, 1fr); } }

/* The bar is not a nav. The badge does not link anywhere, the spots count
   sits in the middle, and the button is the only control. */
.joinbar .hdr__in { justify-content: space-between; }
.joinbar .brand { cursor: default; }
/* Held back over the hero, where the eyebrow chip is already saying it
   twenty pixels lower. It arrives with the button, once that chip is gone. */
.joinbar__spots {
  margin: 0; letter-spacing: .12em; text-transform: uppercase;
  font-size: var(--t-meta); white-space: nowrap;
  opacity: 0; transition: opacity 420ms var(--e-expo);
}
.joinbar.is-past .joinbar__spots { opacity: .72; }
/* Dead weight over the hero, where the hero has its own button two hundred
   pixels below. It arrives once the hero is gone. */
.joinbar__cta {
  opacity: 0; transform: translateY(-6px); pointer-events: none;
  transition: opacity 420ms var(--e-expo), transform 420ms var(--e-expo);
}
.joinbar.is-past .joinbar__cta { opacity: 1; transform: none; pointer-events: auto; }
@media (max-width: 760px) { .joinbar__spots { display: none; } }

/* The scarcity chip. Rust on night in the hero eyebrow — the only place on
   the page a number is allowed to shout. */
.joinflag {
  display: inline-flex; align-items: center;
  padding: .3rem .6rem .34rem;
  border: 1px solid var(--rust-night);
  color: var(--rust-night);
  font-family: var(--f-label); font-size: var(--t-meta);
  letter-spacing: .12em; text-transform: uppercase; line-height: 1;
}

/* Every section closes with this. One button, one destination, one rhythm. */
.joincta { margin-top: var(--s-6); display: flex; align-items: center; gap: var(--s-4); flex-wrap: wrap; }
.joincta__note {
  margin: 0; max-width: 44ch; font-size: var(--t-meta);
  color: var(--ink-3);
}
.night .joincta__note { color: var(--on-night-3); }

/* The card that closes each rail. It replaces one that pointed at another
   page, so it keeps the card's shape and changes only where it goes. */
.rail__card--cta { text-align: left; }

.joinftr .lockup { display: block; }
.joinftr .ftr__legal { justify-content: space-between; }
/* The only link in the footer, so it has to be a real target rather than a
   14px-tall line of type — 44px of height, padded rather than sized, so the
   legal line still reads as one row. */
.joinftr__terms {
  display: inline-flex; align-items: center; min-height: 44px;
  color: var(--on-night-3); text-decoration: underline; text-underline-offset: .25em;
}
.joinftr__terms:hover { color: var(--rust-night); }
