@charset "UTF-8";
/* ==========================================================================
   motorsport.laser.land — Designsystem "Endurance/Nachtschicht"
   EINE Datei, handgeschrieben, kein Build-Step.
   Gliederung: 01 TOKENS · 02 RESET/BASE · 03 TYPO · 04 BACKGROUND
               05 LAYOUT/NAV/FOOTER · 06 TABLES · 07 COMPONENTS
               08 UTILITIES
   Der frueher letzte Abschnitt "99 LEGACY" ist am 07.08.2026 (Etappe 7)
   ersatzlos entfallen: keine seiner Klassen kam noch in resources/views vor.
   Zwei seiner Regeln waren Wiederholungen des neuen Systems und leben oben
   weiter — `.data-table a:hover` (06) und `.data-table { min-width: 480px }`
   (06). Nachtrag 07.08.2026: die Legacy-Fassung `.data-table tbody td a:hover`
   war KEINE reine Zweitschrift, sondern staerker (0,2,3 gegen 0,2,1) und
   schlug damit `.team-cell a:hover`. Die Zusage steht seitdem ausdruecklich
   in Abschnitt 06 (`.data-table .team-cell a:hover`).
   Erlaubte Breakpoints: 768px / 1200px / 767.98px. Sonst nichts.
   ========================================================================== */

/* ==========================================================================
   01 TOKENS
   ========================================================================== */
:root {
    /* Flaechen */
    --bg-deep: #121317;
    --bg-0: #17181c;
    --bg-1: #1d1f24;
    --bg-2: #23262c;
    --bg-3: #2b2f36;
    --line-1: #2e3138;
    --line-2: #3d414a;

    /* Text — nie dunkler als --text-3 */
    --text-1: #f2efe9;
    --text-2: #b8b4ac;
    --text-3: #94908a;
    /* Fuer Labels auf dem offenen Hintergrund (Lichtspuren wandern darueber) */
    --text-label: #c8c4bb;

    /* Akzent */
    --accent: #e8a33d;
    --accent-strong: #f5b942;
    --accent-ink: #17181c;
    --accent-wash: rgba(232, 163, 61, .12);

    /* Emblem-Plakette (Serien-/Herstellerzeichen, siehe 07 COMPONENTS).
       Heller Traeger, weil die gemeinfreien Original-SVGs fuer hellen Grund
       gezeichnet sind — gezaehlt ueber alle 55 Dateien: 69x fill:#000000 und
       43x fill:#000 gegen 34x #fff, und die weissen Flaechen sind Aussparungen
       INNERHALB dunkler Formen. Auf --bg-1 waere davon nichts zu sehen.
       Der Ton ist derselbe wie --text-1, damit die Plakette zur Palette
       gehoert und nicht als Fremdkoerper wirkt. */
    --emblem-plate: #f2efe9;
    --emblem-plate-line: rgba(23, 24, 28, .18);

    /* Podium */
    --pod-1: #e6c15a;
    --pod-2: #c0c7d1;
    --pod-3: #d08a5a;

    /* Status */
    --ok: #6fbf82;
    --err: #e07a6b;
    --warn: var(--accent);

    /* Chart-Palette (8) */
    --c-1: #e8a33d;
    --c-2: #7aaee0;
    --c-3: #5bbcae;
    --c-4: #a892e0;
    --c-5: #d98aa6;
    --c-6: #9db36b;
    --c-7: #d97a66;
    --c-8: #9aa1ab;

    /* Spacing (4px-Raster) */
    --sp-1: 4px;
    --sp-2: 8px;
    --sp-3: 12px;
    --sp-4: 16px;
    --sp-5: 24px;
    --sp-6: 32px;
    --sp-7: 48px;
    --sp-8: 64px;

    /* Radius */
    --r-s: 4px;
    --r-m: 8px;

    /* Schatten — NUR fuer Dropdown/Sheet */
    --shadow-pop: 0 16px 40px rgba(0, 0, 0, .5);

    /* Typo */
    --font-display: 'Barlow Condensed', 'Arial Narrow', sans-serif;
    --font-text: 'Inter', system-ui, -apple-system, sans-serif;

    --fs-meta: 13px;
    --fs-sm: 14px;
    --fs-base: 16px;
    --fs-lead: 18px;
    --fs-h3: 20px;
    --fs-h2: clamp(24px, 3vw, 30px);
    --fs-h1: clamp(34px, 5.5vw, 54px);
    --fs-display: clamp(32px, 6vw, 56px);

    /* Layout */
    --container: 1160px;
    --nav-h: 56px;

    color-scheme: dark;
}

/* ==========================================================================
   02 RESET / BASE
   ========================================================================== */
*,
*::before,
*::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html {
    font-size: 16px;
    line-height: 1.6;
    background: var(--bg-0);
    -webkit-text-size-adjust: 100%;
}

body {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    background: var(--bg-0);
    color: var(--text-1);
    font-family: var(--font-text);
    font-size: var(--fs-base);
    font-weight: 400;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

img,
svg,
canvas {
    max-width: 100%;
}

img {
    height: auto;
}

a {
    color: var(--accent);
    text-decoration: none;
}

a:hover {
    color: var(--accent-strong);
}

button,
input,
select,
textarea {
    font: inherit;
    color: inherit;
}

:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

::selection {
    background: var(--accent-wash);
    color: var(--text-1);
}

/* Scrollbar (dezent, nicht amber — amber bleibt den Tabellen vorbehalten) */
::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}

::-webkit-scrollbar-track {
    background: var(--bg-0);
}

::-webkit-scrollbar-thumb {
    background: var(--line-2);
    border-radius: 5px;
}

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

/* ==========================================================================
   03 TYPO — selbst gehostete Fonts, font-display: swap
   ========================================================================== */
@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('/fonts/inter-latin-400-normal.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('/fonts/inter-latin-ext-400-normal.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('/fonts/inter-latin-500-normal.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('/fonts/inter-latin-600-normal.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('/fonts/inter-latin-ext-600-normal.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('/fonts/inter-latin-700-normal.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Barlow Condensed';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('/fonts/barlow-condensed-latin-600-normal.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Barlow Condensed';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('/fonts/barlow-condensed-latin-ext-600-normal.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Barlow Condensed';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('/fonts/barlow-condensed-latin-700-normal.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

h1,
h2,
h3,
h4 {
    font-family: var(--font-display);
    font-weight: 600;
    line-height: 1.15;
    color: var(--text-1);
    letter-spacing: 0;
}

h1 {
    font-size: var(--fs-h1);
}

h2 {
    font-size: var(--fs-h2);
}

h3 {
    font-size: var(--fs-h3);
    font-weight: 700;
}

p {
    max-width: 70ch;
}

.lead {
    font-size: var(--fs-lead);
    color: var(--text-2);
    max-width: 70ch;
}

/* Eyebrows und Kategorie-Labels stehen auf dem OFFENEN Hintergrund, ueber den
   die Lichtspuren wandern — deshalb --text-label statt --text-3. Damit halten
   sie auch an der hellsten Stelle einer Spur noch 5.3:1 (nachgerechnet). */
.eyebrow {
    font-family: var(--font-text);
    font-size: var(--fs-meta);
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--text-label);
    margin: 0 0 var(--sp-2);
}

.muted {
    color: var(--text-2);
}

.meta {
    font-size: var(--fs-meta);
    color: var(--text-3);
}

.num {
    font-variant-numeric: tabular-nums;
}

/* Amber-Strich unter Headlines/Sektionen */
.rule {
    display: block;
    width: 32px;
    height: 2px;
    background: var(--accent);
    border: 0;
    margin: var(--sp-3) 0 0;
}

/* ==========================================================================
   04 BACKGROUND — "Lichtfahrt" (CSS-only; ersetzt das fruehere WebGL-Skript,
   dessen Datei am 07.08.2026 aus public/js entfernt wurde)
   ========================================================================== */
/* Jede Lichtspur besteht aus einem weichen Schein (::before) und einem schmalen,
   hellen Kern (::after) — wie ein Scheinwerfer in einer Langzeitbelichtung. Der
   Kern traegt die Sichtbarkeit, der Schein nur die Stimmung; deshalb bleibt die
   mittlere Flaechenhelligkeit niedrig und der Text auf dem Grund lesbar.
   Budget: Amber-Beimischung auf --bg-0 darf 0.126 nicht ueberschreiten, sonst
   faellt --text-3 unter 4.5:1 (nachgerechnet 05.08.2026). */
.bg-scene {
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    overflow: hidden;
    /* Grundtiefe: auch ohne Bewegung keine flache Flaeche */
    background:
        radial-gradient(120% 80% at 50% -15%, #1e1f25 0%, rgba(30, 31, 37, 0) 60%),
        radial-gradient(90% 60% at 85% 110%, #1c1a1e 0%, rgba(28, 26, 30, 0) 55%),
        var(--bg-0);
}

/* Zwei Ebenen, damit sich Scroll- und Eigenbewegung nicht ueberschreiben:
   <i>    = Scroll-Ebene   (Tiefenversatz --py, Streckung --st beim schnellen Scrollen)
   <span> = Eigenbewegung  (die langsame Drift-Animation)
   --py und --st setzt public/js/app.js auf .bg-scene; ohne JavaScript bleiben
   die Rueckfallwerte 0px und 1, dann laeuft nur die Drift. */
.bg-scene i {
    position: absolute;
    left: -25vw;
    width: 150vw;
    height: 30vh;
    will-change: transform;
    transform: translate3d(0, var(--py, 0px), 0) scaleX(var(--st, 1));
}

/* Tiefenstaffelung: die obere Spur zieht am schnellsten, die untere am langsamsten */
.bg-scene i:nth-child(1) { transform: translate3d(0, calc(var(--py, 0px) * 1.5), 0) scaleX(var(--st, 1)); }
.bg-scene i:nth-child(2) { transform: translate3d(0, calc(var(--py, 0px) * 0.9), 0) scaleX(calc(1 + (var(--st, 1) - 1) * .7)); }
.bg-scene i:nth-child(3) { transform: translate3d(0, calc(var(--py, 0px) * 0.45), 0) scaleX(calc(1 + (var(--st, 1) - 1) * .45)); }

.bg-scene i > span {
    position: absolute;
    inset: 0;
    display: block;
    will-change: transform;
}

/* weicher Schein */
.bg-scene i > span::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 50%;
    filter: blur(60px);
}

/* heller Kern — die eigentliche Lichtspur */
.bg-scene i > span::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: 2px;
    filter: blur(1.5px);
}

.bg-scene i:nth-child(1) { top: 12%; }
.bg-scene i:nth-child(1) > span {
    animation: drift-a 26s ease-in-out infinite alternate;
}
.bg-scene i:nth-child(1) > span::before {
    background: linear-gradient(100deg, rgba(232, 163, 61, 0) 8%, rgba(232, 163, 61, .10) 48%, rgba(232, 163, 61, 0) 92%);
}
.bg-scene i:nth-child(1) > span::after {
    background: linear-gradient(90deg, rgba(255, 209, 138, 0) 12%, rgba(255, 209, 138, .09) 40%, rgba(255, 209, 138, .15) 52%, rgba(255, 209, 138, .07) 64%, rgba(255, 209, 138, 0) 90%);
}

.bg-scene i:nth-child(2) { top: 46%; }
.bg-scene i:nth-child(2) > span {
    animation: drift-b 35s ease-in-out infinite alternate;
}
.bg-scene i:nth-child(2) > span::before {
    background: linear-gradient(78deg, rgba(198, 214, 235, 0) 10%, rgba(198, 214, 235, .09) 52%, rgba(198, 214, 235, 0) 94%);
}
.bg-scene i:nth-child(2) > span::after {
    background: linear-gradient(90deg, rgba(230, 240, 252, 0) 18%, rgba(230, 240, 252, .07) 44%, rgba(230, 240, 252, .12) 56%, rgba(230, 240, 252, 0) 88%);
}

.bg-scene i:nth-child(3) { top: 76%; }
.bg-scene i:nth-child(3) > span {
    animation: drift-c 44s ease-in-out infinite alternate;
}
.bg-scene i:nth-child(3) > span::before {
    background: linear-gradient(115deg, rgba(232, 163, 61, 0) 12%, rgba(232, 163, 61, .07) 55%, rgba(232, 163, 61, 0) 92%);
}
.bg-scene i:nth-child(3) > span::after {
    background: linear-gradient(90deg, rgba(255, 209, 138, 0) 22%, rgba(255, 209, 138, .06) 48%, rgba(255, 209, 138, .11) 60%, rgba(255, 209, 138, 0) 86%);
}

@keyframes drift-a {
    from { transform: translate3d(-9vw, 3vh, 0) rotate(-14deg); }
    to   { transform: translate3d(9vw, -6vh, 0) rotate(-11deg); }
}

@keyframes drift-b {
    from { transform: translate3d(8vw, 3vh, 0) rotate(-14deg); }
    to   { transform: translate3d(-8vw, -3vh, 0) rotate(-17deg); }
}

@keyframes drift-c {
    from { transform: translate3d(-7vw, -3vh, 0) rotate(-14deg); }
    to   { transform: translate3d(7vw, 4vh, 0) rotate(-12deg); }
}

.bg-vignette {
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background: radial-gradient(120% 90% at 50% 0%, transparent 40%, rgba(18, 19, 23, .9) 100%);
}

/* ==========================================================================
   05 LAYOUT / NAV / FOOTER
   ========================================================================== */
.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 999;
    padding: var(--sp-3) var(--sp-4);
    background: var(--accent);
    color: var(--accent-ink);
    font-weight: 600;
    border-radius: 0 0 var(--r-s) 0;
}

.skip-link:focus {
    left: 0;
    color: var(--accent-ink);
}

#page-content {
    position: relative;
    z-index: 1;
    flex: 1;
    width: 100%;
    max-width: var(--container);
    margin: 0 auto;
    padding: var(--sp-4) var(--sp-4) 88px;
}

.section {
    margin-top: var(--sp-6);
}

/* Sprungziel-Abschnitte (/records#poles, /champions#d1950 …). Die Kopfleiste
   ist fixiert; ohne diesen Abstand landet die angesprungene Ueberschrift genau
   DAHINTER, und der Leser sieht als erstes die Tabellenmitte. Gemessen am
   05.08.2026 im Browser. Gleiche Rechnung wie bei den Chronik-Zeilen in 06. */
.section[id] {
    scroll-margin-top: calc(var(--nav-h) + var(--sp-4));
}

.section > .eyebrow {
    margin-bottom: var(--sp-1);
}

.section-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-4);
    margin-bottom: var(--sp-3);
    flex-wrap: wrap;
}

.section-head .rule {
    margin: var(--sp-2) 0 0;
}

/* --- Topnav (Desktop) --- */
.topnav {
    position: sticky;
    top: 0;
    z-index: 200;
    height: var(--nav-h);
    display: flex;
    align-items: center;
    background: rgba(23, 24, 28, .88);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--line-1);
}

/* Lesefortschritt: duenne Linie an der Unterkante der Kopfleiste.
   --sp (0..1) setzt public/js/app.js; ohne JavaScript bleibt sie bei 0 und
   damit unsichtbar — sie traegt keine Information, die sonst fehlen wuerde. */
.nav-progress {
    position: absolute;
    left: 0;
    bottom: -1px;
    height: 2px;
    width: 100%;
    transform: scaleX(var(--sp, 0));
    transform-origin: 0 50%;
    background: linear-gradient(90deg, rgba(232, 163, 61, .55), var(--accent));
    pointer-events: none;
}

.topnav-inner {
    width: 100%;
    max-width: var(--container);
    margin: 0 auto;
    padding: 0 var(--sp-4);
    display: flex;
    align-items: center;
    gap: var(--sp-5);
}

.nav-links {
    display: none;
    align-items: center;
    gap: var(--sp-1);
    margin-left: auto;
}

.nav-links a,
.nav-menu > summary {
    display: flex;
    align-items: center;
    gap: var(--sp-1);
    height: var(--nav-h);
    padding: 0 var(--sp-3);
    font-size: var(--fs-sm);
    font-weight: 500;
    color: var(--text-2);
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    white-space: nowrap;
    cursor: pointer;
    list-style: none;
}

.nav-links a:hover,
.nav-menu > summary:hover {
    color: var(--text-1);
}

.nav-links a[aria-current="page"] {
    color: var(--text-1);
    font-weight: 600;
    border-bottom-color: var(--accent);
}

/* --- "Mehr"-Menue: <details>, funktioniert ohne JS --- */
.nav-menu {
    position: relative;
}

.nav-menu > summary::-webkit-details-marker {
    display: none;
}

.nav-menu > summary::after {
    content: "";
    width: 0;
    height: 0;
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-top: 5px solid currentColor;
    margin-left: 2px;
}

.nav-menu[open] > summary {
    color: var(--text-1);
    border-bottom-color: var(--accent);
}

.nav-menu-panel {
    position: absolute;
    top: calc(var(--nav-h) - 1px);
    right: 0;
    min-width: 200px;
    background: var(--bg-1);
    border: 1px solid var(--line-1);
    border-top: 2px solid var(--accent);
    border-radius: 0 0 var(--r-m) var(--r-m);
    box-shadow: var(--shadow-pop);
    padding: var(--sp-2) 0;
}

.nav-menu-panel a {
    display: block;
    padding: var(--sp-3) var(--sp-4);
    min-height: 44px;
    font-size: var(--fs-sm);
    font-weight: 500;
    color: var(--text-2);
    white-space: nowrap;
}

.nav-menu-panel a:hover {
    color: var(--text-1);
    background: var(--bg-2);
}

.nav-menu-panel a[aria-current="page"] {
    color: var(--text-1);
    background: var(--accent-wash);
    box-shadow: inset 2px 0 0 var(--accent);
}

/* --- Brand --- */
.brand {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    color: var(--accent);
    flex-shrink: 0;
}

.brand:hover {
    color: var(--accent-strong);
}

.brand svg {
    display: block;
    flex-shrink: 0;
}

.brand-word {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 21px;
    line-height: 1;
    letter-spacing: .01em;
    white-space: nowrap;
}

.brand-word .b-1 {
    color: var(--text-1);
}

.brand-word .b-2 {
    color: var(--accent);
}

/* --- Footer --- */
.site-footer {
    display: none;
    position: relative;
    z-index: 1;
    border-top: 1px solid var(--line-1);
    background: var(--bg-deep);
    padding: var(--sp-5) var(--sp-4);
}

.site-footer .footer-inner {
    max-width: var(--container);
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    flex-wrap: wrap;
    font-size: var(--fs-meta);
    color: var(--text-3);
}

/* --- Mobile Bottom-Nav --- */
.bottomnav {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 200;
    background: rgba(18, 19, 23, .96);
    -webkit-backdrop-filter: blur(14px);
    backdrop-filter: blur(14px);
    border-top: 1px solid var(--line-1);
    padding-bottom: env(safe-area-inset-bottom);
}

.bottomnav-inner {
    display: flex;
    align-items: stretch;
}

.bn-more {
    flex: 1 1 0;
    display: flex;
}

.bottomnav a,
.bn-more > summary {
    flex: 1 1 0;
    min-height: 56px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    /* Mindestens 13px — aeltere Zielgruppe. Die fuenf Slots teilen sich die
       Breite gleichmaessig (flex: 1 1 0); das laengste Label ("Serien",
       6 Zeichen) misst bei 13px/600 rund 43px und passt damit auch auf
       320px-Geraeten (64px je Slot). nowrap verhindert Umbruch, falls ein
       Label spaeter waechst — dann bitte das Label kuerzen, nicht die
       Schrift verkleinern. */
    font-size: var(--fs-meta);
    font-weight: 600;
    color: var(--text-3);
    white-space: nowrap;
    cursor: pointer;
    list-style: none;
    -webkit-tap-highlight-color: transparent;
}

.bottomnav a[aria-current="page"] {
    color: var(--accent);
}

.bottomnav .icon {
    width: 24px;
    height: 24px;
}

.bn-more > summary::-webkit-details-marker {
    display: none;
}

.bn-more[open] > summary {
    color: var(--text-1);
}

.bn-sheet {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 100%;
    border-top: 2px solid var(--accent);
    box-shadow: var(--shadow-pop);
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1px;
    /* Die Flaeche traegt die Trennlinienfarbe, die Kacheln daneben --bg-1;
       so entstehen 1px-Trenner ohne zusaetzliche Border-Regeln. */
    background-color: var(--line-1);
}

.bn-sheet a {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 64px;
    padding: var(--sp-3) var(--sp-4);
    background: var(--bg-1);
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--text-1);
}

.bn-sheet a span {
    font-size: var(--fs-meta);
    font-weight: 400;
    color: var(--text-3);
}

.bn-sheet a:hover {
    background: var(--bg-2);
    color: var(--text-1);
}

/* --- "Nach oben"-Knopf --- */
/* Schwebt unten rechts und bringt den Leser mit einem Tipp an den Seitenanfang.
   z-index 150 ist ABSICHTLICH kleiner als die 200 der Bottom-Nav und ihres
   "Mehr"-Sheets: das aufgeklappte Sheet soll den Knopf ueberdecken, nicht
   umgekehrt.
   Der Knopf steht mit `hidden` im Markup (layouts/app.blade.php) und wird erst
   von app.js freigeschaltet. `display: flex` der Klasse wuerde die
   UA-Regel `[hidden] { display: none }` ueberstimmen — deshalb die eigene
   Regel darunter. Ohne JavaScript bleibt der Knopf damit vollstaendig weg. */
.to-top {
    position: fixed;
    right: 16px;
    /* Oberhalb der Bottom-Nav (56px Slot + Geraeteecke + 12px Luft).
       Desktop-Wert steht im 768er-Block. */
    bottom: calc(56px + env(safe-area-inset-bottom) + 12px);
    z-index: 150;
    width: 48px;
    height: 48px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border-radius: 50%;
    background: var(--bg-1);
    border: 1px solid var(--line-2);
    color: var(--accent);
    box-shadow: var(--shadow-pop);
    cursor: pointer;
    opacity: 0;
    visibility: hidden;
    transition: opacity .18s ease, visibility .18s ease;
    -webkit-tap-highlight-color: transparent;
}

.to-top[hidden] {
    display: none;
}

.to-top .icon {
    width: 24px;
    height: 24px;
}

.to-top--sichtbar {
    opacity: 1;
    visibility: visible;
}

.to-top:hover {
    background: var(--bg-2);
    border-color: var(--accent);
}

/* ==========================================================================
   06 TABLES
   Basis fuer die neuen <x-table>-Komponenten UND die noch alten Seiten.
   Grundsatz: Tabellen sind auf dem Handy IMMER ohne JavaScript sichtbar.
   ========================================================================== */
.table-wrap {
    position: relative;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border: 1px solid var(--line-1);
    border-radius: var(--r-m);
    background: var(--bg-1);
    scrollbar-width: thin;
    scrollbar-color: var(--accent) var(--bg-2);
}

.table-wrap::-webkit-scrollbar {
    height: 8px;
}

.table-wrap::-webkit-scrollbar-track {
    background: var(--bg-2);
}

.table-wrap::-webkit-scrollbar-thumb {
    background: var(--accent);
    border-radius: 4px;
}

.data-table {
    width: 100%;
    min-width: 480px;
    border-collapse: collapse;
    font-size: 15px;
    line-height: 1.45;
}

.data-table thead th {
    font-size: var(--fs-meta);
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--text-3);
    background: var(--bg-2);
    text-align: left;
    padding: var(--sp-2) var(--sp-3);
    border-bottom: 1px solid var(--line-1);
    white-space: nowrap;
}

.data-table tbody td {
    padding: var(--sp-3);
    border-bottom: 1px solid var(--line-1);
    color: var(--text-1);
    vertical-align: middle;
    background: var(--bg-1);
}

.data-table tbody tr:last-child td {
    border-bottom: 0;
}

.data-table tbody tr:hover td {
    background: var(--bg-2);
}

.data-table a {
    color: var(--text-1);
    font-weight: 500;
}

/* Links in Tabellen faerben sich beim Ueberfahren bernstein — AUCH die
   gedaempften Teamzellen. Die zweite Zeile ist kein Schmuck:
   `.team-cell a:hover { color: var(--text-1) }` (Abschnitt 07, gleiche
   Auswahlstaerke 0,2,1, aber SPAETER in der Datei) gewinnt sonst nach der
   Reihenfolge-Regel, und Team-Links in Tabellen wuerden hell statt bernstein.
   Bis zum 07.08.2026 erledigte das die Legacy-Regel
   `.data-table tbody td a:hover` (0,2,3); mit ihrer Entfernung fiel das
   Hover fuer Teamzellen aus (Pruefer-Befund M4, 07.08.2026).
   EIN Klassenname mehr (0,3,1) statt `!important` und statt der Rueckkehr
   zum dreiteiligen Alt-Selektor — die Regel sagt jetzt selbst, wen sie
   schlaegt. `.driver-cell` braucht keine Zeile: dort ist der Hover-Wert
   ohnehin `--accent`. */
.data-table a:hover,
.data-table .team-cell a:hover {
    color: var(--accent);
}

/* Zahlenzellen */
.data-table .num,
.data-table .cell-num,
.data-table td.cell-num {
    font-variant-numeric: tabular-nums;
    text-align: right;
    white-space: nowrap;
}

.data-table th.cell-num {
    text-align: right;
}

/* Zwischenueberschriftszeile (z. B. WEC-Klassen) — beide Modi */
.data-table tbody tr.row-sec td {
    background: var(--bg-0);
    color: var(--accent);
    font-size: var(--fs-meta);
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    padding: var(--sp-2) var(--sp-3);
    border-bottom: 1px solid var(--line-1);
}

.data-table tbody tr.row-sec:hover td {
    background: var(--bg-0);
}

/* --- Muster B: horizontal scrollen + Sticky-Spalten --- */
.table--scroll .data-table th:first-child {
    position: sticky;
    left: 0;
    z-index: 3;
    background: var(--bg-2);
}

.table--scroll .data-table td:first-child {
    position: sticky;
    left: 0;
    z-index: 2;
    background: var(--bg-1);
}

.table--scroll .data-table tbody tr:hover td:first-child {
    background: var(--bg-2);
}

/* ZWEITE klebende Spalte — NUR fuer Tabellen mit einer Rangziffer als erster
   Spalte (series/race: "Pos"). Der Versatz unten ist eine feste Pixelzahl und
   stimmt deshalb ausschliesslich fuer diese eine Spaltenart.

   GEMESSEN 05.08.2026: Etappe 3 hatte `sticky="2"` auf fuenf Tabellen gesetzt,
   deren erste Spalte Datum, Saison, Streckenname oder Teamname enthaelt. Die
   Datumsspalte ist 106 px breit — die zweite Spalte begann bei 56 px und deckte
   die erste um 50 px zu: aus "18.11.2007" wurde "18.11.2". Auf dem Desktop
   unsichtbar (kein Ueberlauf), auf dem Handy immer. Diese fuenf Tabellen
   benutzen seitdem `sticky="1"`.

   MERKSATZ: `sticky="2"` setzt voraus, dass die erste Spalte in die 56 px
   passt. Ist sie breiter, gehoert dort `sticky="1"` hin. Als Notnagel liegt die
   zweite Spalte eine z-Ebene TIEFER als die erste (2/1 statt 3/2): geraet der
   Versatz doch einmal zu klein, schiebt sich die zweite Spalte unter die erste,
   statt sie zu ueberdecken — dann fehlt schlimmstenfalls Text in Spalte 2,
   nie in der Ankerspalte. */
.table--scroll.sticky-2 .data-table th:nth-child(2) {
    position: sticky;
    z-index: 2;
    background: var(--bg-2);
}

.table--scroll.sticky-2 .data-table td:nth-child(2) {
    position: sticky;
    z-index: 1;
    background: var(--bg-1);
}

.table--scroll.sticky-2 .data-table tbody tr:hover td:nth-child(2) {
    background: var(--bg-2);
}

/* Sticky-Positionen: erste Spalte 0, zweite hinter der ersten */
.table--scroll.sticky-2 .data-table th:nth-child(2),
.table--scroll.sticky-2 .data-table td:nth-child(2) {
    left: 56px;
}

/* Die zweite Sticky-Spalte sitzt auf `left: 56px` — damit das stimmt, ist die
   Breite der ersten Spalte (Position) hier festgelegt statt am <th>. */
.table--scroll.sticky-2 .data-table th:first-child,
.table--scroll.sticky-2 .data-table td:first-child {
    width: 56px;
    min-width: 56px;
}

/* Anker-Zeilen (Event-Chroniken: id="j{jahr}", Ziel des Jahres-Redirects).
   Ohne scroll-margin verschwindet die angesprungene Zeile unter der
   klebenden Topnav. */
.data-table tbody tr[id] {
    scroll-margin-top: calc(var(--nav-h) + var(--sp-4));
}

/* Jahres-Spalte einer Chronik */
.data-table td.cell-jahr {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: var(--fs-h3);
    font-variant-numeric: tabular-nums;
    color: var(--text-1);
    white-space: nowrap;
}

/* Zweitzeile IN einer Tabellenzelle — z. B. das Datum unter dem Rennnamen der
   Event-Chroniken.
   BEWUSST OHNE ELTERN-SELEKTOR: Vorher stand dort `.dc-sub`, die im CSS nur als
   `.driver-cell .dc-sub` existiert. In einer normalen <td> hat die Zelle keinen
   Elternteil `.driver-cell`, die Regel griff also nie — Rennname und Datum
   standen in einer Zeile, gleiche Groesse, gleiche Farbe (gemessen 05.08.2026:
   865 betroffene Zeilen in allen acht Chroniken). Eine Klasse, die ueberall in
   einer Zelle benutzt werden darf, muss auch ueberall greifen. */
.cell-sub {
    display: block;
    margin-top: 2px;
    font-size: var(--fs-meta);
    color: var(--text-3);
}

/* Wert + Zweitzeile als EIN Block (z. B. "NASCAR" / "2.818 von 4.007" auf
   /teams). Am Schreibtisch aendert die Klasse nichts — der Wert steht links,
   die Zweitzeile darunter. Sie wird erst in der Kartenansicht gebraucht: dort
   ist jede Zelle ein Flex-Streifen "Label ... Wert", und OHNE diese Klammer
   waeren Wert und Zweitzeile zwei eigene Flex-Kinder. Gemessen 12.08.2026 im
   400px-Rahmen: der Serienname stand dann in der Mitte statt rechts, waehrend
   Einsaetze/Siege/Podien/Punkte darunter alle rechtsbuendig standen. */
.cell-stack {
    display: inline-block;
}

/* Mehrere Angaben in EINER Zelle — Streckenseite, Rennen mit mehreren Siegern
   (19.08.2026). Ein Rennen steht dort einmal da und nennt alle seine Sieger;
   Sieger- und Teamspalte muessen deshalb zeilenweise zusammenpassen.

   FLEX, NICHT BLOCK: Die Klassenmarke gehoert NEBEN den Namen, nicht darueber.
   `.driver-cell` ist selbst ein Flex-Kasten und damit ein Block — als
   Block-Kind haette die Marke eine eigene Zeile bekommen (gesehen am
   Nuerburgring, 318ti-Cup 2025: „G" ueber „Martin Garbrecht" statt davor).
   `.team-cell` ist umgekehrt inline und liefe ohne diese Klammer in EINER
   Zeile zusammen. */
.sieger-zeile {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    min-width: 0;
}

.sieger-zeile + .sieger-zeile {
    margin-top: var(--sp-2);
}

/* Die Fahrer EINES Autos, untereinander (Nutzerwunsch 19.08.2026: „diese 2
   Fahrer lieber untereinander in die selbe Zeile schreiben"). Ohne Gap und
   ohne eigene Zeilenhoehe: jede `.driver-cell` ist genau eine Zeilenbox hoch,
   der Block also so hoch wie die Zahl seiner Fahrer. Genau darauf ruht die
   Luecke unten. `min-width: 0` wie bei `.driver-cell`, damit lange Namen den
   Flex-Kasten nicht aufblaehen. */
.sieger-stapel {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

/* Der Platzhalter unter einem Teamnamen — einer je MITfahrer.
   Sieger- und Teamspalte tragen gleich viele Bloecke; ohne diese Luecke waere
   der Teamblock eines Autos mit drei Fahrern nur eine Zeile hoch, und das
   naechste Team stuende neben dem zweiten Fahrer des vorigen Autos (sichtbar
   z. B. an den 6 Stunden von Spa 2026: zwei Autos zu je drei Fahrern).

   `1lh` ist die Zeilenhoehe dieses Elements — also per Definition genau so
   hoch wie eine Fahrerzeile daneben, ohne Zahl aus zweiter Hand. `1.6em` davor
   ist der Rueckfall fuer Browser ohne `lh` und rechnet dasselbe aus, solange
   die Zeilenhoehe des Dokuments 1.6 ist (`html`/`body` weiter oben). */
.sieger-luecke {
    display: block;
    height: 1.6em;
    height: 1lh;
}

/* KEIN UMBRUCH IN DEN BEIDEN SPALTEN — sonst zaehlt die Luecke oben falsch.
   Sie ist EINE Zeile hoch; ein umgebrochener Name ist zwei. Gemessen am
   19.08.2026 in Chrome, Wrapper auf 390 px gestellt (Spa 2026, zwei Autos zu je
   drei Fahrern): „Sheldon Van Der Linde" brach um, und die Teamblocke standen
   danach 76 px zu tief bzw. 11 px zu hoch. Mit `nowrap` sind es 0 px.

   Die Tabelle laeuft in `mode="scroll"`: Ist sie breiter als ihr Rahmen,
   bekommt der Rahmen eine waagerechte Bildlaufleiste — breiter statt
   umgebrochen ist dort genau das vorgesehene Verhalten und sprengt nichts.
   Gemessen am 19.08.2026 in einem echten 390-px-Rahmen: die Tabelle „Rennen
   und Sieger" misst **820,9 px** im 346 px breiten Rahmen; die SEITE scrollt
   trotzdem nicht mit (`documentElement.scrollWidth` 380 = `clientWidth` 380,
   bei 320 px Rahmen 310 = 310).

   KORREKTUR 19.08.2026 (Pruefermangel M3): Hier stand „480 px". Die Zahl war
   nicht erfunden, sondern an der FALSCHEN Tabelle gemessen — `querySelector(
   'table')` trifft auf dieser Seite zuerst „Rekordsieger" (480 px), und die
   hat mit `.sieger-stapel` nichts zu tun. Wer nachmisst, muss die Tabelle
   nehmen, die wirklich einen `.sieger-stapel` enthaelt. */
.sieger-stapel .driver-cell,
.sieger-stapel .team-cell {
    white-space: nowrap;
}

/* Duelltabelle (/compare): die bessere der beiden Platzierungen wird
   hervorgehoben — genau das ist die Aussage einer Duellzeile. Die
   Podiumsfarben treten hier bewusst zurueck.

   DIE FARBE BEZEICHNET DEN FAHRER, nicht den Sieg. Bis zum 18.08.2026 stand
   JEDE gewonnene Zeile in Amber, auch die von Fahrer B — der auf derselben
   Seite ueberall sonst blau ist (Nutzermeldung: „wenn Ralf im direkten Duell
   gewinnt sollte er auch blau bekommen"). Das war der Rest einer aelteren
   Logik: Amber hiess frueher „vorn", seit demselben Tag heisst es „Fahrer A".
   Auf Michael/Ralf Schumacher betrifft das 36 der 157 Duellzeilen.

   Dieselben beiden Farben tragen die KPI-Werte (`.kpi-val` / `.kpi-val.kpi-b`),
   die Balkenabschnitte (`.kpi-bar i:nth-child(1|2)`) und die beiden Karten der
   Auswahl oben (`.vs-card--a` / `.vs-card--b`). */
.data-table td.cell-lead .pos {
    color: var(--c-1);
    border-bottom-color: var(--c-1);
}

.data-table td.cell-lead--b .pos {
    color: var(--c-2);
    border-bottom-color: var(--c-2);
}

/* ELO-Veraenderung in der Ergebnistabelle (/series/{slug}/{jahr}/{runde}).
   Die Zahl davor ist der Stand NACH dem Rennen, hier steht der Sprung dorthin.
   Kleiner und gedaempft, damit die Spalte auf einen Blick den Stand zeigt und
   erst auf den zweiten die Bewegung. Die beiden Richtungsfarben sind dieselben
   wie bei den Wertungsspalten (--ok / --err) — sie sagen „hoch" und „runter",
   nicht „gut" und „schlecht". */
.elo-delta {
    font-size: var(--fs-meta);
    color: var(--text-3);
    margin-left: 2px;
}

.elo-delta.is-up {
    color: var(--ok);
}

.elo-delta.is-down {
    color: var(--err);
}

/* Sortier-Pfeile (JS setzt die Klassen) */
.data-table thead th.th-sort {
    cursor: pointer;
    user-select: none;
    -webkit-user-select: none;
}

.data-table thead th.th-sort:hover {
    color: var(--text-1);
}

.data-table thead th.th-sort::after {
    content: " \2195";
    opacity: .35;
    font-size: 11px;
}

.data-table thead th.th-sort.sort-asc::after {
    content: " \25B2";
    opacity: .95;
    color: var(--accent);
}

.data-table thead th.th-sort.sort-desc::after {
    content: " \25BC";
    opacity: .95;
    color: var(--accent);
}

/* ==========================================================================
   07 COMPONENTS
   ========================================================================== */

/* --- page-header --- */
.page-header {
    padding: var(--sp-5) 0 var(--sp-5);
    border-bottom: 1px solid var(--line-1);
    margin-bottom: var(--sp-5);
}

.page-header h1 {
    font-size: var(--fs-h1);
    font-family: var(--font-display);
    font-weight: 600;
    color: var(--text-1);
}

.page-header .ph-meta {
    margin-top: var(--sp-3);
    color: var(--text-2);
    font-size: var(--fs-sm);
}

/* Emblem in der Kopfzeile (series/show, manufacturers/show). Bewusst nur ein
   Abstand statt eines Flex-Umbaus von .ph-meta: dieselbe Zeile traegt auf
   anderen Seiten ganze Absaetze (<p class="prose"> auf /manufacturers), die
   ein `display:flex` in eine Spalte zwingen wuerde. */
.page-header .ph-meta .emblem {
    margin-right: var(--sp-3);
}

.page-header .ph-actions {
    margin-top: var(--sp-4);
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
}

/* Kopfzeilen, deren Aktionsleiste eine Blaetter-Leiste ist (zurueck · Mitte ·
   vor). Sie steht dann genauso gespreizt wie .btn-row--split, mit dem
   Vor-Knopf am rechten Rand. Auf der Rennseite rendert dieselbe Vorlage
   (partials/rennen-blaettern) oben und unter der Ergebnistabelle: unten lag
   sie in .btn-row--split und war verteilt, oben klebten alle drei Knoepfe
   links — dieselbe Leiste, zweimal anders ausgerichtet.

   EIGENE KLASSE STATT UMBAU VON .ph-actions: Die Saisonseite
   (pages/series/season.blade.php) traegt in derselben Kopfzeile dieselben
   drei Knoepfe und wuerde mitwandern — "Spaeter →" sprang in der Gegenprobe
   um 800 px nach rechts. /drivers/{slug} waere KEIN Grund dagegen, wie
   frueher hier stand: ein einzelnes Flex-Kind ("Vergleichen") bleibt auch
   unter space-between links stehen (gemessen: 0 px Unterschied).

   UMBRUCH: Passen die drei Knoepfe nicht in eine Zeile — sehr lange
   Rennnamen oder schmale Schirme —, bricht die Leiste um. Der Vor-Knopf
   steht dann LINKS auf der naechsten Zeile; rechtsbuendig ist er nur im
   ungebrochenen Fall. Bleiben Zurueck und Mitte zusammen auf Zeile 1 (so
   bei allen Desktop-Faellen), rutscht der Mittelknopf an den rechten Rand.
   Passen auch die beiden nicht mehr nebeneinander, steht jeder Knopf auf
   einer eigenen Zeile und alle drei stehen links. Auf
   /series/porsche-supercup/2025/5 gemessen: eine Zeile ab 520 px
   Leistenbreite, zwei Zeilen von 309 bis 519 px, drei Zeilen ab 308 px
   abwaerts. Das tut .btn-row--split unten seit jeher genauso — die beiden
   Leisten bleiben in JEDER dieser Lagen gleich (441 Messpunkte je 1 px
   geprueft, obere und untere Leiste durchgaengig deckungsgleich), und nur
   darauf kommt es hier an. Bei voller Leistenbreite
   (1112 px) betrifft der Umbruch 66 von 16.325 Rennseiten, 43 davon
   stock-car-brasil (gemessen 18.08.2026 aus den Canvas-Zeichenbreiten der
   Knopfschrift; am Grenzfall /series/indycar/1999/7 nachgestellt: 1132 px
   Bedarf, 2 Zeilen. Der Nenner waechst mit jedem Import weiter). */
.page-header--split .ph-actions {
    justify-content: space-between;
}

/* --- Positionen --- */
.pos {
    display: inline-block;
    min-width: 26px;
    text-align: center;
    font-weight: 600;
    font-size: 15px;
    font-variant-numeric: tabular-nums;
    color: var(--text-2);
    border-bottom: 2px solid transparent;
    line-height: 1.3;
}

.pos-1 {
    color: var(--pod-1);
    border-bottom-color: var(--pod-1);
}

.pos-2 {
    color: var(--pod-2);
    border-bottom-color: var(--pod-2);
}

.pos-3 {
    color: var(--pod-3);
    border-bottom-color: var(--pod-3);
}

/* KEINE Position — der Fahrer hat kein gewertetes Ergebnis, x-pos zeigt "—".
   N1 (Etappe 3): Das ist seit dem Umbau die EINZIGE Bedeutung dieser Klasse.
   Bis dahin vergab `renumber()` in app.js sie zusaetzlich fuer jeden Rang ab 4
   — zwei Aussagen unter einem Namen. Ein Rang ab 4 traegt jetzt nur `.pos`
   (Farbe --text-2 aus der Basisregel). */
.pos-none {
    color: var(--text-3);
    font-size: var(--fs-meta);
}

.pos-dnf {
    color: var(--err);
    font-size: var(--fs-meta);
    font-weight: 600;
}

/* --- driver-cell / team-cell --- */
/* Flagge in den Listenzeilen der Startseite („Letzte Ergebnisse", „ELO Top 10",
   Nutzer-Vorgabe 18.08.2026). Diese Zeilen benutzen NICHT `.driver-cell`,
   sondern `.lr-title`/`.lr-sub` — beides `display: block` mit
   `text-overflow: ellipsis`. Die Flagge steht deshalb INNERHALB des Links und
   braucht ihren Abstand als Rand statt als Flex-Gap; ohne ihn klebt sie am
   Namen („DEMarco Wittmann", in Chrome gesehen 18.08.2026). Der Wert ist
   derselbe wie das Gap von `.driver-cell`, damit der Abstand ueberall gleich
   aussieht.

   Eigene Klasse statt eines Randes an `.flag`: den truege sonst jede Flagge im
   Projekt, und in `.driver-cell` kaeme er zum Flex-Gap hinzu. */
.lr-flag {
    margin-right: var(--sp-2);
}

.driver-cell {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    min-width: 0;
}

.driver-cell .dc-body {
    min-width: 0;
}

.driver-cell a {
    font-weight: 600;
    color: var(--text-1);
}

.driver-cell a:hover {
    color: var(--accent);
}

.driver-cell .dc-sub {
    display: block;
    font-size: var(--fs-meta);
    color: var(--text-3);
}

.flag {
    width: 1.33em;
    height: 1em;
    object-fit: cover;
    border-radius: 2px;
    border: 1px solid rgba(242, 239, 233, .18);
    vertical-align: -0.14em;
    display: inline-block;
    flex-shrink: 0;
}

/* --- Emblem (Serien- und Herstellerzeichen) ------------------------------
   Markup: resources/views/components/emblem.blade.php, Regeln und Farbwerte:
   App\Support\Emblem + config/emblems.php.

   Eine Plakette, zwei Fuellungen: entweder das gemeinfreie Original-SVG
   (`.emblem--bild`) oder das Kuerzel als Eigen-Emblem (`.emblem--eigen`).
   Beide sitzen auf demselben hellen Traeger, damit eine Uebersichtsseite
   nicht in zwei Bildsprachen zerfaellt.

   Die MARKENFARBE ist bewusst dosiert: ein 1px-Ring (--em-ring, 55 % Deckung)
   und beim Eigen-Emblem ein 10-%-Wash hinter dem Kuerzel plus die Schriftfarbe
   (--em-ink). Keine bunten Vollflaechen — sonst kippt das ruhige
   Erscheinungsbild (Auto-Memory „Design erst anschauen").

   --em-ink ist NICHT die rohe Markenfarbe, sondern die auf 4,5:1 gegen die
   Plakette nachgerechnete Fassung (Emblem::lesbareFarbe()). Ohne das haette
   ADAC-Gelb #FFCC00 auf #f2efe9 ein Kontrastverhaeltnis von 1,3:1.

   KEIN eigener Breakpoint: die drei Groessen sind fest, und beide Karten-Grids
   (.series-grid, .event-grid) fuellen per auto-fill selbst auf. Der Kommentar
   in pages/manufacturers/index.blade.php warnt ausdruecklich davor, hier neue
   Haltepunkte einzufuehren. */
.emblem {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    background-color: var(--emblem-plate);
    border: 1px solid var(--em-ring, var(--emblem-plate-line));
    border-radius: var(--r-s);
    overflow: hidden;
    vertical-align: middle;
}

/* Feste Masse: die Plakette steht, bevor das SVG geladen ist — kein
   Layout-Sprung beim Nachladen (loading="lazy" am <img>). */
.emblem--sm {
    width: 56px;
    height: 32px;
    padding: 3px 5px;
}

.emblem--md {
    width: 76px;
    height: 42px;
    padding: 4px 7px;
}

.emblem--lg {
    width: 104px;
    height: 56px;
    padding: 6px 9px;
}

.emblem img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.emblem--eigen {
    /* Der Wash liegt als Verlauf UEBER der Plakettenfarbe — zwei Farben in
       einer background-Kurzschrift gibt es nicht. */
    background-image: linear-gradient(var(--em-wash, transparent), var(--em-wash, transparent));
}

.em-abbr {
    font-family: var(--font-display);
    font-weight: 700;
    line-height: 1;
    letter-spacing: .01em;
    color: var(--em-ink, var(--accent-ink));
    white-space: nowrap;
}

.emblem--sm .em-abbr {
    font-size: 16px;
}

.emblem--md .em-abbr {
    font-size: 21px;
}

.emblem--lg .em-abbr {
    font-size: 28px;
}

.team-cell a {
    color: var(--text-2);
    font-weight: 400;
}

.team-cell a:hover {
    color: var(--text-1);
}

.team-cell .tc-none {
    color: var(--text-2);
}

/* Trenner zwischen mehreren Teams einer Saison (Fahrerwechsel, Gaststart).
   Eigene Klasse statt eines nackten Punkts im Markup: der Trenner soll
   blasser sein als die Teamnamen und die Abstaende sollen nicht am
   Leerraum der Blade-Vorlage haengen. */
.team-sep {
    color: var(--text-3);
    margin: 0 4px;
}

/* --- stat-tile --- */
.stat-tile {
    background: var(--bg-1);
    border: 1px solid var(--line-1);
    border-radius: var(--r-m);
    padding: var(--sp-4);
}

.stat-value {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: clamp(28px, 5vw, 38px);
    line-height: 1.05;
    color: var(--text-1);
    font-variant-numeric: tabular-nums;
}

.stat-tile--accent .stat-value {
    color: var(--accent);
}

.stat-label {
    margin-top: var(--sp-2);
    font-size: var(--fs-meta);
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--text-3);
}

/* Fussnote einer Kachel (x-stat-tile, Prop `hint`). Bewusst NICHT in
   Grossbuchstaben wie das Label: sie ist ein Satz, keine Rubrik. */
.stat-hint {
    margin-top: var(--sp-1);
    font-size: var(--fs-meta);
    line-height: 1.35;
    color: var(--text-3);
    text-transform: none;
    letter-spacing: 0;
}

.stat-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--sp-3);
}

/* --- Podium (series/race) --- */
.podium-grid {
    display: grid;
    /* Gestapelt bis 768px. Bis zum 18.08.2026 stand hier ein reines
       `repeat(auto-fit, minmax(220px, 1fr))` ohne Breakpoint. Das musste
       weichen, als die Podestform dazukam (Sieger in der Mitte, weiter unten):
       auto-fit stellte die drei Karten schon ab rund 726px Fenster
       nebeneinander, die Form begann aber erst bei 768px — gemessen 18.08.2026
       lagen dazwischen rund 40px, in denen drei Spalten schlicht als 1, 2, 3
       dastanden. Jetzt fangen Spalten und Form gemeinsam an.

       Fuer Podeste mit nur einer oder zwei Karten (an der Live-Datenbank
       gemessen: 50 bzw. 181 von 16.913 Rennen) heisst das, dass sie unter 768px
       untereinander stehen statt sich zu zweit einen knappen Streifen zu
       teilen — bei 500px waeren das zwei Karten zu je 223px fuer Fahrername,
       Flagge und Team gewesen. */
    grid-template-columns: 1fr;
    gap: var(--sp-3);
}

@media (min-width: 768px) {
    .podium-grid {
        grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    }
}

.podium-card {
    background: var(--bg-1);
    border: 1px solid var(--line-1);
    border-top: 3px solid var(--line-2);
    border-radius: var(--r-m);
    padding: var(--sp-4);
    display: flex;
    gap: var(--sp-3);
    align-items: flex-start;
}

.podium-card--1 { border-top-color: var(--pod-1); }
.podium-card--2 { border-top-color: var(--pod-2); }
.podium-card--3 { border-top-color: var(--pod-3); }

/* PODESTFORM: Sieger in die Mitte und hoeher (Nutzer-Vorgabe 18.08.2026,
   `/series/f1/2001/8`: „beim Podium den ersten in die Mitte schreiben, und ein
   Stueck hoeher"). Vorher standen die drei Karten schlicht als 1, 2, 3 von
   links nach rechts auf einer Linie.

   NUR NEBENEINANDER, und nur bei drei Karten: `--stufen` setzt die View
   ausschliesslich bei genau drei Podestplaetzen (race.blade.php), und die Form
   gilt erst ab 768px. Untereinander gestapelt gibt es keine Mitte, und der
   Sieger gehoert dort nach oben — die DOM-Reihenfolge bleibt deshalb 1, 2, 3
   und wird hier nur VISUELL umgestellt. Vorlesende Hilfsmittel und die
   Ergebnistabelle darunter lesen weiter in der Platzierungsreihenfolge; die
   Ziffer steht ausserdem in jeder Karte.

   `minmax(0, 1fr)` statt `1fr`: bei 768px bleiben je Spalte rund 230px, und ein
   langer Fahrername darf die Spalte nicht aufblaehen (`.podium-body` bringt
   `min-width: 0` schon mit). Sonst schoebe die Karte das Raster ueber den
   Bildschirmrand. */
@media (min-width: 768px) {
    .podium-grid--stufen {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        align-items: start;
    }

    .podium-grid--stufen .podium-card--2 { order: 1; }
    .podium-grid--stufen .podium-card--1 { order: 2; }
    .podium-grid--stufen .podium-card--3 { order: 3; }

    /* Nicht der Sieger wird angehoben, sondern die beiden anderen abgesenkt:
       So bleibt der Abstand zur Ueberschrift „Podium" unveraendert, statt dass
       die mittlere Karte nach oben in sie hineinlaeuft. Sichtbar ist dasselbe —
       Platz 1 steht hoeher. */
    .podium-grid--stufen .podium-card--2,
    .podium-grid--stufen .podium-card--3 { margin-top: var(--sp-5); }
}

.podium-rank {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: clamp(28px, 5vw, 38px);
    line-height: 1;
    color: var(--text-2);
    font-variant-numeric: tabular-nums;
}

.podium-card--1 .podium-rank { color: var(--pod-1); }
.podium-card--2 .podium-rank { color: var(--pod-2); }
.podium-card--3 .podium-rank { color: var(--pod-3); }

.podium-body {
    min-width: 0;
}

.podium-team {
    display: block;
    margin-top: var(--sp-1);
    font-size: var(--fs-meta);
}

/* --- Buttons / Prev-Next-Paare --- */
.btn {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    min-height: 44px;
    padding: 0 var(--sp-4);
    border: 1px solid var(--line-1);
    border-radius: var(--r-s);
    background: var(--bg-1);
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--text-1);
}

.btn:hover {
    border-color: var(--accent);
    color: var(--accent);
}

.btn--off {
    color: var(--text-3);
    opacity: .5;
}

/* Blaetter-Buttons, die einen Rennnamen tragen ("Runde 2: Saudi Arabian Grand
   Prix"). Der Name ist die eigentliche Information und wird deshalb NICHT
   weggelassen, sondern auf schmalen Schirmen abgeschnitten:
   .btn ist inline-flex, text-overflow wirkt dort nicht am Button selbst,
   sondern nur an einem eigenen Textkind mit overflow:hidden — daher
   .btn-label. min-width:0 erlaubt dem Flex-Kind, unter seine Inhaltsbreite zu
   schrumpfen; ohne das greift ellipsis nie. Kein neuer Breakpoint noetig. */
.btn--nav {
    max-width: 100%;
    min-width: 0;
}

.btn--nav .btn-label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.btn-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2);
}

.btn-row--split {
    justify-content: space-between;
}

/* --- Event-Karten (/events) --- */
.event-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: var(--sp-3);
}

.event-card {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    padding: var(--sp-4);
    background: var(--bg-1);
    border: 1px solid var(--line-1);
    border-radius: var(--r-m);
}

.event-card:hover {
    border-color: var(--accent);
    background: var(--bg-2);
}

.event-card .ec-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    flex-wrap: wrap;
}

/* Emblem + Name als eine Gruppe in der Kopfzeile der Karte (/manufacturers).
   Ohne sie wuerde `justify-content: space-between` von .ec-top die drei Kinder
   gleichmaessig verteilen. `min-width: 0` ist Pflicht, damit ein langer
   Herstellername im Grid umbrechen kann statt die Karte zu sprengen. */
.event-card .ec-lead {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    min-width: 0;
}

.event-card .ec-name {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: var(--fs-h3);
    line-height: 1.2;
    color: var(--text-1);
}

.event-card:hover .ec-name {
    color: var(--accent);
}

.event-card .ec-text {
    font-size: var(--fs-sm);
    color: var(--text-2);
}

.event-card .ec-facts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-4);
    margin-top: auto;
    padding-top: var(--sp-3);
    border-top: 1px solid var(--line-1);
}

/* Eine Kennzahl der Karte (Zahl ueber Beschriftung). Die Regel stand vorher
   nicht im CSS — die Klasse war ein toter Name, und dass der Block trotzdem
   stimmte, lag allein an der Blockifizierung als Flex-Kind von .ec-facts.
   Hier ausgeschrieben, damit die Absicht am Markup ablesbar bleibt; die
   Darstellung aendert sich dadurch nicht. */
.event-card .ec-fact {
    display: block;
    min-width: 0;
}

.event-card .ec-num {
    display: block;
    font-weight: 600;
    color: var(--text-1);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.event-card .ec-lab {
    display: block;
    font-size: var(--fs-meta);
    color: var(--text-3);
}

/* --- series-card --- */
.series-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: var(--sp-3);
}

.series-card {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: var(--sp-3);
    min-height: 112px;
    padding: var(--sp-4);
    background: var(--bg-1);
    border: 1px solid var(--line-1);
    border-radius: var(--r-m);
    overflow: hidden;
}

.series-card:hover {
    border-color: var(--line-2);
    background: var(--bg-2);
}

.series-card::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    height: 2px;
    width: 0;
    background: var(--accent);
    transition: width .18s ease;
}

.series-card:hover::after {
    width: 100%;
}

/* `.series-abbr` (Barlow 700, 34px) ist am 10.08.2026 ersatzlos entfallen: Die
   Serien-Karte traegt seitdem das Emblem (.emblem--md) statt des nackten
   Text-Kuerzels, und die Klasse kam in resources/views nirgends sonst vor
   (grep, beide Fundstellen waren diese Regel und ihre Handy-Fassung). Eine
   Regel ohne Markup ist toter Code — dieselbe Begruendung, aus der der
   Abschnitt „99 LEGACY" am 07.08.2026 verschwunden ist. */

.series-name {
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--text-1);
}

.series-meta {
    display: block;
    font-size: var(--fs-meta);
    font-weight: 400;
    color: var(--text-3);
    font-variant-numeric: tabular-nums;
}

/* --- Saison-Chips (series/show) --- */
/* NUTZER-BEFUND 05.08.2026: Auf /series/f1 lief der Status "Abgeschlossen" aus
   der Kachel. Ursache war die Zeile "Jahr | Badge" NEBENEINANDER in einer
   150px-Spalte: nach 32px Innenabstand blieben 118px fuer beides, das Badge
   allein braucht rund 105px. Zwei Aenderungen, beide noetig:
     1. Inhalt UNTEREINANDER (flex-direction: column) — das Badge bekommt die
        volle Kachelbreite.
     2. Spalte 150px -> 170px, damit auch lange Labels noch Luft haben.
   Die Kachel hat weiterhin nur eine MINDESThoehe und waechst mit dem Inhalt. */
.season-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
    gap: var(--sp-3);
}

.season-chip {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: var(--sp-2);
    min-height: 56px;
    padding: var(--sp-3) var(--sp-4);
    background: var(--bg-1);
    border: 1px solid var(--line-1);
    border-radius: var(--r-m);
}

/* Das Badge bleibt einzeilig (.badge setzt white-space: nowrap) und darf die
   Kachel nicht sprengen: mehr als die Innenbreite bekommt es nicht. */
.season-chip .badge {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
}

.season-chip:hover {
    border-color: var(--accent);
    background: var(--bg-2);
}

/* Eine Ausgabe, die in einer ANDEREN Serie liegt (heute nur /series/24h-le-mans:
   die 47 Jahre, in denen Le Mans ein Lauf der Sportwagen-WM bzw. der WEC war).
   Der Klick verlässt die Serie, also darf die Kachel nicht aussehen wie die
   eigenen — sie bekommt den gestrichelten Rand und den ruhigeren Grund. Kein
   eigener Farbwert: beides sind vorhandene Tokens, damit der helle wie der
   dunkle Modus ohne zweite Regel stimmen. */
.season-chip--fremd {
    background: transparent;
    border-style: dashed;
}

.season-chip--fremd .season-year {
    color: var(--text-2);
}

.season-year {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: var(--fs-h3);
    color: var(--text-1);
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

/* --- badge --- */
.badge {
    display: inline-block;
    padding: 2px var(--sp-2);
    border-radius: var(--r-s);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    white-space: nowrap;
    border: 1px solid transparent;
}

.badge--accent {
    background: var(--accent-wash);
    color: var(--accent);
    border-color: rgba(232, 163, 61, .35);
}

.badge--ok {
    background: rgba(111, 191, 130, .12);
    color: var(--ok);
    border-color: rgba(111, 191, 130, .35);
}

/* Fehlzustand. Ergaenzt 05.08.2026 fuer /status: die Betriebsseite muss einen
   fehlgeschlagenen Scraper-Lauf auf einen Blick von einem erfolgreichen
   unterscheiden. Farbe ist --err, nicht das alte Signalrot. */
.badge--err {
    background: rgba(224, 122, 107, .12);
    color: var(--err);
    border-color: rgba(224, 122, 107, .35);
}

.badge--muted {
    background: var(--bg-2);
    color: var(--text-3);
    border-color: var(--line-1);
}

.badge--outline {
    background: transparent;
    color: var(--text-2);
    border-color: var(--line-2);
}

/* --- pagination --- */
.pagination {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    margin-top: var(--sp-5);
    flex-wrap: wrap;
}

.pagination .pg-link,
.pagination .pg-disabled {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 var(--sp-4);
    border: 1px solid var(--line-1);
    border-radius: var(--r-s);
    background: var(--bg-1);
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--text-1);
}

.pagination .pg-link:hover {
    border-color: var(--accent);
    color: var(--accent);
}

.pagination .pg-disabled {
    color: var(--text-3);
    opacity: .5;
}

.pagination .pg-info {
    font-size: var(--fs-sm);
    color: var(--text-3);
    font-variant-numeric: tabular-nums;
}

/* Seitenzahlen (05.08.2026): erste, aktuelle mit Nachbarn, letzte. Optik und
   Trefferflaeche wie die Segmentleiste — dasselbe Muster fuer dieselbe Geste
   (ein Ziel unter mehreren waehlen), nur schmaler, weil eine Ziffer keine
   Wortbreite braucht. Die aktuelle Seite ist kein Link: sie fuehrt nirgendwo hin. */
.pagination .pg-pages {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    flex-wrap: wrap;
}

.pagination .pg-num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    padding: 0 var(--sp-2);
    border: 1px solid var(--line-1);
    border-radius: var(--r-s);
    background: var(--bg-1);
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--text-2);
    font-variant-numeric: tabular-nums;
}

.pagination a.pg-num:hover {
    border-color: var(--accent);
    color: var(--accent);
}

.pagination .pg-num--jetzt {
    background: var(--accent-wash);
    border-color: rgba(232, 163, 61, .45);
    color: var(--accent);
}

.pagination .pg-gap {
    color: var(--text-3);
    font-size: var(--fs-sm);
}

/* --- chart --- */
.chart-box {
    position: relative;
    background: var(--bg-1);
    border: 1px solid var(--line-1);
    border-radius: var(--r-m);
    padding: var(--sp-4);
}

.chart-box .chart-canvas {
    position: relative;
    width: 100%;
}

.chart-box canvas {
    display: block;
    width: 100%;
}

/* --- empty-state --- */
.empty-state {
    background: var(--bg-1);
    border: 1px dashed var(--line-2);
    border-radius: var(--r-m);
    padding: var(--sp-6) var(--sp-4);
    text-align: center;
    color: var(--text-2);
}

.empty-state .es-action {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    margin-top: var(--sp-3);
    padding: 0 var(--sp-4);
    border: 1px solid var(--accent);
    border-radius: var(--r-s);
    color: var(--accent);
    font-weight: 600;
}

.empty-state .es-action:hover {
    background: var(--accent-wash);
}

/* --- breadcrumb --- */
.breadcrumb {
    font-size: var(--fs-meta);
    color: var(--text-3);
    margin-bottom: var(--sp-3);
}

.breadcrumb ol {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2);
}

.breadcrumb a {
    color: var(--text-2);
}

.breadcrumb a:hover {
    color: var(--accent);
}

.breadcrumb li + li::before {
    content: "/";
    color: var(--line-2);
    margin-right: var(--sp-2);
}

/* --- Listen-Karten (Home: letzte Ergebnisse / ELO) --- */
.card {
    background: var(--bg-1);
    border: 1px solid var(--line-1);
    border-radius: var(--r-m);
    overflow: hidden;
}

.list-row {
    display: grid;
    grid-template-columns: 44px 1fr auto;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    border-bottom: 1px solid var(--line-1);
    min-height: 56px;
}

.list-row:last-child {
    border-bottom: 0;
}

.list-row:hover {
    background: var(--bg-2);
}

.list-row .lr-tag {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 15px;
    color: var(--accent);
    letter-spacing: .02em;
}

.list-row .lr-main {
    min-width: 0;
}

.list-row .lr-title {
    display: block;
    font-size: var(--fs-base);
    font-weight: 600;
    color: var(--text-1);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.list-row .lr-sub {
    display: block;
    font-size: var(--fs-meta);
    color: var(--text-3);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.list-row .lr-side {
    font-size: var(--fs-meta);
    color: var(--text-3);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    text-align: right;
}

.list-row .lr-score {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: var(--fs-h3);
    color: var(--text-1);
    font-variant-numeric: tabular-nums;
}

/* Kategorie-Vorschau (Startseite) */
.cat-preview > * + * {
    margin-top: var(--sp-5);
}

.cat-label {
    font-size: var(--fs-meta);
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--text-label);
    margin-bottom: var(--sp-2);
}

.chip-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
}

.abbr-chip {
    display: inline-flex;
    align-items: baseline;
    gap: var(--sp-2);
    min-height: 44px;
    padding: var(--sp-2) var(--sp-3);
    background: var(--bg-1);
    border: 1px solid var(--line-1);
    border-radius: var(--r-s);
}

.abbr-chip:hover {
    border-color: var(--accent);
    background: var(--bg-2);
}

/* Aktiver Chip einer Filterleiste (Serien-Filter der Streckenseite,
   19.08.2026). Gleiche Auszeichnung, gleicher Hintergrund und gleiche
   Rahmenfarbe wie der aktive Eintrag der Segmentleiste auf /records — dort
   ist das Muster abgenommen: echte Links, genau einer mit
   aria-current="page". Ohne diese Regel waere die Auswahl NUR fuer
   Screenreader sichtbar.

   NICHT „gleiche Farben" (Pruefermangel M4, 19.08.2026): Die Segmentleiste
   setzt zusaetzlich `color: var(--accent)`. Hier waere das eine TOTE Regel —
   `.ac-abbr` und `.ac-name` setzen ihre Farbe beide selbst (Zeile 2204 und
   2212 dieser Datei), eine Vererbung vom Chip erreicht keinen Text. Wer sie
   trotzdem ergaenzt, aendert nichts und glaubt, etwas getan zu haben. */
.abbr-chip[aria-current="page"] {
    background: var(--accent-wash);
    border-color: rgba(232, 163, 61, .45);
}

.abbr-chip .ac-abbr {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: var(--fs-lead);
    color: var(--accent);
    line-height: 1.2;
}

.abbr-chip .ac-name {
    font-size: var(--fs-sm);
    color: var(--text-1);
}

/* Quick-Links */
.link-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--sp-3);
}

.link-tile {
    display: block;
    padding: var(--sp-4);
    background: var(--bg-1);
    border: 1px solid var(--line-1);
    border-radius: var(--r-m);
    min-height: 76px;
}

.link-tile:hover {
    border-color: var(--line-2);
    background: var(--bg-2);
}

.link-tile strong {
    display: block;
    font-size: var(--fs-base);
    font-weight: 600;
    color: var(--text-1);
}

.link-tile span {
    display: block;
    font-size: var(--fs-meta);
    color: var(--text-3);
}

/* Textlink mit Pfeil */
.more-link {
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--accent);
    white-space: nowrap;
}

/* Hero */
.hero {
    padding: var(--sp-6) 0 var(--sp-5);
    border-bottom: 1px solid var(--line-1);
}

.hero h1 {
    font-size: var(--fs-h1);
    margin-bottom: var(--sp-3);
}

/* Zwei-Spalten-Layout */
.two-col {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--sp-5);
}

/* --- Segmentleiste: serverseitige Sortierung / Abschnittswahl --------------
   EINE Leiste, ZWEI Aufgaben: die Sortierung der ELO-Rangliste und die
   Abschnitte des Fahrerprofils. Beide sind in Wahrheit dasselbe — eine Reihe
   echter Links, von denen genau einer die aktuelle Ansicht ist. Deshalb auch
   dieselbe Auszeichnung: <a href> + aria-current="page". Kein JavaScript,
   keine Buttons, keine versteckten Zustaende.
   Umbruch statt horizontalem Scrollen: sechs Abschnitte passen auf einem
   Handy nicht in eine Zeile, und was aus dem Bild geschoben wird, findet
   niemand. 44px Mindesthoehe wie bei allen Zielen. */
.segbar {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
    margin-bottom: var(--sp-4);
}

.segbar a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 var(--sp-4);
    border: 1px solid var(--line-1);
    border-radius: var(--r-s);
    background: var(--bg-1);
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--text-2);
}

.segbar a:hover {
    border-color: var(--accent);
    color: var(--accent);
}

.segbar a[aria-current="page"] {
    background: var(--accent-wash);
    border-color: rgba(232, 163, 61, .45);
    color: var(--accent);
}

/* Variante fuer LANGE Leisten (Serien-Filter auf /records: "Alle Serien" +
   18 Kuerzel). Der Grundfall oben wickelt bewusst um, und bei sechs
   ausgeschriebenen Abschnittsnamen ist das richtig. Neunzehn Eintraege ergeben
   auf einem 360px breiten Schirm aber fuenf Zeilen a 44px — 220px Filterleiste
   vor der ersten Zahl. Deshalb hier eine Zeile zum Wischen (nur unter 768px,
   Regeln im Mobil-Block), mit derselben sichtbaren Amber-Bildlaufleiste wie bei
   den Tabellen: sie ist der Hinweis, dass rechts weitergeht. Ab 768px greift
   wieder der Umbruch, dann passen alle Kuerzel in zwei Zeilen. */
.segbar--scroll a {
    flex: 0 0 auto;
    white-space: nowrap;
}

/* --- Suchfeld + Knopf --- */
.searchbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2);
}

.field {
    flex: 1 1 240px;
    min-width: 0;
    min-height: 44px;
    padding: 0 var(--sp-3);
    background: var(--bg-1);
    border: 1px solid var(--line-1);
    border-radius: var(--r-s);
    color: var(--text-1);
    font-size: var(--fs-base);
}

/* Auswahlfeld als `.field` (ELO-Filter: Land/Serie/Jahr). Ein <select> zieht
   sich sonst auf die Breite seines laengsten Eintrags — „Sportwagen-
   Weltmeisterschaft" neben „2026" ergaebe drei verschieden breite Felder in
   einer Reihe. `width: 100%` im Traeger unten macht sie gleich breit.
   Die Pfeilfarbe kommt vom Browser; `color-scheme: dark` im Layout sorgt
   dafuer, dass er die dunkle Variante zeichnet. */
select.field {
    width: 100%;
    cursor: pointer;
}

/* Filterleiste: drei gleich breite Traeger, darunter die Knoepfe. Unter 420px
   nebeneinander waeren die Felder 100px breit — dort steht jedes auf eigener
   Zeile (der Grundwert von `flex-basis` greift erst ab genug Platz). */
.filterbar-feld {
    flex: 1 1 200px;
    min-width: 0;
}

.field::placeholder {
    color: var(--text-3);
}

.field:focus {
    border-color: var(--accent);
}

.field-label {
    display: block;
    font-size: var(--fs-meta);
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--text-label);
    margin-bottom: var(--sp-2);
}

/* Rueckmeldung am Feld, wenn ein eingegebener Name nicht aufloesbar war
   (compare ohne JavaScript). Ohne sichtbaren Hinweis sieht die Seite so aus,
   als waere nichts eingegeben worden — genau das stille Scheitern, das dieses
   Projekt schon zu oft hatte. */
.field-error {
    margin-top: var(--sp-2);
    font-size: var(--fs-meta);
    color: var(--err);
}

/* .btn wird auch als <button> gebraucht (Suche, Vergleich abschicken). */
button.btn {
    cursor: pointer;
    font-family: inherit;
}

.btn--primary {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--accent-ink);
}

.btn--primary:hover {
    background: var(--accent-strong);
    border-color: var(--accent-strong);
    color: var(--accent-ink);
}

/* --- Vorschlagsliste zum Suchfeld (compare-Picker) ------------------------
   Fuellt sich erst durch JavaScript (fetch auf /api/drivers/search). Ohne
   JavaScript bleibt sie leer und `hidden` — das Textfeld daneben wird dann
   ganz normal abgeschickt und der Server loest den Namen auf. */
.ac {
    position: relative;
}

/* Das Feld steht hier allein in einem Block, nicht in der Flex-Zeile
   `.searchbar` — ohne diese Breite bliebe es auf seiner Standardbreite von
   rund 20 Zeichen stehen, waehrend die Vorschlagsliste darunter die volle
   Spalte einnimmt. */
.ac .field {
    display: block;
    width: 100%;
}

.ac-list {
    position: absolute;
    left: 0;
    right: 0;
    top: calc(100% + 4px);
    z-index: 20;
    max-height: 320px;
    overflow-y: auto;
    list-style: none;
    background: var(--bg-2);
    border: 1px solid var(--line-1);
    border-radius: var(--r-m);
    box-shadow: var(--shadow-pop);
}

.ac-list[hidden] {
    display: none;
}

.ac-item {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    width: 100%;
    min-height: 44px;
    padding: var(--sp-2) var(--sp-3);
    background: transparent;
    border: 0;
    border-bottom: 1px solid var(--line-1);
    color: var(--text-1);
    font-size: var(--fs-sm);
    text-align: left;
    cursor: pointer;
}

.ac-list li:last-child .ac-item {
    border-bottom: 0;
}

.ac-item:hover,
.ac-item.is-active {
    background: var(--bg-3);
}

.ac-item .ac-name {
    font-weight: 600;
}

.ac-item .ac-meta {
    margin-left: auto;
    font-size: var(--fs-meta);
    color: var(--text-3);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* --- Gegenueberstellung zweier Fahrer (compare) --- */
.vs-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--sp-4);
    align-items: start;
}

.vs-mark {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: var(--fs-h2);
    color: var(--accent);
    text-align: center;
    align-self: center;
}

.vs-card {
    background: var(--bg-1);
    border: 1px solid var(--line-1);
    border-radius: var(--r-m);
    padding: var(--sp-4);
}

.vs-card .vs-name {
    font-family: var(--font-display);
    font-size: var(--fs-h2);
    font-weight: 600;
    line-height: 1.1;
}

/* Die beiden Karten sind die Legende der ganzen Seite: Wer hier blau steht,
   ist unten in jedem Balken und jeder Zahl blau. Ohne das muesste der Leser
   raten, welche der beiden Farben zu welchem Namen gehoert — vorher standen
   beide Namen amber, die Farbe sagte also gar nichts.

   DIE KACHEL GEHOERT DAZU: `x-stat-tile ... accent` faerbt die Siegzahl mit
   `--accent`, und zwar in BEIDEN Karten. In Ralf Schumachers blauer Karte
   stand seine Siegzahl damit in Michaels Amber — ausgerechnet die Karte, die
   hier zur Legende erklaert wird, widersprach sich selbst (Pruefer-Befund
   18.08.2026, live gemessen).

   FAHRER A STEHT MIT DA, obwohl `--c-1` heute denselben Wert traegt wie
   `--accent`: Sonst haengt seine Farbe an `a { color: var(--accent) }` und an
   der Kachel-Grundregel, also an einem Ton, den nichts mit `--c-1`
   zusammenhaelt. Wer den Akzent aendert, bekaeme eine Karte, die etwas
   anderes behauptet als die Balken darunter. */
.vs-card--a .vs-name a,
.vs-card--a .stat-tile--accent .stat-value {
    color: var(--c-1);
}

.vs-card--b .vs-name a,
.vs-card--b .stat-tile--accent .stat-value {
    color: var(--c-2);
}

/* HOVER: NUR EIN UNTERSTRICH, UND FUER BEIDE KARTEN.
   Hier stand zuerst eine Regel nur fuer B, mit der Begruendung, `a:hover`
   wuerde B's Namen sonst auf den Akzentton zurueckspringen lassen. Das war
   falsch — aber nicht so pauschal, wie die erste Korrektur behauptete:
   Die Kartenregeln oben haben Spezifitaet (0,2,1) gegen (0,1,1) bei `a:hover`,
   sie gewinnen aber NUR FUER DIE FARBE. Sie deklarieren nichts sonst, und was
   sie nicht nennen, holt sich die schwaechere Regel trotzdem.

   NACHGESTELLT AM 18.08.2026 mit einer KLASSE statt einer Pseudoklasse
   (`a.pruef`, dieselbe Spezifitaet 0,1,1, per `classList.add` sicher
   schaltbar), gegengeprueft an einem gewoehnlichen Navigationslink als
   Kontrolle: Kontrolle nimmt die Farbe an, beide Fahrernamen behalten ihre —
   aber `text-decoration` UND `outline` kommen durch.
   Die frueher hier dokumentierte Probe (`a:focus` + `element.focus()`) taugt
   NICHT: `document.hasFocus()` ist in dieser Umgebung `false`, `:focus`
   trifft also nie, und die Probe meldet „bestanden", egal was im Stylesheet
   steht. Genau das Muster „laeuft, meldet Erfolg, tut nichts" — wer hier
   nachmisst, nimmt die Klassen-Probe.

   WARUM ES DIE REGEL BRAUCHT: Vor dieser Aenderung hellte `a:hover` beide
   Namen auf `--accent-strong` auf. Seit die Kartenregeln die Farbe festnageln,
   passiert dort gar nichts mehr — zwei grosse farbige Namen ohne jedes
   Klick-Signal. Der Unterstrich stellt die Rueckmeldung wieder her, ohne die
   Farbzuordnung anzufassen, und zwar fuer BEIDE Karten: Die erste Fassung gab
   ihn nur B und schuf damit eine Asymmetrie ohne Grund. */
.vs-card .vs-name a:hover {
    text-decoration: underline;
}

.vs-card .vs-sub {
    margin-top: var(--sp-1);
    font-size: var(--fs-meta);
    color: var(--text-3);
}

/* Kennzahl-Gegenueberstellung: Wert links, Bezeichnung mittig, Wert rechts,
   darunter ein Balken, dessen Breite das Verhaeltnis zeigt. Die Balkenbreite
   ist der einzige berechnete Wert der Seite und steht deshalb als einziges
   inline am Element. */
.kpi-row {
    padding: var(--sp-3) 0;
    border-bottom: 1px solid var(--line-1);
}

.kpi-row:last-child {
    border-bottom: 0;
}

.kpi-head {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: baseline;
    gap: var(--sp-3);
}

/* FARBE BEZEICHNET DEN FAHRER, NICHT DEN FUEHRENDEN (Nutzer-Befund
   18.08.2026 zum Vergleich Michael/Ralf Schumacher: „die Farben sind so doof,
   FIA GT hat Ralf 100% und Japanische F3000 Michael 100%, und beide Balken
   sind gelb").

   Bis dahin faerbte `is-lead` den jeweils besseren Wert amber — und den
   Balkenabschnitt gleich mit. Das hatte zwei Folgen: Bei 100:0 war der ganze
   Balken amber, EGAL welcher der beiden Fahrer die 100 hielt (genau der
   gemeldete Fall), und schon bei 60:40 sprang die Farbe von links nach rechts,
   je nachdem wer vorn lag — die Serienliste liess sich nicht mehr nach einem
   Fahrer durchsehen.

   Jetzt gilt durchgehend: linke Spalte = Fahrer A = --c-1, rechte Spalte =
   Fahrer B = --c-2. Das sind die ersten beiden Farben der Chart-Palette dieses
   Stylesheets, --c-1 traegt denselben Wert wie --accent.

   FUER FAHRER A AENDERT SICH TROTZDEM ETWAS, anders als hier zuerst stand:
   Vorher war `.kpi-val` schlicht `--text-1`, amber bekam NUR der jeweils
   fuehrende Wert. Jetzt ist jeder A-Wert amber, auch der unterlegene. Auf der
   Seite Michael/Ralf Schumacher betrifft das 5 der 24 A-Werte (gemessen
   18.08.2026); bei ungleicheren Paarungen mehr. Das ist der Preis dafuer, dass
   die Farbe eine Person bezeichnet und nicht mehr eine Rangfolge — genau der
   Tausch, um den es in dieser Aenderung geht.

   Die Zuordnung lernt man an den beiden Karten der Auswahl oben, die dieselben
   Farben tragen (.vs-card--a / .vs-card--b) — eine eigene Legende braucht es
   deshalb nicht. */
.kpi-val {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: var(--fs-h3);
    color: var(--c-1);
    font-variant-numeric: tabular-nums;
}

/* WER VORN LIEGT, sagt jetzt ein Strich unter dem Wert statt einer Farbe —
   `currentColor`, damit er die Fahrerfarbe uebernimmt und die Zuordnung nicht
   wieder bricht. Dasselbe Mittel benutzt `.pos` fuer die Podiumsplaetze.
   DER STRICH MUSS BLEIBEN, weil laengst nicht jede Zeile einen Balken hat.
   Ohne Balken sind (gemessen an compare.blade.php, 18.08.2026): „Bestes
   Ergebnis" (steht mit `false` in der `$kpis`-Liste), „Ø-Platzierung in
   diesen Rennen", „Podien dabei" und die Duell-Zeilen je Serie — dazu jede
   Zeile, deren beide Werte 0 sind, denn der Balken haengt an `$summe > 0`.
   In diesen Zeilen ist der Strich der EINZIGE Hinweis darauf, wer vorn liegt.
   Er wird dort zusaetzlich gebraucht, weil zwei davon andersherum zaehlen als
   der Rest: Bei „Bestes Ergebnis" (Richtung `tief`) und bei „Ø-Platzierung"
   (`a_avg_pos < b_avg_pos`) ist die KLEINERE Zahl die bessere — das sieht man
   den beiden Zahlen allein nicht an. */
.kpi-val.is-lead {
    border-bottom: 2px solid currentColor;
    padding-bottom: 2px;
}

/* OHNE `justify-self` waere der Strich so breit wie die GRIDSPALTE (1fr), also
   quer ueber die halbe Seite — beim ersten Blick darauf sah er aus wie ein
   zweiter Balken und stritt mit dem echten darunter. Die Werte schrumpfen
   deshalb auf ihre Textbreite; die Ausrichtung (A links, B rechts) bleibt
   dieselbe wie vorher ueber `text-align`. Gilt NUR fuer `.kpi-val`: Die
   grauen `.tag`-Zusatzzeilen der Serienbilanz sollen weiter die volle Spalte
   fuellen, damit ihr rechter Rand mit der Zahl darueber abschliesst. */
.kpi-val {
    justify-self: start;
}

.kpi-val.kpi-b {
    justify-self: end;
}

/* `.kpi-b` sitzt an JEDEM rechten Element der Zeile, auch an den grauen
   `.tag`-Zusaetzen ("3 Siege · 5 Podien"). Die Farbe haengt deshalb an
   `.kpi-val.kpi-b` und nicht an `.kpi-b` allein — sonst wuerden die Zusatz-
   zeilen mitgefaerbt und die Zeile bekaeme drei Farbtoene statt zwei. */
.kpi-b {
    text-align: right;
}

.kpi-val.kpi-b {
    color: var(--c-2);
}

.kpi-label {
    font-size: var(--fs-meta);
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--text-3);
    text-align: center;
}

.kpi-bar {
    display: flex;
    gap: 2px;
    height: 4px;
    margin-top: var(--sp-2);
    background: var(--bg-2);
    border-radius: 2px;
    overflow: hidden;
}

/* Die beiden Abschnitte stehen IMMER in der Reihenfolge A, B im Dokument —
   `nth-child` statt einer Klasse am Element, damit die Zuordnung nicht an
   einer Bedingung in der Blade-Datei haengen kann. Der Rueckfall `--line-2`
   bleibt fuer den Fall stehen, dass jemand einen dritten Abschnitt ergaenzt:
   der faellt dann grau auf statt eine Fahrerfarbe zu doppeln. */
.kpi-bar i {
    display: block;
    height: 100%;
    background: var(--line-2);
}

.kpi-bar i:nth-child(1) {
    background: var(--c-1);
}

.kpi-bar i:nth-child(2) {
    background: var(--c-2);
}

/* --- Fahrerprofil: Kopfzeile mit Lebensdaten --- */
.profile-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2) var(--sp-4);
}

.profile-meta .pm-item {
    font-size: var(--fs-sm);
    color: var(--text-2);
}

/* --- Erfolge: Karten statt Emoji-Zeilen --- */
.badge-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: var(--sp-3);
}

.badge-card {
    background: var(--bg-1);
    border: 1px solid var(--line-1);
    border-radius: var(--r-m);
    padding: var(--sp-4);
}

.badge-card .bc-title {
    display: block;
    margin-top: var(--sp-2);
    font-size: var(--fs-base);
    font-weight: 600;
    color: var(--text-1);
}

.badge-card .bc-text {
    display: block;
    margin-top: var(--sp-1);
    font-size: var(--fs-meta);
    color: var(--text-3);
}

/* --- Erklaerkasten ---
   Ein sichtbarer Absatz mit Rahmen, der eine Auswahlregel erklaert ("Warum
   fehlen manche Serien und Jahre?"). Bewusst kein <details>: was zugeklappt
   ist, liest niemand, und die Antwort auf "hier fehlt doch was" muss auf der
   Seite stehen, nicht hinter einem Klick. Der Amber-Balken links unterscheidet
   ihn von einer Datenkarte — er traegt Erklaerung, keine Zahlen. */
.note {
    background: var(--bg-1);
    border: 1px solid var(--line-1);
    border-left: 3px solid var(--accent);
    border-radius: var(--r-m);
    padding: var(--sp-4);
    /* Der Kasten endet dort, wo der Text endet. Ohne die Schranke ist er so
       breit wie die Seite, waehrend die Zeilen bei 70ch umbrechen — dann steht
       rechts eine handbreite leere Flaeche im Rahmen. */
    max-width: 78ch;
}

.note p,
.note ul {
    max-width: none;
}

.note > * + * {
    margin-top: var(--sp-3);
}

.note .note-title {
    display: block;
    font-family: var(--font-display);
    font-size: var(--fs-h3);
    font-weight: 600;
    color: var(--text-1);
}

.note ul {
    margin: 0;
    padding-left: var(--sp-5);
    max-width: 70ch;
}

.note li {
    font-size: var(--fs-sm);
    color: var(--text-2);
}

.note li + li {
    margin-top: var(--sp-2);
}

/* --- Champions-Karten ---
   Eine Karte je Meisterschaft (Serie + Klasse eines Jahres). KEINE
   .event-card: die ist als Ganzes ein Link und faerbt beim Ueberfahren ihren
   Rand — hier sind Serie, Fahrer und Team drei verschiedene Ziele, ein
   Hover-Rahmen um alles wuerde eine Klickflaeche versprechen, die es nicht
   gibt. */
.champ-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: var(--sp-3);
}

.champ-card {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    padding: var(--sp-3) var(--sp-4);
    background: var(--bg-1);
    border: 1px solid var(--line-1);
    border-radius: var(--r-m);
}

.champ-card .ch-top {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    flex-wrap: wrap;
}

.champ-card .ch-serie {
    font-size: var(--fs-meta);
    font-weight: 600;
    color: var(--text-2);
}

/* Der Teamname steht direkt als <x-team-cell> in der Karte — ein zusaetzlicher
   Wrapper nur fuer zwei Eigenschaften waere 427 Mal im Dokument. */
.champ-card .team-cell {
    font-size: var(--fs-meta);
}

.champ-card .ch-facts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-1) var(--sp-4);
    margin-top: auto;
    padding-top: var(--sp-2);
    border-top: 1px solid var(--line-1);
    font-size: var(--fs-meta);
    color: var(--text-3);
    font-variant-numeric: tabular-nums;
}

.champ-card .ch-num {
    font-weight: 600;
    color: var(--text-1);
}

/* Jahres-Ueberschrift innerhalb einer Dekade. */
.champ-jahr {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--fs-h2);
    font-weight: 600;
    line-height: 1;
    color: var(--accent);
    font-variant-numeric: tabular-nums;
}

/* --- 3D-Streckenviewer (circuits/show) ---
   Die Bedienoberflaeche um die Leinwand herum. Der Viewer selbst
   (three.js-Skriptblock in pages/circuits/show.blade.php) bleibt unangetastet;
   er haengt an den Ids c3dPanel/c3dCanvas/c3dCamOrbit/c3dCamChase/c3dSpeed/
   c3dSpeedVal und an der Klasse .c3d-active. Diese Namen sind Vertrag —
   umbenennen bricht den Viewer stumm.

   Die Regeln standen bis 05.08.2026 als <style>-Block in der View, mit zwei
   eigenen Breakpoints (480px, 640px) und drei Verbotsfarben. Hier tragen sie
   Tokens und nur die erlaubten Haltepunkte. */
.circuit3d-panel {
    position: relative;
    background: var(--bg-1);
    border: 1px solid var(--line-1);
    border-radius: var(--r-m);
    /* Feste Mindesthoehe, weil der Renderer seine Groesse aus
       panel.clientWidth/clientHeight liest — ohne sie waere die Leinwand 0 hoch. */
    min-height: 340px;
    overflow: hidden;
}

.circuit3d-panel canvas {
    display: block;
    width: 100%;
    height: 100%;
    /* touch-action: none — sonst scrollt die Seite, statt die Kamera zu drehen. */
    touch-action: none;
}

.c3d-ui {
    position: absolute;
    left: var(--sp-3);
    right: var(--sp-3);
    display: flex;
    gap: var(--sp-4);
    flex-wrap: wrap;
    z-index: 2;
    /* Die Leiste selbst faengt keine Mausbewegung ab — sonst liesse sich die
       Kamera in ihrem Streifen nicht drehen. Nur die Knoepfe sind aktiv. */
    pointer-events: none;
}

.c3d-ui--top {
    top: var(--sp-3);
    align-items: flex-start;
}

.c3d-ui--bottom {
    bottom: var(--sp-3);
    justify-content: flex-end;
}

.c3d-group {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    pointer-events: auto;
}

.c3d-lab {
    font-size: var(--fs-meta);
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--text-label);
}

.c3d-row {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
}

.c3d-btn {
    -webkit-appearance: none;
    appearance: none;
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 var(--sp-3);
    background: var(--bg-2);
    border: 1px solid var(--line-2);
    border-radius: var(--r-s);
    color: var(--text-2);
    font-family: inherit;
    font-size: var(--fs-meta);
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    white-space: nowrap;
    cursor: pointer;
}

.c3d-btn:hover {
    border-color: var(--accent);
    color: var(--text-1);
}

.c3d-btn.c3d-active {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--accent-ink);
}

.c3d-range {
    -webkit-appearance: none;
    appearance: none;
    width: 110px;
    height: 4px;
    background: var(--bg-3);
    border-radius: 2px;
    outline: none;
    cursor: pointer;
}

.c3d-range::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--accent);
    border: 2px solid var(--bg-0);
    cursor: pointer;
}

.c3d-range::-moz-range-thumb {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--accent);
    border: 2px solid var(--bg-0);
    cursor: pointer;
}

.c3d-val {
    font-size: var(--fs-meta);
    color: var(--text-2);
    font-variant-numeric: tabular-nums;
    min-width: 3ch;
}

/* ==========================================================================
   08 UTILITIES
   ========================================================================== */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.stack > * + * {
    margin-top: var(--sp-3);
}

.mt-3 { margin-top: var(--sp-3); }
.mt-4 { margin-top: var(--sp-4); }
.mt-5 { margin-top: var(--sp-5); }
.mt-6 { margin-top: var(--sp-6); }
.mb-3 { margin-bottom: var(--sp-3); }
.mb-4 { margin-bottom: var(--sp-4); }

.text-right { text-align: right; }
.nowrap { white-space: nowrap; }
.prose { max-width: 70ch; }

/* Mehrere Inline-Bausteine in einer Tabellenzelle nebeneinander (z. B.
   Fahrername + PP/FL-Badge). Noetig, weil .driver-cell selbst ein Flex-Block
   ist und Nachbarn sonst umbrechen. */
.cell-inline {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-2);
    min-width: 0;
}

/* GETEILTE FAHRTEN — mehrere Fahrer, ein Auto, eine Tabellenzeile
   (Nutzerwunsch 19.08.2026, /series/sportwagen-wm/1961/3).

   ZWEI SPALTEN, DIE PARALLEL LAUFEN: Die Namen stehen untereinander, und die
   fahrergebundenen Zahlen daneben (ELO, in seltenen Faellen die Punkte) stehen
   in DERSELBEN Reihenfolge untereinander. Der Leser ordnet den dritten Wert dem
   dritten Namen zu — das geht nur auf, wenn beide Listen dieselbe Zeilenhoehe
   haben. Daher `min-height` auf beiden Seiten statt eines blossen Abstands.

   `white-space: nowrap` an den Namen ist der Preis dafuer: Ein umgebrochener
   Name waere zwei Zeilen hoch und haette alles darunter gegen die Zahlenspalte
   verschoben. Die Ergebnistabelle laeuft als `x-table mode="scroll"` ohnehin
   waagerecht; ein breiterer Name kostet dort keine Lesbarkeit.

   NUR BEI MEHR ALS EINEM FAHRER: Zeilen mit einem einzigen Fahrer rendern
   weiterhin die blanke `.driver-cell` und sehen Zeichen fuer Zeichen aus wie
   vorher. */
.crew-namen,
.crew-werte {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.crew-namen > *,
.crew-werte > * {
    display: flex;
    align-items: center;
    min-height: 1.7em;
}

.crew-namen .driver-cell {
    white-space: nowrap;
}

.crew-werte {
    align-items: flex-end;
}

/* PP- und FL-Abzeichen einer geteilten Zeile stehen UNTER der Namensliste.
   `flex-basis: 100%` erzwingt den Umbruch im umgebenden `.cell-inline`. */
.crew-abzeichen {
    display: flex;
    flex-basis: 100%;
    gap: var(--sp-2);
}

.icon {
    width: 24px;
    height: 24px;
    display: inline-block;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.75;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.tag {
    font-size: var(--fs-meta);
    color: var(--text-3);
}

/* Hervorgehobener Zahlenwert in einer Tabellenzelle (ELO ab 1800). Ersetzt
   die frueheren Inline-Farben an den ELO-Spalten. */
.val-hi {
    color: var(--accent);
    font-weight: 600;
}

/* ==========================================================================
   BREAKPOINT: >= 768px
   ========================================================================== */
@media (min-width: 768px) {
    #page-content {
        padding: var(--sp-5) var(--sp-5) var(--sp-8);
    }

    .nav-links {
        display: flex;
    }

    .bottomnav {
        display: none;
    }

    /* Ohne Bottom-Nav darf der Knopf an die Unterkante ruecken. */
    .to-top {
        bottom: 24px;
    }

    .site-footer {
        display: block;
    }

    .stat-grid {
        grid-template-columns: repeat(4, 1fr);
    }

    .two-col {
        grid-template-columns: 1fr 1fr;
    }

    /* Fahrer A | VS | Fahrer B — auf dem Handy untereinander, hier nebeneinander. */
    .vs-grid {
        grid-template-columns: 1fr auto 1fr;
    }

    .link-grid {
        grid-template-columns: repeat(3, 1fr);
    }

    .topnav-inner {
        padding: 0 var(--sp-5);
    }

    /* Fussraum fuer den "Nach oben"-Knopf (Stand 10.08.2026, nachkorrigiert).
       Der Knopf steht auf dem Desktop fix bei bottom 24px, ist 48px hoch und
       belegt damit das Band 24 bis 72px ueber der Fensterunterkante. Der Footer
       ist 1px Rahmen + 24px + 20,8px Textzeile (13px x 1.6) + 24px = rund 70px
       hoch; seine Textzeile saesse ohne Gegenmassnahme 24 bis 44,8px ueber der
       Unterkante — mitten im Knopfband (Konzept, Verifikation Punkt 2: "der
       Button darf ... den Footer-Text nicht ueberlappen").
       80px unten = 24px Knopfabstand + 48px Knopf + 8px Luft. Die Textzeile
       liegt danach 80 bis 100,8px ueber der Unterkante, also 8px oberhalb der
       Knopfoberkante; der Schlagschatten (0 16px 40px) reicht nur ~4px nach
       OBEN und bleibt darunter.
       VORGAENGER, bewusst ersetzt: `.footer-inner { padding-right: 80px }` —
       das zog "(c) Jahr Motorsport Stats" auf JEDER Fensterbreite 80px nach
       innen, obwohl der Knopf ab 1288px Fensterbreite ohnehin ausserhalb der
       1160er-Spalte steht (24px Mindestrand + (W-1160)/2 >= 64px). Ergebnis war
       ein dauerhaft schiefer Footer. Der Fussraum wirkt dagegen symmetrisch,
       ueberlebt den Zeilenumbruch von `.footer-inner` (flex-wrap) und aendert
       waagerecht nichts. */
    .site-footer {
        padding: var(--sp-5) var(--sp-5) 80px;
    }

    /* Mehr Platz fuer die 3D-Strecke, sobald das Fenster ihn hergibt. */
    .circuit3d-panel {
        min-height: 440px;
    }

    .c3d-range {
        width: 130px;
    }
}

/* ==========================================================================
   BREAKPOINT: >= 1200px (nur Grid-Spaltenzahlen)
   ========================================================================== */
@media (min-width: 1200px) {
    .series-grid {
        grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    }

    .link-grid {
        grid-template-columns: repeat(3, 1fr);
    }
}

/* ==========================================================================
   BREAKPOINT: <= 767.98px — Karten-Tabellen-Muster + Mobil-Feinschliff
   Muster A: jede Zeile wird eine Karte. thead ist sr-only, jede Zelle
   traegt ihr Label ueber data-label. KEIN JavaScript beteiligt.
   ========================================================================== */
@media (max-width: 767.98px) {
    .table-wrap.table--cards {
        overflow: visible;
        border: 0;
        border-radius: 0;
        background: transparent;
    }

    .table--cards .data-table,
    .table--cards .data-table tbody,
    .table--cards .data-table tr,
    .table--cards .data-table td {
        display: block;
    }

    .table--cards .data-table {
        min-width: 0;
        font-size: var(--fs-sm);
    }

    .table--cards .data-table thead {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
    }

    /* VERDICHTET 10.08.2026 (Nutzer: "man sieht zu wenig, man muss zu viel
       scrollen"). Karten-Innenabstand rundum var(--sp-3) statt 12/16 — die
       gewonnenen 8px Breite sind der eigentliche Gewinn, weil lange Namen
       seltener umbrechen; der Aussenabstand faellt von 12px auf 8px.
       NICHT angetastet: die 44px Mindesthoehe der Links weiter unten und jede
       Schriftgroesse. */
    .table--cards .data-table tbody tr {
        position: relative;
        background: var(--bg-1);
        border: 1px solid var(--line-1);
        border-radius: var(--r-m);
        margin-bottom: var(--sp-2);
        padding: var(--sp-3);
    }

    .table--cards .data-table tbody tr:hover td,
    .table--cards .data-table tbody td {
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: var(--sp-3);
        padding: 2px 0;
        border: 0;
        background: transparent;
        text-align: left;
    }

    /* Touch-Ziele: die Trefferflaeche gehoert an den Link, nicht nur an die
       Zelle. 44px ist die Vorgabe fuer die aeltere Zielgruppe; ohne das
       Padding waere eine Namenszeile nur rund 26px hoch. */
    .table--cards .data-table tbody td a {
        display: inline-flex;
        align-items: center;
        min-height: 44px;
        padding: var(--sp-2) 0;
    }

    /* Die Beschriftung der Karte darf UMBRECHEN und SCHRUMPFEN (18.08.2026).
       Vorher stand hier `flex-shrink: 0`, und `white-space`/`text-align` kamen
       aus `.data-table td.cell-num` (Zeile 973: `nowrap`, rechtsbuendig) — fuer
       die ZAHL richtig, fuer das LABEL falsch.

       WAS DAS ANRICHTETE, in Chrome bei 320 px gemessen (18.08.2026,
       `/elo?sort=races&serie=gtwc-europe-endurance&jahr=2013`, Beschriftung
       „Rennen (GTWC Europe Endurance, 2013)"): Die Zahl stand 17 px RECHTS
       AUSSERHALB der Karte — `td.scrollWidth` 282 gegen `clientWidth` 252,
       und `.table-wrap.table--cards` hat `overflow: visible`, es gibt also
       nicht einmal einen Scrollbalken. Mit `flex-shrink: 1` allein rutschte
       die Zahl zwar hinein, legte sich aber AUF den Text („…, 20135").
       Erst `white-space: normal` bricht die Beschriftung um.

       DANACH, gleiche Messung: Karte 252/252 (kein Ueberlauf), Zahl 13 px
       innerhalb des Randes, Zeilenhoehe 24 -> 42 px. Kurze Beschriftungen
       ruehrt das nicht an: „Peak ELO", „Peak am" bleiben bei 24 px und
       252/252 — Flexbox schrumpft erst, wenn es sonst ueberliefe.

       `text-align: left` muss dabeistehen, sonst erbt die zweite Zeile die
       rechte Ausrichtung der Zahlenspalte und steht eingerueckt unter der
       ersten. */
    .table--cards .data-table tbody td::before {
        content: attr(data-label);
        color: var(--text-3);
        font-size: 13px;
        font-weight: 600;
        flex-shrink: 1;
        min-width: 0;
        white-space: normal;
        overflow-wrap: anywhere;
        text-align: left;
    }

    .table--cards .data-table td.cell-num {
        text-align: right;
    }

    /* Wert-plus-Zweitzeile in der Karte: rechte Kante wie bei den Zahlen. */
    .table--cards .data-table tbody td .cell-stack {
        text-align: right;
    }

    /* Position: oben rechts, ohne Label. `right` folgt dem Karten-Padding
       (oben von var(--sp-4) auf var(--sp-3) gezogen) — sonst haengt die
       Platzziffer 4px zu weit aussen. */
    .table--cards .data-table tbody td.cell-pos {
        position: absolute;
        top: var(--sp-3);
        right: var(--sp-3);
        padding: 0;
        display: block;
    }

    .table--cards .data-table tbody td.cell-pos::before {
        content: none;
    }

    /* Primaerzelle: gross, volle Breite, Platz fuer die Position */
    .table--cards .data-table tbody td.cell-primary {
        display: block;
        font-size: var(--fs-base);
        padding-right: 48px;
        padding-bottom: var(--sp-2);
    }

    .table--cards .data-table tbody td.cell-primary::before {
        content: none;
    }

    /* Zwischenueberschriften bleiben Zwischenueberschriften */
    .table--cards .data-table tbody tr.row-sec {
        background: transparent;
        border: 0;
        border-radius: 0;
        padding: var(--sp-4) 0 var(--sp-1);
        margin-bottom: 0;
    }

    .table--cards .data-table tbody tr.row-sec td {
        display: block;
        padding: 0;
        background: transparent;
        color: var(--accent);
        border-bottom: 1px solid var(--line-1);
        padding-bottom: var(--sp-2);
    }

    .table--cards .data-table tbody tr.row-sec td::before {
        content: none;
    }

    /* Lange Segmentleiste: eine wischbare Zeile statt fuenf Zeilen Umbruch
       (Begruendung an .segbar--scroll in 07). */
    .segbar--scroll {
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: thin;
        scrollbar-color: var(--accent) var(--bg-2);
        padding-bottom: var(--sp-2);
    }

    .segbar--scroll::-webkit-scrollbar {
        height: 8px;
    }

    .segbar--scroll::-webkit-scrollbar-track {
        background: var(--bg-2);
    }

    .segbar--scroll::-webkit-scrollbar-thumb {
        background: var(--accent);
        border-radius: 4px;
    }

    .series-grid {
        grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
        gap: var(--sp-2);
    }

    /* VERDICHTET 10.08.2026. Das Konzept wollte hier `min-height: 96px -> 80px`
       und `.series-abbr: 28px -> 24px`. BEIDES GEHT INS LEERE, und zwar seit
       dem Emblem-Umbau vom selben Abend:
         - `.series-abbr` existiert nicht mehr (die Klasse ist ersatzlos weg).
         - Die Mindesthoehe ist gar nicht mehr die bestimmende Groesse. Der
           Karteninhalt misst nachgerechnet 42px Emblem + 12px Gap + 22px Name
           (14px/1.6) + 21px Meta (13px/1.6) = 97px, dazu 2x12px Innenabstand
           = 121px. 96px greift also nie, und 80px wuerde erst recht nichts
           aendern.
       Der einzige echte Hebel ist deshalb der Gap zwischen Emblem und Text
       (12 -> 8px); die Mindesthoehe faellt weg, weil eine Regel, die nie
       greift, nur Irrtuemer wie den obigen naehrt. */
    .series-card {
        min-height: 0;
        padding: var(--sp-3);
        gap: var(--sp-2);
    }

    /* Das Emblem selbst braucht keine Handy-Fassung: .emblem--md ist 76px
       breit, die Karte hat unter 768px 150px Spaltenbreite minus 2x12px
       Innenabstand = 126px Platz. */

    /* Fussraum fuer den "Nach oben"-Knopf (10.08.2026, nachkorrigiert).
       Unter 768px ist `.site-footer` ausgeblendet und `.bottomnav` ist `fixed` —
       das Dokument endet also mit `#page-content`. Der Knopf steht mobil bei
       `bottom: calc(56px + env(safe-area-inset-bottom) + 12px)` und ist 48px
       hoch, belegt also das Band 68 bis 116px (+ Geraeteecke) ueber der
       Fensterunterkante. Mit den urspruenglichen 88px Polster ragte er am
       Seitenende 28px (auf iPhones mit Home-Indicator bis 62px) ueber echten
       Inhalt. Auf jeder paginierten Liste liegt dort die letzte Zeile von
       `.pagination` (44px hoch, `space-between`) — ihr rechtes Element
       "Weiter" sass exakt unter dem Knopf, ein Tipp darauf sprang nach oben,
       statt umzublaettern.
       124px = 68px Knopfabstand + 48px Knopf + 8px Luft, dazu die Geraeteecke,
       die auch im `bottom`-Wert des Knopfes steckt (auf Geraeten ohne
       Home-Indicator ist `env()` = 0, dort bleiben es glatte 124px).
       Kosten: 36px zusaetzlicher Weg ganz am Seitenende — einmal je Seite,
       nicht auf jedem Bildschirm.
       Bewusst NICHT gewaehlt: den Knopf per JS am Dokumentende ausblenden. Er
       verschwaende dann genau dort, wo der Nutzer ihn angefordert hat ("wenn
       ich auf der Seite ganz unten bin"). Und ein Polster nur an `.pagination`
       haette nur die paginierten Seiten geheilt, nicht `/`, `/series` oder die
       Rennergebnis-Seiten. */
    #page-content {
        padding-bottom: calc(124px + env(safe-area-inset-bottom));
    }

    /* ----------------------------------------------------------------------
       Mobil-Verdichtung (10.08.2026, Nutzer-Auftrag "man sieht zu wenig und
       muss zu viel scrollen"). Grundsatz aus der abgenommenen Design-Linie:
       LESBARKEIT SCHLAEGT DICHTE — die Zielgruppe ist aelter. Die Dichte kommt
       hier ausschliesslich aus Abstaenden und weggefallenen Mindesthoehen.
       Keine Schriftgroesse faellt unter ihren Token-Wert, kein Touch-Ziel
       unter 44px, kein neuer Breakpoint.
       ---------------------------------------------------------------------- */

    /* Statistik-Kacheln: Innenabstand 16 -> 12px. Der Zahlenwert steht mobil
       auf festen 26px statt an der clamp-Untergrenze von 28px — Barlow
       Condensed, immer noch deutlich groesser als jeder Fliesstext und weit
       ueber der 13px-Grenze. */
    .stat-tile {
        padding: var(--sp-3);
    }

    .stat-value {
        font-size: 26px;
    }

    /* Quick-Links: Innenabstand 16 -> 12px, und die Mindesthoehe faellt weg.
       Die Kachel ist damit genau so hoch wie ihr Inhalt (Titel + Unterzeile);
       bei zweizeiliger Unterzeile war die Mindesthoehe ohnehin ohne Wirkung. */
    .link-tile {
        padding: var(--sp-3);
        min-height: 0;
    }

    /* Abschnittsabstand 32 -> 24px, Hero-Polster 32/24 -> 16/16px. */
    .section {
        margin-top: var(--sp-5);
    }

    .hero {
        padding: var(--sp-4) 0;
    }

    /* Listenzeilen (der ELO-Block der Startseite, "Letzte Ergebnisse",
       Event-Chronik — hier stand die Ueberschrift des ELO-Blocks mit ihrer
       Zahl, die am 18.08.2026 von 5 auf 10 wechselte und den Kommentar
       ueberholt hat; deshalb jetzt ohne Zahl):
       Innenabstand 12/16 -> 8/12px. `min-height: 56px` bleibt bewusst stehen —
       einzeilige Zeilen (ELO) wuerden sonst unter das Touch-Mass rutschen. */
    .list-row {
        padding: var(--sp-2) var(--sp-3);
    }

    /* Serien-Chips ruecken enger zusammen (8 -> 4px). Die 44px Mindesthoehe
       des Chips selbst bleibt unberuehrt.

       VERDICHTET 11.08.2026 (Nutzer: "mach alles fertig") — der groesste noch
       offene Hebel aus der Liste vom 10.08. Die 23 Serien-Chips der Startseite
       stehen in vier Kategoriezeilen und brachen unter 768px auf rund
       6 + 2 + 3 + 1 = 12 Zeilen um (je 44px + 4px Gap, zusammen ~570px).
       Als EINE waagerecht wischbare Zeile je Kategorie bleiben vier Zeilen.
       Kein Inhalt verschwindet: Er rueckt zur Seite und ist mit dem Daumen
       erreichbar — anders als beim Kuerzen von Listen, das der Nutzer
       ausdruecklich nicht wollte ("man sieht zu wenig").
       Das Muster ist im Haus eingefuehrt und steht 100 Zeilen weiter oben:
       `.segbar--scroll` macht dasselbe mit der Segmentleiste, samt duenner
       Scrollleiste in Akzentfarbe als sichtbarem Hinweis, dass es seitlich
       weitergeht (die Zielgruppe ist aelter — ein unsichtbarer Wischbereich
       waere hier ein Fehler).
       `flex: 0 0 auto` ist Pflicht, nicht Deko: Mit `nowrap` allein wuerde
       flexbox die Chips stauchen (`flex-shrink: 1` ist der Standard), statt
       sie ueberlaufen zu lassen — dann waere die Zeile zwar einzeilig, aber
       die Namen wuerden umbrechen und die Zeile trotzdem hoch.
       NICHT angetastet: die 44px Mindesthoehe der Chips und jede
       Schriftgroesse. */
    .chip-row {
        gap: var(--sp-1);
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: thin;
        scrollbar-color: var(--accent) var(--bg-2);
        padding-bottom: var(--sp-2);
    }

    .chip-row::-webkit-scrollbar {
        height: 8px;
    }

    .chip-row::-webkit-scrollbar-track {
        background: var(--bg-2);
    }

    .chip-row::-webkit-scrollbar-thumb {
        background: var(--accent);
        border-radius: 4px;
    }

    .chip-row .abbr-chip {
        flex: 0 0 auto;
        white-space: nowrap;
    }

    /* Abstand zwischen den Kategorie-Bloecken der Startseite 24 -> 16px. */
    .cat-preview > * + * {
        margin-top: var(--sp-4);
    }

    /* Hintergrund sparsamer auf dem Handy: schwaecherer Weichzeichner spart
       GPU-Last. Der Kern (::after) bleibt scharf, sonst verschwindet die Spur. */
    .bg-scene i > span::before {
        filter: blur(42px);
    }

    .bg-scene i:nth-child(3) {
        display: none;
    }

    /* Seitenzahlen auf dem Handy: die direkten Nachbarn der aktuellen Seite
       entfallen — den Schritt um eins machen Vor/Zurueck, und die volle Leiste
       braeuchte auf 356px eine zweite Zeile. Erste, aktuelle und letzte Seite
       bleiben; genau der Sprung, den Vor/Zurueck nicht kann. */
    .pagination .pg-num--nah {
        display: none;
    }
}

/* ==========================================================================
   REDUZIERTE BEWEGUNG — Streifen bleiben statisch stehen
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
    .bg-scene i > span {
        animation: none;
    }

    /* Auch der Scroll-Effekt bleibt aus: JS prueft dieselbe Einstellung und
       setzt --py/--st gar nicht erst; diese Regel ist der Guertel dazu. */
    .bg-scene i,
    .bg-scene i:nth-child(1),
    .bg-scene i:nth-child(2),
    .bg-scene i:nth-child(3) {
        transform: none;
    }

    .nav-progress {
        display: none;
    }

    * {
        transition-duration: .01ms !important;
    }
}

/* ------------------------------------------------------------------
   SAISON-MATRIX (partials/standings-matrix, 18.08.2026)
   Die Kreuztabelle der Saisonseite: feste Spalten Pos/Fahrer/Team[/Pkt],
   danach eine Spalte je Rennen.

   WARUM DIE AUSRICHTUNG HIER STEHT UND NICHT AM <td>: Die breiteste Seite
   des Bestands ist /series/nascar/1964 mit 100 Zeilen x 62 Rennspalten =
   6.200 Zellen. Ein `class="cell-num"` je Zelle waere dort rund 87 kB
   allein an Attributen — bei einer Projektmarke von 400.000 B je Seite.
   ------------------------------------------------------------------ */

/* KEIN UMBRUCH IN DER GANZEN MATRIX. Mit 17 Rennspalten quetscht der Browser
   sonst die beiden Textspalten zusammen: auf /series/formula-e/2026 wurde
   „Pascal Wehrlein" zweizeilig und „NISSAN FORMULA E TEAM" dreizeilig, jede
   Tabellenzeile also dreimal so hoch wie noetig (gesehen 18.08.2026). Die
   Tabelle scrollt ohnehin seitlich (mode="scroll"), Breite kostet hier also
   nur Scrollweg — Hoehe kostet jede einzelne Zeile. */
.matrix .data-table th,
.matrix .data-table td {
    white-space: nowrap;
}

/* Die Rennspalten mittig und mit gleichbreiten Ziffern.
   ZWEI SELEKTOREN, WEIL DIE ERSTE RENNSPALTE WANDERT: Punktlose Serien
   (Race of Champions) haben keine Pkt-Spalte, dort faengt Rennen 1 schon bei
   Kind 4 an. Das Partial setzt `matrix-pkt`, wenn die Pkt-Spalte steht. Ohne
   die Unterscheidung stuende entweder die Pkt-Spalte mittig (statt rechts wie
   ueberall sonst) oder die erste Rennspalte linksbuendig. */
.matrix:not(.matrix-pkt) .data-table th:nth-child(n+4),
.matrix:not(.matrix-pkt) .data-table td:nth-child(n+4),
.matrix.matrix-pkt .data-table th:nth-child(n+5),
.matrix.matrix-pkt .data-table td:nth-child(n+5) {
    text-align: center;
    font-variant-numeric: tabular-nums;
    padding-left: var(--sp-2);
    padding-right: var(--sp-2);
}

/* Der Kopf einer Rennspalte traegt nur die Rundennummer — schmal halten,
   sonst bestimmt er die Spaltenbreite fuer bis zu 62 Spalten. */
.matrix .data-table thead th a {
    font-size: 12px;
}

/* PP/FL-Marker: klein und gedaempft, ohne die Zeilenhoehe zu treiben. */
.matrix .data-table sup {
    font-size: .62em;
    color: var(--text-3);
    letter-spacing: .02em;
}

/* AUSBRUCH AUS DER INHALTSSPALTE AUF BREITEN SCHIRMEN.
   Nutzer-Befund 18.08.2026 zu /series/euroformula-open/2024 im Wortlaut:
   „hier muss ich rechts links scrollen obwohl der Bildschirm groß genug
   wäre". Gemessen an ebendieser Seite: Fenster 1735 px nutzbar, Matrix
   1660 px breit — sie PASST also —, aber `main` ist auf 1160 px gedeckelt,
   die Inhaltsspalte also 1112 px breit. 550 px Seitwaertslauf, waehrend links
   und rechts je 288 px Bildschirm leer blieben.

   Der Deckel bleibt, wo er ist: Er sorgt auf jeder anderen Seite fuer lesbare
   Zeilenlaengen — Fliesstext ueber die volle Breite eines 1735-px-Schirms
   waere schlechter, nicht besser. Eine Kreuztabelle ist aber kein Fliesstext:
   Sie hat so viele Spalten, wie die Saison Rennen hat, und jede Spalte, die
   nicht sichtbar ist, muss der Leser erscrollen.

   RECHNUNG: `100%` ist die Inhaltsspalte, `100vw` das Fenster; die Haelfte
   der Differenz ist der freie Rand je Seite. Davon bleibt `--sp-5` als Luft
   zum Fensterrand stehen, der Rest wird als negativer Rand zurueckgegeben.
   `100vw` schliesst die Scrollleiste mit ein — die 24 px Luft fangen das ab
   (gemessen: Leiste 10 px, Dokument bleibt ueberlaufsfrei).

   ZWEI TEILE, UND DER ZWEITE IST DER WICHTIGE. Die Huelle `.matrix-bleed`
   spannt sich ueber den verfuegbaren Platz; die Tabelle darin nimmt sich per
   `fit-content` NUR, was sie braucht, und steht mittig. Ohne den zweiten Teil
   zoege die Huelle jede Matrix auf ihre volle Breite auseinander — `.data-table`
   ist `width: 100%`, die Tabelle fuellt also immer ihren Kasten. Genau das war
   der erste Anlauf dieser Aenderung: /series/euroformula-open/2026 (3 Rennen)
   stand auseinandergezogen da, und /series/f1/1980 (14 Rennen, das ohne jeden
   Lauf in die Inhaltsspalte passt) haette 587 px zuviel bekommen.

   KEINE SCHWELLE, KEIN BREAKPOINT. Der zweite Anlauf haengte den Ausbruch an
   die Rennzahl (`> 13`). Das war ein Stellvertreter fuer die eigentliche
   Frage — „ist die Tabelle breiter als die Spalte?" — und lag in BEIDE
   Richtungen daneben: 6 von 13 Saisons mit genau 13 Rennen scrollten weiter
   (bis 185 px), 8 von 20 mit 14 Rennen wurden ueberdehnt, weil die festen
   Spalten je nach Namenslaenge zwischen 437 und 867 px breit sind (alles
   gemessen 18.08.2026). `fit-content` beantwortet die Frage direkt und
   braucht keine Zahl.

   UNTERGRENZE: Die Tabelle darf nie SCHMALER werden als die Inhaltsspalte,
   sonst stuende eine kurze Matrix zusammengeschnurrt neben ihrer eigenen
   Ueberschrift (ohne sie: 955 statt 1.112 px auf /series/f1/1980, gemessen).
   `min(var(--container), 100vw) - 2 * var(--sp-5)` bildet diese Spalte NACH,
   ist aber NICHT dieselbe Rechnung, aus der `main` sie baut — zwei
   Unterschiede, beide gemessen: `main` nimmt `100%` (ohne senkrechte
   Scrollleiste), hier steht `100vw` (mit), und unter 768 px polstert `main`
   mit `--sp-4` statt `--sp-5`. Ungedeckt waeren das 10 px zu viel zwischen
   768 und 1.159 px und 6 px zu wenig darunter. Genau deshalb:

   AB 1.200 px — UND DIE ZAHL IST GERUNDET, NICHT HERGELEITET. Zwei frueher
   hier stehende Begruendungen sind an der Messung gescheitert: „die Rechnung
   kippt darunter ins Negative" (falsch, sie kippt erst unter ~700 px, und
   dann um 6 px) und „darunter gibt es nichts zu gewinnen" (ebenfalls falsch).
   Der gemessene Stand (18.08.2026, Fensterbreite gegen gewonnene Tabelle auf
   /series/euroformula-open/2024):

       1160 px -> +10    1180 px -> +20    1199 px -> +39
       1200 px ->   0    1218 px ->   0

   Es gibt also sehr wohl etwas zu gewinnen, und der Punkt, ab dem der freie
   Rand die 24 px Luft erreicht, liegt bei 1.218 px, nicht bei 1.200. WIR
   VERZICHTEN HIER BEWUSST auf bis zu 39 px zwischen 1.160 und 1.218 px: In
   diesem Band waeren die beiden Abweichungen oben sichtbar (die Matrix stand
   10 px breiter und 5 px links von Fussnote und Teamwertung), und ein paar
   Pixel Tabelle sind das nicht wert. 1.200 ist einfach eine runde Zahl IN
   diesem Band — nicht seine Mitte (die laege bei 1.189) und keine
   hergeleitete Schwelle.

   `min(0px, …)` bleibt als GUERTEL stehen, nicht als Notwendigkeit: Oberhalb
   von 1.200 px kann der Ausbruch gar nicht mehr positiv werden — dort liegt
   `(100vw - 100%) / 2` nie unter 44 px, und mit wie ohne `min(0px, …)` messen
   sich bei 1200/1201/1210/1218/1300/1745/2560/3840 px dieselben Werte. Das
   `min()` sichert allein den Fall ab, dass der Breakpoint eines Tages faellt.

   Und was auch mit vollem Ausbruch nicht passt (NASCAR 1964: 62 Rennspalten,
   2.695 px natuerlich), scrollt weiterhin: der Ausbruch verkuerzt den Weg, er
   ersetzt ihn nicht. */
@media (min-width: 1200px) {
    .matrix-bleed {
        margin-left: min(0px, calc(var(--sp-5) - (100vw - 100%) / 2));
        margin-right: min(0px, calc(var(--sp-5) - (100vw - 100%) / 2));
    }

    .matrix-bleed > .table-wrap {
        width: fit-content;
        min-width: calc(min(var(--container), 100vw) - 2 * var(--sp-5));
        max-width: 100%;
        margin-left: auto;
        margin-right: auto;
    }
}

/* ==========================================================================
   09 INTERN (/admin)
   --------------------------------------------------------------------------
   Der interne Bereich (Nutzer-Auftrag 19.08.2026: Quellen einsehen, eintragen,
   kontrollieren) benutzt DIESELBEN Tokens und Bausteine wie die Website —
   `.field`, `.btn`, `.badge`, `.stat-tile`, `.data-table`, `x-pagination`.
   Neu ist hier nur, was es auf der oeffentlichen Seite nicht gibt: eine
   Topleiste ohne Wortmarke, Formularbloecke (die Website hat nur GET-Filter)
   und die Rueckmeldezeile nach dem Absenden.

   TRENNUNG UEBER DEN NAMEN, NICHT UEBER DEN SELEKTOR: Die Regeln hier tragen
   eigene Namensraeume (`admintop*`, `admin-*`, `anmelden*`) und kollidieren
   deshalb mit keiner bestehenden Regel — nachgemessen 19.08.2026 fuer alle
   sieben neuen Namen gegen den gesamten uebrigen Stil und alle Views: null
   Treffer. Nur `body.admin` und `body.admin #page-content` sind wirklich an
   den Koerper gebunden (dort ist es noetig, siehe unten), und `.footer-intern`
   steht bewusst global — es sitzt im Fuss der OEFFENTLICHEN Seite.
   (Der Abschnittskopf behauptete zuerst „alles unter body.admin"; das war
   schlicht falsch und ist hier richtiggestellt.)

   Der Abschnitt braucht keine Media-Query: Die Topleiste umbricht ueber
   `flex-wrap`, die Anmeldekarte begrenzt sich ueber `max-width`.
   ========================================================================== */

/* Kein Lichtspuren-Hintergrund im Admin: Der Bereich soll sich sichtbar von
   der Website unterscheiden, und eine Animation hinter einer Kontrolltabelle
   ist Unruhe ohne Nutzen. */
body.admin {
    background: var(--bg-deep);
}

/* --- Topleiste ---------------------------------------------------------- */
.admintop {
    position: sticky;
    top: 0;
    z-index: 20;
    background: var(--bg-0);
    border-bottom: 1px solid var(--line-1);
}

.admintop-inner {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    flex-wrap: wrap;
    width: 100%;
    max-width: var(--container);
    margin: 0 auto;
    padding: var(--sp-2) var(--sp-4);
}

.admintop-mark {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    font-family: var(--font-display);
    font-size: var(--fs-h3);
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--accent);
    text-decoration: none;
}

.admintop-links {
    display: flex;
    align-items: center;
    gap: var(--sp-1);
    flex-wrap: wrap;
    flex: 1 1 auto;
}

.admintop-links a {
    min-height: 40px;
    display: inline-flex;
    align-items: center;
    padding: 0 var(--sp-3);
    border-radius: var(--r-s);
    color: var(--text-2);
    text-decoration: none;
    font-size: var(--fs-small);
}

.admintop-links a:hover {
    background: var(--bg-2);
    color: var(--text-1);
}

.admintop-links a[aria-current="page"] {
    background: var(--accent-wash);
    color: var(--accent);
}

.admintop-rechts {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
}

.admintop-raus {
    color: var(--text-3);
    text-decoration: none;
    font-size: var(--fs-small);
}

.admintop-raus:hover {
    color: var(--text-1);
}

/* --- Inhalt -------------------------------------------------------------- */
/* `.admin-main` traegt zusaetzlich die id #page-content und erbt daher Breite
   und Zentrierung. Ueberschrieben wird nur der Fussraum: Den grossen Platz
   unten braucht die Website fuer ihre feste Bottom-Nav, die es hier nicht gibt.

   DER SELEKTOR MUSS DIE ID SCHLAGEN. Die erste Fassung stand als blosses
   `.admin-main { padding-bottom: … }` da — eine tote Regel: `#page-content`
   ist ein ID-Selektor (1,0,0) und gewinnt gegen jede Klasse (0,1,0),
   unabhaengig von der Reihenfolge. Die unabhaengige Pruefung hat am
   19.08.2026 im echten 390px-Viewport 124px gemessen statt der gewollten
   64px. `body.admin #page-content` (1,1,0 + Element) schlaegt die ID. */
body.admin #page-content {
    padding-bottom: var(--sp-8);
}

/* --- Rueckmeldung nach dem Absenden -------------------------------------- */
.admin-flash {
    margin: 0 0 var(--sp-4);
    padding: var(--sp-3) var(--sp-4);
    border: 1px solid var(--line-1);
    border-left-width: 3px;
    border-radius: var(--r-s);
    background: var(--bg-1);
    font-size: var(--fs-small);
}

.admin-flash--ok  { border-left-color: var(--ok); }
.admin-flash--err { border-left-color: var(--err); }

/* --- Formularbloecke ----------------------------------------------------- */
/* Die Website kennt nur waagerechte Filterleisten (`.searchbar.filterbar`),
   in denen `.field` als Flex-Kind sitzt. Im Formular steht es untereinander
   und soll die Breite fuellen — deshalb hier `width: 100%`. */
.field-block {
    display: block;
    margin-bottom: var(--sp-4);
}

.field-block .field {
    width: 100%;
    flex: none;
}

.btn--klein {
    min-height: 36px;
    padding: 0 var(--sp-3);
    font-size: var(--fs-meta);
}

/* --- Anmeldeseite -------------------------------------------------------- */
.anmelden {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: var(--sp-5) var(--sp-4);
}

.anmelden-karte {
    width: 100%;
    max-width: 420px;
    padding: var(--sp-5);
    background: var(--bg-1);
    border: 1px solid var(--line-1);
    border-radius: var(--r-m);
}

.anmelden-titel {
    margin: 0 0 var(--sp-2);
    font-size: var(--fs-h2);
}

.anmelden-sub {
    margin: 0 0 var(--sp-5);
    color: var(--text-3);
    font-size: var(--fs-small);
}

.anmelden-knopf {
    width: 100%;
    justify-content: center;
}

.anmelden-fuss {
    margin: var(--sp-4) 0 0;
    color: var(--text-3);
    font-size: var(--fs-meta);
    line-height: 1.5;
}

/* Der Kommandoname ist lang. `break-all` zerlegte ihn mitten im Wort
   („…mo | torsport:admin-passwort", 19.08.2026 im Browser gesehen) — mit
   `anywhere` bricht die Zeile bevorzugt an den Leerzeichen und nur im
   Notfall im Wort. */
.anmelden-fuss code {
    color: var(--text-2);
    overflow-wrap: anywhere;
}

/* --- Verweis im Fuss der oeffentlichen Seite ----------------------------- */
/* Bewusst unauffaellig: derselbe Ton wie der uebrige Fusstext, kein Knopf.
   Wer den Bereich kennt, findet ihn; alle anderen lesen ein Wort mehr. */
.footer-intern {
    color: var(--text-3);
    text-decoration: none;
}

.footer-intern:hover {
    color: var(--text-2);
    text-decoration: underline;
}

/* Kachel als Link: Jede Zahl der Uebersicht fuehrt dorthin, wo man sie
   nachsehen kann. Der Link darf die Kachel nicht umfaerben — deshalb erbt er
   die Textfarbe und traegt nur den Fokusring. */
.stat-link {
    display: block;
    color: inherit;
    text-decoration: none;
    border-radius: var(--r-m);
}

.stat-link:hover .stat-tile {
    border-color: var(--line-2);
}

/* Zusatzzeile unter einem Tabelleneintrag (Quellen-Notiz, Prueffrist). */
.quelle-notiz {
    margin-top: 2px;
    color: var(--text-3);
    font-size: var(--fs-meta);
    line-height: 1.4;
}
