/* =========================================================
   MERCY ROAD CHURCH — CARMEL
   Design system: near-black canvas, oversized tight display
   type, mono micro-labels, hairline rules, 2px + pill radii.
   ========================================================= */

:root{
  /* ---- Official Mercy Road brand palette ----
     Blue #4daac4 · Orange #f36523 · Black #000000 · White #ffffff · Gray #c4c6c6 */
  --blue:       #4daac4;
  /* Brand blue is 7.9:1 on black but only 2.7:1 on white — below the 3:1
     WCAG floor for large text. Light sections use this darkened tint (3.5:1). */
  --blue-ink:   #3d93ad;
  --orange:     #f36523;
  --red:        #d92027;
  --black:      #000000;
  --white:      #ffffff;
  --gray:       #c4c6c6;

  /* Applied roles (names kept stable across the sheet) */
  --ink:        #000000;   /* the only page black */
  --ink-2:      #101010;   /* the only elevated surface: overlay, wells, map */
  --ink-3:      var(--ink-2);
  --cream:      var(--white);
  --cream-70:   rgba(255,255,255,.72);
  --cream-55:   #c4c6c6;   /* brand gray carries the muted tone */
  --cream-40:   rgba(255,255,255,.42);
  --rule:       rgba(255,255,255,.16);
  --rule-soft:  rgba(255,255,255,.09);
  --accent:     var(--blue);

  /* Inverted (white sections) */
  --ink-on-cream:      #000000;
  --ink-on-cream-65:   rgba(0,0,0,.62);
  --rule-on-cream:     rgba(0,0,0,.14);
  /* Same hairline, for an element that sits off the pixel grid. See .pcard:hover. */
  --rule-on-cream-lifted: rgba(0,0,0,.19);
  --ft-line:           9px;    /* gap under the footer contact line */

  /* Type — Gotham only. Black (900) for display, Book (400) for everything
     else. "gotham" is the Adobe Fonts family name; Montserrat is the
     fallback if the kit is blocked on this domain. */
  --display: "gotham", "Montserrat", "Helvetica Neue", Arial, sans-serif;
  --sans:    "gotham", "Montserrat", "Helvetica Neue", Arial, sans-serif;
  /* Micro-labels: Gotham Book, uppercase, tracked wide — replaces the mono */
  --label:   "gotham", "Montserrat", "Helvetica Neue", Arial, sans-serif;

  /* Gotham weight ladder: Book 400 · Medium 500 · Bold 700 · BLACK 800 · Ultra 900.
     800 is Black — 900 was Ultra and read far too heavy. */
  --w-black: 800;
  --w-book:  400;

  /* Shape */
  --r-sm: 2px;
  --r-md: 6px;
  --r-pill: 999px;

  /* One control height drives every button and the menu pill, so nothing
     drifts out of proportion between breakpoints. */
  --btn-h: 46px;
  --mark-h: 34px;   /* logo mark / menu icon disc */

  /* Rhythm */
  --pad: clamp(20px, 4.5vw, 72px);
  /* THE section spacing. Every gap between two sections is exactly twice
     this, on every page. Change this one line to change the whole site.
     A whole number, and deliberately not tied to vh: a viewport-height unit
     made the gap shrink on shorter windows, so the same page measured
     differently on two machines. Phones get the smaller value below. */
  --sec-y: 144px;
  --gap-in: clamp(34px, 5vh, 56px);   /* spacing between blocks inside a section */
  --gap-sep: calc(var(--gap-in) * 2); /* air either side of a separator rule */
  --maxw: 1680px;   /* content ceiling on wide displays */
  --float: clamp(12px,2vw,28px);   /* side inset for floating panels */
  --r-lg: clamp(14px,1.6vw,26px);  /* floating-panel corner */

  --ease: cubic-bezier(.22,1,.36,1);
}

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

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


body{
  margin:0;
  background:var(--ink);
  color:var(--cream);
  font-family:var(--sans);
  font-size:clamp(15px,.55vw + 13.5px,17px);
  line-height:1.55;
  font-weight:var(--w-book);
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  overflow-x:hidden;
}
body.is-locked{ overflow:hidden; }

img, svg, video{ display:block; max-width:100%; }
a{ color:inherit; text-decoration:none; }
h1, h2, h3, p, ul, figure, blockquote{ margin:0; }
ul{ list-style:none; padding:0; }
button{ font:inherit; color:inherit; background:none; border:0; cursor:pointer; }

:focus-visible{ outline:2px solid var(--accent); outline-offset:3px; border-radius:var(--r-sm); }

/* ---------- Type primitives ----------
   .mono is the micro-label: Gotham Book, uppercase, widely tracked.
   Class name kept so markup stays stable. */
.mono{
  font-family:var(--label);
  font-size:clamp(10px,.28vw + 9.1px,12px);
  font-weight:var(--w-book);
  letter-spacing:.18em;
  text-transform:uppercase;
  line-height:1.4;
}
.lbl{ color:var(--cream-55); display:block; }

.h2{
  font-family:var(--display);
  font-weight:var(--w-black);
  font-size:clamp(36px,7vw,100px);
  line-height:.94;
  /* Gotham Black is wide + heavy — it needs far less negative tracking
     than a condensed grotesk would. */
  letter-spacing:-.025em;
  text-transform:uppercase;
}
.h2 em{ font-style:normal; color:inherit; }

/* =========================================================
   PRELOADER
   ========================================================= */
.loader{
  position:fixed; inset:0; z-index:200;
  background:var(--ink);
  display:grid; place-items:end stretch;
  padding:var(--pad);
  transition:opacity .8s ease, filter .8s var(--ease);
}
.loader.is-done{ opacity:0; filter:blur(16px); pointer-events:none; }

/* The page itself resolves from blur into focus as the loader clears —
   1.6s, twice the loader's own .8s defocus. */
.hdr, main, .ft{
  transition:filter 1.6s var(--ease), opacity 1.2s ease;
}
.is-loading .hdr, .is-loading main, .is-loading .ft{
  filter:blur(20px);
  opacity:0;
}
.loader__inner{ width:100%; }
.loader__mark{
  /* No mask — the blur needs room to bleed past the logo's edges. */
  overflow:visible;
  padding-bottom:.06em;
}
.loader__reveal{
  display:block;
  opacity:0;
  filter:blur(22px);
  transform:scale(1.05);
  animation:focusIn 1.75s var(--ease) forwards;
  will-change:filter, opacity, transform;
}
.loader__logo{
  width:min(70vw, 620px);
  height:auto;
}


.loader__meta{
  display:flex; justify-content:space-between; align-items:baseline;
  margin:clamp(18px,3vh,34px) 0 12px; color:var(--cream-55);
}
.loader__bar{ height:1px; background:var(--rule-soft); overflow:hidden; }
.loader__bar i{ display:block; height:100%; width:0%; background:var(--cream); }



/* =========================================================
   HEADER
   ========================================================= */
.hdr{
  position:fixed; top:0; left:0; right:0; z-index:120;
  display:flex; align-items:center; justify-content:space-between;
  gap:16px;
  padding:clamp(12px,1.6vw,20px) var(--pad);
  transition:transform .45s var(--ease), background .35s ease, backdrop-filter .35s ease, border-color .35s ease;
  border-bottom:1px solid transparent;
}
.hdr.is-stuck{
  background:rgba(0,0,0,.78);
  backdrop-filter:blur(14px) saturate(140%);
  border-bottom-color:var(--rule-soft);
}
.hdr.is-hidden{ transform:translateY(-105%); }
.is-open .hdr{ transform:none; }

.hdr__logo{ display:flex; align-items:center; gap:11px; min-height:44px; }
.hdr__mark{ width:var(--mark-h); height:auto; flex:none; }
.hdr__lockup{ display:none; height:clamp(17px,1.5vw,23px); width:auto; }
.hdr__lockup.is-fallback{ height:auto; width:clamp(30px,2.4vw,38px); }
.hdr__campus{
  font-family:var(--label); font-weight:var(--w-book);
  font-size:clamp(9px,.3vw + 8px,10.5px);
  letter-spacing:.2em; text-transform:uppercase;
  color:var(--cream-55);
  padding-left:11px; margin-left:1px;
  border-left:1px solid var(--rule);
  line-height:1.2;
}


.hdr__inline{ display:none; gap:4px; }
.hdr__inline a{
  font-size:14px; letter-spacing:-.01em; color:var(--cream-70);
  padding:11px 15px; border-radius:var(--r-pill);
  transition:color .25s ease, background .25s ease;
}
.hdr__inline a:hover{ color:var(--cream); background:rgba(255,255,255,.08); }

.hdr__act{ display:flex; align-items:center; gap:8px; }

/* ---------- Buttons ---------- */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  min-height:var(--btn-h); padding:0 22px;
  border-radius:var(--r-pill);
  font-size:14px; font-weight:var(--w-book); letter-spacing:0;
  white-space:nowrap;
  border:1px solid transparent;
  transition:background .3s var(--ease), color .3s var(--ease), border-color .3s var(--ease), transform .3s var(--ease);
}
.btn svg{ width:11px; height:11px; flex:none; }
.btn--solid{ background:var(--cream); color:var(--ink); }
.btn--solid:hover{ background:#fff; transform:translateY(-1px); }
.btn--ghost{ border-color:var(--rule); color:var(--cream); }
.btn--ghost:hover{ border-color:var(--cream); background:rgba(255,255,255,.08); }
.btn--lg{ min-height:calc(var(--btn-h) + 8px); padding:0 28px; font-size:15px; }

/* =========================================================
   HERO
   ========================================================= */
.hero{
  padding:calc(var(--pad) + 78px) var(--pad) var(--sec-y);
  min-height:100svh;
  display:flex; flex-direction:column;
}








.hero__h1{
  font-family:var(--display); font-weight:var(--w-black);
  /* Must never wrap to a third line — sized off the longest line,
     "Love Deeply.", with nowrap as the guarantee. */
  font-size:min(13.2vw, 208px);
  line-height:.9; letter-spacing:-.03em;
  margin-bottom:clamp(26px,5vh,54px);
}
/* The mask box must clear Gotham's descenders or the "y" tails get cut. */
.line{ display:block; overflow:hidden; padding-bottom:.14em; margin-bottom:-.14em; }
.line__i{
  display:block; white-space:nowrap;
  transform:translateY(105%);
  transition:transform 1.05s var(--ease);
}
.is-ready .line__i{ transform:translateY(0); }
.is-ready .line:nth-child(2) .line__i{ transition-delay:.1s; }


.hero__ctas{ display:flex; flex-wrap:wrap; gap:8px; margin-top:12px; }



.hero__bar{
  display:flex; flex-wrap:wrap; gap:clamp(22px,4vw,64px);
  justify-content:space-between; align-items:flex-end;
  padding-bottom:var(--gap-sep);
  border-bottom:1px solid var(--rule-soft); opacity:0; transform:translateY(18px); transition:opacity .8s ease .45s, transform .8s var(--ease) .45s;}
.is-ready .hero__bar, .is-ready .hero__top{ opacity:1; transform:none; }

/* ---------- Contained media panel ---------- */
.media{ margin:var(--gap-sep) 0 0; }
.media--hero{ margin-top:calc(var(--gap-sep) / 2); }
.media__frame{
  position:relative; border-radius:var(--r-md); overflow:hidden;
  aspect-ratio:16/9; background:var(--ink-3);
  border:1px solid var(--rule-soft);
}

.media__frame video, .media__frame img{ width:100%; height:100%; object-fit:cover; }




/* Corner crosshairs */
.cross{
  position:absolute; width:11px; height:11px; opacity:.55;
  background:
    linear-gradient(var(--cream),var(--cream)) center/1px 100% no-repeat,
    linear-gradient(var(--cream),var(--cream)) center/100% 1px no-repeat;
}
.cross--tl{ top:10px; left:10px; } .cross--tr{ top:10px; right:10px; }
.cross--bl{ bottom:10px; left:10px; } .cross--br{ bottom:10px; right:10px; }

/* =========================================================
   SECTIONS
   ========================================================= */
.sec{ padding:var(--sec-y) var(--pad); }
/* Light sections float inside the black page, echoing the menu pill. */

.sec--cream .lbl{ color:var(--ink-on-cream-65); }

.sec__head{
  display:grid; gap:clamp(16px,2.6vh,26px);
  margin-bottom:var(--gap-in);
  max-width:1500px;
}
.sec__head .btn{ justify-self:start; }
.sec--cream .btn--ghost{ border-color:var(--rule-on-cream); color:var(--ink-on-cream); }
.sec--cream .btn--ghost:hover{ border-color:var(--ink-on-cream); background:rgba(0,0,0,.06); }
.sec--cream .btn--solid{ background:var(--ink-on-cream); color:var(--cream); }


/* ---------- Events ---------- */
.events{ border-top:1px solid var(--rule); }
.ev a{
  display:grid;
  grid-template-columns:1fr auto;
  grid-template-areas:"date go" "name name" "time time";
  gap:6px 20px;
  align-items:center;
  padding:clamp(20px,3vh,32px) 0;
  border-bottom:1px solid var(--rule);
  transition:padding .45s var(--ease), background .35s ease;
}
.ev a:hover{ padding-left:clamp(10px,1.6vw,26px); padding-right:clamp(10px,1.6vw,26px); background:rgba(255,255,255,.04); }
.ev__date{ grid-area:date; color:var(--cream-55); }
.ev__name{
  grid-area:name;
  font-family:var(--display); font-weight:var(--w-black);
  font-size:clamp(30px,4.2vw,58px);   /* same as .msg__h */
  line-height:1; letter-spacing:-.025em;
}
.ev__time{ grid-area:time; color:var(--cream-55); }

.ev a:hover 
.events__note{ margin-top:16px; color:var(--cream-40); }

/* ---------- Pathway ---------- */
.path{
  display:grid; gap:1px;
  background:var(--rule-on-cream);
  border:1px solid var(--rule-on-cream);
  border-radius:var(--r-md);
  /* Not overflow:hidden. A card that magnifies on hover has to be able to
     grow past the grid's edge, so the 6px rounding moves onto the corner
     cards instead — they already clip their own images. */
  grid-template-columns:1fr;
}
/* One column: the first card caps the top, the last caps the bottom. */
.path .pcard:first-child{ border-radius:var(--r-md) var(--r-md) 0 0; }
.path .pcard:last-child{ border-radius:0 0 var(--r-md) var(--r-md); }

.pcard:hover{ background:#F2F2F2; }


.pcard p{ font-size:15px; color:var(--ink-on-cream-65); line-height:1.45; }
/* =========================================================
   TEXT LINK — one style, used everywhere
   Inherits the size of whatever it sits in, so it matches body copy inside a
   sentence and card copy inside a card. Change it here and every text link on
   the site changes with it.
   ========================================================= */
/* =========================================================
   TEXT LINK — ONE STYLE, EVERYWHERE
   This is the site's only text-link style, taken from the Next Steps cards on
   the home page. Every "Learn More", "Sign Up" and similar text link uses it,
   at this size, whatever it sits next to.

   DO NOT give .link a different size, family or tracking in a section-specific
   rule. It has drifted twice already: once inheriting body copy size so the
   same link rendered 10px on the home page and 17px inside a paragraph. If a
   link needs to look different, that is a decision to make here, once, so it
   changes everywhere at the same time.
   ========================================================= */
.link{
  display:inline-flex; align-items:center; gap:7px;
  vertical-align:baseline; white-space:normal; text-decoration:none;
  font-family:var(--label); font-size:10px; letter-spacing:.07em;
  text-transform:uppercase; line-height:1.2;
}
/* The arrow is a fixed 10px to match the label, and display:block because .ico
   is block site-wide. */
.link svg,
.link .ico{ display:block; width:10px; height:10px; margin-left:0;
            transition:transform .35s var(--ease); }
.link:hover svg,
.link:hover .ico{ transform:translate(2px,-2px); }
.link:hover{ color:var(--cream); }
/* On a light panel that hover colour is white on white. The arrow's nudge
   carries the feedback there instead. */
.sec--cream .link:hover{ color:var(--ink-on-cream); }


/* ---------- Statements ---------- */











/* ---------- Next Gen ---------- */









/* ---------- Expect ----------
   Palette-aware: dark section by default, inverted inside a cream panel, so
   an .expect list can sit in either without hard-coded colours. */
/* No rules enclosing the list. The columns are separated well enough by the
   space around them, and where the list sits under a full-width image the
   picture's own edge was making the top one read as a double rule. Dividers
   BETWEEN rows are a different thing and still apply -- see .xp below. */
.expect{
  display:grid; grid-template-columns:1fr;
}
/* A list that follows a paragraph rather than a heading needs its own air, or
   the first item reads as the next line of that paragraph. */
.expect--pushed{ margin-top:clamp(20px,3vh,38px); }
.xp{
  padding-block:calc(var(--gap-in) / 2);
  display:grid; gap:10px; align-content:start;
  border-top:1px solid var(--rule-soft);
}
.sec--cream .xp{ border-top-color:rgba(0,0,0,.08); }
.xp:first-child{ border-top:0; }

.xp h3{
  font-family:var(--display); font-weight:var(--w-black);
  font-size:clamp(24px,2.6vw,42px); letter-spacing:-.022em; line-height:1;
}
.xp p{ color:var(--cream-70); max-width:46ch; font-size:clamp(15px,.4vw + 14px,17px); }
/* A row of buttons that lines up with the list above it: same columns, same
   gap, so each button sits under the item it belongs to and both share one
   baseline. Mirrors .expect rather than guessing at widths. */
.colbtns{
  display:grid; grid-template-columns:1fr;
  gap:clamp(14px,2vh,20px) clamp(24px,4vw,64px);
  margin-top:clamp(20px,3vh,34px);
}
.colbtns__cell{ display:flex; }
@media (min-width:760px){
  /* 760px is where .expect itself goes two-up; matching it keeps the buttons
     under their own columns at every width, and stacked below that. */
  .colbtns{ grid-template-columns:repeat(2,1fr); }
}
.sec--cream .xp p{ color:var(--ink-on-cream-65); }

/* ---------- Find Us ---------- */
/* Mobile: the "Find Us" label leads, then the image, then the address and
   buttons. Only the label moves above the image — not the address. */
.find{
  display:grid; grid-template-columns:1fr;
  grid-template-areas:"label" "media" "addr" "actions";
  gap:var(--gap-in);
  align-items:center;
}
.find__label{ grid-area:label; }

.find__addr{ grid-area:addr; }
.find__actions{ grid-area:actions; }

.find .h2{ font-size:clamp(34px,4.6vw,62px); } /* address sits in a half-width column */
.find__btns{ display:flex; flex-wrap:wrap; align-items:flex-start; gap:8px; }



/* ---------- CTA ---------- */
.cta{
  /* No rule above the quote; the space above is half what it was. */
  padding:var(--sec-y) var(--pad);
}
.cta__q{
  font-family:var(--display); font-weight:var(--w-black);
  font-size:clamp(34px,7.4vw,116px);
  line-height:.92; letter-spacing:-.028em;
  max-width:18ch;
}
.cta__q em{ font-style:normal; color:inherit; }
.cta__b{
  display:flex; flex-wrap:wrap; gap:20px; align-items:center; justify-content:space-between;
  margin-top:clamp(30px,5vh,58px);
  padding-top:clamp(20px,3vh,32px);
  border-top:1px solid var(--rule-soft);
}
/* Times and address stack as one block so the band stays two columns. */
.cta__meta{ display:grid; gap:6px; min-width:0; }
.cta__btns{ display:flex; flex-wrap:wrap; gap:8px; }

/* =========================================================
   FOOTER
   ========================================================= */
.ft{ padding:var(--sec-y) var(--pad) var(--pad); }













/* =========================================================
   SCROLL REVEAL
   ========================================================= */
.reveal{ opacity:0; transform:translateY(26px); }
.reveal.in{
  opacity:1; transform:none;
  transition:opacity .85s var(--ease), transform .95s var(--ease);
}
.reveal.in:nth-child(2){ transition-delay:.06s; }
.reveal.in:nth-child(3){ transition-delay:.12s; }
.reveal.in:nth-child(4){ transition-delay:.18s; }
.reveal.in:nth-child(5){ transition-delay:.24s; }

/* =========================================================
   RESPONSIVE — progressive enhancement upward
   ========================================================= */

/* ≥ 560px */


/* ≥ 760px */


/* ≥ 1024px — inline nav appears */


/* =========================================================
   WIDE DISPLAYS
   Gutters absorb everything past --maxw so the measure stays
   readable instead of stretching to the bezel. Full-bleed
   elements (section backgrounds) keep their edges.
   ========================================================= */
.hdr, .hero, .sec, .cta, .ft, .loader{
  padding-inline:max(var(--pad), (100% - var(--maxw)) / 2);
}

/* Light sections float inward by --float, so they subtract it from their own
   padding to keep their text on the same optical line as everything else.
   This subtraction must NOT leak onto the shared rule above. */




/* Ultrawide / 4K: hold the type, widen the rhythm only */


/* Touch: disable hover transforms that can stick */


/* Reduced motion */



/* =========================================================
   AGE MINISTRIES — text buttons, no imagery, no section title
   ========================================================= */
.ages{
  display:grid; grid-template-columns:1fr; gap:0;
}


/* Identical to .ev a:hover — padding shift, background wash, arrow slide. */
.agebtn:hover{
  padding-left:clamp(10px,1.6vw,26px);
  padding-right:clamp(10px,1.6vw,26px);
  background:rgba(255,255,255,.04);
}


/* =========================================================
   ICONS — one stroked set, sized to the type it sits beside
   ========================================================= */
.sprite{ position:absolute; width:0; height:0; overflow:hidden; }
.ico{ width:1.15em; height:1.15em; flex:none; stroke-width:1.6; }
.btn .ico{ width:15px; height:15px; }

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

/* =========================================================
   NAV LINK HOVER
   Top bar (.rl): the label defocuses while its twin resolves into
   focus — the same idea as the loader.
   Drawer / sheet (.dl): keeps the vertical roll.
   ========================================================= */

.rl span, .dl span{
  display:block; position:relative;
  overflow:visible;            /* the blur must not be clipped */
}
/* Bigger type needs a longer focus pull, or the blur reads as a flicker.
   The exit is deliberately much faster than the entrance: with a slow
   symmetric transition, moving down a list leaves the previous row still
   fading out while the next fades in, so two rows look lit at once. */
.rl i, .dl i{
  display:block; font-style:normal; line-height:1.25em;
  --focus-in:.6s;       /* 25% faster than .8s */
  --focus-out:.15s;
  --blur-amt:.3em;      /* was .42em */
  transition:opacity var(--focus-out) ease,
             filter  var(--focus-out) var(--ease);
}
.rl:hover i, .rl:focus-visible i, .dl:hover i, .dl:focus-visible i{
  transition:opacity var(--focus-in) ease,
             filter  var(--focus-in) var(--ease);
}
.dl i{
  --focus-in:.95s;      /* slower, so the focus pull is gentle */
  --focus-out:.22s;
  --blur-amt:.24em;     /* softer — .42em is harsh at 26–34px */
}
/* The first copy holds the width; the twin overlays it. Blur is set in em so
   it stays proportional from 14px nav links up to 58px age rows. */
.rl i:nth-child(2), .dl i:nth-child(2){
  position:absolute; inset:0;
  opacity:0; filter:blur(var(--blur-amt));
}
.rl:hover i:nth-child(1), .rl:focus-visible i:nth-child(1), .dl:hover i:nth-child(1), .dl:focus-visible i:nth-child(1){
  opacity:0; filter:blur(var(--blur-amt));
}
.rl:hover i:nth-child(2), .rl:focus-visible i:nth-child(2), .dl:hover i:nth-child(2), .dl:focus-visible i:nth-child(2){
  opacity:1; filter:blur(0);
}

/* =========================================================
   MENU BUTTON — circular, echoing the logo mark
   ========================================================= */
.menubtn{
  display:flex; align-items:center; gap:11px;
  height:var(--btn-h); padding:0 8px 0 7px;
  border:1px solid var(--rule); border-radius:var(--r-pill);
  transition:border-color .35s ease, background .35s ease;
}
.menubtn:hover{ border-color:var(--cream); background:rgba(255,255,255,.06); }
.menubtn__ico{
  position:relative; display:grid; place-items:center;
  width:calc(var(--btn-h) - 14px); height:calc(var(--btn-h) - 14px); flex:none;
  border-radius:50%; background:var(--cream);
}
.menubtn__ico i{
  position:absolute; left:50%; top:50%;
  width:13px; height:1.5px; border-radius:2px; background:var(--ink);
  transition:transform .45s var(--ease);
}
.menubtn__ico i:nth-child(1){ transform:translate(-50%,-50%) translateY(-3.5px); }
.menubtn__ico i:nth-child(2){ transform:translate(-50%,-50%) translateY(3.5px); }
.is-open .menubtn__ico i:nth-child(1){ transform:translate(-50%,-50%) rotate(45deg); }
.is-open .menubtn__ico i:nth-child(2){ transform:translate(-50%,-50%) rotate(-45deg); }

.menubtn__label{
  position:relative; display:block; overflow:hidden;
  height:13px; width:47px; padding-right:8px;
  font-family:var(--label); font-size:10.5px;
  letter-spacing:.18em; text-transform:uppercase;
}
.menubtn__label i{
  position:absolute; left:0; top:0; font-style:normal; line-height:13px;
  transition:transform .45s var(--ease);
}
.menubtn__label [data-menu-close]{ transform:translateY(100%); }
.is-open .menubtn__label [data-menu-open]{ transform:translateY(-100%); }
.is-open .menubtn__label [data-menu-close]{ transform:translateY(0); }

/* =========================================================
   SIDE DRAWER — white panel inset from the right edge
   ========================================================= */
.scrim{
  position:fixed; inset:0; z-index:135;
  background:rgba(0,0,0,.55);
  backdrop-filter:blur(3px);
  opacity:0; transition:opacity .5s ease;
}
.scrim.is-on{ opacity:1; }

.drawer{
  position:fixed; z-index:140;   /* above .hdr (120) — covers the header */
  top:0; right:0; bottom:0;
  width:min(470px, 100vw);
  padding:var(--float);
  pointer-events:none;

  /* Flip the role tokens once; every descendant inverts with them. */
  --cream:      var(--black);
  --cream-70:   rgba(0,0,0,.70);
  --cream-55:   rgba(0,0,0,.55);
  --cream-40:   rgba(0,0,0,.42);
  --rule:       rgba(0,0,0,.16);
  --rule-soft:  rgba(0,0,0,.09);
  --accent:     var(--blue-ink);
}
.drawer__panel{
  position:relative;   /* containing block for .dclose — see note below */
  height:100%;
  background:var(--white);
  color:var(--black);
  border:1px solid var(--rule);
  border-radius:var(--r-lg);
  box-shadow:0 40px 90px rgba(0,0,0,.7);
  overflow:hidden;
  transform:translateX(calc(100% + var(--float)));
  transition:transform .72s var(--ease);
  pointer-events:auto;
}
.is-open .drawer__panel{ transform:none; }

.drawer__scroll{
  height:100%; overflow-y:auto; overscroll-behavior:contain;
  padding:clamp(78px,11vh,104px) clamp(26px,3vw,38px) clamp(32px,5vh,48px);
  display:flex; flex-direction:column; gap:clamp(34px,5vh,52px);
}

.dnav{ display:flex; flex-direction:column; }
.dl{
  padding:clamp(11px,1.8vh,16px) 0;
  border-bottom:1px solid var(--rule-soft);
  font-family:var(--display); font-weight:var(--w-black);
  font-size:clamp(26px,3.6vw,34px);
  letter-spacing:-.022em; text-transform:uppercase;
}
.dnav .dl{ opacity:0; transform:translateY(18px); }
.is-open .dnav .dl{
  opacity:1; transform:none;
  transition:opacity .5s var(--ease), transform .6s var(--ease);
}
.is-open .dnav .dl:nth-child(1){ transition-delay:.20s; }
.is-open .dnav .dl:nth-child(2){ transition-delay:.25s; }
.is-open .dnav .dl:nth-child(3){ transition-delay:.30s; }
.is-open .dnav .dl:nth-child(4){ transition-delay:.35s; }
.is-open .dnav .dl:nth-child(5){ transition-delay:.40s; }
.is-open .dnav .dl:nth-child(6){ transition-delay:.45s; }

.dsub{
  display:grid; grid-template-columns:repeat(2,1fr);
  gap:clamp(26px,4vh,36px) clamp(20px,3vw,30px);
  padding-top:clamp(26px,4vh,34px);
  opacity:0; transform:translateY(14px);
  transition:opacity .5s ease .5s, transform .55s var(--ease) .5s;
}
.is-open .dsub{ opacity:1; transform:none; }
.dsub .ft__h{
  font-family:var(--label); font-weight:var(--w-black);
  font-size:10.5px; letter-spacing:.18em; text-transform:uppercase;
  color:var(--cream-55);
  padding-bottom:7px; margin-bottom:0;
  border-bottom:1px solid var(--rule);
}
.dsub ul{ margin-top:22px; display:grid; gap:9px; }
.dsub a{ font-size:14.5px; line-height:1.25; color:var(--cream-70); }
.dsub a:hover{ color:var(--cream); }

.dfoot{
  display:grid; gap:16px;
  padding-top:clamp(18px,3vh,26px);
  border-top:1px solid var(--rule-soft);
  opacity:0; transform:translateY(14px);
  transition:opacity .5s ease .6s, transform .55s var(--ease) .6s;
}
.is-open .dfoot{ opacity:1; transform:none; }
.dfoot p{ margin-top:6px; font-size:14.5px; color:var(--cream-70); line-height:1.5; }
.dfoot a:hover{ color:var(--cream); }

/* Drawer covers the header, so it carries its own close control. */
.dclose{
  position:absolute; top:clamp(18px,2.4vh,26px); right:clamp(20px,2.4vw,30px);
  z-index:2;
  display:grid; place-items:center;
  width:42px; height:42px; border-radius:50%;
  background:var(--black);
  transition:transform .35s var(--ease);
}
.dclose:hover{ transform:rotate(90deg); }
.dclose span{ position:relative; display:block; width:15px; height:15px; }
.dclose i{
  position:absolute; top:50%; left:0;
  width:100%; height:1.6px; border-radius:2px; background:var(--white);
}
.dclose i:nth-child(1){ transform:translateY(-50%) rotate(45deg); }
.dclose i:nth-child(2){ transform:translateY(-50%) rotate(-45deg); }

/* =========================================================
   AGE ROWS + EVENT ICON MOTION
   ========================================================= */
.agerow{ display:block; }
.agebtn{
  display:flex; align-items:center; justify-content:space-between; gap:20px;
  padding:clamp(22px,3.4vh,38px) 0;
  border-bottom:1px solid var(--rule);
  font-family:var(--display); font-weight:var(--w-black);
  font-size:clamp(30px,4.2vw,58px);   /* same as .msg__h */
  line-height:1; letter-spacing:-.025em; text-transform:uppercase;
  transition:padding .45s var(--ease), background .35s ease; align-items:center; gap:clamp(14px,2vw,24px);}
/* The opening rule is the item's own border, so it sits inside the row's
   hover highlight exactly like the dividers below it. */
/* The opening rule adds a second border to this row only, so shave its top
   padding by the same 1px to keep every row exactly the same height. */
.agerow:first-child .agebtn{
  border-top:1px solid var(--rule);
  padding-top:calc(clamp(22px,3.4vh,38px) - 1px);
}
.agebtn__img{
  width:clamp(56px,7vw,92px); aspect-ratio:1; object-fit:cover;
  border-radius:var(--r-md); flex:none;
}

.agebtn span{ margin-right:auto; }
.agebtn .ico{ color:var(--cream-40); width:20px; height:20px;
  transition:transform .4s var(--ease), color .3s ease; }
.agebtn:hover .ico{ transform:translateX(7px); color:var(--cream); }

.ev__go{ grid-area:go; color:var(--cream-40); width:20px; height:20px;
  transition:transform .4s var(--ease), color .3s ease; }
.ev a:hover .ev__go{ transform:translateX(7px); color:var(--cream); }

/* =========================================================
   FOOTER COLUMNS
   ========================================================= */
.ft__cols{
  display:grid; grid-template-columns:1fr 1fr;
  gap:clamp(34px,5vw,56px) clamp(24px,4vw,56px);
  padding:0 0 clamp(44px,7vh,80px);
}
.ft__h{
  font-family:var(--display); font-weight:var(--w-black);
  font-size:clamp(15px,1.2vw + 12px,20px);
  letter-spacing:-.01em; text-transform:uppercase;
  color:var(--cream);
  padding-bottom:16px; margin-bottom:18px;
  border-bottom:1px solid var(--rule);
}
.ft__col ul{ display:grid; gap:11px; }
.ft__col a{ font-size:15px; line-height:1.25; color:var(--cream-70); transition:color .25s ease; }
.ft__col a:hover{ color:var(--cream); }


/* =========================================================
   REAL MEDIA
   ========================================================= */
.media__v{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
.map{
  position:relative; aspect-ratio:1/1; border-radius:var(--r-md);
  display:grid; place-items:center;
  border:1px solid var(--rule-soft);
  color:var(--cream-40);
  background:
    linear-gradient(var(--rule-soft) 1px, transparent 1px) 0 0/44px 44px,
    linear-gradient(90deg, var(--rule-soft) 1px, transparent 1px) 0 0/44px 44px,
    radial-gradient(70% 70% at 60% 40%, rgba(77,170,196,.20), transparent 65%),
    var(--ink-2); overflow:hidden;}
.map__img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }

.pcard{
  background:var(--cream);
  padding:clamp(24px,2.6vw,38px) clamp(20px,2.2vw,30px);
  display:flex; flex-direction:column; gap:10px;
  min-height:clamp(190px,26vh,290px);
  transition:background .4s var(--ease); padding:0; overflow:hidden;}
.pcard__img{
  width:100%; aspect-ratio:4/3; object-fit:cover;
  transition:transform .7s var(--ease);
}
/* Same treatment as the team grid: the whole card — image, heading, copy and
   link — grows from its own centre on a springy curve, so it magnifies in
   place rather than lifting. z-index keeps the grown card over its neighbours,
   and the grid's own 1px rules stay put underneath. */
.pcard{
  position:relative; transform-origin:center center; color:inherit;
  /* Same colour as the grid's rules, at zero width. Declaring it here means
     the hover state changes only the width, never the colour. */
  box-shadow:0 0 0 0 var(--rule-on-cream);
  /* The ring and the raised z-index are held for the full length of the
     shrink and only then dropped. Releasing them the instant the pointer
     leaves took the card's edge away while it was still travelling back,
     so it animated home with no border at all.

     steps(1, jump-end), not a delay: a zero-duration transition with a delay
     creates no transition in Chrome at all, so the ring still vanished on the
     first frame. A single step holds the old value for the full .45s and
     swaps at the end, which is the same thing and actually runs. */
  transition:background .4s var(--ease),
             transform .45s cubic-bezier(.34,1.4,.64,1),
             box-shadow .45s steps(1, jump-end),
             z-index .45s steps(1, jump-end);
}
.pcard__img{ transition:filter .7s var(--ease), transform .7s var(--ease); }
.pcard.reveal .pcard__img{ filter:blur(14px); transform:scale(1.06); }
.pcard.reveal.in .pcard__img{ filter:blur(0); transform:none; }
.pcard.reveal.in:nth-child(3n+2) .pcard__img{ transition-delay:.09s; }
.pcard.reveal.in:nth-child(3n+3) .pcard__img{ transition-delay:.18s; }
/* Growing over its neighbours, the card covers the 1px rules that used to
   define its edges, so it draws its own — and it has to be indistinguishable
   from them. A ring, not a border: a border would change the box size and
   reflow the card's contents.

   Two things kept it from matching. The ring is painted inside the scaled
   box, so a 1px spread renders at 1.06px — dividing it out lands back on a
   true hairline. And fading it in left a soft grey edge for most of the
   animation, so it switches instantly instead: the hairline is simply always
   there, first from the grid's rules, then from the card's own ring. */
/* .reveal.in is two classes and .pcard is one, so the reveal rule was winning
   the transition shorthand outright: the card's transition list was only
   opacity and transform, and box-shadow was never in it. That is the real
   reason the ring vanished the instant the pointer left, whatever delay or
   step was written on .pcard. This restates the reveal's own timings so the
   entrance is unchanged, and adds the two properties that were being dropped.
   The ring is held by a single step for the length of the return, so the card
   keeps its edge the whole way back and swaps to the grid's rules at the end. */
.pcard.reveal.in{
  transition:opacity .85s var(--ease),
             transform .95s var(--ease),
             background .4s var(--ease),
             box-shadow .95s steps(1, jump-end),
             z-index .95s steps(1, jump-end);
}
.pcard:hover,.pcard:focus-visible,
.pcard.reveal.in:hover,.pcard.reveal.in:focus-visible{
  transform:scale(1.06); z-index:2;
  /* Entering, both land immediately -- the hold above is for leaving only. */
  transition:background .4s var(--ease),
             transform .45s cubic-bezier(.34,1.4,.64,1),
             box-shadow 0s, z-index 0s;
  /* The colour is nudged up from --rule-on-cream, and only here. The grid's
     rules sit on whole pixels and paint two solid device pixels on a 2x
     screen. A scaled card's edges land between pixels, so the same ink
     becomes one solid pixel with a half-lit one either side -- same weight
     on paper, visibly softer on screen. The extra alpha buys back the
     contrast that the antialiasing spreads out. */
  box-shadow:0 0 0 calc(1px / 1.06) var(--rule-on-cream-lifted);
}
.pcard:focus-visible{ outline:2px solid var(--accent); outline-offset:-2px; }

@media (hover:none){
  .pcard:hover{ transform:none; }
}
@media (prefers-reduced-motion: reduce){
  .pcard.reveal .pcard__img{ filter:none; transform:none; }
  .pcard:hover,.pcard:focus-visible{ transform:none; box-shadow:none; }
}
.pcard h3{
  font-family:var(--display); font-weight:var(--w-black);
  font-size:clamp(24px,2.3vw,36px);
  letter-spacing:-.02em; line-height:1;
  text-transform:uppercase;
  margin-top:auto; margin-top:clamp(16px,1.8vw,22px);}
.pcard h3, .pcard p, .pcard .link{ padding-inline:clamp(18px,2vw,26px); }
.pcard .link{ margin-bottom:clamp(18px,2vw,26px); }

/* The space under the image is not just this margin — the list adds a 1px
   rule and its first cell's padding (--gap-in/2) on top. Subtract both so the
   gap from image to "Park & Arrive" matches the gap from the lede to the
   image. */
.secfig{
  margin:0 0 calc(var(--gap-in) / 2 - 1px);
  border-radius:var(--r-md); overflow:hidden;
}
.secfig img{ width:100%; aspect-ratio:21/9; object-fit:cover; }


/* =========================================================
   MESSAGES — thumbnail left, title block right
   ========================================================= */
.msg{
  display:grid; grid-template-columns:1fr;
  gap:clamp(22px,3vw,52px);
  /* Both columns start on the same line. Centring the shorter column dropped
     the thumbnail ~12px below the label, so the space above the two columns
     read as two different gaps. */
  align-items:start;
}
.msg__media .media__frame{ aspect-ratio:16/9; }
.msg__body{ display:grid; gap:clamp(12px,1.8vh,20px); justify-items:start; }
.msg__h{ font-size:clamp(30px,4.2vw,58px); }
.msg .sec__lede{ max-width:44ch; }


.sec__lede{
  max-width:60ch; font-size:clamp(16px,.7vw + 14px,20px);
  color:var(--ink-on-cream-65); line-height:1.5; color:var(--cream-70);}
.sec--cream .sec__lede{ color:var(--ink-on-cream-65); }
.sec__btns{ display:flex; flex-wrap:wrap; gap:8px; }
/* A button block sitting directly in a section (rather than inside
   .sec__head, which supplies its own gap) had nothing separating it from the
   copy above. */
.sec > .sec__btns,
.prose + .sec__btns{ margin-top:var(--gap-in); }
/* ...but not inside .sec__head, which already puts its own gap between every
   child. Counting both left a button sitting 76px under its paragraph. */
.sec__head .prose + .sec__btns{ margin-top:0; }

/* =========================================================
   DIRECTIONS — inline above 640px, bottom sheet below
   ========================================================= */
.dirs{ position:relative; display:block; }
.dirs__btn{ display:inline-flex; }
/* The inline links are never shown — the sheet is the single entry point at
   every screen size. They remain in the markup as a no-JS fallback. */
.dirs__menu{ display:none; }

.sheet-scrim{
  position:fixed; inset:0; z-index:150;
  background:rgba(0,0,0,.55);
  backdrop-filter:blur(3px);
  opacity:0; transition:opacity .45s ease;
}
.sheet-scrim.is-on{ opacity:1; }
.sheet{
  position:fixed; z-index:155;
  left:0; right:0; bottom:0;
  padding:var(--float);
  pointer-events:none;
  /* keeps it a panel, not a full-width bar, on large screens */
  margin-inline:auto; max-width:560px;
  --cream:      var(--black);
  --cream-70:   rgba(0,0,0,.70);
  --cream-55:   rgba(0,0,0,.55);
  --cream-40:   rgba(0,0,0,.42);
  --rule:       rgba(0,0,0,.16);
  --rule-soft:  rgba(0,0,0,.09);
  --accent:     var(--blue-ink);
}
.sheet__panel{
  background:var(--white); color:var(--black);
  border:1px solid var(--rule); border-radius:var(--r-lg);
  /* No shadow while it is parked. The panel closes to just below the fold, so
     a shadow thrown 30px up with a 70px blur still reached about 100px into
     the page -- a soft grey smudge sitting under the last section on every
     page, whether or not anyone ever opened the sheet. */
  box-shadow:none;
  padding:14px clamp(20px,5vw,28px) clamp(18px,3vh,24px);
  transform:translateY(calc(100% + var(--float)));
  transition:transform .55s var(--ease);
  pointer-events:auto;
}
/* Only the panel that was asked for slides up. The body class still dims the
   page, but with three sheets sharing it, .is-on is what picks one. */
.sheet.is-on .sheet__panel{
  transform:none;
  box-shadow:0 -30px 70px rgba(0,0,0,.6);
}
.sheet__grab{
  display:block; width:38px; height:4px; border-radius:2px;
  background:rgba(0,0,0,.18); margin:0 auto 16px;
}
.sheet__lbl{ margin-bottom:4px; }
.sheetnav{ display:flex; flex-direction:column; }
.sheetnav .dl{ border-bottom:1px solid var(--rule-soft); font-size:clamp(24px,6.6vw,32px); }
.sheetnav .dl:last-of-type{ border-bottom:0; }
.sheet__cancel{
  width:100%; min-height:var(--btn-h); margin-top:14px;
  border:1px solid var(--rule); border-radius:var(--r-pill);
  font-family:var(--label); font-size:11px;
  letter-spacing:.18em; text-transform:uppercase;
  color:rgba(0,0,0,.55);
  transition:border-color .3s ease, color .3s ease;
}
.sheet__cancel:hover{ border-color:var(--black); color:var(--black); }


/* =========================================================
   EDGE NORMALISATION — sections own the rhythm.
   Row lists (events, ages) keep uniform padding on purpose:
   every row must be the same height.
   ========================================================= */


/* Events used to carry double the standard gap beneath it, which left a
   visible hole under the last row. It now closes on the same --sec-y as
   every other section. */

/* Find Us used to close on a doubled gap; every section now shares one
   rhythm, so it uses --sec-y like the rest. */
/* The doubled section gap this paired with is gone, so the extra margin only
   left 26px of dead space at the bottom of the section. */
.find__media{ grid-area:media; }


/* The list's own rules are its visual edges, so every cell keeps its padding
   — the first heading and the last line must not sit flush against them. */




/* =========================================================
   HERO STATEMENT — matches the video width, static, no rules
   ========================================================= */
.statement{
  margin-top:clamp(20px,2.6vw,34px);
  font-family:var(--display);
  font-weight:var(--w-black);
  font-size:clamp(21px,3.3vw,50px);
  line-height:1.06;
  letter-spacing:-.022em;
  text-transform:uppercase;
  text-wrap:balance;
}

/* =========================================================
   MOBILE — wider gutters, tighter rhythm, display type scaled
   so type/button/image ratios track desktop.
   ========================================================= */





/* =========================================================
   FOOTER BASE
   Desktop: logo left, with legal / phone / email / address
   stacked and right-aligned beside it.
   Mobile:  logo left with phone + email opposite, then address
   and copyright below as fine print.
   ========================================================= */
.ft__base{
  display:grid;
  align-items:center;
  padding-top:clamp(40px,6vh,64px);

  grid-template-columns:auto 1fr;
  /* The logo spans both rows rather than sitting only in the first. In the
     first arrangement it was taller than the phone/email line, so it set row
     one's height and pushed the copyright 54px clear of the line it belongs
     to. Spanning lets each row size to its own text, so the gap below the
     contact line is exactly the row gap. */
  grid-template-areas:"logo contact" "logo legal";
  row-gap:var(--ft-line);
  column-gap:clamp(20px,4vw,48px);
}
/* =========================================================
   SOCIAL — one row of icons, footer and side menu
   ========================================================= */
.social{ display:flex; align-items:center; gap:clamp(14px,1.6vw,22px); }
.social a,
.social button{
  display:inline-flex; color:var(--cream-55); cursor:pointer;
  padding:0; border:0; background:none;
  transition:color .25s ease, transform .25s var(--ease);
}
.social a:hover,
.social button:hover{ color:var(--cream); transform:translateY(-1px); }
.social a:focus-visible,
.social button:focus-visible{ outline:2px solid var(--accent); outline-offset:4px; border-radius:4px; }
/* .ico is display:block site-wide and sized in em elsewhere; these want a
   fixed size so the four read as one set whatever they sit beside. */
.social .ico{ width:19px; height:19px; }

/* The footer grid is areas-based, so the row needs naming to land under the
   contact line rather than being dropped into the next implicit cell. */
.ft__base{ grid-template-areas:"logo social" "logo contact" "logo legal"; }
/* Right-aligned like the contact and copyright lines it sits between --
   left-aligned it read as attached to the logo rather than to them. */
.ft__social{ grid-area:social; justify-self:end; padding-block:3px; }
.drawer__social{ padding-top:2px; }

.ft__logo{ grid-area:logo; align-self:center;
            width:clamp(96px,9vw,124px); display:block; }
.ft__logo img{ width:100%; height:auto; display:block; }

/* With the address gone, the contact line is the only thing that pairs with
   the logo. display:contents dissolves this wrapper so the phone/email line
   and the copyright become grid items in their own right — the contact line
   can then centre on the logo exactly, instead of the pair of lines centring
   as a block and leaving it sitting high. */
.ft__lines{ display:contents; }
.ft__contact{
  /* Phone and email share one line, centred against the logo. */
  grid-area:contact; justify-self:end; align-self:end; text-align:right;
  display:flex; flex-wrap:wrap; justify-content:flex-end;
  gap:4px clamp(14px,2vw,26px);
  color:var(--cream-70);
}
.ft__contact a{ transition:color .25s ease; }
.ft__contact a:hover{ color:var(--cream); }

/* Sits beneath both the logo and the contact line, still clearly fine print. */
.ft__legal{
  grid-area:legal; justify-self:end; align-self:start; text-align:right;
  font-size:9px; letter-spacing:.14em; line-height:1.35;
  color:rgba(255,255,255,.34);
}



/* =========================================================
   FLOATING PANELS — vertical rhythm
   A light panel paints over its own padding, so its border-box
   edge is the visible boundary and only the neighbour's padding
   separated them: 73px against 146px between two dark sections.
   Matching margin makes every visible gap equal.
   ========================================================= */
.sec--cream{
  background:var(--cream); color:var(--ink-on-cream);
  margin-inline:var(--float);
  border-radius:var(--r-lg);
  padding-inline:max(calc(var(--pad) - var(--float)), (100% - var(--maxw)) / 2);
  /* A panel paints over its own padding, so its rounded edge -- not its text --
     is what the eye reads as the start of the section. Without this margin the
     visible dark void beside a panel was 114px while the void between two dark
     sections was 228px. The margin pushes the edge out to a full --sec-y, so
     every gap you can actually see is 228px. */
  margin-block:var(--sec-y);}


/* =========================================================
   MOBILE FOOTER DETAIL
   Must come after the FOOTER BASE block above — those rules
   share this specificity and would otherwise win on order.
   Each detail line has to fit without wrapping: the .18em
   tracking is what forces the wraps, so it tightens here and
   the logo gives back the width.
   ========================================================= */


/* =========================================================
   BREAKPOINTS
   Every media query lives below every base rule, so a later
   base declaration can never silently beat an override here.
   ========================================================= */
@media (prefers-reduced-motion: reduce){ html{ scroll-behavior:auto; } }
@keyframes focusIn{
  0%   { opacity:0; filter:blur(22px); transform:scale(1.05); }
  50%{ opacity:1; filter:blur(0);    transform:scale(1); }
  /* soft pulse out of and back into focus before the panel clears */
  68%{ filter:blur(5px);  transform:scale(1.012); }
  84%{ filter:blur(0);    transform:scale(1); }
  92%{ filter:blur(2.5px); transform:scale(1.006); }
  100%{ filter:blur(0);    transform:scale(1); }
}
@media (min-width:560px){
  .hdr__mark{ display:none; }
  .hdr__lockup{ display:block; }
}
@keyframes pulse{ 0%,100%{ opacity:1; } 50%{ opacity:.3; } }
/* Phones: half the desktop rhythm, still one token driving every section. */
@media (max-width:640px){ :root{ --sec-y: 72px; } }
@media (max-width:640px){ .media__frame{ aspect-ratio:4/5; } }
@media (min-width:900px){ .map{ aspect-ratio:4/3; } }
@media (min-width:560px){
  
  .ev a{
    grid-template-columns:minmax(130px,.9fr) 3fr minmax(90px,auto) auto;
    grid-template-areas:"date name time go";
    gap:24px;
  }
  
  
}
@media (min-width:760px){
  .path{ grid-template-columns:repeat(2,1fr); }
  .path .pcard:last-child{ grid-column:span 2; } /* 5 cards, 2 cols — no orphan cell */
  .path .pcard:first-child{ border-radius:var(--r-md) 0 0 0; }
  .path .pcard:nth-child(2){ border-radius:0 var(--r-md) 0 0; }
  .path .pcard:last-child{ border-radius:0 0 var(--r-md) var(--r-md); }
  .expect{ grid-template-columns:repeat(2,1fr); column-gap:clamp(24px,4vw,64px); }
  .xp:nth-child(-n+2){ border-top:0; }
  
  
  
  
  .sec__head{
    grid-template-columns:minmax(200px,1fr) minmax(0,2fr);
    align-items:start; column-gap:clamp(24px,4vw,72px);
  }
  .sec__head .lbl{ grid-row:1; }
  .sec__head .h2{ grid-column:2; grid-row:1; }
  .sec__head .sec__lede{ grid-column:2; }
  .sec__head .btn{ grid-column:2; }
  /* Buttons live in the same column as the heading and copy, not out under
     the little label. Wrapped in .sec__btns they need placing as a unit. */
  /* Direct children only. As a descendant selector this also caught a
     .sec__btns nested inside a .prose -- .prose is itself a grid, so the
     buttons were thrown into a second column that does not exist and landed
     on top of the copy instead of under it. */
  .sec__head > .sec__btns{ grid-column:2; }
  /* Any block dropped into a section head belongs in the copy column too. */
  .sec__head .hlist,
  .sec__head .subs__row,
  .sec__head .prose,
  .sec__head .expect{ grid-column:2; }
  .sec__head .evfilter{ grid-column:2; }
  /* Body content that should line up under the heading rather than the label
     borrows the head's exact column geometry. */
  .sec__body{
    display:grid;
    grid-template-columns:minmax(200px,1fr) minmax(0,2fr);
    column-gap:clamp(24px,4vw,72px);
  }
  .sec__body > *{ grid-column:2; }
  .find{
    grid-template-columns:1fr 1fr;
    grid-template-areas:
      "label   media"
      "addr    media"
      "actions media";
    column-gap:clamp(28px,4vw,64px);
    row-gap:clamp(16px,2.4vh,26px);
    align-content:center;
  }
  .find__media{ grid-row:1 / -1; }
}
@media (min-width:1024px){
  .hdr__inline{ display:flex; }
  .path{ grid-template-columns:repeat(5,1fr); }
  .path .pcard:last-child{ grid-column:auto; }
  /* One row now, so the caps are on the ends rather than top and bottom. */
  .path .pcard:first-child{ border-radius:var(--r-md) 0 0 var(--r-md); }
  .path .pcard:nth-child(2){ border-radius:0; }
  .path .pcard:last-child{ border-radius:0 var(--r-md) var(--r-md) 0; }
  /* The column count follows the number of items, so a list never leaves an
     empty cell at the end. Four across only when there are four (or eight). */
  .expect{ grid-template-columns:repeat(4,1fr); }
  .expect:has(> .xp:nth-child(2):last-child){ grid-template-columns:repeat(2,1fr); }
  .expect:has(> .xp:nth-child(3):last-child){ grid-template-columns:repeat(3,1fr); }
  .expect:has(> .xp:nth-child(4):last-child){ grid-template-columns:repeat(2,1fr); }
  .expect:has(> .xp:nth-child(6):last-child){ grid-template-columns:repeat(3,1fr); }
  /* Five will not divide into equal columns without a hole, so the tracks go
     to six and the items span them: three across, then two across, both rows
     full width. */
  .expect:has(> .xp:nth-child(5):last-child){ grid-template-columns:repeat(6,1fr); }
  .expect:has(> .xp:nth-child(5):last-child) > .xp{ grid-column:span 2; }
  .expect:has(> .xp:nth-child(5):last-child) > .xp:nth-child(4),
  .expect:has(> .xp:nth-child(5):last-child) > .xp:nth-child(5){ grid-column:span 3; }
  /* Rows need their own divider once the list wraps onto more than one. */
  .expect:has(> .xp:nth-child(5)) .xp{ border-top:1px solid var(--rule-soft); }
  .sec--cream .expect:has(> .xp:nth-child(5)) .xp{ border-top-color:rgba(0,0,0,.08); }
  .xp{ border-top:0; }
  
  
  
  .hero__bar{ flex-wrap:nowrap; }
}
@media (min-width:1900px){
  /* --sec-y is deliberately not raised here: one rhythm at every width. */
  /* Wide viewports get more air between the label rail and the headline */
  .sec__head{ column-gap:clamp(48px,5vw,120px); }
}
@media (min-width:2400px){
  :root{ --maxw:1840px; }
  body{ font-size:18px; }
}
@media (hover:none){
  .ev a:hover{ padding-left:0; padding-right:0; background:none; }
  
  
}
@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
  }
  .reveal{ opacity:1; transform:none; }
  .line__i{ transform:none; }
  .loader{ display:none; }
}
@media (min-width:760px){ .ft__cols{ grid-template-columns:repeat(4,1fr); } }
@media (max-width:640px){ .secfig img{ aspect-ratio:3/2; } }
@media (min-width:860px){ .msg{ grid-template-columns:1.1fr 1fr; } }
@media (max-width:640px){ .find__media{ margin-bottom:0; } }
@media (max-width:640px){
  /* Hero must be content-sized: with min-height:100svh the leftover
     viewport space pooled below the statement and the gap drifted. */
  .hero{ min-height:0; }

  :root{
    --pad:26px;
    --float:14px;
    --btn-h:44px;    /* All Events button height — the single control size */
    --mark-h:30px;
    --hero-gap:calc(min(13.2vw, 208px) * .45);  /* .45em of the headline */
  }

  .h2{ font-size:clamp(44px,11.5vw,60px); }
  .cta__q{ font-size:clamp(40px,10.5vw,56px); }
  .ev__name{ font-size:clamp(36px,9.5vw,48px); }   /* same as .msg__h */
  .agebtn{ font-size:clamp(36px,9.5vw,48px); }     /* same as .msg__h */
  .xp h3, .pcard h3{ font-size:clamp(25px,6.4vw,32px); }
  .msg__h{ font-size:clamp(36px,9.5vw,48px); }

  .btn{ padding:0 19px; font-size:13.5px; }
  .btn--lg{ min-height:var(--btn-h); padding:0 20px; font-size:13.5px; }

  .media--hero .media__frame{ aspect-ratio:3/4; }
  .pcard__img{ aspect-ratio:16/10; }
  .agebtn__img{ width:60px; }
  .map{ aspect-ratio:4/3; }

  .sec__head{ gap:14px; }

  .hero{ padding-top:calc(var(--pad) + 68px); }
  /* One value drives the gap above the buttons (headline margin) and the
     gap below them, so the pair stays symmetric. Derived from the headline
     size — .hero__bar can't use em, its own font-size is body copy. */
  .hero__h1{ margin-bottom:var(--hero-gap); }
  /* The buttons carry their own 12px top margin, so mirror it below them and
     take the 1px rule off the bar's padding — above and below then match.
     Both halves are then halved again, so the rule sits closer to the
     buttons above it and to the video below it. */
  .hero__ctas{ margin-bottom:6px; }
  .hero__bar{ padding-bottom:calc((var(--hero-gap) - 1px) / 2); }
  .media--hero{ margin-top:calc(var(--gap-sep) / 4); }

  /* Two categories across on phones. Each category is now half-width, so its
     links go back to a single column -- two columns inside a half-width column
     wrapped almost every label. */
  .ft__cols{ grid-template-columns:1fr 1fr; gap:0 20px; padding:0 0 8px;
             align-items:start; }
  .ft__col{ padding-bottom:26px; }
  .ft__h{ font-size:16px; padding-bottom:11px; margin-bottom:13px; }
  .ft__col ul{ grid-template-columns:1fr; gap:10px; }
  .ft__col a{ font-size:14.5px; }


  /* CTA rhythm: the space above and below the rule is matched, and on phones
     it is half what it was -- a quarter of --sec-y rather than a half. */
  .cta__b{
    margin-top:calc(var(--sec-y) / 4);
    padding-top:calc(var(--sec-y) / 4);
  }

  /* Directions behave identically at every width — see the base rules. */
  body.is-sheet [data-sheet]{ border-color:var(--cream); }
}
@media (hover:none){
  .agebtn:hover{ padding-left:0; padding-right:0; background:none; }
  .pcard:hover .pcard__img{ transform:none; }
}
@media (prefers-reduced-motion: reduce){
  .drawer__panel, .sheet__panel{ transition:none; }
  .dnav .dl, .dsub, .dfoot{ opacity:1; transform:none; }
}
@media (max-width:640px){
  .ft__base{
    grid-template-areas:"logo social" "logo contact" "logo legal";
    align-items:center;
    --ft-line:7px;        /* tighter still at this size */
  }

  /* Find Us stacks — image leads, address follows. */


}
@media (max-width:640px){
  .ft__logo{ width:72px; }
  .social{ gap:16px; }
  .social .ico{ width:17px; height:17px; }
  .ft__contact{ gap:3px 12px; }
  .ft__contact{ font-size:9.5px; letter-spacing:.05em; }
  .ft__legal{ font-size:8px; letter-spacing:.06em; }   /* the row gap spaces it now */
}


/* =========================================================
   SUBPAGE SYSTEM
   Shared shell for every interior page. Reuses the homepage
   tokens (--sec-y, --gap-in, --btn-h, --maxw) so nothing
   drifts. Breakpoint overrides live in the block at the end.
   ========================================================= */

/* --- Page hero. The title block sits on the page's own black and the
       image follows as a contained panel — the same shape language as the
       homepage hero. Nothing overlays the artwork, so images carrying their
       own type stay legible. --- */
.phero{
  /* Closes on --sec-y like every other section so the gap below it matches. */
  padding:calc(var(--pad) + 96px) var(--pad) var(--sec-y);
  display:grid;
  gap:var(--gap-in);
}
/* Pulls the section below up to two thirds of the standard gap: the hero's
   own closing padding drops to a third of --sec-y, and the next section still
   opens on a full one. Has to sit after .phero -- same specificity, and the
   padding shorthand above would otherwise win. Used where a page reads as one
   block rather than two: Our Team, where the buttons lead into the faces. */
.phero--tight{ padding-bottom:calc(var(--sec-y) / 3); }
.phero__inner{ display:grid; gap:clamp(12px,2vh,20px); justify-items:start; }
.phero__lede{
  max-width:56ch; color:var(--cream-70);
  font-size:clamp(16px,.7vw + 14px,20px); line-height:1.5;
}
.phero__media{
  position:relative;
  aspect-ratio:21/9;              /* height reserved before the image decodes */
  border-radius:var(--r-md);
  overflow:hidden;
  background:var(--ink-2);
}
.phero__img{
  position:absolute; inset:0;
  width:100%; height:100%; object-fit:cover;
}

/* --- Prose block for body copy on interior pages --- */
.prose{ display:grid; gap:var(--gap-in); max-width:70ch; }
.prose p{ color:var(--cream-70); font-size:clamp(16px,.5vw + 14px,18px); line-height:1.6; }
.sec--cream .prose p{ color:var(--ink-on-cream-65); }
.prose h3{
  font-family:var(--display); font-weight:var(--w-black);
  font-size:clamp(22px,2.4vw,34px); letter-spacing:-.02em; text-transform:uppercase;
}

/* --- FAQ --- */
.faq{ border-top:1px solid var(--rule); }
.faq__item{ border-bottom:1px solid var(--rule); }
.sec--cream .faq{ border-top-color:var(--rule-on-cream); }
.sec--cream .faq__item{ border-bottom-color:var(--rule-on-cream); }
.faq__q{
  width:100%; text-align:left;
  display:flex; align-items:baseline; justify-content:space-between; gap:20px;
  padding:calc(var(--gap-in) / 2) 0;
  font-family:var(--display); font-weight:var(--w-black);
  font-size:clamp(19px,1.9vw,26px); letter-spacing:-.02em;
  color:var(--cream);
}
.sec--cream .faq__q{ color:var(--ink-on-cream); }
/* Same two-bar construction as the drawer's close control, so a + and an x
   are the one icon language across the site. */
.faqx{ position:relative; display:block; width:15px; height:15px; flex:none; }
.faqx i{
  position:absolute; top:50%; left:0;
  width:100%; height:1.6px; border-radius:2px;
  background:currentColor;
  transition:transform .4s var(--ease);
}
.faqx i:nth-child(1){ transform:translateY(-50%); }
.faqx i:nth-child(2){ transform:translateY(-50%) rotate(90deg); }
.faq__item.is-open .faqx i:nth-child(1){ transform:translateY(-50%) rotate(45deg); }
.faq__item.is-open .faqx i:nth-child(2){ transform:translateY(-50%) rotate(-45deg); }
.faq__a{
  display:grid; grid-template-rows:0fr;
  transition:grid-template-rows .45s var(--ease);
}
.faq__item.is-open .faq__a{ grid-template-rows:1fr; }
.faq__a > div{ overflow:hidden; }
.faq__a p{
  padding-bottom:calc(var(--gap-in) / 2);
  color:var(--cream-70); max-width:62ch;
  font-size:clamp(15px,.4vw + 14px,17px); line-height:1.6;
}
.sec--cream .faq__a p{ color:var(--ink-on-cream-65); }
/* Scripture references under a belief. .faq__a p sets the answer's body size,
   which outranks .mono on its own, so the references were rendering at 17px --
   larger-looking than the text they belong to, once the caps and .18em
   tracking are counted. Back to the label size, and quieter. */
.faq__a p.mono{
  font-size:clamp(10px,.28vw + 9.1px,12px);
  letter-spacing:.12em; line-height:1.6;
  color:var(--cream-40); max-width:none;
}
.sec--cream .faq__a p.mono{ color:var(--ink-on-cream-45, rgba(0,0,0,.45)); }

/* --- Card grid: events, messages, ministries. Fixed ratios so
       nothing varies in size. --- */
.cards{ display:grid; grid-template-columns:1fr; gap:clamp(20px,2.4vw,32px); }
/* A class that sets `display` outranks the hidden attribute's UA rule, so a
   card marked hidden by the search kept right on showing — the count said
   "14 of 211" while all 211 stayed on screen. This makes hidden mean hidden,
   for every element on the site that uses the attribute. */
[hidden]{ display:none !important; }
.card{ display:flex; flex-direction:column; }
.card__media{
  position:relative; width:100%;
  aspect-ratio:16/9;                  /* one ratio everywhere */
  border-radius:var(--r-md); overflow:hidden;
  background:var(--ink-2);
}
.card__media img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
/* The card is a flex column and the body stretches, so pushing the actions
   down with auto margin lands every Watch/Listen pair on the same line across
   a row, whatever length the description happens to be. */
.card{ height:100%; }
/* Flex, not grid: margin-top:auto on the actions only absorbs leftover space
   in a flex column. In a grid the rows pack to the top and the buttons stay
   wherever the copy ends, so they never lined up across a row. */
.card__body{ display:flex; flex-direction:column; gap:7px;
             padding-top:clamp(14px,1.6vw,18px); flex:1; }
.card__meta{ color:var(--cream-55); }
.sec--cream .card__meta{ color:var(--ink-on-cream-65); }
.card__title{
  font-family:var(--display); font-weight:var(--w-black);
  font-size:clamp(20px,1.9vw,27px); letter-spacing:-.02em;
  line-height:1.08; text-transform:uppercase;
}
.card__text{ color:var(--cream-70); font-size:15px; line-height:1.5; }
.sec--cream .card__text{ color:var(--ink-on-cream-65); }
.card__actions{ display:flex; flex-wrap:wrap; gap:8px; padding-top:8px;
                 padding-bottom:clamp(18px,2vw,26px); margin-top:auto; }

/* --- Team: vertical portrait cards, tall enough not to crop faces --- */
.team{ display:grid; grid-template-columns:1fr; gap:clamp(22px,2.6vw,36px); }
.tcard__img{
  width:100%; aspect-ratio:3/4;        /* vertical card, as designed */
  object-fit:cover; object-position:center 22%;
  border-radius:var(--r-md); background:var(--ink-2);
}
.tcard__name{
  font-family:var(--display); font-weight:var(--w-black);
  font-size:clamp(17px,1.4vw,21px); letter-spacing:-.015em;
  /* Was inheriting body leading at 1.55, which on a display face left far more
     air under the name than the title carries between its own two lines.
     The negative margin cancels what the line box still leaves under the
     glyphs -- half-leading plus the descender. The figure is measured off the
     rendered page rather than derived from font metrics, because the metrics
     canvas reports for this face do not match what the browser lays out. In
     em, not px: the name is clamp(17px,1.4vw,21px), so a
     fixed pixel figure is only ever right at one window width, and it was
     tuned at 17px while a wide window renders 21px. */
  line-height:1.13; margin-bottom:-.327em;
  text-transform:uppercase; padding-top:14px;
}
/* With the space under the name cancelled above, this padding is the whole
   gap. A hard px is right here and matches how the rest of these cards are
   built (the name's own 14px above it, the old 4px here): the type scales but
   the gap between two lines should not, and the em on .tcard__name is what
   keeps this honest at every width. */
.tcard__role{ color:var(--cream-55); padding-top:9px; }
.sec--cream .tcard__role{ color:var(--ink-on-cream-65); }

/* --- Team: tap to copy an address ---------------------------------------
   mailto: is unreliable on a phone, so the address is copied to the clipboard
   instead. Hovering the control blurs the role away and blurs the address in
   over the top of it: the two sit in the same grid cell, so the swap costs no
   height and the card never reflows. Tapping holds the address for three
   seconds, which is what a touch screen needs -- it has no hover to give. */
/* The address sits beside the control, in the control's own type so the two
   read as one line, and blurs in on hover. It is always in flow at opacity 0,
   so showing it shifts nothing -- the row is already the width it will be. */
.tcard__addr{
  opacity:0; filter:blur(6px); color:var(--cream);
  /* Tighter than the label's .07em: the longest address is 25 characters and
     there are only ~173px beside the button, which .07em overruns. This fits
     every one on a single line with room to spare. Wrapping is deliberately
     left enabled rather than nowrap -- if a machine's font metrics run wider
     than the ones measured here, a second line is contained inside the card
     whereas nowrap would spill the address out of it. */
  font-family:var(--label); font-size:10px; letter-spacing:.01em;
  line-height:1.3; text-transform:uppercase;
  min-width:0; overflow-wrap:anywhere;
  transition:opacity .3s var(--ease), filter .3s var(--ease);
}
.sec--cream .tcard__addr{ color:var(--ink-on-cream); }

.tcard:has(.tcard__mail:hover) .tcard__addr,
.tcard:has(.tcard__mail:focus-visible) .tcard__addr,
.tcard.is-copied .tcard__addr{ opacity:1; filter:blur(0); }

/* Back under the role. padding-top is 7px rather than the role's own 4px
   because the role's padding sits above a line box that brings its own
   leading and this label, trimmed to line-height:1, brings none -- 7.6px
   against the role's 9px is what makes the gap the eye sees match the one
   between name and role.
   flex, not block: as a block the row laid out a text line at body leading
   and sat the button on its baseline, ~10px below where the padding put it. */
.tcard__mailrow{
  display:flex; align-items:baseline; gap:7px;
  padding-top:7.6px;
}
.tcard__mail{
  display:inline-flex; align-items:center; gap:6px;
  padding:0; border:0; background:none; cursor:pointer;
  font-family:var(--label); font-size:10px; letter-spacing:.07em;
  text-transform:uppercase; color:var(--cream-55);
  /* Body leading above a 10px label added ~9px of its own, which is what put
     the control twice as far below the role as the role sits below the name.
     Trimmed to the glyphs so the 4px padding is the whole gap. */
  line-height:1;
  transition:color .25s ease;
}
.tcard__mail:hover{ color:var(--cream); }
.tcard__mail:focus-visible{ outline:2px solid var(--accent); outline-offset:3px; }
.sec--cream .tcard__mail{ color:var(--ink-on-cream-65); }
.sec--cream .tcard__mail:hover{ color:var(--ink-on-cream); }
.tcard__mail .ico{ display:block; width:10px; height:10px; }

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

/* --- Simple two-column split used across interior pages --- */
.split{ display:grid; grid-template-columns:1fr; gap:var(--gap-in); align-items:center; }
.split__media img{ width:100%; aspect-ratio:4/3; object-fit:cover; border-radius:var(--r-md); }

@media (min-width:760px){
  .cards{ grid-template-columns:repeat(2,1fr); }
  .team{ grid-template-columns:repeat(3,1fr); }
  .split{ grid-template-columns:1fr 1fr; gap:clamp(28px,4vw,64px); }
}
@media (min-width:1024px){
  .cards{ grid-template-columns:repeat(3,1fr); }
  .team{ grid-template-columns:repeat(4,1fr); }
  /* Eight items go two across and then four, never three, so the last row is
     never left holding a single card against an empty cell. */
  .cards--4{ grid-template-columns:repeat(2,1fr); }
}
@media (min-width:1280px){
  .cards--4{ grid-template-columns:repeat(4,1fr); }
}
@media (max-width:640px){
  .phero{ padding-top:calc(var(--pad) + 84px); }
  .phero__media{ aspect-ratio:4/3; }
  .team{ grid-template-columns:repeat(2,1fr); }
  .cards{ gap:26px; }
}


/* =========================================================
   PAGE TRANSITIONS
   The page resolves out of blur on arrival and defocuses on
   the way out, so navigation reads as one continuous move.
   Both states are applied by JS, so with scripting off the
   content simply renders sharp — never hidden.
   ========================================================= */
html.is-entering .hdr,
html.is-entering main,
html.is-entering .ft{
  filter:blur(16px);
  opacity:0;
}
html.is-leaving .hdr,
html.is-leaving main,
html.is-leaving .ft{
  filter:blur(16px);
  opacity:0;
  transition:filter .34s var(--ease), opacity .3s ease;
}
@media (prefers-reduced-motion: reduce){
  html.is-entering .hdr, html.is-entering main, html.is-entering .ft,
  html.is-leaving  .hdr, html.is-leaving  main, html.is-leaving  .ft{
    filter:none; opacity:1;
  }
}


/* =========================================================
   MESSAGE HERO — never crop the artwork
   Message thumbnails carry titles and faces, so the panel
   matches their native 16:9 and the image is contained
   rather than cropped. A different ratio letterboxes onto
   the panel's own background instead of losing edges.
   ========================================================= */
.phero__media--wide{ aspect-ratio:16/9; }
.phero__media--wide .phero__img{ object-fit:contain; }

/* =========================================================
   TEAM — focus animation
   Portraits resolve out of blur as they scroll in, staggered
   across the row. Hovering one sharpens it and eases the
   others back, so the grid reads as a rack of lenses coming
   into focus rather than a static wall of headshots.
   ========================================================= */
.tcard__img{
  transition:transform .7s var(--ease), filter .7s var(--ease), opacity .5s ease;
  will-change:filter, transform;
}

/* enter: blurred and slightly back, then settles */
.tcard.reveal .tcard__img{ filter:blur(14px); transform:scale(1.06); }
.tcard.reveal.in .tcard__img{ filter:blur(0); transform:none; }

/* stagger across each row */
.tcard.reveal.in:nth-child(4n+1) .tcard__img{ transition-delay:0s; }
.tcard.reveal.in:nth-child(4n+2) .tcard__img{ transition-delay:.09s; }
.tcard.reveal.in:nth-child(4n+3) .tcard__img{ transition-delay:.18s; }
.tcard.reveal.in:nth-child(4n+4) .tcard__img{ transition-delay:.27s; }

/* hover: dock-style magnify. The whole card — portrait, name and role —
   scales together from its own centre, so it grows in place rather than
   lifting or shifting. A slight overshoot on the curve gives it the springy
   feel of the macOS dock. z-index keeps the grown card above its neighbours. */
.tcard{
  position:relative;
  transform-origin:center center;
  transition:transform .45s cubic-bezier(.34,1.4,.64,1), z-index 0s;
}
/* :has(:focus-visible), not :focus-within -- clicking the copy button left the
   card focused, so it stayed magnified after the pointer had gone and never
   zoomed back out. A mouse click does not match :focus-visible, so the card
   now shrinks on mouse-out as it should, while keyboard focus still holds it
   open for anyone tabbing through. */
.tcard.in:hover,
.tcard.in:has(:focus-visible){
  transform:scale(1.09);
  z-index:2;
}

@media (hover:none){
  .tcard.in:hover{ transform:none; }
}
@media (prefers-reduced-motion: reduce){
  .tcard.reveal .tcard__img{ filter:none; transform:none; }
  .tcard.in:hover, .tcard.in:has(:focus-visible){ transform:none; }
}

/* =========================================================
   CONTACT FORM
   Same vocabulary as the rest of the site: mono uppercase labels, hairline
   rules, a solid button. No rounded boxes — the section already has them.
   ========================================================= */
.form{ display:grid; gap:var(--gap-in); max-width:760px; }
.form__row{ display:grid; gap:var(--gap-in); grid-template-columns:1fr; }
.field{ display:grid; gap:8px; min-width:0; }
.field .lbl{ color:var(--ink-on-cream-65); }
.field em{ font-style:normal; opacity:.6; }

.input{
  width:100%; font:inherit; font-size:16px;   /* 16px: smaller zooms iOS in */
  color:var(--ink-on-cream);
  background:transparent; border:0;
  border-bottom:1px solid var(--rule-on-cream);
  border-radius:0; padding:10px 2px;
  transition:border-color .25s var(--ease);
}
.input:focus{ outline:none; border-bottom-color:var(--ink-on-cream); }
textarea.input{ resize:vertical; min-height:150px; line-height:1.5; }
select.input{ appearance:none; cursor:pointer; }

/* Off-screen rather than display:none — a bot reading the DOM should still
   find it, which is the whole point of a honeypot. */
.hp{ position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden; }

.formnote{
  margin-bottom:var(--gap-in);
  padding:14px 16px; font-size:15px; line-height:1.5;
  border:1px solid var(--rule-on-cream); border-radius:var(--r-md);
  max-width:760px;
}
.formnote--ok{ color:var(--ink-on-cream); }
.formnote--err{ color:var(--ink-on-cream); border-color:var(--ink-on-cream); }
.formnote a{ text-decoration:underline; }

@media (min-width:760px){
  .form__row{ grid-template-columns:1fr 1fr; }
}

/* A hero with no image should not hold a column open for one. */
.phero--text{ grid-template-columns:1fr; }
.phero--text .phero__inner{ grid-column:1 / -1; }
/* The building shot sits under the form, full width like a section figure. */
.secfig--wide{ margin-top:0; }


/* =========================================================
   WATCH ONLINE — the promo band that opens the Messages page.
   Sits above the hero on black, so it needs its own rhythm rather than the
   standard two-column section head.
   ========================================================= */
/* One child now, so the grid gap was adding a phantom 52px below it; and the
   top clearance matches the page heroes rather than exceeding them. */
.online{ padding-top:calc(var(--pad) + 78px); }
/* Inherits the site's two-column section head — small label on the left,
   headline and description on the right — so the intro reads the same way as
   every other section rather than as a narrow one-off column. */
.online__head{ gap:clamp(14px,2vh,22px); }
/* The site's head rule places a bare .btn in column two; this button is
   wrapped, so the wrapper needs placing instead or it drops under the label. */
.online__head .sec__btns{ margin-top:var(--s-2); }
@media (min-width:760px){ .online__head .sec__btns{ grid-column:2; } }
.online .h2 em{ font-style:normal; color:inherit; }
.online__head .sec__lede{ max-width:46ch; }

/* The times are the one number people actually came for, so they get to be
   the loudest thing after the headline. */
/* Lives inside the section head, so it inherits those exact columns and can
   never drift out of line with the description above it. The rule spans only
   that column. */
.online__when{ display:grid; gap:8px; padding-top:clamp(20px,2.4vh,30px);
               border-top:1px solid var(--rule); }
@media (min-width:760px){ .online__when{ grid-column:2; } }
.online__times{
  font-family:var(--display); font-weight:var(--w-black);
  font-size:clamp(26px,4.2vw,54px); line-height:1.1; letter-spacing:-.03em;
}
.online__times{ display:flex; flex-wrap:wrap; gap:0 clamp(18px,2.4vw,40px); }
.online__times .t{ display:inline-flex; align-items:baseline; }
.online__ampm{ font-size:.44em; letter-spacing:.04em; padding-left:.06em;
               color:var(--cream-55); }

/* Three ways to watch, as equal cards — no platform ranked above another. */
.online__where{ display:grid; gap:1px; background:var(--rule);
                border:1px solid var(--rule); border-radius:var(--r-md);
                overflow:hidden; }
.wcard{
  display:flex; align-items:center; justify-content:space-between; gap:var(--s-3);
  background:var(--ink); color:var(--cream);
  padding:clamp(22px,2.6vw,32px) clamp(20px,2.4vw,30px);
  transition:background .35s var(--ease);
}
.wcard:hover{ background:#141519; }
.wcard strong{ font-family:var(--display); font-weight:var(--w-black);
               font-size:clamp(21px,2.1vw,30px); letter-spacing:-.02em;
               line-height:1.05; min-width:0; overflow-wrap:anywhere; }
.wcard__go{ flex:none; color:var(--cream-40);
            transition:transform .4s var(--ease), color .3s ease; }
.wcard__go .ico{ width:16px; height:16px; }
.wcard:hover .wcard__go{ transform:translate(2px,-2px); color:var(--cream); }


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

/* The latest message reads copy-first, so the graphic sits on the right.
   Source order keeps the image first for the stacked mobile layout. */
@media (min-width:900px){
  .msg--flip .msg__media{ order:2; }
  .msg--flip .msg__body{ order:1; }
}

/* One list, aligned under the heading rather than running the full width.
   Borrows the section head's own columns so the two can't drift apart. */
.subs__row{ margin-top:var(--s-3, 14px); }
@media (min-width:760px){ .subs__row{ grid-column:2; } }

.subs__row{ display:grid; gap:1px; background:var(--rule);
            border:1px solid var(--rule); border-radius:var(--r-md);
            overflow:hidden; }
.scard{
  display:flex; align-items:center; justify-content:space-between; gap:var(--s-3);
  background:var(--ink); color:var(--cream);
  padding:clamp(22px,2.6vw,32px) clamp(20px,2.4vw,30px);
  transition:background .35s var(--ease);
}
.scard:hover{ background:#141519; }
.scard strong{ font-family:var(--display); font-weight:var(--w-black);
               font-size:clamp(21px,2.1vw,30px); letter-spacing:-.02em;
               line-height:1.05; min-width:0; overflow-wrap:anywhere; }
.scard__go{ flex:none; color:var(--cream-40);
            transition:transform .4s var(--ease), color .3s ease; }
.scard__go .ico{ width:16px; height:16px; }
.scard:hover .scard__go{ transform:translate(2px,-2px); color:var(--cream); }
/* One per line — a list, not a row of tiles. */

/* =========================================================
   MESSAGES — subscribe links, search and paging
   ========================================================= */
.msgfind{ margin-bottom:var(--gap-in); max-width:520px; }
.msgfind .input{
  width:100%; font:inherit; font-size:16px;   /* 16px stops iOS zooming in */
  color:var(--cream); background:transparent; border:0;
  border-bottom:1px solid var(--rule); border-radius:0; padding:12px 2px;
  transition:border-color .25s var(--ease);
}
.msgfind .input::placeholder{ color:var(--cream-40); }
.msgfind .input:focus{ outline:none; border-bottom-color:var(--cream); }
/* Safari draws its own clear button on type=search; it does not belong here. */
.msgfind .input::-webkit-search-decoration,
.msgfind .input::-webkit-search-cancel-button{ -webkit-appearance:none; }

.msgnone{ color:var(--cream-55); font-size:15px; margin-bottom:var(--gap-in); }
/* Not a .link: this is an action inside a sentence, so it matches the words
   around it rather than the site's text-link style. Its own class, so .link
   keeps exactly one appearance with no exceptions. */
.textbtn{ font:inherit; color:var(--cream); border:0; background:none;
          cursor:pointer; padding:0; text-decoration:underline; }
.textbtn:hover{ text-decoration:none; }

/* Browsing is a year at a time, so the pager is the list of years rather
   than page numbers — the count beside each says what is in it. */
.pager{ display:flex; align-items:center; justify-content:center;
        /* --gap-sep is exactly two --gap-in, so this is half what it was. */
        gap:10px; flex-wrap:wrap; margin-top:var(--gap-in); }
.pager__at{ font-size:13px; color:var(--cream-55);
            font-variant-numeric:tabular-nums; }
.yearbtn{
  display:inline-flex; align-items:baseline; gap:7px; cursor:pointer;
  font-family:var(--display); font-weight:var(--w-black); font-size:15px;
  letter-spacing:.01em; font-variant-numeric:tabular-nums;
  color:var(--cream-55); background:transparent;
  border:1px solid var(--rule); border-radius:999px; padding:9px 16px;
  transition:color .25s var(--ease), border-color .25s var(--ease),
             background .25s var(--ease);
}
.yearbtn:hover{ color:var(--cream); border-color:var(--cream-40); }
.yearbtn.is-on{ color:var(--ink); background:var(--cream); border-color:var(--cream); }
.yearbtn__n{ font-size:11px; font-weight:400; opacity:.65; }


/* The Messages page used to carry its own tighter rhythm; that spacing is now
   the site default, so only its opening band needs anything special. */
.page-messages .online{ padding-top:calc(var(--pad) + 70px); }

/* =========================================================
   NEED HELP — one list of ways in
   ========================================================= */
.hlist{ display:grid; gap:1px; background:var(--rule);
        border:1px solid var(--rule); border-radius:var(--r-md);
        overflow:hidden; margin-top:var(--s-3, 14px); }
.hrow{
  display:flex; align-items:center; justify-content:space-between;
  gap:var(--s-3); background:var(--ink); color:var(--cream);
  padding:clamp(18px,2.2vw,26px) clamp(18px,2.2vw,26px);
  transition:background .35s var(--ease);
}
.hrow:hover{ background:#141519; }
.hrow__body{ display:grid; gap:5px; min-width:0; }
.hrow strong{ font-family:var(--display); font-weight:var(--w-black);
              font-size:clamp(18px,1.8vw,24px); letter-spacing:-.02em;
              line-height:1.1; text-transform:uppercase; }
.hrow__note{ font-size:14.5px; color:var(--cream-55); line-height:1.45; }
.hrow__go{ flex:none; color:var(--cream-40);
           transition:transform .4s var(--ease), color .3s ease; }
.hrow__go .ico{ width:16px; height:16px; }
.hrow:hover .hrow__go{ transform:translate(2px,-2px); color:var(--cream); }

/* A section whose only content is a button row still needs the head's grid. */
.sec__head--btns{ margin-bottom:0; }
/* The events filter sits with the heading, in the same column as the copy. */
/* The events filter. .input alone is built for the cream contact panel -- its
   ink and rule colours are the on-cream ones, so on this dark section it
   rendered black on black and the control was invisible. */
.evfilter{ display:block; position:relative; max-width:300px; }
.evfilter .input{
  max-width:300px; padding-right:30px;
  color:var(--cream); border-bottom-color:var(--rule);
}
.evfilter .input:focus{ border-bottom-color:var(--cream); }
.evfilter .input option{ color:var(--ink); background:var(--white); }
/* appearance:none removes the native caret, so one is drawn back. */
.evfilter::after{
  content:""; position:absolute; right:8px; bottom:20px; pointer-events:none;
  width:8px; height:8px; border-right:1.6px solid var(--cream-55);
  border-bottom:1.6px solid var(--cream-55); transform:rotate(45deg);
}
/* On a cream section it keeps the light treatment. */
.sec--cream .evfilter .input{ color:var(--ink-on-cream); border-bottom-color:var(--rule-on-cream); }
.sec--cream .evfilter::after{ border-color:var(--ink-on-cream-65); }

/* ---- the custom list ----
   Once script.js enhances it, the real <select> becomes the value carrier and
   this button and panel are what is seen. The field keeps the look above; only
   the option list, which the operating system draws and will not style, is
   rebuilt here. */
.selx__native{
  position:absolute; opacity:0; pointer-events:none;
  width:1px; height:1px; margin:0; padding:0; border:0;
}
.selx__btn{
  width:100%; max-width:300px; padding:10px 30px 10px 2px;
  display:flex; align-items:center; text-align:left;
  background:none; border:0; border-bottom:1px solid var(--rule);
  color:var(--cream); font:inherit; font-size:16px; cursor:pointer;
  transition:border-color .25s var(--ease);
}
.selx__btn:hover{ border-bottom-color:var(--cream-55); }
.selx__btn:focus-visible{ outline:none; border-bottom-color:var(--cream); }
.selx__val{ flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

.selx__menu{
  position:absolute; z-index:60; top:calc(100% + 6px); left:0;
  min-width:100%; max-width:300px; padding:6px;
  background:var(--ink-2); border:1px solid var(--rule);
  border-radius:var(--r-md); box-shadow:0 20px 46px rgba(0,0,0,.6);
}
.selx__opt{
  display:block; width:100%; text-align:left;
  padding:9px 11px; border:0; border-radius:7px; background:none;
  color:var(--cream-70); font:inherit; font-size:15px; cursor:pointer;
  white-space:nowrap; transition:background .2s ease, color .2s ease;
}
.selx__opt:hover{ background:rgba(255,255,255,.07); color:var(--cream); }
.selx__opt[aria-selected="true"]{ background:var(--cream); color:var(--ink); }
.selx__opt:focus-visible{ outline:2px solid var(--accent); outline-offset:-2px; }

.sec--cream .selx__btn{ color:var(--ink-on-cream); border-bottom-color:var(--rule-on-cream); }
.sec--cream .selx__menu{ background:var(--white); border-color:var(--rule-on-cream); }
.sec--cream .selx__opt{ color:var(--ink-on-cream-65); }
.sec--cream .selx__opt:hover{ background:rgba(0,0,0,.05); color:var(--ink-on-cream); }
.sec--cream .selx__opt[aria-selected="true"]{ background:var(--ink-on-cream); color:var(--white); }

@media (prefers-reduced-motion: reduce){
  .selx__opt{ transition:none; }
}
/* A button that follows a list rather than a paragraph wants more air above
   it, or it reads as belonging to the last item. */
.sec__head--pushed{ margin-top:clamp(18px,2.4vh,30px); }
/* Buttons that belong to the list above them rather than to a headline, so
   they start at the left edge instead of in the headline column. */
@media (min-width:960px){
  .sec__head--left > .sec__btns{ grid-column:1 / -1; }
}

/* ---------- Player: audio mode ---------- */
/* SoundCloud beside the message's own artwork, title and description, so
   listening happens on the site rather than in a new tab. */








@media (min-width:720px){
}


/* Section edges are governed by --sec-y alone. A stray margin on the first or
   last child would quietly widen the gap for that section only, which is what
   made a few of them measure differently from the rest. */
.sec > *:first-child,
.cta > *:first-child,
.hero > *:first-child{ margin-top:0; }
.sec > *:last-child,
.cta > *:last-child,
.hero > *:last-child{ margin-bottom:0; }


/* Card layout only. The link's own look comes from .link -- see the note
   there; nothing here may restate its size, family or tracking. */
.pcard .link{ padding-top:4px; min-height:32px; }

/* =========================================================
   PLAYER — docked strip, or the whole window
   Minimized it sits at the foot of the page and nothing behind
   it is locked, so a message keeps playing while the archive is
   browsed. Expanded it takes the window and carries the
   message's description.
   ========================================================= */
.dock{
  position:fixed; left:0; right:0; bottom:0; z-index:160;
  background:#000;                      /* the player is not a page surface */
  border-top:1px solid rgba(255,255,255,.13);
  box-shadow:0 -18px 50px rgba(0,0,0,.7);
  transform:translateY(100%);
  transition:transform .45s var(--ease);
}
body.is-docked .dock{ transform:none; }
.dock__inner{
  display:flex; align-items:center; gap:clamp(12px,1.6vw,22px);
  padding:12px clamp(16px,3vw,30px);
  max-width:var(--maxw); margin-inline:auto;
}
.dock__media{ flex:0 0 auto; display:flex; }
.dock__media img,
.dock__media iframe{
  display:block; aspect-ratio:16/9; height:92px;
  border:0; border-radius:8px; object-fit:cover; background:#000;
  transition:height .35s var(--ease);
}
.dock__media iframe{ height:112px; }

.dock__body{ flex:1 1 auto; min-width:0; display:grid; gap:5px; }
.dock__lbl{ color:var(--cream-40); }
.dock__title{
  font-family:var(--display); font-weight:var(--w-black);
  font-size:clamp(13px,1vw,15px); letter-spacing:-.01em; text-transform:uppercase;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.dock__desc{ display:none; }            /* no room for it in the strip */

/* The widget itself is never seen -- it is only the audio engine. Kept in the
   layout at 1px rather than display:none, which some browsers treat as a cue
   to stop the media. */
.dock__sc{ position:absolute; width:1px; height:1px; opacity:0; border:0;
           pointer-events:none; left:-9999px; }

.dock__tx{ display:flex; align-items:center; gap:clamp(10px,1.2vw,16px); width:100%; }
/* The body is the only thing that can grow, so the bar inside it reaches the
   controls instead of stopping short and leaving a gap before them. */
.dock__body{ flex:1 1 auto; }
.dock__play{
  flex:0 0 auto; width:34px; height:34px; border-radius:50%;
  display:inline-flex; align-items:center; justify-content:center;
  border:1px solid var(--rule); background:none; color:var(--cream); cursor:pointer;
  transition:border-color .25s ease, background .25s ease, color .25s ease;
}
.dock__play:hover{ background:var(--cream); color:var(--ink); border-color:var(--cream); }
.dock__play:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }
.dock__play .ico{ width:14px; height:14px; }
.dock__bar{
  flex:1 1 auto; height:4px; border-radius:2px; cursor:pointer;
  background:rgba(255,255,255,.16);
}
.dock__bar i{ display:block; height:100%; width:0; border-radius:2px; background:var(--cream); }
.dock__bar:focus-visible{ outline:2px solid var(--accent); outline-offset:4px; }
.dock__time{
  flex:0 0 auto; font-size:10px; letter-spacing:.05em;
  color:var(--cream-55); font-variant-numeric:tabular-nums; white-space:nowrap;
}

/* Watch / Listen are two modes of one message. The pair is offered in the
   full view only -- the strip is a transport, not a place to choose. */
/* align-items, or the buttons stretch to the row and read as ovals. */
.dock__modes{ display:none; align-items:center; gap:8px; }
.dock.is-full .dock__modes{ display:flex; }
.dock__mode{
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  height:34px; padding:0 15px;
  border:1px solid var(--rule); border-radius:var(--r-pill);
  background:none; color:var(--cream-70); cursor:pointer; white-space:nowrap;
  font-family:var(--label); font-size:10px; letter-spacing:.07em; text-transform:uppercase;
  transition:border-color .25s ease, color .25s ease, background .25s ease;
}
.dock__mode .ico{ width:10px; height:10px; }
.dock__mode{ border-color:rgba(255,255,255,.26); color:var(--cream); }
.dock__mode:hover{ border-color:var(--cream); background:rgba(255,255,255,.08); }
.dock__mode[aria-pressed="true"]{ background:var(--cream); color:var(--ink); border-color:var(--cream); }
.dock__mode:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }

.dock__foot{ flex:0 0 auto; display:flex; align-items:center; gap:clamp(10px,1.4vw,18px); }
.dock__acts{ flex:0 0 auto; display:flex; align-items:center; gap:clamp(8px,1vw,14px); }
.dock__out{
  display:none;                 /* full view only -- the strip stays a transport */
  font-family:var(--label); font-size:10px; letter-spacing:.07em;
  text-transform:uppercase; color:var(--cream-55); white-space:nowrap;
  transition:color .25s ease;
}
.dock.is-full .dock__out{ display:inline; }
.dock__out:hover{ color:var(--cream); }
.dock__btn{
  min-height:34px; padding:0 14px;
  border:1px solid var(--rule); border-radius:var(--r-pill);
  background:none; color:var(--cream-70); cursor:pointer; white-space:nowrap;
  font-family:var(--label); font-size:10px; letter-spacing:.07em; text-transform:uppercase;
  transition:border-color .25s ease, color .25s ease, background .25s ease;
}
.dock__btn:hover{ border-color:var(--cream); color:var(--cream); }
.dock__x:hover{ background:var(--cream); color:var(--ink); }
.dock__btn:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }

/* ---------- Expanded: the whole window ---------- */
.dock.is-full{
  top:0; border-top:0; background:#000;
  overflow-y:auto; overscroll-behavior:contain;
}
.dock.is-full .dock__inner{
  flex-direction:column; align-items:stretch;
  justify-content:center; min-height:100%;
  /* No shared gap: the frame and the controls want different air, so each
     carries its own. 20px above the controls is a third off the 30 they had. */
  gap:0;
  padding:clamp(20px,4vh,44px) clamp(18px,4vw,56px);
  max-width:min(1180px, 100%);
}
.dock.is-full .dock__media{ width:100%; margin-bottom:clamp(18px,3vh,30px); }
.dock.is-full .dock__media img,
.dock.is-full .dock__media iframe{
  width:100%; height:auto; aspect-ratio:16/9;
  max-height:min(62vh, 660px); border-radius:var(--r-md); margin-inline:auto;
}
/* The artwork takes the same box as the video, so switching mode moves
   nothing on the page -- only what is inside the frame. */
/* align-content, or the grid shares the leftover height out between the rows
   and every gap in here grows: the label sat 70px off its own title. Sized to
   content, the spacing below is the spacing you see. */
/* flex:0 0 auto, or the body keeps the strip's flex-grow and swallows the
   leftover height, stranding the buttons at the foot of the window. */
.dock.is-full .dock__body{ align-content:start; gap:0; flex:0 0 auto; }
/* order, not markup: the transport belongs directly under the frame here,
   while in the strip it reads as part of the title block. One element, two
   places, no second copy to keep in step. */
.dock.is-full .dock__audio{ order:-1; margin-bottom:26px; }
.dock.is-full .dock__lbl{ margin-bottom:12px; }
.dock.is-full .dock__title{ margin-bottom:10px; }   /* description rides close */
.dock.is-full .dock__desc{ margin-bottom:0; }
.dock.is-full .dock__title{
  font-size:clamp(22px,2.6vw,34px); white-space:normal; overflow:visible;
}
.dock.is-full .dock__desc{
  display:block; color:var(--cream-70);
  font-size:clamp(15px,.5vw + 13px,17px); line-height:1.6; max-width:70ch;
}
.dock.is-full .dock__foot{
  width:100%; justify-content:space-between; flex-wrap:wrap; gap:16px;
  margin-top:60px;
}
.dock.is-full .dock__acts{ margin-left:auto; flex-wrap:wrap; justify-content:flex-end; }

@media (max-width:640px){
  .dock__inner{ gap:12px; padding:10px 16px; }
  .dock__media img{ height:66px; }
  .dock__media iframe{ height:78px; }
  .dock__time{ display:none; }
  .dock__btn{ padding:0 11px; }
  .dock.is-full .dock__foot{ gap:12px; }
}
@media (prefers-reduced-motion: reduce){
  .dock{ transition:none; }
  .dock__media img, .dock__media iframe{ transition:none; }
}
