/*
 * Page-body layout kit (Plan 03.5).
 *
 * Where components.css is "chrome + primitives" (header, nav, footer, buttons,
 * cards), this file is "page-body sections": the reusable vocabulary that
 * Plan 04+ compose pages from — section rhythm, hero, impact-stat band, card
 * grid, feature split, CTA band and media/gallery grid.
 *
 * Same rules as the rest of the project's CSS:
 *   - Every colour comes from a tokens.css custom property — never a literal
 *     hex, never rgba(), never the dark-mode media query. Translucent tints are
 *     derived from a token with color-mix(), so a token change reflows the whole
 *     kit and both themes come for free.
 *   - All directional spacing uses CSS logical properties (inline/block-start
 *     /end), so dir="rtl" mirrors every section automatically — no RTL sheet.
 *   - Motion is limited to a hover lift on interactive cards and is removed
 *     under prefers-reduced-motion (brand-guidelines.md §7).
 */

/* --- Section rhythm --------------------------------------------------------
   Page-body sections get a more generous vertical rhythm than the base
   `section` rule (base.css) — healthcare calm, whitespace carrying the page
   (brand-guidelines.md §4). Backgrounds are full-bleed; an inner `.wrapper`
   (base.css) holds the max-width and inline padding. */
.section {
  padding-block: var(--space-8);
}

.section--tinted {
  background-color: var(--color-accent-soft-bg);
}

/* Page-scoped rhythm override for a page made up of several short,
   header-less sections stacked back to back (the daily report page) — cuts
   the sitewide `--space-8` gap down to `--space-4` (both existing tokens on
   the `tokens.css` scale, no new value invented) without touching `.section`
   itself, which longer pages still rely on. */
.section--snug {
  padding-block: var(--space-4);
}

/* The Teal-Deep "dark band" (donate band family) — always the deep teal
   ground in both themes, like the footer, so it reads as one visual family
   rather than "dark mode" logic. Text/links switch to the light-on-dark
   footer tokens. */
.section--dark {
  background-color: var(--color-teal-deep);
  color: var(--color-footer-text);
}

.section--dark a {
  color: var(--color-pale-aqua);
}

/* --- Eyebrow + section header ---------------------------------------------- */
.eyebrow {
  font-family: var(--font-heading);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: var(--font-size-xs);
  font-weight: 600;
  color: var(--color-brand);
  margin-block: 0 var(--space-1);
}

.section-header {
  margin-block-end: var(--space-4);
}

.section-header__title {
  max-width: 32rem;
  margin-block: 0;
}

/* Header row with a trailing "view all" link (media grid, etc.). */
.section-header--inline {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.section-link {
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

/* --- Home wordmark ----------------------------------------------------------
   Small, scoped home-page-prominence fix (Plan 11): the org name is otherwise
   never shown as visible text near the top of the home page (the header logo
   is a wordless mark; the hero's eyebrow/headline are free text). Plain,
   compact — no redesign, just a visible name above the hero. */
.home-wordmark {
  padding-block-start: var(--space-3);
}

.home-wordmark__text {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: var(--font-size-sm);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--color-brand);
  margin-block: 0;
}

/* --- Hero -----------------------------------------------------------------
   Single column by default (mobile-first); two columns from the primary-nav
   breakpoint up (56rem, matching components.css). */
.hero__inner {
  display: grid;
  gap: var(--space-4);
  align-items: center;
}

.hero__title {
  margin-block: 0 var(--space-2);
}

.hero__intro {
  font-size: var(--font-size-md);
  color: var(--color-text-soft);
  max-width: 34rem;
  margin-block: 0 var(--space-4);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
}

.hero__tagline {
  font-family: var(--font-urdu-display);
  font-size: var(--font-size-lg);
  color: var(--color-brand);
  margin-block: var(--space-4) 0;
}

/* --media-ratio must match the caller's Wagtail rendition (hero_block.html's
   fill-760x950) so object-fit never has to crop in practice. */
.hero__media {
  position: relative;
  --media-ratio: 4 / 5;
}

/* One framed-image treatment for every media slot. The slot wrapper sets
   --media-ratio once; the loaded image and the unset-state placeholder
   (same fallback chain, below) reserve the identical box, so neither the
   image arriving nor the placeholder swap ever shifts layout. */
.hero__image,
.feature-split__image,
.card__photo img {
  display: block;
  width: 100%;
  aspect-ratio: var(--media-ratio, 1 / 1);
  object-fit: cover;
  border-radius: var(--card-radius);
}

/* Floating stat card, tucked over the media's leading edge. Uses logical
   `inset-inline-start` so it flips to the right under RTL. */
.hero__stat-card {
  position: absolute;
  inset-inline-start: calc(-1 * var(--space-3));
  inset-block-end: var(--space-3);
  padding: var(--space-2) var(--space-3);
}

.hero__stat-value {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: var(--font-size-lg);
  color: var(--color-brand);
  font-variant-numeric: tabular-nums;
  margin-block: 0;
}

.hero__stat-label {
  font-size: var(--font-size-xs);
  color: var(--color-text-soft);
  margin-block: 0;
}

@media (min-width: 56rem) {
  .hero__inner {
    grid-template-columns: 1.05fr 0.95fr;
    gap: var(--space-8);
  }
}

/* --- Impact-stat band ------------------------------------------------------
   A flex row rather than a fixed-column grid: `page.headline_stats` (or the
   CMS-editable ImpactStatsBlock) can hand this any number of stats, and a
   short row of `1fr` grid tracks left-justifies instead of centering when
   there are fewer items than columns. `justify-content: center` on a flex row
   centers the whole row regardless of count, so a 3-stat report and a 4-stat
   one both land centered without hard-coding either number. */
.stat-band__grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-4) var(--space-2);
  text-align: center;
}

.stat-band__grid .stat {
  flex: 0 1 calc(50% - var(--space-2) / 2);
}

.stat__value {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: var(--font-size-2xl);
  line-height: 1;
  color: var(--color-stat-value);
  font-variant-numeric: tabular-nums;
  margin-block: 0;
}

.stat__label {
  font-size: var(--font-size-xs);
  color: var(--color-text-soft);
  margin-block: var(--space-1) 0;
}

.stat-band__caption {
  text-align: center;
  font-size: var(--font-size-xs);
  color: var(--color-text-faint);
  margin-block: var(--space-3) 0;
}

.stat-band__empty {
  text-align: center;
  margin-block: 0;
}

@media (min-width: 56rem) {
  .stat-band__grid {
    gap: var(--space-4);
  }

  .stat-band__grid .stat {
    flex: 0 1 calc(25% - var(--space-4) * 3 / 4);
  }
}

/* --- Card grid ------------------------------------------------------------
   `.card` itself lives in components.css; this arranges it into a responsive
   2/3/4-up grid and adds the icon slot, status tag and hover lift. */
.card-grid {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: 1fr;
}

.card-grid__empty {
  margin-block: 0;
}

@media (min-width: 40rem) {
  .card-grid--2,
  .card-grid--3,
  .card-grid--4 {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 56rem) {
  .card-grid--3 {
    grid-template-columns: repeat(3, 1fr);
  }

  .card-grid--4 {
    grid-template-columns: repeat(4, 1fr);
  }
}

.card__icon {
  width: 2.75rem;
  height: 2.75rem;
  border-radius: var(--card-radius);
  background-color: var(--color-accent-soft-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-block-end: var(--space-2);
}

.card__tag {
  display: inline-block;
  font-family: var(--font-heading);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-size: var(--font-size-xs);
  font-weight: 600;
  color: var(--color-brand);
  background-color: var(--color-accent-soft-bg);
  border-radius: 999px;
  padding: 0.15em 0.75em;
  margin-block-end: var(--space-1);
}

.card__title {
  margin-block: 0 var(--space-1);
}

.card__body {
  color: var(--color-text-soft);
  margin-block: 0;
}

/* Person / service card photo slot. The image (styled by the shared media-slot
   rule under the hero section; 1/1 via the --media-ratio default) or, when
   unset, the shared `.media-placeholder` fills the slot; the card padding
   frames it. */
.card__photo {
  margin-block-end: var(--space-2);
}

/* Role line on a person card, between the name and the bio. */
.card__subtitle {
  color: var(--color-brand);
  font-size: var(--font-size-sm);
  font-weight: 600;
  margin-block: 0 var(--space-1);
}

/* Organisational-partner logo slot (Donors & Partners page / Donate page
   carousel) — landscape rather than the person-card's 1/1, since a logo
   crops badly to a square. Sets --media-ratio for the shared image rule and
   the placeholder's aspect-ratio fallback alike (see the media-slot comment
   above .hero__media). */
.logo-card__logo {
  --media-ratio: 2 / 1;
}

/* Hover lift — interactive cards only, gated below for reduced motion. */
.card--interactive {
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.card--interactive:hover {
  transform: translateY(-3px);
  box-shadow: 0 6px 22px color-mix(in srgb, var(--color-teal-deep) 16%, transparent);
}

/* --- Feature split --------------------------------------------------------
   Media beside text; `--reverse` swaps their order (uses `order`, which the
   grid honours in both LTR and RTL). */
.feature-split {
  display: grid;
  gap: var(--space-4);
  align-items: center;
}

/* Callers passing media_image must pair it with a ~16:9 rendition
   (e.g. fill-1200x675) so the shared image rule's cover never crops. */
.feature-split__media {
  --media-ratio: 16 / 9;
}

.feature-split__stats {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-block: var(--space-2) var(--space-3);
}

.feature-split__body p {
  color: var(--color-text-soft);
}

.feature-split__link {
  font-weight: 600;
  text-decoration: none;
}

@media (min-width: 56rem) {
  .feature-split {
    grid-template-columns: 1fr 1.15fr;
    gap: var(--space-6);
  }

  .feature-split--reverse .feature-split__media {
    order: 2;
  }
}

/* --- CTA band ------------------------------------------------------------- */
.cta-band__inner {
  display: grid;
  gap: var(--space-4);
  align-items: center;
}

.cta-band__heading {
  color: var(--color-footer-text);
  margin-block: 0 var(--space-2);
}

.cta-band__body {
  color: var(--color-pale-aqua);
  max-width: 34rem;
  margin-block: 0;
}

.cta-band__actions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
}

.cta-band__note {
  font-size: var(--font-size-xs);
  color: var(--color-footer-text-soft);
  margin-block: 0;
}

@media (min-width: 56rem) {
  .cta-band__inner {
    grid-template-columns: 1.2fr 0.8fr;
    gap: var(--space-6);
  }
}

/* --- Media / gallery grid -------------------------------------------------- */
.media-grid {
  display: grid;
  gap: var(--space-2);
  grid-template-columns: repeat(2, 1fr);
}

.media-grid__empty {
  margin-block: 0;
}

@media (min-width: 56rem) {
  .media-grid--3 {
    grid-template-columns: repeat(3, 1fr);
  }

  .media-grid--4 {
    grid-template-columns: repeat(4, 1fr);
  }
}

.media-grid__item {
  aspect-ratio: 1 / 1;
  border-radius: var(--card-radius);
  overflow: hidden;
}

.media-grid__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The click-to-expand trigger wrapping each real photo — reset to a plain,
   borderless block the same size as its `.media-grid__item` box so the
   button is invisible until interacted with; opens templates/partials/
   lightbox.html's <dialog> via static/js/lightbox.js. */
.media-grid__trigger {
  display: block;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}

/* The cell wrapping each grid slot (Plan 06) — a plain block, so the grid
   still sizes columns off `.media-grid`; `.media-grid__item` keeps its own
   fixed-aspect image treatment, unaffected by whether a caption follows. */
.media-grid__cell {
  margin: 0;
}

.media-grid__caption {
  font-size: var(--font-size-xs);
  color: var(--color-text-faint);
  margin-block: var(--space-1) 0;
}

/* --- Lightbox --------------------------------------------------------------
   The shared <dialog> from templates/partials/lightbox.html. Sizing/position
   comes from the native `<dialog>` centring plus these overrides; `::backdrop`
   is the native dim-the-page-behind-it layer, styled to match the site's ink
   tone rather than the browser default. */
.lightbox {
  padding: 0;
  border: 0;
  border-radius: var(--card-radius);
  background: var(--color-surface);
  box-shadow: var(--card-shadow);
  max-width: min(92vw, 1200px);
  max-height: 92vh;
}

.lightbox::backdrop {
  background: var(--color-ink);
  opacity: 0.8;
}

.lightbox__img {
  display: block;
  max-width: min(92vw, 1200px);
  max-height: 92vh;
}

.lightbox__close {
  position: absolute;
  top: var(--space-1);
  inset-inline-end: var(--space-1);
  width: 2.5rem;
  height: 2.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: var(--color-surface);
  color: var(--color-text);
  cursor: pointer;
}

.lightbox__close svg {
  width: 1.25rem;
  height: 1.25rem;
}

/* --- Image placeholder ----------------------------------------------------
   The intentional "photo goes here" treatment — a soft diagonal stripe (a
   functional hatch pattern, not a decorative gradient) with a monospace
   caption, shown until a real image field is populated so a page never renders
   a broken or empty box (brand-guidelines.md §5 consent rule: placeholders
   carry no identifiable person). Stripe tints are derived from a token with
   color-mix() so there is no hard-coded colour. */
.media-placeholder {
  aspect-ratio: var(--placeholder-ratio, var(--media-ratio, 1 / 1));
  border: 1px solid var(--color-border-default);
  border-radius: var(--card-radius);
  background-image: repeating-linear-gradient(
    135deg,
    color-mix(in srgb, var(--color-brand) 8%, transparent) 0 10px,
    color-mix(in srgb, var(--color-brand) 3%, transparent) 10px 20px
  );
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.media-placeholder__caption {
  font-family: ui-monospace, "SFMono-Regular", Menlo, monospace;
  font-size: var(--font-size-xs);
  color: var(--color-brand);
  text-align: center;
  padding: var(--space-2);
}

/* --- Reduced motion -------------------------------------------------------
   base.css already near-zeroes transition/animation durations globally; this
   additionally removes the hover displacement itself, so the lift is fully
   absent (not just instant) for visitors who ask for reduced motion. */
@media (prefers-reduced-motion: reduce) {
  .card--interactive:hover {
    transform: none;
  }
}

/* --- Carousel (CSS-only scroll-snap) ----------------------------------------
   No carousel/slider JS precedent exists anywhere in this repo (Plan 03's
   "minimal JS" bias) — a horizontally-scrolling flex row using
   scroll-snap-type/scroll-snap-align instead. Degrades gracefully to a plain
   scrollable row with no JS; base.css's global prefers-reduced-motion rule
   already forces scroll-behavior: auto, and nothing here adds smooth-scroll
   or autoplay for it to override. Used by the Donate page's partner-logo /
   donor carousel (carousel.html). */
.carousel {
  display: flex;
  gap: var(--space-3);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--space-3);
  padding-block-end: var(--space-2);
}

.carousel__item {
  flex: 0 0 auto;
  width: 14rem;
  scroll-snap-align: start;
}

.carousel__empty {
  margin-block: 0;
}

/* --- Pagination -------------------------------------------------------------
   Minimal prev/next pager for the Newsletter and Camp Report archives
   (Plan 06) — plain links and a page-count label, no JS. */
.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  margin-block-start: var(--space-6);
  font-size: var(--font-size-sm);
  color: var(--color-text-faint);
}

/* --- Circle of Care wheel ---------------------------------------------------
   The "Quality of Care" six-wedge wheel (external design handoff, "Circle of
   Care Homepage Update"). The three wedge tones are semantic tokens
   (--color-coc-seg-1/2/3 in tokens.css) rather than being declared here, per
   this file's own "every colour comes from tokens.css, zero per-component
   dark-mode overrides" rule above. Text inside the wheel is sized in
   container query units (cqw) so the whole graphic scales cleanly from
   desktop to a narrow phone with no breakpoints. */
.coc-section__header {
  text-align: center;
}
.coc-section__header .section-header__title {
  max-width: none;
  margin-inline: auto;
}

.coc {
  position: relative;
  width: min(460px, 100%);
  aspect-ratio: 1;
  margin-inline: auto;
  container-type: inline-size;
}

.coc__wheel-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.coc__seg {
  stroke: var(--color-surface);
  stroke-width: 3;
  transition: opacity 0.2s ease;
}
.coc__seg--1 { fill: var(--color-coc-seg-1); }
.coc__seg--2 { fill: var(--color-coc-seg-2); }
.coc__seg--3 { fill: var(--color-coc-seg-3); }

/* Labels are real buttons overlaid on the ring — keyboard focusable. */
.coc__labels {
  position: absolute;
  inset: 0;
}
.coc__label {
  position: absolute;
  transform: translate(-50%, -50%);
  width: 22cqw;
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 3.2cqw;
  line-height: 1.1;
  color: var(--color-on-brand);
  text-align: center;
  cursor: pointer;
  transition: opacity 0.2s ease;
}
.coc__label:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 3px;
  border-radius: 4px;
}
/* Positions: clockwise from the top-right wedge. */
.coc__label--1 { left: 67.6%; top: 19.5%; }
.coc__label--2 { left: 85.25%; top: 50%; }
.coc__label--3 { left: 67.6%; top: 80.5%; }
.coc__label--4 { left: 32.4%; top: 80.5%; }
.coc__label--5 { left: 14.75%; top: 50%; }
.coc__label--6 { left: 32.4%; top: 19.5%; }

/* Hub card in the donut hole. */
.coc__hub {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 47cqw;
  height: 47cqw;
  border-radius: 50%;
  background: var(--color-surface);
  box-shadow: var(--card-shadow);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 6.5cqw;
}
.coc__hub > * { width: 100%; }

.coc__cross {
  width: 9cqw;
  height: 9cqw;
  display: block;
  margin: 0 auto 2cqw;
}
.coc__cross rect { fill: var(--color-coral); }

.coc__hub-brand {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 5cqw;
  line-height: 1.05;
  color: var(--color-brand-deep);
  margin: 0;
}
.coc__hub-hint {
  font-size: 2.7cqw;
  color: var(--color-text-faint);
  margin: 2cqw 0 0;
}
.coc__hub-name {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 4.6cqw;
  line-height: 1.1;
  color: var(--color-brand-deep);
  margin: 0 0 1.5cqw;
}
.coc__hub-desc {
  font-size: 3.1cqw;
  line-height: 1.45;
  color: var(--color-text-soft);
  margin: 0;
}

/* Active / dimmed states, toggled by circle-of-care.js. */
.coc.is-selecting .coc__seg { opacity: 0.4; }
.coc.is-selecting .coc__label { opacity: 0.45; }
.coc .coc__seg.is-active { opacity: 1; }
.coc .coc__label.is-active { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .coc__seg, .coc__label { transition: none; }
}
