/* =====================================================================
   Hareer Donations Platform — design system
   Brand: magenta #EC2C8C + turquoise #17B9D4, taken from the Hareer logo.
   Built mobile-first, RTL-native, with an app-like feel on phones.
   ===================================================================== */

/* ------------------------------------------------------------------
   1. Tokens
   ------------------------------------------------------------------ */
:root {
  color-scheme: light dark;

  /* Brand */
  --pink-50:  #FFF0F7;
  --pink-100: #FFDDEE;
  --pink-200: #FFB9DA;
  --pink-300: #FF8AC0;
  --pink-400: #F65AA6;
  --pink-500: #EC2C8C;   /* primary */
  --pink-600: #D01A76;
  --pink-700: #A81260;
  --pink-800: #7C0C46;

  --cyan-50:  #EAFBFE;
  --cyan-100: #C9F3FA;
  --cyan-200: #93E6F3;
  --cyan-300: #55D4E8;
  --cyan-400: #2AC3DC;
  --cyan-500: #17B9D4;   /* secondary */
  --cyan-600: #0E93AB;
  --cyan-700: #0B7186;

  --violet-500: #7C4DFF;
  --green-500:  #2E9E5B;
  --amber-500:  #F5A623;
  --red-500:    #E5484D;

  /* Neutrals — warm, so the pink never reads clinical */
  --ink-900: #1B1020;
  --ink-800: #2C1D33;
  --ink-700: #453949;
  --ink-600: #6B5A73;
  --ink-500: #75677D;
  --ink-400: #AFA4B4;
  --ink-300: #D5CDD8;
  --ink-200: #E9E3EC;
  --ink-100: #F4F0F6;
  --ink-50:  #FBF9FC;
  --white:   #FFFFFF;

  /* Semantic */
  --bg:            var(--ink-50);
  --bg-elevated:   var(--white);
  --bg-sunken:     var(--ink-100);
  --text:          var(--ink-900);
  --text-muted:    var(--ink-600);
  --text-subtle:   var(--ink-500);
  --border:        var(--ink-200);
  --border-strong: var(--ink-300);
  --primary:       var(--pink-600);
  --primary-hover: var(--pink-700);
  --primary-soft:  var(--pink-50);
  --accent:        var(--cyan-500);
  --accent-soft:   var(--cyan-50);
  --accent-ink:    var(--cyan-700);
  /* Brand as *text* on a tinted or neutral ground, and as a *fill* carrying
     white text. The mid pink is beautiful but only reaches 3.9:1 against
     white, so small print gets the deeper shades. */
  --primary-ink:   var(--pink-600);
  --brand-solid:   var(--pink-600);
  --danger-solid:  #C62B30;
  --tint-pink:     var(--pink-50);
  --tint-cyan:     var(--cyan-50);
  --badge-primary-bg:  var(--pink-100);
  --badge-primary-ink: var(--pink-700);
  --badge-accent-bg:   var(--cyan-100);
  --badge-accent-ink:  var(--cyan-700);
  --success:       var(--green-500);
  --success-soft:  #EAF8F0;
  --success-ink:   #1B6C3E;
  --success-deep:  #1B7742;
  --warning:       var(--amber-500);
  --warning-soft:  #FFF6E5;
  --warning-ink:   #8A5B08;
  --danger:        var(--red-500);
  --danger-soft:   #FDECEC;
  --danger-ink:    #96222A;
  --danger-deep:   #A82228;

  /* Surfaces that are dark on purpose in either theme */
  --inverse:      var(--ink-900);
  --inverse-soft: var(--ink-800);
  --inverse-text: rgba(255, 255, 255, .72);

  /* Frosted bars — the header and the bottom tab bar sit on top of content */
  --glass:         rgba(255, 255, 255, .86);
  --glass-strong:  rgba(255, 255, 255, .94);

  /* Gradients */
  --grad-brand: linear-gradient(135deg, var(--pink-500) 0%, var(--pink-400) 45%, var(--cyan-500) 130%);
  --grad-warm:  linear-gradient(135deg, var(--pink-600) 0%, var(--pink-400) 100%);
  --grad-cool:  linear-gradient(135deg, var(--cyan-600) 0%, var(--cyan-400) 100%);

  /* Type */
  --font-sans: 'Tajawal', 'Plus Jakarta Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-display: 'Cairo', 'Plus Jakarta Sans', system-ui, sans-serif;
  --fs-xs:   0.75rem;
  --fs-sm:   0.8125rem;
  --fs-base: 0.9375rem;
  --fs-md:   1rem;
  --fs-lg:   1.125rem;
  --fs-xl:   1.375rem;
  --fs-2xl:  1.75rem;
  --fs-3xl:  2.25rem;
  --fs-4xl:  3rem;

  /* Space & shape */
  --sp-1: 0.25rem;  --sp-2: 0.5rem;   --sp-3: 0.75rem;  --sp-4: 1rem;
  --sp-5: 1.5rem;   --sp-6: 2rem;     --sp-7: 3rem;     --sp-8: 4rem;
  --sp-9: 6rem;
  --r-sm: 8px;  --r-md: 14px;  --r-lg: 20px;  --r-xl: 28px;  --r-full: 999px;

  /* Elevation — tinted so shadows sit in the brand family */
  --sh-xs: 0 1px 2px rgba(43, 16, 48, .06);
  --sh-sm: 0 2px 8px rgba(43, 16, 48, .07);
  --sh-md: 0 6px 20px rgba(43, 16, 48, .09);
  --sh-lg: 0 16px 44px rgba(43, 16, 48, .13);
  --sh-pink: 0 10px 30px rgba(236, 44, 140, .28);

  /* Motion */
  --ease: cubic-bezier(.22, 1, .36, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --dur-fast: .16s;
  --dur: .28s;
  --dur-slow: .5s;

  /* Layout */
  --container: 1180px;
  --header-h: 68px;
  --tabbar-h: 66px;
  --safe-b: env(safe-area-inset-bottom, 0px);
}

/* ------------------------------------------------------------------
   2. Reset
   ------------------------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  overflow-x: clip;
  overscroll-behavior-y: none;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 12px);
}

/* Frozen while a drawer, the search panel or the lightbox is open.
   Pinning the body at its current offset keeps the reading position, which
   simply hiding the scroller's overflow does not — the browser clamps the
   scroll to zero and the page jumps when the overlay closes. */
html.is-scroll-locked { overflow: hidden; }
html.is-scroll-locked body {
  position: fixed;
  inset-inline: 0;
  width: 100%;
  top: var(--scroll-lock-top, 0);
}

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  line-height: 1.75;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, h5 {
  font-family: var(--font-display);
  font-weight: 800;
  line-height: 1.25;
  margin: 0 0 var(--sp-3);
  color: var(--text);
  letter-spacing: -0.01em;
}
h1 { font-size: var(--fs-3xl); }
h2 { font-size: var(--fs-2xl); }
h3 { font-size: var(--fs-xl); }
h4 { font-size: var(--fs-lg); }

p  { margin: 0 0 var(--sp-4); }
p:last-child { margin-bottom: 0; }

a {
  color: var(--primary);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease);
}
a:hover { color: var(--primary-hover); }

img, svg, video { max-width: 100%; height: auto; display: block; }

ul, ol { margin: 0 0 var(--sp-4); padding-inline-start: 1.35em; }
li { margin-bottom: var(--sp-2); }

button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: 0; padding: 0; }

hr { border: 0; border-top: 1px solid var(--border); margin: var(--sp-6) 0; }

:focus-visible {
  outline: 3px solid var(--cyan-400);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

::selection { background: var(--pink-200); color: var(--ink-900); }

/* ------------------------------------------------------------------
   3. Layout primitives
   ------------------------------------------------------------------ */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--sp-4);
}
.container-narrow { max-width: 760px; }
.container-wide   { max-width: 1400px; }

.section { padding-block: var(--sp-7); }
.section-lg { padding-block: var(--sp-8); }
.section-tint { background: var(--bg-elevated); }
.section-soft { background: linear-gradient(180deg, var(--tint-pink) 0%, var(--bg) 100%); }

.stack > * + * { margin-top: var(--sp-4); }
.stack-sm > * + * { margin-top: var(--sp-2); }
.stack-lg > * + * { margin-top: var(--sp-6); }

.row { display: flex; gap: var(--sp-3); align-items: center; flex-wrap: wrap; }
.row-between { display: flex; gap: var(--sp-3); align-items: center; justify-content: space-between; flex-wrap: wrap; }
.row-tight { gap: var(--sp-2); }
.grow { flex: 1 1 auto; min-width: 0; }

.grid { display: grid; gap: var(--sp-4); }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(268px, 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }

.text-center { text-align: center; }
.text-muted  { color: var(--text-muted); }
.text-subtle { color: var(--text-subtle); }
.text-danger { color: var(--danger-ink); }

/* A button that has to read as part of a sentence. */
.link-button {
  border: 0; background: none; padding: 0; font: inherit; cursor: pointer;
  color: var(--primary-ink); text-decoration: underline; text-underline-offset: 2px;
}
.link-button:hover { color: var(--primary-hover); }
.text-sm { font-size: var(--fs-sm); }
.text-xs { font-size: var(--fs-xs); }
.text-lg { font-size: var(--fs-lg); }
.text-primary { color: var(--primary); }
.text-accent  { color: var(--cyan-600); }
.fw-700 { font-weight: 700; }
.fw-800 { font-weight: 800; }
.nowrap { white-space: nowrap; }
.mt-0 { margin-top: 0 !important; }
.mb-0 { margin-bottom: 0 !important; }
.hidden { display: none !important; }

/* Numbers stay LTR even inside Arabic text */
.num { direction: ltr; unicode-bidi: isolate; font-variant-numeric: tabular-nums; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; inset-inline-start: var(--sp-4); top: -60px;
  z-index: 999; background: var(--primary); color: #fff;
  padding: var(--sp-2) var(--sp-4); border-radius: var(--r-md);
  transition: top var(--dur) var(--ease);
}
.skip-link:focus { top: var(--sp-3); color: #fff; }

/* ------------------------------------------------------------------
   4. Section headings
   ------------------------------------------------------------------ */
.section-head { margin-bottom: var(--sp-6); max-width: 640px; }
.section-head.center { margin-inline: auto; text-align: center; }

.eyebrow {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-xs); font-weight: 800; letter-spacing: .06em;
  text-transform: uppercase; color: var(--primary-ink);
  background: var(--primary-soft); padding: 6px 14px;
  border-radius: var(--r-full); margin-bottom: var(--sp-3);
}
.eyebrow.accent { color: var(--accent-ink); background: var(--accent-soft); }

.section-head h2 { margin-bottom: var(--sp-2); }
.section-head p  { color: var(--text-muted); font-size: var(--fs-md); margin: 0; }

/* ------------------------------------------------------------------
   5. Buttons
   ------------------------------------------------------------------ */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--sp-2);
  padding: 0.72rem 1.4rem;
  font-family: var(--font-display);
  font-size: var(--fs-base); font-weight: 700; line-height: 1.2;
  border-radius: var(--r-full);
  border: 1.5px solid transparent;
  cursor: pointer; white-space: nowrap;
  transition: transform var(--dur-fast) var(--ease),
              box-shadow var(--dur) var(--ease),
              background-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
  -webkit-tap-highlight-color: transparent;
}
.btn:active { transform: scale(.97); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: .55; pointer-events: none; }
.btn svg { width: 1.15em; height: 1.15em; flex: none; }

.btn-primary { background: var(--grad-warm); color: #fff; box-shadow: var(--sh-pink); }
.btn-primary:hover { color: #fff; box-shadow: 0 14px 36px rgba(236, 44, 140, .36); }

.btn-accent { background: var(--grad-cool); color: #fff; box-shadow: 0 10px 30px rgba(23, 185, 212, .3); }
.btn-accent:hover { color: #fff; }

.btn-outline { background: transparent; border-color: var(--border-strong); color: var(--text); }
.btn-outline:hover { border-color: var(--primary); color: var(--primary); background: var(--primary-soft); }

.btn-ghost { background: var(--bg-sunken); color: var(--text); }
.btn-ghost:hover { background: var(--border); color: var(--text); }

.btn-white { background: #fff; color: var(--primary-ink); box-shadow: var(--sh-md); }
.btn-white:hover { color: var(--primary-hover); }

.btn-glass {
  background: rgba(255,255,255,.16); color: #fff;
  border-color: rgba(255,255,255,.4); backdrop-filter: blur(10px);
}
.btn-glass:hover { background: rgba(255,255,255,.26); color: #fff; }

.btn-danger { background: var(--danger); color: #fff; }
.btn-danger:hover { color: #fff; filter: brightness(.94); }

.btn-sm  { padding: .48rem 1rem; font-size: var(--fs-sm); }
.btn-lg  { padding: .95rem 2rem; font-size: var(--fs-lg); }
.btn-block { width: 100%; }
.btn-icon { padding: .6rem; width: 2.6rem; height: 2.6rem; border-radius: var(--r-full); }

/* Loading state driven by JS */
.btn.is-loading { pointer-events: none; position: relative; color: transparent !important; }
.btn.is-loading::after {
  content: ''; position: absolute; inset: 0; margin: auto;
  width: 1.1em; height: 1.1em; border-radius: 50%;
  border: 2px solid currentColor; border-top-color: transparent;
  color: #fff; animation: spin .7s linear infinite;
}
.btn-outline.is-loading::after, .btn-ghost.is-loading::after { color: var(--primary); }
@keyframes spin { to { transform: rotate(360deg); } }

/* ------------------------------------------------------------------
   6. Cards
   ------------------------------------------------------------------ */
.card {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.card-pad { padding: var(--sp-5); }
.card-hover:hover { transform: translateY(-4px); box-shadow: var(--sh-lg); }
.card-flat { border-radius: var(--r-md); box-shadow: none; }

.card-media {
  position: relative; aspect-ratio: 16 / 10;
  background: var(--grad-brand); overflow: hidden;
}
.card-media img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur-slow) var(--ease); }
.card-hover:hover .card-media img { transform: scale(1.06); }
.card-media-tall { aspect-ratio: 4 / 5; }

.card-body { padding: var(--sp-4) var(--sp-5) var(--sp-5); }
.card-body h3 { font-size: var(--fs-lg); margin-bottom: var(--sp-2); }
.card-body p  { color: var(--text-muted); font-size: var(--fs-base); margin-bottom: var(--sp-3); }

.card-link { color: inherit; display: block; }
.card-link:hover { color: inherit; }

/* ------------------------------------------------------------------
   7. Badges & pills
   ------------------------------------------------------------------ */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--fs-xs); font-weight: 800; line-height: 1;
  padding: 5px 11px; border-radius: var(--r-full);
  background: var(--bg-sunken); color: var(--text-muted);
}
.badge-primary { background: var(--badge-primary-bg); color: var(--badge-primary-ink); }
.badge-accent  { background: var(--badge-accent-bg); color: var(--badge-accent-ink); }
.badge-success { background: var(--success-soft); color: var(--success-ink); }
.badge-warning { background: var(--warning-soft); color: var(--warning-ink); }
.badge-danger  { background: var(--danger-soft); color: var(--danger-ink); }
.badge-urgent  { background: var(--danger-solid); color: #fff; animation: pulse-soft 2.4s ease-in-out infinite; }

@keyframes pulse-soft {
  0%, 100% { box-shadow: 0 0 0 0 rgba(229, 72, 77, .45); }
  50%      { box-shadow: 0 0 0 7px rgba(229, 72, 77, 0); }
}

.card-media .badge { position: absolute; inset-block-start: var(--sp-3); inset-inline-start: var(--sp-3); z-index: 2; }

/* ------------------------------------------------------------------
   8. Progress
   ------------------------------------------------------------------ */
.progress {
  height: 9px; border-radius: var(--r-full);
  background: var(--border); overflow: hidden;
}
.progress-bar {
  height: 100%; border-radius: var(--r-full);
  background: var(--grad-warm);
  width: 0;
  transition: width 1.1s var(--ease-out);
  position: relative;
}
.progress-bar::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.4), transparent);
  animation: shimmer 2.4s infinite;
}
@keyframes shimmer { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } }
.progress-bar.accent { background: var(--grad-cool); }
.progress-bar.done   { background: linear-gradient(135deg, #2E9E5B, #46C27C); }

.progress-meta {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: var(--sp-3); margin-top: var(--sp-2); font-size: var(--fs-sm);
}
.progress-meta strong { font-size: var(--fs-md); font-family: var(--font-display); }

/* ------------------------------------------------------------------
   9. Forms
   ------------------------------------------------------------------ */
.field { margin-bottom: var(--sp-4); }
.field:last-child { margin-bottom: 0; }

.label {
  display: block; font-weight: 700; font-size: var(--fs-sm);
  margin-bottom: var(--sp-2); color: var(--text);
}
.label .opt { font-weight: 500; color: var(--text-subtle); font-size: var(--fs-xs); }

.input, .select, .textarea {
  display: block; width: 100%;
  padding: 0.72rem 1rem;
  font-size: var(--fs-base);
  background: var(--bg-elevated);
  border: 1.5px solid var(--border-strong);
  border-radius: var(--r-md);
  color: var(--text);
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
  -webkit-appearance: none; appearance: none;
}
.input::placeholder, .textarea::placeholder { color: var(--text-subtle); }
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 4px rgba(236, 44, 140, .13);
}
.textarea { min-height: 130px; resize: vertical; line-height: 1.7; }

.select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236B5A73' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-size: 1.1em;
  background-position: left 1rem center;
  padding-inline-end: 1rem;
  padding-inline-start: 2.6rem;
}
[dir="ltr"] .select { background-position: right 1rem center; padding-inline-start: 1rem; padding-inline-end: 2.6rem; }

.input.has-error, .select.has-error, .textarea.has-error {
  border-color: var(--danger);
  box-shadow: 0 0 0 4px rgba(229, 72, 77, .11);
}
.field-error {
  display: flex; align-items: center; gap: 5px;
  font-size: var(--fs-xs); color: var(--danger);
  margin-top: 6px; font-weight: 600;
}
.field-hint { font-size: var(--fs-xs); color: var(--text-subtle); margin-top: 6px; }

/* Checkbox & radio */
.check {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  cursor: pointer; font-size: var(--fs-base); line-height: 1.6;
}
.check input[type="checkbox"], .check input[type="radio"] {
  flex: none; width: 20px; height: 20px; margin-top: 3px;
  accent-color: var(--primary); cursor: pointer;
}

/* Segmented control — used for one-time vs monthly */
.segment {
  display: inline-flex; padding: 4px; gap: 4px;
  background: var(--bg-sunken); border-radius: var(--r-full);
  width: 100%;
}
.segment input { position: absolute; opacity: 0; pointer-events: none; }
.segment label {
  flex: 1; text-align: center; padding: .6rem 1rem;
  border-radius: var(--r-full); font-weight: 700; font-size: var(--fs-sm);
  color: var(--text-muted); cursor: pointer;
  transition: all var(--dur-fast) var(--ease);
}
.segment input:checked + label {
  background: var(--bg-elevated); color: var(--primary);
  box-shadow: var(--sh-sm);
}
.segment input:focus-visible + label { outline: 3px solid var(--cyan-400); outline-offset: 2px; }

/* Amount chooser */
.amount-grid {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-2);
}
.amount-opt input { position: absolute; opacity: 0; pointer-events: none; }
.amount-opt label {
  display: flex; align-items: center; justify-content: center;
  padding: .95rem .5rem;
  border: 1.5px solid var(--border-strong); border-radius: var(--r-md);
  font-family: var(--font-display); font-weight: 800; font-size: var(--fs-lg);
  cursor: pointer; background: var(--bg-elevated);
  transition: all var(--dur-fast) var(--ease);
}
.amount-opt label:hover { border-color: var(--pink-300); }
.amount-opt input:checked + label {
  border-color: var(--primary); background: var(--primary-soft);
  color: var(--primary); box-shadow: 0 0 0 3px rgba(236,44,140,.12);
}
.amount-opt input:focus-visible + label { outline: 3px solid var(--cyan-400); outline-offset: 2px; }

/* Input with a currency affix */
.input-affix { position: relative; display: flex; align-items: center; }
.input-affix .affix {
  position: absolute; inset-inline-start: 1rem;
  font-weight: 700; color: var(--text-subtle); pointer-events: none;
}
.input-affix .input { padding-inline-start: 3.1rem; font-weight: 800; font-size: var(--fs-lg); }

/* Choice cards — payment methods, designations */
.choice-list { display: grid; gap: var(--sp-2); }
.choice input { position: absolute; opacity: 0; pointer-events: none; }
.choice label {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border: 1.5px solid var(--border-strong); border-radius: var(--r-md);
  cursor: pointer; background: var(--bg-elevated);
  transition: all var(--dur-fast) var(--ease);
}
.choice label:hover { border-color: var(--pink-300); }
.choice input:checked + label {
  border-color: var(--primary); background: var(--primary-soft);
  box-shadow: 0 0 0 3px rgba(236,44,140,.1);
}
.choice input:focus-visible + label { outline: 3px solid var(--cyan-400); outline-offset: 2px; }
.choice .choice-icon {
  flex: none; width: 40px; height: 40px; border-radius: var(--r-sm);
  display: grid; place-items: center; background: var(--bg-sunken); color: var(--primary);
}
.choice .choice-text { flex: 1; min-width: 0; }
.choice .choice-text strong { display: block; font-size: var(--fs-base); }
.choice .choice-text span { font-size: var(--fs-xs); color: var(--text-muted); }

/* Honeypot — invisible to humans, still reachable for bots.
   Clipped rather than pushed off-canvas, which would extend the document
   and create a phantom horizontal scrollbar (badly so in RTL). */
.hp-field {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px; border: 0;
  overflow: hidden; white-space: nowrap;
  clip: rect(0 0 0 0); clip-path: inset(50%);
  opacity: 0; pointer-events: none;
}

/* ------------------------------------------------------------------
   10. Alerts & toasts
   ------------------------------------------------------------------ */
.alert {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  border-inline-start: 4px solid;
  font-size: var(--fs-base);
  margin-bottom: var(--sp-4);
}
.alert svg { flex: none; width: 20px; height: 20px; margin-top: 2px; }
.alert-success { background: var(--success-soft); border-color: var(--success); color: var(--success-ink); }
.alert-error   { background: var(--danger-soft); border-color: var(--danger);  color: var(--danger-ink); }
.alert-info    { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-ink); }
.alert-warning { background: var(--warning-soft); border-color: var(--warning); color: var(--warning-ink); }

.toast-stack {
  position: fixed; inset-block-end: calc(var(--tabbar-h) + var(--safe-b) + 12px);
  inset-inline: var(--sp-4); z-index: 400;
  display: flex; flex-direction: column; gap: var(--sp-2);
  pointer-events: none;
}
@media (min-width: 720px) {
  .toast-stack { inset-block-end: var(--sp-5); inset-inline-start: auto; max-width: 380px; }
}
.toast {
  pointer-events: auto;
  display: flex; align-items: center; gap: var(--sp-3);
  background: var(--inverse); color: #fff;
  padding: var(--sp-3) var(--sp-4); border-radius: var(--r-md);
  box-shadow: var(--sh-lg); font-size: var(--fs-base);
  animation: toast-in .35s var(--ease-out);
}
.toast.success { background: var(--success-deep); }
.toast.error   { background: var(--danger-deep); }
@keyframes toast-in { from { opacity: 0; transform: translateY(16px) scale(.96); } }
.toast.is-leaving { animation: toast-out .25s var(--ease) forwards; }
@keyframes toast-out { to { opacity: 0; transform: translateY(10px) scale(.97); } }

/* ------------------------------------------------------------------
   11. Header
   ------------------------------------------------------------------ */
.site-header {
  position: sticky; top: 0; z-index: 200;
  height: var(--header-h);
  background: var(--glass);
  backdrop-filter: saturate(180%) blur(16px);
  -webkit-backdrop-filter: saturate(180%) blur(16px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.site-header.is-stuck { border-bottom-color: var(--border); box-shadow: var(--sh-sm); }

.header-inner {
  height: 100%; display: flex; align-items: center;
  gap: var(--sp-4); justify-content: space-between;
}

.brand { display: flex; align-items: center; gap: var(--sp-3); flex: none; }
.brand img { height: 40px; width: auto; }
.brand-text { display: none; line-height: 1.15; }
.brand-text strong { display: block; font-family: var(--font-display); font-weight: 800; font-size: var(--fs-base); }
.brand-text span { font-size: 10px; color: var(--text-subtle); letter-spacing: .04em; }
@media (min-width: 900px) { .brand-text { display: block; } }

.main-nav { display: none; }
@media (min-width: 1024px) {
  .main-nav { display: flex; align-items: center; gap: var(--sp-1); }
}
.nav-link {
  padding: .5rem .8rem; border-radius: var(--r-full);
  font-weight: 700; font-size: var(--fs-sm); color: var(--text-muted);
  transition: all var(--dur-fast) var(--ease); white-space: nowrap;
}
.nav-link:hover { background: var(--primary-soft); color: var(--primary); }
.nav-link.is-active { color: var(--primary); background: var(--primary-soft); }

.header-actions { display: flex; align-items: center; gap: var(--sp-2); flex: none; }
.header-actions .btn-donate { display: none; }
@media (min-width: 560px) { .header-actions .btn-donate { display: inline-flex; } }

.icon-btn {
  width: 42px; height: 42px; border-radius: var(--r-full);
  display: grid; place-items: center; color: var(--text-muted);
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.icon-btn:hover { background: var(--bg-sunken); color: var(--primary); }
.icon-btn svg { width: 21px; height: 21px; }

.lang-switch {
  display: inline-flex; align-items: center; gap: 5px;
  padding: .4rem .75rem; border-radius: var(--r-full);
  border: 1.5px solid var(--border); font-weight: 800; font-size: var(--fs-xs);
  color: var(--text-muted);
}
.lang-switch:hover { border-color: var(--primary); color: var(--primary); }

/* The full name where it fits, the code where it does not. */
.lang-code { display: none; }
@media (max-width: 719px) {
  .lang-full { display: none; }
  .lang-code { display: inline; }
}

/* The header carries a logo and up to five controls, and on a narrow phone
   those cannot all keep their comfortable sizes — the row grew past the
   viewport and the whole page could be panned sideways. Below 720px it
   tightens instead: smaller gaps, smaller targets, and no wordmark. */
@media (max-width: 719px) {
  .header-inner { gap: var(--sp-2); }
  .header-actions { gap: 2px; }
  .icon-btn { width: 38px; height: 38px; }
  .icon-btn svg { width: 20px; height: 20px; }
  .lang-switch { padding: .35rem .5rem; }
  .brand img { height: 34px; }
}
@media (max-width: 359px) {
  .header-actions { gap: 0; }
  .icon-btn { width: 34px; height: 34px; }
  .brand img { height: 30px; }
}

.menu-toggle { display: grid; }
@media (min-width: 1024px) { .menu-toggle { display: none; } }

/* ------------------------------------------------------------------
   12. Mobile drawer
   ------------------------------------------------------------------ */
.drawer-backdrop {
  position: fixed; inset: 0; z-index: 290;
  background: rgba(27, 16, 32, .5);
  backdrop-filter: blur(3px);
  opacity: 0; visibility: hidden;
  transition: opacity var(--dur) var(--ease), visibility var(--dur);
}
.drawer-backdrop.is-open { opacity: 1; visibility: visible; }

.drawer {
  position: fixed; inset-block: 0; inset-inline-end: 0; z-index: 300;
  width: min(340px, 88vw);
  background: var(--bg-elevated);
  display: flex; flex-direction: column;
  transform: translateX(100%);
  visibility: hidden;
  transition: transform var(--dur) var(--ease-out), visibility var(--dur);
  overflow-y: auto; overscroll-behavior: contain;
}
[dir="rtl"] .drawer { transform: translateX(-100%); }
.drawer.is-open { transform: translateX(0); visibility: visible; }

.drawer-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--sp-4); border-bottom: 1px solid var(--border);
  position: sticky; top: 0; background: var(--bg-elevated); z-index: 2;
}
.drawer-body { padding: var(--sp-4); flex: 1; }
.drawer-link {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: .85rem var(--sp-3); border-radius: var(--r-md);
  font-weight: 700; color: var(--text);
  transition: background var(--dur-fast) var(--ease);
}
.drawer-link:hover, .drawer-link.is-active { background: var(--primary-soft); color: var(--primary-ink); }
.drawer-link svg { width: 20px; height: 20px; color: var(--primary); flex: none; }
.drawer-foot { padding: var(--sp-4); border-top: 1px solid var(--border); }

/* ------------------------------------------------------------------
   13. Bottom tab bar (mobile app feel)
   ------------------------------------------------------------------ */
.tabbar {
  position: fixed; inset-inline: 0; inset-block-end: 0; z-index: 180;
  height: calc(var(--tabbar-h) + var(--safe-b));
  padding-bottom: var(--safe-b);
  background: var(--glass-strong);
  backdrop-filter: saturate(180%) blur(18px);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  border-top: 1px solid var(--border);
  display: grid; grid-template-columns: repeat(5, 1fr);
  align-items: center;
}
@media (min-width: 1024px) { .tabbar { display: none; } }
body.has-tabbar { padding-bottom: calc(var(--tabbar-h) + var(--safe-b)); }
@media (min-width: 1024px) { body.has-tabbar { padding-bottom: 0; } }

.tab {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; height: 100%; font-size: 10px; font-weight: 700;
  color: var(--text-subtle); transition: color var(--dur-fast) var(--ease);
  -webkit-tap-highlight-color: transparent;
}
.tab svg { width: 22px; height: 22px; transition: transform var(--dur) var(--ease); }
.tab.is-active { color: var(--primary); }
.tab.is-active svg { transform: translateY(-2px) scale(1.08); }
.tab:active svg { transform: scale(.9); }

.tab-donate { position: relative; }
.tab-donate .tab-fab {
  width: 46px; height: 46px; border-radius: var(--r-full);
  background: var(--grad-warm); color: #fff;
  display: grid; place-items: center;
  box-shadow: var(--sh-pink); margin-top: -18px;
}
.tab-donate .tab-fab svg { width: 24px; height: 24px; }
.tab-donate span { margin-top: -2px; }

/* ------------------------------------------------------------------
   14. Hero
   ------------------------------------------------------------------ */
.hero {
  position: relative; overflow: hidden;
  background: var(--grad-brand);
  color: #fff;
  padding-block: var(--sp-7) var(--sp-8);
}
.hero::before {
  content: ''; position: absolute; inset: 0;
  background:
    radial-gradient(ellipse 60% 50% at 15% 0%, rgba(255,255,255,.22), transparent 60%),
    radial-gradient(ellipse 50% 60% at 90% 100%, rgba(23,185,212,.35), transparent 60%);
  pointer-events: none;
}
.hero .container { position: relative; z-index: 1; }
.hero h1 { color: #fff; font-size: clamp(2rem, 6vw, 3.4rem); margin-bottom: var(--sp-4); }
.hero p.lead { font-size: var(--fs-lg); color: rgba(255,255,255,.94); max-width: 620px; margin-bottom: var(--sp-5); }
.hero .eyebrow { background: rgba(255,255,255,.18); color: #fff; backdrop-filter: blur(8px); }

.hero-grid {
  display: grid; gap: var(--sp-6); align-items: center;
}
@media (min-width: 900px) { .hero-grid { grid-template-columns: 1.15fr .85fr; gap: var(--sp-7); } }

.hero-card {
  background: rgba(255,255,255,.13);
  border: 1px solid rgba(255,255,255,.28);
  backdrop-filter: blur(18px);
  border-radius: var(--r-xl);
  padding: var(--sp-5);
  box-shadow: var(--sh-lg);
}

/* Decorative blobs echoing the logo shapes */
.blob {
  position: absolute; border-radius: 46% 54% 62% 38% / 52% 44% 56% 48%;
  filter: blur(2px); opacity: .3; pointer-events: none;
  animation: blob-float 14s ease-in-out infinite;
}
.blob-1 { width: 220px; height: 220px; background: rgba(255,255,255,.35); top: -70px; inset-inline-end: -60px; }
.blob-2 { width: 300px; height: 300px; background: rgba(23,185,212,.5); bottom: -140px; inset-inline-start: -80px; animation-delay: -5s; }
@keyframes blob-float {
  0%, 100% { transform: translate(0,0) rotate(0deg); }
  50%      { transform: translate(18px,-22px) rotate(9deg); }
}

/* ------------------------------------------------------------------
   15. Stats / counters
   ------------------------------------------------------------------ */
.stat-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp-3); }
@media (min-width: 720px)  { .stat-grid { grid-template-columns: repeat(4, 1fr); gap: var(--sp-4); } }

.stat {
  background: var(--bg-elevated); border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: var(--sp-4);
  text-align: center;
}
.stat-icon {
  width: 46px; height: 46px; border-radius: var(--r-md);
  background: var(--primary-soft); color: var(--primary);
  display: grid; place-items: center; margin: 0 auto var(--sp-3);
}
.stat-icon svg { width: 24px; height: 24px; }
.stat-value {
  font-family: var(--font-display); font-weight: 800;
  font-size: var(--fs-2xl); line-height: 1.1; color: var(--primary);
  direction: ltr; unicode-bidi: isolate;
}
.stat-label { font-size: var(--fs-sm); color: var(--text-muted); margin-top: 4px; }

.stat.on-brand { background: rgba(255,255,255,.13); border-color: rgba(255,255,255,.24); }
.stat.on-brand .stat-value, .stat.on-brand .stat-label { color: #fff; }
.stat.on-brand .stat-icon { background: rgba(255,255,255,.2); color: #fff; }

/* ------------------------------------------------------------------
   16. Campaign & initiative cards
   ------------------------------------------------------------------ */
.campaign-card .card-body { display: flex; flex-direction: column; gap: var(--sp-3); }
.campaign-card .progress-meta strong { color: var(--primary); }

.initiative-card { position: relative; overflow: visible; margin-top: 34px; }
.initiative-card .init-icon {
  position: absolute; inset-block-start: -22px; inset-inline-start: var(--sp-5);
  width: 48px; height: 48px; border-radius: var(--r-md);
  display: grid; place-items: center; color: #fff;
  background: var(--grad-warm); box-shadow: var(--sh-md);
}
.initiative-card .init-icon svg { width: 24px; height: 24px; }
.initiative-card .card-body { padding-top: var(--sp-6); }

/* Horizontal scroller for mobile card rows */
.scroller {
  display: grid; grid-auto-flow: column;
  grid-auto-columns: minmax(268px, 78vw);
  gap: var(--sp-4);
  overflow-x: auto; scroll-snap-type: x mandatory;
  padding-block-end: var(--sp-3);
  margin-inline: calc(var(--sp-4) * -1);
  padding-inline: var(--sp-4);
  scrollbar-width: none;
}
.scroller::-webkit-scrollbar { display: none; }
.scroller > * { scroll-snap-align: start; }
@media (min-width: 780px) {
  .scroller {
    grid-auto-flow: row;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    overflow: visible; margin-inline: 0; padding-inline: 0;
  }
}

/* ------------------------------------------------------------------
   17. Ways to give
   ------------------------------------------------------------------ */
.way-card {
  display: flex; gap: var(--sp-4); align-items: flex-start;
  padding: var(--sp-5); border-radius: var(--r-lg);
  background: var(--bg-elevated); border: 1px solid var(--border);
  transition: all var(--dur) var(--ease); color: inherit;
}
.way-card:hover { transform: translateY(-3px); box-shadow: var(--sh-md); border-color: var(--pink-200); color: inherit; }
.way-icon {
  flex: none; width: 52px; height: 52px; border-radius: var(--r-md);
  display: grid; place-items: center; background: var(--accent-soft); color: var(--cyan-600);
}
.way-icon svg { width: 26px; height: 26px; }
.way-card:nth-child(even) .way-icon { background: var(--primary-soft); color: var(--primary); }
.way-card h3 { font-size: var(--fs-md); margin-bottom: 4px; }
.way-card p  { font-size: var(--fs-sm); color: var(--text-muted); margin: 0; }

/* ------------------------------------------------------------------
   18. Quote / founder
   ------------------------------------------------------------------ */
.quote {
  position: relative;
  background: var(--bg-elevated);
  border-radius: var(--r-xl);
  padding: var(--sp-6);
  border: 1px solid var(--border);
}
.quote::before {
  content: '”';
  position: absolute; inset-block-start: -8px; inset-inline-start: var(--sp-5);
  font-family: var(--font-display); font-size: 5rem; line-height: 1;
  color: var(--pink-200);
}
.quote blockquote {
  margin: 0; font-size: var(--fs-lg); line-height: 1.85;
  color: var(--text); position: relative; z-index: 1;
}
.quote-author { display: flex; align-items: center; gap: var(--sp-3); margin-top: var(--sp-5); }
.quote-avatar {
  width: 52px; height: 52px; border-radius: var(--r-full);
  background: var(--grad-warm); color: #fff;
  display: grid; place-items: center; font-family: var(--font-display);
  font-weight: 800; font-size: var(--fs-lg); flex: none;
}
.quote-author strong { display: block; font-family: var(--font-display); }
.quote-author span { font-size: var(--fs-sm); color: var(--text-muted); }

/* ------------------------------------------------------------------
   19. CTA band
   ------------------------------------------------------------------ */
.cta-band {
  background: var(--grad-brand); color: #fff;
  border-radius: var(--r-xl); padding: var(--sp-7) var(--sp-5);
  text-align: center; position: relative; overflow: hidden;
}
.cta-band h2 { color: #fff; font-size: var(--fs-2xl); }
.cta-band p  { color: rgba(255,255,255,.92); max-width: 560px; margin-inline: auto; }
.cta-band .row { justify-content: center; margin-top: var(--sp-5); }

/* ------------------------------------------------------------------
   20. Footer
   ------------------------------------------------------------------ */
.site-footer {
  background: var(--inverse); color: var(--inverse-text);
  padding-block: var(--sp-7) var(--sp-5); margin-top: var(--sp-7);
}
.site-footer h4 { color: #fff; font-size: var(--fs-base); margin-bottom: var(--sp-3); }
.site-footer a { color: rgba(255,255,255,.72); font-size: var(--fs-sm); }
.site-footer a:hover { color: var(--pink-300); }
.footer-grid {
  display: grid; gap: var(--sp-6);
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
.footer-brand { grid-column: 1 / -1; }
@media (min-width: 780px) { .footer-brand { grid-column: auto; max-width: 320px; } }
.footer-brand img { height: 48px; margin-bottom: var(--sp-3); }
.footer-links { list-style: none; padding: 0; margin: 0; }
.footer-links li { margin-bottom: var(--sp-2); }
.footer-bottom {
  margin-top: var(--sp-6); padding-top: var(--sp-4);
  border-top: 1px solid rgba(255,255,255,.11);
  display: flex; flex-wrap: wrap; gap: var(--sp-3);
  justify-content: space-between; align-items: center;
  font-size: var(--fs-xs);
}
.social-row { display: flex; gap: var(--sp-2); }
.social-row a {
  width: 38px; height: 38px; border-radius: var(--r-full);
  display: grid; place-items: center;
  background: rgba(255,255,255,.09); color: #fff;
  transition: all var(--dur-fast) var(--ease);
}
.social-row a:hover { background: var(--primary); color: #fff; transform: translateY(-2px); }
.social-row svg { width: 18px; height: 18px; }

.newsletter-form { display: flex; gap: var(--sp-2); margin-top: var(--sp-3); }
.newsletter-form .input {
  background: rgba(255,255,255,.08); border-color: rgba(255,255,255,.18); color: #fff;
  padding: .6rem .9rem; font-size: var(--fs-sm);
}
.newsletter-form .input::placeholder { color: rgba(255,255,255,.45); }
.newsletter-form .input:focus { border-color: var(--pink-400); box-shadow: 0 0 0 3px rgba(236,44,140,.2); }

/* ------------------------------------------------------------------
   21. Page headers & breadcrumbs
   ------------------------------------------------------------------ */
.page-head {
  background: linear-gradient(160deg, var(--tint-pink) 0%, var(--tint-cyan) 100%);
  padding-block: var(--sp-6) var(--sp-6);
  border-bottom: 1px solid var(--border);
}
.page-head h1 { margin-bottom: var(--sp-2); }
.page-head p { color: var(--text-muted); max-width: 640px; margin: 0; }

.crumbs {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  font-size: var(--fs-xs); color: var(--text-subtle); margin-bottom: var(--sp-3);
}
.crumbs a { color: var(--text-muted); }
.crumbs a:hover { color: var(--primary); }
.crumbs .sep { opacity: .5; }

/* ------------------------------------------------------------------
   22. Article body
   ------------------------------------------------------------------ */
.prose { font-size: var(--fs-md); line-height: 1.95; color: var(--text); }
.prose > * + * { margin-top: var(--sp-4); }
.prose h2 { font-size: var(--fs-xl); margin-top: var(--sp-6); }
.prose h3 { font-size: var(--fs-lg); margin-top: var(--sp-5); }
.prose ul, .prose ol { padding-inline-start: 1.4em; }
.prose li { margin-bottom: var(--sp-2); }
.prose strong { color: var(--text); font-weight: 800; }
.prose img { border-radius: var(--r-md); margin-block: var(--sp-4); }
.prose blockquote {
  margin: var(--sp-5) 0; padding: var(--sp-4) var(--sp-5);
  border-inline-start: 4px solid var(--primary);
  background: var(--primary-soft); border-radius: var(--r-md);
  font-size: var(--fs-lg);
}
.prose a { text-decoration: underline; text-underline-offset: 3px; }

/* ------------------------------------------------------------------
   23. Tables
   ------------------------------------------------------------------ */
.table-wrap { overflow-x: auto; border-radius: var(--r-md); border: 1px solid var(--border); background: var(--bg-elevated); }
.table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); min-width: 560px; }
.table th, .table td { padding: var(--sp-3) var(--sp-4); text-align: start; }
.table th {
  background: var(--bg-sunken); font-weight: 800; font-size: var(--fs-xs);
  text-transform: uppercase; letter-spacing: .03em; color: var(--text-muted);
  white-space: nowrap;
}
.table tbody tr { border-top: 1px solid var(--border); }
.table tbody tr:hover { background: var(--bg-sunken); }

/* ------------------------------------------------------------------
   24. Gallery & lightbox
   ------------------------------------------------------------------ */
.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: var(--sp-2); }
.gallery-item {
  position: relative; aspect-ratio: 1; border-radius: var(--r-md);
  overflow: hidden; cursor: zoom-in; background: var(--bg-sunken);
}
.gallery-item img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur-slow) var(--ease); }
.gallery-item:hover img { transform: scale(1.07); }

.lightbox {
  position: fixed; inset: 0; z-index: 500;
  background: rgba(15, 8, 18, .93);
  display: grid; place-items: center; padding: var(--sp-4);
  opacity: 0; visibility: hidden; transition: opacity var(--dur) var(--ease), visibility var(--dur);
}
.lightbox.is-open { opacity: 1; visibility: visible; }
.lightbox img { max-width: 92vw; max-height: 84vh; border-radius: var(--r-md); }
.lightbox-close {
  position: absolute; top: var(--sp-4); inset-inline-end: var(--sp-4);
  width: 44px; height: 44px; border-radius: var(--r-full);
  background: rgba(255,255,255,.15); color: #fff; display: grid; place-items: center;
}

/* ------------------------------------------------------------------
   25. Timeline (campaign updates, strategy)
   ------------------------------------------------------------------ */
.timeline { position: relative; padding-inline-start: var(--sp-6); }
.timeline::before {
  content: ''; position: absolute; inset-block: 6px 6px;
  inset-inline-start: 7px; width: 2px; background: var(--border);
}
.timeline-item { position: relative; padding-bottom: var(--sp-5); }
.timeline-item::before {
  content: ''; position: absolute; inset-inline-start: calc(var(--sp-6) * -1 + 1px);
  top: 6px; width: 14px; height: 14px; border-radius: 50%;
  background: var(--primary); border: 3px solid var(--bg);
}
.timeline-item:last-child { padding-bottom: 0; }
.timeline-date { font-size: var(--fs-xs); color: var(--text-subtle); font-weight: 700; }

/* ------------------------------------------------------------------
   26. Pagination
   ------------------------------------------------------------------ */
.pagination { display: flex; flex-wrap: wrap; gap: var(--sp-2); justify-content: center; margin-top: var(--sp-6); }
.pagination a, .pagination span {
  min-width: 40px; height: 40px; padding: 0 .7rem;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--r-md); border: 1px solid var(--border);
  font-weight: 700; font-size: var(--fs-sm); color: var(--text-muted);
  background: var(--bg-elevated);
}
.pagination a:hover { border-color: var(--primary); color: var(--primary); }
.pagination .is-current { background: var(--brand-solid); border-color: var(--brand-solid); color: #fff; }
.pagination .is-disabled { opacity: .45; pointer-events: none; }

/* ------------------------------------------------------------------
   27. Empty state
   ------------------------------------------------------------------ */
.empty {
  text-align: center; padding: var(--sp-7) var(--sp-4);
  color: var(--text-muted);
}
.empty-icon {
  width: 72px; height: 72px; border-radius: var(--r-full);
  background: var(--bg-sunken); color: var(--text-subtle);
  display: grid; place-items: center; margin: 0 auto var(--sp-4);
}
.empty-icon svg { width: 34px; height: 34px; }

/* ------------------------------------------------------------------
   28. Sticky donate bar (campaign pages, mobile)
   ------------------------------------------------------------------ */
.sticky-cta {
  position: fixed; inset-inline: 0;
  inset-block-end: calc(var(--tabbar-h) + var(--safe-b));
  z-index: 170; padding: var(--sp-3) var(--sp-4);
  background: rgba(255,255,255,.96);
  backdrop-filter: blur(14px);
  border-top: 1px solid var(--border);
  transform: translateY(110%);
  transition: transform var(--dur) var(--ease-out);
}
.sticky-cta.is-visible { transform: translateY(0); }
@media (min-width: 1024px) { .sticky-cta { display: none; } }

/* ------------------------------------------------------------------
   29. Page transitions (client-side router)
   ------------------------------------------------------------------ */
#page {
  animation: page-in .34s var(--ease-out);
}
@keyframes page-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
body.is-navigating #page { opacity: .5; transition: opacity .15s linear; }

.route-progress {
  position: fixed; inset-block-start: 0; inset-inline-start: 0;
  height: 3px; z-index: 999; width: 0;
  background: var(--grad-cool);
  transition: width .25s var(--ease), opacity .3s;
  box-shadow: 0 0 12px rgba(23,185,212,.7);
}

/* Reveal-on-scroll.
   Only hidden once JS has confirmed it can reveal them again, so a failed
   script or a no-JS visitor still sees the whole page. */
.js .reveal { opacity: 0; transform: translateY(22px); }
.js .reveal.is-visible {
  opacity: 1; transform: none;
  transition: opacity .6s var(--ease-out), transform .6s var(--ease-out);
}

/* ------------------------------------------------------------------
   30. Skeletons
   ------------------------------------------------------------------ */
.skeleton {
  background: linear-gradient(90deg, var(--bg-sunken) 25%, var(--border) 50%, var(--bg-sunken) 75%);
  background-size: 200% 100%;
  animation: sk 1.4s infinite;
  border-radius: var(--r-sm);
}
@keyframes sk { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

/* ------------------------------------------------------------------
   31. Offline banner & install prompt
   ------------------------------------------------------------------ */
.offline-bar {
  position: fixed; inset-inline: 0; inset-block-start: 0; z-index: 500;
  background: var(--inverse-soft); color: #fff; text-align: center;
  padding: var(--sp-2) var(--sp-4); font-size: var(--fs-sm);
  transform: translateY(-100%); transition: transform var(--dur) var(--ease);
}
.offline-bar.is-visible { transform: translateY(0); }

.install-card {
  position: fixed; z-index: 320;
  inset-inline: var(--sp-4);
  inset-block-end: calc(var(--tabbar-h) + var(--safe-b) + var(--sp-3));
  background: var(--bg-elevated); border: 1px solid var(--border);
  border-radius: var(--r-lg); box-shadow: var(--sh-lg);
  padding: var(--sp-4); display: flex; gap: var(--sp-3); align-items: center;
  transform: translateY(160%); transition: transform var(--dur-slow) var(--ease-out);
}
.install-card.is-visible { transform: translateY(0); }
.install-card img { width: 46px; height: 46px; border-radius: var(--r-md); flex: none; }
@media (min-width: 720px) { .install-card { max-width: 400px; inset-inline-start: auto; } }

/* ------------------------------------------------------------------
   32. Search overlay
   ------------------------------------------------------------------ */
.search-overlay {
  position: fixed; inset: 0; z-index: 350;
  background: rgba(27,16,32,.55); backdrop-filter: blur(6px);
  opacity: 0; visibility: hidden; transition: opacity var(--dur) var(--ease), visibility var(--dur);
  padding-top: 10vh;
}
.search-overlay.is-open { opacity: 1; visibility: visible; }
.search-panel {
  max-width: 640px; margin-inline: auto;
  background: var(--bg-elevated); border-radius: var(--r-lg);
  box-shadow: var(--sh-lg); overflow: hidden;
  transform: translateY(-14px); transition: transform var(--dur) var(--ease-out);
}
.search-overlay.is-open .search-panel { transform: none; }
.search-input-row { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-4); border-bottom: 1px solid var(--border); }
.search-input-row input { border: 0; outline: 0; flex: 1; font-size: var(--fs-lg); background: transparent; }
.search-results { max-height: 56vh; overflow-y: auto; }
.search-result {
  display: flex; gap: var(--sp-3); align-items: center;
  padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--border);
  color: inherit;
}
.search-result:hover { background: var(--primary-soft); color: inherit; }
.search-result strong { display: block; font-size: var(--fs-base); }
.search-result span { font-size: var(--fs-xs); color: var(--text-muted); }

/* ------------------------------------------------------------------
   33. Utilities for the donate flow
   ------------------------------------------------------------------ */
.donate-layout { display: grid; gap: var(--sp-5); }
/* A grid item will not shrink below its content's natural width unless told
   to; without this the column keeps its widest child's size and the whole
   page pans sideways on a narrow phone. */
.donate-layout > * { min-width: 0; }
@media (min-width: 960px) {
  .donate-layout { grid-template-columns: 1.35fr .65fr; align-items: start; }
  .donate-summary { position: sticky; top: calc(var(--header-h) + var(--sp-4)); }
}

.summary-row {
  display: flex; justify-content: space-between; gap: var(--sp-3);
  padding-block: var(--sp-2); font-size: var(--fs-sm);
}
.summary-row + .summary-row { border-top: 1px dashed var(--border); }
.summary-total {
  display: flex; justify-content: space-between; align-items: baseline;
  margin-top: var(--sp-3); padding-top: var(--sp-3);
  border-top: 2px solid var(--border);
  font-family: var(--font-display); font-weight: 800; font-size: var(--fs-xl);
  color: var(--primary);
}

.impact-hint {
  display: flex; align-items: center; gap: var(--sp-3);
  background: var(--accent-soft); border-radius: var(--r-md);
  padding: var(--sp-3) var(--sp-4); font-size: var(--fs-sm); color: var(--cyan-700);
}
.impact-hint svg { flex: none; width: 22px; height: 22px; }

.bank-detail {
  display: flex; justify-content: space-between; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) 0; border-bottom: 1px dashed var(--border);
  font-size: var(--fs-sm);
}
.bank-detail:last-child { border-bottom: 0; }
.bank-detail .value { font-family: ui-monospace, 'SFMono-Regular', monospace; font-weight: 700; direction: ltr; word-break: break-all; text-align: end; }

.copy-btn { flex: none; color: var(--primary); padding: 4px; }
.copy-btn svg { width: 17px; height: 17px; }

/* Steps indicator */
.steps { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-5); }
.step { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-xs); color: var(--text-subtle); font-weight: 700; }
.step-num {
  width: 26px; height: 26px; border-radius: var(--r-full);
  display: grid; place-items: center; background: var(--bg-sunken); color: var(--text-subtle);
  font-size: var(--fs-xs);
}
.step.is-active { color: var(--primary); }
.step.is-active .step-num { background: var(--primary); color: #fff; }
.step.is-done .step-num { background: var(--success); color: #fff; }
.step-line { flex: 1; height: 2px; background: var(--border); border-radius: 2px; min-width: 12px; }

/* ------------------------------------------------------------------
   34. Print (donation receipts)
   ------------------------------------------------------------------ */
@media print {
  .site-header, .tabbar, .site-footer, .sticky-cta, .install-card,
  .toast-stack, .no-print, .drawer, .drawer-backdrop { display: none !important; }
  body { background: #fff; padding: 0; }
  .card { box-shadow: none; border: 1px solid #ddd; }
  a { color: #000; text-decoration: none; }
}

/* ------------------------------------------------------------------
   35. Reduced motion & dark scheme preference
   ------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .js .reveal { opacity: 1; transform: none; }
}

/* ------------------------------------------------------------------
   32. Dark theme

   Only the semantic tokens flip. The raw --ink-* scale stays absolute so
   surfaces that are dark on purpose — the footer, toasts, the admin sidebar —
   stay dark instead of inverting into unreadable light-on-light.

   Declaring color-scheme (top of this file) is also what makes Chrome's
   "Auto dark theme" stand down and use this palette instead of algorithmically
   inverting the page.
   ------------------------------------------------------------------ */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:            #141019;
    --bg-elevated:   #1D1724;
    --bg-sunken:     #241E2E;
    --text:          #F4F0F7;
    --text-muted:    #B9AFC1;
    --text-subtle:   #92879B;
    --border:        #342C3E;
    --border-strong: #473D53;

    /* Brand tints lift a little so they hold up against a dark ground */
    --primary:       var(--pink-400);
    --primary-hover: var(--pink-300);
    --primary-soft:  #34162A;
    --accent:        var(--cyan-400);
    --accent-soft:   #10303A;
    --accent-ink:    var(--cyan-200);
    --primary-ink:   var(--pink-300);
    /* the fill keeps its own dark-enough pink so white text still reads */
    --brand-solid:   var(--pink-600);

    --success-soft:  #14301F;
    --success-ink:   #7FD9A4;
    --warning-soft:  #33260B;
    --warning-ink:   #F0C368;
    --danger-soft:   #3A1719;
    --danger-ink:    #F19A9D;

    --tint-pink:     #23142B;
    --tint-cyan:     #10222B;
    --badge-primary-bg:  #3A1A32;
    --badge-primary-ink: var(--pink-200);
    --badge-accent-bg:   #123742;
    --badge-accent-ink:  var(--cyan-200);

    /* The page itself is dark now, so these lift away from it rather than down */
    --inverse:       #241E2E;
    --inverse-soft:  #2E2739;
    --inverse-text:  rgba(255, 255, 255, .78);

    --glass:         rgba(20, 16, 25, .86);
    --glass-strong:  rgba(20, 16, 25, .94);

    --sh-xs: 0 1px 2px rgba(0, 0, 0, .40);
    --sh-sm: 0 2px 8px rgba(0, 0, 0, .44);
    --sh-md: 0 6px 20px rgba(0, 0, 0, .50);
    --sh-lg: 0 16px 44px rgba(0, 0, 0, .58);
    --sh-pink: 0 10px 30px rgba(236, 44, 140, .34);
  }

  /* Components whose colours are not expressible as a single token. */
  :root:not([data-theme="light"]) .site-footer { background: #0E0B13; }
  :root:not([data-theme="light"]) .btn-white { background: var(--bg-elevated); color: var(--primary); }
  :root:not([data-theme="light"]) .btn-outline { border-color: var(--border-strong); }
  :root:not([data-theme="light"]) .skip-link { color: #fff; }
  :root:not([data-theme="light"]) .progress-bar.done { background: linear-gradient(135deg, #2E9E5B, #46C27C); }
  :root:not([data-theme="light"]) .toast { color: #fff; border: 1px solid var(--border); }

  /* Photos and the logo are authored for a light page; take the glare off. */
  :root:not([data-theme="light"]) .card-media img,
  :root:not([data-theme="light"]) .media-item img { filter: brightness(.92); }
}

/* The same values, reached by an explicit choice rather than the device.
   Plain CSS cannot share one declaration block between a media query and a
   selector, so this twin exists on purpose — edit the pair together. */
:root[data-theme="dark"] {
  --bg:            #141019;
  --bg-elevated:   #1D1724;
  --bg-sunken:     #241E2E;
  --text:          #F4F0F7;
  --text-muted:    #B9AFC1;
  --text-subtle:   #92879B;
  --border:        #342C3E;
  --border-strong: #473D53;

  /* Brand tints lift a little so they hold up against a dark ground */
  --primary:       var(--pink-400);
  --primary-hover: var(--pink-300);
  --primary-soft:  #34162A;
  --accent:        var(--cyan-400);
  --accent-soft:   #10303A;
  --accent-ink:    var(--cyan-200);
  --primary-ink:   var(--pink-300);
  /* the fill keeps its own dark-enough pink so white text still reads */
  --brand-solid:   var(--pink-600);

  --success-soft:  #14301F;
  --success-ink:   #7FD9A4;
  --warning-soft:  #33260B;
  --warning-ink:   #F0C368;
  --danger-soft:   #3A1719;
  --danger-ink:    #F19A9D;

  --tint-pink:     #23142B;
  --tint-cyan:     #10222B;
  --badge-primary-bg:  #3A1A32;
  --badge-primary-ink: var(--pink-200);
  --badge-accent-bg:   #123742;
  --badge-accent-ink:  var(--cyan-200);

  /* The page itself is dark now, so these lift away from it rather than down */
  --inverse:       #241E2E;
  --inverse-soft:  #2E2739;
  --inverse-text:  rgba(255, 255, 255, .78);

  --glass:         rgba(20, 16, 25, .86);
  --glass-strong:  rgba(20, 16, 25, .94);

  --sh-xs: 0 1px 2px rgba(0, 0, 0, .40);
  --sh-sm: 0 2px 8px rgba(0, 0, 0, .44);
  --sh-md: 0 6px 20px rgba(0, 0, 0, .50);
  --sh-lg: 0 16px 44px rgba(0, 0, 0, .58);
  --sh-pink: 0 10px 30px rgba(236, 44, 140, .34);
}

/* Components whose colours are not expressible as a single token. */
:root[data-theme="dark"] .site-footer { background: #0E0B13; }
:root[data-theme="dark"] .btn-white { background: var(--bg-elevated); color: var(--primary); }
:root[data-theme="dark"] .btn-outline { border-color: var(--border-strong); }
:root[data-theme="dark"] .skip-link { color: #fff; }
:root[data-theme="dark"] .progress-bar.done { background: linear-gradient(135deg, #2E9E5B, #46C27C); }
:root[data-theme="dark"] .toast { color: #fff; border: 1px solid var(--border); }

/* Photos and the logo are authored for a light page; take the glare off. */
:root[data-theme="dark"] .card-media img,
:root[data-theme="dark"] .media-item img { filter: brightness(.92); }

/* ------------------------------------------------------------------
   33. Page transitions

   The router swaps #page in a view transition, so the browser cross-fades
   the old screen into the new one the way a native stack does. The shell —
   header, tab bar, drawer — is named separately so it stays put instead of
   fading with the content under it.
   ------------------------------------------------------------------ */
@view-transition { navigation: auto; }

::view-transition-old(page),
::view-transition-new(page) {
  animation-duration: .22s;
  animation-timing-function: var(--ease-out);
}
::view-transition-old(page) { animation-name: page-out; }
::view-transition-new(page) { animation-name: page-in; }

@keyframes page-out { to { opacity: 0; transform: translateY(-6px); } }
@keyframes page-in  { from { opacity: 0; transform: translateY(8px); } }

#page { view-transition-name: page; }
.site-header, .tabbar { view-transition-name: none; }

@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(page),
  ::view-transition-new(page) { animation: none; }
}

/* ------------------------------------------------------------------
   34. Launch intro — «عطاء يتجمّع»

   Small dots in the brand colours fly in from the edges and gather into
   each face, right to left the way «حرير» is read; the wordmark rises and
   the whole thing hands over in about 2.6 seconds. pointer-events stays
   off, so an eager tap goes straight through to the page underneath.
   ------------------------------------------------------------------ */
#splash{display:none}
html.splashing #splash{
  position:fixed; inset:0; z-index:900;
  display:grid; place-items:center;
  background:var(--bg);
  pointer-events:none;
  animation:splash-out .38s 2.3s var(--ease) both;
}
@keyframes splash-out{to{opacity:0; visibility:hidden}}

#splash .splash-stage{position:relative; width:min(72vw,340px)}
#splash svg{width:100%; display:block; overflow:visible}
#splash .head, #splash .letter{transform-box:fill-box; transform-origin:center; opacity:0}

html.splashing #splash .head{animation:splash-bloom .55s cubic-bezier(.2,.9,.3,1.25) both}
html.splashing #splash .head4{animation-delay:.50s}
html.splashing #splash .head3{animation-delay:.70s}
html.splashing #splash .head2{animation-delay:.90s}
html.splashing #splash .head1{animation-delay:1.10s}
@keyframes splash-bloom{from{opacity:0; transform:scale(.4)} 60%{opacity:1} to{opacity:1; transform:none}}

html.splashing #splash .letter{animation:splash-rise .45s cubic-bezier(.2,.9,.3,1.3) both}
html.splashing #splash .letter:nth-of-type(5){animation-delay:1.32s}
html.splashing #splash .letter:nth-of-type(6){animation-delay:1.39s}
html.splashing #splash .letter:nth-of-type(7){animation-delay:1.46s}
html.splashing #splash .letter:nth-of-type(8){animation-delay:1.53s}
html.splashing #splash .letter:nth-of-type(9){animation-delay:1.60s}
html.splashing #splash .letter:nth-of-type(10){animation-delay:1.67s}
@keyframes splash-rise{from{opacity:0; transform:translateY(22px)} to{opacity:1; transform:none}}

#splash .splash-brand{
  position:absolute; top:calc(100% + 22px); inset-inline:0;
  text-align:center; font-family:var(--font-display); font-weight:700;
  font-size:var(--fs-sm); color:var(--text-subtle); opacity:0;
}
html.splashing #splash .splash-brand{animation:splash-rise .5s 1.78s both}

.splash-dust{
  position:absolute; width:9px; height:9px; margin:-4px; border-radius:50%;
  opacity:0; pointer-events:none;
}
html.splashing .splash-dust{animation:splash-gather .8s cubic-bezier(.5,0,.2,1) both}
@keyframes splash-gather{
  0%{opacity:0; transform:translate(var(--fx),var(--fy)) scale(1)}
  25%{opacity:.95}
  92%{opacity:.5}
  100%{opacity:0; transform:translate(0,0) scale(.25)}
}

@media (prefers-reduced-motion:reduce){
  #splash{display:none !important}
}

/* ------------------------------------------------------------------
   35. «باروكة الأمل» — the story drawing under the numbers

   Two stacked SVGs: the soft ground reads from theme tokens so dark mode
   restates it, and the figures play their sequence when the shared reveal
   mechanism marks the scene visible — the giver appears, the braid is
   handed over, the child appears, hearts drift.
   ------------------------------------------------------------------ */
.story-block{max-width:520px; margin:var(--sp-5) auto 0}
.story-scene{position:relative}
.story-scene svg{width:100%; display:block; overflow:visible}
.story-figures{position:absolute; inset:0; pointer-events:none}

.story-ground .g-main{fill:var(--tint-pink)}
.story-ground .g-pink{fill:var(--primary-soft); opacity:.5}
.story-ground .g-cyan{fill:var(--accent-soft); opacity:.8}
.story-ground .g-shadow{fill:var(--ink-300); opacity:.35}
.story-ground .g-shadow-cyan{fill:var(--cyan-200); opacity:.4}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]) .story-ground .g-shadow,
  :root:not([data-theme="light"]) .story-ground .g-shadow-cyan{fill:#000; opacity:.3}
}

/* The same values, reached by an explicit choice rather than the device.
   Plain CSS cannot share one declaration block between a media query and a
   selector, so this twin exists on purpose — edit the pair together. */
:root[data-theme="dark"] .story-ground .g-shadow,
:root[data-theme="dark"] .story-ground .g-shadow-cyan{fill:#000; opacity:.3}

.story-figures .donor, .story-figures .braid, .story-figures .receiver{
  transform-box:fill-box; transform-origin:center;
}
.js .story-block:not(.is-visible) .story-figures .donor,
.js .story-block:not(.is-visible) .story-figures .braid,
.js .story-block:not(.is-visible) .story-figures .receiver{opacity:0}
.story-block.is-visible .donor{animation:story-pop .6s cubic-bezier(.2,.9,.3,1.25) .15s both,
  story-bob 5s ease-in-out 2s infinite alternate}
.story-block.is-visible .braid{animation:story-slide .55s cubic-bezier(.2,.8,.3,1.1) .62s both}
.story-block.is-visible .receiver{animation:story-pop .6s cubic-bezier(.2,.9,.3,1.25) .95s both,
  story-bob 5s ease-in-out 2.6s infinite alternate-reverse}
@keyframes story-pop{from{opacity:0; transform:scale(.5)} 65%{opacity:1} to{opacity:1; transform:none}}
@keyframes story-slide{from{opacity:0; transform:translateX(46px)} to{opacity:1; transform:none}}
@keyframes story-bob{to{transform:translateY(-7px)}}

.story-figures .heart{transform-box:fill-box; transform-origin:center}
.js .story-block:not(.is-visible) .heart, .js .story-block:not(.is-visible) .spark{opacity:0}
.story-block.is-visible .heart{animation:story-float 3.2s ease-in-out 1.25s infinite}
@keyframes story-float{0%{opacity:0; transform:translateY(8px) scale(.7)} 25%{opacity:1; transform:translateY(0)}
  75%{opacity:.85} 100%{opacity:0; transform:translateY(-14px) scale(.9)}}
.story-block.is-visible .spark{animation:story-twinkle 2.6s ease-in-out 1.35s infinite}
@keyframes story-twinkle{0%,100%{opacity:0; transform:scale(.6)} 30%{opacity:1} 60%{opacity:.5}}

@media (prefers-reduced-motion:reduce){
  .story-figures .donor, .story-figures .braid, .story-figures .receiver,
  .story-figures .heart, .story-figures .spark{opacity:1 !important; animation:none !important}
}

/* the drawing hands over to its own call to action */
.story-cta{display:flex; justify-content:center; flex-wrap:wrap; gap:var(--sp-3); margin-top:calc(var(--sp-3) * -1); position:relative; z-index:2}
.js .story-block:not(.is-visible) .story-cta{opacity:0}
.story-block.is-visible .story-cta{animation:story-cta-in .55s cubic-bezier(.2,.9,.3,1.2) 1.5s both}
@keyframes story-cta-in{from{opacity:0; transform:translateY(14px)} to{opacity:1; transform:none}}
@media (prefers-reduced-motion:reduce){
  .story-cta{opacity:1 !important; animation:none !important}
}

/* ------------------------------------------------------------------
   36. Team ring — the people behind the initiatives
   A real ring of plates rotating on its axis, not tilted cards: each plate
   carries a front, a back and two perpendicular strips, so it keeps its
   thickness when it turns side-on. The showcase panel stays dark in both
   themes because the cosine lighting only reads against a deep ground.
   ------------------------------------------------------------------ */
.team-case{
  --case-ink:#F6EEF9;
  --case-mute:#B49CC0;
  border-radius: var(--r-lg);
  overflow: hidden;
  /* the ring is only as wide as the plates need — a full-container case
     leaves dead panel on either side of it */
  max-width: 820px;
  margin-inline: auto;
  background:
    radial-gradient(90% 120% at 18% 0%, rgba(236, 44, 140, .22), transparent 58%),
    radial-gradient(80% 110% at 84% 6%, rgba(23, 185, 212, .20), transparent 60%),
    linear-gradient(170deg, #3A2448, #180E20 72%);
  box-shadow: var(--sh-lg);
}

.team-mount{
  position: relative;
  width: 100%;
  height: clamp(300px, 70vw, 430px);
  perspective: 1000px;
  perspective-origin: 50% 48%;
  cursor: grab;
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.team-mount:active{ cursor: grabbing; }
.team-mount:focus-visible{ outline: 2.5px solid var(--pink-300); outline-offset: -6px; border-radius: var(--r-lg); }

.team-ring{
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transform: rotateX(-7deg) translateZ(calc(var(--r, 200px) * -1)) rotateY(var(--a, 0deg));
  will-change: transform;
}

.team-plate{
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--pw, 160px);
  height: var(--ph, 212px);
  /* left/top are physical, so the centring margin has to be physical too —
     a logical margin flips under dir="rtl" and throws the ring off centre */
  margin-left: calc(var(--pw, 160px) / -2);
  margin-top: calc(var(--ph, 212px) / -2);
  transform-style: preserve-3d;
  transform: rotateY(var(--p-a)) translateZ(var(--r, 200px));
}

.team-face,
.team-back{
  position: absolute;
  inset: 0;
  border-radius: 12px;
  overflow: hidden;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  filter: brightness(var(--p-b, 1));
}
.team-face{
  background: #2A1B33;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .22), inset 0 1px 0 rgba(255, 255, 255, .4);
}
.team-face img{ width: 100%; height: 100%; object-fit: cover; display: block; }
.team-cap{
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  padding: 26px 10px 10px;
  text-align: center;
  background: linear-gradient(transparent, rgba(18, 9, 24, .88) 58%);
  color: #fff;
}
.team-cap b{ display: block; font-size: var(--fs-xs); font-weight: 800; line-height: 1.35; }
.team-cap span{ font-size: 11px; opacity: .78; }

/* the far half of the ring shows backs, never mirrored faces */
.team-back{
  transform: rotateY(180deg);
  background:
    radial-gradient(75% 55% at 50% 30%, rgba(255, 255, 255, .18), transparent 70%),
    linear-gradient(150deg, rgba(236, 44, 140, .5), rgba(23, 185, 212, .4));
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .18);
  /* far side of the ring: present enough to read as a ring, quiet enough
     that the eye stays on the portrait in front */
  filter: brightness(calc(.34 + var(--p-b, 1) * .5));
}

/* the thickness: a strip on each perpendicular plane */
.team-edge{
  position: absolute;
  top: 0;
  width: 11px;
  height: 100%;
  border-radius: 3px;
  background: linear-gradient(180deg, var(--pink-500), var(--cyan-500));
  filter: brightness(calc(var(--p-b, 1) * .9));
}
.team-edge-r{ right: 0; transform-origin: right center; transform: rotateY(90deg); }
.team-edge-l{ left: 0;  transform-origin: left center;  transform: rotateY(-90deg); }

.team-bar{
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
  padding: 0 var(--sp-4) var(--sp-5);
}
.team-nav{
  width: 44px;
  height: 44px;
  flex: none;
  border-radius: 50%;
  cursor: pointer;
  border: 1px solid rgba(255, 255, 255, .26);
  background: rgba(255, 255, 255, .08);
  color: var(--case-ink);
  display: grid;
  place-items: center;
  transition: background .2s, border-color .2s, transform .2s;
}
.team-nav:hover{ background: rgba(255, 255, 255, .18); border-color: rgba(255, 255, 255, .5); transform: translateY(-1px); }
.team-readout{ min-width: min(22ch, 60vw); text-align: center; color: var(--case-ink); margin: 0; }
.team-readout b{ display: block; font-size: var(--fs-md); font-weight: 800; line-height: 1.4; }
.team-readout span{ font-size: var(--fs-sm); color: var(--case-mute); }
.team-hint{ text-align: center; padding: 0 var(--sp-4) var(--sp-4); font-size: var(--fs-xs); color: var(--case-mute); margin: 0; }

/* No JS, no rotation — fall back to a plain readable grid of portraits.
   Every 3D property is unwound here, not just overridden: a preserve-3d
   subtree with backface-visibility still culls faces that are laid out flat. */
.team-case:not(.is-live) .team-bar,
.team-case:not(.is-live) .team-hint{ display: none; }
.team-case:not(.is-live) .team-mount{
  height: auto;
  perspective: none;
  padding: var(--sp-5);
  cursor: auto;
}
.team-case:not(.is-live) .team-ring{
  position: static;
  transform: none;
  transform-style: flat;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-4);
}
.team-case:not(.is-live) .team-plate{
  position: relative;
  margin: 0;
  width: clamp(120px, 22vw, 160px);
  aspect-ratio: 3 / 4;
  height: auto;
  transform: none;
  transform-style: flat;
}
.team-case:not(.is-live) .team-face{
  backface-visibility: visible;
  filter: none;
}
.team-case:not(.is-live) .team-back,
.team-case:not(.is-live) .team-edge{ display: none; }

/* Dashboard → Settings → Team ring. Every default here reproduces the ring
   exactly as it was before the controls existed; a case without these classes
   is untouched. */

/* Bigger portraits. The panel grows with them so the ring keeps its room, and
   the caption shrinks because a long job title over a face is the thing the
   larger photo was meant to fix. */
.team-case.is-large{ max-width: 1000px; }
.team-case.is-large .team-mount{ height: clamp(330px, 84vw, 560px); }
.team-case.is-large .team-cap{ padding: 30px 12px 12px; }
.team-case.is-large .team-cap b{ font-size: var(--fs-sm); }
.team-case.is-large .team-readout b{ font-size: var(--fs-lg); }

/* Names off the photo: the portrait is left alone and the readout under the
   ring carries the name, which it already did for screen readers. */
.team-case.no-captions .team-cap{ display: none; }

/* ------------------------------------------------------------------
   37. Volunteering certificate
   Printed as often as it is viewed, so the screen version is only the
   paper one with a background behind it.
   ------------------------------------------------------------------ */
.certificate{ padding: clamp(18px, 4vw, 34px); }
.cert-frame{
  border: 2px solid var(--pink-200);
  border-radius: var(--r-md);
  padding: clamp(22px, 5vw, 52px) clamp(18px, 5vw, 56px);
  text-align: center;
  position: relative;
  background:
    radial-gradient(70% 50% at 50% 0%, var(--pink-50), transparent 70%),
    radial-gradient(60% 45% at 50% 100%, var(--cyan-50), transparent 70%),
    #fff;
}
.cert-logo{ height: 55px; width: auto; margin: 0 auto var(--sp-5); display: block; }
.cert-kicker{
  margin: 0 0 var(--sp-2); font-size: var(--fs-xs); font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--primary-ink);
}
.cert-title{ margin: 0 0 var(--sp-6); font-size: clamp(22px, 4.5vw, 32px); font-weight: 900; color: var(--ink-900); }
.cert-lead{ margin: 0 0 var(--sp-2); color: var(--ink-600); font-size: var(--fs-sm); }
.cert-name{
  margin: 0 0 var(--sp-5); font-size: clamp(24px, 5.5vw, 38px); font-weight: 800;
  color: var(--ink-900); line-height: 1.3;
  border-bottom: 2px solid var(--pink-200); display: inline-block; padding-bottom: var(--sp-2);
}
.cert-body{ margin: 0 auto var(--sp-4); max-width: 52ch; line-height: 2; color: var(--ink-700); }
.cert-note{
  margin: 0 auto var(--sp-5); max-width: 52ch; line-height: 1.9;
  color: var(--ink-600); font-style: italic;
}
.cert-foot{
  display: flex; flex-wrap: wrap; justify-content: center; gap: var(--sp-5);
  margin-top: var(--sp-6); padding-top: var(--sp-5); border-top: 1px solid var(--pink-100);
}
.cert-foot-block{ display: grid; gap: 2px; min-width: 130px; }
.cert-label{ font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-500); }
.cert-value{ font-weight: 700; color: var(--ink-800); font-variant-numeric: tabular-nums; }
.cert-verify{ margin: var(--sp-5) 0 0; font-size: 11px; color: var(--ink-500); line-height: 1.8; }
.cert-actions{ text-align: center; margin-top: var(--sp-5); }

@media print{
  .cert-actions{ display: none; }
  .cert-frame{ border-color: #E6B9D2; }
  .certificate{ padding: 0; }
}

/* ------------------------------------------------------------------
   38. Theme toggle
   Only rendered when an administrator allows visitors to switch, so the
   button's absence is a decision rather than a missing feature.
   ------------------------------------------------------------------ */
.theme-toggle{ position: relative; }
.theme-icon{ display: grid; place-items: center; transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease); }
.theme-icon-moon{ position: absolute; inset: 0; }

/* Whichever scheme is active, the button offers the other one. */
.theme-icon-sun{ opacity: 0; transform: rotate(-40deg) scale(.7); }
.theme-icon-moon{ opacity: 1; transform: none; }
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]) .theme-icon-sun{ opacity: 1; transform: none; }
  :root:not([data-theme="light"]) .theme-icon-moon{ opacity: 0; transform: rotate(40deg) scale(.7); }
}

/* The same values, reached by an explicit choice rather than the device.
   Plain CSS cannot share one declaration block between a media query and a
   selector, so this twin exists on purpose — edit the pair together. */
:root[data-theme="dark"] .theme-icon-sun{ opacity: 1; transform: none; }
:root[data-theme="dark"] .theme-icon-moon{ opacity: 0; transform: rotate(40deg) scale(.7); }
:root[data-theme="dark"] .theme-icon-sun{ opacity: 1; transform: none; }
:root[data-theme="dark"] .theme-icon-moon{ opacity: 0; transform: rotate(40deg) scale(.7); }
:root[data-theme="light"] .theme-icon-sun{ opacity: 0; transform: rotate(-40deg) scale(.7); }
:root[data-theme="light"] .theme-icon-moon{ opacity: 1; transform: none; }

/* ------------------------------------------------------------------
   39. Optional motion
   Everything here hangs off body[data-motion~="…"], an attribute the layout
   only emits for effects an administrator switched on. With none enabled the
   attribute is absent, none of these selectors match, and the page is exactly
   what it was.
   ------------------------------------------------------------------ */

/* --- counters: an arc that fills with the count ------------------- */
.stat-dial{ position: relative; width: 96px; height: 96px; margin: 0 auto var(--sp-2); }
.stat-dial svg{ width: 100%; height: 100%; transform: rotate(-90deg); }
.stat-dial .dial-track{ fill: none; stroke: var(--border); stroke-width: 6; }
.stat-dial .dial-arc{
  fill: none; stroke: url(#hareer-dial); stroke-width: 6; stroke-linecap: round;
  stroke-dashoffset: var(--dash, 264);
}
.stat-dial > .stat-value{
  position: absolute; inset: 0; display: grid; place-items: center; margin: 0;
}
body[data-motion~="counters"] .stat .stat-icon{ display: none; }

/* --- timeline ----------------------------------------------------- */
.tl{ position: relative; padding-inline-start: 34px; max-width: 62ch; margin-inline: auto; }
.tl::before{
  content: ''; position: absolute; inset-block: 6px; inset-inline-start: 9px; width: 2px;
  border-radius: 2px; background: linear-gradient(180deg, var(--primary), var(--accent));
  transform: scaleY(0); transform-origin: top;
  transition: transform 1.4s cubic-bezier(.4, 0, .2, 1);
}
.tl.is-visible::before{ transform: scaleY(1); }
.tl-item{ position: relative; padding-bottom: var(--sp-5); }
.js .tl:not(.is-visible) .tl-item{ opacity: 0; transform: translateY(16px); }
.tl.is-visible .tl-item{ animation: tl-in .6s cubic-bezier(.2, .9, .3, 1.1) both; }
@keyframes tl-in{ from{ opacity: 0; transform: translateY(16px); } to{ opacity: 1; transform: none; } }
.tl-item::before{
  content: ''; position: absolute; inset-inline-start: -30px; top: 7px; width: 12px; height: 12px;
  border-radius: 50%; background: var(--bg-elevated); border: 3px solid var(--primary);
  box-shadow: 0 0 0 4px var(--tint-pink);
}
.tl-item:nth-child(even)::before{ border-color: var(--accent); box-shadow: 0 0 0 4px var(--tint-cyan); }
.tl-year{ font-size: var(--fs-xs); font-weight: 800; letter-spacing: .08em; color: var(--primary-ink); font-variant-numeric: tabular-nums; }
.tl-item:nth-child(even) .tl-year{ color: var(--accent-ink); }
.tl-title{ font-size: var(--fs-md); font-weight: 800; margin-top: 2px; }
.tl-text{ font-size: var(--fs-sm); color: var(--text-muted); margin-top: 3px; }

/* --- story: the braid becomes the wig, driven by scroll ----------- */
/* The stock choreography stands down so the two cannot fight over the
   same transforms; from here the scroll position is the only driver. */
body[data-motion~="story"] .story-block.is-visible .braid,
body[data-motion~="story"] .story-block.is-visible .receiver{ animation: none; }
body[data-motion~="story"] .story-figures .braid{
  transform: translate(calc(var(--story-t, 0) * -300px), calc(var(--story-t, 0) * -150px))
             scale(calc(1 - var(--story-t, 0) * 0.45));
  opacity: calc(1 - var(--story-t, 0) * var(--story-t, 0));
  transform-box: fill-box; transform-origin: center;
}
body[data-motion~="story"] .story-figures .wig{ opacity: var(--story-t, 0); }

/* --- campaign cards: tilt toward the pointer ---------------------- */
body[data-motion~="cards"] .campaign-card{
  transform-style: preserve-3d;
  transition: transform .35s cubic-bezier(.22, 1, .36, 1), box-shadow .35s var(--ease);
  will-change: transform;
}
body[data-motion~="cards"] .campaign-card .card-media,
body[data-motion~="cards"] .campaign-card .card-body{ transform: translateZ(18px); }

/* --- thank you: one pass of petals -------------------------------- */
.petals{ position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.petal{
  position: absolute; top: -24px; border-radius: 60% 40% 55% 45%;
  animation: petal-fall linear forwards;
}
@keyframes petal-fall{
  0%{ opacity: 0; transform: translateY(-10px) rotate(0deg); }
  10%{ opacity: 1; }
  100%{ opacity: 0; transform: translateY(70vh) rotate(var(--spin, 360deg)); }
}

/* --- reading progress + glass header ------------------------------ */
.read-bar{
  position: fixed; inset-inline: 0; top: 0; height: 3px; z-index: 60;
  background: linear-gradient(90deg, var(--primary), var(--accent));
  transform: scaleX(var(--read, 0)); transform-origin: inline-start;
  transition: transform .1s linear;
}
body[data-motion~="reading"] .site-header.is-reading{
  background: color-mix(in srgb, var(--bg-elevated) 74%, transparent);
  backdrop-filter: saturate(160%) blur(12px);
  -webkit-backdrop-filter: saturate(160%) blur(12px);
}

/* --- initiative icons: one play when the card arrives -------------- */
body[data-motion~="icons"] .initiative-card .init-icon svg{
  transform-box: fill-box; transform-origin: center;
}
body[data-motion~="icons"] .initiative-card.reveal.is-visible .init-icon svg{
  animation: icon-in .7s cubic-bezier(.2, .9, .3, 1.3) both;
}
@keyframes icon-in{
  0%{ opacity: 0; transform: scale(.4) rotate(-18deg); }
  60%{ opacity: 1; }
  100%{ opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce){
  .tl::before{ transform: none; }
  .tl.is-visible .tl-item{ animation: none; }
  .js .tl:not(.is-visible) .tl-item{ opacity: 1; transform: none; }
  .petal{ display: none; }
  body[data-motion~="story"] .story-figures .braid{ transform: none; opacity: 1; }
  body[data-motion~="story"] .story-figures .wig{ opacity: 1; }
  body[data-motion~="icons"] .initiative-card.reveal.is-visible .init-icon svg{ animation: none; }
}

/* ---------------------------------------------------------------------
   40. Notification opt-in
   Rendered hidden and revealed by script only where the browser can really
   subscribe, so a device that cannot do this is never offered the choice.
   ------------------------------------------------------------------ */
.push-optin{
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--border); border-radius: var(--r-lg);
  background: var(--bg-elevated);
}
.push-optin-icon{
  display: grid; place-items: center; flex: none;
  width: 42px; height: 42px; border-radius: 50%;
  background: color-mix(in srgb, var(--primary) 12%, transparent);
  color: var(--primary);
}
.push-optin-text{ display: grid; gap: .15rem; min-width: 0; flex: 1 1 auto; }
.push-optin-text strong{ font-size: var(--fs-sm); }
.push-optin-text span{ font-size: var(--fs-xs); color: var(--text-muted); }
.push-optin .btn{ flex: none; }

@media (max-width: 560px){
  .push-optin{ flex-wrap: wrap; }
  .push-optin .btn{ width: 100%; }
}

/* ---------------------------------------------------------------------
   41. Notification centre
   The list of what the foundation has announced. It exists because a push
   notification is gone once dismissed — and never arrives at all on a device
   that cannot register for one.
   ------------------------------------------------------------------ */
.bell-btn{ position: relative; }
.bell-count{
  position: absolute; inset-block-start: 2px; inset-inline-end: 2px;
  min-width: 17px; height: 17px; padding: 0 4px;
  display: grid; place-items: center;
  font-size: 10px; font-weight: 700; line-height: 1;
  color: #fff; background: var(--primary);
  border: 2px solid var(--bg-elevated); border-radius: var(--r-full);
}

.notify-panel{
  position: fixed; inset: 0; z-index: 70;
  background: rgba(20, 16, 25, .45);
  display: grid; justify-items: end; align-items: start;
  padding: calc(var(--header-h, 64px) + var(--sp-2)) var(--sp-3) var(--sp-3);
  animation: notify-in var(--dur-fast) var(--ease);
}
/* One rule for all of them: an author `display` beats the browser's own
   [hidden] rule, so anything the markup hides stays on screen and, when it
   covers the page, swallows every click. */
[hidden]{ display: none !important; }
@keyframes notify-in{ from{ opacity: 0 } to{ opacity: 1 } }

.notify-sheet{
  width: min(380px, 100%); max-height: min(70vh, 560px);
  display: flex; flex-direction: column;
  background: var(--bg-elevated); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: 0 18px 48px rgba(20, 16, 25, .22);
  overflow: hidden;
}
.notify-head{
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3); padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--border);
}
.notify-list{ overflow-y: auto; overscroll-behavior: contain; }
.notify-empty{
  margin: 0; padding: var(--sp-6) var(--sp-4);
  text-align: center; color: var(--text-muted); font-size: var(--fs-sm);
}

.notify-item{
  display: grid; gap: .15rem;
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--border);
  color: inherit; text-decoration: none;
}
.notify-item:last-child{ border-bottom: 0; }
.notify-item:hover{ background: var(--bg-sunken); }
.notify-item strong{ font-size: var(--fs-sm); }
.notify-item span{ font-size: var(--fs-xs); color: var(--text-muted); }
.notify-item time{ font-size: var(--fs-xs); color: var(--text-subtle, var(--text-muted)); }

/* Unread since the reader last looked: a mark in the margin, which survives
   both colour schemes better than a tinted row. */
.notify-item.is-fresh{ position: relative; }
.notify-item.is-fresh::before{
  content: ""; position: absolute; inset-block: 0; inset-inline-start: 0;
  width: 3px; background: var(--primary);
}

@media (max-width: 560px){
  .notify-panel{ justify-items: stretch; padding-inline: var(--sp-2); }
  .notify-sheet{ width: 100%; }
}

/* The offer to be told next time, sitting above the list of what was missed. */
.notify-ask{
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--primary) 6%, transparent);
}
.notify-ask-text{ flex: 1 1 auto; min-width: 0; }
.notify-ask-text strong{ font-size: var(--fs-xs); font-weight: 500; color: var(--text-muted); }
.notify-ask .btn{ flex: none; }
