/* Ported verbatim from concepts/concept-a-v14.html <style> block (client-approved homepage design).
   Fonts loaded via next/font/google in layout.tsx under the SAME family names ('Cormorant Garamond',
   'Inter'), so the font: shorthands below resolve to the self-hosted fonts without any class-name rewriting.
   Removed vs. v14: .badge rule (preview-only nav pill); the #slfb-btn / .slfb-panel feedback
   widget lived in a separate <style> block in v14 (not part of this one) and was never ported.

   MOBILE-FIRST REFACTOR (task: "make it genuinely mobile-first"): every rule below is written
   base-first for the smallest phones, then progressively enhanced with `@media(min-width: …)`.
   Breakpoint scale used throughout: 640px (phone → large phone/small tablet), 900px (tablet →
   desktop — the point at which the original v14 desktop layout takes over), 1200px (the `.wrap`
   container cap — not a hard layout-switch breakpoint, so no min-width query needed for it).
   Every `min-width` override below restores the exact value the ORIGINAL (pre-refactor,
   desktop-first) stylesheet declared unconditionally — so anything ≥900px renders pixel-identical
   to the client-approved design. Colors/typography/radius tokens are untouched; only layout,
   responsive behavior, and the explicitly-required a11y/touch-target/no-overflow fixes changed. */

  :root{
    /* body — white, with a whisper of warmth on the page ground so
       white cards read as cards and the whole thing stays liturgical */
    --paper:#FFFFFF; --ground:#FCFBFA; --ink:#1A1D24; --muted:#5F6672;
    /* accent — martyr's red. St. Lawrence's own liturgical colour. */
    --red:#A81E2D; --red-deep:#7E1420; --red-soft:#FBEEEF;
    /* brightened red, for use on dark blue grounds only */
    --red-bright:#DC4B5C;
    /* gold — the label layer: eyebrows, small caps, sacred details.
       Never a surface, never a button.
       --gold is used ONLY on light grounds (.kicker, .mass-cell h4, .data-table th,
       .contact-info .row b, the nav underline) and --gold-soft ONLY on dark ones —
       audited across the live site, no crossover. v14's #A87C2A scored 3.76:1 on
       white, under the 4.5:1 WCAG AA floor for text this size (the ≥24px / ≥18.66px-
       bold large-text exemption doesn't reach 11–13px labels), so the light-ground
       gold is deepened to #8A6420 — deep enough to clear AA on BOTH light grounds it
       actually lands on: 5.35:1 on white, and 4.59:1 on the --blue-soft table headers
       (.data-table th), which an interim #966C22 still failed at 4.04:1. The tinted
       ground, not white, is the binding constraint.
       --gold-soft is untouched: on the dark blues it already measures 8.2–9.3:1. */
    --gold:#8A6420; --gold-soft:#D9BE85;
    /* everything else — Marian blue, now carrying real surface area */
    --blue:#1B3A6B; --blue-deep:#12274A; --blue-mid:#2E5490; --blue-soft:#E9EEF6;
    --blue-tint:#F1F4FA; --blue-night:#0E1D38;
    --line:#E3E7EE; --line-blue:#CFD9E9;
    /* soft-radius system: order from the grid, warmth from the corners */
    --r-card:12px; --r-chip:6px; --r-btn:6px;
  }
  *{margin:0;padding:0;box-sizing:border-box}
  /* The canvas (the surface behind the page, revealed by iOS Safari's rubber-band
     overscroll and its collapsing toolbars) takes its colour from <html> — and when
     <html> has none, CSS propagates <body>'s up to it instead. With only a body
     background declared, overscrolling past the footer on iPhone painted a full
     screen of --blue-tint below it, reading as a broken white gap. Both page EDGES
     are --blue-night (the topbar above, the footer below), so pinning the canvas to
     that navy makes overscroll at either end look like those bars continuing. */
  html{text-size-adjust:100%;background:var(--blue-night)}
  body{font-family:'Inter',sans-serif;background:var(--blue-tint);color:var(--ink);-webkit-font-smoothing:antialiased}
  .serif{font-family:'Cormorant Garamond',serif}

  /* ── Keyboard focus ────────────────────────────────────────────────────────
     Only .navtoggle and the form inputs carried a focus style, so tabbing through
     the nav, cards, buttons or footer moved an INVISIBLE cursor — unusable without
     a mouse. :focus-visible (not :focus) means pointer users never see a ring on
     click, only keyboard/switch users do. Offset keeps it clear of the element's
     own border. On the dark blue bands a blue ring would vanish, so those flip to
     the gold that already reads at 8:1+ there. */
  a:focus-visible,button:focus-visible,summary:focus-visible,
  [tabindex]:not([tabindex="-1"]):focus-visible{
    outline:2px solid var(--blue-mid);outline-offset:3px;border-radius:4px}
  .hero a:focus-visible,.sunday a:focus-visible,.giving a:focus-visible,
  footer a:focus-visible,.hero button:focus-visible{outline-color:var(--gold-soft)}

  /* Brand the text selection instead of the OS default blue-on-blue. */
  ::selection{background:var(--blue-soft);color:var(--blue-deep)}

  /* Anchor jumps land under the sticky-ish header without this; smooth scrolling
     is opt-in here and disabled again in the reduced-motion block below. */
  html{scroll-behavior:smooth}
  [id]{scroll-margin-top:24px}

  /* ── Reduced motion ───────────────────────────────────────────────────────
     The hero ran a 24s infinite Ken Burns zoom with no escape hatch. "Reduce
     Motion" is a common iOS/macOS setting (vestibular disorders, migraine), and
     an endlessly drifting photo is exactly what it exists to stop. Animations
     collapse to a single instant frame rather than being removed outright, so
     anything that animates INTO a visible state still ends up visible. */
  @media(prefers-reduced-motion:reduce){
    *,*::before,*::after{
      animation-duration:.01ms!important;animation-iteration-count:1!important;
      transition-duration:.01ms!important;scroll-behavior:auto!important}
    html{scroll-behavior:auto}
    .hero-media img{animation:none;transform:none}
  }

  /* ── Skip link ────────────────────────────────────────────────────────────
     First tab stop on every page: jumps past the topbar, crest and full nav
     straight to <main>. Off-screen until focused, so it costs the visual design
     nothing. */
  .skiplink{position:absolute;left:-9999px;top:0;z-index:100;
    background:var(--blue-deep);color:#fff;padding:14px 22px;
    font:600 15px/1 'Inter';text-decoration:none;border-radius:0 0 var(--r-btn) 0}
  .skiplink:focus{left:0;outline:2px solid var(--gold-soft);outline-offset:-4px}
  /* defensive baseline (outcome 8): nothing with an intrinsic pixel size should
     ever force the viewport wider than it is — existing images already carry
     their own width:100% rules (more specific, so they win unchanged); this
     just guarantees any future/CMS-authored <img> can't blow out the layout. */
  img,svg{max-width:100%;height:auto}
  .wrap{max-width:1200px;margin:0 auto;padding:0 20px}
  @media(min-width:640px){.wrap{padding:0 32px}}

  /* top bar — blue does structure */
  .topbar{background:var(--blue-deep);color:#C7D4E8;font-size:14px}
  .topbar .wrap{display:flex;flex-wrap:wrap;justify-content:center;gap:4px 14px;padding-top:8px;padding-bottom:8px;text-align:center}
  @media(min-width:900px){.topbar .wrap{flex-wrap:nowrap;justify-content:space-between;text-align:left;gap:0}}
  /* centered crest header — Father's request: logo centered, nav beneath */
  .brandrow{background:#fff;display:flex;justify-content:center;padding:24px 0 18px}
  @media(min-width:640px){.brandrow{padding:32px 0 24px}}
  .navrow{position:-webkit-sticky;position:sticky;top:0;z-index:50;background:rgba(255,255,255,.94);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-top:1px solid var(--line-blue);border-bottom:1px solid var(--line-blue)}
  .navwrap{display:flex;justify-content:space-between;align-items:center;gap:16px;min-height:56px;flex-wrap:nowrap}
  @media(min-width:900px){.navwrap{justify-content:center;column-gap:22px;row-gap:10px;padding-block:8px;flex-wrap:wrap}}
  .givesm{padding:10px 18px;font-size:12px;min-height:44px;display:inline-flex;align-items:center;justify-content:center}
  @media(min-width:900px){.givesm{min-height:auto;display:inline-block}}
  .brand{display:flex;align-items:center;gap:12px}
  @media(min-width:640px){.brand{gap:18px}}
  /* the parish's real seal, rescued from the old site */
  .seal{height:52px;width:auto;display:block}
  @media(min-width:640px){.seal{height:68px}}
  .brand h1{font:600 26px/1.05 'Cormorant Garamond';letter-spacing:.02em}
  @media(min-width:640px){.brand h1{font-size:32px}}
  .brand span{display:block;font:500 11px/1 'Inter';letter-spacing:.26em;color:var(--muted);margin-top:6px;text-transform:uppercase}
  @media(min-width:640px){.brand span{font-size:12.5px}}

  /* primary nav — collapses to a hamburger-triggered dropdown below 900px
     (globals.css side of SiteNav.tsx, the client component that owns the
     open/close state + a11y wiring). At 900px+ this CSS forces the original
     always-visible horizontal bar regardless of that component's state. */
  nav{display:none;flex-direction:column;gap:0;position:absolute;left:0;right:0;top:100%;background:#fff;border-bottom:1px solid var(--line-blue);box-shadow:0 24px 40px -24px rgba(18,39,74,.35);padding:8px 0;max-height:calc(100vh - 100%);overflow-y:auto;font:500 15.5px/1 'Inter'}
  nav.open{display:flex}
  nav a{color:var(--ink);text-decoration:none;position:relative;display:flex;align-items:center;min-height:48px;padding:0 20px;width:100%}
  nav a:after{content:"";position:absolute;left:20px;bottom:6px;height:1.5px;width:0;background:var(--gold);transition:width .3s}
  nav a:hover:after{width:calc(100% - 40px)}
  @media(min-width:640px){nav a{padding:0 32px}nav a:after{left:32px}nav a:hover:after{width:calc(100% - 64px)}}
  @media(min-width:900px){
    nav{display:flex;position:static;flex-direction:row;gap:clamp(13px,1.05vw,28px);background:transparent;border-bottom:0;box-shadow:none;padding:0;max-height:none;overflow:visible}
    nav a{display:inline-block;min-height:auto;padding:6px 0;width:auto}
    nav a:after{left:0;bottom:0;width:0}
    nav a:hover:after{width:100%}
  }
  /* hamburger toggle — 44×44 touch target; hidden entirely once the desktop
     nav bar takes over at 900px. Bars animate into an X when open. */
  .navtoggle{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;padding:0;border:0;background:transparent;cursor:pointer;position:relative;-webkit-tap-highlight-color:transparent;flex-shrink:0}
  /* .navtoggle-bars is itself position:absolute (placed relative to the 44px
     button), which makes IT the containing block for its own ::before/::after
     — so those pseudo-elements are positioned relative to the bars span's own
     24px box (left:10/right:10 of .navtoggle), not the button. They use
     left:0/right:0 (full width of that 24px box) accordingly. */
  .navtoggle-bars{content:"";position:absolute;left:10px;right:10px;top:21px;height:2px;border-radius:2px;background:var(--blue-deep);transition:background .2s ease}
  .navtoggle-bars:before,.navtoggle-bars:after{content:"";position:absolute;left:0;right:0;height:2px;border-radius:2px;background:var(--blue-deep);transition:transform .25s ease,top .25s ease}
  .navtoggle-bars:before{top:-7px}
  .navtoggle-bars:after{top:7px}
  .navtoggle.open .navtoggle-bars{background:transparent}
  .navtoggle.open .navtoggle-bars:before{top:0;transform:rotate(45deg)}
  .navtoggle.open .navtoggle-bars:after{top:0;transform:rotate(-45deg)}
  .navtoggle:focus-visible{outline:2px solid var(--blue-mid);outline-offset:2px;border-radius:4px}
  @media(min-width:900px){.navtoggle{display:none}}
  /* language switcher — was a decorative <b>EN</b><span>ES</span> pill, now
     real links (LanguageSwitcher.tsx); .active marks the current locale the
     same way the old bold <b> always marked English. */
  .lang{display:inline-flex;border:1px solid var(--line-blue);border-radius:999px;overflow:hidden;font:600 11.5px/1 'Inter'}
  .lang a{padding:7px 12px;color:var(--muted);text-decoration:none;display:inline-block}
  .lang a.active{background:var(--blue);color:#fff}
  /* EN/ES is a primary control in a bilingual parish, but at 10px/5px padding it
     measured 34x20 — under the 24x24 WCAG 2.5.8 minimum and hard to hit at all.
     Sized up to ~29px tall; still visually a small pill in the topbar. */
  .topbar .lang{border-color:rgba(255,255,255,.3);font-size:11px;vertical-align:middle;margin-left:10px}
  .topbar .lang a{color:#C7D4E8;padding:9px 13px}
  .topbar .lang a.active{background:#fff;color:var(--blue-deep)}
  /* the mobile-menu copy of the switcher (SiteNav's dropdown) — desktop
     already shows one in the topbar, so hide this one once nav goes
     always-visible-horizontal at 900px (matches .navtoggle's own cutoff). */
  .navlang{margin:14px 20px 6px}
  @media(min-width:640px){.navlang{margin:14px 32px 6px}}
  @media(min-width:900px){.navlang{display:none}}
  /* action = red, always. .btn's own padding/line-height already clears the
     44px touch-target minimum (15px vertical padding + 15px line-height), so
     no responsive override is needed here — only .givesm (a deliberately
     small "compact button") needed one, above. */
  .btn{display:inline-block;background:var(--red);color:#fff;text-decoration:none;font:600 15px/1 'Inter';padding:15px 26px;border-radius:var(--r-btn);letter-spacing:.04em;transition:background .25s}
  .btn:hover{background:var(--red-deep)}
  .btn.alt{background:transparent;color:var(--blue);border:1px solid var(--blue-mid)}
  .btn.alt:hover{background:var(--blue);color:#fff}
  .hero .btn.alt{color:#fff;border-color:rgba(255,255,255,.45)}
  .hero .btn.alt:hover{background:#fff;color:var(--blue-deep);border-color:#fff}

  /* hero — deep blue field. This is what stops the page reading white. */
  .hero{position:relative;overflow:hidden;background:var(--blue-deep);color:#fff;display:flex;flex-direction:column}
  @media(min-width:900px){.hero{display:block}}
  .hero:after{content:"";position:absolute;inset:0;background:radial-gradient(120% 90% at 15% 20%,rgba(46,84,144,.55),transparent 60%);pointer-events:none}
  .hero .wrap{position:relative;z-index:2;display:block;padding-top:8px;padding-bottom:36px}
  @media(min-width:900px){.hero .wrap{padding-top:190px;padding-bottom:190px}}
  .hero .copy{max-width:100%}
  @media(min-width:900px){.hero .copy{max-width:50%}}
  .kicker{font:600 13px/1 'Inter';letter-spacing:.28em;color:var(--gold);text-transform:uppercase;margin-bottom:20px}
  .hero .kicker{color:var(--gold-soft)}
  /* fluid headline (outcome 5): clamps to the exact original 64px once the
     viewport reaches ~900px (same point the layout itself goes desktop), and
     never drops below a legible ~28px on the smallest phones. The `4rem` cap
     guarantees 900/1024/1280/1440px all render the client-approved 64px
     pixel-exact, same as before this refactor. overflow-wrap is a zero-cost
     safety net — it only ever engages if the fluid size still isn't enough
     room for the non-breaking "North Miami Beach" phrase to fit on one line. */
  .hero h2{font-weight:500;font-size:clamp(1.75rem,0.5rem + 6.2vw,4rem);line-height:1.06;font-family:'Cormorant Garamond';letter-spacing:-.01em;color:#fff;overflow-wrap:anywhere}
  /* "the red cannot be prominent" — Fr., 2026-07-24. Display emphasis is
     gold; red stays in small assets (buttons, links, feast, rules). */
  .hero h2 em{font-style:italic;color:var(--gold-soft)}
  .hero p{margin:26px 0 34px;font-size:18.5px;line-height:1.75;color:#C3D0E4;max-width:52ch}
  /* blended hero media — the photo dissolves into the blue field
     (edge-fade mask) and sits under a whisper of blue scrim, so it
     reads as part of the section's atmosphere, not a placed object */
  /* mobile: photo stacks above the copy, top-fading down into the field.
     side blend (the approved v8 treatment) returns at 900px+: photo owns
     the right 64%, eased S-curve mask fades its left edge into the field;
     Father and the families stay fully visible in the solid zone. */
  .hero-media{position:relative;width:100%;height:clamp(300px,68vw,420px);order:-1;z-index:1}
  @media(min-width:900px){.hero-media{position:absolute;top:0;right:0;bottom:0;width:64%;height:auto;order:0}}
  .hero-media img{width:100%;height:100%;object-fit:cover;object-position:38% 22%;display:block;
    -webkit-mask-image:linear-gradient(to top,#000 55%,transparent 100%);
    mask-image:linear-gradient(to top,#000 55%,transparent 100%);
    transform-origin:50% 25%;animation:kb 24s ease-in-out infinite alternate}
  @media(min-width:900px){
    .hero-media img{
      -webkit-mask-image:linear-gradient(to left,#000 34%,rgba(0,0,0,.94) 48%,rgba(0,0,0,.78) 60%,rgba(0,0,0,.52) 72%,rgba(0,0,0,.26) 82%,rgba(0,0,0,.08) 92%,transparent 100%);
      mask-image:linear-gradient(to left,#000 34%,rgba(0,0,0,.94) 48%,rgba(0,0,0,.78) 60%,rgba(0,0,0,.52) 72%,rgba(0,0,0,.26) 82%,rgba(0,0,0,.08) 92%,transparent 100%);
    }
  }
  @keyframes kb{from{transform:scale(1)}to{transform:scale(1.05)}}
  /* MOBILE scrim: the photo is a full-width band above the copy, so it only
     needs a soft bottom fade into the blue field. The heavy left-side and top
     gradients below are for the DESKTOP side-blend — on a phone they fell
     across Fr. Cletus (upper-left of frame) and read as if his head had been
     cropped out. Keep the top clean so faces stay legible. */
  .hero-media:after{content:"";position:absolute;inset:0;pointer-events:none;z-index:1;
    background:linear-gradient(0deg,var(--blue-deep) 0%,rgba(18,39,74,.35) 18%,rgba(18,39,74,0) 45%),
               linear-gradient(180deg,rgba(18,39,74,.16) 0%,rgba(18,39,74,0) 18%)}
  @media(min-width:900px){
    .hero-media:after{
      background:linear-gradient(90deg,rgba(18,39,74,.62) 0%,rgba(18,39,74,.34) 25%,rgba(18,39,74,.14) 48%,rgba(18,39,74,0) 70%),
                 linear-gradient(0deg,rgba(18,39,74,.62) 0%,rgba(18,39,74,0) 38%),
                 linear-gradient(180deg,rgba(18,39,74,.45) 0%,rgba(18,39,74,0) 24%)}
  }
  /* Sunday times live in the copy column — nothing floats on the photo */
  .sun{margin-top:36px;padding-top:20px;border-top:1px solid rgba(255,255,255,.18);display:flex;align-items:baseline;gap:18px;flex-wrap:wrap}
  .sun span{font:600 12px/1 'Inter';letter-spacing:.24em;color:var(--gold-soft);text-transform:uppercase}
  .sun b{font:600 23px/1.2 'Cormorant Garamond';color:#fff;letter-spacing:.02em}

  /* mass schedule */
  .section{padding:48px 0;background:var(--paper)}
  @media(min-width:640px){.section{padding:64px 0}}
  @media(min-width:900px){.section{padding:78px 0}}
  .section.tint{background:var(--blue-soft);border-top:1px solid var(--line-blue);border-bottom:1px solid var(--line-blue)}
  .sec-head{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:12px 24px;border-bottom:1px solid var(--line-blue);padding-bottom:18px;margin-bottom:28px}
  @media(min-width:900px){.sec-head{flex-wrap:nowrap;gap:24px;margin-bottom:38px}}
  .sec-head h3{font:500 28px/1.15 'Cormorant Garamond'}
  @media(min-width:640px){.sec-head h3{font-size:36px;line-height:1.1}}
  .ssub{font:400 16px/1.5 'Cormorant Garamond';font-style:italic;color:var(--muted);margin-top:8px;max-width:60ch}
  @media(min-width:640px){.ssub{font-size:17.5px}}
  .sec-head a{font:600 13.5px/1 'Inter';letter-spacing:.14em;color:var(--red);text-decoration:none;text-transform:uppercase}
  /* Mass Schedule — the parish's most-visited answer, staged like it.
     Sunday gets its own blue field (echoes the hero); weekday liturgies
     read as the supporting cast; a Next-Mass strip does the thinking. */
  .mass{background:var(--paper);border:1px solid var(--line-blue);border-radius:var(--r-card);overflow:hidden;box-shadow:0 30px 60px -40px rgba(18,39,74,.35)}
  .mass-top{display:grid;grid-template-columns:1fr}
  @media(min-width:900px){.mass-top{grid-template-columns:1.05fr 1.95fr}}
  .sunday{background:var(--blue-deep);color:#fff;padding:26px 22px;position:relative;overflow:hidden}
  @media(min-width:640px){.sunday{padding:32px 30px}}
  .sunday:before{content:"✠";position:absolute;right:-26px;bottom:-38px;font-size:170px;color:rgba(217,190,133,.09);line-height:1}
  .sunday h4{font:600 11px/1 'Inter';letter-spacing:.24em;color:var(--gold-soft);text-transform:uppercase}
  .sunday .lord{font:400 15px/1.4 'Cormorant Garamond';font-style:italic;color:#C3D0E4;margin:6px 0 18px}
  .stime{display:flex;justify-content:space-between;align-items:center;padding:13px 0;border-bottom:1px solid rgba(255,255,255,.14);position:relative;z-index:1;min-height:44px}
  .stime:last-child{border-bottom:0}
  .stime b{font:600 27px/1 'Cormorant Garamond'}
  .mchip{font:600 9.5px/1 'Inter';letter-spacing:.12em;text-transform:uppercase;padding:5px 10px;border-radius:999px;border:1px solid rgba(255,255,255,.35);color:#E6EDF7}
  .mchip.es{border-color:rgba(217,190,133,.55);color:var(--gold-soft)}
  .mass-rest{display:grid;grid-template-columns:1fr}
  @media(min-width:900px){.mass-rest{grid-template-columns:repeat(2,1fr)}}
  .mass-cell{padding:22px;border-left:1px solid var(--line-blue);border-top:1px solid var(--line-blue)}
  @media(min-width:640px){.mass-cell{padding:26px}}
  .mass-rest .mass-cell:first-child{border-top:0}
  @media(min-width:900px){.mass-rest .mass-cell:first-child{border-top:0}.mass-rest .mass-cell:nth-child(2){border-top:0}}
  .mass-cell h4{font:600 11px/1 'Inter';letter-spacing:.2em;color:var(--gold);text-transform:uppercase;margin-bottom:14px}
  .mass-cell .t{font:600 26px/1.25 'Cormorant Garamond'}
  /* Fr. Cletus asked twice for larger type; the Mass schedule is the page's most
     consulted block and its detail line was the smallest copy on it. */
  .mass-cell p{font:400 15.5px/1.6 'Inter';color:var(--muted);margin-top:8px}
  .next{display:flex;justify-content:space-between;align-items:center;gap:18px;flex-wrap:wrap;border-top:1px solid var(--line-blue);background:var(--blue-soft);padding:16px 22px}
  @media(min-width:640px){.next{padding:16px 26px}}
  .nextpill{background:var(--red);color:#fff;font:600 10px/1 'Inter';letter-spacing:.16em;text-transform:uppercase;padding:8px 14px;border-radius:999px}
  .nextt{font:600 20px/1.2 'Cormorant Garamond';color:var(--ink)}
  .next .live{display:flex;align-items:center;gap:8px;font:500 13px/1.4 'Inter';color:var(--blue-deep)}
  .next .dot{width:8px;height:8px;border-radius:50%;background:var(--red);animation:pulse 2s infinite}
  @keyframes pulse{0%,100%{opacity:1}50%{opacity:.35}}

  /* quick actions */
  .quick{display:grid;grid-template-columns:1fr;grid-gap:16px;gap:16px}
  @media(min-width:640px){.quick{grid-template-columns:1fr 1fr;gap:20px}}
  @media(min-width:900px){.quick{grid-template-columns:repeat(4,1fr)}}
  .qcard{background:var(--paper);border:1px solid var(--line-blue);border-radius:var(--r-card);padding:26px 22px;text-decoration:none;color:var(--ink);transition:transform .25s,box-shadow .25s,border-color .25s;position:relative;display:block;min-height:44px}
  @media(min-width:640px){.qcard{padding:30px 26px}}
  .qcard:hover{transform:translateY(-4px);box-shadow:0 24px 44px -24px rgba(18,39,74,.32);border-color:var(--blue-mid)}
  .qcard .ic{font-size:24px;margin-bottom:16px}
  .qcard b{font:600 23px/1.25 'Cormorant Garamond';display:block;margin-bottom:8px;color:var(--blue-deep)}
  .qcard span{font:400 14.5px/1.6 'Inter';color:var(--muted)}

  /* events */
  .events{display:grid;grid-template-columns:1fr;grid-gap:16px;gap:16px}
  @media(min-width:640px){.events{grid-template-columns:1fr 1fr;gap:20px}}
  @media(min-width:900px){.events{grid-template-columns:repeat(3,1fr)}}
  .ev{background:var(--paper);border:1px solid var(--line-blue);border-radius:var(--r-card);padding:22px;display:flex;gap:18px;align-items:flex-start}
  @media(min-width:640px){.ev{padding:26px;gap:20px}}
  .date{min-width:58px;text-align:center;border:1px solid var(--line-blue);border-radius:var(--r-chip);padding:10px 6px}
  .date b{font:700 25px/1 'Cormorant Garamond';color:var(--blue);display:block}
  .date span{font:600 11px/1 'Inter';letter-spacing:.14em;color:var(--muted)}
  /* the patronal feast is vested in red — so it is red here too */
  .ev.feast{border-color:rgba(168,30,45,.35);background:var(--red-soft)}
  .ev.feast .date{border-color:rgba(168,30,45,.45);background:var(--paper)}
  .ev.feast .date b{color:var(--red)}
  /* h4, not h5: these sit under the section's h3, and skipping a level makes a
     screen reader announce a heading that isn't there. Styling is unchanged. */
  .ev h4{font:600 21px/1.3 'Cormorant Garamond';margin-bottom:6px}
  .ev p{font:400 14px/1.6 'Inter';color:var(--muted)}
  .feast-note{font:600 11.5px/1 'Inter';letter-spacing:.16em;color:var(--red);text-transform:uppercase;margin-top:10px;display:block}

  /* giving — blue carries the heavy band */
  .giving{background:var(--blue-deep);color:#D6E0F0}
  .giving .wrap{display:grid;grid-template-columns:1fr;grid-gap:40px;gap:40px;padding-top:56px;padding-bottom:56px;align-items:center}
  @media(min-width:900px){.giving .wrap{grid-template-columns:1fr 1fr;gap:64px;padding-top:84px;padding-bottom:84px}}
  .giving h3{font:500 32px/1.15 'Cormorant Garamond';color:#fff}
  @media(min-width:640px){.giving h3{font-size:42px}}
  .giving p{margin:20px 0 30px;font-size:17px;line-height:1.8;color:#B8C7DE}
  .funds{display:grid;grid-gap:12px;gap:12px}
  .fund{display:flex;justify-content:space-between;align-items:center;gap:12px;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.16);border-radius:10px;padding:16px 18px;text-decoration:none;color:#E6EDF7;transition:background .25s,border-color .25s;min-height:44px}
  @media(min-width:640px){.fund{padding:18px 22px;gap:0}}
  .fund:hover{background:rgba(255,255,255,.11);border-color:rgba(255,255,255,.3)}
  .fund b{font:600 20px/1.2 'Cormorant Garamond'}
  .fund span{font:600 12px/1 'Inter';letter-spacing:.14em;color:var(--gold-soft);text-transform:uppercase}
  .campaign{margin-top:14px;background:rgba(217,190,133,.08);border:1px solid rgba(217,190,133,.45);border-radius:10px;padding:20px 22px}
  .campaign b{font:600 18px/1.25 'Cormorant Garamond';color:#fff}
  .bar{height:6px;background:rgba(255,255,255,.16);margin:14px 0 8px;border-radius:99px;overflow:hidden}
  .bar i{display:block;height:100%;width:38%;background:var(--red)}
  .campaign span{font:500 12px/1 'Inter';color:#B8C7DE}

  /* story teaser */
  .story{display:grid;grid-template-columns:1fr;grid-gap:32px;gap:32px;align-items:center}
  @media(min-width:900px){.story{grid-template-columns:1fr 1.1fr;gap:52px}}
  .simg{background:var(--blue-soft);border-radius:var(--r-card);overflow:hidden;box-shadow:0 26px 50px -30px rgba(18,39,74,.4)}
  .simg img{width:100%;height:260px;object-fit:cover;display:block}
  @media(min-width:640px){.simg img{height:350px}}
  .stitle{font:500 27px/1.2 'Cormorant Garamond';margin-bottom:14px}
  @media(min-width:640px){.stitle{font-size:34px;line-height:1.15}}
  .stext{font-size:16.5px;line-height:1.75;color:var(--muted);margin-bottom:24px;max-width:56ch}

  /* trio + footer */
  .trio{display:grid;grid-template-columns:1fr;grid-gap:16px;gap:16px}
  @media(min-width:640px){.trio{grid-template-columns:1fr 1fr;gap:20px}}
  @media(min-width:900px){.trio{grid-template-columns:repeat(3,1fr)}}
  .tcard{background:var(--blue-soft);position:relative;height:230px;overflow:hidden;border-radius:var(--r-card)}
  .tcard img{width:100%;height:100%;object-fit:cover;transition:transform .4s}
  .tcard:hover img{transform:scale(1.05)}
  .tcard .ov{position:absolute;inset:0;background:linear-gradient(180deg,transparent 30%,rgba(18,39,74,.88));display:flex;align-items:flex-end;padding:22px}
  .tcard .ov b{color:#fff;font:600 25px/1.2 'Cormorant Garamond'}
  /* line-height 1.8 -> 2 buys room for the link padding below without the taller
     hit areas overlapping between wrapped rows. */
  footer{background:#0E1D38;color:#9FB0C9;padding:48px 0 32px;font:400 15px/2 'Inter'}
  @media(min-width:640px){footer{padding:64px 0 40px}}
  footer .wrap{display:grid;grid-template-columns:1fr;grid-gap:32px;gap:32px}
  @media(min-width:900px){footer .wrap{grid-template-columns:2fr 1fr 1fr;gap:48px}}
  /* h4 for the same reason as .ev — h6 after the page's h3 sections was a two-level
     skip. Appearance identical. */
  footer h3{font:600 11px/1 'Inter';letter-spacing:.2em;color:var(--gold-soft);text-transform:uppercase;margin-bottom:16px}
  footer .name{font:600 22px/1.2 'Cormorant Garamond';color:#fff;margin-bottom:12px}
  @media(min-width:640px){footer .name{font-size:24px}}
  /* Footer crest — the reversed mark, deliberately smaller than the header's
     (52/68px) so the page reads header-first. Sits above the existing red rule,
     which stays as the divider between mark and parish name. */
  .fseal{height:56px;width:auto;display:block;margin-bottom:18px;opacity:.92}
  @media(min-width:640px){.fseal{height:64px}}
  footer .rule{height:2px;width:44px;background:var(--red);margin-bottom:18px}
  /* Footer links measured 18px tall — below the 24px WCAG 2.5.8 target minimum,
     and the densest tap area on the page (the "·"-separated rows sit close
     together). inline-block + vertical padding lifts them to ~28px without
     disturbing the separators or the approved layout. */
  footer a{color:inherit;text-decoration:none;display:inline-block;padding:5px 0}
  footer a:hover{text-decoration:underline}
  /* Links carrying colour meaning only (the pale grey on navy) get an underline
     on hover AND a brighter tone, so the affordance isn't colour-alone. */
  footer a:hover,footer a:focus-visible{color:#D7E2F2}

  /* Homepage section ordering. Fr. Cletus asked that "what's happening this
     week" be the first thing on mobile — but ordering it above the hero pushed
     the hero to y=1059 on an 844px-tall phone, so the welcome image was never
     seen at all. Hero now leads (compact on mobile, see .hero .wrap below) and
     happenings sits immediately beneath it, still the first CONTENT block. */
  .home{display:flex;flex-direction:column}
  .home>*{order:3}
  .home>.hero{order:1}
  .home>.happenings{order:2}
  /* >=900px: no reordering, sections follow document order */
  @media(min-width:900px){.home>*,.home>.hero,.home>.happenings{order:0}}

  /* slim page hero for inner pages */
  .page-hero .wrap{padding-top:40px;padding-bottom:40px}
  @media(min-width:640px){.page-hero .wrap{padding-top:64px;padding-bottom:64px}}
  .page-hero h2{font-size:clamp(1.75rem,1.2rem + 2.76vw,2.75rem)}

  /* generic content-page card chrome (task 6: sacraments grid, religious-ed
     registering/contact blocks) — same tokens/radius as .qcard, sized for
     longer verbatim copy-deck paragraphs instead of homepage teaser text */
  .card-grid{display:grid;grid-template-columns:1fr;grid-gap:16px;gap:16px}
  @media(min-width:900px){.card-grid{grid-template-columns:repeat(2,1fr);gap:20px}}
  .card-grid .wide{grid-column:1/-1}
  .info-card{background:var(--paper);border:1px solid var(--line-blue);border-radius:var(--r-card);padding:24px 22px}
  @media(min-width:640px){.info-card{padding:30px 28px}}
  .info-card h3,.info-card h4{font:600 22px/1.25 'Cormorant Garamond';color:var(--blue-deep);margin-bottom:10px}
  @media(min-width:640px){.info-card h3,.info-card h4{font-size:24px}}
  .info-card p{font:400 15.5px/1.7 'Inter';color:var(--muted)}
  .info-card p+p{margin-top:12px}
  /* Card links (incl. "Give to ABCD →") sat at 19px — under the 24px WCAG 2.5.8
     target minimum. These run inline inside body copy, so inline-block padding
     would break the text flow; padding-block on an inline box grows the hit area
     without affecting line layout. Underlined always, not just on hover: red-on-
     white alone is a colour-only affordance inside a paragraph. */
  .info-card a{color:var(--red);font-weight:600;text-decoration:underline;
    text-underline-offset:3px;padding-block:6px}
  .info-card a:hover,.info-card a:focus-visible{text-decoration-thickness:2px}

  /* generic data table (task 6: religious-education program grid) */
  .data-table-wrap{border:1px solid var(--line-blue);border-radius:var(--r-card);overflow:hidden;background:var(--paper);overflow-x:auto}
  .data-table{width:100%;border-collapse:collapse;font-size:14px}
  @media(min-width:640px){.data-table{font-size:16px}}
  .data-table th,.data-table td{text-align:left;padding:10px 12px;border-bottom:1px solid var(--line-blue)}
  @media(min-width:640px){.data-table th,.data-table td{padding:14px 20px}}
  .data-table tr:last-child td{border-bottom:0}
  .data-table th{font:600 11px/1 'Inter';letter-spacing:.14em;text-transform:uppercase;color:var(--gold);background:var(--blue-soft)}
  .data-table td{font:400 15.5px/1.6 'Inter';color:var(--ink)}
  .data-table td:first-child{font:600 17px/1.3 'Cormorant Garamond';color:var(--blue-deep)}

  /* bulletins index (task 7) */
  .bulletin-list{display:grid;grid-gap:2px;gap:2px;border:1px solid var(--line-blue);border-radius:var(--r-card);overflow:hidden;background:var(--line-blue)}
  .bulletin-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:8px 14px;background:var(--paper);padding:16px 18px;text-decoration:none;color:var(--ink);transition:background .2s;min-height:44px}
  @media(min-width:640px){.bulletin-row{padding:18px 24px;gap:10px 14px}}
  .bulletin-row:hover{background:var(--blue-tint)}
  .bulletin-row .bdate{font:600 12px/1 'Inter';letter-spacing:.1em;color:var(--muted);min-width:100px}
  .bulletin-row .bsep{color:var(--line-blue)}
  .bulletin-row .btitle{font:500 19px/1.3 'Cormorant Garamond';color:var(--blue-deep);flex:1 1}
  .bulletin-row .bread{font:600 12.5px/1 'Inter';letter-spacing:.08em;color:var(--red);white-space:nowrap;margin-left:auto}
  .bulletin-empty{font:400 16px/1.6 'Cormorant Garamond';font-style:italic;color:var(--muted);padding:30px 0}

  /* contact page office info (task 7) */
  .contact-info{display:grid;grid-gap:18px;gap:18px}
  .contact-info .row b{display:block;font:600 11px/1 'Inter';letter-spacing:.14em;text-transform:uppercase;color:var(--gold);margin-bottom:6px}
  .contact-info .row div,.contact-info .row a{font:400 16px/1.6 'Inter';color:var(--ink);text-decoration:none;white-space:pre-line}
  /* Tap-to-call, tap-to-email and Get Directions are the primary mobile actions on
     the contact page, and they measured 20px tall — under the 24px WCAG 2.5.8
     minimum. inline-block + vertical padding takes them to ~30px; they're already
     on their own lines, so nothing shifts. */
  .contact-info .row a{color:var(--blue);display:inline-block;padding:6px 0}
  .contact-info .row a:hover,.contact-info .row a:focus-visible{text-decoration:underline}

  /* ParishForm (task 7) — inputs styled like the preview feedback widget
     (concepts/feedback-widget.snippet.html): 1px line-blue border, r-chip
     radius, Inter, focus outline blue-mid. Font-size is 16px (not the
     original 15px) unconditionally — below 16px, iOS Safari zooms the
     viewport on focus regardless of breakpoint, so this can't be a
     mobile-only override; it's the one place this refactor intentionally
     changes a typographic value, per the explicit "form inputs must be
     ≥16px" outcome. */
  .pform{display:grid;grid-gap:16px;gap:16px;max-width:560px}
  .pform-row{display:grid;grid-template-columns:1fr;grid-gap:16px;gap:16px}
  @media(min-width:640px){.pform-row{grid-template-columns:1fr 1fr}}
  .pform label{display:grid;grid-gap:6px;gap:6px;font:600 12px/1 'Inter';letter-spacing:.06em;color:var(--muted);text-transform:uppercase}
  .pform input,.pform textarea{width:100%;border:1px solid var(--line-blue);border-radius:var(--r-chip);padding:12px 14px;font:400 16px/1.5 'Inter';color:var(--ink);background:var(--paper)}
  .pform textarea{resize:vertical;min-height:120px}
  .pform input:focus,.pform textarea:focus{outline:2px solid var(--blue-mid);outline-offset:0}
  .pform button.btn{justify-self:start;border:0;cursor:pointer}
  .pform button.btn:disabled{opacity:.6;cursor:default}
  .pform-status{font:500 14.5px/1.6 'Inter'}
  .pform-status.ok{font:400 20px/1.5 'Cormorant Garamond';color:var(--blue-deep);padding:20px 0}
  .pform-status.err{color:var(--red)}
  /* honeypot — visually hidden but not display:none (some bots skip
     display:none fields but still fill absolutely-positioned off-screen
     ones, which is exactly the behavior we want to catch). */
  .hp{position:absolute;left:-9999px;top:auto;width:1px;height:1px;overflow:hidden}

