/* ==========================================================================
   isanctuaryug.org — shared design system
   Palette per an explicit "design exactly like this" reference (Template/
   home.png, about.png, trafficking.png - full mockups of these actual pages,
   colors sampled directly from them): a vivid, saturated green system
   (--teal/--teal-dark/--teal-darker now all sit on that green, not the
   earlier muted blue-teal), a neon-green accent for text on dark sections
   (--green-neon), and fully rounded pills/circles in place of the old boxy
   corners - a deliberate reversal of the earlier "boxy, not pill" rule
   elsewhere in this codebase's history, per the same reference.
   Lora for headings, Abhaya Libre for serif accents, Helvetica for body.
   Layout language (hero split, stat rows, rounded card grids, dark CTA
   bands) adapted from Media/Template/1.jpg + 2.jpg, restyled per the above.
   ========================================================================== */

:root {
  --bg: #FFFFFF;
  --bg-alt: #F1FBF7;
  --card-bg: #FFFFFF;
  --sage: #BDEFDC;
  --teal: #1FA971;
  --teal-dark: #12805A;
  --teal-darker: #023D35;
  --ink: #16241F;
  --ink-soft: #23362F;
  --muted: #4A5F5C;
  --border: rgba(31, 169, 113, 0.28);
  --gold: #D9A441;
  /* Text/accent color reserved for dark-green sections (hero, CTA bands,
     the dark pillars/services sections) - --teal reads fine on white but
     loses contrast on --teal-darker, so dark contexts get this instead
     (see .lead-word's dark-section overrides further down). */
  --green-neon: #00E676;

  --font-heading: "Lora", serif;
  --font-serif: "Abhaya Libre", serif;
  --font-body: "Helvetica", "Arial", sans-serif;

  --radius-lg: 24px;
  --radius-md: 16px;
  --radius-sm: 10px;
  --radius-pill: 999px;
  --shadow: 0 20px 60px rgba(31, 169, 113, 0.14), 0 8px 20px rgba(0, 0, 0, 0.05);
}

* { margin: 0; padding: 0; box-sizing: border-box; }
/* The browser's default [hidden]{display:none} is a UA-stylesheet rule, so
   any author rule that sets display on the same element (e.g. .story-blog-
   card's display:flex) silently wins over it regardless of specificity —
   toggling the `hidden` property via JS then does nothing visually. Force it
   back on top for every element site-wide. */
[hidden] { display: none !important; }

html { scroll-behavior: smooth; }

/* ---------- gentle scroll reveal (see main.js) ---------- */

.reveal { opacity: 0; transform: translateY(22px); transition: opacity 0.7s ease, transform 0.7s ease; }
.reveal.revealed { opacity: 1; transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
  .pillars-timeline .timeline-progress { height: 100%; transition: none; }
  .pillar-node { opacity: 1; transform: translate(-50%, -50%) scale(1); transition: none; }
  .pillar-title-desktop::after { transform: scaleX(1); transition: none; }
  h2::after { transform: scaleX(1); transition: none; }
  .section-header.center h2::after { transform: translateX(-50%) scaleX(1); }
}

body {
  background: var(--bg);
  color: var(--ink-soft);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.7;
  background-image:
    radial-gradient(circle at 8% 10%, rgba(164, 201, 191, 0.16) 0%, transparent 42%),
    radial-gradient(circle at 92% 60%, rgba(31, 169, 113, 0.09) 0%, transparent 50%);
  background-attachment: fixed;
}

/* Widened from 1180px per an explicit client complaint (backed by two
   reference sites they liked - raisingvoices.org, girlsnotbrides.org) that
   the site felt "boxed in the middle" on a wide screen instead of using the
   available width. Don't shrink this back down without being asked. */
.wrap {
  max-width: 1320px;
  margin: 0 auto;
  padding: 0 1.5rem;
}

img { max-width: 100%; display: block; }

h1, h2, h3, h4 { font-family: var(--font-heading); color: var(--ink); font-weight: 700; letter-spacing: -0.01em; line-height: 1.15; }
h1 { font-size: 3.4rem; }
/* Space below every h2 site-wide, not just inside .section-header - the
   global reset (* { margin: 0 }) otherwise left a heading sitting flush
   against whatever text follows it (a .split-copy's h2 + p, a quote block,
   a custom section, ...), everywhere a heading precedes body copy. */
h2 { font-size: 2.6rem; margin-bottom: 1.6rem; padding-bottom: 0.9rem; position: relative; }
/* A short accent bar under every h2, drawing in left-to-right once the
   heading's section scrolls into view - reuses the same .reveal/.revealed
   toggle main.js already applies to every "main > section" (no new JS),
   so this and the page's existing fade-up both fire off one observer.
   A fixed short width (not 100% of the heading) means it never has to
   account for how many lines a given heading wraps to - unlike
   .pillar-title-desktop::after, which can assume a single short line. */
h2::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  height: 3px;
  width: 3.5rem;
  background: var(--teal);
  border-radius: 2px;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.6s ease 0.15s;
}
/* A centered heading (.section-header.center) needs its underline centered
   under it too - left:0 would anchor to the h2's own full-width box, not
   the centered text inside it. */
.section-header.center h2::after { left: 50%; transform: translateX(-50%) scaleX(0); transform-origin: center; }
.reveal.revealed h2::after { transform: scaleX(1); }
.reveal.revealed .section-header.center h2::after { transform: translateX(-50%) scaleX(1); }
/* Brighter on a dark background - var(--teal) is close enough to
   .section-dark/.cta-band's own teal-darker fill to nearly disappear. */
.section-dark h2::after, .cta-band h2::after, .cta-band-photo h2::after { background: var(--green-neon); }
h3 { font-size: 1.5rem; }
h4 { font-size: 1.2rem; }

a { color: inherit; text-decoration: none; }

p { margin-bottom: 1rem; }
p:last-child { margin-bottom: 0; }

ul { list-style: none; }

/* ---------- buttons & badges ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.9rem 1.7rem;
  border-radius: var(--radius-pill);
  font-weight: 600;
  font-size: 0.95rem;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease, gap 0.15s ease;
}
/* Every button/button-styled link ends in a small arrow, per the reference
   mockups ("Learn More →", "Partner With Us →", "View Details →" -
   an explicit request covers *all* of them, not just the ones the mockups
   happened to show one on). A pseudo-element rather than typing "→" into
   every template means it can never be forgotten on a future button. */
.btn::after {
  content: "\2192";
  transition: transform 0.15s ease;
}
.btn:hover::after { transform: translateX(3px); }
.btn:hover { transform: translateY(-2px); }
/* Inline SVG instead of the &hearts; text glyph - guarantees the same heart
   renders everywhere regardless of whether a given platform's font/fallback
   chain happens to carry that Unicode glyph. */
.icon-heart { width: 0.85em; height: 0.85em; flex-shrink: 0; }

.btn-primary { background: var(--teal); color: #fff; box-shadow: 0 10px 24px rgba(31, 169, 113, 0.35); }
.btn-primary:hover { background: var(--teal-dark); }

.btn-outline { background: transparent; color: var(--teal-dark); border-color: var(--teal); }
.btn-outline:hover { background: rgba(31, 169, 113, 0.08); }

.btn-light { background: #fff; color: var(--teal-dark); }
.btn-light:hover { background: var(--bg-alt); }

/* for use over a dark photo (hero, cta-band-photo) where .btn-outline's dark
   teal text/border would disappear */
.btn-outline-light { background: transparent; color: #fff; border-color: rgba(255, 255, 255, 0.6); }
.btn-outline-light:hover { background: rgba(255, 255, 255, 0.12); }

.btn-cta-group { display: flex; flex-wrap: wrap; gap: 0.9rem; margin-top: 2rem; }

/* Glassmorphism - a frosted, translucent surface for the handful of elements
   that sit on top of a photo or need to stand out while floating over
   changing content: the hero's primary CTA, the always-visible nav Donate
   button, and the floating back-to-top button. Real backdrop-filter blur
   plus a light border/sheen, not just a flat transparent color. */
.hero .btn-primary {
  background: rgba(255, 255, 255, 0.16);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid rgba(255, 255, 255, 0.4);
  color: #fff;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
}
.hero .btn-primary:hover { background: rgba(255, 255, 255, 0.3); }

.nav-cta {
  background: rgba(31, 169, 113, 0.7);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(255, 255, 255, 0.4);
  box-shadow: 0 6px 20px rgba(31, 169, 113, 0.25);
}
.nav-cta:hover { background: rgba(31, 169, 113, 0.9); }

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  background: rgba(31, 169, 113, 0.12);
  color: var(--teal-dark);
  border: 1px solid var(--border);
  padding: 0.4rem 1rem;
  border-radius: var(--radius-pill);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  margin-bottom: 1.2rem;
}

/* ---------- header / nav ---------- */

.site-header {
  position: sticky;
  top: 0;
  /* Higher than #back-to-top's z-index (60) - .site-header creates its own
     stacking context (positioned + z-index), so the mobile nav panel and its
     backdrop nested inside it are only ever compared against the header's
     own z-index at the page level, regardless of their own (higher) values
     relative to each other. Without this, the backdrop could render behind
     - but still capture clicks in front of - the back-to-top button. */
  z-index: 70;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
}

.site-header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.9rem 1.5rem;
  gap: 1rem;
}

/* The brand logo is a full lockup (mark + wordmark baked into one image,
   uploaded via Admin -> Settings), not a small icon needing separate HTML
   text next to it — sized generously and flowed normally so it reads
   clearly against the header instead of being cropped down to icon size. */
.brand { display: flex; align-items: center; flex-shrink: 0; gap: 0.6rem; }
.brand-logo { height: 76px; width: auto; object-fit: contain; }
.brand-text { display: flex; align-items: baseline; gap: 0.3rem; flex-wrap: wrap; }
.brand-name { font-family: var(--font-heading); font-weight: 700; font-size: 1.4rem; color: var(--ink); letter-spacing: -0.01em; }
.brand-name span { font-weight: 400; color: var(--teal); }
.brand-domain { font-family: var(--font-heading); font-size: 0.85rem; color: var(--teal); }

.site-nav { display: flex; align-items: center; gap: 1.6rem; }
.site-nav a {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink-soft);
  padding: 0.3rem 0;
  border-bottom: 2px solid transparent;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.site-nav a:hover, .site-nav a.active { color: var(--teal-dark); border-bottom-color: var(--teal); }
.site-nav a.nav-cta { border-bottom: none; padding: 0.75rem 1.5rem; }
.site-nav a.nav-cta:hover { color: #fff; }

/* ---------- nav dropdowns (About, Media) ---------- */

.nav-dropdown { position: relative; }
.nav-dropdown-toggle {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  background: none;
  border: none;
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink-soft);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 0.3rem 0;
  border-bottom: 2px solid transparent;
  cursor: pointer;
}
.nav-dropdown-toggle:hover, .nav-dropdown-toggle.active, .nav-dropdown.open .nav-dropdown-toggle { color: var(--teal-dark); border-bottom-color: var(--teal); }
/* An open "v" chevron (stroke-drawn SVG, not a filled/solid triangle glyph)
   - matches the dropdown caret style in the reference sites the client
   shared, and renders identically everywhere unlike a Unicode glyph. */
.nav-caret { width: 0.65rem; height: 0.65rem; flex-shrink: 0; transition: transform 0.15s ease; }
.nav-dropdown.open .nav-caret { transform: rotate(180deg); }

/* Click-to-open only (JS in main.js) — deliberately NOT CSS :hover. A
   :hover-triggered menu has a well-known gap-closes-the-menu bug: moving the
   mouse from the toggle button down to the menu crosses a non-hovered gap
   (the visual margin-top below) and the menu disappears before the pointer
   ever reaches a link. Click-to-open (with an outside-click to close) has no
   such gap and is stable on both mouse and touch — don't reintroduce a
   `.nav-dropdown:hover .nav-dropdown-menu` rule. */
.nav-dropdown-menu {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-top: 0.9rem;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  padding: 0.5rem;
  min-width: 190px;
  display: none;
  z-index: 51;
}
.nav-dropdown.open .nav-dropdown-menu {
  display: flex;
  flex-direction: column;
}
.nav-dropdown-menu a {
  padding: 0.7rem 0.9rem !important;
  border-bottom: none !important;
  border-radius: var(--radius-sm);
  text-transform: uppercase !important;
  letter-spacing: 0.03em !important;
  font-size: 0.82rem !important;
}
.nav-dropdown-menu a:hover, .nav-dropdown-menu a.active { background: var(--bg-alt); color: var(--teal-dark) !important; }

.nav-toggle { display: none; }
.nav-burger { display: none; }
.nav-backdrop { display: none; }

/* ---------- hero ----------
   The photo is a true full-bleed background for the whole section (not just
   a right-hand column) — see Media/Template/1.jpg. A dark-to-transparent
   scrim sits over it left-to-right (bold white headline on the photo, per
   Media/Template/NEWW.jpg) so the text stays legible where it overlaps the
   photo, while the donate widget — an opaque white card — floats directly on
   the more-visible right side. Both the widget and the text sit in their own
   absolutely-positioned layers so their vertical position is independent of
   each other. Collapses to a simple stacked layout on narrower screens
   (below). */

.hero {
  position: relative;
  min-height: 620px;
  padding: 4.5rem 0;
  overflow: hidden;
  /* Vertically centers the headline block in the photo instead of pinning it
     to the top, which left a large empty band underneath the buttons. */
  display: flex;
  align-items: center;
}

.hero-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}

.hero-scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  /* Centered text (see .hero-copy below) can land anywhere across the photo
     depending on viewport width, not just the left side - a darkened zone
     around the middle, fading out toward the edges, keeps it legible
     wherever it sits instead of only darkening one side. */
  background: radial-gradient(ellipse 75% 65% at 50% 45%,
    rgba(2, 61, 53, 0.82) 0%,
    rgba(2, 61, 53, 0.66) 45%,
    rgba(2, 61, 53, 0.48) 75%,
    rgba(2, 61, 53, 0.36) 100%);
}

.hero-inner {
  position: relative;
  z-index: 2;
  width: 100%;
  /* Per an explicit request - the headline block sits centered in the hero
     rather than anchored left. */
  display: flex;
  justify-content: center;
}

.hero-copy { max-width: 900px; text-align: center; }
.hero-copy .btn-cta-group { justify-content: center; }

/* The whole statement ("Freedom isn't just leaving exploitation behind It's
   having the power to choose what comes next.") reads as one plain sentence
   at one size, no separate word/line treatment. A soft dark text-shadow
   keeps it legible over the photo regardless of what's behind it. */
.hero h1 {
  font-size: clamp(2rem, 3.2vw, 3rem);
  margin-bottom: 1.8rem;
  color: #fff;
  text-shadow: 0 2px 18px rgba(10, 18, 16, 0.75), 0 0 3px rgba(10, 18, 16, 0.45);
}
.hero-body {
  max-width: 620px;
  margin: -1rem auto 1.8rem;
  color: rgba(255, 255, 255, 0.92);
  font-size: 1.05rem;
  line-height: 1.6;
  text-shadow: 0 2px 14px rgba(10, 18, 16, 0.7), 0 0 3px rgba(10, 18, 16, 0.4);
}

/* ---------- tagline strip (below hero) ---------- */

.tagline-strip {
  padding: 3.2rem 0;
  text-align: center;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.tagline-strip p {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 1.15rem;
  line-height: 1.8;
  color: var(--ink-soft);
}
.tagline-strip p span { color: var(--teal-dark); }

/* ---------- dark action bar (below hero, per Media/Template/NEWW.jpg) ---------- */

.action-bar { background: var(--teal-darker); color: #fff; padding: 1.6rem 0; }
.action-bar-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1.2rem 2rem;
}
.action-bar-inner h3 { color: #fff; font-size: 1.25rem; max-width: 420px; }
.action-bar-divider { width: 1px; align-self: stretch; background: rgba(255, 255, 255, 0.2); display: none; }
.action-bar-contact { display: flex; align-items: center; gap: 0.8rem; }
.action-bar-contact .icon {
  width: 2.6rem;
  height: 2.6rem;
  flex-shrink: 0;
  background: #fff;
  color: var(--teal-darker);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
}
.action-bar-contact .label { font-size: 0.78rem; opacity: 0.8; }
.action-bar-contact .value { font-weight: 700; font-size: 1.05rem; }

/* ---------- about badge / mini checklist / avatar row (About section) ---------- */

/* Shrink-wrapped and centered in its column rather than stretched full
   width - needed so a height-capped (see .split img above) image's corner
   badge still lands on the image's own corner instead of the empty space
   where the uncapped box used to extend to. */
/* width: var(--img-w-desktop, fit-content) - falls back to the normal
   fit-content sizing unless Admin's per-image "Desktop width" field set a
   custom property inline on this element (see split_media_size_attr() in
   includes/content.php) - every section that doesn't use that field renders
   identically to before. */
.split-media { position: relative; width: var(--img-w-desktop, fit-content); max-width: 100%; justify-self: center; }
.image-badge {
  position: absolute;
  right: 1.4rem;
  bottom: 1.4rem;
  background: rgba(2, 61, 53, 0.55);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(255, 255, 255, 0.3);
  color: #fff;
  border-radius: var(--radius-md);
  padding: 1rem 1.3rem;
  text-align: center;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.2);
}
.image-badge .value { display: block; font-family: var(--font-heading); font-size: 1.8rem; font-weight: 700; line-height: 1; }
.image-badge .label { font-size: 0.75rem; opacity: 0.85; margin-top: 0.2rem; }

.mini-checklist-card {
  display: flex;
  align-items: stretch;
  gap: 1.2rem;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 1rem;
  margin: 1.4rem 0;
  box-shadow: 0 8px 24px rgba(31, 169, 113, 0.08);
}
.split .mini-checklist-card img { width: 110px; aspect-ratio: 1 / 1; border-radius: var(--radius-sm); object-fit: cover; box-shadow: none; flex-shrink: 0; }
.mini-checklist-card .check-grid { grid-template-columns: 1fr; gap: 0.5rem; align-self: center; }
.mini-checklist-card .check-item { font-size: 0.9rem; }

.avatar-row { display: flex; align-items: center; gap: 0.8rem; margin-top: 1.4rem; }
.avatar-row .avatars { display: flex; }
.avatar-row .avatars img {
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px var(--border);
  margin-left: -0.6rem;
}
.avatar-row .avatars img:first-child { margin-left: 0; }
.avatar-row a { font-weight: 700; font-size: 0.9rem; color: var(--teal-dark); }
.avatar-row a:hover { text-decoration: underline; }

/* ---------- stats row with dividers (light section, no card chrome) ---------- */

.stats-row-dividers {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 2.5rem;
}
.stats-row-dividers .stat {
  display: flex;
  align-items: baseline;
  gap: 0.9rem;
  padding-right: 2.5rem;
  border-right: 1px solid var(--border);
}
.stats-row-dividers .stat:last-child { border-right: none; padding-right: 0; }
.stats-row-dividers .stat .stat-icon { width: 1.8rem; height: 1.8rem; align-self: center; color: var(--teal); flex-shrink: 0; }
.stats-row-dividers .stat .value { font-family: var(--font-heading); font-size: 2.4rem; font-weight: 700; color: var(--teal); }
.stats-row-dividers .stat .label { font-size: 0.85rem; color: var(--muted); max-width: 130px; line-height: 1.35; }

/* ---------- dark service cards (per NEWW.jpg's "Our Services" section) ---------- */

.dark-services-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1.2rem;
  margin-bottom: 2.5rem;
}
.dark-services-header .eyebrow { color: var(--sage); background: rgba(255, 255, 255, 0.1); border-color: rgba(255, 255, 255, 0.15); }
.dark-services-header h2 { color: #fff; }
.dark-services-header p { color: rgba(255, 255, 255, 0.75); max-width: 460px; }

.dark-service-card {
  position: relative;
  display: block;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(31, 169, 113, 0.4);
  border-radius: var(--radius-md);
  padding: 1.6rem 1.6rem 1.8rem;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.dark-service-card:hover { background: rgba(255, 255, 255, 0.09); border-color: rgba(31, 169, 113, 0.7); }
.dark-service-card-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.6rem;
  height: 2.6rem;
  margin-bottom: 1rem;
  border-radius: var(--radius-sm);
  background: var(--green-neon);
  color: var(--teal-darker);
}
.dark-service-card-icon svg { width: 1.4rem; height: 1.4rem; }
.dark-service-card h3 { color: #fff; font-size: 1.3rem; margin: 0 0 0.7rem 0; }
.dark-service-card p { color: rgba(255, 255, 255, 0.7); font-size: 0.92rem; margin-bottom: 1rem; }
.dark-service-card .check-item { color: rgba(255, 255, 255, 0.85); font-size: 0.88rem; }
.dark-service-card .check-item .tick { background: rgba(255, 255, 255, 0.16); color: #fff; }

/* ---------- generic section rhythm ---------- */

.section { padding: 4.5rem 0; }
.section[id] { scroll-margin-top: 90px; }
.section-alt { background: var(--bg-alt); }

/* A broad, soft-edged organic shape sweeping diagonally through the
   section - a wave of tonal variation in the section's own color family,
   not a distinct graphic. The clipping (overflow:hidden) lives on a
   dedicated .blob-decor-bg layer, a sibling of .wrap rather than the
   <section> itself - position:sticky breaks on any element whose ancestor
   chain crosses an overflow:hidden box, and several of these sections also
   have a sticky split-media image, so the <section> stays overflow:visible
   and the blobs get their own absolutely-positioned clipping box instead.
   .blob-decor-dark is the same idea in lighter tones, for a dark section. */
.blob-decor { position: relative; }
.blob-decor-bg { position: absolute; inset: 0; overflow: hidden; z-index: 0; pointer-events: none; }
.blob-decor-bg::before,
.blob-decor-bg::after {
  content: "";
  position: absolute;
  border-radius: 42% 58% 61% 39% / 45% 36% 64% 55%;
  filter: blur(70px);
}
.blob-decor-bg::before {
  width: 65%;
  height: 55%;
  top: -18%;
  left: -18%;
  background: rgba(31, 169, 113, 0.16);
  transform: rotate(-8deg);
}
.blob-decor-bg::after {
  width: 55%;
  height: 50%;
  bottom: -20%;
  right: -14%;
  background: rgba(2, 61, 53, 0.1);
  transform: rotate(12deg);
}
.blob-decor.blob-warm .blob-decor-bg::before { background: rgba(217, 164, 65, 0.18); }
.blob-decor > .wrap { position: relative; z-index: 1; }

.blob-decor-dark .blob-decor-bg::before { background: rgba(255, 255, 255, 0.06); }
.blob-decor-dark .blob-decor-bg::after { background: rgba(0, 230, 118, 0.1); }
.section-header { max-width: 720px; margin-bottom: 2.5rem; }
.section-header h2 { font-size: 2.7rem; }
.section-header p { color: var(--muted); font-size: 1.05rem; }
.section-header.center { margin-left: auto; margin-right: auto; text-align: center; }

.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 3rem;
  align-items: center;
}
/* No forced aspect-ratio box - a box sized for one ratio and an image of a
   different one is exactly what caused the "sitting in a white card" look
   (a visible gap around the photo even with a transparent fill). Sizing to
   the image's own natural proportions means it always fills its rounded
   frame edge to edge, with nothing to crop and nothing to pad. */
/* Capped at roughly square - the tallest a portrait photo is allowed to
   render next to its text column (a landscape image is already shorter
   than this and is untouched; only a tall/portrait one gets scaled down,
   width:auto, so it shrinks as a whole - never cropped). The cap tracks
   the actual split column's width with the same arithmetic .wrap/.split
   use to size it (max-width 1320px, 2x 1.5rem wrap padding, 3rem gap,
   2 equal columns), so "square" holds at any viewport, not just one. */
.split img {
  display: block;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: calc((min(100vw, 1320px) - 96px) / 2);
  margin: 0 auto;
}
/* Every .split image - illustration or photo alike - now gets the same
   rounded-corner + shadow "card" treatment above (an explicit request to
   look consistent, like the Home/Our Approach photo); .cutout is kept as a
   harmless marker in the markup rather than stripped everywhere, in case a
   future image genuinely needs the uncropped look back. */
.split.reverse .split-media { order: -1; }

/* For a split whose text column runs much longer than its image (About's
   Our Story / Our Approach, now several paragraphs long) - the image stays
   pinned in view as you scroll through the text instead of being a short
   visual stranded at the top of a tall, mostly-empty column. */
.split.sticky-media { align-items: start; }
.split.sticky-media .split-media { position: sticky; top: 6.5rem; }

/* ---------- point / checklist ---------- */

.point-list { display: flex; flex-direction: column; gap: 0.8rem; margin-top: 1.2rem; }
.point-list.cols-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0.8rem 1.2rem; }
.point-list li {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.9rem 1.1rem;
  font-size: 0.98rem;
}
.point-list li::before {
  content: "✓";
  flex-shrink: 0;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  background: var(--teal);
  color: #fff;
  font-size: 0.75rem;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 0.1rem;
}
.point-list.plain li { background: transparent; border: none; padding: 0.2rem 0; }
.point-list.plain li::before { background: var(--sage); color: var(--teal-darker); }

/* lightweight checklist — icon + text, no card chrome (used for Our Impact, and
   inside the photo CTA band) */
.check-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.7rem 2rem;
}
.check-item {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  color: var(--ink-soft);
  font-size: 0.98rem;
}
.check-item .tick {
  flex-shrink: 0;
  width: 1.4rem;
  height: 1.4rem;
  border-radius: 50%;
  background: rgba(31, 169, 113, 0.14);
  color: var(--teal-dark);
  font-size: 0.7rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ---------- card grid ---------- */

.card-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.6rem; }
.card-grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
.card-grid.cols-4 { grid-template-columns: repeat(4, 1fr); }

.card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  box-shadow: 0 8px 24px rgba(31, 169, 113, 0.08);
  display: flex;
  flex-direction: column;
}
.card-media { aspect-ratio: 16/11; overflow: hidden; }
.card-media img { width: 100%; height: 100%; object-fit: cover; }
.card-body { padding: 1.4rem 1.5rem 1.7rem; flex: 1; display: flex; flex-direction: column; }
.card-number { font-family: var(--font-heading); font-size: 1.6rem; color: var(--sage); font-weight: 700; margin-bottom: 0.4rem; }
.card-body h3 { font-size: 1.4rem; margin-bottom: 0.5rem; }
.card-body .card-intro { color: var(--teal-dark); font-weight: 600; font-size: 0.92rem; margin-bottom: 0.6rem; }
.card-body .card-note { margin-top: auto; padding-top: 0.8rem; color: var(--muted); font-size: 0.88rem; font-style: italic; }

/* simple text-only cards (no media), e.g. trafficking forms */
.card.plain { padding: 1.6rem 1.5rem; }
.card.plain h3 { font-size: 1.05rem; }

/* trafficking forms — icon + label cards, 3-up desktop, 2-up mobile */
.trafficking-form-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.2rem; }
.trafficking-form-card {
  display: flex;
  align-items: flex-start;
  gap: 0.9rem;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 1.2rem 1.3rem;
}
.trafficking-form-card h3 { font-size: 1rem; margin: 0; }
.trafficking-form-explanation { font-size: 0.85rem; color: var(--muted); margin-top: 0.35rem; line-height: 1.4; }
.trafficking-form-icon {
  flex-shrink: 0;
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 50%;
  background: rgba(31, 169, 113, 0.12);
  color: var(--teal-dark);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Myth/Fact comparison cards (trafficking.json's "myths" section) - each
   card pairs the misconception with the correction, visually separated so
   they read as two distinct claims rather than one run-on paragraph. */
.myth-fact-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.4rem; margin-top: 0.5rem; }
.myth-fact-card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 1.5rem 1.6rem;
  box-shadow: 0 8px 24px rgba(31, 169, 113, 0.06);
}
.myth-fact-card .myth-line,
.myth-fact-card .fact-line { display: flex; gap: 0.9rem; align-items: flex-start; }
.myth-fact-card .myth-line {
  padding-bottom: 1rem;
  margin-bottom: 1rem;
  border-bottom: 1px dashed var(--border);
}
.myth-fact-card .myth-line p { margin: 0; color: var(--muted); font-style: italic; }
.myth-fact-card .fact-line p { margin: 0; color: var(--ink-soft); }
.myth-tag, .fact-tag {
  flex-shrink: 0;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 0.3rem 0.65rem;
  border-radius: var(--radius-pill);
  margin-top: 0.1rem;
}
.myth-tag { background: rgba(217, 164, 65, 0.16); color: #8a6414; }
.fact-tag { background: rgba(31, 169, 113, 0.14); color: var(--teal-dark); }
.trafficking-form-icon svg { width: 1.4rem; height: 1.4rem; }

/* Our Work's Four Pillars: an image-beside-text row per pillar (reuses
   .split, alternating .reverse), now a light timeline instead of a dark card
   block — a central spine runs behind every row with a numbered node per
   pillar, the spine's fill animating in as the section scrolls into view
   (.in-view is toggled by IntersectionObserver in main.js). */
.pillars-timeline { position: relative; }
.pillars-timeline::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 3px;
  background: var(--border);
  transform: translateX(-50%);
}
.pillars-timeline .timeline-progress {
  /* Height is set directly from scroll position every frame (see main.js) -
     not a CSS transition - so the line draws and un-draws exactly in step
     with scrolling in either direction rather than firing once and sitting
     "done" while you keep scrolling through the rest of the pillars. The
     short transition only smooths between animation frames. */
  position: absolute;
  top: 0;
  left: 50%;
  width: 3px;
  height: 0;
  background: var(--teal);
  transform: translateX(-50%);
  transition: height 0.05s linear;
}

.pillar-row { position: relative; margin-bottom: 3.5rem; }
.pillar-row:last-child { margin-bottom: 0; }
.pillar-node {
  position: absolute;
  top: 2.6rem;
  left: 50%;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3.2rem;
  height: 3.2rem;
  border-radius: 50%;
  background: var(--teal);
  color: #fff;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1.2rem;
  box-shadow: 0 0 0 6px var(--bg), 0 8px 20px rgba(31, 169, 113, 0.3);
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.4);
  transition: opacity 0.35s ease, transform 0.35s ease;
}
.pillar-row.revealed .pillar-node { opacity: 1; transform: translate(-50%, -50%) scale(1); }

/* An underline that draws in under each pillar's title once its row is
   revealed, and retracts the same way the node does when scrolled back
   past - alternating rows draw from the opposite edge to match their
   left/right zigzag. */
.pillar-title-desktop {
  position: relative;
  display: inline-block;
  padding-bottom: 0.3rem;
}
.pillar-title-desktop::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  height: 3px;
  width: 100%;
  background: var(--teal);
  border-radius: 2px;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.6s ease 0.15s;
}
.pillar-row.reverse .pillar-title-desktop::after { transform-origin: right; }
.pillar-row.revealed .pillar-title-desktop::after { transform: scaleX(1); }

/* .pillar-caption is the mobile-only "01 Employment" overlay on the image —
   hidden on desktop, where the title already reads fine as plain text at the
   top of .split-copy (see the 900px breakpoint below for the swap). */
.pillar-caption { display: none; }

/* Each pillar's What We Do / What She Gains / Longer-Term Change subheads. */
.pillar-subhead {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--teal-dark);
  margin: 0 0 0.3rem;
}

/* The line connecting why one pillar leads into the next - sits right on
   the spine, breaking it with a small pill so the copy reads as part of the
   timeline rather than a floating caption. */
.pillar-connector {
  position: relative;
  max-width: 420px;
  margin: -1.6rem auto 2rem;
  padding: 0.5rem 1.1rem;
  text-align: center;
  font-style: italic;
  font-family: var(--font-serif);
  color: var(--muted);
  font-size: 0.92rem;
  background: var(--bg);
}

/* ---------- team ---------- */

/* Centered at every width, unlike most .section-header.center instances
   (which the mobile "left-aligned content" block further down deliberately
   flips back to left on phones) - this one's an explicit exception, so the
   extra .team-header class gives it enough specificity (3 classes) to beat
   that block's 2-class .section-header.center rule regardless of source
   order, without changing the shared default other pages still rely on. */
.section-header.center.team-header { text-align: center; margin-left: auto; margin-right: auto; }
/* The closing line below the grid - centered and a step larger than body
   text so it reads as a closing statement, not a trailing caption. */
.team-outro { margin-top: 2rem; text-align: center; font-size: 1.2rem; color: var(--ink-soft); }

.team-section { position: relative; overflow: hidden; }
.team-decor-leaf, .team-decor-wave { position: absolute; pointer-events: none; opacity: 0.6; z-index: 0; }
.team-decor-leaf { top: -1rem; right: -1rem; width: 220px; height: 220px; }
.team-decor-wave { bottom: 0; left: -2rem; width: 320px; height: 160px; }
.team-section > .wrap { position: relative; z-index: 1; }

/* Three per row, wrapping to a centered (not left-stuck) remainder row -
   flexbox rather than CSS grid specifically so a 5th/8th/etc member doesn't
   leave an orphan card stranded alone on the left; justify-content:center
   centers whatever's left on the last row automatically, for any team size. */
.team-grid { display: flex; flex-wrap: wrap; justify-content: center; gap: 1.6rem; }
.team-card {
  width: calc(33.333% - 1.1rem);
  min-width: 220px;
  background: var(--card-bg);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow);
  text-align: left;
}
.team-photo { aspect-ratio: 4 / 5; }
.team-photo img { display: block; width: 100%; height: 100%; object-fit: cover; }
.team-card-body { padding: 1.2rem 1.3rem 1.4rem; }
.team-card h3 { font-size: 1.2rem; margin-bottom: 0.6rem; white-space: normal; overflow-wrap: break-word; }
.team-card-divider { display: block; width: 2rem; height: 3px; margin-bottom: 0.7rem; background: var(--teal); border-radius: 2px; }
.team-card .role { color: var(--ink-soft); font-size: 0.92rem; font-weight: 500; white-space: normal; overflow-wrap: break-word; line-height: 1.4; }

/* ---------- quote / affirmation gallery ---------- */

.gallery-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.2rem 1rem;
  max-width: 820px;
  margin: 0 auto;
}
.gallery-grid img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow);
}

.quote-block {
  background: var(--teal-darker);
  color: #fff;
  border-radius: var(--radius-lg);
  padding: 2.6rem;
  font-family: var(--font-serif);
  font-size: 1.3rem;
  font-style: italic;
  line-height: 1.6;
}

/* ---------- stat row ---------- */

.stat-bar {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
  background: var(--teal-darker);
  border-radius: var(--radius-lg);
  padding: 2rem;
  color: #fff;
}
.stat-chip { text-align: center; padding: 0.6rem; }
.stat-chip .stat-icon { width: 1.7rem; height: 1.7rem; margin: 0 auto 0.5rem; color: var(--green-neon); }
.stat-chip .value { display: block; font-family: var(--font-heading); font-size: 1.8rem; font-weight: 700; margin-bottom: 0.2rem; }
.stat-chip .label { font-size: 0.85rem; opacity: 0.85; }

/* ---------- CTA band ---------- */

.cta-band {
  background: linear-gradient(135deg, var(--teal-darker), var(--teal-dark));
  color: #fff;
  border-radius: var(--radius-lg);
  padding: 3.2rem;
  text-align: center;
}
.cta-band h2 { color: #fff; }
.cta-band p { color: rgba(255,255,255,0.85); max-width: 620px; margin: 0.8rem auto 0; }
.cta-band .btn-cta-group { justify-content: center; }
.cta-band .btn-outline { color: #fff; border-color: rgba(255,255,255,0.5); }
.cta-band .btn-outline:hover { background: rgba(255,255,255,0.1); }

/* ---------- misc content blocks ---------- */

.prose { font-size: 1.02rem; color: var(--ink-soft); }
.prose p { margin-bottom: 1.1rem; }

/* A short italic reflection right under a stat block (Our Work's "Why 30
   Women", "Our Measure of Success", Trafficking's "The Longer Journey") -
   was three copies of the same inline style with one accidentally sized
   differently from the other two. One shared class instead, so they can't
   drift apart again. */
.closing-statement {
  margin-top: 1.4rem;
  font-style: italic;
  font-family: var(--font-serif);
  color: var(--teal-dark);
  font-size: 1.05rem;
}

/* Small-print note directly under a stat row (a detection caveat, a source
   citation) - same role wherever it appears, so one size for all of them. */
.stat-footnote {
  margin-top: 1rem;
  font-size: 0.85rem;
  color: var(--muted);
}

/* The first word of a page-section heading (h2) reads italic and regular
   weight against the rest of the heading's bold upright text - a light
   typographic accent used consistently across every section heading,
   e.g. "*Specialised*, long-term aftercare..." / "*Leaving* exploitation
   is only the first step." Applied via e_lead_word() in includes/content.php
   rather than hand-wrapping each heading's first word in markup, so it can
   never be applied inconsistently from one section to the next. */
.lead-word { font-style: italic; font-weight: 400; color: var(--teal); }
/* On a dark-green section, --teal loses contrast against --teal-darker -
   the reference mockups use a much brighter neon green for this same
   heading accent whenever it sits on a dark background. */
.pattern-bg .lead-word,
.pillars-dark .lead-word,
.cta-band .lead-word,
.cta-band-photo .lead-word,
.dark-services-header .lead-word { color: var(--green-neon); }

.two-col-highlight { display: grid; grid-template-columns: 1fr 1fr; gap: 1.6rem; margin-top: 1rem; }
.highlight-box {
  background: var(--sage);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 1.8rem;
}
.highlight-box h3 { font-size: 1.1rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--teal-dark); margin-bottom: 0.6rem; }
.highlight-box p { font-family: var(--font-serif); font-size: 1.15rem; font-style: italic; color: var(--ink); }

/* Mission/Vision (About Us) - a round icon badge beside the title+quote
   instead of stacked, per the reference mockup. A modifier on the shared
   .highlight-box rather than changes to its base rules, since donate-
   confirm.php and Trafficking's Legal Framework box both use plain
   .highlight-box on its own. */
.highlight-box-icon { display: flex; align-items: flex-start; gap: 1.1rem; }
.highlight-box-icon .icon-badge {
  flex-shrink: 0;
  width: 2.8rem;
  height: 2.8rem;
  border-radius: 50%;
  background: var(--teal-darker);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
}
.highlight-box-icon .icon-badge svg { width: 1.4rem; height: 1.4rem; }
.highlight-box-icon h3 { text-transform: none; letter-spacing: normal; font-size: 1.45rem; color: var(--ink); font-family: var(--font-heading); margin-bottom: 0.5rem; }
.highlight-box-icon p { font-size: 1.25rem; line-height: 1.5; }
.legal-icon { width: 1.3rem; height: 1.3rem; flex-shrink: 0; color: var(--teal); }

.notice-box {
  background: rgba(217, 164, 65, 0.12);
  border: 1px dashed var(--gold);
  border-radius: var(--radius-sm);
  padding: 1rem 1.2rem;
  font-size: 0.92rem;
  color: #7a5a1f;
  margin-top: 1rem;
}

/* ---------- CTA band with background photo ---------- */

.cta-band-photo {
  position: relative;
  background-size: cover;
  background-position: center;
  isolation: isolate;
  text-align: left;
}
.cta-band-photo::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(2, 61, 53, 0.94) 0%, rgba(2, 61, 53, 0.86) 30%, rgba(2, 61, 53, 0.45) 62%, rgba(2, 61, 53, 0.08) 100%);
  z-index: -1;
  border-radius: inherit;
}
.cta-band-photo .cta-content { max-width: 460px; }
.cta-band-photo h2 { font-size: 2.3rem; }
.cta-band-photo p { margin: 0.6rem 0 0; }
.cta-band-photo .check-grid { margin: 1.3rem 0 1.6rem; grid-template-columns: 1fr; gap: 0.5rem; }
.cta-band-photo .check-grid .check-item { color: rgba(255, 255, 255, 0.92); }
.cta-band-photo .check-grid .check-item .tick { background: rgba(255, 255, 255, 0.18); color: #fff; }
.cta-band-photo .btn-cta-group { justify-content: flex-start; }

/* Two-column variant of .cta-content - text+button on the left, a 2x2 icon
   grid of "ways to help" on the right, instead of everything stacked in one
   left-aligned column - per the reference mockup's "Why Partner With
   Omugaso?" band. .cta-content-copy keeps the 460px reading width .cta-
   content itself used to set directly; the grid gets the rest. */
.cta-content-split { display: grid; grid-template-columns: minmax(0, 460px) 1fr; gap: 2.5rem; align-items: center; max-width: none; }
.cta-ways-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.8rem 2.2rem; }
.cta-way-item { display: flex; align-items: center; gap: 1rem; }
.cta-way-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3.2rem;
  height: 3.2rem;
  flex-shrink: 0;
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.16);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(255, 255, 255, 0.35);
  color: var(--green-neon);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.12);
}
.cta-way-icon svg { width: 1.7rem; height: 1.7rem; }
.cta-way-item strong { display: block; color: #fff; font-size: 0.95rem; }
.cta-way-item span { color: #fff; font-size: 1.1rem; font-weight: 600; font-family: var(--font-heading); }

/* Full-bleed variant: the band itself spans the full browser width edge to
   edge (no rounded corners, no outer margin) instead of sitting as a
   rounded card floating inside .wrap with pale page background visible on
   both sides - one of the specific "boxed in the middle" patterns the
   reference sites (raisingvoices.org, girlsnotbrides.org) avoid. Add
   alongside .cta-band.cta-band-photo, and move the markup so the section
   itself carries this class with .wrap nested *inside* it (for the text
   only), rather than the band being nested inside .wrap. */
.cta-band-full { border-radius: 0; padding: 4rem 0; }

/* Events page "Partner With Us" - a small grid of glass-style cards filling
   the split-media slot in place of a photo (5 items: 2 columns, the 5th
   floats to a new row on its own). */
.partner-ways-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; align-content: start; }
.partner-way-card {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 1rem;
  background: rgba(255, 255, 255, 0.5);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(31, 169, 113, 0.25);
  border-radius: var(--radius-md);
  box-shadow: 0 8px 24px rgba(31, 169, 113, 0.08);
}
.partner-way-card span:last-child { font-weight: 600; color: var(--ink); font-size: 0.95rem; }
.partner-way-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.6rem;
  height: 2.6rem;
  flex-shrink: 0;
  border-radius: var(--radius-sm);
  background: rgba(31, 169, 113, 0.16);
  color: var(--teal-dark);
}
.partner-way-icon svg { width: 1.3rem; height: 1.3rem; }

/* ---------- events ---------- */

.events-list { display: flex; flex-direction: column; gap: 0.9rem; max-width: 780px; margin: 0 auto; }
.event-item {
  display: flex;
  align-items: center;
  gap: 1.2rem;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 1rem 1.2rem;
}
.event-date {
  flex-shrink: 0;
  width: 60px;
  text-align: center;
  background: var(--teal-darker);
  color: #fff;
  border-radius: var(--radius-sm);
  padding: 0.5rem 0;
}
.event-date .day { display: block; font-family: var(--font-heading); font-size: 1.3rem; font-weight: 700; line-height: 1; }
.event-date .month { display: block; font-size: 0.7rem; letter-spacing: 0.06em; opacity: 0.85; margin-top: 0.2rem; }
.event-info { flex: 1; }
.event-info h3 { font-size: 1.05rem; margin-bottom: 0.15rem; }
.event-info .event-location { color: var(--muted); font-size: 0.88rem; }
.event-info .event-description { color: var(--ink-soft); font-size: 0.92rem; margin-top: 0.4rem; }
.event-item .btn { flex-shrink: 0; padding: 0.55rem 1.1rem; font-size: 0.85rem; }
.event-item-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; flex-shrink: 0; }

/* Home's "Upcoming Events" preview only - a 3-column card grid instead of
   the plain stacked list events.php itself uses (its own layout, unaffected
   - this is an additive modifier on the shared .events-list/.event-item,
   not a change to their defaults). Each card stacks its date badge, title,
   location and button vertically instead of the wide single-column row. */
.events-grid { max-width: none; }
@media (min-width: 769px) {
  .events-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1.4rem;
  }
  .events-grid .event-item {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.8rem;
    height: 100%;
  }
  .events-grid .event-item-actions { width: 100%; flex-direction: column; }
  .events-grid .event-item .btn { width: 100%; }
}

/* ---------- news ---------- */

.news-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.4rem; }
.news-card { background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--radius-md); overflow: hidden; }
.news-card img { aspect-ratio: 16/10; object-fit: cover; width: 100%; }
.news-card-body { padding: 1.1rem 1.2rem 1.3rem; }
.news-card-body .news-date { font-size: 0.78rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.news-card-body h3 { font-size: 1.02rem; margin-top: 0.3rem; }

/* ---------- newsletter band ---------- */

.newsletter-band { background: var(--teal-darker); color: #fff; padding: 2.6rem 0; }
.newsletter-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
  flex-wrap: wrap;
}
.newsletter-band h2 { color: #fff; font-size: 1.5rem; }
.newsletter-band p { color: rgba(255,255,255,0.8); margin-top: 0.3rem; }
.newsletter-form { display: flex; gap: 0.6rem; flex-wrap: wrap; }
.newsletter-form input[type="email"] {
  padding: 0.8rem 1.1rem;
  border-radius: var(--radius-pill);
  border: none;
  min-width: 260px;
  font-family: var(--font-body);
  font-size: 0.95rem;
}
.newsletter-flash { padding-top: 0.8rem; font-size: 0.88rem; color: #fff; }
.newsletter-flash-error { color: #ffd3d3; }

/* ---------- donation form ---------- */

.donate-form { max-width: 620px; margin: 2rem auto 0; text-align: center; }

.donate-amounts {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.8rem;
  margin-bottom: 1.4rem;
}

.donate-amount-option {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  background: var(--card-bg);
  border: 2px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 0.7rem 1.3rem;
  cursor: pointer;
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--ink-soft);
  transition: border-color 0.15s ease, background 0.15s ease;
}
.donate-amount-option input[type="radio"] { accent-color: var(--teal); width: 16px; height: 16px; }
.donate-amount-option:has(input:checked) { border-color: var(--teal); background: rgba(31, 169, 113, 0.1); color: var(--teal-dark); }

.donate-amount-custom { flex-direction: column; align-items: stretch; text-align: left; border-radius: var(--radius-sm); }
.donate-amount-custom .custom-label { font-size: 0.85rem; color: var(--muted); }
.donate-amount-custom input[type="number"] {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.5rem 0.7rem;
  font-family: var(--font-body);
  font-size: 0.95rem;
  width: 140px;
}

.donate-submit { width: 100%; max-width: 320px; }
.donate-payment-note { margin-top: 1rem; font-size: 0.85rem; color: var(--muted); }

/* ---------- generic form fields (e.g. event registration) ---------- */

.field { margin-bottom: 1.1rem; }
.field label { display: block; font-weight: 600; font-size: 0.9rem; color: var(--ink-soft); margin-bottom: 0.4rem; }
.field input, .field textarea {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.7rem 0.9rem;
  font-family: var(--font-body);
  font-size: 0.95rem;
  background: var(--card-bg);
}
.field input:focus, .field textarea:focus { outline: 2px solid var(--teal); outline-offset: 1px; }
.field textarea { resize: vertical; }

/* ---------- survivor story blog cards (listing) ---------- */

.story-filter { display: flex; flex-wrap: wrap; justify-content: flex-start; gap: 0.7rem; margin-bottom: 2.2rem; }
.story-filter-btn {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 0.6rem 1.3rem;
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--ink-soft);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.story-filter-btn:hover { border-color: var(--teal); }
.story-filter-btn.active { background: var(--teal); border-color: var(--teal); color: #fff; }

.story-blog-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.6rem; }
.story-blog-card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  box-shadow: 0 8px 24px rgba(31, 169, 113, 0.08);
}
.story-blog-card img { aspect-ratio: 16/10; width: 100%; object-fit: cover; }
/* Text-only variant (Stories page cards) - no photo, so the body padding
   needs a bit more breathing room at the top since it's now the card's
   first visible element instead of sitting below an image. */
.story-blog-card-text .story-blog-body { padding-top: 1.8rem; }
.story-blog-card .story-blog-body { padding: 1.3rem 1.4rem 1.6rem; flex: 1; display: flex; flex-direction: column; }
.story-blog-card .story-blog-tag {
  display: inline-block;
  align-self: flex-start;
  background: rgba(31, 169, 113, 0.12);
  color: var(--teal-dark);
  border-radius: var(--radius-pill);
  padding: 0.25rem 0.7rem;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 0.7rem;
}
.story-blog-card h3 { font-size: 1.3rem; margin-bottom: 0.15rem; }
.story-blog-card .story-blog-tagline { color: var(--teal-dark); font-weight: 600; font-size: 0.88rem; margin-bottom: 0.7rem; }
.story-blog-card .story-blog-excerpt { color: var(--muted); font-size: 0.92rem; flex: 1; margin-bottom: 1rem; }
.story-blog-card .story-blog-link { font-weight: 700; font-size: 0.88rem; color: var(--teal-dark); }
.story-blog-card .story-blog-link:hover { text-decoration: underline; }

/* ---------- survivor story detail page ---------- */

.story-detail-hero img { width: 100%; aspect-ratio: 21/9; object-fit: contain; border-radius: var(--radius-lg); box-shadow: var(--shadow); margin-bottom: 2rem; }
.story-detail-tagline { color: var(--teal-dark); font-weight: 600; font-size: 1.1rem; margin-bottom: 1.6rem; font-family: var(--font-serif); font-style: italic; }
.story-detail-body { max-width: 720px; margin: 0 auto; }
.story-detail-body .prose { font-size: 1.03rem; }
.story-detail-body .prose p { margin-bottom: 1.1rem; }

.partner-list { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.8rem; }
.partner-list span {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 0.6rem 1.3rem;
  font-weight: 600;
  font-size: 0.92rem;
  color: var(--ink-soft);
}

/* ---------- reusable dark pattern background ---------- */

/* The decorative pattern behind the footer, generalized so any dark section
   can use it (.action-bar, the "Our Work" services section, About's
   Mission/Vision, Our Work's Four Pillars) — fully visible at the top,
   fading down into solid --teal-darker so content lower in a tall section
   still has a plain, readable background. Apply alongside whatever class
   already sets the section's dark background color; add `pattern-bg` to the
   element and wrap its content in `.wrap` (or give the direct child
   `z-index:1` manually) so text sits above the image/gradient layers. */
.pattern-bg { position: relative; overflow: hidden; }
.pattern-bg::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: url('../images/footer-pattern.jpg');
  background-size: cover;
  background-position: center top;
  opacity: 0.5;
  z-index: 0;
}
.pattern-bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(2, 61, 53, 0.3) 0%, var(--teal-darker) 85%);
  z-index: 0;
}
.pattern-bg > .wrap { position: relative; z-index: 1; }

/* A custom section set to Dark background in Admin (see render_bg_toggle()
   in admin/includes/editor.php) - white text on the dark teal-darker +
   pattern-bg texture, matching the hero-style dark intro band in the
   reference mockups (Trafficking's "Human Trafficking in Uganda: What Is
   It?"). Always paired with pattern-bg in the markup for the texture/bg
   color; this rule only handles text contrast. */
.section-dark h2, .section-dark h3 { color: #fff; }
.section-dark .prose, .section-dark .prose p { color: rgba(255, 255, 255, 0.85); }
.section-dark .eyebrow { color: var(--sage); background: rgba(255, 255, 255, 0.12); border-color: rgba(255, 255, 255, 0.2); }
.section-dark .lead-word { color: var(--green-neon); }

/* ---------- partners collage (sitewide, above the footer) ---------- */

.partners-band { padding: 3.5rem 0; background: var(--bg-alt); }
.partners-collage { display: grid; grid-template-columns: repeat(5, 1fr); column-gap: 0.1rem; row-gap: 0.5rem; }
.partner-tile {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 160px;
  padding: 0.5rem;
}
.partner-tile img { max-height: 92px; max-width: 100%; object-fit: contain; }
.partner-tile .partner-name { font-weight: 700; font-size: 1.1rem; text-align: center; color: var(--ink-soft); }

/* ---------- footer ---------- */

.site-footer {
  background: var(--teal-darker);
  padding: 3.5rem 0 0;
  color: rgba(255, 255, 255, 0.78);
}
.footer-grid, .footer-copyright { position: relative; z-index: 1; }

.footer-grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: 2rem;
  padding-bottom: 2.5rem;
}
/* The uploaded logo file is a flat JPG with its own opaque white
   background (not transparent), and dark ink linework/wordmark - both would
   disappear (or invert into a solid black block) straight against the
   footer's dark teal, so it sits in a small white card instead, the same
   way a light-background logo commonly gets placed on a dark section. */
.footer-logo-card {
  display: block;
  width: fit-content;
  background: #fff;
  padding: 0.6rem 1rem;
  margin-bottom: 1rem;
  line-height: 0;
}
.footer-logo { height: 76px; width: auto; }
.footer-brand .brand-name, .footer-brand .brand-domain { color: #fff; }
.footer-brand .brand-name span { color: var(--sage); }
.footer-brand p { margin-top: 0.8rem; color: rgba(255, 255, 255, 0.72); font-size: 0.9rem; }
.footer-col { display: flex; flex-direction: column; gap: 0.6rem; }
.footer-col h4 { font-size: 1rem; font-family: var(--font-heading); color: var(--green-neon); margin-bottom: 0.6rem; }
.footer-col a, .footer-col span { color: rgba(255, 255, 255, 0.72); font-size: 0.92rem; }
.footer-col a:hover { color: var(--sage); }

.footer-copyright {
  border-top: 1px solid rgba(255, 255, 255, 0.16);
  padding: 1.4rem 1.5rem 1.6rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.9rem;
  color: rgba(255, 255, 255, 0.65);
}
.razertech-logo { height: 40px; width: auto; }

/* ---------- back to top ---------- */

.back-to-top {
  position: fixed;
  right: 1.5rem;
  bottom: 1.5rem;
  z-index: 60;
  width: 2.8rem;
  height: 2.8rem;
  border: 1px solid rgba(255, 255, 255, 0.4);
  border-radius: var(--radius-sm);
  background: rgba(31, 169, 113, 0.65);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  color: #fff;
  font-size: 1.2rem;
  cursor: pointer;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.18);
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s, background 0.15s ease;
}
.back-to-top.visible { opacity: 1; visibility: visible; transform: translateY(0); }
.back-to-top:hover { background: rgba(18, 128, 90, 0.85); }

/* ---------- popup banner (Admin -> Popup Banners) ---------- */

.promo-banner-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background: rgba(10, 18, 16, 0.6);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.25s ease, visibility 0.25s;
}
.promo-banner-overlay.visible { opacity: 1; visibility: visible; }
/* [hidden] (no banner live) must win over the .visible toggle above, since
   JS only ever adds/removes .visible on an element that already passed the
   PHP active_banner() check and so never carries [hidden] itself - this is
   just a hard belt-and-braces stop against an empty overlay ever painting. */
.promo-banner-overlay[hidden] { display: none !important; }
.promo-banner {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  width: 100%;
  max-width: 760px;
  max-height: 90vh;
  overflow: auto;
  background: var(--card-bg);
  border-radius: var(--radius-lg);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.35);
  transform: scale(0.96) translateY(8px);
  transition: transform 0.25s ease;
}
.promo-banner-overlay.visible .promo-banner { transform: scale(1) translateY(0); }
/* No image set for this banner - one column, centered, rather than the
   copy half sitting alone in a 2-column grid with an empty second cell. */
.promo-banner:has(.promo-banner-copy:only-child) { grid-template-columns: 1fr; max-width: 480px; }
.promo-banner-media { position: relative; min-height: 260px; background: var(--sage); }
.promo-banner-media img { width: 100%; height: 100%; object-fit: cover; position: absolute; inset: 0; }
.promo-banner-copy { position: relative; padding: 2.4rem 2.2rem; text-align: center; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.promo-banner-copy .eyebrow { margin-bottom: 0.8rem; }
.promo-banner-copy h2 { font-size: 2rem; margin-bottom: 0.6rem; padding-bottom: 0; }
.promo-banner-copy h2::after { display: none; }
.promo-banner-subheading { color: var(--muted); font-size: 1rem; margin-bottom: 1.4rem; }
.promo-banner-actions { display: flex; flex-wrap: wrap; gap: 0.8rem; justify-content: center; width: 100%; }
.promo-banner-note { margin-top: 1.2rem; font-size: 0.78rem; color: var(--muted); }
.promo-banner-close {
  position: absolute;
  top: 0.8rem;
  right: 0.8rem;
  width: 2.2rem;
  height: 2.2rem;
  border-radius: 50%;
  border: none;
  background: var(--bg-alt);
  color: var(--ink);
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.promo-banner-close:hover { background: var(--border); }

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */

@media (max-width: 1024px) {
  .card-grid, .card-grid.cols-4 { grid-template-columns: repeat(2, 1fr); }
  .stat-bar { grid-template-columns: repeat(2, 1fr); }
  .team-card { width: calc(50% - 0.8rem); }
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .news-grid { grid-template-columns: 1fr 1fr; }
  .story-blog-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 900px) {
  .cta-content-split { grid-template-columns: 1fr; gap: 1.8rem; }

  /* Image on top (capped height, not the roughly-half-the-card it gets on
     desktop) with the text below, rather than a cramped side-by-side -
     there's no room left to read anything otherwise once a photo claims
     half a phone-width popup. */
  .promo-banner { grid-template-columns: 1fr; max-width: 420px; }
  .promo-banner-media { min-height: 160px; }
  .promo-banner-copy { padding: 2rem 1.4rem; }
  .promo-banner-copy h2 { font-size: 1.6rem; }

  /* The square-max cap above is sized for the desktop 2-column .split -
     .split stacks to one full-width column below this breakpoint, so the
     cap no longer applies; images go back to their natural proportions. */
  .split img { width: 100%; max-width: none; max-height: none; margin: 0; }
  .split-media { width: var(--img-w-mobile, 100%); }

  /* Hamburger opens a half-width side panel (not a full-width dropdown) that
     slides in from the left, with a dimmed backdrop covering the other half
     of the screen. The backdrop is itself a <label for="nav-toggle"> - the
     same checkbox the burger button toggles - so tapping anywhere outside
     the panel closes it again with no JS required. */
  .site-nav {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 50vw;
    max-width: 340px;
    background: var(--bg);
    border-right: 1px solid var(--border);
    flex-direction: column;
    align-items: flex-start;
    padding: 5.5rem 1.5rem 2rem;
    gap: 0.9rem;
    display: flex;
    overflow-y: auto;
    z-index: 95;
    transform: translateX(-100%);
    transition: transform 0.28s ease;
    box-shadow: 12px 0 32px rgba(0, 0, 0, 0.18);
  }
  .nav-toggle:checked ~ .site-nav { transform: translateX(0); }

  .nav-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(15, 26, 24, 0.45);
    z-index: 90;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.28s ease, visibility 0.28s;
  }
  .nav-toggle:checked ~ .nav-backdrop { opacity: 1; visibility: visible; }

  /* Dropdowns become an inline expandable section within the stacked mobile
     menu instead of a floating popover (hover doesn't exist on touch, and a
     centered absolute menu doesn't make sense in a vertical list). */
  .nav-dropdown { width: 100%; }
  .nav-dropdown-toggle { width: 100%; justify-content: space-between; }
  .nav-dropdown-menu {
    position: static;
    transform: none;
    margin-top: 0.6rem;
    margin-left: 0.8rem;
    box-shadow: none;
    border: none;
    border-left: 2px solid var(--border);
    border-radius: 0;
    padding: 0 0 0 0.8rem;
    display: none;
  }
  .nav-dropdown.open .nav-dropdown-menu { display: flex; }
  .nav-burger {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    width: 26px;
    height: 22px;
    cursor: pointer;
  }
  .nav-burger span, .nav-burger::before, .nav-burger::after {
    content: "";
    display: block;
    height: 2px;
    background: var(--ink);
    border-radius: 2px;
  }

  /* Nudged up ~1cm from its desktop position so it clears mobile browser
     chrome (address bar / home-indicator area) a bit more comfortably. */
  .back-to-top { bottom: calc(1.5rem + 2cm); }

  .split { grid-template-columns: 1fr; }
  .split .split-media, .split.reverse .split-media { order: -1; }
  .split.sticky-media .split-media { position: static; }
  .two-col-highlight { grid-template-columns: 1fr; }

  /* Our Work's pillar rows: the "01 Employment" heading moves onto the photo
     instead of appearing as plain text below it — swap the desktop text for
     the image-overlay caption. The timeline spine/nodes are a desktop-only
     effect (the alternating zigzag they connect stacks to one column here),
     so they're hidden rather than left pinned to a now-meaningless center. */
  .pillar-row .pillar-title-desktop { display: none; }
  /* Needs to match (0,3,0) specificity, same as .split.sticky-media
     .split-media above, to actually win - position:relative here is what
     the mobile photo caption overlay below needs to anchor correctly.
     top must be reset too: unlike position:static (which ignores offset
     properties entirely), position:relative still honors the desktop
     rule's "top: 6.5rem" it inherits otherwise - that was silently
     shoving every pillar photo 104px down into its own row's text below,
     a mobile-only overlap invisible on desktop where position stays sticky. */
  .pillar-row.sticky-media .split-media { position: relative; top: 0; }
  .pillars-timeline::before, .pillars-timeline .timeline-progress, .pillar-node { display: none; }
  .pillar-connector { background: none; }
  .pillar-caption {
    display: block;
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 2.5rem 1.2rem 1.2rem;
    background: linear-gradient(180deg, transparent 0%, rgba(10, 18, 16, 0.85) 100%);
  }
  .pillar-caption .card-number { display: block; color: var(--sage); font-family: var(--font-heading); font-weight: 700; font-size: 1.3rem; }
  .pillar-caption h3 { color: #fff; margin: 0; }

  /* Mobile hero: stays a full-bleed photo (not a stacked column — the photo
     must stay visible per an explicit request). The min-height keeps a real
     slice of it tall enough to read as a photo even with the headline and
     both CTA buttons stacked on top of it. The desktop scrim is a radial
     gradient centered for a wide viewport; on a narrow phone that reads as
     mostly-uniform dark, so it's swapped here for a top-to-bottom gradient
     (dark behind the headline, easing off lower down) so a real slice of
     the photo actually reads as a photo. */
  .hero { min-height: 520px; padding: 3.5rem 0 2.5rem; align-items: flex-start; }
  .hero-scrim {
    background: linear-gradient(180deg,
      rgba(2, 61, 53, 0.82) 0%,
      rgba(2, 61, 53, 0.68) 38%,
      rgba(2, 61, 53, 0.38) 68%,
      rgba(2, 61, 53, 0.55) 100%);
  }
  .hero-copy .btn-cta-group { justify-content: center; margin-top: 1.4rem; }
}

@media (max-width: 768px) {
  .hero h1 { font-size: 1.9rem; margin-bottom: 1.1rem; }
  .section-header h2 { font-size: 2.1rem; }

  /* A pill button at full padding/radius reads oversized once its text
     wraps to 2 lines on a narrow phone (the long CTA labels - "See How
     Trafficking Connects to Our Work" and similar - always do) - smaller
     padding/radius keeps it proportionate at 1 or 2 lines alike. */
  .btn { padding: 0.75rem 1.3rem; font-size: 0.88rem; border-radius: var(--radius-md); }

  /* The "Why Partner With Omugaso?" ways-to-help grid (render_join_band(),
     shared by every page's closing CTA band): a 2-column icon+text grid has
     no minmax(0, 1fr) on its tracks, so each column's automatic minimum is
     its own content's min-content width - on a narrow phone that minimum
     (icon + "Volunteer opportunities") is wider than half the available
     space, so the grid (and everything nested inside .cta-content-split
     above it) overflowed the viewport instead of shrinking, clipping text
     off the right edge. One column removes the unshrinkable 2-up minimum. */
  .cta-ways-grid { grid-template-columns: 1fr; gap: 1rem; }
  .cta-band-photo h2 { font-size: 1.7rem; }

  /* Events page's own "Partner With Us" ways grid - same unshrinkable
     2-column minimum-width overflow as .cta-ways-grid above, same fix. */
  .partner-ways-grid { grid-template-columns: 1fr; }
  .partner-way-card { padding: 0.8rem; }
  .card-grid, .card-grid.cols-2, .card-grid.cols-4 { grid-template-columns: 1fr; }
  .myth-fact-grid { grid-template-columns: 1fr; }
  .trafficking-form-grid { grid-template-columns: 1fr 1fr; gap: 0.8rem; }
  .trafficking-form-card { padding: 0.9rem 1rem; flex-direction: column; text-align: center; gap: 0.5rem; }
  .trafficking-form-card h3 { font-size: 0.88rem; }
  .stat-bar { grid-template-columns: repeat(2, 1fr); padding: 1.2rem; gap: 0.6rem; }
  .stat-chip { padding: 0.4rem; }
  .stat-chip .stat-icon { width: 1.3rem; height: 1.3rem; margin-bottom: 0.3rem; }
  .stat-chip .value { font-size: 1.25rem; }
  .stat-chip .label { font-size: 0.72rem; }
  .gallery-grid { grid-template-columns: repeat(2, 1fr); }
  /* One full-width card per row, not three - a card that narrow left each
     headshot too small to read clearly on a phone-width screen. */
  .team-card { width: 100%; min-width: 0; }
  .footer-grid { grid-template-columns: 1fr 1fr; gap: 1.8rem 1.2rem; }
  .partners-collage { grid-template-columns: repeat(3, 1fr); }
  .footer-brand { grid-column: 1 / -1; }
  .cta-band { padding: 2.2rem 1.5rem; }
  .quote-block { padding: 1.8rem; font-size: 1.1rem; }
  .news-grid { grid-template-columns: 1fr; }
  .story-blog-grid { grid-template-columns: 1fr; }
  .story-detail-tagline { font-size: 1rem; }
  .check-grid { grid-template-columns: 1fr; }
  .point-list.cols-2 { grid-template-columns: 1fr; }
  .cta-band-photo .cta-content { max-width: none; }
  .event-item { flex-wrap: wrap; }
  .event-item-actions { width: 100%; }
  .event-item .btn { width: 100%; text-align: center; }
  .newsletter-inner { flex-direction: column; align-items: flex-start; }
  .newsletter-form { width: 100%; }
  .newsletter-form input[type="email"] { flex: 1; min-width: 0; }

  .action-bar-inner { flex-direction: column; align-items: flex-start; text-align: left; }
  /* .mini-checklist-card intentionally keeps its desktop side-by-side layout
     at every width — see the .hero-copy note above, same explicit request.
     The photo itself still shrinks though - at the full 110px it was
     cropping a disproportionate, overly-tight slice of the image inside a
     card not much wider than that. */
  .split .mini-checklist-card img { width: 72px; }
  .mini-checklist-card { gap: 0.8rem; padding: 0.8rem; }
  .mini-checklist-card .check-item { font-size: 0.82rem; }
  .stats-row-dividers { flex-direction: column; align-items: flex-start; gap: 1.2rem; }
  .stats-row-dividers .stat {
    width: 100%;
    border-right: none;
    padding-right: 0;
    padding-bottom: 1.2rem;
    border-bottom: 1px solid var(--border);
  }
  .stats-row-dividers .stat:last-child { border-bottom: none; padding-bottom: 0; }
  .stats-row-dividers .stat .value { font-size: 1.9rem; white-space: nowrap; }
  .stats-row-dividers .stat .label { max-width: none; }
  .dark-services-header { align-items: flex-start; }
  /* Shrunk further on mobile - at the desktop-ish size this badge covered a
     third of a now full-width, already-shorter photo and crowded its
     2-line label against the image edges. */
  .image-badge { right: 0.6rem; bottom: 0.6rem; padding: 0.5rem 0.75rem; max-width: 72%; }
  .image-badge .value { font-size: 1.1rem; }
  .image-badge .label { font-size: 0.7rem; }
  /* About's "2007" badge specifically sits on top of its photo on mobile,
     not the bottom-right corner every other badge uses. */
  .image-badge-top-mobile { top: 0.6rem; bottom: auto; }
}

@media (max-width: 480px) {
  body { font-size: 15px; }
  .section { padding: 3rem 0; }
  .hero h1 { font-size: 1.6rem; margin-bottom: 0.9rem; }
  .section-header h2 { font-size: 1.8rem; }
  .brand-logo { height: 56px; }
  .brand-name { font-size: 1.1rem; }
  .gallery-grid { grid-template-columns: repeat(2, 1fr); }
  /* Stays inline/2-column (copyright left, Razertech logo right) rather than
     stacking - a deliberate request, kept compact via smaller text/logo
     below rather than by dropping to one column. */
  .footer-copyright { font-size: 0.78rem; gap: 0.6rem; }
  .razertech-logo { height: 30px; }
}

/* ---------- mobile: left-aligned content ----------
   On phones, section headings, paragraphs, stats, cards and closing notes
   read left-aligned (per an explicit request) rather than centered as on
   desktop. Deliberately still centered: text *inside* buttons, icon
   circles, and the day/month date badge - centering is right for those.
   Kept as one block at the end of the file so it wins over the desktop
   centering rules above; the attribute selector catches the many one-off
   inline `style="text-align:center"` paragraphs/wrappers in the page
   templates and content.php's custom-section block. */
@media (max-width: 768px) {
  .section-header.center { margin-left: 0; margin-right: 0; text-align: left; }
  .tagline-strip,
  .cta-band,
  .cta-band .cta-content,
  .stat-bar,
  .stat-chip,
  .pillar-connector,
  .donate-form,
  .notice-box,
  .highlight-box,
  .trafficking-form-card { text-align: left; }
  .wrap [style*="text-align:center"],
  .section [style*="text-align:center"] { text-align: left !important; }
  .trafficking-form-card { align-items: flex-start; }
  .story-filter,
  .donate-amounts { justify-content: flex-start; }
  .donate-payment-note { text-align: left; }
}
