/* ─────────────────────────────────────────────────────────────
   1765 Sanctum — App-mode CSS
   Applied ONLY when site is loaded inside the native Capacitor
   shell (detected via userAgent in /assets/app-mode.js).
   Web visitors never see any of these rules.

   DESIGN TOKEN SYSTEM (locked 2026-05-19 from world-class app
   research — see _logs/agent_research/world_class_app_design.md):

   Surface hierarchy is 4 tonal levels (Linear/Day One/Arc pattern),
   NOT a flat single shade. Premium dark mode reads depth through
   tone, not borders.

   Motion is split into two registers: SACRED (400-500ms ease-out-
   quint, used on contemplative routes — Rosary, Examination, Today
   prayer cards) and UTILITY (180ms ease-out, used on settings,
   portal, signin, modal opens). The slowness on sacred routes is
   the calmness signal — Headspace/Calm both clock 400-600ms on
   intentional contemplative transitions.

   Haptic vocabulary is semantic (Apple HIG) — light/medium/heavy
   are physical-impact (tap, scrub-snap), success/warning/error are
   outcome notifications, selection is discrete-step (scrubber,
   picker). Wiring lives in app-mode.js wireHapticCTAs.
   ───────────────────────────────────────────────────────────── */

:root {
  /* Chrome dimensions */
  --app-tab-bar-h: 64px;
  --app-safe-bottom: env(safe-area-inset-bottom, 0px);
  --app-shell-header-h: 42px;

  /* SURFACE HIERARCHY — 4 tonal levels */
  --sanctum-surface-base:    #0A0A0A;  /* page background */
  --sanctum-surface-1:       #141416;  /* elevated cards */
  --sanctum-surface-2:       #1C1C1F;  /* 2nd elevation — sheet contents, hover */
  --sanctum-surface-3:       #25252A;  /* 3rd elevation — modal overlays, popovers */
  --sanctum-surface-overlay: rgba(8, 9, 12, 0.84); /* full-screen backdrops */

  /* Brand palette — locked from CLAUDE.md visual brand-spec */
  --sanctum-gold:        #FFD400;  /* primary accent, active states */
  --sanctum-gold-warm:   #c9a96a;  /* hover, secondary accent */
  --sanctum-bone:        #f5e6c8;  /* primary text on dark */
  --sanctum-bone-soft:   #cfc6b0;  /* body text */
  --sanctum-bone-quiet:  #9a8d6f;  /* muted, captions */
  --sanctum-oxblood:     #6E1B1F;  /* sparingly — refusal, warning */
  --sanctum-line:        rgba(255, 212, 0, 0.16);  /* gold-tinted hairline */
  --sanctum-line-soft:   rgba(245, 230, 200, 0.08); /* bone-tinted hairline */

  /* TYPE SCALE — Cinzel display, Cormorant elevation italic, EB Garamond body.
     Mapped to iOS 26 spec sizes (34/17/15/13/11pt) translated to rem. */
  --type-display:   clamp(28px, 6vw, 34px);    /* hero titles */
  --type-title-l:   clamp(22px, 4.5vw, 26px);  /* section heads */
  --type-title-m:   clamp(18px, 3.8vw, 20px);  /* card titles */
  --type-title-s:   17px;                      /* small titles */
  --type-body-l:    17px;                      /* primary body */
  --type-body-m:    15px;                      /* secondary body */
  --type-body-s:    13px;                      /* captions */
  --type-label:     11px;                      /* tab labels, eyebrows */

  /* MOTION SYSTEM — split into sacred and utility registers */
  --motion-sacred:        500ms;    /* contemplative routes */
  --motion-sacred-fast:   400ms;    /* sacred but interactive */
  --motion-utility:       180ms;    /* settings, portal, snappy CTAs */
  --motion-instant:       120ms;    /* press states, tap-down */
  --ease-sacred:          cubic-bezier(0.22, 1, 0.36, 1);   /* ease-out-quint */
  --ease-utility:         cubic-bezier(0.4, 0, 0.2, 1);     /* Material standard */
  --ease-spring:          cubic-bezier(0.34, 1.56, 0.64, 1); /* sheet snap, slight overshoot */

  /* RADII — corner rounding tokens */
  --radius-pill:    999px;
  --radius-lg:      18px;  /* sheets, dialogs */
  --radius-md:      12px;  /* cards */
  --radius-sm:      8px;   /* inputs, buttons */
  --radius-xs:      4px;   /* chips */

  /* ELEVATION SHADOWS — tonal+shadow combo, not just shadow */
  --elev-1: 0 2px 6px rgba(0, 0, 0, 0.30);
  --elev-2: 0 6px 16px rgba(0, 0, 0, 0.42);
  --elev-3: 0 14px 36px rgba(0, 0, 0, 0.55);
  --elev-glow-gold: 0 0 24px rgba(255, 212, 0, 0.32);

  /* SPACING — 4px-grid scale (Material/iOS standard) */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;
}

/* Hide site chrome that doesn't belong inside an app shell.
   Use bare `footer` (not just footer.footer / .footer) so the
   class-less <footer> on /brotherhood-pass/ and /manifesto/ also
   gets hidden — Will called this out in the 2026-05-19 audit, those
   pages were rendering 366-398px of "Pro Deo et Patria" footer chrome
   inside the app shell. */
body[data-app-mode="1"] .dispatch-nav,
body[data-app-mode="1"] header.dispatch-nav,
body[data-app-mode="1"] footer,
body[data-app-mode="1"] .footer,
body[data-app-mode="1"] footer.footer,
body[data-app-mode="1"] .skip-to-content,
body[data-app-mode="1"] .site-footer {
  display: none !important;
}

/* Reserve space so content never sits under the floating tab bar */
body[data-app-mode="1"] {
  padding-bottom: calc(var(--app-tab-bar-h) + var(--app-safe-bottom)) !important;
  background-color: #08090C !important;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  overscroll-behavior: none;
  -webkit-overflow-scrolling: touch;
}
/* Prevent the html-level overscroll from making the fixed tab-bar
   appear to lift/drop during momentum scrolls on Android WebView */
html:has(body[data-app-mode="1"]) {
  overscroll-behavior: none;
  background-color: #08090C;
}

/* The tab bar itself.
   GPU-accelerated (translateZ + will-change) so Android WebView keeps
   it pinned on scroll momentum instead of letting it jitter or drop.
   contain:layout style isolates the bar from page-reflow side effects.
   Visibility:visible + opacity:1 explicit so the bar can never be hidden
   by an ancestor's fade-out transition during page navigation. */
/* Pray Mode is a full-screen immersive prayer surface - no app chrome over it
   (fixes the rosary advance button being blocked/overlapped by the tab bar). */
body.pray-mode-open .app-tab-bar,
body.pray-mode-open .app-shell-header,
body.pray-mode-open .app-auth-button { display: none !important; }

.app-tab-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 9999;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  height: calc(var(--app-tab-bar-h) + var(--app-safe-bottom));
  padding-bottom: var(--app-safe-bottom);
  /* Surface-1 elevation via tonal+blur+border combo, not just shadow.
     Premium dark mode reads depth through tone (#141416), not via pure
     translucent gradients. Soft hairline gold line + bone-line above. */
  background: linear-gradient(180deg, rgba(20, 20, 22, 0.96) 0%, rgba(10, 10, 10, 1) 100%);
  backdrop-filter: blur(12px) saturate(120%);
  -webkit-backdrop-filter: blur(12px) saturate(120%);
  border-top: 1px solid var(--sanctum-line);
  box-shadow: var(--elev-2);
  font-family: 'Cinzel', 'Cormorant Garamond', Georgia, serif;
  -webkit-user-select: none;
  user-select: none;
  /* GPU pin — kills the scroll-jitter Will reported on builds 5-6 + the
     paint-on-scroll bug Will reported 2026-05-19 ("bottom bar goes away
     when I tap Tools and only reappears when I scroll"). Forcing a new
     compositor layer (translate3d) plus paint containment makes the
     Android WebView paint the bar synchronously on every page load,
     not just on the first scroll event. */
  transform: translate3d(0, 0, 0);
  -webkit-transform: translate3d(0, 0, 0);
  will-change: transform;
  contain: layout paint style;
  /* Belt: never hide via opacity/visibility regardless of cascade */
  visibility: visible !important;
  opacity: 1 !important;
  /* Prevent the bar from being scrolled out by overscroll-bounce */
  touch-action: pan-x pan-y;
}

.app-tab {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  height: var(--app-tab-bar-h);
  padding: 8px 4px;
  color: rgba(245, 230, 200, 0.62);
  text-decoration: none;
  /* Bumped 10px → 11px for legibility on smaller phones — Will called
     out tab bar text was hard to read at 10px Cinzel uppercase. */
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  transition: color 180ms ease, transform 120ms ease;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.app-tab:active {
  transform: scale(0.94);
}

.app-tab[aria-current="page"],
.app-tab.is-active {
  color: #FFD400;
}

/* Active tab now gets a clear gold accent line at the TOP of the tab
   (not just a gold tint on the text). Standard pill/line indicator
   pattern that reads as "you are here" instantly. */
.app-tab[aria-current="page"]::before,
.app-tab.is-active::before {
  content: "";
  position: absolute;
  top: 0;
  left: 30%;
  right: 30%;
  height: 2px;
  background: #FFD400;
  border-radius: 0 0 2px 2px;
  box-shadow: 0 0 8px rgba(255, 212, 0, 0.55);
}

.app-tab[aria-current="page"] .app-tab-icon,
.app-tab.is-active .app-tab-icon {
  filter: drop-shadow(0 0 6px rgba(255, 212, 0, 0.45));
}

.app-tab-icon {
  width: 22px;
  height: 22px;
  display: block;
  pointer-events: none;
  flex-shrink: 0;
}

.app-tab-icon svg {
  width: 100%;
  height: 100%;
  fill: currentColor;
}

.app-tab-label {
  display: block;
  line-height: 1;
}

/* Subtle pull-to-refresh affordance — a thin gold bar that appears at the top
   of the viewport when the user is at scrollTop=0 and pulling down. Handled
   visually only — actual refresh is wired in app-mode.js. Sits BELOW the
   app-shell header so it doesn't overlap the brand mark. */
.app-pull-refresh {
  position: fixed;
  top: calc(max(env(safe-area-inset-top, 0px), 36px) + var(--app-shell-header-h));
  left: 0;
  right: 0;
  height: 0;
  background: linear-gradient(180deg, rgba(255, 212, 0, 0.85) 0%, rgba(255, 212, 0, 0) 100%);
  z-index: 9998;
  transition: height 120ms ease-out, opacity 200ms ease;
  opacity: 0;
  pointer-events: none;
}

.app-pull-refresh.is-pulling {
  opacity: 1;
}

.app-pull-refresh.is-refreshing {
  height: 3px;
  opacity: 1;
  background: #FFD400;
  animation: app-pull-refresh-pulse 900ms ease-in-out infinite;
}

@keyframes app-pull-refresh-pulse {
  0%, 100% { opacity: 0.6; }
  50% { opacity: 1; }
}

/* Status bar safe-area spacer at top of every page (so content doesn't sit
   directly against the OS status bar). Adaptive — env(safe-area-inset-top)
   returns the OS-reported notch/cutout/status-bar height; floor at 36px
   so no-notch devices still get a deliberate dark strip, deep-cutout
   devices (Pixel 8 Pro 38px, iPhone 14 Pro Dynamic Island 47px) get
   their full inset. Sits BEHIND the app-shell header. */
body[data-app-mode="1"]::before {
  content: "";
  position: fixed;
  top: 0; left: 0; right: 0;
  display: block;
  height: max(env(safe-area-inset-top, 0px), 36px);
  background: #08090C;
  z-index: 9998;
  pointer-events: none;
}

/* App-shell header — small Cinzel "1765 ◆ SANCTUM" wordmark, centered,
   sits at the top of every page below the status-bar safe-area inset.
   Tappable; routes home to /today/. Gives the app a consistent brand
   presence so every screen reads as Sanctum, not raw web content. */
:root {
  --app-shell-header-h: 42px;
}
.app-shell-header {
  position: fixed;
  top: max(env(safe-area-inset-top, 0px), 36px);
  left: 0;
  right: 0;
  height: var(--app-shell-header-h);
  z-index: 9997;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  /* Surface-1 elevation matches tab bar; glass register from NN/g
     guidance (Liquid Glass only on chrome, never content). */
  background: linear-gradient(180deg, rgba(20, 20, 22, 0.94) 0%, rgba(14, 14, 16, 0.88) 100%);
  border-bottom: 1px solid var(--sanctum-line);
  -webkit-backdrop-filter: blur(10px) saturate(120%);
  backdrop-filter: blur(10px) saturate(120%);
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
  pointer-events: auto;
}
.app-shell-mark-1765,
.app-shell-mark-sanctum {
  font-family: 'Cinzel', serif;
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.22em;
  color: #FFD400;
}
.app-shell-mark-sanctum {
  color: #f5e6c8;
}
.app-shell-mark-diamond {
  width: 7px;
  height: 7px;
  background: #FFD400;
  transform: rotate(45deg);
  display: inline-block;
  box-shadow: 0 0 6px rgba(255, 212, 0, 0.5);
}

/* Body padding accounts for both the status-bar spacer AND the app-shell
   header so content doesn't sit under either. */
body[data-app-mode="1"] {
  padding-top: calc(max(env(safe-area-inset-top, 0px), 36px) + var(--app-shell-header-h)) !important;
}

/* Sign In button repositioned to sit IN the app-shell header on the right,
   not below it. */
.app-auth-button {
  top: calc(max(env(safe-area-inset-top, 0px), 36px) + 6px) !important;
  height: 30px;
}

/* ─── Sign In / Account button — persistent top-right affordance ──
   The web Sign In nav link lives in .dispatch-nav which app-mode hides.
   Without an explicit affordance, the only path to /portal/ from inside
   the app is to know the URL. Floats top-right on every page (except
   /signin/ and /portal/ themselves). Label flips "Sign In" → "Account"
   + href flips /signin/ → /portal/ when /api/auth/me reports signed in.
   Scroll-aware: hides on scroll-down past 40px, returns on scroll-up,
   so it never permanently occludes title content (Will hit this on
   long pages 2026-05-19). */
.app-auth-button {
  position: fixed;
  top: calc(max(env(safe-area-inset-top, 0px), 36px) + 8px);
  right: 12px;
  z-index: 9999;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px 7px 9px;
  background: rgba(255, 212, 0, 0.10);
  color: #FFD400;
  border: 1px solid rgba(255, 212, 0, 0.42);
  border-radius: 999px;
  font-family: 'Cinzel', serif;
  font-weight: 600;
  font-size: 0.66rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  -webkit-tap-highlight-color: transparent;
  transition: transform 220ms ease, opacity 220ms ease, background 180ms ease;
  /* Sit above the dark spacer + the page content */
  pointer-events: auto;
}
.app-auth-button.is-hidden {
  transform: translateY(-72px);
  opacity: 0;
  pointer-events: none;
}
.app-auth-button:active {
  transform: scale(0.94);
  background: rgba(255, 212, 0, 0.22);
}
.app-auth-button svg {
  width: 14px;
  height: 14px;
  fill: currentColor;
}
.app-auth-label {
  line-height: 1;
}

/* Subtle reading-mode tweaks for long-form content in app shell */
body[data-app-mode="1"] .hero {
  /* hero is full-bleed image; keep it but trim the top padding that
     was sized for the missing top-nav-bar */
  padding-top: 0;
}

/* For sub-pages with a sub-header (dispatch index, brotherhood pass, etc.)
   the existing top padding looks wrong without the nav. Pull it up. */
body[data-app-mode="1"] main,
body[data-app-mode="1"] .page-shell,
body[data-app-mode="1"] .dispatch-shell {
  padding-top: 8px;
}

/* App-mode does not show inline "view in browser" or "share via" hints
   that assume desktop or mobile-web context */
body[data-app-mode="1"] .web-only,
body[data-app-mode="1"] [data-web-only] {
  display: none !important;
}

/* ─── /tools/ page: tile grid in app-mode ────────────────────
   The /tools/ web shelf is prose-heavy (Latin tagline + 2-sentence
   description per card). In an app, that reads like a website — Will
   called this out. Convert each .tool-card to a square-ish tile with
   only the status pill + name + latin tagline visible. Whole tile is
   tappable. Prose + redundant "Open →" link hidden in app-mode. */
body[data-app-mode="1"] .tools-grid {
  display: grid !important;
  grid-template-columns: repeat(2, 1fr) !important;
  gap: 12px !important;
  margin: 12px 0 28px !important;
}
body[data-app-mode="1"] .tools-section-title {
  font-size: 0.74rem !important;
  letter-spacing: 0.24em !important;
  text-transform: uppercase !important;
  margin: 18px 4px 10px !important;
}
body[data-app-mode="1"] .tools-section-divider,
body[data-app-mode="1"] .tools-prose,
body[data-app-mode="1"] .tools-section-prose,
body[data-app-mode="1"] .tools-shelf-prose {
  display: none !important;
}
body[data-app-mode="1"] .tool-card {
  background: #0e1015 !important;
  border: 1px solid rgba(255, 230, 200, 0.12) !important;
  border-radius: 14px !important;
  padding: 18px 16px 16px !important;
  min-height: 150px !important;
  display: flex !important;
  flex-direction: column !important;
  justify-content: space-between !important;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35) !important;
  transition: border-color 200ms ease, transform 120ms ease !important;
}
body[data-app-mode="1"] .tool-card a {
  display: flex !important;
  flex-direction: column !important;
  justify-content: space-between !important;
  height: 100% !important;
  text-decoration: none !important;
  color: inherit !important;
  gap: 8px !important;
}
body[data-app-mode="1"] .tool-card:active {
  transform: scale(0.97);
}
body[data-app-mode="1"] .tool-card.live,
body[data-app-mode="1"] .tool-card.beta {
  border-color: rgba(255, 212, 0, 0.28) !important;
}
body[data-app-mode="1"] .tool-card.coming {
  /* PLANNED tools are not yet shippable — make that unambiguously
     visible. 35% opacity (was 55%), no hover affordance, no tap-scale,
     cursor:default. Will called out 2026-05-19 that PLANNED tiles
     "render at full visual weight" and users tap them expecting tools. */
  opacity: 0.35 !important;
  cursor: default !important;
  pointer-events: none !important;
  border-style: dashed !important;
  border-color: rgba(255, 230, 200, 0.18) !important;
}
body[data-app-mode="1"] .tool-card.coming .tool-status {
  background: rgba(154, 141, 111, 0.16) !important;
  color: #9a8d6f !important;
}
body[data-app-mode="1"] .tool-card.coming:active {
  transform: none !important;
}
body[data-app-mode="1"] .tool-card .tool-status {
  position: static !important;
  display: inline-block !important;
  align-self: flex-start !important;
  background: rgba(255, 212, 0, 0.12) !important;
  color: #FFD400 !important;
  border: 0 !important;
  padding: 4px 10px !important;
  border-radius: 999px !important;
  font-family: 'Cinzel', serif !important;
  font-size: 0.6rem !important;
  letter-spacing: 0.22em !important;
  text-transform: uppercase !important;
  margin-bottom: 4px !important;
}
body[data-app-mode="1"] .tool-card.coming .tool-status {
  background: rgba(255, 230, 200, 0.08) !important;
  color: #9a8d6f !important;
}
body[data-app-mode="1"] .tool-card h2 {
  font-family: 'Cinzel', serif !important;
  font-weight: 600 !important;
  font-size: 1rem !important;
  line-height: 1.22 !important;
  color: #f5e6c8 !important;
  margin: 0 !important;
  letter-spacing: 0.01em !important;
  /* Override the 80px right-padding from the web style (which reserved
     space for the absolutely-positioned BETA pill). In app-mode the pill
     is static-flow above the h2, so the right padding is dead weight.
     Worse: with long single-word titles ("EXAMINATION", "BROTHERHOOD"),
     the h2 min-content + 80px reserve forced grid columns wider than the
     viewport and the right column clipped off-screen. */
  padding-right: 0 !important;
}
/* Belt-and-suspenders: kill horizontal overflow on the page wrapper in
   app-mode so any future content-too-wide bug clips instead of forcing a
   horizontal scroll. */
body[data-app-mode="1"] { overflow-x: hidden !important; }
body[data-app-mode="1"] .tools-section { min-width: 0 !important; }
body[data-app-mode="1"] .tools-section .container { min-width: 0 !important; max-width: 100% !important; }
body[data-app-mode="1"] .tools-grid { min-width: 0 !important; }
body[data-app-mode="1"] .tool-card { min-width: 0 !important; }

/* Lead-magnet preview cards + Beehiiv embed iframes hard-code width: 400px
   for desktop. On a 375px-wide phone they push the viewport ~97px wider
   than it should be, which is what actually caused the right-column-clip
   on the /tools/ page in the Sanctum app screenshot. Constrain all
   magnet + embed surfaces to viewport width in app-mode. */
body[data-app-mode="1"] .examen-magnet-preview,
body[data-app-mode="1"] .examen-magnet-body,
body[data-app-mode="1"] .beehiiv-embed-frame,
body[data-app-mode="1"] .beehiiv-embed,
body[data-app-mode="1"] .rule-of-life-magnet,
body[data-app-mode="1"] .magnet-eyebrow,
body[data-app-mode="1"] .magnet-lede,
body[data-app-mode="1"] .magnet-deal,
body[data-app-mode="1"] .magnet-finepoint {
  max-width: 100% !important;
  width: 100% !important;
  box-sizing: border-box !important;
}
/* Universal media safety net — any <img> or <iframe> with a fixed pixel
   width in source is constrained to its parent's width in app-mode. The
   intrinsic aspect ratio is preserved via auto height. */
body[data-app-mode="1"] img,
body[data-app-mode="1"] iframe {
  max-width: 100% !important;
  height: auto;
}
body[data-app-mode="1"] .tool-card .tool-latin {
  font-family: 'Cormorant Garamond', serif !important;
  font-style: italic !important;
  font-size: 0.86rem !important;
  color: #c9a96a !important;
  margin: 0 !important;
  line-height: 1.3 !important;
}
body[data-app-mode="1"] .tool-card p:not(.tool-latin),
body[data-app-mode="1"] .tool-card .tool-link {
  display: none !important;
}
/* Brotherhood-pass callout on /tools/ keeps prose since it's the
   conversion CTA — but tighten its margins */
body[data-app-mode="1"] .brotherhood-callout {
  margin: 16px 0 28px !important;
}

/* ─── /brotherhood-pass/ page: pull the Founding apply-now CTA up to
   the top of the screen in app-mode so it's not buried below a long
   marketing scroll */
body[data-app-mode="1"] .bp-app-cta {
  display: block !important;
}

/* ════════════════════════════════════════════════════════════════
   ── WAVE 2: HERO COMPRESSION + DENSE APP-MODE LAYOUTS ──────────
   Will (2026-05-19): /brotherhood-pass/ was 19.9 screens tall in the
   app; /manifesto/ was 22.1 screens. App-mode now KILLS the long-
   form marketing heroes and surfaces the actionable content first.
   Web visitors are unaffected (none of this fires outside app-mode).
   ════════════════════════════════════════════════════════════════ */

/* /brotherhood-pass/ — was 19.9 screens; target ~3 screens.
   Strategy: hide the full-viewport .threshold V2 hero, hide the long
   marketing prose sections after the CTA strip, keep only the
   conversion-critical content (price + 4 tools + subscribe form +
   Founding 15 + manage subscription footer). */
body[data-app-mode="1"].bp-v2-page .threshold { display: none !important; }
body[data-app-mode="1"].bp-v2-page section.bp-status-strip {
  padding: 20px 16px 24px !important;
  margin-top: 0 !important;
}
/* Hide deep-dive marketing sections — "Why $8.99", "What you get inside",
   the long prose blocks. App users tap "Subscribe" or "Apply for the 15"
   from the strip; they don't need 19 screens of marketing to decide. */
body[data-app-mode="1"].bp-v2-page section:not(.bp-status-strip):not(.fifteen):not(.bp-app-cta):not(#fifteen) {
  display: none !important;
}
/* Keep the Founding 15 application card visible (the second CTA) and
   tighten its padding. */
body[data-app-mode="1"].bp-v2-page #fifteen,
body[data-app-mode="1"].bp-v2-page section.fifteen {
  display: block !important;
  padding: 24px 16px 32px !important;
}
body[data-app-mode="1"].bp-v2-page #fifteen h2,
body[data-app-mode="1"].bp-v2-page section.fifteen h2 {
  font-size: 1.4rem !important;
  margin: 0 0 12px !important;
}

/* /manifesto/ — was 22.1 screens. Manifesto IS the content (it can't
   be hidden the way brotherhood-pass marketing can), but the web
   layout has massive vertical padding between sections that bloats
   the page. Tighten and let it read as a tappable essay. */
body[data-app-mode="1"] .manifesto-page section,
body[data-app-mode="1"] main.manifesto section,
body[data-app-mode="1"] .manifesto-section {
  padding-top: 24px !important;
  padding-bottom: 24px !important;
}
body[data-app-mode="1"] .manifesto-hero,
body[data-app-mode="1"] .manifesto-page > header,
body[data-app-mode="1"] main.manifesto > header {
  padding: 20px 20px 16px !important;
  min-height: auto !important;
}
body[data-app-mode="1"] .manifesto-hero h1,
body[data-app-mode="1"] .manifesto-page h1 {
  font-size: clamp(1.6rem, 6vw, 2.2rem) !important;
  margin: 0 0 8px !important;
}

/* /tools/ — was 6.4 screens. Web hero is a full screen of tagline +
   subtitle + lede paragraph before the user sees the first tool. App
   users open this tab to access tools. Compress hero + lede so the
   first tool tile is visible without scrolling. */
body[data-app-mode="1"] .tools-hero {
  padding: 16px 20px 8px !important;
  text-align: left !important;
}
body[data-app-mode="1"] .tools-hero h1 {
  font-size: 1.5rem !important;
  margin: 4px 0 6px !important;
  line-height: 1.18 !important;
}
body[data-app-mode="1"] .tools-hero h1 br { display: none !important; }
body[data-app-mode="1"] .tools-hero h1 em { display: inline !important; margin-left: 6px; }
body[data-app-mode="1"] .tools-hero p.subtitle {
  font-size: 1rem !important;
  margin: 0 0 4px !important;
  line-height: 1.45 !important;
}
body[data-app-mode="1"] .tools-hero p.latin-cite {
  font-size: 0.7rem !important;
  letter-spacing: 0.22em !important;
  margin: 0 0 2px !important;
}
body[data-app-mode="1"] .tools-hero .section-flourish { display: none !important; }
body[data-app-mode="1"] .tools-section .lede {
  font-size: 0.96rem !important;
  margin: 8px 0 18px !important;
  line-height: 1.55 !important;
  /* Truncate to first 2 lines with native CSS line-clamp; tap to expand
     could be added in Wave 3 — for now just show less. */
  display: -webkit-box !important;
  -webkit-line-clamp: 3 !important;
  -webkit-box-orient: vertical !important;
  overflow: hidden !important;
}
body[data-app-mode="1"] .tools-section { padding: 12px !important; }
body[data-app-mode="1"] .tools-section-header {
  margin-bottom: 12px !important;
}
body[data-app-mode="1"] .tools-section-eyebrow {
  font-size: 0.7rem !important;
  letter-spacing: 0.22em !important;
  margin: 0 0 4px !important;
}
body[data-app-mode="1"] .tools-section-title {
  font-size: 1.2rem !important;
  margin: 0 0 6px !important;
}
body[data-app-mode="1"] .tools-section-intro {
  font-size: 0.92rem !important;
  line-height: 1.5 !important;
  margin: 0 0 12px !important;
}

/* /dispatch/ — was 3.3 screens. Compress the hero so the Archive
   (the actual content users came for) is closer to the top. */
body[data-app-mode="1"] .dispatch-list-hero {
  padding: 16px 20px 20px !important;
}
body[data-app-mode="1"] .dispatch-list-title {
  font-size: clamp(1.6rem, 5vw, 2rem) !important;
  margin: 6px 0 8px !important;
}
body[data-app-mode="1"] .dispatch-list-tagline {
  font-size: 0.98rem !important;
  margin: 0 0 8px !important;
}
body[data-app-mode="1"] .dispatch-list-body {
  font-size: 0.95rem !important;
  margin: 0 0 14px !important;
  line-height: 1.55 !important;
}
body[data-app-mode="1"] .dispatch-list-section {
  padding: 16px 0 32px !important;
}
body[data-app-mode="1"] .dispatch-list-eyebrow {
  font-size: 0.72rem !important;
  letter-spacing: 0.22em !important;
  margin: 0 0 8px !important;
  padding: 0 20px;
}

/* /today/ — give it an app-specific brand header bar so the page
   doesn't feel like raw H1 content under the status bar spacer.
   Subtle Cinzel "1765 SANCTUM" wordmark, gold dot, centered, sits
   between the spacer and the page content. */
body[data-app-mode="1"]::after {
  /* No-op pseudo — would mount a header here but ::after on body
     would render at body END, not start. Instead handled by JS in
     app-mode.js via injectAppHeader. Reserving the rule comment. */
}

/* /signin/ — app-mode wants a full-bleed form, not a centered card */
body[data-app-mode="1"] .auth-shell {
  min-height: auto !important;
  padding: 24px 20px !important;
  align-items: flex-start !important;
}
body[data-app-mode="1"] .auth-card {
  max-width: 100% !important;
  width: 100% !important;
  background: transparent !important;
  border: 0 !important;
  padding: 16px 0 !important;
}
body[data-app-mode="1"] .auth-title {
  font-size: 1.8rem !important;
  margin: 0 0 12px !important;
}
body[data-app-mode="1"] .auth-lede {
  font-size: 1.05rem !important;
  margin: 0 0 24px !important;
}
body[data-app-mode="1"] .auth-form input[type="email"],
body[data-app-mode="1"] .auth-form input[type="password"] {
  padding: 16px 16px !important;
  font-size: 1.08rem !important;
}
body[data-app-mode="1"] .auth-form button {
  padding: 16px 24px !important;
  font-size: 0.88rem !important;
}

/* /portal/ — compress the giant hero header into an app-feel banner */
body[data-app-mode="1"] .portal-eyebrow {
  font-size: 0.72rem !important;
  letter-spacing: 0.22em !important;
  margin: 0 0 8px !important;
}
body[data-app-mode="1"] .portal-title {
  font-size: 1.7rem !important;
  margin: 0 0 12px !important;
}
body[data-app-mode="1"] .portal-lede {
  font-size: 1.02rem !important;
  margin: 0 0 18px !important;
}
body[data-app-mode="1"] .portal-card {
  padding: 18px 16px !important;
  margin-bottom: 14px !important;
}
body[data-app-mode="1"] main.portal,
body[data-app-mode="1"] .portal-page {
  padding: 16px 16px 32px !important;
}

/* ────────────────────────────────────────────────────────────────
   ── WAVE 3: MORE BOTTOM SHEET + PORTAL APP DASHBOARD ──────────
   ──────────────────────────────────────────────────────────── */

.app-more-backdrop {
  position: fixed;
  inset: 0;
  z-index: 10000;
  background: rgba(0, 0, 0, 0.62);
  opacity: 0;
  transition: opacity 240ms ease;
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}
.app-more-backdrop.is-open {
  opacity: 1;
}
.app-more-sheet {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 10001;
  /* Surface-2: 2nd elevation tone for sheet content (per Linear/Day
     One pattern). Reads as elevated above the surface-1 tab bar. */
  background: var(--sanctum-surface-2);
  border-top-left-radius: var(--radius-lg);
  border-top-right-radius: var(--radius-lg);
  border-top: 1px solid var(--sanctum-line);
  padding: 10px 0 calc(var(--app-safe-bottom) + 20px);
  max-height: 78vh;
  max-height: 78svh;
  display: flex;
  flex-direction: column;
  transform: translateY(100%);
  /* Spring physics with slight overshoot — matches Material 3
     Expressive spring motion system + iOS sheet snap feel. */
  transition: transform var(--motion-sacred-fast) var(--ease-spring);
  box-shadow: var(--elev-3);
}
.app-more-sheet.is-open {
  transform: translateY(0);
}
.app-more-handle {
  width: 38px;
  height: 4px;
  background: rgba(245, 230, 200, 0.22);
  border-radius: 2px;
  margin: 6px auto 12px;
  flex-shrink: 0;
}
.app-more-title {
  font-family: 'Cinzel', serif;
  font-weight: 600;
  font-size: 0.86rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #FFD400;
  text-align: center;
  margin: 0 0 14px;
  flex-shrink: 0;
}
.app-more-scroll {
  overflow-y: auto;
  padding: 0 16px;
  -webkit-overflow-scrolling: touch;
  flex: 1;
}
.app-more-group {
  margin-bottom: 22px;
}
.app-more-group-label {
  font-family: 'Cinzel', serif;
  font-size: 0.7rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #9a8d6f;
  margin: 0 0 10px;
  padding: 0 4px;
}
.app-more-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 14px;
  /* Surface-3: items sit one level above the sheet's surface-2 */
  background: var(--sanctum-surface-3);
  border: 1px solid var(--sanctum-line-soft);
  border-radius: var(--radius-md);
  text-decoration: none;
  color: var(--sanctum-bone);
  margin-bottom: var(--space-2);
  transition: background var(--motion-utility) var(--ease-utility),
              transform var(--motion-instant) var(--ease-utility);
  -webkit-tap-highlight-color: transparent;
}
.app-more-item:active {
  transform: scale(0.98);
  background: rgba(255, 212, 0, 0.08);
}
.app-more-item-label {
  font-family: 'Cinzel', serif;
  font-weight: 600;
  font-size: 0.92rem;
  letter-spacing: 0.04em;
  flex-shrink: 0;
  flex-grow: 0;
}
.app-more-item-desc {
  font-family: 'Cormorant Garamond', serif;
  font-style: italic;
  font-size: 0.88rem;
  color: #9a8d6f;
  flex-grow: 1;
  margin-left: 8px;
  line-height: 1.3;
}
.app-more-item-chevron {
  width: 16px;
  height: 16px;
  color: #c9a96a;
  flex-shrink: 0;
}
.app-more-close {
  margin: 14px 16px 0;
  background: transparent;
  border: 1px solid rgba(245, 230, 200, 0.16);
  color: #cfc6b0;
  font-family: 'Cinzel', serif;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-size: 0.78rem;
  padding: 12px;
  border-radius: 999px;
  cursor: pointer;
  flex-shrink: 0;
  -webkit-tap-highlight-color: transparent;
}
.app-more-close:active {
  background: rgba(245, 230, 200, 0.06);
}

/* ── Portal app-mode quick-access tiles ─────────────────────
   Injected by app-mode.js when user lands on /portal/ signed-in.
   4 paid-tool tiles + 7 free-essentials chip strip + recent activity. */
.app-portal-tiles {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 4px 0 18px;
}
.app-portal-tile {
  background: #0e1015;
  border: 1px solid rgba(255, 212, 0, 0.28);
  border-radius: 12px;
  padding: 14px 12px 12px;
  text-decoration: none;
  color: #f5e6c8;
  display: flex;
  flex-direction: column;
  min-height: 110px;
  transition: border-color 180ms ease, transform 120ms ease;
  -webkit-tap-highlight-color: transparent;
}
.app-portal-tile:active {
  transform: scale(0.97);
  border-color: #FFD400;
}
.app-portal-tile-eyebrow {
  font-family: 'Cinzel', serif;
  font-size: 0.6rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #FFD400;
  margin: 0 0 6px;
}
.app-portal-tile-title {
  font-family: 'Cinzel', serif;
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: 0.04em;
  margin: 0 0 4px;
  line-height: 1.2;
}
.app-portal-tile-desc {
  font-family: 'Cormorant Garamond', serif;
  font-style: italic;
  color: #9a8d6f;
  font-size: 0.84rem;
  margin: 0;
  line-height: 1.3;
}
.app-portal-section-label {
  font-family: 'Cinzel', serif;
  font-size: 0.72rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #c9a96a;
  margin: 18px 0 10px;
}
.app-portal-free-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0 0 18px;
}
.app-portal-free-chip {
  background: rgba(154, 141, 111, 0.12);
  border: 1px solid rgba(154, 141, 111, 0.28);
  color: #f5e6c8;
  font-family: 'Cinzel', serif;
  font-size: 0.7rem;
  letter-spacing: 0.10em;
  padding: 7px 11px;
  border-radius: 999px;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
.app-portal-free-chip:active {
  background: rgba(154, 141, 111, 0.22);
}

/* /signin/ + /portal/ bottom safe-area — make sure forms aren't
   under the OS gesture pill or the app tab bar. */
body[data-app-mode="1"] main.auth-shell,
body[data-app-mode="1"] main.portal,
body[data-app-mode="1"] .portal-page,
body[data-app-mode="1"] .auth-shell {
  padding-bottom: calc(var(--app-tab-bar-h) + var(--app-safe-bottom) + 24px) !important;
}

/* ────────────────────────────────────────────────────────────────
   ── WAVE 4: PAGE TRANSITIONS + LOADING BAR + GESTURES ─────────
   ──────────────────────────────────────────────────────────── */

/* Page-leave fade with split motion register (Wave 7, world-class research):
   - SACRED routes (Today, Rosary, Examination, Consecrations, Sed Contra,
     Manifesto, Dispatch entries) get 500ms ease-out-quint — the slowness
     IS the calmness signal. Headspace/Calm clock 400-600ms intentionally.
   - UTILITY routes (Portal, Signin, Brotherhood marketing, Tools shelf,
     FAQs, Support, About) get 180ms — productivity feel.

   Only main content fades; fixed chrome (header, tab bar, sign-in,
   loading bar) persists through transitions.

   Body class .sacred-route is set by app-mode.js on path match. */
body[data-app-mode="1"] > main,
body[data-app-mode="1"] > section,
body[data-app-mode="1"] > div:not(.app-shell-header):not(.app-tab-bar):not(.app-auth-button):not(.app-loading-bar):not(.app-pull-refresh):not(.app-more-sheet):not(.app-more-backdrop) {
  transition: opacity var(--motion-utility) var(--ease-utility),
              transform var(--motion-utility) var(--ease-utility);
}
body[data-app-mode="1"].sacred-route > main,
body[data-app-mode="1"].sacred-route > section,
body[data-app-mode="1"].sacred-route > div:not(.app-shell-header):not(.app-tab-bar):not(.app-auth-button):not(.app-loading-bar):not(.app-pull-refresh):not(.app-more-sheet):not(.app-more-backdrop) {
  transition: opacity var(--motion-sacred) var(--ease-sacred),
              transform var(--motion-sacred) var(--ease-sacred);
}
body[data-app-mode="1"].app-page-leaving > main,
body[data-app-mode="1"].app-page-leaving > section,
body[data-app-mode="1"].app-page-leaving > div:not(.app-shell-header):not(.app-tab-bar):not(.app-auth-button):not(.app-loading-bar):not(.app-pull-refresh):not(.app-more-sheet):not(.app-more-backdrop) {
  opacity: 0;
  transform: translateY(6px);
}
body[data-app-mode="1"].sacred-route.app-page-leaving > main,
body[data-app-mode="1"].sacred-route.app-page-leaving > section,
body[data-app-mode="1"].sacred-route.app-page-leaving > div:not(.app-shell-header):not(.app-tab-bar):not(.app-auth-button):not(.app-loading-bar):not(.app-pull-refresh):not(.app-more-sheet):not(.app-more-backdrop) {
  opacity: 0;
  transform: translateY(12px);
}

/* Loading bar — thin gold progress bar at the top of the viewport
   during page navigation. Animates 0% → 70% over 600ms, then to 100%
   when nav completes. Standard mobile pattern. */
.app-loading-bar {
  position: fixed;
  top: max(env(safe-area-inset-top, 0px), 36px);
  left: 0;
  right: 0;
  height: 0;
  background: #FFD400;
  z-index: 10002;
  pointer-events: none;
  transform-origin: left center;
  transform: scaleX(0);
  opacity: 0;
}
.app-loading-bar.is-loading {
  height: 2px;
  opacity: 1;
  animation: app-loading-progress 0.7s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
.app-loading-bar.is-done {
  transform: scaleX(1);
  opacity: 0;
  transition: transform 200ms ease-out, opacity 300ms ease-out 100ms;
}
@keyframes app-loading-progress {
  0%   { transform: scaleX(0); }
  20%  { transform: scaleX(0.15); }
  50%  { transform: scaleX(0.45); }
  80%  { transform: scaleX(0.65); }
  100% { transform: scaleX(0.72); }
}

/* ────────────────────────────────────────────────────────────────
   ── WAVE 10: GENERIC SHEET API + STATE-OF-THE-FIGHT CHECK-IN ──
   Sanctum-only differentiation move Hallow STRUCTURALLY can't ship.
   ──────────────────────────────────────────────────────────── */

/* Generic sheet (reusable for State-of-Fight, future intention
   setting, prayer settings, streak repair). Spring physics, pull-
   down dismiss handle, surface-2 content. */
.app-sheet-backdrop {
  position: fixed; inset: 0;
  z-index: 10000;
  background: var(--sanctum-surface-overlay);
  opacity: 0;
  transition: opacity var(--motion-sacred-fast) var(--ease-utility);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}
.app-sheet-backdrop.is-open { opacity: 1; }
.app-sheet {
  position: fixed; left: 0; right: 0; bottom: 0;
  z-index: 10001;
  background: var(--sanctum-surface-2);
  border-top-left-radius: var(--radius-lg);
  border-top-right-radius: var(--radius-lg);
  border-top: 1px solid var(--sanctum-line);
  padding: 10px 0 calc(var(--app-safe-bottom) + 20px);
  max-height: 78vh;
  max-height: 78svh;
  display: flex;
  flex-direction: column;
  transform: translateY(100%);
  transition: transform var(--motion-sacred-fast) var(--ease-spring);
  box-shadow: var(--elev-3);
}
.app-sheet.is-open { transform: translateY(0); }
.app-sheet-handle {
  width: 38px; height: 4px;
  background: rgba(245, 230, 200, 0.22);
  border-radius: 2px;
  margin: 6px auto 12px;
  flex-shrink: 0;
  touch-action: none;
  cursor: grab;
}
.app-sheet-title {
  font-family: 'Cinzel', serif;
  font-weight: 600;
  font-size: 0.86rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--sanctum-gold);
  text-align: center;
  margin: 0 0 14px;
  flex-shrink: 0;
}
.app-sheet-body {
  flex: 1;
  overflow-y: auto;
  padding: 0 20px;
  -webkit-overflow-scrolling: touch;
}
.app-sheet-close {
  margin: 14px 20px 0;
  background: transparent;
  border: 1px solid var(--sanctum-line-soft);
  color: var(--sanctum-bone-soft);
  font-family: 'Cinzel', serif;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-size: 0.78rem;
  padding: 12px;
  border-radius: var(--radius-pill);
  cursor: pointer;
  flex-shrink: 0;
  -webkit-tap-highlight-color: transparent;
}
.app-sheet-close:active { background: rgba(245, 230, 200, 0.06); }

/* State-of-Fight specific styling */
.app-sof-progress {
  font-family: 'Cinzel', serif;
  font-size: 0.7rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--sanctum-gold-warm);
  margin: 8px 0 14px;
  text-align: center;
}
.app-sof-title {
  font-family: 'Cinzel', serif;
  font-weight: 600;
  font-size: clamp(1.3rem, 5vw, 1.6rem);
  color: var(--sanctum-bone);
  margin: 0 0 8px;
  text-align: center;
  line-height: 1.22;
}
.app-sof-sub {
  font-family: 'Cormorant Garamond', serif;
  font-style: italic;
  font-size: 1rem;
  color: var(--sanctum-bone-soft);
  margin: 0 0 22px;
  text-align: center;
}
.app-sof-options {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.app-sof-options.is-three {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 8px;
}
.app-sof-option {
  background: var(--sanctum-surface-3);
  border: 1px solid var(--sanctum-line-soft);
  color: var(--sanctum-bone);
  font-family: 'Cinzel', serif;
  font-weight: 600;
  font-size: 0.94rem;
  letter-spacing: 0.06em;
  padding: 14px 14px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: all var(--motion-utility) var(--ease-utility);
}
.app-sof-options.is-three .app-sof-option {
  padding: 16px 4px;
  font-size: 0.86rem;
}
.app-sof-option:active { transform: scale(0.96); }
.app-sof-option.is-gold {
  background: rgba(255, 212, 0, 0.08);
  border-color: rgba(255, 212, 0, 0.32);
  color: var(--sanctum-gold);
}
.app-sof-option.is-warm {
  background: rgba(201, 169, 106, 0.08);
  border-color: rgba(201, 169, 106, 0.32);
  color: var(--sanctum-gold-warm);
}
.app-sof-option.is-oxblood {
  background: rgba(110, 27, 31, 0.16);
  border-color: rgba(110, 27, 31, 0.5);
  color: #e5908a;
}
.app-sof-option.is-chosen {
  background: rgba(255, 212, 0, 0.18);
  border-color: var(--sanctum-gold);
  color: var(--sanctum-gold);
  transform: scale(1.02);
}
.app-sof-rx {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--sanctum-surface-3);
  border: 1px solid rgba(255, 212, 0, 0.32);
  border-radius: var(--radius-md);
  padding: 16px 18px;
  text-decoration: none;
  color: var(--sanctum-bone);
  margin-top: 20px;
  box-shadow: var(--elev-1);
  -webkit-tap-highlight-color: transparent;
}
.app-sof-rx:active { transform: scale(0.98); }
.app-sof-rx-eyebrow {
  display: block;
  font-family: 'Cinzel', serif;
  font-size: 0.66rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--sanctum-gold);
  margin-bottom: 4px;
}
.app-sof-rx-title {
  flex: 1;
  font-family: 'Cinzel', serif;
  font-weight: 600;
  font-size: 0.98rem;
  letter-spacing: 0.02em;
}
.app-sof-rx svg { color: var(--sanctum-gold); flex-shrink: 0; }

/* "Log the Fight" CTA on /today/ hero (secondary button below
   primary CTA — entry point to State-of-Fight sheet). */
.app-today-hero-secondary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
  background: transparent;
  border: 1px solid rgba(255, 212, 0, 0.32);
  color: var(--sanctum-gold-warm);
  font-family: 'Cinzel', serif;
  font-weight: 600;
  font-size: 0.74rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 10px 16px;
  border-radius: var(--radius-pill);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background var(--motion-utility) var(--ease-utility),
              transform var(--motion-instant) var(--ease-utility);
}
.app-today-hero-secondary:active {
  transform: scale(0.96);
  background: rgba(255, 212, 0, 0.08);
}

/* ────────────────────────────────────────────────────────────────
   ── WAVE 9: 5-QUESTION ONBOARDING (full-screen first-launch) ───
   ──────────────────────────────────────────────────────────── */

body.app-onboarding-open {
  overflow: hidden !important;
}
.app-onboarding {
  position: fixed;
  inset: 0;
  z-index: 10100;
  background:
    radial-gradient(ellipse at top, rgba(255, 212, 0, 0.06) 0%, rgba(8, 9, 12, 0) 50%),
    var(--sanctum-surface-base);
  display: flex;
  align-items: stretch;
  justify-content: center;
  opacity: 0;
  transition: opacity var(--motion-sacred-fast) var(--ease-sacred);
}
.app-onboarding.is-open { opacity: 1; }
.app-onboarding-shell {
  width: 100%;
  max-width: 480px;
  padding: max(env(safe-area-inset-top, 0px), 36px) 24px calc(var(--app-safe-bottom) + 24px);
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.app-onboarding-progress {
  display: flex;
  gap: 6px;
  justify-content: center;
  padding: 12px 0;
}
.app-onboarding-dot {
  width: 30px;
  height: 3px;
  background: var(--sanctum-line-soft);
  border-radius: 2px;
  transition: background var(--motion-utility) var(--ease-utility);
}
.app-onboarding-dot.is-done { background: var(--sanctum-gold-warm); }
.app-onboarding-dot.is-active {
  background: var(--sanctum-gold);
  box-shadow: 0 0 8px rgba(255, 212, 0, 0.55);
}
.app-onboarding-step {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 24px 0;
  animation: app-onboarding-in var(--motion-sacred-fast) var(--ease-sacred);
}
@keyframes app-onboarding-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
.app-onboarding-eyebrow {
  font-family: 'Cinzel', serif;
  font-weight: 500;
  font-size: 0.7rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--sanctum-gold);
  margin: 0 0 16px;
  text-align: center;
}
.app-onboarding-title {
  font-family: 'Cinzel', serif;
  font-weight: 600;
  font-size: clamp(1.6rem, 5.5vw, 2rem);
  color: var(--sanctum-bone);
  margin: 0 0 12px;
  text-align: center;
  line-height: 1.2;
  letter-spacing: 0.01em;
}
.app-onboarding-sub {
  font-family: 'Cormorant Garamond', serif;
  font-style: italic;
  font-size: 1.04rem;
  color: var(--sanctum-bone-soft);
  margin: 0 0 24px;
  text-align: center;
  line-height: 1.5;
}
.app-onboarding-options {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.app-onboarding-option {
  background: var(--sanctum-surface-1);
  border: 1px solid var(--sanctum-line-soft);
  color: var(--sanctum-bone);
  font-family: 'Cinzel', serif;
  font-weight: 500;
  font-size: 0.96rem;
  letter-spacing: 0.04em;
  padding: 16px 18px;
  border-radius: var(--radius-md);
  cursor: pointer;
  text-align: left;
  -webkit-tap-highlight-color: transparent;
  transition: all var(--motion-utility) var(--ease-utility);
}
.app-onboarding-option:active {
  transform: scale(0.98);
  background: var(--sanctum-surface-2);
}
.app-onboarding-option.is-chosen {
  background: rgba(255, 212, 0, 0.12);
  border-color: var(--sanctum-gold);
  color: var(--sanctum-gold);
}
.app-onboarding-loading {
  display: flex;
  justify-content: center;
  gap: 6px;
  margin-top: 24px;
}
.app-onboarding-loading span {
  width: 8px; height: 8px;
  background: var(--sanctum-gold);
  border-radius: 50%;
  animation: app-onboarding-pulse 1.2s ease-in-out infinite;
}
.app-onboarding-loading span:nth-child(2) { animation-delay: 0.15s; }
.app-onboarding-loading span:nth-child(3) { animation-delay: 0.30s; }
@keyframes app-onboarding-pulse {
  0%, 100% { opacity: 0.3; transform: scale(0.8); }
  50%      { opacity: 1;   transform: scale(1.2); }
}
.app-onboarding-err {
  text-align: center;
  color: #c87f7f;
  font-family: 'EB Garamond', serif;
  margin-top: 16px;
}

/* ────────────────────────────────────────────────────────────────
   ── WAVE 8: /TODAY/ DOMINANT HERO CARD + STREAK COUNTER ───────
   The single most important screen in the app. World-class
   research (Hallow Home, Calm "Daily Calm," Headspace "Today
   Recommended," Duolingo daily quest, Strava training calendar)
   all share a SINGLE DOMINANT hero card pattern. /today/ used to
   show 7+ competing CTAs; this card decides ONE thing to do RIGHT
   NOW based on day-of-week + liturgical season.
   ──────────────────────────────────────────────────────────── */

.app-today-hero {
  position: relative;
  background:
    radial-gradient(ellipse at top left, rgba(255, 212, 0, 0.10) 0%, rgba(255, 212, 0, 0) 60%),
    var(--sanctum-surface-1);
  border: 1px solid rgba(255, 212, 0, 0.36);
  border-radius: var(--radius-lg);
  padding: 20px 22px 22px;
  margin: 12px 16px 18px;
  box-shadow: var(--elev-2), var(--elev-glow-gold);
  overflow: hidden;
}
.app-today-hero::before {
  /* Subtle inner halo — depth without busyness */
  content: "";
  position: absolute;
  top: -40px; right: -40px;
  width: 140px; height: 140px;
  background: radial-gradient(circle, rgba(255, 212, 0, 0.22) 0%, transparent 70%);
  pointer-events: none;
}
.app-today-hero-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}
.app-today-hero-eyebrow {
  font-family: 'Cinzel', serif;
  font-weight: 600;
  font-size: 0.72rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--sanctum-gold);
  margin: 0;
}
.app-today-streak {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 11px 5px 9px;
  background: rgba(255, 212, 0, 0.10);
  border: 1px solid rgba(255, 212, 0, 0.32);
  border-radius: var(--radius-pill);
  color: var(--sanctum-gold-warm);
  font-family: 'Cinzel', serif;
  font-weight: 700;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  transition: all var(--motion-utility) var(--ease-utility);
}
.app-today-streak.is-burning {
  color: var(--sanctum-gold);
  border-color: rgba(255, 212, 0, 0.55);
  background: rgba(255, 212, 0, 0.16);
}
.app-today-streak.is-roaring {
  color: #FFE15B;
  border-color: rgba(255, 212, 0, 0.80);
  background: rgba(255, 212, 0, 0.22);
  box-shadow: 0 0 12px rgba(255, 212, 0, 0.30);
}
.app-today-streak-flame { display: inline-flex; }
.app-today-hero-title {
  font-family: 'Cinzel', serif;
  font-weight: 600;
  font-size: clamp(1.6rem, 6vw, 2rem);
  color: var(--sanctum-bone);
  margin: 0 0 10px;
  letter-spacing: 0.01em;
  line-height: 1.18;
}
.app-today-hero-sub {
  font-family: 'Cormorant Garamond', serif;
  font-style: italic;
  font-size: 1.04rem;
  color: var(--sanctum-bone-soft);
  margin: 0 0 18px;
  line-height: 1.46;
}
.app-today-hero-cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--sanctum-gold);
  color: #0A0A0A;
  font-family: 'Cinzel', serif;
  font-weight: 700;
  font-size: 0.86rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 13px 22px;
  border-radius: var(--radius-sm);
  text-decoration: none;
  box-shadow: var(--elev-1);
  transition: transform var(--motion-instant) var(--ease-utility),
              box-shadow var(--motion-utility) var(--ease-utility);
  -webkit-tap-highlight-color: transparent;
}
.app-today-hero-cta:active {
  transform: scale(0.96);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.40);
}
.app-today-hero-cta svg { color: #0A0A0A; }

/* Demote the existing /today/ cards to secondary — the hero is the
   primary surface now. Keep them visible but visually quieter so
   they read as "more for today" not as competing primary actions. */
body[data-app-mode="1"] .today-shell .today-action {
  background: var(--sanctum-surface-1) !important;
  border-color: var(--sanctum-line-soft) !important;
  box-shadow: none !important;
}
body[data-app-mode="1"] .today-shell .today-action-title {
  font-size: 1.15rem !important;
}

/* ────────────────────────────────────────────────────────────────
   ── WAVE 5: NATIVE BEEHIIV FORM (replaces iframe in app-mode) ──
   ──────────────────────────────────────────────────────────── */

.app-bhv-native {
  margin: 14px 0;
  width: 100%;
  max-width: 100%;
}
.app-bhv-form {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
}
.app-bhv-form input[type="email"] {
  background: #0e1015;
  border: 1px solid rgba(255, 212, 0, 0.32);
  color: #f5e6c8;
  font-family: 'EB Garamond', serif;
  font-size: 1.04rem;
  padding: 15px 16px;
  border-radius: 8px;
  outline: none;
  width: 100%;
  box-sizing: border-box;
  -webkit-appearance: none;
  appearance: none;
}
.app-bhv-form input[type="email"]:focus {
  border-color: #FFD400;
  box-shadow: 0 0 0 3px rgba(255, 212, 0, 0.16);
}
.app-bhv-form button {
  background: #FFD400;
  color: #0a0b0f;
  border: 0;
  padding: 15px 24px;
  font-family: 'Cinzel', serif;
  font-weight: 700;
  font-size: 0.86rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  border-radius: 8px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 180ms ease, transform 120ms ease;
}
.app-bhv-form button:active { transform: scale(0.97); }
.app-bhv-form button:disabled { background: #5a4d2e; cursor: not-allowed; }
.app-bhv-msg {
  font-family: 'EB Garamond', serif;
  font-size: 0.96rem;
  margin: 0;
  padding: 10px 14px;
  background: #13141a;
  border-left: 3px solid #c9a96a;
  color: #cfc6b0;
}
.app-bhv-msg.is-err { border-left-color: #9b1c1c; }
.app-bhv-msg.is-ok  { border-left-color: #7c9d6c; }

.app-bhv-success {
  text-align: center;
  padding: 22px 18px;
  background: rgba(255, 212, 0, 0.06);
  border: 1px solid rgba(255, 212, 0, 0.22);
  border-radius: 12px;
  color: #f5e6c8;
}
.app-bhv-success svg {
  margin-bottom: 8px;
}
.app-bhv-success p {
  margin: 4px 0;
  font-family: 'Cormorant Garamond', serif;
  font-size: 1.1rem;
  line-height: 1.4;
}
.app-bhv-success p strong {
  font-family: 'Cinzel', serif;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: #FFD400;
}
.app-bhv-success-sub {
  color: #9a8d6f !important;
  font-style: italic;
  font-size: 0.98rem !important;
}

/* Eyebrow readability fix — the bp-status-strip eyebrow ("— Subscribe to
   the Brotherhood Pass —") and the threshold-eyebrow are set at 0.68rem
   / 11px with 0.24em–0.36em letter-spacing. On mobile, the wide letter-
   spacing forces text to wrap awkwardly (e.g. "PASS —" alone on a line),
   and Cinzel's hairline strokes at that size render so thin on Android
   WebView they look outline-only (Will called this out on Member #001's
   /brotherhood-pass/ screenshot 2026-05-19). Bump up the size + reduce
   the letter-spacing in app-mode so the line fits and reads solid. */
body[data-app-mode="1"] .bp-status-strip > div > div > p:first-child,
body[data-app-mode="1"] #bp-status-pre > p:first-child,
body[data-app-mode="1"] #bp-status-live > p:first-child {
  font-size: 0.82rem !important;
  letter-spacing: 0.14em !important;
  line-height: 1.5 !important;
}
body[data-app-mode="1"] .threshold-eyebrow {
  font-size: clamp(12px, 3.2vw, 14px) !important;
  letter-spacing: 0.18em !important;
  line-height: 1.5 !important;
}
