/*
Theme Name: PrayerStream
Theme URI: https://prayerstreamcarolinas.com
Author: Speak Up
Author URI: https://speakupmag.org
Description: A one-page site for the PrayerStream — a mobile prayer room. Block theme; all design lives in theme.json so the Site Editor always wins.
Version: 0.12.22
Requires at least: 6.6
Tested up to: 7.1
Requires PHP: 8.0
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: prayerstream
Tags: full-site-editing, block-patterns, one-column, landing-page
*/

/* ══════════════════════════════════════════════════════════════════
   MECHANICS ONLY.

   The design lives in theme.json, in styles/block/, and in the block
   attributes of the patterns. Matt must be able to change any colour,
   size or typeface from Appearance → Editor → Styles and see it take
   effect. That only stays true while this file contains no design
   decisions.

   ⛔ Every colour below is a --wp--preset--* variable. A literal is a bug.

   THE DIRECTION — "Row", Matt 2026-09-23, after five rounds that went
   Gallery → Mono → "mono became a little heavy" → "photos are still too
   much" / "start with headline" / "do a lightbox smaller photo gallery"
   → "sure let's do row - but the story and the what's next can be
   expanded and more distinctive sections".

   So: white, Instrument Serif over Instrument Sans, outlined buttons,
   hairlines, no accent hue. The headline comes first; the photographs
   are one row of small squares that open large (in colour since
   2026-09-24, his word); the story and what's next are sections of
   their own.
   ══════════════════════════════════════════════════════════════════ */


/* ── Type mechanics ────────────────────────────────────────────── */
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}
body {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
h1, h2, h3 { text-wrap: balance; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}


/* ── Accessibility ─────────────────────────────────────────────── */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100000;
  padding: 0.75rem 1.25rem;
  background: var(--wp--preset--color--ink);
  color: var(--wp--preset--color--paper);
  font-size: var(--wp--preset--font-size--small);
  text-decoration: none;
}
.skip-link:focus { left: 0; }

:where(a, button, .wp-block-button__link, input, textarea, summary):focus-visible {
  outline: 2px solid var(--wp--preset--color--ink);
  outline-offset: 3px;
}


/* Over a photograph (cover blocks) the ink focus ring would vanish; use the
   text's own colour there instead. */
.wp-block-cover :where(a, button, .wp-block-button__link):focus-visible {
  outline-color: currentColor;
}


/* ── Links ─────────────────────────────────────────────────────── */
:where(body) a { text-underline-offset: 0.22em; }


/* ── Buttons ───────────────────────────────────────────────────────
   The button look is theme.json's (outlined, ink, fills on hover).
   "Text link" (styles/block/text-link.json) is the quiet link-button —
   no side padding since 2026-09-25, so on its own (the hero lost its
   Give button) it lines up with the words above it. Formerly the second
   action beside it. theme.json cannot express a hover for a style
   variation, so its hover lives here: a heavier underline, no fill.
   ─────────────────────────────────────────────────────────────── */
.wp-block-button.is-style-text-link .wp-block-button__link:hover,
.wp-block-button.is-style-text-link .wp-block-button__link:focus-visible {
  background-color: transparent;
  color: var(--wp--preset--color--ink);
  text-decoration-thickness: 2px;
}


/* ── Hero ───────────────────────────────────────────────────────────
   The Cover's 21:9 is a MINIMUM height (its own min-height, 42.86vw — set
   in the block), not an aspect-ratio. An aspect-ratio box can't grow past
   its shape in Safari/WebKit, so on Matt's iPhone the headline and the
   paragraph were cut off top and bottom (2026-09-25, "Mobile error");
   Chrome grew the same box, which is why it tested fine here.

   On phones the hero is the whole screen under the header — Matt: "make it
   fullscreen hero on mobile". 91px = the header (75) + the 16px gap before
   the page content; svh so Safari's own bars don't push the bottom off.
   ─────────────────────────────────────────────────────────────── */
@media (max-width: 781px) {
  .wp-block-cover.ps-hero {
    min-height: calc(100vh - 91px) !important;
    min-height: calc(100svh - 91px) !important;
  }
}


/* ── Donorbox's fallback link ──────────────────────────────────────
   The campaign's address under the giving form (blocks/donorbox), for
   when Donorbox's script is blocked. Quiet: it is a way round, not a
   second call to give.
   ─────────────────────────────────────────────────────────────── */
.ps-dbfall {
  margin: 0.75rem 0 0;
  font-size: var(--wp--preset--font-size--x-small);
  color: var(--wp--preset--color--mute);
}
.ps-dbfall a { color: inherit; }


/* ── Instagram, kept by hand ────────────────────────────────────────
   Matt, 2026-09-30, from the mock-ups: "Combine B and C I like the little
   icons and also like the heavy instagram emphasis". A profile card (group
   style "Instagram profile"), Instagram's tab row (blocks/ig-tabs), and the
   posts as a Gallery in the style "Instagram grid": tall 3:4 tiles, hairline
   gaps, three across at every width like Instagram's own grid. A photo in
   it takes the style "Instagram album" or "Instagram reel" for the mark in
   its corner. Each photo links to its post and opens in a new tab.
   ─────────────────────────────────────────────────────────────── */
.wp-block-group.is-style-ig-profile {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 16px 22px;
  padding-bottom: 16px;
}
.wp-block-group.is-style-ig-profile > * { margin: 0; }
.is-style-ig-profile .wp-block-image { margin: 0; }
.is-style-ig-profile .wp-block-image img { display: block; box-shadow: 0 0 0 1px var(--wp--preset--color--rule-strong); }
.is-style-ig-profile .wp-block-group { display: grid; gap: 2px; }
.is-style-ig-profile .wp-block-group > * { margin: 0; }
.ps-ig-user { display: flex; align-items: center; gap: 7px; font-weight: 600; }
.ps-ig-user a { color: inherit; text-decoration: none; }
.ps-ig-user a:hover { text-decoration: underline; }
.ps-ig-user::before,
.is-style-ig-profile .wp-block-button__link::before {
  content: "";
  flex: none;
  width: 17px;
  height: 17px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect x='3' y='3' width='18' height='18' rx='5' fill='none' stroke='black' stroke-width='1.8'/%3E%3Ccircle cx='12' cy='12' r='4.2' fill='none' stroke='black' stroke-width='1.8'/%3E%3Ccircle cx='17.4' cy='6.6' r='1.2' fill='black'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect x='3' y='3' width='18' height='18' rx='5' fill='none' stroke='black' stroke-width='1.8'/%3E%3Ccircle cx='12' cy='12' r='4.2' fill='none' stroke='black' stroke-width='1.8'/%3E%3Ccircle cx='17.4' cy='6.6' r='1.2' fill='black'/%3E%3C/svg%3E") center / contain no-repeat;
}
.is-style-ig-profile .wp-block-button__link { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }
.is-style-ig-profile .wp-block-button__link::before { width: 15px; height: 15px; }
.ps-ig-name { color: var(--wp--preset--color--mute); font-size: var(--wp--preset--font-size--small); }
.ps-ig-bio { margin-top: 4px !important; color: var(--wp--preset--color--ink-soft); font-size: var(--wp--preset--font-size--small); }
@media (max-width: 599px) {
  .wp-block-group.is-style-ig-profile { grid-template-columns: auto 1fr; gap: 14px 16px; }
  .wp-block-group.is-style-ig-profile > .wp-block-buttons { grid-column: 1 / -1; }
  .is-style-ig-profile .wp-block-image img { width: 60px !important; height: 60px !important; }
}

.ps-ig-tabs {
  display: flex;
  justify-content: center;
  gap: clamp(40px, 12vw, 88px);
  border-top: 1px solid var(--wp--preset--color--rule-strong);
}
.ps-ig-tabs a { display: grid; place-items: center; padding: 11px 6px 10px; margin-top: -1px; border-top: 1px solid transparent; color: var(--wp--preset--color--mute); }
.ps-ig-tabs a.is-active { color: var(--wp--preset--color--ink); border-top-color: var(--wp--preset--color--ink); }
.ps-ig-tabs a:hover { color: var(--wp--preset--color--ink); }
.ps-ig-tabs svg { display: block; width: 22px; height: 22px; }

.wp-block-gallery.has-nested-images.is-style-instagram figure.wp-block-image:not(#individual-image) {
  flex-grow: 0;
  width: calc(33.333% - var(--wp--style--unstable-gallery-gap, 16px) * 0.66667);
}
.wp-block-gallery.has-nested-images.is-cropped.is-style-instagram figure.wp-block-image:not(#individual-image) img {
  aspect-ratio: 3 / 4;
  height: auto;
  object-fit: cover;
}
.wp-block-gallery.is-style-instagram figure.wp-block-image a { transition: opacity 0.15s ease; }
.wp-block-gallery.is-style-instagram figure.wp-block-image a:hover { opacity: 0.85; }
.wp-block-image.is-style-ig-album,
.wp-block-image.is-style-ig-reel { position: relative; }
.wp-block-image.is-style-ig-album::after,
.wp-block-image.is-style-ig-reel::after {
  content: "";
  position: absolute;
  top: 8px;
  right: 8px;
  width: 18px;
  height: 18px;
  background: center / contain no-repeat;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.45));
  pointer-events: none;
}
.wp-block-image.is-style-ig-album::after { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect x='7' y='3' width='14' height='14' rx='2' fill='white'/%3E%3Cpath d='M4 7v12a2 2 0 0 0 2 2h12' fill='none' stroke='white' stroke-width='2'/%3E%3C/svg%3E"); }
.wp-block-image.is-style-ig-reel::after { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect x='3' y='3' width='18' height='18' rx='4' fill='none' stroke='white' stroke-width='2'/%3E%3Cpath d='M10 8.5v7l6-3.5z' fill='white'/%3E%3C/svg%3E"); }


/* ── Instagram feed (blocks/instagram) ─────────────────────────────
   The latest posts as one row of squares, like the photographs: six
   across, three across under 50rem (the gallery's breakpoint), same
   16px gap. Square by class, not by the images' own shape. The block
   renders nothing until its Behold feed has posts.
   ─────────────────────────────────────────────────────────────── */
.wp-block-prayerstream-instagram { padding-top: var(--wp--preset--spacing--50); }
.ps-ig-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 16px;
}
@media (max-width: 49.99rem) {
  .ps-ig-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.ps-ig-grid a { display: block; line-height: 0; transition: opacity 0.15s ease; }
.ps-ig-grid a:hover { opacity: 0.85; }
.ps-ig-grid img { display: block; width: 100%; height: auto; aspect-ratio: 1; object-fit: cover; }
.ps-ig-handle {
  margin: 0.75rem 0 0;
  font-size: var(--wp--preset--font-size--x-small);
  color: var(--wp--preset--color--mute);
}
.ps-ig-handle a { color: inherit; }


/* ── Andrew's Google Form (Connect) ─────────────────────────────────
   Embedded as Google gives it (Matt, 2026-09-25: "i'd rather embed his
   form"), so every change Andrew makes in Google shows here by itself.
   Google gives an embedded form no way to tell the page its height, so
   the frame is set to it — measured 1,282px at this 40rem column and
   1,363px on a phone, plus room. If he adds questions and a scrollbar
   appears inside the frame, raise these two numbers.
   ─────────────────────────────────────────────────────────────── */
.ps-gform {
  display: block;
  width: 100%;
  height: 1320px;
  border: 0;
}
@media (max-width: 600px) {
  .ps-gform { height: 1410px; }
}


/* ── Photographs: "One row of squares" gallery style ───────────────
   Matt, 2026-09-24, looking at twelve grey squares in two rows of six:
   "can be color", "centered", "maybe one row", then took three out.
   So the squares are in colour and share ONE row across the gallery's
   width, however many photographs it holds — nothing hangs in a
   half-empty second row, and a row that spans its column is centred by
   construction (the gallery is aligned Wide, the rule's width). Each one
   opens in core's lightbox, large and whole, with previous / next.

   Under 50rem one row would make postage stamps, so the squares go
   three across there, and a short last row sits in the middle.

   ⚠ The square is NOT the gallery's Aspect ratio setting, on purpose.
   Core copies that setting onto the enlarged image (image.php reads the
   thumbnail's inline style into the lightbox), so the lightbox showed a
   square crop of every photograph. A class-level square leaves the
   enlarged image its own shape. Setting an Aspect ratio on the gallery
   in the editor still wins over this (inline style), lightbox crop and
   all. Take the style off the gallery and everything goes back to
   core's cropped-row gallery.
   ─────────────────────────────────────────────────────────────── */
.wp-block-gallery.has-nested-images.is-cropped.is-style-row figure.wp-block-image:not(#individual-image) img {
  aspect-ratio: 1;
  height: auto;
  object-fit: cover;
}
.wp-block-gallery.has-nested-images.is-style-row {
  justify-content: center;
}
@media (min-width: 50rem) {
  .wp-block-gallery.has-nested-images.is-style-row {
    flex-wrap: nowrap;
  }
  .wp-block-gallery.has-nested-images.is-style-row figure.wp-block-image:not(#individual-image) {
    flex: 1 1 0;
    min-width: 0;
  }
}
@media (max-width: 49.99rem) {
  .wp-block-gallery.has-nested-images.is-style-row figure.wp-block-image:not(#individual-image) {
    flex-grow: 0;
    width: calc(33.333% - var(--wp--style--unstable-gallery-gap, 16px) * 0.66667);
  }
}

/* ── Lightbox: the whole photograph ────────────────────────────────
   Core sizes the enlarged frame to the thumbnail's DISPLAYED shape
   (view.js: container ratio = offsetWidth / offsetHeight of the
   thumbnail), so square thumbnails open as square crops, with no
   setting to change it. Here the frame shrink-wraps the image instead
   and the image takes its own shape, inside the same margins core
   uses: 320px across (room for the arrows) and 80px down above 960px,
   80 / 160 above 480px, 0 / 160 below.

   The zoom still starts from the thumbnail's corner at the thumbnail's
   height, so it reads as the crop opening out. If core renames these
   classes this simply stops applying and core's crop comes back.
   ─────────────────────────────────────────────────────────────── */
.wp-lightbox-overlay .lightbox-image-container {
  width: auto;
  height: auto;
}
.wp-lightbox-overlay .lightbox-image-container .wp-block-image img {
  width: auto;
  height: auto;
  min-width: 0;
  min-height: 0;
  max-width: 100vw;
  max-height: calc(100vh - 160px);
}
@media (min-width: 481px) {
  .wp-lightbox-overlay .lightbox-image-container .wp-block-image img {
    max-width: calc(100vw - 80px);
  }
}
@media (min-width: 961px) {
  .wp-lightbox-overlay .lightbox-image-container .wp-block-image img {
    max-width: calc(100vw - 320px);
    max-height: calc(100vh - 80px);
  }
}


/* ── Placeholder frames ────────────────────────────────────────────
   An empty frame standing in for something that does not exist yet —
   today, only the Donorbox form, until the campaign is created. A
   hairline box on the band tint, nothing more. It vanishes the moment
   the real thing is set, so it deliberately does not follow Global
   Styles beyond the palette.

   The ratio is stated here and only here: the frame holds no image,
   so there is no crop of Matt's to fight.
   ─────────────────────────────────────────────────────────────── */
.ps-frame {
  aspect-ratio: 3 / 2;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--wp--preset--spacing--30);
  background-color: var(--wp--preset--color--band);
  border: 1px solid var(--wp--preset--color--rule);
  color: var(--wp--preset--color--mute);
  font-size: var(--wp--preset--font-size--x-small);
  font-weight: 500;
  letter-spacing: 0.04em;
  line-height: 1.6;
}
.ps-frame p { margin: 0; max-width: 30ch; }


/* ── Unwritten copy ────────────────────────────────────────────────
   A block Matt has not written (the Contact slot, the 404 and empty-
   archive templates) renders in its real face at its real size, in the
   muted grey, with a small plate naming its block id. The grey is keyed
   to the plate (:has(code)), not the class: when Matt types over the
   placeholder the plate goes, and his words come out in normal ink even
   though the editor keeps the ps-ghost class on the block.
   ─────────────────────────────────────────────────────────────── */
.ps-ghost:has(code) { color: var(--wp--preset--color--mute); }

.ps-ghost code,
.ps-frame code {
  display: inline-block;
  vertical-align: middle;
  margin-inline-start: 0.6em;
  padding: 0.3em 0.55em;
  border: 1px solid var(--wp--preset--color--rule);
  border-radius: 0.2rem;
  background-color: var(--wp--preset--color--paper);
  color: var(--wp--preset--color--mute);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--wp--preset--font-size--x-small);
  font-weight: 500;
  letter-spacing: 0;
  line-height: 1.2;
  text-transform: none;
  white-space: nowrap;
}



/* ── Media-library images ──────────────────────────────────────────
   WordPress 6.7+ emits sizes="auto" on attachment images and ships
   `img:is([sizes=auto i]) { contain-intrinsic-size: 3000px 1500px }`,
   which computes to contain:size — so the box takes WordPress's
   placeholder and renders 1500px tall regardless of the real file.
   functions.php switches the attribute off; this covers cover blocks,
   which size their own image, in case it is ever switched back on.
   ─────────────────────────────────────────────────────────────── */
.wp-block-cover img.wp-block-cover__image-background {
  aspect-ratio: auto;
  contain: none;
  contain-intrinsic-size: auto none;
}


/* ── Footer logo lockup ────────────────────────────────────────────
   Speak Up's bubble (2.02:1) capped at 44px, with the Instagram icon.
   The 24-7 Prayer YC lockup moved to Who are we on 2026-09-27 (Matt:
   "remove ycp logo from footer and add just before the Meet the YCP
   Team link"), where the image block states its 1280/210 ratio.
   ─────────────────────────────────────────────────────────────── */
.ps-lockup { align-items: center; }
.ps-lockup img { height: auto; width: auto; object-fit: contain; }
.ps-lockup .ps-logo-speakup img  { max-height: 44px; }
.ps-lockup a { display: block; line-height: 0; transition: opacity 0.15s ease; }
.ps-lockup a:hover { opacity: 0.78; }


/* ── Print ─────────────────────────────────────────────────────── */
@media print {
  .wp-block-buttons, .ps-subscribe { display: none !important; }
}

/* The menu button below 780px, not just below WordPress's 600px (his "mobile versions of all the websites go to a mobile style
   menu … not just a weird compressed stacked nav bar", 2026-10-01): below ~780px the four links wrapped and "Give" broke in two. */
@media (min-width: 600px) and (max-width: 779px) {
  body .wp-block-navigation__responsive-container-open:not(.always-shown) { display: flex; }
  body .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) { display: none; }
}
