/* =========================================================
   JK Photography — Site stylesheet
   Design: "Warm Editorial"  ·  Jonah & Kayla Bolton
   Fonts: Cormorant Garamond (display) + DM Sans (UI/body), self-hosted
   Motion: enhanced by motion.dev (progressive enhancement)

   ★ PER-PROJECT THEME ★
   Four brand colors and two typefaces; everything below derives from them.

   Their photography is warm, bright and true-to-color, and the logo is a
   high-contrast serif monogram in black. So the page is ivory rather than
   white (white turns warm skin tones yellow by comparison), the ink is a warm
   espresso rather than black, and the single accent is the taupe already
   sitting in the olive sprigs of their monogram.
   ========================================================= */

/* ---- self-hosted variable fonts: latin + latin-ext, no external requests ---- */
@font-face{font-family:'Cormorant Garamond';font-style:normal;font-weight:300 700;font-display:swap;
  src:url(/assets/fonts/CormorantGaramond-normal-300-latin-e99b45.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Cormorant Garamond';font-style:normal;font-weight:300 700;font-display:swap;
  src:url(/assets/fonts/CormorantGaramond-normal-300-latin-ext-211149.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'Cormorant Garamond';font-style:italic;font-weight:300 700;font-display:swap;
  src:url(/assets/fonts/CormorantGaramond-italic-300-latin-fe99e3.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Cormorant Garamond';font-style:italic;font-weight:300 700;font-display:swap;
  src:url(/assets/fonts/CormorantGaramond-italic-300-latin-ext-0365c5.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'DM Sans';font-style:normal;font-weight:100 1000;font-display:swap;
  src:url(/assets/fonts/DMSans-normal-300-latin-b9df62.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'DM Sans';font-style:normal;font-weight:100 1000;font-display:swap;
  src:url(/assets/fonts/DMSans-normal-300-latin-ext-33d679.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}

:root{
  /* Brand palette — exactly four colors */
  --navy:#22201d;       /* Espresso — dark surface AND strongest text */
  --snow:#faf7f2;       /* Ivory                                      */
  --charcoal:#4e483f;   /* Warm slate                                 */
  --cyan:#a08a6f;       /* Taupe — the one accent                     */
  /* Semantic tokens derived only from the four above */
  /* Navy does two jobs: it is a dark surface, and it is the strongest text
     color on a light one. Compline is the one dark theme, and it remaps
     --navy to near-black so the surfaces stay right - which left every
     heading and label that used it as text invisible. Text asks for this
     token instead, so the two jobs can part company where they must. */
  --ink-strong:var(--navy);
  /* The mirror of the same problem: text that sits ON a dark surface asks
     for a light color, and in Compline the surface tokens went dark too. */
  --ink-invert:var(--paper);
  --ink-invert-soft:var(--cream);
  /* Card surfaces asked for var(--card,#fff) and nothing ever defined it, so
     they were white in every theme including the dark one. */
  --card:#fff;
  --slate:var(--charcoal);
  --paper:var(--snow);
  --cream:color-mix(in srgb,var(--navy) 4%,var(--snow));
  --cream-2:color-mix(in srgb,var(--navy) 8%,var(--snow));
  --teal:var(--cyan);
  --cyan-deep:color-mix(in srgb,var(--cyan) 60%,var(--navy));
  --bg:var(--cream);--ink:var(--navy);--ink-soft:color-mix(in srgb,var(--navy) 80%,white);
  /* 66%, not 52%. At 52% this landed on 3.20:1 against the page — below AA —
     and it is the color of every caption, date, byline and helper line on the
     site, so it was the single most-read failing thing here. 66% clears 4.9:1
     on the page and 4.7:1 on a cream panel while still reading as secondary. */
  --muted:color-mix(in srgb,var(--navy) 70%,white);--line:color-mix(in srgb,var(--navy) 14%,var(--snow));
  /* DM Sans carries the interface — nav, buttons, labels, body copy.
     Cormorant Garamond carries every heading and the italic accent words. */
  --font-display:"DM Sans",system-ui,sans-serif;   /* UI: nav, buttons, labels, h4 */
  --font-body:"DM Sans",system-ui,sans-serif;      /* body copy                    */
  --font-serif:"Cormorant Garamond",Georgia,serif;
  --font-head:"Cormorant Garamond",Georgia,serif;  /* accent: italic display serif */
  --font-accent:"Cormorant Garamond",Georgia,serif;/* headings h1–h3               */
  --space-2xs:4px;--space-xs:8px;--space-sm:12px;--space-md:16px;--space-lg:24px;--space-xl:32px;--space-2xl:48px;--space-3xl:64px;--space-4xl:96px;
  --radius:18px;--radius-sm:10px;--radius-lg:28px;
  /* The Invites card set the pair the rest of the site now follows: the card
     corner, and the corner of anything sitting inset within it. The 8px
     difference is the padding between them - concentric corners look wrong
     when the inner one is not tightened by exactly the gap. */
  --radius-card:30px;--radius-inset:22px;--maxw:1240px;
  --shadow-sm:0 1px 2px rgba(34,32,29,.07),0 2px 10px rgba(34,32,29,.05);
  --shadow-md:0 12px 36px rgba(34,32,29,.13),0 2px 8px rgba(34,32,29,.06);
  --shadow-lg:0 28px 70px rgba(34,32,29,.22);
  --ease-out:cubic-bezier(.22,1,.36,1);--ease-in-out:cubic-bezier(.65,0,.35,1);
}
*,*::before,*::after{box-sizing:border-box;}*{margin:0;}
/* Fluid base type: locked at 16px on anything ≥ ~389px wide (all normal phones,
   tablets, desktop are unchanged), then eases down to ~14px on small handsets so
   the whole rem-based UI scales to fit instead of overflowing. */
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%;text-size-adjust:100%;color-scheme:light;font-size:clamp(14px,3.6vw + 2px,16px);}

/* ---------------------------------------------------------------- dark mode
   Chosen, never assumed: the switch lives in the member's profile and this
   class is written before first paint, so the app never flashes white on the
   way to being dark.

   Only the signed-in surfaces follow it — the installed app and the members'
   area. The public pages are built on full-bleed photography and the brand
   navy, and inverting them would fight the artwork rather than help anybody.

   Defaults here are the Sanctuary dark ramp; picking a theme overrides them
   further down the file. */
html.dark{color-scheme:dark;}
html.dark body{
  /* Warm dark, not cold: the same espresso the light theme uses as ink,
     dropped to a surface, so client photographs sit on a neutral that does
     not tint them blue. */
  --navy:#1a1815;--snow:#100e0c;--charcoal:#cfc7bb;--cyan:#c2a684;
  --paper:#100e0c;--bg:#100e0c;--cream:#191612;--cream-2:#211d18;
  --ink:#f6f2ec;--ink-soft:#e2dbd1;--muted:#a89e91;
  --line:#3a342d;--cyan-deep:#c9ab86;
/* These four are derived tokens, and deriving them was the bug: --ink-strong
   is var(--navy), --ink-invert is var(--paper), and both of those move dark
   in this block. Text asking for "the strongest color" got the surface
   color and vanished. They have to be restated here, pointing the other way. */
--ink-strong:var(--ink);--ink-invert:var(--ink);--ink-invert-soft:var(--ink-soft);
/* Cards are a raised surface, so on a dark page they sit above the page
   rather than below it. Nothing defined this before and they stayed white. */
--card:#1c1915;
  --shadow-sm:0 1px 2px rgba(0,0,0,.5),0 2px 10px rgba(0,0,0,.4);
  --shadow-md:0 12px 36px rgba(0,0,0,.55),0 2px 8px rgba(0,0,0,.4);
  --shadow-lg:0 28px 70px rgba(0,0,0,.65);
  background:var(--paper);color:var(--ink);
}

/* --- dark: the components that name light and dark directly -----------------
   Most of the site colors itself from the tokens above and follows without
   being asked. What does not follow is anything that spelled out "light fill,
   dark text": both halves invert together and the thing disappears into
   itself. The fix is always the same shape - the surface and the label have
   to move in opposite directions - and the components already expose the two
   variables that decide it, so only values change here, never structure.

   Measured rather than guessed: the primary button shipped at 1.13:1 in dark
   before this block existed, which is to say the label was not there. */
html.dark body .btn{--bg:var(--ink);--fg:var(--paper);}
html.dark body .btn--light{--bg:var(--ink);--fg:var(--paper);}
html.dark body .btn--member{--bg:var(--ink);--fg:var(--paper);box-shadow:inset 0 0 0 1.5px var(--ink);}
html.dark body .btn--ghost{--bg:transparent;--fg:var(--ink);box-shadow:inset 0 0 0 1.5px color-mix(in srgb,var(--ink) 34%,transparent);}
html.dark body .btn--ondark.btn--ghost{--fg:var(--ink);box-shadow:inset 0 0 0 1.5px color-mix(in srgb,var(--ink) 40%,transparent);}
/* White on the brand cyan needs the fill darkened to clear 4.5:1, which is
   what the light theme does. On a dark page the fill can go the other way
   instead - full-strength cyan with near-black on top reads 6.8:1, and a
   bright button is the right thing on a dark page anyway. */
html.dark body .btn--accent{--bg:var(--cyan);--fg:#17120c;}

/* --- dark: the calendar ------------------------------------------------------
   The month grid colors events two ways, and both of them broke the same way.

   The six category chips are a pale tint with saturated type on it. Neither
   half is a token, so in the dark both stayed exactly as they were: bright
   blocks on a dark page. Each pair is restated here with the roles swapped -
   a deep tint of the same hue, and the type lightened to sit on it. Every one
   measures above 7.7:1; the palest of them measured 4.36:1 before.

   The chips taken from an event poster get their color inline from the
   artwork, so the tint follows the page down but the type cannot. The app
   theme already solved this one; the same answer applies here. */
html.dark body .ev-c1{background:#282118;color:#c5b49e;}
html.dark body .ev-c2{background:#312923;color:#dbcbbf;}
html.dark body .ev-c3{background:#35131f;color:#f5a6c2;}
html.dark body .ev-c4{background:#33260f;color:#e9b866;}
html.dark body .ev-c5{background:#102a19;color:#8ad6a1;}
html.dark body .ev-c6{background:#2c241d;color:#d8cabb;}
html.dark body .cal__ev--photo{color:var(--ink) !important;}
/* Today's date sits on the brand cyan. White on it measured 2.81:1 once the
   cyan brightened for the dark palette - the fill is light now, so what sits
   on it has to be dark. */
html.dark body .cal__cell.is-today .cal__num{color:#17120c;}

/* --- dark: the children's pages ---------------------------------------------
   These sections are painted a fixed coral, mint, amber or white, and the
   color is the design rather than a surface. The first attempt pinned the
   whole page to its light values so it would at least be correct - but that
   left one page glowing white in the middle of a dark site, which is its own
   kind of wrong.

   So the paints go deep instead. Every section color is a custom property and
   the waves between them take the same property through currentColor, so one
   set of values moves the panels and the joins together. Near-white type
   measures 12.9:1 or better on all four. */
html.dark .khero, html.dark .ksec, html.dark .kinvite{
  --kcoralbg:#4a1a15;
  --kmintbg:#0f3527;
  --ksunbg:#3f2f0e;
  --kplainbg:#100e0c;
  /* Body copy inside the panels is darkened for the light theme; on the deep
     ones it has to travel the other way. */
  --ink-soft:#ebe7e3;
}
html.dark .khero a:not(.btn):not(.spl),
html.dark .ksec a:not(.btn):not(.spl),
html.dark .kinvite a:not(.btn):not(.spl){
  color:#d8cab9;
  text-decoration-color:color-mix(in srgb,#d8cab9 45%,transparent);
}

html.dark .kicklabel{
  color:#faf8f6;
  background:color-mix(in srgb,var(--kc,var(--cyan)) 24%,#17130e);
  border-color:color-mix(in srgb,var(--kc,var(--cyan)) 52%,#17130e);
}
html.dark .ksec .spl{
  color:#d8cab9;
  text-decoration-color:color-mix(in srgb,#d8cab9 45%,transparent);
}

/* --- dark: the mobile menu ---------------------------------------------------
   The browser menu is a frosted sheet, and frost is built from literals: a pale
   gradient with white cards floating on it. The type on those cards asks for
   --ink-strong, which in the dark is near-white, so the menu arrived as white
   text on white cards and could not be read at all. Only the frost was wrong.

   The dots beside the folder items cycle through the brand blues, and two of
   those are navy - invisible on a dark card - so that cycle lightens too. */
html.dark:not(.app-mode) .mobmenu{
  background:linear-gradient(180deg,rgba(9,20,35,.76),rgba(4,10,18,.88));
}
html.dark .mobmenu .menu>li{background:rgba(255,255,255,.07);}
html.dark .mobmenu .dropdown li:nth-child(6n+1) a::before{background:#c9ab86;}
html.dark .mobmenu .dropdown li:nth-child(6n+2) a::before{background:#b9ada0;}
html.dark .mobmenu .dropdown li:nth-child(6n+3) a::before{background:#d9c4a8;}
html.dark .mobmenu .dropdown li:nth-child(6n+4) a::before{background:#c5b29f;}
html.dark .mobmenu .dropdown li:nth-child(6n+5) a::before{background:#b6a895;}
html.dark .mobmenu .dropdown li:nth-child(6n+6) a::before{background:#cdbdaa;}

/* Photographs and logos shouldn't be dimmed — only the chrome around them. */
html.dark img,html.dark video,html.dark .fill{filter:none;}
body{font-family:var(--font-body);background:var(--bg);color:var(--ink);line-height:1.6;font-size:1.02rem;-webkit-font-smoothing:antialiased;overflow-x:hidden;}

/* Smooth cross-page transitions (View Transitions API — auto-ignored where unsupported).
   The page content fades + lifts; the nav/footer stay put via a quick root cross-fade. */
@view-transition{navigation:auto;}
/* installed app: view transitions stay OFF (they hard-cut on iOS home-screen apps).
   Instead the app uses its own JS push: the page slides out on tap and the next
   one slides in. Transform + opacity only — fully GPU-composited, no snapshots. */
@media (display-mode: standalone),(display-mode: fullscreen){
  @view-transition{navigation:none;}
}
/* will-change was here as a compositing hint, and it cost more than it bought:
   it makes `main` a permanent containing block for fixed-position descendants,
   so anything position:fixed inside a page — the giving modal, a loader — is
   positioned against the whole scrollable page rather than the viewport. That
   put people at the bottom of the giving iframe in the installed app.

   The animation is 0.3s at page load; the browser composites it perfectly well
   without being told to, and the moment it finishes there's no transform left
   to trap anything. */
html.app-mode main{animation:appPageIn .3s var(--ae-out,cubic-bezier(.16,1,.3,1)) both;}
html.app-mode.page-exit main{animation:appPageOut .13s ease both;}
@keyframes appPageIn{from{opacity:0;transform:translateY(16px);}}
/* Was fading all the way to 0, which uncovered the white body for a beat
   before the next page painted — clearly visible going into Documents. It now
   lifts and dims only part way, so there's never a fully blank frame. */
@keyframes appPageOut{to{opacity:.55;transform:translateY(-8px);}}
/* returning to a page this session: no dashboard cascade — just the quick page slide */
html.app-revisit .appdash>*,html.app-revisit .appdash .applist__row,html.app-revisit .appdash .appms__t{animation:none !important;}
@media(prefers-reduced-motion:reduce){
  html.app-mode main,html.app-mode.page-exit main{animation:none;}
}
main{view-transition-name:page-main;}
/* The fixed chrome stays part of the root surface (no view-transition-name). A
   view-transition-name isolates an element into its own snapshot surface, and a
   backdrop-filter inside that surface has no page content to sample — which makes the
   nav's frosted blur render against nothing. Keeping it in root lets the blur work. */
::view-transition-old(root),::view-transition-new(root){animation:none;mix-blend-mode:normal;}
::view-transition-old(page-main){animation:ptOut .26s var(--ease-out) both;}
::view-transition-new(page-main){animation:ptIn .38s var(--ease-out) both;}
::view-transition-old(root),::view-transition-new(root){animation-duration:.3s;}
@keyframes ptOut{to{opacity:0;transform:translateY(-8px);}}
@keyframes ptIn{from{opacity:0;transform:translateY(14px);}}
@media(prefers-reduced-motion:reduce){
  ::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){animation:none !important;}
}
img{max-width:100%;display:block;}a{color:inherit;text-decoration:none;}button{font:inherit;cursor:pointer;}
/* h4 and below stay in the interface face — they are labels, not display. */
h1,h2,h3,h4{font-family:var(--font-display);line-height:1.2;font-weight:600;letter-spacing:-.01em;color:var(--ink);}
/* h1–h3 are the editorial voice: a light, large, high-contrast serif. Cormorant
   is drawn for display sizes, so it wants a low weight and near-zero tracking —
   the grotesk's 800/-.02em would tighten it into a smear. */
h1,h2,h3{font-family:var(--font-accent);font-weight:300;letter-spacing:-.012em;line-height:1.04;}
/* …and the accent words in the same family, italic */
.serif{font-family:var(--font-head);font-weight:400;font-style:italic;
  font-size:1.02em;letter-spacing:0;color:var(--cyan-deep);}
.eyebrow{font-family:var(--font-body);text-transform:uppercase;letter-spacing:.26em;font-size:.66rem;font-weight:500;color:var(--cyan-deep);}
.wrap{width:100%;max-width:var(--maxw);margin-inline:auto;padding-inline:clamp(20px,5vw,52px);}
.section{padding-block:clamp(48px,6.5vw,92px);}
.section--tight{padding-block:clamp(40px,6vw,72px);}
/* when two same-tone sections stack, trim the seam so spacing stays even */
.section + .section,.band + .band,.band--cream + .band--cream{padding-top:clamp(8px,2vw,24px);}
.band + .band,.band--cream + .band--cream{padding-top:clamp(28px,5vw,68px);}
.lead{font-size:clamp(1.05rem,.97rem + .4vw,1.22rem);color:var(--ink-soft);max-width:62ch;line-height:1.65;}
.center{text-align:center;}.center .lead{margin-inline:auto;}

/* keyboard focus — consistent, visible ring for every interactive element (mouse clicks stay clean) */
a:focus-visible,button:focus-visible,[tabindex]:focus-visible,summary:focus-visible,
input:focus-visible,select:focus-visible,textarea:focus-visible{
  outline:2.5px solid var(--cyan);outline-offset:3px;border-radius:6px;
}
/* on cyan/navy-filled controls a white ring reads better against the fill */
.btn--accent:focus-visible,.btn--cyan:focus-visible,.mobtop__burger:focus-visible,
.botbar__item--give:focus-visible{outline-color:#fff;outline-offset:2px;}
/* form fields already show a soft inner ring — don't double it */
.field input:focus-visible,.field select:focus-visible,.field textarea:focus-visible{outline:none;}

/* buttons */
.btn{--bg:var(--navy);--fg:var(--paper);display:inline-flex;align-items:center;gap:.55em;background:var(--bg);color:var(--fg);padding:.9em 1.6em;border:none;border-radius:100px;font-family:var(--font-display);font-weight:600;font-size:.95rem;position:relative;overflow:hidden;transition:transform .4s var(--ease-out),box-shadow .4s var(--ease-out);box-shadow:var(--shadow-sm);}
.btn::after{content:"";position:absolute;inset:0;background:radial-gradient(120% 140% at 50% 120%,rgba(255,255,255,.22),transparent 60%);opacity:0;transition:opacity .4s;}
.btn:hover{transform:translateY(-2px);box-shadow:var(--shadow-md);}.btn:hover::after{opacity:1;}
.btn:active{transform:translateY(0) scale(.97);box-shadow:var(--shadow-sm);transition-duration:.1s;}
.btn .arrow{transition:transform .4s var(--ease-out);}.btn:hover .arrow{transform:translateX(4px);}
/* "Watch this message" is too long for a phone: it pushes the button beside it
   onto its own line. Below 560px the label shortens to "Watch", which is clear
   enough sitting directly under the sermon's title. The full wording stays on
   the element as aria-label, so a screen reader still hears all of it. */
@media (max-width:560px){ .btn__long{display:none;} }
/* White on the brand cyan measures 3.62:1 - under the 4.5 that normal-sized
   text needs to stay legible, and this is the primary call to action on every
   page ("Give", "Plan Your Visit", "Watch a Message"). Taken down to 88% of
   the same hue it measures 4.54:1 and passes. Mixed rather than hard-coded so
   each theme darkens its OWN accent instead of every theme inheriting this
   one's. The difference is close to invisible side by side; the difference in
   sunlight, on a phone, at arm's length, is not. */
.btn--accent{--bg:color-mix(in srgb,var(--cyan) 88%,#000);--fg:#fff;}
.btn--member{--bg:var(--navy);--fg:#fff;box-shadow:inset 0 0 0 1.5px var(--navy);}
.btn--member:hover{--bg:var(--cyan-deep);box-shadow:inset 0 0 0 1.5px var(--cyan-deep);}
.btn--ghost{--bg:transparent;--fg:var(--ink);box-shadow:inset 0 0 0 1.5px color-mix(in srgb,var(--navy) 30%,transparent);}
.btn--ghost:hover{box-shadow:inset 0 0 0 1.5px var(--cyan);color:var(--cyan-deep);}
.btn--light{--bg:var(--paper);--fg:var(--navy);}
.btn--ondark.btn--ghost{--fg:var(--paper);box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.4);}
.btn--ondark.btn--ghost:hover{box-shadow:inset 0 0 0 1.5px #fff;color:#fff;}

/* =========================================================
   IMAGE FIGURE (image-forward placeholder w/ hover zoom)
   ========================================================= */
.img{position:relative;border-radius:var(--radius);overflow:hidden;background:var(--slate);box-shadow:var(--shadow-sm);isolation:isolate;}
.img>.fill{position:absolute;inset:0;background:linear-gradient(155deg,var(--c1,var(--teal)),var(--c2,var(--cyan-deep)));transition:transform .6s var(--ease-out);}
.img>.fill::after{content:"";position:absolute;inset:0;background:radial-gradient(60% 45% at 28% 22%,color-mix(in srgb,var(--cyan) 50%,transparent),transparent 60%),repeating-linear-gradient(125deg,rgba(255,255,255,.05) 0 3px,transparent 3px 13px);}
.img:hover>.fill{transform:scale(1.06);}
.img .tag{position:absolute;bottom:12px;left:12px;z-index:2;background:rgba(34,32,29,.55);color:var(--ink-invert-soft);font-size:.64rem;letter-spacing:.1em;text-transform:uppercase;font-weight:700;padding:5px 11px;border-radius:100px;backdrop-filter:blur(6px);}
.img .ico{position:absolute;top:12px;right:12px;z-index:2;width:30px;height:30px;border-radius:50%;display:grid;place-items:center;background:rgba(255,255,255,.18);color:#fff;backdrop-filter:blur(4px);}
.img.v-navy>.fill{background:linear-gradient(155deg,var(--slate),var(--navy));}
.img.v-cyan>.fill{background:linear-gradient(155deg,var(--cyan),var(--cyan-deep));}
.img.v-teal>.fill{background:linear-gradient(155deg,var(--teal),var(--cyan-deep));}
.img.v-deep>.fill{background:linear-gradient(155deg,var(--cyan-deep),var(--navy));}
.img.has-photo{background:var(--navy);}
.img.has-photo>.ph{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transition:transform .6s var(--ease-out);}
.img.has-photo:hover>.ph{transform:scale(1.06);}
.hero__right>.ph{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;}
.ar-43{aspect-ratio:4/3;}.ar-11{aspect-ratio:1;}.ar-169{aspect-ratio:16/9;}.ar-34{aspect-ratio:3/4;}.ar-32{aspect-ratio:3/2;}

/* =========================================================
   HEADER / NAV
   ========================================================= */
/* Floating frosted "pill" nav — fixed overlay so header images reach the very top */
.navshell{position:fixed;left:0;right:0;top:14px;z-index:200;display:flex;justify-content:center;padding-inline:14px;pointer-events:none;transition:transform .5s var(--ease-out),opacity .4s ease;}
.navshell.hide{transform:translateY(-185%);}   /* slide only — fading opacity makes the backdrop blur snap */
.pillnav{pointer-events:auto;position:relative;display:flex;align-items:center;gap:4px;max-width:100%;background:transparent;border:0;border-radius:100px;padding:8px 9px;box-shadow:0 20px 50px rgba(20,18,16,.40),inset 0 1px 0 rgba(255,255,255,.09);}
/* Blur lives on a pseudo-element (not the pill itself) so the pill isn't a backdrop-filter
   ancestor of the dropdowns — that would stop each dropdown's own blur from sampling the page. */
.pillnav::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;background:rgba(34,32,29,.70);backdrop-filter:blur(16px) saturate(1.5);-webkit-backdrop-filter:blur(16px) saturate(1.5);}

/* brand (base styles also used by footer) */
.brand{display:flex;align-items:center;gap:.7em;flex-shrink:0;color:var(--ink-strong);}
.brand__mark{width:46px;height:46px;flex-shrink:0;object-fit:contain;transition:transform .5s var(--ease-out);}
.brand:hover .brand__mark{transform:rotate(-4deg) scale(1.05);}
.brand__name{font-family:var(--font-display);font-weight:700;font-size:1.02rem;line-height:1.05;letter-spacing:-.01em;}
.brand__name span{display:block;font-family:var(--font-body);font-size:.6rem;letter-spacing:.24em;text-transform:uppercase;color:var(--muted);font-weight:600;margin-top:2px;}
/* pill-scoped brand */
.pillnav .brand{color:#fff;}
/* Circular knockout badge: navy circle, white mark, monogram shows the navy through */
.brand__logo{width:44px;height:44px;border-radius:50%;overflow:hidden;background:var(--navy);flex-shrink:0;display:grid;place-items:center;box-shadow:0 2px 8px rgba(34,32,29,.22);transition:transform .5s var(--ease-out);}
.brand:hover .brand__logo{transform:rotate(-4deg) scale(1.05);}
.brand__logo img{width:100%;height:100%;object-fit:contain;}
.pillnav .brand__name{display:none;}

.menu{position:relative;display:flex;align-items:center;gap:0;list-style:none;padding:0;margin:0 2px;}
.menu>li{position:relative;}
.menu>li>a,.menu>li>button{position:relative;z-index:1;display:inline-flex;align-items:center;gap:.32em;padding:.62em .92em;border-radius:100px;font-family:var(--font-display);font-weight:600;font-size:.9rem;color:rgba(244,238,225,.78);background:none;border:none;white-space:nowrap;transition:color .3s ease;}
.menu>li>a:hover,.menu>li>button:hover,.menu>li>a[aria-current="page"],.menu>li>button[aria-current="page"]{color:#fff;}
.menu .caret{width:9px;height:9px;opacity:.7;transition:transform .35s var(--ease-out);}
.menu>li:hover .caret,.menu>li:focus-within .caret{transform:rotate(180deg);}
.menu__pill{position:absolute;left:0;top:0;height:0;width:0;background:rgba(255,255,255,.16);border-radius:100px;z-index:0;opacity:0;pointer-events:none;}
.dropdown{position:absolute;top:calc(100% + 16px);left:50%;translate:-50% 0;min-width:230px;list-style:none;padding:8px;margin:0;background:rgba(34,32,29,.70);backdrop-filter:blur(16px) saturate(1.5);-webkit-backdrop-filter:blur(16px) saturate(1.5);border:0;border-radius:var(--radius);box-shadow:0 20px 50px rgba(20,18,16,.40),inset 0 1px 0 rgba(255,255,255,.09);opacity:0;visibility:hidden;transform:translateY(8px);transition:opacity .28s var(--ease-out),transform .28s var(--ease-out),visibility .28s;}
.dropdown::before{content:"";position:absolute;top:-16px;left:0;right:0;height:16px;}
/* Pointer devices only. On a touch screen Safari invents a hover on the first
   tap, and tapping a link inside the item also satisfies :focus-within - either
   one opened this desktop dropdown over the mobile UI and swallowed the tap, so
   you had to tap again to get anywhere. The mobile overlay opens its folders by
   a different route (.mobmenu .has-dropdown.open, driven by a real button and
   max-height), so it is unaffected by this guard. */
@media (hover: hover) {
  .menu>li:hover .dropdown,.menu>li:focus-within .dropdown{opacity:1;visibility:visible;transform:translateY(0);}
}
.dropdown a{display:block;padding:.6em .85em;border-radius:var(--radius-sm);font-size:.9rem;font-weight:500;color:rgba(250,247,242,.86);transition:background .2s,color .2s,padding-left .25s var(--ease-out);}
.dropdown a:hover{background:rgba(255,255,255,.10);color:#fff;padding-left:1.15em;}
.nav__links{display:flex;align-items:center;gap:6px;}
.nav__actions{display:flex;align-items:center;gap:6px;}
.nav__actions .btn{padding:.7em 1.25em;font-size:.88rem;box-shadow:none;}
.hamburger{display:none;width:42px;height:42px;border:none;background:rgba(255,255,255,.10);border-radius:50%;position:relative;flex-shrink:0;}
.hamburger span{position:absolute;left:12px;right:12px;height:2px;background:#fff;border-radius:2px;transition:transform .4s var(--ease-out),opacity .3s,top .3s;}
.hamburger span:nth-child(1){top:15px;}.hamburger span:nth-child(2){top:20px;}.hamburger span:nth-child(3){top:25px;}
body.menu-open .hamburger span:nth-child(1){top:20px;transform:rotate(45deg);}
body.menu-open .hamburger span:nth-child(2){opacity:0;}
body.menu-open .hamburger span:nth-child(3){top:20px;transform:rotate(-45deg);}

/* =========================================================
   HOME — HERO split
   ========================================================= */
.hero{position:relative;}
.hero__grid{display:grid;grid-template-columns:1fr 1fr;min-height:clamp(520px,78vh,760px);}
.hero__left{display:flex;flex-direction:column;justify-content:center;padding:clamp(104px,13vh,128px) clamp(20px,5vw,72px) clamp(28px,5vw,64px);}
.hero__left .eyebrow{margin-bottom:var(--space-lg);}
.hero h1{font-size:clamp(2.6rem,1.7rem + 3.6vw,4.6rem);font-weight:800;line-height:1.0;letter-spacing:-.03em;}
.hero h1 .serif{color:var(--cyan);font-weight:400;}
.hero__sub{margin-top:var(--space-lg);color:var(--ink-soft);max-width:42ch;}
.hero__cta{margin-top:var(--space-xl);display:flex;gap:var(--space-md);flex-wrap:wrap;}
.hero__quick{margin-top:var(--space-2xl);display:flex;gap:var(--space-xl);flex-wrap:wrap;}
.hero__quick div{display:flex;flex-direction:column;}
.hero__quick dt{font-size:.66rem;letter-spacing:.16em;text-transform:uppercase;color:var(--muted);font-weight:700;}
.hero__quick dd{font-family:var(--font-display);font-weight:700;font-size:1.05rem;color:var(--ink-strong);}
.hero__right{position:relative;background:linear-gradient(150deg,var(--teal),var(--cyan-deep));overflow:hidden;}
.hero__right .fill{position:absolute;inset:0;transition:transform 1s var(--ease-out);}
.hero__right .fill::after{content:"";position:absolute;inset:0;background:radial-gradient(70% 50% at 70% 20%,color-mix(in srgb,var(--cyan) 55%,transparent),transparent 60%),repeating-linear-gradient(125deg,rgba(255,255,255,.05) 0 3px,transparent 3px 13px);}
.hero__photo-tag{position:absolute;top:20px;right:20px;z-index:2;background:rgba(34,32,29,.5);color:var(--ink-invert-soft);font-size:.66rem;letter-spacing:.12em;text-transform:uppercase;font-weight:700;padding:6px 12px;border-radius:100px;backdrop-filter:blur(6px);}
.hero__card{position:absolute;bottom:26px;left:26px;right:26px;max-width:380px;z-index:2;background:var(--paper);border-radius:var(--radius);padding:var(--space-lg);box-shadow:var(--shadow-lg);display:flex;gap:var(--space-md);align-items:center;}
.hero__card .thumb{width:74px;height:74px;border-radius:var(--radius-sm);flex-shrink:0;background:linear-gradient(150deg,var(--cyan),var(--navy));}
.hero__card h3{font-size:1.05rem;}.hero__card p{font-size:.84rem;color:var(--muted);margin-top:2px;}
.hero__card .when{color:var(--cyan-deep);font-weight:700;font-size:.82rem;margin-top:4px;}

/* =========================================================
   INNER PAGE BANNER (image-forward hero)
   ========================================================= */
.banner{position:relative;overflow:hidden;color:var(--ink-invert);isolation:isolate;background:var(--navy);}
/* Shorter banner for pages that are mostly a form — the hero shouldn't be the
   tallest thing on a page whose job is to be filled in. */
.banner--short .banner__inner{padding-block:clamp(56px,9vw,96px);}
.banner--short .banner__card{max-width:640px;}
html.app-mode .banner--short .banner__inner{padding-top:calc(env(safe-area-inset-top,0px) + clamp(40px,8vw,64px));}
.banner .fill{position:absolute;inset:0;z-index:-2;background:linear-gradient(150deg,var(--c1,var(--slate)),var(--c2,var(--navy)));}
.banner .fill::after{content:"";position:absolute;inset:0;background:radial-gradient(70% 60% at 75% 15%,color-mix(in srgb,var(--teal) 50%,transparent),transparent 60%),radial-gradient(60% 55% at 12% 95%,color-mix(in srgb,var(--cyan) 45%,transparent),transparent 55%),repeating-linear-gradient(125deg,rgba(255,255,255,.04) 0 3px,transparent 3px 13px);}
/* real photos don't get the placeholder texture — only the gradient placeholders do */
.banner .fill[style*="background-image"]::after,
.img>.fill[style*="background-image"]::after,
.hero__right .fill[style*="background-image"]::after{background:linear-gradient(to top,rgba(34,32,29,.28),transparent 60%);}
.banner::after{content:"";position:absolute;inset:0;z-index:-1;background:linear-gradient(to top,rgba(34,32,29,.5),transparent 70%);}
.banner__inner{padding-top:clamp(120px,15vw,190px);padding-bottom:clamp(56px,9vw,104px);max-width:760px;}
.banner__photo{position:absolute;inset:0;z-index:-2;background-size:cover;background-position:center;}
.banner__scrim{position:absolute;inset:0;z-index:-1;background:linear-gradient(160deg,rgba(34,32,29,.82),rgba(34,32,29,.6) 55%,rgba(34,32,29,.86));}
.banner .crumb{margin-bottom:var(--space-md);}
.banner h1{color:var(--ink-invert);font-size:clamp(2.4rem,1.6rem + 3.6vw,4.4rem);line-height:1.0;letter-spacing:-.02em;}
.banner h1 .serif{color:var(--teal);}
.banner p{margin-top:var(--space-lg);color:rgba(244,238,225,.9);font-size:clamp(1.05rem,1rem + .4vw,1.25rem);max-width:54ch;}
.banner .btn{margin-top:var(--space-xl);}
.crumb{display:flex;gap:.5em;align-items:center;font-size:.78rem;font-weight:600;letter-spacing:.04em;color:rgba(244,238,225,.7);flex-wrap:wrap;}
.crumb a{color:rgba(244,238,225,.7);}.crumb a:hover{color:var(--teal);}
.crumb .sep{opacity:.5;}

/* =========================================================
   PROSE
   ========================================================= */
.prose{max-width:70ch;}
.prose h2{font-size:clamp(1.7rem,1.3rem + 1.8vw,2.5rem);margin-top:var(--space-2xl);margin-bottom:var(--space-md);}
.prose h2:first-child{margin-top:0;}
.prose h2 .serif{color:var(--cyan);}
.prose h3{font-size:1.3rem;margin-top:var(--space-xl);margin-bottom:var(--space-xs);}
.prose p{margin-bottom:var(--space-md);color:var(--ink-soft);}
.prose ul{margin:0 0 var(--space-md) 1.1em;color:var(--ink-soft);display:grid;gap:8px;}
.prose strong{color:var(--ink);}
.prose a:not(.btn){color:var(--cyan-deep);font-weight:600;border-bottom:1.5px solid color-mix(in srgb,var(--cyan) 40%,transparent);}

/* section heading block */
.head{margin-bottom:var(--space-2xl);}
.head h2{font-size:clamp(1.9rem,1.4rem + 2.2vw,3rem);max-width:18ch;}
.head h2 .serif{color:var(--cyan);}
.head.center h2{margin-inline:auto;}
.head p{margin-top:var(--space-md);}
.head--row{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--space-lg);flex-wrap:wrap;}

/* =========================================================
   SPLIT (image + text)
   ========================================================= */
.split{display:grid;grid-template-columns:1fr 1fr;gap:clamp(28px,5vw,72px);align-items:center;}
.split + .split{margin-top:clamp(40px,6vw,80px);}
.split .img{aspect-ratio:4/3;width:100%;}
.split.rev .split__media{order:2;}
.split__copy h2{font-size:clamp(1.7rem,1.3rem + 1.8vw,2.6rem);margin-bottom:var(--space-md);}
.split__copy h2 .serif{color:var(--cyan);}
.split__copy p{color:var(--ink-soft);}.split__copy p+p{margin-top:var(--space-md);}
.split__copy .btn{margin-top:var(--space-lg);}
.split__copy .eyebrow{margin-bottom:var(--space-sm);}

/* =========================================================
   GALLERY
   ========================================================= */
.gallery{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--space-md);grid-auto-rows:1fr;}
.gallery .img{aspect-ratio:1;}
.gallery .img.big{grid-column:span 2;grid-row:span 2;aspect-ratio:auto;}
.gallery .img.wide{grid-column:span 2;aspect-ratio:auto;}
.gallery--3{grid-template-columns:repeat(3,1fr);}
/* A placeholder tile that has had a photo uploaded to it shows the photo (and hides the gradient/icon). */
.img[style*="background-image"]{background-size:cover;background-position:center;}
.img[style*="background-image"]>.fill,.img[style*="background-image"]>.ico,.img[style*="background-image"]>.tag{display:none;}
/* photos set as figure backgrounds get the same hover zoom as <img> photos */
.img[style*="background-image"]::before{content:"";position:absolute;inset:0;background:inherit;background-size:cover;background-position:center;transition:transform .6s var(--ease-out);}
.img[style*="background-image"]:hover::before{transform:scale(1.06);}

/* Polaroid filmstrip — drag/swipe through photos (e.g. Our History) */
.filmstrip{position:relative;margin-top:clamp(28px,5vw,52px);}
/* overflow-x:auto clips the other axis too, and the polaroids' drop-shadow
   reaches 38px below the image (0 16px 22px) against 34px of padding — so the
   soft edge was being sliced off in a hard line just above the next section.
   The extra room is padding, pulled back by a negative margin, so the strip
   has somewhere to cast into without moving anything on the page. */
.filmstrip__track{display:flex;gap:clamp(18px,3vw,36px);overflow-x:auto;scroll-snap-type:x proximity;padding:18px clamp(20px,5vw,52px) 58px;margin-bottom:-24px;scrollbar-width:thin;-webkit-overflow-scrolling:touch;cursor:grab;}
.filmstrip__track.is-drag{cursor:grabbing;scroll-snap-type:none;}
.filmstrip__track.is-drag .polaroid{pointer-events:none;}
.polaroid{flex:none;scroll-snap-align:center;width:clamp(200px,26vw,280px);transform:rotate(var(--r,0deg));transition:transform .3s var(--ease-out);}
.polaroid:nth-child(odd){--r:-1.7deg;}
.polaroid:nth-child(even){--r:1.5deg;}
.polaroid:nth-child(3n){--r:.7deg;}
.polaroid:nth-child(5n){--r:-2.4deg;}
.polaroid img{display:block;width:100%;height:auto;filter:drop-shadow(0 16px 22px rgba(34,32,29,.28));transition:filter .3s var(--ease-out);}
.polaroid::after{display:none;}
.polaroid:hover{transform:rotate(0deg) translateY(-6px) scale(1.03);position:relative;z-index:2;}
.polaroid:hover img{filter:drop-shadow(0 24px 34px rgba(34,32,29,.34));}
.filmstrip__nav{position:absolute;top:calc(50% - 6px);transform:translateY(-50%);z-index:3;width:46px;height:46px;border-radius:50%;background:#fff;border:1px solid var(--line);box-shadow:0 6px 18px rgba(34,32,29,.16);color:var(--navy);font-size:1.7rem;line-height:1;display:grid;place-items:center;cursor:pointer;transition:background .2s,color .2s;}
.filmstrip__nav:hover{background:var(--navy);color:#fff;border-color:var(--navy);}
.filmstrip__nav--prev{left:max(8px,calc(50% - 620px));}
.filmstrip__nav--next{right:max(8px,calc(50% - 620px));}
@media(max-width:680px){.filmstrip__nav{display:none;}}

/* Scroll-velocity image marquee (legacy, unused) */
.velo-sec{overflow:hidden;}
.velo{display:flex;flex-direction:column;gap:clamp(12px,1.8vw,20px);margin-top:clamp(28px,5vw,52px);width:100%;}
.velo__row{overflow:hidden;}
.velo__track{display:flex;gap:clamp(12px,1.8vw,20px);width:max-content;will-change:transform;}
.velo__item{flex:none;height:clamp(150px,21vw,290px);margin:0;border-radius:var(--radius-card);overflow:hidden;background:var(--cream-2);box-shadow:var(--shadow-sm);}
.velo__item img{height:100%;width:auto;display:block;object-fit:cover;}
/* If motion is reduced, fall back to a normal swipeable strip with no auto-animation */
@media(prefers-reduced-motion:reduce){
  .velo__row{overflow-x:auto;scrollbar-width:thin;}
  .velo__track{transform:none !important;}
}

/* =========================================================
   FEATURE CARDS (image-top)
   ========================================================= */
/* Card rows: max 3 across, balanced so the last row is never a lone card (5→3+2, 4→2+2). */
.cards{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-lg);}
.cards:has(> :nth-child(2):last-child){grid-template-columns:repeat(2,minmax(0,1fr));}   /* exactly 2 */
.cards:has(> :nth-child(4):last-child){grid-template-columns:repeat(2,minmax(0,1fr));}   /* exactly 4 → 2+2 */
@media(max-width:900px){
  .cards,.cards:has(> :nth-child(2):last-child),.cards:has(> :nth-child(4):last-child){grid-template-columns:repeat(2,minmax(0,1fr));}
  .cards > :last-child:nth-child(odd){grid-column:1 / -1;}     /* lone trailing card spans the row instead of sitting alone */
}
@media(max-width:560px){
  .cards,.cards:has(> :nth-child(2):last-child),.cards:has(> :nth-child(4):last-child){grid-template-columns:1fr;}
  .cards > :last-child:nth-child(odd){grid-column:auto;}
}
.card{display:flex;flex-direction:column;background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;transition:transform .5s var(--ease-out),box-shadow .5s var(--ease-out);}
.card:hover{transform:translateY(-6px);box-shadow:var(--shadow-lg);}
.card .img{aspect-ratio:16/10;border-radius:0;box-shadow:none;}
.card__body{padding:var(--space-lg);display:flex;flex-direction:column;flex:1;}
.card .kicker{font-size:.66rem;letter-spacing:.14em;text-transform:uppercase;font-weight:700;color:var(--cyan-deep);}
.card h3{font-size:1.25rem;margin-top:4px;}
.card p{color:var(--ink-soft);font-size:.94rem;margin-top:var(--space-xs);}
.card .go{margin-top:var(--space-md);font-family:var(--font-display);font-weight:700;font-size:.88rem;color:var(--cyan-deep);display:inline-flex;gap:.4em;align-items:center;transition:gap .3s var(--ease-out);}
.card:hover .go{gap:.75em;}

/* YouTube video grid (real thumbnails) */
.vidgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:var(--space-lg);}
.vidcard{display:flex;flex-direction:column;background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;transition:transform .5s var(--ease-out),box-shadow .5s var(--ease-out);}
.vidcard:hover{transform:translateY(-6px);box-shadow:var(--shadow-lg);}
.vidcard__thumb{position:relative;aspect-ratio:16/9;overflow:hidden;background:var(--navy);}
.vidcard__thumb img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transition:transform .6s var(--ease-out);}
.vidcard:hover .vidcard__thumb img{transform:scale(1.06);}
.vidcard__play{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:54px;height:54px;border-radius:50%;background:rgba(34,32,29,.66);color:#fff;display:grid;place-items:center;backdrop-filter:blur(2px);transition:background .3s,transform .3s var(--ease-out);}
.vidcard:hover .vidcard__play{background:var(--cyan);transform:translate(-50%,-50%) scale(1.08);}
.vidcard__play svg{margin-left:3px;}
.vidcard__title{font-family:var(--font-display);font-weight:600;font-size:1rem;color:var(--ink);padding:var(--space-md) var(--space-lg) 4px;line-height:1.3;}
.vidcard__date{padding:0 var(--space-lg) var(--space-lg);color:var(--muted);font-size:.82rem;}
.vidcard{cursor:pointer;}

/* ═══ media pages (Testimonies & Music): highlighted-video hero melting into navy,
       whole page carries the dark blue — same treatment as the Sermons page ═══ */
.mpage{background:var(--navy)}
.mpage .section{background:var(--navy)}
.mhero{position:relative;isolation:isolate;background:var(--navy);color:#fff;overflow:hidden;
  padding:clamp(96px,12vw,138px) 0 clamp(56px,8vw,92px);text-align:center}
.mhero__bg{position:absolute;inset:-50px;z-index:-2;background-size:cover;background-position:center 30%;
  filter:blur(42px) saturate(1.25) brightness(.85);transform:scale(1.12)}
.mhero__fade{position:absolute;inset:0;z-index:-1;
  background:linear-gradient(180deg,rgba(34,32,29,.30) 0%,rgba(34,32,29,.44) 34%,rgba(34,32,29,.62) 58%,rgba(34,32,29,.86) 80%,var(--navy) 100%)}
.mhero__kick{font-size:.7rem;font-weight:700;letter-spacing:.28em;text-transform:uppercase;color:#d9c4a8;margin-bottom:16px}
.mhero__player{max-width:740px;margin-inline:auto}
.mhero__player .vidcard{background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.13);border-radius:var(--radius);padding:0;box-shadow:0 30px 70px rgba(0,0,0,.45)}
.mhero__player .vidcard:hover{border-color:rgba(217,196,168,.5)}
.mhero__player .vidcard__thumb{border-radius:0;box-shadow:none}
.mhero__title{font-size:clamp(1.6rem,3.4vw,2.6rem);letter-spacing:-.025em;line-height:1.08;color:#fff;max-width:26ch;margin:20px auto 0}
.mhero__cta{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;margin-top:20px}
/* dark content below the fade */
.mpage .head .eyebrow{color:#d9c4a8}
.mpage .head h2{color:#fff}
.mpage .head h2 .serif{color:#d9c4a8}
.mpage .vidcard{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.13)}
.mpage .vidcard:hover{border-color:rgba(217,196,168,.5)}
.mpage .vidcard__title{color:#fff}
.mpage .vidcard__date{color:rgba(244,238,225,.62)}
.mpage .quote blockquote{color:#fff}
.mpage .quote cite{color:rgba(244,238,225,.7)}
.mpage .quote .hl{color:#d9c4a8}
.mpage .split__copy .eyebrow{color:#d9c4a8}
.mpage .split__copy h2{color:#fff}
.mpage .split__copy h2 .serif{color:#d9c4a8}
.mpage .split__copy p,.mpage .split__copy .lead{color:rgba(250,247,242,.85)}
html.app-mode .mhero{padding-top:calc(env(safe-area-inset-top,0px) + clamp(52px,9vw,80px))}

/* In-site video player (lightbox) */
body.vplayer-open{overflow:hidden;}
.vplayer{position:fixed;inset:0;z-index:1000;display:none;align-items:center;justify-content:center;padding:clamp(14px,4vw,40px);}
.vplayer.open{display:flex;}
.vplayer__backdrop{position:absolute;inset:0;background:rgba(7,18,33,.78);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);animation:vfade .25s var(--ease-out) both;}
.vplayer__box{position:relative;width:min(1040px,100%);animation:vrise .35s var(--ease-out) both;}
.vplayer__frame{position:relative;aspect-ratio:16/9;background:#000;border-radius:var(--radius);overflow:hidden;box-shadow:0 40px 120px rgba(0,0,0,.55);}
.vplayer__frame iframe{position:absolute;inset:0;width:100%;height:100%;border:0;}
.vplayer__title{margin-top:14px;color:var(--ink-invert);font-family:var(--font-display);font-weight:600;font-size:1.05rem;text-align:center;text-shadow:0 1px 12px rgba(0,0,0,.5);}
.vplayer__tags{display:flex;flex-wrap:wrap;gap:6px;justify-content:center;margin-top:10px;}
.vplayer__tags:empty{display:none;}
.vplayer__tags .vtag{color:#e8ded2;background:rgba(217,196,168,.13);border-color:rgba(217,196,168,.34);}
/* Close button floats on top of the video, top-right corner */
.vplayer__x{position:absolute;top:12px;right:12px;z-index:5;width:40px;height:40px;border-radius:50%;border:none;background:rgba(34,32,29,.55);color:#fff;display:grid;place-items:center;cursor:pointer;-webkit-backdrop-filter:blur(8px) saturate(1.4);backdrop-filter:blur(8px) saturate(1.4);box-shadow:0 6px 20px rgba(0,0,0,.4);transition:transform .25s var(--ease-out),background .25s;}
.vplayer__x:hover{transform:scale(1.08) rotate(90deg);background:var(--cyan);}
/* Sermon tag chips (used on cards and in the player) */
.vidcard__tags{display:flex;flex-wrap:wrap;gap:6px;padding:0 var(--space-lg) var(--space-lg);margin-top:auto;}
.vidcard:has(.vidcard__tags) .vidcard__date{padding-bottom:12px;}
.vidcard:has(.vidcard__tags):not(:has(.vidcard__date)) .vidcard__tags{padding-top:12px;}
.vtag{display:inline-block;font-size:.62rem;font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:var(--cyan-deep,#5f4a31);background:color-mix(in srgb,var(--cyan,#a08a6f) 8%,transparent);border:1px solid color-mix(in srgb,var(--cyan,#a08a6f) 18%,transparent);border-radius:100px;padding:.44em .85em;line-height:1;white-space:nowrap;}
@keyframes vfade{from{opacity:0}to{opacity:1}}
@keyframes vrise{from{opacity:0;transform:translateY(16px) scale(.98)}to{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){.vplayer__backdrop,.vplayer__box{animation:none;}}

/* =========================================================
   HORIZONTAL RAIL
   ========================================================= */
.railwrap{position:relative;}
.rail{display:flex;gap:var(--space-lg);overflow-x:auto;scroll-snap-type:x mandatory;padding-bottom:var(--space-sm);scrollbar-width:none;cursor:grab;}
.rail::-webkit-scrollbar{display:none;}
.rail.is-drag{cursor:grabbing;scroll-snap-type:none;scroll-behavior:auto;}
.rail.is-drag a{pointer-events:none;}
.rail__arrow{position:absolute;top:42%;transform:translateY(-50%);z-index:4;width:46px;height:46px;border-radius:50%;border:1px solid var(--line);background:#fff;color:var(--navy);display:grid;place-items:center;cursor:pointer;box-shadow:0 10px 26px rgba(34,32,29,.18);transition:transform .2s var(--ease-out),opacity .25s var(--ease-out),background .2s,color .2s;}
.rail__arrow:hover{background:var(--navy);color:#fff;transform:translateY(-50%) scale(1.07);}
.rail__arrow--prev{left:-10px;}
.rail__arrow--next{right:-10px;}
.rail__arrow[disabled]{opacity:0;pointer-events:none;}
@media(hover:none){.rail__arrow{display:none;}}
.rcard{scroll-snap-align:start;flex:0 0 clamp(240px,30vw,300px);}
.rcard .img{aspect-ratio:1.08;}
.rcard h3{margin-top:var(--space-md);font-size:1.15rem;}
.rcard .meta{color:var(--muted);font-size:.86rem;margin-top:2px;}
.rcard .meta b{color:var(--cyan-deep);}

/* =========================================================
   VLIST (sermons / events rows)
   ========================================================= */
.vlist{display:grid;gap:var(--space-md);}
.vrow{display:grid;grid-template-columns:auto 1fr auto;gap:var(--space-lg);align-items:center;background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);padding:var(--space-md);transition:transform .4s var(--ease-out),box-shadow .4s var(--ease-out);}
.vrow:hover{transform:translateY(-3px);box-shadow:var(--shadow-md);}
.vrow .img{width:clamp(96px,14vw,150px);aspect-ratio:16/10;}
.vrow .play{position:absolute;inset:0;z-index:2;display:grid;place-items:center;color:#fff;}
.vrow .play svg{filter:drop-shadow(0 2px 8px rgba(0,0,0,.4));}
.vrow h3{font-size:1.12rem;}
.vrow .meta{color:var(--muted);font-size:.85rem;margin-top:2px;}
.vrow .tagline{color:var(--cyan-deep);font-weight:600;font-size:.8rem;text-transform:uppercase;letter-spacing:.08em;}
.vrow .when{text-align:center;font-family:var(--font-display);}
.vrow .when .d{font-size:1.6rem;font-weight:800;color:var(--ink-strong);line-height:1;}
.vrow .when .m{font-size:.7rem;text-transform:uppercase;letter-spacing:.1em;color:var(--cyan-deep);font-weight:700;}
@media(max-width:620px){.vrow{grid-template-columns:auto 1fr;}.vrow .when{display:none;}}

/* =========================================================
   ACCORDION (beliefs / FAQ)
   ========================================================= */
.acc{display:grid;gap:var(--space-sm);max-width:860px;}
.acc__item{background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;}
.acc__q{width:100%;display:flex;align-items:center;justify-content:space-between;gap:var(--space-md);padding:var(--space-lg);font-family:var(--font-display);font-weight:700;font-size:1.05rem;color:var(--ink-strong);background:none;border:none;text-align:left;cursor:pointer;-webkit-tap-highlight-color:transparent;}
.acc__q .pm{flex-shrink:0;width:24px;height:24px;position:relative;transition:transform .4s var(--ease-out);}
.acc__q .pm::before,.acc__q .pm::after{content:"";position:absolute;background:var(--cyan);border-radius:2px;}
.acc__q .pm::before{top:11px;left:3px;right:3px;height:2px;}
.acc__q .pm::after{left:11px;top:3px;bottom:3px;width:2px;transition:transform .4s var(--ease-out);}
.acc__item.open .pm::after{transform:scaleY(0);}
.acc__a{display:grid;grid-template-rows:0fr;transition:grid-template-rows .45s var(--ease-out);}
.acc__item.open .acc__a{grid-template-rows:1fr;}
.acc__a>div{overflow:hidden;transform:translateY(-10px);transition:transform .42s var(--ae-out,cubic-bezier(.16,1,.3,1));}
.acc__item.open .acc__a>div{transform:translateY(0);}
@media(prefers-reduced-motion:reduce){.acc__a>div{transition:none;transform:none;}}
.acc__a p{padding:0 var(--space-lg) var(--space-lg);color:var(--ink-soft);}
.acc__a a{color:var(--cyan-deep);font-weight:600;text-decoration:underline;text-underline-offset:2px;text-decoration-thickness:1px;transition:color .2s;}
.acc__a a:hover{color:var(--cyan);}

/* =========================================================
   TEAM
   ========================================================= */
/* Fixed-width people so every photo is the same size in every section, centered rows. */
.team{display:flex;flex-wrap:wrap;justify-content:center;gap:var(--space-lg);}
.team .person{flex:0 1 260px;max-width:260px;width:100%;}
.person .img{aspect-ratio:3/4;}
.person h3{font-size:1.12rem;margin-top:var(--space-md);}
.person .role{color:var(--cyan-deep);font-weight:600;font-size:.88rem;}
.person .bio{margin-top:8px;color:var(--ink-soft);font-size:.88rem;line-height:1.55;}
.team--bio .person{flex-basis:290px;max-width:290px;}
/* cap a section to 3 across so rows stay even (e.g. 6 pastors → 3 + 3) */
.team--cap3{max-width:calc(290px * 3 + var(--space-lg) * 2);margin-inline:auto;}

/* =========================================================
   STAT BAND / QUOTE
   ========================================================= */
.band{background:var(--navy);color:var(--ink-invert-soft);}
.band h2,.band h3{color:var(--ink-invert);}
.band--cream{background:var(--cream-2);color:var(--ink);}
.band--cream h2{color:var(--ink-strong);}
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:var(--space-lg);text-align:center;}
.stat .n{font-family:var(--font-serif);font-style:italic;font-size:clamp(2.6rem,2rem + 2vw,4rem);color:var(--teal);line-height:1;}
.stat .l{margin-top:var(--space-xs);font-size:.85rem;color:rgba(244,238,225,.8);text-transform:uppercase;letter-spacing:.1em;font-weight:600;}
.quote{text-align:center;max-width:900px;margin-inline:auto;}
.quote blockquote{font-family:var(--font-serif);font-style:italic;font-size:clamp(1.7rem,1.2rem + 2.2vw,2.8rem);line-height:1.26;color:var(--ink-strong);}
.band .quote blockquote{color:var(--ink-invert);}
.quote .hl{color:var(--cyan);}.band .quote .hl{color:var(--teal);}
.quote cite{display:block;margin-top:var(--space-lg);font-family:var(--font-display);font-style:normal;font-weight:700;font-size:.9rem;letter-spacing:.06em;color:var(--muted);}
.band .quote cite{color:rgba(244,238,225,.7);}

/* times list */
/* contained navy gradient card (e.g. home "Plan your first Sunday") */
.homecard--navy{position:relative;overflow:hidden;color:var(--ink-invert-soft);border-radius:clamp(22px,3vw,32px);
  background:linear-gradient(145deg,var(--cyan-deep),var(--navy) 62%);
  padding:clamp(30px,5vw,60px);box-shadow:0 26px 64px rgba(20,18,16,.28);}
.homecard--navy h2{color:var(--ink-invert);}
.homecard--navy .btn{margin-top:var(--space-lg);}
.times__grid{display:grid;grid-template-columns:1.2fr 1fr;gap:clamp(28px,5vw,72px);align-items:center;}
.times__list{display:grid;gap:var(--space-sm);}
.times__list li{list-style:none;display:flex;justify-content:space-between;gap:var(--space-md);padding:var(--space-md) 0;border-bottom:1px solid rgba(255,255,255,.14);font-family:var(--font-display);}
.times__list .lab{color:var(--ink-invert-soft);font-weight:600;}
.times__list .val{color:var(--teal);font-weight:700;white-space:nowrap;}

/* find (search moment) */
.find{background:var(--paper);text-align:center;}
.find h2{font-size:clamp(2.2rem,1.6rem + 4vw,4.6rem);font-weight:800;color:color-mix(in srgb,var(--navy) 32%,var(--cream));letter-spacing:-.03em;}
.find h2 .serif{color:var(--cyan);-webkit-text-stroke:0;}
.find__bar{margin:var(--space-xl) auto 0;max-width:560px;display:flex;gap:var(--space-sm);background:var(--cream);border:1px solid var(--line);border-radius:100px;padding:8px 8px 8px 22px;align-items:center;box-shadow:var(--shadow-sm);}
.find__bar span{color:var(--muted);font-size:.95rem;text-align:left;flex:1;}
.findtags{margin-top:var(--space-lg);display:flex;gap:var(--space-sm);justify-content:center;flex-wrap:wrap;}
.findtags a{font-size:.86rem;font-weight:600;padding:.5em 1.1em;border-radius:100px;background:var(--cream);border:1px solid var(--line);color:var(--ink-soft);transition:background-color .2s ease,color .2s ease,border-color .2s ease;}
.findtags a:hover{background:var(--navy);color:var(--ink-invert);border-color:var(--navy);transform:translateY(-2px);}

/* CTA / invite */
.invite{background:var(--cream-2);text-align:center;}
.invite h2{font-size:clamp(2.2rem,1.6rem + 3vw,4rem);max-width:18ch;margin-inline:auto;}
.invite h2 .serif{color:var(--cyan);}
.invite p{margin-top:var(--space-lg);color:var(--ink-soft);font-size:1.18rem;max-width:44ch;margin-inline:auto;}
.invite__cta{margin-top:var(--space-2xl);display:flex;gap:var(--space-md);justify-content:center;flex-wrap:wrap;}
.invite--navy{background:var(--navy);}
.invite--navy h2{color:var(--ink-invert);}.invite--navy h2 .serif{color:var(--teal);}
.invite--navy p{color:rgba(244,238,225,.88);}

/* =========================================================
   FOOTER
   ========================================================= */
.footer{--footer-head:color-mix(in srgb,var(--cyan) 84%,#fff);background:var(--navy);color:rgba(244,238,225,.72);padding-block:var(--space-3xl) var(--space-xl);}
.footer__grid{display:grid;grid-template-columns:1.4fr repeat(3,1fr);gap:var(--space-2xl) var(--space-lg);}
.footer__brand .brand,.footer__brand .brand__mark{color:var(--ink-invert-soft);}
.footer__brand .brand__name{color:var(--ink-invert);}
.footer p{font-size:.94rem;margin-top:var(--space-md);max-width:32ch;line-height:1.6;}
.footer h4{color:var(--footer-head);font-family:var(--font-display);font-size:1.02rem;letter-spacing:.08em;text-transform:uppercase;margin-bottom:var(--space-md);font-weight:700;text-decoration:underline;text-underline-offset:5px;text-decoration-thickness:1.5px;}
.footer ul{list-style:none;padding:0;display:grid;gap:10px;}
.footer a{font-size:.94rem;transition:color .25s;}
.footer li a{display:inline-block;transition:color .25s,transform .25s var(--ease-out);}
.footer li a:hover{transform:translateX(4px);}
.footer__contact a{display:block;}
.footer__contact li a{display:block;}
.socials{display:flex;gap:var(--space-sm);margin-top:var(--space-lg);}
.socials a{width:40px;height:40px;display:inline-flex;border-radius:50%;transition:transform .3s var(--ease-out),filter .3s;}
.socials a img{width:100%;height:100%;display:block;}
.socials a:hover{transform:translateY(-3px) scale(1.05);filter:drop-shadow(0 5px 12px rgba(0,0,0,.35));}
.footer__bottom{margin-top:var(--space-3xl);padding-top:var(--space-lg);border-top:1px solid rgba(255,255,255,.1);display:flex;justify-content:space-between;flex-wrap:wrap;gap:var(--space-sm);font-size:.84rem;color:rgba(244,238,225,.62);}

/* =========================================================
   ANNOUNCEMENT BAR
   ========================================================= */
/* ---- service alert -------------------------------------------------------
   A Sunday that is not going ahead as usual. Deliberately NOT brand-colored:
   it has to read as an exception to the normal chrome rather than part of it,
   and the cyan announcement bar directly below is the thing it must not be
   mistaken for. Amber rather than red - the service has changed, it is not an
   emergency, and a congregation that sees red for a bit of snow will discount
   red when it matters. Navy on this amber is about 8.7:1, so it holds up in
   sun on a phone in a car park, which is exactly where it gets read. */
.svcalert{background:#f2c14e;color:#22201d;}
.svcalert__in{display:flex;align-items:flex-start;justify-content:center;gap:10px;
  padding:11px clamp(16px,4vw,28px);text-align:left;font-size:.92rem;line-height:1.45;}
.svcalert__ic{flex:none;display:grid;place-items:center;width:20px;height:20px;margin-top:1px;}
.svcalert__ic svg{width:20px;height:20px;display:block;}
.svcalert__tx b{font-weight:800;}
.svcalert__note{opacity:.78;}
@media (max-width:640px){ .svcalert__in{font-size:.86rem;padding:10px 16px;} }
.announce{background:var(--cyan-deep);color:var(--ink-invert-soft);font-size:.92rem;}
.announce__in{display:flex;align-items:center;justify-content:center;gap:var(--space-md);padding:10px clamp(40px,5vw,52px);text-align:center;position:relative;flex-wrap:wrap;}
.announce a{font-weight:700;color:#fff;border-bottom:1.5px solid rgba(255,255,255,.5);}
.announce a:hover{border-color:#fff;}
.announce__x{position:absolute;right:12px;top:50%;transform:translateY(-50%);background:none;border:none;color:rgba(255,255,255,.8);width:30px;height:30px;border-radius:50%;font-size:1.1rem;line-height:1;display:grid;place-items:center;}
.announce__x:hover{background:rgba(255,255,255,.15);color:#fff;}
/* announcement bar designs (base .announce = the classic solid bar) */
.announce--bold{font-size:1.02rem;font-weight:700;letter-spacing:.01em;background:var(--navy);}
.announce--bold .announce__in{padding-top:14px;padding-bottom:14px;text-transform:none;}
.announce--soft{background:color-mix(in srgb,var(--cyan) 13%,#fff);color:var(--navy);}
.announce--soft a{color:var(--cyan-deep);border-bottom-color:color-mix(in srgb,var(--cyan-deep) 45%,transparent);}
.announce--soft a:hover{border-color:var(--cyan-deep);}
.announce--soft .announce__x{color:rgba(34,32,29,.55);}
.announce--soft .announce__x:hover{background:rgba(34,32,29,.1);color:var(--ink-strong);}
.announce--gradient{background:linear-gradient(90deg,var(--navy),var(--cyan-deep) 55%,var(--cyan));color:#fff;}
/* announcement bar fonts */
.announce--fserif{font-family:var(--font-display,Georgia,serif);}
.announce--frounded{font-family:'Trebuchet MS','Segoe UI',sans-serif;}
/* ===== Blurred-artwork hero — shared by Messages, series pages, and the CMS "hero" header type.
   (The sermons/series pages add their own extras inline; this is the reusable base.) ===== */
/* --- Adaptive header sizing wrapper (page-builder banners) --- */
.bnrbox{position:relative;--bnr-h:60vh;--bnr-w:100%;--bnr-r:0px;}
.bnrbox--h > .banner,.bnrbox--h > .smhero{min-height:var(--bnr-h);}
.bnrbox--inset{padding:clamp(12px,3vw,34px);}
.bnrbox--inset > .banner,.bnrbox--inset > .smhero{width:var(--bnr-w);max-width:100%;margin-inline:auto;border-radius:var(--bnr-r);overflow:hidden;}
@media(max-width:640px){.bnrbox--inset{padding:10px;}.bnrbox--inset > .banner,.bnrbox--inset > .smhero{width:100%;}}
/* header title/text alignment overrides */
.bnr-al-left .smhero,.bnr-al-left .smhero__wrap,.bnr-al-left .banner__inner,.bnr-al-left .banner__card{text-align:left;}
.bnr-al-left .smhero__crumb,.bnr-al-left .smhero__cta,.bnr-al-left .banner__cta{justify-content:flex-start;}
.bnr-al-center .smhero,.bnr-al-center .smhero__wrap,.bnr-al-center .banner__inner,.bnr-al-center .banner__card{text-align:center;}
.bnr-al-center .smhero__crumb,.bnr-al-center .smhero__cta,.bnr-al-center .banner__cta{justify-content:center;}
.bnr-al-center .banner__inner .eyebrow,.bnr-al-center .banner__card .eyebrow{margin-inline:auto;}
.bnr-al-right .smhero,.bnr-al-right .smhero__wrap,.bnr-al-right .banner__inner,.bnr-al-right .banner__card{text-align:right;}
.bnr-al-right .smhero__crumb,.bnr-al-right .smhero__cta,.bnr-al-right .banner__cta{justify-content:flex-end;}
.bnr-al-right .banner__inner .eyebrow,.bnr-al-right .banner__card .eyebrow{margin-left:auto;}

.smhero{position:relative;isolation:isolate;background:var(--navy,#22201d);color:#fff;overflow:hidden;padding:clamp(96px,12vw,138px) 0 clamp(48px,7vw,72px);text-align:center;}
.smhero__bg{position:absolute;inset:-50px;z-index:-2;background-size:cover;background-position:center 30%;filter:blur(42px) saturate(1.25) brightness(.85);transform:scale(1.12);}
.smhero__fade{position:absolute;inset:0;z-index:-1;background:linear-gradient(180deg,rgba(34,32,29,.30) 0%,rgba(34,32,29,.44) 34%,rgba(34,32,29,.62) 58%,rgba(34,32,29,.86) 80%,var(--navy,#22201d) 100%);}
.smhero__crumb{justify-content:center;display:flex;margin-bottom:14px;}
.smhero__crumb,.smhero__crumb a{color:rgba(250,247,242,.8);}
.smhero__kick{font-size:.7rem;font-weight:700;letter-spacing:.28em;text-transform:uppercase;color:#d9c4a8;margin-bottom:14px;}
.smhero__title{font-size:clamp(1.9rem,4vw,2.9rem);letter-spacing:-.025em;line-height:1.08;color:#fff;max-width:22ch;margin:0 auto;}
.smhero__meta{color:rgba(244,238,225,.78);font-size:clamp(.92rem,1.2vw,1.04rem);margin:12px auto 0;max-width:54ch;}
.smhero__cta{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;margin-top:22px;}
/* "Crisp top" variant: a sharp copy of the photo layered over the blurred one, masked so it
   fades out as it nears the transition line — the image starts sharp and gradually blurs down. */
.smhero--sharp .smhero__bg{z-index:-3;}
.smhero__sharp{position:absolute;inset:-50px;z-index:-2;background-size:cover;background-position:center 30%;transform:scale(1.12);
  -webkit-mask-image:linear-gradient(to bottom,#000 0%,#000 30%,rgba(0,0,0,.4) 55%,transparent 74%);
          mask-image:linear-gradient(to bottom,#000 0%,#000 30%,rgba(0,0,0,.4) 55%,transparent 74%);}
@media(max-width:700px){.smhero--cms{padding-top:clamp(84px,20vw,104px);}.smhero--cms .smhero__title{font-size:1.6rem;}}
/* ===== CMS page sections: stat row, FAQ accordion, pull quote ===== */
.cmsstats{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:24px;text-align:center;margin-top:var(--space-lg,28px);}
.cmsstat__n{display:block;font-family:var(--font-display,inherit);font-weight:800;font-size:clamp(2rem,4.5vw,3rem);color:var(--navy,#22201d);line-height:1;letter-spacing:-.02em;}
.cmsstat__l{display:block;margin-top:8px;font-size:.84rem;letter-spacing:.05em;text-transform:uppercase;color:var(--muted,#6e6459);font-weight:600;}
.cmsfaq{margin-top:var(--space-lg,28px);display:flex;flex-direction:column;gap:10px;}
.cmsfaq__it{border:1px solid var(--line,#ece9e5);border-radius:12px;background:#fff;overflow:hidden;}
.cmsfaq__it summary{cursor:pointer;padding:15px 18px;font-weight:700;color:var(--navy,#22201d);list-style:none;display:flex;justify-content:space-between;align-items:center;gap:12px;}
.cmsfaq__it summary::-webkit-details-marker{display:none;}
.cmsfaq__it summary::after{content:"+";font-size:1.5rem;font-weight:400;line-height:1;color:var(--cyan-deep,#7d6a52);transition:transform .2s;}
.cmsfaq__it[open] summary::after{transform:rotate(45deg);}
.cmsfaq__a{padding:0 18px 16px;color:#5a5147;line-height:1.6;}
.cmsquote{max-width:760px;margin-inline:auto;text-align:center;}
.cmsquote blockquote{font-family:var(--font-display,Georgia,serif);font-size:clamp(1.3rem,2.6vw,1.9rem);line-height:1.32;color:var(--navy,#22201d);margin:0;font-style:italic;}
.cmsquote blockquote::before{content:"\201C";}
.cmsquote blockquote::after{content:"\201D";}
.cmsquote figcaption{margin-top:16px;font-size:.92rem;color:var(--muted,#6e6459);}
.cmsquote figcaption b{color:var(--navy,#22201d);}

/* --- Universal CMS section layout modifiers (alignment / spacing / width / dark band) --- */
.cmssec--al-center{text-align:center;}
.cmssec--al-center .wrap > *{margin-inline:auto;}
.cmssec--al-right{text-align:right;}
.cmssec--compact{padding-block:clamp(28px,4vw,52px);}
.cmssec--roomy{padding-block:clamp(72px,9vw,140px);}
.cmssec--narrow .wrap{max-width:760px;}
.cmssec--wide .wrap{max-width:1240px;}
.cmssec--dark{background:var(--navy)!important;color:#f5f1ed;}
.cmssec--dark h2,.cmssec--dark h3,.cmssec--dark p,.cmssec--dark li,.cmssec--dark figcaption,.cmssec--dark blockquote{color:#f5f1ed;}
.cmssec--dark .eyebrow{color:#ccbeb1;}
.cmssec--dark .cmsstat b,.cmssec--dark .cmsstat span{color:#fff;}
.cmssec--dark .cmsfaq__it{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.16);}
.cmssec--dark .cmsfaq__it summary{color:#fff;}
.cmssec--dark .cmsfaq__a{color:#ddd6cf;}
.cmssec--dark a:not(.btn){color:#fff;text-decoration:underline;}

/* --- Free grid positioning of a block's content (opt-in; shared by sections + header) --- */
.cmpos--free{position:relative;}
.cmpos--free > .wrap{position:absolute;left:var(--px,50%);top:var(--py,50%);transform:translate(calc(var(--px,50%) * -1),calc(var(--py,50%) * -1));margin:0;width:fit-content;max-width:100%;}
.cmpos--flow{position:relative;}
.cmpos--flow > .wrap{position:relative;left:var(--px,50%);transform:translateX(calc(var(--px,50%) * -1));width:fit-content;max-width:100%;}
.section.cmpos-mh{min-height:var(--secmh,auto);}
.section.cmpos--free{min-height:var(--secmh,45vh);}
/* A block's free-positioned text sits in the flow rather than floating on top
   of it. Floating (position:absolute) had two faults: the text got squeezed
   narrower the further right it went, and when it was taller than the block -
   always the case on a phone, where lines wrap - it spilled out of the top.
   In the flow the same numbers put it in the same place when it fits, and the
   block simply grows when it does not: the space above and below the text is
   shared out by --pyn, and left/right works the way .cmpos--flow always has. */
.section.cmpos--free{display:flex;flex-direction:column;}
.section.cmpos--free::before{content:"";flex:var(--pyn,.5) 1 0;}
.section.cmpos--free::after{content:"";flex:calc(1 - var(--pyn,.5)) 1 0;}
.section.cmpos--free > .wrap{position:relative;flex:none;top:auto;left:var(--px,50%);
  transform:translateX(calc(var(--px,50%) * -1));margin:0;width:fit-content;max-width:100%;}
/* Shrink-to-fit is right for a few lines of text, and wrong for a gallery or a
   row of cards: a grid of flexible columns has no natural width, so it shrank
   to nothing and the photos vanished. Those keep the full width and move up
   and down only. */
.section.cmpos--free > .wrap:has(.cmsgal,.cmscards,.cmsstats,.cmspeople,.cmssteps,.cmsfaq,.split,form,iframe){width:100%;left:0;transform:none;}
.cmpos--free.banner,.cmpos--free.smhero{min-height:var(--bnr-h,45vh);}
@media(max-width:640px){
  /* keep positioned content readable on phones: recentre and return to normal flow -
     unless the block has a height someone set (cmpos--sized). Then there is
     room to place the text, and it stays where it was put. */
  .cmpos--free:not(.cmpos--sizedm) > .wrap,.section.cmpos--free:not(.cmpos--sizedm) > .wrap,.cmpos--flow > .wrap{position:static;left:auto;top:auto;transform:none;margin-inline:auto;}
  /* A height someone chose still holds on a phone; the 45vh default for a
     free-positioned block does not, because the text drops back into flow.
     A phone height or position set in the phone view (--secmhm, --pxm, --pym)
     wins; until then the phone uses the desktop numbers. */
  .section.cmpos--free{min-height:var(--secmhm,var(--secmh,0));}
  .section.cmpos-mh{min-height:var(--secmhm,var(--secmh,auto));}
  .section.cmpos--free::before{flex-grow:var(--pynm,var(--pyn,.5));}
  .section.cmpos--free::after{flex-grow:calc(1 - var(--pynm,var(--pyn,.5)));}
  .section.cmpos--free > .wrap{left:var(--pxm,var(--px,50%));transform:translateX(calc(var(--pxm,var(--px,50%)) * -1));}
  /* ...and with no height of its own, back to an ordinary block. */
  .section.cmpos--free:not(.cmpos--sizedm){display:block;}
  .section.cmpos--free:not(.cmpos--sizedm)::before,.section.cmpos--free:not(.cmpos--sizedm)::after{content:none;}
}

/* =========================================================
   FORMS
   ========================================================= */
/* Full-screen image stage behind the form */
.formstage{position:relative;isolation:isolate;overflow:hidden;padding-block:clamp(64px,13vh,150px);display:grid;place-items:center;}
/* opt-in multi-step forms — one section at a time, waiver-style */
.fwiz__bar{display:none;height:6px;border-radius:100px;background:rgba(255,255,255,.18);overflow:hidden;margin-bottom:24px}
.fwiz__fill{display:block;height:100%;width:0;border-radius:inherit;background:var(--cyan);transition:width .45s var(--ease-out)}
.fwiz__nav{display:none}
.fwiz-on .fwiz__bar{display:block}
.fwiz-on .fwslide{display:none}
.fwiz-on .fwslide.is-on{display:block;animation:fwIn .4s var(--ease-out) both}
@keyframes fwIn{from{opacity:0;transform:translateX(18px)}}
.fwiz-on .fwiz__nav{display:flex;gap:10px;justify-content:space-between;margin-top:22px}
.formstage__bg{position:absolute;inset:0;z-index:-2;background-size:cover;background-position:center;}
/* Placeholder "photo" gradients — replace with a real photo via background-image */
.formstage__bg--a{background:linear-gradient(150deg,var(--charcoal),var(--navy) 60%,var(--navy));}
.formstage__bg--b{background:linear-gradient(150deg,var(--navy),var(--charcoal) 70%,var(--navy));}
.formstage__bg--c{background:linear-gradient(150deg,color-mix(in srgb,var(--navy) 78%,var(--cyan)),var(--navy));}
.formstage__bg--d{background:linear-gradient(150deg,var(--charcoal),color-mix(in srgb,var(--navy) 82%,var(--cyan)));}
.formstage__bg::after{content:"";position:absolute;inset:0;background:radial-gradient(75% 55% at 50% 0%,rgba(160,138,111,.20),transparent 60%),radial-gradient(70% 70% at 82% 100%,rgba(88,157,166,.18),transparent 60%),repeating-linear-gradient(125deg,rgba(255,255,255,.025) 0 2px,transparent 2px 26px),linear-gradient(to bottom,rgba(6,18,31,.5),rgba(6,18,31,.74));}
.formstage .wrap{width:100%;display:flex;justify-content:center;}

/* Frosted glass form card */
.form{width:100%;max-width:560px;display:grid;gap:var(--space-md);text-align:left;position:relative;color:#fff;
  background:rgba(34,32,29,.55);backdrop-filter:blur(22px) saturate(1.4);-webkit-backdrop-filter:blur(22px) saturate(1.4);
  border:1px solid rgba(255,255,255,.12);border-radius:var(--radius-card);padding:clamp(24px,4vw,46px);
  box-shadow:0 40px 90px rgba(0,0,0,.45),inset 0 1px 0 rgba(255,255,255,.10);}
.form::before{content:"";position:absolute;inset:0;border-radius:var(--radius-card);background:radial-gradient(120% 55% at 50% 0%,rgba(255,255,255,.06),transparent 60%);pointer-events:none;}
.form__badge{width:62px;height:62px;border-radius:18px;margin:0 auto 4px;display:grid;place-items:center;color:#fff;background:linear-gradient(160deg,#41382f,#22201d);box-shadow:0 0 0 1px rgba(255,255,255,.18),0 0 30px 5px rgba(214,196,170,.32),inset 0 1px 0 rgba(255,255,255,.28);}
.form__title{text-align:center;color:#fff;font-size:clamp(1.5rem,1.2rem + 1vw,2rem);}
.form__title .serif{color:var(--teal);}
.form__sub{text-align:center;color:rgba(244,238,225,.72);font-size:.95rem;margin:-2px auto 4px;max-width:42ch;line-height:1.5;}
.form .row{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-md);}
.field{display:grid;gap:6px;}
.field.full{grid-column:1/-1;}
.field label{font-family:var(--font-display);font-weight:600;font-size:.82rem;color:rgba(244,238,225,.92);}
.field .req{color:var(--cyan);}
.field input,.field select,.field textarea{font:inherit;font-size:.95rem;color:#fff;background:rgba(255,255,255,.06);border:1.5px solid rgba(255,255,255,.14);border-radius:14px;padding:.85em 1em;transition:border-color .25s,box-shadow .25s,background .25s;width:100%;}
.field input::placeholder,.field textarea::placeholder{color:rgba(244,238,225,.45);}
.field select{appearance:none;-webkit-appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23a9c0d6' stroke-width='1.6' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 1em center;padding-right:2.4em;}
.field select option{color:#22201d;}
.field textarea{min-height:128px;resize:vertical;}
.field input:focus,.field select:focus,.field textarea:focus{outline:none;border-color:var(--cyan);box-shadow:0 0 0 3px rgba(160,138,111,.3);background:rgba(255,255,255,.10);}
/* Multi-select options render as toggle pills */
.checks{display:flex;flex-wrap:wrap;gap:9px;}

/* Checkbox groups are a <fieldset>/<legend> now, so the group's question is
   announced with each option instead of floating free. The reset is because a
   browser's default fieldset border and legend indent would otherwise break
   the form's layout. */
.checkgroup{border:0;margin:0;padding:0;min-width:0;}
.checkgroup>legend{display:block;padding:0;float:left;width:100%;
  font-family:var(--font-display);font-weight:600;font-size:.82rem;
  color:rgba(244,238,225,.92);margin-bottom:6px;}
.checkgroup>legend+.checks{clear:both;}
/* Visible marker when a required group was left empty. Color is not the only
   signal — the message below it says the same thing in words. */
.checkgroup.is-bad>legend{color:#ffb4a2;}
.checkgroup.is-bad .checks{outline:2px solid rgba(255,150,130,.55);outline-offset:6px;border-radius:10px;}
.checkgroup__err{margin:9px 0 0;font-size:.82rem;font-weight:600;color:#ffb4a2;}
.checkgroup__err[hidden]{display:none;}
/* The name field's group heading is a span, not a label — it names two inputs,
   so it can't legitimately point at either. */
.namefield>.lbl{display:block;font-family:var(--font-display);font-weight:600;
  font-size:.82rem;color:rgba(244,238,225,.92);margin-bottom:6px;}
/* Announced, never shown. */
.vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0;}
.checks label{display:inline-flex;align-items:center;cursor:pointer;padding:.5em .95em;border-radius:100px;border:1.5px solid rgba(255,255,255,.26);background:rgba(255,255,255,.05);font-family:var(--font-display);font-weight:600;font-size:.86rem;color:rgba(244,238,225,.9);transition:background .2s,border-color .2s,color .2s;}
.checks label:hover{border-color:rgba(255,255,255,.5);}
.checks input{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none;}
.checks label:has(input:checked){background:var(--cyan);border-color:var(--cyan);color:#fff;}
.checks label:has(input:focus-visible){outline:2.5px solid #fff;outline-offset:2px;}
/* The consent box used to be a native checkbox wearing the text inputs' fill, and a dark
   scheme paints that as a black square with a tick nobody can see - which is what it was
   doing on the CLC newsletter. Drawn properly here instead: our own box, a clip-path tick,
   and fixed colors rather than theme tokens, because the form stage is navy in light and
   dark alike and a token that flipped would be wrong in one of them. */
.inline-check input[type=checkbox]{accent-color:var(--cyan);appearance:none;-webkit-appearance:none;
  flex:none;margin:0;padding:0;box-sizing:border-box;width:20px;height:20px;min-width:0;border-radius:6px;
  border:1.5px solid rgba(255,255,255,.45);background:rgba(255,255,255,.08);
  display:inline-grid;place-content:center;cursor:pointer;
  transition:background .15s var(--ease-out),border-color .15s var(--ease-out);}
.inline-check input[type=checkbox]:hover{border-color:rgba(255,255,255,.72);}
.inline-check input[type=checkbox]::before{content:"";width:12px;height:12px;background:#fff;
  transform:scale(0);transition:transform .16s var(--ease-out);
  clip-path:polygon(14% 44%,0 65%,50% 100%,100% 16%,80% 0%,43% 62%);}
.inline-check input[type=checkbox]:checked{background:#a08a6f;border-color:#a08a6f;}
.inline-check input[type=checkbox]:checked::before{transform:scale(1);}
.inline-check input[type=checkbox]:focus-visible{outline:2px solid #fff;outline-offset:2px;}
/* First / Last name pair */
.namefield > label{margin-bottom:2px;}
.namefield .field label.sub{font-weight:500;font-size:.78rem;color:rgba(244,238,225,.62);}
.namefield .opt{font-weight:500;color:rgba(244,238,225,.62);}
.inline-check{display:inline-flex;align-items:center;gap:10px;font-size:.9rem;color:rgba(244,238,225,.82);font-weight:500;}
.form__send{width:100%;justify-content:center;padding:1em;font-size:1rem;margin-top:4px;}
.form .hint{font-size:.8rem;color:rgba(244,238,225,.55);text-align:center;}
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden;}
.formnote{border-radius:14px;padding:var(--space-md) var(--space-lg);font-weight:600;}
.formnote.ok{background:rgba(88,157,166,.22);color:#e9e5de;border:1px solid rgba(88,157,166,.5);}
.formnote.err{background:rgba(214,75,74,.18);color:#ffd9d4;border:1px solid rgba(214,75,74,.45);}
.qlist{display:grid;gap:var(--space-sm);counter-reset:q;max-width:760px;}
.qlist li{list-style:none;display:flex;gap:var(--space-md);align-items:flex-start;background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);padding:var(--space-lg);}
.qlist li::before{counter-increment:q;content:counter(q);font-family:var(--font-serif);font-style:italic;font-size:1.5rem;color:var(--cyan);line-height:1;flex-shrink:0;}
.sgpray{max-width:760px;margin-inline:auto;margin-top:var(--space-lg);background:var(--navy);color:#fff;border-radius:var(--radius);padding:var(--space-lg);}

/* Small-group week: opener, then the passage, then the questions. The opener
   is a light card; the passage is set larger with a rule down its left edge so
   it reads as scripture being quoted rather than more instruction. */
.sgopen{max-width:760px;margin-inline:auto;margin-top:var(--space-md);padding:var(--space-md) var(--space-lg);
  background:color-mix(in srgb,var(--cyan,#a08a6f) 8%,transparent);
  border-radius:var(--radius);}
.sgopen p:last-child{margin:4px 0 0;color:var(--ink,#22201d);}

/* The passage is a reference — book and chapter — so it's set like a heading
   somebody turns to, not a block quote of the verses. */
.sgref{max-width:760px;margin-inline:auto;margin-top:var(--space-lg);}
.sgref__b{margin-top:4px;font-family:var(--font-display,Montserrat,sans-serif);
  font-size:clamp(1.25rem,1.05rem + .8vw,1.7rem);font-weight:700;line-height:1.2;
  color:var(--ink,#22201d);}
.sgref__b a{color:inherit;text-decoration:none;
  border-bottom:2px solid color-mix(in srgb,var(--cyan,#a08a6f) 45%,transparent);
  transition:border-color .16s,color .16s;}
.sgref__b a:hover{color:var(--cyan,#a08a6f);border-bottom-color:currentColor;}

/* The Sunday these questions belong to, sitting under the passage. */
.sgdate{margin-top:8px;font-size:.9rem;font-weight:600;letter-spacing:.02em;
  color:var(--muted);}
.head.center .sgdate{text-align:center;}

/* Questions folded away until asked for. A <details>, so it opens with a tap
   or the keyboard and needs no JavaScript. */
.sgcard{max-width:760px;margin-inline:auto;margin-top:var(--space-lg);border-radius:var(--radius);
  background:var(--card,#fff);
  border:1px solid color-mix(in srgb,var(--ink,#22201d) 11%,transparent);
  box-shadow:0 10px 30px -20px rgba(34,32,29,.35);
  overflow:hidden;transition:border-color .18s,box-shadow .18s;}
.sgcard[open]{border-color:color-mix(in srgb,var(--cyan,#a08a6f) 32%,transparent);
  box-shadow:0 16px 40px -22px rgba(34,32,29,.45);}

.sgcard__sum{display:flex;align-items:center;justify-content:space-between;gap:var(--space-md);
  padding:var(--space-md) var(--space-lg);cursor:pointer;list-style:none;
  -webkit-tap-highlight-color:transparent;}
.sgcard__sum::-webkit-details-marker{display:none;}
.sgcard__sum:hover{background:color-mix(in srgb,var(--cyan,#a08a6f) 5%,transparent);}
.sgcard__sum:focus-visible{outline:2.5px solid var(--cyan,#a08a6f);outline-offset:-3px;}

.sgcard__t{display:flex;flex-direction:column;gap:2px;min-width:0;}
.sgcard__lab{font-family:var(--font-display,Montserrat,sans-serif);font-weight:700;
  font-size:.72rem;letter-spacing:.16em;text-transform:uppercase;color:var(--cyan,#a08a6f);}
.sgcard__n{font-size:1.02rem;font-weight:600;color:var(--ink,#22201d);}

.sgcard__btn{flex:none;display:inline-flex;align-items:center;gap:7px;
  font-family:var(--font-display,Montserrat,sans-serif);font-weight:700;font-size:.85rem;
  color:var(--cyan,#a08a6f);padding:.5em .9em;border-radius:100px;
  background:color-mix(in srgb,var(--cyan,#a08a6f) 10%,transparent);}

/* The week's questions as a sheet of paper. The link sits beside the open/close
   control rather than inside the card, because whoever wants them printed tends
   to know that before they have read a word of them. Outlined rather than
   filled, so it never competes with the control that actually opens the card. */
.sgcard__acts{flex:none;display:inline-flex;align-items:center;gap:8px;}
.sgcard__dl{flex:none;display:inline-flex;align-items:center;gap:6px;
  font-family:var(--font-display,Montserrat,sans-serif);font-weight:700;font-size:.85rem;
  color:var(--ink-soft,#22201d);text-decoration:none;
  padding:.5em .9em;border-radius:100px;
  border:1px solid color-mix(in srgb,var(--ink,#22201d) 17%,transparent);
  transition:color .18s,border-color .18s,background-color .18s;}
.sgcard__dl:hover{color:var(--cyan,#a08a6f);
  border-color:color-mix(in srgb,var(--cyan,#a08a6f) 45%,transparent);
  background:color-mix(in srgb,var(--cyan,#a08a6f) 7%,transparent);}
.sgcard__dl:focus-visible{outline:2.5px solid var(--cyan,#a08a6f);outline-offset:2px;}
.sgcard__dl svg{flex:none;transition:transform .3s var(--ae-spring,cubic-bezier(.22,1.14,.36,1));}
.sgcard__dl:hover svg{transform:translateY(2px);}
@media(prefers-reduced-motion:reduce){.sgcard__dl:hover svg{transform:none;}}
/* Only one of the two labels is ever shown, so the button reads correctly in
   both states without any script. */
.sgcard__hide{display:none;}
.sgcard[open] .sgcard__show{display:none;}
.sgcard[open] .sgcard__hide{display:inline;}
.sgcard__chev{transition:transform .42s var(--ae-spring,cubic-bezier(.22,1.14,.36,1));}
.sgcard[open] .sgcard__chev{transform:rotate(180deg);}

.sgcard__list{transform-origin:50% 0;margin:0;padding:0 var(--space-lg) var(--space-lg);
  border-top:1px solid color-mix(in srgb,var(--ink,#22201d) 8%,transparent);
  padding-top:var(--space-md);}
.sgcard[open] .sgcard__list{animation:sgOpen .5s var(--ae-spring,cubic-bezier(.22,1.14,.36,1)) both;}
/* A little overshoot on the way in — the house spring, not the classic back-ease
   that draws attention to itself. transform-origin at the top so it unfolds
   from the summary rather than growing out of its own middle. */
@keyframes sgOpen{
  0%  {opacity:0;transform:translateY(-10px) scaleY(.97);}
  60% {opacity:1;}
  100%{opacity:1;transform:none;}
}

/* The Small Groups variant holds the whole week — title, opener, passage,
   questions and prayer — behind one button, rather than only the questions. */
.sgcard--week .sgcard__n{font-family:var(--font-display,Montserrat,sans-serif);
  font-size:1.2rem;font-weight:700;line-height:1.25;overflow-wrap:anywhere;}
.sgcard__meta{font-size:.86rem;color:var(--muted);margin-top:3px;}
.sgcard__body{transform-origin:50% 0;padding:0 var(--space-lg) var(--space-lg);
  border-top:1px solid color-mix(in srgb,var(--ink,#22201d) 8%,transparent);
  padding-top:var(--space-md);}
.sgcard[open] .sgcard__body{animation:sgOpen .5s var(--ae-spring,cubic-bezier(.22,1.14,.36,1)) both;}
/* Inside the card these sit flush — their own outer margins would double up. */
.sgcard__body .sgopen,
.sgcard__body .sgref,
.sgcard__body .sgpray{max-width:none;}
.sgcard__body .sgopen{margin-top:0;}
.sgcard__body .qlist{margin-top:6px;}
.sgcard__qlab{margin-top:var(--space-lg);}
.sgcard__more{margin-top:var(--space-lg);font-size:.9rem;font-weight:600;}
.sgcard__more a{color:var(--cyan,#a08a6f);text-decoration:none;}
.sgcard__more a:hover{text-decoration:underline;}

@media(max-width:560px){
  .sgcard__sum{flex-direction:column;align-items:flex-start;gap:10px;}
  .sgcard__acts{align-self:stretch;width:100%;}
  .sgcard__btn{flex:1 1 auto;align-self:stretch;justify-content:center;}
  .sgcard__dl{flex:none;}
  .sgcard__body{padding-left:var(--space-md);padding-right:var(--space-md);}
}
@media(prefers-reduced-motion:reduce){
  .sgcard[open] .sgcard__body{animation:none;}
}
/* The card's own height springs open too, where the browser can do it.
   A <details> normally snaps to full height and only the contents can be
   animated, which reads as a jump with a fade after it. interpolate-size lets
   height animate to and from `auto`, so the card unfolds. Everywhere else this
   block is simply ignored and the content animation above carries it. */
@supports (interpolate-size: allow-keywords){
  .sgcard{interpolate-size:allow-keywords;}
  .sgcard::details-content{
    block-size:0;overflow:hidden;
    transition:block-size .5s var(--ae-spring,cubic-bezier(.22,1.14,.36,1)),
               content-visibility .5s allow-discrete;}
  .sgcard[open]::details-content{block-size:auto;}
}

/* The questions arrive just behind the card, a few milliseconds apart, so the
   list settles rather than appearing all at once. */
.sgcard[open] .sgcard__list li{animation:sgQIn .42s var(--ae-spring,cubic-bezier(.22,1.14,.36,1)) both;}
.sgcard[open] .sgcard__list li:nth-child(1){animation-delay:.06s}
.sgcard[open] .sgcard__list li:nth-child(2){animation-delay:.10s}
.sgcard[open] .sgcard__list li:nth-child(3){animation-delay:.14s}
.sgcard[open] .sgcard__list li:nth-child(4){animation-delay:.18s}
.sgcard[open] .sgcard__list li:nth-child(5){animation-delay:.22s}
.sgcard[open] .sgcard__list li:nth-child(6){animation-delay:.26s}
.sgcard[open] .sgcard__list li:nth-child(n+7){animation-delay:.3s}
@keyframes sgQIn{from{opacity:0;transform:translateY(7px);}to{opacity:1;transform:none;}}

@media(prefers-reduced-motion:reduce){
  .sgcard__chev{transition:none;}
  .sgcard[open] .sgcard__list{animation:none;}
  .sgcard[open] .sgcard__list li{animation:none;}
  @supports (interpolate-size: allow-keywords){
    .sgcard::details-content{transition:none;}
  }
}
@media(max-width:600px){
  .sgtext__b{font-size:1rem;padding-left:var(--space-sm);}
}
.sgpray .eyebrow{color:var(--cyan);margin-bottom:6px;}
.sgpray p:last-child{margin:0;color:rgba(255,255,255,.9);line-height:1.6;}

/* Announcements — the church's news at the end of a small group evening.
   Deliberately not styled like the study sections above it: those are navy and
   full-bleed because they carry the evening, and this is a notice board. A
   quiet bordered card reads as "one more thing" rather than as a sixth part of
   the study. */
.sgann{max-width:760px;margin:clamp(26px,4vw,40px) auto 0;padding:clamp(20px,3vw,28px);
  background:color-mix(in srgb,var(--cyan) 5%,var(--cream));border:1px solid color-mix(in srgb,var(--cyan) 24%,var(--line));
  border-radius:var(--radius);}
.sgann .eyebrow{margin-bottom:10px;}
.sgann p{margin:0;color:var(--ink-soft);line-height:1.65;}
.sgann__l{margin:0;padding-left:1.15em;display:grid;gap:8px;color:var(--ink-soft);line-height:1.55;}
.sgann__l li::marker{color:var(--cyan-deep);}

/* ------------------------------------------------- an event on a ministry card
   A quiet strip at the foot of a card, only ever present when something is
   actually on. It reads as a footnote to the card rather than competing with
   the heading, because the card's job is still to describe the ministry — the
   event is the extra. */
.cardev{display:flex;flex-wrap:wrap;align-items:baseline;gap:.15em .6em;margin-top:14px;
  padding-top:12px;border-top:1px solid var(--line);text-decoration:none;color:inherit;}
.cardev__k{flex:0 0 100%;font-size:.66rem;font-weight:700;letter-spacing:.18em;
  text-transform:uppercase;color:var(--cyan-deep);}
/* secondary nudge inside the "Coming up" label - lighter and tighter so it
   reads as a hint rather than a second heading */
.cardev__hint{font-weight:600;letter-spacing:.09em;color:var(--muted);}
.cardev:hover .cardev__hint{color:var(--cyan-deep);}
.cardev__t{font-family:var(--font-display);font-weight:700;font-size:.95rem;color:var(--ink);
  line-height:1.3;}
.cardev__d{font-size:.85rem;color:var(--muted);font-variant-numeric:tabular-nums;white-space:nowrap;}
.cardev:hover .cardev__t{color:var(--cyan-deep);text-decoration:underline;text-underline-offset:2px;}
.cardev:focus-visible{outline:2.5px solid var(--cyan);outline-offset:3px;border-radius:6px;}

/* Community Life Center (staff page) */
.footer__clc{color:inherit;text-decoration:underline;text-underline-offset:2px;}

/* --- appearance switch ------------------------------------------------------
   The footer is navy in both schemes, so this is colored against the footer
   rather than against the page. Theme tokens would invert underneath it and
   put near-black type on near-black - the literals here are the same literals
   the rest of the footer already uses, and for the same reason.

   Sized off the label rather than the text: the input covers the whole pill,
   so the target is the pill, not the four letters inside it. */
/* One pill that slides, rather than three that cross-fade. The highlight is a single
   ::before on the track and the choice only moves it, which is the honest picture of what
   the control is: one setting with three positions, not three independent buttons. The
   three columns are made equal so the travel is exact arithmetic and needs no measuring
   in script. :has() reads the checked radio, so nothing has to be told when it changes -
   keyboard, click and a value restored from storage all land the same way. */
.fsch{position:relative;display:inline-grid;grid-template-columns:repeat(3,1fr);align-items:center;gap:2px;padding:3px;border-radius:100px;
  border:1px solid rgba(244,238,225,.22);background:rgba(0,0,0,.18);}
.fsch::before{content:"";position:absolute;top:3px;left:3px;z-index:0;
  width:calc((100% - 10px) / 3);height:calc(100% - 6px);border-radius:100px;background:#f4eee1;
  transform:translateX(calc(var(--i,0) * (100% + 2px)));
  transition:transform .34s var(--ease-out),background .2s var(--ease-out);}
.fsch:has(input[value="light"]:checked){--i:0;}
.fsch:has(input[value="dark"]:checked){--i:1;}
.fsch:has(input[value="auto"]:checked){--i:2;}
.fsch:has(.fsch__o:hover input:checked)::before{background:#fff;}
.fsch__o{position:relative;z-index:1;display:inline-flex;}
.fsch__o input{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:pointer;}
.fsch__o span{display:inline-flex;align-items:center;justify-content:center;width:100%;
  min-height:40px;padding:0 1em;border-radius:100px;
  font-size:.82rem;font-weight:600;line-height:1;white-space:nowrap;
  color:rgba(244,238,225,.86);
  transition:background .22s var(--ease-out),color .22s var(--ease-out);}
.fsch__o:hover input:not(:checked)+span{color:#fff;background:rgba(244,238,225,.12);}
.fsch__o input:focus-visible+span{outline:2px solid var(--footer-head);outline-offset:3px;}
.fsch__o input:checked+span{color:#22201d;}
/* Without :has() there is no track to slide, so the old fill comes back and nothing is lost. */
@supports not (selector(:has(*))){
  .fsch::before{display:none;}
  .fsch__o input:checked+span{background:#f4eee1;}
}
@media (prefers-reduced-motion:reduce){.fsch__o span{transition:none;}}

.footer__clc:hover{opacity:1;}
.clcgate{max-width:420px;margin:0 auto;background:var(--card,#fff);border:1px solid var(--line);border-radius:var(--radius-lg);box-shadow:0 14px 40px rgba(34,32,29,.08);padding:clamp(26px,5vw,40px);text-align:center;}
.clcgate h2{font-size:clamp(1.5rem,1.2rem + 1.4vw,2rem);margin-bottom:8px;}
.clcgate p{color:var(--ink-soft);margin-bottom:20px;}
.clcgate form{display:grid;gap:12px;}
.clcgate input{width:100%;padding:.85em 1em;border:1.5px solid var(--line);border-radius:12px;font:inherit;text-align:center;letter-spacing:.08em;}
.clcgate input:focus{outline:none;border-color:var(--cyan);}
.clcgate__err{background:#fdecea;color:#c0392b;border-radius:10px;padding:.6em;font-size:.9rem;}
.clc__signout{margin-top:22px;font-size:.88rem;}
.clc__signout a{color:var(--muted);text-decoration:underline;text-underline-offset:2px;}

/* =========================================================================
   CLC volunteer schedule
   -------------------------------------------------------------------------
   Two ways to read the same rotation. The week list is what somebody standing
   at the desk on a phone wants — today first, big enough to read at arm's
   length. The month grid is the wall calendar, and is also what prints.

   Both are built from the same markup so the print rules below only have to
   understand one shape.
   ========================================================================= */



/* ===========================================================
   Community Life Center, on the Serve page
   ---------------------------------------------------------------------------
   The gym desk is the one thing on this page somebody can act on the same
   minute they read about it, so it sits above the two 'here are the sorts of
   things people do here' columns rather than under them.

   A panel and not another full-width band: the page already ends on a navy
   one, and two slabs in a row stop reading as emphasis and start reading as
   wallpaper. The cyan wash is mixed into --card, so the dark scheme gets a
   deep tinted panel from the same line without a second rule.

   Two doors, because there are two people standing at it: somebody already on
   the rota who wants the week, and somebody who has never done it and needs a
   human. The first would hit the passcode screen and think they'd been turned
   away if the second were the only way through. */
.clcpitch{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-lg);
  padding:var(--space-lg) clamp(20px,3.5vw,34px);border-radius:var(--radius);
  background:color-mix(in srgb,var(--cyan) 7%,var(--card,#fff));
  border:1px solid color-mix(in srgb,var(--cyan) 22%,transparent);
  margin-bottom:var(--space-2xl);}
.clcpitch__tx{flex:1 1 320px;min-width:0;}
.clcpitch__tx h2{margin:2px 0 8px;}
.clcpitch__tx p:last-child{margin:0;color:var(--ink-soft);max-width:52ch;}
.clcpitch__go{flex:0 0 auto;display:flex;flex-wrap:wrap;gap:10px;}
@media(max-width:640px){
  .clcpitch__go{width:100%;}
  .clcpitch__go .btn{flex:1 1 100%;justify-content:center;}
}



/* ===========================================================
   The Community Life Center month, on the public page
   ---------------------------------------------------------------------------
   A wall calendar on a laptop and a list of days on a phone. Seven columns of
   booking names at 390px is not a calendar, it is a wall — so below 640 the
   grid stops being a grid and becomes what it was always describing: the days
   that have something on, in order. Empty days drop out entirely; on a rota
   that is mostly evenings, a screenful of blanks is not information.

   Surfaces come from --card so the whole thing follows the scheme without a
   second set of rules underneath. */


/* Upcoming community engagement. A list, not cards: these are six lines of
   fact — what, when, where — and six boxes around six lines of fact is
   packaging, not design. The date sits in its own column so the eye can run
   down it and stop at the one that suits. */
/* Opening hours. A short list with a live status line, and it sits above the
   calendar because "are you open now" is the question somebody arrives with;
   the month is what they read second. The status is worked out on the server
   from the same numbers the list prints, so the two cannot drift apart. */

/* The gym chips carry a time as well as a name, which is the whole reason
   this calendar exists — so unlike the ones on /calendar they are allowed
   two lines rather than being cut off mid-word. Everything else about the
   chip is the site's own. */
.cal--clc .cal__ev--clc{white-space:normal;line-height:1.25;padding-top:5px;padding-bottom:5px;}
.cal--clc .cal__ev--clc b{display:block;font-weight:800;font-variant-numeric:tabular-nums;}

/* The opening hours, printed on every day that has any, as the first chip in the cell.
   Deliberately not styled like a booking: a quieter fill and the body ink rather than the
   cyan the activities use, so "1–7pm" reads as the state of the building and not as
   another thing on. Sundays get none, which is the honest answer for a Sunday. */
.cal--clc .cal__ev--hrs{background:color-mix(in srgb,var(--ink) 7%,transparent);color:var(--muted);font-weight:700;}
.dot--hrs{background:color-mix(in srgb,var(--ink) 22%,var(--paper));}

/* The day panel. The dialog itself is the site's own - .caldial, the same one /calendar
   opens - so all that is new here is what sits inside it and how it arrives. The rows
   stagger in 45ms apart, starting 70ms after the box, which is short enough that the last
   line has landed before the box has finished settling: it reads as one movement rather
   than a panel and then a list. Transform and opacity only, so it composites, and the
   sitewide prefers-reduced-motion reset already flattens all of it to nothing. */
.clcdial__hrs{margin:0 0 var(--space-md);font-weight:800;font-size:.9rem;}
.clcdial__hrs.is-open{color:var(--cyan-deep);}
.clcdial__hrs.is-shut{color:var(--muted);}
.clcdial__none{margin:0;color:var(--muted);}
.clcday{display:flex;align-items:baseline;gap:.75em;padding:.6em .85em;border-radius:12px;background:color-mix(in srgb,var(--cyan) 12%,transparent);}
.clcday__t{flex:none;font-weight:800;font-variant-numeric:tabular-nums;font-size:.92rem;color:var(--cyan-deep);}
.clcday__n{color:var(--ink);font-weight:600;}
.caldial--clc.is-open .clcday,.caldial--clc.is-open .clcdial__none{animation:clcdayin .34s var(--ease-out) backwards;}
@keyframes clcdayin{from{opacity:0;transform:translateY(9px);}to{opacity:1;transform:none;}}
/* Out at about 70% of the way in, so dismissing feels like a decision and not a wait.
   The script hides the dialog at 200ms, which lands just after this finishes. */
.caldial--clc:not(.is-open) .caldial__box,.caldial--clc:not(.is-open) .caldial__backdrop{transition-duration:.18s;}
.cal--clc .cal__cell[data-day]:focus-visible{outline:2px solid var(--cyan);outline-offset:2px;}

/* On a phone each day is about 43px across, which will not hold a time and an activity
   stacked. Rather than invent a second layout for this one page, the chips fold to a
   single line and clip exactly as /calendar's do; the hours chip above them carries the
   when. The full string stays in the title attribute for anything reading the markup. */
@media(max-width:620px){
  .cal--clc .cal__ev--clc{white-space:nowrap;padding-top:4px;padding-bottom:4px;}
  .cal--clc .cal__ev--clc b{display:none;}
}
.clchrs{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-md) var(--space-xl);
  padding:var(--space-md) clamp(16px,3vw,26px);border-radius:var(--radius);
  background:color-mix(in srgb,var(--cyan) 6%,var(--card,#fff));
  border:1px solid color-mix(in srgb,var(--cyan) 20%,transparent);}
.clchrs__head{display:flex;align-items:center;gap:.7em;flex:none;}
.clchrs__now{display:inline-flex;align-items:center;gap:.45em;font-size:.76rem;font-weight:800;
  letter-spacing:.06em;text-transform:uppercase;color:var(--muted);}
.clchrs__now::before{content:"";width:8px;height:8px;border-radius:50%;background:currentColor;flex:none;}
.clchrs__now.is-open{color:#1c7a46;}
html.dark .clchrs__now.is-open{color:#6ddba0;}
.clchrs__l{display:flex;flex-wrap:wrap;gap:var(--space-sm) var(--space-xl);margin:0;}
.clchrs__l div{display:flex;align-items:baseline;gap:.6em;}
.clchrs__l dt{font-weight:700;font-size:.94rem;}
.clchrs__l dd{margin:0;font-size:.94rem;color:var(--ink-soft);font-variant-numeric:tabular-nums;}
@media(max-width:560px){
  .clchrs{flex-direction:column;align-items:flex-start;gap:var(--space-sm);}
  .clchrs__l{flex-direction:column;gap:5px;}
}

.ceev{list-style:none;margin:var(--space-lg) 0 0;padding:0;display:grid;gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;}
.ceev__i{display:flex;align-items:center;gap:var(--space-md);padding:14px 16px;background:var(--card,#fff);}
.ceev__d{flex:none;width:3.1em;text-align:center;line-height:1;}
.ceev__d b{display:block;font-family:var(--font-display);font-weight:800;font-size:1.32rem;
  letter-spacing:-.02em;font-variant-numeric:tabular-nums;}
.ceev__d span{display:block;margin-top:2px;font-size:.62rem;font-weight:800;
  letter-spacing:.14em;text-transform:uppercase;color:var(--cyan-deep);}
.ceev__x{display:grid;gap:2px;min-width:0;}
.ceev__x b{font-weight:700;font-size:1.02rem;line-height:1.3;}
.ceev__m{font-size:.85rem;color:var(--muted);line-height:1.35;}
@media(max-width:520px){
  .ceev__i{gap:var(--space-sm);padding:13px 14px;}
  .ceev__x b{font-size:.96rem;}
}

.clcal__bar{display:flex;flex-wrap:wrap;align-items:baseline;gap:10px;margin-bottom:var(--space-md);}
.clcal__label{font-family:var(--font-display);font-weight:800;letter-spacing:-.02em;
  font-size:clamp(1.2rem,1rem + .8vw,1.55rem);margin-right:auto;}
.clcal__note{font-size:.84rem;color:var(--muted);}

.clcal__grid{display:grid;grid-template-columns:repeat(7,1fr);gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;}
.clcal__dow{background:var(--cream);padding:8px 6px;text-align:center;
  font-size:.66rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);}
.clcal__cell{background:var(--card,#fff);min-height:106px;padding:7px 8px;}
.clcal__cell.is-out{background:color-mix(in srgb,var(--ink) 4%,var(--card,#fff));}
/* A day already gone is not the same as a day with nothing on it. Same
   treatment as a day from the month either side — present, countable, and
   plainly behind you. */
.clcal__cell.is-past{background:color-mix(in srgb,var(--ink) 4%,var(--card,#fff));}
.clcal__cell.is-past .clcal__n{color:var(--muted);opacity:.55;}
.clcal__cell.is-today{background:color-mix(in srgb,var(--cyan) 9%,var(--card,#fff));}
.clcal__n{font-family:var(--font-display);font-weight:800;font-size:.9rem;line-height:1;
  margin-bottom:6px;font-variant-numeric:tabular-nums;}
.clcal__cell.is-out .clcal__n{color:var(--muted);opacity:.55;}
.clcal__cell.is-today .clcal__n{color:var(--cyan-deep);}
.clcal__dl{display:none;}
.clcal__it{font-size:.72rem;line-height:1.3;margin-bottom:5px;}
.clcal__it:last-child{margin-bottom:0;}
.clcal__t{display:block;font-weight:700;color:var(--cyan-deep);font-variant-numeric:tabular-nums;}
.clcal__w{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.clcal__empty{padding:var(--space-lg);text-align:center;color:var(--muted);
  background:var(--card,#fff);border:1px solid var(--line);border-radius:var(--radius);}

@media(max-width:900px){ .clcal__cell{min-height:90px;} .clcal__it{font-size:.68rem;} }

@media screen and (max-width:640px){
  .clcal__grid{display:block;background:none;border:0;border-radius:0;overflow:visible;}
  .clcal__dow{display:none;}
  .clcal__cell{display:none;}
  .clcal__cell.has-on{display:block;min-height:0;padding:11px 13px;margin-bottom:8px;
    border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow-sm);}
  .clcal__cell.is-out{display:none;}
  .clcal__cell.is-today{border-color:var(--cyan);
    box-shadow:0 0 0 2px color-mix(in srgb,var(--cyan) 22%,transparent);}
  .clcal__n{display:flex;align-items:baseline;gap:.5em;font-size:.92rem;
    margin-bottom:8px;padding-bottom:7px;border-bottom:1px solid var(--line);}
  .clcal__n>span:first-child{display:none;}   /* the bare number; the row says the date in full */
  .clcal__dl{display:inline;}
  .clcal__it{display:grid;grid-template-columns:5.6em 1fr;gap:10px;font-size:.86rem;margin-bottom:6px;}
  .clcal__w{white-space:normal;overflow:visible;text-overflow:clip;}
}

.vsch__bar{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:18px;}
.vsch__title{font-family:var(--font-display);font-weight:800;font-size:clamp(1.3rem,1.1rem + .9vw,1.8rem);letter-spacing:-.02em;margin-right:auto;}
.vsch__title em{font-family:var(--font-serif);font-style:italic;font-weight:400;color:var(--cyan-deep);}
.vsch__nav{display:flex;align-items:center;gap:4px;}
.vsch__nav a,.vsch__btn{display:inline-flex;align-items:center;justify-content:center;gap:.4em;
  min-height:42px;padding:0 .95em;border-radius:100px;border:1.5px solid var(--line);background:var(--card,#fff);
  color:var(--ink);font:inherit;font-size:.9rem;font-weight:600;cursor:pointer;text-decoration:none;
  transition:border-color .18s,color .18s,background .18s;}
.vsch__nav a:hover,.vsch__btn:hover{border-color:var(--cyan);color:var(--cyan-deep);}
.vsch__btn.is-on{background:var(--navy);border-color:var(--navy);color:#fff;}

/* --- dark: the CLC volunteer schedule -------------------------------------
   The surfaces above draw on --card now, so most of this page follows the
   scheme on its own. What is left is the handful of colors that only make
   sense one way round: a selected pill that would otherwise be navy on navy,
   a dashed blank drawn in navy, and an error chip mixed for white paper. */
html.dark .vsch__btn.is-on{
  background:var(--cyan-deep);
  border-color:var(--cyan-deep);
  color:#17120c;
}
html.dark .vopen__d{
  border-bottom-color:color-mix(in srgb,var(--ink) 26%,transparent);
}
html.dark .clcgate__err{
  background:#3a1512;
  color:#ffb3aa;
}
/* A past day is dimmed rather than hidden. On white .6 still leaves a name
   legible; on a deep card it does not, so the dark scheme dims less. */
html.dark .vday.is-past{opacity:.72;}

.vsch__arrow{min-width:42px;padding:0;font-size:1.1rem;}

/* Week A / Week B. Which half of the rotation a week belongs to is the single
   most confusing thing about a fortnightly rota, so it is stated rather than
   implied, everywhere a week appears. */
.vsch__cyc{display:inline-flex;align-items:center;gap:.4em;padding:.3em .8em;border-radius:100px;
  background:color-mix(in srgb,var(--cyan) 12%,var(--snow));color:var(--cyan-deep);
  font-size:.72rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;}

/* ---- the week list ---- */
.vsch__days{display:grid;gap:12px;}
.vday{background:var(--card,#fff);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;}
.vday.is-today{border-color:var(--cyan);box-shadow:0 0 0 3px color-mix(in srgb,var(--cyan) 16%,transparent);}
.vday.is-past{opacity:.6;}
/* The hairline between the week ahead and the week behind. It only ever
   prints when both halves exist, so it never labels an empty stretch. */
.vday__earlier{margin:var(--space-sm) 0 -2px;font-size:.7rem;font-weight:800;
  letter-spacing:.12em;text-transform:uppercase;color:var(--muted);}

.vday__h{display:flex;align-items:baseline;gap:.6em;padding:12px 16px;background:var(--cream);border-bottom:1px solid var(--line);}
.vday__dow{font-family:var(--font-display);font-weight:800;font-size:1.02rem;letter-spacing:-.01em;}
.vday__date{color:var(--muted);font-size:.86rem;font-weight:600;}
.vday__flag{margin-left:auto;font-size:.74rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--cyan-deep);}
.vday__empty{padding:14px 16px;color:var(--muted);font-size:.9rem;}

.vshift{display:grid;grid-template-columns:5.6em 1fr;gap:10px;padding:11px 16px;border-top:1px solid var(--line);}
.vshift:first-child{border-top:none;}
.vshift__t{font-family:var(--font-display);font-weight:700;font-size:.86rem;color:var(--cyan-deep);
  font-variant-numeric:tabular-nums;padding-top:.15em;}
.vshift__who{display:grid;gap:6px;min-width:0;}
.vname{display:flex;align-items:center;gap:.5em;font-weight:600;font-size:.98rem;min-width:0;}
.vname__x{font-size:.72rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--cyan-deep);background:color-mix(in srgb,var(--cyan) 13%,var(--snow));
  padding:.15em .55em;border-radius:100px;flex:none;}
.vname--was{color:var(--muted);font-weight:500;font-size:.84rem;text-decoration:line-through;}
/* An unfilled slot has to look like a gap, not like a blank. It is the one
   thing on this page anybody is being asked to do something about. */
.vopen{display:flex;align-items:center;gap:.5em;font-size:.92rem;color:var(--muted);}
.vopen__d{flex:1;border-bottom:1.5px dashed color-mix(in srgb,var(--navy) 28%,var(--snow));}
.vclaim{border:1.5px solid var(--cyan);background:var(--card,#fff);color:var(--cyan-deep);border-radius:100px;
  padding:.35em 1em;font:inherit;font-size:.84rem;font-weight:700;cursor:pointer;flex:none;min-height:34px;}
.vclaim:hover{background:var(--cyan);color:#fff;}

/* ---- the month grid ---- */
.vmon{width:100%;border-collapse:collapse;table-layout:fixed;background:var(--card,#fff);
  border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;}
.vmon th{background:var(--cream);border-bottom:1px solid var(--line);padding:9px 6px;
  font-size:.7rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);}
.vmon td{border:1px solid var(--line);vertical-align:top;padding:6px 7px;height:112px;width:14.28%;}
.vmon td.is-out{background:color-mix(in srgb,var(--navy) 3%,var(--snow));}
.vmon td.is-today{background:color-mix(in srgb,var(--cyan) 8%,var(--snow));}
.vmon__n{font-family:var(--font-display);font-weight:800;font-size:.94rem;line-height:1;
  margin-bottom:5px;font-variant-numeric:tabular-nums;
  display:flex;align-items:baseline;justify-content:space-between;gap:6px;}
/* Week A / Week B, printed in the row's Sunday cell. Needs its own screen rule
   as well as the print one — without it the badge sits flush against the date
   number and reads as "26Week A". */
.vmon__dow{display:none;}
.vmon__wk{font-family:var(--font-body);font-size:.6rem;font-weight:700;letter-spacing:.1em;
  text-transform:uppercase;color:var(--cyan-deep);white-space:nowrap;}
.vmon td.is-out .vmon__n{color:var(--muted);opacity:.6;}
.vmon td.is-today .vmon__n{color:var(--cyan-deep);}
.vmon__s{display:grid;grid-template-columns:3.3em 1fr;gap:5px;margin-bottom:3px;font-size:.72rem;line-height:1.25;}
.vmon__t{font-weight:700;color:var(--cyan-deep);font-variant-numeric:tabular-nums;}
.vmon__p{min-width:0;}
.vmon__p span{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.vmon__p .is-open{color:var(--muted);font-style:italic;}
.vmon__p .is-chg{font-weight:700;color:var(--cyan-deep);}

/* ---- roster ---- */
/* The desk list is four rosters now — volunteers, substitutes, callers, prayer
   team — so each one gets a heading and its own table rather than one long run
   of names where the only clue to somebody's job was where they happened to sit. */
.vroster__h{margin:var(--space-lg) 0 var(--space-2xs);font-size:.7rem;font-weight:800;
  letter-spacing:.12em;text-transform:uppercase;color:var(--muted);
  display:flex;align-items:baseline;gap:.5em}
.vroster__h:first-of-type{margin-top:var(--space-sm)}
.vroster__h span{font-weight:700;letter-spacing:0;font-size:.72rem;
  color:var(--muted);opacity:.6;font-variant-numeric:tabular-nums}
.vroster + .vroster__h{margin-top:var(--space-xl)}
.vroster{width:100%;border-collapse:collapse;background:var(--card,#fff);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;}
.vroster th{background:var(--cream);text-align:left;padding:10px 12px;font-size:.72rem;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);border-bottom:1px solid var(--line);}
.vroster td{padding:10px 12px;border-top:1px solid var(--line);font-size:.94rem;}
.vroster td a{color:var(--cyan-deep);}
.vroster tr:first-child td{border-top:none;}

.vsch__legend{display:flex;flex-wrap:wrap;gap:14px;margin-top:14px;font-size:.82rem;color:var(--muted);}
.vsch__legend span{display:inline-flex;align-items:center;gap:.45em;}
.vsch__key{width:14px;height:14px;border-radius:4px;flex:none;}

@media(max-width:900px){
  .vmon td{height:auto;min-height:76px;}
  .vmon__s{grid-template-columns:3em 1fr;font-size:.66rem;}
}
@media(max-width:640px){
  .vsch__title{width:100%;margin-right:0;}
}

/* -- the month, on a phone ------------------------------------------------
   Seven columns of names at this width is unreadable, so the grid stops being
   a grid and becomes what it was always describing: a list of days, in order.
   Days with nothing on drop out — on a rota that is mostly Sundays, and a
   screenful of blanks is not information.

   Scoped to `screen`. The print sheet lays the month out at letter landscape,
   which is far wider than this, but an unscoped max-width query still applies
   to print on some engines and would quietly turn the wall calendar into a
   list. */
@media screen and (max-width:640px){
  .vmon{border-collapse:separate;border-spacing:0;table-layout:auto;background:none;
    border:0;box-shadow:none;}
  .vmon thead{display:none;}
  .vmon tbody,.vmon tr{display:contents;}
  .vmon td{display:none;}                       /* the empty ones, and the padding cells */
  .vmon td.has-on{display:block;width:auto;height:auto;min-height:0;
    border:1px solid var(--line);border-radius:14px;background:var(--card,#fff);
    padding:11px 13px;margin-bottom:8px;box-shadow:var(--shadow-sm);}
  .vmon td.is-out{opacity:.62;}                 /* a day from the month either side */
  .vmon td.is-today{border-color:var(--cyan);box-shadow:0 0 0 2px color-mix(in srgb,var(--cyan) 22%,transparent);}
  .vmon__n{display:flex;align-items:baseline;gap:.5em;font-size:.9rem;margin-bottom:7px;
    padding-bottom:6px;border-bottom:1px solid var(--line);}
  .vmon__n>span:first-child{display:none;}      /* the bare number; the list says the date in full */
  .vmon__dow{display:inline;font-family:var(--font-display);font-weight:800;
    letter-spacing:-.01em;color:var(--ink-strong);}
  .vmon td.is-today .vmon__dow{color:var(--cyan-deep);}
  .vmon__wk{margin-left:auto;}
  .vmon__s{grid-template-columns:4.6em 1fr;gap:9px;font-size:.86rem;margin-bottom:5px;}
  .vmon__s:last-child{margin-bottom:0;}
  .vmon__t{font-size:.8rem;}
  /* Names get their own line and stop being truncated — the whole reason the
     grid could not work here was that there was no room for them. */
  .vmon__p span{white-space:normal;overflow:visible;text-overflow:clip;}
  /* An unclaimed shift is a blank line in the grid, where the column keeps it
     aligned and a printed blank is somewhere to write a name. In a list it just
     looks like something failed to load, so here it says what it is. */
  .vmon__p .is-open{font-size:0;}
  .vmon__p .is-open::after{content:"open";font-size:.84rem;font-style:italic;color:var(--muted);}
}
@media(max-width:560px){.form .row{grid-template-columns:1fr;}.form{border-radius:22px;}}

/* =========================================================
   CALENDAR
   ========================================================= */
.cal{background:var(--paper);border:1px solid var(--line);border-radius:var(--radius-lg);overflow:hidden;box-shadow:0 14px 40px rgba(34,32,29,.06);}
.cal__bar{display:flex;align-items:center;gap:var(--space-md);padding:clamp(var(--space-md),2.4vw,var(--space-xl)) clamp(var(--space-md),3vw,var(--space-xl));}
.cal__navwrap{display:flex;gap:6px;}
.cal__nav{width:38px;height:38px;border-radius:12px;display:grid;place-items:center;border:1px solid var(--line);color:var(--ink-strong);font-size:1.3rem;line-height:1;transition:background .2s,color .2s,border-color .2s;}
.cal__nav:hover{background:var(--navy);color:#fff;border-color:var(--navy);}
.cal__title{font-family:var(--font-display);font-weight:800;font-size:clamp(1.2rem,1rem + 1vw,1.7rem);letter-spacing:-.01em;}
.cal__today{margin-left:auto;font-family:var(--font-display);font-weight:600;font-size:.85rem;color:var(--cyan-deep);border:1px solid var(--line);border-radius:100px;padding:.55em 1.2em;transition:background .2s,color .2s,border-color .2s;}
.cal__today:hover{background:var(--cyan);color:#fff;border-color:var(--cyan);}
.cal__dow{display:grid;grid-template-columns:repeat(7,1fr);padding:0 clamp(6px,1.4vw,12px);}
.cal__dow div{padding:6px;text-align:center;font-size:.68rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);}
/* minmax(0,1fr): plain 1fr means minmax(auto,1fr), whose auto minimum is the
   max-content width of the day cell - a long nowrap event chip therefore made its
   column wider than 1/7 and pushed the rest of the row sideways. */
.cal__grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:6px;padding:clamp(6px,1.4vw,12px);}
.cal__cell{min-height:122px;min-width:0;border:1px solid transparent;border-radius:14px;padding:8px;display:flex;flex-direction:column;gap:4px;transition:background .2s;}
.cal__cell:not(.cal__cell--mute):hover{background:color-mix(in srgb,var(--cyan) 4%,var(--paper));}
.cal__cell--mute{background:transparent;opacity:.45;}
.cal__num{font-family:var(--font-display);font-weight:700;font-size:.82rem;color:var(--ink-soft);width:28px;height:28px;display:grid;place-items:center;border-radius:50%;margin-bottom:1px;}
.cal__cell.is-today{background:color-mix(in srgb,var(--cyan) 7%,var(--paper));}
.cal__cell.is-today .cal__num{background:var(--cyan);color:#fff;box-shadow:0 3px 10px rgba(160,138,111,.4);}
.cal__ev{display:block;font-size:.72rem;font-weight:600;line-height:1.25;padding:4px 8px;border-radius:8px;background:color-mix(in srgb,var(--cyan) 14%,var(--paper));color:var(--cyan-deep);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-decoration:none;max-width:100%;min-width:0;transition:transform .15s var(--ease-out),filter .2s;}
a.cal__ev:hover{transform:translateY(-1px);filter:brightness(.96);}
.cal__ev[hidden],.cal__more[hidden]{display:none !important;}
.cal__ev--rec{background:repeating-linear-gradient(45deg,color-mix(in srgb,var(--navy) 8%,var(--paper)) 0 6px,color-mix(in srgb,var(--navy) 12%,var(--paper)) 6px 12px);color:var(--ink-strong);}
/* event category palette */
.ev-c1{background:#efebe6;color:#7d6a52;}
.ev-c2{background:#f5f1ee;color:#9e7f68;}
.ev-c3{background:#fde5ee;color:#bf3a6e;}
.ev-c4{background:#fbedd2;color:#a96f12;}
.ev-c5{background:#e1f3e4;color:#2c8048;}
.ev-c6{background:#f4f0eb;color:#856c53;}
.cal__more{font-size:.68rem;color:var(--muted);font-weight:600;padding-left:4px;}
.cal__legend{display:flex;gap:var(--space-xl);padding:var(--space-md) clamp(var(--space-md),3vw,var(--space-xl)) clamp(var(--space-md),2.4vw,var(--space-xl));font-size:.82rem;color:var(--muted);flex-wrap:wrap;}
.cal__legend .dot{display:inline-block;width:11px;height:11px;border-radius:4px;margin-right:7px;vertical-align:-1px;}
.cal__legend .dot--ev{background:#cbbfaf;}
.cal__legend .dot--rec{background:repeating-linear-gradient(45deg,color-mix(in srgb,var(--navy) 25%,#fff) 0 4px,color-mix(in srgb,var(--navy) 40%,#fff) 4px 8px);}
@media(max-width:680px){
  .cal__grid{gap:3px;padding:6px;}
  .cal__cell{min-height:62px;padding:5px;gap:3px;border-radius:9px;}
  .cal__num{font-size:.76rem;width:22px;height:22px;}
  /* On a phone every event used to collapse to a 7px colored stub — the title
   was still in the markup, rendered at font-size:0, so the calendar showed a
   stack of unlabelled bars and people could not tell what was on. The text
   comes back. A seventh of a phone screen is only about six characters, so
   what does not fit fades out at the right edge rather than being cut with an
   ellipsis: a chip never leaves its own day, so nothing can ever overlap the
   day beside it. The fade is applied only to chips that actually overflow —
   see site.js — because masking one that fits would dim the end of a word
   that had every right to be there. */
.cal__more{font-size:.55rem;padding-left:2px;white-space:nowrap;}
  .cal__ev{font-size:.58rem;line-height:1.5;height:auto;padding:1px 4px;border-radius:5px;
  white-space:nowrap;overflow:hidden;text-overflow:clip;}
.cal__ev.is-cut{-webkit-mask-image:linear-gradient(to right,#000 calc(100% - 11px),transparent);
  mask-image:linear-gradient(to right,#000 calc(100% - 11px),transparent);}
  .cal__more{font-size:.58rem;}
  .cal__dow div{font-size:.58rem;padding:6px 2px;}
}

/* ===== Serve ROA opportunity grid ===== */
.srgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,290px),1fr));gap:18px;margin-top:var(--space-xl);}
.srcard{--ec:#a08a6f;position:relative;background:#fff;border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;box-shadow:0 8px 26px rgba(34,32,29,.05);transition:transform .3s var(--ease-out),box-shadow .3s;}
.srcard:hover{transform:translateY(-4px);box-shadow:0 18px 40px rgba(34,32,29,.12);}
.srcard__img{aspect-ratio:16/10;background:linear-gradient(150deg,color-mix(in srgb,var(--ec) 62%,#fff),var(--ec));background-size:cover;background-position:center;transition:transform .6s var(--ease-out);}
.srcard:hover .srcard__img{transform:scale(1.06);}
.srcard__in{position:relative;z-index:1;background:#fff;padding:16px 20px 20px;}
.srcard h3{display:flex;align-items:center;gap:.55em;font-size:1.12rem;color:var(--ink-strong);line-height:1.25;}
.srcard h3::before{content:"";flex:none;width:9px;height:9px;border-radius:50%;background:var(--ec);}
.srcard__body{margin-top:10px;color:var(--ink-soft);font-size:.92rem;line-height:1.6;}
/* lively accent palette, matching the calendar chips + menu dots */
.srgrid>article:nth-child(6n+1){--ec:#a08a6f;}
.srgrid>article:nth-child(6n+2){--ec:#9e7f68;}
.srgrid>article:nth-child(6n+3){--ec:#2c8048;}
.srgrid>article:nth-child(6n+4){--ec:#e0a23b;}
.srgrid>article:nth-child(6n+5){--ec:#bf3a6e;}
.srgrid>article:nth-child(6n+6){--ec:#856c53;}
.srreg{display:flex;flex-wrap:wrap;gap:12px;margin-top:var(--space-lg);}

/* ===== FLC Waiver wizard ===== */
.waiver{max-width:540px;margin-inline:auto;background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg);box-shadow:0 18px 50px rgba(34,32,29,.1);padding:clamp(20px,5vw,34px);}
.waiver__bar{height:6px;border-radius:100px;background:color-mix(in srgb,var(--navy) 10%,#fff);overflow:hidden;margin-bottom:clamp(20px,5vw,30px);}
.waiver__fill{height:100%;width:0;border-radius:100px;background:var(--cyan);transition:width .45s var(--ease-out);}
.wslide{display:none;}
.wslide.is-active{display:block;animation:wslidein .4s var(--ease-out);}
@keyframes wslidein{from{opacity:0;transform:translateY(12px);}to{opacity:1;transform:none;}}
.wslide h2{font-size:clamp(1.4rem,1.2rem + 1.4vw,2rem);color:var(--ink-strong);letter-spacing:-.02em;line-height:1.15;}
.wsub{margin-top:8px;color:var(--ink-soft);font-size:.95rem;}
.waiver label{display:block;margin-top:16px;font-weight:600;font-size:.85rem;color:var(--ink-strong);}
.wopt-note{font-weight:400;color:var(--muted);}
.waiver label input[type=text],.waiver label input[type=email],.waiver label input[type=tel]{display:block;width:100%;margin-top:6px;padding:.85em 1em;border:1.5px solid var(--line);border-radius:12px;font:inherit;background:var(--snow);transition:border-color .2s,background .2s;}
.waiver label input:focus{outline:none;border-color:var(--cyan);background:#fff;}
.wrow2{display:grid;grid-template-columns:1fr 1fr;gap:14px;}
@media(max-width:460px){.wrow2{grid-template-columns:1fr;}}
.wchoice{display:grid;gap:14px;margin-top:clamp(20px,5vw,28px);}
.wopt{display:flex;flex-direction:column;align-items:flex-start;gap:3px;text-align:left;width:100%;padding:18px 20px;border:1.5px solid var(--line);border-radius:var(--radius-card);background:var(--snow);cursor:pointer;transition:border-color .2s,background .2s,transform .15s var(--ease-out);}
.wopt strong{font-size:1.1rem;color:var(--ink-strong);}
.wopt small{color:var(--muted);font-size:.85rem;}
.wopt:hover,.wopt:active{border-color:var(--cyan);background:#fff;transform:translateY(-2px);}
.wterms{margin-top:14px;max-height:300px;overflow-y:auto;padding:16px 18px;border:1px solid var(--line);border-radius:12px;background:var(--snow);font-size:.88rem;line-height:1.6;color:var(--ink-soft);-webkit-overflow-scrolling:touch;}
.wterms p{margin-bottom:10px;}
.wcheck{display:flex;align-items:flex-start;gap:10px;margin-top:18px;font-weight:500;font-size:.9rem;color:var(--ink-strong);cursor:pointer;}
.wcheck input{margin-top:2px;width:20px;height:20px;flex-shrink:0;accent-color:var(--cyan);}
.wsign{position:relative;margin-top:14px;border:1.5px solid var(--line);border-radius:14px;background:var(--snow);overflow:hidden;}
#sigpad{display:block;width:100%;height:200px;touch-action:none;cursor:crosshair;}
.wsign__clear{position:absolute;top:8px;right:8px;border:1px solid var(--line);background:#fff;color:var(--navy);font:600 .75rem/1 var(--font-display);padding:.5em .8em;border-radius:100px;cursor:pointer;}
.wslide[data-step=done]{text-align:center;}
.wdone{width:64px;height:64px;border-radius:50%;background:var(--cyan);color:#fff;display:grid;place-items:center;font-size:2rem;margin:6px auto 16px;}
.waiver__nav{display:flex;justify-content:space-between;gap:12px;margin-top:clamp(22px,5vw,30px);}
.waiver__nav .btn{flex:1;justify-content:center;}
.wmsg{margin-top:14px;color:#c0392b;font-weight:600;font-size:.9rem;min-height:1.2em;text-align:center;}

/* ===== Day modal ===== */
.cal__cell[data-day]{cursor:pointer;}
.cal__cell[data-day] .cal__ev{pointer-events:none;}
.caldial[hidden]{display:none;}
.caldial{position:fixed;inset:0;z-index:1000;display:grid;place-items:center;padding:20px;}
.caldial__backdrop{position:absolute;inset:0;background:rgba(7,18,33,.55);opacity:0;transition:opacity .22s var(--ease-out);}
/* Blur the page itself (real filter) — reliable where backdrop-filter misses
   compositing layers like animated cards. The dialog is moved out of <main>. */
main{transition:filter .24s var(--ease-out);}
html.caldial-open main{filter:blur(6px);}
.caldial.is-open .caldial__backdrop{opacity:1;}
.caldial__box{position:relative;width:min(440px,100%);max-height:84vh;overflow:auto;background:var(--paper);border-radius:var(--radius-card);box-shadow:0 40px 90px rgba(20,18,16,.42);padding:clamp(20px,3vw,30px);transform:translateY(14px) scale(.98);opacity:0;transition:transform .26s var(--ease-out),opacity .26s var(--ease-out);}
.caldial.is-open .caldial__box{transform:none;opacity:1;}
.caldial__x{position:absolute;top:14px;right:14px;width:34px;height:34px;border-radius:50%;border:none;background:color-mix(in srgb,var(--navy) 7%,var(--paper));color:var(--ink-strong);font-size:1.4rem;line-height:1;cursor:pointer;display:grid;place-items:center;transition:background .2s;}
.caldial__x:hover{background:color-mix(in srgb,var(--navy) 14%,var(--paper));}
.caldial__date{font-family:var(--font-display);font-weight:800;font-size:1.25rem;color:var(--ink-strong);letter-spacing:-.01em;margin-bottom:var(--space-md);padding-right:34px;}
.caldial__list{display:flex;flex-direction:column;gap:10px;}
.caldayev{display:grid;grid-template-columns:1fr auto;align-items:center;gap:5px 12px;text-decoration:none;border:1px solid var(--line);border-radius:14px;padding:12px 14px;transition:border-color .2s,background .2s,transform .15s var(--ease-out);}
.caldayev:not(.caldayev--static):hover{border-color:color-mix(in srgb,var(--cyan) 50%,var(--line));background:color-mix(in srgb,var(--cyan) 4%,var(--paper));}
.caldayev--static{cursor:default;}
.caldayev__chip{grid-column:1;justify-self:start;display:inline-block;font-weight:600;font-size:.82rem;line-height:1.3;padding:5px 11px;border-radius:9px;background:color-mix(in srgb,var(--cyan) 14%,var(--paper));color:var(--cyan-deep);}
.caldayev__meta{grid-column:1;font-size:.82rem;color:var(--muted);}
.caldayev__cat{grid-column:1;font-size:.64rem;letter-spacing:.1em;text-transform:uppercase;font-weight:700;color:var(--cyan-deep);}
.caldayev__go{grid-column:2;grid-row:1/span 3;align-self:center;color:var(--cyan-deep);font-size:1.15rem;}
.caldial__empty{color:var(--muted);padding:6px 0;}
.caldial__all{width:100%;justify-content:center;margin-top:var(--space-lg);}

/* ===== Event detail page ===== */
.eventpage{display:grid;grid-template-columns:1fr clamp(260px,30%,340px);gap:clamp(var(--space-lg),4vw,var(--space-3xl));align-items:start;}
.eventpage__body{white-space:normal;}
.eventpage__cta{display:flex;gap:var(--space-md);flex-wrap:wrap;margin-top:var(--space-xl);}
.eventcard{background:var(--paper);border:1px solid var(--line);border-radius:var(--radius-lg);padding:clamp(var(--space-lg),2.5vw,var(--space-xl));display:grid;gap:var(--space-lg);box-shadow:0 14px 40px rgba(34,32,29,.06);position:sticky;top:96px;}
.eventcard__row{display:flex;gap:14px;align-items:flex-start;}
.eventcard__ic{flex:none;width:40px;height:40px;border-radius:12px;display:grid;place-items:center;background:color-mix(in srgb,var(--cyan) 12%,var(--snow));color:var(--cyan-deep);}
.eventcard__ic svg{width:20px;height:20px;}
.eventcard__k{display:block;font-size:.68rem;letter-spacing:.12em;text-transform:uppercase;font-weight:700;color:var(--muted);margin-bottom:2px;}
.eventcard__row b{font-family:var(--font-display);font-weight:600;color:var(--ink-strong);font-size:.98rem;line-height:1.3;}
@media(max-width:760px){.eventpage{grid-template-columns:1fr;}.eventcard{position:static;order:-1;}}

/* =========================================================
   MOTION (progressive enhancement)
   Only hide pre-animation when JS marks <html class="motion">
   ========================================================= */
.motion [data-reveal]{opacity:0;}
.motion [data-reveal-group]>*{opacity:0;}
/* letter-assemble reveals: characters are split at runtime and animate in sequence */
.chw{display:inline-block;white-space:nowrap;}
.chr{display:inline-block;}
.motion [data-kenburns] .fill{transform:scale(1.12);}

/* =========================================================
   RESPONSIVE
   ========================================================= */
@media(max-width:960px){
  .hero__grid{grid-template-columns:1fr;}
  .hero__right{min-height:380px;}
  .split,.split.rev .split__media,.times__grid{grid-template-columns:1fr;}
  .split.rev .split__media{order:0;}
  .gallery{grid-template-columns:repeat(2,1fr);}
  .footer__grid{grid-template-columns:1fr 1fr;}
}
/* ===== Mobile bottom bar + full-menu overlay ===== */
/* The opacity here is load-bearing, not taste. iOS does not re-sample what is
   behind a fixed, backdrop-filtered element while the page is flinging, so the
   bar shows a STALE blur of where the page used to be — which is exactly what
   reads as it drifting or scrolling with the content. At .46 you were mostly
   looking at that stale copy; at .86 a dropped sample is just a solid bar. */
.botbar{display:none;position:fixed;left:50%;bottom:16px;transform:translateX(-50%);z-index:200;align-items:stretch;gap:2px;background:rgba(20,28,40,.86);backdrop-filter:blur(14px) saturate(1.35);-webkit-backdrop-filter:blur(14px) saturate(1.35);border:1px solid rgba(255,255,255,.18);border-radius:100px;padding:7px;box-shadow:0 18px 45px rgba(20,18,16,.34);transition:transform .45s var(--ease-out),opacity .4s;max-width:calc(100vw - 22px);}
.botbar.hide{transform:translateX(-50%) translateY(170%);}
/* Same journey as .hide, its own class: scrolling and the keyboard both want
   the bar gone, and sharing one class means whichever finishes second puts it
   back while the other still wants it away. */
.botbar.hide-kb{transform:translateX(-50%) translateY(170%);}   /* slide only — keeps the blur from snapping */
.botbar__item{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;min-width:60px;padding:8px 10px;border-radius:100px;border:none;background:none;color:rgba(244,238,225,.7);font-family:var(--font-display);font-weight:600;font-size:.64rem;letter-spacing:.02em;cursor:pointer;transition:color .25s,background .25s,transform .22s var(--ease-out);text-decoration:none;}
.botbar__item:active{transform:scale(.86);transition-duration:.1s;}
.botbar__item svg,.botbar__item span{position:relative;z-index:1;}
/* soft chip behind the active tab — one shared pill, positioned by JS, slides between tabs */
.botbar__pill{position:absolute;left:0;top:0;width:0;height:0;border-radius:100px;background:rgba(255,255,255,.16);
  border:1px solid rgba(255,255,255,.14);z-index:0;opacity:0;transform:translate(0,0);
  transition:transform .4s cubic-bezier(.65,0,.35,1),width .4s cubic-bezier(.65,0,.35,1),height .4s cubic-bezier(.65,0,.35,1);}
@media (prefers-reduced-motion:reduce){.botbar__pill{transition:none;}}
.botbar__item svg{width:23px;height:23px;}
.botbar__item span{line-height:1;}
.botbar__item:hover,.botbar__item.is-active{color:#fff;}
.botbar__item--give:hover{color:#fff;}
.botbar__more .ic-x{display:none;}
body.menu-open .botbar__more .ic-menu{display:none;}
body.menu-open .botbar__more .ic-x{display:block;}
body.menu-open .botbar__more{color:#fff;}
/* Narrow phones: let the five tabs share the width evenly instead of overflowing. */
@media(max-width:400px){
  html.app-mode .botbar,.botbar{width:calc(100vw - 20px);max-width:420px;gap:0;padding:6px;justify-content:space-between;}
  .botbar__item{flex:1 1 0;min-width:0;padding:8px 4px;font-size:.58rem;gap:2px;}
  .botbar__item svg{width:21px;height:21px;}
}
@media(max-width:340px){
  .botbar__item{font-size:.54rem;padding:8px 2px;}
  .botbar__item svg{width:20px;height:20px;}
}

.mobmenu{display:none;position:fixed;top:0;left:0;right:0;height:100vh;height:100dvh;z-index:190;background:var(--cream);flex-direction:column;padding:clamp(20px,6vw,40px) clamp(20px,6vw,40px) 116px;overflow-y:auto;-webkit-overflow-scrolling:touch;opacity:0;visibility:hidden;transform:translateY(14px);transition:opacity .35s var(--ease-out),transform .35s var(--ease-out),visibility .35s;}
body.menu-open .mobmenu{opacity:1;visibility:visible;transform:none;}
/* overflow:hidden on <body> does not stop iOS scrolling the document. In the
   installed app the page behind an open menu still moved under your finger -
   you could read Wednesday's events through the panel. position:fixed does
   stop it, and it is what the small-group modal (body.sgm-open) has always
   used here. The top offset is written by setMenu() so pinning the page does
   not throw you back to the top, and is put back on close.
   overscroll-behavior on the panel stops the other half of it: a scroll that
   reaches the end of the menu chaining into the page underneath. */
body.menu-open{position:fixed;left:0;right:0;width:100%;overflow:hidden;overscroll-behavior:none;}
.mobmenu,.mobmenu__panel{overscroll-behavior:contain;}
/* staggered reveal of menu items */
.mobmenu .menu>li,.mobmenu__actions{opacity:0;transform:translateY(12px);transition:opacity .45s var(--ease-out),transform .45s var(--ease-out);}
body.menu-open .mobmenu .menu>li,body.menu-open .mobmenu__actions{opacity:1;transform:none;}
body.menu-open .mobmenu .menu>li:nth-child(1){transition-delay:.06s;}
body.menu-open .mobmenu .menu>li:nth-child(2){transition-delay:.10s;}
body.menu-open .mobmenu .menu>li:nth-child(3){transition-delay:.14s;}
body.menu-open .mobmenu .menu>li:nth-child(4){transition-delay:.18s;}
body.menu-open .mobmenu .menu>li:nth-child(5){transition-delay:.22s;}
body.menu-open .mobmenu .menu>li:nth-child(6){transition-delay:.26s;}
body.menu-open .mobmenu .menu>li:nth-child(7){transition-delay:.30s;}
body.menu-open .mobmenu__actions{transition-delay:.34s;}
@media(prefers-reduced-motion:reduce){.mobmenu .menu>li,.mobmenu__actions{transition:none;transform:none;opacity:1;}}
.mobmenu__head{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--space-md);}
html:not(.app-mode) .mobmenu__head{display:none;}       /* floating pill already shows the logo + close */
html:not(.app-mode) .mobmenu{padding-top:86px;}         /* clear the floating pill */
.mobmenu__head .brand__mark{box-shadow:0 2px 8px rgba(34,32,29,.14);}
.mobmenu__head .brand__name{color:var(--ink-strong);}
.mobmenu .menu{flex-direction:column;align-items:stretch;gap:0;width:100%;position:static;margin:0;}
.mobmenu .menu>li{border-bottom:1px solid var(--line);}
.mobmenu .menu>li>a,.mobmenu .menu>li>button{width:100%;justify-content:space-between;padding:.95em .3em;font-size:1.2rem;border-radius:var(--radius-sm);color:var(--ink-strong);font-weight:600;background:none;}
.mobmenu .menu>li>a[aria-current="page"],.mobmenu .menu>li>button[aria-current="page"]{color:var(--cyan-deep);}
.mobmenu .caret{margin-left:auto;width:11px;height:11px;}
.mobmenu .dropdown{position:static;translate:none;transform:none;opacity:1;visibility:visible;box-shadow:none;border:none;background:transparent;backdrop-filter:none;-webkit-backdrop-filter:none;padding:0 0 var(--space-sm) var(--space-md);min-width:0;max-height:0;overflow:hidden;transition:max-height .38s var(--ease-out),padding .38s var(--ease-out);}
.mobmenu .dropdown::before{display:none;}
.mobmenu .dropdown a{color:var(--ink-soft);}
.mobmenu .has-dropdown.open .dropdown{max-height:760px;}
.mobmenu .caret{transition:transform .35s var(--ease-out);}
.mobmenu .has-dropdown.open .caret{transform:rotate(180deg);}
/* folder items drift in with a gentle stagger once the folder is open */
.mobmenu .dropdown a{opacity:0;transform:translateX(-8px);transition:opacity .22s ease,transform .3s var(--ease-out),background .2s,color .2s;}
.mobmenu .has-dropdown.open .dropdown a{opacity:1;transform:none;}
.mobmenu .has-dropdown.open .dropdown li:nth-child(2) a{transition-delay:.03s;}
.mobmenu .has-dropdown.open .dropdown li:nth-child(3) a{transition-delay:.06s;}
.mobmenu .has-dropdown.open .dropdown li:nth-child(4) a{transition-delay:.09s;}
.mobmenu .has-dropdown.open .dropdown li:nth-child(5) a{transition-delay:.12s;}
.mobmenu .has-dropdown.open .dropdown li:nth-child(6) a{transition-delay:.15s;}
.mobmenu .has-dropdown.open .dropdown li:nth-child(7) a{transition-delay:.18s;}
.mobmenu .has-dropdown.open .dropdown li:nth-child(8) a{transition-delay:.21s;}
@media(prefers-reduced-motion:reduce){.mobmenu .dropdown,.mobmenu .dropdown a,.mobmenu .caret{transition:none !important;}}
.mobmenu__actions{margin-top:auto;padding-top:var(--space-lg);display:grid;gap:var(--space-sm);}
.mobmenu__actions .btn{width:100%;justify-content:center;}

/* ===== Mobile browser menu — frosted grouped cards (Craft-style) ===== */
html:not(.app-mode) .mobmenu{background:linear-gradient(180deg,rgba(250,247,242,.64),rgba(243,237,229,.76));backdrop-filter:blur(30px) saturate(1.5);-webkit-backdrop-filter:blur(30px) saturate(1.5);}
.mobmenu .menu{gap:12px;}
.mobmenu .menu>li{border:0;border-radius:22px;overflow:hidden;background:rgba(255,255,255,.46);}
.mobmenu a,.mobmenu button{-webkit-tap-highlight-color:transparent;}
.mobmenu .menu>li>a,
.mobmenu .menu>li>button{display:flex;align-items:center;gap:.6em;width:100%;justify-content:space-between;padding:1.05em 1.15em;font-size:1.15rem;font-weight:700;color:var(--ink-strong);border-radius:0;background:none;}
/* direct-link items get a ">" chevron like the reference */
.mobmenu .menu>li:not(.has-dropdown)>a::after{content:"";width:9px;height:9px;border-right:2.2px solid var(--muted);border-top:2.2px solid var(--muted);transform:rotate(45deg);margin-left:auto;flex-shrink:0;}
.mobmenu .caret{width:14px;height:9px;color:var(--muted);}
/* expanded group: divider + indented list with colored dots */
.mobmenu .dropdown{padding:0 1.15em;}
.mobmenu .has-dropdown.open .dropdown{padding-top:.35em;padding-bottom:.7em;}
.mobmenu .dropdown a{display:flex;align-items:center;gap:.75em;padding:.6em 0;font-size:1.05rem;font-weight:700;color:var(--ink-strong);}
.mobmenu .dropdown a::before{content:"";width:9px;height:9px;border-radius:50%;flex-shrink:0;background:var(--muted);}
/* dots cycle through the site's blue family */
.mobmenu .dropdown li:nth-child(6n+1) a::before{background:#a08a6f;}
.mobmenu .dropdown li:nth-child(6n+2) a::before{background:#22201d;}
.mobmenu .dropdown li:nth-child(6n+3) a::before{background:#d9c4a8;}
.mobmenu .dropdown li:nth-child(6n+4) a::before{background:#856c53;}
.mobmenu .dropdown li:nth-child(6n+5) a::before{background:#92816c;}
.mobmenu .dropdown li:nth-child(6n+6) a::before{background:#b4a087;}
/* springy, staggered pop when a group is expanded (liquid-glass feel) */
.mobmenu .dropdown li{opacity:0;transform:translateY(-8px) scale(.96);transform-origin:left center;transition:opacity .28s ease,transform .5s cubic-bezier(.22,1.14,.36,1);}
.mobmenu .has-dropdown.open .dropdown li{opacity:1;transform:none;}
.mobmenu .has-dropdown.open .dropdown li:nth-child(1){transition-delay:.05s;}
.mobmenu .has-dropdown.open .dropdown li:nth-child(2){transition-delay:.10s;}
.mobmenu .has-dropdown.open .dropdown li:nth-child(3){transition-delay:.15s;}
.mobmenu .has-dropdown.open .dropdown li:nth-child(4){transition-delay:.20s;}
.mobmenu .has-dropdown.open .dropdown li:nth-child(5){transition-delay:.25s;}
.mobmenu .has-dropdown.open .dropdown li:nth-child(6){transition-delay:.30s;}
.mobmenu .has-dropdown.open .dropdown li:nth-child(7){transition-delay:.35s;}
.mobmenu .has-dropdown.open .dropdown li:nth-child(8){transition-delay:.40s;}
/* the chevron gives a tiny spring overshoot too */
.mobmenu .has-dropdown>button .caret{transition:transform .24s var(--ae-out,cubic-bezier(.16,1,.3,1));}
@media(prefers-reduced-motion:reduce){.mobmenu .dropdown li{transition:none;transform:none;opacity:1;}}
/* actions: one prominent pill + a plain text link */
.mobmenu__actions{gap:8px;}
.mobmenu__actions .btn--accent{order:2;border-radius:100px;padding:1.05em;font-size:1.05rem;box-shadow:0 12px 30px rgba(160,138,111,.28);}
.mobmenu__actions .btn--member{order:1;border-radius:100px;padding:1.05em;font-size:1.05rem;box-shadow:0 12px 30px rgba(34,32,29,.26);}
.mobmenu__actions .btn--ghost{order:2;background:none;border:none;box-shadow:none;color:var(--ink-strong);font-weight:700;}

@media(max-width:1040px){
  .navshell{display:none;}
  .mobtop{display:flex;}            /* traditional top bar for the mobile browser */
  .mobmenu{display:flex;}
  .banner__inner{padding-top:clamp(82px,13vw,104px);}
  .hero__frame{padding-top:clamp(78px,12vw,108px);}
  .hero__left{padding-top:clamp(40px,8vw,72px);}
}
@media(max-width:560px){
  .footer__grid{grid-template-columns:1fr;}
  .gallery{grid-template-columns:1fr 1fr;}
  .gallery .img.big{grid-column:span 2;grid-row:span 1;}
  .hero__card{position:static;margin:18px;max-width:none;}
}
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms !important;transition-duration:.01ms !important;scroll-behavior:auto !important;}
  .motion [data-reveal]{opacity:1 !important;}
  .motion .img[data-kenburns] .fill{transform:none !important;}
}

/* =========================================================
   LARGE DISPLAYS — widen the content column and scale type up
   so the design fills big monitors instead of sitting tiny in
   the middle. rem-based sizing follows the html font-size bump.
   ========================================================= */
@media(min-width:1700px){
  :root{--maxw:1480px;--space-3xl:76px;--space-4xl:112px;}
  html{font-size:17.5px;}
}
@media(min-width:2200px){
  :root{--maxw:1720px;--space-2xl:60px;--space-3xl:88px;--space-4xl:132px;}
  html{font-size:19.5px;}
}
@media(min-width:2900px){   /* 4K and up */
  :root{--maxw:2080px;--space-2xl:72px;--space-3xl:108px;--space-4xl:160px;}
  html{font-size:22.5px;}
}
@media(min-width:3700px){   /* 5K / ultrawide */
  :root{--maxw:2400px;}
  html{font-size:25px;}
}

/* =========================================================
   REFINEMENTS — legibility, photo cleanup, varied hovers
   ========================================================= */
:root{
  /* a brighter cyan used only for text sitting on dark navy/photos */
  --cyan-bright:color-mix(in srgb,var(--cyan) 52%,white);
}

/* ---- 1. Legibility: brighten blue text & strengthen scrims on dark ---- */
.banner__scrim{background:linear-gradient(165deg,rgba(10,28,52,.88),rgba(10,28,52,.66) 50%,rgba(8,20,38,.92));}
.banner h1{text-shadow:0 2px 22px rgba(7,18,33,.5);}
.banner h1 .serif{color:var(--cyan-bright);}
.banner p{color:rgba(250,247,242,.96);text-shadow:0 1px 12px rgba(7,18,33,.4);}
.banner .eyebrow{color:var(--cyan-bright) !important;text-shadow:0 1px 10px rgba(7,18,33,.5);}
.banner .crumb,.banner .crumb a{color:rgba(250,247,242,.82);}
.banner .crumb a:hover{color:var(--cyan-bright);}
/* blue-on-navy text elsewhere */
.band .quote .hl,.invite--navy h2 .serif{color:var(--cyan-bright);}
.stat .n{color:var(--cyan-bright);}
.times__list .val{color:var(--cyan-bright);}
.footer a:hover{color:var(--cyan-bright);}

/* ---- 2. No badges over real photos ---- */
.img.has-photo .tag,.img.has-photo .ico{display:none !important;}

/* ---- 3. Varied hover micro-interactions ---- */
/* Feature cards: lighter lift + growing accent underline + image push-in */
.card{position:relative;transition:transform .45s var(--ease-out),box-shadow .45s var(--ease-out);}
.card::after{content:"";position:absolute;left:0;right:0;bottom:0;height:3px;background:var(--cyan);transform:scaleX(0);transform-origin:left;transition:transform .45s var(--ease-out);}
.card:hover{transform:translateY(-5px);box-shadow:var(--shadow-md);}
.card:hover::after{transform:scaleX(1);}
.card:hover h3{color:var(--cyan-deep);}
.card h3{transition:color .35s ease;}
.card:hover .img.has-photo>.ph{transform:scale(1.06);}

/* Rail cards: image zoom + title shifts to cyan (no shadow) */
.rcard .img{transition:transform .5s var(--ease-out);}
.rcard h3{transition:color .35s ease;}
.rcard:hover .img.has-photo>.ph{transform:scale(1.06);}
.rcard:hover h3{color:var(--cyan-deep);}

/* Video cards: outline highlight + image zoom instead of heavy shadow */
.vidcard{transition:transform .4s var(--ease-out),box-shadow .4s var(--ease-out),border-color .4s ease;}
.vidcard:hover{transform:translateY(-4px);box-shadow:var(--shadow-md);border-color:color-mix(in srgb,var(--cyan) 55%,transparent);}

/* Sermon/event rows: slide right + growing left accent bar */
.vrow{position:relative;overflow:hidden;transition:transform .4s var(--ease-out),box-shadow .4s var(--ease-out);}
.vrow::before{content:"";position:absolute;left:0;top:0;bottom:0;width:4px;background:var(--cyan);transform:scaleY(0);transform-origin:top;transition:transform .4s var(--ease-out);z-index:3;}
.vrow:hover{transform:translateX(6px);box-shadow:var(--shadow-md);}
.vrow:hover::before{transform:scaleY(1);}
.vrow h3{transition:color .35s ease;}
.vrow:hover h3{color:var(--cyan-deep);}

/* People: subtle image zoom + name shifts to cyan */
.person .img{overflow:hidden;}
.person .img.has-photo>.ph{transition:transform .6s var(--ease-out);}
.person:hover .img.has-photo>.ph{transform:scale(1.06);}
.person h3{transition:color .35s ease;}
.person:hover h3{color:var(--cyan-deep);}

/* Quick "go" link arrow already slides; add color deepen */
.card:hover .go{color:var(--cyan);}

@media(prefers-reduced-motion:reduce){
  .card:hover,.rcard:hover,.vrow:hover,.vidcard:hover{transform:none;}
  .card::after,.vrow::before{transition:none;}
}

/* =========================================================
   BATCH 2 — banner cards, home hero, accordion spring, etc.
   ========================================================= */

/* Full-color header photo (no tint) + frosted text card */
.banner--photo::after{display:none;}
.banner--photo .banner__photo{filter:none;}
.banner__inner{padding-top:clamp(132px,16vw,200px);}
.banner__card{
  max-width:660px;background:rgba(34,32,29,.44);
  backdrop-filter:blur(16px) saturate(1.4);-webkit-backdrop-filter:blur(16px) saturate(1.4);
  border:1px solid rgba(255,255,255,.18);border-radius:var(--radius-card);
  padding:clamp(22px,3vw,38px);box-shadow:0 30px 70px rgba(20,18,16,.34);
}
.banner__card .crumb,.banner__card .crumb a{color:rgba(250,247,242,.85);text-shadow:none;}
.banner__card .crumb a:hover{color:var(--cyan-bright);}
.banner__card .eyebrow{color:var(--cyan-bright);text-shadow:none;}
.banner__card h1{color:#fff;text-shadow:none;margin:0;}
.banner__card h1 .serif{color:var(--cyan-bright);}
.banner__card p{color:rgba(250,247,242,.93);text-shadow:none;margin-top:var(--space-md);}
.banner__cta{margin-top:var(--space-lg);display:flex;gap:var(--space-md);flex-wrap:wrap;}
.banner__cta .btn{margin-top:0;}
/* Face-aware card placement on desktop — card sits on the photo's clear side */
@media(min-width:1041px){
  .banner--card-right .banner__inner{max-width:none;}
  .banner--card-right .banner__card{margin-left:auto;}
  .banner--card-narrow .banner__card{max-width:430px;}
}

/* Home hero — full-width rounded image w/ white margin + overlay text card */
.hero__frame{padding:10px;}
.hero__media{position:relative;border-radius:clamp(18px,2.4vw,28px);overflow:hidden;
  min-height:clamp(540px,86vh,820px);background:var(--navy);display:flex;align-items:flex-end;isolation:isolate;}
/* On desktop the nav floats over the top of the image — anchor the card below it so they never overlap. */
@media(min-width:1041px){.hero__media{align-items:flex-start;padding-top:clamp(96px,11vh,132px);}}
.hero__media>.ph{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:-1;}
.hero__media::after{content:"";position:absolute;inset:0;z-index:-1;
  background:linear-gradient(to top,rgba(7,18,33,.45),transparent 55%);}
.hero__panel{position:relative;z-index:2;container-type:inline-size;margin:clamp(14px,2.4vw,30px);width:470px;max-width:100%;
  background:rgba(34,32,29,.46);backdrop-filter:blur(18px) saturate(1.4);-webkit-backdrop-filter:blur(18px) saturate(1.4);
  border:1px solid rgba(255,255,255,.18);border-radius:var(--radius-card);padding:clamp(20px,2.2vw,32px);
  color:var(--ink-invert);box-shadow:0 30px 70px rgba(20,18,16,.42);}
.hero__panel .eyebrow{color:var(--cyan-bright);margin-bottom:var(--space-md);}
/* font scales with the card width (cqw) so the headline holds ~3 lines at any size */
.hero__panel h1{color:#fff;font-size:clamp(1.5rem,10.3cqw,2.9rem);line-height:1.08;letter-spacing:-.03em;text-wrap:balance;}
.hero__panel h1 .serif{color:var(--cyan-bright);font-weight:400;}
.hero__panel .hero__sub{margin-top:var(--space-md);color:rgba(250,247,242,.92);max-width:46ch;}
.hero__panel .hero__cta{margin-top:var(--space-lg);}
.hero__panel .hero__quick{margin-top:var(--space-xl);gap:var(--space-lg) var(--space-xl);}
.hero__panel .hero__quick dt{color:rgba(250,247,242,.7);}
.hero__panel .hero__quick dd{color:#fff;}
@media(max-width:640px){
  /* A photo band reads as the header; a compact card tucks under its bottom edge and runs below. */
  .hero__media{display:block;overflow:visible;min-height:0;background:transparent;}
  .hero__scatter{position:relative;inset:auto;height:46vh;border-radius:clamp(18px,2.4vw,28px);}
  .hero__media::after{display:none;}
  .hero__panel{position:relative;z-index:5;margin:-7vh 14px 14px;width:auto;max-width:none;padding:18px 18px 20px;background:rgba(34,32,29,.93);}
  .hero__panel .eyebrow{margin-bottom:5px;font-size:.62rem;}
  .hero__panel .hero__sub{margin-top:8px;font-size:.92rem;}
  .hero__panel .hero__cta{margin-top:12px;gap:8px;}
  .hero__panel .hero__cta .btn{padding:.75em 1.15em;font-size:.85rem;}
  .hero__panel .hero__quick{margin-top:14px;gap:10px 20px;}
  /* show ~6 photos on phones so the band isn't cramped */
  .htile--desk,
  .htile:has([data-eimg="hero_tile_2"]),.htile:has([data-eimg="hero_tile_3"]),
  .htile:has([data-eimg="hero_tile_6"]),.htile:has([data-eimg="hero_tile_7"]),
  .htile:has([data-eimg="hero_tile_9"]),.htile:has([data-eimg="hero_tile_11"]){display:none;}
}

/* ===== Floating image scatter (home hero) ===== */
.hero__scatter{overflow:hidden;border-radius:inherit;z-index:0;}
@media(min-width:641px){.hero__scatter{position:absolute;inset:0;}}   /* phones use the relative 46vh band defined above */
/* default: a solid grainy navy (admin can swap this for a photo via the editor) */
.hero__bg{position:absolute;inset:0;z-index:0;background:radial-gradient(120% 100% at 28% 16%,#3a332b,var(--navy) 62%);}
/* grain is rendered at 600px and displayed at 200px (3x supersampled) so it stays
   crisp on retina phones — Safari rasterizes SVG backgrounds at intrinsic size */
.hero__bg::after{content:"";position:absolute;inset:0;pointer-events:none;mix-blend-mode:overlay;opacity:.14;
  background-size:200px 200px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='600'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");}
.htile{position:absolute;z-index:1;border-radius:clamp(10px,1.2vw,16px);overflow:hidden;background:var(--navy);box-shadow:0 18px 44px rgba(7,18,33,.5);will-change:transform;transition:opacity .5s ease;}
/* Hidden until its photo can be painted (site.js gates on decode(), not load).
   The transition above carries the fade; nth-child gives a small stagger so
   thirteen tiles don't all arrive on the same frame. */
.htile.is-loading{opacity:0;}
.htile:nth-child(2){transition-delay:.04s}.htile:nth-child(3){transition-delay:.08s}
.htile:nth-child(4){transition-delay:.12s}.htile:nth-child(5){transition-delay:.16s}
.htile:nth-child(6){transition-delay:.2s} .htile:nth-child(7){transition-delay:.24s}
.htile:nth-child(8){transition-delay:.28s}.htile:nth-child(9){transition-delay:.32s}
.htile:nth-child(n+10){transition-delay:.36s}
.htile img{width:100%;height:100%;object-fit:cover;display:block;border-radius:inherit;}
.edit-mode .htile{overflow:visible;}   /* let the "Replace photo" button show on small tiles */
.hero__panel{z-index:3;}
/* ministry rail cards lift on hover */
.rcard{transition:transform .4s var(--ease-out);}
.rcard:hover{transform:translateY(-5px);}
.rcard:active{transform:translateY(-2px) scale(.99);}
/* text links: an underline wipes in on hover */
.lead a:not(.btn),.split__copy p a:not(.btn),.prose a:not(.btn),.crumb a{background-image:linear-gradient(currentColor,currentColor);background-repeat:no-repeat;background-position:0 100%;background-size:0% 1.5px;transition:background-size .35s var(--ease-out),color .2s;}
.lead a:not(.btn):hover,.split__copy p a:not(.btn):hover,.prose a:not(.btn):hover,.crumb a:hover{background-size:100% 1.5px;}

/* Accordion — springy open */
/* Deceleration, not overshoot. grid-template-rows is a layout property — an
   overshoot curve made the panel expand past its real height and snap back,
   reflowing everything beneath it on every frame of the bounce. */
.acc__a{transition:grid-template-rows .42s var(--ae-out,cubic-bezier(.16,1,.3,1));}
.acc__q .pm{transition:transform .28s var(--ae-out,cubic-bezier(.16,1,.3,1));}
.acc__item.open .acc__q .pm{transform:rotate(90deg);}
.acc__item.open{box-shadow:var(--shadow-md);}
.acc__item{transition:box-shadow .4s var(--ease-out);}

/* Partner logo grid (missions) */
.logos{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:var(--space-md);align-items:center;}
.logos figure{background:var(--navy);border:1px solid color-mix(in srgb,var(--navy) 55%,var(--snow));border-radius:var(--radius);aspect-ratio:3/2;display:grid;place-items:center;padding:22px;transition:transform .4s var(--ease-out),box-shadow .4s var(--ease-out);}
.logos figure:hover{transform:translateY(-4px);box-shadow:var(--shadow-md);}
.logos img{max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain;}

/* Single full-image form stage (connect page) — lighter scrim so the photo shows */
.formstage--solo .formstage__bg{background-size:cover;background-position:center;}
.formstage--solo .formstage__bg::after{background:linear-gradient(to bottom,rgba(6,18,31,.34),rgba(6,18,31,.56));}

/* Nav nudged down slightly */
.navshell{top:24px;}

/* Home: one off-white field; color reserved for the Plan-a-Visit band */
.page-home{background:var(--snow);}
.page-home .section{background:var(--snow);}
/* Creative section break — cross motif between hairlines (replaces color transitions) */
.pagebreak{display:flex;align-items:center;gap:clamp(14px,3vw,30px);max-width:720px;margin-inline:auto;padding-inline:clamp(20px,5vw,52px);padding-block:clamp(18px,3.5vw,40px);}

/* --- divider boundary -------------------------------------------------------
   Two systems separate sections on this site: a change of background (Give,
   Events - about 102px between sections) and this divider (the home page).
   The divider version came to 256px: 78px of section padding, a 100px divider,
   then 78px again - two and a half times the rest of the site for a boundary
   that is one hairline rule and a small mark.

   The ornament stays; the air around it comes in. The sections either side of a
   divider give up roughly a third of their padding, which lands the boundary
   near 170px - still plainly more generous than a background change, which is
   right, because a divider is a softer signal and needs the room to read as
   deliberate rather than accidental. */
/* The CMS drops <style> and <script> nodes between blocks, so a bare
   `+ .pagebreak` misses the sections that happen to have one after them - which
   left the boundaries uneven, 186px on some and 211px on others. Those nodes
   have no layout, so stepping over them explicitly is enough. */
.section:has(+ .pagebreak),
.section:has(+ :is(style,script) + .pagebreak),
.section:has(+ :is(style,script) + :is(style,script) + .pagebreak){
  padding-bottom:clamp(34px,4.4vw,62px);
}
.pagebreak + .section{padding-top:clamp(34px,4.4vw,62px);}
.pagebreak{padding-block:clamp(10px,2vw,22px);}

.pagebreak__rule{flex:1;height:1px;background:linear-gradient(to right,transparent,color-mix(in srgb,var(--navy) 20%,transparent),transparent);}
.pagebreak__mark{color:var(--cyan);display:grid;place-items:center;flex-shrink:0;opacity:.85;animation:pbspin 18s linear infinite;}
@keyframes pbspin{from{transform:rotate(0deg);}to{transform:rotate(360deg);}}
@media(prefers-reduced-motion:reduce){.pagebreak__mark{animation:none;transform:rotate(45deg);}}

/* =========================================================
   MOBILE BROWSER — traditional top bar
   ========================================================= */
/* Floating pill on the mobile browser — same glass treatment as the desktop nav, always visible */
.mobtop{display:none;position:fixed;top:12px;left:auto;right:12px;z-index:210;align-items:center;gap:6px;
  padding:6px 8px;background:rgba(34,32,29,.70);backdrop-filter:blur(16px) saturate(1.5);-webkit-backdrop-filter:blur(16px) saturate(1.5);
  border:1px solid rgba(255,255,255,.12);border-radius:100px;box-shadow:0 8px 22px rgba(20,18,16,.22),inset 0 1px 0 rgba(255,255,255,.09);}
.mobtop .brand{color:#fff;display:flex;align-items:center;overflow:hidden;max-width:80px;
  transition:max-width .42s var(--ease-out),opacity .26s var(--ease-out),transform .42s var(--ease-out),margin .42s var(--ease-out);}
.mobtop .brand__logo{width:40px;height:40px;}
/* scrolling down: the logo slides into the hamburger and disappears (returns on scroll up) */
.mobtop.is-min .brand{max-width:0;opacity:0;margin-right:-6px;transform:translateX(10px) scale(.4);}
.mobtop__burger{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;border:none;background:transparent;color:#fff;cursor:pointer;border-radius:50%;-webkit-tap-highlight-color:transparent;transition:background .2s;}
.mobtop__burger:hover,.mobtop__burger:active{background:rgba(255,255,255,.12);}
.burger{position:relative;display:block;width:22px;height:14px;}
.burger span{position:absolute;left:0;right:0;height:2px;border-radius:2px;background:currentColor;transition:transform .35s var(--ease-out),top .35s var(--ease-out);}
.burger span:nth-child(1){top:3px;}
.burger span:nth-child(2){top:9px;}
body.menu-open .burger span{top:6px;}
body.menu-open .burger span:nth-child(1){transform:rotate(45deg);}
body.menu-open .burger span:nth-child(2){transform:rotate(-45deg);}

/* =========================================================
   INSTALLED APP (PWA standalone) — app chrome
   ========================================================= */
.apphead{display:none;position:fixed;top:0;left:0;right:0;z-index:200;align-items:center;justify-content:center;gap:.5em;
  padding:calc(env(safe-area-inset-top,0px) + 11px) 16px 11px;background:rgba(34,32,29,.94);backdrop-filter:blur(16px);
  -webkit-backdrop-filter:blur(16px);color:#fff;box-shadow:0 2px 16px rgba(20,18,16,.3);}
.apphead .brand__logo{width:30px;height:30px;}
.apphead__name{font-family:var(--font-display);font-weight:700;font-size:.95rem;letter-spacing:.01em;}
/* Members Portal shortcut — right side of the app bar */
.apphead__member{position:absolute;right:10px;bottom:7px;width:38px;height:38px;display:grid;place-items:center;border-radius:50%;color:#fff;background:rgba(255,255,255,.12);-webkit-tap-highlight-color:transparent;transition:background .2s,transform .25s var(--ease-out);}
.apphead__member svg{width:21px;height:21px;}
.apphead__member:active{transform:scale(.92);}
.apphead__member.is-in::after{content:none;}
/* Members icon in the app home greeting row (replaces the logo circle there) */
.appdash__avatar--member{position:relative;color:#fff;-webkit-tap-highlight-color:transparent;}
.appdash__avatar--member svg{width:23px;height:23px;}
.appdash__avatar--member:active{transform:scale(.93);}
.appdash__avatar--member.is-in::after{content:none;}

html.app-mode .navshell{display:none !important;}
html.app-mode .mobtop{display:none !important;}
/* Show the mobile-browser top bar (defined after the base .mobtop rule so source order can't hide it). */
@media(max-width:1040px){html:not(.app-mode) .mobtop{display:flex;}}
html.app-mode .announce{display:none;}            /* skip time-sensitive bar inside the app */
html.app-mode .apphead{display:none !important;}  /* no top banner — the app runs edge-to-top */
html.app-mode .botbar{display:flex;bottom:calc(env(safe-area-inset-bottom,0px) + 10px);}

/* --- status bar scrim ------------------------------------------------------
   The app runs with apple-mobile-web-app-status-bar-style: black-translucent so
   the page reaches the top of the screen. iOS then draws the clock, battery and
   signal in WHITE and gives no way to ask for dark — so a screen that is pale at
   the top loses them entirely. A script in the header measures the top of each
   page once it has rendered and sets .app-lighttop where it is needed.

   Height is exactly the safe-area inset, so a phone with no notch gets nothing at
   all, and the gradient fades to transparent so it reads as shading rather than
   as the very bar we just removed.
   The color comes from --scrim, so it does not have to be the site's navy on
   every screen. A page can name its own with 'scrim' => '#5a2036' in its $PAGE
   array; left alone, the same script that decides whether the shading is needed
   also tints it toward the color it measured at the top of that page, so a warm
   screen gets a warm shadow rather than a navy one laid over it. It takes the hue
   and holds the lightness at the 15% the navy already sat at, so every page's
   shading is about as dark as every other page's: a per-page color changes the
   temperature of the shading, never whether the white clock can be read. */
html.app-mode{--scrim:#22201d;}
html.app-mode.app-lighttop::before{
  content:'';position:fixed;top:0;left:0;right:0;z-index:400;pointer-events:none;
  height:env(safe-area-inset-top,0px);
  /* first declaration is the fallback for engines without color-mix() */
  background:linear-gradient(180deg,rgba(34,32,29,.62),rgba(34,32,29,.34) 62%,rgba(34,32,29,0));
  background:linear-gradient(180deg,
    color-mix(in srgb,var(--scrim) 62%,transparent),
    color-mix(in srgb,var(--scrim) 34%,transparent) 62%,
    transparent);
}
@media (prefers-reduced-transparency:reduce){
  html.app-mode.app-lighttop::before{
    background:rgba(34,32,29,.7);
    background:color-mix(in srgb,var(--scrim) 70%,transparent);
  }
}

html.app-mode body{padding-top:0;padding-bottom:calc(env(safe-area-inset-bottom,0px) + 86px);}
/* the iOS status icons float directly over the page — no strip behind them */
/* pull-to-refresh pill (installed app) */
.ptr{position:fixed;top:calc(env(safe-area-inset-top,0px) + 6px);left:50%;transform:translateX(-50%);z-index:420;
  width:40px;height:40px;border-radius:50%;display:grid;place-items:center;opacity:0;pointer-events:none;
  background:rgba(20,28,40,.6);backdrop-filter:blur(18px) saturate(1.5);-webkit-backdrop-filter:blur(18px) saturate(1.5);
  border:1px solid rgba(255,255,255,.22);box-shadow:0 10px 30px rgba(20,18,16,.35);transition:opacity .2s}
.ptr.show{opacity:1}
.ptr__spin{width:18px;height:18px;border-radius:50%;border:2.5px solid rgba(255,255,255,.28);border-top-color:#d9c4a8;transition:transform .2s}
.ptr.ready .ptr__spin{transform:rotate(180deg);border-top-color:#fff}
.ptr.spin .ptr__spin{animation:ptrspin .7s linear infinite}
@keyframes ptrspin{to{transform:rotate(360deg)}}
/* The status bar now uses iOS's "default" style — black clock, battery and
   signal on the theme color — so the dark gradient that used to sit behind
   white icons is gone. The element stays in the markup (it's referenced
   elsewhere) but paints nothing. */
.appstatus{display:none;}
html.app-mode .appstatus{display:none;}
/* floating account button, tucked beside the notch (app only) */
.appuser{display:none;}
html.app-mode .appuser{position:fixed;top:calc(env(safe-area-inset-top,0px) + 8px);right:14px;z-index:390;
  display:grid;place-items:center;width:38px;height:38px;border-radius:50%;overflow:hidden;color:#fff;
  background:rgba(34,32,29,.55);border:1px solid rgba(255,255,255,.22);
  backdrop-filter:blur(16px) saturate(1.5);-webkit-backdrop-filter:blur(16px) saturate(1.5);
  box-shadow:0 8px 22px rgba(20,18,16,.35);-webkit-tap-highlight-color:transparent;transition:transform .25s var(--ease-out);}
html.app-mode .appuser:active{transform:scale(.92);}
html.app-mode .appuser svg{width:20px;height:20px;}
/* Signed out, the same button says so. A silhouette in a circle is a face, not
   an instruction, and the people most likely to need the portal are the least
   likely to work out that the little gray head is the way in. It keeps its
   place beside the notch and keeps its glass; it only gets wider. */
html.app-mode .appuser--out{width:auto;height:38px;grid-auto-flow:column;gap:.42em;
  padding:0 13px 0 11px;border-radius:100px;}
html.app-mode .appuser--out svg{width:16px;height:16px;}
.appuser__lbl{font-size:.78rem;font-weight:700;line-height:1;white-space:nowrap;}
/* Settings sheet — morphs open from the profile icon */
.setmodal{position:fixed;inset:0;z-index:600;display:flex}
.setmodal[hidden]{display:none}
.setmodal__scrim{position:absolute;inset:0;background:rgba(6,15,30,.55);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);opacity:0;transition:opacity .32s ease}
.setmodal.is-open .setmodal__scrim{opacity:1}
/* Settings drops in from the top and settles on a spring.
   It used to inflate from a dot at the tapped icon, which is a lovely trick
   and the wrong one here: a settings panel isn't born out of the button, it
   comes down over the page like a drawer. Coming from above also means the
   thing you tapped stays visible underneath, so it's obvious what you're on
   top of and which way out is.

   The overshoot is small — it passes its resting place by a few pixels and
   comes back. Enough to feel like weight, not enough to read as a wobble. */
.setmodal__card{position:relative;margin:auto;width:min(600px,94vw);height:min(84vh,760px);max-height:calc(100vh - 40px);background:var(--snow,#faf7f2);
  border-radius:24px;overflow:hidden;display:flex;flex-direction:column;box-shadow:0 40px 90px rgba(6,15,30,.5);
  opacity:0;transform:translateY(-118%);
  transition:transform .52s var(--ae-spring,cubic-bezier(.22,1.14,.36,1)),opacity .22s ease}
.setmodal.is-open .setmodal__card{opacity:1;transform:translateY(0)}
/* Leaving is quicker and doesn't bounce — an exit that springs reads as
   indecision. */
.setmodal:not(.is-open) .setmodal__card{transition:transform .26s cubic-bezier(.4,0,1,1),opacity .2s ease}
@media (prefers-reduced-motion:reduce){
  .setmodal__card,.setmodal:not(.is-open) .setmodal__card{transition:opacity .2s ease;transform:none}
}
/* The card floats in the middle of the screen and never touches the top, so
   the safe-area inset it used to carry was pure dead space above the word. */
.setmodal__bar{flex:none;display:flex;align-items:center;justify-content:space-between;padding:14px 18px;border-bottom:1px solid var(--line);background:var(--asurf,var(--card,#fff))}
.setmodal__bar strong{font-family:var(--font-display);font-weight:700;font-size:1.05rem;color:var(--ink-strong)}
.setmodal__x{border:0;background:none;font-size:1.9rem;line-height:1;color:var(--muted);cursor:pointer;padding:0 6px;-webkit-tap-highlight-color:transparent}
.setmodal__frame{flex:1;width:100%;border:0;background:transparent}
body.set-open{overflow:hidden}
@media(prefers-reduced-motion:reduce){.setmodal__card{transition:opacity .2s}}
html.app-mode .appuser img{width:100%;height:100%;object-fit:cover;}
html.app-mode .appuser.is-in::after{content:none;}
/* the home dashboard already has its own member avatar — hide the floating one there */
html.app-mode body.page-home .appuser{display:none;}
/* ...except when there is nobody to be. The app home hides the floating button
   because it carries its own account control, and that control is only there
   for a member. Signed out that corner was simply empty, on the one screen the
   app opens to, so the way in was invisible to exactly the person looking for
   it. Only the signed-out pill comes back; a member sees no change. */
html.app-mode body.page-home .appuser--out{display:grid;}

/* App "More" = a bottom sheet that rises out of the tab bar (not a full-screen takeover) */
html.app-mode .mobmenu{
  inset:auto 0 0 0;top:auto;height:auto;max-height:80vh;
  border-radius:26px 26px 0 0;
  /* same frosted glass as the bottom bar, one notch lighter */
  --ai:#faf9f8;
  --am:rgba(255,255,255,.88);
  --aline:rgba(255,255,255,.13);
  --aicobg:rgba(255,255,255,.13);
  --aac:rgba(226,208,182,.55);
  --aacd:#ddd0c0;
  color:#faf9f8;
  background:
    linear-gradient(180deg,rgba(255,255,255,.13),rgba(255,255,255,.03) 42%,rgba(255,255,255,0) 72%),
    linear-gradient(180deg,rgba(20,28,40,.66),rgba(16,23,34,.72));
  backdrop-filter:blur(30px) saturate(1.9);
  -webkit-backdrop-filter:blur(30px) saturate(1.9);
  padding:8px clamp(18px,6vw,28px) calc(env(safe-area-inset-bottom,0px) + 96px);
  transform:translateY(103%);opacity:1;visibility:hidden;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.16), 0 -18px 55px rgba(20,18,16,.45), 0 0 0 100vmax rgba(20,18,16,0);
  transition:transform .44s var(--ease-out),visibility .44s,box-shadow .5s ease;
  will-change:transform;
}
html.app-mode body.menu-open .mobmenu{
  transform:translateY(0);visibility:visible;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.16), 0 -18px 55px rgba(20,18,16,.45), 0 0 0 100vmax rgba(20,18,16,.42);
}
/* the sheet is dark glass now, so its contents read light-on-dark */
html.app-mode .mobmenu .appsheet__h{color:rgba(255,255,255,.92)}
html.app-mode .mobmenu .appsheet__ic{box-shadow:inset 0 0 0 1px rgba(255,255,255,.10)}
html.app-mode .mobmenu .appsheet__go{opacity:.62}
html.app-mode .mobmenu .appsheet__n{background:#ddd0c0;color:#292118}
html.app-mode .mobmenu .appsheet__out--in{color:#f7f4f0;background:rgba(226,208,182,.14)}
html.app-mode .mobmenu__head{display:none}                 /* the grab handle stands in for the header */
html.app-mode .mobmenu::before{
  content:"";display:block;flex:none;width:42px;height:5px;border-radius:100px;
  background:rgba(255,255,255,.32);margin:2px auto 14px;
}
html.app-mode .mobmenu .menu>li>a,
html.app-mode .mobmenu .menu>li>button{font-size:1.08rem;padding:.95em 1.1em;}
/* in the app, page tops clear the notch (content flows under the status bar) */
html.app-mode .banner__inner{padding-top:calc(env(safe-area-inset-top,0px) + clamp(56px,10vw,84px));}
html.app-mode .hero__frame{padding-top:calc(env(safe-area-inset-top,0px) + clamp(52px,9vw,80px));}
html.app-mode .smhero,html.app-mode .khero{padding-top:calc(env(safe-area-inset-top,0px) + clamp(52px,9vw,80px));}
html.app-mode .shero__copy{padding-top:calc(env(safe-area-inset-top,0px) + clamp(56px,10vw,84px));}
html.app-mode .appdash{padding-top:calc(env(safe-area-inset-top,0px) + 12px);}
html.app-mode .ptl-banner .banner__inner{padding-top:calc(env(safe-area-inset-top,0px) + clamp(48px,9vw,72px));}

/* "Turn on notifications" — app dashboard card */
.apppush{display:flex;align-items:center;gap:13px;width:100%;text-align:left;cursor:pointer;
  margin-top:4px;padding:14px 16px;border-radius:var(--radius-card);border:1px solid rgba(160,138,111,.28);
  background:linear-gradient(135deg,rgba(160,138,111,.10),rgba(34,32,29,.05));color:var(--ink-strong);
  font-family:var(--font-display);transition:background .25s,border-color .25s,transform .15s;}
.apppush:active{transform:scale(.99);}
.apppush[data-state="on"]{border-color:rgba(34,150,90,.35);background:rgba(34,150,90,.08);}
.apppush[disabled]{opacity:.7;cursor:default;}
.apppush__ic{flex:none;display:grid;place-items:center;width:40px;height:40px;border-radius:12px;background:var(--cyan);color:#fff;}
.apppush__ic svg{width:21px;height:21px;}
.apppush[data-state="on"] .apppush__ic{background:#22965a;}
.apppush__tx{display:flex;flex-direction:column;gap:1px;line-height:1.2;}
.apppush__tx b{font-size:.96rem;font-weight:700;}
.apppush__tx small{font-size:.76rem;color:var(--ink-soft);font-weight:500;}

/* "Get notifications" — footer link/button */
.footpush{background:none;border:1px solid rgba(255,255,255,.28);color:inherit;cursor:pointer;
  font:inherit;font-size:.82rem;padding:.4em .9em;border-radius:100px;transition:background .25s,border-color .25s;}
.footpush:hover{background:rgba(255,255,255,.1);}
.footpush[data-state="on"]{border-color:rgba(120,210,160,.5);color:#bfe9cf;}
.footpush[disabled]{opacity:.6;cursor:default;}

/* app-only vs browser-only blocks */
.app-only{display:none;}
html.app-mode .app-only{display:block;}
html.app-mode .browser-only{display:none;}
/* keep buttons flowing as buttons when toggled by app/browser mode */
.btn.app-only{display:none;}
html.app-mode .btn.app-only{display:inline-flex;align-items:center;justify-content:center;}
html.app-mode .mobmenu__actions a.btn--member{display:flex;align-items:center;justify-content:center;}

/* =========================================================
   APP HOME DASHBOARD (app-mode home)
   ========================================================= */
.appdash{display:none;padding:14px clamp(16px,5vw,26px) clamp(28px,7vw,44px);flex-direction:column;gap:18px;}
html.app-mode .appdash{display:flex;}
/* On the app home we drop the slim header bar entirely so the page background runs to the top */
html.app-mode body.page-home .apphead{display:none;}
/* let the flex gap own all vertical rhythm — no element adds its own top margin */
.appdash > * { margin-top:0; }

/* ── PWA home entrance: springy staggered rise (replaces the plain fade) ──
   In app-mode the anim-* fade utilities inside the dash are neutralized and
   every dash block springs up with a slight overshoot, cascading top→bottom. */
html.app-mode .appdash .anim-fade-up.aa,html.app-mode .appdash .anim-card.aa,
html.app-mode .appdash .anim-fade-up.aa.is-in,html.app-mode .appdash .anim-card.aa.is-in{opacity:1;transform:none;transition:none;}
@keyframes appdashSpring{from{opacity:0;transform:translateY(38px) scale(.94);}to{opacity:1;transform:none;}}
html.app-mode .appdash>*{animation:appdashSpring .72s var(--ae-spring,cubic-bezier(.22,1.14,.36,1)) both;}
html.app-mode .appdash>*:nth-child(1){animation-delay:.04s;}
html.app-mode .appdash>*:nth-child(2){animation-delay:.12s;}
html.app-mode .appdash>*:nth-child(3){animation-delay:.2s;}
html.app-mode .appdash>*:nth-child(4){animation-delay:.26s;}
html.app-mode .appdash>*:nth-child(5){animation-delay:.32s;}
html.app-mode .appdash>*:nth-child(6){animation-delay:.62s;}
html.app-mode .appdash>*:nth-child(7){animation-delay:.68s;}
html.app-mode .appdash>*:nth-child(8){animation-delay:.74s;}
/* quick-link rows cascade individually instead of the whole list at once */
html.app-mode .appdash .applist{animation:none;}
html.app-mode .appdash .applist__row{animation:appdashSpring .6s var(--ae-spring,cubic-bezier(.22,1.14,.36,1)) both;}
html.app-mode .appdash .applist__row:nth-child(1){animation-delay:.32s;}
html.app-mode .appdash .applist__row:nth-child(2){animation-delay:.37s;}
html.app-mode .appdash .applist__row:nth-child(3){animation-delay:.42s;}
html.app-mode .appdash .applist__row:nth-child(4){animation-delay:.47s;}
html.app-mode .appdash .applist__row:nth-child(5){animation-delay:.52s;}
html.app-mode .appdash .applist__row:nth-child(6){animation-delay:.57s;}
/* the tiles cascade individually too, on the same clock as the rows */
html.app-mode .appdash .appms{animation:none;}
html.app-mode .appdash .appms__t{animation:appdashSpring .6s var(--ae-spring,cubic-bezier(.22,1.14,.36,1)) both;}
html.app-mode .appdash .appms__t:nth-child(1){animation-delay:.32s;}
html.app-mode .appdash .appms__t:nth-child(2){animation-delay:.37s;}
html.app-mode .appdash .appms__t:nth-child(3){animation-delay:.42s;}
html.app-mode .appdash .appms__t:nth-child(4){animation-delay:.47s;}
html.app-mode .appdash .appms__t:nth-child(5){animation-delay:.52s;}
html.app-mode .appdash .appms__t:nth-child(6){animation-delay:.57s;}
@media(prefers-reduced-motion:reduce){
  html.app-mode .appdash>*,html.app-mode .appdash .applist__row,html.app-mode .appdash .appms__t{animation:none;}
}
.appk{font-size:.62rem;letter-spacing:.18em;text-transform:uppercase;font-weight:700;}

/* greeting row */
.appdash__top{display:flex;align-items:center;justify-content:space-between;gap:14px;}
.appdash__kick{font-size:.64rem;letter-spacing:.18em;text-transform:uppercase;font-weight:700;color:var(--cyan-deep);}
.appdash__greet{font-family:var(--font-serif);font-style:italic;font-weight:400;font-size:clamp(1.9rem,1.4rem + 2.6vw,2.6rem);color:var(--ink-strong);line-height:1.05;margin-top:2px;}
.appdash__avatar{width:46px;height:46px;border-radius:50%;overflow:hidden;flex-shrink:0;background:var(--navy);display:grid;place-items:center;box-shadow:var(--shadow-sm);}
.appdash__avatar img{width:100%;height:100%;object-fit:contain;}

/* "This Sunday" hero card */
.appcard--sunday{display:block;text-decoration:none;border-radius:var(--radius-card);overflow:hidden;background:linear-gradient(155deg,var(--cyan-deep),var(--navy));color:#fff;padding:18px;box-shadow:0 16px 40px rgba(20,18,16,.28);position:relative;isolation:isolate;}
.appcard--sunday::after{content:"";position:absolute;inset:0;z-index:0;background:radial-gradient(70% 60% at 85% 0%,rgba(160,138,111,.45),transparent 60%);}
.appweek{position:relative;z-index:1;display:flex;justify-content:space-between;gap:4px;margin-bottom:16px;}
.appweek span{flex:1;display:flex;flex-direction:column;align-items:center;gap:4px;font-size:.6rem;font-weight:700;letter-spacing:.05em;color:rgba(255,255,255,.6);}
.appweek b{width:30px;height:30px;display:grid;place-items:center;border-radius:50%;font-size:.82rem;font-weight:700;color:rgba(255,255,255,.85);}
.appweek .is-today b{background:#fff;color:var(--navy);}
.appweek .is-sun{color:var(--cyan-bright);}
.appweek .is-sun b{box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.5);}
.appcard__body{position:relative;z-index:1;}
.appcard__body .appk{color:var(--cyan-bright);}
.appcard__body h2{color:#fff;font-size:1.5rem;line-height:1.05;margin-top:3px;}
.appcard__body h2 .serif{color:var(--cyan-bright);}
.appcard__body p{color:rgba(255,255,255,.85);font-size:.86rem;margin-top:5px;}
.appweekly{position:relative;z-index:1;margin:12px 0 0;padding:0;list-style:none;display:flex;flex-direction:column;}
.appweekly li{display:flex;align-items:center;gap:12px;padding:9px 0;border-top:1px solid rgba(255,255,255,.14);}
.appweekly li:first-child{border-top:none;}
.appweekly b{width:44px;flex-shrink:0;font-size:.64rem;letter-spacing:.08em;text-transform:uppercase;font-weight:700;color:var(--cyan-bright);}
.appweekly span{flex:1;min-width:0;color:#fff;font-family:var(--font-display);font-weight:500;font-size:.92rem;}
.appweekly i{flex-shrink:0;color:rgba(255,255,255,.72);font-style:normal;font-size:.82rem;}
.appchip{display:inline-flex;align-items:center;gap:.4em;margin-top:16px;background:rgba(255,255,255,.16);color:#fff;font-weight:600;font-size:.82rem;padding:.5em 1em;border-radius:100px;}

/* latest-message media card */
.appfeature{position:relative;display:flex;align-items:flex-end;aspect-ratio:16/9;border-radius:var(--radius-card);overflow:hidden;text-decoration:none;background:var(--navy);box-shadow:var(--shadow-sm);isolation:isolate;}
.appfeature img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;}
.appfeature::after{content:"";position:absolute;inset:0;z-index:1;background:linear-gradient(to top,rgba(7,18,33,.92),rgba(7,18,33,.34) 45%,rgba(7,18,33,.04) 72%);}
.appfeature__body{position:relative;z-index:2;padding:16px;width:100%;}
.appfeature__body .appk{color:var(--cyan-bright);}
.appfeature__body h3{color:#fff;font-size:1.1rem;line-height:1.12;margin-top:3px;max-width:80%;}
.appfeature__play{position:absolute;z-index:2;right:16px;bottom:16px;width:42px;height:42px;border-radius:50%;background:rgba(255,255,255,.92);color:var(--ink-strong);display:grid;place-items:center;}
.appfeature__play svg{margin-left:2px;}

/* quick-links list card */
/* each quick link is its own rounded rectangle card, stacked with breathing room */
.applist{display:flex;flex-direction:column;gap:10px;}
.applist__row{display:flex;align-items:center;gap:14px;padding:14px 16px;text-decoration:none;color:var(--ink);
  background:var(--paper);border:1px solid var(--line);border-radius:18px;box-shadow:var(--shadow-sm);
  transition:background .2s,transform .18s var(--ease-out),box-shadow .2s;}
.applist__row:active{background:color-mix(in srgb,var(--cyan) 8%,var(--paper));transform:scale(.985);}
.applist__ico{width:44px;height:44px;flex-shrink:0;border-radius:13px;display:grid;place-items:center;background:color-mix(in srgb,var(--cyan) 12%,var(--snow));color:var(--cyan-deep);}
.applist__ico svg{width:22px;height:22px;}
.applist__row b{flex:1;font-family:var(--font-display);font-weight:600;font-size:1rem;color:var(--ink-strong);}
.applist__row small{color:var(--muted);font-size:.78rem;}
.applist__chev{color:var(--muted);width:18px;height:18px;flex-shrink:0;}

/* ================================================= home-screen tiles
   Replaces the row list (card + icon chip + chevron, eight times) that every
   destination shared. Two problems with that, and only one was styling: it is
   the stock settings-list pattern, and drawing all eight at identical weight
   left the eye nothing to land on.

   Three weights now. One gradient tile leads each block, using the SAME two
   stops as the Sunday card above so it reads as part of the screen rather
   than a second accent invented for it. Below that a full-width tint, then
   quiet outlined squares. Sizes are uneven on purpose — a strict grid of
   equal cards is the thing that reads as templated however it is styled.

   .appms__ico svg carries an explicit size. The icons are inline SVGs with a
   viewBox and no width attribute, so without it they expand to fill the tile
   and the screen turns into one enormous speech bubble. */
.appms{display:grid;grid-template-columns:1fr 1fr;gap:10px;}
.appms__t{display:flex;flex-direction:column;gap:5px;padding:15px;text-decoration:none;border-radius:var(--radius-card);
  min-height:104px;justify-content:flex-end;background:var(--paper);border:1px solid var(--line);
  color:var(--ink);transition:transform .18s var(--ease-out);}
.appms__t:active{transform:scale(.985);}
.appms__ico{width:26px;height:26px;margin-bottom:auto;color:var(--cyan-deep);}
.appms__ico svg{width:26px;height:26px;}
.appms__t b{font-family:var(--font-display);font-weight:600;font-size:.97rem;line-height:1.2;}
.appms__t small{color:var(--muted);font-size:.75rem;line-height:1.3;}
/* ══ photo tiles ═══════════════════════════════════════════════════════
   A square whose subject actually has a photograph. Only squares: the lead
   and wide tiles carry the church's own color and a picture behind those
   turns a brand banner into a stock slide.

   The image is a real <img> rather than a background, so it lazy-loads, is
   sized by the browser and costs nothing on a tile scrolled past. The label
   rides a bottom-up scrim — that gradient, not the photo, is what guarantees
   white text stays legible when somebody swaps a bright picture in later. */
.appms__t--photo{position:relative;overflow:hidden;isolation:isolate;
  min-height:132px;border-color:transparent;color:#fff;}
.appms__ph{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:-2;
  transition:transform .5s var(--ease-out);}
/* Measured against the brightest photo in the set: at .88/.52/.10 the small
   line under the title was washing out wherever the picture went pale. The
   scrim is the only thing guaranteeing contrast — the photograph itself is
   whatever somebody uploads next year — so it carries further up the tile and
   sits heavier at the bottom. The picture still reads; the words always win. */
.appms__t--photo::after{content:"";position:absolute;inset:0;z-index:-1;
  background:linear-gradient(to top,rgba(6,16,28,.94) 0%,rgba(6,16,28,.76) 30%,
    rgba(6,16,28,.42) 62%,rgba(6,16,28,.20) 100%);}
/* The picture moves inside its frame on press, not the whole tile — a tile
   that shrinks drags its neighbors' shadows with it. */
.appms__t--photo:active .appms__ph{transform:scale(1.04);}
.appms__t--photo .appms__ico{color:#fff;opacity:.92;
  filter:drop-shadow(0 1px 4px rgba(4,12,22,.55));}
.appms__t--photo b{color:#fff;text-shadow:0 1px 5px rgba(4,12,22,.45);}
.appms__t--photo small{color:rgba(255,255,255,.93);text-shadow:0 1px 4px rgba(4,12,22,.55);}
/* Themed app shells re-color every tile from their own tokens; a photo tile
   sets its own contrast, so it opts out of all of that. */
/* Doubling the class is not decoration. body[class*="ath-"] .appms__t small
   and body[class*="ath-"] .appms__t--photo small score identically — an
   attribute selector counts as a class, so both are (0,2,2) — and the themed
   rule is written later in this file, so it was quietly winning and painting
   the sub-line muted gray on top of a photograph. .appms__t.appms__t--photo
   takes it to (0,3,2) and settles it on specificity rather than on which of
   us edited the file last. */
body[class*="ath-"] .appms__t.appms__t--photo{background:transparent;border-color:transparent;color:#fff;}
body[class*="ath-"] .appms__t.appms__t--photo b{color:#fff;}
body[class*="ath-"] .appms__t.appms__t--photo small{color:rgba(255,255,255,.93);}
body[class*="ath-"] .appms__t.appms__t--photo .appms__ico{color:#fff;}
@media(prefers-reduced-motion:reduce){
  .appms__ph{transition:none;}
  .appms__t--photo:active .appms__ph{transform:none;}
}
.appms__t--wide{grid-column:1 / -1;min-height:92px;padding:17px 18px;
  background:color-mix(in srgb,var(--cyan) 12%,var(--snow));border-color:transparent;}
.appms__t--wide b{font-size:1.14rem;letter-spacing:-.01em;}
.appms__t--wide small{font-size:.8rem;}
.appms__t--lead{grid-column:1 / -1;min-height:96px;padding:18px;border:0;color:#fff;
  background:linear-gradient(150deg,var(--cyan-deep),var(--navy));box-shadow:0 12px 30px rgba(20,18,16,.2);}
.appms__t--lead .appms__ico{color:#fff;opacity:.92;width:28px;height:28px;}
.appms__t--lead .appms__ico svg{width:28px;height:28px;}
.appms__t--lead b{font-size:1.2rem;letter-spacing:-.015em;font-weight:700;}
.appms__t--lead small{color:#fff;opacity:.84;font-size:.82rem;}
@media(prefers-reduced-motion:reduce){
  .appms__t{transition:none !important;}
}
.appdash__foot{text-align:center;color:var(--muted);font-size:.72rem;letter-spacing:.04em;padding-top:4px;}
/* "Tonight" strip — shows only when an event is happening today */
.apptonight{display:flex;align-items:center;gap:12px;background:color-mix(in srgb,var(--cyan) 10%,#fff);
  border:1px solid color-mix(in srgb,var(--cyan) 32%,#fff);border-radius:var(--radius-card);padding:12px 14px;color:var(--navy);}
/* The serving strip is the one line on this screen that is about you
   personally, so it reads as a card you can press rather than another tinted
   notice. White needs help separating from the off-white page behind it —
   that is what the neutral hairline and the shallow shadow are for. The dot
   and the chevron keep their cyan, because those are the parts saying "live"
   and "there is more". */
.apptonight--serve{background:#fff;border-color:var(--line);
  box-shadow:0 1px 2px rgba(34,32,29,.05),0 8px 20px -12px rgba(34,32,29,.28);}
.apptonight--serve:active{transform:scale(.99)}
.apptonight__dot{flex:none;width:10px;height:10px;border-radius:50%;background:var(--cyan);position:relative;}
.apptonight__dot::after{content:"";position:absolute;inset:-4px;border-radius:50%;border:2px solid color-mix(in srgb,var(--cyan) 55%,transparent);animation:tnpulse 2.2s ease-out infinite;}
@keyframes tnpulse{0%{transform:scale(1);opacity:.75}100%{transform:scale(2.2);opacity:0}}
.apptonight__t{flex:1;min-width:0;display:flex;flex-direction:column;}
.apptonight__t b{font-family:var(--font-display);font-size:.92rem;}
.apptonight__t small{color:var(--ink-soft);font-size:.8rem;margin-top:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.apptonight__chev{flex:none;width:16px;height:16px;color:var(--cyan-deep);}

/* ═══ App home color themes — picked in the member profile; home screen only.
   Each theme sets a small palette; the overrides below repaint the dashboard. ═══ */
/* =========================================================================
   App color themes — eight palettes, each with a light and a dark set.

   Every value here is generated, not eyeballed, and the generator refuses to
   emit a palette whose text fails WCAG AA against every surface it can land
   on. That matters because the previous --muted shipped at 3.20:1 across 337
   uses; secondary text is now 4.8-5.5:1 in all sixteen combinations.

   Two accent roles, deliberately kept apart:
     --aac   a FILL. Only needs to be visible (3:1), so it stays saturated.
     --aacd  accent as TEXT. Needs 4.5:1, so it's deeper.
   Collapsing those two is what makes most dark modes look washed out.
   ========================================================================= */
/* =========================================================================
   App color themes.

   Every value is generated and contrast-checked, not eyeballed: the generator
   refuses to emit a palette whose text fails WCAG AA against any surface it
   can land on. Secondary text sits at 4.9-5.4:1 across all six, where the old
   --muted shipped at 3.20:1 over 337 uses.

   Two accent roles, deliberately separate:
     --aac   a FILL. Only needs to be visible (3:1), so it stays saturated.
     --aacd  accent as TEXT. Needs 4.5:1, so it's deeper.
   Collapsing those two is what makes a palette look washed out.

   Dark ramps are emitted too but nothing adds html.dark right now — see
   app_mode() in inc/portal.php.
   ========================================================================= */
body.ath-sanctuary{--ab:#faf7f2;--ai:#22201d;--am:#6e6459;--ac1:#6e604e;--ac2:#22201d;--abr:#d9c4a8;--aac:#a08a6f;--aacd:#6e604e;--aacink:#faf7f2;--arow:#f6f2ec;--aline:#e0d9cd;--aicobg:#ece3d6;--asurf:#fffdfa;--aglow:rgba(160,138,111,.42);}
html.dark body.ath-sanctuary{--ab:#100e0c;--ai:#f6f2ec;--am:#a89e91;--ac1:#8a7359;--ac2:#1a1815;--abr:#c2a684;--aac:#c2a684;--aacd:#c9ab86;--aacink:#100e0c;--arow:#211d18;--aline:#3a342d;--aicobg:#2b241c;--asurf:#191612;--aglow:rgba(194,166,132,.42);}
body.ath-kashmir{--ab:#eeece9;--ai:#322819;--am:#5d5548;--ac1:#4d3e29;--ac2:#322819;--abr:#abe1d6;--aac:#6b593e;--aacd:#5a4b34;--aacink:#111111;--arow:#f4f9f8;--aline:#d6d1ca;--aicobg:#dad4cc;--asurf:#fafaf9;--aglow:rgba(26,143,122,.42);}
html.dark body.ath-kashmir{--ab:#130f09;--ai:#f8f7f6;--am:#999287;--ac1:#4f412b;--ac2:#261e12;--abr:#8c7b61;--aac:#6b593e;--aacd:#9b8c75;--aacink:#100e0c;--arow:#221b10;--aline:#423a2f;--aicobg:#2e2518;--asurf:#1e180f;--aglow:rgba(26,143,122,.42);}
body.ath-peonyblush{--ab:#ffe4e1;--ai:#830f42;--am:#8c435f;--ac1:#c42a69;--ac2:#ad1457;--abr:#ffe6f0;--aac:#e0447f;--aacd:#b33666;--aacink:#111111;--arow:#fff3f2;--aline:#f4c7ce;--aicobg:#facad1;--asurf:#fff7f7;--aglow:rgba(224,68,127,.42);}
html.dark body.ath-peonyblush{--ab:#420821;--ai:#fff4f3;--am:#bc9fa7;--ac1:#c62c6b;--ac2:#820f41;--abr:#eb87ad;--aac:#e24f87;--aacd:#ef9ebc;--aacink:#100e0c;--arow:#740d3a;--aline:#802f50;--aicobg:#801945;--asurf:#680c34;--aglow:rgba(226,79,135,.42);}
body.ath-violetdusk{--ab:#f8f4e9;--ai:#502d55;--am:#6b5a68;--ac1:#6e3d62;--ac2:#502d55;--abr:#d5b7c7;--aac:#935073;--aacd:#935073;--aacink:#ffffff;--arow:#fcfaf5;--aline:#e0d8d4;--aicobg:#e8dad6;--asurf:#fdfcf9;--aglow:rgba(147,80,115,.42);}
html.dark body.ath-violetdusk{--ab:#1e1120;--ai:#fcfbf6;--am:#958d8f;--ac1:#723e64;--ac2:#3c2240;--abr:#b3849d;--aac:#9c5e7e;--aacd:#bc92a8;--aacink:#ffffff;--arow:#361e39;--aline:#503e50;--aicobg:#462842;--asurf:#301b33;--aglow:rgba(156,94,126,.42);}
body.ath-sunset{--ab:#ffe3b3;--ai:#722d08;--am:#7f4d2a;--ac1:#c24800;--ac2:#ac3d00;--abr:#fff4eb;--aac:#dc5b12;--aacd:#a8460e;--aacink:#111111;--arow:#fff2dd;--aline:#f5cd9c;--aicobg:#f9cd99;--asurf:#fff7ea;--aglow:rgba(220,91,18,.42);}
html.dark body.ath-sunset{--ab:#461b05;--ai:#fff4e1;--am:#c9b5a2;--ac1:#d15410;--ac2:#8a360a;--abr:#f3a376;--aac:#ec6e26;--aacd:#f6bd9c;--aacink:#100e0c;--arow:#7b3009;--aline:#854823;--aicobg:#87380e;--asurf:#6e2b08;--aglow:rgba(236,110,38,.42);}
body.ath-marple{--ab:#ffeade;--ai:#851a35;--am:#8f4856;--ac1:#d1334d;--ac2:#ba1144;--abr:#fff5f4;--aac:#e05b5a;--aacd:#b24847;--aacink:#111111;--arow:#fff6f0;--aline:#f8cfca;--aicobg:#fad3c9;--asurf:#fff9f6;--aglow:rgba(224,91,90,.42);}
html.dark body.ath-marple{--ab:#4d0f1f;--ai:#fff7f2;--am:#c9b1b2;--ac1:#e4485c;--ac2:#981e3d;--abr:#ff9594;--aac:#ff6766;--aacd:#ffb3b2;--aacink:#100e0c;--arow:#871b36;--aline:#8e3a4d;--aicobg:#94283c;--asurf:#791831;--aglow:rgba(255,103,102,.42);}

html.dark body.ath-sanctuary{--paper:#100e0c;--bg:#100e0c;--ink:#f6f2ec;--ink-soft:#f6f2ec;--muted:#8d847b;--line:#3a342d;--cream:#191612;--cream-2:#211d18;--snow:#100e0c;}
html.dark body.ath-kashmir{--paper:#130f09;--bg:#130f09;--ink:#f8f7f6;--ink-soft:#f8f7f6;--muted:#999287;--line:#423a2f;--cream:#1e180f;--cream-2:#221b10;--snow:#130f09;}
html.dark body.ath-peonyblush{--paper:#420821;--bg:#420821;--ink:#fff4f3;--ink-soft:#fff4f3;--muted:#bc9fa7;--line:#802f50;--cream:#680c34;--cream-2:#740d3a;--snow:#420821;}
html.dark body.ath-violetdusk{--paper:#1e1120;--bg:#1e1120;--ink:#fcfbf6;--ink-soft:#fcfbf6;--muted:#958d8f;--line:#503e50;--cream:#301b33;--cream-2:#361e39;--snow:#1e1120;}
html.dark body.ath-sunset{--paper:#461b05;--bg:#461b05;--ink:#fff4e1;--ink-soft:#fff4e1;--muted:#c9b5a2;--line:#854823;--cream:#6e2b08;--cream-2:#7b3009;--snow:#461b05;}
html.dark body.ath-marple{--paper:#4d0f1f;--bg:#4d0f1f;--ink:#fff7f2;--ink-soft:#fff7f2;--muted:#c9b1b2;--line:#8e3a4d;--cream:#791831;--cream-2:#871b36;--snow:#4d0f1f;}

/* -- Quarry ---------------------------------------------------------------
   The seventh light theme, and the one the other six do not offer: nearly
   achromatic. Chroma stays under .03 everywhere, so it reads as stone rather
   than as a blue theme, for anyone who finds the rest too colorful. */
body.ath-quarry{--ab:#f3f1ef;--ai:#332f2a;--am:#615a52;--ac1:#61564b;--ac2:#332f2a;--abr:#cfc8c1;--aac:#796c5e;--aacd:#6b6054;--aacink:#111111;--arow:#fbfbfb;--aline:#dad7d3;--aicobg:#d8d4cf;--asurf:#fdfdfd;--aglow:rgba(84,106,131,0.42);}

/* -- Compline -------------------------------------------------------------
   Dark as a palette you pick, not a mode that switches. There is no toggle,
   no class written before first paint and nothing to flash, because from the
   stylesheet's point of view this is just the eighth theme.

   Warm rather than blue-black: the point is evening reading, and a cool dark
   reads clinical. Amber because it is the one accent that holds AA on
   near-black without going neon. */
body.ath-compline{--ab:#100e0c;--ai:#f6f3f1;--am:#ada296;--ac1:#483c2e;--ac2:#27211b;--abr:#ddd0c0;--aac:#d9c4a8;--aacd:#d4c4b1;--aacink:#100e0c;--arow:#2b241e;--aline:#423930;--aicobg:#352d23;--asurf:#211c17;--aglow:rgba(217,196,168,.42);}

/* Where the light themes only repaint the app components, a dark one has to
   carry the site ramp as well — the tokens the others inherit from :root.
   Scoped to the installed app and to the theme preview, which is exactly what
   the picker promises ("how the app looks on your phone"). Public pages in a
   browser are untouched for everyone. */
html.app-mode body.ath-compline,
body.emb.ath-compline{
  color-scheme:dark;
  --navy:#1d1814;--snow:#100e0c;--charcoal:#dad3cc;--cyan:#d9c4a8;--paper:#100e0c;--bg:#100e0c;--cream:#211c17;--cream-2:#2b241e;--ink:#f6f3f1;--ink-soft:#dad3cc;--muted:#ada296;--ink-strong:var(--ink);--ink-invert:var(--ink);--ink-invert-soft:var(--ink-soft);--card:var(--cream);--line:#423930;--cyan-deep:#d4c4b1;--cyan-bright:#ddd0c0;--shadow-sm:0 1px 2px rgba(0,0,0,.55),0 2px 10px rgba(0,0,0,.45);--shadow-md:0 12px 36px rgba(0,0,0,.6),0 2px 8px rgba(0,0,0,.45);--shadow-lg:0 28px 70px rgba(0,0,0,.7);
  background:var(--paper);color:var(--ink);
}
/* Buttons name the brand primitives directly: .btn is --bg:var(--navy) with
   --fg:var(--paper). In every light theme that reads "dark fill, light text".
   In a dark palette both are near-black, and the shipped button measured
   1.06:1 — the label was simply not there.

   The rule itself is fine; it already exposes the two variables that decide
   this, so only the values change. --aacink exists for exactly this job:
   whatever reads on the accent fill. */
html.app-mode body.ath-compline .btn,
body.emb.ath-compline .btn,
html.app-mode body.ath-compline .btn--accent,
body.emb.ath-compline .btn--accent{--bg:var(--aac);--fg:var(--aacink);}
html.app-mode body.ath-compline .btn--member,
body.emb.ath-compline .btn--member{--bg:var(--aac);--fg:var(--aacink);box-shadow:inset 0 0 0 1.5px var(--aac);}
html.app-mode body.ath-compline .btn--light,
body.emb.ath-compline .btn--light{--bg:var(--ink);--fg:var(--paper);}
html.app-mode body.ath-compline .btn--ghost,
body.emb.ath-compline .btn--ghost{box-shadow:inset 0 0 0 1.5px color-mix(in srgb,var(--ink) 34%,transparent);}
/* The old html.dark mode has the same shape of bug and would need the same
   block. It is left alone deliberately: nothing sets that class today, and a
   rule for a mode that never runs is a rule nobody will remember to test. */

/* Photographs and logos are not chrome — never dim them. */
html.app-mode body.ath-compline img,
html.app-mode body.ath-compline video,
html.app-mode body.ath-compline .fill{filter:none;}

html.app-mode body[class*="ath-"].page-home{background:var(--ab);}
body[class*="ath-"] .appdash__kick{color:var(--aacd);}
body[class*="ath-"] .appdash__greet{color:var(--ai);}
body[class*="ath-"] .appdash__avatar{background:var(--ac2);}
body[class*="ath-"] .appcard--sunday{background:linear-gradient(155deg,var(--ac1),var(--ac2));}
body[class*="ath-"] .appcard--sunday::after{background:radial-gradient(70% 60% at 85% 0%,var(--aglow),transparent 60%);}
body[class*="ath-"] .appweek .is-today b{color:var(--ac2);}
body[class*="ath-"] .appweek .is-sun{color:var(--abr);}
body[class*="ath-"] .appcard__body .appk,
body[class*="ath-"] .appcard__body h2 .serif,
body[class*="ath-"] .appweekly b{color:var(--abr);}
body[class*="ath-"] .appfeature__body .appk{color:var(--abr);}
body[class*="ath-"] .applist__row{background:var(--arow);border-color:var(--aline);}
body[class*="ath-"] .applist__row b{color:var(--ai);}
body[class*="ath-"] .applist__row small,body[class*="ath-"] .applist__chev{color:var(--am);}
body[class*="ath-"] .applist__ico{background:var(--aicobg);color:var(--aacd);}
/* the tiles, per theme — same var mapping the rows used */
body[class*="ath-"] .applist__lbl{color:var(--aacd);}
body[class*="ath-"] .appms__t{background:var(--arow);border-color:var(--aline);color:var(--ai);}
body[class*="ath-"] .appms__t small{color:var(--am);}
body[class*="ath-"] .appms__ico{color:var(--aacd);}
body[class*="ath-"] .appms__t--wide{background:var(--aicobg);border-color:transparent;}
body[class*="ath-"] .appms__t--lead{background:linear-gradient(150deg,var(--ac1),var(--ac2));color:#fff;border-color:transparent;}
body[class*="ath-"] .appms__t--lead .appms__ico{color:#fff;}
body[class*="ath-"] .appms__t--lead b{color:#fff;}
body[class*="ath-"] .appms__t--lead small{color:#fff;}
body[class*="ath-"] .apptonight{background:var(--aicobg);border-color:var(--aline);color:var(--ai);}
/* The strip was picking up --aicobg, which is the theme's tinted icon chip —
   that pale blue is Sanctuary's. The serving line is a card you press, not a
   chip, so it takes --arow: the same surface the member tiles and the push
   card already sit on. White on the seven light themes, and correctly dark
   on Compline, rather than a hardcoded #fff that would blind that one. */
body[class*="ath-"] .apptonight--serve{background:var(--arow);border-color:var(--aline);}
body[class*="ath-"] .apptonight__dot{background:var(--aac);}
body[class*="ath-"] .apptonight__dot::after{border-color:var(--aac);}
body[class*="ath-"] .apptonight__t small{color:var(--am);}
body[class*="ath-"] .apptonight__chev{color:var(--aacd);}
body[class*="ath-"] .apppush{background:var(--arow);border-color:var(--aline);}
body[class*="ath-"] .apppush__ic{background:var(--aac);}
body[class*="ath-"] .apppush__tx b{color:var(--ai);}
body[class*="ath-"] .apppush__tx small{color:var(--am);}
body[class*="ath-"] .appdash__foot{color:var(--am);}
/* the inline-styled cards on the home page need a nudge */
body[class*="ath-"] .appcontinue{background:var(--arow) !important;border-color:var(--aline) !important;}
body[class*="ath-"] .appcontinue__body .appk{color:var(--aacd) !important;}
body[class*="ath-"] .appcountdown{background:linear-gradient(160deg,var(--ac2),var(--ac1)) !important;}
body[class*="ath-"] .appcountdown__k{color:var(--abr) !important;}
/* ---- contrast repair (see §2b) --------------------------------------------
   .appweekly i and .appweek span were rgba(255,255,255,.72) and .60 over the
   Sunday card. On the warmer palettes that measured 3.2:1 and 2.6:1 — under
   AA for normal text. Size and weight already separate them from the titles,
   so the alpha was buying nothing but a legibility problem.

   .appchip was rgba(255,255,255,.16), which lightened the gradient beneath it
   and made white-on-chip the worst pairing on the card in every theme. Sunk
   into the card instead of floating on it, it now improves contrast rather
   than eroding it. */
.appweekly i{color:#fff;opacity:.96;}
.appweek span{color:rgba(255,255,255,.88);}
.appweek b{color:#fff;}
.appchip{background:rgba(0,0,0,.20);box-shadow:inset 0 0 0 1px rgba(255,255,255,.24);}


/* =========================================================
   EDITORIAL LAYER — typography craft, pull quotes, lead story
   ========================================================= */

/* Kicker rule — a short tick beside section eyebrows */
.head .eyebrow,.split__copy .eyebrow{display:inline-flex;align-items:center;gap:.7em;}
.head .eyebrow::before,.split__copy .eyebrow::before{content:"";width:26px;height:1.5px;background:currentColor;opacity:.55;}
.head.center .eyebrow{justify-content:center;}
.head.center .eyebrow::after{content:"";width:26px;height:1.5px;background:currentColor;opacity:.55;}

/* Lede — a larger, lighter standfirst paragraph */
.lede{font-size:clamp(1.16rem,1rem + .8vw,1.5rem);line-height:1.55;color:var(--ink-soft);font-weight:400;letter-spacing:-.01em;}

/* Drop cap — Instrument Serif initial on a lead paragraph */
.dropcap::first-letter{float:left;font-family:var(--font-serif);font-style:italic;font-weight:400;
  font-size:3.5em;line-height:.72;padding:.04em .1em 0 0;color:var(--cyan-deep);}

/* Pull quotes — refined cite with rule (decorative quote mark removed) */
.quote blockquote{position:relative;}
.quote cite{position:relative;display:inline-flex;align-items:center;gap:.7em;}
.quote cite::before{content:"";width:34px;height:1.5px;background:currentColor;opacity:.5;}

/* Numbered editorial badge (Who We Are pillars) */
.card__num{font-family:var(--font-serif);font-style:italic;font-size:1.9rem;line-height:1;
  color:var(--cyan-deep);display:block;margin-bottom:6px;}
.card .kicker + h3{margin-top:2px;}

/* Small-caps photo caption */
.figcap{margin-top:10px;font-size:.7rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--muted);font-weight:600;display:flex;align-items:center;gap:.6em;}
.figcap::before{content:"";width:18px;height:1.5px;background:var(--cyan);opacity:.7;}

/* Sermons lead story — magazine cover feature */
.leadstory{display:grid;grid-template-columns:1.5fr 1fr;gap:clamp(28px,5vw,64px);align-items:center;}
.leadstory__media .vidcard{box-shadow:var(--shadow-md);}
.leadstory__kicker{font-family:var(--font-body);text-transform:uppercase;letter-spacing:.22em;font-size:.72rem;font-weight:700;color:var(--cyan-deep);display:inline-flex;align-items:center;gap:.7em;}
.leadstory__kicker::before{content:"";width:26px;height:1.5px;background:currentColor;opacity:.6;}
.leadstory__title{font-family:var(--font-serif);font-style:italic;font-weight:400;
  font-size:clamp(2rem,1.4rem + 2.4vw,3.4rem);line-height:1.04;letter-spacing:-.01em;color:var(--ink);margin-top:var(--space-md);}
.leadstory__meta{margin-top:var(--space-sm);color:var(--muted);font-size:.92rem;font-weight:600;letter-spacing:.02em;}
.leadstory__copy .btn{margin-top:var(--space-lg);}
@media(max-width:860px){.leadstory{grid-template-columns:1fr;}}

/* Header (frosted) card text dialed down ~30% for a calmer, more refined header */
.banner__card{max-width:560px;padding:clamp(20px,2.4vw,32px);}
.banner__card h1{font-size:clamp(1.7rem,1.15rem + 2.4vw,3.05rem);}
.banner__card p{font-size:clamp(.9rem,.86rem + .26vw,1.02rem);margin-top:var(--space-sm);}
.banner__card .eyebrow{font-size:.6rem;}
.banner__card .crumb{font-size:.72rem;margin-bottom:var(--space-sm);}

/* Event row with a promo image (calendar + events list) */
.vrow__img{width:clamp(116px,16vw,184px);aspect-ratio:16/10;border-radius:var(--radius-sm);overflow:hidden;flex-shrink:0;background:var(--navy);align-self:stretch;}
.vrow__img img{width:100%;height:100%;object-fit:cover;transition:transform .6s var(--ease-out);}
.vrow--img:hover .vrow__img img{transform:scale(1.06);}
@media(max-width:620px){.vrow--img{grid-template-columns:auto 1fr;}.vrow__img{width:108px;height:auto;aspect-ratio:auto;align-self:center;background:transparent;}.vrow__img img{height:auto;object-fit:contain;}}

/* ===== Summer Chapel — dark page + floating photo gallery ===== */
.scpage{background:#1e1812;color:var(--ink-invert-soft);}
.scpage--deep{background:#110e0b;}
.scpage h2{color:#fff;}
.scpage .head .eyebrow{color:var(--teal);}
.scpage .lead p{color:rgba(255,255,255,.84);}
.scpage .lead strong{color:var(--teal);}
.scfloat{position:relative;height:clamp(360px,48vw,560px);margin-top:var(--space-lg);}
.scfloat__t{position:absolute;border-radius:14px;overflow:hidden;background:#2e261d;box-shadow:0 22px 48px rgba(0,0,0,.5);opacity:0;will-change:transform,opacity;}
.scfloat__t img{width:100%;height:100%;object-fit:cover;display:block;}
.scfloat__hint{text-align:center;margin-top:var(--space-md);color:rgba(255,255,255,.5);font-size:.82rem;letter-spacing:.04em;}
@media(hover:none){.scfloat__hint{display:none;}}
@media(max-width:640px){
  .scfloat{height:clamp(320px,92vw,440px);}
  .scfloat__t--desk{display:none;}
}
/* hold tiles still + visible while an admin is editing the page */
body.edit-mode .scfloat__t{opacity:1 !important;transform:none !important;}

/* ===== Custom builder pages: gallery + embed ===== */
.cmsgal{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,240px),1fr));gap:14px;margin-top:var(--space-lg);}
/* Gallery shapes. Portrait and square tiles run a little narrower so a row
   still holds four on a desktop; the mosaic leads with one photo twice the
   size of the rest, the way a photographer opens a story. */
.cmsgal--portrait,.cmsgal--square{grid-template-columns:repeat(auto-fill,minmax(min(100%,200px),1fr));}
.cmsgal--mosaic{grid-template-columns:repeat(4,minmax(0,1fr));}
.cmsgal--mosaic>figure{aspect-ratio:1;}
.cmsgal--mosaic>figure:first-child{grid-column:span 2;grid-row:span 2;}
@media (max-width:640px){
  .cmsgal--portrait,.cmsgal--square{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;}
  .cmsgal--mosaic{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;}
  .cmsgal--mosaic>figure:first-child{grid-row:span 1;aspect-ratio:3/2;}
}
.cmsgal__ph{box-shadow:none;}
.cmsembed__v{position:relative;max-width:900px;margin:0 auto;aspect-ratio:16/9;border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow-md);background:var(--navy);}
.cmsembed__v iframe{position:absolute;inset:0;width:100%;height:100%;border:0;}

/* ===== Image lightbox (Creed / Covenant graphics, etc.) ===== */
.lightbox{position:fixed;inset:0;z-index:300;display:none;place-items:center;padding:24px;background:rgba(7,16,30,.88);backdrop-filter:blur(4px);}
.lightbox.is-open{display:grid;animation:lbfade .25s var(--ease-out);}
@keyframes lbfade{from{opacity:0;}to{opacity:1;}}
.lightbox img{max-width:min(620px,94vw);max-height:92vh;width:auto;height:auto;border-radius:12px;box-shadow:0 30px 90px rgba(0,0,0,.6);}
.lightbox__x{position:absolute;top:calc(env(safe-area-inset-top,0px) + 16px);right:16px;width:46px;height:46px;border-radius:50%;border:0;background:rgba(255,255,255,.16);color:#fff;font-size:1.5rem;line-height:1;cursor:pointer;display:grid;place-items:center;transition:background .2s,transform .2s var(--ease-out);}
.lightbox__x:hover{background:rgba(255,255,255,.28);transform:rotate(90deg);}
/* A labelled way out, top-left where a back control belongs — next to the cross
   rather than instead of it, because the person looking for a × and the person
   looking for the word "back" are not always the same person. */
.lightbox__back{position:absolute;top:calc(env(safe-area-inset-top,0px) + 16px);left:16px;min-height:46px;padding:0 18px 0 13px;
  border:0;border-radius:100px;background:rgba(255,255,255,.16);color:#fff;font:inherit;
  font-size:.95rem;font-weight:600;cursor:pointer;display:inline-flex;align-items:center;gap:7px;
  transition:background .2s;}
.lightbox__back:hover{background:rgba(255,255,255,.28);}
.lightbox__back svg{width:1.15em;height:1.15em;flex:none;}
/* A PDF read as pictures of its pages: one column that scrolls like anything
   else, rather than an iframe the phone will not let you move inside. The top
   padding is the room the Back control stands in. */
.lightbox--doc .lightbox__pages{width:min(980px,94vw);max-height:100vh;overflow:auto;overscroll-behavior:contain;
  -webkit-overflow-scrolling:touch;
  padding:calc(env(safe-area-inset-top,0px) + 76px) 0 calc(env(safe-area-inset-bottom,0px) + 28px);}
.lightbox--doc .lightbox__page{display:block;width:100%;height:auto;background:#fff;border-radius:6px;
  box-shadow:0 10px 30px rgba(0,0,0,.38);margin:0 auto 14px;}
.lightbox--doc .lightbox__page:last-child{margin-bottom:0;}
.lightbox__wait{color:#fff;opacity:.78;text-align:center;margin:0;padding:44px 0;font-size:.95rem;}
/* A PDF opened in the lightbox. An image sizes itself to its own dimensions; a
   document viewer has none of its own, so it is given a generous sheet of the
   viewport instead — tall, because these are pages of text meant to be read. */
.lightbox--doc{padding:16px;}
.lightbox__doc{width:min(900px,96vw);height:min(88vh,1100px);border:0;border-radius:var(--radius-inset);
  background:#fff;box-shadow:0 30px 90px rgba(0,0,0,.6);}
.lightbox__doc[hidden]{display:none;}
.lightbox--doc img{display:none;}
.lightbox__open{position:absolute;bottom:18px;left:50%;transform:translateX(-50%);
  color:#fff;font-size:.82rem;font-weight:600;letter-spacing:.02em;text-decoration:none;
  background:rgba(255,255,255,.16);padding:.55em 1.1em;border-radius:100px;transition:background .2s;}
.lightbox__open:hover{background:rgba(255,255,255,.3);}
.lightbox__open[hidden]{display:none;}
@media(max-width:640px){
  .lightbox--doc{padding:10px;}
  .lightbox__doc{width:100%;height:82vh;}
  .lightbox__open{bottom:10px;}
}

/* ===== Push notifications: friendly ask toast + "blocked" help sheet ===== */
.pushtoast{position:fixed;left:50%;bottom:calc(20px + env(safe-area-inset-bottom,0px));transform:translate(-50%,140%);z-index:240;display:flex;align-items:center;gap:16px;width:min(460px,calc(100vw - 28px));background:rgba(34,32,29,.86);backdrop-filter:blur(18px) saturate(1.5);-webkit-backdrop-filter:blur(18px) saturate(1.5);border:1px solid rgba(255,255,255,.16);border-radius:var(--radius-card);padding:14px 18px;box-shadow:0 24px 60px rgba(20,18,16,.45);transition:transform .5s var(--ease-out),opacity .4s;opacity:0;}
.pushtoast.is-in{transform:translate(-50%,0);opacity:1;}
html.app-mode .pushtoast{bottom:calc(96px + env(safe-area-inset-bottom,0px));}   /* clear the app bottom bar */
.pushtoast__txt{flex:1;min-width:0;color:rgba(250,247,242,.85);font-size:.82rem;line-height:1.4;}
.pushtoast__txt strong{display:block;color:#fff;font-family:var(--font-display);font-size:.92rem;margin-bottom:1px;}
.pushtoast__btns{display:flex;flex-direction:column;align-items:stretch;gap:6px;flex-shrink:0;}
.pushtoast__btns .btn{--bg:var(--cyan);padding:.55em 1.15em;font-size:.82rem;justify-content:center;}
.pushtoast__no{border:0;background:none;color:rgba(244,238,225,.6);font-family:var(--font-display);font-weight:600;font-size:.76rem;cursor:pointer;transition:color .2s;}
.pushtoast__no:hover{color:#fff;}

.pushhelp{position:fixed;inset:0;z-index:250;display:grid;place-items:end center;}
.pushhelp__backdrop{position:absolute;inset:0;background:rgba(7,18,33,.55);backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);opacity:0;transition:opacity .3s;}
.pushhelp.is-open .pushhelp__backdrop{opacity:1;}
.pushhelp__card{position:relative;width:min(480px,100vw);max-height:82vh;overflow:auto;background:var(--paper);border-radius:var(--radius-card) 24px 0 0;padding:26px 24px calc(26px + env(safe-area-inset-bottom,0px));box-shadow:0 -20px 60px rgba(20,18,16,.4);transform:translateY(30px);opacity:0;transition:transform .38s var(--ease-out),opacity .3s;}
@media(min-width:640px){.pushhelp{place-items:center;} .pushhelp__card{border-radius:var(--radius-card);padding-bottom:26px;}}
.pushhelp.is-open .pushhelp__card{transform:none;opacity:1;}
.pushhelp__card h3{font-size:1.3rem;letter-spacing:-.01em;}
.pushhelp__card p{color:var(--ink-soft);font-size:.92rem;margin-top:6px;}
.pushhelp__card ol{margin:14px 0 18px;padding-left:1.3em;display:grid;gap:8px;color:var(--ink-soft);font-size:.92rem;line-height:1.5;}
.pushhelp__card ol li::marker{color:var(--cyan-deep);font-weight:700;}
.pushhelp__card .btn{width:100%;justify-content:center;}
@media(prefers-reduced-motion:reduce){.pushtoast,.pushhelp__card,.pushhelp__backdrop{transition:none !important;}}

/* ===== Media request — "what happens next" ================================= */
.mrhelp{max-width:900px;}
.mrhelp h2{text-align:center;margin-bottom:28px;}
.mrsteps{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:20px;}
.mrstep{background:#fff;border:1px solid var(--line,#ece9e6);border-radius:var(--radius-card);padding:24px 22px;
  box-shadow:0 1px 2px rgba(34,32,29,.06),0 4px 16px -8px rgba(34,32,29,.10);}
.mrstep__n{display:grid;place-items:center;width:32px;height:32px;border-radius:50%;
  background:color-mix(in srgb,var(--cyan,#a08a6f) 13%,#fff);
  color:color-mix(in srgb,var(--cyan,#a08a6f) 78%,var(--navy,#22201d));
  font-weight:800;font-size:.9rem;margin-bottom:12px;}
.mrstep strong{display:block;font-size:1.02rem;margin-bottom:6px;}
.mrstep p{color:var(--muted,#6e6459);font-size:.92rem;line-height:1.6;margin:0;}
.mrhelp__note{text-align:center;color:var(--muted,#6e6459);font-size:.92rem;max-width:56ch;margin:28px auto 0;}
@media(max-width:640px){.mrsteps{gap:14px;}.mrstep{padding:20px 18px;}}

/* ===== App launch splash ==================================================
   The home hero's photographs crossing a grainy navy wash around the church
   mark. Standalone (home-screen) launches only.

   THE ENTRANCE IS DRIVEN FROM JAVASCRIPT, NOT FROM HERE — deliberately.

   Three CSS attempts at this all failed the same way: the tiles would settle
   into place and then the animation would start over. A CSS animation begins
   the moment its rule matches, and there is no way to be certain that moment
   is after the photographs have decoded. Declaring it paused and unpausing via
   a class still leaves the browser free to run it during a style recalculation
   it does on its own schedule.

   So there is no @keyframes for the tiles at all. This file only describes
   where a tile SITS before anything happens: off screen and invisible. The
   controller in inc/header.php creates the animation with element.animate()
   once decode has finished. An animation that doesn't exist yet cannot start
   early, and cannot restart. */
.csplash{position:fixed;inset:0;z-index:99999;overflow:hidden;
  display:grid;place-items:center;background:transparent;}

/* Every opaque pixel is on this layer, so this leaving is what reveals the app. */
.csplash__bg{position:absolute;inset:0;background:#000;}
.csplash__bg::before{content:"";position:absolute;inset:0;opacity:0;
  background:radial-gradient(120% 100% at 28% 16%,#57493a 0%,#3a332b 38%,var(--navy,#22201d) 76%);}
/* The wash is the one thing still animated in CSS: it has no dependency on the
   photographs, so starting it at first paint is correct. */
.csplash.is-ready .csplash__bg::before{animation:csWashIn .7s ease both;}

/* Grain: a fine speckle over a coarser mottle, so a flat gradient doesn't read
   as digital. Stronger here than on the home page — no photography behind it. */
.csplash__bg::after{content:"";position:absolute;inset:0;pointer-events:none;
  mix-blend-mode:overlay;opacity:.5;
  background-size:170px 170px,340px 340px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='600'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"),url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='600'%3E%3Cfilter id='m'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.35' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23m)'/%3E%3C/svg%3E");}
@keyframes csWashIn{ from{opacity:0} to{opacity:1} }

.csplash__scatter{position:absolute;inset:0;}

/* Resting state only. No animation, no keyframes — see the note above. */
.cstile{position:absolute;left:var(--l);top:var(--t);width:var(--w);aspect-ratio:var(--ar);
  border-radius:clamp(10px,2.6vw,16px);overflow:hidden;
  box-shadow:0 18px 44px rgba(0,0,0,.5);
  opacity:0;}
.cstile--l{transform:translate3d(-75vw,0,0);}
.cstile--r{transform:translate3d(75vw,0,0);}
/* Rotation lives on the image, which is never animated. */
.cstile img{width:100%;height:100%;object-fit:cover;display:block;
  transform:rotate(var(--r,0deg));}

.csplash__mark{position:relative;z-index:3;display:grid;place-items:center;opacity:0;}
.csplash__mark img{width:clamp(108px,30vw,168px);height:auto;display:block;
  filter:drop-shadow(0 12px 34px rgba(0,0,0,.55));}

/* Granted shortcuts in the app — the admin, a form, the CLC desk. Marked
   apart from the ordinary member rows with a tinted icon, so it reads as
   "something you've been given" rather than another menu item. */
.applist__row--extra .applist__ico{
  background:color-mix(in srgb,var(--cyan,#a08a6f) 15%,transparent);
  color:color-mix(in srgb,var(--cyan,#a08a6f) 82%,var(--ink,#22201d));}

/* ===== Members directory — households ====================================
   Modelled on the printed book: one photo, the family's name, then the people
   in it. Wide enough to read at a glance, dense enough that 312 families are
   still scannable. */
.pdirbar{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-bottom:var(--space-lg);}
.pdircount{color:var(--muted);font-size:.88rem;white-space:nowrap;}
.pdiraz{display:flex;flex-wrap:wrap;gap:4px;margin:0 0 var(--space-lg);position:sticky;top:0;z-index:4;
  background:var(--paper,#fff);padding:8px 0;}
.pdiraz a{display:inline-flex;align-items:center;justify-content:center;min-width:30px;height:30px;
  border-radius:8px;font-size:.82rem;font-weight:600;color:var(--muted);text-decoration:none;
  transition:background .14s,color .14s;}
.pdiraz a:hover{background:color-mix(in srgb,var(--cyan,#a08a6f) 14%,transparent);color:var(--navy,#22201d);}

.pdirltr{grid-column:1/-1;margin:var(--space-xl) 0 2px;font-size:.82rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--muted);font-weight:700;
  border-bottom:1px solid color-mix(in srgb,var(--ink,#22201d) 12%,transparent);padding-bottom:6px;}
.pdirltr:first-child{margin-top:0;}
.pdirltr[hidden]{display:none;}

.pdirhh{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:var(--space-md);align-items:start;}
.phh{display:flex;gap:14px;padding:14px;border-radius:var(--radius-card);background:var(--card,#fff);
  border:1px solid color-mix(in srgb,var(--ink,#22201d) 10%,transparent);
  transition:border-color .16s,box-shadow .16s,transform .16s;}
.phh:hover{border-color:color-mix(in srgb,var(--cyan,#a08a6f) 34%,transparent);
  box-shadow:0 10px 26px -14px rgba(34,32,29,.3);transform:translateY(-2px);}
.phh[hidden]{display:none;}

.phh__photo{flex:none;width:84px;aspect-ratio:4/5;border-radius:var(--radius-inset);overflow:hidden;
  background:color-mix(in srgb,var(--cyan,#a08a6f) 12%,transparent);
  display:flex;align-items:center;justify-content:center;}
.phh__photo img{width:100%;height:100%;object-fit:cover;display:block;}
.phh__initials{font-weight:700;font-size:1.15rem;color:var(--navy,#22201d);opacity:.62;letter-spacing:.02em;}

.phh__body{min-width:0;flex:1;}
.phh__name{margin:0;font-size:1.02rem;line-height:1.25;color:var(--ink,#22201d);
  overflow-wrap:anywhere;}
.phh__shared{margin:3px 0 0;font-size:.88rem;}
.phh__shared a{color:var(--muted);text-decoration:none;}
.phh__shared a:hover{color:var(--cyan,#a08a6f);text-decoration:underline;}

.phh__people{list-style:none;margin:8px 0 0;padding:0;display:grid;gap:6px;}
.phh__people li{font-size:.9rem;line-height:1.35;}
.phh__pn{display:block;font-weight:600;color:var(--ink,#22201d);}
.phh__pc{display:flex;flex-direction:column;gap:1px;margin-top:1px;}
.phh__pc a{color:var(--muted);text-decoration:none;font-size:.84rem;overflow-wrap:anywhere;}
.phh__pc a:hover{color:var(--cyan,#a08a6f);text-decoration:underline;}

@media(max-width:520px){
  .pdirhh{grid-template-columns:1fr;}
  .phh__photo{width:68px;}
}
/* The lift on hover is decoration, not information — the border still changes. */
@media(prefers-reduced-motion:reduce){
  .phh{transition:border-color .01s;}
  .phh:hover{transform:none;}
  .pdiraz a{transition:none;}
}

/* ------------------------------------------------- installed app: no footer
   The footer is a website's business card — address, socials, "add to home
   screen". Somebody already running the installed app has done all of that,
   so in standalone mode it's a long scroll to nothing.

   It's replaced by exactly the space the floating nav needs, so the last card
   on a page clears the bar instead of hiding behind it. Height is the bar
   (~62px) plus its 16px offset plus breathing room and the home indicator. */
html.app-mode .footer{display:none;}
html.app-mode main{padding-bottom:calc(env(safe-area-inset-bottom,0px) + 104px);}
/* The bar is only ever shown on small screens, so the reserve goes with it. */
@media (min-width:1041px){ html.app-mode main{padding-bottom:calc(env(safe-area-inset-bottom,0px) + 40px);} }

/* =========================================================================
   PRINTING
   -------------------------------------------------------------------------
   There was no print stylesheet on this site at all. Every page printed as a
   screenshot of a website: the navigation, the footer, the announcement bar,
   photographs bled to the edge, and the actual content squeezed into whatever
   was left. The CLC schedule is the first thing here anybody genuinely needs
   on paper — it goes on the wall behind the front desk and stays there for a
   month — so it gets a real one.

   The rule everything below follows: a printed page is a different document,
   not a photograph of a screen. Nothing that exists to be clicked survives.
   ========================================================================= */

@media print{
  /* Landscape, because a month is seven columns wide and nothing makes seven
     readable columns fit across a portrait page. */
  @page{ size:letter landscape; margin:11mm 10mm; }

  html,body{background:#fff !important;font-size:10pt;}
  body{overflow:visible;}

  /* Anything whose purpose is to be interacted with. A printed page has no
     hover, no tap and no next page — every one of these is either an
     instruction that can't be followed or ink spent on nothing. */
  .hdr,.header,.mobtop,.footer,.announce,.popup,.pop,.splash,.appnav,
  .banner,.crumb,.vsch__nav,.vsch__btn,.vclaim,.clc__signout,.vsch__actions,
  .skip,.js-push-enable,.footpush,[data-noprint]{ display:none !important; }

  /* Reveal the print-only masthead and footer, which never show on screen.
     Deliberately NOT !important: .vprint__head and .vprint__foot need to be
     flex, and an !important display:block here beats them and collapses both
     strips into one run-on line. The rule that hides these on screen is
     wrapped in @media screen instead, so there is nothing here to fight. */
  .vprint{ display:block; }

  main,.section,.wrap{ padding:0 !important;margin:0 !important;max-width:none !important; }
  section{ background:#fff !important; }

  /* Backgrounds carry meaning here — a closed day and an ordinary one differ
     only by their fill — so they must survive the browser's ink-saving. */
  .vmon,.vmon *,.vprint,.vprint *{ -webkit-print-color-adjust:exact;print-color-adjust:exact; }

  /* ---- the masthead ---- */
  .vprint__head{ display:flex;align-items:flex-end;gap:12pt;
    border-bottom:1.6pt solid #22201d;padding-bottom:4pt;margin-bottom:6pt; }
  .vprint__ttl{ margin-right:auto; }
  .vprint__eyebrow{ font-size:6.6pt;font-weight:700;letter-spacing:.22em;text-transform:uppercase;
    color:#a08a6f;margin-bottom:2pt; }
  .vprint__h{ font-family:"Montserrat",system-ui,sans-serif;font-size:17pt;font-weight:800;
    letter-spacing:-.02em;line-height:1;color:#22201d; }
  .vprint__h em{ font-family:"Instrument Serif",Georgia,serif;font-style:italic;font-weight:400; }
  .vprint__meta{ text-align:right;font-size:7.4pt;line-height:1.5;color:#574e44; }
  .vprint__meta strong{ color:#22201d; }

  /* ---- the grid ---- */
  .vsch__mon{ display:block !important; }
  .vmon{ width:100%;border-collapse:collapse;table-layout:fixed;border:.8pt solid #a89e91;
    border-radius:0;box-shadow:none; }
  .vmon th{ background:#f5f3f0 !important;border:.8pt solid #a89e91;padding:2.4pt 2pt;
    font-size:6.6pt;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:#595047; }
  /* Six rows is the worst a month can be, so every cell is sized for six and
     a five-row month simply breathes. Sizing for the common case instead is
     how you get one month a year that silently loses its last line. */
  /* 23mm x 6 rows = 138mm, which leaves about 20mm of slack under the
     masthead and footer on Letter landscape. Sized with slack on purpose:
     browsers disagree by a millimetre or two about margins and font metrics,
     and "fits in Chrome" is not the same promise as "fits". */
  .vmon td{ border:.6pt solid #cbc5be;vertical-align:top;padding:1.8pt 2.4pt;
    height:23mm;overflow:hidden; }
  .vmon td.is-out{ background:#f8f7f5 !important; }
  .vmon td.is-today{ background:#fff !important; }        /* "today" is a screen idea */

  .vmon__n{ font-family:"Montserrat",system-ui,sans-serif;font-size:9.2pt;font-weight:800;
    line-height:1;margin-bottom:2pt;color:#22201d;
    display:flex;align-items:baseline;justify-content:space-between;gap:3pt; }
  .vmon td.is-out .vmon__n{ color:#a89e91; }
  .vmon__wk{ font-size:5.8pt;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:#a08a6f; }

  .vmon__s{ display:grid;grid-template-columns:9mm 1fr;gap:1.6pt;margin-bottom:1.6pt; }
  .vmon__t{ font-size:6.4pt;font-weight:700;color:#a08a6f;line-height:1.15;padding-top:.3pt; }
  /* line-height carries a second job here. These spans are overflow:hidden so
     a long name can ellipsis, and at 1.16 the box ended exactly where the
     underline on a changed name sits — so the one mark that says "this is not
     the usual person" was being clipped away by the rule that shortens long
     names. 1.25 puts the descender space back and the underline inside the box. */
  .vmon__p span{ display:block;font-size:7.2pt;line-height:1.25;color:#22201d;font-weight:600;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }
  /* An open slot is the only thing on this sheet anybody has to act on, so on
     paper it is a rule to write on rather than the word "open" set in gray. */
  .vmon__p .is-open{ color:#968b80;font-weight:400;font-style:normal;
    border-bottom:.5pt dotted #a89e91;min-height:7.2pt; }
  .vmon__p .is-chg{ color:#22201d;font-weight:800;text-decoration:underline;
    text-underline-offset:1pt;text-decoration-thickness:.5pt; }

  /* One page is the whole point. Nothing may push a seventh row onto a second
     sheet, and no row may be split across a fold. */
  .vmon tr,.vmon td{ break-inside:avoid;page-break-inside:avoid; }
  .vsch__mon{ break-after:avoid;page-break-after:avoid; }

  /* ---- the footer strip ---- */
  .vprint__foot{ display:flex;align-items:center;flex-wrap:wrap;gap:4pt 14pt;
    margin-top:5pt;padding-top:4pt;
    border-top:.8pt solid #cbc5be;font-size:6.8pt;color:#595047; }
  .vprint__foot strong{ color:#22201d; }
  .vprint__foot .sp{ margin-left:auto; }
  .vprint__k{ display:inline-block;width:7pt;height:7pt;border:.6pt solid #a89e91;
    vertical-align:-.5pt;margin-right:2.5pt; }
  .vprint__k--open{ background:#fff !important;border-bottom:1.2pt dotted #a89e91; }

  /* The week list and the roster are screen furniture on a month print. They
     have their own sheets — see the print=week and print=roster views. */
  body.printing-month .vsch__days,body.printing-month .vsch__roster{ display:none !important; }
  body.printing-roster .vsch__days,body.printing-roster .vsch__mon{ display:none !important; }

  /* ---- the roster sheet, when that is what's being printed ---- */
  .vroster{ border:.8pt solid #a89e91;box-shadow:none;border-radius:0; }
  .vroster th{ background:#f5f3f0 !important;border-bottom:.8pt solid #a89e91;
    font-size:6.6pt;padding:3pt 4pt; }
  .vroster td{ border-top:.5pt solid #dad5cf;font-size:8.4pt;padding:3pt 4pt;color:#22201d; }
  .vroster tr{ break-inside:avoid;page-break-inside:avoid; }
  .vroster td a{ color:#22201d;text-decoration:none; }

  /* Links elsewhere shouldn't print their href — this is a rota, not a
     bibliography, and "(https://…)" after every name would be noise. */
  a[href]::after{ content:none !important; }
}

/* The print masthead and footer exist in the markup on every schedule page so
   the browser's own print button produces the right document with nothing
   asked of anybody. They are simply never shown on a screen — and this is
   scoped to @media screen rather than left unscoped, so it cannot reach into
   the print rules above and undo them. */
@media screen{ .vprint{ display:none; } }


/* ══ Small groups: the message the questions came from ═══════════════════
   Sits between the prayer and the announcements, on the same 760px measure
   as every other block on that page so the column never wobbles. Built as a
   two-up rather than a stacked card: at reading width the thumbnail earns
   its place beside the title instead of pushing the announcements a whole
   screen further down. */
.sgserm{
  display:grid;grid-template-columns:minmax(0,196px) minmax(0,1fr);
  gap:clamp(15px,2.4vw,24px);align-items:center;
  max-width:760px;margin:var(--space-lg) auto 0;padding:14px;
  border-radius:var(--radius);background:var(--card,#fff);
  border:1px solid color-mix(in srgb,var(--ink,#22201d) 11%,transparent);
  box-shadow:0 10px 30px -20px rgba(34,32,29,.35);
  color:inherit;text-decoration:none;
  transition:box-shadow .3s cubic-bezier(.25,1,.5,1),border-color .3s cubic-bezier(.25,1,.5,1);
}
.sgserm:hover{border-color:color-mix(in srgb,var(--cyan) 45%,transparent);box-shadow:0 18px 44px -22px rgba(34,32,29,.5)}
.sgserm:focus-visible{outline:2px solid var(--cyan);outline-offset:3px}
.sgserm__thumb{position:relative;display:block;border-radius:calc(var(--radius) - 6px);overflow:hidden;background:var(--cream-2);aspect-ratio:16/9}
.sgserm__thumb img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .55s cubic-bezier(.22,1,.36,1)}
/* The image moves, not the card. A card that lifts on hover nudges the
   announcements below it; scaling inside a clipped frame costs nothing. */
.sgserm:hover .sgserm__thumb img{transform:scale(1.045)}
.sgserm__play{position:absolute;inset:0;display:grid;place-items:center;color:#fff}
.sgserm__play svg{width:46px;height:46px;filter:drop-shadow(0 2px 10px rgba(20,18,16,.55));
  transition:transform .3s cubic-bezier(.25,1,.5,1)}
.sgserm:hover .sgserm__play svg{transform:scale(1.09)}
.sgserm__body{display:flex;flex-direction:column;gap:5px;min-width:0}
.sgserm__lab{font-family:var(--font-display);font-weight:800;font-size:.7rem;
  letter-spacing:.15em;text-transform:uppercase;color:var(--cyan)}
.sgserm__t{font-family:var(--font-display);font-weight:700;font-size:1.12rem;line-height:1.3;color:var(--ink-strong)}
.sgserm__m{font-size:.88rem;color:var(--muted)}
.sgserm__go{margin-top:4px;font-weight:600;font-size:.9rem;color:var(--cyan);display:inline-flex;align-items:center;gap:.4em}
.sgserm__go .arrow{transition:transform .3s cubic-bezier(.25,1,.5,1)}
.sgserm:hover .sgserm__go .arrow{transform:translateX(4px)}
@media(max-width:560px){
  .sgserm{grid-template-columns:1fr;gap:13px}
  .sgserm__t{font-size:1.05rem}
}
@media(prefers-reduced-motion:reduce){
  .sgserm,.sgserm__thumb img,.sgserm__play svg,.sgserm__go .arrow{transition:none}
  .sgserm:hover .sgserm__thumb img,.sgserm:hover .sgserm__play svg{transform:none}
}


/* ---- footer action row -----------------------------------------------------
   Members, Community Life Center, Get the App and the notifications button.
   All four used color:inherit, so they picked up the footer's 0.5-alpha body
   color — about 4.4:1 on the navy, under the 4.5:1 AA floor and dimmer than
   the ordinary nav links sitting above them. The most useful things in the
   footer were the hardest to see. They now read as buttons, reusing the pill
   shape .footpush already had so the row is one thing rather than three
   underlined links and a pill. */
.footer__clc,
.footpush{
  display:inline-flex;align-items:center;gap:.4em;
  color:rgba(244,238,225,.95);
  text-decoration:none;
  font-weight:600;
  font-size:.82rem;
  padding:.45em .95em;
  border:1px solid rgba(255,255,255,.3);
  border-radius:100px;
  background:rgba(255,255,255,.04);
  transition:background .25s,border-color .25s,color .25s;
}
.footer__clc:hover,
.footpush:hover{
  background:rgba(255,255,255,.12);
  border-color:rgba(255,255,255,.55);
  color:#fff;
}
.footer__clc:focus-visible,
.footpush:focus-visible{outline:2px solid #d9c4a8;outline-offset:2px;}

/* "Get the App" carries .footer__app too, a button reset that lives in a later
   stylesheet and so wins on order at equal specificity. Two classes beats one
   wherever it sits, which keeps the row consistent without unpicking the reset. */
.footer__clc.footer__app{
  display:inline-flex;align-items:center;gap:.4em;
  color:rgba(244,238,225,.95);
  font-weight:600;
  font-size:.82rem;
  padding:.45em .95em;
  border:1px solid rgba(255,255,255,.3);
  border-radius:100px;
  background:rgba(255,255,255,.04);
}
.footer__clc.footer__app:hover{
  background:rgba(255,255,255,.12);
  border-color:rgba(255,255,255,.55);
  color:#fff;
}

/* The base .footer__clc underline is right for a text link and wrong once the
   thing is a pill — it was still showing under "Get the App". */
.footer__clc,.footer__clc:hover,.footer__clc.footer__app{text-decoration:none;}
/* Give the row room now that its items have borders, and keep them on one
   baseline when it wraps. */
.footer__bottom{display:flex;flex-wrap:wrap;align-items:center;gap:10px 12px;}

/* The three destinations group together; the service time is prose and should
   not sit in the same visual run as the buttons. */
.footer__acts{display:flex;flex-wrap:wrap;align-items:center;gap:10px;}
.footer__svc{opacity:.9;font-size:.9em;}

/* ---- desktop: shortcuts for signed-in members --------------------------
   The portal was reachable from the installed app and the footer, and nowhere
   else. Anyone at a desk had to go looking for it. This is the same set of
   links the app gives, sitting where a signed-in person expects to find them.
   Hover and focus-within only, no JS, so it cannot fall out of step with the
   pill animation the main menu runs. */
.navmem{position:relative;display:none;}
@media (min-width:1041px){ .navmem{display:block;} }
.navmem__btn{display:inline-flex;align-items:center;gap:.5em;padding:.4em .9em .4em .45em;
  border:1px solid rgba(255,255,255,.28);border-radius:100px;background:rgba(255,255,255,.06);
  /* The pill it sits in is always rgba(34,32,29,.7). Inheriting the page ink
     put navy on navy - the name was there, just unreadable. Every other item
     in the pill is paper; this is now the same. */
  color:var(--ink-invert,#faf7f2);text-decoration:none;font-weight:600;font-size:.84rem;white-space:nowrap;
  transition:background .25s,border-color .25s;}
.navmem__btn:hover{background:rgba(255,255,255,.13);border-color:rgba(255,255,255,.45);}
.navmem:focus-within .navmem__btn{background:rgba(255,255,255,.13);border-color:rgba(255,255,255,.45);}
.navmem__ava{width:24px;height:24px;border-radius:50%;flex:none;display:block;overflow:hidden;
  background:rgba(255,255,255,.18);}
.navmem__ava img{width:100%;height:100%;object-fit:cover;display:block;}
.navmem__ava svg{width:16px;height:16px;margin:4px;display:block;}
.navmem__menu{position:absolute;right:0;top:calc(100% + 10px);min-width:212px;background:#fff;
  border-radius:14px;padding:8px;border:1px solid rgba(34,32,29,.08);
  box-shadow:0 18px 44px rgba(20,18,16,.18);opacity:0;visibility:hidden;transform:translateY(-6px);
  transition:opacity .2s var(--ease-out),transform .2s var(--ease-out),visibility .2s;z-index:120;}
@media (hover:hover){ .navmem:hover .navmem__menu{opacity:1;visibility:visible;transform:translateY(0);} }
.navmem:focus-within .navmem__menu{opacity:1;visibility:visible;transform:translateY(0);}
.navmem__hd{padding:.35em .7em .5em;font-size:.72rem;letter-spacing:.08em;text-transform:uppercase;
  color:rgba(34,32,29,.5);font-weight:700;}
/* 14px popover, 8px padding over a 1px border: the item corner is what is
   left of the outer curve once the inset is taken off it. */
.navmem__menu a{display:block;padding:.55em .7em;border-radius:5px;color:#22201d;
  text-decoration:none;font-size:.88rem;font-weight:600;}
/* Access given to this person by name gets its own heading rather than being
   mixed into the portal list - "why can she see that?" should be answerable by
   looking. The icons are the same drawings the installed app uses for the same
   shortcuts, so one thing looks like one thing wherever you meet it. */
.navmem__hd--grant{margin-top:6px;padding-top:.62em;box-shadow:inset 0 1px 0 rgba(34,32,29,.1);}
.navmem__menu a.navmem__grant{display:flex;align-items:center;gap:.55em;}
.navmem__gic{flex:none;display:grid;place-items:center;width:18px;height:18px;
  color:var(--cyan-deep,#7d6a52);}
.navmem__gic svg{width:16px;height:16px;display:block;}
.navmem__menu a:hover{background:rgba(34,32,29,.06);}
@media (prefers-reduced-motion:reduce){ .navmem__menu{transition:none;} }

/* ---- photo framing: zoom on background images ---------------------------
   <img> photos have had position and zoom for a while. The background layers
   only ever had position, which is the gap. The zoom arrives as --eiz rather
   than as an inline transform so that a layer already carrying a scale of its
   own composes with it instead of losing it: the blurred hero backdrops are
   scaled 1.12 to hide the soft edge left by the blur, and an inline transform
   would have quietly dropped that and shown a halo. */
.banner__photo,.formstage__bg{transform:scale(var(--eiz,1));transform-origin:var(--eix,50%) var(--eiy,50%);}
.mhero__bg,.smhero__bg,.smhero__sharp{transform:scale(calc(1.12 * var(--eiz,1)));transform-origin:var(--eix,50%) var(--eiy,50%);}

/* The reveal button on password boxes. Built by site.js, which wraps every
   input[type=password] on the site rather than each form doing it itself.
   Color is inherited so the same button reads correctly on the dark sign-in
   panels and the light admin ones. */
.pwfield{position:relative;display:block;}
.pwfield input{width:100%;padding-right:3em;}
.pwfield__t{position:absolute;top:50%;right:.5em;transform:translateY(-50%);
  display:grid;place-items:center;width:2.1em;height:2.1em;padding:0;
  border:0;background:transparent;cursor:pointer;border-radius:50%;
  color:inherit;opacity:.55;
  transition:opacity .18s,background-color .18s;}
.pwfield__t:hover{opacity:1;background:color-mix(in srgb,currentColor 12%,transparent);}
.pwfield__t:focus-visible{opacity:1;outline:2.5px solid var(--cyan,#a08a6f);outline-offset:1px;}
.pwfield__t svg{width:18px;height:18px;display:block;}
@media(prefers-reduced-motion:reduce){.pwfield__t{transition:none;}}

/* --- app themes: color the app, not the paper ----------------------------
   A theme was repainting the page itself — Sunset turned every white surface
   cream, Peony Blush turned it pink. The intent is that the color lands on
   the things that are already colored: accents, buttons, headings, icon
   chips. So the three surface tokens are pinned back to the church's own
   near-whites and everything else stays themed.

   Compline is excepted because it is the dark theme and dark paper is the
   whole point of it. Site dark mode is untouched for the same reason: there
   the surfaces are supposed to move. */
html:not(.dark) body[class*="ath-"]:not(.ath-compline){
  --ab:#faf9f7;
  --arow:#f6f2ec;
  --asurf:#fdfdfd;
}

/* --- Compline: the swatch is the promise ----------------------------------
   The tile shows the theme before you pick it, so the two have to agree. The
   accent family here is the site accent, not a second one: app chrome and
   page share a single ice blue on obsidian. An earlier pass rebuilt this
   around a slate blue while the page was still rendering gold - the tile and
   the theme disagreed in both directions at once. */
body.ath-compline, html.dark body.ath-compline{
  --ac1:#483c2e;
  --ac2:#27211b;
  --abr:#ddd0c0;
  --aac:#d9c4a8;
  --aacd:#d4c4b1;
  --aacink:#100e0c;
  --aicobg:#352d23;
  --aglow:rgba(217,196,168,.42);
}

/* --- tab bar: immediate answer to a press ------------------------------- */
.botbar__item{-webkit-tap-highlight-color:transparent;transition:transform .14s cubic-bezier(.22,1,.36,1),opacity .18s}
.botbar__item:active{transform:scale(.9)}
/* held from the tap until the next page paints, so the bar is never dead */
.botbar__item.is-going{opacity:.6}
@media (prefers-reduced-motion:reduce){.botbar__item{transition:none}.botbar__item:active{transform:none}}


/* ---------- Which way the page went ------------------------------------
   The installed app already slid one page out and the next one in, but both
   moved vertically, so every navigation looked the same: a lift and a fade,
   whether you were going somewhere or coming back. That is what made the
   conversations read as a cut - nothing in the movement said which
   direction you had traveled.

   header.php works that out before anything paints and leaves the answer on
   the html element. The first page of a session still lifts, because it did
   not come from anywhere. After that: onward from the right, back from the
   left, the way iOS has always done it. */
html.app-mode[data-nav="push"] main{animation:appPushIn .34s var(--ae-out,cubic-bezier(.16,1,.3,1)) both;}
html.app-mode[data-nav="pop"] main {animation:appPopIn  .34s var(--ae-out,cubic-bezier(.16,1,.3,1)) both;}
@keyframes appPushIn{from{opacity:0;transform:translate3d(26px,0,0);}}
@keyframes appPopIn {from{opacity:0;transform:translate3d(-20px,0,0);}}

/* The page leaves in the direction it is traveling, and only part way - it
   is still on screen when the next one is requested, so there is never a
   blank frame in between. Faster than the arrival, which is what stops the
   pair reading as a crossfade. */
/* The old page has to keep moving for as long as the next one takes to
   arrive, and nobody knows how long that is. A short animation finishes and
   then the page sits there, stopped, until the new document commits - and a
   thing that was moving and has stopped reads as stuck, which is worse than
   never having moved.

   So the movement is long and the timing is linear, with the easing written
   into the keyframes instead: a quick shove over the first fifth, then a
   slow drift that still has somewhere to go two seconds later. Whenever the
   next page paints it cuts this off mid-stride, which is the point. The
   navigation is requested immediately, so none of this is delay - it is
   what covers the wait that was always there. */
html.app-mode.page-exit[data-exit="push"] main{animation:appPushOut 2s linear both;}
html.app-mode.page-exit[data-exit="pop"] main {animation:appPopOut  2s linear both;}
@keyframes appPushOut{
  0%  {opacity:1;  transform:none;}
  10% {opacity:.82;transform:translate3d(-15px,0,0);}
  30% {opacity:.68;transform:translate3d(-27px,0,0);}
  100%{opacity:.42;transform:translate3d(-74px,0,0);}
}
@keyframes appPopOut{
  0%  {opacity:1;  transform:none;}
  10% {opacity:.82;transform:translate3d(15px,0,0);}
  30% {opacity:.68;transform:translate3d(27px,0,0);}
  100%{opacity:.42;transform:translate3d(74px,0,0);}
}

@media(prefers-reduced-motion:reduce){
  html.app-mode[data-nav] main,html.app-mode.page-exit[data-exit] main{animation:none;}
}


/* ---------- Page motion moves to script -------------------------------
   A CSS animation on a freshly loaded document starts its clock the moment
   the element is first rendered - which, in an installed iOS app, can be
   well before the compositor is allowed to show anything. Load a page that
   is already cached and the animation has finished before you ever see it,
   so the screen simply appears. That is the hard cut.

   Script can wait for the first frame the reader actually gets, so the
   entrance is started there instead. These rules stand down; site.js owns
   the movement now. */
html.app-mode main,
html.app-mode[data-nav] main,
html.app-mode.page-exit main,
html.app-mode.page-exit[data-exit] main,
html.msg-app main,
html.msg-app.page-exit main{animation:none !important;}

/* ---------- The tab pill ----------------------------------------------
   Four tenths of a second on an ease-in-out: it crept away from the old tab
   before committing, and was still settling long after the finger had gone.
   The pill is chasing a finger that has already arrived, so it wants no
   slow start at all - full speed immediately, then a decelerating landing. */
.botbar__pill{transition:transform .22s cubic-bezier(.22,1,.36,1),
                          width .22s cubic-bezier(.22,1,.36,1),
                          height .22s cubic-bezier(.22,1,.36,1),
                          opacity .16s linear;}
@media (prefers-reduced-motion:reduce){ .botbar__pill{transition:none;} }

/* A screen traveling the full width of the viewport is briefly outside it.
   The body already hides the overflow; the root needs telling too, or the
   page gains a scrollbar for a third of a second on the way past. */
html.app-mode{overflow-x:hidden;}

/* Where an arriving page starts.

   This has to be in CSS rather than in the animation, because it has to be
   true in the very first frame the compositor is allowed to show, and on an
   installed app that can be before any script has run. Setting it from
   script meant a cached page appeared in place and then hopped backwards to
   slide in - clearly visible in a recording, and worse than no animation.

   site.js takes over on the first animation frame: it creates the animation
   holding this same value, then removes the attribute, so nothing is ever
   painted in between. header.php clears the attribute after a second
   regardless, so a page can never be left parked off screen. */
html.app-mode[data-nav="push"] main{transform:translate3d(100%,0,0);}
html.app-mode[data-nav="pop"] main{transform:translate3d(-30%,0,0);}
@media (prefers-reduced-motion:reduce){
  html.app-mode[data-nav="push"] main,
  html.app-mode[data-nav="pop"] main{transform:none;}
}

/* Said out loud when a page catches itself up, because content that changes
   under a reader without saying so is worse than content that is a minute
   old. Sits above the tab bar, gone in under three seconds. */
.freshtip{position:fixed;left:50%;bottom:96px;transform:translateX(-50%);z-index:220;
  padding:9px 16px;border-radius:100px;font-size:.86rem;font-weight:600;
  background:rgba(34,32,29,.92);color:#faf7f2;
  -webkit-backdrop-filter:saturate(180%) blur(10px);backdrop-filter:saturate(180%) blur(10px);
  box-shadow:0 10px 30px rgba(20,18,16,.28);pointer-events:none;}
@media (min-width:1041px){ .freshtip{bottom:28px;} }


/* ── events that have already happened ────────────────────────────────────
   They stay on their month, sorted last and quietened. Muted color rather
   than a dropped opacity: fading the whole row takes the title below a
   readable contrast, and a past event is still something somebody may be
   looking for. The hover lift goes, because there is nothing to anticipate. */
.vrow.is-past{background:var(--cream)}
.vrow.is-past:hover{transform:none;box-shadow:none}
.vrow.is-past h3{color:var(--muted)}
.vrow.is-past .tagline{color:var(--muted)}
.vrow.is-past .when .d,.vrow.is-past .when .m{color:var(--muted)}
.vrow.is-past .img img,.vrow.is-past .vrow__img img{filter:grayscale(1);opacity:.6}
.vlist__sep{margin:var(--space-lg) 0 var(--space-md);
  font-family:var(--font-display);font-weight:700;font-size:.72rem;
  text-transform:uppercase;letter-spacing:.1em;color:var(--muted)}

/* .........................................................
   EVENT LISTS - one shape for every card
   Two things happen here. Every card takes the height of the tallest in its
   list, so the column reads as a column rather than a ragged edge. And the
   blurb is held to two lines, so the tallest card is not simply the one whose
   description ran long. The full text is on the event's own page, which is
   where the Details link has always gone.
   Scoped to .vlist--even so sermon rows keep their natural height.
   ......................................................... */
.vlist--even{grid-auto-rows:1fr}
.vlist--even .vrow{align-content:center}
.vlist--even .vrow h3,
.vlist--even .vrow .meta,
.vlist--even .vrow__desc{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden}
.vlist--even .vrow h3{-webkit-line-clamp:2}
.vlist--even .vrow .meta{-webkit-line-clamp:2}
.vlist--even .vrow__desc{-webkit-line-clamp:2}
.vrow__desc{color:var(--muted);font-size:.85rem;margin-top:2px}
/* Equal rows get a list its shape, but the calendar splits upcoming from past
   into two lists, and two lists can settle at two different heights. Reserving
   the clamped number of lines - 2lh is exactly two lines of this element - ties
   them together. Browsers without the lh unit fall back to the grid above,
   which is uniform within each list. */
.vlist--even .vrow__desc{min-height:2lh}
/* Calendar thumbnails come in whatever shape the artwork was made in, which
   left the rows sitting at slightly different heights. One ratio for all of
   them; the events page keeps its own larger treatment. */
/* 16:9, because that is the shape the artwork is actually made in - an event graphic is
   widescreen, and a near-square frame was cropping the top and bottom off every one of them.
   The height has to come off the ratio rather than the row, so align-self:center is part of
   the fix and not decoration: stretched to the row the frame was landing at 150x129 and the
   declared ratio was being quietly ignored. */
.vlist--even:not(.vlist--wide) .vrow__img{width:clamp(150px,19vw,232px);aspect-ratio:16/9;height:auto;align-self:center;overflow:hidden;border-radius:calc(var(--radius) - 6px);margin:0}
.vlist--even:not(.vlist--wide) .vrow__img img{width:100%;height:100%;object-fit:cover;display:block}
@media(max-width:860px){
  .vlist--even .vrow h3{min-height:2lh}
  .vlist--even .vrow .meta{min-height:2lh}
}
/* The category line was the last thing setting rows adrift: a short category
   sat on one line, a long one ran to three. Two lines for every card. The
   calendar leads with the date so a clamp can never take it. */
.vlist--even .vrow .tagline{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;min-height:2lh}
/* On a 320px phone the Details label wrapped in the one row that has no
   artwork, which pushed that card taller than its neighbors. */
.vlist--even .vrow .btn{white-space:nowrap}
.vrow.is-past .vrow__desc{color:var(--muted)}

/* .........................................................
   EVENT CARDS ON PHONES
   Artwork full width, the date and Details as frosted chips on top of it,
   the words underneath. Lifted out of the events page so the calendar can
   wear the same clothes. .vlist--wide is the desktop row treatment, which
   only the events page uses.
   ......................................................... */
.reg-open-tag{display:inline-block;margin-left:.5em;color:var(--cyan-deep);font-weight:700;font-size:.78em}
/* frosted chips live on the image in the mobile card layout only */
.evmob__pill,.evmob__cta{display:none}
/* desktop rows: artwork fills the card with a clean 5px inset */
/* The calendar's rows fell through to the plain .vrow padding above the card
   breakpoint, so the same event carried a 5px inset on /events/ and 16px on
   /calendar/, with a smaller photo to match: two paddings for one card, on two
   pages a visitor moves straight between. Above the card breakpoint they now
   share the wide treatment. The phone layout below is untouched. */
@media(min-width:641px){
  .vlist--wide .vrow--img,.vlist--card .vrow--img{padding:5px;gap:0 var(--space-lg)}
  .vlist--wide .vrow--img .vrow__img,.vlist--card .vrow--img .vrow__img{width:clamp(210px,24vw,320px);aspect-ratio:16/9;height:auto;min-height:0;align-self:center;border-radius:calc(var(--radius) - 5px)}
  .vlist--wide .vrow--img>div,.vlist--card .vrow--img>div{padding:var(--space-md) 0}
  .vlist--wide .vrow--img>.btn,.vlist--card .vrow--img>.btn{margin-right:var(--space-md)}
}
@media(max-width:640px){
  .vlist--card{gap:var(--space-lg)}
  .vlist--card .vrow--img{display:block;padding:0;background:transparent;border:0;box-shadow:none;overflow:visible}
  .vlist--card .vrow--img::before{display:none}
  .vlist--card .vrow--img:hover{transform:none;box-shadow:none}
  .vlist--card .vrow--img .vrow__img{position:relative;width:100%;height:auto;aspect-ratio:16/9;border-radius:var(--radius-inset);overflow:hidden;background:var(--navy);box-shadow:0 16px 38px rgba(34,32,29,.2);align-self:auto}
  .vlist--card .vrow--img .vrow__img img{width:100%;height:100%;object-fit:cover}
  .vlist--card .vrow--img>div{padding:12px 8px 2px}
  .vlist--card .vrow--img .tagline{display:none}
  .vlist--card .vrow--img>.btn{display:none}
  .evmob__pill,.evmob__cta{display:inline-flex;align-items:center;position:absolute;top:12px;z-index:2;height:36px;padding:0 15px;border-radius:999px;
    font-size:.82rem;font-weight:700;letter-spacing:.02em;color:#fff;text-shadow:0 1px 4px rgba(0,0,0,.3);
    background:rgba(255,255,255,.16);border:1px solid rgba(255,255,255,.38);
    backdrop-filter:blur(14px) saturate(1.5);-webkit-backdrop-filter:blur(14px) saturate(1.5);
    box-shadow:0 6px 18px rgba(0,0,0,.14)}
  .evmob__pill{left:12px}
  .evmob__cta{right:12px}
}

/* .........................................................
   COMPLINE - surfaces the theme could not reach through a token
   Three components hard-code a light background, and the calendar paints its
   event chips with an inline color worked out for a light grid. Nothing in
   the palette can reach any of them, so they are named here. The !important
   is aimed at an inline style, which is the only thing that outranks it.
   ......................................................... */
html.app-mode body.ath-compline .clcgate,
body.emb.ath-compline .clcgate{background:var(--cream)}
/* The children page paints its own sections a fixed coral, green, amber or
   white and lets the heading take the theme ink, which works while the ink
   is dark. Those four surfaces do not follow the theme, so on this one page
   the text does not either. */
html.app-mode body.ath-compline .ksec,
body.emb.ath-compline .ksec,
html.app-mode body.ath-compline .ksec h2,
body.emb.ath-compline .ksec h2,
html.app-mode body.ath-compline .ksec h3,
body.emb.ath-compline .ksec h3,
html.app-mode body.ath-compline .ksec p,
body.emb.ath-compline .ksec p{color:var(--navy)}
html.app-mode body.ath-compline .ksec .serif,
body.emb.ath-compline .ksec .serif{color:color-mix(in srgb,var(--cyan) 45%,#000)}
html.app-mode body.ath-compline .cal__ev--photo,
body.emb.ath-compline .cal__ev--photo{color:var(--ink) !important}


/* ---- small group directory -------------------------------------------------
   Photo-led, because the question somebody is really asking is "who are these
   people", and a face answers it faster than a paragraph.

   Everything here is on the site's own 4pt scale. The card has two zones and
   the spacing says so: the four lines that identify a group sit tight together,
   then a full step of air before the names you can actually click. No rule
   between them - a hairline would make this read like a table, which is the
   one thing a page of families in their living rooms should not do. */
.sgdir__list{display:grid;gap:var(--space-md);
  grid-template-columns:repeat(auto-fill,minmax(215px,1fr));margin-top:var(--space-lg)}
/* A card that behaves like a button should not behave like a paragraph:
   no blue flash on tap, no accidental text selection on a long press. */
.sgdir{position:relative;background:var(--card,#fff);border:1px solid var(--line);border-radius:var(--radius);
  -webkit-tap-highlight-color:transparent;-webkit-user-select:none;user-select:none;
  overflow:hidden;display:flex;flex-direction:column;
  transition:border-color .16s var(--ease-out),box-shadow .16s var(--ease-out),transform .16s var(--ease-out)}
.sgdir:hover{border-color:color-mix(in srgb,var(--cyan) 45%,var(--line));
  box-shadow:0 10px 26px rgba(34,32,29,.10);transform:translateY(-2px)}
.sgdir:active{transform:translateY(0)}
@media(prefers-reduced-motion:reduce){.sgdir,.sgdir:hover{transform:none}}
/* the whole card opens the panel; the button is the only tab stop in it */
.sgdir__go{font:inherit;color:inherit;background:none;border:0;padding:0;text-align:left;cursor:pointer;
  -webkit-tap-highlight-color:transparent}
.sgdir__go::after{content:"";position:absolute;inset:0;border-radius:inherit}
.sgdir:has(.sgdir__go:focus-visible){outline:2px solid var(--cyan);outline-offset:3px}
.sgdir__go:focus-visible{outline:none}
.sgdir__photo{margin:0;aspect-ratio:3/4;overflow:hidden;background:var(--cream)}
.sgdir__photo img{width:100%;height:100%;object-fit:cover;display:block}

.sgdir__body{padding:var(--space-sm) var(--space-md) var(--space-md);
  display:flex;flex-direction:column;flex:1}
.sgdir__body .kicker{font-size:.64rem;letter-spacing:.11em;text-transform:uppercase;
  font-weight:700;color:var(--cyan-deep)}
.sgdir__body h3{margin:var(--space-2xs) 0 0;font-size:1.125rem;line-height:1.22}
.sgdir__where{color:var(--muted);font-size:.8rem;margin:var(--space-2xs) 0 0;
  display:flex;align-items:center;gap:var(--space-xs);flex-wrap:wrap}
.sgtag{font-size:.6rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--cyan-deep);background:color-mix(in srgb,var(--cyan) 12%,#fff);
  border-radius:999px;padding:var(--space-2xs) var(--space-xs);white-space:nowrap}
.sgdir__soon{margin:var(--space-xs) 0 0;font-size:.78rem;font-weight:600;color:var(--navy)}

/* auto pushes the names to the foot of the card, so a two-line group name and a
   one-line one still line their names up across a row */
.sgdir__who{margin:auto 0 0;padding-top:var(--space-md);font-size:.9rem;line-height:1.5}
.sgdir__amp{color:var(--muted)}
/* keeps "& Melissa Barrett" together, so an ampersand never ends a line */
.sgdir__pair{white-space:nowrap}
.sgdir__who{color:var(--navy);font-weight:600}

@media(max-width:600px){
  .sgdir__list{grid-template-columns:repeat(auto-fill,minmax(145px,1fr));gap:var(--space-sm)}
  .sgdir__body{padding:var(--space-sm)}
  .sgdir__body h3{font-size:1rem}
  .sgdir__who{padding-top:var(--space-sm);font-size:.85rem}
}

/* ---- the map ---------------------------------------------------------------
   Circles, not pins. A pin says "this house". A circle says "somewhere around
   here", which is the only thing this page is willing to tell you. */
.sgmap{margin-top:var(--space-lg)}
.sgmap__canvas{height:clamp(290px,44vw,430px);border-radius:var(--radius);overflow:hidden;
  border:1px solid var(--line);background:var(--cream);z-index:0}
.sgmap__note{color:var(--muted);font-size:.8rem;line-height:1.55;
  margin:var(--space-sm) auto 0;text-align:center;max-width:56ch}
.sgmap .leaflet-container{font:inherit;background:var(--cream)}
.sgmap .leaflet-control-attribution{font-size:.62rem;background:rgba(255,255,255,.82);color:var(--muted)}
.sgmap .leaflet-control-attribution a{color:var(--cyan-deep)}
.sgmap .leaflet-bar a{color:var(--navy);border-bottom-color:var(--line)}
.sgmap .leaflet-bar a:hover{background:var(--cream)}
.sgmap .leaflet-popup-content-wrapper{border-radius:var(--radius-sm);box-shadow:0 8px 26px rgba(34,32,29,.16)}
.sgmap .leaflet-popup-content{margin:var(--space-sm) var(--space-md);font-size:.86rem;line-height:1.45}
.sgmap .leaflet-popup-content strong{display:block;font-size:.95rem;color:var(--navy)}
.sgmap .leaflet-popup-content span{color:var(--muted);font-size:.8rem}
.sgpop__go{display:inline-block;margin-top:var(--space-xs);font-weight:600;color:var(--cyan-deep);
  cursor:pointer;text-decoration:underline;text-underline-offset:3px}

/* ---- the leader panel ------------------------------------------------------
   A modal, because the alternative - a page per leader - is eleven pages
   nobody links to. It behaves itself: escape closes it, tab stays inside, and
   focus returns to the name that opened it.

   Padding steps down as the panel gets smaller: --space-lg on a desktop panel
   that can afford the air, --space-md on a phone sheet where it cannot. */
.sgm[hidden]{display:none}
.sgm{position:fixed;inset:0;z-index:120;display:grid;place-items:center;padding:var(--space-md)}
/* Pinning the body is the only thing iOS actually honors. The JS records the
   scroll position, parks it in top, and puts it back on close. */
body.sgm-open{position:fixed;left:0;right:0;width:100%;overflow:hidden;overscroll-behavior:none}
.sgm__veil{position:absolute;inset:0;background:rgba(34,32,29,.52);backdrop-filter:blur(2px);
  animation:sgmFade .22s linear}
.sgm__panel{position:relative;width:min(520px,100%);max-height:min(88vh,760px);
  display:flex;flex-direction:column;background:#fff;border-radius:var(--radius-lg);
  box-shadow:0 26px 70px rgba(34,32,29,.3);overflow:hidden;
  animation:sgmRise .3s var(--ease-out-expo,cubic-bezier(.16,1,.3,1))}
.sgm__panel:focus{outline:none}
@keyframes sgmFade{from{opacity:0}to{opacity:1}}
@keyframes sgmVeilOut{to{opacity:0}}
@keyframes sgmRise{from{opacity:0;transform:translateY(18px) scale(.97)}to{opacity:1;transform:none}}
@keyframes sgmDrop{to{opacity:0;transform:translateY(10px) scale(.985)}}
/* the sheet comes up from the edge it lives on, which is where the thumb is */
@keyframes sgmSheetIn{from{transform:translateY(100%)}to{transform:none}}
@keyframes sgmSheetOut{to{transform:translateY(100%)}}
/* three parts arriving a beat apart - one orchestrated moment, not three animations */
@keyframes sgmPart{from{opacity:0;transform:translateY(9px)}to{opacity:1;transform:none}}
.sgm__head {animation:sgmPart .36s var(--ease-out-expo,cubic-bezier(.16,1,.3,1)) .04s backwards}
.sgm__scroll{animation:sgmPart .36s var(--ease-out-expo,cubic-bezier(.16,1,.3,1)) .09s backwards}
.sgm__foot {animation:sgmPart .36s var(--ease-out-expo,cubic-bezier(.16,1,.3,1)) .14s backwards}

/* leaving is quicker than arriving - about three quarters, and it accelerates
   away rather than easing out, which is what a thing being dismissed does */
.sgm.is-closing .sgm__panel{animation:sgmDrop .2s cubic-bezier(.4,0,1,1) forwards}
.sgm.is-closing .sgm__veil{animation:sgmVeilOut .18s linear forwards}
.sgm.is-closing .sgm__head,
.sgm.is-closing .sgm__scroll,
.sgm.is-closing .sgm__foot{animation:none}

@media(prefers-reduced-motion:reduce){
  .sgm__veil,.sgm__panel,.sgm__head,.sgm__scroll,.sgm__foot,
  .sgm.is-closing .sgm__panel,.sgm.is-closing .sgm__veil{animation:none;transform:none;opacity:1}
}

.sgm__x{position:absolute;top:var(--space-sm);right:var(--space-sm);z-index:2;
  width:34px;height:34px;display:grid;place-items:center;border:0;border-radius:50%;
  background:rgba(255,255,255,.86);color:var(--navy);cursor:pointer;
  transition:background .14s var(--ease-out),transform .14s var(--ease-out)}
.sgm__x svg{width:18px;height:18px}
.sgm__x:hover{background:#fff;transform:scale(1.06)}
.sgm__x:focus-visible{outline:2px solid var(--cyan);outline-offset:2px}

.sgm__head{display:flex;gap:var(--space-md);align-items:flex-end;
  padding:var(--space-lg) var(--space-lg) var(--space-md);
  background:var(--cream);border-bottom:1px solid var(--line)}
.sgm__photo{width:96px;height:128px;object-fit:cover;flex-shrink:0;background:var(--cream-2);
  border-radius:calc(var(--radius) - 4px)}
.sgm__id{min-width:0;padding-bottom:2px}
.sgm__group{font-size:.64rem;font-weight:700;letter-spacing:.11em;text-transform:uppercase;
  color:var(--cyan-deep);margin:0}
.sgm__panel h3{margin:var(--space-2xs) 0 0;font-size:1.3rem;line-height:1.2}
.sgm__where{margin:var(--space-xs) 0 0;font-size:.82rem;color:var(--muted);line-height:1.5}

.sgm__scroll{padding:var(--space-md) var(--space-lg) var(--space-lg);overflow-y:auto;
  /* keeps a flick at the end of the list from scrolling the page behind */
  overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
.sgm__desc{margin:0 0 var(--space-md);font-size:.92rem;line-height:1.65;max-width:60ch}
.sgm__lbl{font-size:.64rem;font-weight:700;letter-spacing:.11em;text-transform:uppercase;
  color:var(--muted);margin:0 0 var(--space-xs)}
.sgm__weeks{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--space-2xs)}
.sgm__weeks li{display:flex;gap:var(--space-sm);align-items:baseline;
  padding:var(--space-xs) var(--space-sm);border-radius:var(--radius-sm);
  background:var(--cream);font-size:.87rem}
.sgm__weeks li.is-off{color:var(--muted)}
.sgm__weeks li.is-plain{display:block;color:var(--muted);font-size:.85rem;line-height:1.5}
.sgm__weeks li.is-soon{display:block;background:color-mix(in srgb,var(--cyan) 11%,var(--card,#fff));
  color:var(--cyan-deep);font-weight:600;font-size:.83rem}
.sgm__wdate{flex:0 0 98px;font-weight:600;color:var(--ink);font-size:.8rem}
.sgm__weeks li.is-off .sgm__wdate{color:var(--muted)}
/* The dialogue predates the second palette, so one or two things in it name a
   color rather than a role. The date column asked for --navy, which is the
   same ink in daylight but all but invisible on the dark surfaces at night, so
   it now asks for --ink and reads correctly under either. The close disc was a
   white scrim meant to sit over a photograph; in the dark it was the brightest
   thing on the panel, louder than the button people are meant to press. */
html.dark body .sgm__x,
html.app-mode body.ath-compline .sgm__x,
body.emb.ath-compline .sgm__x{background:color-mix(in srgb,var(--ink) 13%,transparent);color:var(--ink);}
html.dark body .sgm__x:hover,
html.app-mode body.ath-compline .sgm__x:hover,
body.emb.ath-compline .sgm__x:hover{background:color-mix(in srgb,var(--ink) 22%,transparent);}
.sgm__wtext{min-width:0}

.sgm__foot{padding:var(--space-md) var(--space-lg) calc(var(--space-md) + env(safe-area-inset-bottom,0px));border-top:1px solid var(--line);background:var(--card,#fff)}
.sgm__contact{width:100%;justify-content:center}

.sgm__form{margin-top:var(--space-lg);border-top:1px solid var(--line);padding-top:var(--space-md)}
.sgm__how{border:0;margin:0 0 var(--space-sm);padding:0;
  display:flex;gap:var(--space-md);align-items:center;flex-wrap:wrap}
.sgm__how legend{float:left;width:100%;font-size:.82rem;color:var(--muted);margin-bottom:var(--space-xs)}
.sgm__how label{display:flex;align-items:center;gap:var(--space-xs);font-size:.9rem;cursor:pointer}
.sgm__f{display:block;margin:0 0 var(--space-sm)}
.sgm__f span{display:block;font-size:.78rem;font-weight:600;color:var(--navy);margin-bottom:var(--space-2xs)}
.sgm__f input,.sgm__f textarea{font:inherit;font-size:16px;width:100%;background:var(--card,#fff);
  border:1.5px solid var(--line);border-radius:var(--radius-sm);padding:.55em .7em;color:var(--ink)}
.sgm__f textarea{resize:vertical;min-height:88px;line-height:1.55}
.sgm__f input:focus,.sgm__f textarea:focus{outline:none;border-color:var(--cyan);
  box-shadow:0 0 0 3px rgba(160,138,111,.16)}
.sgm__send{width:100%;justify-content:center;margin-top:var(--space-2xs)}
.sgm__err{margin:var(--space-sm) 0 0;font-size:.85rem;color:#a3242b;background:#fdeced;
  border-radius:var(--radius-sm);padding:var(--space-xs) var(--space-sm)}
.sgm__done{margin:var(--space-md) 0 0;font-size:.95rem;line-height:1.65;
  background:color-mix(in srgb,var(--cyan) 10%,#fff);border-radius:var(--radius-sm);
  padding:var(--space-sm) var(--space-md);color:var(--navy)}

@media(max-width:520px){
  .sgm{padding:0;place-items:end stretch}
  .sgm__panel{width:100%;max-height:92vh;border-radius:var(--radius-lg) var(--radius-lg) 0 0;
    animation:sgmSheetIn .34s var(--ease-out-expo,cubic-bezier(.16,1,.3,1))}
  .sgm.is-closing .sgm__panel{animation:sgmSheetOut .24s cubic-bezier(.4,0,1,1) forwards}
  @media(prefers-reduced-motion:reduce){
    .sgm__panel,.sgm.is-closing .sgm__panel{animation:none;transform:none}
  }
  .sgm__head{padding:var(--space-md) var(--space-md) var(--space-sm);gap:var(--space-sm)}
  .sgm__scroll{padding:var(--space-sm) var(--space-md) var(--space-md)}
  .sgm__foot{padding:var(--space-sm) var(--space-md)}
  .sgm__photo{width:78px;height:104px}
  .sgm__panel h3{font-size:1.15rem}
}

/* ===========================================================================
   App dock: four tabs in a pill, the plus on its own
   ---------------------------------------------------------------------------
   The plus is not a fifth tab. Tabs take you somewhere and stay lit; this one
   opens a drawer and shuts it again, and two different behaviors should not
   wear the same clothes. Detaching it says so before anything is tapped, and
   it puts the one control reachable from every screen under the thumb that is
   already resting there.

   Same fill as the bar, deliberately. An accent color on a menu button reads
   as the most important thing on the screen, which is the one thing it is not.
   =========================================================================== */
html.app-mode .botbar,.botbar{background:none;border:0;box-shadow:none;padding:0;gap:10px;
  align-items:center;backdrop-filter:none;-webkit-backdrop-filter:none}
.botbar__tabs{position:relative;display:flex;align-items:stretch;gap:2px;
  /* Actual frosted glass rather than a dark panel with a hint of see-through.
     Three things make the difference: the fill comes down enough for the blur
     to have something to do, the blur goes up far enough to turn what is
     behind into color instead of shapes, and a light catches the top edge.
     It does not come down further than this because the labels sit on it, and
     over a pale page a thinner fill takes them under 4.5:1. */
  background:linear-gradient(180deg,rgba(255,255,255,.13),rgba(255,255,255,.03) 42%,rgba(255,255,255,0) 72%),rgba(20,28,40,.72);
  backdrop-filter:blur(30px) saturate(1.9);
  -webkit-backdrop-filter:blur(30px) saturate(1.9);
  border:1px solid rgba(255,255,255,.18);border-radius:100px;padding:7px;
  box-shadow:0 18px 45px rgba(20,18,16,.34)}
.botbar__more{flex:none;width:58px;height:58px;min-width:0;padding:0;border-radius:50%;
  /* Actual frosted glass rather than a dark panel with a hint of see-through.
     Three things make the difference: the fill comes down enough for the blur
     to have something to do, the blur goes up far enough to turn what is
     behind into color instead of shapes, and a light catches the top edge.
     It does not come down further than this because the labels sit on it, and
     over a pale page a thinner fill takes them under 4.5:1. */
  background:linear-gradient(180deg,rgba(255,255,255,.13),rgba(255,255,255,.03) 42%,rgba(255,255,255,0) 72%),rgba(20,28,40,.72);
  backdrop-filter:blur(30px) saturate(1.9);
  -webkit-backdrop-filter:blur(30px) saturate(1.9);
  border:1px solid rgba(255,255,255,.18);box-shadow:0 18px 45px rgba(20,18,16,.34);
  color:rgba(244,238,225,.92);display:grid;place-items:center;
  transition:transform .18s var(--ease-out),color .2s,background .25s}
.botbar__more svg{width:26px;height:26px;transition:transform .3s var(--ease-out)}
/* Idle labels were rgba(244,238,225,.7), which measured 5.7:1 on the old navy
   and 3.96:1 once the bar picked up Sunset. .76 puts the worst theme back over
   5:1 without closing the gap to the active tab, which is pure white and has a
   chip behind it as well. */
.botbar__item{color:rgba(244,238,225,.76)}
/* the label is for screen readers only — a lone plus is legible on sight */
.botbar__more span{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}
.botbar__more:active{transform:scale(.92)}
/* one glyph, turned a quarter turn: the plus becomes the close, so the drawer
   looks shut by the same control that opened it rather than by a stranger */
body.menu-open .botbar__more{color:#fff;background:rgba(34,32,29,.96)}
body.menu-open .botbar__more svg{transform:rotate(45deg)}
@media (prefers-reduced-motion:reduce){
  .botbar__more,.botbar__more svg{transition:none}
  .botbar__more:active{transform:none}
}
@media(max-width:400px){
  html.app-mode .botbar,.botbar{width:calc(100vw - 20px);max-width:440px;gap:9px;padding:0;
    justify-content:center}
  .botbar__tabs{flex:1 1 auto;min-width:0;gap:0;padding:6px;justify-content:space-between}
  .botbar__more{flex:none;width:54px;height:54px;padding:0}
  .botbar__more svg{width:24px;height:24px}
}
@media(max-width:340px){
  .botbar__more{width:50px;height:50px}
  .botbar__more svg{width:22px;height:22px}
}

/* --- what the plus opens --------------------------------------------------
   The sheet itself already exists further up: it rises out of the bar, keeps
   its grab handle and dims the screen behind. What changes here is only what
   is inside it. In the app it is no longer the website menu — About, Ministries
   and When You Visit are for somebody deciding whether to come, and whoever
   installed this decided a while ago. Those pages are still exactly what the
   hamburger opens on the mobile web, where that person actually is. */
html.app-mode .mobmenu{overscroll-behavior:contain}
html.app-mode .mobmenu__actions{display:none}
html.app-mode .appsheet{width:100%}


/* The lit edge that says glass. Separate rule so the shadows already on these
   two keep whatever they were doing. */
.botbar__tabs,.botbar__more{box-shadow:inset 0 1px 0 rgba(255,255,255,.16),0 10px 30px rgba(0,0,0,.28)}
.appsheet__h{margin:var(--space-lg) 0 var(--space-2xs);font-size:.64rem;font-weight:800;
  letter-spacing:.13em;text-transform:uppercase;color:var(--am,#6e6459)}
.appsheet__h:first-of-type{margin-top:var(--space-2xs)}
.appsheet__r{display:flex;align-items:center;gap:var(--space-sm);padding:var(--space-sm) 0;
  text-decoration:none;color:var(--ai,#22201d);-webkit-tap-highlight-color:transparent;
  transition:opacity .16s var(--ease-out),transform .16s var(--ease-out)}
.appsheet__r + .appsheet__r{border-top:1px solid var(--aline,#e3ddd2)}
.appsheet__r:active{transform:scale(.985);opacity:.66}
.appsheet__ic{flex:none;width:44px;height:44px;border-radius:14px;
  background:var(--aicobg,#f3f1ef);display:grid;place-items:center;color:var(--aacd,#654e31)}
.appsheet__ic svg{width:22px;height:22px}
.appsheet__tx{min-width:0;flex:1 1 auto;display:flex;flex-direction:column;gap:1px}
.appsheet__tx b{font-size:.94rem;font-weight:700;line-height:1.25}
.appsheet__tx span{font-size:.76rem;color:var(--am,#6e6459);line-height:1.3}
/* How many have landed on that board since this person last opened it. The
   text block takes the slack instead of the chevron, so the count and the
   chevron sit together on the right and the label keeps the left. */
.appsheet__n{flex:none;display:grid;place-items:center;min-width:21px;height:21px;
  padding:0 6px;border-radius:100px;background:var(--cyan,#a08a6f);color:#fff;
  font-size:.7rem;font-weight:700;letter-spacing:.01em}
.appsheet__go{margin-left:auto;flex:none;color:var(--am,#6e6459);opacity:.5;display:grid;place-items:center}
.appsheet__go svg{width:17px;height:17px}
.appsheet__r.is-here{opacity:.45;pointer-events:none}
.appsheet__foot{margin-top:var(--space-xl);padding-top:var(--space-md);
  border-top:1px solid var(--aline,#e3ddd2);display:flex;align-items:center;
  justify-content:space-between;gap:var(--space-sm)}
.appsheet__who{margin:0;font-size:.78rem;color:var(--am,#6e6459)}
.appsheet__who b{color:var(--ai,#22201d);font-weight:700}
.appsheet__out{font-size:.82rem;font-weight:700;color:var(--am,#6e6459);text-decoration:none;
  padding:var(--space-2xs) var(--space-sm);border-radius:99px;
  border:1px solid var(--aline,#e3ddd2)}
.appsheet__out--in{margin-left:auto;color:var(--aacd,#654e31);border-color:var(--aac,#a08a6f)}

/* --- the dock wears the theme the member picked --------------------------
   Every other surface in the app already reads --ab / --ai / --aac and shifts
   with the theme; the bar was the one thing still hard-coded navy, so anyone
   on Kashmir or Sunset had a strip of somebody else's app pinned to the bottom
   of theirs.

   --ac2 is each theme's deep end. Pulled a further step toward black it lands
   dark enough for white labels in all eight ramps — the saturated ones (Peony
   Blush, Marple, Sunset) need that step or the bar shouts louder than the page
   it is sitting on. The neutral rgba above stays as the answer for anything
   without color-mix, which is only iOS before 16.2 by now. */
@supports (color: color-mix(in srgb, red 50%, blue)){
  html.app-mode .botbar{--bot-ink:color-mix(in srgb, var(--ac2,#22201d) 56%, #110f0d)}
  .botbar__tabs,.botbar__more{
    background:color-mix(in srgb, var(--bot-ink,#231e19) 90%, transparent);
    box-shadow:0 18px 45px color-mix(in srgb, var(--bot-ink,#231e19) 40%, transparent)}
  /* open: a shade deeper than the bar, so the button reads as pressed in */
  body.menu-open .botbar__more{background:color-mix(in srgb, var(--ac2,#22201d) 92%, #0b0907)}
}

/* --- app home header: you, then the time of day, then what is waiting ------
   The avatar moved to the leading edge. It is the only personal thing in the
   row, and the thumb that opens settings now travels from the side it already
   rests on rather than across the phone. The greeting sits beside it, which
   costs the serif line about a third of its old size — worth it, because a
   greeting that takes two lines to say Good evening is a headline, and this
   is a hello. */
.appdash__top{display:flex;align-items:center;gap:var(--space-sm);justify-content:flex-start}
.appdash__hello{min-width:0;flex:1 1 auto}
.appdash__kick{margin:0}
.appdash__greet{margin:1px 0 0;font-size:clamp(1.12rem,1rem + 1.1vw,1.4rem);line-height:1.2;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.appdash__avatar{width:44px;height:44px}
.appdash__cog{flex:none;margin-left:auto;position:relative;width:40px;height:40px;border-radius:50%;
  display:grid;place-items:center;background:var(--asurf,#fff);border:1px solid var(--aline,var(--line));
  color:var(--ai,var(--navy));-webkit-tap-highlight-color:transparent;cursor:pointer;padding:0;
  transition:transform .16s var(--ease-out),background .2s}
.appdash__cog svg{width:19px;height:19px}
.appdash__cog:active{transform:scale(.92)}
/* The face is not a button any more, so it should stop behaving like one —
   a press state on something that does nothing is a promise it cannot keep. */
.appdash__avatar--member,.appdash__avatar--member:active{transform:none;cursor:default}
@media (prefers-reduced-motion:reduce){.appdash__cog{transition:none}.appdash__cog:active{transform:none}}

/* --- unread badge ---------------------------------------------------------
   Top-right of the icon, small, and ringed so it stays legible wherever the
   icon happens to sit — on the Messages tile that is a navy-to-cyan gradient,
   and a badge with no ring dissolves into the lighter end of it. */
.appms__ico{position:relative;overflow:visible}
.appms__n{position:absolute;top:-6px;left:calc(100% - 9px);min-width:20px;height:20px;padding:0 5px;
  border-radius:99px;background:#d2432f;color:#fff;border:2px solid #fff;
  font-family:var(--font-display);font-size:.66rem;font-weight:800;font-style:normal;
  line-height:16px;text-align:center;letter-spacing:0;box-shadow:0 2px 6px rgba(20,18,16,.28)}

/* --- small groups: the modal is the top layer while it is open -------------
   .mobtop is the floating logo-and-menu pill on mobile web, pinned at z-index
   210; the group modal opens at 120. The pill therefore landed exactly on the
   modal's close button, and once the sheet had grown tall enough to reach the
   top of the screen there was no way out of it at all. Caught on a screen
   recording rather than by reading the file, which is the honest version of
   how this was found. */
body.sgm-open .mobtop,body.sgm-open .navshell{display:none !important}
.sgm{z-index:220}

@media(max-width:520px){
  /* Leave a strip of the page showing above the sheet. 92vh was 92% of the
     LARGE viewport, so with Safari's toolbar on screen the sheet ran past the
     top and tucked its own header under the status bar. dvh measures what is
     actually visible, and the inset keeps it clear of the notch. */
  .sgm__panel{max-height:min(88dvh, calc(100dvh - env(safe-area-inset-top,0px) - 34px))}
  /* something to pull */
  .sgm__panel::before{content:"";position:absolute;top:7px;left:50%;transform:translateX(-50%);
    width:38px;height:4px;border-radius:99px;background:rgba(34,32,29,.16);z-index:3;pointer-events:none}
  .sgm__head{padding-top:calc(var(--space-md) + 6px)}
}

/* --- Coming up: a rail, not a headline -------------------------------------
   The single-event pill said what was next and nothing else, which is a
   smaller answer than the question. Five cards you push with a thumb say
   "here is the shape of the week" in the same strip of screen.

   The rail bleeds to both screen edges — a card half off the side is the only
   honest way of saying there is more, and it costs no label to say it. */
.appup{margin:0}
.appup__head{display:flex;align-items:baseline;justify-content:space-between;gap:var(--space-sm);
  margin:0 0 var(--space-xs)}
.appup__head h2{margin:0;font-size:1.05rem;letter-spacing:-.01em;color:var(--ai,var(--ink))}
.appup__head a{font-size:.78rem;font-weight:700;text-decoration:none;color:var(--aacd,var(--cyan-deep));
  -webkit-tap-highlight-color:transparent}
.appup__rail{display:flex;gap:var(--space-sm);overflow-x:auto;overscroll-behavior-x:contain;
  scroll-snap-type:x proximity;-webkit-overflow-scrolling:touch;scrollbar-width:none;
  padding:3px clamp(16px,5vw,26px) var(--space-2xs);
  margin-inline:calc(clamp(16px,5vw,26px) * -1);
  /* Without this the browser lines a snapped card up with the scrollport edge
     and ignores the padding — which it did on load, nudging the rail 20px and
     leaving the first card hanging off the screen while the heading above it
     sat properly indented. scroll-padding moves the snap line to where the
     text starts, so a card at rest and a card snapped to both land there. */
  scroll-padding-inline:clamp(16px,5vw,26px)}
.appup__rail::-webkit-scrollbar{display:none}

.appup__c{flex:0 0 172px;scroll-snap-align:start;display:flex;flex-direction:column;
  background:var(--asurf,var(--paper,#fff));border:1px solid var(--aline,var(--line));
  border-radius:var(--radius);overflow:hidden;text-decoration:none;color:var(--ai,var(--ink));
  -webkit-tap-highlight-color:transparent;transition:transform .18s var(--ease-out)}
.appup__c:active{transform:scale(.975)}
.appup__pic{display:block;height:92px;background:var(--aicobg,var(--cream-2,#f3f1ef))}
.appup__pic img{width:100%;height:100%;object-fit:cover;display:block}
.appup__b{display:block;padding:10px var(--space-sm) var(--space-sm)}
.appup__k{display:block;font-size:.6rem;font-weight:800;letter-spacing:.09em;text-transform:uppercase;
  color:var(--aacd,var(--cyan-deep))}
.appup__c b{display:block;margin-top:4px;font-size:.87rem;font-weight:700;line-height:1.25;
  /* two lines, then stop — a rail of ragged card heights reads as broken */
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.appup__c small{display:block;margin-top:3px;font-size:.72rem;color:var(--am,var(--muted));
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* on now: the one card that is not about later */
/* Each card takes a wash of its own poster. The color is read off the image
   in the browser (same-origin, so the canvas stays clean) and greys are thrown
   away first — an average that counts the white border of a flyer comes back
   beige for everything and the row loses the very variety this is for.

   7% is deliberately almost nothing. It should read as the cards having
   different temperatures, not as five colored boxes. */
.appup__c.has-tint{background:rgb(var(--up-tint) / .07);
  border-color:rgb(var(--up-tint) / .28)}
.appup__c.is-live{border-color:color-mix(in srgb,var(--aac,#a08a6f) 55%,var(--aline,var(--line)))}
.appup__c.is-live .appup__k{color:#c0392b}

.appup__more{flex:0 0 106px;scroll-snap-align:end;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:9px;text-decoration:none;
  border:1px dashed var(--aline,var(--line));border-radius:var(--radius);
  background:none;color:var(--am,var(--muted));font-size:.78rem;font-weight:700;
  -webkit-tap-highlight-color:transparent;transition:transform .18s var(--ease-out)}
.appup__more:active{transform:scale(.975)}
.appup__morec{width:34px;height:34px;border-radius:50%;display:grid;place-items:center;
  background:var(--aicobg,var(--cream-2,#f3f1ef));color:var(--aacd,var(--cyan-deep))}
.appup__morec svg{width:16px;height:16px}
@media (prefers-reduced-motion:reduce){
  .appup__c,.appup__more{transition:none}
  .appup__c:active,.appup__more:active{transform:none}
}

/* the notifications row now lives in settings */
.ppanel .apppush{width:100%}
.pnote{margin:var(--space-sm) 0 0;font-size:.82rem;line-height:1.6;color:var(--am,var(--muted))}


/* --- printing from a dark page ----------------------------------------------
   The print rules already force white paper, which is right. What they could
   not know is that the ink tokens might have gone light on the way here, and
   near-white type on white paper prints as an empty page. Everything is put
   back to the light values for the duration of the print, and nothing else
   about the print layout is touched. */
@media print{
  html.dark body{
    --navy:#22201d;--snow:#faf7f2;--charcoal:#4e483f;--cyan:#a08a6f;
    --paper:#faf7f2;--bg:#fff;--cream:#f6f5f3;--cream-2:#f1efed;--card:#fff;
    --ink:#22201d;--ink-soft:#3f362d;--muted:#574e44;--line:#e1ddd8;
    --ink-strong:#22201d;--ink-invert:#faf7f2;--ink-invert-soft:#f6f5f3;
    --cyan-deep:#7d6a52;
    background:#fff;color:#22201d;
  }
}


/* --- dark app themes: a theme is an accent, not a coat of paint --------------
   Every theme carries a dark block, and each of those blocks also restates the
   site palette - --bg, --paper, --snow, --cream. That was written for Compline,
   whose colors are already obsidian, so restating them there is harmless. For
   the colored themes it is not: Sunset put #461b05 into --bg and --paper and
   the entire app went rust, page, cards, rows and all. The accent had become
   the paint.

   So the surfaces are handed back to the dark palette, and the theme keeps what
   it should have kept all along - --aac, --aacd, --abr, --ac1, --aglow. The app
   surfaces are rebuilt from near-black with a few percent of the theme mixed in,
   which is enough to feel like the theme without becoming it.

   Compline is excluded on purpose. It is the one theme designed dark from the
   start, and its own values are the right ones. */
html.dark body[class*="ath-"]:not(.ath-compline){
  /* the page, back to obsidian */
  --navy:#1a1815;--snow:#100e0c;--paper:#100e0c;--bg:#100e0c;
  --cream:#191612;--cream-2:#211d18;--card:#1c1915;--charcoal:#d1ccc6;
  --ink:#f6f2ec;--ink-soft:#ece9e6;--muted:#aca49b;--line:#3a342d;
  --ink-strong:var(--ink);--ink-invert:var(--ink);--ink-invert-soft:var(--ink-soft);
  /* the app surfaces, near-black carrying a trace of the theme */
  --ab:color-mix(in srgb,var(--aac) 5%,#0f0c09);
  --asurf:color-mix(in srgb,var(--aac) 7%,#17130f);
  --arow:color-mix(in srgb,var(--aac) 6%,#14110d);
  /* The home card is a gradient from --ac1 to --ac2, and in every light theme
     --ac1 is a DEEP form of the accent, not the bright one - Sanctuary pairs a
     deep blue with navy, never the bright cyan. The dark blocks handed it the
     bright value, which is why the card arrived as a slab of orange. Deep here
     too, and the card reads as the theme without shouting it. */
  --ac1:color-mix(in srgb,var(--aac) 42%,#100d0a);
  --ac2:color-mix(in srgb,var(--aac) 8%,#17130f);
  --aline:color-mix(in srgb,var(--aac) 16%,#342e28);
  --aicobg:color-mix(in srgb,var(--aac) 20%,#1a1611);
  --ai:#faf9f8;
  --am:color-mix(in srgb,var(--aac) 10%,#aca49b);
}


/* --- app chrome yields to a sheet --------------------------------------------
   The tab bar carries a backdrop-filter, which puts it in its own composited
   layer, and a composited layer does not reliably lose to a plain z-index on a
   sibling. Measured, not assumed: with the leader sheet open and covering the
   whole viewport at z-index 220, a tap at the center of the bar still landed on
   the bar at z-index 200. Forty pixels to the left it landed on the sheet.

   The profile avatar needs no such explanation - it sits at z-index 390 and was
   simply above the sheet.

   Raising numbers is a game nobody wins, and the answer here is the one the
   interface wanted anyway: a sheet is modal, so the chrome steps out while one
   is open, and comes back when it closes. The bar already carries a transition,
   so it leaves the way it arrived. */
html.app-mode body.sgm-open .botbar{
  opacity:0;
  transform:translateX(-50%) translateY(14px);
  pointer-events:none;
}
html.app-mode .appuser{transition:opacity .25s var(--ease-out),transform .25s var(--ease-out);}
html.app-mode body.sgm-open .appuser{
  opacity:0;
  transform:translateY(-10px);
  pointer-events:none;
}
@media (prefers-reduced-motion:reduce){
  html.app-mode body.sgm-open .botbar,
  html.app-mode body.sgm-open .appuser{transform:none;}
}

/* ---- extra tags on an event ------------------------------------------
   The category keeps its own eyebrow treatment; these sit quieter beside it,
   because a tag is a note about the event rather than the name of it. */
.evtags{display:flex;flex-wrap:wrap;gap:6px;margin:8px 0 0}
.evtag{display:inline-block;padding:.22em .6em;border-radius:999px;
  border:1px solid var(--line);background:var(--cream);color:var(--muted);
  font-size:.7rem;font-weight:700;letter-spacing:.04em;line-height:1.5;
  white-space:nowrap}
.evmeta .evtag{align-self:center}
html.dark .evtag{background:var(--cream-2);border-color:var(--line);color:var(--muted)}

/* ---- navigation options ----------------------------------------------------
   Set in Admin → Pages. Each one is opt-in: with nothing chosen the attribute
   is absent from the markup, none of these rules match, and the nav behaves
   exactly as it did before any of them existed. */

/* Click to open, rather than hover. The hover rule above has to be undone as
   well as the click rule added, or a menu would open twice over. */
@media (hover: hover){
  .navshell[data-nav-open="click"] .menu>li:hover .dropdown,
  .navshell[data-nav-open="click"] .menu>li:focus-within .dropdown{opacity:0;visibility:hidden;transform:translateY(8px);}
  .navshell[data-nav-open="click"] .menu>li:hover .caret,
  .navshell[data-nav-open="click"] .menu>li:focus-within .caret{transform:none;}
}
.navshell[data-nav-open="click"] .menu>li.is-open .dropdown{opacity:1;visibility:visible;transform:translateY(0);}
.navshell[data-nav-open="click"] .menu>li.is-open .caret{transform:rotate(180deg);}

/* Two columns, for a menu with a lot in it. Only where there is room: below
   900px the dropdown is not what you are looking at anyway. */
@media (min-width:900px){
  .navshell[data-nav-drop="two"] .dropdown{min-width:436px;display:grid;grid-template-columns:1fr 1fr;gap:0 6px;align-content:start;}
}

/* Stay put rather than sliding away as the page scrolls. */
.navshell[data-nav-scroll="always"].hide{transform:none;}

/* ---- per-block hover effects -----------------------------------------------
   Chosen per section in the page editor. Nothing is applied unless a block
   asks for it, and nothing is applied on a touch screen or to somebody who
   has asked their computer for less movement. */
@media (hover: hover){
  .cmssec--hv-lift figure.img,.cmssec--hv-lift .cmsstat,.cmssec--hv-lift .cmsfaq__it,.cmssec--hv-lift .cmsperson,.cmssec--hv-lift .cmsstep{
    transition:transform .32s var(--ease-out),box-shadow .32s var(--ease-out);}
  .cmssec--hv-lift figure.img:hover,.cmssec--hv-lift .cmsstat:hover,.cmssec--hv-lift .cmsfaq__it:hover,.cmssec--hv-lift .cmsperson:hover,.cmssec--hv-lift .cmsstep:hover{
    transform:translateY(-4px);box-shadow:0 18px 40px rgba(7,20,38,.16);}
  .cmssec--hv-zoom figure.img{overflow:hidden;}
  .cmssec--hv-zoom figure.img img{transition:transform .55s var(--ease-out);}
  .cmssec--hv-zoom figure.img:hover img{transform:scale(1.045);}
  /* A block with nothing like a photo or a card in it - a Text block, a call
     to action - lifts or grows as a whole. The individual translate/scale
     properties are used rather than transform, so this adds to a free
     position instead of replacing it. */
  .cmssec--hv-lift:not(:has(figure.img,.cmsstat,.cmsfaq__it,.cmsperson,.cmsstep,.cmscard,[data-hv])) > .wrap,
  .cmssec--hv-zoom:not(:has(figure.img,[data-hv])) > .wrap{transition:translate .32s var(--ease-out),scale .4s var(--ease-out);}
  .cmssec--hv-lift:not(:has(figure.img,.cmsstat,.cmsfaq__it,.cmsperson,.cmsstep,.cmscard,[data-hv])):hover > .wrap{translate:0 -6px;}
  .cmssec--hv-zoom:not(:has(figure.img,[data-hv])):hover > .wrap{scale:1.03;}
  /* One element at a time, chosen in the editor (data-hv on the element).
     translate/scale rather than transform, so a free position, a card's own
     hover or a reveal animation is added to rather than replaced. */
  [data-hv="lift"],[data-hv="zoom"]{transition:translate .32s var(--ease-out),scale .4s var(--ease-out),box-shadow .32s var(--ease-out);}
  a[data-hv],span[data-hv]{display:inline-block;}
  [data-hv="lift"]:hover{translate:0 -5px;}
  figure[data-hv="lift"]:hover,.cmscard[data-hv="lift"]:hover,.cmsstat[data-hv="lift"]:hover,.cmsperson[data-hv="lift"]:hover,
  .cmsstep[data-hv="lift"]:hover,.cmsfaq__it[data-hv="lift"]:hover,.btn[data-hv="lift"]:hover{box-shadow:0 18px 40px rgba(7,20,38,.16);}
  [data-hv="zoom"]:not(figure):hover{scale:1.04;}
  figure[data-hv="zoom"]{overflow:hidden;}
  figure[data-hv="zoom"] img{transition:transform .55s var(--ease-out);}
  figure[data-hv="zoom"]:hover img{transform:scale(1.045);}
  /* "None" switches off whatever the block would have done to this one. */
  [data-hv="none"]:hover,[data-hv="none"]:hover img{transform:none !important;translate:none !important;scale:none !important;box-shadow:none !important;}
}
@media (prefers-reduced-motion:reduce){
  .cmssec--hv-lift figure.img,.cmssec--hv-lift .cmsstat,.cmssec--hv-lift .cmsfaq__it,.cmssec--hv-lift .cmsperson,.cmssec--hv-lift .cmsstep,
  .cmssec--hv-zoom figure.img img{transition:none !important;transform:none !important;}
  .cmssec--hv-lift > .wrap,.cmssec--hv-zoom > .wrap,[data-hv],[data-hv] img{transition:none !important;translate:none !important;scale:none !important;}
}

/* ---- the shape of the navigation bar ---------------------------------------
   Chosen in Admin → Pages. Desktop only, and not by accident: below 1040px
   .navshell is display:none and a different bar takes over, so nothing here
   can reach a phone.

   'pill' is the default and emits no attribute at all, which is why there is
   no rule for it — the bar it describes is the one already in the stylesheet. */

/* Curved rectangle: the same floating panel with its corners relaxed. The
   links and the button follow, or a rounded pill inside a soft rectangle
   reads as two different decisions. */
.navshell[data-nav-shape="soft"] .pillnav{border-radius:18px;}
.navshell[data-nav-shape="soft"] .menu>li>a,
.navshell[data-nav-shape="soft"] .menu>li>button,
.navshell[data-nav-shape="soft"] .menu__pill,
.navshell[data-nav-shape="soft"] .nav__actions .btn,
.navshell[data-nav-shape="soft"] .navmem__btn{border-radius:10px;}
.navshell[data-nav-shape="soft"] .dropdown{border-radius:14px;}

/* Square. */
.navshell[data-nav-shape="square"] .pillnav{border-radius:0;}
.navshell[data-nav-shape="square"] .menu>li>a,
.navshell[data-nav-shape="square"] .menu>li>button,
.navshell[data-nav-shape="square"] .menu__pill,
.navshell[data-nav-shape="square"] .nav__actions .btn,
.navshell[data-nav-shape="square"] .navmem__btn{border-radius:0;}
.navshell[data-nav-shape="square"] .dropdown{border-radius:0;}

/* Full width, flush to the top. The church's name comes back beside the logo:
   the floating pill hides it for want of room, and a bar this wide has room. */
.navshell[data-nav-shape="bar"]{top:0;padding-inline:0;}
.navshell[data-nav-shape="bar"] .pillnav{width:100%;max-width:none;border-radius:0;
  padding:10px clamp(16px,3vw,40px);
  box-shadow:inset 0 -1px 0 rgba(255,255,255,.09),0 10px 30px rgba(7,20,38,.20);}
.navshell[data-nav-shape="bar"] .nav__links{margin-left:auto;}
.navshell[data-nav-shape="bar"] .brand__name{display:block;color:#fff;}
.navshell[data-nav-shape="bar"] .brand__name span{color:rgba(255,255,255,.6);}
.navshell[data-nav-shape="bar"] .menu>li>a,
.navshell[data-nav-shape="bar"] .menu>li>button,
.navshell[data-nav-shape="bar"] .menu__pill{border-radius:8px;}
.navshell[data-nav-shape="bar"] .dropdown{top:calc(100% + 8px);}
.navshell[data-nav-shape="bar"] .dropdown::before{top:-8px;height:8px;}
.navshell[data-nav-shape="bar"].hide{transform:translateY(-100%);}

/* No bar — while you are still on the hero.

   The first version of this was bare all the way down the page, and over a
   light one the links went to almost nothing: pale type on white, with only
   the Give button surviving. A scrim dark enough to fix that is just a bar
   with soft edges, so instead the panel comes back the moment you have
   scrolled past the hero, which is the behaviour people already expect from a
   transparent header. site.js sets .at-top; nothing else reads it. */
.navshell[data-nav-shape="ghost"]{top:0;padding-top:16px;padding-bottom:26px;}
.navshell[data-nav-shape="ghost"]::before{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(to bottom,rgba(9,24,42,.5),rgba(9,24,42,0));
  opacity:0;transition:opacity .3s var(--ease-out);}
.navshell[data-nav-shape="ghost"].at-top::before{opacity:1;}
.navshell[data-nav-shape="ghost"] .pillnav{transition:box-shadow .3s var(--ease-out);}
.navshell[data-nav-shape="ghost"] .pillnav::before{transition:opacity .3s var(--ease-out);}
.navshell[data-nav-shape="ghost"].at-top .pillnav{box-shadow:none;}
.navshell[data-nav-shape="ghost"].at-top .pillnav::before{opacity:0;}
.navshell[data-nav-shape="ghost"] .dropdown{top:calc(100% + 10px);}
.navshell[data-nav-shape="ghost"].hide{transform:translateY(-140%);}

/* Last word: whatever shape it is, "keep it on screen" means keep it. */
.navshell[data-nav-scroll="always"].hide{transform:none;}

/* ---- the shape of the phone's menu -----------------------------------------
   The desktop bar is hidden below 1040px and this panel does the work instead,
   so these are the phone's equivalent of the shapes above. Chosen in the same
   place, and with nothing chosen nothing here matches.

   .mobmenu__panel is display:contents by default, which takes it out of layout
   altogether: its children go on being flex items of .mobmenu exactly as they
   were before the wrapper existed. A sheet or a drawer promotes it to a real
   box — and it has to be one, because the panel must scroll on its own or its
   content slides up out of the sheet and over the dimmed page. */
.mobmenu__panel{display:contents;}

/* The `html` prefix is not decoration. site.css already carries
   html:not(.app-mode) .mobmenu {background: <frosted gradient>} at (0,2,1),
   which outranks a bare .mobmenu[data-mob=…] at (0,2,0) - so without it the
   scrim never appears on the mobile web, which is the only place it matters.
   Matching the specificity and coming later is enough, and keeps app mode and
   the browser on the same rule. */
html .mobmenu[data-mob="sheet"],html .mobmenu[data-mob="drawer"]{
  background:rgba(8,20,36,.5);padding:0;overflow:hidden;transform:none;}
.mobmenu[data-mob="sheet"] .mobmenu__panel,
.mobmenu[data-mob="drawer"] .mobmenu__panel{
  display:flex;flex-direction:column;background:var(--cream);
  overflow-y:auto;-webkit-overflow-scrolling:touch;
  transition:transform .38s var(--ease-out);}

/* ...except in the installed app, where the sheet is dark glass and every
   word in it is painted light-on-dark. The panel above paints the menu's own
   light card, and that was landing in the app too: white text on a white
   sheet, which is what the More sheet had become. In the app the panel keeps
   its shape and lets the glass show through; the mobile web is untouched. */
html.app-mode .mobmenu[data-mob="sheet"] .mobmenu__panel,
html.app-mode .mobmenu[data-mob="drawer"] .mobmenu__panel{background:transparent;}

/* Holding the page still while the app's sheet is open. Pinning the body
   (position:fixed, the rule further up) is what the mobile web needs, but in
   the installed app on iOS a pinned body leaves the page with nothing to
   scroll, and the phone answers by moving its bottom edge up: the tab bar
   jumped and the sheet stopped short of the bottom of the screen. In the app
   the body stays where it is and simply stops scrolling, and a clear layer
   under the sheet takes any drag that starts on the dimmed page. A tap there
   still lands on the page, which is what closes the sheet. */
html.app-mode body.menu-open{position:static;}
html.app-mode:has(body.menu-open){overflow:hidden;}
html.app-mode body.menu-open::after{content:"";position:fixed;inset:0;z-index:189;touch-action:none;}

/* The app's sheet moves as one piece again. The web sheet slides its inner
   panel inside a fixed frame, and in the app that meant the glass frame
   appeared first and the rows slid up inside it - and on the way out the rows
   left and an empty pane of glass hung on screen for half a second. Here the
   frame itself slides (the way the app sheet was built), the panel just
   scrolls, and it is never taller than the frame, so the top of the sheet
   - the handle, "For you", the first row - is never pushed out of view.
   Leaving is quicker than arriving. */
html.app-mode .mobmenu[data-mob="sheet"]{
  transform:translateY(103%);
  transition:transform .3s cubic-bezier(.4,0,1,1),visibility 0s linear .3s,box-shadow .3s ease;}
html.app-mode body.menu-open .mobmenu[data-mob="sheet"]{
  transform:translateY(0);
  transition:transform .44s var(--ease-out),visibility 0s,box-shadow .5s ease;}
html.app-mode .mobmenu[data-mob="sheet"] .mobmenu__panel{
  transform:none;transition:none;max-height:80vh;box-shadow:none;border-radius:0;}

/* The bottom of the screen, measured from the top. On iOS an installed app
   moves the bottom edge that fixed things sit on whenever the page cannot
   scroll - a short page, the Messages screen, a page held still under the
   sheet - and everything pinned to it rides up with it. The top of the screen
   never moves, and 100lvh is the full height of the screen in an app with no
   browser bars, so the tab bar and the sheet are placed from there instead. */
html.app-mode .botbar{
  bottom:auto;top:calc(100lvh - env(safe-area-inset-bottom,0px) - 10px);translate:0 -100%;}
html.app-mode .mobmenu[data-mob="sheet"]{
  top:100lvh;bottom:auto;translate:0 -100%;}

/* Rises from the bottom. 88dvh so the page is visibly still there above it,
   which is the whole point of a sheet. */
html .mobmenu[data-mob="sheet"]{align-items:stretch;justify-content:flex-end;}
.mobmenu[data-mob="sheet"] .mobmenu__panel{
  max-height:88dvh;border-radius:22px 22px 0 0;
  padding:clamp(18px,5vw,32px) clamp(20px,6vw,40px) 116px;
  box-shadow:0 -18px 50px rgba(7,20,38,.32);transform:translateY(100%);}
body.menu-open .mobmenu[data-mob="sheet"] .mobmenu__panel{transform:none;}

/* Slides in from the right. */
html .mobmenu[data-mob="drawer"]{flex-direction:row;align-items:stretch;justify-content:flex-end;}
.mobmenu[data-mob="drawer"] .mobmenu__panel{
  width:min(86vw,400px);height:100%;
  padding:clamp(20px,6vw,36px) clamp(20px,6vw,32px) 116px;
  box-shadow:-18px 0 50px rgba(7,20,38,.32);transform:translateX(100%);}
body.menu-open .mobmenu[data-mob="drawer"] .mobmenu__panel{transform:none;}
/* The drawer is the one shape that reaches the top of the screen, so its first
   row lands underneath the floating menu button and the two collide. 84px
   clears the tallest of the button shapes (the full-width bar, 65px) with room
   to spare, and clears the pill (70px) by 14. The `html` prefix matches the
   (0,2,1) of the frosted-menu rule above, without which this never applies.
   The env() is 0 in every mobile browser - the button is already measured from
   below the notch - and it is here for the day that stops being true. */
html:not(.app-mode) .mobmenu[data-mob="drawer"] .mobmenu__panel{
  padding-top:calc(env(safe-area-inset-top,0px) + 84px);}
/* Button in the left corner, drawer from the left, so the X lands on the panel
   it closes rather than on the page behind it. */
html .mobmenu[data-mob="drawer"][data-side="left"]{justify-content:flex-start;}
.mobmenu[data-mob="drawer"][data-side="left"] .mobmenu__panel{
  box-shadow:18px 0 50px rgba(7,20,38,.32);transform:translateX(-100%);}
body.menu-open .mobmenu[data-mob="drawer"][data-side="left"] .mobmenu__panel{transform:none;}

/* Every folder already open, one long list, instead of tapping to open one. */
.mobmenu[data-mob-folders="open"] .dropdown{max-height:1400px;padding-bottom:var(--space-sm);}
.mobmenu[data-mob-folders="open"] .dropdown a{opacity:1;transform:none;}
.mobmenu[data-mob-folders="open"] .caret{transform:rotate(180deg);}

@media (prefers-reduced-motion:reduce){
  .mobmenu[data-mob="sheet"] .mobmenu__panel,
  .mobmenu[data-mob="drawer"] .mobmenu__panel{transition:none;}
}

/* =========================================================
   THE PHONE MENU BUTTON — five shapes, either corner
   =========================================================
   .mobtop is a floating glass pill in the top-right and every rule below is
   attribute-gated, so a site that has never chosen renders exactly what it
   always did. The server emits nothing for a default.

   The `html` prefix on the bar is not decoration. Further up the file,
   @media(max-width:1040px){html:not(.app-mode) .mobtop{display:flex}} sets
   this element at (0,2,1), which outranks a bare .mobtop[data-top] at (0,2,0);
   matching the specificity and coming later is enough. Same trap the menu
   scrim fell into, same fix. */

/* --- which corner ------------------------------------------------------- */
.mobtop[data-side="left"]{right:auto;left:12px;}

/* --- full-width bar ----------------------------------------------------- */
/* What most sites do: a header across the top, logo one end, menu the other.
   The logo does NOT collapse on scroll here. Sliding it into the hamburger is
   a pill idea that only works because the pill shrinks with it; in a bar it
   just leaves a hole where the logo was. */
html .mobtop[data-top="bar"]{
  top:0;left:0;right:0;justify-content:space-between;gap:12px;
  padding:calc(env(safe-area-inset-top,0px) + 10px) 16px 10px;
  border-radius:0;border-width:0 0 1px;
  background:rgba(13,37,65,.82);
  box-shadow:0 2px 16px rgba(7,20,38,.24);}
.mobtop[data-top="bar"] .brand{max-width:none;}
.mobtop[data-top="bar"].is-min .brand{max-width:none;opacity:1;margin-right:0;transform:none;}
/* Button on the left means logo on the right, or the bar has both ends empty. */
html .mobtop[data-top="bar"][data-side="left"]{flex-direction:row-reverse;}

/* --- icon only: rounded square, or circle -------------------------------- */
/* display:none rather than the pill's collapse, so the padding stays even on
   all four sides and the thing is an actual square. */
.mobtop[data-top="square"] .brand,
.mobtop[data-top="circle"] .brand,
.mobtop[data-top="bare"]   .brand{display:none;}
.mobtop[data-top="square"],
.mobtop[data-top="circle"]{gap:0;padding:6px;}
.mobtop[data-top="square"]{border-radius:16px;}

/* --- just the icon ------------------------------------------------------ */
/* No pill, no glass, nothing behind it - which leaves two white lines to stay
   legible over whatever the page puts underneath them. A drop shadow does not
   do it: on a pale page the lines are still white on near-white and the shadow
   only turns them into a grey smudge. I rendered both and the smudge is the
   worse of the two failures, because it looks broken rather than subtle.

   mix-blend-mode:difference is the actual answer. The lines invert against
   whatever is behind them - black on a white page, white on the navy hero,
   and still crisp over a photograph - and it is one property with no state to
   keep in sync. It also fixes the close X: with the menu open the lines sit on
   the cream panel and come out dark, where before they were white on cream.

   The box-shadow outside the @supports is the fallback for a browser without
   blending. Nothing shipping has been without it since 2015, so this is
   belt-and-braces; it is three lines and it fails soft instead of invisible. */
.mobtop[data-top="bare"]{
  gap:0;padding:0;background:none;border:none;box-shadow:none;
  backdrop-filter:none;-webkit-backdrop-filter:none;}
.mobtop[data-top="bare"] .burger span{box-shadow:0 1px 2px rgba(7,20,38,.5);}
@supports (mix-blend-mode:difference){
  .mobtop[data-top="bare"] .burger{mix-blend-mode:difference;}
  .mobtop[data-top="bare"] .burger span{box-shadow:none;background:#fff;}
}
.mobtop[data-top="bare"] .mobtop__burger:hover,
.mobtop[data-top="bare"] .mobtop__burger:active{background:rgba(7,20,38,.18);}

/* =========================================================
   PAGE-BUILDER BLOCKS — cards, people, steps, place, notice,
   table, downloads, divider
   =========================================================
   All eight sit inside the house shape (section > wrap), so the universal
   alignment / spacing / width / motion / hover options fold onto them with no
   help from here. Everything below is the inside of the block only.

   Colours come from the four brand tokens through color-mix, never as literal
   hex, so a church that changes its accent changes these too — which is the
   whole point of the theme screen and the thing the older block backgrounds
   still get wrong. */

/* --- shared: a smaller button, for notices and card feet ----------------- */
.btn--sm{padding:.62em 1.15em;font-size:.86rem;}

/* --- cards --------------------------------------------------------------- */
/* auto-fit with a floor rather than a hard column count: three cards on a
   laptop become two on a tablet and one on a phone without a breakpoint, and
   the data-cols choice only sets how wide they are allowed to get. */
.cmscards{display:grid;gap:var(--space-lg);
  grid-template-columns:repeat(auto-fit,minmax(min(100%,260px),1fr));}
.cmscards[data-cols="2"]{grid-template-columns:repeat(auto-fit,minmax(min(100%,380px),1fr));}
.cmscards[data-cols="4"]{grid-template-columns:repeat(auto-fit,minmax(min(100%,210px),1fr));}
.cmscard{display:flex;flex-direction:column;background:var(--card);border:1px solid var(--line);
  border-radius:var(--radius);overflow:hidden;text-decoration:none;color:inherit;
  transition:transform .4s var(--ease-out),box-shadow .4s var(--ease-out),border-color .3s;}
a.cmscard:hover{transform:translateY(-3px);box-shadow:var(--shadow-md);border-color:color-mix(in srgb,var(--cyan) 40%,var(--line));}
a.cmscard:focus-visible{outline:2px solid var(--cyan);outline-offset:3px;}
.cmscard__ph{margin:0;aspect-ratio:4/3;}
.cmscard__ph .ph{width:100%;height:100%;object-fit:cover;display:block;}
.cmscard__b{padding:var(--space-lg);display:flex;flex-direction:column;gap:var(--space-xs);flex:1;}
.cmscard__t{margin:0;font-size:1.12rem;line-height:1.3;color:var(--ink-strong);}
.cmscard__x{font-size:.92rem;line-height:1.6;color:var(--ink-soft);}
.cmscard__x p{margin:0 0 .6em;}
.cmscard__x p:last-child{margin-bottom:0;}
/* margin-top:auto pins the link to the bottom, so a row of cards with unequal
   text still lines its links up. */
.cmscard__go{margin-top:auto;padding-top:var(--space-xs);font-weight:600;font-size:.9rem;color:var(--cyan-deep);
  display:inline-flex;align-items:center;gap:.4em;}
a.cmscard:hover .cmscard__go .arrow{transform:translateX(3px);}
.cmscard__go .arrow{transition:transform .3s var(--ease-out);}

/* --- people -------------------------------------------------------------- */
.cmspeople{display:grid;gap:var(--space-xl) var(--space-lg);
  grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));}
.cmspeople[data-cols="2"]{grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr));}
.cmspeople[data-cols="4"]{grid-template-columns:repeat(auto-fit,minmax(min(100%,180px),1fr));}
/* Two across on a phone, always. Left to auto-fit, a 220px floor gives one
   column at 414px, and a square photo then stands 350px tall - four of them is
   a page and a half of scrolling to read four names. The Large setting is the
   one case where somebody asked for a big photo, so it keeps its single file. */
@media(max-width:560px){
  .cmspeople,.cmspeople[data-cols="4"]{grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-lg) var(--space-md);}
  .cmspeople[data-cols="2"]{grid-template-columns:minmax(0,1fr);}
  .cmsperson__n{font-size:.98rem;}
  .cmsperson__r{font-size:.74rem;}
}
.cmsperson{text-align:center;}
/* A square crop, not a circle. A circle eats the top of somebody's head on
   half the photographs a church actually has. */
.cmsperson__ph{margin:0 0 var(--space-md);aspect-ratio:1;border-radius:var(--radius);overflow:hidden;}
.cmsperson__ph .ph{width:100%;height:100%;object-fit:cover;display:block;}
.cmsperson__n{margin:0;font-size:1.05rem;color:var(--ink-strong);}
.cmsperson__r{margin:2px 0 0;font-size:.82rem;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--cyan-deep);}
.cmsperson__b{margin-top:var(--space-xs);font-size:.9rem;line-height:1.6;color:var(--ink-soft);}
.cmsperson__b p{margin:0 0 .5em;}
.cmsperson__b p:last-child{margin-bottom:0;}
.cmsperson__l{margin:var(--space-xs) 0 0;display:flex;gap:var(--space-sm);justify-content:center;flex-wrap:wrap;}
.cmsperson__l a{font-size:.86rem;font-weight:600;color:var(--cyan-deep);border-bottom:1px solid color-mix(in srgb,var(--cyan) 35%,transparent);}
.cmsperson__l a:hover{border-bottom-color:var(--cyan);}

/* --- numbered steps ------------------------------------------------------ */
/* The numerals come from the list counter, so they cannot disagree with the
   order the rows were dragged into. */
.cmssteps{list-style:none;counter-reset:cmsstep;margin:0;padding:0;display:grid;gap:var(--space-lg);}
/* 6px between a step's title and its own text, 24px to the numeral beside it:
   the two belong together and the row gap was reading as a paragraph break. */
.cmsstep{counter-increment:cmsstep;display:grid;grid-template-columns:auto minmax(0,1fr);gap:6px var(--space-lg);
  align-items:start;padding:var(--space-lg);background:var(--card);border:1px solid var(--line);border-radius:var(--radius);}
.cmsstep::before{content:counter(cmsstep);display:grid;place-items:center;width:44px;height:44px;border-radius:50%;
  background:color-mix(in srgb,var(--cyan) 14%,var(--card));color:var(--cyan-deep);
  font-family:var(--font-display);font-weight:800;font-size:1.05rem;
  /* 1/-1, not span 2: a step with a title and no text, or text and no title,
     has one row rather than two, and span 2 would invent an empty one. */
  grid-row:1/-1;}
.cmsstep__t{margin:0;font-size:1.08rem;color:var(--ink-strong);align-self:center;}
.cmsstep__b{grid-column:2;font-size:.94rem;line-height:1.65;color:var(--ink-soft);}
.cmsstep__b p{margin:0 0 .6em;}
.cmsstep__b p:last-child{margin-bottom:0;}

/* --- where to find us ---------------------------------------------------- */
.cmsplace{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);gap:var(--space-xl);align-items:start;}
.cmsplace.is-nomap{grid-template-columns:minmax(0,1fr);}
@media(max-width:860px){.cmsplace{grid-template-columns:minmax(0,1fr);}}
.cmsplace__a{font-style:normal;font-size:1.12rem;line-height:1.55;font-weight:600;color:var(--ink-strong);margin:0 0 var(--space-md);}
.cmsplace__h{font-size:.95rem;line-height:1.65;color:var(--ink);margin-bottom:var(--space-sm);}
.cmsplace__n{font-size:.92rem;line-height:1.65;color:var(--ink-soft);margin-bottom:var(--space-lg);max-width:46ch;}
.cmsplace__h p,.cmsplace__n p{margin:0 0 .5em;}
.cmsplace__h p:last-child,.cmsplace__n p:last-child{margin-bottom:0;}
.cmsplace__m{border-radius:var(--radius);overflow:hidden;border:1px solid var(--line);aspect-ratio:4/3;background:var(--cream-2);}
.cmsplace__m iframe{width:100%;height:100%;border:0;display:block;}

/* --- notice -------------------------------------------------------------- */
/* A full border and a tinted face. Not a fat coloured stripe down one edge:
   that is the most over-used decoration in admin design and it never reads as
   a choice, whatever colour it is. */
.cmsnotice{display:flex;gap:var(--space-lg);align-items:center;flex-wrap:wrap;justify-content:space-between;
  padding:var(--space-lg) var(--space-xl);border-radius:var(--radius);
  border:1px solid color-mix(in srgb,var(--cyan) 30%,var(--line));
  background:color-mix(in srgb,var(--cyan) 7%,var(--card));}
.cmsnotice[data-tone="warn"]{border-color:color-mix(in srgb,#b06a1c 34%,var(--line));background:color-mix(in srgb,#b06a1c 8%,var(--card));}
.cmsnotice[data-tone="good"]{border-color:color-mix(in srgb,#2f8b5d 32%,var(--line));background:color-mix(in srgb,#2f8b5d 8%,var(--card));}
.cmsnotice__b{min-width:min(100%,260px);flex:1;}
.cmsnotice__t{margin:0;font-family:var(--font-display);font-weight:700;font-size:1.04rem;color:var(--ink-strong);}
.cmsnotice__x{margin-top:4px;font-size:.93rem;line-height:1.6;color:var(--ink-soft);}
.cmsnotice__x p{margin:0 0 .5em;}
.cmsnotice__x p:last-child{margin-bottom:0;}

/* --- table --------------------------------------------------------------- */
/* tabindex + role=region on the scroller: a table that scrolls sideways has to
   be reachable from the keyboard, or the columns past the fold are unreadable
   without a mouse. */
.cmstablewrap{overflow-x:auto;border:1px solid var(--line);border-radius:var(--radius);background:var(--card);}
.cmstablewrap:focus-visible{outline:2px solid var(--cyan);outline-offset:2px;}
.cmstable{width:100%;border-collapse:collapse;font-size:.94rem;}
.cmstable th,.cmstable td{padding:.82em 1.1em;text-align:left;vertical-align:top;
  border-bottom:1px solid color-mix(in srgb,var(--navy) 8%,transparent);}
.cmstable thead th{background:color-mix(in srgb,var(--navy) 5%,var(--card));
  font-family:var(--font-display);font-weight:700;font-size:.78rem;letter-spacing:.06em;
  text-transform:uppercase;color:var(--muted);white-space:nowrap;}
.cmstable tbody tr:last-child th,.cmstable tbody tr:last-child td{border-bottom:0;}
.cmstable tbody tr:hover{background:color-mix(in srgb,var(--cyan) 4%,transparent);}
.cmstable__n{margin:var(--space-sm) 0 0;font-size:.84rem;color:var(--muted);}

/* --- downloads ----------------------------------------------------------- */
.cmsfiles{list-style:none;margin:0;padding:0;display:grid;gap:var(--space-xs);}
.cmsfile__a{display:flex;align-items:center;gap:var(--space-md);padding:var(--space-md);
  background:var(--card);border:1px solid var(--line);border-radius:var(--radius-sm);
  text-decoration:none;color:inherit;transition:border-color .25s,transform .3s var(--ease-out),box-shadow .3s var(--ease-out);}
.cmsfile__a:hover{border-color:color-mix(in srgb,var(--cyan) 45%,var(--line));transform:translateX(2px);box-shadow:var(--shadow-sm);}
.cmsfile__a:focus-visible{outline:2px solid var(--cyan);outline-offset:2px;}
.cmsfile__ic{display:grid;place-items:center;width:44px;height:44px;flex:none;border-radius:var(--radius-sm);
  background:color-mix(in srgb,var(--cyan) 12%,var(--card));color:var(--cyan-deep);
  font-family:var(--font-display);font-weight:800;font-size:.68rem;letter-spacing:.03em;}
.cmsfile__m{display:grid;gap:2px;min-width:0;}
.cmsfile__t{font-weight:600;color:var(--ink-strong);font-size:.98rem;}
.cmsfile__n{font-size:.82rem;color:var(--muted);}

/* --- divider ------------------------------------------------------------- */
/* The block's own padding is the spacing, so the section padding is removed
   and put back here in one place per size. */
.cmsrule{padding-block:0;}
.cmsrule[data-size="s"]{padding-block:var(--space-lg);}
.cmsrule[data-size="m"]{padding-block:var(--space-2xl);}
.cmsrule[data-size="l"]{padding-block:var(--space-4xl);}
.cmsrule__m{height:1px;background:var(--line);}
/* Three dots, drawn as one repeating gradient rather than three elements the
   renderer would have to emit. 54px / 18px is exactly three. */
.cmsrule[data-style="dots"] .cmsrule__m{height:5px;width:54px;margin-inline:auto;background:none;
  background-image:radial-gradient(circle at 2.5px 50%,color-mix(in srgb,var(--navy) 30%,transparent) 2.5px,transparent 2.6px);
  background-size:18px 5px;background-repeat:repeat-x;}

/* --- next service -------------------------------------------------------- */
/* Big numbers, but they are the content rather than decoration: the block
   exists to answer "when is the next one", and a date alone makes the reader
   do the subtraction. The written-out time sits underneath and is the thing
   that is actually authoritative - the dial is only ever JavaScript's opinion
   of how long is left, so it is hidden from assistive technology and the line
   below carries the meaning. */
.cmscd{display:grid;gap:var(--space-xl) clamp(var(--space-xl),5vw,var(--space-3xl));
  padding:var(--space-xl) clamp(var(--space-lg),4vw,var(--space-2xl));
  border:1px solid var(--line);border-radius:var(--radius-lg);background:var(--card);
  box-shadow:var(--shadow-sm);}
/* Wide enough, and with other services to name, the card runs in two columns -
   the countdown keeps the weight it has earned and the rest of the week fills
   the space that would otherwise sit empty beside it. */
@media(min-width:800px){.cmscd[data-more]{grid-template-columns:minmax(0,1fr) minmax(230px,.72fr);align-items:center;}}
.cmscd__main{display:grid;justify-items:start;gap:var(--space-sm);}
.cmssec--al-center .cmscd__main{justify-items:center;text-align:center;}
.cmscd__k{margin:0;font-family:var(--font-display);font-weight:800;text-transform:uppercase;
  letter-spacing:.09em;font-size:.7rem;color:var(--cyan-deep);}
.cmscd__dial{display:flex;flex-wrap:wrap;align-items:flex-start;gap:var(--space-xs) clamp(var(--space-md),3vw,var(--space-xl));
  margin-block:var(--space-xs) 2px;}
.cmscd__dial:empty{display:none;}
.cmscd__u{display:flex;flex-direction:column;align-items:center;}
.cmscd__u b{font-family:var(--font-display);font-weight:800;line-height:.95;
  font-size:clamp(2.1rem,7vw,3.4rem);color:var(--ink-strong);font-variant-numeric:tabular-nums;}
.cmscd__u i{font-style:normal;margin-top:8px;font-size:.64rem;letter-spacing:.12em;
  text-transform:uppercase;color:var(--muted);}
.cmscd__dial.is-live{gap:.55em;align-items:center;font-family:var(--font-display);font-weight:800;
  font-size:1.05rem;color:var(--cyan-deep);padding:.5em 1.05em;border-radius:999px;
  background:color-mix(in srgb,var(--cyan) 13%,transparent);}
.cmscd__pip{width:9px;height:9px;border-radius:50%;background:var(--cyan);flex:0 0 auto;}
.motion .cmscd__pip{animation:cmscdpip 2s var(--ease-out) infinite;}
@keyframes cmscdpip{0%,100%{opacity:1;transform:scale(1);}50%{opacity:.35;transform:scale(.78);}}
.cmscd__when{margin:0;font-size:1rem;color:var(--ink-soft);}
.cmscd__a{margin:var(--space-xs) 0 0;}
/* The services after the next one. A quiet list, not a second panel - it is
   reference, and giving it the same weight as the countdown would flatten the
   one piece of hierarchy this block has. */
.cmscd__more{list-style:none;margin:0;padding:0;display:grid;gap:2px;align-content:center;}
/* Stacked rather than label-left / time-right: the times are long enough that
   a two-column row wraps on one line and not the next, and a list where only
   some rows wrap looks broken rather than responsive. */
.cmscd__more li{display:grid;gap:1px;padding:.7em 2px;border-top:1px solid var(--line);font-size:.9rem;}
.cmscd__ml{font-weight:600;color:var(--ink-strong);}
.cmscd__mw{color:var(--muted);font-variant-numeric:tabular-nums;}
.cmssec--dark .cmscd{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.16);box-shadow:none;}
.cmssec--dark .cmscd__u b,.cmssec--dark .cmscd__ml{color:#fff;}
.cmssec--dark .cmscd__when{color:#c6d3e6;}
.cmssec--dark .cmscd__u i,.cmssec--dark .cmscd__mw{color:#9fb2ca;}
.cmssec--dark .cmscd__k,.cmssec--dark .cmscd__dial.is-live{color:#7fd8ef;}
.cmssec--dark .cmscd__more li{border-top-color:rgba(255,255,255,.14);}

/* --- latest message ------------------------------------------------------ */
.cmssermon{display:grid;gap:clamp(var(--space-lg),4vw,var(--space-2xl));
  grid-template-columns:minmax(0,1.25fr) minmax(0,1fr);align-items:center;}
@media(max-width:860px){.cmssermon{grid-template-columns:1fr;}}
.cmssermon__media:empty{display:none;}
.cmssermon__ph{margin:0;border-radius:var(--radius);overflow:hidden;}
.cmssermon__ph img{display:block;width:100%;height:auto;}
.cmssermon__copy{display:grid;gap:var(--space-xs);justify-items:start;}
.cmssermon__k{margin:0;font-family:var(--font-display);font-weight:800;text-transform:uppercase;
  letter-spacing:.09em;font-size:.7rem;color:var(--cyan-deep);}
.cmssermon__t{margin:0;font-family:var(--font-display);font-weight:700;line-height:1.14;
  font-size:clamp(1.5rem,3.2vw,2.15rem);color:var(--ink-strong);}
.cmssermon__m{margin:2px 0 0;font-size:.92rem;color:var(--muted);}
.cmssermon__a{margin:var(--space-sm) 0 0;display:flex;flex-wrap:wrap;gap:var(--space-md);align-items:center;}
.cmssermon__more{font-size:.92rem;font-weight:600;color:var(--cyan-deep);text-decoration:none;
  border-bottom:1px solid color-mix(in srgb,var(--cyan) 42%,transparent);padding-bottom:1px;
  transition:border-color .2s var(--ease-out);}
.cmssermon__more:hover{border-bottom-color:var(--cyan);}
.cmssec--dark .cmssermon__t{color:#fff;}
.cmssec--dark .cmssermon__m{color:#9fb2ca;}
.cmssec--dark .cmssermon__k,.cmssec--dark .cmssermon__more{color:#7fd8ef;}

/* --- giving -------------------------------------------------------------- */
/* Every amount is a link, so each one has to be a comfortable target in its
   own right - 48px, not a text link with padding pretending to be a button. */
.cmsgive{display:grid;gap:var(--space-lg);justify-items:start;}
.cmssec--al-center .cmsgive{justify-items:center;}
.cmsgive__amts{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:var(--space-sm);}
.cmsgive__amt{display:inline-flex;align-items:baseline;gap:.08em;min-height:48px;padding:0 1.15em;
  align-content:center;flex-wrap:wrap;border-radius:var(--radius-sm);text-decoration:none;
  border:1px solid color-mix(in srgb,var(--cyan) 32%,var(--line));
  background:color-mix(in srgb,var(--cyan) 6%,var(--card));
  font-family:var(--font-display);font-weight:800;font-size:1.22rem;color:var(--ink-strong);
  font-variant-numeric:tabular-nums;line-height:48px;
  transition:background .2s var(--ease-out),border-color .2s var(--ease-out),transform .2s var(--ease-out);}
.cmsgive__amt:hover{background:color-mix(in srgb,var(--cyan) 14%,var(--card));
  border-color:color-mix(in srgb,var(--cyan) 58%,var(--line));transform:translateY(-2px);}
.cmsgive__amt:focus-visible{outline:2px solid var(--cyan);outline-offset:2px;}
.cmsgive__cur{font-size:.74em;font-weight:700;color:var(--cyan-deep);}
.cmsgive__amt--other{font-size:.92rem;font-weight:700;letter-spacing:.01em;background:transparent;
  border-style:dashed;color:var(--ink-soft);}
.cmsgive__n{margin:0;font-size:.9rem;color:var(--muted);max-width:60ch;}
.cmsgive__a{margin:0;}
/* Not cards: three short facts do not each need a box round them. A column
   rule and some air group them perfectly well. */
.cmsgive__ways{margin:var(--space-2xl) 0 0;padding:0;display:grid;gap:var(--space-lg) var(--space-2xl);
  grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));}
.cmsgive__way{padding-top:var(--space-md);border-top:2px solid color-mix(in srgb,var(--cyan) 38%,var(--line));}
.cmsgive__way dt{font-family:var(--font-display);font-weight:700;font-size:1rem;color:var(--ink-strong);}
.cmsgive__way dd{margin:.35em 0 0;font-size:.92rem;line-height:1.6;color:var(--ink-soft);}
.cmssec--dark .cmsgive__amt{background:rgba(255,255,255,.07);border-color:rgba(255,255,255,.2);color:#fff;}
.cmssec--dark .cmsgive__amt:hover{background:rgba(255,255,255,.13);}
.cmssec--dark .cmsgive__cur{color:#7fd8ef;}
.cmssec--dark .cmsgive__amt--other{background:transparent;color:#c6d3e6;}
.cmssec--dark .cmsgive__n{color:#9fb2ca;}
.cmssec--dark .cmsgive__way{border-top-color:rgba(255,255,255,.28);}
.cmssec--dark .cmsgive__way dt{color:#fff;}
.cmssec--dark .cmsgive__way dd{color:#c6d3e6;}
