/* Lacuna v0.4.1 — Login UI styled to match the lacunamosaic.de apex
 * design system: dark navy background, gold (#c9a86a) accent, plexus
 * canvas animation. Design tokens lifted verbatim from the apex
 * landing.html so the visual brand stays continuous between apex,
 * future migration, and (formerly) Nextcloud at /cloud/login. */

:root {
    --bg: #0a0f1c;
    --bg-elev: #111726;
    --fg: #e8e8ea;
    --fg-dim: #9aa0a8;
    --accent: #c9a86a;
    --accent-hover: #d9b87a;
    --field: #1a1f2e;
    --border: #2a3142;
    --border-focus: #c9a86a;
    --error-bg: rgba(220, 60, 60, 0.10);
    --error-fg: #f08080;
}

*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }

#bg-canvas {
    position: fixed;
    inset: 0;
    width: 100vw;
    height: 100vh;
    z-index: 0;
    pointer-events: none;
}

/* Sprint 25 Move 2: defensive CSS gate paired with the JS opt-out in
 * login.js — on dense surfaces (mandate_detail, brief_detail) the canvas
 * is noise behind data, so hide it even if the JS doesn't run early. */
body.dense #bg-canvas { display: none; }

main { position: relative; z-index: 1; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--fg);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, system-ui, sans-serif;
    font-size: 16px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
    min-height: 100vh;
}

main {
    width: 100%;
    max-width: 26rem;
}

.brand {
    text-align: center;
    margin-bottom: 3rem;
}

.brand-logo {
    max-width: 17rem;
    width: 100%;
    height: auto;
    display: block;
    margin: 0 auto 0.9rem;
}

.brand-tagline {
    font-size: 0.78rem;
    color: var(--fg-dim);
    letter-spacing: 0.06em;
    margin: 0;
}

form {
    background: var(--bg-elev);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 2rem 1.75rem;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.field {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

label {
    font-size: 0.7rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--fg-dim);
}

input {
    background: var(--field);
    border: 1px solid var(--border);
    color: var(--fg);
    padding: 0.75rem 0.875rem;
    font-size: 0.95rem;
    font-family: inherit;
    border-radius: 3px;
    transition: border-color 0.15s ease;
    width: 100%;
}

input:focus {
    outline: none;
    border-color: var(--border-focus);
}

button {
    background: var(--accent);
    color: var(--bg);
    border: none;
    padding: 0.85rem;
    font-size: 0.85rem;
    font-weight: 600;
    font-family: inherit;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    cursor: pointer;
    border-radius: 3px;
    margin-top: 0.5rem;
    transition: background-color 0.15s ease;
}

button:hover:not(:disabled) { background: var(--accent-hover); }
button:disabled { opacity: 0.55; cursor: wait; }

.error {
    background: var(--error-bg);
    color: var(--error-fg);
    padding: 0.7rem 0.875rem;
    font-size: 0.85rem;
    border-radius: 3px;
    border: 1px solid rgba(220, 60, 60, 0.25);
}

footer {
    margin-top: 2.5rem;
    text-align: center;
    font-size: 0.72rem;
    color: var(--fg-dim);
    line-height: 1.7;
    letter-spacing: 0.02em;
}

footer a {
    color: var(--fg-dim);
    text-decoration: none;
    border-bottom: 1px solid var(--border);
}

footer a:hover { color: var(--fg); }

@media (max-width: 480px) {
    .brand-logo { max-width: 13rem; }
}

/* v0.6.13 — compact brand-block on dense work surfaces.
 *
 * On login/dashboard/apex the brand block is the hero: centered, 17rem
 * wide, with tagline and 3rem bottom margin. That eats ~140px on dense
 * surfaces (mandate_detail, brief_detail, mandate_connector) where the
 * operator's viewport is finite and they want to see the workshop
 * content above the fold.
 *
 * Compact variant: left-aligned, 8rem logo (~50px tall, was ~70px on
 * desktop), tagline hidden (the logo identifies), 1rem margin-bottom.
 * Saves ~80-90px of vertical space without losing the brand cue. */
body.dense .brand {
    text-align: left;
    margin-bottom: 1rem;
    display: flex;
    align-items: center;
    gap: 0.75rem;
}
body.dense .brand-logo {
    max-width: 8rem;
    margin: 0;
}
body.dense .brand-tagline {
    /* Keep tagline as inline footnote next to the logo on wide
     * screens; hide on phones where width is tight. */
    font-size: 0.72rem;
    margin: 0;
    color: var(--fg-faint, var(--fg-dim));
}
@media (max-width: 720px) {
    body.dense .brand-tagline { display: none; }
}

/* Dashboard-specific (authenticated landing) */

.dashboard-shell {
    background: var(--bg-elev);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 2rem 1.75rem;
}

.dashboard-shell h1 {
    margin: 0 0 0.5rem;
    font-size: 1.25rem;
    color: var(--fg);
    letter-spacing: 0.02em;
}

.dashboard-shell .subtitle {
    margin: 0 0 1.5rem;
    color: var(--fg-dim);
    font-size: 0.85rem;
}

.dashboard-meta {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 0.4rem 1rem;
    font-size: 0.85rem;
    margin-bottom: 1.5rem;
}

.dashboard-meta dt {
    color: var(--fg-dim);
    text-transform: uppercase;
    /* Sprint 37 (v0.6.23): mirror .kv dt bump — 0.7rem (~11.2px) was below
       banker-legibility for all-caps micro-labels. 0.75rem (12px) AA-min. */
    font-size: 0.75rem;
    letter-spacing: 0.1em;
}

.dashboard-meta dd { margin: 0; color: var(--fg); }

/* Sprint 31 Phase 3 - Gesamt-PDF CTA on mandate_detail.html. Gold-bordered
   link that matches the Sprint 30A app-shell visual language; the
   "alle Kandidaten" PDF download is the headline action on the page. */
.mandate-aggregated-cta {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.6rem 1rem;
    margin: -0.25rem 0 1.5rem;
}

.mandate-aggregated-cta__link {
    display: inline-block;
    padding: 0.55rem 1.1rem;
    border: 1px solid var(--color-brand, var(--accent));
    border-radius: 3px;
    color: var(--color-brand, var(--accent));
    font-size: 0.85rem;
    font-weight: 600;
    text-decoration: none;
    background: transparent;
    transition: background-color 0.12s ease, color 0.12s ease;
}

.mandate-aggregated-cta__link:hover,
.mandate-aggregated-cta__link:focus {
    background: var(--color-brand, var(--accent));
    color: var(--color-bg, #0a0f1c);
    text-decoration: none;
}

.mandate-aggregated-cta__hint {
    font-size: 0.75rem;
}

.placeholder-card {
    border: 1px dashed var(--border);
    border-radius: 3px;
    padding: 1rem 1.25rem;
    font-size: 0.85rem;
    color: var(--fg-dim);
    background: rgba(201, 168, 106, 0.03);
}

.logout-form { margin-top: 1.5rem; text-align: right; }

.logout-form button {
    background: transparent;
    color: var(--fg-dim);
    border: 1px solid var(--border);
    padding: 0.5rem 1rem;
    font-size: 0.75rem;
    margin: 0;
}

.logout-form button:hover:not(:disabled) {
    background: transparent;
    border-color: var(--accent);
    color: var(--accent);
}

/* ===========================================================
 * Sprint 21 — Operator Review Browser
 * Mandate index + detail + brief detail pages.
 * Reuses dark-gold tokens; adds decision-band/priority chips,
 * brief-cards, and a wide main-column variant.
 * =========================================================== */

:root {
    --band-strong: #c9a86a;          /* gold — same as --accent */
    --band-cautious: #d4a85a;        /* muted amber */
    --band-blocked: #f08080;         /* red */
    --band-insufficient: #9aa0a8;    /* dim grey */
    --band-needs: #7ab8d9;           /* info blue */
    --chip-bg: rgba(255, 255, 255, 0.04);
    --chip-border: var(--border);
}

main.wide {
    max-width: 56rem;
}

.page-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 0.5rem;
}

.page-header h1 {
    margin: 0;
}

.back-link {
    color: var(--fg-dim);
    text-decoration: none;
    font-size: 0.8rem;
    letter-spacing: 0.04em;
    border-bottom: 1px solid var(--border);
    padding-bottom: 1px;
}

.back-link:hover {
    color: var(--accent);
    border-color: var(--accent);
}

/* --- CTA on dashboard --------------------------------------- */

.dashboard-cta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: rgba(201, 168, 106, 0.08);
    border: 1px solid var(--accent);
    border-radius: 3px;
    padding: 1rem 1.25rem;
    margin: 1.5rem 0 0;
    text-decoration: none;
    color: var(--accent);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    font-size: 0.85rem;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.dashboard-cta:hover {
    background: var(--accent);
    color: var(--bg);
}

.dashboard-cta__arrow {
    font-size: 1.1rem;
    line-height: 1;
}

/* Sprint 37 (v0.6.23) — "Pilot-Lauf starten" button on the idle-state
   pipeline-status card. Gold-on-navy filled CTA matching the
   dashboard-cta aesthetic; this is the headline action the end-user
   (Christian) takes to convert a seeded mandate into a live pilot.
   Generous padding so the button reads as a primary, decisive action
   rather than a tertiary link. */
.pipeline-status__action {
    /* Sprint 63 — same global-`form {}`-card defeat as
       .app-header__logout: this is a <form> wrapping the pilot-start
       button and would otherwise render inside a padded bordered box. */
    margin: 0.75rem 0 0;
    padding: 0;
    background: none;
    border: 0;
    border-radius: 0;
    display: flex;
}

.pilot-start-btn {
    display: inline-block;
    padding: 0.75rem 1.5rem;
    background: var(--accent);
    color: var(--bg);
    border: 1px solid var(--accent);
    border-radius: 3px;
    font-weight: 600;
    font-size: 0.9rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease,
                border-color 0.15s ease;
}

.pilot-start-btn:hover:not(:disabled),
.pilot-start-btn:focus:not(:disabled) {
    background: var(--accent-hover);
    border-color: var(--accent-hover);
    color: var(--bg);
}

.pilot-start-btn:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.pipeline-status__hint {
    margin: 0.75rem 0 0;
    font-size: 0.8rem;
    font-style: italic;
}

/* --- Chips -------------------------------------------------- */

.chip {
    display: inline-block;
    padding: 0.15rem 0.55rem;
    border-radius: 999px;
    font-size: 0.7rem;
    letter-spacing: 0.06em;
    border: 1px solid var(--chip-border);
    background: var(--chip-bg);
    color: var(--fg);
    text-transform: lowercase;
    white-space: nowrap;
}

.chip--small { font-size: 0.62rem; padding: 0.1rem 0.45rem; }
.chip--neutral { color: var(--fg-dim); }

.chip--band-strong              { color: var(--band-strong); border-color: rgba(201, 168, 106, 0.45); background: rgba(201, 168, 106, 0.10); }
.chip--band-cautious            { color: var(--band-cautious); border-color: rgba(212, 168, 90, 0.45); background: rgba(212, 168, 90, 0.10); }
.chip--band-blocked             { color: var(--band-blocked); border-color: rgba(240, 128, 128, 0.45); background: rgba(240, 128, 128, 0.10); }
.chip--band-insufficient_evidence { color: var(--band-insufficient); }
.chip--band-needs_evidence      { color: var(--band-needs); border-color: rgba(122, 184, 217, 0.40); background: rgba(122, 184, 217, 0.08); }

.chip--status-ready_for_review  { color: var(--band-strong); border-color: rgba(201, 168, 106, 0.45); background: rgba(201, 168, 106, 0.10); }
.chip--status-needs_evidence    { color: var(--band-needs); border-color: rgba(122, 184, 217, 0.40); background: rgba(122, 184, 217, 0.08); }
.chip--status-blocked           { color: var(--band-blocked); border-color: rgba(240, 128, 128, 0.45); background: rgba(240, 128, 128, 0.10); }
.chip--status-insufficient      { color: var(--band-insufficient); }

.chip--priority-high    { color: var(--band-blocked); border-color: rgba(240, 128, 128, 0.45); }
.chip--priority-medium  { color: var(--band-cautious); border-color: rgba(212, 168, 90, 0.45); }
.chip--priority-low     { color: var(--fg-dim); }

.chip--conf-high    { color: var(--band-strong); }
.chip--conf-medium  { color: var(--band-cautious); }
.chip--conf-low     { color: var(--fg-dim); }

/* --- Mandate list ------------------------------------------ */

.mandate-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.mandate-row {
    background: rgba(255, 255, 255, 0.02);
    border: 1px solid var(--border);
    border-radius: 3px;
    padding: 0.75rem 1rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

.mandate-row:hover { border-color: var(--accent); background: rgba(201, 168, 106, 0.05); }

.mandate-row__link {
    color: var(--fg);
    text-decoration: none;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    flex: 1;
    min-width: 0;
}

.mandate-row__name { font-weight: 500; font-size: 0.95rem; }

.mandate-row__meta {
    display: flex;
    gap: 0.6rem;
    font-size: 0.75rem;
    color: var(--fg-dim);
    align-items: center;
    flex-wrap: wrap;
}

.mandate-row__mtime { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.7rem; }

.mandate-row__indicators {
    display: flex;
    gap: 0.35rem;
    flex-shrink: 0;
}

.indicator {
    font-size: 0.62rem;
    letter-spacing: 0.06em;
    padding: 0.1rem 0.4rem;
    border-radius: 2px;
    border: 1px solid var(--border);
    text-transform: lowercase;
}

.indicator--on  { color: var(--accent); border-color: rgba(201, 168, 106, 0.45); }
.indicator--off { color: var(--fg-dim); opacity: 0.4; }

/* Sprint 52 — banker-readable variants. Unlike --on/--off these carry
   mixed-case German labels ("Pilot ausstehend", "Summary ✓") so the
   parent .indicator's text-transform: lowercase is overridden. */
.indicator--ok {
    color: var(--accent);
    border-color: rgba(201, 168, 106, 0.45);
    text-transform: none;
}
.indicator--pending {
    color: var(--fg-dim);
    border-color: rgba(255, 255, 255, 0.18);
    background: rgba(255, 255, 255, 0.02);
    text-transform: none;
    font-style: italic;
}

/* --- Brief grid (mandate detail) ---------------------------- */

.brief-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
    gap: 0.75rem;
    margin-top: 1.5rem;
}

.brief-card {
    background: rgba(255, 255, 255, 0.02);
    border: 1px solid var(--border);
    border-radius: 3px;
    padding: 1rem;
    text-decoration: none;
    color: var(--fg);
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

.brief-card:hover { border-color: var(--accent); background: rgba(201, 168, 106, 0.05); }

.brief-card__name { margin: 0; font-size: 0.95rem; font-weight: 500; letter-spacing: 0.01em; }
.brief-card__chips { display: flex; gap: 0.4rem; flex-wrap: wrap; }
.brief-card__nbs { margin: 0; font-size: 0.75rem; color: var(--fg-dim); }
.brief-card__nbs code { font-size: 0.72rem; color: var(--fg); }

/* --- Review blocks (brief detail) --------------------------- */

.review-block {
    border-top: 1px solid var(--border);
    padding-top: 1.25rem;
    margin-top: 1.25rem;
}

.review-block h2 {
    margin: 0 0 0.75rem;
    /* Sprint 37 (v0.6.23): wire to fluid --text-h2 token (introduced in
       Sprint 33). Pre-Sprint-37 the H1→H2 drop was 44px → 16px (~28px),
       a banker reads that as "two unrelated documents stitched together".
       Token reads ~22-32px on viewport, restoring a ~12-16px hierarchy
       gap and lifting the verdict-band above the fold on 1366×768. */
    font-size: var(--text-h2);
    font-weight: 600;
    color: var(--accent);
    letter-spacing: 0.04em;
}

.review-block h3 {
    margin: 0.5rem 0 0.5rem;
    font-size: 0.85rem;
    color: var(--fg);
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.review-block--packet { background: rgba(201, 168, 106, 0.04); border-radius: 3px; padding: 1.25rem 1rem; border-top-color: var(--accent); }

.kv {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 0.4rem 1rem;
    font-size: 0.85rem;
}

.kv dt {
    color: var(--fg-dim);
    text-transform: uppercase;
    /* Sprint 37 (v0.6.23): 0.68rem (~10.9px) was below banker-legibility —
       Reviewer 3 (Banker IA) flagged the dl-dt micro-labels as illegible at
       arm's length. 0.75rem (12px) is the minimum AA-compliant body for
       all-caps small-text. */
    font-size: 0.75rem;
    letter-spacing: 0.1em;
    padding-top: 0.15rem;
}

.kv dd {
    margin: 0;
    color: var(--fg);
    /* Sprint 37 (v0.6.23): decision-summary content is what bankers actually
       read — bump from inherited 0.85rem (13.6px) to 0.9375rem (15px) so
       the verdict-card prose has body-text legibility. */
    font-size: 0.9375rem;
}

.signal-list {
    margin: 0;
    padding-left: 1.1rem;
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
}

.signal-list--ol { padding-left: 1.4rem; }
.signal-list--support li::marker { color: var(--band-strong); }
.signal-list--weaken li::marker  { color: var(--band-blocked); }
.signal-list--mono code { font-size: 0.72rem; color: var(--fg-dim); }

.checklist {
    margin: 0;
    padding-left: 1.4rem;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    font-size: 0.9rem;
}

.checklist li { color: var(--fg); }

.gap-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.gap-item {
    border: 1px solid var(--border);
    border-radius: 3px;
    padding: 0.5rem 0.75rem;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.gap-item .chip { align-self: flex-start; }
.gap-item code { font-size: 0.72rem; }
.gap-rationale { color: var(--fg-dim); font-size: 0.78rem; }

.audit-trail {
    margin-top: 1rem;
    font-size: 0.75rem;
}

.audit-trail summary {
    cursor: pointer;
    color: var(--fg-dim);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    font-size: 0.7rem;
    padding-bottom: 0.5rem;
}

.audit-trail summary:hover { color: var(--accent); }

.dim { color: var(--fg-dim); }

.review-block pre { background: var(--bg); border-radius: 2px; padding: 0.75rem; overflow-x: auto; font-size: 0.78rem; }
.placeholder-card pre { background: var(--bg); border-radius: 2px; padding: 0.5rem 0.75rem; overflow-x: auto; font-size: 0.75rem; margin: 0.5rem 0; }
.placeholder-card code { color: var(--fg); }

/* ===========================================================
 * Sprint 22 — Pipeline-on-Hetzner
 * /mandates/new form + queue status banner + recent-jobs table.
 * Reuses --band-strong / --band-blocked etc.; adds two tokens
 * for the queued/running amber + the running-pulse animation.
 * =========================================================== */

:root {
    --band-queued: #d4a85a;          /* muted amber — same shade as cautious */
    --band-running: #d4a85a;
}

/* --- Form banner (re-rendered on validation error) ---------- */

.form-banner {
    border-radius: 3px;
    padding: 0.75rem 1rem;
    margin: 1rem 0 1.25rem;
    font-size: 0.85rem;
}

.form-banner--error {
    background: rgba(240, 128, 128, 0.08);
    border: 1px solid rgba(240, 128, 128, 0.4);
    color: var(--band-blocked);
}

/* --- /mandates/new form -------------------------------------- */

.mandate-form {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    margin-top: 1rem;
}

.mandate-form .field {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.field__hint {
    color: var(--fg-dim);
    font-weight: 400;
    font-size: 0.72rem;
    letter-spacing: 0.02em;
    text-transform: none;
}

.field__radio-row,
.field__check-row {
    display: flex;
    gap: 0.75rem;
    flex-wrap: wrap;
    align-items: center;
}

.radio,
.check {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.85rem;
    color: var(--fg);
    cursor: pointer;
    padding: 0.25rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: 3px;
    background: var(--field);
}

.radio input,
.check input {
    accent-color: var(--accent);
}

.mandate-form textarea {
    width: 100%;
    box-sizing: border-box;
    padding: 0.65rem 0.85rem;
    background: var(--field);
    border: 1px solid var(--border);
    border-radius: 3px;
    color: var(--fg);
    font-family: inherit;
    font-size: 0.9rem;
    resize: vertical;
    min-height: 4.5rem;
}

.mandate-form textarea:focus {
    border-color: var(--border-focus);
    outline: none;
}

.mandate-form select {
    padding: 0.65rem 0.85rem;
    background: var(--field);
    border: 1px solid var(--border);
    border-radius: 3px;
    color: var(--fg);
    font-family: inherit;
    font-size: 0.9rem;
}

.mandate-form__actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin-top: 0.5rem;
}

.mandate-form__actions button {
    min-width: 12rem;
}

.mandate-form__note {
    margin-top: 1.5rem;
    font-size: 0.78rem;
    line-height: 1.5;
}

/* --- Status banner (mandate-detail header) ------------------- */

.status-banner {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    padding: 0.9rem 1rem;
    border-radius: 3px;
    border: 1px solid var(--border);
    margin: 1.25rem 0;
    font-size: 0.88rem;
}

.status-banner strong { color: var(--fg); }
.status-banner .dim { font-size: 0.78rem; }

.status-banner__action {
    color: var(--accent);
    text-decoration: none;
    font-size: 0.78rem;
    letter-spacing: 0.04em;
    border-bottom: 1px solid rgba(201, 168, 106, 0.4);
    align-self: flex-start;
    padding-bottom: 1px;
}

.status-banner__action:hover {
    border-color: var(--accent);
}

.status-banner__actions {
    display: flex;
    gap: 1rem;
    flex-wrap: wrap;
    align-items: center;
}

/* Sprint 63 — "Erneut versuchen" is now a POST <form> (re-runs the
   mandate's existing thesis). Defeat the global form-card styling and
   restyle the button to match the sibling .status-banner__action
   text-links. */
.status-banner__retry {
    display: inline-flex;
    margin: 0;
    padding: 0;
    background: none;
    border: 0;
    border-radius: 0;
    gap: 0;
}

.status-banner__action--retry {
    background: none;
    color: var(--accent);
    border: 0;
    border-bottom: 1px solid rgba(201, 168, 106, 0.4);
    border-radius: 0;
    padding: 0 0 1px;
    margin: 0;
    font-family: inherit;
    font-weight: 400;
    text-transform: none;
    cursor: pointer;
}

.status-banner__action--retry:hover:not(:disabled) {
    background: none;
    color: var(--accent);
    border-color: var(--accent);
}

.status-banner__error {
    margin-top: 0.5rem;
    font-size: 0.78rem;
}

.status-banner__error summary {
    cursor: pointer;
    color: var(--fg-dim);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-size: 0.7rem;
    padding-bottom: 0.5rem;
}

.status-banner__error pre {
    background: var(--bg);
    border-radius: 2px;
    padding: 0.6rem 0.75rem;
    overflow-x: auto;
    font-size: 0.72rem;
    max-height: 12rem;
    white-space: pre-wrap;
    word-break: break-word;
}

.status-banner--queued {
    background: rgba(212, 168, 90, 0.08);
    border-color: rgba(212, 168, 90, 0.4);
}
.status-banner--queued strong { color: var(--band-queued); }

.status-banner--running {
    background: rgba(212, 168, 90, 0.08);
    border-color: rgba(212, 168, 90, 0.4);
    /* Subtle pulse so the operator clocks "this is live" at a glance. */
    animation: status-running-pulse 2.4s ease-in-out infinite;
}
.status-banner--running strong { color: var(--band-running); }

@keyframes status-running-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(212, 168, 90, 0.0); }
    50%      { box-shadow: 0 0 0 4px rgba(212, 168, 90, 0.15); }
}

@media (prefers-reduced-motion: reduce) {
    .status-banner--running { animation: none; }
}

.status-banner--done {
    background: rgba(201, 168, 106, 0.08);
    border-color: rgba(201, 168, 106, 0.45);
}
.status-banner--done strong { color: var(--band-strong); }

.status-banner--failed {
    background: rgba(240, 128, 128, 0.08);
    border-color: rgba(240, 128, 128, 0.45);
}
.status-banner--failed strong { color: var(--band-blocked); }

/* --- Recent-jobs table (mandates index) --------------------- */

.recent-jobs {
    margin-top: 2rem;
    border-top: 1px solid var(--border);
    padding-top: 1.25rem;
}

.recent-jobs h2 {
    margin: 0 0 0.75rem;
    font-size: 0.85rem;
    color: var(--accent);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.recent-jobs__table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.82rem;
}

.recent-jobs__table th {
    text-align: left;
    padding: 0.4rem 0.6rem;
    color: var(--fg-dim);
    font-weight: 500;
    text-transform: uppercase;
    font-size: 0.68rem;
    letter-spacing: 0.06em;
    border-bottom: 1px solid var(--border);
}

.recent-jobs__table td {
    padding: 0.45rem 0.6rem;
    border-bottom: 1px solid var(--border);
}

.recent-jobs__table td code {
    color: var(--fg-dim);
    font-size: 0.78rem;
}

.recent-jobs__mtime {
    color: var(--fg-dim);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.72rem;
}

.recent-jobs__table a {
    color: var(--fg);
    text-decoration: none;
}

.recent-jobs__table a:hover {
    color: var(--accent);
}

/* Sprint 25 Move 15 — chip-axis collapse.
 * Job-status and connector-outcome chips are EXECUTION-tier (mono).
 * They answer "did the machine work?" — not "what does the system say?".
 * Mono treatment prevents an operator from confusing "DEGRADED" (one
 * connector failed) with "cautious" (a deal-verdict band).
 *
 * The verdict-tier chips (chip--band-*, chip--quadrant-*) stay loud
 * and colored because those ARE the verdict.
 *
 * Glyph prefix (●▲✕○✓?) gives shape-coded redundancy for colorblind
 * users — WCAG 1.4.1 (use of color). */
.chip--job-queued,
.chip--job-running,
.chip--job-done,
.chip--job-failed,
.chip--connector-ok,
.chip--connector-degraded,
.chip--connector-failed,
.chip--connector-skipped,
.chip--connector-unknown {
    color: var(--color-exec-fg, #e8e8ea);
    border-color: var(--color-exec-border, rgba(154, 160, 168, 0.35));
    background: var(--color-exec-bg, rgba(154, 160, 168, 0.10));
    font-variant-numeric: tabular-nums;
}
.chip--connector-skipped,
.chip--connector-unknown { color: var(--color-exec-dim-fg, #6b7280); }

.chip--job-queued::before    { content: "○ "; }
.chip--job-running::before   { content: "● "; }
.chip--job-done::before      { content: "✓ "; }
.chip--job-failed::before    { content: "✕ "; }
.chip--connector-ok::before       { content: "● "; }
.chip--connector-degraded::before { content: "▲ "; }
.chip--connector-failed::before   { content: "✕ "; }
.chip--connector-skipped::before  { content: "○ "; }
.chip--connector-unknown::before  { content: "? "; }

/* --- v0.7.0 Source-Reality recommended-mode chips ------------------------
 * Roadmap-verdict chips for the /sources Quellen-Readiness page.
 * native_connector reads positive (the source is build-worthy); the
 * manual / spike / licensed modes read cautious (work still required);
 * do_not_build reads dim/neutral (a deliberate non-build). */
.chip--mode-native_connector {
    color: var(--band-strong);
    border-color: rgba(201, 168, 106, 0.45);
    background: rgba(201, 168, 106, 0.10);
}
.chip--mode-manual_assisted,
.chip--mode-browser_automation_spike,
.chip--mode-licensed_feed {
    color: var(--band-cautious);
    border-color: rgba(212, 168, 90, 0.45);
    background: rgba(212, 168, 90, 0.10);
}
.chip--mode-do_not_build,
.chip--mode-unknown { color: var(--fg-dim); }

/* --- v0.7.5 OSS Source Fabric chips -------------------------------------
 * The /sources page is re-framed from a roadmap board into the OSS
 * Source Fabric view. Acquisition-mode chips: free modes read positive
 * (the OSS-first path), the licensed feed reads dim (an optional
 * accelerator, never the core). Signal chips are neutral. Evidence-grade
 * chips: review-grade reads strong, supporting reads dim. */
.chip--acq-free {
    color: var(--band-strong);
    border-color: rgba(201, 168, 106, 0.45);
    background: rgba(201, 168, 106, 0.10);
}
.chip--acq-licensed {
    color: var(--fg-dim);
    border-color: rgba(154, 160, 168, 0.35);
    background: rgba(154, 160, 168, 0.08);
}
.chip--acq-licensed::before { content: "€ "; }
.chip--signal { color: var(--fg-dim); }
.chip--evidence-review {
    color: var(--band-strong);
    border-color: rgba(201, 168, 106, 0.45);
    background: rgba(201, 168, 106, 0.10);
}
.chip--evidence-supporting { color: var(--fg-dim); }

/* --- Inline-variant of the CTA used in the empty-state ------- */

.dashboard-cta--inline {
    display: inline-flex;
    margin: 0.5rem 0;
    font-size: 0.75rem;
    padding: 0.5rem 0.85rem;
}

/* ===========================================================
 * Sprint 23 — Stage-5 + Stage-6 visibility panels
 * Mandate-detail: connector telemetry table.
 * Brief-detail:  scoring breakdown (quadrant + score bars + trajectory).
 * Reuses dark-gold tokens + decision-band chips; adds:
 *   --band-skipped  (gray, distinct from --band-insufficient pure-grey
 *                    so SKIPPED reads as "intentional skip" not "thin
 *                    evidence")
 * =========================================================== */

:root {
    --band-skipped: #8a8e94;       /* slate-grey — operator-skipped */
    --band-unknown: #6b7280;       /* deeper grey — fallback for unknown statuses */
}

.stage-panel {
    margin: 1.5rem 0 0;
    padding: 1rem 1.1rem 1.1rem;
    border: 1px solid var(--border);
    border-radius: 3px;
    background: rgba(255, 255, 255, 0.015);
}

.stage-panel__title {
    margin: 0 0 0.6rem;
    /* Sprint 37 (v0.6.23): same --text-h2 wiring as .review-block h2 — the
       "Bewertung" panel-title is structurally an H2 even when the element
       happens to be <h2> with its own class. Without this, the hierarchy
       drop from page-hero H1 → 16px panel title is visually a section break. */
    font-size: var(--text-h2);
    font-weight: 600;
    color: var(--accent);
    letter-spacing: 0.04em;
}

.stage-panel__lede {
    margin: 0 0 0.75rem;
    font-size: 0.78rem;
}

.stage-panel h3 {
    margin: 1rem 0 0.4rem;
    font-size: 0.78rem;
    color: var(--fg);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.stage-panel__table-wrap {
    overflow-x: auto;
}

/* --- Connector telemetry table ----------------------------- */

.connector-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.8rem;
}

.connector-table thead th {
    text-align: left;
    color: var(--fg-dim);
    text-transform: uppercase;
    font-size: 0.65rem;
    letter-spacing: 0.1em;
    padding: 0.35rem 0.5rem;
    border-bottom: 1px solid var(--border);
    font-weight: 500;
}

.connector-table tbody td {
    padding: 0.45rem 0.5rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.04);
    vertical-align: middle;
}

.connector-table tbody tr:last-child td { border-bottom: 0; }

.connector-table__name code { font-size: 0.78rem; color: var(--fg); }
.connector-table__count { font-variant-numeric: tabular-nums; }
.connector-table__ts code { font-size: 0.7rem; color: var(--fg-dim); }
.connector-table__reason { font-size: 0.74rem; max-width: 20rem; }

/* Connector-outcome chip rules now live with the job-status family
 * higher up in the file (Sprint 25 Move 15 — execution-tier mono
 * treatment + glyph prefix). Single source for both axes. */

/* --- Stage-6 score grid + bars ----------------------------- */

.score-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
    gap: 0.75rem 1.25rem;
    margin: 0.25rem 0 0.75rem;
}

.score-cell { display: flex; flex-direction: column; gap: 0.35rem; }

.score-cell__label {
    color: var(--fg-dim);
    text-transform: uppercase;
    font-size: 0.66rem;
    letter-spacing: 0.1em;
}

.score-cell__value {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    flex-wrap: wrap;
}

.score-bar {
    display: inline-block;
    position: relative;
    width: 8rem;
    height: 0.55rem;
    background: rgba(255, 255, 255, 0.05);
    border-radius: 2px;
    overflow: hidden;
}

.score-bar--mini { width: 5rem; height: 0.4rem; }

.score-bar__fill {
    display: block;
    height: 100%;
    background: var(--accent);
    transition: width 0.2s ease;
}

.score-bar__num {
    font-variant-numeric: tabular-nums;
    font-size: 0.78rem;
    color: var(--fg);
}

.kv--compact {
    grid-template-columns: minmax(8rem, max-content) 1fr;
    gap: 0.25rem 0.85rem;
    font-size: 0.78rem;
}

.kv--compact dd { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }

/* Quadrant chips — reuse band-tokens. top_pick = gold; auto_enrich =
   amber; b_list = blue; reject = red; unknown = grey. We allow both
   the spec quadrant names AND the report_builder-emitted variants
   (shortlist/longlist/wildcard/out_of_scope) so future relabels don't
   silently drop styling. */
.chip--quadrant-top_pick      { color: var(--band-strong); border-color: rgba(201, 168, 106, 0.45); background: rgba(201, 168, 106, 0.10); }
.chip--quadrant-auto_enrich   { color: var(--band-cautious); border-color: rgba(212, 168, 90, 0.45); background: rgba(212, 168, 90, 0.10); }
.chip--quadrant-shortlist     { color: var(--band-cautious); border-color: rgba(212, 168, 90, 0.45); background: rgba(212, 168, 90, 0.10); }
.chip--quadrant-b_list        { color: var(--band-needs); border-color: rgba(122, 184, 217, 0.40); background: rgba(122, 184, 217, 0.08); }
.chip--quadrant-longlist      { color: var(--band-needs); border-color: rgba(122, 184, 217, 0.40); background: rgba(122, 184, 217, 0.08); }
.chip--quadrant-wildcard      { color: var(--band-needs); border-color: rgba(122, 184, 217, 0.40); background: rgba(122, 184, 217, 0.08); }
.chip--quadrant-reject        { color: var(--band-blocked); border-color: rgba(240, 128, 128, 0.45); background: rgba(240, 128, 128, 0.10); }
.chip--quadrant-out_of_scope  { color: var(--band-skipped); border-color: rgba(138, 142, 148, 0.40); background: rgba(138, 142, 148, 0.08); }
.chip--quadrant-unknown       { color: var(--band-unknown); border-color: rgba(107, 114, 128, 0.40); background: rgba(107, 114, 128, 0.08); }

/* Sprint 25 Move 4: banker-vocab quadrant chips. The quadrant_chip_class
   Jinja filter emits these slugs (tier-1 / tier-2 / watchlist / aus /
   unbekannt) — same colors as the engineering-vocab classes above so a
   future enum rename does not silently restyle. */
.chip--quadrant-tier-1        { color: var(--band-strong); border-color: rgba(201, 168, 106, 0.45); background: rgba(201, 168, 106, 0.10); }
.chip--quadrant-tier-2        { color: var(--band-needs); border-color: rgba(122, 184, 217, 0.40); background: rgba(122, 184, 217, 0.08); }
.chip--quadrant-watchlist     { color: var(--band-cautious); border-color: rgba(212, 168, 90, 0.45); background: rgba(212, 168, 90, 0.10); }
.chip--quadrant-aus           { color: var(--band-blocked); border-color: rgba(240, 128, 128, 0.45); background: rgba(240, 128, 128, 0.10); }
.chip--quadrant-unbekannt     { color: var(--band-unknown); border-color: rgba(107, 114, 128, 0.40); background: rgba(107, 114, 128, 0.08); }

/* Pipeline-action chip — secondary information chip beside a verdict
   chip when the schema value is a pipeline action (currently only
   `auto_enrich`). Mono-coloured, smaller weight so it does not compete
   with the verdict. */
.chip--pipeline-action {
    color: var(--fg-dim);
    border-color: rgba(154, 160, 168, 0.30);
    background: rgba(154, 160, 168, 0.05);
    font-size: 0.62rem;
    text-transform: none;
    letter-spacing: 0;
}

/* Inline variant of placeholder-card used inside stage-panels — looser
   padding + no top border (the panel itself supplies the frame). */
.placeholder-card--inline {
    margin: 0;
    padding: 0.65rem 0.85rem;
    border: 1px dashed var(--border);
    border-radius: 3px;
    background: transparent;
    font-size: 0.8rem;
}

/* ===========================================================================
 * Sprint 35 (v0.6.21) — Pipeline-Status card.
 *
 * Customer-readable replacement for the "Quellenstatus nicht verfügbar"
 * placeholder. Shows ONE of four states (idle / queued / running /
 * failed) with state-tinted left-border so the eye triages instantly.
 * Operator-feedback 2026-05-18: "der kunde kann keinerlei vorstellung
 * davon gewinnen wie lange das produkt noch braucht" → this card
 * carries the duration estimate + concrete next step per state.
 * =========================================================================== */

.pipeline-status {
    margin: 0;
    padding: var(--space-4, 1rem) var(--space-6, 1.5rem);
    background: var(--color-bg-elev, var(--navy-800));
    border: 1px solid var(--color-brand-border, rgba(201, 168, 106, 0.45));
    border-left: 3px solid var(--color-text-faint, #6b7280);
    border-radius: var(--radius-md, 4px);
    font-size: var(--text-sm, 0.875rem);
    line-height: var(--leading-snug, 1.4);
    color: var(--color-text, var(--fg));
}

.pipeline-status--idle    { border-left-color: var(--color-text-subtle, var(--fg-dim)); }
.pipeline-status--queued  { border-left-color: var(--color-state-info, var(--teal-500)); }
.pipeline-status--running { border-left-color: var(--color-brand, var(--accent)); }
.pipeline-status--failed  { border-left-color: var(--color-state-bad, var(--red-500)); }
.pipeline-status--done    { border-left-color: var(--color-state-good, var(--gold-500)); }

.pipeline-status__title {
    display: inline-block;
    font-size: var(--text-base, 1rem);
    font-weight: var(--weight-semibold, 600);
    color: var(--color-text, var(--fg));
    margin-bottom: var(--space-2, 0.5rem);
}

.pipeline-status--queued  .pipeline-status__title { color: var(--color-state-info, var(--teal-500)); }
.pipeline-status--running .pipeline-status__title { color: var(--color-brand, var(--accent)); }
.pipeline-status--failed  .pipeline-status__title { color: var(--color-state-bad, var(--red-500)); }

.pipeline-status__lead {
    margin: 0 0 var(--space-3, 0.75rem) 0;
    color: var(--color-text-subtle, var(--fg-dim));
    line-height: var(--leading-base, 1.5);
}

.pipeline-status__meta {
    display: grid;
    grid-template-columns: max-content 1fr;
    column-gap: var(--space-4, 1rem);
    row-gap: var(--space-1, 0.25rem);
    margin: 0;
    font-size: var(--text-xs, 0.75rem);
}

.pipeline-status__meta dt {
    color: var(--color-text-faint, #6b7280);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: var(--weight-medium, 500);
}

.pipeline-status__meta dd {
    margin: 0;
    color: var(--color-text-subtle, var(--fg-dim));
    word-break: break-word;
}

.pipeline-status__meta code {
    background: var(--color-bg, var(--navy-900));
    padding: 0.1rem 0.35rem;
    border-radius: var(--radius-sm, 2px);
    font-size: var(--text-xs, 0.75rem);
    color: var(--color-text, var(--fg));
}

@media (max-width: 519px) {
    .pipeline-status__meta {
        grid-template-columns: 1fr;
        row-gap: var(--space-2, 0.5rem);
    }
    .pipeline-status__meta dd { padding-bottom: var(--space-2, 0.5rem); border-bottom: 1px dashed rgba(255,255,255,0.05); }
}

/* ===========================================================================
 * Sprint 25 Move 7 — brief_detail hero strip
 *
 * 5-tile triage grid at the very top of brief_detail.html: Verdict +
 * Attractiveness + Decision Readiness + Decision Band + Recommended
 * Action. A banker should be able to decide "worth a partner call?"
 * in under 2 seconds without scrolling.
 *
 * Layout: CSS grid with intrinsic minmax so the 5 tiles collapse to
 * 2 columns under ~900px and 1 column on phones. No new color tokens —
 * reuses --bg-elev / --border / --accent / --band-*.
 * =========================================================================== */
.hero-strip {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    gap: 0.75rem;
    margin: 1.25rem 0 1.5rem 0;
}

.hero-strip__tile {
    background: var(--bg-elev);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 0.75rem 0.9rem 0.85rem;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    min-height: 5.5rem;
}

.hero-strip__tile--action {
    /* Recommended-Action tile spans 2 cols on wide layouts so the
       sentence breathes. */
    grid-column: span 2;
}
@media (max-width: 60rem) {
    .hero-strip__tile--action { grid-column: span 1; }
}

.hero-strip__label {
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--fg-dim);
    font-weight: 600;
}

.hero-strip__value {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    color: var(--fg);
}

.hero-strip__value--text {
    font-size: 0.92rem;
    line-height: 1.4;
    color: var(--fg);
}

.hero-strip__num {
    font-size: 1.5rem;
    font-weight: 600;
    color: var(--accent);
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}
/* v0.6.50 — leverage tile when EBITDA is non-positive: the multiple is
   undefined, so the "n/a" reads in the warn colour, not the gold accent
   (which would imply a real, in-range figure). */
.hero-strip__num--na {
    color: var(--color-state-warn, #d4a85a);
    font-size: 1.3rem;
}

/* Larger chip variant for the hero strip — same colors, slightly more
   prominent than the inline chips inside the review blocks below. */
.chip--hero {
    font-size: 0.72rem;
    padding: 0.18rem 0.55rem;
    letter-spacing: 0.04em;
}

/* Thicker score-bar variant for the hero tile — 8px tall vs the
   default 4px, narrower max-width so the numeric value sits next to
   it rather than below. */
.score-bar--hero {
    height: 8px;
    width: 6rem;
    flex-shrink: 0;
}

/* Sprint 25 Tier 4 — brief-page action row: PDF-download + Back. */
.page-header__actions {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    flex-wrap: wrap;
}
.back-link--cta {
    color: var(--color-brand, var(--accent));
    border-color: var(--color-brand-border, rgba(201, 168, 106, 0.45));
    background: var(--color-brand-bg, rgba(201, 168, 106, 0.10));
    border-style: solid;
    border-width: 1px;
    padding: 0.2rem 0.6rem;
    border-radius: 4px;
}
.back-link--cta:hover {
    background: rgba(201, 168, 106, 0.18);
}

/* ===========================================================================
 * Sprint 25 Tier 5 — Accessibility + Performance
 *
 * Closes the Frontend reviewer's WCAG 2.2 findings:
 *   - SC 2.4.11 (Focus Not Obscured) + 2.4.13 (Focus Appearance) —
 *     keyboard tab through the mandate-new form landed on radio/check
 *     chips with no visible ring on dark navy.
 *   - SC 2.4.1 (Bypass Blocks) — skip-link missing.
 *   - SC 2.4.7 (Focus Visible) — :focus-visible discipline.
 *   - CLS reservation on the status-banner so the queued -> running ->
 *     done transitions don't jolt the page.
 * =========================================================================== */

/* Global :focus-visible — gold outline + offset so it reads on the
 * dark navy background without competing with the chip colors. */
:focus-visible {
    outline: 2px solid var(--color-brand, var(--accent));
    outline-offset: 2px;
    border-radius: 2px;
}
/* Suppress the default browser focus ring for mouse-down clicks where
 * :focus-visible would be redundant (matches the post-2020 norm). */
:focus:not(:focus-visible) { outline: none; }

/* Skip-link — invisible until focused, then a gold pill at the top
 * of the page that jumps to #main-content. */
.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 1000;
    padding: 0.5rem 1rem;
    background: var(--color-brand, var(--accent));
    color: var(--color-bg, var(--bg));
    font-size: 0.875rem;
    font-weight: 600;
    text-decoration: none;
    border-radius: 0 0 4px 4px;
}
.skip-link:focus,
.skip-link:focus-visible {
    left: 0;
    outline: 2px solid var(--color-text, var(--fg));
    outline-offset: -4px;
}

/* CLS reservation on the status banner — the queued / running / done
 * transitions each render slightly different banner heights. Reserving
 * a min-height stops the brief grid below from jumping. */
#status-banner {
    min-height: 4rem;
    transition: opacity var(--motion-base, 200ms) var(--motion-ease, ease);
}
#status-banner[data-status="none"] {
    min-height: 0;
}

/* Sprint 26 — clickable connector chips in the Stage-5 Sourcing table.
 * The chip-as-link keeps the same visual treatment but adds a hover
 * indicator + removes the default <a> blue underline. */
a.chip--linked {
    text-decoration: none;
    cursor: pointer;
    transition: filter var(--motion-fast, 120ms) var(--motion-ease, ease);
}
a.chip--linked:hover,
a.chip--linked:focus-visible {
    filter: brightness(1.25);
}

/* Sprint 27 — clickable evidence-gap entries. The gap-item__link wraps
 * the label + source so the whole row is hover-actionable; the hint
 * pill on the right makes the affordance discoverable. */
.gap-item__link {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--fg, var(--color-text));
    text-decoration: none;
    border-bottom: 1px dashed transparent;
    transition: border-color var(--motion-fast, 120ms) var(--motion-ease, ease);
}
.gap-item__link:hover,
.gap-item__link:focus-visible {
    border-bottom-color: var(--color-brand, var(--accent));
}
.gap-item__retry-hint {
    font-size: 0.65rem;
    color: var(--color-brand, var(--accent));
    border: 1px solid var(--color-brand-border, rgba(201, 168, 106, 0.45));
    background: var(--color-brand-bg, rgba(201, 168, 106, 0.10));
    padding: 0.05rem 0.4rem;
    border-radius: 2px;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

/* ===== Sprint 29 — Distress Surface ============================================
 * Christian-Spec distress-brief surface. New molecules:
 *   .peer-table .indicator-row .ratio-bar .cite .limitation .vertiefung-grid
 *   .vertiefung-card .distress-narrative .distress-chips
 * New chip variants: trigger-{a,b,ab,none} · urgency-{acute,mittelfristig,latent}
 *                    peer-{in_rahmen,erhoehtes_risiko,kritisch,unbekannt}
 *                    indicator-{bestaetigt,nicht_bestaetigt,keine_daten}
 *                    owner-{family,pe,listed,mbo} · cause · role
 * All colours pass WCAG AA against the navy-900 background. Defensive —
 * every unknown variant uses a neutral muted treatment so a future
 * enum-bump won't ghost-render.
 * ----------------------------------------------------------------------------- */

/* New token — distinct acute-red separate from the existing band-blocked
   red, so "AKUT" reads even when an unrelated band-blocked chip is on
   the same row. */
:root { --color-urgency-acute: #e85d5d; }

/* Hero-Strip — distress variant. */
.hero-strip--distress { margin-bottom: 1.5rem; }
.hero-strip__rule { display: block; font-size: 0.7rem; margin-top: 0.25rem; }

/* Ratio-Bar — bidirectional, threshold-aware. */
.ratio-bar {
    display: inline-block;
    position: relative;
    width: 8rem;
    height: 6px;
    background: var(--color-bg-elev, var(--bg-elev));
    border-radius: 1px;
    vertical-align: middle;
    margin: 0 0.4rem;
}
.ratio-bar__fill {
    display: block;
    height: 100%;
    border-radius: 1px;
    transition: width var(--motion-base, 200ms) var(--motion-ease, ease);
}
.ratio-bar__threshold {
    position: absolute;
    top: -2px;
    bottom: -2px;
    width: 1px;
    background: var(--color-brand-border, rgba(201, 168, 106, 0.45));
}
.ratio-bar[data-direction="negative-up"][data-class="good"] .ratio-bar__fill { background: var(--color-state-good, var(--accent)); }
.ratio-bar[data-direction="negative-up"][data-class="elevated"] .ratio-bar__fill { background: var(--color-state-warn, #d4a85a); }
.ratio-bar[data-direction="negative-up"][data-class="critical"] .ratio-bar__fill { background: var(--color-state-bad, #f08080); }
.ratio-bar[data-class="unknown"] .ratio-bar__fill { background: var(--color-text-faint, #6b7280); width: 0; }

/* Score-grid distress variant. */
.score-grid--leverage {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1rem;
    margin: 0.5rem 0 1rem;
}
@media (max-width: 720px) { .score-grid--leverage { grid-template-columns: 1fr; } }

/* v0.6.50 — leverage-callout for non-positive EBITDA. The multiple is
   undefined; this block states that honestly and still surfaces the
   absolute debt figures (which are known). */
.leverage-na-callout {
    margin: 0.5rem 0 1rem;
    padding: 0.85rem 1rem;
    border: 1px solid rgba(240, 128, 128, 0.35);
    border-left-width: 3px;
    border-radius: 6px;
    background: rgba(240, 128, 128, 0.06);
}
.leverage-na-callout__head {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
    margin: 0 0 0.4rem;
}
.leverage-na-callout p { margin: 0 0 0.5rem; }
.leverage-na-callout .dashboard-meta { margin: 0; }

.leverage-verdict {
    margin-top: 0.75rem;
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
}

/* Peer-Table — native semantic table. */
.peer-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--text-sm, 0.875rem);
    margin: 0.75rem 0 0.25rem;
}
.peer-table thead th {
    position: sticky;
    top: 0;
    background: var(--color-bg-elev, var(--bg-elev));
    border-bottom: 1px solid var(--color-brand-border, rgba(201, 168, 106, 0.45));
    padding: var(--space-2, 0.5rem) var(--space-3, 0.75rem);
    text-align: left;
    font-weight: 600;
    color: var(--color-text-subtle, var(--fg-dim));
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-size: 0.72rem;
}
.peer-table td,
.peer-table th.num,
.peer-table td.num {
    padding: var(--space-2, 0.5rem) var(--space-3, 0.75rem);
    border-bottom: 1px solid var(--border);
}
.peer-table th.num,
.peer-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.peer-table tr.peer-table__row--subject { background: rgba(201, 168, 106, 0.12); }
.peer-table tr.peer-table__row--subject td { border-bottom-color: var(--color-brand-border, rgba(201, 168, 106, 0.45)); }
.peer-table tr.peer-table__row--median {
    border-top: 2px solid var(--color-brand-border, rgba(201, 168, 106, 0.45));
    font-weight: 600;
}
.peer-table__verdict { white-space: nowrap; }

/* Indicator-Row — 3-col grid. */
.indicator-checklist { display: flex; flex-direction: column; gap: 0; }
.indicator-row {
    display: grid;
    grid-template-columns: max-content 1fr auto;
    gap: var(--space-3, 0.75rem);
    align-items: baseline;
    padding: var(--space-2, 0.5rem) 0;
    border-bottom: 1px solid var(--border);
}
.indicator-row:last-child { border-bottom: none; }
.indicator-row__main { min-width: 0; }
.indicator-row__label { color: var(--color-text, var(--fg)); }
.indicator-row__datapoint { font-variant-numeric: tabular-nums; font-size: var(--text-sm, 0.875rem); }
.indicator-row__source {
    color: var(--color-text-subtle, var(--fg-dim));
    font-size: var(--text-xs, 0.75rem);
    text-align: right;
}
.indicator-row__status { margin-right: 0.5rem; }
.indicator-row[data-status="bestaetigt"] { background: rgba(201, 168, 106, 0.04); }
.indicator-row__limitation { font-size: var(--text-xs, 0.75rem); margin-top: 0.25rem; }

/* Cite atom — inline source citation. */
.cite {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: var(--text-xs, 0.75rem);
    color: var(--color-text-subtle, var(--fg-dim));
    padding-left: var(--space-2, 0.5rem);
    border-left: 1px solid var(--color-brand-border, rgba(201, 168, 106, 0.45));
    margin-left: 0.4rem;
    text-decoration: none;
}
a.cite { border-bottom: 1px dotted var(--color-brand-border, rgba(201, 168, 106, 0.45)); }
a.cite:hover, a.cite:focus-visible {
    color: var(--color-brand, var(--accent));
    border-bottom-style: solid;
    text-decoration: none;
}
.cite__year { font-variant-numeric: tabular-nums; opacity: 0.7; margin-left: 0.2em; }

/* Limitation-callout. */
.limitation {
    display: flex;
    gap: var(--space-3, 0.75rem);
    padding: var(--space-3, 0.75rem) var(--space-4, 1rem);
    border: 1px solid rgba(212, 168, 90, 0.35);
    border-left: 3px solid var(--color-state-warn, #d4a85a);
    background: rgba(212, 168, 90, 0.04);
    border-radius: var(--radius-md, 4px);
    font-size: var(--text-sm, 0.875rem);
    color: var(--color-text, var(--fg));
    margin: 1.5rem 0;
}
.limitation__glyph {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-weight: 600;
    color: var(--color-state-warn, #d4a85a);
    flex-shrink: 0;
}
.limitation__body strong { display: block; margin-bottom: 0.4rem; }
.limitation__list { margin: 0; padding-left: var(--space-4, 1rem); }
.limitation__list li { padding: var(--space-1, 0.25rem) 0; }
.limitation__engine { color: var(--color-text-subtle, var(--fg-dim)); }

/* Vertiefung-Grid + cards. */
.review-block--vertiefung { background: rgba(255, 255, 255, 0.01); }
.vertiefung-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-4, 1rem);
}
@media (max-width: 720px) { .vertiefung-grid { grid-template-columns: 1fr; } }
.vertiefung-card {
    border: 1px solid var(--border);
    border-radius: var(--radius-md, 4px);
    padding: var(--space-3, 0.75rem) var(--space-4, 1rem);
    background: rgba(255, 255, 255, 0.02);
}
.vertiefung-card__lens {
    font-size: var(--text-xs, 0.75rem);
    color: var(--color-text-subtle, var(--fg-dim));
    text-transform: uppercase;
    letter-spacing: 0.08em;
}
.vertiefung-card__question {
    font-size: var(--text-base, 1rem);
    font-style: italic;
    color: var(--color-text, var(--fg));
    margin: var(--space-1, 0.25rem) 0 0;
}
.vertiefung-card__answer {
    font-size: var(--text-sm, 0.875rem);
    color: var(--color-text, var(--fg));
    margin: var(--space-2, 0.5rem) 0 0;
}

/* Distress narrative — Section 5 freitext. */
.distress-narrative {
    font-size: var(--text-base, 1rem);
    line-height: var(--leading-base, 1.5);
    color: var(--color-text, var(--fg));
    margin-top: var(--space-3, 0.75rem);
    padding: var(--space-3, 0.75rem);
    background: rgba(255, 255, 255, 0.02);
    border-left: 2px solid var(--color-brand-border, rgba(201, 168, 106, 0.45));
    border-radius: var(--radius-sm, 2px);
}
.distress-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
    margin: 0 0 0.5rem;
}

/* Chip variants — Trigger. */
.chip--trigger-none {
    color: var(--color-text-subtle, var(--fg-dim));
    border-color: var(--border);
}
.chip--trigger-a,
.chip--trigger-b {
    color: var(--color-state-warn, #d4a85a);
    border-color: rgba(212, 168, 90, 0.45);
    background: rgba(212, 168, 90, 0.10);
}
.chip--trigger-ab {
    color: var(--color-state-bad, #f08080);
    border-color: rgba(240, 128, 128, 0.45);
    background: rgba(240, 128, 128, 0.10);
}
/* v0.6.50 — non-positive-EBITDA standalone triggers. A negative or zero
   EBITDA is a hard distress signal — styled like the twin-trigger red so
   it never reads as benign. */
.chip--trigger-negative-ebitda,
.chip--trigger-zero-ebitda {
    color: var(--color-state-bad, #f08080);
    border-color: rgba(240, 128, 128, 0.45);
    background: rgba(240, 128, 128, 0.10);
}
/* Unknown / unmapped trigger value — warn-coloured, never neutral-green:
   an unrecognised status is an open question, not a confirmed absence. */
.chip--trigger-unclassified {
    color: var(--color-state-warn, #d4a85a);
    border-color: rgba(212, 168, 90, 0.45);
    background: rgba(212, 168, 90, 0.10);
}

/* Chip variants — Zeitdruck. */
.chip--urgency-acute {
    color: #fff;
    background: var(--color-urgency-acute);
    border-color: var(--color-urgency-acute);
}
.chip--urgency-mittelfristig {
    color: var(--color-state-warn, #d4a85a);
    border-color: rgba(212, 168, 90, 0.45);
    background: rgba(212, 168, 90, 0.10);
}
.chip--urgency-latent {
    color: var(--color-text-subtle, var(--fg-dim));
    border-color: var(--border);
}

/* Chip variants — Peer-Klassifikation. */
.chip--peer-in_rahmen {
    color: var(--color-state-good, var(--accent));
    background: rgba(201, 168, 106, 0.08);
    border-color: rgba(201, 168, 106, 0.45);
}
.chip--peer-erhoehtes_risiko {
    color: var(--color-state-warn, #d4a85a);
    background: rgba(212, 168, 90, 0.10);
    border-color: rgba(212, 168, 90, 0.45);
}
.chip--peer-kritisch {
    color: var(--color-state-bad, #f08080);
    background: rgba(240, 128, 128, 0.10);
    border-color: rgba(240, 128, 128, 0.45);
}
.chip--peer-unbekannt {
    color: var(--color-text-subtle, var(--fg-dim));
    border-color: var(--border);
}

/* Chip variants — Indikator-Status (with leading-glyph). */
.chip--indicator-bestaetigt {
    color: var(--color-state-good, var(--accent));
    background: rgba(201, 168, 106, 0.08);
    border-color: rgba(201, 168, 106, 0.45);
}
.chip--indicator-bestaetigt::before { content: "● "; color: var(--color-state-good, var(--accent)); }
.chip--indicator-nicht_bestaetigt {
    color: var(--color-state-warn, #d4a85a);
    border-color: rgba(212, 168, 90, 0.45);
}
.chip--indicator-nicht_bestaetigt::before { content: "▲ "; color: var(--color-state-warn, #d4a85a); }
.chip--indicator-keine_daten {
    color: var(--color-text-faint, #6b7280);
    border-color: var(--border);
}
.chip--indicator-keine_daten::before { content: "○ "; color: var(--color-text-faint, #6b7280); }

/* Chip variants — Eigentümer-Klassen. */
.chip--owner-listed   { color: var(--color-state-info, #7ab8d9); }
.chip--owner-pe       { color: var(--color-brand, var(--accent)); }
.chip--owner-family   { color: var(--color-state-good, var(--accent)); }
.chip--owner-mbo      { color: var(--color-text-subtle, var(--fg-dim)); }
.chip--owner-unknown  { color: var(--color-text-faint, #6b7280); }

/* Chip variants — semantic helpers (Cause, Role). */
.chip--cause { color: var(--color-state-warn, #d4a85a); border-color: rgba(212, 168, 90, 0.45); }
.chip--role  { color: var(--color-brand, var(--accent)); border-color: var(--color-brand-border, rgba(201, 168, 106, 0.45)); }

/* ===== Sprint 51 — ProceedingType chips (v0.6.32) ===========================
 * Reviewer 2 #2: 16 distress-NLP keywords now route into ProceedingType.
 * Deal-shape urgency colour semantics:
 *   gold   — debtor still negotiating  (Schutzschirm §270b, StaRUG §31)
 *   amber  — partially debtor-controlled / mid-stage
 *   teal   — pre-statutory (Sanierungsmoderation §94)
 *   red    — late stage, asset-deal only (Regelinsolvenz §1)
 *   slate  — kein Verfahren
 * ============================================================================ */
.chip--proceeding-schutzschirm,
.chip--proceeding-starug {
    color: var(--color-brand, var(--accent));
    background: rgba(201, 168, 106, 0.10);
    border-color: var(--color-brand-border, rgba(201, 168, 106, 0.45));
}
.chip--proceeding-eigenverwaltung,
.chip--proceeding-insolvenzplan {
    color: var(--color-state-warn, #d4a85a);
    background: rgba(212, 168, 90, 0.10);
    border-color: rgba(212, 168, 90, 0.45);
}
.chip--proceeding-sanierungsmoderation {
    color: var(--color-state-info, #7ab8d9);
    background: rgba(122, 184, 217, 0.10);
    border-color: rgba(122, 184, 217, 0.45);
}
.chip--proceeding-regelinsolvenz {
    color: var(--color-state-bad, #f08080);
    background: rgba(240, 128, 128, 0.10);
    border-color: rgba(240, 128, 128, 0.45);
}
.chip--proceeding-keinverfahren {
    color: var(--color-text-faint, #6b7280);
    border-color: var(--border);
}

/* ===========================================================================
 * Sprint 30A — App-Shell (v0.6.16).
 *
 * Persistent header + breadcrumb for every authenticated surface. Replaces
 * the giant centered login-style brand block that authenticated pages were
 * inheriting from `dashboard.html` onward.
 *
 * Layout strategy:
 *  - Position: sticky at top so the nav stays visible while scrolling long
 *    briefs and tables. NOT fixed — pages without enough content don't get
 *    a phantom-scroll the way fixed positioning would cause.
 *  - Height: 56px header band + optional ~32px breadcrumb row.
 *  - Backdrop: solid navy-800 (one elev-step above body) with a thin
 *    bottom hairline using the brand-border alpha. No blur — saves a
 *    compositing layer on lower-tier hardware.
 *  - The shell is OUTSIDE the .app-main wrapper so a page's `width:100%`
 *    constraints don't pinch the header.
 *
 * Z-stack:
 *  - bg-canvas:      z-index: 0  (the existing decorative canvas)
 *  - app-main:       z-index: 1
 *  - app-header:     z-index: 50 (above content, below modals/toasts)
 * ========================================================================= */

/* Body + main are flex-centered for the login surface (a single
   26rem-wide form, vertically centered on a 100vh viewport). That
   layout breaks the app-shell completely — content gets pinched into
   a 416px column on a 1920px screen, and the sticky header can't
   stick because the body itself is flex-centered.

   Override those rules ONLY when the page contains an .app-header.
   :has() is widely supported (Chrome 105+, Safari 15.4+, Firefox 121+);
   the @supports gate gracefully degrades on the few engines that don't. */

@supports selector(body:has(*)) {
    body:has(.app-header) {
        display: block;
        align-items: initial;
        justify-content: initial;
        padding: 0;
        min-height: 100vh;
    }
    body:has(.app-header) > main,
    body:has(.app-header) .app-main {
        max-width: 1400px;
        width: 100%;
        padding-inline: var(--space-6, 1.5rem);
    }
}

/* Fallback: any page with body class containing 'page' (e.g.
   dashboard-page, mandate-page) opts into the app-shell layout
   override. Safer than relying purely on :has() and a no-cost
   override since the templates already emit these classes. */
body.dashboard-page:has(.app-header),
body.mandates-page,
body.mandate-page,
body.brief-page,
body.mandate-new-page,
body.connector-page {
    display: block;
    align-items: initial;
    justify-content: initial;
    padding: 0;
}

body.mandates-page > main,
body.mandate-page > main,
body.brief-page > main,
body.mandate-new-page > main,
body.connector-page > main,
body.dashboard-page > main {
    max-width: 1400px;
    width: 100%;
}

.app-header {
    position: sticky;
    top: 0;
    z-index: 50;
    background: var(--color-bg-elev, var(--navy-800));
    border-bottom: 1px solid var(--color-brand-border, rgba(201, 168, 106, 0.45));
    /* The canvas behind the body is decorative; keeping the header opaque
       guarantees text contrast meets WCAG AA regardless of canvas pattern. */
    backdrop-filter: none;
}

.app-header__inner {
    display: flex;
    align-items: center;
    gap: var(--space-6, 1.5rem);
    height: 56px;
    padding: 0 var(--space-6, 1.5rem);
    max-width: 1400px;
    margin: 0 auto;
}

.app-header__brand {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2, 0.5rem);
    color: var(--color-text, var(--fg));
    text-decoration: none;
    flex: 0 0 auto;
}

.app-header__brand:hover,
.app-header__brand:focus-visible {
    color: var(--color-brand, var(--accent));
    outline: none;
}

.app-header__logo {
    height: 28px;
    width: auto;
    display: block;
}

/* Sprint 61 — the logo PNG already carries the "Lacuna" wordmark; the
   separate brand-text <span> rendered "Lacuna" a second time right
   next to it. The span + this rule are removed. */

/* The nav-wrap is a <details> element so the mobile menu works with no
   JS. On viewports ≥720px we override its display so the nav is always
   visible and the summary is hidden. */
.app-header__nav-wrap {
    flex: 1 1 auto;
    min-width: 0;
}

.app-header__nav-wrap > summary {
    list-style: none;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2, 0.5rem);
    padding: var(--space-2, 0.5rem) var(--space-3, 0.75rem);
    border-radius: var(--radius-md, 4px);
    color: var(--color-text-subtle, var(--fg-dim));
    font-size: var(--text-sm, 0.875rem);
    transition: color var(--motion-fast, 120ms) var(--motion-ease, ease);
}

.app-header__nav-wrap > summary::-webkit-details-marker { display: none; }
.app-header__nav-wrap > summary::marker { content: ''; }

.app-header__nav-wrap > summary:hover,
.app-header__nav-wrap > summary:focus-visible {
    color: var(--color-text, var(--fg));
    outline: none;
}

.app-header__nav-toggle-icon {
    font-size: 1.25rem;
    line-height: 1;
}

.app-header__nav {
    display: flex;
    gap: var(--space-2, 0.5rem);
    margin-top: var(--space-2, 0.5rem);
    padding: var(--space-2, 0.5rem);
    background: var(--color-bg-inset, var(--navy-700));
    border: 1px solid var(--color-brand-border, rgba(201, 168, 106, 0.45));
    border-radius: var(--radius-md, 4px);
    flex-direction: column;
    position: absolute;
    min-width: 12rem;
    box-shadow: var(--shadow-md, 0 4px 12px rgba(0,0,0,0.35));
}

.app-header__nav-link {
    display: inline-block;
    padding: var(--space-2, 0.5rem) var(--space-4, 1rem);
    color: var(--color-text-subtle, var(--fg-dim));
    text-decoration: none;
    font-size: var(--text-sm, 0.875rem);
    font-weight: var(--weight-medium, 500);
    border-radius: var(--radius-md, 4px);
    transition: color var(--motion-fast, 120ms) var(--motion-ease, ease),
                background var(--motion-fast, 120ms) var(--motion-ease, ease);
    position: relative;
}

.app-header__nav-link:hover,
.app-header__nav-link:focus-visible {
    color: var(--color-text, var(--fg));
    background: rgba(255, 255, 255, 0.04);
    outline: none;
}

.app-header__nav-link.is-active {
    color: var(--color-brand, var(--accent));
}

/* Desktop layout: ≥720px → flatten the <details>, show nav inline,
   hide the toggle. */
@media (min-width: 720px) {
    .app-header__nav-wrap > summary { display: none; }
    .app-header__nav {
        position: static;
        flex-direction: row;
        margin: 0;
        padding: 0;
        background: transparent;
        border: none;
        box-shadow: none;
        min-width: 0;
    }
    .app-header__nav-link.is-active::after {
        content: "";
        position: absolute;
        left: var(--space-4, 1rem);
        right: var(--space-4, 1rem);
        bottom: -19px;  /* meets the header's bottom-border */
        height: 2px;
        background: var(--color-brand, var(--accent));
    }
}

/* Sprint 59 — user-menu polish. The previous treatment (plain dim
   username + thin-outline "ABMELDEN" button) read as unfinished. The
   block is now an avatar-anchored unit: a gold-tinted initial disc, a
   full-weight username, and a borderless ghost logout button that
   only fills on hover. */
.app-header__user {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2, 0.5rem);
    flex: 0 0 auto;
    margin-left: auto;
}

.app-header__avatar {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    background: linear-gradient(135deg,
                rgba(201, 168, 106, 0.32),
                rgba(201, 168, 106, 0.07));
    border: 1px solid rgba(201, 168, 106, 0.5);
    color: var(--color-brand, var(--accent));
    font-size: 0.8rem;
    font-weight: 600;
    line-height: 1;
    text-transform: uppercase;
    user-select: none;
}

.app-header__username {
    color: var(--color-text, var(--fg));
    font-size: var(--text-sm, 0.875rem);
    font-weight: 500;
    max-width: 12rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    margin-right: var(--space-1, 0.25rem);
}

/* Sprint 63 — THE actual cause of the logout button "hanging out of
   the header". The global `form {}` rule (login.css:80) styles EVERY
   <form> as a login-style card: var(--bg-elev) background, a border,
   border-radius, and `padding: 2rem 1.75rem` (64px of vertical
   padding). The header logout IS a <form>, so it rendered as a ~94px
   bordered panel dropping out the bottom of the 56px header. Sprint 59
   + 61 only ever touched the inner <button>; the <form> card-styling
   was never reset. Strip it to a bare inline wrapper. */
.app-header__logout {
    display: inline-flex;
    align-items: center;
    margin: 0;
    padding: 0;
    background: none;
    border: 0;
    border-radius: 0;
    gap: 0;
}

/* Sprint 61 — vertical alignment fix. The button carried only
   top/bottom padding for its height; the inline <svg> defaulted to
   baseline alignment, adding descender space and pushing the button
   off the header's centre line ("sitzt nicht sauber"). Now: an
   explicit 30px box (matching the avatar disc), line-height:1, and a
   block-level icon so flex centring is exact. */
.app-header__logout-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    height: 30px;
    box-sizing: border-box;
    /* Reset the global `button {}` margin-top:0.5rem so the button is
       not nudged off the header's vertical centre. */
    margin: 0;
    background: transparent;
    color: var(--color-text-subtle, var(--fg-dim));
    border: 1px solid transparent;
    padding: 0 0.7rem;
    border-radius: var(--radius-md, 6px);
    font-size: var(--text-xs, 0.78rem);
    font-weight: 500;
    line-height: 1;
    text-transform: none;
    letter-spacing: 0;
    cursor: pointer;
    transition: color var(--motion-fast, 120ms) var(--motion-ease, ease),
                background-color var(--motion-fast, 120ms) var(--motion-ease, ease);
}

.app-header__logout-btn:hover,
.app-header__logout-btn:focus-visible {
    color: var(--color-brand, var(--accent));
    background: rgba(201, 168, 106, 0.12);
    outline: none;
}

.app-header__logout-icon {
    display: block;
    flex: 0 0 auto;
    opacity: 0.85;
}

/* Hide-on-narrow username + logout label — the avatar anchors identity,
   the logout icon-button stays the action. */
@media (max-width: 519px) {
    .app-header__username { display: none; }
    .app-header__logout-label { display: none; }
    .app-header__logout-btn { padding: 0; width: 30px; justify-content: center; }
}

/* Breadcrumb row */
.app-header__breadcrumb {
    border-top: 1px solid rgba(201, 168, 106, 0.15);
    background: var(--color-bg, var(--navy-900));
}

.app-header__crumbs {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2, 0.5rem);
    align-items: center;
    margin: 0;
    padding: var(--space-2, 0.5rem) var(--space-6, 1.5rem);
    max-width: 1400px;
    margin-inline: auto;
    font-size: var(--text-xs, 0.75rem);
    color: var(--color-text-subtle, var(--fg-dim));
}

.app-header__crumb { display: inline-flex; align-items: center; gap: var(--space-2, 0.5rem); }
.app-header__crumb a {
    color: var(--color-text-subtle, var(--fg-dim));
    text-decoration: none;
    transition: color var(--motion-fast, 120ms) var(--motion-ease, ease);
}
.app-header__crumb a:hover,
.app-header__crumb a:focus-visible {
    color: var(--color-brand, var(--accent));
    outline: none;
}
.app-header__crumb.is-current {
    color: var(--color-text, var(--fg));
    font-weight: var(--weight-medium, 500);
}
.app-header__crumb-sep {
    color: var(--color-text-faint, #6b7280);
    user-select: none;
}

/* Content wrapper for authenticated pages. The login-style centered
   layout from `main { display:grid; place-items:center; min-height:100vh }`
   would now compete with the sticky header, so we provide an alternative
   main for shelled pages that scrolls naturally. */
.app-main {
    max-width: 1400px;
    margin: 0 auto;
    padding: var(--space-6, 1.5rem) var(--space-6, 1.5rem) var(--space-8, 2rem);
    width: 100%;
    box-sizing: border-box;
    /* Override the login-page main that centers via grid. The base.html
       has no main at all; .app-main wins because pages extending app.html
       no longer hit the `main { display:grid; place-items:center }` rule
       — but for safety we re-state it. */
    display: block;
    min-height: auto;
}

/* Reduce-motion: kill the bottom-border underline transition. */
@media (prefers-reduced-motion: reduce) {
    .app-header__nav-link,
    .app-header__logout-btn,
    .app-header__brand,
    .app-header__crumb a { transition: none; }
}


/* =========================================================================
 * Sprint 33 — UI polish layer (v0.6.19).
 *
 * Layout primitives the templates lean on:
 *
 *   .container             — centered max-w 1100px content column
 *   .container--narrow     — 720px for forms / dashboard / focused reading
 *   .container--wide       — 1400px for data-dense briefs + mandate-detail
 *   .page-hero             — top-of-page molecule: eyebrow + h1 + lead +
 *                            back-link, with subtle gold-hairline divider
 *   .page-hero__decoration — per-surface accent (buy-side / distress / dash)
 *   .page-body             — vertical-rhythm wrapper around sections
 *   .section               — single content block with --rhythm gap-after
 *
 * Banker-tool reference: 1100px reading width matches Pitchbook / S&P CIQ
 * so long pages stop feeling stretched on 1920px screens.
 * ========================================================================= */

.container,
.container--narrow,
.container--wide {
    width: 100%;
    margin-inline: auto;
    padding-inline: var(--page-padding-x, 1.5rem);
    box-sizing: border-box;
}

.container          { max-width: var(--container-base,   1100px); }
.container--narrow  { max-width: var(--container-narrow,  720px); }
.container--wide    { max-width: var(--container-wide,  1400px); }

/* Page-hero — the top-of-page molecule. Each route gets a distinct
   .page-hero__eyebrow so the operator can identify the surface by
   peripheral vision (the "wechselnde grafiken" problem). */

.page-hero {
    position: relative;
    padding: var(--rhythm-loose, 2.5rem) 0 var(--rhythm, 1.5rem);
    margin-bottom: var(--rhythm-loose, 2.5rem);
    border-bottom: 1px solid var(--color-brand-border, rgba(201, 168, 106, 0.45));
    overflow: hidden;
}

/* Sprint 37 (v0.6.23): dense-surface page-hero compaction.
   Reviewer 3 (Banker IA) + Reviewer 11 (Product Strategist) converged on:
   the verdict-band on /mandates/<id>/brief/<slug> sits 290-340px below
   the viewport top on a 1080-line desktop and falls below the fold on
   1366×768. The structural driver is ~104px of chrome around the
   page-hero block on these dense surfaces. Drop padding-top from
   --rhythm-loose to --rhythm (40px → 24px), bottom-padding to --space-3
   (24px → 12px), and margin-bottom to --rhythm (40px → 24px). Net
   saving: ~80px vertical. */
.brief-detail-page .page-hero,
.mandate-detail-page .page-hero {
    padding: var(--rhythm, 1.5rem) 0 var(--space-3, 0.75rem);
    margin-bottom: var(--rhythm, 1.5rem);
}

/* Sprint 37 (v0.6.23): dense-surface .dashboard-shell neutralization.
   The .dashboard-shell envelope adds 2rem×1.75rem of padding plus a
   1px border + elevated background. On the dashboard landing this is
   correct (it IS the card). On brief-detail / mandate-detail it adds
   a second container around content that already has .page-body
   padding from app.html — the result is a nested-card visual that
   pushes verdict content further down. Strip the visual envelope so
   the inner sections sit directly on the page background. */
.brief-detail-page .dashboard-shell,
.mandate-detail-page .dashboard-shell {
    background: transparent;
    border: 0;
    padding: 0;
}

.page-hero__inner {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    gap: var(--rhythm-tight, 1rem);
}

.page-hero__eyebrow {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2, 0.5rem);
    font-size: 0.6875rem;     /* 11pt */
    font-weight: var(--weight-semibold, 600);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--color-brand, var(--accent));
    margin: 0;
}

.page-hero__eyebrow--distress {
    color: var(--color-state-warn, var(--amber-500));
}

.page-hero__title {
    margin: 0;
    font-size: var(--text-h1, 2rem);
    font-weight: var(--weight-semibold, 600);
    line-height: var(--leading-tight, 1.2);
    letter-spacing: -0.01em;
    color: var(--color-text, var(--fg));
}

.page-hero__lead {
    margin: 0;
    font-size: 1.125rem;
    line-height: var(--leading-snug, 1.4);
    color: var(--color-text-subtle, var(--fg-dim));
    max-width: 60ch;
}

.page-hero__actions {
    display: inline-flex;
    flex-wrap: wrap;
    gap: var(--space-3, 0.75rem);
    align-items: center;
    margin-top: var(--space-2, 0.5rem);
}

.page-hero__chips {
    display: inline-flex;
    flex-wrap: wrap;
    gap: var(--space-2, 0.5rem);
}

/* Per-surface decorative accent. Opacity capped at 0.06-0.08 so it's
   texture, not decoration. */
.page-hero__decoration {
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: 0.06;
    z-index: 0;
}

.page-hero--dashboard .page-hero__decoration {
    background-image: radial-gradient(
        circle at 1px 1px,
        var(--color-brand, #c9a86a) 1px,
        transparent 1px
    );
    background-size: 18px 18px;
}

.page-hero--buyside .page-hero__decoration {
    background-image: repeating-linear-gradient(
        0deg,
        transparent 0px, transparent 7px,
        var(--color-brand, #c9a86a) 7px, var(--color-brand, #c9a86a) 8px
    );
}

.page-hero--distress {
    border-bottom-color: rgba(244, 144, 100, 0.35);
}
.page-hero--distress .page-hero__decoration {
    background-image: repeating-linear-gradient(
        135deg,
        transparent 0px, transparent 11px,
        var(--color-state-warn, #d4a85a) 11px, var(--color-state-warn, #d4a85a) 12px
    );
}

.page-hero--brief .page-hero__decoration {
    background-image: repeating-linear-gradient(
        45deg,
        transparent 0px, transparent 5px,
        var(--color-brand, #c9a86a) 5px, var(--color-brand, #c9a86a) 6px
    );
}

.page-hero--form .page-hero__decoration {
    background-image: repeating-linear-gradient(
        90deg,
        transparent 0px, transparent 23px,
        var(--color-brand, #c9a86a) 23px, var(--color-brand, #c9a86a) 24px
    );
}

.page-hero--connector .page-hero__decoration {
    background-image: radial-gradient(
        circle at 2px 2px,
        var(--teal-500, #7ab8d9) 1px,
        transparent 1px
    );
    background-size: 24px 24px;
}

.page-body {
    display: flex;
    flex-direction: column;
    gap: var(--rhythm-loose, 2.5rem);
}

.section { display: block; }
.section + .section { margin-top: 0; }

.page-body h1 {
    font-size: var(--text-h1, 2rem);
    line-height: var(--leading-tight, 1.2);
}
.page-body h2 {
    font-size: var(--text-h2, 1.5rem);
    line-height: var(--leading-tight, 1.2);
    margin-top: 0;
    margin-bottom: var(--rhythm-tight, 1rem);
}
.page-body h3 {
    font-size: var(--text-h3, 1.25rem);
    line-height: var(--leading-snug, 1.4);
    margin-top: 0;
    margin-bottom: var(--space-3, 0.75rem);
}

/* Tighten the legacy .page-header when both are present during migration. */
.page-hero ~ .page-header { display: none; }

/* Empty-state — used by mandates-list / brief grid when there's no data. */
.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--rhythm-tight, 1rem);
    padding: var(--rhythm-loose, 2.5rem) var(--rhythm, 1.5rem);
    text-align: center;
    background: rgba(201, 168, 106, 0.03);
    border: 1px dashed var(--color-brand-border, rgba(201, 168, 106, 0.45));
    border-radius: var(--radius-lg, 8px);
}

.empty-state__illustration {
    width: 120px;
    height: 120px;
    opacity: 0.7;
}

.empty-state__illustration img,
.empty-state__illustration svg {
    width: 100%;
    height: 100%;
    display: block;
}

.empty-state__title {
    font-size: 1.125rem;
    font-weight: var(--weight-semibold, 600);
    color: var(--color-text, var(--fg));
    margin: 0;
}

.empty-state__lead {
    font-size: var(--text-sm, 0.875rem);
    color: var(--color-text-subtle, var(--fg-dim));
    margin: 0;
    max-width: 48ch;
}

@media (max-width: 720px) {
    .page-hero {
        padding-top: var(--rhythm, 1.5rem);
        padding-bottom: var(--rhythm-tight, 1rem);
        margin-bottom: var(--rhythm, 1.5rem);
    }
    .page-hero__lead { font-size: 1rem; }
}

/* =========================================================================
 * Sprint 33 Phase 3 — Global app-footer (_app_footer.html).
 *
 * 4-col grid on ≥ 1024px (Brand / Produkt / Vertrauen / Kontakt) +
 * 1-row legal strip below. Collapses to 2-col 720-1024px, 1-col < 720px.
 *
 * Sticky-footer behavior: body uses grid-template-rows: auto 1fr auto so
 * the footer always sits at the bottom on short pages but flows naturally
 * on tall pages. Scoped via :has(.app-footer) so login + error stay on
 * their existing single-line footer.
 *
 * Removed from each of the 8 authenticated templates' inline <footer>
 * blocks; this file is now the canonical footer.
 * ========================================================================= */

/* Sticky-footer grid — only opt in when the global footer is present. */
@supports selector(body:has(*)) {
    body:has(.app-footer) {
        display: grid;
        grid-template-rows: auto 1fr auto;
        min-height: 100vh;
    }
    body:has(.app-footer) .app-main {
        /* Override the rule above .app-main from Sprint 30A; the grid
           parent gives the main row 1fr, which means the footer never
           floats up into the content even on a 200px page. */
        margin: 0 auto;
    }
}

/* Fallback for engines that lack :has() — page-class opt-in. */
body.dashboard-page,
body.mandates-page,
body.mandate-page,
body.brief-page,
body.mandate-new-page,
body.connector-page {
    /* grid-template-rows kicks in via :has() above on modern engines;
       on older ones we keep the block layout — footer just won't stick. */
}

.app-footer {
    background: var(--color-bg-elev, var(--navy-800));
    border-top: 1px solid var(--color-brand-border, rgba(201, 168, 106, 0.45));
    padding: var(--rhythm-loose, 2.5rem) 0 var(--rhythm, 1.5rem);
    margin-top: var(--rhythm-loose, 2.5rem);
    color: var(--color-text-subtle, var(--fg-dim));
    font-size: var(--text-sm, 0.875rem);
    position: relative;
    z-index: 2;
}

.app-footer__grid {
    display: grid;
    gap: var(--rhythm, 1.5rem);
    grid-template-columns: 1fr;
    padding-bottom: var(--rhythm, 1.5rem);
}

@media (min-width: 720px) {
    .app-footer__grid {
        grid-template-columns: 1fr 1fr;
        gap: var(--rhythm-loose, 2.5rem) var(--rhythm, 1.5rem);
    }
}

@media (min-width: 1024px) {
    .app-footer__grid {
        grid-template-columns: 1.4fr 1fr 1fr 1fr;
        gap: var(--rhythm, 1.5rem) var(--rhythm-loose, 2.5rem);
    }
}

.app-footer__brand-col {
    display: flex;
    flex-direction: column;
    gap: var(--space-2, 0.5rem);
}

.app-footer__brand-mark {
    color: var(--color-brand, var(--accent));
    font-size: 1.25rem;
    font-weight: var(--weight-semibold, 600);
    text-transform: uppercase;
    letter-spacing: 0.18em;
    display: inline-block;
}

.app-footer__tagline {
    margin: 0;
    color: var(--color-text-subtle, var(--fg-dim));
    font-size: var(--text-sm, 0.875rem);
    line-height: var(--leading-snug, 1.4);
    max-width: 32ch;
}

.app-footer__version {
    margin: 0;
    color: var(--color-text-faint, var(--slate-400));
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
    font-size: var(--text-xs, 0.75rem);
    letter-spacing: 0.04em;
}

.app-footer__nav-title {
    color: var(--color-brand, var(--accent));
    text-transform: uppercase;
    letter-spacing: 0.12em;
    font-size: 0.6875rem;     /* 11pt */
    font-weight: var(--weight-semibold, 600);
    margin: 0 0 var(--space-3, 0.75rem);
}

.app-footer__nav-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2, 0.5rem);
}

.app-footer__nav-list a {
    color: var(--color-text-subtle, var(--fg-dim));
    text-decoration: none;
    font-size: var(--text-sm, 0.875rem);
    transition: color var(--motion-fast, 120ms) var(--motion-ease, ease);
    border-bottom: none;
}

.app-footer__nav-list a:hover,
.app-footer__nav-list a:focus-visible {
    color: var(--color-brand, var(--accent));
    outline: none;
}

.app-footer__legal {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-2, 0.5rem);
    padding-top: var(--rhythm, 1.5rem);
    border-top: 1px solid rgba(201, 168, 106, 0.10);
    color: var(--color-text-faint, var(--slate-400));
    font-size: var(--text-xs, 0.75rem);
    text-align: center;
}

.app-footer__legal-sep {
    color: var(--color-text-faint, var(--slate-400));
    opacity: 0.5;
}

@media (min-width: 720px) {
    .app-footer__legal {
        justify-content: space-between;
        text-align: left;
    }
}

/* Login footer (the existing 2-link block in login.html + error.html)
   stays untouched — different visual context, different boundary. The
   .app-footer block is for authenticated surfaces only. */

/* =========================================================================
 * Sprint 33 Phase 6 — Responsive + a11y + table polish (v0.6.19).
 *
 * Reach into the rendered surfaces the operator actually sees:
 *
 *   1. Standardized :focus-visible — WCAG 2.4.7 demands a visible focus
 *      indicator with sufficient contrast. Default browser ring + the
 *      ad-hoc `outline: none` rules in the legacy CSS would fail an
 *      audit; we standardize on a gold 2px outline with 2px offset.
 *
 *   2. Table polish — recent-jobs__table + connector-table render naked
 *      <thead>/<tbody> with no row-banding, no hover. Banker eye expects
 *      a zebra-striped + hover-highlighted data-grid.
 *
 *   3. Distress-page eyebrow contrast — verify the amber on navy-800
 *      hits 4.5:1.
 *
 *   4. Mobile breakpoint: page-hero__chips wraps to its own line so the
 *      title doesn't collide with chips at < 480px.
 *
 * Print + reduced-motion already shipped in Phase 5's visual.css.
 * ========================================================================= */

/* WCAG 2.4.7 — visible focus indicator on every interactive surface.
   The legacy `outline: none` rules in the codebase suppress focus on
   buttons + nav-links + inputs; we re-establish a consistent gold ring
   via :focus-visible (mouse clicks don't show it, keyboard does). */
*:focus-visible {
    outline: 2px solid var(--color-brand, var(--accent, #c9a86a));
    outline-offset: 2px;
    border-radius: var(--radius-sm, 2px);
}

/* Inputs get a more visible variant since their default border is dark. */
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
    outline: 2px solid var(--color-brand, var(--accent, #c9a86a));
    outline-offset: 0;
    border-color: var(--color-brand, var(--accent, #c9a86a));
}

/* Page-hero chips wrap below the title on phones. */
@media (max-width: 480px) {
    .page-hero__chips {
        margin-top: 0.25rem;
    }
    .page-hero__title {
        word-break: break-word;
    }
}

/* Sticky-footer body-grid — Sprint 33 standard breakpoint table.
   The breakpoint catalog the rest of Sprint 33 honors:
     480  sm — phone (vertical)
     720  md — phone (horizontal) + small tablet
    1024  lg — laptop
    1280  xl — desktop
   The header / footer / page-hero rules above use 720 + 1024 as the
   primary break-points. xl is reserved for future widescreen surfaces. */

/* Table polish — operator's data-tables get row-banding + hover. */

.recent-jobs__table tbody tr:nth-child(odd),
.connector-table   tbody tr:nth-child(odd) {
    background: rgba(154, 160, 168, 0.04);
}

.recent-jobs__table tbody tr:hover,
.connector-table   tbody tr:hover {
    background: rgba(201, 168, 106, 0.06);
}

.recent-jobs__table th,
.connector-table   th {
    font-size: var(--text-xs, 0.75rem);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-text-faint, var(--slate-400, #6b7280));
    font-weight: var(--weight-medium, 500);
    border-bottom: 1px solid var(--color-brand-border, rgba(201, 168, 106, 0.45));
    padding: var(--space-2, 0.5rem) var(--space-3, 0.75rem);
    text-align: left;
}

.recent-jobs__table td,
.connector-table   td {
    padding: var(--space-2, 0.5rem) var(--space-3, 0.75rem);
    border-bottom: 1px solid rgba(154, 160, 168, 0.10);
    font-size: var(--text-sm, 0.875rem);
}

/* Empty-state details — within the .empty-state molecule. */
.empty-state__details {
    margin-top: var(--rhythm, 1.5rem);
    width: 100%;
    max-width: 56ch;
    text-align: left;
}

.empty-state__details summary {
    cursor: pointer;
    list-style: none;
    color: var(--color-text-subtle, var(--fg-dim, #9aa0a8));
    font-size: var(--text-sm, 0.875rem);
    padding: var(--space-2, 0.5rem);
    border-radius: var(--radius-md, 4px);
}
.empty-state__details summary::-webkit-details-marker { display: none; }
.empty-state__details summary:hover,
.empty-state__details summary:focus-visible {
    color: var(--color-brand, var(--accent, #c9a86a));
    outline: none;
}

.empty-state__details pre {
    margin: var(--space-2, 0.5rem) 0;
    padding: var(--space-3, 0.75rem);
    background: var(--color-bg-inset, var(--navy-700, #1e2436));
    border-radius: var(--radius-md, 4px);
    font-size: var(--text-xs, 0.75rem);
    overflow-x: auto;
}

/* Reduced-motion: kill page-hero decoration transitions (none today,
   but future-proof). */
@media (prefers-reduced-motion: reduce) {
    .page-hero,
    .page-hero__decoration,
    .app-footer,
    .app-footer__nav-list a,
    .empty-state,
    .empty-state__illustration { transition: none !important; animation: none !important; }
}

/* ===========================================================================
 * Sprint 37 — §824 BGB Defamation-Shield Disclaimer
 * ---------------------------------------------------------------------------
 * Distress briefs render structurally-defamation-capable claims about named
 * third parties. The `.legal-disclaimer` block frames those claims as
 * source-privileged heuristic indicator-evaluations rather than verdicts,
 * shielding §824 BGB / §4 UWG / §186 StGB exposure.
 *
 * Visual intent: smaller font (0.78rem), subtle slate-300 color, hairline
 * borders top + bottom — present without shouting. Uses existing tokens
 * only (--color-text-subtle, --rhythm, --space-4, --text-xs).
 * =========================================================================== */
.legal-disclaimer {
    margin: var(--rhythm, 1.5rem) 0;
    padding: var(--space-4, 1rem) var(--space-4, 1rem);
    border-top: 1px solid var(--border, rgba(255, 255, 255, 0.08));
    border-bottom: 1px solid var(--border, rgba(255, 255, 255, 0.08));
    font-size: 0.78rem;
    line-height: 1.55;
    color: var(--color-text-subtle, var(--fg-dim));
    font-style: italic;
}
.legal-disclaimer__lede {
    margin: 0 0 var(--space-2, 0.5rem) 0;
    font-style: normal;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-size: var(--text-xs, 0.75rem);
    color: var(--color-text-subtle, var(--fg-dim));
}
.legal-disclaimer p { margin: 0; }
.legal-disclaimer p + p { margin-top: var(--space-2, 0.5rem); }

/* ===========================================================================
 * Sprint 39 (v0.6.25) — Public /demo/bekleidung surface molecules.
 *
 * Reviewer 12 (End-User-Journey) flagged the missing pre-credential funnel
 * as the #1 conversion blocker. The demo route renders one curated brief
 * behind a clear watermark + CTA. These three molecule-classes carry the
 * visual scaffolding:
 *
 *   .demo-watermark        — gold-on-navy sticky banner at viewport top
 *   .demo-cta              — gold-filled "Live-Version anfragen" button
 *   .demo-redacted-mask    — diagonal-stripe overlay on pilot-only blocks
 *
 * Pure tokens-driven, no new color literals. Mirrors the .pilot-start-btn
 * pattern from Sprint 37 for the CTA (banker-decisive action affordance)
 * and the .legal-disclaimer hairline-frame pattern for the mask overlay.
 * =========================================================================== */
.demo-watermark {
    position: sticky;
    top: 0;
    z-index: 100;
    width: 100%;
    min-height: 56px;
    background: var(--color-bg-elev, var(--navy-800));
    border-bottom: 1px solid var(--color-brand, var(--gold-500));
    box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.25));
    color: var(--color-text, var(--slate-100));
    font-size: var(--text-sm, 0.875rem);
    line-height: var(--leading-snug, 1.4);
}
.demo-watermark__inner {
    max-width: var(--container-wide, 1400px);
    margin: 0 auto;
    padding: var(--space-3, 0.75rem) var(--page-padding-x, 1rem);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3, 0.75rem);
}
.demo-watermark__icon {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    color: var(--color-brand, var(--gold-500));
}
.demo-watermark__icon img {
    filter: invert(72%) sepia(33%) saturate(469%) hue-rotate(2deg) brightness(91%) contrast(86%);
    /* Approximates --gold-500 (#c9a86a) on the navy-800 background. */
}
.demo-watermark__text {
    flex: 1 1 280px;
    color: var(--color-text, var(--slate-100));
}
.demo-watermark__text strong {
    color: var(--color-brand, var(--gold-500));
    letter-spacing: 0.04em;
}

.demo-cta {
    display: inline-block;
    padding: 0.5rem 1rem;
    background: var(--color-brand, var(--gold-500));
    color: var(--color-bg, var(--navy-900));
    border: 1px solid var(--color-brand, var(--gold-500));
    border-radius: var(--radius-md, 3px);
    font-weight: var(--weight-semibold, 600);
    font-size: var(--text-sm, 0.875rem);
    letter-spacing: 0.04em;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--motion-fast, 120ms) var(--motion-ease, ease),
                color var(--motion-fast, 120ms) var(--motion-ease, ease),
                border-color var(--motion-fast, 120ms) var(--motion-ease, ease);
}
.demo-cta:hover,
.demo-cta:focus {
    background: var(--color-brand-hover, var(--gold-600));
    border-color: var(--color-brand-hover, var(--gold-600));
    color: var(--color-bg, var(--navy-900));
}
.demo-cta:focus-visible {
    outline: 2px solid var(--color-brand, var(--gold-500));
    outline-offset: 2px;
}
.demo-cta--block {
    display: inline-block;
    margin-top: var(--space-2, 0.5rem);
    padding: 0.75rem 1.5rem;
    font-size: var(--text-base, 1rem);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.demo-redacted-mask {
    position: relative;
    min-height: 140px;
    border: 1px solid var(--color-brand-border, var(--gold-200));
    border-radius: var(--radius-md, 3px);
    background-color: var(--color-bg-inset, var(--navy-700));
    background-image: repeating-linear-gradient(
        45deg,
        rgba(201, 168, 106, 0.04) 0,
        rgba(201, 168, 106, 0.04) 12px,
        rgba(201, 168, 106, 0.10) 12px,
        rgba(201, 168, 106, 0.10) 24px
    );
    overflow: hidden;
    padding: var(--space-4, 1rem);
}
.demo-redacted-mask__overlay {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-2, 0.5rem);
    background: rgba(10, 15, 28, 0.55);
    text-align: center;
    padding: var(--space-3, 0.75rem);
}
.demo-redacted-mask__overlay strong {
    color: var(--color-brand, var(--gold-500));
    font-size: var(--text-base, 1rem);
    font-weight: var(--weight-semibold, 600);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.demo-redacted-mask__overlay .dim {
    max-width: 36ch;
    font-size: var(--text-sm, 0.875rem);
    color: var(--color-text-subtle, var(--slate-300));
}
.demo-redacted-mask__placeholder {
    opacity: 0.25;
    filter: blur(2px);
}
.demo-redacted-mask .redacted {
    font-family: var(--font-mono, monospace);
    color: var(--color-text-faint, var(--slate-400));
}

