/* ==========================================================================
   BRAND NEW CHURCH — brandnewchurch.com
   Clean, cinematic, Apple-style design system. SF Pro via system font stack.
   ========================================================================== */

:root {
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text",
          "Helvetica Neue", "Segoe UI", Roboto, Inter, Arial, sans-serif;

  --black: #0b0b0f;
  --near-black: #101014;
  --white: #ffffff;
  --off: #f5f5f7;            /* light section background */
  --ink: #1d1d1f;            /* primary text on light */
  --ink-2: #6e6e73;          /* secondary text on light */
  --paper-ink-2: rgba(255, 255, 255, 0.68); /* secondary text on dark */
  --hairline: rgba(0, 0, 0, 0.08);
  --hairline-dark: rgba(255, 255, 255, 0.14);
  --blue: #0066cc;
  --blue-bright: #2997ff;

  --radius-card: 24px;
  --radius-panel: 32px;

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --pad-x: clamp(20px, 5vw, 48px);
  --section-w: 1280px;
  --narrow-w: 820px;
}

/* ---------- Reset ---------- */

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

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

/* Lenis smooth scroll (desktop only — see js/main.js).
   When active, Lenis adds the `lenis` / `lenis-smooth` classes to <html> and
   takes over scrolling. We deliberately OMIT Lenis's default
   `.lenis.lenis-smooth iframe { pointer-events: none }` rule so the Subsplash
   video and Pushpay embeds stay clickable. */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.55;
  color: var(--ink);
  background: var(--white);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

a { color: inherit; text-decoration: none; }

h1, h2, h3, h4, p { margin: 0; }

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

::selection { background: #0b0b0f; color: #fff; }

/* ---------- Type ---------- */

.display {
  font-size: clamp(44px, 7.2vw, 104px);
  line-height: 1.02;
  font-weight: 700;
  letter-spacing: -0.035em;
}

.title-xl {
  font-size: clamp(36px, 5vw, 72px);
  line-height: 1.05;
  font-weight: 700;
  letter-spacing: -0.03em;
}

.title-lg {
  font-size: clamp(28px, 3.6vw, 48px);
  line-height: 1.08;
  font-weight: 700;
  letter-spacing: -0.025em;
}

.title-md {
  font-size: clamp(22px, 2.4vw, 30px);
  line-height: 1.15;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.eyebrow {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.lede {
  font-size: clamp(18px, 1.6vw, 22px);
  line-height: 1.5;
  color: var(--ink-2);
  font-weight: 400;
  letter-spacing: -0.01em;
}

.on-dark { color: var(--white); }
.on-dark .eyebrow { color: var(--paper-ink-2); }
.on-dark .lede { color: var(--paper-ink-2); }

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 14px 28px;
  border-radius: 999px;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1;
  white-space: nowrap;
  transition: transform 0.45s var(--ease-out), background 0.3s ease,
              color 0.3s ease, border-color 0.3s ease, opacity 0.3s ease;
}

.btn:hover { transform: scale(1.035); }
.btn:active { transform: scale(0.98); }

.btn-solid { background: var(--ink); color: var(--white); }
.btn-solid:hover { background: var(--black); }

.btn-white { background: var(--white); color: var(--black); }
.btn-white:hover { background: #f0f0f2; }

.btn-ghost {
  color: var(--white);
  background: rgba(255, 255, 255, 0.18);
  border: 1px solid rgba(255, 255, 255, 0.32);
}
.btn-ghost:hover { background: rgba(255, 255, 255, 0.24); }

.btn-ghost-dark {
  color: var(--ink);
  background: rgba(0, 0, 0, 0.05);
  border: 1px solid rgba(0, 0, 0, 0.16);
}
.btn-ghost-dark:hover { background: rgba(0, 0, 0, 0.1); }

.btn-sm { padding: 10px 20px; font-size: 15px; }

.text-link {
  font-weight: 600;
  color: var(--blue);
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 6px 0;                 /* taller tap target without moving the text */
  margin: -6px 0;
}
.text-link .chev { transition: transform 0.3s var(--ease-out); }
.text-link:hover .chev { transform: translateX(4px); }
.on-dark .text-link { color: var(--blue-bright); }

/* ---------- Layout helpers ---------- */

.wrap { max-width: var(--section-w); margin: 0 auto; padding-left: var(--pad-x); padding-right: var(--pad-x); }
.wrap-narrow { max-width: var(--narrow-w); margin: 0 auto; padding-left: var(--pad-x); padding-right: var(--pad-x); }

.section { padding: clamp(84px, 11vw, 150px) 0; }
.section-head { max-width: 780px; margin-bottom: clamp(40px, 5vw, 72px); }
.section-head .eyebrow { margin-bottom: 16px; }
.section-head .lede { margin-top: 18px; }
.section-head.center { margin-left: auto; margin-right: auto; text-align: center; }

.bg-black { background: var(--black); }
.bg-off { background: var(--off); }

/* ==========================================================================
   NAV
   ========================================================================== */

.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  transition: background 0.4s ease, box-shadow 0.4s ease;
}

.nav-inner {
  max-width: 1440px;
  margin: 0 auto;
  padding: 0 var(--pad-x);
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}

.nav-logo {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 700;
  letter-spacing: 0.02em;
  font-size: 15px;
}

.nav-logo img { height: 34px; width: auto; transition: filter 0.4s ease; }

.nav-links {
  display: flex;
  align-items: center;
  gap: clamp(18px, 2.2vw, 30px);
  font-size: 14.5px;
  font-weight: 500;
}

.nav-links a:not(.btn) {
  color: rgba(255, 255, 255, 0.92);
  transition: color 0.3s ease, opacity 0.3s ease;
  opacity: 0.9;
}
.nav-links a:not(.btn):hover { opacity: 1; }
.nav-links a.active { opacity: 1; font-weight: 700; }

.nav .btn-give {
  padding: 8px 18px;
  font-size: 14px;
  background: var(--white);
  color: var(--black);
}

/* Scrolled state: solid translucent bar.
   NOTE: deliberately NO backdrop-filter here. A live blur on a fixed bar forces
   Safari to repaint the whole bar every scroll frame (Safari Timeline showed
   ~80% of scroll time in Paint from this alone). A near-opaque solid background
   looks the same and costs nothing per frame. */
.nav.solid {
  background: rgba(251, 251, 253, 0.92);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08);
}
.nav.solid .nav-links a:not(.btn) { color: var(--ink); }
.nav.solid .nav-logo img { filter: none; }
.nav.solid .btn-give { background: var(--ink); color: var(--white); }
.nav.solid .nav-burger span { background: var(--ink); }

/* White logo variant over imagery (solid frosted bar always wins) */
.nav.over-image:not(.solid) .nav-logo img { filter: invert(1) brightness(1.6); }

.nav-burger {
  display: none;
  flex-direction: column;
  gap: 5px;
  /* 44x44 touch target; the negative margin cancels the padding so the icon
     sits exactly where it did and only the tappable box grows. */
  padding: 14px 11px;
  margin: -14px -11px;
  z-index: 130;
}
.nav-burger span {
  width: 22px; height: 2px;
  background: #fff;
  border-radius: 2px;
  transition: transform 0.35s var(--ease-out), opacity 0.3s, background 0.3s;
}

/* Mobile menu overlay */
.menu-overlay {
  position: fixed;
  inset: 0;
  z-index: 120;
  background: rgba(10, 10, 14, 0.92);
  -webkit-backdrop-filter: blur(24px);
  backdrop-filter: blur(24px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0 8vw;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.4s ease, visibility 0.4s;
}

.menu-overlay a {
  color: #fff;
  font-size: clamp(30px, 7vw, 44px);
  font-weight: 700;
  letter-spacing: -0.02em;
  padding: 10px 0;
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.5s var(--ease-out), transform 0.5s var(--ease-out);
}

.menu-overlay .menu-minor { font-size: 17px; font-weight: 500; color: rgba(255,255,255,0.7); padding: 10px 0; }

body.menu-open { overflow: hidden; }
body.menu-open .menu-overlay { opacity: 1; visibility: visible; }
body.menu-open .menu-overlay a { opacity: 1; transform: none; }
body.menu-open .nav-burger span { background: #fff; }
body.menu-open .nav-burger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
body.menu-open .nav-burger span:nth-child(2) { opacity: 0; }
body.menu-open .nav-burger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

@media (max-width: 1020px) {
  .nav-links { display: none; }
  .nav-burger { display: flex; }
}

/* ==========================================================================
   HERO — cinematic campus header, sky as negative space
   ========================================================================== */

.hero {
  position: relative;
  height: 172vh; /* scroll runway for the cinematic move */
  /* Extended sky, sampled from the photo, so text floats in pure sky */
  background: linear-gradient(
    180deg,
    #143d80 0%,
    #1f5cb4 30%,
    #4a86d8 62%,
    #7fade6 82%,
    #a3c8ee 100%
  );
}

.hero-sticky {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
}

.hero-bg {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    #143d80 0%,
    #1f5cb4 30%,
    #4a86d8 62%,
    #7fade6 82%,
    #a3c8ee 100%
  );
}

.hero-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Keep the full sky; crop parking lot from the bottom on wide screens */
  object-position: center top;
  transform-origin: center 30%;
  will-change: transform;
}

/* Cinematic grade: deepen the upper sky so white type sits in negative space */
.hero-grade {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(6, 12, 24, 0.62) 0%, rgba(8, 16, 30, 0.38) 26%, rgba(10, 18, 32, 0.12) 48%, rgba(0, 0, 0, 0) 66%),
    linear-gradient(0deg, rgba(7, 9, 14, 0.42) 0%, rgba(0, 0, 0, 0) 22%);
  pointer-events: none;
}

/* Soft vignette for focus */
.hero-vignette {
  position: absolute;
  inset: 0;
  background: radial-gradient(120% 90% at 50% 42%, rgba(0,0,0,0) 58%, rgba(4, 8, 16, 0.3) 100%);
  pointer-events: none;
}

.hero-copy {
  position: absolute;
  left: 0; right: 0;
  top: clamp(96px, 15svh, 170px);
  text-align: center;
  color: #fff;
  padding: 0 var(--pad-x);
  will-change: transform, opacity;
}

.hero-copy .eyebrow {
  color: rgba(255, 255, 255, 0.82);
  margin-bottom: 20px;
}

.hero-copy h1 {
  text-shadow: 0 2px 24px rgba(4, 10, 22, 0.35);
}

.hero-ctas {
  display: flex;
  gap: 14px;
  justify-content: center;
  flex-wrap: wrap;
  margin-top: 36px;
}

.hero-times {
  position: absolute;
  left: 0; right: 0;
  bottom: 58px;
  display: flex;
  justify-content: center;
  padding: 0 var(--pad-x);
}

.hero-times span {
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: rgba(255, 255, 255, 0.95);
  /* Solid tint instead of a live blur — this pill stays pinned through the
     whole hero scroll, so a backdrop blur here repaints every frame too. */
  background: rgba(10, 16, 28, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.22);
  padding: 10px 22px;
  border-radius: 999px;
  text-align: center;
}

.scroll-cue {
  position: absolute;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%);
  width: 22px; height: 34px;
  border: 1.5px solid rgba(255, 255, 255, 0.55);
  border-radius: 12px;
}
.scroll-cue::after {
  content: "";
  position: absolute;
  top: 6px; left: 50%;
  width: 3px; height: 7px;
  margin-left: -1.5px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.85);
  animation: cue 2.2s var(--ease-out) infinite;
}

@keyframes cue {
  0% { transform: translateY(0); opacity: 1; }
  60% { transform: translateY(10px); opacity: 0; }
  100% { transform: translateY(0); opacity: 0; }
}

/* Content sheet that slides over the hero */
.sheet {
  position: relative;
  z-index: 5;
  background: var(--white);
  border-radius: var(--radius-panel) var(--radius-panel) 0 0;
  margin-top: -14vh;
  box-shadow: 0 -30px 80px rgba(6, 10, 20, 0.35);
}

/* ==========================================================================
   HOME SECTIONS
   ========================================================================== */

/* --- Welcome / Sunday --- */

.times-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 14px;
  margin-top: clamp(36px, 4vw, 56px);
}

.time-card {
  border: 1px solid var(--hairline);
  border-radius: 20px;
  padding: 26px 26px 22px;
  background: var(--white);
  transition: transform 0.5s var(--ease-out), box-shadow 0.5s var(--ease-out);
}

.time-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.09);
}

.time-card .tc-day {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin-bottom: 10px;
}

.time-card .tc-name { font-size: 20px; font-weight: 700; letter-spacing: -0.02em; }
.time-card .tc-time { font-size: 17px; color: var(--ink-2); margin-top: 4px; font-weight: 500; }

/* --- Cinematic feature panels (series / events hot-swap) --- */

.panel {
  position: relative;
  border-radius: var(--radius-panel);
  overflow: hidden;
  min-height: clamp(520px, 72vh, 720px);
  display: flex;
  align-items: flex-end;
  isolation: isolate;
}

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

.panel-bg img {
  width: 100%; height: 100%;
  object-fit: cover;
  transform: scale(1.06);
  transition: transform 1.4s var(--ease-out);
}

.panel:hover .panel-bg img { transform: scale(1.01); }

.panel-scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(200deg, rgba(5, 8, 14, 0.05) 30%, rgba(5, 8, 14, 0.68) 100%),
              linear-gradient(0deg, rgba(5, 8, 14, 0.55) 0%, rgba(0, 0, 0, 0) 45%);
}

.panel-content {
  position: relative;
  width: 100%;
  padding: clamp(32px, 5vw, 64px);
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 28px;
  color: #fff;
}

.panel-copy { max-width: 560px; }

.panel-badge {
  display: inline-block;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  background: rgba(35, 40, 50, 0.42);
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 999px;
  padding: 8px 16px;
  margin-bottom: 18px;
}

.panel-badge-img {
  display: inline-block;
  height: clamp(28px, 3vw, 38px);
  width: auto;
  margin-bottom: 18px;
  border-radius: 8px;
  filter: drop-shadow(0 6px 18px rgba(0, 0, 0, 0.35));
}

.panel-copy h3 {
  font-size: clamp(32px, 4vw, 54px);
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.05;
}

.panel-copy p {
  margin-top: 14px;
  font-size: clamp(17px, 1.5vw, 20px);
  color: rgba(255, 255, 255, 0.85);
  max-width: 48ch;
}

.panel-art {
  align-self: center;
  margin: 0 auto;
}

.panel-art img {
  max-height: clamp(180px, 30vw, 320px);
  width: auto;
  max-width: min(86vw, 560px);
  object-fit: contain;
  filter: drop-shadow(0 18px 50px rgba(0, 0, 0, 0.45));
}

.panel-ctas { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 26px; }

/* Series panel gets a taller, poster-like layout */
.panel.series .panel-content {
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding-top: clamp(56px, 8vw, 96px);
}
.panel.series { align-items: center; }
.panel.series .panel-copy { max-width: 720px; }
.panel.series .panel-copy p { margin-left: auto; margin-right: auto; }
.panel.series .panel-ctas { justify-content: center; }

/* --- Series + side promo, side by side --- */

.series-split { display: grid; gap: 20px; }

/* The series frame carries a logo and two buttons, so it needs the wider
   half; the promo is a portrait graphic and reads fine narrower. */
@media (min-width: 1000px) {
  .series-split { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); }
}

/* One frame only (promo cleared in content.js) — go back to full width. */
.series-split--solo { grid-template-columns: minmax(0, 1fr) !important; }
.series-split--solo #promo-root { display: none; }

/* Solo series (no side promo) has the full panel width to work with. Let the
   poster fill it the way every other element in the panel does - bounded by
   panel-content's own padding, not an arbitrary smaller cap - so it actually
   reaches toward the frame's edges instead of floating with a wide gutter. */
@media (min-width: 700px) {
  .series-split--solo .panel.series .panel-art img {
    max-height: clamp(300px, 44vw, 620px);
    max-width: 100%;
  }
}

/* --- Series artwork that IS the frame (content.js: artworkFillsFrame) ---
   A finished graphic fills the rounded frame edge to edge. It sits in flow
   rather than as an absolute background layer, so the panel inherits the
   image's own height and nothing is ever cropped - the tall min-height meant
   for cinematic photo panels would otherwise force a crop. */
.panel.panel--artwork {
  min-height: 0;
  display: block;
}

.panel-artwork {
  display: block;
  width: 100%;
  height: auto;
}

.series-root--artwork { flex-direction: column; }
/* Don't let the shared "panel fills its cell" rule stretch the frame taller
   than the artwork once the column direction makes height the main axis. */
.series-root--artwork > .panel { flex: 0 0 auto; }

/* Buttons live below the frame here, centred, on the section background. */
.series-ctas {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  margin-top: 28px;
}

/* Let each panel fill its grid cell so both frames end up the same height. */
.series-split > div { display: flex; }
.series-split > div > .panel { flex: 1; width: 100%; }

/* Narrower series frame: pull the poster art in so it doesn't crowd the edges.
   Scoped to :not(--solo) - series-split--solo is an ADDED class (the base
   .series-split stays), so without this exclusion a solo full-width series
   with no promo would still get squeezed down to the narrow-column size. */
@media (min-width: 1000px) {
  .series-split:not(.series-split--solo) .panel.series .panel-art img { max-height: clamp(150px, 17vw, 260px); }
}

/* --- Side promo frame --- */

.panel.promo {
  align-items: flex-end;
  text-decoration: none;
  cursor: pointer;
}

/* Seats the button against the artwork. The gradient matches the artwork's
   own tone, so on the light notebook graphic it reads as the paper fading
   up rather than as an overlay. */
.promo-scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(to top, rgba(255, 255, 255, 0.96) 4%, rgba(255, 255, 255, 0) 40%);
}
.panel.promo-dark .promo-scrim {
  background: linear-gradient(to top, rgba(5, 8, 14, 0.78) 4%, rgba(5, 8, 14, 0) 42%);
}

.promo-content {
  position: relative;
  width: 100%;
  padding: clamp(26px, 3vw, 44px);
  display: flex;
  justify-content: center;
}

/* The "button" is a span (the whole frame is the anchor), so it needs the
   hover state driven from the panel. */
.panel.promo:hover .btn { transform: scale(1.035); }
.panel.promo:active .btn { transform: scale(0.98); }

/* --- Event cards --- */

/* auto-fill (not auto-fit) so a lone card keeps a normal width
   instead of stretching across the whole row */
.event-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 22px;
  margin-top: 26px;
}

.event-card {
  background: var(--white);
  border-radius: var(--radius-card);
  overflow: hidden;
  border: 1px solid var(--hairline);
  display: flex;
  flex-direction: column;
  transition: transform 0.55s var(--ease-out), box-shadow 0.55s var(--ease-out);
}

.event-card:hover {
  transform: translateY(-6px);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.12);
}

.event-media {
  aspect-ratio: 16 / 10;
  overflow: hidden;
  position: relative;
  background: var(--off);
}

.event-media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 1s var(--ease-out);
}

.event-card:hover .event-media img { transform: scale(1.05); }

/* An event with nothing to sign up for renders as a div, not a link, so it
   should not lift or zoom under the cursor either. */
.event-card.is-static { cursor: default; }
.event-card.is-static:hover { transform: none; box-shadow: none; }
.event-card.is-static:hover .event-media img { transform: none; }

.event-body { padding: 24px 26px 26px; display: flex; flex-direction: column; gap: 8px; flex: 1; }

.event-date {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.event-body h4 { font-size: 22px; font-weight: 700; letter-spacing: -0.02em; }
.event-body p { color: var(--ink-2); font-size: 15.5px; flex: 1; }
.event-body .text-link { margin-top: 10px; font-size: 15.5px; }

/* --- Gallery marquee (imagery speaks) --- */

.marquee-section { padding: clamp(70px, 8vw, 110px) 0; overflow: hidden; }

.marquee { display: flex; flex-direction: column; gap: 16px; }

.marquee-row { display: flex; gap: 16px; width: max-content; }

.marquee-row .track {
  display: flex;
  gap: 16px;
  animation: marquee 52s linear infinite;
  will-change: transform;
  backface-visibility: hidden;
}

.marquee-row.reverse .track { animation-direction: reverse; animation-duration: 62s; }

.marquee-row img {
  height: clamp(180px, 24vw, 300px);
  width: auto;
  border-radius: 18px;
  object-fit: cover;
}

.marquee:hover .track { animation-play-state: paused; }

@keyframes marquee {
  from { transform: translate3d(0, 0, 0); }
  to { transform: translate3d(calc(-50% - 8px), 0, 0); }
}

/* --- Next steps tiles --- */

.steps-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 22px;
}

.step-tile {
  position: relative;
  border-radius: var(--radius-card);
  overflow: hidden;
  aspect-ratio: 4 / 5;
  display: flex;
  align-items: flex-end;
  color: #fff;
  isolation: isolate;
}

.step-tile img.bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 1.1s var(--ease-out);
}

.step-tile::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(0deg, rgba(4, 6, 12, 0.78) 0%, rgba(4, 6, 12, 0.3) 52%, rgba(4, 6, 12, 0.06) 100%);
  transition: background 0.5s ease;
}

.step-tile:hover img.bg { transform: scale(1.06); }

.step-body { padding: 28px; }

.step-body .eyebrow { color: rgba(255, 255, 255, 0.75); margin-bottom: 8px; }

/* Midweek tiles: make the night + time unmistakable */
.step-body .midweek-tag {
  display: inline-block;
  color: #fff;
  background: rgba(20, 24, 33, 0.5);
  border: 1px solid rgba(255, 255, 255, 0.38);
  border-radius: 999px;
  padding: 6px 13px;
  margin-bottom: 12px;
  font-size: 11.5px;
  letter-spacing: 0.08em;
}

.step-body h4 { font-size: clamp(24px, 2.2vw, 30px); font-weight: 700; letter-spacing: -0.02em; }
.step-body p { margin-top: 8px; color: rgba(255, 255, 255, 0.82); font-size: 15.5px; max-width: 34ch; }
.step-body .text-link { margin-top: 14px; color: #fff; }

/* --- Locations --- */

.loc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 22px;
}

.loc-card {
  border-radius: var(--radius-card);
  overflow: hidden;
  background: #16161c;
  border: 1px solid var(--hairline-dark);
  transition: transform 0.55s var(--ease-out), box-shadow 0.55s var(--ease-out);
}

.loc-card:hover { transform: translateY(-6px); box-shadow: 0 26px 60px rgba(0, 0, 0, 0.45); }

.loc-media { aspect-ratio: 16 / 10; overflow: hidden; }
.loc-media img { width: 100%; height: 100%; object-fit: cover; transition: transform 1s var(--ease-out); }
.loc-card:hover .loc-media img { transform: scale(1.05); }

/* Branded fallback for campuses we don't have a photo of yet */
.loc-media.brand {
  display: grid;
  place-items: center;
  background:
    radial-gradient(120% 120% at 30% 20%, rgba(41, 151, 255, 0.28) 0%, rgba(0, 0, 0, 0) 60%),
    linear-gradient(140deg, #16233c 0%, #0b0b0f 100%);
}

.loc-media.brand img {
  width: 46%;
  height: auto;
  object-fit: contain;
  filter: invert(1) brightness(1.9);
  opacity: 0.92;
}

.loc-card:hover .loc-media.brand img { transform: scale(1.04); }

/* Full-colour partner logos (e.g. CBS Channel 5 on BNCTV). The base .brand
   treatment inverts the image for our own black wordmark; that would turn
   this logo's yellow 5 blue, so skip the filter and keep true colours. The
   dark brand gradient behind it is what lets the white CBS eye read. */
.loc-media.brand--color img { filter: none; opacity: 1; width: 40%; }

.loc-body { padding: 24px 26px 26px; color: #fff; }
.loc-body h4 { font-size: 21px; font-weight: 700; letter-spacing: -0.02em; }
.loc-time { margin-top: 6px; font-weight: 600; font-size: 15.5px; color: var(--blue-bright); }
.loc-addr { margin-top: 6px; color: rgba(255, 255, 255, 0.62); font-size: 15px; }
.loc-body .text-link { margin-top: 12px; font-size: 15px; }

/* --- App / media band --- */

.app-band { overflow: hidden; }

.app-flex {
  display: flex;
  align-items: center;
  gap: clamp(36px, 6vw, 90px);
  flex-wrap: wrap;
}

.app-copy { flex: 1 1 380px; }

.app-shot { flex: 1 1 340px; display: flex; justify-content: center; }

.app-shot img {
  width: min(420px, 88%);
  border-radius: 28px;
  box-shadow: 0 30px 70px rgba(0, 0, 0, 0.18);
  border: 1px solid rgba(0, 0, 0, 0.06);
}

.store-btns { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 30px; }

/* ==========================================================================
   SUBPAGE HEADERS
   ========================================================================== */

.page-hero {
  position: relative;
  min-height: clamp(420px, 62vh, 620px);
  display: flex;
  align-items: flex-end;
  color: #fff;
  isolation: isolate;
  overflow: hidden;
  background: var(--black);
}

.page-hero .ph-bg {
  position: absolute;
  inset: 0;
  z-index: -2;
}

.page-hero .ph-bg img {
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0.72;
}

.page-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(0deg, rgba(5, 7, 12, 0.88) 0%, rgba(5, 7, 12, 0.25) 55%, rgba(5, 7, 12, 0.6) 100%);
}

.page-hero .wrap { padding-bottom: clamp(48px, 7vw, 90px); padding-top: 140px; width: 100%; }

.page-hero .eyebrow { color: rgba(255, 255, 255, 0.78); margin-bottom: 14px; }
.page-hero .lede { color: rgba(255, 255, 255, 0.85); max-width: 62ch; margin-top: 18px; }

/* ---------- About page ---------- */

.verse-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 22px;
}

.verse-card {
  background: var(--off);
  border-radius: var(--radius-card);
  padding: clamp(28px, 3.4vw, 44px);
}

.verse-card .ref { font-weight: 700; letter-spacing: -0.01em; font-size: 19px; }
.verse-card p { margin-top: 14px; color: var(--ink-2); font-size: 17px; line-height: 1.65; }

.beliefs-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 22px;
}

.belief-card {
  border: 1px solid var(--hairline);
  border-radius: var(--radius-card);
  padding: clamp(26px, 3vw, 38px);
  background: var(--white);
}

.belief-card h4 { font-size: 21px; font-weight: 700; letter-spacing: -0.02em; }
.belief-card p { margin-top: 12px; color: var(--ink-2); font-size: 15.5px; line-height: 1.65; }
.belief-card .refs { margin-top: 14px; font-size: 13px; color: #9b9ba0; line-height: 1.6; }

.expect-list { display: grid; gap: 0; margin-top: 10px; }

.expect-item {
  display: flex;
  gap: 18px;
  align-items: baseline;
  padding: 22px 4px;
  border-bottom: 1px solid var(--hairline);
  font-size: clamp(18px, 1.8vw, 22px);
  font-weight: 600;
  letter-spacing: -0.015em;
}

.expect-item .num {
  font-size: 13px;
  font-weight: 700;
  color: var(--ink-2);
  letter-spacing: 0.08em;
}

.staff-feature {
  display: flex;
  gap: clamp(30px, 5vw, 70px);
  align-items: center;
  flex-wrap: wrap;
}

.staff-feature .photo { flex: 1 1 420px; }
.staff-feature .photo img { border-radius: var(--radius-card); }
.staff-feature .copy { flex: 1 1 340px; }

.photo-grid-3 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 16px;
}

.photo-grid-3 img {
  border-radius: 18px;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  width: 100%;
}

/* ---------- Midweek ---------- */

.ministry-row {
  display: flex;
  align-items: center;
  gap: clamp(30px, 5vw, 80px);
  flex-wrap: wrap;
  padding: clamp(40px, 5vw, 70px) 0;
  border-bottom: 1px solid var(--hairline);
}

.ministry-row:last-child { border-bottom: 0; }

.ministry-row .m-copy { flex: 1 1 360px; }
.ministry-row .m-media { flex: 1 1 420px; }

.ministry-row .m-logo { height: clamp(64px, 7vw, 96px); width: auto; margin-bottom: 22px; }

.ministry-row .m-grade { font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.12em; color: var(--ink-2); margin-bottom: 10px; }

.m-photos {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

.m-photos img { border-radius: 16px; aspect-ratio: 1; object-fit: cover; width: 100%; }
.m-photos img:first-child { grid-column: 1 / -1; aspect-ratio: 16 / 9; }

/* Full-width third child of a ministry row: wraps below the copy/media pair
   so the schedule spans the row rather than squeezing into one column. */
.ministry-row .m-extra { flex: 1 1 100%; margin-top: clamp(26px, 3vw, 44px); }

.m-sched-lede {
  font-size: 16px;
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 62ch;
  margin: 8px 0 20px;
}

/* --- Brand New Kids Fall schedule ---
   A list rather than a card per date. In a card, a night with nothing special
   on it reads as an empty box with something missing; a single line that is
   just a date reads as complete. Grouped by month so 21 dates scan as five
   short runs instead of one long column. */

.sched-list { columns: 3; column-gap: clamp(30px, 4vw, 70px); }
@media (max-width: 900px) { .sched-list { columns: 2; } }
@media (max-width: 560px) { .sched-list { columns: 1; } }

/* Keep a month from being split across two columns mid-list. */
.sched-month {
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
  margin-bottom: 26px;
}

.sched-month-name {
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
  padding-bottom: 9px;
  border-bottom: 1px solid var(--hairline);
}

.sched-month ul { list-style: none; margin: 0; padding: 0; }

.sched-month li {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 9px 2px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
}
.sched-month li:last-child { border-bottom: 0; }

/* tabular-nums keeps the day numbers in a straight column */
.sl-day {
  min-width: 24px;
  font-size: 16px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.sl-label { font-size: 15px; line-height: 1.4; color: var(--ink-2); }

/* Nights with something on: heavier and dotted, so they carry emphasis
   without needing a box drawn around them. */
.sched-month li.is-event .sl-label { color: var(--ink); font-weight: 600; }
.sched-month li.is-event .sl-label::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--ink);
  margin-right: 9px;
  vertical-align: 0.14em;
}

/* Weeks we are off: recede rather than shout. */
.sched-month li.is-break .sl-day { color: var(--ink-2); font-weight: 500; }
.sched-month li.is-break .sl-label { font-style: italic; }

/* A Wednesday that has already been and gone. The class is applied at load
   by js/main.js from each row's data-date, so the list ages by itself. */
.sched-month li.is-past { opacity: 0.4; }
.sched-month li.is-past .sl-day,
.sched-month li.is-past .sl-label { text-decoration: line-through; }
/* Drop the emphasis dot once a night is past — it has nothing left to flag,
   and it keeps the strike a single clean line. */
.sched-month li.is-past .sl-label::before { display: none; }

/* ---------- Video embeds ---------- */

.video-shell {
  position: relative;
  border-radius: var(--radius-card);
  overflow: hidden;
  background: #000;
  aspect-ratio: 16 / 9;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.18);
}

.video-shell iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

/* "App" embed (message library, etc.) — fills the content width with a
   viewport-scaled height so it stays wide without becoming a giant square */
.embed-frame {
  width: 100%;
}

.sap-embed-player {
  position: relative;
  width: 100%;
  height: clamp(620px, 82vh, 960px);
  border-radius: var(--radius-card);
  overflow: hidden;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.18);
  color-scheme: light;
}

/* On phones a taller square-ish box reads better than a short wide one */
@media (max-width: 640px) {
  .sap-embed-player { height: min(128vw, 560px); }
}

.sap-embed-player > iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: 0;
  border-radius: var(--radius-card);
  color-scheme: light;
}

/* ---------- Contact ---------- */

.contact-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 22px;
}

.contact-card {
  background: var(--off);
  border-radius: var(--radius-card);
  padding: clamp(28px, 3.4vw, 44px);
}

.contact-card h4 { font-size: 20px; font-weight: 700; letter-spacing: -0.02em; }
.contact-card p { margin-top: 10px; color: var(--ink-2); }
.contact-card .big { font-size: clamp(18px, 1.6vw, 21px); font-weight: 700; letter-spacing: -0.02em; color: var(--ink); margin-top: 12px; overflow-wrap: anywhere; }
.contact-card .big a { text-decoration: none; }

.form {
  display: grid;
  gap: 14px;
  margin-top: 34px;
}

.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }

.form input, .form textarea {
  font: inherit;
  border: 1px solid rgba(0, 0, 0, 0.14);
  border-radius: 14px;
  padding: 15px 18px;
  background: var(--white);
  color: var(--ink);
  width: 100%;
  transition: border-color 0.25s ease, box-shadow 0.25s ease;
}

.form input:focus, .form textarea:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 4px rgba(0, 102, 204, 0.14);
}

.form textarea { min-height: 150px; resize: vertical; }

.form-success {
  border: 1px solid var(--hairline);
  border-radius: var(--radius-card);
  background: var(--off);
  padding: clamp(32px, 4vw, 52px);
  text-align: center;
  animation: successIn 0.7s var(--ease-out) both;
}

.form-success h3 {
  font-size: clamp(24px, 2.6vw, 32px);
  font-weight: 700;
  letter-spacing: -0.02em;
}

.form-success p {
  margin-top: 12px;
  color: var(--ink-2);
  max-width: 46ch;
  margin-left: auto;
  margin-right: auto;
}

.form-success::before {
  content: "";
  display: block;
  width: 56px;
  height: 56px;
  margin: 0 auto 20px;
  border-radius: 50%;
  background: var(--ink)
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7'/%3E%3C/svg%3E")
    center / 26px no-repeat;
}

@keyframes successIn {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}

@media (max-width: 640px) { .form-row { grid-template-columns: 1fr; } }

/* ==========================================================================
   GIVING — Pushpay embedded campus selector
   The Pushpay script toggles three classes: `hidden` on non-selected tiles,
   `selected` on the chosen tile, and `visible` on #pushpay-wrapper.
   Everything here is scoped to .pushpay-widget so those generic class names
   can't leak into the rest of the site.
   ========================================================================== */

.giving-embed {
  max-width: 720px;
  margin: 0 auto;
}

/* Test-mode notice: shown only while data-env="qa", auto-hides in production */
.giving-testmode {
  display: none;
  background: #fff8e1;
  border: 1px solid #f0d68a;
  color: #6b5312;
  border-radius: 14px;
  padding: 14px 18px;
  font-size: 14.5px;
  line-height: 1.5;
  margin-bottom: 28px;
}

.pushpay-widget[data-env="qa"] .giving-testmode { display: block; }

.pushpay-campus-select-label {
  font-size: clamp(20px, 2vw, 26px);
  font-weight: 700;
  letter-spacing: -0.02em;
  margin-bottom: 1.5rem;
  text-align: center;
}

/* Row containing the campus list + the Change Campus link. Full width while
   picking a campus (grid of cards); once one is selected, the list shrinks
   to hug its single remaining tile so it can sit side by side with the
   Change Campus button instead of stacking. */
.pushpay-selection-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 14px;
}

.pushpay-listing-select-menu {
  list-style: none;
  margin: 0;
  padding: 0;
  width: 100%;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 14px;
}

.pushpay-listing-select-menu:has(li.selected) {
  display: inline-flex;
  width: auto;
  align-items: center;
}

.pushpay-listing-select-menu li {
  transition: opacity 0.4s var(--ease-out), transform 0.4s var(--ease-out);
}

.pushpay-listing-select-menu li a {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  min-height: 92px;
  padding: 20px 18px;
  border: 1px solid rgba(0, 0, 0, 0.14);
  border-radius: 18px;
  background: var(--white);
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--ink);
  transition: transform 0.4s var(--ease-out), border-color 0.3s ease,
              box-shadow 0.4s var(--ease-out), background 0.3s ease;
}

.pushpay-listing-select-menu li a:hover {
  transform: translateY(-3px);
  border-color: rgba(0, 0, 0, 0.3);
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.1);
}

/* Non-selected campuses collapse away once a choice is made */
.pushpay-listing-select-menu li.hidden {
  display: none;
}

/* Once chosen, the tile no longer needs to fill the grid row like a card —
   shrink it to a compact pill so it reads as a status badge. */
.pushpay-listing-select-menu li.selected a {
  min-height: 0;
  padding: 11px 26px;
  font-size: 15.5px;
  border-radius: 999px;
  background: var(--ink);
  border-color: var(--ink);
  color: var(--white);
  cursor: default;
  transform: none;
  box-shadow: none;
}

.pushpay-listing-select-menu li.selected a:hover {
  transform: none;
  box-shadow: none;
  border-color: var(--ink);
}

/* Widget container — revealed by the script once a campus is chosen */
#pushpay-wrapper {
  display: none;
  margin-top: 26px;
}

#pushpay-wrapper.visible {
  display: block;
  animation: successIn 0.6s var(--ease-out) both;
}

#pushpay-embedded-giving { min-height: 200px; }

/* Outlined pill button, sits inline next to the selected-campus tile (shown
   by the Pushpay script once a campus is chosen). !important overrides the
   inline style="display:block" the script applies when revealing it. */
#pushpay-change-campus-link {
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  width: max-content;
  max-width: 100%;
  margin: 0;
  text-align: center;
  font-size: 15.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
  background: transparent;
  cursor: pointer;
  padding: 11px 26px;
  border-radius: 999px;
  border: 1.5px solid rgba(0, 0, 0, 0.35);
  transition: transform 0.4s var(--ease-out), background 0.3s ease, border-color 0.3s ease;
}

#pushpay-change-campus-link:hover { background: rgba(0, 0, 0, 0.05); border-color: rgba(0, 0, 0, 0.55); transform: scale(1.035); }
#pushpay-change-campus-link:active { transform: scale(0.98); }

/* Fallback button Pushpay injects if the widget can't load */
.pushpay-fallback-give-now-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 14px 28px;
  border-radius: 999px;
  background: var(--ink);
  color: var(--white);
  font-size: 17px;
  font-weight: 600;
  cursor: pointer;
}

.giving-help {
  max-width: 720px;
  margin: 46px auto 0;
  text-align: center;
  color: var(--ink-2);
  font-size: 15.5px;
}

.giving-help a { color: var(--blue); font-weight: 600; }

/* Giving Help Links — 2x2 grid of help topics */
.help-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(30px, 4vw, 54px) clamp(30px, 5vw, 70px);
  max-width: 960px;
  margin: 0 auto;
}

.help-item { display: flex; gap: 20px; align-items: flex-start; }

.help-icon {
  flex: 0 0 auto;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  border: 1.5px solid rgba(0, 102, 204, 0.35);
  color: var(--blue);
}

.help-icon svg { width: 26px; height: 26px; }

.help-body h4 { font-size: 20px; font-weight: 700; letter-spacing: -0.02em; }
.help-body p { margin-top: 8px; color: var(--ink-2); font-size: 15.5px; line-height: 1.6; }
.help-body .btn { margin-top: 18px; }

.help-footnote {
  max-width: 760px;
  margin: clamp(44px, 5vw, 64px) auto 0;
  text-align: center;
  color: var(--ink-2);
  font-size: 15.5px;
  line-height: 1.6;
}
.help-footnote strong { color: var(--ink); }
.help-footnote a { color: var(--blue); font-weight: 600; }

@media (max-width: 720px) {
  .help-grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   CTA BAND + FOOTER
   ========================================================================== */

.cta-band {
  position: relative;
  overflow: hidden;
  text-align: center;
  color: #fff;
  isolation: isolate;
}

.cta-band .band-bg { position: absolute; inset: 0; z-index: -2; }
.cta-band .band-bg img { width: 100%; height: 100%; object-fit: cover; }
.cta-band::after {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  background: rgba(6, 8, 14, 0.62);
}

.footer {
  background: var(--black);
  color: #fff;
  padding: clamp(70px, 8vw, 110px) 0 46px;
}

.footer-top {
  display: flex;
  justify-content: space-between;
  gap: 48px;
  flex-wrap: wrap;
  padding-bottom: 56px;
  border-bottom: 1px solid var(--hairline-dark);
}

.footer-brand { max-width: 380px; }
.footer-brand img { height: 74px; filter: invert(1) brightness(1.7); margin-bottom: 20px; }
.footer-brand p { color: rgba(255, 255, 255, 0.6); font-size: 15.5px; }

.footer-cols { display: flex; gap: clamp(40px, 6vw, 96px); flex-wrap: wrap; }

.footer-col h5 {
  margin: 0 0 16px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
}

.footer-col a {
  display: block;
  padding: 8px 0;                 /* 39px rows: comfortable to tap, no visual bloat */
  color: rgba(255, 255, 255, 0.82);
  font-size: 15px;
  transition: color 0.25s ease;
}

.footer-col a:hover { color: #fff; }

.footer-bottom {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  padding-top: 34px;
  color: rgba(255, 255, 255, 0.45);
  font-size: 13.5px;
}

.socials { display: flex; gap: 10px; }

.socials a {
  width: 40px; height: 40px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.12);
  transition: background 0.3s ease, transform 0.3s var(--ease-out);
}

.socials a:hover { background: rgba(255, 255, 255, 0.18); transform: scale(1.08); }
.socials svg { width: 17px; height: 17px; fill: #fff; }

/* ==========================================================================
   REVEAL ANIMATIONS
   ========================================================================== */

/* No permanent will-change here: it would pin every finished reveal to its own
   GPU layer for the life of the page, which Safari handles badly (scroll jank).
   The one-shot opacity/transform transition composites fine without the hint. */
.reveal {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity 0.9s var(--ease-out), transform 0.9s var(--ease-out);
  transition-delay: var(--d, 0s);
}

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

/* Shadow clipping during the reveal
   ---------------------------------
   While a .reveal transitions opacity/transform it is promoted to its own
   compositing layer, and that layer is sized to the element's box. A shadow
   belonging to a DESCENDANT extends past that box, so it gets cut off at a
   hard rectangle for the duration of the transition and then snaps to its
   full size when the layer is discarded — read as a harsh box flashing around
   every shadowed image while scrolling.

   Giving the shadowed child its own layer makes its shadow rasterise
   independently of the parent's bounds, so it is never clipped. Only these
   few elements get a layer (unlike the old blanket will-change on every
   .reveal, which is what caused the Safari scroll jank), so the cost is nil.

   A shadow on the .reveal element ITSELF is fine and needs nothing — the
   browser includes an element's own box-shadow in its layer bounds. That is
   why .video-shell, .loc-card, .event-card and friends are absent here. */
.panel-art img,      /* series + event logos — drop-shadow(0 18px 50px) */
.panel-badge-img,    /* series badge graphic — drop-shadow(0 6px 18px)  */
.app-shot img,       /* BNC app screenshot   — box-shadow(0 30px 70px)  */
.sap-embed-player {  /* message library      — box-shadow(0 30px 80px)  */
  transform: translateZ(0);
}

/* ==========================================================================
   RESPONSIVE + MOTION
   ========================================================================== */

@media (max-width: 720px) {
  .hero { height: 150vh; }
  .hero-copy { top: clamp(84px, 12svh, 130px); }
  .hero-times span { font-size: 12.5px; padding: 9px 16px; }
  .panel-content { flex-direction: column; align-items: flex-start; }
  .step-tile { aspect-ratio: 4 / 4.4; }
  .footer-top { flex-direction: column; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  .marquee-row .track { animation: none; }
  .marquee-section { overflow-x: auto; }
  .scroll-cue::after { animation: none; }
  .hero-img, .hero-copy { transform: none !important; }
  *, *::before, *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}

/* ==========================================================================
   /tap — link-tree landing page (tap.html)
   Opened from a QR code or NFC tag, so it is built thumb-first: one column,
   large targets, and no nav or footer to scroll past.
   ========================================================================== */

.tap-page { background: var(--black); color: #fff; }

.tap {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(32px, 7vw, 64px) var(--pad-x);
  overflow: hidden;
}

.tap-bg { position: absolute; inset: 0; z-index: 0; }
.tap-bg img { width: 100%; height: 100%; object-fit: cover; }
.tap-bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(6, 8, 14, 0.82), rgba(6, 8, 14, 0.9));
}

.tap-inner {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 440px;
  text-align: center;
}

.tap-logo {
  height: 82px;
  width: auto;
  margin: 0 auto 20px;
  filter: invert(1) brightness(1.7);
}

.tap-tagline {
  font-size: 15px;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.62);
  margin-bottom: clamp(28px, 5vw, 40px);
}

.tap-links { display: flex; flex-direction: column; gap: 14px; }

.tap-btn {
  display: block;
  padding: 18px 22px;
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.2);
  text-align: center;
  transition: transform 0.35s var(--ease-out), background 0.3s ease, border-color 0.3s ease;
}
.tap-btn:hover { background: rgba(255, 255, 255, 0.18); border-color: rgba(255, 255, 255, 0.4); }
.tap-btn:active { transform: scale(0.985); }

/* First link is the primary action, so it gets the solid treatment. */
.tap-btn:first-child { background: #fff; border-color: #fff; color: var(--black); }
.tap-btn:first-child:hover { background: #f0f0f2; border-color: #f0f0f2; }

.tap-label {
  display: block;
  font-size: 17.5px;
  font-weight: 600;
  letter-spacing: -0.015em;
}
.tap-sub {
  display: block;
  margin-top: 4px;
  font-size: 13.5px;
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.58);
}
.tap-btn:first-child .tap-sub { color: rgba(0, 0, 0, 0.55); }

.tap-alt {
  margin-top: 20px;
  font-size: 13.5px;
  color: rgba(255, 255, 255, 0.45);
}
.tap-alt a { color: rgba(255, 255, 255, 0.8); text-decoration: underline; text-underline-offset: 3px; }
.tap-alt a:hover { color: #fff; }

.tap-socials {
  display: flex;
  justify-content: center;
  gap: 22px;
  margin-top: clamp(30px, 5vw, 42px);
}
.tap-socials a {
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.1);
  transition: background 0.3s ease;
}
.tap-socials a:hover { background: rgba(255, 255, 255, 0.2); }
.tap-socials svg { width: 19px; height: 19px; fill: #fff; opacity: 0.85; }

.tap-home {
  display: inline-block;
  margin-top: 26px;
  font-size: 13px;
  letter-spacing: 0.04em;
  color: rgba(255, 255, 255, 0.4);
}
.tap-home:hover { color: rgba(255, 255, 255, 0.75); }

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

/* --- Be Brand New (bebrandnew.html) ---
   Class artwork in a contained frame. The shadow sits on this element rather
   than on the img inside it, so it is not clipped during the reveal (see the
   note by .reveal). */
.bbn-art {
  max-width: 820px;
  margin: 0 auto;
  border-radius: var(--radius-card);
  overflow: hidden;
  box-shadow: 0 30px 70px rgba(0, 0, 0, 0.16);
}
.bbn-art img { width: 100%; height: auto; }

/* ==========================================================================
   MIDWEEK BAND (homepage) — built to the Midweek brand sheet.
   Palette sampled from that artwork: cyan #73d7d5 down to blue #1a7de7,
   with #0068f0 for the marks, headline and pill.
   ========================================================================== */

.mw-band {
  --mw-cyan: #73d7d5;
  --mw-blue: #1a7de7;
  --mw-ink:  #0068f0;

  position: relative;
  overflow: hidden;
  padding: 0 0 clamp(56px, 7vw, 96px);
  /* All the type sits on the pale cyan and the wash only drops to blue below
     the button. Blue-on-blue measured 1.4:1 when the gradient darkened under
     the copy, which is unreadable; on cyan the same brand blue clears 4.5:1. */
  background: linear-gradient(170deg,
    #82ddd9 0%, #79d7d9 56%, #6dccdb 88%, var(--mw-blue) 100%);
  text-align: center;
}

/* The soft light bloom the artwork has in its upper right. */
.mw-band::before {
  content: "";
  position: absolute;
  top: -10%; right: -10%;
  width: 60%; aspect-ratio: 1;
  background: radial-gradient(closest-side, rgba(226, 252, 246, 0.75), transparent 70%);
  pointer-events: none;
}

.mw-band > * { position: relative; }

/* ---------- Photo collage ---------- */

/* Two offset rows of tilted tiles that run off both edges, as on the sheet.
   Fixed tile widths (not a grid) so the rows can bleed and overlap. */
.mw-collage {
  display: flex;
  flex-direction: column;
  gap: clamp(10px, 1.2vw, 16px);
  padding: clamp(26px, 3.4vw, 44px) 0 clamp(30px, 4vw, 52px);
  pointer-events: none;
}

.mw-row {
  display: flex;
  justify-content: center;
  gap: clamp(10px, 1.2vw, 16px);
  /* Pull wider than the viewport so the end tiles are cut off by the edge. */
  margin-inline: clamp(-90px, -6vw, -40px);
}
.mw-row-2 { transform: translateX(clamp(-56px, -4vw, -24px)); }

.mw-collage img {
  flex: 0 0 auto;
  width: clamp(116px, 15vw, 214px);
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: clamp(12px, 1.4vw, 20px);
  box-shadow: 0 10px 26px rgba(6, 40, 80, 0.16);
}

/* Alternating tilt, so the strip reads as a scattered collage not a filmstrip */
.mw-row img:nth-child(odd)  { transform: rotate(-2.2deg); }
.mw-row img:nth-child(even) { transform: rotate(1.8deg); }
.mw-row-2 img:nth-child(odd)  { transform: rotate(2deg); }
.mw-row-2 img:nth-child(even) { transform: rotate(-1.6deg); }

/* ---------- Copy ---------- */

.mw-marks {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: clamp(24px, 4vw, 64px);
  margin-bottom: clamp(22px, 3vw, 38px);
}
.mw-marks img { height: clamp(30px, 3.4vw, 46px); width: auto; }

.mw-title {
  /* A shade under the brand blue. #0068f0 measured 2.96:1 on the cyan, just
     shy of the 3.0 display-type minimum; this clears it at 3.27 and reads as
     the same colour. */
  color: #0060e8;
  font-weight: 800;
  line-height: 0.86;
  letter-spacing: -0.045em;
  font-size: clamp(58px, 12vw, 168px);
  text-transform: uppercase;
}
.mw-title span {
  display: block;
  font-size: 0.42em;
  letter-spacing: -0.03em;
  margin-top: 0.1em;
}

.mw-pill {
  display: inline-block;
  margin-top: clamp(22px, 3vw, 38px);
  padding: clamp(12px, 1.5vw, 20px) clamp(28px, 4vw, 56px);
  border-radius: 999px;
  background: var(--mw-ink);
  color: #fff;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: -0.02em;
  font-size: clamp(22px, 3.4vw, 46px);
  line-height: 1;
}
.mw-pill i { font-style: normal; padding: 0 0.3em; opacity: 0.85; }

/* A deeper blue than the marks and headline. This line is body-sized, so it
   has to clear 4.5:1, which the brand blue does not manage on cyan. */
.mw-ages {
  margin-top: clamp(18px, 2.4vw, 30px);
  color: #00397f;
  font-weight: 700;
  font-size: clamp(16px, 1.8vw, 23px);
}

.mw-ctas { justify-content: center; margin-top: clamp(26px, 3.4vw, 40px); }

@media (max-width: 640px) {
  /* Three tiles a row reads better than five squeezed ones on a phone. */
  .mw-row img:nth-child(n + 4) { display: none; }
  .mw-row-2 img:nth-child(n + 4) { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .mw-collage img { transform: none !important; }
}

/* --- /links: the long link-in-bio page (links.html) ---
   Shares the /tap look, but scrolls rather than fitting one screen, and adds
   labelled groups plus a compact chip grid for the secondary links. */

.tap-long { align-items: flex-start; padding-top: clamp(40px, 8vw, 72px); }
.tap-long .tap-inner { max-width: 480px; }

/* This page is several screens tall, so far more of the photo shows than on
   /tap and the campus sign started competing with the chips. Deepen the scrim
   and hold the image to the viewport so it stays a texture, not a subject. */
.tap-long .tap-bg { position: fixed; }
.tap-long .tap-bg::after {
  background: linear-gradient(180deg, rgba(6, 8, 14, 0.88), rgba(6, 8, 14, 0.95));
}

.tap-sec {
  margin: clamp(30px, 5vw, 42px) 0 14px;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
}

.tap-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

.tap-chip {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  min-height: 54px;
  padding: 12px 16px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.2);
  font-size: 15.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.25;
  transition: transform 0.35s var(--ease-out), background 0.3s ease, border-color 0.3s ease;
}
.tap-chip:hover { background: rgba(255, 255, 255, 0.18); border-color: rgba(255, 255, 255, 0.4); }
.tap-chip:active { transform: scale(0.985); }

/* An odd number of chips leaves a gap; let the last one span both columns. */
.tap-grid > .tap-chip:last-child:nth-child(odd) { grid-column: 1 / -1; }

.tap-contact { margin-top: 26px; }

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

/* ── Accessibility ─────────────────────────────────────────────────────── */

/* Skip link: invisible until a keyboard user tabs to it, then pinned top-left. */
.skip-link {
  position: absolute;
  left: 16px; top: -100px;
  z-index: 1000;
  padding: 12px 18px;
  background: var(--ink);
  color: var(--white);
  font-weight: 600;
  border-radius: 999px;
  transition: top 0.2s var(--ease-out);
}
.skip-link:focus { top: 16px; }

/* One visible focus ring for keyboard users; mouse clicks don't trigger it. */
a:focus-visible, button:focus-visible {
  outline: 2px solid var(--blue-bright);
  outline-offset: 3px;
  border-radius: 6px;
}
