/* ===================================================================
   Prayer Chain — marketing site
   Shared stylesheet for welcome.html (members) and churches.html.

   Design: candlelight on deep navy — see prayerchain/WEBSITE_DESIGN.md.
   Colour grammar: candlelight carries the prayer the whole way — offered,
   received by the church, and arriving on every device. Source and recipient
   are separated by VALUE (pale #FFF1CE vs warm #E4AE4F), never by hue.
   The parish page carries the ripple, where something really is passed
   along; the members' page carries the app-icon identity mark instead —
   its job there is recognition in a store search, not metaphor.
   The site commits to ONE designed look (Morning ground, Vesper navy
   bands). Every colour is painted explicitly so it holds on any host
   background; there is deliberately no dark variant — the navy bands
   ARE the identity, and the app's own dark mode is shown in the film.

   Naming: site chrome is unprefixed; anything drawn INSIDE a phone
   screen is `.ap-` (app) so film markup can never collide with page
   styles. Film machinery is `.film-` / `.scene`.
   =================================================================== */

:root {
  /* ── Palette ───────────────────────────────────────── */
  --vesper:     #141B33;   /* navy bands, film stage */
  --vesper-2:   #1D2742;   /* raised surfaces on navy */
  --vesper-3:   #0E1426;   /* the film stage floor, deeper than the band */
  --morning:    #F4F6FA;   /* page ground */
  --card:       #FFFFFF;
  --ink:        #1C2333;   /* body text — cool-biased, not neutral grey */
  --ink-2:      #545B6E;
  --ink-3:      #8A90A0;
  --line:       #DDE2EC;
  --line-soft:  #EAEEF5;
  --blue:       #0044FE;   /* the app's own --blue: actions, links */
  --blue-deep:  #0033BB;
  --blue-tint:  #EEF2FF;
  --candle:     #E4AE4F;   /* the thread of light — on navy only */
  --candle-lit: #F4D48A;
  /* On-navy text */
  --on-navy:    #EDEFF6;
  --on-navy-2:  #AEB6CC;
  --on-navy-3:  #7E88A4;

  /* The fictional parish used in every screen and film — never a real one. */
  --parish:     #6B2A47;

  --serif: 'Newsreader', Georgia, 'Times New Roman', serif;
  --sans:  'Source Sans 3', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;

  --nav-h: 66px;
  --cw: 660px;             /* film design-canvas width */
  --ps: 1;                 /* film stage scale — both stepped in media queries */
}

/* ── Reset ───────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
body, h1, h2, h3, h4, p, figure, ul, ol, dl, dd { margin: 0; }
ul[class] { list-style: none; padding: 0; }
img, svg { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }

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

body {
  background: var(--morning);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 18px;            /* large-print baseline — much of this audience is 60+ */
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* ── Layout primitives ───────────────────────────────── */
.wrap { width: 100%; max-width: 1080px; margin-inline: auto; padding-inline: 26px; }
.wrap--narrow { max-width: 820px; }

.sec { padding-block: clamp(56px, 8vw, 92px); }
.sec--tight { padding-block: clamp(42px, 6vw, 66px); }

.sec--navy { background: var(--vesper); color: var(--on-navy); }
.sec--tint { background: var(--blue-tint); }
.sec--card { background: var(--card); }

/* ── Type ────────────────────────────────────────────── */
.eyebrow {
  font-size: 13px; font-weight: 700; letter-spacing: .15em;
  text-transform: uppercase; color: var(--blue);
}
.sec--navy .eyebrow { color: var(--candle); }

h1 {
  font-family: var(--serif); font-weight: 400; font-style: italic;
  font-size: clamp(38px, 6.2vw, 60px); line-height: 1.1;
  letter-spacing: -0.01em; text-wrap: balance;
}
h2 {
  font-family: var(--serif); font-weight: 500;
  font-size: clamp(30px, 4.2vw, 40px); line-height: 1.18;
  text-wrap: balance;
}
h3 { font-size: 21px; font-weight: 700; line-height: 1.3; text-wrap: balance; }

.lede { font-size: clamp(18px, 2.2vw, 20.5px); color: var(--ink-2); max-width: 60ch; }
.sec--navy .lede { color: var(--on-navy-2); }

.sec-head { display: flex; flex-direction: column; gap: 10px; margin-bottom: clamp(34px, 4vw, 52px); }
.sec-head--center { align-items: center; text-align: center; }
.sec-head--center .lede { text-align: center; }

.devotional {
  font-family: var(--serif); font-style: italic;
  font-size: clamp(22px, 3vw, 27px); line-height: 1.4;
  color: var(--ink); text-wrap: balance;
}
.sec--navy .devotional { color: #fff; }

a { color: var(--blue); text-decoration-thickness: 1px; text-underline-offset: 3px; }
.sec--navy a { color: var(--candle-lit); }

:focus-visible { outline: 3px solid var(--blue); outline-offset: 3px; border-radius: 4px; }
.sec--navy :focus-visible, .film :focus-visible { outline-color: var(--candle); }

/* ── Buttons ─────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  padding: 14px 26px; border: 1.5px solid transparent; border-radius: 10px;
  font-size: 17px; font-weight: 600; line-height: 1.2;
  text-decoration: none; cursor: pointer; background: none;
  transition: background-color .18s ease, border-color .18s ease, color .18s ease, transform .18s ease;
}
.btn--primary { background: var(--blue); color: #fff; }
.btn--primary:hover { background: var(--blue-deep); }
.btn--ghost { border-color: var(--line); color: var(--ink); background: var(--card); }
.btn--ghost:hover { border-color: var(--blue); color: var(--blue); }
.btn--onnavy { border-color: rgba(237,239,246,.32); color: var(--on-navy); }
.btn--onnavy:hover { border-color: var(--candle); color: var(--candle-lit); }
.btn:active { transform: translateY(1px); }

.textlink {
  display: inline-flex; align-items: center; gap: 7px;
  font-weight: 600; text-decoration: none;
}
.textlink:hover { text-decoration: underline; }

/* ── Nav ─────────────────────────────────────────────── */
.nav {
  position: sticky; top: 0; z-index: 60;
  background: rgba(244,246,250,.92);
  backdrop-filter: saturate(150%) blur(10px);
  -webkit-backdrop-filter: saturate(150%) blur(10px);
  border-bottom: 1px solid transparent;
  transition: border-color .2s ease, box-shadow .2s ease;
}
.nav.is-scrolled { border-bottom-color: var(--line); box-shadow: 0 1px 14px rgba(20,27,51,.05); }
.nav-inner {
  min-height: var(--nav-h);
  display: flex; align-items: center; gap: 18px;
}
.nav-brand {
  display: flex; align-items: center; gap: 11px;
  text-decoration: none; color: var(--ink); margin-right: auto;
}
/* Square asset, square box — the old 34x41 box letterboxed a 256x256 emblem
   down to 34px, where five figures, a cross and its rays became a smudge. */
.nav-brand img { width: 42px; height: 42px; object-fit: contain; }
.nav-brand b { font-family: var(--serif); font-weight: 600; font-size: 21px; letter-spacing: .005em; }
.nav-links { display: flex; align-items: center; gap: 8px; }
.nav-links a:not(.btn) {
  padding: 9px 12px; border-radius: 8px; font-size: 16.5px; font-weight: 600;
  color: var(--ink-2); text-decoration: none;
}
.nav-links a:not(.btn):hover { color: var(--blue); background: var(--card); }
.nav-links .btn { padding: 11px 20px; font-size: 16px; }
@media (max-width: 620px) {
  .nav-brand b { font-size: 19px; }
  .nav-brand img { width: 38px; height: 38px; }
  .nav-links .nav-secondary { display: none; }
}

/* ── Hero ────────────────────────────────────────────── */
.hero {
  position: relative; overflow: hidden;
  background:
    radial-gradient(900px 460px at 74% -12%, rgba(228,174,79,.13), transparent 62%),
    radial-gradient(760px 520px at 8% 108%, rgba(0,68,254,.17), transparent 62%),
    var(--vesper);
  color: var(--on-navy);
  padding-block: clamp(52px, 7vw, 84px) clamp(40px, 5vw, 60px);
}
.hero h1 { color: #fff; margin-block: 16px 20px; }
.hero .lede { color: var(--on-navy-2); font-size: clamp(18.5px, 2.3vw, 21px); }
.hero-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 14px; margin-top: 34px; }

/* Split hero — copy beside the parish ripple. The ripple needs to run
   continuously (its full loop is 43s, one turn per phone), which is why it
   lives here rather than inside a 6-second film scene. */
.hero--split .hero-grid {
  display: grid; grid-template-columns: 1.02fr .98fr;
  gap: clamp(24px, 4vw, 56px); align-items: center;
}
.hero--split .hero-art { display: flex; justify-content: center; }
@media (max-width: 880px) {
  .hero--split .hero-grid { grid-template-columns: 1fr; }
  .hero--split .hero-art { margin-top: 30px; }
  .hero--split .ripple { max-width: 380px; }
}
.hero-note { margin-top: 16px; font-size: 16px; color: var(--on-navy-3); }
.hero-note a { color: var(--on-navy-2); }

/* Identity mark — the app icon at store size, in the store's shape.
   Replaced the scattered candle points here (2026-08-25): they were carrying a
   "nothing is passed between people" idea that nobody read as anything, while
   the one job this spot can do is let a visitor MATCH the icon they are about to
   search for. The candle motif still lives on the parish page's ripple and
   throughout the film, so nothing is lost from the brand. */
.idmark {
  display: flex; align-items: center; gap: clamp(16px, 2.4vw, 22px);
  margin-top: clamp(34px, 5vw, 52px);
}
.idmark-tile {
  flex: none; width: clamp(76px, 9vw, 96px); aspect-ratio: 1;
  background: #fff; border-radius: 22.5%;   /* iOS superellipse proportion */
  display: grid; place-items: center;
  box-shadow: 0 10px 30px rgba(0,0,0,.34), 0 0 0 1px rgba(255,255,255,.10);
}
.idmark-tile img { width: 88%; height: 88%; object-fit: contain; }
.idmark-note { margin: 0; color: var(--on-navy-3); font-size: 16px; line-height: 1.45; max-width: 34ch; }
.idmark-note b { color: var(--on-navy-2); font-weight: 600; }

/* ── Store badges. Both listings are live (Google Play 9 Sep 2026, App Store 10 Sep 2026); a pending one would stay a <span> reading "Coming to" ── */
.badges { display: flex; flex-wrap: wrap; gap: 12px; }
a.badge { text-decoration: none; cursor: pointer; }
a.badge:hover, a.badge:focus-visible { filter: brightness(1.08); outline-offset: 3px; }
.badge {
  display: flex; align-items: center; gap: 11px;
  padding: 11px 18px 11px 15px; border-radius: 11px;
  border: 1.5px solid rgba(237,239,246,.28); color: var(--on-navy);
  text-decoration: none; background: rgba(237,239,246,.05);
}
.badge svg { width: 24px; height: 24px; flex: none; fill: currentColor; }
.badge .bl { display: flex; flex-direction: column; line-height: 1.15; }
.badge .bl small { font-size: 11.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--on-navy-3); }
.badge .bl b { font-size: 16.5px; font-weight: 600; }
.badges--light .badge { border-color: var(--line); color: var(--ink); background: var(--card); }
.badges--light .badge .bl small { color: #656C7D; } /* not --ink-3: 11.5px caption needs AA on white/--morning/--blue-tint; --ink-3 measures 3.19:1 */

/* ═══════════════════════════════════════════════════════
   FILM
   ═══════════════════════════════════════════════════════ */
.film { background: var(--vesper); color: var(--on-navy); padding-block: clamp(46px, 6vw, 74px); }
.film .eyebrow { color: var(--candle); }
.film-head { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 9px; margin-bottom: 26px; }
.film-head h2 { color: #fff; }

/* The film is composed on a fixed design canvas and scaled to fit. Two knobs,
   because one is not enough: --ps scales it, and --cw NARROWS the canvas on
   small screens. Scaling alone would keep the 660px canvas and squeeze the
   phone down to an unreadable ~115px on a 320px handset; narrowing the canvas
   first (the extra width only ever serves the two-phone scene) keeps the phone
   large. Every step satisfies  cw * ps <= viewport - 52px of wrap padding. */
.stage {
  position: relative;
  height: calc(604px * var(--ps));
  margin-inline: auto;
  isolation: isolate;
}
.stage-canvas {
  position: absolute; top: 0; left: 50%;
  width: var(--cw); height: 604px; margin-left: calc(var(--cw) / -2);
  transform: scale(var(--ps)); transform-origin: top center;
}

.scene {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  padding-bottom: 88px;              /* reserve the caption's slot */
  opacity: 0; visibility: hidden;
  transition: opacity 1.2s ease, visibility 0s linear 1.2s;
}
.scene.is-on { opacity: 1; visibility: visible; transition: opacity 1.2s ease, visibility 0s; }

/* Every scene centres its content in the area above the caption, so a tall
   single phone and a pair of short ones both sit on the same optical line. */
.scene-body {
  flex: 1; width: 100%;
  display: flex; align-items: center; justify-content: center;
}

/* Caption — always the same slot, so it never shifts between scenes. */
.scene-cap {
  position: absolute; left: 0; right: 0; bottom: 6px;
  text-align: center; padding-inline: 20px;
  font-family: var(--serif); font-style: italic; font-weight: 400;
  font-size: 24px; line-height: 1.35; color: #fff;
  text-wrap: balance; opacity: 0;
}
.scene.is-live .scene-cap { animation: capIn 1.1s ease forwards; animation-delay: var(--cap-at, 2.6s); }
@keyframes capIn { from { opacity: 0; transform: translateY(9px); } to { opacity: 1; transform: none; } }

/* Opening line — scene 1 only. NOT a caption: it occupies the stage on its own,
   centred on exactly the optical line the lights will use (top:0/bottom:88px
   matches .scene's reserved caption slot, so it lands where .scene-body does).
   It holds ~3s at full strength — the bottom caption slot was both outside the
   eye's path and gone too fast to read — then dissolves upward as the first
   points light, handing the space over. */
.open-line {
  position: absolute; left: 0; right: 0; top: 0; bottom: 88px;
  display: grid; place-items: center;
  padding-inline: clamp(24px, 6vw, 64px); text-align: center;
  font-family: var(--serif); font-style: italic; font-weight: 400;
  font-size: clamp(23px, 3.1vw, 30px); line-height: 1.32; color: #fff;
  text-wrap: balance; margin: 0; opacity: 0;
}
.scene.is-live .open-line { animation: openLine 5.4s ease forwards .35s; }
@keyframes openLine {
  0%   { opacity: 0; transform: translateY(9px); }
  15%  { opacity: 1; transform: none; }
  70%  { opacity: 1; transform: none; }
  100% { opacity: 0; transform: translateY(-7px); }
}

/* ── Phone ───────────────────────────────────────────── */
.phone {
  position: relative; width: 288px; height: 512px;
  border-radius: 34px; padding: 9px;
  background: linear-gradient(160deg, #39415F, #222B44 42%, #171E33);
  box-shadow: 0 22px 50px rgba(0,0,0,.42), 0 0 0 1px rgba(255,255,255,.07) inset;
  flex: none;
}
.phone-screen {
  position: relative; width: 100%; height: 100%;
  border-radius: 26px; overflow: hidden;
  background: #fff; display: flex; flex-direction: column;
  font-size: 13px; line-height: 1.4; color: #222;
}
.phone::after {           /* dynamic-island hint */
  content: ""; position: absolute; top: 17px; left: 50%; transform: translateX(-50%);
  width: 66px; height: 8px; border-radius: 5px; background: #0B0F1C; z-index: 4;
}
.phone--sm { width: 190px; height: 340px; border-radius: 25px; padding: 7px; }
.phone--sm .phone-screen { border-radius: 19px; font-size: 11px; }
.phone--sm::after { top: 13px; width: 44px; height: 6px; }

/* Three-up, for "it lands on every phone". Sized so 3 phones + 2 gaps fit the
   NARROW 440px canvas (3*136 + 2*12 = 432), not just the 660px desktop one. */
.phone--xs { width: 136px; height: 250px; border-radius: 20px; padding: 6px; }
.phone--xs .phone-screen { border-radius: 15px; font-size: 9px; }
.phone--xs::after { top: 11px; width: 34px; height: 5px; }
.phone--xs .ap-lock { padding: 16px 8px 10px; }
.phone--xs .ap-lock .lk-time { font-size: 23px; }
.phone--xs .ap-lock .lk-date { font-size: 8px; margin-bottom: 10px; }
.phone--xs .ap-push { padding: 6px 7px; gap: 5px; border-radius: 9px; }
.phone--xs .ap-push img { width: 15px; height: 15px; border-radius: 4px; }
.phone--xs .ap-push .pu-t, .phone--xs .ap-push .pu-b { font-size: 7.5px; line-height: 1.3; }

.phones { display: flex; align-items: center; justify-content: center; gap: 18px; }
.phones--three { gap: 12px; }

/* ═══════════════════════════════════════════════════════
   APP CHROME  (.ap-*) — a faithful reduction of the real
   PWA: colours, hierarchy and wording taken from index.html.
   ═══════════════════════════════════════════════════════ */
.ap {
  display: flex; flex-direction: column; height: 100%;
  background: #fff; color: #222;
  transition: background-color .9s ease, color .9s ease;
}
.ap-top {
  flex: none; background: var(--blue); color: #fff;
  /* Top padding clears the device notch, the same job env(safe-area-inset-top)
     does in the real app — without it the title sits under the island. */
  padding: 22px 10px 7px; display: flex; align-items: center; gap: 8px;
  transition: background-color .9s ease;
}
.phone--sm .ap-top { padding-top: 16px; }
.ap-top--parish { background: var(--parish); }
.ap-logo {
  flex: none; width: 30px; height: 30px; border-radius: 7px;
  background: #fff; padding: 2px; object-fit: contain;
}
.ap-toptext { flex: 1; text-align: center; min-width: 0; }
.ap-title { font-size: 13px; line-height: 1.25; font-weight: 500; }
.ap-sub { font-size: 10.5px; color: rgba(255,255,255,.78); margin-top: 1px; }
.ap-role {
  flex: none; font-size: 9px; font-weight: 700; letter-spacing: .05em;
  background: rgba(255,255,255,.2); border-radius: 4px; padding: 2px 5px;
}

.ap-search {
  flex: none; padding: 6px 8px; border-bottom: 1px solid #e8e8e8;
}
.ap-search span {
  display: block; background: #f0f0f3; border-radius: 8px;
  padding: 5px 9px; font-size: 11.5px; color: #9a9aa2;
}

.ap-list { flex: 1; overflow: hidden; }
.ap-cat {
  background: #f6f6f7; border-top: 1px solid #808080; border-bottom: 1px solid #808080;
  padding: 4px 9px; font-size: 11.5px; font-weight: 700; color: #333;
  transition: background-color .9s ease, color .9s ease;
}
.ap-row {
  display: flex; align-items: center; gap: 5px;
  padding: 6px 8px 6px 6px; border-bottom: 1px solid #e8e8e8;
  min-height: 38px; position: relative;
  transition: border-color .9s ease;
}
.ap-name {
  flex: 0 0 36%; font-size: 12.5px; font-weight: 500; color: #222;
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  transition: color .9s ease, font-size .9s ease;
}
.ap-summary {
  flex: 1; font-size: 12.5px; color: #4d4d4d;
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  transition: color .9s ease, font-size .9s ease;
}
.ap-days {
  flex: none; font-size: 11.5px; color: #98B7FE; text-align: right; min-width: 34px;
  transition: font-size .9s ease;
}
.ap-badge {
  font-size: 8.5px; font-weight: 800; letter-spacing: .07em;
  color: #fff; background: #22c55e; border-radius: 3px; padding: 1px 4px; margin-right: 4px;
}
.ap-bottom {
  flex: none; border-top: 1px solid #ddd; padding: 7px 9px;
  display: flex; align-items: flex-end; justify-content: space-between; gap: 8px;
  background: #fff; transition: background-color .9s ease, border-color .9s ease;
}
.ap-stats { font-size: 10.5px; color: #4d4d4d; line-height: 1.45; transition: color .9s ease; }
.ap-stats b { color: #222; transition: color .9s ease; }
.ap-btns { display: flex; gap: 6px; }
.ap-btn {
  font-size: 10.5px; border: 1px solid #ccc; border-radius: 6px;
  padding: 4px 8px; color: #333; background: #fff;
  transition: background-color .9s ease, color .9s ease, border-color .9s ease;
}

/* The app's dark-mode and large-text repaints are driven per-scene by
   @keyframes (see welcome.html, scene 7) rather than by state classes here,
   so the whole sequence replays identically on every loop of the film. */

/* ── App: login / join card ──────────────────────────── */
.ap-login {
  flex: 1; display: flex; flex-direction: column; align-items: center;
  padding: 26px 20px; text-align: center; gap: 4px; background: #fff;
}
.ap-login img.ap-mark { width: 92px; height: auto; margin-bottom: 6px; }
.ap-login h4 { font-size: 15px; font-weight: 700; margin: 6px 0 2px; color: #222; }
.ap-login p { font-size: 11.5px; color: #6e6e6e; line-height: 1.45; margin-bottom: 10px; }
.ap-field {
  width: 100%; border: 1px solid #ccc; border-radius: 8px;
  padding: 9px 11px; font-size: 13px; text-align: left; color: #222;
  background: #fff; margin-bottom: 9px; min-height: 36px;
  display: flex; align-items: center; letter-spacing: .06em;
}
.ap-field.is-placeholder { color: #b0b0b0; letter-spacing: 0; }
.ap-cta {
  width: 100%; background: var(--blue); color: #fff; border-radius: 9px;
  padding: 10px; font-size: 13.5px; font-weight: 600; text-align: center;
  transition: background-color .5s ease, transform .25s ease;
}
.ap-cta--parish { background: var(--parish); }
.ap-cta.is-pressed { transform: scale(.96); }
.ap-cta--ghost { background: none; color: var(--blue); border: 1px solid #ccc; }

/* Parish confirmation (scene 2) */
.ap-parishcard {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 12px 10px; border-radius: 11px; width: 100%;
  background: #F7EFF3; border: 1px solid #E3CBD6;
}
.ap-shield {
  width: 38px; height: 44px; border-radius: 7px 7px 19px 19px;
  background: var(--parish); display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 19px; line-height: 1;
}
.ap-parishcard b { font-size: 13px; color: var(--parish); }
.ap-parishcard span { font-size: 11px; color: #7a6070; }

/* ── App: form (scene 4) ─────────────────────────────── */
.ap-form { flex: 1; padding: 12px 12px 10px; display: flex; flex-direction: column; gap: 3px; background: #fff; }
.ap-form h4 { font-size: 14.5px; font-weight: 700; color: #222; margin-bottom: 8px; }
.ap-lbl { font-size: 10.5px; font-weight: 600; color: #6e6e6e; margin-top: 7px; }
.ap-input {
  border: 1px solid #ccc; border-radius: 7px; padding: 7px 9px;
  font-size: 12.5px; color: #222; min-height: 32px; background: #fff;
}
.ap-input.is-placeholder { color: #b0b0b0; }
.ap-input--area { min-height: 62px; align-items: flex-start; line-height: 1.45; }
.ap-select {
  border: 1px solid #ccc; border-radius: 7px; padding: 7px 9px; font-size: 12.5px;
  color: #222; display: flex; justify-content: space-between; align-items: center;
}
.ap-select span:last-child { color: #8c8c8c; font-size: 10px; }

/* Toast — the real app's toast is a near-black pill. */
.ap-toast {
  position: absolute; left: 50%; bottom: 22px; transform: translate(-50%, 10px);
  background: #23242b; color: #fff; border-radius: 9px;
  padding: 8px 14px; font-size: 11.5px; font-weight: 500;
  white-space: nowrap; opacity: 0; z-index: 5; max-width: 88%;
}

/* ── App: review queue (admin) ───────────────────────── */
.ap-note {
  font-size: 10.5px; line-height: 1.45; color: #4d4d4d;
  background: #eef2ff; border: 1px solid #d6e0ff; border-radius: 8px;
  padding: 7px 9px; margin-bottom: 9px;
}
.ap-rqitem {
  border: 1px solid #e8e8e8; border-radius: 9px; padding: 9px 10px;
  display: flex; flex-direction: column; gap: 5px; background: #fff; margin-bottom: 8px;
}
.ap-rqname { font-size: 13px; font-weight: 600; color: #333; }
.ap-rqmeta { font-size: 10.5px; color: #8c8c8c; }
.ap-rqtext { font-size: 11.5px; color: #4d4d4d; line-height: 1.45; }
.ap-match {
  align-self: flex-start; font-size: 9.5px; font-weight: 700; border-radius: 4px;
  padding: 2px 6px; background: #dcfce7; color: #166534;
}
.ap-rqbtns { display: flex; gap: 6px; margin-top: 3px; }
.ap-rqbtn {
  flex: 1; text-align: center; border-radius: 7px; padding: 6px;
  font-size: 11.5px; font-weight: 600; border: 1px solid #ccc; color: #333;
  transition: transform .25s ease, background-color .3s ease;
}
.ap-rqbtn--go { background: #38a169; border-color: #38a169; color: #fff; }
.ap-rqbtn.is-pressed { transform: scale(.94); }

/* ── App: prayer note (scene 6) ──────────────────────── */
.ap-noteitem {
  border: 1px solid #e8e8e8; border-radius: 9px; overflow: hidden; background: #fff;
}
.ap-notemeta {
  display: flex; justify-content: space-between; align-items: center;
  padding: 5px 9px; background: #f0f4ff; border-bottom: 1px solid #e8e8e8;
}
.ap-notedate {
  font-size: 9.5px; font-weight: 700; color: #0033BB;
  text-transform: uppercase; letter-spacing: .06em;
}
.ap-notetext { font-size: 12px; color: #333; line-height: 1.5; padding: 8px 9px; }

/* ── App: lock screen (push) ─────────────────────────── */
.ap-lock {
  flex: 1; display: flex; flex-direction: column; align-items: center;
  padding: 22px 11px 14px; gap: 4px;
  background: linear-gradient(168deg, #202A47, #121829 62%, #0B1020);
  color: #fff;
}
.ap-lock .lk-time { font-size: 40px; font-weight: 300; letter-spacing: -.01em; line-height: 1; }
.ap-lock .lk-date { font-size: 11px; color: rgba(255,255,255,.62); margin-bottom: 16px; }
.ap-push {
  width: 100%; border-radius: 12px; padding: 8px 10px;
  background: rgba(255,255,255,.15);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(255,255,255,.14);
  display: flex; gap: 8px; align-items: flex-start; text-align: left;
  opacity: 0;
}
.ap-push img { width: 21px; height: 21px; border-radius: 5px; background: #fff; padding: 1px; flex: none; }
.ap-push .pu-t { font-size: 10.5px; font-weight: 700; line-height: 1.3; }
.ap-push .pu-b { font-size: 10.5px; color: rgba(255,255,255,.8); line-height: 1.35; margin-top: 1px; }
.phone--sm .ap-lock .lk-time { font-size: 31px; }
.phone--sm .ap-push .pu-t, .phone--sm .ap-push .pu-b { font-size: 9px; }

/* ── Scene 1 / page-2 scene 1: the motif, full stage ─── */
.motif { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; }
.motif svg { width: 600px; max-width: 100%; height: auto; overflow: visible; }
/* Deliberately NOT scoped to .motif — the thread also runs between the two
   phones in the hand-off scene, where there is no .motif wrapper. Scoped, the
   path fell back to a black fill and drew as a blob. */
.mo-path { fill: none; stroke: var(--candle); stroke-width: 1.3; stroke-opacity: .5; }
.mo-dot  { fill: var(--candle-lit); opacity: 0; }
.mo-glow { opacity: 0; }

/* ── Scene 8 / page-2 scene 6: the close ─────────────── */
.closing {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 16px; height: 100%; text-align: center; padding-inline: 30px;
}
/* The lockup's wordmark and cross are navy, so on a navy ground they vanish.
   A white tile is the same answer the app itself uses for parish logos in
   dark mode, and it reads as an app icon rather than a patch. */
.closing img {
  width: 128px; height: auto;
  background: #fff; border-radius: 20px; padding: 15px 18px;
  box-shadow: 0 18px 44px rgba(0,0,0,.4);
}
.closing .cl-line { font-size: 16px; color: var(--on-navy-2); }
.closing .badges { justify-content: center; }

/* ── Film controls ───────────────────────────────────── */
.film-controls {
  display: flex; align-items: center; justify-content: center; gap: 16px;
  margin-top: 22px; flex-wrap: wrap;
}
.film-play {
  display: inline-flex; align-items: center; gap: 8px;
  border: 1.5px solid rgba(237,239,246,.28); border-radius: 999px;
  padding: 9px 18px; color: var(--on-navy); background: rgba(237,239,246,.05);
  font-size: 15px; font-weight: 600; cursor: pointer;
}
.film-play:hover { border-color: var(--candle); color: var(--candle-lit); }
.film-play svg { width: 13px; height: 13px; fill: currentColor; }
.film-dots { display: flex; gap: 9px; flex-wrap: wrap; justify-content: center; }
.film-dot {
  width: 30px; height: 5px; border-radius: 3px; border: 0; padding: 0;
  background: rgba(237,239,246,.22); cursor: pointer;
  transition: background-color .3s ease;
}
.film-dot:hover { background: rgba(237,239,246,.45); }
.film-dot.is-on { background: var(--candle); }
.film-scenename {
  font-size: 14px; color: var(--on-navy-3); min-width: 15ch; text-align: center;
}
@media (max-width: 560px) { .film-scenename { display: none; } }

/* ═══════════════════════════════════════════════════════
   PAGE FURNITURE
   ═══════════════════════════════════════════════════════ */

/* Steps — a real sequence, so it is numbered. */
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 26px; counter-reset: step; }
.step { display: flex; flex-direction: column; gap: 10px; }
.step-n {
  counter-increment: step; display: flex; align-items: center; gap: 11px;
  font-family: var(--serif); font-size: 15px; color: var(--ink-3);
}
.step-n::before {
  content: counter(step); display: grid; place-items: center;
  width: 34px; height: 34px; border-radius: 50%; flex: none;
  background: var(--blue); color: #fff;
  font-family: var(--sans); font-size: 16px; font-weight: 700;
}
.step p { color: var(--ink-2); font-size: 17px; }
@media (max-width: 760px) { .steps { grid-template-columns: 1fr; gap: 22px; } }

/* Feature cards — no numbering; these are a set, not a sequence. */
.cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.cards--2 { grid-template-columns: repeat(2, 1fr); }
.card {
  background: var(--card); border: 1px solid var(--line); border-radius: 14px;
  padding: 26px 24px; display: flex; flex-direction: column; gap: 9px;
}
.card p { color: var(--ink-2); font-size: 16.5px; }
.card-ic {
  width: 40px; height: 40px; border-radius: 10px; display: grid; place-items: center;
  background: var(--blue-tint); color: var(--blue); margin-bottom: 4px; flex: none;
}
.card-ic svg { width: 21px; height: 21px; stroke: currentColor; fill: none; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.sec--navy .card {
  background: rgba(237,239,246,.055); border-color: rgba(237,239,246,.14);
}
.sec--navy .card h3 { color: #fff; }
.sec--navy .card p { color: var(--on-navy-2); }
.sec--navy .card-ic { background: rgba(228,174,79,.14); color: var(--candle); }
@media (max-width: 900px) { .cards, .cards--2 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .cards, .cards--2 { grid-template-columns: 1fr; } }

/* Chips — the "more than parishes" band */
.chips { display: flex; flex-wrap: wrap; gap: 11px; margin-top: 8px; }
.chip {
  background: var(--card); border: 1px solid #C9D6FF; border-radius: 999px;
  padding: 9px 18px; font-size: 16px; font-weight: 600; color: var(--ink);
}

/* Split — text beside a visual */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(28px, 5vw, 60px); align-items: center; }
@media (max-width: 860px) { .split { grid-template-columns: 1fr; } }
.split-visual { display: flex; justify-content: center; }

/* Timeline — "A week in the life" */
.timeline { display: grid; grid-template-columns: repeat(6, 1fr); gap: 0; margin-top: 12px; }
.tl-step { position: relative; padding: 30px 14px 0; display: flex; flex-direction: column; gap: 5px; }
.tl-step::before {
  content: ""; position: absolute; top: 12px; left: 0; right: 0; height: 2px;
  background: var(--line);
}
.tl-step:first-child::before { left: 50%; border-radius: 2px 0 0 2px; }
.tl-step:last-child::before { right: 50%; border-radius: 0 2px 2px 0; }
.tl-step::after {
  content: ""; position: absolute; top: 7px; left: 50%; transform: translateX(-50%);
  width: 13px; height: 13px; border-radius: 50%;
  background: var(--card); border: 2.5px solid var(--blue);
}
.tl-step.is-key::after { background: var(--blue); box-shadow: 0 0 0 4px var(--blue-tint); }
.tl-day { font-size: 12.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--blue); text-align: center; }
.tl-what { font-size: 15.5px; color: var(--ink-2); text-align: center; line-height: 1.45; }
@media (max-width: 880px) {
  .timeline { grid-template-columns: 1fr; }
  .tl-step { padding: 0 0 22px 34px; }
  .tl-step::before { top: 0; bottom: 0; left: 6px; right: auto; width: 2px; height: auto; }
  .tl-step:first-child::before { top: 10px; left: 6px; }
  .tl-step:last-child::before { bottom: auto; height: 10px; left: 6px; }
  .tl-step::after { top: 4px; left: 6px; }
  .tl-day, .tl-what { text-align: left; }
}

/* Pricing */
.tiers { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; align-items: stretch; }
.tier {
  background: var(--card); border: 1px solid var(--line); border-radius: 14px;
  padding: 26px 22px; display: flex; flex-direction: column; gap: 5px;
}
.tier.is-feature { border-color: var(--blue); box-shadow: 0 0 0 1px var(--blue), 0 14px 34px rgba(0,68,254,.12); }
.tier-badge {
  align-self: flex-start; font-size: 11.5px; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: #fff; background: var(--blue);
  border-radius: 999px; padding: 4px 12px; margin-bottom: 6px;
}
.tier h3 { font-family: var(--serif); font-weight: 500; font-size: 24px; }
.tier-price {
  font-size: 34px; font-weight: 700; color: var(--ink); line-height: 1.1;
  font-variant-numeric: tabular-nums; margin-block: 4px 2px;
}
.tier-price small { font-size: 17px; font-weight: 600; color: var(--ink-2); }
.tier-fit { font-size: 16px; color: var(--ink-2); border-top: 1px solid var(--line); padding-top: 12px; margin-top: 10px; }
@media (max-width: 900px) { .tiers { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .tiers { grid-template-columns: 1fr; } }
.tiers-note { margin-top: 22px; font-size: 16.5px; color: var(--ink-2); text-align: center; }

/* FAQ */
.faq { display: flex; flex-direction: column; gap: 0; border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  cursor: pointer; list-style: none; padding: 20px 40px 20px 0; position: relative;
  font-size: 19px; font-weight: 600; color: var(--ink);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; position: absolute; right: 8px; top: 50%; width: 11px; height: 11px;
  border-right: 2.2px solid var(--blue); border-bottom: 2.2px solid var(--blue);
  transform: translateY(-70%) rotate(45deg); transition: transform .22s ease;
}
.faq details[open] summary::after { transform: translateY(-30%) rotate(-135deg); }
.faq .faq-a { padding: 0 0 22px; color: var(--ink-2); font-size: 17px; max-width: 68ch; }
.faq .faq-a p + p { margin-top: 12px; }

/* Final CTA */
.cta-final { text-align: center; display: flex; flex-direction: column; align-items: center; gap: 18px; }
.cta-final .badges { justify-content: center; }

/* Footer */
.foot { background: var(--vesper); color: var(--on-navy-2); padding-block: 46px; font-size: 16px; }
.foot-inner { display: flex; flex-wrap: wrap; gap: 22px 40px; align-items: flex-start; }
.foot-brand { display: flex; align-items: center; gap: 11px; margin-right: auto; }
/* Same navy-on-navy problem as the film's closing mark, at a smaller size. */
.foot-brand img {
  width: 42px; height: 42px; object-fit: contain;
  background: #fff; border-radius: 11px; padding: 3px;
}
.foot-brand b { font-family: var(--serif); font-size: 20px; color: #fff; font-weight: 600; }
.foot a { color: var(--on-navy-2); }
.foot-links { display: flex; flex-direction: column; gap: 6px; }
.foot-legal { width: 100%; border-top: 1px solid rgba(237,239,246,.13); padding-top: 20px; margin-top: 6px; font-size: 15px; color: var(--on-navy-3); }

/* ── The parish ripple ─────────────────────────────────
   One phone offers a request (gold), it travels in to the church, and a
   ripple carries it back out so every phone lights at once (blue). Each
   phone takes its turn via a negative animation-delay of -(i x 3.6s);
   one keyframe set therefore covers all 12. Full loop 43.2s. */
.ripple { width: 100%; max-width: 460px; height: auto; overflow: visible; }

.rp-ring   { fill: none; stroke: rgba(228,174,79,.13); stroke-width: 1; }
.rp-spoke  { stroke: rgba(228,174,79,.10); stroke-width: 1; }
/* The rider: what actually carries the prayer inward. A hard uniform dash read
   like a data packet, so this is a soft candle-light instead — a warm halo with
   a bright core, taken in by the church as it arrives. */
.rp-rider { opacity: 0; }
.rp-ember-halo { fill: url(#rpEmber); }
.rp-ember-core { fill: #FFF1CE; }
.rp-dove { fill: #F4D48A; }
.rp-dove-wing { fill: #FFF1CE; }
.rp-wave   { fill: none; stroke: #E4AE4F; stroke-width: 1.4; opacity: 0;
             transform-origin: 260px 260px; }
.rp-core   { opacity: .34; transform-origin: 260px 260px; }

.rp-church  { opacity: .72; }
.rp-ch-line { fill: none; stroke: #E4AE4F; stroke-width: 1.5;
               stroke-linecap: round; stroke-linejoin: round; opacity: .92; }
.rp-ch-door { fill: rgba(228,174,79,.20); stroke: #E4AE4F; stroke-width: 1.3; opacity: .92; }
.rp-ch-win  { fill: rgba(228,174,79,.28); stroke: none; }

.rp-glow   { fill: url(#rpLit); opacity: 0; }
.rp-body   { fill: rgba(237,239,246,.06); stroke: rgba(237,239,246,.28); stroke-width: 1.1; }
.rp-screen { fill: rgba(237,239,246,.09); }
/* The phone offering the request, in the palest gold so it still reads as the
   source against the warmer amber of the ones receiving. It has to be its own
   element: both this and rpLit animate `fill`, and on a single element the
   later animation would win outright and kill the other. */
.rp-offer  { fill: #FFF1CE; opacity: 0; }
.rp-speaker{ stroke: rgba(237,239,246,.34); stroke-width: 1.4; stroke-linecap: round; }

@media (prefers-reduced-motion: no-preference) {
  /* Per-cycle: the church receives, then the ripple goes out. */
  .rp-core       { animation: rpCore 3.6s ease-in-out infinite; }
  .rp-church     { animation: rpChurch 3.6s ease-in-out infinite; }
  .rp-wave-1     { animation: rpWave 3.6s ease-out infinite; }
  .rp-wave-2     { animation: rpWave 3.6s ease-out infinite; animation-delay: .28s; }
  /* Every phone lights on every cycle... */
  .rp-screen     { animation: rpLit 3.6s ease-out infinite; }
  .rp-glow       { animation: rpHalo 3.6s ease-out infinite; }
  /* ...but only the phone whose turn it is offers the request. */
  .rp-ph         { animation: rpOffer 43.2s ease-in-out infinite;
                    animation-delay: calc(var(--i) * -3.6s); transform-origin: 0 0; }
  .rp-offer      { animation: rpOfferLit 43.2s ease-out infinite;
                    animation-delay: calc(var(--i) * -3.6s); }
  .rp-rider      { animation: rpRide 43.2s cubic-bezier(.34,.05,.30,1) infinite;
                    animation-delay: calc(var(--i) * -3.6s); }
}

/* Within one cycle (3.6s): request 0-0.5s, travel 0.4-1.3s,
   church 1.2-1.8s, ripple 1.5-2.5s, phones 2.0-2.8s, rest. */
@keyframes rpCore {
  0%, 28%   { opacity: .34; transform: scale(1); }
  44%       { opacity: .95; transform: scale(1.14); }
  70%, 100% { opacity: .34; transform: scale(1); }
}
/* Rests at .72 so it has somewhere to bloom TO — opacity above 1 is clamped,
   so the previous `1 -> 1.6` bloom was a no-op. */
@keyframes rpChurch {
  0%, 28%   { opacity: .72; }
  44%       { opacity: 1; }
  70%, 100% { opacity: .72; }
}
@keyframes rpWave {
  0%, 40%   { opacity: 0; transform: scale(.30); }
  48%       { opacity: .60; }
  72%       { opacity: 0; transform: scale(1.06); }
  100%      { opacity: 0; transform: scale(1.06); }
}
@keyframes rpLit {
  0%, 55%   { fill: rgba(237,239,246,.09); }
  62%       { fill: rgba(228,174,79,.90); }
  78%       { fill: rgba(228,174,79,.90); }
  92%, 100% { fill: rgba(237,239,246,.09); }
}
@keyframes rpHalo {
  0%, 55%   { opacity: 0; }
  64%       { opacity: .9; }
  78%       { opacity: .9; }
  94%, 100% { opacity: 0; }
}
/* A phone's turn is ONE cycle inside the 43.2s loop, so every timing below is
   a percentage of the LOOP, not of the cycle — 1s = 2.3%. Writing these by
   hand put the pulse at 1.3-4.8s, i.e. still swollen a whole cycle later. */
@keyframes rpOffer {
  0%             { transform: scale(1) translateY(0); }
  0.7%  { transform: scale(1.22) translateY(-3px); }
  2.5%  { transform: scale(1) translateY(0); }
  100%           { transform: scale(1) translateY(0); }
}
@keyframes rpOfferLit {
  0%             { opacity: 0; }
  0.5%  { opacity: .95; }
  2%  { opacity: .95; }
  3.5%  { opacity: 0; }
  100%           { opacity: 0; }
}
/* Eases out of the phone and decelerates into the church, shrinking slightly as
   it is received — motion with a little weight, rather than a constant slide. */
@keyframes rpRide {
  0%             { opacity: 0; transform: translate(0,0) scale(.5); }
  0.8%  { opacity: 1; transform: translate(0,0) scale(1); }
  3%  { opacity: 1;
                    transform: translate(calc(var(--dx) * 1px), calc(var(--dy) * 1px)) scale(.82); }
  3.7%  { opacity: 0;
                    transform: translate(calc(var(--dx) * 1px), calc(var(--dy) * 1px)) scale(.34); }
  100%           { opacity: 0;
                    transform: translate(calc(var(--dx) * 1px), calc(var(--dy) * 1px)) scale(.34); }
}

/* ── Responsive: film canvas ─────────────────────────── */
/* Above 540px the full 660px canvas is scaled down; below it, the canvas
   narrows to 440px (still wide enough for the two-phone scene: 190+18+190)
   so the phone can go back to near full size instead of shrinking away. */
/* Values solved against  cw * ps <= vw - 52  at the SMALLEST viewport in each
   band (a max-width band's binding case is its lower edge, not the breakpoint
   itself — hand-picked numbers overflowed at 375 and 414). Narrowing the
   canvas at 740 rather than scaling keeps the phone full-size down to 541px.
   Verified overflow-free across 320-1440px. */
@media (max-width: 740px) { :root { --cw: 440px; --ps: 1; } }
@media (max-width: 540px) { :root { --ps: .88; } }
@media (max-width: 440px) { :root { --ps: .79; } }
@media (max-width: 400px) { :root { --ps: .70; } }
@media (max-width: 360px) { :root { --ps: .60; } }

/* ── Reduced motion ──────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .scene { transition: none; }
  /* NOT `animation: none` — every reveal in a scene is a `forwards` animation,
     so switching them off would leave each scene at its EMPTY first frame: no
     typed code, no approved request, no note. Running them instantly instead
     gives the settled picture with no motion at all, which is what reduced
     motion actually asks for. */
  .scene *, .scene *::after, .scene *::before {
    animation-duration: .001s !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
  }
  .scene-cap { opacity: 1; }
  /* openLine ENDS at opacity 0, so collapsing it to .001s would erase the
     sentence entirely for these users. Pin it to the caption slot instead —
     visible for as long as the scene is, with the lights clear above it. */
  .open-line {
    opacity: 1 !important; animation: none !important;
    place-items: end center; padding-bottom: 8px; font-size: 24px;
  }
  .ap, .ap * { transition: none !important; }
}

/* Paused film: freeze every in-scene animation where it stands. */
.stage.is-paused .scene * { animation-play-state: paused !important; }

