/* ============================================================================
   TNI — Type & Colour Implementation                       brand/type-color.css
   ----------------------------------------------------------------------------
   Extends brand/tokens.css. Imports nothing. Never re-values a token declared
   in tokens.css: inherited values are CONSUMED via var(), never re-typed.

   Layers
     1  Typography metrics      --tni-font-size-* / -leading-* / -weight-* / -tracking-*
     2  Measures (text width)   --tni-measure-*
     3  Grid, spacing, radii    --tni-space-* / --tni-radius-* / --tni-grid-*
     4  Colour ramps             --tni-accent-50..900 / --tni-neutral-50..900
     5  Semantics (light)        --tni-bg-* / --tni-fg-* / --tni-line-* / --tni-focus-*
     6  Semantics (dark)         [data-tni-theme="dark"] + prefers-color-scheme
     7  Role classes             .tni-display-1 … .tni-number, .tni-markers
     8  Motion                   --tni-dur-* / --tni-ease-* / --tni-stagger-*
     9  Print                    monochrome survival

   Every contrast figure quoted here is measured; the matrix lives in
   brand/accessibility.md. Derived ramps are documented in brand/color-system.md.
   ========================================================================= */


/* ---------------------------------------------------------------------------
   1. TYPOGRAPHY
   Two ratios: 1.125 (major second) from caption → lead, 1.250 (major third)
   from title-4 → display-1. Base step = 16px.
   Poppins ships 400/500/600 only. There is no italic and no 700.
   ------------------------------------------------------------------------ */
:root {
  /* families */
  --tni-font-sans-fallback: ui-sans-serif, system-ui, sans-serif;

  /* sizes — 12/14/16/18 text band, 20/25/32/40/50/63 title band */
  --tni-font-size-display-1: 3.9375rem;  /* 63px */
  --tni-font-size-display-2: 3.125rem;   /* 50px */
  --tni-font-size-title-1:   2.5rem;     /* 40px */
  --tni-font-size-title-2:   2rem;       /* 32px */
  --tni-font-size-title-3:   1.5625rem;  /* 25px */
  --tni-font-size-title-4:   1.25rem;    /* 20px */
  --tni-font-size-lead:      1.125rem;   /* 18px */
  --tni-font-size-body:      1rem;       /* 16px */
  --tni-font-size-body-sm:   0.875rem;   /* 14px */
  --tni-font-size-label:     1rem;       /* 16px */
  --tni-font-size-overline:  0.75rem;    /* 12px */
  --tni-font-size-caption:   0.75rem;    /* 12px */
  --tni-font-size-number:    1rem;       /* 16px */

  /* line heights — unitless; every value resolves to a multiple of 4px except
     title-3 (31px), which has a snapped 32px variant for grid alignment */
  --tni-leading-display-1: 1.05;   /* 66px */
  --tni-leading-display-2: 1.08;   /* 54px */
  --tni-leading-title-1:   1.15;   /* 46px */
  --tni-leading-title-2:   1.20;   /* 38px */
  --tni-leading-title-3:   1.24;   /* 31px */
  --tni-leading-title-4:   1.30;   /* 26px */
  --tni-leading-lead:      1.45;   /* 26px */
  --tni-leading-body:      1.50;   /* 24px */
  --tni-leading-body-sm:   1.50;   /* 21px */
  --tni-leading-label:     1.25;   /* 20px */
  --tni-leading-overline:  1.34;   /* 16px */
  --tni-leading-caption:   1.34;   /* 16px */
  --tni-leading-number:    1.50;   /* 24px */
  --tni-leading-title-3-raster: 32px; /* snapped variant when on the 4px grid */

  /* weights — the complete available set */
  --tni-weight-regular:  400;
  --tni-weight-medium:   500;
  --tni-weight-semibold: 600;

  /* tracking */
  --tni-tracking-display-1: -0.025em;
  --tni-tracking-display-2: -0.020em;
  --tni-tracking-title-1:   -0.020em;
  --tni-tracking-title-2:   -0.015em;
  --tni-tracking-title-3:   -0.010em;
  --tni-tracking-title-4:   -0.005em;
  --tni-tracking-lead:       0em;
  --tni-tracking-body:       0em;
  --tni-tracking-body-sm:    0em;
  --tni-tracking-label:      0.010em;
  --tni-tracking-overline:   0.120em;
  --tni-tracking-caption:    0.010em;
  --tni-tracking-number:     0em;
  --tni-tracking-marker:     0.020em;

  /* German typographic defaults.
     Hyphenation is split by ROLE, not applied blanket-wide.
       display — large, short, art-directed headlines (display-1/2, title-1);
                 a breaking hyphen reads as a typesetting error, so: none.
       title   — anything that can sit in a card, column or sidebar
                 (title-2/3/4): German compounds exceed the narrow measure
                 and MUST be allowed to break, so: auto.
     Both require lang="de" on <html> (see brand/typography.md §4); the
     constrained role also carries overflow-wrap: break-word as a safety net
     for un-hyphenatable tokens (product names, URLs). */
  --tni-hyphens-body:    auto;
  --tni-hyphens-title:   auto;
  --tni-hyphens-display: none;
  --tni-q-open: "\201E";    /* „ */
  --tni-q-close: "\201C";   /* " */
}

/* ---------------------------------------------------------------------------
   2. MEASURES — German words are longer than English ones; a 65ch English
   measure carries ~12-14 words, the German equivalent only 8-11.
   ------------------------------------------------------------------------ */
:root {
  --tni-measure-body:    65ch;  /* single-column prose, 55-70 chars/line */
  --tni-measure-lead:    55ch;
  --tni-measure-card:    48ch;  /* multi-column grid, 38-48 chars/line */
  --tni-measure-caption: 50ch;
  --tni-measure-min:     35ch;  /* below this, do not set prose */
}


/* ---------------------------------------------------------------------------
   3. GRID, SPACING, RADII
   Base unit 4px (--tni-space-unit, from tokens.css). Only these steps.
   ------------------------------------------------------------------------ */
:root {
  --tni-space-3xs: var(--tni-space-unit);                              /* 4px   */
  --tni-space-2xs: calc(var(--tni-space-unit) * 2);                    /* 8px   */
  --tni-space-xs:  calc(var(--tni-space-unit) * 3);                    /* 12px  */
  --tni-space-sm:  calc(var(--tni-space-unit) * 4);                    /* 16px  */
  --tni-space-md:  calc(var(--tni-space-unit) * 6);                    /* 24px  */
  --tni-space-lg:  calc(var(--tni-space-unit) * 8);                    /* 32px  */
  --tni-space-xl:  calc(var(--tni-space-unit) * 12);                   /* 48px  */
  --tni-space-2xl: calc(var(--tni-space-unit) * 16);                   /* 64px  */
  --tni-space-3xl: calc(var(--tni-space-unit) * 24);                   /* 96px  */
  --tni-space-4xl: calc(var(--tni-space-unit) * 32);                   /* 128px */

  --tni-grid-columns: 12;
  --tni-grid-gutter: var(--tni-space-md);   /* 24px */
  --tni-grid-margin: var(--tni-space-md);   /* 24px, mobile  */
  --tni-grid-max: 1440px;                  /* entschieden 2026-10-03: breite Displays */

  --tni-radius-sm: 0px;    /* scharfes Kantensystem, Kundenentscheid 2026-10-03 */
  --tni-radius-md: 0px;    /* Oberflächen, Karten, Panels, Buttons: rechteckig */
  --tni-radius-lg: 0px;    /* echo der quadratischen Rasterverlauf-Module */
  --tni-radius-full: 0px;  /* auch Chips/Tags/Glyphen: keine Pill-Form mehr */

  --tni-target-min: 24px;   /* WCAG 2.2 SC 2.5.8 */
  --tni-target-comfort: 44px;
}
@media (min-width: 640px)  { :root { --tni-grid-margin: var(--tni-space-2xl); } }
@media (min-width: 1024px) { :root { --tni-grid-margin: var(--tni-space-2xl); } }


/* ---------------------------------------------------------------------------
   4. COLOUR RAMPS
   Derived in OKLCh: hue pinned per family, lightness followed as a fixed
   ladder, chroma under a gamut-clamped envelope. Inherited steps are consumed
   from tokens.css so there is exactly one source of truth for them.
   Full derivation: brand/color-system.md §1.
   ------------------------------------------------------------------------ */
:root {
  /* accent — chartreuse/olive family, H = 109.33deg (accent-900: 127.09deg) */
  --tni-accent-50:  #F7F8E9;                      /* L 97.50  C 0.0200 */
  --tni-accent-100: #F0F1D8;                      /* L 95.00  C 0.0320 */
  --tni-accent-200: #E3E5BB;                      /* L 91.00  C 0.0550 */
  --tni-accent-300: #CCCD7F;                      /* L 83.00  C 0.1000 */
  --tni-accent-400: var(--tni-chartreuse-light);  /* #B0AF00  L 73.07 — inherited */
  --tni-accent-500: var(--tni-chartreuse);        /* #A6A500  L 69.97 — inherited */
  --tni-accent-600: #8E8D04;                      /* L 62.50  C 0.1350 — graphic only */
  --tni-accent-700: var(--tni-chartreuse-dark);   /* #797802  L 55.53 — inherited */
  --tni-accent-800: var(--tni-accent-text);       /* #5F5E00  L 46.75 — canonical, tokens.css */
  --tni-accent-900: var(--tni-olive-deep);        /* #3C4C24  L 39.21 — inherited */

  /* neutral — hue drifts 106.60deg (cream) to 124.06deg (charcoal), inherited */
  --tni-neutral-50:  var(--tni-white);            /* #FFFFFF  L 100.00 — inherited */
  --tni-neutral-100: var(--tni-cream);            /* #F5F5ED  L  96.80 — inherited */
  --tni-neutral-200: #DEDFD6;                     /* L 90.00  C 0.0120 */
  --tni-neutral-300: var(--tni-stone);            /* #B8B7AF  L 77.79 — inherited */
  --tni-neutral-400: #959690;                     /* L 67.00  C 0.0080 */
  --tni-neutral-500: #747571;                     /* L 56.00  C 0.0060 */
  --tni-neutral-600: #5F5F5D;                     /* L 48.50  C 0.0040 */
  --tni-neutral-700: var(--tni-graphite);         /* #4C4C4C  L 41.65 — inherited */
  --tni-neutral-800: #393B36;                     /* L 35.00  C 0.0100 */
  --tni-neutral-900: var(--tni-charcoal);         /* #2A2D25  L 29.14 — inherited */

  /* extension below the 50-900 ladder (same method, L 22.00) */
  --tni-neutral-below-900: #191C15;
}


/* ---------------------------------------------------------------------------
   5. SEMANTIC TOKENS — LIGHT (default)
   Distinct names from tokens.css on purpose: tokens.css owns the fixed light
   contract (--tni-surface, --tni-text, …), this layer owns the THEMEABLE
   contract. Light values point at tokens.css wherever a value is inherited.
   ------------------------------------------------------------------------ */
:root {
  /* surfaces */
  --tni-bg:                 var(--tni-neutral-100);  /* #F5F5ED  cream, page   */
  --tni-bg-raised:          var(--tni-neutral-50);   /* #FFFFFF  cards, nav    */
  --tni-bg-sunken:          var(--tni-neutral-200);  /* #DEDFD6  inset, thead  */
  --tni-bg-inverse:         var(--tni-neutral-900);  /* #2A2D25  dark section  */
  --tni-bg-accent-subtle:   var(--tni-accent-50);    /* #F7F8E9 */
  --tni-bg-accent-soft:     var(--tni-accent-100);   /* #F0F1D8  badge, tag    */
  --tni-bg-accent-mid:      var(--tni-accent-200);   /* #E3E5BB  selected row  */
  --tni-bg-accent-chip:     var(--tni-accent-300);   /* #CCCD7F  chip          */
  --tni-bg-accent-solid:    var(--tni-accent-500);   /* #A6A500  accent button */
  --tni-bg-accent-solid-hover: var(--tni-accent-400);/* #B0AF00  LIGHTER       */
  --tni-bg-accent-solid-press: var(--tni-accent-300);/* #CCCD7F  LIGHTER still */
  --tni-bg-brand-deep:      var(--tni-accent-900);   /* #3C4C24  brand panel   */

  /* text — every value below is AA on cream unless marked */
  --tni-fg:                 var(--tni-neutral-900);  /* #2A2D25  12.77:1 */
  --tni-fg-muted:           var(--tni-neutral-700);  /* #4C4C4C   7.84:1 */
  --tni-fg-subtle:          var(--tni-neutral-600);  /* #5F5F5D   5.84:1 */
  --tni-fg-disabled:        var(--tni-neutral-500);  /* #747571   4.24:1 — exempt (1.4.3) */
  --tni-fg-inverse:         var(--tni-neutral-50);   /* #FFFFFF  14.00:1 on charcoal */
  --tni-fg-inverse-muted:   var(--tni-neutral-200);  /* #DEDFD6  10.42:1 on charcoal */
  --tni-fg-inverse-subtle:  var(--tni-neutral-300);  /* #B8B7AF   6.95:1 on charcoal */

  /* accent roles
     --tni-accent-text is OWNED BY tokens.css (canonical #5F5E00). It is consumed
     here and never re-declared: it is by definition the light-surface-safe accent.
     The themeable ROLE token for applications is --tni-fg-accent. */
  --tni-fg-accent:          var(--tni-accent-text);  /* links + accent numerals    */
  --tni-accent-graphic:     var(--tni-accent-500);   /* #A6A500 — GRAPHIC ONLY on light (2.39:1) */
  --tni-accent-strong:      var(--tni-accent-700);   /* #797802   4.26:1 — large text only */
  --tni-brand-deep:         var(--tni-accent-900);   /* #3C4C24 */
  --tni-fg-on-accent:       var(--tni-neutral-900);  /* charcoal on #A6A500 = 5.33:1 */

  /* lines — two classes, do not mix */
  --tni-line:               var(--tni-neutral-300);  /* 1.84:1 DECORATIVE ONLY */
  --tni-line-subtle:        var(--tni-neutral-200);  /* 1.23:1 DECORATIVE ONLY */
  --tni-line-strong:        var(--tni-neutral-500);  /* 4.24:1 control borders */

  /* focus — 2px ring + 2px halo of surface colour */
  --tni-focus-ring:         var(--tni-accent-800);   /* #5F5E00 6.21:1 on cream */
  --tni-focus-halo:         var(--tni-neutral-100);
  --tni-focus-ring-width:   2px;
  --tni-focus-ring-offset:  2px;
  --tni-focus-ring-on-accent: var(--tni-neutral-900); /* on #A6A500: 5.33:1; #5F5E00 there is only 2.59:1 */

  /* disabled surfaces */
  --tni-bg-disabled:        var(--tni-neutral-200);
  --tni-line-disabled:      var(--tni-neutral-300);

  /* Elevation — minimaler Lift für scharfkantige Flächen (Kundenentscheid 2026-10-04):
     ein Kontaktschatten + ein weicher Umgebungsschatten; die Hairline bleibt Trennung 1. */
  --tni-elevation: 0 1px 2px rgb(42 45 37 / 0.06), 0 12px 32px -16px rgb(42 45 37 / 0.18);
}


/* ---------------------------------------------------------------------------
   6. SEMANTIC TOKENS — DARK
   Only this layer flips. The ramps never change. The accent TEXT token swaps
   family by direction rule: light surfaces -> accent-800, dark -> accent-500.
   ------------------------------------------------------------------------ */
[data-tni-theme="dark"] {
  --tni-bg:                 var(--tni-neutral-900);  /* #2A2D25 */
  --tni-bg-raised:          var(--tni-neutral-800);  /* #393B36 */
  --tni-bg-sunken:          var(--tni-neutral-below-900); /* #191C15 */
  --tni-bg-inverse:         var(--tni-neutral-100);  /* inverted block */
  --tni-bg-accent-subtle:   #20251A;                 /* L 25.50 C 0.0200, cream 14.29:1 */
  --tni-bg-accent-soft:     var(--tni-accent-900);   /* #3C4C24, cream  8.51:1 */
  --tni-bg-accent-mid:      var(--tni-accent-800);   /* #5F5E00, cream  6.21:1 */
  --tni-bg-accent-chip:     var(--tni-accent-300);   /* #CCCD7F, charcoal 8.40:1 */
  --tni-bg-accent-solid:    var(--tni-accent-500);   /* #A6A500 */
  --tni-bg-accent-solid-hover: var(--tni-accent-400);
  --tni-bg-accent-solid-press: var(--tni-accent-300);
  --tni-bg-brand-deep:      var(--tni-accent-900);
  --tni-elevation: 0 1px 2px rgb(0 0 0 / 0.45), 0 12px 32px -16px rgb(0 0 0 / 0.60);

  --tni-fg:                 var(--tni-neutral-100);  /* #F5F5ED  12.77:1 */
  --tni-fg-muted:           var(--tni-neutral-300);  /* #B8B7AF   6.93:1 */
  --tni-fg-subtle:          var(--tni-neutral-400);  /* #959690   4.69:1 */
  --tni-fg-disabled:        var(--tni-neutral-500);  /* #747571   3.02:1 — exempt */
  --tni-fg-inverse:         var(--tni-neutral-900);
  --tni-fg-inverse-muted:   var(--tni-neutral-700);
  --tni-fg-inverse-subtle:  var(--tni-neutral-600);

  /* DIRECTION RULE (documented in tokens.css). The light-safe #5F5E00 measures only
     2.06:1 here, so the accent-text ROLE repoints to the chartreuse. The canonical
     --tni-accent-text token itself is left untouched. */
  --tni-fg-accent:          var(--tni-accent-500);   /* #A6A500   5.33:1 */
  --tni-accent-graphic:     var(--tni-accent-500);
  --tni-accent-strong:      var(--tni-accent-400);   /* #B0AF00   5.98:1 */
  --tni-fg-on-accent:       var(--tni-neutral-900);

  --tni-line:               var(--tni-neutral-800);
  --tni-line-subtle:        #31322F;                 /* L 31.50 C 0.0060 */
  --tni-line-strong:        var(--tni-neutral-400);  /* 4.69:1 */

  --tni-focus-ring:         var(--tni-accent-400);   /* #B0AF00 5.98:1, min 4.85:1 */
  --tni-focus-halo:         var(--tni-neutral-900);
  --tni-focus-ring-on-accent: var(--tni-neutral-900);

  --tni-bg-disabled:        var(--tni-neutral-800);
  --tni-line-disabled:      var(--tni-neutral-700);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-tni-theme="light"]) {
    --tni-bg:                 var(--tni-neutral-900);
    --tni-bg-raised:          var(--tni-neutral-800);
    --tni-bg-sunken:          var(--tni-neutral-below-900);
    --tni-bg-inverse:         var(--tni-neutral-100);
    --tni-bg-accent-subtle:   #20251A;
    --tni-bg-accent-soft:     var(--tni-accent-900);
    --tni-bg-accent-mid:      var(--tni-accent-800);
    --tni-bg-accent-chip:     var(--tni-accent-300);
    --tni-bg-brand-deep:      var(--tni-accent-900);
    --tni-elevation: 0 1px 2px rgb(0 0 0 / 0.45), 0 12px 32px -16px rgb(0 0 0 / 0.60);
    --tni-bg-accent-solid:    var(--tni-accent-500);
    --tni-bg-accent-solid-hover: var(--tni-accent-400);
    --tni-bg-accent-solid-press: var(--tni-accent-300);

    --tni-fg:                 var(--tni-neutral-100);
    --tni-fg-muted:           var(--tni-neutral-300);
    --tni-fg-subtle:          var(--tni-neutral-400);
    --tni-fg-disabled:        var(--tni-neutral-500);
    --tni-fg-inverse:         var(--tni-neutral-900);
    --tni-fg-inverse-muted:   var(--tni-neutral-700);
    --tni-fg-inverse-subtle:  var(--tni-neutral-600);

    --tni-fg-accent:          var(--tni-accent-500);
    --tni-accent-strong:      var(--tni-accent-400);

    --tni-line:               var(--tni-neutral-800);
    --tni-line-subtle:        #2F3230;
    --tni-line-strong:        var(--tni-neutral-400);

    --tni-focus-ring:         var(--tni-accent-400);
    --tni-focus-halo:         var(--tni-neutral-900);

    --tni-bg-disabled:        var(--tni-neutral-800);
    --tni-line-disabled:      var(--tni-neutral-700);
  }
}


/* ---------------------------------------------------------------------------
   7. ROLE CLASSES
   Thin wrappers so the scale is used, not re-invented. They set metrics only;
   colour comes from the semantic tokens.

   Wiring the theme is EXPLICIT and opt-in: put .tni-theme on the root element
   of the application (or on any subtree that should carry its own surface).
   No global body reset is imposed, so the website layer keeps control of layout.
   ------------------------------------------------------------------------ */
.tni-theme {
  background-color: var(--tni-bg);
  color: var(--tni-fg);
}

.tni-display-1, .tni-display-2,
.tni-title-1, .tni-title-2, .tni-title-3, .tni-title-4 {
  font-family: var(--tni-font-sans);
  font-synthesis: none;              /* no faux bold, no faux oblique */
  text-wrap: balance;
  margin-block: 0;
}

/* Art-directed headlines: large and short, never broken. */
.tni-display-1, .tni-display-2, .tni-title-1 {
  hyphens: var(--tni-hyphens-display);
}

/* Titles in constrained measures (cards, columns, sidebars). German
   compounds ("Prozessautomatisierung", "Datensouveränität") exceed a
   3-column card, so they MUST be allowed to hyphenate; overflow-wrap is
   the last-resort safety net for tokens that cannot hyphenate at all
   (product names, URLs). Both need lang="de" on <html>. */
.tni-title-2, .tni-title-3, .tni-title-4 {
  hyphens: var(--tni-hyphens-title);
  overflow-wrap: break-word;
}

.tni-display-1 {
  font-size: var(--tni-font-size-display-1);
  line-height: var(--tni-leading-display-1);
  font-weight: var(--tni-weight-semibold);
  letter-spacing: var(--tni-tracking-display-1);
}
.tni-display-2 {
  font-size: var(--tni-font-size-display-2);
  line-height: var(--tni-leading-display-2);
  font-weight: var(--tni-weight-semibold);
  letter-spacing: var(--tni-tracking-display-2);
}
.tni-title-1 {
  font-size: var(--tni-font-size-title-1);
  line-height: var(--tni-leading-title-1);
  font-weight: var(--tni-weight-semibold);
  letter-spacing: var(--tni-tracking-title-1);
}
.tni-title-2 {
  font-size: var(--tni-font-size-title-2);
  line-height: var(--tni-leading-title-2);
  font-weight: var(--tni-weight-semibold);
  letter-spacing: var(--tni-tracking-title-2);
}
.tni-title-3 {
  font-size: var(--tni-font-size-title-3);
  line-height: var(--tni-leading-title-3);
  font-weight: var(--tni-weight-semibold);
  letter-spacing: var(--tni-tracking-title-3);
}
.tni-title-3--raster { line-height: var(--tni-leading-title-3-raster); }
.tni-title-4 {
  font-size: var(--tni-font-size-title-4);
  line-height: var(--tni-leading-title-4);
  font-weight: var(--tni-weight-semibold);
  letter-spacing: var(--tni-tracking-title-4);
}

.tni-lead,
.tni-body,
.tni-body-sm {
  font-family: var(--tni-font-sans);
  font-synthesis: none;
  hyphens: var(--tni-hyphens-body);
  overflow-wrap: break-word;
  text-wrap: pretty;
  margin-block: 0;
}
.tni-lead    { font-size: var(--tni-font-size-lead);    line-height: var(--tni-leading-lead);    font-weight: var(--tni-weight-regular); letter-spacing: var(--tni-tracking-lead);    max-width: var(--tni-measure-lead); }
.tni-body    { font-size: var(--tni-font-size-body);    line-height: var(--tni-leading-body);    font-weight: var(--tni-weight-regular); letter-spacing: var(--tni-tracking-body);    max-width: var(--tni-measure-body); }
.tni-body-sm { font-size: var(--tni-font-size-body-sm); line-height: var(--tni-leading-body-sm); font-weight: var(--tni-weight-regular); letter-spacing: var(--tni-tracking-body-sm); max-width: var(--tni-measure-body); }

.tni-label {
  font-family: var(--tni-font-sans);
  font-synthesis: none;
  font-size: var(--tni-font-size-label);
  line-height: var(--tni-leading-label);
  font-weight: var(--tni-weight-medium);
  letter-spacing: var(--tni-tracking-label);
}

.tni-overline {
  font-family: var(--tni-font-sans);
  font-synthesis: none;
  font-size: var(--tni-font-size-overline);
  line-height: var(--tni-leading-overline);
  font-weight: var(--tni-weight-medium);
  letter-spacing: var(--tni-tracking-overline);
  text-transform: uppercase;   /* never .capitalize: breaks German compounds */
  hyphens: none;
}

.tni-caption {
  font-family: var(--tni-font-sans);
  font-synthesis: none;
  font-size: var(--tni-font-size-caption);
  line-height: var(--tni-leading-caption);
  font-weight: var(--tni-weight-regular);
  letter-spacing: var(--tni-tracking-caption);
  max-width: var(--tni-measure-caption);
  hyphens: none;
}

.tni-number {
  font-family: var(--tni-font-sans);
  font-synthesis: none;
  font-size: var(--tni-font-size-number);
  line-height: var(--tni-leading-number);
  font-weight: var(--tni-weight-medium);
  letter-spacing: var(--tni-tracking-number);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
/* documented dense-table pairing, not a new step */
.tni-number--dense {
  font-size: var(--tni-font-size-body-sm);
  line-height: var(--tni-leading-body-sm);
}

/* Link: colour alone does NOT identify it — #5F5E00 measures only 2.06:1
   against #2A2D25 body text. The underline is mandatory (WCAG 1.4.1). */
.tni-link {
  color: var(--tni-fg-accent);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}
.tni-link:hover  { text-decoration-thickness: 2px; }
.tni-link:focus-visible {
  outline: var(--tni-focus-ring-width) solid var(--tni-focus-ring);
  outline-offset: var(--tni-focus-ring-offset);
  border-radius: var(--tni-radius-sm);
}

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: var(--tni-focus-ring-width) solid var(--tni-focus-ring);
  outline-offset: var(--tni-focus-ring-offset);
}
/* On a solid accent fill the accent ring disappears (2.59:1 on #A6A500),
   so the ring switches to charcoal. */
.tni-on-accent :where(a, button, [tabindex]):focus-visible,
.tni-button-accent:focus-visible {
  outline-color: var(--tni-focus-ring-on-accent);
}

/* -- buttons ------------------------------------------------------------- */
.tni-button {
  font-family: var(--tni-font-sans);
  font-synthesis: none;
  font-size: var(--tni-font-size-label);
  line-height: var(--tni-leading-label);
  font-weight: var(--tni-weight-medium);
  letter-spacing: var(--tni-tracking-label);
  border: 1px solid transparent;
  border-radius: var(--tni-radius-md);
  box-sizing: border-box;            /* min-height is the OUTER target size (WCAG 2.5.8) */
  padding: var(--tni-space-xs) var(--tni-space-md);
  min-height: var(--tni-target-comfort);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--tni-space-2xs);
  cursor: pointer;
  text-decoration: none;
}

.tni-button-primary {                      /* charcoal is the primary fill   */
  background: var(--tni-neutral-900);      /* #2A2D25 vs #FFFFFF -> 14.00:1  */
  color: var(--tni-neutral-50);
}
.tni-button-primary:hover  { background: var(--tni-neutral-800); }  /* 11.33:1 */
.tni-button-primary:active { background: var(--tni-neutral-700); }  /*  8.59:1 */

.tni-button-accent {                       /* accent fill LIGHTENS on state  */
  background: var(--tni-bg-accent-solid);  /* #A6A500 vs #2A2D25 -> 5.33:1  */
  color: var(--tni-fg-on-accent);
}
.tni-button-accent:hover  { background: var(--tni-bg-accent-solid-hover); } /* 5.98:1 */
.tni-button-accent:active { background: var(--tni-bg-accent-solid-press); } /* 8.40:1 */

.tni-button-outline {
  background: transparent;
  border-color: var(--tni-line-strong);    /* #747571 on cream -> 4.24:1 */
  color: var(--tni-fg);
}
.tni-button-outline:hover  { background: var(--tni-bg-sunken);     border-color: var(--tni-neutral-600); }
.tni-button-outline:active { background: var(--tni-neutral-300);   border-color: var(--tni-neutral-700); }

:where(.tni-button-primary, .tni-button-accent, .tni-button-outline):disabled,
:where(.tni-button-primary, .tni-button-accent, .tni-button-outline)[aria-disabled="true"] {
  background: var(--tni-bg-disabled);
  border-color: var(--tni-line-disabled);
  color: var(--tni-fg-disabled);
  cursor: not-allowed;
}


/* -- the 01-04 numeral device ------------------------------------------- */
:root {
  /* The gutter MUST be derived from the marker's own font size. `ch` on the li
     resolves against the li's font size (16px) while the ::before resolves `ch`
     against the marker size (25px), which made the numeral overrun the text.
     Deriving both sides from --tni-marker-font-size keeps them identical. */
  --tni-marker-font-size: var(--tni-font-size-title-3);           /* 25px */
  --tni-marker-gutter: calc(var(--tni-marker-font-size) * 2.2);   /* 55px */
  --tni-marker-gap: var(--tni-space-xs);                          /* 12px */
  --tni-marker-square-size: 12px;
  --tni-marker-square-space: 0px;
}

.tni-markers {
  counter-reset: tni-marker;
  list-style: none;
  padding: 0;
  margin: 0;
}
.tni-markers > li {
  counter-increment: tni-marker;
  position: relative;
  padding-left: calc(var(--tni-marker-gutter) + var(--tni-marker-square-space) + var(--tni-marker-gap));
}
.tni-markers > li::before {
  content: counter(tni-marker, decimal-leading-zero);  /* 01, 02, … 10 */
  position: absolute;
  left: var(--tni-marker-square-space);
  top: 0;
  width: var(--tni-marker-gutter);
  text-align: right;
  font-family: var(--tni-font-sans);
  font-size: var(--tni-marker-font-size);
  line-height: 1;
  font-weight: var(--tni-weight-semibold);
  letter-spacing: var(--tni-tracking-marker);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  color: var(--tni-fg-accent);      /* #5F5E00 = 6.21:1 on cream; #A6A500 would be 2.39:1 */
}
.tni-markers > li + li { margin-top: var(--tni-space-md); }

/* larger variant for the highlighted 01-04 block */
.tni-markers--hero {
  --tni-marker-font-size: var(--tni-font-size-title-1);
  --tni-marker-gutter: calc(var(--tni-marker-font-size) * 2.2);
}

/* optional decorative mosaic module in #A6A500 — graphic, never the only
   carrier of the number */
.tni-markers--module { --tni-marker-square-space: 20px; }
.tni-markers--module > li::after {
  content: "";
  position: absolute;
  left: 0;
  top: 0.3em;
  width: var(--tni-marker-square-size);
  height: var(--tni-marker-square-size);
  background: var(--tni-accent-graphic);
}


/* ---------------------------------------------------------------------------
   8. MOTION
   Promoted from brand/imagery-motion.md §8.2/§8.3 (§8.6) — the values were
   previously prose only. Time base 20 ms; only these durations are permitted.
   Only opacity/transform are animated, and never more than one raster
   sequence per viewport (imagery-motion.md §8.1/§8.4).
   ------------------------------------------------------------------------ */
:root {
  /* durations — the six permitted steps plus the raster stagger */
  --tni-dur-instant:    80ms;   /* hover, focus, press, icon colour change */
  --tni-dur-micro:      140ms;  /* toggle, tab, tooltip, checkbox          */
  --tni-dur-base:       200ms;  /* standard transition, card, dropdown     */
  --tni-dur-enter:      260ms;  /* section content, modal in               */
  --tni-dur-page:       320ms;  /* page/hero transition, image crossfade   */
  --tni-dur-node:       600ms;  /* node pulse — real live status only      */
  --tni-stagger-modul:  40ms;   /* offset per module in raster sequences   */

  /* easing — no bounce, no overshoot, no spring, no ease-in-out default */
  --tni-ease-standard:  cubic-bezier(0.2, 0, 0, 1);
  --tni-ease-enter:     cubic-bezier(0.05, 0.7, 0.1, 1);   /* decelerate   */
  --tni-ease-exit:      cubic-bezier(0.3, 0, 1, 1);        /* accelerate   */
  --tni-ease-emphasis:  cubic-bezier(0.2, 0.9, 0.25, 1);   /* node only    */
  --tni-ease-linear:    linear;                            /* progress     */
}


/* ---------------------------------------------------------------------------
   9. PRINT — must survive one-colour output
   ------------------------------------------------------------------------ */
@media print {
  :root {
    --tni-bg: #FFFFFF;
    --tni-bg-raised: #FFFFFF;
    --tni-bg-sunken: #FFFFFF;
    --tni-fg: #2A2D25;
    --tni-fg-muted: #2A2D25;
    --tni-fg-subtle: #2A2D25;
    --tni-fg-accent: #2A2D25;
    --tni-accent-graphic: #2A2D25;
    --tni-focus-ring: #2A2D25;
    --tni-line-strong: #2A2D25;
  }
  .tni-markers > li::before { color: #2A2D25; }
  .tni-markers--module > li::after { background: #2A2D25; }
  .tni-body, .tni-body-sm, .tni-lead, .tni-caption { max-width: var(--tni-measure-body); }
}
