/* =============================================================================
 * euraki — theme.css (S20 — Corporate-Identity-Theme, K&K Software AG)
 *
 * Canonical materialisation of  docs/design/theme-tokens.md  — the 2026
 * light editorial print look: warm cream paper, near-black ink, indigo as
 * the carrying brand color, hard 1px ink rules, condensed display headlines,
 * monospaced uppercase captions, deep-indigo emphasis bands.
 *
 * DO NOT EDIT this file directly without first updating theme-tokens.md.
 * Every color, spacing, radius, and shadow used anywhere in the app MUST
 * resolve to a CSS custom property declared in the :root block below.
 * No literal color/spacing/radius value may appear in any other CSS file.
 * ============================================================================= */

/* --- Self-hosted fonts (Constitution IX: no CDNs) ----------------------------
   Barlow (UI sans), Barlow Condensed (display), JetBrains Mono (captions,
   data labels, code). All SIL-OFL, vendored under wwwroot/fonts/. */

@font-face {
    font-family: 'Barlow';
    src: url('../fonts/barlow/barlow-regular.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Barlow';
    src: url('../fonts/barlow/barlow-italic.woff2') format('woff2');
    font-weight: 400;
    font-style: italic;
    font-display: swap;
}

@font-face {
    font-family: 'Barlow';
    src: url('../fonts/barlow/barlow-medium.woff2') format('woff2');
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Barlow';
    src: url('../fonts/barlow/barlow-mediumitalic.woff2') format('woff2');
    font-weight: 500;
    font-style: italic;
    font-display: swap;
}

@font-face {
    font-family: 'Barlow';
    src: url('../fonts/barlow/barlow-bold.woff2') format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Barlow';
    src: url('../fonts/barlow/barlow-extrabold.woff2') format('woff2');
    font-weight: 800;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Barlow';
    src: url('../fonts/barlow/barlow-extrabolditalic.woff2') format('woff2');
    font-weight: 800;
    font-style: italic;
    font-display: swap;
}

@font-face {
    font-family: 'Barlow Condensed';
    src: url('../fonts/barlow-condensed/barlow-condensed-bold.woff2') format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Barlow Condensed';
    src: url('../fonts/barlow-condensed/barlow-condensed-extrabold.woff2') format('woff2');
    font-weight: 800;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Barlow Condensed';
    src: url('../fonts/barlow-condensed/barlow-condensed-extrabolditalic.woff2') format('woff2');
    font-weight: 800;
    font-style: italic;
    font-display: swap;
}

@font-face {
    font-family: 'JetBrains Mono';
    src: url('../fonts/jetbrains-mono/jetbrains-mono-regular.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'JetBrains Mono';
    src: url('../fonts/jetbrains-mono/jetbrains-mono-bold.woff2') format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

/* --- Design tokens (contracts/design-tokens.md §1 — normative) ---------------- */

:root {
    /* --- Brand palette (manual: 4 primary + 4 accent) ------------------ */
    --brand-indigo:        #001478;
    --brand-lila:          #AA5AFF;
    --brand-tuerkis:       #69F5C8;
    --brand-blau:          #0AAEFE;
    --brand-tuerkis-hell:  #A0FFDC;
    --brand-tuerkis-dunkel:#00E1B9;
    --brand-orange:        #FF6600;
    --brand-gelb:          #E6FF00;

    /* --- Grounds (paper world + night tones) --------------------------- */
    --paper:      #f4f1ea;   /* page ground                                */
    --paper-deep: #ebe5d6;   /* recessed fields, alt rows, inline-code bg  */
    --paper-card: #fffcf3;   /* print-box / card surface                   */
    --ink:        #0a0a14;   /* body text, rules                           */
    --night:      #050a18;   /* dark emphasis only (FR-001)                */
    --night-card: #0a1128;   /* code-slab ground (dark emphasis element)   */

    /* --- Ink alpha steps (the ONLY translucency, folded into tokens) --- */
    --ink-70:  rgba(10, 10, 20, 0.7);    /* secondary text                 */
    --ink-60:  rgba(10, 10, 20, 0.6);    /* muted captions — 0.55 fails
                                            WCAG AA at 4.35:1 on
                                            --paper-card; 0.6 measures
                                            5.18 card / 5.02 paper /
                                            4.85 deep (P16)               */
    --ink-40:  rgba(10, 10, 20, 0.4);    /* hairline on paper              */
    --ink-15:  rgba(10, 10, 20, 0.15);   /* faint grid/dividers            */
    --light-80: rgba(255, 252, 243, 0.8);  /* secondary text on bands      */
    --light-25: rgba(255, 252, 243, 0.25); /* hairline on bands            */

    /* --- Text semantics ------------------------------------------------ */
    --text-primary:   var(--ink);
    --text-secondary: var(--ink-70);
    --text-muted:     var(--ink-60);
    --text-on-band:   var(--paper-card);  /* text on indigo bands / night slabs */

    /* --- Surface semantics ---------------------------------------------- */
    --bg-page:    var(--paper);
    --bg-input:   var(--paper-card);
    --bg-overlay: rgba(10, 10, 20, 0.55);          /* modal scrim          */
    --band-bg:    var(--brand-indigo);              /* emphasis bands       */
    --rule-strong:   var(--ink);                    /* 1px print-box frame  */
    --rule-hairline: var(--ink-40);
    --rule-faint:    var(--ink-15);

    /* --- Feedback semantics (orange = signal channel, FR-011) -----------
       --color-error is a DERIVED darkened signal orange. The manual's
       verbatim brand orange measures 2.60:1 on --paper, below the
       SC-004 P9 threshold of 3.0:1, so the derived mix is what carries
       the error signal on FILLS, FRAMES, OUTLINES and the dark code
       slab (3.45:1 on paper, 4.80:1 on the slab). Grounds/borders keep
       the verbatim brand orange via --color-warning(-bg/-border).
       Recorded deviation from contract §1; see
       docs/design/theme-tokens.md § Signal colors.

       For the orange signal as TEXT, do NOT reach for --color-error —
       it does not clear AA body text. Use --color-signal-text below. */
    --color-success:        var(--brand-tuerkis-dunkel);
    --color-success-bg:     rgba(0, 225, 185, 0.14);
    --color-success-border: var(--brand-tuerkis-dunkel);
    --color-warning:        var(--brand-orange);
    --color-warning-bg:     rgba(255, 102, 0, 0.10);
    --color-warning-border: var(--brand-orange);
    --color-info:           var(--brand-indigo);
    --color-info-bg:        rgba(0, 20, 120, 0.08);
    --color-info-border:    var(--brand-indigo);
    --color-error:          color-mix(in srgb, var(--brand-orange) 85%, var(--ink));

    /* Text-safe partner of the orange signal channel.
       NEITHER --color-warning (2.34:1 on --paper-deep) NOR --color-error
       (3.10:1) clears the AA body-text bar of 4.5:1 on the paper grounds,
       and --color-error cannot simply be darkened to fix that: it is also
       the danger-button FILL (ink on it needs >=80% orange) and
       --syntax-deleted on the dark code slab (needs >=78%), whereas body
       text needs <=66%. Those windows are disjoint, so the text role gets
       its own value rather than a compromise that fails all three.
       Measures 5.62:1 on --paper-card, 5.11 on --paper, 4.59 on
       --paper-deep, 5.04 on the warning tint.

       Use it wherever the orange signal must carry TEXT on a paper
       ground. On a signal TINT prefer ink instead (P17/FR-016) so the
       tint carries the channel and the frame carries the signal — see
       .brand-pill--danger and .api-access__panel-error. */
    --color-signal-text:    color-mix(in srgb, var(--brand-orange) 66%, var(--ink));

    /* --- Elevated/impersonation state (R9 — gelb caution-tape) ---------- */
    --elevated-bg:     var(--brand-gelb);
    --elevated-ink:    var(--ink);
    --elevated-border: var(--ink);

    /* --- Chat / rendered-content tokens (S16 + S17 renamed, R2/R6) ------ */
    --chat-unread-dot: var(--brand-indigo);
    --code-bg:     var(--night-card);     /* dark emphasis slab            */
    --code-border: var(--ink);
    --code-text:   #f0f0f8;               /* light code ink on night-card  */
    --inline-code-bg:     var(--paper-deep);
    --inline-code-border: var(--ink-40);
    --inline-code-text:   var(--ink);
    --table-border:       var(--ink-40);
    --table-header-bg:    var(--paper-card);
    --table-header-text:  var(--brand-indigo);
    --table-row-alt-bg:   var(--paper-deep);
    --blockquote-accent:  var(--brand-indigo);
    --blockquote-bg:      var(--paper-deep);
    --code-copy-success:  var(--brand-tuerkis);

    /* Syntax hues — read on --code-bg (dark), S17 mapping preserved */
    --syntax-comment:     var(--light-80);
    --syntax-keyword:     var(--brand-lila);
    --syntax-string:      var(--brand-tuerkis);
    --syntax-number:      var(--brand-orange);
    --syntax-function:    var(--brand-blau);
    --syntax-operator:    var(--brand-tuerkis-hell);
    --syntax-punctuation: var(--light-80);
    --syntax-class-name:  var(--brand-tuerkis-dunkel);
    --syntax-tag:         var(--brand-lila);
    --syntax-attr-name:   var(--brand-blau);
    --syntax-attr-value:  var(--brand-tuerkis);
    --syntax-regex:       var(--brand-gelb);
    --syntax-variable:    var(--brand-tuerkis-hell);
    --syntax-deleted:     var(--color-error);
    --syntax-inserted:    var(--brand-tuerkis);

    /* --- Status page (S22 — five states + "Keine Daten", D13/R17) -------
       Severity is carried on TWO independent channels, because the brand
       owns exactly ONE alarm hue (orange) and three severity steps cannot
       be told apart by that hue alone. The shipped colour-only ramp
       separated "Beeinträchtigte Leistung" from "Teilausfall" by just
       1.33:1 — on a page whose whole job is telling states apart.

       Channel 1 — luminance. The orange ramp is spread as far as it will
       go: flat brand orange → 72 % orange over ink → 35 % orange over ink.
       A three-step ramp between the brightest orange the cream ground
       tolerates and pure ink tops out at ~2.6:1 per step, so colour alone
       cannot reach 3:1 here at any value. That ceiling is why channel 2
       exists rather than being a nice-to-have.

       Channel 2 — a horizontal band texture whose WEIGHT escalates with
       severity: flat (betriebsbereit) → light → medium → heavy. Read it
       as "flat means nothing is wrong, and the heavier the ruling the
       worse it is". Bands run ACROSS the segment, so they survive the
       3 px segment width of a 320 px viewport, where a 45° hatch would
       dissolve into a flat tint. Texture also survives greyscale and
       colour-vision deficiency, which a re-hue would not, and follows
       the in-house precedent set by the dashed "Keine Daten" hairline.

       "Beeinträchtigte Leistung" is banded too, even though the reported
       defect was only degraded↔partial: türkis and orange collapse to
       1.20:1 under deuteranopia, so without a texture the two MOST
       common states had no reliable channel between them at all. Banding
       it costs 0.35 of the degraded↔partial ratio and buys a second
       channel on every adjacent severity pair.

       Area-averaged adjacent separation after the change (standard
       vision / deuteranopia):
         operational↔degraded  2.03:1 / 1.40:1  (was 1.74 / 1.20)
         degraded↔partial      2.11:1 / 2.06:1  (was 1.33 / 1.31)
         partial↔major         2.31:1 / 2.24:1  (was 1.69 / 1.65)
         maintenance↔nodata    1.12:1           (unchanged — the dashed
                                                 hairline is its channel)
       Full matrix in specs/022-status-page/contracts/status-view.md §4.
       Segments carry NO text, so these pairings introduce no AA text
       requirement.

       --status-maintenance reuses the gelb caution-tape ground; "Keine
       Daten" is the recessed paper field with a dashed hairline border +
       muted ink. Status.razor.css references ONLY these tokens
       (Principle V). */
    --status-operational:  var(--color-success);
    --status-degraded:     var(--color-warning);
    --status-partial:      color-mix(in srgb, var(--brand-orange) 72%, var(--ink));
    --status-major:        color-mix(in srgb, var(--brand-orange) 35%, var(--ink));
    --status-maintenance:  var(--elevated-bg);
    --status-nodata:        var(--paper-deep);
    --status-nodata-border: var(--rule-hairline);
    --status-nodata-ink:    var(--text-muted);

    /* Channel 2 — the band textures. Hard colour stops only (each stop
       pair shares a position), so nothing is interpolated towards
       `transparent` and no grey fringing can appear. Periods are 6/5/4 px:
       fine enough to show at least two full bands inside the 16 px legend
       swatch, coarse enough to stay legible in a 32 px-tall segment.
       Ruled weight is 1 → 2 → 3 px, i.e. 17 % → 40 % → 75 % coverage. */
    --status-band-degraded:
        repeating-linear-gradient(180deg,
            var(--ink) 0 1px, transparent 1px 6px);
    --status-band-partial:
        repeating-linear-gradient(180deg,
            var(--ink) 0 2px, transparent 2px 5px);
    --status-band-major:
        repeating-linear-gradient(180deg,
            var(--ink) 0 3px, transparent 3px 4px);

    /* --- Typography ------------------------------------------------------ */
    --font-sans:    'Barlow', system-ui, sans-serif;
    --font-display: 'Barlow Condensed', 'Barlow', sans-serif;
    --font-mono:    'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo,
                    Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
    /* Scale: base 16 / ratio 1.333 (manual §03) */
    --text-display: clamp(2.75rem, 7vw, 4.5rem);  /* ≈72px hero display    */
    --text-h1:      clamp(2.25rem, 5vw, 3rem);    /* 48px section          */
    --text-h2:      2rem;                          /* 32px sub             */
    --text-h3:      1.375rem;                      /* 22px lead            */
    --text-body:    1rem;                          /* 16px                 */
    --text-caption: 0.75rem;                       /* 12px mono captions   */

    /* --- Spacing (unchanged 4px scale) ----------------------------------- */
    --space-0: 0; --space-1: 0.25rem; --space-2: 0.5rem; --space-3: 0.75rem;
    --space-4: 1rem; --space-5: 1.5rem; --space-6: 2rem; --space-7: 2.25rem;
    --space-8: 2.5rem; --space-10: 3rem; --space-12: 4rem; --space-16: 5rem;
    --space-sm: var(--space-2); --space-md: var(--space-4);

    /* --- Radii (FR-004: square boxes, small-radius accents) -------------- */
    --radius-box: 0;
    --radius-stamp: 2px;
    --radius-sticker: 4px;
    --radius-pill: 999px;   /* chips ONLY — content boxes are square */

    /* --- Shadows (print-tactile; glow family retired) --------------------- */
    --shadow-sticker: 2px 3px 0 rgba(0, 0, 0, 0.15);
    --shadow-tape:    0 2px 6px rgba(0, 0, 0, 0.12);
    --shadow-md:      0 12px 32px rgba(0, 0, 0, 0.25);
    --shadow-focus-ring: 0 0 0 3px rgba(0, 20, 120, 0.35); /* indigo ring */

    /* --- Motion (manual §05; FR-014) -------------------------------------- */
    --motion-micro: 120ms;  /* hover · press        */
    --motion-snap:  220ms;  /* toggle · tab         */
    --motion-move:  400ms;  /* page · modal         */
    --motion-hero:  600ms;  /* reveal · story       */
    --motion-stage: 1000ms; /* onboarding           */
    --ease-out-soft: cubic-bezier(0.2, 0.8, 0.2, 1);
    --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);

    /* --- Layout / z (unchanged) ------------------------------------------- */
    --layout-max-width: 1600px;
    --layout-max-width-wide: 1880px;
    --z-modal: 1000;
}

/* --- Base reset --------------------------------------------------------------- */

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

html,
body {
    margin: 0;
    padding: 0;
    /* Establish a full-height root so the chat workspace can claim the
       viewport without page-level scrolling. Safe globally: no overflow
       constraint here, so every non-chat page keeps normal document flow. */
    height: 100%;
}

body {
    background: var(--bg-page);
    color: var(--text-primary);
    font-family: var(--font-sans);
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

/* --- Chat workspace: full-viewport, no page scroll ---------------------------
   The /chat route renders <main class="app-main … app-main--chat">. We scope
   the bounded-height model to THAT modifier via :has() so the rest of the app
   (incl. admin FullWidth pages) keeps ordinary document scrolling.

   Height chain (page never scrolls; the conversation scrolls internally):
     body:has(.app-main--chat)  → 100dvh, overflow:hidden, flex column
       .app-main--chat          → flex:1, min-height:0, overflow:hidden
         .chat-shell            → height:100%, min-height:0
           .chat-panel          → min-height:0, flex column
             .chat-message-list → flex:1, min-height:0, overflow-y:auto
   The header (auto) is accounted for by the flex column at any breakpoint —
   no fixed header-height subtraction required. 100dvh is mobile-safe. */
body:has(.app-main--chat) {
    height: 100dvh;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

/* Chat-route-only header trim (spacing only — brand marks/wordmark untouched).
   In the 641–~900px two-column band the authenticated nav (Chat / Mein Konto /
   Admin-Konsole / QuotaIndicator / Abmelden) wraps to multiple rows, making the
   sticky header tall and eating the bounded panel's vertical budget. Tightening
   the header's block padding + the nav's row/column gaps reclaims that height.
   Scoped to body:has(.app-main--chat) so EVERY non-chat route is byte-identical
   (FR-013) and it never restructures or resizes the K&K brand block. */
body:has(.app-main--chat) .app-header__inner {
    padding-block: var(--space-2);
}

body:has(.app-main--chat) .app-nav {
    row-gap: var(--space-1);
    column-gap: var(--space-2);
}

/* 2026-09-15 — same reasoning for the second header band (the "Produkt"
   strip added when the public product pages were carried into the
   signed-in menu). The strip STAYS on the chat route — every non-login
   link must be reachable while signed in, on every route — it just
   gives back its block padding where the vertical budget is bounded. */
body:has(.app-main--chat) .product-nav {
    padding-block: var(--space-1);
}

a {
    color: inherit;
    text-decoration: none;
}

img {
    display: block;
    max-width: 100%;
}

/* --- Container ----------------------------------------------------------------- */

.container {
    max-width: var(--layout-max-width);
    margin: 0 auto;
    padding: 0 var(--space-5);
}

/* --- Paper backdrop (rendered once by PaperBackdrop.razor) ---------------------
   Fixed cream ground + feTurbulence grain overlay. The data-URI carries no
   color literals (feColorMatrix numeric values only). */

.paper-backdrop {
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    overflow: hidden;
    background: var(--paper);
}

.paper-grain {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.08 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
    mix-blend-mode: multiply;
    opacity: 0.5;
}

/* --- Print box (the universal editorial surface) ------------------------------
   Successor of the former translucent panel: honest card plate, 1px ink
   frame, square corners. No blur, no glow, no hover lift. */

.print-box {
    background: var(--paper-card);
    border: 1px solid var(--rule-strong);
    border-radius: var(--radius-box);
}

.print-box__header {
    border-bottom: 1px solid var(--rule-strong);
    padding: var(--space-3) var(--space-4);
}

/* --- Section label (`§ NN` + rule + mono label) -------------------------------- */

.section-label {
    display: flex;
    align-items: center;
    gap: var(--space-3);
}

.section-label__num {
    font-family: var(--font-mono);
    font-weight: 700;
    font-size: var(--text-caption);
    letter-spacing: 0.18em;
    color: var(--brand-indigo);
    white-space: nowrap;
}

.section-label__rule {
    flex: 1;
    border-top: 1px solid var(--rule-hairline);
}

.section-label__text {
    font-family: var(--font-mono);
    font-size: var(--text-caption);
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--ink);
    white-space: nowrap;
}

/* Transitional mono eyebrow (legacy markup; major sections move to
   .section-label per contract §2). */
.section-eyebrow {
    font-family: var(--font-mono);
    font-size: var(--text-caption);
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--brand-indigo);
}

/* --- Display headline (manual §03) ---------------------------------------------
   Condensed extra-bold italic uppercase. German compound safety: manual
   hyphenation only — authors place soft hyphens at intended break points. */

.display-head {
    font-family: var(--font-display);
    font-weight: 800;
    font-style: italic;
    text-transform: uppercase;
    letter-spacing: -0.025em;
    line-height: 0.96;
    color: var(--brand-indigo);
    hyphens: manual;
}

.band .display-head {
    color: var(--text-on-band);
}

/* --- Riso shift (print-misregistration; display headlines ONLY, FR-005) --------
   Markup pattern: visible text + aria-hidden ghost span. Static — this is
   print misregistration, not animation. Ghost hue MUST come from a
   different hue family than the text (cross-hue pairing). */

.riso-shift {
    position: relative;
    display: inline-block;
    white-space: nowrap;
}

.riso-shift__ghost {
    position: absolute;
    inset: 0;
    pointer-events: none;
    transform: translate(0.045em, 0.045em);
    mix-blend-mode: multiply;
}

.riso-shift--tuerkis .riso-shift__ghost { color: var(--brand-tuerkis); }
.riso-shift--orange .riso-shift__ghost { color: var(--brand-orange); }
.riso-shift--lila .riso-shift__ghost { color: var(--brand-lila); }
.riso-shift--gelb .riso-shift__ghost { color: var(--brand-gelb); }

/* --- Stamp (mono bordered chip) ------------------------------------------------- */

.stamp {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    border: 1.5px solid currentColor;
    padding: 4px 10px 3px;
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    border-radius: var(--radius-stamp);
}

/* --- Sticker (rotated marketing label; restraint per R5) ------------------------ */

.sticker {
    display: inline-flex;
    align-items: center;
    padding: var(--space-1) var(--space-3);
    background: var(--brand-orange);
    color: var(--ink); /* FR-016 convention: ink text on signal tints
                          (paper-card on orange fails AA at 2.86:1;
                          ink measures 6.71:1 — P15) */
    font-family: var(--font-sans);
    font-weight: 800;
    font-style: italic;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-radius: var(--radius-sticker);
    box-shadow: var(--shadow-sticker);
    transform: rotate(-2deg);
}

.sticker--gelb {
    background: var(--brand-gelb);
    color: var(--ink);
}

/* --- Band (deep-indigo emphasis block: footer, pull-quotes, hero panel) --------- */

.band {
    background: var(--band-bg);
    color: var(--text-on-band);
}

/* --- Brand block (header) -------------------------------------------------------
   <a class="brand-mark"><img class="brand-logo" …><span class="brand-wordmark">
   euraki</span></a>. The mark is never filtered, transformed or recolored
   (FR-006). */

.brand-mark {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3);
    text-decoration: none;
}

.brand-logo {
    display: block;
    height: 28px;
    width: auto;
}

.brand-wordmark {
    font-family: var(--font-sans);
    font-weight: 800;
    font-style: italic;
    color: var(--brand-indigo);
    letter-spacing: -0.01em;
}

/* --- Editorial button family (names kept; visual restyled per R5) ---------------
   Square buttons, uppercase verb-first labels. Hover is a 120ms
   color/border change — no lift, no glow. */

.brand-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-5);
    border-radius: var(--radius-box);
    background: var(--paper-card);
    border: 1.5px solid var(--ink);
    color: var(--ink);
    font-family: inherit;
    font-weight: 700;
    font-size: 0.9rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
    transition: color var(--motion-micro) var(--ease-standard),
                border-color var(--motion-micro) var(--ease-standard),
                background var(--motion-micro) var(--ease-standard);
}

.brand-pill:hover {
    border-color: var(--brand-indigo);
    color: var(--brand-indigo);
}

.brand-pill:focus-visible {
    outline: none;
    box-shadow: var(--shadow-focus-ring);
}

.brand-pill:disabled,
.brand-pill[aria-disabled="true"] {
    opacity: 0.55;
    cursor: not-allowed;
    box-shadow: none;
}

.brand-pill--primary {
    background: var(--brand-indigo);
    border-color: var(--brand-indigo);
    color: var(--text-on-band);
}

.brand-pill--primary:hover {
    background: var(--ink);
    border-color: var(--ink);
    color: var(--text-on-band);
}

.brand-pill--ghost {
    background: transparent;
    border: 1.5px solid currentColor;
    color: var(--text-secondary);
    padding: var(--space-2) var(--space-4);
    font-size: 0.85rem;
}

.brand-pill--ghost:hover {
    color: var(--brand-indigo);
}

/* Danger pill — FR-016 "ink text on signal tints" (P17): error TEXT on
   the warning tint measured only 3.12:1 (axe wcag2aa, /account
   Gefahrenzone, 14.4px bold < large-text cutoff). The pill now paints
   its own --color-warning-bg ground with ink text (15.77:1 over paper)
   and keeps the danger affordance via the --color-error frame. Hover
   fills with the error orange and keeps INK text (5.04:1 — paper-card
   on the error fill was only 3.80:1). */
.brand-pill--danger {
    background: var(--color-warning-bg);
    border-color: var(--color-error);
    color: var(--ink);
}

.brand-pill--danger:hover {
    background: var(--color-error);
    border-color: var(--color-error);
    color: var(--ink);
}

/* Admin sibling — same editorial contract as .brand-pill. Scoped files
   layer modifiers (.btn-pill--danger, compact paddings) on top. */

.btn-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-5);
    border-radius: var(--radius-box);
    background: var(--paper-card);
    border: 1.5px solid var(--ink);
    color: var(--ink);
    font-family: inherit;
    font-weight: 700;
    font-size: 0.9rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
    transition: color var(--motion-micro) var(--ease-standard),
                border-color var(--motion-micro) var(--ease-standard),
                background var(--motion-micro) var(--ease-standard);
}

.btn-pill:hover {
    border-color: var(--brand-indigo);
    color: var(--brand-indigo);
}

/* --- Toast (print-stamp skin; placement + z unchanged — Constitution V) --------- */

.toast-notification {
    position: fixed;
    bottom: var(--space-6);
    left: 50%;
    transform: translateX(-50%) translateY(150%);
    background: var(--paper-card);
    color: var(--ink);
    border: 2px solid var(--ink);
    border-radius: var(--radius-stamp);
    box-shadow: var(--shadow-sticker);
    padding: var(--space-3) var(--space-5);
    font-family: var(--font-mono);
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    z-index: 1000;
    transition: transform var(--motion-snap) var(--ease-standard);
}

.toast-notification.show {
    transform: translateX(-50%) translateY(0);
}

/* --- Bootstrap-derived form overrides — see theme-tokens.md § Forms ------------- */

.form-control:disabled,
.form-select:disabled {
    background-color: var(--paper-deep);
    color: var(--text-muted);
    opacity: 0.65;
}

.input-group-text {
    background-color: var(--paper-deep);
    color: var(--text-secondary);
    border-color: var(--rule-hairline);
}

.nav-tabs .nav-link.active {
    color: var(--text-primary);
    background-color: var(--paper-card);
    border-color: var(--rule-hairline);
}

.text-muted {
    color: var(--text-secondary) !important;
}

/* --- WebKit scrollbar (ink on paper) -------------------------------------------- */

::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}

::-webkit-scrollbar-track {
    background: var(--paper-deep);
}

::-webkit-scrollbar-thumb {
    background: var(--rule-hairline);
    border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
    background: var(--text-muted);
}

/* --- Tier card (S02 pricing; class kept, print-box treatment) ------------------- */

.tier-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-6) var(--space-5);
    background: var(--paper-card);
    border: 1px solid var(--rule-strong);
    border-radius: var(--radius-box);
    transition: border-color var(--motion-micro) var(--ease-standard);
}

.tier-card:hover {
    border-color: var(--brand-indigo);
}

.tier-card--recommended {
    border-color: var(--brand-indigo);
}

.tier-card__badge {
    position: absolute;
    top: var(--space-3);
    right: var(--space-3);
    padding: var(--space-1) var(--space-3);
    background: var(--brand-orange);
    color: var(--ink); /* ink on signal tint — P15 (AA 6.71:1) */
    border-radius: var(--radius-sticker);
    box-shadow: var(--shadow-sticker);
    transform: rotate(2deg);
    font-size: 0.75rem;
    font-weight: 800;
    font-style: italic;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

/* --- Tier badge (S04 /account; stamp treatment) ---------------------------------- */

.tier-badge {
    display: inline-flex;
    align-items: center;
    padding: 4px 10px 3px;
    border: 1.5px solid currentColor;
    border-radius: var(--radius-stamp);
    color: var(--brand-indigo);
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
}

.auth-card__tier-price {
    margin-inline-start: var(--space-2);
    color: var(--text-secondary);
    font-size: 0.85rem;
}

/* --- Feature card (S02; class kept, print-box treatment) ------------------------- */

.feature-card {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-8) var(--space-6);
    background: var(--paper-card);
    border: 1px solid var(--rule-strong);
    border-radius: var(--radius-box);
    transition: border-color var(--motion-micro) var(--ease-standard);
}

.feature-card:hover {
    border-color: var(--brand-indigo);
}

/* --- Legal prose container (S02) -------------------------------------------------- */

.legal-prose {
    font-size: var(--text-body);
    line-height: 1.7;
    color: var(--text-primary);
}

.legal-prose h1 {
    font-family: var(--font-display);
    font-size: var(--text-h2);
    font-weight: 800;
    font-style: italic;
    text-transform: uppercase;
    letter-spacing: -0.025em;
    line-height: 0.96;
    color: var(--brand-indigo);
    margin: var(--space-8) 0 var(--space-4);
}

.legal-prose h2 {
    font-family: var(--font-display);
    font-size: 1.5rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: -0.02em;
    line-height: 1.0;
    color: var(--brand-indigo);
    margin: var(--space-6) 0 var(--space-3);
}

.legal-prose h3 {
    font-size: 1.125rem;
    font-weight: 700;
    color: var(--text-primary);
    margin: var(--space-5) 0 var(--space-2);
}

.legal-prose p {
    margin: 0 0 var(--space-4);
}

.legal-prose ul,
.legal-prose ol {
    padding-inline-start: var(--space-6);
    margin: 0 0 var(--space-4);
}

.legal-prose li {
    margin-bottom: var(--space-2);
}

.legal-prose a {
    color: var(--brand-indigo);
    text-decoration: underline;
}

/* --- Auth page layout primitives (global) -----------------------------------------
   Covers /login, /register, /account and the 14 auth-shaped pages without
   their own scoped CSS. Editorial form language: card plates with ink
   frames, indigo display headings. */

.auth-page {
    max-width: 640px;
    padding-block: var(--space-12) var(--space-16);
    display: flex;
    flex-direction: column;
    gap: var(--space-6);
    text-align: left;
}

.auth-page h1 {
    font-family: var(--font-display);
    font-size: var(--text-h1);
    font-style: italic;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: -0.025em;
    margin: 0;
    line-height: 0.96;
    color: var(--brand-indigo);
    hyphens: manual;
}

.auth-page__lead {
    margin: 0;
    color: var(--text-secondary);
    font-size: 1.0625rem;
    line-height: 1.6;
}

.auth-page__alt {
    margin: 0;
    color: var(--text-secondary);
    font-size: 0.95rem;
}

.auth-page__alt a {
    color: var(--brand-indigo);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.auth-card {
    background: var(--paper-card);
    border: 1px solid var(--rule-strong);
    border-radius: var(--radius-box);
    padding: var(--space-6) var(--space-7);
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.auth-card__heading {
    margin: 0 0 var(--space-2);
    font-size: 1.25rem;
    font-weight: 800;
    font-style: italic;
    letter-spacing: 0.5px;
    color: var(--text-primary);
}

.auth-card__actions {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
}

/* --- Form primitives (global) ------------------------------------------------------ */

.form-control-group {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.form-control-group label {
    font-weight: 600;
    color: var(--text-primary);
    font-size: 0.9375rem;
}

.form-control-group--inline label {
    display: inline-flex;
    flex-direction: row;
    align-items: center;
    gap: var(--space-2);
    font-weight: 500;
    color: var(--text-secondary);
}

.form-control {
    width: 100%;
    background: var(--bg-input);
    border: 1px solid var(--rule-hairline);
    border-radius: var(--radius-box);
    padding: var(--space-3) var(--space-4);
    color: var(--text-primary);
    font: inherit;
    line-height: 1.4;
    transition: border-color var(--motion-micro) var(--ease-standard),
                box-shadow var(--motion-micro) var(--ease-standard);
    accent-color: var(--brand-indigo);
}

.form-control::placeholder {
    color: var(--text-muted);
}

.form-control:hover {
    border-color: var(--rule-strong);
}

.form-control:focus,
.form-control:focus-visible {
    border-color: var(--brand-indigo);
    outline: none;
    box-shadow: var(--shadow-focus-ring);
    background: var(--paper-card);
}

.validation-message {
    color: var(--color-signal-text);
    font-size: 0.85rem;
    font-weight: 600;
    margin: 0;
}

/* Inline logout form lives in the nav bar and inside .auth-card.
   Strip the default block layout so the button sits flush with
   surrounding nav items / card actions. */
.public-nav__logout {
    display: inline-flex;
    align-items: center;
    margin: 0;
}

/* --- Reduced motion (FR-014 kill-switch — covers animation + transition) ----------- */

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