/* ═══════════════════════════════════════════════════════════════════════════
   San Diego Bama Fans — global styles

   Every style on the site lives in this file. No Tailwind, no component style
   blocks. Written mobile-first: base rules are the phone layout and media
   queries add the wider ones.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* ─── Bootleg ────────────────────────────────────────────────────────────
     The approved direction. The surface IS the colour. Crimson is the field
     the page is built on rather than an accent applied to a white page, and
     photography punches holes in it.

     Contrast, measured rather than assumed:
     The crimson is the university's official #9e1b32, confirmed by the client
     2026-08-18. The page had drifted to #97182e; the supporting shades below
     are derived from the official colour using the same relationships the
     drifted palette already had, so the family keeps its shape.

     Contrast, measured rather than assumed:
       --bone on --field ............ 6.7:1   AA body, AAA large
       --bone-dim on --field ........ 5.0:1   AA body
       --bone on --field-deep ....... 9.9:1
       --bone on --ink ............. 16.7:1
       --field on --bone ............ 6.7:1
       --field on white ............. 7.9:1
       --ink on --bone ............. 15.9:1 */
  --field: #9e1b32;          /* the crimson surface. The university's own. */
  /* One crimson on the page, Jason 2026-08-26. This was #711122, a shade
     derived from the brand colour and used for the header, the gutters, the
     past-seasons schedule and the error text on the forms. Two reds on the home
     page was the complaint, so it now points at the brand colour itself.

     Left as an alias rather than deleted: fifteen rules reference it, and the
     places that lost their contrast because of this are a separate job. When
     those are sorted, this is the one line to change. */
  --field-deep: var(--field);
  --ink: #12080a;            /* near-black with the crimson still in it */
  --bone: #f1ebeb;           /* the light surface, tinted toward crimson */
  --bone-2: #e4dbdb;         /* one step deeper, for inset panels */
  --bone-dim: rgba(241, 235, 235, 0.82);
  --bone-line: rgba(241, 235, 235, 0.28);
  --ink-line: rgba(18, 8, 10, 0.16);

  /* Time TBD and anything else that is honestly unknown. Warm enough to read
     as "not settled" without becoming an error state. 5.6:1 on --field-deep. */
  --pending: #f0b357;

  /* Two-token accent system, per house rule. Everything that needs an accent
     reads one of these two rather than reaching for a brand color directly. */
  --color-accent: var(--bone);      /* accent ON dark and crimson surfaces */
  --color-accent-text: var(--field); /* accent ON light surfaces */

  /* ─── Legacy surface names ───────────────────────────────────────────────
     Pages built during the scaffold read these. They now point at the Bootleg
     palette so an unconverted page stays coherent instead of half-crimson and
     half-cream. They come out as each page is rebuilt in the new language;
     nothing new should reach for them. */
  --crimson: var(--field);
  --crimson-hover: var(--field-deep);
  --crimson-dim: rgba(158, 27, 50, 0.08);
  --sand: var(--bone);
  --sand-deep: var(--field-deep);

  --light: var(--bone);
  --light2: var(--bone);
  --light3: var(--bone-2);
  --light-border: var(--ink-line);

  --dark: var(--ink);
  --dark2: var(--field-deep);
  --dark-border: var(--bone-line);

  /* ─── Text ─────────────────────────────────────────────────────────────── */
  --text-on-light: var(--ink);
  --text-muted-on-light: #5b4247;   /* 7.7:1 on --bone */
  --text-on-dark: var(--bone);
  --text-muted-on-dark: var(--bone-dim);

  /* ─── Type ───────────────────────────────────────────────────────────────
     Archivo carries everything. Zilla Slab is gone: the display face in the
     approved direction is Archivo at 900, set large and tight, so a second
     family would only dilute it. Saira Condensed appears in exactly one place,
     the schedule row, where the condensed numerals are what make the row read
     as a scorebug rather than as a list. */
  --display: 'Archivo', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --sans: 'Archivo', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --condensed: 'Saira Condensed', 'Arial Narrow', system-ui, sans-serif;

  /* ─── Layout ───────────────────────────────────────────────────────────── */
  --max-width: 1180px;
  --narrow: 680px;
  --radius: 10px;
  --radius-sm: 6px;
  /* The club's mark carries its own wordmark inside the artwork, so it needs
     real height to stay legible. The header is sized around it. */
  --nav-height: 80px;

  --space-section: clamp(64px, 8vw, 112px);

  --shadow-sm: 0 1px 2px rgba(26, 21, 18, 0.06), 0 2px 8px rgba(26, 21, 18, 0.05);
  --shadow-md: 0 4px 12px rgba(26, 21, 18, 0.08), 0 12px 32px rgba(26, 21, 18, 0.08);
}

/* ═══ Reset ═══════════════════════════════════════════════════════════════ */

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 16px;
  scroll-behavior: smooth;
  /* Anchored sections clear the fixed header instead of hiding under it. */
  scroll-padding-top: calc(var(--nav-height) + 16px);
  -webkit-text-size-adjust: 100%;
}

body {
  font-family: var(--sans);
  font-weight: 400;
  background-color: var(--light);
  color: var(--text-on-light);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 700;
  line-height: 1.14;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

/* The two levels that carry the direction. Archivo at 900, tracked in tight
   enough that the counters close up and the line reads as one mass. Below h2
   the weight drops back so a card title is not competing with a page title. */
h1, h2 {
  font-weight: 900;
  line-height: 1.02;
  letter-spacing: -0.035em;
}

h5, h6 {
  font-family: var(--sans);
  font-weight: 700;
}

p {
  margin-bottom: 1.4em;
}

p:last-child {
  margin-bottom: 0;
}

a {
  color: var(--color-accent-text);
  text-decoration: none;
  transition: color 0.18s ease;
}

a:hover {
  color: var(--crimson-hover);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

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

ul, ol {
  padding-left: 1.4em;
}

li {
  margin-bottom: 0.5em;
}

li::marker {
  color: var(--color-accent-text);
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: none;
  cursor: pointer;
}

/* The hidden attribute has to win.
   A browser applies [hidden] { display: none } from its own stylesheet, which
   any class selector outranks. `.field { display: block }` was quietly beating
   it, so a field marked hidden in the markup rendered anyway. This is one of
   the few places !important is the correct tool: hidden means hidden, and there
   is never a reason for a layout rule to override it. */
[hidden] {
  display: none !important;
}

/* A single visible focus treatment everywhere, so keyboard users always know
   where they are. Never remove this without replacing it. */
:focus-visible {
  outline: 3px solid var(--crimson);
  outline-offset: 2px;
  border-radius: 2px;
}

.section-dark :focus-visible,
.footer :focus-visible,
.nav :focus-visible {
  outline-color: var(--sand);
}

/* ═══ Layout ══════════════════════════════════════════════════════════════ */

.container {
  width: 100%;
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 20px;
}

.narrow {
  max-width: var(--narrow);
  margin-left: auto;
  margin-right: auto;
}

.section-light,
.section-alt,
.section-deep,
.section-dark,
.section-crimson {
  padding: var(--space-section) 0;
}

.section-light { background-color: var(--light); }
.section-alt { background-color: var(--light2); }
.section-deep { background-color: var(--light3); }

.section-dark {
  background-color: var(--dark);
  color: var(--text-on-dark);
}

.section-crimson {
  background-color: var(--crimson);
  color: #ffffff;
}

.section-dark a,
.section-crimson a,
.footer a {
  color: var(--color-accent);
}

.section-dark a:hover,
.section-crimson a:hover,
.footer a:hover {
  color: #ffffff;
}

.section-dark li::marker,
.section-crimson li::marker {
  color: var(--color-accent);
}

.section-head {
  max-width: 720px;
  margin-bottom: 44px;
}

.section-head--center {
  margin-left: auto;
  margin-right: auto;
  text-align: center;
}

.section-title {
  font-size: clamp(1.9rem, 4.2vw, 2.75rem);
  margin-bottom: 16px;
}

.eyebrow {
  display: inline-block;
  font-family: var(--sans);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--color-accent-text);
  margin-bottom: 12px;
}

.section-dark .eyebrow,
.section-crimson .eyebrow {
  color: var(--color-accent);
}

.section-crimson .eyebrow {
  color: rgba(255, 255, 255, 0.88);
}

.lead {
  font-size: 1.09rem;
  color: var(--text-muted-on-light);
}

.section-dark .lead {
  color: var(--text-muted-on-dark);
}

.section-crimson .lead {
  color: rgba(255, 255, 255, 0.9);
}

@media (min-width: 640px) {
  .container { padding: 0 32px; }
}

/* ═══ Buttons ═════════════════════════════════════════════════════════════ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  /* 48px tall at the default font size, which clears the 44px touch target
     minimum with room to spare. */
  padding: 13px 26px;
  font-family: var(--sans);
  font-size: 0.97rem;
  font-weight: 600;
  line-height: 1.2;
  border-radius: var(--radius-sm);
  border: 2px solid transparent;
  text-align: center;
  cursor: pointer;
  transition: background-color 0.18s ease, color 0.18s ease, border-color 0.18s ease,
    transform 0.18s ease;
}

.btn:hover {
  text-decoration: none;
  transform: translateY(-1px);
}

.btn:active {
  transform: translateY(0);
}

.btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  transform: none;
}

.btn--primary {
  background-color: var(--crimson);
  border-color: var(--crimson);
  color: #ffffff;
}

.btn--primary:hover {
  background-color: var(--crimson-hover);
  border-color: var(--crimson-hover);
  color: #ffffff;
}

.btn--outline {
  background-color: transparent;
  border-color: var(--crimson);
  color: var(--crimson);
}

.btn--outline:hover {
  background-color: var(--crimson);
  color: #ffffff;
}

.section-dark .btn--outline,
.section-crimson .btn--outline {
  border-color: currentColor;
  color: var(--text-on-dark);
}

.section-dark .btn--outline:hover {
  background-color: var(--sand);
  border-color: var(--sand);
  color: var(--dark);
}

.section-crimson .btn--primary {
  background-color: #ffffff;
  border-color: #ffffff;
  color: var(--crimson);
}

.section-crimson .btn--primary:hover {
  background-color: var(--sand);
  border-color: var(--sand);
  color: var(--dark);
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 28px;
}

.btn-row--center {
  justify-content: center;
}

/* ═══ Navigation ══════════════════════════════════════════════════════════ */

.nav-wrap {
  position: sticky;
  top: 0;
  z-index: 100;
}

/* The header sits on the deep crimson rather than on the field, so the hero
   below it reads as the surface starting rather than as a second band. */
.nav {
  background-color: var(--field-deep);
  color: var(--bone);
  transition: box-shadow 0.2s ease;
}

.nav-wrap.is-scrolled .nav {
  box-shadow: 0 2px 18px rgba(18, 8, 10, 0.4);
}

.nav__inner {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 20px;
  min-height: var(--nav-height);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.nav__logo {
  display: flex;
  align-items: center;
  color: var(--text-on-dark);
  padding: 10px 0;
}

.nav__logo:hover {
  text-decoration: none;
  color: var(--sand);
}

/* The mark is bigger than the bar that holds it.
   A logo with its own wordmark baked in always loses when it is forced to fit
   a header's height, and making the header tall enough for it costs the same
   space on every page. So the bar stays a normal height and the mark hangs
   below it, overlapping whatever the page starts with. The header is
   `overflow: visible` and sits above the page, which is what lets this work.

   It shrinks back inside the bar once you scroll, so the overhang is a moment
   at the top of the page rather than something permanently covering content. */
/* The reserved width matches the mark's height because the artwork is square.
   Keep these two in step: the box is what holds space in the header row, the
   image height is what actually sizes the mark. */
.nav__logo {
  position: relative;
  width: 112px;
  height: var(--nav-height);
  flex: none;
  padding: 0;
  z-index: 2;
}

.nav__logo-img {
  position: absolute;
  top: 4px;
  left: 0;
  height: 112px;
  width: auto;
  /* The global `img { max-width: 100% }` resolves against this element's
     containing block, which is the 112px box above, so without this the mark
     gets clamped to the box width while keeping its set height and comes out
     squashed. It is deliberately allowed to exceed its box in both directions. */
  max-width: none;
  transition: height 0.22s ease, top 0.22s ease;
}

@media (min-width: 900px) {
  .nav__logo { width: 140px; }
  .nav__logo-img { height: 140px; }
}

.nav-wrap.is-scrolled .nav__logo-img {
  height: 64px;
  top: 8px;
}

@media (min-width: 900px) {
  .nav-wrap.is-scrolled .nav__logo-img { height: 72px; top: 6px; }
}

@media (prefers-reduced-motion: reduce) {
  .nav__logo-img { transition: none; }
}

.nav__wordmark {
  display: flex;
  flex-direction: column;
  line-height: 1;
}

.nav__wordmark-top {
  font-family: var(--sans);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.19em;
  text-transform: uppercase;
  color: var(--sand);
  margin-bottom: 3px;
}

.nav__wordmark-main {
  font-family: var(--display);
  font-size: 1.32rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.nav__toggle {
  position: relative;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  color: var(--text-on-dark);
  margin-right: -8px;
}

/* Three bars drawn from one element: the middle is the element itself and the
   outer two are its pseudo-elements. The middle fades and the outer two rotate
   into an X. */
.nav__toggle-bar,
.nav__toggle-bar::before,
.nav__toggle-bar::after {
  content: '';
  position: absolute;
  left: 50%;
  width: 22px;
  height: 2px;
  margin-left: -11px;
  background-color: currentColor;
  border-radius: 2px;
  transition: transform 0.22s ease, opacity 0.16s ease;
}

.nav__toggle-bar { top: 50%; margin-top: -1px; }
.nav__toggle-bar::before { top: -7px; margin-left: 0; left: 0; }
.nav__toggle-bar::after { top: 7px; margin-left: 0; left: 0; }

.nav[data-open='true'] .nav__toggle-bar { opacity: 0; }
.nav[data-open='true'] .nav__toggle-bar::before { transform: translateY(7px) rotate(45deg); opacity: 1; }
.nav[data-open='true'] .nav__toggle-bar::after { transform: translateY(-7px) rotate(-45deg); opacity: 1; }

.nav__menu {
  position: fixed;
  inset: var(--nav-height) 0 0 0;
  background-color: var(--dark);
  padding: 8px 20px 40px;
  overflow-y: auto;
  /* Hidden from both sight and the accessibility tree when closed, so a
     keyboard user cannot tab into an invisible menu. */
  visibility: hidden;
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s;
}

.nav[data-open='true'] .nav__menu {
  visibility: visible;
  opacity: 1;
  transform: translateY(0);
}

.nav__list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.nav__item {
  margin: 0;
  border-bottom: 1px solid var(--dark-border);
}

.nav__link {
  display: block;
  padding: 16px 4px;
  font-size: 1.02rem;
  font-weight: 600;
  color: var(--text-on-dark);
}

.nav__link:hover {
  color: var(--sand);
  text-decoration: none;
}

.nav__link[aria-current='page'] {
  color: var(--sand);
}

.nav__item--cta {
  border-bottom: none;
  margin-top: 20px;
}

.nav__cta {
  width: 100%;
}

@media (min-width: 900px) {
  .nav__toggle { display: none; }

  .nav__menu {
    position: static;
    inset: auto;
    padding: 0;
    background: none;
    overflow: visible;
    visibility: visible;
    opacity: 1;
    transform: none;
  }

  .nav__list {
    display: flex;
    align-items: center;
    gap: 4px;
  }

  .nav__item {
    border-bottom: none;
  }

  .nav__link {
    position: relative;
    padding: 10px 14px;
    font-size: 0.95rem;
  }

  /* Underline grows from the link rather than appearing all at once, and it
     never shifts layout because it is absolutely positioned. */
  .nav__link::after {
    content: '';
    position: absolute;
    left: 14px;
    right: 14px;
    bottom: 2px;
    height: 2px;
    background-color: var(--sand);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.2s ease;
  }

  .nav__link:hover::after,
  .nav__link[aria-current='page']::after {
    transform: scaleX(1);
  }

  .nav__item--cta { margin-top: 0; margin-left: 12px; }
  .nav__cta { width: auto; }
  .nav__cta::after { display: none; }
}

/* ═══ Hero ════════════════════════════════════════════════════════════════ */

.hero {
  position: relative;
  background-color: var(--dark);
  color: var(--text-on-dark);
  padding: clamp(72px, 12vw, 132px) 0 clamp(64px, 10vw, 108px);
  overflow: hidden;
}

/* A wide, soft crimson wash anchored off the top-right corner. It gives the
   dark hero some depth without needing an image to be present. */
.hero::before {
  content: '';
  position: absolute;
  top: -30%;
  right: -20%;
  width: 70%;
  padding-bottom: 70%;
  background: radial-gradient(circle, rgba(158, 27, 50, 0.55) 0%, rgba(158, 27, 50, 0) 68%);
  pointer-events: none;
}

.hero__inner {
  position: relative;
  max-width: 760px;
}

.hero__title {
  font-size: clamp(2.3rem, 7vw, 4rem);
  margin-bottom: 20px;
}

.hero__sub {
  font-size: clamp(1.05rem, 2.2vw, 1.22rem);
  color: var(--text-muted-on-dark);
  max-width: 56ch;
}

.page-hero {
  background-color: var(--dark);
  color: var(--text-on-dark);
  padding: clamp(48px, 8vw, 82px) 0;
}

.page-hero__title {
  font-size: clamp(1.95rem, 5vw, 3rem);
  margin-bottom: 14px;
}

.page-hero__lead {
  font-size: clamp(1.05rem, 2.4vw, 1.3rem);
  font-weight: 700;
  color: var(--text-on-dark);
  max-width: 58ch;
}

.page-hero__sub {
  color: var(--text-muted-on-dark);
  max-width: 58ch;
}

/* ═══ Cards and grids ═════════════════════════════════════════════════════ */

.grid {
  display: grid;
  gap: 24px;
}

@media (min-width: 640px) {
  .grid--2 { grid-template-columns: repeat(2, 1fr); }
  .grid--3 { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 960px) {
  .grid--3 { grid-template-columns: repeat(3, 1fr); }
}

.card {
  display: flex;
  flex-direction: column;
  background-color: var(--light);
  border: 1px solid var(--light-border);
  border-radius: var(--radius);
  overflow: hidden;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
}

.card__media {
  aspect-ratio: 16 / 9;
  background-color: var(--light3);
  overflow: hidden;
}

.card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.card__body {
  padding: 22px;
  display: flex;
  flex-direction: column;
  flex: 1;
}

.card__title {
  font-size: 1.24rem;
  margin-bottom: 8px;
}

.card__title a {
  color: inherit;
}

.card__title a:hover {
  color: var(--color-accent-text);
  text-decoration: none;
}

.card__meta {
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text-muted-on-light);
  margin-bottom: 10px;
}

.card__text {
  color: var(--text-muted-on-light);
  font-size: 0.96rem;
}

.card__footer {
  margin-top: auto;
  padding-top: 16px;
}

/* ═══ Event list ══════════════════════════════════════════════════════════ */

.event-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 16px;
}

.event {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 18px;
  align-items: start;
  margin: 0;
  padding: 20px;
  background-color: var(--light);
  border: 1px solid var(--light-border);
  border-radius: var(--radius);
}

/* The date block reads as a calendar tile, which makes a long list scannable
   without the visitor having to parse a sentence per row. It is also what
   separates upcoming from past: a solid crimson tile for what is still ahead,
   a quiet one for what has already happened. Carrying that distinction in the
   tile rather than an accent stripe down the side keeps the meaning where the
   eye is already looking. */
.event__date {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-width: 62px;
  padding: 10px 8px;
  background-color: var(--crimson);
  color: #ffffff;
  border-radius: var(--radius-sm);
  text-align: center;
  line-height: 1.1;
}

.event--past .event__date {
  background-color: var(--light3);
  color: var(--text-muted-on-light);
}

.event__month {
  font-family: var(--sans);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.92;
}

.event__day {
  font-family: var(--display);
  font-size: 1.6rem;
  font-weight: 700;
}

.event__title {
  font-size: 1.18rem;
  margin-bottom: 6px;
}

.event__title a { color: inherit; }
.event__title a:hover { color: var(--color-accent-text); text-decoration: none; }

.event__meta {
  font-size: 0.92rem;
  color: var(--text-muted-on-light);
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
}

.event__meta--tbd {
  color: var(--sand-deep);
  font-weight: 600;
}

/* ═══ Gallery ═════════════════════════════════════════════════════════════ */

.gallery-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 28px;
}

.filter-chip {
  padding: 9px 16px;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text-on-light);
  background-color: var(--light3);
  border: 1px solid transparent;
  border-radius: 999px;
  transition: background-color 0.16s ease, color 0.16s ease;
}

.filter-chip:hover {
  background-color: var(--light-border);
}

.filter-chip[aria-pressed='true'] {
  background-color: var(--crimson);
  color: #ffffff;
}

.gallery-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
  list-style: none;
  padding: 0;
  margin: 0;
}

@media (min-width: 640px) {
  .gallery-grid { grid-template-columns: repeat(3, 1fr); gap: 14px; }
}

@media (min-width: 1024px) {
  .gallery-grid { grid-template-columns: repeat(4, 1fr); }
}

.gallery-item {
  margin: 0;
}

.gallery-item[hidden] {
  display: none;
}

.gallery-item img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--radius-sm);
  background-color: var(--light3);
  transition: transform 0.25s ease;
}

.gallery-item a:hover img {
  transform: scale(1.03);
}

.gallery-group {
  margin-bottom: 48px;
}

.gallery-group__title {
  font-size: 1.3rem;
  margin-bottom: 4px;
}

.gallery-group__meta {
  font-size: 0.88rem;
  color: var(--text-muted-on-light);
  margin-bottom: 16px;
}

/* ═══ Forms ═══════════════════════════════════════════════════════════════ */

.form {
  max-width: var(--narrow);
}

.form__row {
  display: grid;
  gap: 18px;
}

@media (min-width: 640px) {
  .form__row { grid-template-columns: repeat(2, 1fr); }
}

.field {
  display: block;
  margin-bottom: 18px;
}

.field__label {
  display: block;
  font-size: 0.9rem;
  font-weight: 600;
  margin-bottom: 6px;
}

.field__req {
  color: var(--crimson);
}

.field__input {
  width: 100%;
  /* 16px minimum, or iOS Safari zooms the viewport when the field is focused. */
  font-family: var(--sans);
  font-size: 1rem;
  padding: 12px 14px;
  color: var(--text-on-light);
  background-color: var(--light);
  border: 1px solid var(--light-border);
  border-radius: var(--radius-sm);
  transition: border-color 0.16s ease, box-shadow 0.16s ease;
}

.field__input:focus {
  outline: none;
  border-color: var(--crimson);
  box-shadow: 0 0 0 3px var(--crimson-dim);
}

.field__input--area {
  resize: vertical;
  min-height: 140px;
}

/* For answers that are only ever a couple of characters, like a party size. A
   field the full width of the form reads as though a long answer is wanted. */
.field__input--short {
  max-width: 120px;
}

select.field__input {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M2 4l4 4 4-4' fill='none' stroke='%235f544c' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 40px;
}

.field__hint {
  display: block;
  font-size: 0.84rem;
  color: var(--text-muted-on-light);
  margin-top: 5px;
}

/* The honeypot is positioned off-screen rather than display:none, because some
   bots skip fields that are not rendered. It must never have a label and must
   never be named something autofill recognises. See ERRORS.md. */
.form__hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
  margin-top: 8px;
}

.form__status {
  font-size: 0.94rem;
  font-weight: 500;
  margin: 0;
}

.form__status--ok { color: var(--crimson); }
/* Deeper than the success crimson so the two states are still told apart by
   colour and not only by the words. */
.form__status--error { color: var(--field-deep); }

/* ═══ Membership tiers ════════════════════════════════════════════════════ */

.tiers {
  display: grid;
  gap: 20px;
  margin-bottom: 36px;
}

@media (min-width: 640px) {
  .tiers { grid-template-columns: repeat(2, 1fr); }
}

.tier {
  position: relative;
  padding: 26px 24px;
  background-color: var(--light);
  border: 2px solid var(--light-border);
  border-radius: var(--radius);
  cursor: pointer;
  transition: border-color 0.18s ease, box-shadow 0.18s ease;
}

.tier:hover {
  border-color: var(--crimson);
}

/* The whole card is the label for a visually hidden radio, so the entire tile
   is a tap target rather than a small circle beside it. */
.tier input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}

.tier:has(input:checked) {
  border-color: var(--crimson);
  box-shadow: 0 0 0 3px var(--crimson-dim);
}

.tier:has(input:focus-visible) {
  outline: 3px solid var(--crimson);
  outline-offset: 2px;
}

/* These are spans so the whole tile can be one <label>, so they need to be told
   to behave as blocks. */
.tier__price,
.tier__name,
.tier__blurb {
  display: block;
}

.tier__price {
  font-family: var(--display);
  font-size: 2.3rem;
  font-weight: 700;
  line-height: 1;
  color: var(--crimson);
  margin-bottom: 6px;
}

.tier__name {
  font-size: 1.1rem;
  font-weight: 700;
  margin-bottom: 6px;
}

.tier__blurb {
  font-size: 0.94rem;
  color: var(--text-muted-on-light);
}

/* ═══ Fieldsets and radios ════════════════════════════════════════════════ */

.fieldset {
  border: none;
  padding: 0;
  margin: 0 0 20px;
}

.fieldset legend {
  padding: 0;
  margin-bottom: 10px;
}

.radio-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.radio {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 11px 16px;
  font-size: 0.94rem;
  background-color: var(--light);
  border: 1px solid var(--light-border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color 0.16s ease;
}

.radio:hover {
  border-color: var(--crimson);
}

.radio input {
  width: 18px;
  height: 18px;
  accent-color: var(--crimson);
  margin: 0;
  flex-shrink: 0;
}

.radio:has(input:checked) {
  border-color: var(--crimson);
  box-shadow: 0 0 0 2px var(--crimson-dim);
}

/* ═══ Upload ══════════════════════════════════════════════════════════════ */

.upload-drop {
  display: block;
  padding: 32px 20px;
  text-align: center;
  background-color: var(--light2);
  border: 2px dashed var(--light-border);
  border-radius: var(--radius);
  cursor: pointer;
  transition: border-color 0.18s ease, background-color 0.18s ease;
}

.upload-drop:hover,
.upload-drop.is-dragover {
  border-color: var(--crimson);
  background-color: var(--crimson-dim);
}

.upload-drop__title {
  font-family: var(--display);
  font-size: 1.15rem;
  font-weight: 700;
  margin-bottom: 6px;
}

.upload-drop__hint {
  font-size: 0.9rem;
  color: var(--text-muted-on-light);
}

.upload-preview {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  list-style: none;
  padding: 0;
  margin: 20px 0 0;
}

@media (min-width: 640px) {
  .upload-preview { grid-template-columns: repeat(5, 1fr); }
}

.upload-preview li {
  position: relative;
  margin: 0;
}

.upload-preview img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--radius-sm);
}

.upload-preview__remove {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  font-size: 0.8rem;
  line-height: 1;
  color: #ffffff;
  background-color: rgba(23, 17, 15, 0.72);
  border-radius: 50%;
}

.upload-progress {
  font-size: 0.92rem;
  color: var(--text-muted-on-light);
  margin-top: 12px;
}

/* ═══ Footer ══════════════════════════════════════════════════════════════ */

.footer {
  background-color: var(--dark);
  color: var(--text-on-dark);
  padding: 56px 0 28px;
}

.footer__inner {
  display: grid;
  gap: 36px;
}

@media (min-width: 768px) {
  .footer__inner { grid-template-columns: 1.4fr 1fr 1.2fr; gap: 48px; }
}

.footer__wordmark {
  display: block;
  font-family: var(--display);
  font-size: 1.35rem;
  font-weight: 700;
  margin-bottom: 8px;
}

.footer__descriptor {
  color: var(--text-muted-on-dark);
  font-size: 0.94rem;
}

.footer__heading {
  font-family: var(--sans);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--sand);
  margin-bottom: 14px;
}

.footer__list,
.footer__social,
.footer__legal-links {
  list-style: none;
  padding: 0;
  margin: 0;
}

.footer__list li,
.footer__social li {
  margin-bottom: 0;
}

.footer__link {
  color: var(--text-on-dark);
  font-size: 0.94rem;
}

.footer__link:hover {
  color: var(--sand);
}

.footer__note {
  color: var(--text-muted-on-dark);
  font-size: 0.94rem;
}

/* Stacked, not in a row. Two links side by side read as a fragment of a
   sentence; one per line reads as a list, and matches the Explore column
   beside it. */
.footer__social {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 14px;
}

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 24px;
  justify-content: space-between;
  align-items: center;
  margin-top: 40px;
  padding-top: 20px;
  border-top: 1px solid var(--dark-border);
}

/* One size for everything on the legal row. .footer__link is 0.94rem for the
   navigation lists above, which left Privacy and dwellTEK sitting larger than
   the copyright line they sit beside. */
.footer__bottom,
.footer__bottom .footer__link {
  font-size: 0.84rem;
}

.footer__legal,
.footer__disclaimer {
  font-size: 0.84rem;
  color: var(--text-muted-on-dark);
  margin: 0;
}

.footer__legal-links {
  display: flex;
  gap: 18px;
}

/* The dwellTEK credit. Quieter than the copyright it sits beside, and its own
   span so it wraps as a unit on a phone rather than breaking mid-sentence. */
.footer__credit {
  display: inline-block;
  opacity: 0.72;
}

.footer__disclaimer {
  margin-top: 14px;
  max-width: 60ch;
}

/* ═══ Prose ═══════════════════════════════════════════════════════════════ */

.prose {
  max-width: var(--narrow);
}

.prose h2 {
  font-size: 1.55rem;
  margin: 1.8em 0 0.6em;
}

.prose h3 {
  font-size: 1.24rem;
  margin: 1.5em 0 0.5em;
}

.prose h2:first-child,
.prose h3:first-child {
  margin-top: 0;
}

.prose ul,
.prose ol {
  margin-bottom: 1.4em;
}

/* ═══ Utilities and states ════════════════════════════════════════════════ */

.skip-link {
  position: absolute;
  top: -100px;
  left: 16px;
  z-index: 200;
  padding: 12px 20px;
  background-color: var(--crimson);
  color: #ffffff;
  font-weight: 600;
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  transition: top 0.16s ease;
}

.skip-link:focus {
  top: 0;
  text-decoration: none;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.empty-state {
  padding: 40px 24px;
  text-align: center;
  background-color: var(--light2);
  border: 1px dashed var(--light-border);
  border-radius: var(--radius);
  color: var(--text-muted-on-light);
}

/* The reservation windows, shown the moment somebody picks Table Reservations.
   Crimson tinted rather than the neutral notice ground, because this one is
   selling membership rather than reporting a state. */
.res-perks {
  padding: 18px 20px;
  margin-bottom: 22px;
  background-color: var(--crimson-dim);
  border: 1px solid var(--crimson);
  border-radius: var(--radius-sm);
  font-size: 0.94rem;
}

.res-perks p {
  margin-bottom: 10px;
}

.res-perks__title {
  font-size: 1.06rem;
  font-weight: 700;
  color: var(--field-deep);
}

.res-perks__label {
  font-weight: 700;
  margin-bottom: 4px;
}

.res-perks__list {
  margin: 0 0 10px;
  padding-left: 20px;
}

.res-perks__list li {
  margin-bottom: 4px;
}

.res-perks__close {
  margin-bottom: 0;
}

.notice {
  padding: 16px 18px;
  background-color: var(--light3);
  border: 1px solid var(--light-border);
  border-radius: var(--radius-sm);
  font-size: 0.94rem;
  color: var(--text-on-light);
}

/* Success state. CHS tints a left accent bar; this notice is a uniform bordered
   block, so it tints the ground and the border instead. Crimson rather than the
   usual green, so every success on the site reads in the club's own colour. The
   webhook's email still uses green, so the two no longer match. */
.notice--ok {
  background-color: var(--crimson-dim);
  border-color: var(--crimson);
  color: var(--field-deep);
}

.notice--ok p { margin-bottom: 0; }

main:focus {
  outline: none;
}

/* ═══ Reveal on scroll ════════════════════════════════════════════════════

   Only applies once JS has confirmed it is running. Without the .js class
   nothing is hidden, so a script failure cannot leave the page blank. */

.js .reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.5s ease, transform 0.5s ease;
}

.js .reveal.is-visible {
  opacity: 1;
  transform: none;
}

.js .reveal-delay-1 { transition-delay: 0.08s; }
.js .reveal-delay-2 { transition-delay: 0.16s; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  .js .reveal {
    opacity: 1;
    transform: none;
  }

  .btn:hover,
  .card:hover,
  .gallery-item a:hover img {
    transform: none;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   BOOTLEG — the approved direction
   ═══════════════════════════════════════════════════════════════════════════

   The surface IS the colour. Crimson is the field the page is built on, not an
   accent laid over white, and photography punches holes in it. Type is Archivo
   900, large and tight.

   These are the home page components. Interior pages still run on the scaffold
   styles above and get converted one at a time.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ─── Houndstooth ──────────────────────────────────────────────────────────
   Generated from the weave rather than approximated. A 2/2 twill where the
   warp runs 4 dark to 4 light against a weft doing the same produces real
   dogtooth, legs and all. Worked out on an 8x8 grid and drawn as twelve rects,
   so it is a few hundred bytes of CSS and no image file, and it stays sharp at
   any background-size. */
.hound {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8' shape-rendering='crispEdges'%3E%3Cpath fill='%23f1ebeb' d='M2,8L0,8L0,6ZM4,6L4,8L0,4L0,2ZM0,0L2,0L4,2L4,4ZM0,0L4,4L2,4L0,2ZM2,0L4,0L8,4L6,4ZM6,0L8,0L8,2Z'/%3E%3C/svg%3E");
  background-size: 40px 40px;
}

/* ─── Hero ─────────────────────────────────────────────────────────────────
   Photograph and type occupy the same grid cell so the type sits on the image
   without absolute positioning, and the block keeps its height from whichever
   of the two is taller. */
.bl-hero {
  display: grid;
  grid-template-columns: 1fr;
  background-color: var(--field);
  color: var(--bone);
  min-height: min(78vh, 620px);
}

.bl-hero__media {
  grid-area: 1 / 1;
  position: relative;
  /* Lifting the room a little keeps faces readable once the wash lands. */
  filter: saturate(0.82) contrast(1.04) brightness(1.14);
}

.bl-hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The wash has to bed the type into the photograph without burying the room.
   The crowd stays legible at the top and the crimson has taken over by the
   fold, so the section below continues the same surface rather than starting
   a new one. */
.bl-hero__media::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(108, 15, 31, 0.08) 0%,
    rgba(108, 15, 31, 0.58) 58%,
    var(--field) 100%
  );
}

.bl-hero__body {
  grid-area: 1 / 1;
  position: relative;
  align-self: end;
  padding: clamp(28px, 6vw, 64px) 0 clamp(24px, 4vw, 44px);
}

.bl-hero__title {
  font-weight: 900;
  text-transform: uppercase;
  font-size: clamp(2.5rem, 7.4vw, 5.4rem);
  line-height: 0.88;
  letter-spacing: -0.045em;
  margin-bottom: 18px;
  text-wrap: initial; /* the line breaks are authored, not balanced */
}

.bl-hero__sub {
  max-width: 44ch;
  color: var(--bone-dim);
  font-size: 1.02rem;
  margin-bottom: 0;
}

/* A slice of the weave rather than a rule. The tile is set a little smaller
   than the strip is tall so a whole tooth shows rather than a band of dots. */
/* Black and white, at the client's request on 2026-08-17. It was crimson under
   a bone houndstooth at low opacity, which read as a dusty pink line. Ink and
   bone rather than pure #000 and #fff, so the bar stays inside the palette and
   does not sit colder than everything around it. Full opacity, because the
   whole point of the change is that the pattern is legible. */
/* One full tile tall, so a complete row of teeth reads rather than a sliced
   half that looks like loose triangles. Bigger and heavier at the client's
   request; the pattern itself is now a real vector houndstooth with straight
   diagonals rather than the 8x8 pixel grid it used to be, which is what made it
   look digitized at small sizes. */
.bl-strip {
  height: 34px;
  background-color: var(--ink);
  background-size: 34px 34px;
}

/* ─── Next watch party ─────────────────────────────────────────────────────
   Continues the hero's surface. This is the single most important block on the
   site, so it gets the largest type after the headline and nothing competes
   with it. */
.bl-next {
  background-color: var(--field);
  color: var(--bone);
  padding: clamp(36px, 6vw, 68px) 0;
}

.bl-next__inner {
  display: grid;
  gap: 28px;
  grid-template-columns: 1fr;
}

@media (min-width: 900px) {
  .bl-next__inner {
    grid-template-columns: 1.15fr 0.85fr;
    align-items: center;
    gap: 40px;
  }

  /* With a logo present the block becomes three columns: name, mark, details. */
  .bl-next__inner:has(.bl-next__crest) {
    grid-template-columns: 1fr auto 0.85fr;
  }

  .bl-next__inner:has(.bl-next__crest) .bl-next__details {
    grid-column: 3;
  }
}

/* The one kicker on the page. It names the block rather than decorating it,
   which is why it is not repeated above every other section. */
.bl-next__label {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--bone-dim);
  margin-bottom: 14px;
}

.bl-next__date {
  font-size: clamp(1rem, 2vw, 1.28rem);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  color: var(--bone-dim);
  margin-bottom: 6px;
}

.bl-next__match {
  font-size: clamp(1.9rem, 4.6vw, 3.2rem);
  font-weight: 900;
  text-transform: uppercase;
  line-height: 0.9;
  letter-spacing: -0.04em;
  margin-bottom: 0;
}

.bl-next__match a {
  color: inherit;
}

.bl-next__match a:hover {
  color: var(--bone-dim);
  text-decoration: none;
}

.bl-when {
  border-top: 1px solid var(--bone-line);
  padding-top: 18px;
  display: flex;
  flex-wrap: wrap;
  gap: 18px 28px;
  margin: 0;
}

/* Venue names run long, so the three facts hold one line once there is room
   and wrap only on narrow screens. Letting them wrap on desktop breaks the row
   into an uneven two-and-one. */
@media (min-width: 900px) {
  .bl-when { flex-wrap: nowrap; }
}

.bl-when > div { min-width: 0; }

.bl-when dt {
  font-size: 0.68rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--bone-dim);
  margin-bottom: 5px;
}

.bl-when dd {
  margin: 0;
  font-weight: 700;
  font-size: 1.06rem;
  letter-spacing: -0.01em;
  white-space: nowrap;
}

.bl-empty {
  font-size: 1.08rem;
  color: var(--bone-dim);
  max-width: 52ch;
}

.bl-empty a { color: var(--bone); }

/* ─── Schedule ─────────────────────────────────────────────────────────────
   Direction 2's scorebug row, carried into Bootleg's palette. It already
   solved the mixed-event problem, so it is reused rather than redesigned:
   football, basketball and a chapter social all sit in the same row without
   any of them looking like a special case. */
.bl-sched {
  background-color: var(--ink);
  color: var(--bone);
  padding: clamp(44px, 7vw, 84px) 0;
}

.bl-sched__head {
  max-width: 62ch;
  margin-bottom: 28px;
}

.bl-sched__title {
  font-size: clamp(1.7rem, 3.6vw, 2.5rem);
  text-transform: uppercase;
  margin-bottom: 10px;
}

.bl-sched__note {
  color: var(--bone-dim);
  font-size: 0.98rem;
  margin-bottom: 0;
}

.sched {
  list-style: none;
  margin: 0 0 24px;
  padding: 0;
  display: grid;
  gap: 1px;
  background-color: var(--bone-line);
  border-top: 1px solid var(--bone-line);
  border-bottom: 1px solid var(--bone-line);
}

/* The whole row is the target.
   Rather than wrapping the row in an anchor, which would swallow the date and
   the crests into the link text and force a second nested link for the title,
   the title's own anchor is stretched across the row with a pseudo-element.
   One link, one accessible name, and the entire row is clickable. */
.sched__row {
  position: relative;
  background-color: var(--ink);
  display: grid;
  align-items: center;
  gap: 16px;
  padding: 16px 12px;
  grid-template-columns: 60px 1fr auto;
  margin: 0;
  transition: background-color 0.18s ease;
}

.sched__name a::after {
  content: '';
  position: absolute;
  inset: 0;
  /* Above the row's own content so the whole area is clickable, below anything
     that needs its own pointer target later. */
  z-index: 1;
}

.sched__row:hover,
.sched__row:focus-within {
  background-color: #1e1013;
}

/* The date tile is what confirms the hover, because a background lift alone is
   easy to miss on a near-black surface. */
.sched__row:hover .sched__date,
.sched__row:focus-within .sched__date {
  border-color: var(--field);
}

/* The stretched pseudo-element is what receives focus visually, so the outline
   is drawn on the row instead of on a zero-height anchor. */
.sched__row:focus-within {
  outline: 3px solid var(--bone);
  outline-offset: -3px;
}

.sched__name a:focus-visible { outline: none; }

@media (prefers-reduced-motion: reduce) {
  .sched__row { transition: none; }
}

@media (max-width: 700px) {
  .sched__row {
    grid-template-columns: 56px 1fr;
    row-gap: 10px;
  }
  .sched__when {
    grid-column: 2;
    text-align: left;
  }
}

.sched__date {
  font-family: var(--condensed);
  text-transform: uppercase;
  text-align: center;
  border: 1px solid var(--bone-line);
  padding: 7px 4px;
  line-height: 1;
}

.sched__date span {
  display: block;
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  color: var(--bone-dim);
}

.sched__date strong {
  display: block;
  font-size: 1.5rem;
  font-weight: 700;
  margin-top: 3px;
  font-variant-numeric: tabular-nums;
}

.sched__teams {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

.crest {
  width: 36px;
  height: 36px;
  flex: none;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-family: var(--condensed);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.02em;
  background-color: rgba(241, 235, 235, 0.08);
  color: var(--bone-dim);
  border: 1px solid var(--bone-line);
}

.crest--home {
  background-color: var(--field);
  color: var(--bone);
  border-color: var(--field);
}

.sched__id { min-width: 0; }

.sched__name {
  font-weight: 700;
  font-size: 1.02rem;
  letter-spacing: -0.01em;
  line-height: 1.3;
  margin: 0;
}

.sched__name a { color: var(--bone); }

.sched__name a:hover { color: var(--bone-dim); }

.sched__sub {
  font-size: 0.78rem;
  color: var(--bone-dim);
  margin: 3px 0 0;
}

/* Event type is carried by a chip, never by a coloured stripe down the side of
   the row. That stripe is the single most recognisable tell of a generated
   interface and the client asked for none of them. */
.chip {
  display: inline-block;
  font-family: var(--condensed);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 3px 8px;
  border: 1px solid var(--bone-line);
  color: var(--bone-dim);
  margin-right: 8px;
  vertical-align: 2px;
}

/* Football keeps the base chip's bone treatment. It used to carry its own red,
   #d02440 with #f08a9c text, which was a second crimson sitting on a crimson
   background and the loudest of the drifted colours. Basketball and chapter
   stay blue and green because those are not red and do not compete. */
.chip--basketball { border-color: #4c8dd8; color: #9cc4ee; }
.chip--chapter { border-color: #4fa07a; color: #8fcfae; }

.sched__when {
  text-align: right;
  font-family: var(--condensed);
  text-transform: uppercase;
}

.sched__time {
  font-size: 1.16rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  margin: 0;
}

.sched__tv {
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  color: var(--bone-dim);
  margin: 3px 0 0;
}

/* An unknown kickoff is a fact, not a gap. It gets its own colour so it reads
   as information rather than as something failing to load. */
.is-pending { color: var(--pending); }

.bl-sched__more { margin: 0; }

.bl-textlink {
  font-weight: 700;
  font-size: 0.92rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--bone);
  border-bottom: 2px solid var(--field);
  padding-bottom: 2px;
}

.bl-textlink:hover {
  color: var(--bone);
  border-bottom-color: var(--bone);
  text-decoration: none;
}

/* ─── Photographs ──────────────────────────────────────────────────────────
   Full bleed and edge to edge. The gallery is the point of the site, so it is
   not boxed inside the container with everything else. */
.bl-shots {
  background-color: var(--field-deep);
  color: var(--bone);
  padding: clamp(40px, 6vw, 72px) 0 clamp(28px, 4vw, 48px);
  /* The track starts flush with the container and runs off the right edge, so
     the strip reads as continuing past the viewport rather than as a row that
     happens to end. */
  --shots-inset: max(20px, calc((100vw - var(--max-width)) / 2 + 20px));
}

@media (min-width: 640px) {
  .bl-shots {
    --shots-inset: max(32px, calc((100vw - var(--max-width)) / 2 + 32px));
  }
}

.bl-shots__head {
  max-width: 60ch;
  margin-bottom: 24px;
}

.bl-shots__title {
  font-size: clamp(1.7rem, 3.6vw, 2.5rem);
  text-transform: uppercase;
  margin-bottom: 10px;
}

.bl-shots__note {
  color: var(--bone-dim);
  font-size: 0.98rem;
  margin-bottom: 0;
}

.bl-shots__note a {
  color: var(--bone);
  border-bottom: 2px solid var(--field);
  padding-bottom: 1px;
}

.bl-shots__note a:hover {
  border-bottom-color: var(--bone);
  text-decoration: none;
}

/* ─── The strip ────────────────────────────────────────────────────────────
   Fixed height, automatic width. Every photograph keeps its own proportions
   instead of being cropped to a common square, which is what makes a mixed set
   of phone photos sit together without looking processed. */
.shots-scroll {
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -ms-overflow-style: none;
  cursor: grab;
  padding-left: var(--shots-inset);
  /* Focusable so it can be scrolled from the keyboard. A scroll container that
     only responds to a mouse is a WCAG failure, and this is the whole gallery
     on the home page. */
  scroll-behavior: smooth;
}

.shots-scroll::-webkit-scrollbar { display: none; }
.shots-scroll.is-dragging { cursor: grabbing; }
.shots-scroll.is-dragging img { pointer-events: none; }

.shots-scroll:focus-visible {
  outline: 3px solid var(--bone);
  outline-offset: -3px;
}

.shots-track {
  display: flex;
  gap: 8px;
  width: max-content;
  list-style: none;
  margin: 0;
  padding: 0 var(--shots-inset) 0 0;
}

.shots-item {
  margin: 0;
  height: 260px;
  flex: none;
  overflow: hidden;
  background-color: var(--ink);
}

@media (min-width: 720px) {
  .shots-item { height: 380px; }
}

.shots-item img {
  height: 100%;
  width: auto;
  max-width: none;
  object-fit: cover;
  transition: transform 0.4s ease;
}

.shots-item:hover img { transform: scale(1.04); }

/* The last card in the track, so the strip ends somewhere deliberate rather
   than trailing off into whitespace. */
.shots-all {
  height: 260px;
  width: 190px;
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-end;
  gap: 6px;
  padding: 20px;
  background-color: var(--field);
  color: var(--bone);
}

@media (min-width: 720px) {
  .shots-all { height: 380px; width: 240px; }
}

.shots-all:hover {
  background-color: var(--ink);
  color: var(--bone);
  text-decoration: none;
}

.shots-all__count {
  font-size: clamp(2.2rem, 5vw, 3rem);
  font-weight: 900;
  line-height: 1;
  letter-spacing: -0.04em;
}

.shots-all__label {
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--bone-dim);
}

@media (prefers-reduced-motion: reduce) {
  .shots-scroll { scroll-behavior: auto; }
  .shots-item img,
  .shots-item:hover img { transition: none; transform: none; }
}

/* ─── Membership ───────────────────────────────────────────────────────────
   The one light band on the page. A page drenched end to end has nowhere to
   rest, and prices are the one thing here that has to be read rather than
   felt. */
.bl-join {
  background-color: var(--bone);
  color: var(--ink);
  padding: clamp(48px, 8vw, 96px) 0;
}

.bl-join__head {
  max-width: 60ch;
  margin-bottom: 32px;
}

.bl-join__title {
  font-size: clamp(1.8rem, 4vw, 2.7rem);
  text-transform: uppercase;
  color: var(--field);
  margin-bottom: 12px;
}

.bl-join__lead {
  font-size: 1.08rem;
  color: var(--text-muted-on-light);
  margin-bottom: 0;
}

.tier-cards {
  display: grid;
  gap: 16px;
  grid-template-columns: 1fr;
  margin-bottom: 32px;
}

@media (min-width: 640px) {
  .tier-cards { grid-template-columns: repeat(2, 1fr); }
}

.tier-card {
  border: 1px solid var(--ink-line);
  background-color: var(--bone-2);
  padding: 24px;
}

.tier-card__price {
  font-family: var(--display);
  font-size: clamp(2.4rem, 6vw, 3.4rem);
  font-weight: 900;
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--field);
  margin-bottom: 6px;
}

.tier-card__name {
  font-size: 1.05rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 6px;
}

.tier-card__blurb {
  color: var(--text-muted-on-light);
  font-size: 0.95rem;
  margin-bottom: 0;
}

.bl-join__action { margin: 0; }

/* ─── Closing ──────────────────────────────────────────────────────────────
   Back onto the field for the last word. */
.bl-close {
  background-color: var(--field);
  color: var(--bone);
  padding: clamp(48px, 8vw, 88px) 0;
}

.bl-close__title {
  font-size: clamp(1.7rem, 3.8vw, 2.6rem);
  text-transform: uppercase;
  margin-bottom: 14px;
  max-width: 20ch;
}

.bl-close__sub {
  font-size: 1.06rem;
  color: var(--bone-dim);
  max-width: 52ch;
  margin-bottom: 26px;
}

.bl-close__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin: 0;
}

/* ─── Buttons on the field ─────────────────────────────────────────────────
   The crimson primary button disappears against a crimson surface, so the
   field gets its own pair. */
.btn--bone {
  background-color: var(--bone);
  color: var(--field-deep);
  border: 2px solid var(--bone);
}

.btn--bone:hover {
  background-color: transparent;
  color: var(--bone);
  text-decoration: none;
}

.btn--ghost {
  background-color: transparent;
  color: var(--bone);
  border: 2px solid var(--bone-line);
}

.btn--ghost:hover {
  border-color: var(--bone);
  color: var(--bone);
  text-decoration: none;
}

/* ─── Footer marks ─────────────────────────────────────────────────────────
   The club's elephant and the university-approved chapter mark sit together
   here. The club loves the elephant and the university is directing which mark
   it may use, so both appear rather than one standing in for the other. */
.footer__mark {
  height: 76px;
  width: auto;
  margin-bottom: 14px;
}

/* A white plate, because the only chapter mark available is a JPEG on white.
   Delete this rule the day a transparent version arrives. */
.footer__chapter {
  margin-top: 20px;
  background-color: #ffffff;
  padding: 12px 16px;
  border-radius: var(--radius-sm);
  max-width: 340px;
}

.footer__chapter img {
  width: 100%;
  height: auto;
}

/* ═══════════════════════════════════════════════════════════════════════════
   PROGRAM — the About page only
   ═══════════════════════════════════════════════════════════════════════════

   Direction 3 from the comps, held back for this one page. A printed game-day
   program: paper stock, a heavy slab face, double rules, and photography that
   has been through a press rather than a phone.

   It is deliberately the only page that looks like this. A page about who the
   chapter is earns a different texture; using it anywhere else would fragment
   the site. The paper is tinted toward crimson rather than yellow, so it reads
   as ink on stock instead of as the warm-cream default that every generated
   site arrives with.

   Contrast on --paper:
     --prog-ink ...... 15.2:1
     --prog-crim ...... 7.5:1
     --prog-dim ....... 5.4:1
   ═══════════════════════════════════════════════════════════════════════════ */

.program {
  --paper: #f3efef;
  --paper-2: #e7e0e1;
  --prog-ink: #171314;
  --prog-crim: #9e1b32;
  --prog-dim: #6b5f61;
  background-color: var(--paper);
  color: var(--prog-ink);
}

.program a { color: var(--prog-crim); }
.program a:hover { color: var(--prog-ink); }

.prog-slab {
  font-family: 'Alfa Slab One', Georgia, serif;
  font-weight: 400;
  letter-spacing: -0.02em;
  line-height: 0.98;
}

/* ─── Masthead ─────────────────────────────────────────────────────────── */
/* No rule under the masthead. It carried a 3px double border, which was right
   when the houndstooth below it was a faint 13% divider and wrong the moment
   that became a solid black band: two hairlines floating above a heavy band
   read as a mistake rather than a flourish. The band is the separator now. */
.prog-head {
  text-align: center;
  padding: clamp(48px, 8vw, 96px) 0 clamp(28px, 4vw, 44px);
}

/* The registered name, set like the line of small caps on a title page. */
.prog-est {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--prog-dim);
  margin-bottom: 20px;
}

.prog-head h1 {
  font-size: clamp(2.1rem, 6.4vw, 4.4rem);
  color: var(--prog-crim);
  margin-bottom: 18px;
}

.prog-lede {
  max-width: 56ch;
  margin: 0 auto;
  font-size: 1.1rem;
  color: var(--prog-dim);
}

/* A rule made of the weave rather than a line. */
/* One full tile tall, matching the 40px houndstooth. At 26px the bigger pattern
   was sliced mid-tooth and read as a row of hooks rather than houndstooth. */
.prog-rule {
  height: 40px;
  opacity: 0.13;
}

.hound--ink {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8' shape-rendering='crispEdges'%3E%3Cpath fill='%23171314' d='M2,8L0,8L0,6ZM4,6L4,8L0,4L0,2ZM0,0L2,0L4,2L4,4ZM0,0L4,4L2,4L0,2ZM2,0L4,0L8,4L6,4ZM6,0L8,0L8,2Z'/%3E%3C/svg%3E");
  background-size: 40px 40px;
}

/* ─── The billing block: plate beside copy ─────────────────────────────── */
.prog-bill {
  display: grid;
  grid-template-columns: 1fr;
}

@media (min-width: 880px) {
  .prog-bill { grid-template-columns: 1fr 1fr; }
}

/* Holds the chapter mark. This was originally built for a photograph, with a
   duotone and a cover crop over it; both were wrong for a logo and are gone.
   The plate is white rather than ink because the mark is a JPEG on white with
   black type, so a dark plate would either show a pale rectangle or need the
   mark shrunk onto a card, which reads as a sticker on a wall. */
.prog-plate {
  position: relative;
  min-height: 280px;
  overflow: hidden;
  background-color: #ffffff;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(24px, 4vw, 52px);
}

/* Fills the plate. The mark is the only thing in this half of the section, so
   there is no reason to hold it small. */
.prog-plate img {
  width: 100%;
  height: auto;
  display: block;
}

.prog-bill__body {
  background-color: var(--paper-2);
  padding: clamp(28px, 5vw, 56px);
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.prog-bill__body h2 {
  font-size: clamp(1.5rem, 3.4vw, 2.2rem);
  color: var(--prog-crim);
  margin-bottom: 16px;
}

.prog-bill__body p {
  color: var(--prog-dim);
  font-size: 1.02rem;
}

/* ─── The four pillars ─────────────────────────────────────────────────── */
/* The one crimson band in the body of the page. Everything from the masthead
   down to here was light, which left the About page reading as a lot of white
   with colour only at the very bottom.

   Deliberately the same idiom as the venue page's "What to expect": a numbered
   list on crimson, separated by bone hairlines rather than boxed into cards. The
   two "list of things" sections on the site now look like each other. */
.prog-section {
  padding: clamp(44px, 7vw, 88px) 0;
  background-color: var(--prog-crim);
  color: var(--paper);
}

.prog-section__head {
  text-align: center;
  max-width: 60ch;
  margin: 0 auto clamp(28px, 4vw, 48px);
}

.prog-section__head h2 {
  font-size: clamp(1.6rem, 3.8vw, 2.6rem);
  margin-bottom: 12px;
}

.prog-section__head p {
  color: rgba(243, 239, 239, 0.88);
  margin-bottom: 0;
}

.pillars {
  display: grid;
  gap: 1px;
  grid-template-columns: 1fr;
  background-color: rgba(243, 239, 239, 0.3);
  border-top: 1px solid rgba(243, 239, 239, 0.3);
  border-bottom: 1px solid rgba(243, 239, 239, 0.3);
  list-style: none;
  margin: 0;
  padding: 0;
}

@media (min-width: 700px) {
  .pillars { grid-template-columns: repeat(2, 1fr); }
}

.pillar {
  background-color: var(--prog-crim);
  padding: clamp(24px, 3.5vw, 36px);
  margin: 0;
}

/* A set number instead of an icon. It reads as a printed programme running
   order, and it does the job the emoji were doing without the emoji. */
.pillar__num {
  font-family: 'Alfa Slab One', Georgia, serif;
  font-weight: 400;
  font-size: 1.5rem;
  line-height: 1;
  /* Was crimson, which is invisible on crimson. Bone held back, the same call
     as the numbers on the venue page's crimson band. */
  color: var(--paper);
  opacity: 0.55;
  display: block;
  margin-bottom: 12px;
}

.pillar h3 {
  font-size: 1.16rem;
  letter-spacing: -0.01em;
  margin-bottom: 8px;
}

.pillar p {
  color: rgba(243, 239, 239, 0.88);
  font-size: 0.98rem;
  margin-bottom: 0;
}

/* ─── Closing ──────────────────────────────────────────────────────────── */
/* Ink, not crimson. With "What we stand for" now a crimson band, leaving this
   crimson too would have put two crimson slabs either side of one houndstooth
   strip and read as a single mass. The page now runs light, crimson, then dark,
   which is the same progression the venue page uses. */
.prog-close {
  background-color: var(--prog-ink);
  color: var(--paper);
  text-align: center;
  padding: clamp(44px, 7vw, 88px) 0;
}

.prog-close h2 {
  font-size: clamp(1.8rem, 5vw, 3.2rem);
  margin-bottom: 18px;
}

.prog-close p {
  max-width: 56ch;
  margin-left: auto;
  margin-right: auto;
  color: rgba(243, 239, 239, 0.88);
}

.prog-close__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  margin: 26px 0 0;
}

.prog-close .btn--bone {
  background-color: var(--paper);
  color: var(--prog-ink);
  border-color: var(--paper);
}

.prog-close .btn--bone:hover {
  background-color: transparent;
  color: var(--paper);
}

.prog-close .btn--ghost {
  color: var(--paper);
  border-color: rgba(243, 239, 239, 0.4);
}

.prog-close .btn--ghost:hover { border-color: var(--paper); color: var(--paper); }

/* The sign-off. Their words, set as the last line on the page. */
.prog-signoff {
  font-family: 'Alfa Slab One', Georgia, serif;
  font-weight: 400;
  font-size: clamp(1.4rem, 3.4vw, 2.1rem);
  letter-spacing: -0.02em;
  text-align: center;
  color: var(--prog-crim);
  padding: clamp(32px, 5vw, 56px) 0;
  margin: 0;
}

.footer__affiliation {
  margin: 0;
  padding: 18px 0 28px;
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  color: var(--bone-dim);
}

/* ═══ Bootleg: interior pages ═════════════════════════════════════════════ */

/* Page masthead. Sits on the field so the header's overhanging mark has
   something crimson to land on, the way it lands on the hero at home. */
/* Deep crimson, not the field. The next watch party below is on the field, and
   two identical crimson bands stacked read as one shapeless mass with a
   houndstooth line through it. */
.bl-page-head {
  background-color: var(--field-deep);
  color: var(--bone);
  padding: clamp(44px, 7vw, 92px) 0 clamp(32px, 5vw, 56px);
}

.bl-page-head__title {
  font-size: clamp(2.2rem, 6.4vw, 4.4rem);
  text-transform: uppercase;
  line-height: 0.9;
  margin-bottom: 16px;
}

.bl-page-head__sub {
  max-width: 58ch;
  color: var(--bone-dim);
  font-size: 1.06rem;
  margin-bottom: 14px;
}

.bl-page-head__sub:last-child {
  margin-bottom: 0;
}

/* Past seasons. Quieter than the season in play, without becoming unreadable:
   the rows keep full-strength titles and only the furniture recedes. */
.bl-sched--past { background-color: var(--field-deep); }
.bl-sched--past .sched__row { background-color: var(--field-deep); }
.bl-sched--past .sched__row:hover,
.bl-sched--past .sched__row:focus-within { background-color: var(--field); }

.season { margin-bottom: 36px; }
.season:last-child { margin-bottom: 0; }

.season__label {
  font-family: var(--condensed);
  font-size: 0.86rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--bone-dim);
  margin-bottom: 10px;
}

.sched--past .sched__crests { opacity: 0.55; }
.sched--past .sched__time { color: var(--bone-dim); font-size: 1rem; }

/* ─── Event detail ─────────────────────────────────────────────────────── */
.bl-event-head {
  background-color: var(--field);
  color: var(--bone);
  padding: clamp(40px, 6vw, 80px) 0 clamp(28px, 4vw, 48px);
}

.bl-event-head__season {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  font-family: var(--condensed);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--bone-dim);
  margin-bottom: 14px;
}

.bl-event-head__past {
  border: 1px solid var(--bone-line);
  padding: 3px 9px;
  letter-spacing: 0.14em;
}

.bl-event-head__title {
  font-size: clamp(2rem, 5.6vw, 3.8rem);
  text-transform: uppercase;
  line-height: 0.9;
  margin-bottom: 26px;
}

.bl-when--head {
  border-top-color: var(--bone-line);
  flex-wrap: wrap;
}

.bl-event-body {
  background-color: var(--bone);
  color: var(--ink);
  padding: clamp(40px, 6vw, 80px) 0;
}

/* One column on a phone, always. The image comes first in the source, so it
   stacks above the copy without any reordering. */
.bl-event-body__grid {
  display: grid;
  gap: clamp(24px, 3.5vw, 44px);
  grid-template-columns: 1fr;
}

/* A tall image goes beside the copy rather than above it. These are usually
   watch party flyers, which are portrait off a phone and repeat what the
   masthead already says, so at full width one dominated a page whose body is
   often a single sentence. Landscape images do not get this: shrunk into a
   340px column they would be postage stamps, so they keep the full width. */
@media (min-width: 800px) {
  .bl-event-body__grid--aside {
    grid-template-columns: minmax(0, 340px) minmax(0, 1fr);
    align-items: start;
  }
}

/* Whatever shape it arrives in, never cropped and never upscaled. The height
   cap only bites on the full-width case, where a tall image would otherwise
   push everything below it off the screen. */
.bl-event-body__image {
  display: block;
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 70vh;
  margin: 0 auto;
}

.bl-prose {
  max-width: 68ch;
  font-size: 1.06rem;
}

.bl-prose p { margin-bottom: 1.2em; }
.bl-prose p:last-child { margin-bottom: 0; }

.bl-notice {
  border-left: none;
  background-color: var(--bone-2);
  border: 1px solid var(--ink-line);
  padding: 16px 20px;
  font-size: 0.98rem;
}

.bl-event-body__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin: 32px 0 0;
}

/* A grid rather than the home page's strip: on a single game you want to see
   everything at once, not scroll through it. */
.shots-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 6px;
}

@media (min-width: 720px) {
  .shots-grid { grid-template-columns: repeat(4, 1fr); }
}

.shots-grid__item {
  margin: 0;
  aspect-ratio: 1;
  overflow: hidden;
  background-color: var(--ink);
}

.shots-grid__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Links on the crimson and ink surfaces.
   The global link colour is crimson, which is the right default on the bone
   pages and invisible on every dark Bootleg section. This is the counterpart to
   the scaffold's .section-dark rule, covering the new surfaces in one place so
   each new section does not have to remember. */
.bl-page-head a:not(.btn),
.bl-next a:not(.btn),
.bl-sched a:not(.btn),
.bl-shots a:not(.btn),
.bl-close a:not(.btn),
.bl-event-head a:not(.btn) {
  color: var(--bone);
}

.bl-page-head a:not(.btn):hover,
.bl-next a:not(.btn):hover,
.bl-sched a:not(.btn):hover,
.bl-shots a:not(.btn):hover,
.bl-close a:not(.btn):hover,
.bl-event-head a:not(.btn):hover {
  color: var(--bone-dim);
}

/* Buttons are excluded above: a .btn--bone carries its own colours, and forcing
   the link colour onto it paints bone text on a bone background. */

/* Body links in these sections get an underline; the row and button links do
   not, which is why this is opt-in rather than blanket. */
.bl-sched__note a,
.bl-shots__note a,
.bl-empty a {
  text-decoration: underline;
  text-underline-offset: 0.2em;
  text-decoration-thickness: 2px;
  text-decoration-color: var(--bone-line);
}

.bl-sched__note a:hover,
.bl-shots__note a:hover,
.bl-empty a:hover {
  text-decoration-color: var(--bone);
}

/* ═══ Bootleg: gallery ════════════════════════════════════════════════════ */

.bl-gallery {
  background-color: var(--bone);
  color: var(--ink);
  padding: clamp(40px, 6vw, 80px) 0;
}

.season-filter {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 36px;
}

.season-chip {
  font-family: var(--condensed);
  font-size: 0.86rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  /* 44px tall, so it clears the touch target minimum. */
  padding: 12px 18px;
  border: 1px solid var(--ink-line);
  background-color: transparent;
  color: var(--text-muted-on-light);
  transition: background-color 0.16s ease, color 0.16s ease, border-color 0.16s ease;
}

.season-chip:hover {
  border-color: var(--field);
  color: var(--field);
}

/* aria-pressed is the state, so the style keys off it rather than off a class.
   One source of truth, and the JS only ever sets the attribute. */
.season-chip[aria-pressed='true'] {
  background-color: var(--field);
  border-color: var(--field);
  color: var(--bone);
}

@media (prefers-reduced-motion: reduce) {
  .season-chip { transition: none; }
}

.game-set {
  margin-bottom: 44px;
}

.game-set:last-child { margin-bottom: 0; }

.game-set__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 16px;
  margin-bottom: 14px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--ink-line);
}

.game-set__title {
  font-size: clamp(1.3rem, 2.6vw, 1.9rem);
  text-transform: uppercase;
  margin: 0;
}

.game-set__title a { color: var(--field); }
.game-set__title a:hover { color: var(--ink); text-decoration: none; }

.game-set__meta {
  font-family: var(--condensed);
  font-size: 0.84rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted-on-light);
  margin: 0;
}

/* The empty state on a light surface. .bl-empty is written for crimson. */
.bl-empty--ink {
  color: var(--text-muted-on-light);
}

.bl-empty--ink a { color: var(--field); }

/* ═══ Bootleg: upload ═════════════════════════════════════════════════════ */

.bl-upload {
  background-color: var(--bone);
  color: var(--ink);
  padding: clamp(40px, 6vw, 80px) 0;
}

.bl-form {
  max-width: 560px;
}

.bl-field {
  display: block;
  margin-bottom: 24px;
}

.bl-field__label {
  display: block;
  font-family: var(--condensed);
  font-size: 0.88rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin-bottom: 8px;
}

.bl-field__req { color: var(--field); }

.bl-field__input {
  display: block;
  width: 100%;
  font-family: var(--sans);
  font-size: 1.02rem;
  /* 16px minimum, or iOS zooms the whole page when the field takes focus. */
  padding: 14px 16px;
  background-color: var(--bone-2);
  border: 1px solid var(--ink-line);
  color: var(--ink);
  border-radius: 0;
  -webkit-appearance: none;
  appearance: none;
}

select.bl-field__input {
  /* The arrow has to be drawn back on after appearance:none. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='%2312080a' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 16px center;
  background-size: 12px 8px;
  padding-right: 44px;
}

.bl-field__input:focus-visible {
  outline: 3px solid var(--field);
  outline-offset: 1px;
  background-color: var(--bone);
}

.bl-field__hint {
  display: block;
  font-size: 0.88rem;
  color: var(--text-muted-on-light);
  margin-top: 6px;
}

/* The drop panel. Big because it is used standing up, one-handed, in a bar. */
.bl-drop {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  text-align: center;
  min-height: 128px;
  padding: 28px 20px;
  background-color: var(--bone-2);
  border: 2px dashed var(--ink-line);
  cursor: pointer;
  transition: border-color 0.16s ease, background-color 0.16s ease;
}

.bl-drop:hover,
.bl-drop.is-dragover {
  border-color: var(--field);
  background-color: var(--bone);
}

/* The input inside is visually hidden, so focus has to be drawn on the panel. */
.bl-drop:focus-within {
  outline: 3px solid var(--field);
  outline-offset: 2px;
}

.bl-drop__title {
  font-family: var(--display);
  font-size: 1.14rem;
  font-weight: 900;
  letter-spacing: -0.02em;
  text-transform: uppercase;
}

.bl-drop__hint {
  font-size: 0.88rem;
  color: var(--text-muted-on-light);
}

.bl-thumbs {
  list-style: none;
  margin: 14px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
  gap: 8px;
}

.bl-thumbs li {
  position: relative;
  margin: 0;
  aspect-ratio: 1;
  overflow: hidden;
  background-color: var(--bone-2);
}

.bl-thumbs img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.bl-thumbs .upload-preview__remove {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  font-size: 1.1rem;
  line-height: 1;
  background-color: var(--ink);
  color: var(--bone);
  border-radius: 50%;
}

.bl-thumbs .upload-preview__remove:hover { background-color: var(--field); }

.bl-progress {
  font-family: var(--condensed);
  font-size: 0.88rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted-on-light);
  margin: 10px 0 0;
  min-height: 1.2em;
}

.bl-form__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
  margin-top: 28px;
}

.bl-form__submit {
  background-color: var(--field);
  color: var(--bone);
  border-color: var(--field);
}

.bl-form__submit:hover:not(:disabled) {
  background-color: var(--field-deep);
  border-color: var(--field-deep);
  color: var(--bone);
}

.bl-form__submit:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.bl-form__status {
  font-size: 0.96rem;
  margin: 0;
}

.bl-form__status--ok { color: var(--crimson); }
.bl-form__status--error { color: var(--field-deep); }

.bl-form__note {
  margin-top: 22px;
  padding-top: 16px;
  border-top: 1px solid var(--ink-line);
}

@media (prefers-reduced-motion: reduce) {
  .bl-drop { transition: none; }
}

/* A crest carrying a real logo rather than letters. The plate goes light so a
   dark logo reads on the near-black row, and the artwork is inset so it does
   not touch the edge of the circle. */
.crest--logo {
  background-color: var(--bone);
  border-color: var(--bone);
  padding: 4px;
  overflow: hidden;
}

.crest--logo img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

/* The home crest keeps its crimson fill unless it too has a logo. */
.crest--home.crest--logo {
  background-color: var(--bone);
  border-color: var(--bone);
}

/* The whole next-watch-party panel is the link. The title's anchor is stretched
   across it, the same trick the schedule rows use. */
.bl-next--link { position: relative; }

.bl-next--link .bl-next__match a::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
}

.bl-next--link:hover { background-color: var(--crimson-hover); }

.bl-next--link:focus-within {
  outline: 3px solid var(--bone);
  outline-offset: -3px;
}

.bl-next--link .bl-next__match a:focus-visible { outline: none; }

/* The location link sits inside the panel, so it has to be lifted above the
   stretched overlay or it becomes unclickable. Same fix as .sched__venue on a
   schedule row. */
.bl-next--link .bl-when a {
  position: relative;
  z-index: 2;
  border-bottom: 1px solid var(--bone-line);
}

.bl-next--link .bl-when a:hover {
  border-bottom-color: var(--bone);
  text-decoration: none;
}

.bl-next__go {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 14px 0 0;
  font-family: var(--condensed);
  font-size: 0.84rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--bone-dim);
}

.bl-next--link:hover .bl-next__go { color: var(--bone); }

.bl-next__go svg { transition: transform 0.18s ease; }
.bl-next--link:hover .bl-next__go svg { transform: translateX(3px); }

@media (prefers-reduced-motion: reduce) {
  .bl-next__go svg,
  .bl-next--link:hover .bl-next__go svg { transition: none; transform: none; }
}

/* 4. The vs/at label and the opponent mark. */
.sched__facing {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: none;
}

.sched__vs {
  font-family: var(--condensed);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--bone-dim);
  min-width: 1.6em;
  text-align: right;
}

@media (max-width: 460px) {
  .sched__facing { gap: 6px; }
  .sched__vs { font-size: 0.72rem; min-width: 0; }
}

/* The occasion on an event page, beside the season. */
.bl-event-head__note {
  border: 1px solid var(--bone-line);
  padding: 3px 9px;
  letter-spacing: 0.14em;
  color: var(--bone);
}

/* The opponent's mark beside the next watch party. Only ever rendered when a
   logo exists, so the layout does not reserve space for one that never comes. */
.bl-next__crest {
  display: none;
}

@media (min-width: 900px) {
  .bl-next__crest {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    grid-row: 1;
    grid-column: 2;
    padding-left: 24px;
  }

  .bl-next__crest img {
    width: auto;
    height: clamp(72px, 8vw, 110px);
    max-width: 100%;
    object-fit: contain;
    /* The plate keeps a dark logo legible on the crimson field. */
    background-color: var(--bone);
    border-radius: 50%;
    padding: 10px;
  }
}

/* Event detail header: title on the left, opponent mark on the right. The mark
   is only ever rendered when one exists, so the row collapses to a single
   column rather than reserving space for an absent logo. */
.bl-event-head__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}

.bl-event-head__lead {
  min-width: 0;
  flex: 1 1 320px;
}

.bl-event-head__crest {
  flex: none;
}

.bl-event-head__crest img {
  width: auto;
  height: clamp(84px, 11vw, 140px);
  object-fit: contain;
  background-color: var(--bone);
  border-radius: 50%;
  padding: 12px;
}

/* ═══ Location page ═══════════════════════════════════════════════════════ */

.venue-head {
  position: relative;
  background-color: var(--ink);
  color: var(--bone);
}

.venue-head__media {
  position: relative;
  max-height: 52vh;
  overflow: hidden;
}

/* Anchored near the top, not centred. The Smoking Gun's sign hangs on the
   ceiling in the top 8-22% of this photograph, and a centred cover crop cut it
   off entirely on shorter viewports: at 1440x900 the crop was already eating the
   top 25% of the image. 8% keeps the sign clear at every width from 1440 to
   2560 with headroom above it. */
.venue-head__media img {
  width: 100%;
  height: 100%;
  max-height: 52vh;
  object-fit: cover;
  object-position: 50% 8%;
}

/* The venue's own photograph gets to be the photograph. The wash only darkens
   the lower part enough to carry the name, rather than drenching it in crimson
   the way our own hero does. This page is about them. */
.venue-head__media::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(18, 8, 10, 0) 35%, rgba(18, 8, 10, 0.9) 100%);
}

.venue-head__body {
  position: relative;
  padding: 28px 0 clamp(28px, 4vw, 44px);
  margin-top: -1px;
  background-color: var(--ink);
}

/* With a photo above, the name overlaps it rather than sitting in its own band. */
@media (min-width: 720px) {
  .venue-head__media + .venue-head__body {
    margin-top: clamp(-160px, -12vw, -90px);
    background: transparent;
  }
}

.venue-head__label {
  font-family: var(--condensed);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--bone-dim);
  margin-bottom: 14px;
}

.venue-head__title {
  font-size: clamp(2rem, 5.6vw, 3.6rem);
  text-transform: uppercase;
  margin-bottom: 10px;
}

.venue-logo img {
  width: auto;
  height: clamp(56px, 9vw, 96px);
  max-width: 100%;
  object-fit: contain;
}

/* A light logo needs dark behind it, which the ink surface already provides.
   The class exists so a dark logo can be given a plate instead. */
.venue-logo--light img {
  background: transparent;
  padding: 0;
}

.venue-logo:not(.venue-logo--light) img {
  background-color: var(--bone);
  padding: 12px 16px;
  border-radius: var(--radius-sm);
}

.venue-head__tagline {
  font-size: 1.02rem;
  color: var(--bone-dim);
  margin: 14px 0 0;
}

.venue-body {
  background-color: var(--bone);
  color: var(--ink);
  padding: clamp(40px, 6vw, 76px) 0;
}

.venue-grid {
  display: grid;
  gap: 32px;
  grid-template-columns: 1fr;
}

@media (min-width: 860px) {
  .venue-grid {
    grid-template-columns: 1.4fr 0.6fr;
    gap: 48px;
  }
}

.venue-about__note,
.venue-about__thanks {
  color: var(--text-muted-on-light);
  max-width: 62ch;
}

.venue-about__thanks {
  margin-top: 20px;
  padding-top: 18px;
  border-top: 1px solid var(--ink-line);
}

.venue-facts {
  display: grid;
  gap: 22px;
  align-content: start;
}

.venue-fact__label {
  font-family: var(--condensed);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-muted-on-light);
  margin-bottom: 6px;
}

.venue-fact__value {
  font-size: 1.04rem;
  font-weight: 600;
  line-height: 1.5;
  margin: 0;
}

.venue-links {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 6px;
}

.venue-links li { margin: 0; }

.venue-links a,
.venue-fact__value a {
  color: var(--field);
  border-bottom: 2px solid transparent;
}

.venue-links a:hover,
.venue-fact__value a:hover {
  border-bottom-color: var(--field);
  text-decoration: none;
}

/* ─── The venue photo band ──────────────────────────────────────────────── */

/* Full bleed with no gutters and no container, so it runs the whole width of
   the screen and gives the page a horizontal breath between the crimson band
   above it and the ink schedule below. No padding and no background: the
   photographs are the section. */
.venue-band {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
}

/* A crimson wash over the whole band, at the client's request. Multiply rather
   than a flat overlay, so the photographs keep their own shadows instead of
   going flat behind a sheet of colour. Same technique as the About page plate.
   Not clickable, so it cannot swallow anything underneath it. */
.venue-band::after {
  content: '';
  position: absolute;
  inset: 0;
  background-color: var(--field);
  mix-blend-mode: multiply;
  opacity: 0.42;
  pointer-events: none;
}

@media (min-width: 720px) {
  .venue-band { grid-template-columns: repeat(3, 1fr); }
}

/* Square, because the files are already cropped square. The aspect ratio is
   stated anyway so the row cannot go ragged if a photo is ever swapped for one
   of a different shape. */
.venue-band img,
.venue-band video {
  width: 100%;
  height: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  display: block;
}

/* The venue link inside a schedule row. The row's own title link covers the
   whole row via a stretched pseudo-element, so this has to be lifted above it
   or it is unclickable. */
.sched__venue {
  position: relative;
  z-index: 2;
  color: var(--bone-dim);
  border-bottom: 1px solid var(--bone-line);
}

.sched__venue:hover {
  color: var(--bone);
  border-bottom-color: var(--bone);
  text-decoration: none;
}

/* The venue under a game heading in the gallery. */
.game-set__venue {
  font-size: 0.9rem;
  margin: 4px 0 0;
}

.game-set__venue a {
  color: var(--text-muted-on-light);
  border-bottom: 1px solid var(--ink-line);
}

.game-set__venue a:hover {
  color: var(--field);
  border-bottom-color: var(--field);
  text-decoration: none;
}

/* ═══ Lightbox ════════════════════════════════════════════════════════════ */

/* The thumbnail is a button, so it has to be stripped back to behaving like the
   image it wraps. */
.shot-open {
  display: block;
  width: 100%;
  height: 100%;
  padding: 0;
  border: none;
  background: none;
  cursor: zoom-in;
}

.shot-open img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.35s ease;
}

.shot-open:hover img { transform: scale(1.04); }

.shot-open:focus-visible {
  outline: 3px solid var(--field);
  outline-offset: -3px;
}

.lb {
  position: fixed;
  inset: 0;
  z-index: 500;
  /* A column rather than a centred box: the photo and its details read as one
     group, instead of the photo centring in the viewport while the caption is
     pinned to the bottom with a gap between them. */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 64px 16px 24px;
}

.lb[hidden] { display: none; }

.lb__backdrop {
  position: absolute;
  inset: 0;
  border: none;
  padding: 0;
  /* Solid, not translucent. The page behind is a bright crimson field, and even
     6% of it bleeding through competes with the photograph, which is the one
     thing this view exists to show. */
  background-color: var(--ink);
  cursor: zoom-out;
}

.lb__frame {
  position: relative;
  z-index: 1;
  min-height: 0;
  display: grid;
  place-items: center;
}

/* Sized against the viewport rather than the parent.
   A percentage height inside a shrink-to-fit flex column is circular: the
   frame's height comes from the image and the image's height comes from the
   frame, so the browser falls back to the image's intrinsic size and a large
   photo overflows. Subtracting the chrome explicitly is the one thing that
   holds at every window size.

   The reserve covers the caption block, the column gap and the padding.
   dvh first so a phone's collapsing address bar does not clip it, with vh as
   the fallback for browsers that lack dvh. */
.lb__img {
  max-width: 100%;
  max-height: calc(100vh - 230px);
  max-height: calc(100dvh - 230px);
  width: auto;
  height: auto;
  object-fit: contain;
  display: block;
}

.lb__btn {
  position: absolute;
  z-index: 2;
  width: 48px;
  height: 48px;
  display: grid;
  place-items: center;
  color: var(--bone);
  background-color: rgba(18, 8, 10, 0.6);
  border: 1px solid var(--bone-line);
  border-radius: 50%;
}

.lb__btn:hover {
  background-color: var(--field);
  border-color: var(--field);
}

.lb__btn:focus-visible {
  outline: 3px solid var(--bone);
  outline-offset: 2px;
}

.lb__btn[hidden] { display: none; }

.lb__btn--close { top: 16px; right: 16px; }
.lb__btn--prev { left: 12px; top: 50%; transform: translateY(-50%); }
.lb__btn--next { right: 12px; top: 50%; transform: translateY(-50%); }

@media (min-width: 720px) {
  .lb__btn--close { top: 24px; right: 24px; }
  .lb__btn--prev { left: 24px; }
  .lb__btn--next { right: 24px; }
}

/* Details under the photo. Centred and quiet: it names what you are looking at
   without competing with it. */
.lb__meta {
  position: relative;
  z-index: 2;
  flex: none;
  max-width: 46ch;
  text-align: center;
}

.lb__game {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(0.98rem, 2.4vw, 1.18rem);
  font-weight: 900;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  color: var(--bone);
}

.lb__game:empty { display: none; }

.lb__when {
  margin: 3px 0 0;
  font-size: 0.86rem;
  color: var(--bone-dim);
}

.lb__when:empty { display: none; }

.lb__count {
  margin: 6px 0 0;
  font-family: var(--condensed);
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(241, 235, 235, 0.55);
}

@media (prefers-reduced-motion: reduce) {
  .shot-open img,
  .shot-open:hover img { transition: none; transform: none; }
}

/* ═══ Venmo instructions ══════════════════════════════════════════════════ */

/* Replaces the form once Venmo is chosen. The reference code is the whole
   point of this panel, so it is the largest thing on it. */
.venmo-panel {
  max-width: 560px;
  padding: clamp(24px, 4vw, 36px);
  background-color: var(--bone-2);
  border: 1px solid var(--ink-line);
}

.venmo-panel[hidden] { display: none; }

.venmo-panel__title {
  font-size: clamp(1.5rem, 3.4vw, 2.1rem);
  text-transform: uppercase;
  color: var(--field);
  margin-bottom: 12px;
}

.venmo-panel__lead {
  font-size: 1.06rem;
  margin-bottom: 20px;
}

.venmo-code {
  font-family: var(--condensed);
  font-size: clamp(1.8rem, 6vw, 2.6rem);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-align: center;
  color: var(--bone);
  background-color: var(--ink);
  padding: 16px 12px;
  margin: 0 0 20px;
  /* Selectable on purpose: somebody will want to copy rather than retype it. */
  user-select: all;
}

.venmo-panel__actions { margin: 0 0 18px; }

.venmo-panel__note {
  font-size: 0.92rem;
  color: var(--text-muted-on-light);
  margin: 0;
  padding-top: 16px;
  border-top: 1px solid var(--ink-line);
}

/* The hint under each payment option. */
.radio__hint {
  display: block;
  font-size: 0.88rem;
  color: var(--text-muted-on-light);
  margin-top: 2px;
}

/* The headline now carries the page, so the tagline rule is retired in favour
   of a lede sized to be read rather than glanced at. */
.venue-head__lede {
  font-size: clamp(1.06rem, 2.4vw, 1.24rem);
  color: var(--bone-dim);
  max-width: 46ch;
  margin: 14px 0 0;
}

.venue-head__title {
  margin-top: 14px;
}

/* Every paragraph in the copy block is the same size. They carry equal weight,
   so making the first one larger read as an error rather than as emphasis. */
.venue-about__para {
  font-size: 1.06rem;
  line-height: 1.65;
  max-width: 62ch;
  margin-bottom: 1.1em;
}

.venue-about__para:last-child { margin-bottom: 0; }

.venue-about__para strong {
  font-weight: 700;
  color: var(--ink);
}

/* ─── What to expect ────────────────────────────────────────────────────── */

/* Crimson, not ink. The schedule directly below is on the ink, and two dark
   sections stacked read as one shapeless block. This also gives the page a
   rhythm: bone, crimson, ink, bone, crimson. */
.venue-expect {
  background-color: var(--field);
  color: var(--bone);
  padding: clamp(40px, 6vw, 76px) 0;
}

.venue-expect__title {
  font-size: clamp(1.6rem, 3.6vw, 2.4rem);
  text-transform: uppercase;
  margin-bottom: 28px;
}

.venue-expect__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1px;
  grid-template-columns: 1fr;
  background-color: var(--bone-line);
  border-top: 1px solid var(--bone-line);
  border-bottom: 1px solid var(--bone-line);
}

@media (min-width: 760px) {
  .venue-expect__list { grid-template-columns: repeat(2, 1fr); }
}

.venue-expect__list li {
  margin: 0;
  padding: 18px 16px;
  background-color: var(--field);
  display: flex;
  align-items: baseline;
  gap: 14px;
  font-size: 1.02rem;
}

/* The number does the job the client's emoji did: it marks each line without
   borrowing somebody else's artwork or being read aloud as "football". */
.venue-expect__num {
  font-family: var(--display);
  font-size: 0.9rem;
  font-weight: 900;
  letter-spacing: 0.02em;
  color: var(--bone);
  opacity: 0.55;
  flex: none;
}

/* The sign-off. Their words, set as the last thing before the call to action. */
/* One full-width photograph of the room in use. Edge to edge with no gutters,
   so it butts straight up against the bone sign-off above it and the crimson
   closing block below.

   The file is cut at 2.4:1 and shown at 2.4:1 on anything wide enough, so the
   browser is not cropping an already cropped image. Below that a 2.4:1 strip
   across a phone is about 150px tall and the faces stop being readable, so it
   opens up to 16:9 and takes the crop from the middle, where the crowd is. */
.venue-scene {
  position: relative;
  display: block;
}

/* Same wash as .venue-band, same values, so the two read as one treatment.
   Multiply rather than a flat overlay, so the photograph keeps its own shadows
   instead of going flat behind a sheet of colour. */
.venue-scene::after {
  content: '';
  position: absolute;
  inset: 0;
  background-color: var(--field);
  mix-blend-mode: multiply;
  opacity: 0.42;
  pointer-events: none;
}

.venue-scene__img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  object-position: center;
}

@media (min-width: 720px) {
  .venue-scene__img { aspect-ratio: 2.4 / 1; }
}

.venue-signoff {
  background-color: var(--bone);
  color: var(--field);
  font-family: var(--display);
  font-size: clamp(1.4rem, 4vw, 2.2rem);
  font-weight: 900;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  text-align: center;
  margin: 0;
  padding: clamp(32px, 5vw, 56px) 20px;
}

/* An odd last item spans the row rather than leaving a dead cell beside it.
   :nth-child(odd):last-child is "the last one, when the count is odd". */
@media (min-width: 760px) {
  .venue-expect__list li:nth-child(odd):last-child {
    grid-column: 1 / -1;
  }
}

/* ═══ Membership page ═════════════════════════════════════════════════════ */

/* The deeper light surface, not the default bone. --light and --light2 are the
   same colour in this palette, so the band and the form below it would have run
   together into one undifferentiated field with a gap in the middle. */
.join-benefits {
  background-color: var(--light3);
  padding: clamp(40px, 6vw, 68px) 0;
}

.join-benefits__title {
  font-size: clamp(1.5rem, 3.4vw, 2.1rem);
  text-transform: uppercase;
  margin-bottom: clamp(20px, 3vw, 32px);
}

/* One column on a phone, three across once there is room. Hairline gaps rather
   than cards, the same treatment as the what-to-expect list on the venue page,
   so the two read as the same site. */
.join-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1px;
  grid-template-columns: 1fr;
  background-color: var(--ink-line);
  border-top: 1px solid var(--ink-line);
  border-bottom: 1px solid var(--ink-line);
}

@media (min-width: 860px) {
  .join-list { grid-template-columns: repeat(3, 1fr); }
}

.join-list__item {
  margin: 0;
  padding: clamp(22px, 3vw, 32px);
  background-color: var(--light3);
}

.join-list__num {
  display: block;
  font-size: 0.9rem;
  font-weight: 900;
  letter-spacing: 0.02em;
  color: var(--color-accent-text);
  margin-bottom: 12px;
}

.join-list__heading {
  font-size: 1.14rem;
  line-height: 1.25;
  margin-bottom: 8px;
}

.join-list__body {
  color: var(--text-muted-on-light);
  font-size: 0.98rem;
  margin-bottom: 0;
}

/* The reservation windows. Indented under their benefit rather than run into
   the paragraph, because the whole point of them is the contrast between the
   two, and that only reads when they are on separate lines. */
.join-list__points {
  list-style: none;
  margin: 14px 0 0;
  padding: 0;
  display: grid;
  gap: 8px;
}

.join-list__points li {
  margin: 0;
  padding-left: 16px;
  position: relative;
  font-size: 0.92rem;
  color: var(--text-muted-on-light);
}

.join-list__points li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 6px;
  height: 1px;
  background-color: var(--color-accent-text);
}

/* The term is a fact, not a benefit, so it sits outside the numbered set. */
.join-term {
  margin: clamp(20px, 3vw, 30px) 0 0;
  font-size: 0.98rem;
  color: var(--text-muted-on-light);
  max-width: 62ch;
}

.join-term__label {
  display: block;
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 900;
  color: var(--color-accent-text);
  margin-bottom: 6px;
}

/* The lead-in above the form. */
.join-ready {
  max-width: 62ch;
  padding-top: clamp(30px, 4vw, 48px);
}

.join-ready__title {
  font-size: clamp(1.5rem, 3.4vw, 2.1rem);
  text-transform: uppercase;
  margin-bottom: 14px;
}

.join-ready__body {
  margin-bottom: 1em;
}

.join-ready__body:last-child { margin-bottom: 0; }

/* The hero's jump link to the form. */
.page-hero__actions {
  margin: 22px 0 0;
}

/* The club signs off its own copy this way on the About and venue pages, so the
   privacy page does too rather than ending on a flat full stop. */
.prose__signoff {
  font-weight: 900;
  letter-spacing: 0.02em;
  color: var(--color-accent-text);
  margin-top: 2em;
}

/* The hero carries two paragraphs now, so the first needs air under it. */
.bl-hero__sub + .bl-hero__sub { margin-top: 14px; }

/* The client set their sign-off line in italics. It gets weight and the full
   bone instead: an italic would fight the display face above it, and the point
   of the line is emphasis rather than an aside. */
.bl-hero__sub--closing {
  color: var(--bone);
  font-weight: 700;
}

/* The reservation button, first item in the venue sidebar. */
.venue-reserve {
  margin: 0 0 26px;
}

.venue-reserve .btn {
  width: 100%;
  text-align: center;
}

/* The reservation button under the kickoff details on the home page.
   The whole next-watch-party panel is a stretched link at z-index 1, so this
   has to be lifted above it or the panel swallows the click and sends people to
   the event page instead of the contact form. Same fix as .sched__venue.

   The margin is the entire gap now, because the button shares a grid cell with
   the details rather than sitting in the row below them. */
.bl-when__cta {
  position: relative;
  z-index: 2;
  margin: 40px 0 0;
}
