/* ===========================================================================
   tokens.css — the single source of truth for color, type, spacing and motion
   ===========================================================================

   RULE: components do NOT use raw values (hex, px). They use semantic tokens
   (--color-text-primary, --space-6, --radius-md).

   Layered structure:
     1. Base palette (--ink-*, --blue-*)     — raw colors, do NOT use in components
     2. Semantic tokens (--color-*)          — THESE are what components use
     3. Typography, spacing, radii, shadows, motion

   ONE THEME. The site is light and has no theme switch. The dark set that used
   to live here, and the toggle that went with it, were removed — two themes
   meant every colour decision had to be made twice, and the second one was
   always the one nobody looked at.

   That is why no component may define a colour of its own: with a single
   palette there is no excuse left for a hard-coded value.

   Rebranding to another color = swap the --blue-* ramp in section 1.
   =========================================================================== */

/* ---------------------------------------------------------------------------
   1. BASE PALETTE — raw colors
   ---------------------------------------------------------------------------
   Do not use these variables directly in components. They exist solely to feed
   the semantic tokens in section 2.
--------------------------------------------------------------------------- */
:root {
  /* Navy — cool, distinctly blue near-blacks. Backdrop and panels.
     Direction matches the reference ("technical institution", not consumer SaaS),
     but with our own choice of intermediate steps. */
  --ink-950: #06090f; /* deepest section, footer */
  --ink-900: #090f1c; /* LEVEL 0 — page background */
  --ink-850: #0b1322; /* recessed: data field, code block */
  --ink-800: #0d1526;
  --ink-750: #111b30; /* LEVEL 1 — section panel, card on the page */
  --ink-700: #16223a;
  --ink-650: #1a2740; /* LEVEL 2 — card sitting on a level-1 panel */
  --ink-600: #1c273f; /* subtle border */
  --ink-550: #2b3a5c; /* PANEL EDGE — the line that makes a panel an object */
  --ink-500: #2b3a5c; /* strong border, large numerals on dark */
  --ink-450: #637193; /* control border — 3.06:1 even on level 2 (WCAG 1.4.11) */
  --ink-400: #3f4d6d;
  /* Raised from #7d879e: with three depth levels the darkest surface a caption
     can land on is now level 2 (#1a2740), where the old value gave only 4.14:1. */
  --ink-300: #858fa6; /* darkest text allowed on dark, level 2 included */
  --ink-200: #acb6cc;
  --ink-100: #d3d8e9;
  --ink-050: #eaeefa;

  /* Paper — cool whites with a blue cast. Backdrop of the light theme.
     Replaced the warm porcelain: next to the blue accent, a warm background looked dirty. */
  --paper-000: #ffffff; /* LEVEL 1 — section panel and card on page */
  --paper-050: #f4f7fd; /* LEVEL 2 — card sitting on a level-1 panel */
  --paper-100: #e9eef9; /* LEVEL 0 — page background, deepened so panels read
                           as objects rather than as a flat colour change */
  --paper-150: #eef2fb; /* recessed field */
  --paper-200: #dde4f2; /* deepest section */
  --paper-250: #c9d1e6; /* PANEL EDGE */
  --paper-300: #d3d8e9;
  --paper-400: #bdc2d4;
  --paper-500: #7f879d; /* control border — 3.09:1 on the deepened page */
  --paper-600: #646c7a; /* darkest text still allowed on light, incl. level 0 */

  /* Signal blue — the brand accent. ONE accent across the whole site.
     A bright, clean blue on the navy backdrop. Deliberately NOT the purple-blue
     gradient that gives away a generic "AI" product. */
  --blue-200: #c5d8ff;
  --blue-300: #93bcff; /* accent as TEXT on dark + focus ring */
  --blue-400: #5f97fb;
  --blue-500: #2e7bf0; /* brand core — fill on dark */
  --blue-600: #2370e5;
  --blue-650: #2370e5; /* fill on light — white letters 4.65:1 */
  --blue-700: #1a4694; /* accent as TEXT on light */
  --blue-800: #12356e;

  /* State colors — deliberately separate from the brand accent. */
  --green-300: #6fd3a4;
  --green-500: #3fb27f;
  --green-700: #1f7a54;
  --gold-300: #f0cd77;
  --gold-500: #d9a62e;
  --gold-700: #8b6504;
  --red-300: #f39288;
  --red-500: #e15a4c;
  --red-700: #b3392c;
  /* The "info" state is NEUTRAL — a state color must not compete with the brand. */
  --slate-300: #a8b2c8;
  --slate-500: #67718a;
  --slate-700: #414c63;
}

/* ---------------------------------------------------------------------------
   2. SEMANTIC TOKENS — dark theme (default)
--------------------------------------------------------------------------- */
:root {
  /* Backdrops and surfaces */
  /* THREE DEPTH LEVELS. Sections have to read as separate objects, so every step
     must be visible: level 0 -> 1 is now 1.115:1, where the previous pair
     (#090f1c / #0d1526) gave 1.051:1 — a difference nobody could see, which is
     exactly what made the page feel like one undifferentiated slab. */
  --color-canvas: var(--ink-900);          /* L0 — page */
  --color-canvas-deep: var(--ink-950);     /* sections "recessed" deeper, footer */
  --color-surface: var(--ink-750);         /* L1 — section panel, card on page */
  --color-surface-raised: var(--ink-650);  /* L2 — card on a panel, hover */
  --color-surface-sunken: var(--ink-850);  /* recessed: data field, code block */
  --color-panel-edge: var(--ink-550);      /* the line that makes a panel an object */
  --color-surface-inverse: var(--paper-100);

  /* Text */
  --color-text-primary: var(--ink-050);
  --color-text-secondary: var(--ink-200);
  --color-text-muted: var(--ink-300);
  --color-text-inverse: var(--ink-900);
  --color-text-on-accent: #05101f;         /* text on an accent fill */

  /* Borders and lines */
  --color-border: var(--ink-600);            /* decorative border (cards) */
  --color-border-subtle: rgba(255 255 255 / 8%);
  --color-border-strong: var(--ink-500);
  --color-border-control: var(--ink-450);    /* FIELD/BUTTON border — 3:1 */
  --color-hairline: rgba(255 255 255 / 6%);  /* decorative grid */

  /* Brand accent */
  --color-accent: var(--blue-500);
  --color-accent-hover: var(--blue-400);
  --color-accent-text: var(--blue-300);      /* accent as TEXT on dark */
  --color-accent-quiet: rgba(46 123 240 / 15%);
  --color-accent-border: rgba(46 123 240 / 38%);

  /* States */
  --color-ok: var(--green-500);
  --color-ok-text: var(--green-300);
  --color-ok-quiet: rgba(63 178 127 / 12%);
  --color-warn: var(--gold-500);
  --color-warn-text: var(--gold-300);
  --color-warn-quiet: rgba(217 166 46 / 12%);
  --color-crit: var(--red-500);
  --color-crit-text: var(--red-300);
  --color-crit-quiet: rgba(225 90 76 / 12%);
  --color-info: var(--slate-500);
  --color-info-text: var(--slate-300);
  --color-info-quiet: rgba(168 178 200 / 10%);

  /* Keyboard focus — must stay visible on every backdrop */
  --color-focus: var(--blue-300);

  /* Sticky navigation */
  --color-nav-bg: rgba(9 15 28 / 84%);
  --color-nav-border: rgba(255 255 255 / 8%);

  /* Filled face of an isometric solid — the side turned away from the light.
     It must read as a shadow on the surface BEHIND the drawing, so it darkens
     on dark and goes near-black on light; a single fixed value disappears in
     one theme or the other. */
  --color-illus-shadow: rgba(3 7 14 / 55%);

  /* --- LIGHT IS NOW THE ONLY THEME -------------------------------------
     These values used to live in a :root[data-theme='light'] override. The
     dark theme was dropped, so they are appended here instead of replacing
     the old declarations one by one: a later declaration in the same block
     wins, and appending cannot silently drop a token that existed in the
     dark set but was never overridden in the light one.
  --------------------------------------------------------------------- */
  --color-canvas: var(--paper-100);        /* L0 — page */
  --color-canvas-deep: var(--paper-200);   /* deepest section, footer */
  --color-surface: var(--paper-000);       /* L1 — section panel, card on page */
  --color-surface-raised: var(--paper-050);/* L2 — card on a panel, hover */
  --color-surface-sunken: var(--paper-150);/* recessed: data field, code block */
  --color-panel-edge: var(--paper-250);    /* the line that makes a panel an object */
  --color-surface-inverse: var(--ink-850);
  --color-text-primary: #0b1220;
  --color-text-secondary: #404a5c;
  --color-text-muted: var(--paper-600);
  --color-text-inverse: var(--paper-050);
  --color-text-on-accent: #ffffff;
  --color-border: var(--paper-300);
  --color-border-subtle: rgba(20 24 31 / 10%);
  --color-border-strong: var(--paper-400);
  --color-border-control: var(--paper-500);
  --color-hairline: rgba(20 24 31 / 6%);
  --color-accent: var(--blue-650);
  --color-accent-hover: var(--blue-700);
  --color-accent-text: var(--blue-700);
  --color-accent-quiet: rgba(35 112 229 / 10%);
  --color-accent-border: rgba(35 112 229 / 30%);
  --color-ok: var(--green-700);
  --color-ok-text: var(--green-700);
  --color-ok-quiet: rgba(31 122 84 / 10%);
  --color-warn: var(--gold-700);
  --color-warn-text: var(--gold-700);
  --color-warn-quiet: rgba(150 112 15 / 10%);
  --color-crit: var(--red-700);
  --color-crit-text: var(--red-700);
  --color-crit-quiet: rgba(179 57 44 / 10%);
  --color-info: var(--slate-700);
  --color-info-text: var(--slate-700);
  --color-info-quiet: rgba(65 76 99 / 9%);
  --color-focus: var(--blue-700);
  --color-nav-bg: rgba(240 243 253 / 86%);
  --color-nav-border: rgba(20 24 31 / 10%);
  --color-illus-shadow: rgba(12 18 32 / 88%);
  color-scheme: light;
}

/* ---------------------------------------------------------------------------
   3. TYPOGRAPHY
--------------------------------------------------------------------------- */
:root {
  --font-display: 'Archivo', 'Segoe UI', system-ui, sans-serif;
  --font-body: 'IBM Plex Sans', 'Segoe UI', system-ui, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, 'Cascadia Mono', monospace;

  /* Fluid scale. The min/max values are deliberate — do not add steps by eye. */
  --text-display-xl: clamp(2.5rem, 1.6rem + 3.6vw, 4.25rem);
  --text-display-lg: clamp(1.9rem, 1.35rem + 2.2vw, 3rem);
  --text-display-md: clamp(1.45rem, 1.2rem + 1vw, 1.95rem);
  --text-title: clamp(1.1875rem, 1.05rem + 0.55vw, 1.3125rem);
  /* Base text is 17 px, not 16. The reader is a housing association board member —
     legibility matters more than density.

     THAT HOLDS ON A DESKTOP, AND ONLY THERE. On a 390 px screen a 19 px lead
     left 29 characters per line, and a line that short is harder to read than
     slightly smaller type — the eye spends its time jumping lines instead of
     reading them. So the large end keeps 19/17 px exactly as decided, and the
     small end relaxes to 17/16 px, which is the normal floor for running text
     on a phone. Nothing changes above roughly 1100 px. */
  --text-body-lg: clamp(1.0625rem, 0.95rem + 0.5vw, 1.1875rem);
  --text-body: clamp(1rem, 0.95rem + 0.25vw, 1.0625rem);
  --text-body-sm: 1rem;
  --text-caption: 0.875rem;
  --text-label: 0.75rem;

  --leading-tight: 1.08;
  --leading-snug: 1.25;
  --leading-normal: 1.55;
  --leading-relaxed: 1.7;

  --tracking-display: -0.025em;
  --tracking-normal: 0;
  --tracking-label: 0.09em;   /* eyebrows set in small caps */

  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;
}

/* ---------------------------------------------------------------------------
   4. SPACING, RADII, SHADOWS, LAYOUT
--------------------------------------------------------------------------- */
:root {
  /* 4 px scale. Use these steps only. */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  /* FROM HERE UP THE SCALE IS RESPONSIVE, AND IT HAS TO BE.

     These are the values components use for their own padding, and padding
     nests: on a 390 px screen the container, the panel and the card each
     applied its full desktop inset, so a paragraph inside .pledge__limits was
     left 242 px of a 390 px screen — 44% of the width spent on air, and a line
     of 24 characters where 45-75 is readable.

     Fixing it in the tokens fixes every component at once. Patching the
     handful of components measured as worst would leave the next nested panel
     to reintroduce the same bug.

     Values are chosen so the small end lands on the current mobile-sane figure
     and the large end keeps today's desktop spacing exactly, which is why
     nothing changes above roughly 1000 px. */
  --space-5: clamp(1rem, 0.7rem + 1.2vw, 1.5rem);
  --space-6: clamp(1.25rem, 0.8rem + 1.8vw, 2rem);
  --space-7: clamp(1.5rem, 0.9rem + 2.4vw, 2.5rem);
  --space-8: clamp(1.75rem, 1rem + 3vw, 3rem);
  --space-9: clamp(2.25rem, 1.2rem + 4vw, 4rem);
  --space-10: 5rem;
  --space-11: 6rem;
  --space-12: 8rem;

  /* Vertical rhythm of sections — one token, consistent across the whole site. */
  /* The gap between two sections, and now the ONLY thing that sets it — see
     the adjacency rules in layout.css, where exactly one neighbour pays.
     Trimmed from 7vw/--space-12 (101 px at 1440) to land near 80, which is
     where the reference sites sit; at 101 the page read as a series of
     unrelated slabs rather than one document. */
  --section-pad-y: clamp(var(--space-8), 5.5vw, var(--space-11));
  --section-pad-y-sm: clamp(var(--space-8), 5vw, var(--space-10));

  /* Radii are deliberately SMALL. Large roundings read like a consumer app;
     we want the feel of a document and of instrumentation. */
  --radius-xs: 2px;
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-pill: 999px;

  --shadow-sm: 0 1px 2px rgba(0 0 0 / 24%);
  --shadow-md: 0 8px 24px -8px rgba(0 0 0 / 45%);
  --shadow-lg: 0 24px 64px -20px rgba(0 0 0 / 55%);
  --shadow-accent: 0 12px 32px -12px rgba(46 123 240 / 50%);

  /* Layout widths */
  --width-page: 1240px;      /* main grid — text columns */
  /* Comfortable measure for running text. Past roughly 75 characters the eye
     loses the start of the next line, and several paragraphs here ran to 110
     and one to 133. Expressed in ch so it follows the font, not the viewport. */
  --width-text: 68ch;
  --width-panel: 1400px;     /* section panels: deliberately WIDER than the text
                                grid, so a panel edge is visible beside the
                                content instead of coinciding with it */
  --width-narrow: 920px;     /* focused sections (FAQ, form) */
  --width-prose: 68ch;       /* running text — readable line length */
  --gutter: clamp(var(--space-4), 4vw, var(--space-8));

  --nav-height: 68px;

  /* --- LIGHT IS NOW THE ONLY THEME -------------------------------------
     These values used to live in a :root[data-theme='light'] override. The
     dark theme was dropped, so they are appended here instead of replacing
     the old declarations one by one: a later declaration in the same block
     wins, and appending cannot silently drop a token that existed in the
     dark set but was never overridden in the light one.
  --------------------------------------------------------------------- */
  --shadow-sm: 0 1px 2px rgba(20 24 31 / 8%);
  --shadow-md: 0 8px 24px -8px rgba(20 24 31 / 12%);
  --shadow-lg: 0 24px 64px -20px rgba(20 24 31 / 16%);
  --shadow-accent: 0 12px 32px -12px rgba(35 112 229 / 34%);
}

/* ---------------------------------------------------------------------------
   5. MOTION
   Animation serves understanding (step order, data flow), not decoration.
--------------------------------------------------------------------------- */
:root {
  --duration-fast: 140ms;
  --duration-base: 240ms;
  --duration-slow: 480ms;
  --duration-deliberate: 900ms;

  --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-in-out: cubic-bezier(0.45, 0.05, 0.55, 0.95);
  --ease-spring: cubic-bezier(0.34, 1.32, 0.64, 1);

  --z-base: 0;
  --z-raised: 10;
  --z-nav: 100;
  --z-overlay: 200;
}

/* A user who asks for reduced motion gets the site without animation. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-fast: 1ms;
    --duration-base: 1ms;
    --duration-slow: 1ms;
    --duration-deliberate: 1ms;
  }
}
