/* ==========================================================================
   تعاونية العائلات الأردنية — Design System
   Hand-written CSS. No framework, no build step, no preprocessor.
   Direction-agnostic: uses CSS logical properties throughout so RTL is
   structural rather than patched. Do not introduce left/right properties.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Fonts (self-hosted — no third-party CDN request)
   -------------------------------------------------------------------------- */

@font-face {
  font-family: 'IBM Plex Sans Arabic';
  src: url('../fonts/ibm-plex-sans-arabic-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'IBM Plex Sans Arabic';
  src: url('../fonts/ibm-plex-sans-arabic-500.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'IBM Plex Sans Arabic';
  src: url('../fonts/ibm-plex-sans-arabic-600.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'IBM Plex Sans Arabic';
  src: url('../fonts/ibm-plex-sans-arabic-700.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter-500.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter-600.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter-700.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* --------------------------------------------------------------------------
   2. Tokens
   -------------------------------------------------------------------------- */

:root {
  /* Brand green — derived from the association mark. 6.8:1 on white (AA). */
  --green-900: #1c3a2f;
  --green-800: #26503f;
  --green-700: #326451;
  --green-600: #3d7a63;
  --green-400: #7ba694;
  --green-100: #e4efe9;
  --green-50:  #f2f8f5;

  /* Warm sand. NOTE: --sand-400 is 1.7:1 on white — decorative ONLY,
     never body text. --sand-800 is the accessible text-weight variant. */
  --sand-800: #8a6a2f;
  --sand-400: #dfc696;
  --sand-200: #f0e3c8;
  --sand-100: #faf4e8;

  /* Neutrals */
  --ink-900: #161a18;
  --ink-800: #262c29;
  --ink-700: #3a403c;
  --ink-500: #5f6862;  /* 5.7:1 on white (AA) */
  --ink-300: #a8b0ab;
  --ink-200: #dde2df;
  --ink-100: #edf0ee;
  --white:   #ffffff;
  --paper:   #fcfbf8;

  --danger:  #a3282b;
  --danger-bg: #fdf2f2;

  /* Typography */
  --font-ar: 'IBM Plex Sans Arabic', 'Noto Kufi Arabic', 'Segoe UI', system-ui, sans-serif;
  --font-en: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font: var(--font-en);

  /* Fluid type scale */
  --t-xs:   0.8125rem;
  --t-sm:   0.9063rem;
  --t-base: 1rem;
  --t-md:   clamp(1.0625rem, 0.2vw + 1rem, 1.125rem);
  --t-lg:   clamp(1.1875rem, 0.4vw + 1.1rem, 1.375rem);
  --t-xl:   clamp(1.375rem, 0.9vw + 1.15rem, 1.75rem);
  --t-2xl:  clamp(1.625rem, 1.6vw + 1.2rem, 2.25rem);
  --t-3xl:  clamp(1.875rem, 2.6vw + 1.25rem, 3rem);
  --t-4xl:  clamp(2.25rem, 3.6vw + 1.35rem, 3.75rem);

  /* Spacing */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.5rem;
  --s-6: 2rem;
  --s-7: 2.5rem;
  --s-8: 3rem;
  --s-9: 4rem;
  --s-10: 5rem;
  --s-11: 6.5rem;

  /* Measured 2026-09-20: at 6.5rem the ink-to-ink gap between two sections was
     209-286px (104px bottom + 104px top + heading margins) and sections ran 24-44%
     empty. Tightened to 5rem, which lands the same gap around 160-190px. Adjust
     here, never per-section, so the page keeps one vertical rhythm. */
  --section-y: clamp(2.75rem, 5.2vw, 5rem);
  --shell: 1200px;
  --shell-narrow: 780px;
  --gutter: clamp(1.125rem, 4vw, 2.5rem);

  /* Shape */
  --r-sm: 8px;
  --r-md: 14px;
  --r-lg: 20px;
  --r-xl: 28px;
  --r-pill: 999px;

  /* Elevation — soft, warm-tinted, never harsh */
  --sh-sm: 0 1px 2px rgba(28, 58, 47, 0.05), 0 1px 3px rgba(28, 58, 47, 0.04);
  --sh-md: 0 4px 6px -2px rgba(28, 58, 47, 0.05), 0 12px 20px -6px rgba(28, 58, 47, 0.08);
  --sh-lg: 0 8px 16px -6px rgba(28, 58, 47, 0.07), 0 24px 40px -12px rgba(28, 58, 47, 0.12);

  /* Scene — the one palette the canvas and the CSS fallback both read.
     Experience.js pulls these off :root with getComputedStyle rather than
     carrying its own copy, so the 3D and the stylesheet can never drift apart.
     Changing a value here changes both.

     LIGHT. The scene is ink and sand on paper. There is no dark mode and no
     dark hero: the canvas draws the country in the brand's own sand on a
     near-white ground, and the network over it in brand green. */
  --scene-sky-top:    #ffffff;
  --scene-sky-bottom: #f2f7f4;
  --scene-pool:       #e7f0ea;  /* where the pointer warms the paper */
  --scene-land:       #dfc696;  /* = sand-400, the map of Jordan */
  --scene-thread:     #26503f;  /* = green-800, the lacing */
  --scene-node:       #1c3a2f;  /* = green-900, the strongest marks */
  --scene-glow:       #8a6a2f;  /* = sand-800, warm ink under the pointer */
  --scene-key-light:  #fff4e2;

  /* The two inks the logo is actually printed in, sampled from
     assets/brand/logo.png. The crowd wears the scene greens above; the moment
     they stand up as the mark they wear these, so the logo the scene builds
     and the logo in the header are the same colours. */
  --scene-mark-sand:  #d8c9a2;
  --scene-mark-ink:   #406051;

  --ring: 0 0 0 3px var(--white), 0 0 0 6px var(--green-600);
  --dur: 220ms;
  --ease: cubic-bezier(0.22, 0.68, 0.3, 1);
}

/* Scoped to any element, not just <html>: the language switch carries its own
   lang/dir and is the one label written in the other script, so it gets that
   script's bundled face instead of a system fallback. */
[lang='ar'] { --font: var(--font-ar); }
[lang='en'] { --font: var(--font-en); }

/* --------------------------------------------------------------------------
   3. Reset & base
   -------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-block-start: 6rem;
}

body {
  font-family: var(--font);
  font-size: var(--t-base);
  line-height: 1.65;
  color: var(--ink-800);
  background: var(--white);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* Arabic needs slightly more leading and no letter-spacing games. */
html[lang='ar'] body { line-height: 1.85; letter-spacing: 0; }

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

h1, h2, h3, h4 {
  line-height: 1.2;
  font-weight: 700;
  color: var(--ink-900);
  text-wrap: balance;
}
html[lang='ar'] h1,
html[lang='ar'] h2,
html[lang='ar'] h3,
html[lang='ar'] h4 { line-height: 1.4; font-weight: 600; }

p { text-wrap: pretty; }

a { color: var(--green-700); text-underline-offset: 3px; }
a:hover { color: var(--green-800); }

ul, ol { padding-inline-start: 1.25rem; }

button, input, select, textarea { font: inherit; color: inherit; }

:focus-visible {
  outline: none;
  box-shadow: var(--ring);
  border-radius: var(--r-sm);
}

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

/* --------------------------------------------------------------------------
   4. Utilities & layout primitives
   -------------------------------------------------------------------------- */

.shell {
  inline-size: min(100% - (var(--gutter) * 2), var(--shell));
  margin-inline: auto;
}
.shell-narrow { inline-size: min(100% - (var(--gutter) * 2), var(--shell-narrow)); margin-inline: auto; }

.section { padding-block: var(--section-y); }
.section-tight { padding-block: clamp(2rem, 3.6vw, 3rem); }
.bg-paper { background: var(--paper); }
.bg-sand  { background: var(--sand-100); }
.bg-green { background: var(--green-50); }

.visually-hidden {
  position: absolute;
  inline-size: 1px; block-size: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%);
  white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute;
  inset-block-start: -100px;
  inset-inline-start: var(--s-4);
  z-index: 200;
  background: var(--green-700);
  color: var(--white);
  padding: var(--s-3) var(--s-5);
  border-radius: 0 0 var(--r-md) var(--r-md);
  font-weight: 600;
  text-decoration: none;
  transition: inset-block-start var(--dur) var(--ease);
}
.skip-link:focus { inset-block-start: 0; color: var(--white); }

/* Section heading block */
.sec-head { max-inline-size: 46rem; margin-block-end: var(--s-8); }
.sec-head.center { margin-inline: auto; text-align: center; }

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--green-700);
  margin-block-end: var(--s-3);
}
html[lang='ar'] .eyebrow { letter-spacing: 0; text-transform: none; font-size: var(--t-sm); }
.eyebrow::before {
  content: '';
  inline-size: 22px; block-size: 2px;
  background: var(--sand-400);
  border-radius: 2px;
}
.sec-head.center .eyebrow::before { display: none; }

.sec-head h2 { font-size: var(--t-3xl); }
.sec-head .lead { margin-block-start: var(--s-4); font-size: var(--t-md); color: var(--ink-500); }

.lead { font-size: var(--t-md); color: var(--ink-500); }

/* --------------------------------------------------------------------------
   5. Buttons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  padding: 0.8125rem 1.5rem;
  border-radius: var(--r-pill);
  font-weight: 600;
  font-size: var(--t-base);
  text-decoration: none;
  border: 1.5px solid transparent;
  cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
              border-color var(--dur) var(--ease), transform var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease);
}
.btn .arrow { transition: transform var(--dur) var(--ease); flex: none; }
/* Arrow travels toward the reading direction — mirrors automatically in RTL. */
.btn:hover .arrow { transform: translateX(3px); }
html[dir='rtl'] .btn:hover .arrow { transform: translateX(-3px); }
html[dir='rtl'] .btn .arrow { scale: -1 1; }

.btn-primary { background: var(--green-700); color: var(--white); box-shadow: var(--sh-sm); }
.btn-primary:hover { background: var(--green-800); color: var(--white); box-shadow: var(--sh-md); transform: translateY(-1px); }

.btn-secondary { background: var(--white); color: var(--green-800); border-color: var(--ink-200); }
.btn-secondary:hover { background: var(--green-50); color: var(--green-900); border-color: var(--green-400); }

.btn-ghost { background: transparent; color: var(--green-800); }
.btn-ghost:hover { background: var(--green-50); color: var(--green-900); }

.btn-on-dark { background: var(--white); color: var(--green-800); }
.btn-on-dark:hover { background: var(--sand-100); color: var(--green-900); transform: translateY(-1px); }

.btn-outline-light { background: transparent; color: var(--white); border-color: rgba(255,255,255,0.45); }
.btn-outline-light:hover { background: rgba(255,255,255,0.12); color: var(--white); border-color: var(--white); }

.btn-sm { padding: 0.5rem 1rem; font-size: var(--t-sm); }
.btn[aria-disabled='true'] { opacity: 0.55; pointer-events: none; }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--s-3); }

/* On narrow screens stacked buttons look ragged at intrinsic width — give them
   a single full-width column instead. */
@media (max-width: 560px) {
  .btn-row { flex-direction: column; align-items: stretch; }
  .btn-row > .btn { inline-size: 100%; }
}

/* --------------------------------------------------------------------------
   6. Header
   -------------------------------------------------------------------------- */

.site-header {
  position: sticky;
  inset-block-start: 0;
  z-index: 100;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(10px);
  border-block-end: 1px solid transparent;
  transition: box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease),
              background var(--dur) var(--ease);
}
.site-header.is-scrolled {
  box-shadow: var(--sh-sm);
  border-block-end-color: var(--ink-100);
}

.header-inner {
  display: flex;
  align-items: center;
  gap: var(--s-5);
  min-block-size: 84px;
  transition: min-block-size var(--dur) var(--ease);
}
.site-header.is-scrolled .header-inner { min-block-size: 68px; }

.brand { display: inline-flex; align-items: center; gap: var(--s-3); text-decoration: none; flex: none; }
.brand img, .brand svg { block-size: 46px; inline-size: auto; transition: block-size var(--dur) var(--ease); }
.site-header.is-scrolled .brand img,
.site-header.is-scrolled .brand svg { block-size: 38px; }

.nav-desktop { display: none; margin-inline-start: auto; }
.nav-desktop ul { display: flex; align-items: center; gap: var(--s-1); list-style: none; margin: 0; padding: 0; }
.nav-desktop a {
  display: block;
  padding: 0.5rem 0.75rem;
  border-radius: var(--r-sm);
  font-size: var(--t-sm);
  font-weight: 500;
  color: var(--ink-700);
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.nav-desktop a:hover { color: var(--green-800); background: var(--green-50); }
.nav-desktop a[aria-current='page'] { color: var(--green-800); font-weight: 600; }

.header-actions { display: flex; align-items: center; gap: var(--s-2); margin-inline-start: auto; }

.lang-switch {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: 0.45rem 0.85rem;
  border: 1.5px solid var(--ink-200);
  border-radius: var(--r-pill);
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--ink-700);
  text-decoration: none;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.lang-switch:hover { border-color: var(--green-400); color: var(--green-800); background: var(--green-50); }
.lang-switch, .mobile-menu-foot .btn[lang] { font-family: var(--font); }

.header-cta { display: none; }

.menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 44px; block-size: 44px;
  background: transparent;
  border: 1.5px solid var(--ink-200);
  border-radius: var(--r-md);
  cursor: pointer;
  color: var(--ink-800);
}
.menu-toggle:hover { border-color: var(--green-400); color: var(--green-800); }

@media (min-width: 1080px) {
  .nav-desktop { display: block; }
  /* Only once the nav is actually visible does it take over pushing the group
     to the inline end; below this width .header-actions keeps its auto margin
     and does that itself. */
  .nav-desktop + .header-actions { margin-inline-start: var(--s-3); }
  .header-cta { display: inline-flex; }
  .menu-toggle { display: none; }
}

/* Mobile menu ---------------------------------------------------------- */

.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: 150;
  display: grid;
  grid-template-rows: auto 1fr;
  background: var(--white);
  visibility: hidden;
  opacity: 0;
  transition: opacity var(--dur) var(--ease), visibility var(--dur) var(--ease);
}
.mobile-menu.is-open { visibility: visible; opacity: 1; }

.mobile-menu-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-4);
  min-block-size: 84px;
  border-block-end: 1px solid var(--ink-100);
}
.mobile-menu-body { overflow-y: auto; padding-block: var(--s-6) var(--s-8); }
.mobile-menu ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-1); }
.mobile-menu li a {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--s-4) var(--s-3);
  border-radius: var(--r-md);
  font-size: var(--t-lg);
  font-weight: 500;
  color: var(--ink-800);
  text-decoration: none;
  border-block-end: 1px solid var(--ink-100);
}
.mobile-menu li a:hover { background: var(--green-50); color: var(--green-800); }
.mobile-menu li a[aria-current='page'] { color: var(--green-800); font-weight: 700; }
.mobile-menu li a .arrow { color: var(--ink-300); }
html[dir='rtl'] .mobile-menu li a .arrow { scale: -1 1; }
.mobile-menu-foot { margin-block-start: var(--s-7); display: grid; gap: var(--s-3); }

body.menu-open { overflow: hidden; }

/* --------------------------------------------------------------------------
   7. Hero
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(ellipse 80% 60% at 50% -10%, var(--green-50), transparent 70%),
    var(--paper);
  padding-block: clamp(2.5rem, 5vw, 4.5rem) clamp(2.75rem, 5.5vw, 5rem);
}
.hero::after {
  /* Organic curve echoing the mark, anchored to the reading direction. */
  content: '';
  position: absolute;
  inset-block-start: -30%;
  inset-inline-end: -12%;
  inline-size: 46rem; block-size: 46rem;
  background: radial-gradient(circle, var(--sand-100) 0%, transparent 62%);
  border-radius: 50%;
  pointer-events: none;
  z-index: 0;
}
.hero > * { position: relative; z-index: 1; }

.hero-grid { display: grid; gap: clamp(2.5rem, 5vw, 4rem); align-items: center; }
@media (min-width: 900px) { .hero-grid { grid-template-columns: 1.05fr 0.95fr; } }

.hero h1 { font-size: var(--t-4xl); }
.hero .lead { margin-block-start: var(--s-5); max-inline-size: 38rem; font-size: var(--t-md); }
.hero .btn-row { margin-block-start: var(--s-7); }

.hero-note {
  margin-block-start: var(--s-6);
  font-size: var(--t-sm);
  color: var(--ink-500);
  display: flex; align-items: flex-start; gap: var(--s-2);
}
.hero-note svg { flex: none; margin-block-start: 3px; color: var(--green-600); }

/* Page hero (interior pages) */
.page-hero {
  position: relative;
  overflow: hidden;
  background: linear-gradient(180deg, var(--green-50), var(--paper));
  padding-block: clamp(2rem, 4vw, 3rem) clamp(3rem, 6vw, 4.5rem);
}
.page-hero h1 { font-size: var(--t-3xl); margin-block-start: var(--s-2); }
.page-hero .lead { margin-block-start: var(--s-4); max-inline-size: 44rem; }
.page-hero::after {
  content: '';
  position: absolute;
  inset-block-end: -60%;
  inset-inline-start: -10%;
  inline-size: 32rem; block-size: 32rem;
  background: radial-gradient(circle, var(--sand-100) 0%, transparent 65%);
  border-radius: 50%;
  pointer-events: none;
}
.page-hero > * { position: relative; z-index: 1; }

/* Hero visual composition — built from the brand mark, not stock photography */
.hero-visual { position: relative; display: grid; place-items: center; }
.hero-visual-frame {
  position: relative;
  inline-size: min(100%, 30rem);
  aspect-ratio: 1 / 1;
  display: grid;
  place-items: center;
  background:
    radial-gradient(circle at 50% 45%, var(--white) 0%, var(--sand-100) 55%, var(--green-50) 100%);
  border-radius: 46% 54% 52% 48% / 50% 46% 54% 50%;
  box-shadow: var(--sh-lg);
}
.hero-visual-frame > svg,
.hero-visual-frame > img { inline-size: 62%; block-size: auto; }

.hero-chip {
  position: absolute;
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-4);
  background: var(--white);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-md);
  font-size: var(--t-sm);
  inline-size: max-content;
  max-inline-size: 19rem;
}
.hero-chip strong { display: block; color: var(--ink-900); font-size: var(--t-base); margin-block-end: 2px; }
.hero-chip span { color: var(--ink-500); font-size: var(--t-xs); line-height: 1.5; display: block; }
.hero-chip .chip-icon {
  flex: none;
  inline-size: 38px; block-size: 38px;
  display: grid; place-items: center;
  background: var(--green-50);
  color: var(--green-700);
  border-radius: var(--r-md);
}
/* Sits on the blob's lower edge rather than across the mark itself. */
.hero-chip-1 { inset-block-end: 2%; inset-inline-start: -6%; }

@media (max-width: 899px) {
  .hero-visual-frame { inline-size: min(100%, 22rem); }
  .hero-chip-1 { inset-block-end: -4%; inset-inline-start: 0; max-inline-size: 17rem; }
}

/* --------------------------------------------------------------------------
   8. Cards & grids
   -------------------------------------------------------------------------- */

.grid { display: grid; gap: var(--s-5); }
.grid-2 { grid-template-columns: 1fr; }
.grid-3 { grid-template-columns: 1fr; }
.grid-4 { grid-template-columns: 1fr; }
@media (min-width: 620px) {
  .grid-2 { grid-template-columns: repeat(2, 1fr); }
  .grid-3 { grid-template-columns: repeat(2, 1fr); }
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 960px) {
  .grid-3 { grid-template-columns: repeat(3, 1fr); }
  .grid-4 { grid-template-columns: repeat(4, 1fr); }
}

.card {
  background: var(--white);
  border: 1px solid var(--ink-100);
  border-radius: var(--r-lg);
  padding: var(--s-6);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.card:hover { transform: translateY(-3px); box-shadow: var(--sh-md); border-color: var(--ink-200); }
.card h3 { font-size: var(--t-lg); margin-block-end: var(--s-2); }
.card p { color: var(--ink-500); font-size: var(--t-sm); }

.card-icon {
  inline-size: 52px; block-size: 52px;
  display: grid; place-items: center;
  border-radius: var(--r-md);
  background: var(--green-50);
  color: var(--green-700);
  margin-block-end: var(--s-4);
}
.card-icon.sand { background: var(--sand-100); color: var(--sand-800); }

/* Partner card: the organisation's own logo, boxed so wildly different aspect
   ratios (Munich RE is wide, GlobeMed is square) still line up across the row. */
.partner-logo {
  display: grid; place-items: center;
  block-size: 72px;
  margin-block-end: var(--s-4);
}
.partner-logo img {
  max-inline-size: 100%; max-block-size: 72px;
  inline-size: auto; block-size: auto;
  object-fit: contain;
}

/* Supporting line under a centred section head, kept to a readable measure. */
.fund-note {
  max-inline-size: 62ch;
  margin-inline: auto;
  margin-block-start: var(--s-4);
  text-align: center;
}

/* Member organisation wall.

   The nine marks arrive in nine different states - reversed out of boxes, a
   photo collage, one 145px wide - so they are regenerated rather than shown
   raw (scripts/member-logos.py). Every mark sits on the same 480x240 canvas
   at the same optical size, drawn twice: in the site's green ink at rest, so
   the wall reads as one quiet row of proof, and in the organisation's own
   colours on hover or keyboard focus, so each is still recognisably theirs.
   The two images share a grid cell and a canvas, so the crossfade lines up
   to the pixel. */
/* Three columns, not four: there are nine organisations, so 3x3 fills exactly and
   a fourth column would leave one tile orphaned on its own row. */
.member-wall {
  list-style: none; padding: 0; margin: 0;
  display: grid; gap: var(--s-4);
  grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 640px) { .member-wall { grid-template-columns: repeat(3, 1fr); } }
.member-logo {
  display: grid; place-items: center;
  padding: var(--s-4) var(--s-5);
  min-block-size: 128px;
  background: var(--white);
  border: 1px solid var(--ink-100);
  border-radius: var(--r-lg);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.member-logo > * { grid-area: 1 / 1; }
.member-logo img {
  inline-size: 100%; max-inline-size: 280px;
  block-size: auto; aspect-ratio: 2 / 1;
  object-fit: contain;
  transition: opacity var(--dur) var(--ease);
}
.member-logo .member-ink { opacity: 0.82; }
.member-logo .member-color { opacity: 0; }
.member-logo:hover,
.member-logo:focus-visible {
  transform: translateY(-3px);
  box-shadow: var(--sh-md);
  border-color: var(--green-100);
}
.member-logo:focus-visible { outline: 2px solid var(--green-600); outline-offset: 3px; }
.member-logo:hover .member-ink,
.member-logo:focus-visible .member-ink { opacity: 0; }
.member-logo:hover .member-color,
.member-logo:focus-visible .member-color { opacity: 1; }
@media (hover: none) {
  /* Touch has no hover, so phones would never see the real colours. Show
     them outright; the ink version is for the pointer's quiet state only. */
  .member-logo .member-ink { opacity: 0; }
  .member-logo .member-color { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .member-logo, .member-logo img { transition: none; }
  .member-logo:hover, .member-logo:focus-visible { transform: none; }
}
/* An organisation with no logo supplied gets its name set as a wordmark in
   the same ink, so the ninth tile reads as part of the wall, not a gap. */
.member-logo-text span {
  font-weight: 600; color: var(--green-800);
  font-size: var(--t-md); letter-spacing: 0.02em;
  text-align: center; line-height: 1.2;
}

/* Partner card: role + contract date, above the descriptive line */
.partner-meta {
  display: flex; flex-wrap: wrap; gap: var(--s-1) var(--s-3);
  margin-block-end: var(--s-3);
  padding-block-end: var(--s-3);
  border-block-end: 1px solid var(--ink-100);
}
.card .partner-meta span { font-size: var(--t-xs); color: var(--ink-700); font-weight: 600; }

/* Compact category tile */
.tile {
  display: flex; align-items: center; gap: var(--s-4);
  padding: var(--s-5);
  background: var(--white);
  border: 1px solid var(--ink-100);
  border-radius: var(--r-lg);
  font-weight: 600;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.tile:hover { transform: translateY(-3px); box-shadow: var(--sh-md); }
.tile .card-icon { margin-block-end: 0; inline-size: 46px; block-size: 46px; }

/* Bulleted check list */
.checklist { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--s-3); }
.checklist li { display: flex; align-items: flex-start; gap: var(--s-3); }
.checklist svg { flex: none; margin-block-start: 4px; color: var(--green-600); }

/* --------------------------------------------------------------------------
   9. Info / notice panels
   -------------------------------------------------------------------------- */

.panel {
  display: flex;
  gap: var(--s-4);
  padding: var(--s-6);
  border-radius: var(--r-lg);
  background: var(--sand-100);
  border: 1px solid var(--sand-200);
  /* Accent bar on the reading-start edge — mirrors in RTL automatically. */
  border-inline-start: 4px solid var(--sand-400);
}
.panel .panel-icon { flex: none; color: var(--sand-800); margin-block-start: 2px; }
.panel h3 { font-size: var(--t-lg); margin-block-end: var(--s-2); }
.panel p { color: var(--ink-700); }
.panel p + p { margin-block-start: var(--s-3); }

.panel-green { background: var(--green-50); border-color: var(--green-100); border-inline-start-color: var(--green-600); }
.panel-green .panel-icon { color: var(--green-700); }

/* --------------------------------------------------------------------------
   10. Timeline / steps
   -------------------------------------------------------------------------- */

.timeline { display: grid; gap: var(--s-5); counter-reset: step; }
@media (min-width: 700px)  { .timeline.cols-4 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .timeline.cols-4 { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 700px)  { .timeline.cols-2 { grid-template-columns: repeat(2, 1fr); } }

.step { position: relative; padding-block-start: var(--s-5); }
.step::before {
  content: '';
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  block-size: 3px;
  background: var(--ink-100);
  border-radius: 3px;
}
.step.is-accent::before { background: var(--sand-400); }
.step-num {
  font-size: var(--t-sm);
  font-weight: 700;
  color: var(--green-700);
  letter-spacing: 0.05em;
  display: block;
  margin-block-end: var(--s-2);
}
.step h3 { font-size: var(--t-md); margin-block-end: var(--s-2); }
.step p { color: var(--ink-500); font-size: var(--t-sm); }

/* Vertical journey (long list of steps) */
.journey { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.journey li {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s-5);
  padding-block-end: var(--s-7);
}
.journey li:last-child { padding-block-end: 0; }
.journey li::before {
  /* connector line, positioned on the reading-start side */
  content: '';
  position: absolute;
  inset-block: 3rem 0;
  inset-inline-start: 1.4375rem;
  inline-size: 2px;
  background: var(--ink-100);
}
.journey li:last-child::before { display: none; }
.journey .j-num {
  position: relative;
  z-index: 1;
  inline-size: 3rem; block-size: 3rem;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--white);
  border: 2px solid var(--green-100);
  color: var(--green-700);
  font-weight: 700;
  font-size: var(--t-sm);
}
.journey h3 { font-size: var(--t-md); margin-block-end: var(--s-2); padding-block-start: 0.6rem; }
.journey p { color: var(--ink-500); }

/* Horizontal flow with arrows */
.flow { display: grid; gap: var(--s-4); }
@media (min-width: 900px) { .flow { grid-template-columns: repeat(4, 1fr); gap: var(--s-5); } }
.flow-item {
  position: relative;
  background: var(--white);
  border: 1px solid var(--ink-100);
  border-radius: var(--r-lg);
  padding: var(--s-5);
}
.flow-item .flow-idx {
  inline-size: 2rem; block-size: 2rem;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--green-700); color: var(--white);
  font-size: var(--t-xs); font-weight: 700;
  margin-block-end: var(--s-3);
}
.flow-item h3 { font-size: var(--t-base); margin-block-end: var(--s-2); }
.flow-item p { font-size: var(--t-sm); color: var(--ink-500); }
.flow-item:not(:last-child)::after {
  content: '';
  position: absolute;
  inset-block-start: 50%;
  inset-inline-end: calc(var(--s-5) * -1 + 6px);
  inline-size: 10px; block-size: 10px;
  border-block-start: 2px solid var(--ink-300);
  border-inline-end: 2px solid var(--ink-300);
  transform: translateY(-50%) rotate(45deg);
}
html[dir='rtl'] .flow-item:not(:last-child)::after { transform: translateY(-50%) rotate(225deg); }
@media (max-width: 899px) {
  .flow-item:not(:last-child)::after {
    inset-block-start: auto;
    inset-block-end: calc(var(--s-4) * -1 + 1px);
    inset-inline: 50% auto;
    transform: translateX(-50%) rotate(135deg);
  }
  html[dir='rtl'] .flow-item:not(:last-child)::after { transform: translateX(50%) rotate(135deg); }
}

/* --------------------------------------------------------------------------
   11. Two-party (association / partner) comparison
   -------------------------------------------------------------------------- */

.roles { display: grid; gap: var(--s-5); }
/* One equal column per party, so the cooperative and both administration
   partners sit in a single row rather than leaving the third alone. Three
   columns at 800px were 225px wide and twice as tall, so they stack until 1024. */
@media (min-width: 1024px) { .roles { grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: var(--s-6); } }

.role {
  padding: var(--s-6);
  border-radius: var(--r-lg);
  background: var(--white);
  border: 1px solid var(--ink-100);
}
.role.is-primary { background: var(--green-700); color: var(--white); border-color: var(--green-700); }
.role.is-primary h3, .role.is-primary .role-party { color: var(--white); }
.role.is-primary .checklist svg { color: var(--sand-400); }
.role.is-primary li { color: rgba(255,255,255,0.92); }

.role-party {
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-500);
  display: block;
  margin-block-end: var(--s-2);
}
html[lang='ar'] .role-party { letter-spacing: 0; text-transform: none; font-size: var(--t-sm); }
/* sand-400 on green-700 is 4.11:1 — under AA for text this size. sand-200 is 5.37:1
   and keeps the warm accent. sand-400 stays on the checklist ticks below, where the
   3:1 non-text threshold applies. */
.role.is-primary .role-party { color: var(--sand-200); }
.role h3 { font-size: var(--t-lg); margin-block-end: var(--s-5); }

/* --------------------------------------------------------------------------
   12. Accordion (FAQ)
   -------------------------------------------------------------------------- */

.accordion { display: grid; gap: var(--s-3); }
.acc-item {
  background: var(--white);
  border: 1px solid var(--ink-100);
  border-radius: var(--r-lg);
  overflow: hidden;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.acc-item:hover { border-color: var(--ink-200); }
.acc-item.is-open { border-color: var(--green-100); box-shadow: var(--sh-sm); }

.acc-trigger {
  inline-size: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  padding: var(--s-5);
  background: transparent;
  border: 0;
  cursor: pointer;
  text-align: start;
  font-size: var(--t-md);
  font-weight: 600;
  color: var(--ink-900);
}
.acc-trigger:hover { color: var(--green-800); }
.acc-icon {
  flex: none;
  inline-size: 28px; block-size: 28px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--green-50);
  color: var(--green-700);
  transition: transform var(--dur) var(--ease), background var(--dur) var(--ease);
}
.acc-item.is-open .acc-icon { transform: rotate(180deg); background: var(--green-100); }

.acc-panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur) var(--ease);
}
.acc-item.is-open .acc-panel { grid-template-rows: 1fr; }
.acc-panel > div { overflow: hidden; }
.acc-panel p {
  padding-inline: var(--s-5);
  padding-block-end: var(--s-5);
  color: var(--ink-500);
}
.acc-panel a { font-weight: 600; }

/* --------------------------------------------------------------------------
   13. CTA bands
   -------------------------------------------------------------------------- */

.cta-band {
  position: relative;
  overflow: hidden;
  background: var(--green-700);
  color: var(--white);
  border-radius: var(--r-xl);
  padding: clamp(2.5rem, 5vw, 4rem);
  text-align: center;
}
.cta-band::before {
  content: '';
  position: absolute;
  inset-block-start: -50%;
  inset-inline-end: -10%;
  inline-size: 28rem; block-size: 28rem;
  background: radial-gradient(circle, rgba(223, 198, 150, 0.18) 0%, transparent 65%);
  border-radius: 50%;
}
.cta-band > * { position: relative; z-index: 1; }
.cta-band h2 { color: var(--white); font-size: var(--t-2xl); }
.cta-band p { margin-block-start: var(--s-4); color: rgba(255,255,255,0.86); max-inline-size: 40rem; margin-inline: auto; }
.cta-band .btn-row { margin-block-start: var(--s-7); justify-content: center; }

/* --------------------------------------------------------------------------
   14. Download cards
   -------------------------------------------------------------------------- */

.download-card {
  display: flex;
  gap: var(--s-4);
  padding: var(--s-5);
  background: var(--white);
  border: 1px solid var(--ink-100);
  border-radius: var(--r-lg);
  align-items: flex-start;
}
.download-card .dl-icon {
  flex: none;
  inline-size: 48px; block-size: 48px;
  display: grid; place-items: center;
  border-radius: var(--r-md);
  background: var(--sand-100);
  color: var(--sand-800);
}
.download-card h3 { font-size: var(--t-md); margin-block-end: var(--s-1); }
.download-card p { font-size: var(--t-sm); color: var(--ink-500); margin-block-end: var(--s-4); }
.download-card.is-unavailable { background: var(--paper); }
.download-card.is-unavailable .dl-icon { background: var(--ink-100); color: var(--ink-500); }
.dl-status {
  display: inline-flex; align-items: center; gap: var(--s-2);
  font-size: var(--t-sm); font-weight: 600; color: var(--ink-500);
}

/* --------------------------------------------------------------------------
   15. Forms
   -------------------------------------------------------------------------- */

.form-grid { display: grid; gap: var(--s-5); }
@media (min-width: 700px) { .form-grid .span-2 { grid-column: span 2; } .form-grid { grid-template-columns: 1fr 1fr; } }

.field { display: grid; gap: var(--s-2); }
.field label { font-weight: 600; font-size: var(--t-sm); color: var(--ink-800); }
.field .opt { font-weight: 400; color: var(--ink-500); }

.field input, .field select, .field textarea {
  inline-size: 100%;
  padding: 0.75rem 0.9375rem;
  border: 1.5px solid var(--ink-200);
  border-radius: var(--r-md);
  background: var(--white);
  color: var(--ink-900);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.field textarea { min-block-size: 8rem; resize: vertical; }
.field input::placeholder, .field textarea::placeholder { color: var(--ink-300); }
.field input:hover, .field select:hover, .field textarea:hover { border-color: var(--ink-300); }
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible {
  border-color: var(--green-600);
  box-shadow: 0 0 0 3px var(--green-100);
}
.field select {
  appearance: none;
  /* Chevron drawn as a background image; flips side with the reading direction. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%235f6862' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  padding-inline-end: 2.5rem;
}
html[dir='rtl'] .field select { background-position: left 1rem center; padding-inline-end: 0.9375rem; padding-inline-start: 2.5rem; }

.field .err { font-size: var(--t-sm); color: var(--danger); font-weight: 500; }
.field.has-error input, .field.has-error select, .field.has-error textarea { border-color: var(--danger); }
.field.has-error input:focus-visible,
.field.has-error select:focus-visible,
.field.has-error textarea:focus-visible { box-shadow: 0 0 0 3px #f7dcdc; }

.form-note {
  display: flex; gap: var(--s-3); align-items: flex-start;
  padding: var(--s-4);
  background: var(--sand-100);
  border-radius: var(--r-md);
  font-size: var(--t-sm);
  color: var(--ink-700);
}
.form-note svg { flex: none; margin-block-start: 2px; color: var(--sand-800); }

.form-status { border-radius: var(--r-md); padding: var(--s-5); display: flex; gap: var(--s-3); }
.form-status h3 { font-size: var(--t-md); margin-block-end: var(--s-1); }
.form-status p { font-size: var(--t-sm); }
.form-status.is-success { background: var(--green-50); border: 1px solid var(--green-100); }
.form-status.is-success svg { color: var(--green-700); }
.form-status.is-info { background: var(--sand-100); border: 1px solid var(--sand-200); }
.form-status.is-info svg { color: var(--sand-800); }
.form-status.is-error { background: var(--danger-bg); border: 1px solid #f0cccc; }
.form-status.is-error svg { color: var(--danger); }
.form-status svg { flex: none; margin-block-start: 2px; }
.form-status[hidden] { display: none; }

/* --------------------------------------------------------------------------
   16. Contact channel cards
   -------------------------------------------------------------------------- */

.channels { display: grid; gap: var(--s-4); }
@media (min-width: 620px) { .channels { grid-template-columns: repeat(2, 1fr); } }

.channel {
  display: flex; gap: var(--s-4); align-items: flex-start;
  padding: var(--s-5);
  background: var(--white);
  border: 1px solid var(--ink-100);
  border-radius: var(--r-lg);
}
.channel .ch-icon {
  flex: none; inline-size: 44px; block-size: 44px;
  display: grid; place-items: center;
  border-radius: var(--r-md);
  background: var(--green-50); color: var(--green-700);
}
.channel .ch-label { font-size: var(--t-xs); font-weight: 600; color: var(--ink-500); display: block; margin-block-end: 2px; }
.channel .ch-value { font-weight: 600; color: var(--ink-900); text-decoration: none; word-break: break-word; }
a.channel:hover { border-color: var(--green-400); }
a.channel:hover .ch-value { color: var(--green-800); }

/* Numbers stay LTR even inside RTL text */
.ltr-num { direction: ltr; unicode-bidi: isolate; display: inline-block; }

/* --------------------------------------------------------------------------
   17. Breadcrumb
   -------------------------------------------------------------------------- */

.breadcrumb ol { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); list-style: none; margin: 0; padding: 0; }
.breadcrumb li { display: flex; align-items: center; gap: var(--s-2); font-size: var(--t-sm); color: var(--ink-500); }
.breadcrumb a { color: var(--ink-500); text-decoration: none; }
.breadcrumb a:hover { color: var(--green-800); text-decoration: underline; }
.breadcrumb .sep { color: var(--ink-300); }
/* The separator glyph itself mirrors with direction. */
html[dir='rtl'] .breadcrumb .sep { scale: -1 1; }
.breadcrumb [aria-current='page'] { color: var(--ink-800); font-weight: 600; }

/* --------------------------------------------------------------------------
   18. Footer
   -------------------------------------------------------------------------- */

.site-footer { background: var(--green-900); color: rgba(255,255,255,0.75); padding-block: var(--s-10) var(--s-6); margin-block-start: 0; }
.footer-grid { display: grid; gap: var(--s-8); }
@media (min-width: 760px)  { .footer-grid { grid-template-columns: 1.4fr 1fr 1fr; } }
@media (min-width: 1060px) { .footer-grid { grid-template-columns: 1.6fr repeat(4, 1fr); } }

/* The mark is dark green; on the dark green footer it needs a light chip behind it
   rather than a recoloured copy of the logo. */
.footer-brand img, .footer-brand svg {
  block-size: 66px;
  inline-size: auto;
  padding: var(--s-2);
  background: var(--white);
  border-radius: var(--r-md);
  margin-block-end: var(--s-4);
}
.footer-brand .f-name { color: var(--white); font-weight: 700; font-size: var(--t-md); }
.footer-brand .f-tag { color: var(--sand-400); font-size: var(--t-sm); margin-block-end: var(--s-4); }
.footer-brand p { font-size: var(--t-sm); max-inline-size: 26rem; }

.footer-col h3 { color: var(--white); font-size: var(--t-sm); font-weight: 700; margin-block-end: var(--s-4); letter-spacing: 0.04em; }
html[lang='ar'] .footer-col h3 { letter-spacing: 0; }
/* The links were 17px tall with a 12px gap. The padding moves 8px of that gap
   inside each link, so the list keeps its rhythm and a thumb gets 25px. */
.footer-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-1); }
.footer-col a { display: inline-block; padding-block: var(--s-1); color: rgba(255,255,255,0.75); text-decoration: none; font-size: var(--t-sm); }
.footer-col a:hover { color: var(--white); text-decoration: underline; }

.footer-contact { display: grid; gap: var(--s-3); font-size: var(--t-sm); }
.footer-contact a { color: rgba(255,255,255,0.75); text-decoration: none; }
.footer-contact a:hover { color: var(--white); }

.footer-bottom {
  margin-block-start: var(--s-8);
  padding-block-start: var(--s-5);
  border-block-start: 1px solid rgba(255,255,255,0.14);
  display: flex; flex-wrap: wrap; gap: var(--s-4);
  align-items: center; justify-content: space-between;
  font-size: var(--t-sm);
}
/* The studio credit. Quiet at rest: it is the third thing on this row, after
   the copyright line and the language switch, and it should read that way.
   The name is the only part at full white, so the eye lands on it and the
   phrase before it stays at the footer's own text weight.

   On hover the mark moves the way its own arrow points. One short step, and
   it is the same direction in Arabic: the artwork is not mirrored, so neither
   is the motion. */
.site-credit {
  display: inline-flex; align-items: center; gap: var(--s-2);
  /* A 20px mark on its own is too small to tap. The padding makes the target
     44px tall without moving the baseline of the row. */
  padding-block: var(--s-3);
  color: rgba(255,255,255,0.75);
  text-decoration: none;
  border-radius: var(--r-sm);
}
.site-credit img {
  inline-size: 20px; block-size: 20px; flex: none;
  transition: transform 220ms cubic-bezier(0.2, 0.7, 0.2, 1);
}
.site-credit strong { color: var(--white); font-weight: 700; }
.site-credit:hover { color: var(--white); }
.site-credit:hover strong { text-decoration: underline; text-underline-offset: 0.2em; }
.site-credit:hover img { transform: translate(2px, -2px); }
@media (prefers-reduced-motion: reduce) {
  .site-credit img { transition: none; }
  .site-credit:hover img { transform: none; }
}
/* Three items share this row on a wide screen. On a phone they stack, and the
   credit goes last: the organisation's own line and its language switch first. */
@media (max-width: 759px) {
  .footer-bottom { flex-direction: column; align-items: flex-start; gap: var(--s-2); }
  .footer-bottom .site-credit { order: 3; }
}

.footer-bottom .lang-switch { border-color: rgba(255,255,255,0.28); color: rgba(255,255,255,0.85); }
.footer-bottom .lang-switch:hover { background: rgba(255,255,255,0.1); border-color: var(--white); color: var(--white); }

.footer-disclaimer {
  margin-block-start: var(--s-6);
  padding: var(--s-5);
  background: rgba(255,255,255,0.05);
  border-radius: var(--r-md);
  font-size: var(--t-xs);
  line-height: 1.7;
  color: rgba(255,255,255,0.7);
}

/* --------------------------------------------------------------------------
   19. Floating actions
   -------------------------------------------------------------------------- */

.float-stack {
  position: fixed;
  inset-block-end: var(--s-5);
  inset-inline-end: var(--s-5);
  z-index: 90;
  display: grid;
  gap: var(--s-3);
  justify-items: center;
}
.fab {
  inline-size: 52px; block-size: 52px;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 0;
  cursor: pointer;
  box-shadow: var(--sh-md);
  transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease), visibility var(--dur) var(--ease);
}
.fab:hover { transform: translateY(-2px); }
.fab-whatsapp { background: #25d366; color: #fff; text-decoration: none; }
.fab-top { background: var(--white); color: var(--green-800); border: 1px solid var(--ink-200); }
.fab-top { opacity: 0; visibility: hidden; }
.fab-top.is-visible { opacity: 1; visibility: visible; }

/* --------------------------------------------------------------------------
   20. 404
   -------------------------------------------------------------------------- */

.notfound { display: grid; place-items: center; text-align: center; padding-block: var(--s-11); }
/* Decorative numeral. Kept subtle but at 3.3:1 on white so it still meets AA
   for large text — a near-white tint failed contrast. */
.notfound .code { font-size: clamp(4rem, 14vw, 8rem); font-weight: 700; color: #6b9584; line-height: 1; }
.notfound h1 { margin-block-start: calc(var(--s-5) * -1); }
.notfound .suggestions { margin-block-start: var(--s-7); }
.notfound .suggestions ul { list-style: none; padding: 0; display: flex; flex-wrap: wrap; gap: var(--s-3); justify-content: center; }

/* --------------------------------------------------------------------------
   21. Motion — subtle, fast, and fully opt-out
   -------------------------------------------------------------------------- */

.reveal { opacity: 0; transform: translateY(14px); }
.js .reveal { transition: opacity 500ms var(--ease), transform 500ms var(--ease); }
.reveal.is-visible { opacity: 1; transform: none; }

/* No JS: content must never stay invisible. */
html:not(.js) .reveal { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .reveal { opacity: 1 !important; transform: none !important; }
  .btn:hover, .card:hover, .tile:hover, .fab:hover { transform: none !important; }
}

/* --------------------------------------------------------------------------
   22. Print
   -------------------------------------------------------------------------- */

@media print {
  .site-header, .mobile-menu, .float-stack, .cta-band, .skip-link { display: none !important; }
  body { color: #000; }
  a[href^='http']::after { content: ' (' attr(href) ')'; font-size: 0.8em; }
}

/* --------------------------------------------------------------------------
   21. The experience layer
   --------------------------------------------------------------------------

   LIGHT. There is no dark mode here and no dark hero. The canvas draws the map
   of Jordan in the brand's own sand on a near-white ground, with the network
   over it in brand green, so the scene and the rest of the site are the same
   document rather than two moods stitched together.

   Everything here is additive and scoped to html[data-scene]. A page without
   that attribute is styled exactly as it was before, which keeps the legal
   pages, the contact page and the forms out of the blast radius.

   The canvas is one fixed layer behind the whole document. Content sheets are
   opaque and scroll over it; the hero and the interlude bands are transparent
   and let it through. That is the whole composition, and it is why the scene
   can carry the page without ever putting a paragraph of Arabic on top of
   something moving.
   -------------------------------------------------------------------------- */

.experience {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  /* The scene never receives input. Scrolling, selecting and tapping belong to
     the document above it; the pointer is only *observed*. */
  pointer-events: none;
  background: var(--scene-sky-bottom);
}

.experience-canvas {
  position: relative;
  z-index: 1;
  display: block;
  inline-size: 100%;
  block-size: 100%;
}

/* The scene as CSS. This is what a visitor sees when boot.js declines — on a
   low-memory phone, on Data Saver, with reduced motion, or with WebGL blocked —
   and what everyone sees for the moments before the canvas paints. Same
   palette, same composition, so the page never flashes and never looks like
   something failed. */
.experience::before {
  content: '';
  position: absolute;
  inset: 0;
}

.experience::before {
  background:
    radial-gradient(68% 52% at 50% 46%, var(--scene-pool), transparent 70%),
    linear-gradient(180deg, var(--scene-sky-top) 0%, var(--scene-sky-bottom) 100%);
}

/* The mark itself, held still.

   This is what a visitor sees when boot.js declines - reduced motion, Data
   Saver, 2g, a low-memory phone, WebGL blocked, JavaScript off, or three.js
   failing to arrive. It sits in the same box the live mark assembles in, at
   the same size, in the same two inks, so the declined page is the finished
   composition rather than a different and weaker one.

   IT IS NOT SHOWN TO ANYONE WHO IS GETTING THE REAL SCENE. It used to be,
   for the whole length of the three.js download, and then it crossfaded out
   over 700ms while the crowd underneath was already gathering. Measured:
   sharp at 232ms, still sharp at 400ms, dissolving until 1100ms - and on
   mobile data that middle number is seconds, not milliseconds. Two things
   were wrong with it. The canvas opens SCATTERED, so the handoff never read
   as the mark breaking apart into its people; it read as one picture
   dissolving and an unrelated animation starting from zero. And it gave away
   the payoff before the thirty-three hundred milliseconds that earn it.

   So it is painted only once boot.js has actually DECLINED, which is the one
   place that decision is made. A visitor with JavaScript off never reaches
   that code at all, so the <noscript> block in the head covers them - the
   only other way to be sure of a page with no scene on it.

   It lives INSIDE the hero rather than on the fixed canvas layer on purpose:
   a full-strength logo on a fixed backdrop would still be behind the
   interlude headings a thousand pixels further down, where the live scene has
   deliberately receded to a watermark. Here it scrolls away with the hero.

   The old fallback drew a tiled line lattice. No line patterns - see the note
   at the top of this file and in CLAUDE.md. */
html[data-scene-still] .hero-stage {
  background: url('../brand/logo.png') center / contain no-repeat;
}

/* No fade. The still mark is either the composition this visitor is getting,
   in which case it stays, or it is gone before they have seen it - and a
   700ms dissolve of something that was up for one frame is a ghost, not a
   transition. The stage is never bare: the scene's own warm sky is painted
   behind it by .experience::before while three.js is still arriving. */

/* Once the real scene is drawing, the painted lattice would double up behind
   an opaque canvas for no benefit. */
.experience[data-experience='live']::before {
  opacity: 0;
  transition: opacity 1200ms var(--ease);
}

/* --------------------------------------------------------------------------
   Page scaffolding for a scened page
   -------------------------------------------------------------------------- */

html[data-scene] body {
  background: var(--scene-sky-bottom);
}

/* Content sheets ride above the scene and are fully opaque, because this is
   where the reading happens. */
html[data-scene] main > .section,
html[data-scene] main > .section-tight {
  position: relative;
  z-index: 1;
  background: var(--white);
}

html[data-scene] main > .section.bg-paper {
  background: var(--paper);
}

/* The first sheet after the hero lifts over the scene with a soft edge, so the
   transition from scene to document reads as one surface sliding over another
   rather than a hard cut. */
html[data-scene] main > .sheet-lead {
  border-start-start-radius: var(--r-xl);
  border-start-end-radius: var(--r-xl);
  box-shadow: 0 -20px 50px -24px rgba(28, 58, 47, 0.28);
}

html[data-scene] main > .sheet-tail {
  border-end-start-radius: var(--r-xl);
  border-end-end-radius: var(--r-xl);
}

html[data-scene] .site-footer {
  position: relative;
  z-index: 1;
}

/* --------------------------------------------------------------------------
   Hero over the scene
   -------------------------------------------------------------------------- */

.hero-scene {
  position: relative;
  z-index: 1;
  background: transparent;
  /* svh, not vh: on mobile Safari and Chrome Android vh includes the address
     bar, so a 100vh hero is cut off on arrival — the one moment it matters.

     Minus the header, which is sticky and therefore takes flow space above
     this section (04-header.css, 84px). A flat 100svh made the hero 84px
     taller than the first screen, and everything pinned to its bottom edge -
     the scroll cue - sat just under the fold where nobody would ever see it. */
  min-block-size: calc(100svh - 84px);
  display: grid;
  align-content: center;
  padding-block: clamp(5rem, 11vh, 7rem) clamp(4rem, 9vh, 5.5rem);
  text-align: center;
  overflow: hidden;
}

/* Pinned, not stacked. The cue is the one element whose entire job is to say
   the page continues, and it was the first thing pushed below the fold every
   time the copy above it grew by a line. */
.hero-scene .scroll-cue {
  position: absolute;
  inset-block-end: clamp(1rem, 3.5vh, 2.25rem);
  inset-inline: 0;
  margin-block-start: 0;
  z-index: 2;
}

/* A wash of paper under the WORDS, and only under the words.

   It used to cover the whole hero. That was right when the scene was a field
   spread across the full width; it is wrong now that the mark stands in its
   own column, because the wash sat on top of the canvas and put a 30% white
   veil over the logo. Measured: the brand's #406051 green arrived on screen
   as #859990. Nothing in the shader was wrong - the page was painting over
   it. */
.hero-copy {
  position: relative;
}

.hero-copy::before {
  content: '';
  position: absolute;
  inset: -8% -6%;
  background: radial-gradient(88% 76% at 46% 50%, rgba(255, 255, 255, 0.62), rgba(255, 255, 255, 0.2) 54%, transparent 100%);
  pointer-events: none;
  z-index: -1;
}

/* The base .hero carries a 46rem sand glow anchored to the reading direction
   (05-hero.css). The canvas is the hero's visual interest now, and the two
   fight. */
.hero-scene::after {
  content: none;
}

.hero-scene > * {
  position: relative;
  z-index: 1;
}

/* --------------------------------------------------------------------------
   The hero, as a stage
   --------------------------------------------------------------------------

   The words get one column and the scene gets the other. That is the whole
   reason this layout exists: the payoff of the scene is the cooperative's own
   mark assembling itself out of thirty thousand people, and a mark that has a
   paragraph lying across it is not a payoff.

   .hero-stage is empty on purpose. It reserves the column, and the scene
   MEASURES it - see frameFromStage in Camera.js - so the logo lands wherever
   the layout put the box: the second column on a laptop, a band under the
   buttons on a phone, and the other side of the page in Arabic, with no
   direction-aware maths anywhere in the 3D code.
   -------------------------------------------------------------------------- */

.hero-scene-grid {
  display: grid;
  gap: clamp(1.25rem, 4vw, 3rem);
  align-items: center;
}

.hero-stage {
  /* Tall enough that the mark is a subject rather than a stamp, and capped so
     it cannot push the buttons off a short laptop screen. */
  min-block-size: clamp(15rem, 36svh, 22rem);
}

@media (min-width: 1000px) {
  .hero-scene {
    text-align: start;
  }

  .hero-scene-grid {
    grid-template-columns: minmax(0, 1.04fr) minmax(0, 0.96fr);
  }

  .hero-scene h1,
  .hero-scene .lead {
    margin-inline: 0;
  }

  .hero-scene .btn-row {
    justify-content: flex-start;
  }

  .hero-stage {
    /* Stretched to the row rather than sized to a guess: the copy column sets
       the height of the hero, and the mark should use all of it. */
    align-self: stretch;
    min-block-size: min(58svh, 30rem);
  }
}

/* --------------------------------------------------------------------------
   Entrance
   --------------------------------------------------------------------------

   The scene opens with movement, and type that is simply already there reads
   as a screenshot sitting in front of it. Staggered, short, and small: 16px
   of travel, not a slide across the screen.

   `both` carries the from-state through the delay, so nothing flashes at full
   opacity before its turn. If a browser does not run the animation at all the
   whole declaration is ignored and the text is simply there, which is the
   right failure.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  html[data-scene] .hero-copy > *,
  html[data-scene] .hero-scene .scroll-cue {
    animation: hero-rise 760ms var(--ease) both;
  }

  html[data-scene] .hero-copy > *:nth-child(1) { animation-delay: 60ms; }
  html[data-scene] .hero-copy > *:nth-child(2) { animation-delay: 150ms; }
  html[data-scene] .hero-copy > *:nth-child(3) { animation-delay: 260ms; }
  html[data-scene] .hero-copy > *:nth-child(4) { animation-delay: 370ms; }
  html[data-scene] .hero-copy > *:nth-child(5) { animation-delay: 470ms; }
  html[data-scene] .hero-copy > *:nth-child(6) { animation-delay: 560ms; }
  html[data-scene] .hero-scene .scroll-cue     { animation-delay: 700ms; }
}

@keyframes hero-rise {
  from { opacity: 0; transform: translate3d(0, 16px, 0); }
  to   { opacity: 1; transform: none; }
}

.hero-scene .eyebrow {
  color: var(--sand-800);
}

.hero-scene h1 {
  color: var(--green-900);
  font-size: var(--t-4xl);
  line-height: 1.12;
  max-inline-size: 18ch;
  margin-inline: auto;
  text-wrap: balance;
}

.hero-scene .lead {
  color: var(--ink-700);
  max-inline-size: 54ch;
  margin-inline: auto;
  margin-block-start: var(--s-5);
}

.hero-scene .btn-row {
  justify-content: center;
  margin-block-start: var(--s-7);
}

/* The membership card, as a piece of glass over the scene. */
.hero-card {
  display: inline-flex;
  align-items: center;
  gap: var(--s-4);
  margin-block-start: var(--s-6);
  padding: var(--s-4) var(--s-5);
  border-radius: var(--r-lg);
  border: 1px solid var(--ink-200);
  background: rgba(255, 255, 255, 0.78);
  /* Progressive: without backdrop-filter support the panel is still legible,
     it is simply flat. Nothing is conditional on it. */
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  box-shadow: var(--sh-md);
  text-align: start;
  max-inline-size: min(100%, 30rem);
}

.hero-card .chip-icon {
  display: grid;
  place-items: center;
  inline-size: 44px;
  block-size: 44px;
  flex: none;
  border-radius: var(--r-md);
  background: var(--green-100);
  color: var(--green-700);
}

.hero-card strong {
  display: block;
  color: var(--ink-900);
  font-size: var(--t-base);
}

.hero-card > span > span {
  display: block;
  color: var(--ink-500);
  font-size: var(--t-sm);
  line-height: 1.5;
}

/* The scroll cue. A real affordance, not decoration: the hero fills the
   screen, so something has to say the page continues. */
.scroll-cue {
  display: grid;
  justify-items: center;
  gap: var(--s-2);
  margin-block-start: clamp(2rem, 6vh, 3.5rem);
  color: var(--ink-500);
  font-size: var(--t-xs);
  letter-spacing: 0.06em;
}

.scroll-cue i {
  display: block;
  inline-size: 1px;
  block-size: 38px;
  background: linear-gradient(180deg, var(--green-600), transparent);
  animation: cue 2.4s var(--ease) infinite;
}

@keyframes cue {
  0%   { transform: scaleY(0.25); transform-origin: top; opacity: 0; }
  35%  { transform: scaleY(1);    transform-origin: top; opacity: 1; }
  70%  { transform: scaleY(1);    transform-origin: bottom; opacity: 1; }
  100% { transform: scaleY(0.05); transform-origin: bottom; opacity: 0; }
}

/* A quiet hint that the scene answers the pointer. It is worth saying once:
   an interaction nobody discovers may as well not exist. */
.scene-hint {
  margin-block-start: var(--s-4);
  /* Measured at 2.1:1 in ink-300, which is a fail at any size. It is quiet
     type, not invisible type. */
  color: var(--ink-500);
  font-size: var(--t-xs);
}

html:not([data-scene-live]) .scene-hint {
  display: none;
}

/* --------------------------------------------------------------------------
   Interlude bands — the scene, uncovered, carrying one section
   -------------------------------------------------------------------------- */

.scene-band {
  position: relative;
  z-index: 1;
  background: transparent;
  /* A full shot, not a letterbox. The canvas is fixed and its composition is
     centred in the viewport, so a 200px band shows whatever happens to be at
     the top of the frame — which is empty sky. */
  min-block-size: 100svh;
  display: grid;
  align-content: center;
  padding-block: clamp(4rem, 12vh, 7rem);
  text-align: center;
}

.scene-band::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(76% 66% at 50% 50%, rgba(255, 255, 255, 0.44), rgba(255, 255, 255, 0.2) 58%, transparent 88%);
  pointer-events: none;
}

.scene-band > * {
  position: relative;
  z-index: 1;
}

.scene-band .eyebrow {
  color: var(--sand-800);
}

.scene-band h2 {
  color: var(--green-900);
  font-size: var(--t-3xl);
  max-inline-size: 20ch;
  margin-inline: auto;
  margin-block-start: var(--s-3);
  text-wrap: balance;
}

.scene-band p,
.scene-band .lead,
.scene-band .fund-note {
  color: var(--ink-700);
  max-inline-size: 56ch;
  margin-inline: auto;
  margin-block-start: var(--s-4);
  font-size: var(--t-md);
}

/* The interlude keeps the tiles it always had, re-dressed as glass so the same
   markup works over the scene. */
.scene-band .tile {
  background: rgba(255, 255, 255, 0.82);
  border-color: var(--ink-200);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  box-shadow: var(--sh-sm);
}

.scene-band .btn-row {
  justify-content: center;
  margin-block-start: var(--s-7);
}

/* The closing band carries the bottom of the document and needs room under the
   buttons before the footer starts. */
.scene-band-close {
  padding-block: clamp(5.5rem, 17vh, 10rem);
}

.scene-band-close h2 {
  font-size: var(--t-3xl);
}

/* --------------------------------------------------------------------------
   Header over the scene
   -------------------------------------------------------------------------- */

/* The ground is light in both states, so the header keeps its normal colours
   throughout — no inverted logo, no light-on-dark nav. It only gains a frosted
   backing once the reader has left the hero, so the hero reads edge to edge. */
html[data-scene] .site-header {
  background: transparent;
  border-block-end-color: transparent;
  box-shadow: none;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease);
}

html[data-scene] .site-header.is-stuck {
  background: rgba(255, 255, 255, 0.86);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  border-block-end-color: var(--ink-200);
  box-shadow: var(--sh-sm);
}

/* The mobile menu is a solid panel in both states — a translucent header is a
   nice effect, an unreadable menu is a bug. */
html[data-scene] .nav-panel {
  background: var(--white);
}

/* --------------------------------------------------------------------------
   Motion
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  /* boot.js has already refused the canvas by this point. What is left is the
     painted scene, and it holds perfectly still. */
  .scroll-cue i {
    animation: none;
    opacity: 0.7;
  }

  html[data-scene] .site-header {
    transition: none;
  }

  /* No entrance either. The rule above is already scoped to
     no-preference, so this is belt and braces for a browser that
     resolves both. */
  html[data-scene] .hero-copy > *,
  html[data-scene] .hero-scene .scroll-cue {
    animation: none;
  }
}

/* --------------------------------------------------------------------------
   Phone
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   The hero on a narrow screen
   --------------------------------------------------------------------------

   Two columns become one, and the MARK GOES FIRST. The copy alone is taller
   than a phone screen - headline, four-line lead, two stacked full-width
   buttons, the benefit card - so a stage placed after it sits a thousand
   pixels below the fold and the whole payoff is invisible on the device most
   of this audience is holding. Measured at 390x844: the stage box was at
   y = 987.

   And the copy sits on paper. It scrolls up over the mark, and a paragraph
   over a solid brand green is not a contrast problem to be feathered away -
   it needs a surface. This is the same sheet-over-scene idea the rest of the
   page already uses, applied to the hero.
   -------------------------------------------------------------------------- */

@media (max-width: 999px) {
  /* The hero is taller than the screen here, so centring its content just
     buys empty paper above the mark. */
  .hero-scene {
    align-content: start;
  }

  .hero-stage {
    order: -1;
    min-block-size: clamp(14rem, 36svh, 19rem);
  }

  .hero-copy {
    padding: var(--s-6) var(--s-5);
    border-radius: var(--r-xl);
    background: rgba(255, 255, 255, 0.9);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
    box-shadow: 0 18px 44px -30px rgba(28, 58, 47, 0.45);
  }

  /* The panel IS the wash now, and the lead does not need a second one
     inside it. */
  .hero-copy::before {
    content: none;
  }

  .hero-scene .lead {
    background: none;
    padding-inline: 0;
  }

  /* A hero taller than the screen says "there is more" by itself, and a cue
     pinned to the bottom of it would be a thousand pixels down. */
  .hero-scene .scroll-cue {
    position: static;
    margin-block-start: var(--s-6);
  }
}

@media (max-width: 760px) {
  .hero-scene {
    padding-block: clamp(4rem, 11vh, 5.5rem) var(--s-7);
  }

  .hero-scene .btn-row {
    margin-block-start: var(--s-6);
  }

  .hero-card {
    margin-block-start: var(--s-6);
    padding: var(--s-4);
  }

  .scroll-cue {
    margin-block-start: var(--s-5);
  }

  /* The copy is already taller than a phone screen. The stage takes what is
     left rather than what it would like. */
  .hero-stage {
    min-block-size: clamp(11rem, 26svh, 15rem);
  }

  .scroll-cue i {
    block-size: 26px;
  }

  /* A full-viewport interlude on a phone leaves a lot of empty scene above and
     below a short heading. Enough height to be a shot, not so much that it is
     a scroll tax. */
  .scene-band {
    min-block-size: 84svh;
  }
}

/* --------------------------------------------------------------------------
   Legibility over a live scene
   --------------------------------------------------------------------------

   Measured, not assumed. Sampling the real rendered pixels behind each text
   element - worst pixel in the box, not the average - is the only way to check
   type that sits over a moving canvas.

   Headings are large and heavy in near-black green, and clear the 3:1 bar
   against the pale sand on their own. Body copy at 17px does not, so it gets
   its own scrim: no visible edge, sized to the text, and enough that no frame
   of the animation can take it below AA.
   -------------------------------------------------------------------------- */

.hero-scene .lead,
.scene-band p,
.scene-band .lead,
.scene-band .fund-note {
  /* Feathered hard, and weak in the middle. At 0.94 it read as a white card
     floating over the scene, which looks like a bug rather than a decision.
     With the country framed low it only has to cover the occasional thread. */
  /* Barely there. Once the crowd gathers it sits in the lower half of the
     frame and the type is on clear paper, so a heavy scrim just looked like a
     floating white card. This only softens the few marks that drift up. */
  background: radial-gradient(84% 132% at 50% 50%, rgba(255, 255, 255, 0.76) 24%, rgba(255, 255, 255, 0.46) 66%, rgba(255, 255, 255, 0.14) 100%);
  padding-block: var(--s-3);
  padding-inline: var(--s-4);
  border-radius: var(--r-lg);
}

@media (max-width: 760px) {
  /* On a phone the country fills more of the frame and crosses the text more
     often, so the scrim is flat rather than feathered. */
  .hero-scene .lead,
  .scene-band p,
  .scene-band .lead,
  .scene-band .fund-note {
    background: rgba(255, 255, 255, 0.66);
  }
}

/* The eyebrow is small, letterspaced and warm — the lowest-contrast text on
   the page by design. Measured at 4.25:1 and 4.38:1 against the darkest pixel
   behind it, which is a green thread crossing the label, so it gets the same
   treatment as the body copy. Sized to the words rather than the column, it
   reads as a chip, which is a reasonable thing for an eyebrow to be. */
.hero-scene .eyebrow,
.scene-band .eyebrow {
  display: inline-block;
  padding-block: 0.3rem;
  padding-inline: 0.85rem;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.95);
}
