/* Just Mercy · design tokens + typography classes
   Same architecture as the NSA build: everything rides the fluid root
   (fluid-root.css) through rem; fluid heading clamps are the documented
   exception, generated with the fluid-type skill (fluid.mjs clamp 390→1440).
   Bricks global classes are NAME-ONLY — the class objects in Bricks carry no
   settings; these rules are the single source of truth.

   STATUS: Colour + static type tokens are now the REAL Figma variables, pulled
   from JM Website HejjbmXxVo85wdUNENknsb on 2026-08-29 via the Figma MCP. The
   fluid heading clamps are still placeholders — see the note above them. */

:root {
  /* ---- Brand: Purple (Figma Brand/Purple) ---- */
  --purple-50:  #ede8f9;
  --purple-100: #d5cce9;
  --purple-200: #ab99d2;
  --purple-300: #8166bc;
  --purple-400: #5733a5;
  --purple-500: #2d008f;   /* primary brand purple */
  --purple-600: #240072;
  --purple-700: #1b0056;

  /* ---- Brand: Gold (Figma Brand/Gold) ---- */
  --gold-400: #f9cc3b;
  --gold-500: #f7bf0a;     /* brand gold */
  --gold-600: #c69908;

  /* ---- Brand: Stone (Figma Brand/Stone) — the warm neutral ramp ---- */
  --stone-100: #fdfcfb;
  --stone-200: #fbfaf7;
  --stone-300: #f8f7f3;
  --stone-400: #f6f5ef;
  --stone-500: #f4f2eb;    /* light page background */
  --stone-600: #e4e1d8;
  --stone-700: #c3c2bc;

  /* ---- Brand: Cream ----
     Cream/500 is its OWN published Figma variable, not a nickname for Stone/500.
     They are two different colours (#faf2e1 is warmer and more saturated) and
     the boards use both: cream for display type on the dark purple sections,
     stone for light page backgrounds.

     An earlier comment here claimed cream WAS Stone/500 and that #faf2e1 only
     lived inside the logo SVGs. That was wrong, and it cost the About page a
     hero headline in the wrong colour. Checked against get_variable_defs on
     2026-08-30, which lists Cream/500 and Stone/500 as separate variables. */
  --cream-500: #faf2e1;

  /* ---- Semantic ----
     No --white token, deliberately. White is not a brand decision, and as a
     token it makes the page-quality gate (build/evals, criterion D2) flag every
     legitimate literal #ffffff. Figma agrees: no white in the Brand ramp, only
     this semantic. */
  --text-inverse: #ffffff;
  --bg-page: var(--stone-500);
  --surface: var(--stone-100);
  --accent: var(--purple-500);
  --line: var(--stone-600);
  --feedback-error: #947306;  /* Figma feedback/error — a dark gold, not a red.
                                 QUERY FOR PHIL: deliberate, or a placeholder? */

  /* Ink / body colours are not in the variable set the Component Library page
     exposes — the library sets text colour per text style. Pulled at the next
     inventory pass; these are working values until then. */
  --ink: #1b0056;          /* headings — Purple/700 */
  --body-color: #1b0056;
  --muted: #5733a5;        /* Purple/400 */
  --scrim: rgba(27, 0, 86, 0.55);
  --ring: rgba(45, 0, 143, 0.35);  /* focus ring */

  /* Spacing (rem, rides the fluid root) */
  --space-2xs: 0.5rem;   /* 8 */
  --space-xs: 0.75rem;   /* 12 */
  --space-s: 1rem;       /* 16 */
  --space-m: 1.5rem;     /* 24 */
  --space-l: 2rem;       /* 32 */
  --space-xl: 2.5rem;    /* 40 */
  --space-2xl: 3rem;     /* 48 */
  --space-3xl: 4.5rem;   /* 72 */
  --space-4xl: 6rem;     /* 96 */
  /* ---- Container ----
     Figma: EVERY page board is 1440 wide, content starts at x=80 and is 1280 wide,
     and the header and footer sit on that same 80px inset. So there is one measure
     for the whole site: an outer max of 1440 with an 80 gutter each side.

     In rem, so it rides the fluid root like every other token. At the 1440 anchor
     the root is exactly 16px, so this renders 1440 / 80 / 1280 exactly as drawn.
     Above 1440 the root grows to 18px at 1920 and the container grows with it,
     which keeps the line length in characters roughly constant instead of
     stranding a fixed 1280 column under larger type. The root is flat above 1920,
     so the container stops growing there too. */
  /* Phil, 2026-08-30: 90rem read too narrow on wide screens, so the cap is
     100rem. At or below a 1440 viewport nothing changes (the viewport is the
     limit there, so the boards still render exactly as drawn); above it the
     content frame now runs to 1800 at 1920 instead of 1620. */
  --container-max: 100rem;                 /* 1600 at the 16px anchor */
  --gutter: 5rem;                          /* 80 — the board's side padding */

  /* ---- Motion ----
     One motion language for the whole site (Phil's requirement: tokenised,
     consistent, reused contextually). The mobile spec board (618:6562) pins
     disclosure motion at 250ms ease; fast is for hovers and small fades.
     Under prefers-reduced-motion, transforms are dropped and fades kept —
     components implement that split themselves. */
  --motion-fast: 150ms;
  --motion-base: 250ms;
  --motion-ease: ease;
  --motion-ease-out: ease-out;
  --motion-ease-enter: cubic-bezier(0.2, 0.7, 0.3, 1);  /* entrances: dialogs, tooltips */
  --motion-slow: 450ms;                                  /* hero entrances, big reveals */

  /* The distance from the bottom of the header to the top of a page's first
     section. ONE value for the whole site.

     It used to be whatever each page's build script happened to set, and the
     boards disagree with each other: About drew 84, Partnerships 80, The Facts
     and Donate 72, Contact 40. So the page-top eyebrow jumped up and down as you
     moved between pages, which a reader feels immediately even without being
     able to name it.

     80 matches --gutter, so the content area is inset equally on all four edges,
     and it is a value the boards do draw. Change it here and every page follows. */
  --page-top: 5rem;                        /* 80 */

  /* Height the header occupies over the page. The header is NOT a painted band:
     on every board it is the first child of the hero frame, so the hero's own
     colour runs behind it and there is no seam. Ours was a Purple/500 strip
     sitting on top of a Purple/700 homepage hero, with the join clearly visible.

     It now overlays the page, so the first section has to reserve this much room
     plus --page-top. Desktop = 80 top inset + 68 logo. Mobile = the 64 bar. */
  --header-h: 9.25rem;                     /* 148 */

  /* The homepage hero's backdrop (7:276). NOT a brand ramp — it is the
     photographic gradient the board composites the hero image against, read
     straight off the board's own gradient definition: an ellipse anchored at the
     bottom-right corner running cream at the corner through greys and blues to
     near-black at the far edge. The photo is laid over it in `luminosity`, so
     this gradient is what supplies all of the colour.

     Blending against flat Purple/700 instead — which is what this did first —
     turned the whole hero purple and lost the silver-to-navy the board draws. */
  --jm-hero-gradient: radial-gradient(
    145.8rem 95.1rem ellipse at 101% 101%,
    rgb(246, 242, 236) 6.73%,
    rgb(191, 193, 192) 21.15%,
    rgb(135, 143, 147) 35.58%,
    rgb(92, 96, 141)   51.20%,
    rgb(70, 72, 137)   59.02%,
    rgb(48, 48, 134)   66.83%,
    rgb(36, 36, 101)   75.12%,
    rgb(25, 25, 68)    83.41%,
    rgb(13, 13, 34)    91.71%,
    rgb(7, 7, 18)      95.85%,
    rgb(1, 1, 1)       100%
  );

  /* Gap between a hero's heading group (eyebrow + heading) and the body copy
     under it. Also ONE value site-wide.

     The boards drift here the same way they drift on --page-top, and between
     layouts that are otherwise identical: About (81:159) draws 64 under a 54px
     display heading with a two-column body; The Facts (430:496) draws 22 under
     the same arrangement; Contact (588:3178) draws 12 under a shorter heading.
     Rendered, the five pages came out 64 / 72 / 30 / 30 / 12.

     Normalised to the About hero, which is the one Phil pointed at as the
     reference. */
  --hero-lede: 4rem;                       /* 64 */

  --section-pad: clamp(2.5rem, 6vw, 6rem); /* vertical section rhythm */

  /* Radii [confirm against Figma at inventory] */
  --radius-s: 0.625rem;
  --radius-m: 0.75rem;
  --radius-l: 1rem;
  --radius-xl: 1.25rem;
  --radius-pill: 999px;


  /* ---- Fluid heading clamps (fluid-type skill, 390 → 1440) ----
     Figma defines ONE type ramp with no mobile counterparts, and there are no
     mobile page boards — the mobile organisms reuse the same text styles. So
     the desktop values below are exactly Figma's; the small ends were proposed
     and approved by Phil on 2026-08-29. Above 1440 the clamp holds and the
     fluid root takes over, which is the intended handoff.

     The min/max are expressed against the ACTUAL root at each anchor, not a flat
     16px. Because these clamps are in rem AND the root is itself fluid, the two
     compound: the root is 15.2552px at 390 and 16px at 1440, so a naive
     `2.125rem` min (34/16) would have rendered 32.4px on mobile, not the 34px
     that was approved. Each min is therefore target ÷ root-at-390 and each max is
     target ÷ root-at-1440. Regenerating these with the fluid-type skill alone is
     NOT enough — the skill assumes a fixed base. Re-derive both ends if the root
     cascade anchors ever change. */

  /* 34px @390 → 54px @1440 · Display/L SemiBold, line-height 1.05 */
  --text-display-l: clamp(2.228744rem, 1.6607142857142856rem + 1.9047619047619049vw, 3.375rem);
  /* 26px @390 → 32px @1440 · Heading/XL SemiBold */
  --text-heading-xl: clamp(1.704334rem, 1.4857142857142858rem + 0.5714285714285714vw, 2rem);
  /* 24px @390 → 28px @1440 · Heading/L SemiBold */
  --text-heading-l: clamp(1.573231rem, 1.407142857142857rem + 0.38095238095238093vw, 1.75rem);
  /* 19px @390 → 21px @1440 · Heading/S Bold */
  --text-heading-s: clamp(1.245474rem, 1.1410714285714285rem + 0.19047619047619047vw, 1.3125rem);
  /* 28px @390 → 36px @1440 · Stat/Number ExtraBold, line-height 1.05 */
  --text-stat: clamp(1.835436rem, 1.5642857142857143rem + 0.7619047619047619vw, 2.25rem);

  /* Static type tokens — EXACT Figma text styles (Host Grotesk throughout).
     rem values ride the fluid root, so these scale with viewport. */
  --text-body-lead: 1.5rem;    /* 24 · Body/L SemiBold */
  --text-body-m: 1.125rem;     /* 18 · Body/M */
  --text-body: 1rem;           /* 16 · Body/S, line-height 1.4 */
  --text-body-s: 0.9375rem;    /* 15 · Body/XS */
  --text-label: 0.9375rem;     /* 15 · Label/M */
  --text-label-s: 0.8125rem;   /* 13 · Label/S */
  --text-caption: 0.875rem;    /* 14 · Caption */
  --text-caption-m: 0.9375rem; /* 15 · Caption/M, letter-spacing 2.5% */
  --text-micro: 0.75rem;       /* 12 · Micro/Medium */
  --text-overline: 0.6875rem;  /* 11 · Overline */
}

/* ---- Gutter steps ----
   Figma draws the gutter at two widths only: 80 on the 1440 board and 24 on the
   390 board. The middle step is our decision.

   Ordered widest to narrowest. Media queries resolve rem against the initial 16px,
   NOT the fluid root, so these are dependable 1152 and 768 pixel breakpoints. */

@media (max-width: 72rem) {   /* 1152 */
  :root { --gutter: 2.5rem; } /* 40 */
}

@media (max-width: 48rem) {   /* 768 */
  /* 24px at the 390 mobile board. The root is 15.2552px there, not 16, so a flat
     1.5rem would render 22.88 — the same rem-on-a-fluid-root compounding that the
     heading clamps have to account for. 24 ÷ 15.2552 = 1.5733rem. */
  :root {
    --gutter: 1.5733rem;
    --header-h: 4rem;                      /* 64 — the mobile bar */
  }
}

/* ---- Typography classes ----
   Applied as Bricks global classes of the same name (NAME-ONLY — the class
   objects in Bricks carry no settings, these rules are the single source of
   truth). Names, sizes, weights and line-heights are the Figma text styles. */

.heading-style-display,
.heading-style-h1,
.heading-style-h2,
.heading-style-h3 {
  font-family: var(--font-sans);
  /* Purple/500, not --ink (Purple/700). Checked on two boards rather than one:
     About's foundation heading (81:75) and The Facts' section headings both emit
     `text-[color:var(--purple/500,#2d008f)]`. Every section heading on the site
     was rendering a ramp step too dark. Sections on a dark ground still override
     this per element, as they must. */
  color: var(--purple-500);
  text-wrap: balance;
}
.heading-style-display { font-size: var(--text-display-l);  font-weight: 600; line-height: 1.05; }
.heading-style-h1      { font-size: var(--text-heading-xl); font-weight: 600; line-height: 1.2; }
.heading-style-h2      { font-size: var(--text-heading-l);  font-weight: 600; line-height: 1.2; }
.heading-style-h3      { font-size: var(--text-heading-s);  font-weight: 700; line-height: 1.2; }

.text-style-lead,
.text-style-body-m,
.text-style-body,
.text-style-small,
.text-style-caption,
.text-style-micro {
  font-family: var(--font-sans);
  color: var(--body-color);
}
.text-style-lead     { font-size: var(--text-body-lead); font-weight: 600; line-height: 1.3; }
.text-style-body-m   { font-size: var(--text-body-m);    font-weight: 500; line-height: 1.4; }
.text-style-body     { font-size: var(--text-body);      font-weight: 400; line-height: 1.4; }
.text-style-small    { font-size: var(--text-body-s);    font-weight: 400; line-height: 1.2; }
.text-style-caption  { font-size: var(--text-caption);   font-weight: 400; line-height: 1.2; color: var(--muted); }
.text-style-micro    { font-size: var(--text-micro);     font-weight: 500; line-height: 1.2; color: var(--muted); }

.text-style-label    { font: 500 var(--text-label)/1.2 var(--font-sans); }
.text-style-label-s  { font: 400 var(--text-label-s)/1.2 var(--font-sans); }

/* Caption/M's letterSpacing of 2.5 is a PERCENT, not pixels.
   2.5% of 15px = 0.375px = 0.025em.

   This was read as 2.5px (0.1667em) and every eyebrow on the site rendered
   6.7 times too wide. Confirmed against Figma's own generated CSS for the About
   eyebrow (62:86), which emits `tracking-[0.375px]` — 15 x 2.5%, not 2.5px.
   Figma's variable dump prints the bare number with no unit, which is what made
   it easy to get wrong; the per-node CSS is the reliable source. */
.text-style-caption-m {
  font: 500 var(--text-caption-m)/1.2 var(--font-sans);
  letter-spacing: 0.025em;
}

/* Overline 11px Medium. Figma's published Overline style records letterSpacing 0,
   so this now carries none.

   It previously carried 0.08em on the reasoning that an 11px all-caps label needs
   some tracking to read. That was my judgement, not the board's, and it sat here
   as an undocumented deviation while the neighbouring Caption/M rule was busy
   being 6.7x too wide for the opposite reason. Both now follow Figma. If Phil
   wants tracking here for legibility it is a deliberate design decision to make,
   not a default to leave in place. */
.text-style-overline {
  font: 500 var(--text-overline)/1.2 var(--font-sans);
  letter-spacing: 0;
  text-transform: uppercase;
  color: var(--accent);
}

.text-style-stat {
  font: 800 var(--text-stat)/1.05 var(--font-sans);
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

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