/* =========================================================================
   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;
  box-sizing: border-box;
  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;
  box-sizing: border-box;
  min-width: 0;
  width: min(34rem, 100%);
  max-width: 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 { padding: 1rem; }
  .invite__card {
    width: calc(100vw - 2rem);
    max-width: calc(100vw - 2rem);
    max-height: calc(100dvh - 2rem);
    padding: 1.5rem;
  }
  .invite__title, .invite__body, .invite__note { overflow-wrap: anywhere; }
  .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); }


/* -- THE SALES PAGE (join.atxwritingclub.com) ---------------------------
   Everything below is scoped either to .join-page or to a class that
   appears on no other page, so none of it can reach the main site. The
   components are deliberately quiet: on a page whose whole job is one
   decision, the design's job is to keep the argument readable and get out
   of the way of the button. */

/* 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. Not a nav: one control, and it is the button. ---------- */
.joinbar .hdr__in { justify-content: space-between; }
.joinbar .brand { cursor: default; }
/* Both of these are dead weight over the hero, which has its own button and
   its own spots chip two hundred pixels lower. They arrive together once the
   hero 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; }
.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 ------------------------------------------------ */
.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;
}

/* ---- the five buttons ------------------------------------------------- */
.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); }

/* ---- 2. the problem --------------------------------------------------- */
/* Three failure modes, ruled rather than boxed. Cards would make them look
   like features; rules make them look like a list of things that did not
   work, which is what they are. */
.prob { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0; border-top: 1px solid var(--rule-night); }
.prob__item { padding: var(--s-5) var(--s-4) var(--s-5) 0; border-right: 1px solid var(--rule-night); }
.prob__item:last-child { border-right: 0; }
.prob__item + .prob__item { padding-left: var(--s-4); }
.prob__n { color: var(--rust-night); margin: 0 0 var(--s-3); }
.prob__t { font-family: var(--f-display); font-size: var(--t-d4); line-height: 1.1; margin: 0; }
.prob__b { margin: var(--s-2) 0 0; max-width: 34ch; color: var(--on-night-2); }
@media (max-width: 860px) {
  .prob { grid-template-columns: 1fr; }
  .prob__item { border-right: 0; border-bottom: 1px solid var(--rule-night); padding: var(--s-4) 0; }
  .prob__item + .prob__item { padding-left: 0; }
  .prob__item:last-child { border-bottom: 0; }
}

/* ---- 3. the mechanism ------------------------------------------------- */
/* The one line on the page that gets to be bigger than body copy without
   being a headline. It carries the 15-20 figure, which is the single most
   persuasive number the club has. */
.mech__kicker {
  max-width: 46ch; padding-left: var(--s-4);
  border-left: 2px solid var(--rust-ink);
  font-family: var(--f-body); font-size: var(--t-lead); line-height: 1.45;
}

/* ---- 4. who teaches --------------------------------------------------- */
.speaker-head p {
  font-size: clamp(.95rem, 1.45vw, 1.15rem);
  letter-spacing: .14em;
}
.faces { display: grid; grid-template-columns: repeat(8, 1fr); gap: var(--s-3); }
.face { margin: 0; }
.face img {
  width: 100%; aspect-ratio: 1 / 1; object-fit: cover; display: block;
  filter: grayscale(1) contrast(1.05); opacity: .86;
  transition: filter 600ms var(--e-expo), opacity 400ms linear;
}
.face:hover img { filter: none; opacity: 1; }
.face__n { margin: var(--s-2) 0 0; font-size: var(--t-meta); line-height: 1.25; }
.face__r { margin: .15rem 0 0; font-family: var(--f-label); font-size: var(--t-meta);
  letter-spacing: .08em; text-transform: uppercase; color: var(--on-night-3); }
@media (max-width: 900px) { .faces { grid-template-columns: repeat(4, 1fr); } }
@media (max-width: 480px) {
  .faces { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .faces .face { grid-column: auto !important; }
}

/* ---- 6. the stack ----------------------------------------------------- */
/* A ruled list, two columns on a wide screen: what it is on the left, why it
   matters on the right. Nine rows read as a lot without anyone counting. */
.stack { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule); }
.stack__row {
  display: grid; grid-template-columns: 1.5rem 22rem 1fr; gap: var(--s-4);
  align-items: baseline;
  padding: var(--s-4) 0; border-bottom: 1px solid var(--rule);
}
.stack__mark { color: var(--rust-ink); font-family: var(--f-label); }
.stack__t { margin: 0; font-family: var(--f-display); font-size: var(--t-d4); line-height: 1.15; }
.stack__b { margin: 0; color: var(--ink-2); max-width: 58ch; }
/* On a phone the grid put the arrow on a line of its own above the title,
   which spent a whole row on a decoration. The row becomes a block and the
   arrow moves into the title as a marker. */
@media (max-width: 900px) {
  .stack__row { display: block; }
  .stack__mark { display: none; }
  .stack__t::before {
    content: "\2192"; color: var(--rust-ink);
    font-family: var(--f-label); margin-right: .5rem;
  }
  .stack__b { max-width: none; margin-top: .25rem; }
}
/* The arithmetic. The one place on the page where a sentence is allowed to
   sit on its own and be read twice. */
.stack__math {
  max-width: 46ch; margin-inline: auto; text-align: center;
  font-family: var(--f-display); font-size: var(--t-d3); line-height: 1.2;
}

/* ---- the event formats ------------------------------------------------ */
.fmts { display: grid; grid-template-columns: repeat(5, 1fr); gap: 0;
  border-top: 1px solid var(--rule); border-left: 1px solid var(--rule); }
/* A button, not a card: keyboard reachable, one tap on a phone. */
.fmt {
  display: block; width: 100%; text-align: left; font: inherit; color: inherit;
  background: none; cursor: pointer; position: relative;
  padding: var(--s-3) 2rem var(--s-3) var(--s-3);
  border: 0; border-right: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
  transition: background-color 420ms var(--e-expo);
}
.fmt:hover, .fmt:focus-visible { background: var(--paper-hi); }
.fmt__t { display: block; font-size: var(--t-meta); line-height: 1.3; }
.fmt__m { display: block; margin-top: .35rem; font-family: var(--f-label); font-size: var(--t-meta);
  letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3); }
/* The plus, drawn rather than typed so it can rotate into a minus. */
.fmt__x { position: absolute; top: var(--s-3); right: var(--s-3); width: 11px; height: 11px; }
.fmt__x::before, .fmt__x::after {
  content: ""; position: absolute; inset: 50% 0 auto 0; height: 1px;
  background: var(--rust-ink); transition: transform 420ms var(--e-expo);
}
.fmt__x::after { transform: rotate(90deg); }
.fmt[aria-expanded="true"] .fmt__x::after { transform: rotate(0deg); }
/* 0fr -> 1fr, so it animates to the height of whatever is inside without
   anyone having to know that height in advance. */
.fmt__body {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows 480ms var(--e-expo);
}
.fmt[aria-expanded="true"] .fmt__body { grid-template-rows: 1fr; }
.fmt__body > span {
  overflow: hidden; min-height: 0;
  font-size: var(--t-small); color: var(--ink-2);
}
.fmt[aria-expanded="true"] .fmt__body > span { padding-top: var(--s-3); }
@media (prefers-reduced-motion: reduce) {
  .fmt__body { transition: none; }
}
@media (max-width: 900px) { .fmts { grid-template-columns: repeat(2, 1fr); } }

/* ---- 8. risk ---------------------------------------------------------- */
.risk { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-5); }
.risk__item { padding-top: var(--s-4); border-top: 2px solid var(--rust-night); }
.risk__t { margin: 0; font-family: var(--f-display); font-size: var(--t-d4); line-height: 1.1; }
.risk__b { margin: var(--s-2) 0 0; color: var(--on-night-2); max-width: 36ch; }
@media (max-width: 860px) { .risk { grid-template-columns: 1fr; gap: var(--s-4); } }

/* ---- the footer ------------------------------------------------------- */
.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); }

/* ---- pictures on the sales page --------------------------------------- */
/* The page was a wall of type. These three components carry the images that
   break it, and none of their class names appear anywhere else. */

/* Full-bleed, edge to edge. Used once, at the turn from "alone with it" to
   "here is what it actually is" — the one place a picture argues better
   than a sentence. */
.bleed { margin: 0; position: relative; }
.bleed img {
  display: block; width: 100%; height: clamp(18rem, 46vw, 34rem);
  object-fit: cover;
}
.bleed__cap {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: var(--s-6) var(--gut) var(--s-4);
  margin: 0; color: var(--on-night);
  font-family: var(--f-label); font-size: var(--t-meta);
  letter-spacing: .12em; text-transform: uppercase;
  background: linear-gradient(to top, color-mix(in srgb, var(--night) 78%, transparent), transparent);
}

/* Copy beside a picture. The mechanism section is the one place on the page
   where the words and the evidence for them should be in the same eyeful. */
.split { display: grid; grid-template-columns: 1fr 42%; gap: clamp(2rem, 5vw, 5rem); align-items: center; }
.split__copy .lead { max-width: 46ch; }
.split__art .caption { margin-top: var(--s-3); }
@media (max-width: 900px) {
  .split { grid-template-columns: 1fr; gap: var(--s-5); }
  .split__art { order: -1; }
}

/* Three across, to break the offer list. */
.trio { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-3); }
.trio__i { margin: 0; }
@media (max-width: 700px) {
  .trio { grid-template-columns: 1fr 1fr; }
  .trio__i:last-child { display: none; }
}

/* ---- the three copy blocks the red team added ------------------------- */
/* The cost of not deciding. Rust rule on the left, same device as the
   mechanism kicker, because they are the two lines that have to land. */
.problem__cost {
  max-width: 46ch; padding-left: var(--s-4);
  border-left: 2px solid var(--rust-night);
  font-family: var(--f-body); font-size: var(--t-lead); line-height: 1.45;
  color: var(--on-night);
}
/* Why the club is capped, sitting directly under the number that claims it. */
.whycap { max-width: 62ch; color: var(--ink-2); }
/* Who it is not for. */
.notfor { list-style: none; margin: 0; padding: 0; max-width: 60ch; }
.notfor li {
  padding: var(--s-4) 0; border-bottom: 1px solid var(--rule);
  color: var(--ink-2);
}
.notfor li::before {
  content: "\2717"; color: var(--rust-ink);
  font-family: var(--f-label); margin-right: .6rem;
}

/* ---- the anchor: one course against a season -------------------------- */
/* A real table, and it has to fit a 390px phone whole — no sideways scroll,
   nothing behind a swipe. That is the whole constraint: the row label gets
   the space it needs and the two value columns are sized so the longest cell
   ("As long as you stay") wraps to two lines rather than pushing the table
   wider than the screen. */
.cmp { width: 100%; border-collapse: collapse; table-layout: fixed; }
.cmp th, .cmp td {
  padding: clamp(.7rem, 1.4vw, 1rem) clamp(.4rem, 1vw, 1rem);
  border-bottom: 1px solid var(--rule);
  text-align: center; vertical-align: middle;
}
.cmp thead th {
  font-family: var(--f-label); font-size: var(--t-meta);
  letter-spacing: .1em; text-transform: uppercase; line-height: 1.25;
  border-bottom: 1px solid var(--rule-strong);
  padding-bottom: var(--s-3);
}
/* Row headers read left, everything else centres under its column. */
.cmp tbody th {
  text-align: left; font-weight: 400; color: var(--ink-2);
  padding-left: 0; width: 42%;
}
.cmp tbody td { font-size: var(--t-small); }
/* Our column is tinted the whole height so the eye tracks one side of the
   table rather than reading it row by row. */
.cmp__ours { background: color-mix(in srgb, var(--rust-ink) 7%, transparent); }
.cmp thead .cmp__ours {
  /* Rust-ink straight is 4.37:1 on its own 7% tint — under AA for a 12px
     uppercase label, and axe is right to flag it. A fifth of the ink mixed in
     keeps the column reading as ours and takes it to 5.7:1. */
  color: color-mix(in srgb, var(--rust-ink) 80%, var(--ink));
}
.cmp tbody tr:last-child th, .cmp tbody tr:last-child td { border-bottom: 0; }
.cmp__yes { color: var(--rust-ink); font-size: 1.15em; }
.cmp__no  { color: var(--ink-3); opacity: .55; }
.cmp__note { margin: var(--s-3) 0 0; font-size: var(--t-meta); color: var(--ink-3); max-width: 56ch; }
@media (max-width: 560px) {
  .cmp tbody th { width: 44%; font-size: var(--t-small); }
  .cmp th, .cmp td { padding-inline: .3rem; }
  /* 12px floor, not 11 — the audit flags anything smaller as tiny text and
     the column headers are the one thing in this table you cannot skip. The
     tracking comes off instead, which buys back the width. */
  .cmp thead th { font-size: .75rem; letter-spacing: .02em; }
}

/* One tier. A single card stretched the full width read as a mistake, so it
   is centred at a readable measure with the rules closed on both sides. */
.tiers--1 { grid-template-columns: 1fr; max-width: 44rem; margin-inline: auto;
  border-left: 1px solid var(--rule); border-right: 1px solid var(--rule); }
.tiers--1 .tier { border-right: 0; }

@media (max-width: 760px) {
  .join-page .hero__eyebrow {
    display: grid;
    grid-template-columns: 28px minmax(0, 1fr);
    column-gap: .75rem;
    row-gap: .55rem;
    align-items: center;
  }
  .join-page .hero__eyebrow .bar { width: 28px; }
  .join-page .hero__eyebrow .label,
  .join-page .hero__eyebrow .joinflag { grid-column: 2; }
  .join-page .hero__eyebrow .joinflag {
    justify-self: start;
    margin-left: 0;
  }
}

@media (max-width: 360px) {
  .join-page .hero__eyebrow .joinflag {
    padding: .32rem .45rem .36rem;
    font-size: .65rem;
    letter-spacing: .06em;
  }
  .join-page .fmts { grid-template-columns: 1fr; }
}

/* ---- how far through --------------------------------------------------- */
.joinbar__prog {
  position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
  background: var(--rust-night); transform: scaleX(0); transform-origin: 0 50%;
}

/* ---- the phone dock ----------------------------------------------------- */
/* Phones only, and never over the hero. */
.dock { display: none; }
@media (max-width: 760px) {
  .dock {
    display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
    position: fixed; inset: auto 0 0 0; z-index: 940;
    padding: .7rem var(--gut) calc(.7rem + env(safe-area-inset-bottom));
    background: color-mix(in srgb, var(--night) 94%, transparent);
    backdrop-filter: blur(10px);
    border-top: 1px solid var(--rule-night);
    transform: translateY(110%);
    transition: transform 480ms var(--e-expo);
  }
  .dock.is-up { transform: none; }
  .dock__t { margin: 0; color: var(--on-night-2); font-size: var(--t-meta);
    letter-spacing: .1em; text-transform: uppercase; }
  .dock__b { flex: none; }
  /* Room for the dock so it never covers the last line of the footer. */
  .joinftr { padding-bottom: 4.5rem; }
  /* One button on screen at a time — the dock replaces the header's. */
  .joinbar__cta { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .dock { transition: none; }
}
/* Centred, because the single tier card underneath it is. */
.whycap--mid { margin-inline: auto; text-align: center; }

/* -- THE MEMBERSHIP PAGE ------------------------------------------------
   membership.html reuses the sales-page components above almost whole. What
   it adds is what comes from having three tiers instead of one: a chooser,
   a three-column version of the comparison table, and a strip of numbers
   under the hero. Everything here is either a new class or a modifier on an
   existing one, so nothing below can reach another page. */

/* ---- the numbers strip ------------------------------------------------ */
/* Ruled rather than boxed, same as .prob and .stack — four boxes under a
   photographic hero would read as a dashboard. */
.qs {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 0;
  border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
}
/* Centred, not hung left. Four cells across a 1320px measure are far wider
   than "52" and "WRITING SESSIONS" need, so left-aligned content left a third
   of each cell empty on its right and the row read as ragged — and the first
   cell, which has no divider to its left, sat further out than the other
   three. Centring makes every cell identical and lets the dividers do the
   work the alignment was failing to do. */
.qs__i {
  padding: var(--s-4) var(--s-3);
  border-right: 1px solid var(--rule);
  text-align: center;
}
.qs__i:last-child { border-right: 0; }
.qs__n {
  margin: 0; font-family: var(--f-display); font-size: var(--t-d2);
  line-height: 1; letter-spacing: -.02em; color: var(--rust-ink);
  /* The count-up rewrites this span every frame; a tabular figure stops the
     whole strip shuffling sideways while it runs. */
  font-variant-numeric: tabular-nums;
}
.qs__n sup { font-size: .5em; vertical-align: super; line-height: 0; }
.qs__t {
  margin: .45rem 0 0; font-family: var(--f-label); font-size: var(--t-meta);
  letter-spacing: .1em; text-transform: uppercase; color: var(--ink-2);
}
@media (max-width: 620px) {
  .qs { grid-template-columns: repeat(2, 1fr); }
  .qs__i:nth-child(2n) { border-right: 0; }
  .qs__i:nth-child(-n+2) { border-bottom: 1px solid var(--rule); }
}

/* ---- the chooser ------------------------------------------------------- */
/* Anchors, not buttons: with the script dead each one still jumps to its
   card, which is most of what it was for. */
.picks { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-3); }
.pick {
  display: flex; flex-direction: column; gap: var(--s-2);
  padding: var(--s-4); text-decoration: none; color: inherit;
  border: 1px solid var(--rule); background: var(--paper-hi);
  transition: border-color 300ms var(--e-expo), transform 300ms var(--e-expo);
}
.pick:hover, .pick:focus-visible { border-color: var(--rust-ink); transform: translateY(-2px); }
.pick__t { font-family: var(--f-display); font-size: var(--t-d4); line-height: 1.15; }
.pick__b { color: var(--ink-2); font-size: var(--t-small); }
.pick__go {
  margin-top: auto; padding-top: var(--s-3);
  font-family: var(--f-label); font-size: var(--t-meta);
  letter-spacing: .1em; text-transform: uppercase; color: var(--rust-ink);
}
.pick:hover .btn__arrow { transform: translateX(3px); }
@media (max-width: 760px) { .picks { grid-template-columns: 1fr; } }

/* The card the chooser sent you to. Two and a half seconds, then gone — a
   permanent highlight would look like a tier we had pre-selected. */
.tier.is-pick { box-shadow: inset 0 0 0 2px var(--rust-ink); }
@media (prefers-reduced-motion: no-preference) {
  .tier.is-pick { animation: pick-flash 2.6s var(--e-expo) both; }
  @keyframes pick-flash {
    0%   { box-shadow: inset 0 0 0 2px var(--rust-ink); }
    82%  { box-shadow: inset 0 0 0 2px var(--rust-ink); }
    100% { box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--rust-ink) 0%, transparent); }
  }
}
.tier:focus { outline: none; }
.tier:focus-visible { outline: 2px solid var(--rust-ink); outline-offset: -2px; }

/* ---- the tiers, side by side ------------------------------------------ */
/* Three value columns rather than two, and the same rule applies: it has to
   fit a 320px phone whole. The row label gives up the width, and the cells
   are short enough by construction — the longest is "$1,000 off". */
.cmp--3 tbody th { width: 34%; }
.cmp--3 th, .cmp--3 td { padding-inline: clamp(.3rem, .8vw, .8rem); }
@media (max-width: 560px) {
  .cmp--3 tbody th { width: 33%; font-size: var(--t-meta); line-height: 1.3; }
  .cmp--3 th, .cmp--3 td { padding-inline: .2rem; }
  /* 14px on a phone, where --t-meta is bumped. Nothing here goes under 12. */
  .cmp--3 tbody td { font-size: var(--t-meta); }
  .cmp--3 thead th { font-size: .75rem; letter-spacing: .02em; }
}

/* ---- room for the dock ------------------------------------------------- */
/* So the fixed bar never covers the last line of the site footer. */
@media (max-width: 760px) { .mem-page .ftr { padding-bottom: 4.5rem; } }

/* ---- the hero, over a bright photograph -------------------------------- */
/* The shared scrim drops to 6% at a third of the way down, which is where the
   headline sits — fine over the home page's dim evening shot, not fine over a
   sunlit one. This keeps a floor under the whole frame instead. Measured at
   11:1 on the headline and 5.6:1 on the eyebrow. */
.hero--deep .hero__scrim {
  background:
    linear-gradient(180deg, rgba(20,16,11,.62) 0%, rgba(20,16,11,.52) 26%,
                            rgba(20,16,11,.58) 58%, rgba(20,16,11,.86) 100%),
    radial-gradient(120% 80% at 50% 0%, transparent 26%, rgba(20,16,11,.42) 100%);
}
/* The chip is an outline over the join page's dark evening hero, which is
   fine there and 1.5:1 here — rust on a sunlit garage door. It gets its own
   ground instead, which also keeps it a step below the filled button rather
   than competing with it. Measured at 7.1:1. */
.join-page .hero .joinflag {
  background: var(--rust-night);
  border: 2px solid var(--rust-night);
  color: var(--night);
  font-weight: 800;
  text-shadow: none;
  box-shadow: 0 .35rem 1.2rem color-mix(in srgb, var(--night) 38%, transparent);
}
/* On a phone the eyebrow label and the spots chip do not fit on one line, and
   without this the chip simply overprints the label. */
.hero--deep .hero__eyebrow { flex-wrap: wrap; row-gap: .6rem; }
