/* ==========================================================================
   carea24.de - design tokens, Phase 1
   File:    260818_doco_carea24-tokens_v2.css
   From:    Keir (Brand Designer), via Parker
   Source:  Lior, "carea24.de - art direction, Phase 1"
            Team Inbox/260818_doco_Carea24-Art-Direction_Lior_v1.md
            plus his three rulings of 2026-08-18 (see CHANGES FROM v1).
   For:     Zephyr (build), Aldo (interface craft), Isla (Bedarfsbogen)
   Date:    2026-08-18

   CHANGES FROM v1 - all three are Lior's rulings, none is my discretion
   1. NEW `action.onDark` #DE805E. The closing-CTA fill on brand.900, with
      an INK label. White on it is 2.86:1 and fails. Section 3.
   2. Eyebrow 14px -> 15px. The 15px floor stands; the token was the defect.
   3. Accent rationing recorded as a rule that travels with the file, and
      read per ROLE not per hex. See ACCENT RATIONING below.

   HOW THIS FILE WORKS - read before editing anything

   There is ONE master colour: --c24-h / --c24-s / --c24-l.
   Every colour token on the site except pure white and pure black is
   derived from it arithmetically. There are no orphaned hex literals in
   the colour system. That is the whole point: the defect that broke the
   old carea24 palette was hard literals replacing generated values, so a
   recolour could never restore it. Here a recolour is one number.

   TO RECOLOUR THE SITE: change --c24-h. Nothing else.
   Both action colours rotate with it (H+184), the neutrals rotate with it,
   the tints rotate with it. Nothing orphans.
   A hue recolour is one number PLUS a run of the assertion script. sRGB
   luminance is hue-dependent at fixed HSL lightness, so some hues break AA
   even with every L held. The script is what makes the recolour safe.

   THE ONE RULE THAT MUST NOT BE RELAXED
   Derivation operates on H and S. The L column is FIXED per step.
   Lightness is what carries every WCAG contrast ratio on this site. If a
   future edit moves an L value, the AA guarantees break silently and no
   eyeball check will catch it.
   This is not enforced by comment. It is enforced by
   260818_doco_carea24-contrast-assert_v2.mjs, which parses THIS FILE,
   recomputes every pair, and exits non-zero. Wire it into the build.
   Changing an L delta below turns the build red. That is intended.

   ACCENT RATIONING - a documented rule, counted by ROLE
   - `brand.700` is the system colour: maximum THREE ROLES per viewport.
     A role is a job, not an instance. Ten links in one paragraph are one
     role. A link colour, an eyebrow and an icon stroke are three roles and
     that is the ceiling.
   - `action` / `action.onDark` are ONE role and they get ONE role AND ONE
     INSTANCE per viewport. Not one each. They are the same role wearing
     two grounds, so they must never co-occur on a single viewport - a hero
     CTA and a closing-band CTA are never simultaneously in view, which is
     exactly why two tokens are safe.
   - If a comp exceeds either count, halve it.
   This is the one rule in the file a build cannot check. It is a review
   item for Aldo and it is written here so it travels with the tokens.

   TWO DERIVATION MECHANISMS, deliberately different
   1. Chromatic ramp (brand.900 to brand.100) - H, S and L all derive as
      DELTAS off the master. A recolour carries the whole ramp coherently.
   2. Neutrals and action (ink, ink.muted, action, action.onDark) - H
      derives as a delta, S and L are ABSOLUTE. Per Lior's Section 2.3
      table. This is correct: ink must stay a near-neutral at a fixed
      lightness whatever the master saturation does, and the action
      colours' contrast must not drift with the ramp.
   ========================================================================== */

:root {
  /* ------------------------------------------------------------------
     1. MASTER - the single variable set
     hsl(192, 62%, 26%) = #195B6B, deep petrol teal
     Unitless numbers so the derivations can do arithmetic on them.
     ------------------------------------------------------------------ */
  --c24-h: 192;
  --c24-s: 62;
  --c24-l: 26;

  /* ------------------------------------------------------------------
     2. DERIVATION CONTRACT
     Named deltas, one per token. The assertion script reads these.
     dh = hue delta, ds = saturation delta, dl = LIGHTNESS DELTA (FIXED).
     Absolute values are written as -s / -l instead of -ds / -dl.
     ------------------------------------------------------------------ */
  --c24-brand-900-dh: 0;    --c24-brand-900-ds: 2;    --c24-brand-900-dl: -12;
  --c24-brand-700-dh: 0;    --c24-brand-700-ds: 0;    --c24-brand-700-dl: 0;
  --c24-brand-500-dh: 0;    --c24-brand-500-ds: -12;  --c24-brand-500-dl: 16;
  --c24-brand-200-dh: 0;    --c24-brand-200-ds: -24;  --c24-brand-200-dl: 60;
  --c24-brand-100-dh: 0;    --c24-brand-100-ds: -18;  --c24-brand-100-dl: 68;

  --c24-ink-dh: 0;          --c24-ink-s: 22;          --c24-ink-l: 11;
  --c24-ink-muted-dh: 0;    --c24-ink-muted-s: 10;    --c24-ink-muted-l: 38;
  --c24-action-dh: 184;     --c24-action-s: 58;       --c24-action-l: 38;

  /* NEW in v2. Same hue delta as `action` - it is the same colour doing
     the same job on a dark ground, not a second accent. Only S and L move. */
  --c24-action-on-dark-dh: 184;
  --c24-action-on-dark-s: 66;
  --c24-action-on-dark-l: 62;

  /* Mix percentages. wash and divider are brand.700 laid over white;
     on-dark-muted is white laid over brand.900. */
  --c24-wash-mix: 4;
  --c24-divider-mix: 12;
  --c24-on-dark-muted-mix: 70;

  /* ------------------------------------------------------------------
     3. COLOUR TOKENS
     Each token exists twice:
       --c24-<name>-hsl  space-separated triplet, for Tailwind's
                         hsl(var(--x) / <alpha-value>) pattern
       --c24-<name>      the resolved colour, for hand-written CSS
     Resolved hex is given in the comment so the numbers stay checkable.
     ------------------------------------------------------------------ */

  /* brand.900  #0D313B  Deep ground. Footer and the closing CTA band */
  --c24-brand-900-hsl:
    calc(var(--c24-h) + var(--c24-brand-900-dh))
    calc((var(--c24-s) + var(--c24-brand-900-ds)) * 1%)
    calc((var(--c24-l) + var(--c24-brand-900-dl)) * 1%);
  --c24-brand-900: hsl(var(--c24-brand-900-hsl));

  /* brand.700  #195B6B  MASTER. Link text, eyebrows, icon strokes,
     secondary button outline and label. Max 3 ROLES per viewport. */
  --c24-brand-700-hsl:
    calc(var(--c24-h) + var(--c24-brand-700-dh))
    calc((var(--c24-s) + var(--c24-brand-700-ds)) * 1%)
    calc((var(--c24-l) + var(--c24-brand-700-dl)) * 1%);
  --c24-brand-700: hsl(var(--c24-brand-700-hsl));

  /* brand.500  #368BA1  UI COMPONENTS ONLY - input borders,
     dividers-strong, hover on outline.
     NEVER a fill under text below 24px. NEVER a text colour on white.
     It measures 3.91:1 against white: legal for a 3:1 non-text component,
     illegal for 4.5:1 body text. This is the single most likely way this
     palette degrades in build. */
  --c24-brand-500-hsl:
    calc(var(--c24-h) + var(--c24-brand-500-dh))
    calc((var(--c24-s) + var(--c24-brand-500-ds)) * 1%)
    calc((var(--c24-l) + var(--c24-brand-500-dl)) * 1%);
  --c24-brand-500: hsl(var(--c24-brand-500-hsl));

  /* brand.200  #CEE3E9  Card fill, quote panels.
     Body copy on this ground is --c24-ink, NEVER --c24-ink-muted. */
  --c24-brand-200-hsl:
    calc(var(--c24-h) + var(--c24-brand-200-dh))
    calc((var(--c24-s) + var(--c24-brand-200-ds)) * 1%)
    calc((var(--c24-l) + var(--c24-brand-200-dl)) * 1%);
  --c24-brand-200: hsl(var(--c24-brand-200-hsl));

  /* brand.100  #E9F4F6  Section tint ground */
  --c24-brand-100-hsl:
    calc(var(--c24-h) + var(--c24-brand-100-dh))
    calc((var(--c24-s) + var(--c24-brand-100-ds)) * 1%)
    calc((var(--c24-l) + var(--c24-brand-100-dl)) * 1%);
  --c24-brand-100: hsl(var(--c24-brand-100-hsl));

  /* ink  #162022  All headings and all body copy.
     Also the LABEL on --c24-action-on-dark. See the trap note below. */
  --c24-ink-hsl:
    calc(var(--c24-h) + var(--c24-ink-dh))
    calc(var(--c24-ink-s) * 1%)
    calc(var(--c24-ink-l) * 1%);
  --c24-ink: hsl(var(--c24-ink-hsl));

  /* ink.muted  #57676B  Secondary copy, meta, captions.
     Legal on wash, white and brand.100. NOT legal on brand.200 (4.44:1). */
  --c24-ink-muted-hsl:
    calc(var(--c24-h) + var(--c24-ink-muted-dh))
    calc(var(--c24-ink-muted-s) * 1%)
    calc(var(--c24-ink-muted-l) * 1%);
  --c24-ink-muted: hsl(var(--c24-ink-muted-hsl));

  /* action  #994729  Primary CTA fill ON LIGHT GROUNDS. Nothing else.
     Hue is 192 + 184 = 376, which CSS normalises mod 360 to 16.
     Derived, not authored - change --c24-h and the CTA re-skins with the
     rest of the site. There is no value in this system that a recolour
     would orphan.
     LABEL IS WHITE. white on action = 6.39:1. ink on action = 2.60:1. */
  --c24-action-hsl:
    calc(var(--c24-h) + var(--c24-action-dh))
    calc(var(--c24-action-s) * 1%)
    calc(var(--c24-action-l) * 1%);
  --c24-action: hsl(var(--c24-action-hsl));

  /* action.onDark  #DE805E  NEW in v2.
     The CLOSING-CTA FILL ON brand.900, and nothing else. Not a hover
     state, not a light-ground alternative, not an icon colour.

     *** THE TRAP, WRITTEN DOWN BEFORE ANYONE HITS IT ***
     The two action tokens take OPPOSITE label colours:
        --c24-action        fill -> WHITE label   (6.39:1, ink is 2.60:1)
        --c24-action-on-dark fill -> INK label    (5.82:1, white is 2.86:1)
     Copying the light button component onto the dark band and keeping the
     white label produces 2.86:1 on the most important control at the
     bottom of every page. White on this fill fails 4.5:1 AND fails the
     3:1 large-text floor, so there is no "make the label bigger" escape.
     Both directions are asserted in the contrast script. */
  --c24-action-on-dark-hsl:
    calc(var(--c24-h) + var(--c24-action-on-dark-dh))
    calc(var(--c24-action-on-dark-s) * 1%)
    calc(var(--c24-action-on-dark-l) * 1%);
  --c24-action-on-dark: hsl(var(--c24-action-on-dark-hsl));

  /* Absolutes - the only two literals the colour system is allowed */
  --c24-white: #FFFFFF;
  --c24-on-dark: #FFFFFF;

  /* wash  #F6F8F9  PAGE BACKGROUND. The site does not sit on white. */
  --c24-wash: color-mix(in srgb, var(--c24-brand-700) calc(var(--c24-wash-mix) * 1%), var(--c24-white));

  /* divider  #E3EBED  Hairlines, section rules */
  --c24-divider: color-mix(in srgb, var(--c24-brand-700) calc(var(--c24-divider-mix) * 1%), var(--c24-white));

  /* onDark.muted  #B6C1C4  Copyright line, footer meta. 7.51:1 on brand.900.
     v1 flagged a 70/72 discrepancy in Lior's prose. He confirmed 70% and
     corrected his source document. Closed. */
  --c24-on-dark-muted: color-mix(in srgb, var(--c24-white) calc(var(--c24-on-dark-muted-mix) * 1%), var(--c24-brand-900));

  /* Footer divider on dark - 12% white, per Section 5 chrome */
  --c24-divider-on-dark: color-mix(in srgb, var(--c24-white) 12%, transparent);

  /* ------------------------------------------------------------------
     4. SEMANTIC ALIASES
     Use these in components. They exist so a component never hard-codes
     a ramp step, and so a ground swap is one line.
     ------------------------------------------------------------------ */
  --c24-bg-page: var(--c24-wash);
  --c24-bg-raised: var(--c24-white);
  --c24-bg-tint: var(--c24-brand-100);
  --c24-bg-card: var(--c24-brand-200);
  --c24-bg-deep: var(--c24-brand-900);

  --c24-text-default: var(--c24-ink);
  --c24-text-muted: var(--c24-ink-muted);
  --c24-text-link: var(--c24-brand-700);
  --c24-text-on-deep: var(--c24-on-dark);
  --c24-text-on-deep-muted: var(--c24-on-dark-muted);

  --c24-border-hairline: var(--c24-divider);
  --c24-border-strong: var(--c24-brand-500);

  /* CTA pairs. Always take fill and label from the SAME pair. */
  --c24-cta-fill: var(--c24-action);
  --c24-cta-label: var(--c24-white);
  --c24-cta-fill-on-deep: var(--c24-action-on-dark);
  --c24-cta-label-on-deep: var(--c24-ink);

  /* ------------------------------------------------------------------
     5. TYPEFACE
     One family: Source Sans 3. Self-hosted woff2, latin + latin-ext.
     Four cuts only: 400, 400 italic, 600, 700.
     WEIGHTS 200 AND 300 DO NOT EXIST IN THIS SYSTEM. Not in buttons, not
     in eyebrows, not in the footer.
     No external font CDN at runtime. font-display: swap, all four
     preloaded. Payload target under 140 KB total.
     ------------------------------------------------------------------ */
  --c24-font-sans: "Source Sans 3", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --c24-fw-regular: 400;
  --c24-fw-semibold: 600;
  --c24-fw-bold: 700;

  /* ------------------------------------------------------------------
     6. TYPE SCALE - mobile first
     Base block = mobile (up to 767px). The md and lg blocks at the bottom
     of this file step it up, so the min-width breakpoints here agree
     exactly with the Tailwind screens.
     HARD FLOOR: nothing on this site is set below 15px. Checkable.
     ------------------------------------------------------------------ */
  --c24-fs-h1: 34px;      --c24-lh-h1: 1.15;    --c24-ls-h1: -0.02em;
  --c24-fs-h2: 28px;      --c24-lh-h2: 1.20;    --c24-ls-h2: -0.01em;
  --c24-fs-h3: 23px;      --c24-lh-h3: 1.25;    --c24-ls-h3: normal;
  --c24-fs-h4: 20px;      --c24-lh-h4: 1.30;    --c24-ls-h4: normal;
  --c24-fs-h5: 18px;      --c24-lh-h5: 1.40;    --c24-ls-h5: normal;
  /* v2: 14px -> 15px. Lior's ruling. The eyebrow is where the section's
     claim lives and it now sits exactly ON the 15px floor, not under it.
     It does not step responsively. */
  --c24-fs-eyebrow: 15px; --c24-lh-eyebrow: 1.40; --c24-ls-eyebrow: 0.08em;
  --c24-fs-lead: 20px;    --c24-lh-lead: 1.50;  --c24-ls-lead: normal;
  --c24-fs-body: 18px;    --c24-lh-body: 1.60;  --c24-ls-body: normal;
  --c24-fs-body-sm: 16px; --c24-lh-body-sm: 1.55;
  --c24-fs-meta: 15px;    --c24-lh-meta: 1.50;
  --c24-fs-nav: 17px;     --c24-lh-nav: 1.40;
  --c24-fs-button: 17px;  --c24-lh-button: 1.00; --c24-ls-button: 0.01em;
  --c24-fs-input: 18px;   --c24-lh-input: 1.40;
  --c24-fs-label: 16px;   --c24-lh-label: 1.40;

  /* Weight per role. Eyebrow is UPPERCASE; every other role is sentence
     case. No role in this system uses uppercase except eyebrow. */
  --c24-fw-h1: var(--c24-fw-bold);
  --c24-fw-h2: var(--c24-fw-bold);
  --c24-fw-h3: var(--c24-fw-semibold);
  --c24-fw-h4: var(--c24-fw-semibold);
  --c24-fw-h5: var(--c24-fw-semibold);
  --c24-fw-eyebrow: var(--c24-fw-semibold);
  --c24-fw-lead: var(--c24-fw-regular);
  --c24-fw-body: var(--c24-fw-regular);
  --c24-fw-nav: var(--c24-fw-semibold);
  --c24-fw-button: var(--c24-fw-semibold);
  --c24-fw-input: var(--c24-fw-regular);
  --c24-fw-label: var(--c24-fw-semibold);

  /* ------------------------------------------------------------------
     7. SPACING - base unit 4px
     ------------------------------------------------------------------ */
  --c24-space-4: 4px;
  --c24-space-8: 8px;
  --c24-space-12: 12px;
  --c24-space-16: 16px;
  --c24-space-24: 24px;
  --c24-space-32: 32px;
  --c24-space-48: 48px;
  --c24-space-64: 64px;
  --c24-space-80: 80px;
  --c24-space-96: 96px;
  --c24-space-128: 128px;

  /* Responsive layout measures - mobile base, stepped at md and lg */
  --c24-section-y: 56px;      /* section padding, vertical */
  --c24-hero-top: 64px;       /* hero padding, top */
  --c24-gutter: 24px;         /* horizontal gutter */
  --c24-grid-gap: 24px;       /* grid and card gap */
  --c24-paragraph-gap: 24px;  /* constant across all breakpoints */

  /* Containers - three tiers, not six.
     prose: BOTH the px and the ch cap apply; whichever is narrower wins.
     The ch cap is what actually protects the reading. */
  --c24-container-content: 1120px;
  --c24-container-prose: 680px;
  --c24-container-prose-ch: 68ch;
  --c24-container-bleed: 100vw;

  --c24-header-height: 72px;
  --c24-target-min: 44px;     /* every interactive target, minimum */

  /* ------------------------------------------------------------------
     8. RADII - one orientation, three sizes
     THE SQUARED CORNER IS ALWAYS BOTTOM-LEFT AND IS NEVER MIRRORED.
     It is the terminal corner of the reading path, so it reads as a full
     stop rather than as decoration. Fixed orientation is what turns a
     shape into a signature; per-element mirroring is what turned it into
     noise on the reference site (seven variants there).
     FREQUENCY BUDGET: media and cards only. Not the header, not the
     footer, not section backgrounds, not badges, not the cookie banner.
     Legal pages are flat - the signature corner does not apply there.
     ------------------------------------------------------------------ */
  --c24-radius-media: 32px 32px 32px 0;
  --c24-radius-card: 24px 24px 24px 0;
  --c24-radius-control: 8px 8px 8px 0;   /* buttons AND inputs, identical,
                                            so the form reads as one system */
  --c24-radius-pill: 999px;              /* category chips and filters only */
  --c24-radius-avatar: 50%;              /* carer and team portraits only */
  --c24-radius-flat: 0;                  /* legal document pages */

  /* ------------------------------------------------------------------
     9. SHADOW - one token, used on raised cards only
     0 2px 8px rgba(22,32,34,0.06) = ink at 6%. Derived, so it rotates
     with a recolour and never tints toward a brand hue independently.
     The reference's green-tinted upward glow is rejected.
     ------------------------------------------------------------------ */
  --c24-shadow-raised: 0 2px 8px color-mix(in srgb, var(--c24-ink) 6%, transparent);

  /* ------------------------------------------------------------------
     10. FOCUS RING - two-tone, and it cannot be simplified to one
     A single ink ring is 15.60:1 on wash but 2.18:1 against the
     brand.700 button fill - it fails on exactly the control that most
     needs it. Two bands guarantee one of them clears 3:1 on any ground.
     DO NOT optimise the second ring away. The failing case is written
     down here so nobody has to rediscover it.
     ------------------------------------------------------------------ */
  --c24-focus-inner: var(--c24-white);
  --c24-focus-outer: var(--c24-ink);
  --c24-focus-width: 2px;
  --c24-focus-offset: 2px;
  --c24-focus-ring:
    0 0 0 var(--c24-focus-width) var(--c24-focus-inner),
    0 0 0 calc(var(--c24-focus-width) * 2) var(--c24-focus-outer);

  /* ------------------------------------------------------------------
     11. MOTION - two moments for the entire site
     1. Section entry: 200ms, opacity 0 to 1 plus 8px rise, once per
        section, never re-triggers on scroll-back.
     2. Disclosure: accordion and step reveal.
     Everything else is forbidden: no parallax, no counters, no marquees,
     no hover lifts on cards, no scroll-linked anything.
     ------------------------------------------------------------------ */
  --c24-duration: 200ms;
  --c24-easing: cubic-bezier(0.2, 0, 0.2, 1);
  --c24-rise: 8px;
}

/* --------------------------------------------------------------------------
   12. BREAKPOINTS - DOCUMENTED, NOT TOKENISED

   LIMITATION, STATED EXPLICITLY: a media query cannot read a CSS custom
   property. `@media (min-width: var(--c24-screen-md))` is invalid CSS and
   is silently dropped by every browser. Custom properties are resolved on
   elements at computed-value time; media queries are evaluated before that
   and have no element to resolve against. There is no workaround in plain
   CSS, so the breakpoint values below are literals in this file and
   literals again in the Tailwind config. They are the ONE set of numbers
   in this token system that exists in two places.

   If the breakpoints ever change, both files must change together:
     260818_doco_carea24-tokens_v2.css        (this file, sections 12-14)
     260818_doco_carea24-tailwind-tokens_v2.js (theme.screens)

   THE BREAKPOINTS, min-width, per Lior Section 4.2. Nothing else.
     md   768px   tablet
     lg  1024px   desktop
     xl  1200px   container tier only
   -------------------------------------------------------------------------- */

/* 13. TABLET - md, 768px */
@media (min-width: 768px) {
  :root {
    --c24-fs-h1: 42px;   --c24-lh-h1: 1.12;
    --c24-fs-h2: 34px;   --c24-lh-h2: 1.18;
    --c24-fs-h3: 26px;
    --c24-fs-h4: 21px;
    --c24-fs-h5: 19px;
    --c24-fs-lead: 21px;

    --c24-section-y: 72px;
    --c24-hero-top: 88px;
    --c24-gutter: 40px;
    --c24-grid-gap: 32px;
  }
}

/* 14. DESKTOP - lg, 1024px */
@media (min-width: 1024px) {
  :root {
    --c24-fs-h1: 56px;   --c24-lh-h1: 1.08;
    --c24-fs-h2: 40px;   --c24-lh-h2: 1.15;
    --c24-fs-h3: 28px;
    --c24-fs-h4: 22px;
    --c24-fs-h5: 20px;
    --c24-fs-lead: 22px;

    --c24-section-y: 96px;
    --c24-hero-top: 120px;
    --c24-gutter: 40px;
    --c24-grid-gap: 32px;
  }
}

/* --------------------------------------------------------------------------
   15. REDUCED MOTION - disables both motion moments, no fallback animation
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  :root {
    --c24-duration: 0ms;
    --c24-rise: 0px;
  }
}

/* --------------------------------------------------------------------------
   16. NOT IN THIS SYSTEM - the prohibition list, so it is one grep away

   Colour:      no hex literal in any component. Every colour comes from a
                --c24-* token. brand.500 is never a text colour and never a
                fill under text below 24px. `action` and `action.onDark` are
                ONE role: one role and one instance per viewport, never both
                on the same viewport, never on icons, rules, hover states or
                the phone number. `action.onDark` is never used on a light
                ground and `action` is never used on brand.900. Neither
                button ever borrows the other's label colour. No green
                anywhere - the Soma hue #61CD66 does not appear.
   Type:        no weight 200, no weight 300, no second family, no size
                below 15px, no letter-spacing on input text, no uppercase
                except the eyebrow role.
   Shape:       no mirrored squared corner, no square-cornered buttons, no
                radius value outside section 8.
   Effects:     no gradients, no drop shadow other than --c24-shadow-raised,
                no decorative borders, no coloured or brand-tinted shadow.
   Layout:      no text set over photography, ever. No decorative element
                larger than the headline on the same viewport. No page where
                the primary action is below the fold on a 360px phone.
   Third party: no font CDN, no maps embed, no YouTube, no analytics before
                consent. Zero third-party requests at load other than the
                consent layer.
   -------------------------------------------------------------------------- */


/* ==========================================================================
   carea24.de - COMING SOON. The whole of the site's styling.

   Loads AFTER tokens.css and holds no colour, size, radius or weight value
   of its own. Every declaration resolves to a --c24-* token, so Keir's
   contrast assertion over the token file is an assertion over this page and
   not merely over a palette that happens to sit next to it.

   NO PHOTOGRAPHY. NO SYMBOL. NO SCRIPT. The wordmark carries the page alone,
   which is Keir's section 5 interim ruling: the existing symbol is redrawn,
   not recoloured, and the redraw is not executed. A mark that vanishes in a
   footer is a worse outcome than no mark.

   FONTS ARE SELF-HOSTED. That is not a performance decision here, it is a
   legal one. The Datenschutzerklaerung's second paragraph states that the
   page loads nothing from third parties. A Google Fonts request would make
   our own privacy notice an untrue statement on a live page, which is the
   defect class the whole cutover exists to remove.
   ========================================================================== */

/* --------------------------------------------------------------- 1. fonts */
/* Weight range clamped to 400 700, not 200 900. The file can render 250; the
   design system says weights 200 and 300 do not exist. Clamping here means a
   stray font-weight: 300 renders as 400 rather than as a forbidden thin. */
@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/fonts/source-sans-3-latin-normal.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/fonts/source-sans-3-latin-ext-normal.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---------------------------------------------------------- 2. reset */
/* :where() so the reset carries zero specificity - Aldo's rule. */
:where(*, *::before, *::after) { box-sizing: border-box; }

:where(html) { -webkit-text-size-adjust: 100%; }

:where(body) {
  margin: 0;
  background-color: var(--c24-bg-page);
  color: var(--c24-text-default);
  font-family: var(--c24-font-sans);
  font-size: var(--c24-fs-body);
  line-height: var(--c24-lh-body);
  font-weight: var(--c24-fw-regular);
  -webkit-font-smoothing: antialiased;
  /* 200% zoom without a horizontal scrollbar is a budget item. Nothing on
     this page may widen the document. */
  overflow-x: hidden;
}

:where(h1, h2, h3, p, ul, ol, dl, dt, dd) { margin: 0; }
:where(ul, ol) { padding: 0; list-style: none; }

:where(a) {
  color: var(--c24-text-link);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

/* Two-tone focus ring. It cannot be reduced to one band: an ink ring
   disappears on the deep ground and a white ring disappears on the wash.
   The two bands together clear their floors on every ground this page uses,
   and the contrast assertion proves that arithmetically. */
:where(a):focus-visible {
  outline: none;
  border-radius: 2px;
  box-shadow: var(--c24-focus-ring);
}

/* ------------------------------------------------------- 3. page skeleton */
.page {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.shell {
  width: 100%;
  max-width: 46rem;
  margin: 0 auto;
  padding-left: var(--c24-space-24);
  padding-right: var(--c24-space-24);
}

.masthead {
  padding-top: var(--c24-space-48);
  padding-bottom: var(--c24-space-32);
}

.main { flex: 1 0 auto; }

.sitefoot {
  padding-top: var(--c24-space-48);
  padding-bottom: var(--c24-space-64);
}

.sitefoot .rule {
  border: 0;
  border-top: 1px solid var(--c24-border-hairline);
  margin: 0 0 var(--c24-space-24);
}

.sitefoot nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--c24-space-24);
}

.sitefoot a {
  font-size: var(--c24-fs-meta);
  line-height: var(--c24-lh-meta);
  font-weight: var(--c24-fw-semibold);
}

/* --------------------------------------------------------- 4. the wordmark */
/* Typographic, one weight, one colour, no symbol beside it. The size is
   deliberately below the display step: this is a placeholder page and a
   56px wordmark over one sentence reads as a launch, which is a claim. */
.wordmark {
  font-size: var(--c24-fs-h3);
  line-height: var(--c24-lh-h3);
  font-weight: var(--c24-fw-bold);
  letter-spacing: -0.01em;
  color: var(--c24-brand-700);
  display: inline-block;
}

.wordmark--link { text-decoration: none; }
.wordmark--link:hover { text-decoration: underline; }

/* ---------------------------------------------------------- 5. home layout */
.announce {
  font-size: var(--c24-fs-h1);
  line-height: var(--c24-lh-h1);
  letter-spacing: var(--c24-ls-h1);
  font-weight: var(--c24-fw-h1);
  color: var(--c24-text-default);
  max-width: 22ch;
  padding-top: var(--c24-space-32);
  padding-bottom: var(--c24-space-64);
}

/* KAT-03. Set quietly and below the announcement: it is a provider statement,
   not a pitch, and typography that promoted it would be doing the promoting
   the catalogue entry is written to avoid. */
.provider {
  font-size: var(--c24-fs-body-sm);
  line-height: var(--c24-lh-body-sm);
  color: var(--c24-text-muted);
  max-width: 58ch;
  margin-top: var(--c24-space-48);
  padding-top: var(--c24-space-24);
  border-top: 1px solid var(--c24-border-hairline);
}

.contact {
  padding-top: 0;
}

.contact h2 {
  font-size: var(--c24-fs-eyebrow);
  line-height: var(--c24-lh-eyebrow);
  letter-spacing: var(--c24-ls-eyebrow);
  font-weight: var(--c24-fw-eyebrow);
  text-transform: uppercase;
  color: var(--c24-text-muted);
  padding-bottom: var(--c24-space-16);
}

.contact dl {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--c24-space-8) var(--c24-space-24);
  align-items: baseline;
}

.contact dt {
  font-size: var(--c24-fs-label);
  line-height: var(--c24-lh-label);
  font-weight: var(--c24-fw-label);
  color: var(--c24-text-muted);
}

.contact dd {
  margin: 0;
  font-size: var(--c24-fs-lead);
  line-height: var(--c24-lh-lead);
}

@media (max-width: 27rem) {
  .contact dl { grid-template-columns: 1fr; gap: var(--c24-space-4); }
  .contact dt { padding-top: var(--c24-space-12); }
}

/* --------------------------------------------------------- 6. legal pages */
/* radius-flat is the legal-document rule: no rounded corner anywhere on a
   page whose job is to be a record. */
.legal { border-radius: var(--c24-radius-flat); }

.legal h1 {
  font-size: var(--c24-fs-h2);
  line-height: var(--c24-lh-h2);
  letter-spacing: var(--c24-ls-h2);
  font-weight: var(--c24-fw-h2);
  padding-bottom: var(--c24-space-32);
}

.legal h2 {
  font-size: var(--c24-fs-h5);
  line-height: var(--c24-lh-h5);
  font-weight: var(--c24-fw-h5);
  color: var(--c24-text-default);
  padding-top: var(--c24-space-32);
  padding-bottom: var(--c24-space-8);
}

.legal p,
.legal .addr {
  font-size: var(--c24-fs-body);
  line-height: var(--c24-lh-body);
  max-width: 66ch;
  padding-bottom: var(--c24-space-12);
}

.legal .label {
  color: var(--c24-text-muted);
  padding-bottom: var(--c24-space-8);
}

.legal .addr { font-style: normal; }
.legal .addr span { display: block; }

.legal dl {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--c24-space-4) var(--c24-space-16);
  max-width: 66ch;
}
.legal dt { color: var(--c24-text-muted); }
.legal dd { margin: 0; }

.legal .stand {
  color: var(--c24-text-muted);
  font-size: var(--c24-fs-meta);
  line-height: var(--c24-lh-meta);
  padding-top: var(--c24-space-32);
}

/* ------------------------------------------------------- 7. draft banner */
/*
   REMOVED 2026-08-19, and the removal was forced by a gate rather than
   noticed by a person - which is the point worth recording.

   The banner itself came off the Datenschutz page once Tamsin closed the last
   unfilled fact. The RULE stayed here as dead code, and the production
   artefact sweep (Reyes C2) failed the build on it: the sweep greps raw bytes
   across EVERY file in the deploy, so it read the string out of the compiled
   stylesheet, where the placeholder gate can never look. The placeholder gate
   reads extracted VISIBLE TEXT of HTML documents; a class name and a comment
   in a CSS file are invisible to it and were shipping regardless.

   Two mechanisms over the same rule, and the second one caught what the first
   one is structurally unable to see. That is the argument for having both.

   If a draft banner is ever needed again, the rule comes back with it. Dead
   CSS that trips a safety sweep is worse than no CSS.
*/

/* ------------------------------------------------------------- 8. 404 */
.notfound h1 {
  font-size: var(--c24-fs-h2);
  line-height: var(--c24-lh-h2);
  font-weight: var(--c24-fw-h2);
  padding-bottom: var(--c24-space-16);
}
.notfound p { max-width: 52ch; padding-bottom: var(--c24-space-24); }

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