/* ============================================================================
   LEHScan - Stylesheet

   Eine Quelle für Schrift, Farben, Abstände und Bausteine.
   Mobile First, nur helles Thema, kein Framework, kein Build-Schritt.

   Idee: Milchglas über einem weichen Farbverlauf. Flächen liegen wie
   Scheiben übereinander, Kanten sind hell, Schatten weit und weich.
   Bewegung ist kurz und federnd - sie zeigt Zusammenhänge, sie spielt nicht.
   ========================================================================= */

@font-face {
    font-family: "Inter";
    src: url("/design/inter.woff2") format("woff2");
    font-weight: 100 900;
    font-display: swap;
}

:root {
    color-scheme: light;

    /* --- Glas ------------------------------------------------------------ */
    --glas:        oklch(100% 0 0 / .58);
    --glas-satt:   oklch(100% 0 0 / .78);
    --glas-dezent: oklch(100% 0 0 / .34);
    --rand:        oklch(100% 0 0 / .72);
    /* ⚠ --rand ist weiss und dient dem Glas. Bedienelemente brauchen eine Linie,
       die man auf hellem Grund wirklich sieht - sonst verschwinden Kaestchen und
       Felder (23.09.2026 gemessen). */
    --rand-satt:   oklch(72% .022 285);
    --rand-innen:  oklch(70% .03 280 / .16);
    --unschaerfe:  saturate(1.7) blur(20px);

    /* --- Tinte ----------------------------------------------------------- */
    --tinte:       oklch(26% .035 285);
    --tinte-leise: oklch(50% .028 285);
    --tinte-still: oklch(63% .024 285);

    /* --- Akzent: Indigo. Keine Vorgabe da, also etwas mit Haltung. ------- */
    --akzent:      oklch(54% .215 285);
    --akzent-hell: oklch(66% .19  288);
    --akzent-duft: oklch(94% .045 285);

    /* --- Zustände ------------------------------------------------------- */
    --gut:        oklch(52% .14 168);   --gut-duft:    oklch(94.5% .05 168);
    --warn:       oklch(56% .14 68);    --warn-duft:   oklch(95% .06 75);
    --fehler:     oklch(54% .20 22);    --fehler-duft: oklch(95% .04 22);
    --hell:       oklch(100% 0 0);

    /* --- Schatten: weit und weich, nie hart ------------------------------ */
    --tiefe-1: 0 1px 2px oklch(35% .05 285/.05), 0 4px 12px -4px oklch(35% .06 285/.10);
    --tiefe-2: 0 2px 4px oklch(35% .05 285/.05), 0 14px 34px -12px oklch(35% .08 285/.20);
    --tiefe-3: 0 4px 8px oklch(35% .05 285/.06), 0 30px 60px -20px oklch(35% .09 285/.28);

    /* --- Raster ---------------------------------------------------------- */
    --a1: .25rem; --a2: .5rem;  --a3: .75rem; --a4: 1rem;
    --a5: 1.5rem; --a6: 2.25rem; --a7: 3.5rem;

    --r-s: 10px; --r: 16px; --r-l: 22px; --r-rund: 999px;

    /* --- Schrift --------------------------------------------------------- */
    --schrift: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    --schrift-fest: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
    --s-mini:  .75rem;   --s-klein: .8125rem;  --s-text: .9375rem;
    --s-gross: clamp(1.0625rem, .95rem + .5vw, 1.25rem);
    --s-titel: clamp(1.5rem, 1.15rem + 1.5vw, 2.125rem);
    --s-zahl:  clamp(1.75rem, 1.15rem + 2.3vw, 2.625rem);

    --kopf: 4rem;  --nav: 4.5rem;  --breite: 70rem;

    --feder: cubic-bezier(.22, 1, .36, 1);      /* weich auslaufend */
    --tempo: .2s var(--feder);
}

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

/* ------------------------------------------------------------------ Basis */

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; }
/* Sonst überstimmt jede eigene display-Regel das Attribut hidden. */
[hidden] { display: none !important; }

body {
    min-block-size: 100dvb;
    color: var(--tinte);
    font: var(--s-text)/1.5 var(--schrift);
    font-feature-settings: "cv05" 1, "ss03" 1;
    -webkit-font-smoothing: antialiased;
    overflow-wrap: break-word;
    background: oklch(97.5% .006 285);
}

/* Der Farbverlauf, auf dem das Glas liegt. Fest, scrollt nicht mit. */
body::before {
    content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
    background:
        radial-gradient(58rem 42rem at 8% -12%,  oklch(86% .105 285 / .62), transparent 62%),
        radial-gradient(48rem 34rem at 102% 2%,  oklch(89% .085 215 / .55), transparent 60%),
        radial-gradient(44rem 40rem at 46% 112%, oklch(92% .075 40  / .50), transparent 62%);
}

h1, h2, h3 { line-height: 1.14; text-wrap: balance; font-weight: 620; letter-spacing: -.025em; }
h1 { font-size: var(--s-titel); letter-spacing: -.035em; }
h2 { font-size: var(--s-gross); }
h3 { font-size: var(--s-text); }
p  { text-wrap: pretty; }
a  { color: inherit; text-underline-offset: 3px; }
a:where(.knopf, .kachel, .marke, .zaehler, .nav a) { text-decoration: none; }
img, svg { display: block; max-inline-size: 100%; }

:where(:focus-visible) { outline: 2px solid var(--akzent); outline-offset: 2px; border-radius: var(--r-s); }

.ic {
    inline-size: 1.15em; block-size: 1.15em; flex: none;
    fill: none; stroke: currentColor; stroke-width: 1.7;
    stroke-linecap: round; stroke-linejoin: round;
}
.ic.gross { inline-size: 1.5rem; block-size: 1.5rem; }

.teil-id {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1, "cv05" 1;
    letter-spacing: -.015em;
}

/* --------------------------------------------------------------- Bewegung */

@keyframes auftauchen { from { opacity: 0; transform: translateY(12px) scale(.99); } }
@keyframes einblenden { from { opacity: 0; } }

/* Kinder gestaffelt einblenden - gibt der Seite einen Anfang. */
.gestaffelt > * { animation: auftauchen .55s var(--feder) backwards; }
.gestaffelt > *:nth-child(1) { animation-delay: .02s }
.gestaffelt > *:nth-child(2) { animation-delay: .06s }
.gestaffelt > *:nth-child(3) { animation-delay: .10s }
.gestaffelt > *:nth-child(4) { animation-delay: .14s }
.gestaffelt > *:nth-child(5) { animation-delay: .18s }
.gestaffelt > *:nth-child(6) { animation-delay: .22s }
.gestaffelt > *:nth-child(7) { animation-delay: .26s }
.gestaffelt > *:nth-child(8) { animation-delay: .30s }
.gestaffelt > *:nth-child(n+9) { animation-delay: .34s }

/* Seitenwechsel: der Browser blendet die Seiten ineinander.
   Kopf und Navigation bleiben dabei stehen. */
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: einblenden .14s ease reverse both; }
::view-transition-new(root) { animation: auftauchen .34s var(--feder) both; }
.kopf { view-transition-name: kopf; }
.nav  { view-transition-name: nav; }

/* ---------------------------------------------------------------- Gerüst */

.huelle { display: flex; flex-direction: column; min-block-size: 100dvb; }

.kopf {
    position: sticky; inset-block-start: 0; z-index: 30;
    display: flex; align-items: center; gap: var(--a3);
    block-size: calc(var(--kopf) + env(safe-area-inset-top));
    padding-block-start: env(safe-area-inset-top);

    /* Das Milchglas liegt auf einer eigenen Ebene. Haette der Kopf selbst
       backdrop-filter, waere er der Bezugsrahmen fuer alles Fixierte darin -
       die Navigation wuerde am Handy dann nicht mehr am Bildschirmrand kleben. */
    &::before {
        content: ""; position: absolute; inset: 0; z-index: -1;
        background: var(--glas);
        backdrop-filter: var(--unschaerfe);
        -webkit-backdrop-filter: var(--unschaerfe);
        border-block-end: 1px solid var(--rand);
    }

    /* Der Kopfinhalt liegt in einem Behaelter mit derselben Breite wie
       .inhalt - dadurch stehen Marke, Navigation und Inhalt auf einer Kante. */
    & .kopf-innen {
        inline-size: min(100% - 2 * var(--a4), var(--breite));
        margin-inline: auto;
        display: flex; align-items: center; gap: var(--a3);
        block-size: 100%;
    }
    /* Das vollstaendige Logo ist gestapelt und im schmalen Kopf unlesbar,
       deshalb hier nur Zeichen und Schriftzug. Das Logo steht auf der
       Anmeldeseite, wo es Platz hat. */
    & .marke {
        display: flex; align-items: center; gap: var(--a2);
        font-weight: 700; font-size: .9375rem; letter-spacing: -.035em;
        & .ic { inline-size: 1.2rem; block-size: 1.2rem; color: var(--akzent); stroke-width: 2; }
    }
    /* ⚠ Der Name darf nicht umbrechen und muss notfalls kuerzen. Seit das
       Hilfe-Symbol dazukam, stand "Mirko Psak" sonst in zwei Zeilen und machte
       die ganze Kopfzeile hoeher (23.09.2026). */
    & .kopf-rechts { margin-inline-start: auto; display: flex; align-items: center;
                     gap: var(--a2); min-inline-size: 0;
        & > span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
                   max-inline-size: 10rem; } }
}

.inhalt {
    flex: 1;
    inline-size: min(100% - 2 * var(--a4), var(--breite));
    margin-inline: auto;
    padding-block: var(--a5) calc(var(--nav) + var(--a6) + env(safe-area-inset-bottom));
}
@media (min-width: 48rem) { .inhalt { padding-block: var(--a6) var(--a7); } }
.inhalt.ohne-nav { display: grid; place-items: center; padding-block: var(--a4); }

.nav {
    position: fixed; inset: auto 0 0 0; z-index: 30;
    display: flex;
    padding-block-end: env(safe-area-inset-bottom);
    background: var(--glas-satt);
    backdrop-filter: var(--unschaerfe);
    -webkit-backdrop-filter: var(--unschaerfe);
    border-block-start: 1px solid var(--rand);

    & a {
        position: relative; flex: 1;
        /* Ohne min-inline-size:0 wächst ein Eintrag auf die Breite seines
           Wortes, und "Einstellungen" schob den letzten über den Rand hinaus
           (17.09.2026). Die Schrift schrumpft auf schmalen Schirmen mit. */
        min-inline-size: 0;
        display: flex; flex-direction: column; align-items: center; justify-content: center;
        gap: 4px; min-block-size: var(--nav);
        font-size: clamp(.66rem, 2.7vw, var(--s-klein)); font-weight: 570; letter-spacing: -.012em;
        /* --tinte-leise statt --tinte-still: Die Beschriftung ist nur 10 bis 13 px
           gross, mit --tinte-still lag sie bei 3,5:1 und damit unter dem, was man
           in der Werkstatt am Handy lesen kann (gemessen 21.09.2026). */
        color: var(--tinte-leise); text-decoration: none;
        transition: color var(--tempo);
        & .ic { inline-size: 1.5rem; block-size: 1.5rem; transition: transform var(--tempo); }
        & span { max-inline-size: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
        &:active .ic { transform: scale(.9); }
        &[aria-current="page"] { color: var(--akzent); }
        &[aria-current="page"]::before {
            content: ""; position: absolute; inset-block-start: 0;
            inline-size: 2rem; block-size: 3px; border-radius: 0 0 3px 3px;
            background: var(--akzent);
            view-transition-name: nav-marke;
        }
    }
}

@media (min-width: 48rem) {
    .nav-oben {
        position: static; border: 0; background: none; backdrop-filter: none;
        -webkit-backdrop-filter: none;
        inline-size: auto; padding: 0;
        margin-inline-start: var(--a5);
        gap: var(--a1);

        & a {
            flex: 0 0 auto; flex-direction: row; gap: var(--a2);
            min-block-size: 44px; padding-inline: var(--a5);
            border-radius: var(--r-rund);
            font-size: var(--s-text); font-weight: 570; letter-spacing: -.012em;
            transition: background var(--tempo), color var(--tempo);
            & span { overflow: visible; }
            & .ic { inline-size: 1.2rem; block-size: 1.2rem; }
            &:hover { background: var(--glas); }
            &[aria-current="page"] {
                color: var(--hell);
                background: var(--akzent);
                box-shadow: var(--tiefe-1);
                &::before { display: none; }
            }
        }
    }
}

/* Der Monitor ist kein Arbeitsbereich, sondern die Bühne für die Halle.
   Deshalb steht er nicht in der Reihe, sondern rechts aussen: am Desktop als
   Symbolknopf im Kopf, am Handy als letzter Eintrag der unteren Leiste, dort
   durch eine feine Linie abgesetzt. */
.buehne-knopf {
    padding-inline: var(--a3);
    & .ic { inline-size: 1.25rem; block-size: 1.25rem; }
    &[aria-current="page"] { color: var(--hell); background: var(--akzent); }
}

/* Sichtbarkeit zum Schluss, damit sie nicht von den .nav-Regeln darueber
   ueberschrieben wird: gleiche Spezifitaet, die spaetere Regel gewinnt.
   Am Handy zaehlt die untere Leiste, ab 48rem die im Kopf. */
.nav.nav-oben  { display: none; }
@media (min-width: 48rem) {
    .nav.nav-unten { display: none; }
    .nav.nav-oben  { display: flex; }
}

/* -------------------------------------------------------------- Bausteine */

.karte {
    position: relative;
    background: var(--glas);
    backdrop-filter: var(--unschaerfe);
    -webkit-backdrop-filter: var(--unschaerfe);
    border: 1px solid var(--rand);
    border-radius: var(--r);
    padding: var(--a4);
    box-shadow: var(--tiefe-1);
}
/* Abstand zwischen allen Bloecken im Inhalt. Das ist verlaesslicher als
   Sonderregeln pro Bausteinpaar: sobald ein neuer Baustein dazukommt, sitzt
   der Abstand automatisch richtig. Innerhalb von Rastern macht gap den
   Abstand, deshalb greift die Regel nur auf oberster Ebene. */
.inhalt > * + *          { margin-block-start: var(--a4); }
.inhalt > .kopfzeile     { margin-block-start: var(--a6); }
.inhalt > .kopfzeile:first-child { margin-block-start: 0; }
.inhalt > form + .liste,
.inhalt > form + .scan-liste { margin-block-start: var(--a5); }

.raster {
    display: grid; gap: var(--a3);
    grid-template-columns: repeat(auto-fit, minmax(min(13rem, 100%), 1fr));
}

.kopfzeile {
    display: flex; align-items: center; flex-wrap: wrap; gap: var(--a3); margin-block-end: var(--a4);
    & .zaehler { margin-inline-start: auto; color: var(--tinte-still);
                 font-size: var(--s-klein); text-decoration: none;
                 transition: color var(--tempo);
                 &:hover { color: var(--akzent); } }
}
.kopfzeile-rechts { margin-inline-start: auto; }
/* Schmale Bildschirme: Stehen rechts mehrere Knöpfe, rutschen sie unter den Titel.
   Neben dem Titel stapelten sie sich sonst zu einem schmalen Turm. */
@media (max-width: 33rem) {
    .kopfzeile:has(.knopfreihe > :nth-child(2)) {
        flex-direction: column; align-items: flex-start;
        & .kopfzeile-rechts { margin-inline-start: 0; }
    }
}
/* Abstände als Klassen, nicht als style="" im HTML. Mehr Stufen braucht es
   nicht: Was im Fluss steht, bekommt seinen Abstand ohnehin von
   .inhalt > * + *, der Rest sind Bausteine in Karten und Formularen. */
.abstand-oben       { margin-block-start: var(--a6); }   /* neuer Abschnitt */
.abstand            { margin-block-start: var(--a4); }
.abstand-eng        { margin-block-start: var(--a3); }
.abstand-unten      { margin-block-end: var(--a4); }
.abstand-unten-eng  { margin-block-end: var(--a3); }
/* "12 Scans · Seite 1 von 2" über einer Liste. */
.liste-zahl         { margin-block: var(--a3); }
/* Flex-Kind, das schrumpfen darf: Ohne das schiebt langer Text die Zeile
   auseinander, statt abgeschnitten zu werden. */
.knapp              { min-inline-size: 0; }
/* Formular, das nur den Knopf beisteuert und selbst kein Kasten sein soll. */
.durchgereicht      { display: contents; }
/* Zeile, die unmittelbar unter ein Feld gehört (Simulator: zuletzt benutzte
   Teilenummern). Der Abstand des Formulars wäre dort zu viel. */
.unters-feld        { margin-block-start: calc(var(--a3) * -1); }

/* Kennzahlen: am Handy zwei nebeneinander, sonst frisst die Reihe den Bildschirm. */
.raster.kennzahlen { grid-template-columns: 1fr 1fr; gap: var(--a2); }
@media (min-width: 40rem) {
    .raster.kennzahlen { grid-template-columns: repeat(4, 1fr); gap: var(--a3); }
    .raster.kennzahlen.fuenf { grid-template-columns: repeat(5, 1fr); }
}
/* Fünf Kacheln am Handy: Die fünfte (Teile in Arbeit) nimmt die ganze Zeile. */
@media (max-width: 39.99rem) {
    .raster.kennzahlen.fuenf > :last-child { grid-column: 1 / -1; }
}
a.kennzahl { color: inherit; text-decoration: none; }

.kennzahl {
    padding: var(--a4) var(--a4) var(--a3);
    & .wert {
        font-size: var(--s-zahl); font-weight: 660; line-height: 1;
        letter-spacing: -.045em; font-variant-numeric: tabular-nums;
        background: linear-gradient(160deg, var(--tinte), oklch(42% .09 285));
        -webkit-background-clip: text; background-clip: text; color: transparent;
    }
    & .wert.achtung { background: linear-gradient(160deg, var(--warn), oklch(52% .16 45));
                      -webkit-background-clip: text; background-clip: text; }
    & .name { color: var(--tinte-leise); font-size: var(--s-mini); margin-block-start: 6px;
              letter-spacing: -.005em; }
}

.knopf {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--a2);
    min-block-size: 44px; padding-inline: var(--a4);   /* feste 44 px, wie die Felder */
    border: 1px solid var(--rand); border-radius: var(--r-rund);
    background: var(--glas-satt);
    backdrop-filter: var(--unschaerfe);
    -webkit-backdrop-filter: var(--unschaerfe);
    color: var(--tinte);
    font: 570 var(--s-text)/1 var(--schrift); letter-spacing: -.012em;
    cursor: pointer; white-space: nowrap;
    text-decoration: none;              /* Knoepfe sind oft <a> - keine Unterstreichung */
    box-shadow: var(--tiefe-1);
    transition: transform var(--tempo), box-shadow var(--tempo), background var(--tempo);

    &:hover  { box-shadow: var(--tiefe-2); transform: translateY(-1px); }
    &:active { transform: translateY(0) scale(.985); box-shadow: var(--tiefe-1); }
    &:disabled { opacity: .45; cursor: not-allowed; box-shadow: none; }

    &.haupt {
        background: linear-gradient(160deg, var(--akzent-hell), var(--akzent));
        border-color: transparent; color: var(--hell);
        box-shadow: 0 1px 2px oklch(40% .18 285/.24), 0 8px 20px -8px oklch(45% .2 285/.55);
        &:hover { box-shadow: 0 2px 4px oklch(40% .18 285/.26), 0 16px 32px -10px oklch(45% .2 285/.6); }
    }
    &.still {
        background: transparent; border-color: transparent; box-shadow: none;
        color: var(--tinte-leise); padding-inline: var(--a3);
        &:hover { background: var(--glas); color: var(--tinte); transform: none; }
    }
    /* Ruhezustand, nicht nur :hover. Ohne Zeiger - also auf jedem Handy und
       Tablet - sah "Alle Scans loeschen" aus wie "Speichern". */
    &.gefahr { color: var(--fehler);
               border-color: color-mix(in oklab, var(--fehler) 38%, var(--rand)); }
    &.gefahr:hover { background: var(--fehler-duft); color: var(--fehler);
                     border-color: var(--fehler); }
    &.breit { inline-size: 100%; }
    /* Solange gearbeitet wird (Rückfrage bestätigt, Zentro wird gefragt),
       dreht sich das Symbol im Knopf. Nicht ausgrauen: Ausgegraut sieht nach
       einem Fehler aus. Keyframes "zahnrad" stehen weiter unten. */
    &.dreht { cursor: progress;
              & .ic { animation: zahnrad .9s linear infinite; } }
    /* Nur ein Symbol (Bearbeiten, Drucken, Löschen in Listen): rund, 44 px, mit
       Rand und Fläche wie jeder Knopf. Als "still" ohne Rand war der Stift nur
       ein Zeichen und sah nicht anklickbar aus. Die Beschriftung steht im title. */
    &.symbol { inline-size: 2.75rem; padding: 0; flex: none; color: var(--tinte-leise);
               & .ic { inline-size: 1.2rem; block-size: 1.2rem; }
               &:hover { color: var(--tinte); } }
    &.symbol.gefahr { color: var(--fehler); }
}

.abzeichen {
    display: inline-flex; align-items: center; gap: 4px;
    padding: .25em .6em; border-radius: var(--r-rund);
    background: var(--glas-dezent); color: var(--tinte-leise);
    border: 1px solid var(--rand);
    font-size: var(--s-mini); font-weight: 580; white-space: nowrap;
    & .ic { inline-size: .95em; block-size: .95em; stroke-width: 2.2; }
    &.gut     { background: var(--gut-duft);    color: var(--gut);    border-color: transparent; }
    &.warnung { background: var(--warn-duft);   color: var(--warn);   border-color: transparent; }
    &.fehler  { background: var(--fehler-duft); color: var(--fehler); border-color: transparent; }
}

.punkt {
    inline-size: 4px; align-self: stretch; min-block-size: 2rem;
    border-radius: var(--r-rund); flex: none;
    background: var(--punkt-farbe, var(--tinte-still));
}
/* Ein Symbol in der Farbe der Maschine oder der Kamera. Die Farbe kommt als
   --punkt-farbe aus den Daten, deshalb steht hier nur die Verbindung. */
.in-farbe { color: var(--punkt-farbe, var(--tinte-still)); }

/* --------------------------------------------------------------- Formular */

.formular { display: flex; flex-direction: column; gap: var(--a4); }
.zwei { display: grid; gap: var(--a4); grid-template-columns: 1fr; }
@media (min-width: 34rem) { .zwei { grid-template-columns: 1fr 1fr; } }

/* ⚠ Die Elemente selbst gestalten, nicht ihre Huellen (23.09.2026). Vorher hing
   das Aussehen eines Eingabefeldes daran, dass jemand ein `.feld` darum gebaut
   hatte; ueberall sonst fiel es auf das nackte Aussehen des Browsers zurueck.
   Deshalb steht das Aussehen jetzt hier, einmal, und `.feld` macht nur noch die
   Anordnung (Beschriftung ueber dem Feld). Das ist zugleich weniger CSS. */
/* ⚠ Bewusst schwach gehalten (nur Elementnamen, keine :is()-Kette). Eine
   staerkere Regel gewinnt sonst gegen `.feld-zahl input[type="number"]`, und
   jedes Zahlenfeld lief ueber die ganze Breite (23.09.2026 gesehen). Kaestchen
   und Punkte holen sich ihr Aussehen in der Regel darunter zurueck. */
input, select, textarea {
    inline-size: 100%; min-block-size: 44px;
    padding: var(--a2) var(--a4);
    border: 1px solid var(--rand-satt); border-radius: var(--r-s);
    background: var(--glas-satt);
    color: var(--tinte); font: var(--s-text)/1.4 var(--schrift);
    box-shadow: inset 0 1px 2px oklch(40% .05 285/.05);
    transition: border-color var(--tempo), box-shadow var(--tempo);
    &::placeholder { color: var(--tinte-still); }
    &:focus-visible {
        outline: none; border-color: var(--akzent);
        box-shadow: 0 0 0 4px var(--akzent-duft);
    }
    &:disabled { background: var(--glas-dezent); color: var(--tinte-still); cursor: not-allowed; }
}
select {
    appearance: none; cursor: pointer;
    background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                      linear-gradient(135deg, currentColor 50%, transparent 50%);
    background-position: right 1.15rem center, right .85rem center;
    background-size: 5px 5px; background-repeat: no-repeat;
    padding-inline-end: var(--a6);
}

/* Kaestchen und Punkte: Ohne diese Regel liefert der Browser seine eigenen,
   13 bis 18 Pixel gross und ohne unsere Farben - auf dem milchigen Grund sah man
   sie kaum (gemessen 23.09.2026: 128 Stueck auf 17 Seiten). */
input[type="checkbox"], input[type="radio"] {
    appearance: none; flex: none; margin: 0; cursor: pointer;
    inline-size: 1.35rem; block-size: 1.35rem; min-block-size: 0;
    padding: 0; box-shadow: none;
    border: 2px solid var(--rand-satt); border-radius: 6px;
    background: var(--hell) no-repeat center / .85rem .85rem;
    transition: border-color var(--tempo), background-color var(--tempo);
    &[type="radio"] { border-radius: 50%; }
    &:checked { border-color: var(--akzent); background-color: var(--akzent); }
    /* Der Haken als kleine Zeichnung im Hintergrund: kein zusaetzliches Element
       noetig, und er bleibt bei jeder Groesse sauber. */
    &[type="checkbox"]:checked {
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.6 4.6L19 7'/%3E%3C/svg%3E");
    }
    &[type="radio"]:checked { box-shadow: inset 0 0 0 4px var(--hell); }
    &:focus-visible { outline: none; box-shadow: 0 0 0 4px var(--akzent-duft); }
    &:disabled { cursor: not-allowed; opacity: .5; }
}

.feld {
    display: block; border: 0; padding: 0; margin: 0;
    & > span { display: block; margin-block-end: var(--a2);
               font-size: var(--s-klein); font-weight: 570; color: var(--tinte-leise); }
}

.knopfreihe { display: flex; align-items: center; gap: var(--a2); flex-wrap: wrap;
              & form { display: contents; } }
.schalter { display: flex; align-items: center; gap: var(--a3);
            min-block-size: 44px; cursor: pointer; }
/* Wird gerade gespeichert: Zeiger zeigt es an, der Schalter bleibt bedienbar. */
.schalter.dreht { cursor: progress; }

.wahl { display: flex; flex-wrap: wrap; gap: var(--a2); }
.wahl-feld {
    /* Winzig, nicht nur unsichtbar: Ein versteckter Radioknopf behielt sonst die
       volle Feldbreite und machte die Seite waagrecht rollbar (17.09.2026). */
    & input { position: absolute; opacity: 0; pointer-events: none;
              inline-size: 1px; block-size: 1px; }
    /* Nur das direkte Kind. Als Nachfahren-Selektor traf die Regel auch einen
       verschachtelten span - im Simulator steht dort Maschine und Kostenstelle,
       und der wurde dadurch selbst zur Pille mit Rand: Pille in der Pille. */
    & > span {
        display: inline-flex; align-items: center; gap: var(--a2);
        min-block-size: 44px; padding-inline: var(--a4);
        border: 1px solid var(--rand); border-radius: var(--r-rund);
        background: var(--glas-dezent);
        font-size: var(--s-klein); font-weight: 570; cursor: pointer;
        transition: all var(--tempo);
    }
    & input:checked + span {
        background: linear-gradient(160deg, var(--akzent-hell), var(--akzent));
        border-color: transparent; color: var(--hell); box-shadow: var(--tiefe-1);
    }
    & input:focus-visible + span { outline: 2px solid var(--akzent); outline-offset: 2px; }
}
/* Die Trefffläche ist das Label mit 44 px, der sichtbare Kreis bleibt 34 px.
   Die Farbe kommt als --punkt-farbe aus der Maschine. */
.wahl-farbe {
    display: grid; place-items: center;
    inline-size: 2.75rem; block-size: 2.75rem;
    & input { position: absolute; opacity: 0; pointer-events: none;
              inline-size: 1px; block-size: 1px; }
    & span { display: block; inline-size: 2.125rem; block-size: 2.125rem;
             background: var(--punkt-farbe, var(--tinte-still));
             border-radius: var(--r-rund); cursor: pointer; box-shadow: var(--tiefe-1);
             transition: transform var(--tempo), box-shadow var(--tempo); }
    & input:checked + span { transform: scale(1.08);
        box-shadow: 0 0 0 3px var(--hell), 0 0 0 5px var(--akzent), var(--tiefe-1); }
    & input:focus-visible + span { outline: 2px solid var(--akzent); outline-offset: 4px; }
}

/* Sprungliste fuer lange Seiten: kleine Pillen, die zu einem Abschnitt fuehren.
   Bewusst keine eigene Gestaltung je Seite - wer sie braucht, setzt die Klasse. */
.sprungliste {
    display: flex; flex-wrap: wrap; gap: var(--a2);
    & a {
        display: inline-flex; align-items: center; min-block-size: 36px;
        padding-inline: var(--a3); border-radius: var(--r-rund);
        border: 1px solid var(--rand-satt); background: var(--glas);
        color: var(--tinte-leise); text-decoration: none;
        font-size: var(--s-klein); font-weight: 570;
        transition: color var(--tempo), border-color var(--tempo);
        &:hover { color: var(--akzent); border-color: var(--akzent); }
    }
}

.filter { display: flex; gap: var(--a2); flex-wrap: wrap; align-items: end;
          /* 10.5rem statt 8rem: Kommt der Link "Zuruecksetzen" dazu, schrumpften
             die Auswahlfelder auf ihre Grundbreite und aus "Alle Maschinen"
             wurde "Alle Maschir" (22.09.2026, bei 1280 px gemessen). */
          /* ⚠ Nicht wachsen lassen (0 statt 1). Standen nur zwei Filter in der
             Zeile, zogen sie sich auf je die halbe Seitenbreite auf und sahen
             aus wie Eingabefelder statt wie Filter (23.09.2026, Notizen). Das
             Suchfeld darf dagegen weiter wachsen und nimmt den Rest. */
          & .feld { flex: 0 1 11.5rem; }
          /* Das Suchfeld ist das wichtigste in der Zeile: Es waechst zuerst und
             faellt nie unter 12rem, sonst wird sein Platzhalter abgeschnitten. */
          & .suchfeld { flex: 3 1 16rem; min-inline-size: 12rem; }
          /* Datumsfelder brauchen nur ihre eigene Breite, sonst nehmen sie
             dem Suchfeld den Platz. */
          & .feld-datum { flex: 0 1 9.5rem; } }
/* Am Handy jeder Filter auf eine eigene Zeile: Nebeneinander blieb von
   "Alle Maschinen" nur "Alle Masch" übrig (17.09.2026). */
@media (max-width: 33rem) {
    .filter > .feld { flex: 1 1 100%; }
}

/* ------------------------------------------------------------------ Liste */

.liste {
    list-style: none; padding: 0;
    background: var(--glas);
    backdrop-filter: var(--unschaerfe);
    -webkit-backdrop-filter: var(--unschaerfe);
    border: 1px solid var(--rand); border-radius: var(--r);
    box-shadow: var(--tiefe-1);
    overflow: hidden;

    & li {
        display: flex; align-items: center; gap: var(--a3);
        padding: var(--a3) var(--a4);
        transition: background var(--tempo);
        & + li { border-block-start: 1px solid var(--rand-innen); }
        &:hover { background: var(--glas-dezent); }
        & .haupt-text { font-weight: 570; letter-spacing: -.014em; }
        & .neben-text { color: var(--tinte-leise); font-size: var(--s-klein); }
        & .rechts { margin-inline-start: auto; text-align: end; flex: none;
                    display: flex; align-items: center; gap: var(--a2); }
        /* ⚠ Ein Symbol am Zeilenanfang steckt in einer Huelle, und die schrumpfte
           mit, sobald der Text lang wurde: Aus dem Warndreieck auf der Startseite
           wurde am Handy ein Punkt (24.09.2026). */
        & > span:has(> .ic) { flex: none; display: inline-flex; align-items: center; }
    }
}
.abschneiden { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.werte {
    /* minmax(0, ...) und Umbruch: Eine lange E-Mail-Adresse sprengte sonst die
       Karte und machte die Seite waagrecht rollbar (17.09.2026). */
    display: grid; grid-template-columns: minmax(0, max-content) minmax(0, 1fr);
    gap: var(--a2) var(--a5); margin: 0; align-items: baseline; align-content: start;
    & dt { color: var(--tinte-leise); font-size: var(--s-klein); }
    & dd { font-weight: 500; min-inline-size: 0; overflow-wrap: anywhere; }
}

.kachel {
    display: flex; align-items: center; gap: var(--a3); text-decoration: none;
    transition: transform var(--tempo), box-shadow var(--tempo);
    & .ic { inline-size: 1.375rem; block-size: 1.375rem; color: var(--akzent); }
    & .haupt-text { font-weight: 600; letter-spacing: -.018em; }
    & .neben-text { color: var(--tinte-leise); font-size: var(--s-klein); }
    & .rechts { margin-inline-start: auto; display: flex; align-items: center;
                gap: var(--a2); color: var(--tinte-still); }
    &:hover { transform: translateY(-2px); box-shadow: var(--tiefe-2); }
}

.meldung {
    display: flex; gap: var(--a3); align-items: flex-start;
    padding: var(--a3) var(--a4);
    border: 1px solid var(--rand); border-radius: var(--r);
    background: var(--glas); backdrop-filter: var(--unschaerfe);
    -webkit-backdrop-filter: var(--unschaerfe);
    font-size: var(--s-klein);
    animation: auftauchen .4s var(--feder) backwards;
    & .ic { margin-block-start: .1em; }
    &.gut     { background: var(--gut-duft);    border-color: transparent; color: var(--gut); }
    &.warnung { background: var(--warn-duft);   border-color: transparent; color: var(--warn); }
    &.fehler  { background: var(--fehler-duft); border-color: transparent; color: var(--fehler); }
}

.leer { display: grid; place-items: center; gap: var(--a3);
        padding: var(--a7) var(--a4); text-align: center; color: var(--tinte-still);
        & .ic { inline-size: 2rem; block-size: 2rem; stroke-width: 1.2; } }

.leise { color: var(--tinte-leise); }
.klein { font-size: var(--s-klein); }
.warn-farbe { color: var(--warn); }
.fehler-farbe { color: var(--fehler); }
.nur-sr { position: absolute; inline-size: 1px; block-size: 1px; padding: 0;
          margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.nur-ab-tablet { display: none; }
@media (min-width: 40rem) { .nur-ab-tablet { display: inline; } }

/* -------------------------------------------------------------- Anmeldung */

.anmelde-karte {
    inline-size: min(100%, 22rem);
    display: flex; flex-direction: column; gap: var(--a4);
    background: var(--glas-satt);
    backdrop-filter: var(--unschaerfe);
    -webkit-backdrop-filter: var(--unschaerfe);
    border: 1px solid var(--rand); border-radius: var(--r-l);
    padding: var(--a6) var(--a5);
    box-shadow: var(--tiefe-3);
    animation: auftauchen .6s var(--feder) backwards;
    & h1 { font-size: 1.5rem; }
    & > p { margin-block-start: calc(var(--a3) * -1);
            color: var(--tinte-leise); font-size: var(--s-klein); }
}

/* --------------------------------------------------------- Scan-Übersicht */

.scan-liste {
    background: var(--glas); backdrop-filter: var(--unschaerfe);
    -webkit-backdrop-filter: var(--unschaerfe);
    border: 1px solid var(--rand); border-radius: var(--r);
    box-shadow: var(--tiefe-1); overflow: hidden;
}
.scan {
    padding: 0; border: 0; border-radius: 0; background: none; box-shadow: none;
    & + .scan { border-block-start: 1px solid var(--rand-innen); }
    & summary {
        display: flex; align-items: center; gap: var(--a3);
        padding: var(--a3) var(--a4); cursor: pointer; list-style: none;
        transition: background var(--tempo);
        &::-webkit-details-marker { display: none; }
        &:hover { background: var(--glas-dezent); }
        & .titel { min-inline-size: 0; display: flex; flex-direction: column; gap: 1px; }
        & .rechts { margin-inline-start: auto; display: flex; align-items: center;
                    gap: var(--a3); flex: none; }
        & .neben-text { color: var(--tinte-leise); font-size: var(--s-klein); }
    }
    &[open] > summary { background: var(--glas-dezent); }
    /* Der Pfeil zeigt an, dass sich die Zeile öffnen lässt, und dreht sich mit. */
    & summary .auf-zu { transition: transform var(--tempo); flex: none; }
    &[open] > summary .auf-zu { transform: rotate(90deg); }
}
.scan-inhalt {
    display: grid; gap: var(--a5); padding: var(--a4) var(--a4) var(--a5);
    grid-template-columns: 1fr;
    animation: auftauchen .3s var(--feder);
}
@media (min-width: 44rem) { .scan-inhalt { grid-template-columns: 1fr 17rem; } }

.blaettern { display: flex; align-items: center; justify-content: center;
             gap: var(--a4); margin-block-start: var(--a5); }

/* ------------------------------------------------------ Werkstück als Bild

   Dieselbe Zeichnung wie im Werkstattmonitor (stueck_bild() in inc/kanten.php,
   stueckBild() in monitor.php). Das frühere flache Kantenbild ist am 22.09.2026
   entfallen: Es zeigte je Kante erledigt oder offen, und das weiss am
   Kantenleimer niemand (Mirko: "mach doch das Bild des Teils wie beim Monitor").
   Die Striche auf der Deckfläche zeichnet nur, wer die Lage mitzählt. */
.stueck {
    display: grid; justify-items: center; gap: var(--a2);
    & .mass { font-size: var(--s-mini); color: var(--tinte-leise);
              font-variant-numeric: tabular-nums; }
}
.stueck-bild {
    inline-size: min(100%, 17rem); block-size: auto;
    filter: drop-shadow(0 8px 14px oklch(35% .06 285 / .18));
}

/* Schmale Bildschirme: Status und Zeit rechts untereinander statt nebeneinander.
   Sonst nimmt ein Scan vom Vortag ("Probe · nicht gemeldet 14.09.2026 23:58")
   der Teilenummer die Breite, und die Nummer bricht Ziffer für Ziffer um. Die
   Teilenummer selbst bricht nie. */
.scan summary .teil-id, .liste li .haupt-text.teil-id { white-space: nowrap; }
@media (max-width: 33rem) {
    /* Status und Uhrzeit untereinander. Knopfreihen sind ausgenommen: Stift und
       Mülleimer gehören nebeneinander, nicht gestapelt (17.09.2026). */
    .scan summary .rechts, .liste li > .rechts:not(.knopfreihe) {
        flex-direction: column; align-items: flex-end; gap: 2px; flex: 0 1 auto;
    }
}

/* Scanner im Handy-Browser (scanner.php). Das Kamerabild füllt am Handy die
   Breite, hochkant; am Desktop quer und begrenzt. Der Rahmen zeigt, wohin das
   Etikett gehört, und leuchtet bei jedem Treffer kurz grün. */
.scanner { display: grid; gap: var(--a4); }
.scanner-bild {
    position: relative; overflow: hidden; border-radius: var(--r);
    background: oklch(20% .02 285); aspect-ratio: 3 / 4; max-inline-size: 100%;
    max-block-size: 62dvh; inline-size: 100%;
    & video { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; object-fit: cover; }
}
@media (min-width: 40rem) { .scanner-bild { aspect-ratio: 16 / 10; max-block-size: 45dvh; } }
.scanner-rahmen {
    position: absolute; inset: 22% 14%; border-radius: var(--r);
    border: 3px solid oklch(100% 0 0 / .9);
    box-shadow: 0 0 0 100vmax oklch(0% 0 0 / .28);
    &.treffer { animation: scanner-treffer .6s ease-out; }
}
@keyframes scanner-treffer {
    0%   { border-color: var(--gut); box-shadow: 0 0 0 100vmax oklch(52% .14 168 / .35); }
    100% { border-color: oklch(100% 0 0 / .9); box-shadow: 0 0 0 100vmax oklch(0% 0 0 / .28); }
}
@media (prefers-reduced-motion: reduce) { .scanner-rahmen.treffer { animation: none; } }
.scanner-zustand {
    position: absolute; inset: 0; display: grid; place-content: center; justify-items: center;
    gap: var(--a3); padding: var(--a5); text-align: center;
    color: oklch(96% .01 285); font-size: var(--s-gross); line-height: 1.4;
    & .ic { inline-size: 3rem; block-size: 3rem; opacity: .8; }
}
.scanner-knoepfe { align-items: center; }
/* Licht und Ton sind dasselbe: zwei Kästchen, rechts aussen, dicht beieinander.
   Vorher war das Licht ein Knopf und der Ton ein Kästchen, mit einer Lücke
   dazwischen (Mirko, 16.09.2026). */
.scanner-schalter { margin-inline-start: auto; display: flex; align-items: center; gap: var(--a4); }

/* Nachbearbeiten in der aufgeklappten Scanzeile: über die ganze Breite. */
.nacharbeit { grid-column: 1 / -1; border-block-start: 1px solid var(--rand-innen);
              padding-block-start: var(--a4); }

/* Teile in Arbeit (in-arbeit.php): eine Karte je Teil, das Kantenbild klein
   links, daneben was fehlt. Hängt ein Teil seit dem Vortag, bekommt die Karte
   einen roten Rand - nur dann, Rot ist für echte Probleme reserviert. */
.arbeit-liste { display: grid; gap: var(--a3); }
.arbeit { padding: var(--a4); display: grid; gap: var(--a3); }
.arbeit.haengt { box-shadow: inset 3px 0 0 var(--fehler), var(--tiefe-1); }
.arbeit-kopf { display: flex; align-items: center; gap: var(--a3); min-inline-size: 0;
               & .titel { display: grid; min-inline-size: 0; }
               & .rechts { margin-inline-start: auto; flex: none; } }
.arbeit-inhalt { display: grid; gap: var(--a4); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 40rem) { .arbeit-inhalt { grid-template-columns: 11rem 1fr; } }
.offen-kante { display: inline-flex; gap: .35em; align-items: baseline; margin-inline-end: var(--a3);
               & .teil-id { font-size: .9em; color: var(--akzent); } }
.arbeit-knoepfe { border-block-start: 1px solid var(--rand-innen); padding-block-start: var(--a3);
                  & form { display: contents; } }

.kanten-legende {
    display: flex; flex-wrap: wrap; gap: var(--a1) var(--a4);
    font-size: var(--s-mini); color: var(--tinte-leise); margin-block-start: var(--a2);
    & span { display: inline-flex; align-items: center; gap: .4em; }
    & i { inline-size: 1.6em; block-size: .45em; border-radius: 2px; }
    & .l-erledigt { background: var(--tinte); }
    & .l-offen { background: repeating-linear-gradient(90deg, var(--akzent) 0 5px, var(--akzent-duft) 5px 8px);
                 box-shadow: inset 0 0 0 1px var(--akzent); }
}

.anschlag-marke {
    display: inline-block; inline-size: 1.25em; block-size: .32em; flex: none;
    border-radius: 2px; background: var(--tinte); vertical-align: middle;
    box-shadow: 0 0 0 2px var(--hell), 0 0 0 3px var(--tinte);
    margin-inline-end: .5em;
}
.lage-unklar { color: var(--warn); font-weight: 600; }

/* Fehllesungen je Kamera: eine Kamera je Block, darunter heute und 7 Tage. */
.fehl-kamera { display: grid; gap: var(--a2); }
.fehl-kamera + .fehl-kamera { margin-block-start: var(--a4); padding-block-start: var(--a4);
                              border-block-start: 1px solid var(--rand); }

.kanten-liste {
    list-style: none; padding: 0; margin-block-start: var(--a3);
    display: grid; gap: 3px; font-size: var(--s-klein);
    & li { display: flex; justify-content: space-between; gap: var(--a4); }
    & li span:first-child { color: var(--tinte-leise); }
}

/* ------------------------------------------------------------------ Teile */
/* teile.php: nachschlagen, Auftrag, Sammeln. Der Stand je Maschine steht als
   Karte beim Teil, als kleiner Kreis in Listen, der Laufweg als Zeitleiste. */

.zeilen-verweis { min-inline-size: 0; color: inherit; text-decoration: none;
                  &:hover .haupt-text { text-decoration: underline; } }
.verweis-still { color: inherit; text-decoration: none; &:hover { text-decoration: underline; } }

.pillen .knopf .abzeichen { margin-inline-start: 2px; }
.pillen .knopf[aria-current="page"] {
    background: var(--akzent); color: var(--hell);
    & .abzeichen { background: oklch(100% 0 0 / .2); color: var(--hell); border-color: transparent; }
}

.teile-suche { display: flex; gap: var(--a2); align-items: center;
               & .feld { flex: 1 1 auto; min-inline-size: 0; } }
.knopf.symbol-breit { inline-size: 2.75rem; padding: 0; flex: none;
                      & .ic { inline-size: 1.25rem; block-size: 1.25rem; } }
.teile-kamera { display: grid; gap: var(--a3); }

.teil-kopf { display: grid; gap: var(--a4); grid-template-columns: 1fr;
             & h2 { margin-block: var(--a2) var(--a1); }
             & .werte { margin-block-start: var(--a3); } }
@media (min-width: 40rem) { .teil-kopf { grid-template-columns: 1fr 11rem; } }
.teil-kopf-zeile { display: flex; align-items: center; flex-wrap: wrap; gap: var(--a2) var(--a3); }
.teil-kopf-bild { display: grid; gap: var(--a2); align-content: start; }

.stationen { display: grid; gap: var(--a2);
             grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr)); }
.station {
    display: flex; align-items: center; gap: var(--a3); padding: var(--a3) var(--a4);
    & .station-text { min-inline-size: 0; flex: 1 1 auto; }
    & .haupt-text { font-weight: 600; }
    & .neben-text { color: var(--tinte-leise); font-size: var(--s-klein); }
    & .abzeichen { flex: none; }
}
.station-zeichen {
    display: grid; place-items: center; inline-size: 2.5rem; block-size: 2.5rem; flex: none;
    border-radius: var(--r-rund); color: var(--punkt-farbe);
    background: color-mix(in oklab, var(--punkt-farbe) 12%, transparent);
    & .ic { inline-size: 1.3rem; block-size: 1.3rem; }
}
.station.st-rand-fehler { box-shadow: inset 3px 0 0 var(--fehler), var(--tiefe-1); }
.station.st-rand-arbeit, .station.st-rand-wartet { box-shadow: inset 3px 0 0 var(--warn), var(--tiefe-1); }
.station.st-rand-offen, .station.st-rand-entfaellt { opacity: .78; }

.teil-hinweise { display: grid; gap: var(--a2); }
/* Hinweis aus der Stückliste (Zentro note2, "Achtung Nachschnitt und
   nachbekanten"). Der Schreiner soll ihn sehen, bevor er das Teil anfasst,
   deshalb fett und in Fehlerfarbe, aber nicht grösser als der Rest. */
.teil-hinweis-kante { font-weight: 600; }

.laufweg {
    list-style: none; padding: var(--a1) var(--a4); display: grid;
    & li { display: grid; grid-template-columns: 6.2rem 1fr auto; gap: var(--a3);
           align-items: start; padding-block: var(--a3); }
    & li + li { border-block-start: 1px solid var(--rand-innen); }
    & .laufweg-zeit { color: var(--tinte-leise); font-size: var(--s-klein);
                      padding-block-start: .15em; white-space: nowrap; }
    & .laufweg-text { min-inline-size: 0; padding-inline-start: var(--a3);
                      border-inline-start: 3px solid var(--punkt-farbe, var(--tinte-still)); }
    & .haupt-text { font-weight: 600; }
    & .neben-text { color: var(--tinte-leise); font-size: var(--s-klein); }
    & li.fehler .laufweg-text { border-color: var(--fehler); }
}
@media (max-width: 33rem) {
    .laufweg li { grid-template-columns: 1fr auto; }
    .laufweg .laufweg-zeit { grid-column: 1 / -1; padding: 0; }
}

.auftrag-kopf { display: grid; gap: var(--a2); & h2 { margin-block-start: var(--a1); } }
.fortschritt { display: grid; gap: var(--a1); margin-block-start: var(--a3); }
.fortschritt-zeile {
    display: grid; align-items: center; gap: 2px var(--a3);
    grid-template-columns: minmax(0, 15rem) 1fr auto;
    grid-template-areas: "name balken zahl" ". neben neben";
    padding: var(--a2); border-radius: var(--r-s); color: inherit; text-decoration: none;
    transition: background var(--tempo);
    &:hover { background: var(--glas-dezent); }
}
.fortschritt-name { grid-area: name; display: flex; align-items: center; gap: var(--a2);
                    min-inline-size: 0; font-weight: 570; }
.fortschritt-balken {
    grid-area: balken; block-size: .55rem; border-radius: var(--r-rund); overflow: hidden;
    background: var(--glas-dezent); box-shadow: inset 0 0 0 1px var(--rand);
    & i { display: block; block-size: 100%; inline-size: var(--anteil); border-radius: inherit;
          background: linear-gradient(90deg, var(--akzent-hell), var(--akzent)); }
}
.fortschritt-zahl { grid-area: zahl; font-weight: 620; white-space: nowrap; }
.fortschritt-neben { grid-area: neben; }
@media (max-width: 33rem) {
    .fortschritt-zeile { grid-template-columns: 1fr auto;
                         grid-template-areas: "name zahl" "balken balken" "neben neben"; }
}

.auftrag-filter { display: flex; flex-wrap: wrap; gap: var(--a2) var(--a3); align-items: center;
                  & .auftrag-gruppe { margin-inline-start: auto; } }
.auftrag-legende { margin-block-start: var(--a3); & b.st { inline-size: 1rem; block-size: 1rem; } }

.auftrag-liste li { flex-wrap: wrap; }
.auftrag-liste li.hier { background: var(--akzent-duft); }
.auftrag-teil { display: grid; min-inline-size: 0; flex: 1 1 12rem; color: inherit; text-decoration: none;
                &:hover .haupt-text { text-decoration: underline; } }
.stationen-mini { display: flex; gap: var(--a1); flex: none; margin-inline-start: auto; }

/* Stand an einer Maschine als kleiner Kreis mit dem Symbol der Maschine. Die
   Form trägt mit, nicht nur die Farbe: offen gestrichelt, in Arbeit halb
   gefüllt, ohne Kanten fast unsichtbar. */
.st {
    display: inline-grid; place-items: center; inline-size: 2rem; block-size: 2rem; flex: none;
    border-radius: var(--r-rund);
    border: 1.5px solid color-mix(in oklab, var(--tinte-still) 60%, transparent);
    color: var(--tinte-leise); background: transparent;
    & .ic { inline-size: 1rem; block-size: 1rem; stroke-width: 2; }
}
.st-fertig     { background: var(--gut); border-color: var(--gut); color: var(--hell); }
.st-probe      { background: var(--gut-duft); border-color: var(--gut); color: var(--gut); }
.st-arbeit     { background: linear-gradient(90deg, var(--warn-duft) 50%, transparent 50%);
                 border-color: var(--warn); color: var(--warn); }
.st-wartet     { border-color: var(--warn); color: var(--warn); }
.st-fehler     { background: var(--fehler); border-color: var(--fehler); color: var(--hell); }
.st-aufgegeben { border-style: dotted; }
.st-offen      { border-style: dashed; }
.st-entfaellt  { border-color: transparent; background: var(--rand-innen); opacity: .55; }

.sammel-gruppe {
    display: grid; gap: var(--a2);
    & h2 { font-size: var(--s-gross); }
    &.vollstaendig { box-shadow: inset 3px 0 0 var(--gut), var(--tiefe-1); }
}
.sammel-fehlt {
    font-size: var(--s-klein);
    & strong { display: block; margin-block-end: var(--a1); color: var(--tinte); }
    & ul { list-style: none; padding: 0; display: grid; gap: 2px; }
    & li { display: flex; gap: var(--a2); }
    & .teil-id { font-weight: 600; min-inline-size: 4rem; }
    &.warn strong { color: var(--warn); }
    & details { margin-block-start: var(--a1); }
    & summary { display: inline-flex; align-items: center; gap: var(--a1); cursor: pointer;
                min-block-size: 44px; color: var(--akzent); font-weight: 570; list-style: none;
                &::-webkit-details-marker { display: none; }
                & .ic { transition: transform var(--tempo); } }
    & details[open] > summary .ic { transform: rotate(90deg); }
}
.liste li.nochmal { animation: nochmal .8s ease-out; }
@keyframes nochmal { 0% { background: var(--warn-duft); } 100% { background: transparent; } }
@media (prefers-reduced-motion: reduce) { .liste li.nochmal { animation: none; } }

/* ============================================================================
   Werkstattmonitor - hängt in der Halle, wird aus mehreren Metern gelesen.
   ========================================================================= */

body.monitor {
    /* Durch den Zoom teilen: zoom skaliert dvb nicht mit. Bei 150 % waere der
       Koerper anderthalbmal so hoch wie der Bildschirm, und overflow:hidden
       schnitte die unteren Reihen ab - genau das, was hier verhindert werden soll. */
    block-size: calc(100dvb / var(--zoom, 1));
    min-block-size: 0;     /* hebt body { min-block-size: 100dvb } auf, sonst wirkt der Zoom nicht */
    display: flex; flex-direction: column; overflow: hidden;
    font-size: clamp(.9375rem, .7rem + .55vw, 1.25rem);
}

.m-kopf {
    display: flex; align-items: center; gap: var(--a4);
    padding: var(--a3) var(--a5);
    background: var(--glas-satt);
    border-block-end: 1px solid var(--rand); flex: none;
}
.m-marke { display: flex; align-items: center; gap: var(--a2);
           font-weight: 700; letter-spacing: -.04em;
           & .ic { color: var(--akzent); inline-size: 1.3em; block-size: 1.3em; stroke-width: 2; } }
/* Feste Hoehe, damit die Kopfzeile nicht springt, waehrend das SVG laedt.
   Steht hier und nicht weiter unten: Die Media-Regel fuer schmale Schirme
   (1.6rem) hat dieselbe Spezifitaet und muss spaeter kommen, sonst greift sie nie. */
.m-marke img { block-size: 1.9rem; inline-size: auto; display: block; }
.m-reiter { display: flex; align-items: center; gap: var(--a1); overflow-x: auto; flex: 1 1 0;
            min-inline-size: 0;   /* sonst schiebt sich die Reiterleiste unter die Uhr */
            position: relative;   /* Bezug für offsetLeft in reiterSichtbar() */
            scrollbar-width: none; &::-webkit-scrollbar { display: none; }
            /* Weicher Rand, wo es weitergeht (reiterRand() setzt die Klassen) */
            &.mehr-rechts { mask-image: linear-gradient(to right, #000 calc(100% - 3rem), transparent); }
            &.mehr-links  { mask-image: linear-gradient(to right, transparent, #000 3rem); }
            &.mehr-links.mehr-rechts { mask-image: linear-gradient(to right, transparent, #000 3rem,
                                                                  #000 calc(100% - 3rem), transparent); } }
/* Zwischen den Modi und den Maschinen */
.m-reiter-trenner { flex: none; inline-size: 1px; block-size: 1.4em; margin-inline: var(--a2);
                    background: var(--rand); }
.m-reiter-knopf {
    display: inline-flex; align-items: center; gap: var(--a2);
    flex: none;       /* nicht schrumpfen: "dran" hat overflow: hidden und fiele sonst auf null */
    padding: var(--a2) var(--a4);
    border: 0; border-radius: var(--r-rund);
    background: transparent; color: var(--tinte-leise);
    font: 580 .9em/1 var(--schrift); letter-spacing: -.02em;
    white-space: nowrap; cursor: pointer;
    transition: background var(--tempo), color var(--tempo), box-shadow var(--tempo);
    & .m-anzahl { font-variant-numeric: tabular-nums; opacity: .55; }
    &:hover { background: var(--glas); }
    &.aktiv { background: var(--farbe, var(--akzent)); color: var(--hell); box-shadow: var(--tiefe-1);
              & .m-anzahl { opacity: .85; } }
    /* Im Wechsel: die Maschine, die gerade dran ist. Nur ein Rahmen, gewählt
       ist sie nicht. Von links füllt sie sich in ihrer Farbe, bis zum Wechsel
       (--fortschritt 0 bis 1, alle 100 ms gesetzt, dazwischen gleitend). */
    &.dran { color: var(--tinte); box-shadow: inset 0 0 0 2px var(--farbe, var(--akzent));
             position: relative; isolation: isolate; overflow: hidden;
             &::before { content: ""; position: absolute; inset: 0; z-index: -1;
                         background: color-mix(in oklab, var(--farbe, var(--akzent)) 30%, transparent);
                         transform-origin: left center; transform: scaleX(var(--fortschritt, 0));
                         /* 120 ms statt 1 s: Der Wert kommt jetzt alle 100 ms
                            (WECHSEL_TAKT), der Uebergang glaettet nur noch die
                            Stufen. Mit 1 s lief die Fuellung der Zahl hinterher
                            und war beim Wechsel noch nicht am rechten Rand. */
                         transition: transform .12s linear; }
             /* Steht der Wechsel (Teil auf der Bühne), atmet die Füllung */
             &.haelt::before { animation: fuellung-haelt 2.4s ease-in-out infinite; } }
}
/* Zu viele Reiter für eine Zeile neben Marke und Uhr: eigene Zeile (kopfEng()) */
.m-kopf.eng { flex-wrap: wrap; row-gap: var(--a2);
              & .m-reiter { order: 3; flex: 1 0 100%; } }
.m-rechts { margin-inline-start: auto; display: flex; align-items: center; gap: var(--a3); flex: none; }
.m-uhr { font: 640 1.15em/1 var(--schrift); font-variant-numeric: tabular-nums; letter-spacing: -.035em; }
.m-datum { font-weight: 520; color: var(--tinte-leise); margin-inline-end: .5em; font-size: .8em; }
.m-gesamt {
    position: relative; perspective: 300px; font-weight: 620; font-variant-numeric: tabular-nums; color: var(--tinte-leise); white-space: nowrap; }
/* Solange nichts an Zentro geht, muss das jeder sehen. */
/* Kontrast: --warn auf --warn-duft lag bei 4,05:1 und damit unter AA. Eigener,
   dunklerer Ton nur hier - das Band ist die einzige Anzeige, dass nichts an
   Zentro geht, und steht in kleiner Schrift. */
.m-probe {
    font: 650 .82em/1 var(--schrift); color: oklch(48% .14 68); background: var(--warn-duft);
    border: 1px solid color-mix(in oklab, var(--warn) 35%, transparent);
    border-radius: var(--r-rund); padding: .45em .9em; white-space: nowrap;
}
.m-puls { inline-size: 7px; block-size: 7px; border-radius: var(--r-rund);
          background: var(--gut); animation: pulsieren 2.4s ease-in-out infinite;
          &.weg { background: var(--fehler); animation: none; } }
@keyframes pulsieren { 0%, 100% { opacity: 1 } 50% { opacity: .28 } }

/* Die Buehne bekommt die ganze uebrige Hoehe, der Kopf nur so viel wie er
   braucht.

   **Der Monitor darf nie scrollen.** Er haengt in der Halle, dort bedient
   niemand ein Rad, und was unter der Kante liegt, sieht keiner. Deshalb
   ueberall `overflow: hidden` und `min-block-size: 0`: Ohne das Zweite waechst
   eine Grid- oder Flexzeile mit ihrem Inhalt ueber die zugeteilte Hoehe hinaus,
   und `1fr` haelt sie nicht auf. Lieber schneidet die Anzeige unten etwas ab,
   als dass das Wichtige oben aus dem Bild rutscht. */
.m-buehne {
    /* Unten nur --a3: Das ist derselbe Abstand wie zwischen den Kennzahlkarten
       und zwischen den Reihen im Feld. Mit --a5 rundherum sass die dunkle
       Leiste sichtbar weiter weg als alles andere (Mirko, 22.09.2026). */
    flex: 1; min-block-size: 0; overflow: hidden;
    padding: var(--a5) var(--a5) var(--a3);
    display: grid; grid-template-rows: minmax(0, 1fr);
    position: relative;          /* Bezug für den Geist beim Maschinenwechsel */
}

/* Maschinenwechsel als Fahrt (maschineTauschen()): Das alte Feld fährt
   hinaus, die neue herein, beide gleichzeitig wie ein Karussell. Der Geist
   zeigt nur noch, was war: keine Animationen darin, nicht anklickbar.
   Sanft an, sanft aus (nicht --feder). */
.m-buehne { --fahrt: cubic-bezier(.65, 0, .3, 1); }
.m-geist { z-index: 1; pointer-events: none;
           & * { animation: none !important; transition: none !important; } }
/* ⚠ Nacheinander, nicht gleichzeitig: Erst faehrt die alte Maschine ganz
   hinaus (0,38 s), dann kommt die neue herein (0,38 s, um dieselbe Zeit
   verzoegert). Liefen beide zugleich, sah man sie einen Moment halb
   nebeneinander, und der Wechsel wirkte unsauber (Mirko, 23.09.2026).
   "both" haelt die neue waehrend der Wartezeit ausserhalb des Bildes. */
.m-raus-links  { animation: m-raus .38s var(--fahrt) both; --weg: calc(-100% - var(--a5)); }
.m-raus-rechts { animation: m-raus .38s var(--fahrt) both; --weg: calc(100% + var(--a5)); }
.m-rein-rechts { animation: m-rein .38s var(--fahrt) .38s both; --her: calc(100% + var(--a5)); }
.m-rein-links  { animation: m-rein .38s var(--fahrt) .38s both; --her: calc(-100% - var(--a5)); }
@keyframes m-raus { to   { translate: var(--weg) 0; opacity: .4; scale: .96; } }
@keyframes m-rein { from { translate: var(--her) 0; opacity: .4; scale: .96; } }

/* Die Felder: je gewählte Maschine eins, im Raster. Die Spaltenzahl rechnet
   das Skript aus dem Format (--spalten), die Zeilen teilen sich die Höhe. */
.m-felder {
    display: grid; gap: var(--a5); min-block-size: 0; min-inline-size: 0;
    grid-template-columns: repeat(var(--spalten, 1), minmax(0, 1fr));
    grid-auto-rows: minmax(0, 1fr);
}

/* Ein Feld je Maschine: oben der Kopf (Maschine, Mitarbeiter, Kennzahlen),
   darunter die Bühne. Das Feld ist ein Container "kachel" für den Kopf.
   Kein Abstand zwischen Kopf und Buehne: Der Maschinenkopf und die
   Auftragszeile darunter sollen als **eine** Karte gelesen werden (Mirko,
   22.09.2026). Die Raender an der Nahtstelle sind abgeschaltet, gerundet wird
   nur oben und unten.
   Frueher mit :has(.w-raster) - das ist die teuerste Selektorform in Blink und
   hier immer wahr, seit es nur noch die eine Ansicht gibt.
   position: relative ist der Bezug fuer den Meilenstein, der sich vollflaechig
   ueber das Feld legt. --span setzt monitor.php, wenn das letzte Feld die
   freien Spalten aufspannen soll. */
.m-feld {
    container: kachel / size;
    min-block-size: 0; min-inline-size: 0; overflow: hidden;
    position: relative;
    grid-column: span var(--span, 1);
    display: grid; grid-template-rows: auto minmax(0, 1fr); gap: 0;
}

/* Die Bühne ist ein eigener Container "feld". Alles darin richtet sich nach
   ihr, nicht nach dem Bildschirm: Stehen zwei Maschinen nebeneinander, wird
   jede halb so gross, statt über den Rand zu laufen.

   --s ersetzt vw: ein Hundertstel der Bühnenbreite, aber nie mehr, als die
   Höhe hergibt. In einem flachen Feld (zwei übereinander am Handy) bestimmt
   die Höhe. Die Einheiten lösen sich dort auf, wo --s benutzt wird, also in
   den Kindern gegen diesen Container. */
.m-feld-buehne {
    container: feld / size;
    --s: min(1cqi, 2.1cqb);
    min-block-size: 0; min-inline-size: 0; overflow: hidden;
    display: grid; grid-template-rows: minmax(0, 1fr); gap: var(--a4);
}

/* --------------------------------------------------------------------------
   Bausteine, die Feldkopf und Kennzahlen weiterverwenden: das Symbol der
   Maschine, der Hinweis auf eine verzögerte Anzeige und die Tageskurve.
   ----------------------------------------------------------------------- */
.m-feld-symbol { display: inline-block; inline-size: 1.05em; block-size: 1.05em; flex: none; vertical-align: -.14em;
                 margin-inline-end: .35em; fill: none; stroke: currentColor; stroke-width: 1.9;
                 stroke-linecap: round; stroke-linejoin: round; }
.m-reiter-symbol { inline-size: 1.1em; block-size: 1.1em; flex: none; fill: none;
                   stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
/* Hinweis im Kopf einer Maschine, deren Anzeige verzögert läuft (der Scan
   passiert am Auslauf, gezeigt wird er, wenn das Teil vorne ankommt). */
.m-verzoegert {
    flex: none; font-size: .62em; font-weight: 600; letter-spacing: -.01em;
    color: var(--tinte-still); border: 1px solid var(--rand); border-radius: var(--r-rund);
    padding: .1em .55em; white-space: nowrap;
}
/* Teile je Stunde, in der Kennzahlenreihe (wKurve()). */
.m-kurve { display: grid; gap: 3px; }
.m-kurve-balken { display: flex; align-items: flex-end; gap: 2px; block-size: clamp(1.8rem, 1.2rem + 1.4cqi, 3rem); }
.m-balken {
    flex: 1 1 0; min-block-size: 2px; block-size: calc(var(--h) * 100%);
    border-radius: 2px 2px 0 0;
    background: color-mix(in oklab, var(--farbe, var(--akzent)) 38%, var(--hell));
    &.jetzt { background: var(--farbe, var(--akzent)); }
    &.spaeter { background: color-mix(in oklab, var(--tinte-still) 18%, var(--hell)); }
}
.m-kurve-achse { display: flex; justify-content: space-between; color: var(--tinte-still);
                 font-size: .68rem; font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------------------
   Zwei Bausteine der ersten Fassung, die die Ansicht weiterbenutzt: die
   Einblendung einer neuen Karte und die Zeile "noch offen" am Kantenleimer
   (kantenOffen(), nur an Maschinen, die die Lage mitzählen).
   ----------------------------------------------------------------------- */
@keyframes jetzt-rein {
    from { opacity: 0; transform: translateY(18px) scale(.985); }
}
.m-kante-zeile {
    margin-block-start: var(--a3);
    font-size: clamp(.9rem, .65rem + 1.05 * var(--s), 1.9rem); color: var(--tinte);
    font-weight: 560; letter-spacing: -.01em;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    &.grund { color: var(--warn); font-weight: 600; }
}
.m-band {
    font-family: var(--schrift-fest); font-size: .88em; font-weight: 600;
    padding: .05em .4em; border-radius: 6px;
    background: var(--akzent-duft); color: var(--akzent);
}

/* --------------------------------------------------------------------------
   Anmeldung an der Maschine. Das Personensymbol ist als Strich gezeichnet wie
   alle Symbole im Sprite; es steht vor dem Namen, wo immer eine Person genannt
   wird (Bühne, Liste, Wartebild), damit man den Namen nie für eine Kundin hält.
   ----------------------------------------------------------------------- */
.m-person-ic {
    inline-size: 1em; block-size: 1em; flex: none; vertical-align: -.12em;
    margin-inline-end: .35em;
    fill: none; stroke: currentColor; stroke-width: 1.8;
    stroke-linecap: round; stroke-linejoin: round;
}
.m-reiter-person { font-weight: 500; opacity: .8;
                   &::before { content: "· "; } }

/* Die Karte auf der Bühne, wenn sich jemand an- oder abmeldet. Kein Teil, also
   kein Kantenbild: die Person groß, in der Farbe der Maschine. Die Abmeldung
   ist grau, damit man beides aus drei Metern auseinanderhält. */
/* Vollflaechig in der Farbe der Maschine, Schrift weiss - wie der Meilenstein
   bei 50 Teilen (Mirko, 22.09.2026). Der farbige Streifen links faellt weg, die
   ganze Karte traegt die Farbe. Sie bleibt in der Buehne der Maschine: Stehen
   mehrere nebeneinander, muss die Anmeldung bei der richtigen erscheinen. */
.m-person {
    display: grid; place-content: safe center; justify-items: center;
    gap: var(--a3); text-align: center; min-block-size: 0; overflow: hidden;
    background: var(--farbe, var(--akzent)); color: var(--hell);
    border-radius: var(--r-l); padding: var(--a5); box-shadow: var(--tiefe-2);
    /* Wie der Meilenstein bei 50 Teilen: aus der Tiefe auf, nicht von unten
       hereingeschoben wie eine Teilekarte (Mirko, 22.09.2026 - "es so
       reinkommen lassen"). Derselbe Anfang wie @keyframes meilenstein. */
    animation: auftritt-rein .45s var(--feder) backwards;
}
@keyframes auftritt-rein {
    from { opacity: 0; transform: scale(.85); }
}
.m-person-rund {
    display: grid; place-items: center; inline-size: clamp(4.5rem, 2rem + 8 * var(--s), 10rem);
    aspect-ratio: 1; border-radius: 50%;
    background: oklch(100% 0 0 / .18); color: var(--hell);
    & .m-person-ic { inline-size: 58%; block-size: 58%; margin: 0; stroke-width: 1.5; }
}
.m-person-art { color: var(--hell); opacity: .85; font-weight: 700;
                letter-spacing: .08em; text-transform: uppercase;
                font-size: clamp(.95rem, .75rem + .9 * var(--s), 1.9rem); }
.m-person-name { font-size: clamp(2rem, 1.1rem + 6.5 * var(--s), 6.5rem); font-weight: 680;
                 letter-spacing: -.045em; line-height: 1; overflow-wrap: anywhere;
                 perspective: 600px; }
/* Buchstabe fuer Buchstabe hereinrollen - dieselbe Bewegung wie die Ziffern des
   Meilensteins (ziffer-rollt), nicht das Hereinfliegen der Teilenamen.
   ⚠ Drei Klassen tief, nicht zwei: Die gemeinsame Regel ".name-neu .b,
   .m-person-name .b" steht weiter unten in der Datei und gewaenne sonst bei
   gleicher Genauigkeit (22.09.2026 gemessen). */
.m-person .m-person-name .b {
    animation: ziffer-rollt .7s var(--feder) backwards;
    animation-delay: calc(var(--i) * 55ms + 150ms);
}
.m-person-neben { opacity: .85; font-size: clamp(1rem, .72rem + 1.25 * var(--s), 2.15rem); }
.m-person-zeit { opacity: .7; font-variant-numeric: tabular-nums;
                 font-size: clamp(.9rem, .7rem + .6 * var(--s), 1.4rem); }
/* Abmelden ist kein Anlass zur Farbe: gedecktes Grau statt der Maschinenfarbe. */
.m-person.ab { background: oklch(38% .02 285); }

/* ⚠ Im flachen Feld (zwei Maschinen uebereinander, oder vier) braucht die Karte
   311 px und hat nur 288 - die Uhrzeit wurde unten abgeschnitten (gemessen
   22.09.2026). Der Kreis ist mit bis zu 160 px der groesste Brocken und dabei
   reiner Schmuck: Die Bedeutung tragen die Maschinenfarbe und das Wort
   "ANGEMELDET". Ohne ihn bleiben 227 px, also Luft. */
@container feld (block-size < 26rem) {
    .m-person-rund { display: none; }
    /* Enger zusammen, sonst reicht die Hoehe nicht: place-content: safe center
       faellt beim Ueberlaufen auf "start" zurueck, und dann wird **unten**
       abgeschnitten - beim Abmelden traf es die Zeile "mit dem Ausweis
       abgemeldet" (Mirko, 22.09.2026). */
    .m-person { gap: var(--a2); padding: var(--a4); }
}
/* Noch flacher: die Uhrzeit weicht. Sie steht auch in der Liste rechts. */
@container feld (block-size < 20rem) {
    .m-person-zeit { display: none; }
}

/* --------------------------------------------------------------------------
   Der Wartezustand. Zwischen zwei Teilen soll der Bildschirm nicht tot
   wirken, sondern bereit: ein langsam drehendes Zahnrad, mehr nicht.
   ----------------------------------------------------------------------- */

.m-warte {
    display: grid; place-content: center; justify-items: center; gap: var(--a2);
    block-size: 100%; min-block-size: 0; overflow: hidden;
    color: var(--tinte-still); text-align: center;
    animation: einblenden .6s ease backwards;
}
/* Zahnrad mit drei Ringen, die versetzt nach aussen laufen. Der Kreis wird
   ueber den Rand gezeichnet, nicht ueber eine Fuellung: So bleibt die Mitte
   frei und das Zahnrad davor lesbar. */
/* Nie höher als gut ein Drittel der Bühne: Sonst stösst es in flachen Feldern
   (zwei Maschinen übereinander am Handy) oben an die Karte. */
.m-warte-rad {
    position: relative; display: grid; place-items: center;
    inline-size: min(clamp(5rem, 4rem + 11 * var(--s), 14rem), 26cqb); aspect-ratio: 1;
    margin-block-end: var(--a3);
}
.m-ring {
    position: absolute; inset: 0; border-radius: var(--r-rund);
    border: 2px solid var(--farbe, var(--akzent));
    opacity: 0; animation: ring-puls 3.6s cubic-bezier(.2, .6, .3, 1) infinite;
}
.m-ring:nth-child(2) { animation-delay: 1.2s; }
.m-ring:nth-child(3) { animation-delay: 2.4s; }

@keyframes ring-puls {
    0%   { transform: scale(.42); opacity: 0; }
    12%  { opacity: .42; }
    100% { transform: scale(1); opacity: 0; }
}

.m-zahnrad {
    position: relative;
    inline-size: clamp(2.5rem, 1.5rem + 5 * var(--s), 5.5rem); block-size: auto;
    fill: none; stroke: var(--farbe, var(--akzent)); stroke-width: 1.4;
    stroke-linecap: round; stroke-linejoin: round; opacity: .62;
    animation: zahnrad 9s linear infinite;
}
@keyframes zahnrad { to { transform: rotate(360deg); } }

.m-warte-haupt {
    font-size: clamp(1.4rem, 1rem + 1.5 * var(--s), 2.6rem); font-weight: 620;
    letter-spacing: -.035em; color: var(--tinte-leise);
    animation: bereit-atmen 3.6s ease-in-out infinite;
}
@keyframes bereit-atmen { 50% { opacity: .48; } }

.m-warte-neben { font-size: clamp(.9rem, .75rem + .6 * var(--s), 1.4rem);
    text-align: center; }
/* Symbol und Name der Maschine in ihrer Farbe, genau wie im Kopf des Feldes
   (.w-kopf-name). So erkennt man aus zehn Metern, welche Maschine wartet. */
/* Eigene Zeile: Erst die Maschine, darunter "wartet auf das nächste Teil".
   Frei umbrechen liess das Symbol allein auf einer Zeile landen (Mirko,
   23.09.2026). Der Name selbst bricht nie, er kuerzt lieber. */
.m-warte-maschine { display: block; color: var(--farbe, var(--akzent));
                    font-size: 1.3em; font-weight: 700; white-space: nowrap;
                    overflow: hidden; text-overflow: ellipsis;
                    margin-block-end: .2em; }
/* ⚠ display: inline-block noetig: Die Grundregel oben setzt jedes svg auf
   block, dadurch stand das Symbol in einer eigenen Zeile ueber dem Namen
   (Mirko, 23.09.2026). */
.m-warte-ic { display: inline-block;
              inline-size: 1.05em; block-size: 1.05em; vertical-align: -.16em;
              margin-inline-end: .3em; fill: none; stroke: currentColor;
              stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

@media (prefers-reduced-motion: reduce) {
    .m-zahnrad, .w-teil, .m-person, .m-warte-haupt, .w-zeile.neu { animation: none; }
    .m-ring { display: none; }
}

/* ==========================================================================
   Werkstattansicht - die Ansicht des Monitors (monitor.php)

   Der Entwurf von Christoph und den Schreinern: je Maschine ein Feld, oben der
   Auftrag mit Fortschritt, links das laufende Teil gross mit massstaeblichem
   Werkstueck, darunter das Teil davor, rechts die letzten Durchlaeufe, unten
   die Kennzahlen. Seit 21.09.2026 die einzige Ansicht; die erste Fassung mit
   Spur und Kantenbild ist raus (Kopie in sicherungen/).

   Es gilt dieselbe Regel wie oben: Der Monitor scrollt nie. Jede Spalte und
   jede Zeile bekommt min-block-size: 0, die Liste schneidet lieber unten ab.
   ======================================================================= */

/* min-inline-size am Kopf ist Pflicht: Ohne das bestimmt der laengste Name im
   Kopf die Spaltenbreite des ganzen Feldes, und am Handy stand die halbe Seite
   ausserhalb des Bildes (gemessen am 18.09.2026). */
.m-feld-kopf { min-inline-size: 0; overflow: hidden; }

.w-raster {
    display: grid; gap: var(--a3) var(--a4); min-block-size: 0; min-inline-size: 0;
    grid-template-columns: minmax(0, 1.75fr) minmax(0, 1fr);
    /* Oben der Auftrag ueber die ganze Breite - er gehoert zum Maschinenkopf
       darueber und bildet mit ihm eine Karte. Darunter das laufende Teil (zwei
       Drittel) und das Teil davor (ein Drittel), rechts daneben die Liste. */
    grid-template-rows: auto minmax(0, 2fr) minmax(0, 1fr) auto;
    grid-template-areas: "auftrag auftrag" "jetzt liste" "vorher liste" "zahlen zahlen";
}
.w-buehne { grid-area: jetzt; min-block-size: 0; min-inline-size: 0;
            display: grid; grid-template-rows: minmax(0, 1fr); overflow: hidden; }

/* Zustandsfarbe. Sie faerbt die ganze Karte und die Zeile in der Liste:
   rot = Hinweis Kante aus Zentro oder Fehler, orange = es fehlen Kanten,
   gruen = alle Kanten durch (dann geht auch die Fertigmeldung raus). */
/* Eigene Namen, nicht .st-*: Die gehoeren der Teileseite (dort ist .st-fehler
   weiss auf Rot - und genau das faerbte hier die Namen weiss, 18.09.2026). */
.zu-gut    { --zustand: var(--gut);    --zustand-duft: var(--gut-duft); }
.zu-warn   { --zustand: var(--warn);   --zustand-duft: var(--warn-duft); }
.zu-fehler { --zustand: var(--fehler); --zustand-duft: var(--fehler-duft); }

/* -------------------------------------------------------- Auftrag und Fortschritt */
.w-feld-auftrag { grid-area: auftrag; display: grid; min-inline-size: 0; }
.w-feld-zahlen  { grid-area: zahlen;  display: grid; min-inline-size: 0; }
.w-auftrag {
    display: flex; align-items: center; gap: var(--a4);
    min-inline-size: 0; overflow: hidden;
    background: var(--glas-satt);
    border: 1px solid var(--rand); border-radius: 0 0 var(--r-l) var(--r-l);
    padding: var(--a2) var(--a4); padding-block-start: var(--a1);
    box-shadow: var(--tiefe-1);
    font-size: clamp(.85rem, .7rem + .7 * var(--s), 1.4rem);
    /* Eng gesetzt: Die grosse Auftragsnummer brachte sonst eine Zeilenhoehe von
       1,5 mit, und die Zeile wirkte oben und unten aufgeblasen (Mirko,
       22.09.2026). */
    line-height: 1.15;
}
.w-auftrag.leer { color: var(--tinte-still); justify-content: center; }
.w-marke { color: var(--tinte-still); font-size: .72em; font-weight: 700;
           letter-spacing: .09em; text-transform: uppercase; }
/* Mittig, nicht auf der Grundlinie: Die Marke "AUFTRAG" ist viel kleiner als
   die Nummer daneben und sass damit optisch zu tief (Mirko, 22.09.2026). */
.w-auftrag-nr { flex: 0 1 auto; display: flex; align-items: center; gap: var(--a3);
                min-inline-size: 0; overflow: hidden;
    & b { font-size: 1.7em; font-weight: 720; letter-spacing: -.03em;
          font-variant-numeric: tabular-nums; } }
.w-auftrag-kunde { color: var(--tinte-leise); overflow: hidden;
                   text-overflow: ellipsis; white-space: nowrap; }
.w-fortschritt { flex: 1 1 50%; display: flex; align-items: center; gap: var(--a3);
                 min-inline-size: 0; }
/* Der Balken darf nicht auf null zusammenschrumpfen, wenn der Kundenname lang
   ist - genau das passierte am 18.09.2026 bei "Kath. Kirchengemeinde Zell a. H." */
.w-kaesten, .w-streifen { min-inline-size: 6rem; }
/* Ein Kaestchen je Teil des Auftrags, gefuellt, was an dieser Maschine fertig ist. */
.w-kaesten { flex: 1; display: flex; gap: .28em; min-inline-size: 0; overflow: hidden; }
.w-kasten { flex: 1 1 0; min-inline-size: 2px; block-size: 1.15em;
            border-radius: 3px; background: oklch(88% .01 285); }
.w-kasten.voll { background: var(--gut); }
.w-streifen { flex: 1; block-size: 1.15em; border-radius: var(--r-rund);
              background: oklch(88% .01 285); overflow: hidden;
              /* --anteil setzt monitor.php. Ohne Angabe faellt die Breite auf
                 auto, dann sah jeder Auftrag ab 25 Teilen nach 100 % aus. */
              & span { display: block; block-size: 100%; background: var(--gut);
                       inline-size: var(--anteil, 0%);
                       transition: inline-size .6s var(--feder); } }
.w-prozent { flex: none; white-space: nowrap; font-size: 1.7em; font-weight: 720;
             letter-spacing: -.03em; font-variant-numeric: tabular-nums; color: var(--gut); }
/* ⚠ Schrumpfen erlaubt (flex: 0 1 auto, min-inline-size: 0). Mit "flex: none"
   schob sich die Zeile ueber den Kartenrand hinaus und wurde dort mitten im
   Wort hart abgeschnitten - am Fernseher bei "1/125 an dieser Maschine"
   gesehen (Mirko, 23.09.2026). Die Zahl bleibt immer stehen, nur der Zusatz
   weicht und endet mit Auslassungspunkten. */
.w-fortschritt-neben { flex: 0 1 auto; min-inline-size: 0; overflow: hidden;
                       color: var(--tinte-leise); white-space: nowrap;
                       font-weight: 600;
    /* Der Zusatz "an dieser Maschine" leiser und kleiner, in derselben Zeile
       und mittig zur Zahl (Mirko, 22.09.2026). */
    display: inline-flex; align-items: center; gap: .45em;
    /* Die Zahl weicht nie ("2/125"), nur der Zusatz gibt Platz ab. */
    & b { flex: none; font-weight: inherit; }
    & small { font-size: .8em; font-weight: 500; opacity: .75;
              letter-spacing: -.01em;
              min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; } }

/* ---------------------------------------------------------- Laufendes Teil */
/* Stilles Nachziehen: Der Inhalt eines Bereichs hat sich geaendert, aber es
   steht dasselbe da wie eben - dann kein Auftritt. Ohne das fuhr ein Teil ein
   zweites Mal ein, sobald seine Fertigmeldung raus war, und bei der letzten
   Kante noch ein drittes Mal (Mirko, 22.09.2026).
   Gilt auch fuer die Kinder: Der Name faehrt Buchstabe fuer Buchstabe ein, das
   gehoert genauso dazu. monitor.php setzt die Klasse vor dem Einsetzen.

   ⚠ Ausgenommen ist alles mit **.dauerhaft**: das Zahnrad und die Ringe der
   Karte "Bereit", das Atmen des Wortes, das sich drehende Zeichen waehrend der
   Zentro-Abfrage. Die laufen endlos und haben mit einem Auftritt nichts zu tun -
   ohne die Ausnahme blieben sie beim ersten stillen Nachziehen stehen. */
[data-t].ohne-auftritt,
[data-t].ohne-auftritt *:not(.dauerhaft) { animation: none; }

/* Zentro wird gerade gefragt. */
.w-fragt { display: inline-flex; align-items: center; gap: .4em; }
.w-fragt .ic { inline-size: .8em; block-size: .8em; flex: none;
               color: var(--tinte-leise); animation: zahnrad 1.1s linear infinite; }

.w-teil {
    /* Spalte aus Flex, nicht aus Grid: Der Hinweisstreifen ist nur manchmal da,
       feste Grid-Zeilen verrutschten dann (am 18.09.2026 gesehen). */
    display: flex; flex-direction: column; gap: var(--a3);
    background: color-mix(in oklab, var(--zustand-duft) 75%, var(--hell));
    border: 2px solid color-mix(in oklab, var(--zustand) 45%, transparent);
    border-inline-start: 10px solid var(--zustand);
    border-radius: var(--r-l); padding: var(--a4) var(--a5); box-shadow: var(--tiefe-2);
    min-block-size: 0; overflow: hidden;
    animation: jetzt-rein .5s var(--feder) backwards;
}
/* Hinweis Kante aus Zentro (note2): das Teil darf nicht einfach durchlaufen. */
.w-achtung {
    flex: none; display: flex; align-items: center; gap: var(--a3);
    background: var(--fehler); color: var(--hell);
    border-radius: var(--r); padding: var(--a2) var(--a4);
    font-weight: 700; letter-spacing: -.01em; text-transform: uppercase;
    font-size: clamp(1rem, .8rem + 1.05 * var(--s), 2rem);
    & .ic { inline-size: 1.4em; block-size: 1.4em; flex: none; }
}
.w-teil-oben {
    flex: none; display: flex; align-items: center; gap: var(--a3); min-inline-size: 0;
    color: var(--tinte-leise); font-size: clamp(.95rem, .78rem + .8 * var(--s), 1.6rem);
}
/* Der Stand der Position in der Pille: "A11 5 / 12". Abgesetzt durch einen
   halbdurchsichtigen Block, damit man Position und Zahl auseinanderhaelt. */
.w-pille b {
    margin-inline-start: .4em; padding-inline-start: .4em;
    border-inline-start: 1px solid oklch(100% 0 0 / .45);
    font-weight: 800;
}
.w-pille {
    display: inline-block; vertical-align: .08em;
    background: var(--zustand, var(--akzent)); color: var(--hell);
    border-radius: var(--r-rund); padding: .05em .45em;
    font-size: .8em; font-weight: 700; letter-spacing: -.01em;
    font-variant-numeric: tabular-nums; white-space: nowrap;
}
.w-teil-person { display: inline-flex; align-items: center; color: var(--tinte); }
.w-teil-zeit { margin-inline-start: auto; font-variant-numeric: tabular-nums; }

/* Drei Spalten wie im Entwurf der Schreiner: Zustand, Werkstueck, Daten. */
.w-teil-haupt {
    /* stretch statt center: Nur mit einer festen Zellenhoehe kann sich das
       Werkstueck daran messen (max-block-size: 100%). Mit center war die Zelle
       inhaltshoch, und die Zeichnung wuchs aus der Karte heraus. */
    flex: 1; display: grid; gap: var(--a4); min-block-size: 0;
    grid-template-columns: auto minmax(0, 1.15fr) minmax(0, 1fr); align-items: stretch;
}

/* Zustand: Zeichen im Kreis und ein Wort, aus zehn Metern lesbar. */
.w-stand { display: grid; justify-items: center; gap: var(--a2); text-align: center;
           color: var(--zustand); }
.w-stand-kreis {
    display: grid; place-items: center; border-radius: var(--r-rund);
    background: var(--zustand); color: var(--hell);
    inline-size: clamp(2.6rem, 1.6rem + 3.4 * var(--s), 6.5rem); aspect-ratio: 1;
    & svg { inline-size: 62%; block-size: 62%; fill: none; stroke: currentColor;
            stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
}
.w-stand-wort { font-size: clamp(1rem, .72rem + 1.15 * var(--s), 2.4rem); font-weight: 800;
                line-height: 1.05; letter-spacing: -.02em; text-transform: uppercase;
                max-inline-size: 7em; }
.w-stand-neben { color: var(--tinte-leise); font-weight: 600;
                 font-size: clamp(.78rem, .68rem + .45 * var(--s), 1.1rem); }

.w-teil-text { min-inline-size: 0; display: grid; gap: var(--a2); align-content: center; }
/* Zwei Zeilen statt Abschneiden: "SOCKEL 40 U KANTEN" passt sonst nie. */
.w-teil-name {
    font-size: clamp(1.2rem, .85rem + 2.3 * var(--s), 3.6rem); font-weight: 700;
    line-height: 1.04; letter-spacing: -.035em; overflow-wrap: break-word;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
    line-clamp: 2; overflow: hidden;
}
.w-teil-id {
    font-size: clamp(1.05rem, .82rem + 1.3 * var(--s), 2.3rem); font-weight: 640;
    letter-spacing: -.04em; font-variant-numeric: tabular-nums; color: var(--tinte-leise);
}
/* Zwei Zeilen erlaubt: "440 × 295 mm · MUP Counter & Cash Desk · 1KFPF-..."
   wurde vorher mitten im Material abgeschnitten. */
.w-werte {
    min-inline-size: 0; color: var(--tinte-leise); font-weight: 560;
    overflow: hidden; overflow-wrap: anywhere;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2;
    font-size: clamp(.85rem, .72rem + .6 * var(--s), 1.35rem);
}
.w-teil-fuss { display: flex; flex-wrap: wrap; align-items: center; gap: var(--a3); }
.w-kanten {
    display: flex; align-items: baseline; gap: .4em; white-space: nowrap;
    color: var(--zustand);
    font-size: clamp(.9rem, .75rem + .7 * var(--s), 1.5rem); font-weight: 700;
    text-transform: uppercase;
    & b { font-size: 1.6em; font-weight: 800; letter-spacing: -.03em;
          font-variant-numeric: tabular-nums; }
}

/* -------------------------------------------------------------- Werkstueck
   Die Platte raeumlich, drei Flaechen aus monitor.php (stueckBild). Der Deckel
   hell, die Kanten in der Zustandsfarbe - so ist auch am Bild zu sehen, ob das
   Teil durch ist. Hoehe gedeckelt, die Zeichnung verkleinert sich dann von
   selbst und bleibt mittig (preserveAspectRatio). */
.w-teil-bild { display: grid; align-items: center; justify-items: stretch;
               min-inline-size: 0; min-block-size: 0; overflow: hidden; }
.w-stand, .w-teil-text { align-self: center; }
/* Das Bild fuellt seine Zelle und verkleinert sich von selbst. Die Masse stehen
   im Text, nicht darunter: Dort schob die Zeichnung sie aus der Karte. */
.w-stueck-bild {
    inline-size: 100%; block-size: 100%; max-block-size: min(42cqb, 100%);
    filter: drop-shadow(0 10px 16px oklch(35% .06 285 / .22));
}
.w-ohne-masse { color: var(--tinte-still); text-align: center; align-self: center; }

/* Kanten auf der Deckfläche: erledigt dunkel und voll, offen indigo gestrichelt -
   dieselbe Sprache wie das Kantenbild der alten Ansicht. Nur an Maschinen, die
   die Lage mitzählen. */
.w-kante-strich { stroke-width: 5; stroke-linecap: round; fill: none; }
.w-kante-strich.erledigt { stroke: var(--tinte); }
.w-kante-strich.offen    { stroke: var(--akzent); stroke-dasharray: 7 6; }
.w-deckel      { fill: oklch(96% .015 90); }
.w-kante-seite { fill: color-mix(in oklab, var(--zustand, oklch(70% .03 85)) 55%, var(--hell)); }
.w-kante-vorn  { fill: var(--zustand, oklch(76% .045 78)); }
polygon.w-deckel, polygon.w-kante-seite, polygon.w-kante-vorn {
    stroke: color-mix(in oklab, var(--zustand, var(--tinte-leise)) 60%, transparent);
    stroke-width: .8; stroke-linejoin: round;
}

/* ------------------------------------------------------------- Teil davor */
.w-vorher { grid-area: vorher; display: grid; gap: var(--a2); min-inline-size: 0;
            min-block-size: 0; overflow: hidden; }
.w-vor {
    display: flex; align-items: center; gap: var(--a4); min-inline-size: 0;
    block-size: 100%; position: relative;   /* traegt die Fahne oben rechts */
    background: color-mix(in oklab, var(--zustand-duft) 55%, var(--hell));
    border: 1px solid color-mix(in oklab, var(--zustand) 35%, transparent);
    border-inline-start: 8px solid var(--zustand);
    border-radius: var(--r); padding: var(--a2) var(--a4); overflow: hidden;
    font-size: clamp(.8rem, .7rem + .5 * var(--s), 1.25rem);
    animation: auftauchen .4s var(--feder) backwards;
}
.w-vor-stand { flex: none; display: flex; align-items: center; gap: var(--a3);
               color: var(--zustand);
               & .w-stand-kreis { inline-size: clamp(1.8rem, 1.2rem + 1.7 * var(--s), 3.2rem); }
               & .w-stand-wort { font-size: clamp(.8rem, .68rem + .55 * var(--s), 1.3rem);
                                 text-align: start; } }
/* Das Werkstueck nimmt die ganze Kartenhoehe: Im unteren Drittel ist Platz,
   und klein erkennt man aus zehn Metern nichts (Mirko, 18.09.2026). */
.w-vor-bild { flex: none; inline-size: auto; block-size: 100%; max-block-size: 20cqb;
              max-inline-size: 34%; }
/* Die Textspalte nimmt den freien Platz. Ohne das klebte die Kantenzahl direkt
   am Namen, weil nichts wuchs und alles links zusammenrutschte. */
.w-vor-text { flex: 1 1 14rem; min-inline-size: 0; display: grid;
    /* Nur das eigene b, nicht das im <small> mit dem Positionsstand - das war
       damit so gross wie die Ueberschrift (gemessen 22.09.2026). */
    & > b { font-weight: 660; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
          font-size: 1.25em; }
    & small { color: var(--tinte-leise); font-variant-numeric: tabular-nums;
              overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } }
/* Letzte Zeile: der Kantenstand in der Zustandsfarbe, wie in der Liste rechts. */
.w-vor-text .w-vor-kanten { color: var(--zustand); font-weight: 700; }
.w-vor-zeit { flex: none; margin-inline-start: auto; color: var(--tinte-still);
              font-variant-numeric: tabular-nums; }
/* Die Fahne in der oberen **linken** Ecke (Mirko, 22.09.2026). Sie sitzt buendig
   im Rand - die Karte hat overflow: hidden, deshalb schneidet die Rundung sie
   sauber ab - und traegt die Zustandsfarbe wie der Balken links. So sieht man
   auf einen Blick, dass diese Karte das vorige Teil zeigt, nicht das laufende. */
.w-vor-marke {
    position: absolute; inset-block-start: 0; inset-inline-start: 0;
    background: var(--zustand); color: var(--hell);
    padding: .5em 1.2em .6em; border-end-end-radius: var(--r);
    font-size: clamp(.68rem, .6rem + .34 * var(--s), 1rem);
    font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
    line-height: 1.15;
}

/* ------------------------------------------------------------ Liste rechts
   Die letzten Durchlaeufe mit farbigem Zustandsblock. Auch die nicht
   gezaehlten stehen mit da (blass), sonst wundert sich der Schreiner, warum
   sein Durchlauf fehlt. */

.w-liste {
    grid-area: liste; margin: 0; padding: 0; list-style: none;
    /* Jede Zeile so hoch, wie ihr Inhalt braucht. Vorher teilten sie sich die
       Hoehe zu gleichen Teilen (1fr) - seit Kunde und Kantenstand eigene Zeilen
       haben, sind die Karten vierzeilig und brauchen rund 95 px, bekamen bei
       acht Zeilen aber nur 72. Die erste Zeile jeder Karte wurde oben
       abgeschnitten (Mirko, 22.09.2026, mit Foto belegt).
       Wie viele Zeilen hineinpassen, summiert listePassend() in monitor.php
       aus den wirklichen Hoehen - so steht am Ende nie eine halbe Zeile. */
    /* Enger Abstand: Acht Karten brauchen mit --a2 genau so viel Platz, wie da
       ist - mit --a1 bleibt Luft, ohne dass es gedraengt wirkt. */
    display: grid; grid-auto-rows: min-content; gap: var(--a1);
    grid-template-rows: repeat(var(--zeilen), minmax(min-content, 1fr));
    min-block-size: 0; min-inline-size: 0; overflow: hidden;
}
.w-zeile {
    display: flex; align-items: stretch; gap: var(--a3);
    min-inline-size: 0; overflow: hidden;
    background: color-mix(in oklab, var(--zustand-duft) 45%, var(--hell));
    border: 1px solid color-mix(in oklab, var(--zustand) 28%, transparent);
    border-radius: var(--r); padding-inline-end: var(--a3);
    font-size: clamp(.78rem, .66rem + .5 * var(--s), 1.2rem);
}
/* Die neue Zeile faehrt von rechts herein. Die anderen stehen dabei schon an
   ihrem neuen Platz, das Auge liest es als "sie wurden nach unten geschoben"
   (Mirko, 22.09.2026). Nur die oberste bekommt die Klasse, und nur wenn wirklich
   ein anderes Teil dazugekommen ist - siehe werkstattZeichnen. */
.w-zeile.neu { animation: zeile-rein .45s var(--feder) backwards; }
@keyframes zeile-rein {
    /* Der negative Abstand oben macht die Zeile am Anfang hoehenlos - sie
       waechst auf und **schiebt** die anderen dabei wirklich nach unten. Ohne
       das sprangen die anderen sofort an ihren neuen Platz, und man sah nur die
       neue Karte hereinfahren (Mirko, 22.09.2026). --zeilen-hoehe setzt
       monitor.php auf die Hoehe der Zeile plus Zeilenabstand.
       ⚠ Nicht --h nennen: Das gibt es schon fuer die Tageskurve (.m-balken). */
    from { opacity: 0; transform: translateX(45%);
           margin-block-start: calc(-1 * var(--zeilen-hoehe, 0px)); }
}
.w-zeile.jetzt { border-color: var(--zustand); box-shadow: var(--tiefe-1); }
.w-zeile.leise { opacity: .72; }   /* nicht gezaehlt, aber noch lesbar */
.w-zeile.leer { display: grid; place-items: center; grid-row: 1 / -1;
                background: var(--glas); border-color: var(--rand);
                color: var(--tinte-still); padding: var(--a3); }
.w-z-zeichen {
    flex: none; display: grid; place-items: center; align-self: stretch;
    inline-size: 2.6em; background: var(--zustand); color: var(--hell);
    & svg { inline-size: 1.3em; block-size: 1.3em; fill: none; stroke: currentColor;
            stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
}
.w-z-bild { flex: none; inline-size: auto; block-size: 3.4em; max-inline-size: 30%;
            align-self: center; }
/* Der Stand der Position hinter "A11", in beiden kleinen Karten. */
.w-z-text small b, .w-vor-text small b { color: var(--tinte); font-weight: 700; }
.w-z-text { min-inline-size: 0; display: grid; align-content: center;
            padding-block: var(--a1);
    & b { font-weight: 660; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    & small { color: var(--tinte-leise); font-size: .82em;
              overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } }
/* Letzte Zeile: Kantenstand und Kunde. Der Kantenstand traegt die
   Zustandsfarbe, der Kunde dahinter bleibt leise - sonst schreit die ganze
   Zeile. Getrennt durch " · ", monitor.php setzt sie zusammen. */
/* ⚠ Zwei Klassen tief, wie die Schwesterregel .w-vor-text .w-vor-kanten:
   Verkuerzt verliert sie gegen ".w-z-text small" (0,1,1) und der Kantenstand
   waere grau statt farbig (gemessen 22.09.2026). */
.w-z-text .w-z-kanten { color: var(--zustand); font-weight: 700; }
.w-z-zeit { flex: none; margin-inline-start: auto; align-self: center;
            color: var(--tinte-still); font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------- Kennzahlen */
.w-zahlen {
    display: grid; gap: var(--a3);
    grid-template-columns: repeat(4, minmax(0, 1fr)) minmax(0, 1.3fr);
}
/* Die Tageskurve sitzt in derselben Reihe wie die Zahlen, nur breiter. */
.w-kurve-feld { padding: var(--a1) var(--a3); }
.w-kurve-feld .m-kurve { inline-size: 100%; }
.w-kurve-feld .m-kurve-balken { block-size: clamp(1.4rem, .9rem + 1.6 * var(--s), 2.6rem); }
.w-zahl {
    /* position und perspective gehoeren hierher: Die "+1" haengt sich an diese
       Kachel (monitor.php, kopfBewegen) und flog ohne position: relative in die
       Ecke des ganzen Feldes - gemessen x 1884 statt x 24. Und der Wirbel der
       Zahl dreht um die X-Achse, dafuer braucht der Elternteil perspective. */
    position: relative; perspective: 300px;
    display: flex; align-items: center; gap: var(--a3); min-inline-size: 0;
    background: var(--glas-satt); border: 1px solid var(--rand);
    border-radius: var(--r); padding: var(--a2) var(--a4); box-shadow: var(--tiefe-1);
    & b { font-size: clamp(1.1rem, .85rem + 1.2 * var(--s), 2.4rem); font-weight: 700;
          letter-spacing: -.03em; font-variant-numeric: tabular-nums; }
    & > span { color: var(--tinte-leise); min-inline-size: 0;
               font-size: clamp(.75rem, .66rem + .4 * var(--s), 1.05rem);
               overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}
.w-zahl.warn { border-color: var(--warn); & b, & .w-zahl-ic { color: var(--warn); } }
/* Die Einheit gehört an die Zahl, aber kleiner und leiser (Projektdoku). */
.mit-einheit small { font-size: .55em; font-weight: 600; opacity: .75;
                     margin-inline-start: .15em; letter-spacing: 0; }
.w-zahl-ic { flex: none; inline-size: 1.5em; block-size: 1.5em; color: var(--tinte-still);
             fill: none; stroke: currentColor; stroke-width: 1.8;
             stroke-linecap: round; stroke-linejoin: round; }

/* ⚠ Kopf, Auftragszeile und Maschinenkopf tragen **kein** backdrop-filter mehr
   (22.09.2026). Der Grund dahinter sind drei statische Farbflecken, also fast
   flach, und --glas-satt ist mit 78 % ohnehin fast deckend - die Unschaerfe war
   praktisch unsichtbar und wurde auf dem Fire TV Stick bei jedem Bild neu
   gerechnet, je Maschinenfeld einmal. Dieselbe Begruendung wie beim Meilenstein.

   ------------------------------------------------- Kopf der Werkstattansicht */
.w-kopf {
    display: flex; align-items: center; gap: var(--a4); min-inline-size: 0;
    background: var(--glas-satt);
    border: 1px solid var(--rand); border-block-start: 4px solid var(--farbe, var(--akzent));
    border-radius: var(--r-l) var(--r-l) 0 0; border-block-end: 0;
    padding: var(--a2) var(--a5); box-shadow: var(--tiefe-1);
    /* Kopf und Auftragszeile sind zusammen eine Karte. An der Naht standen
       vorher beide Polster uebereinander und dazu die Unterlaengen der
       Zeilenhoehe (Mirko, 22.09.2026). */
    padding-block-end: var(--a1); line-height: 1.15;
}
.w-kopf-name { flex: 0 1 auto; min-inline-size: 0; overflow: hidden; white-space: nowrap;
               text-overflow: ellipsis;
               font-size: clamp(1.1rem, .8rem + 1.5cqi, 2.2rem); font-weight: 680;
               letter-spacing: -.03em; color: var(--farbe, var(--akzent)); }
.w-kopf-person {
    display: flex; align-items: baseline; gap: var(--a3); min-inline-size: 0;
    font-size: clamp(.9rem, .72rem + .9cqi, 1.5rem);
    & b { font-weight: 660; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    & small { color: var(--tinte-leise); white-space: nowrap; }
}
.w-kopf-person.niemand { color: var(--tinte-still); & b { font-weight: 560; } }
/* Frist hinter dem Namen: wie lange die Anmeldung noch gilt. Den Text schreibt
   abmeldungTicken() im Sekundentakt, leer heisst weg - sonst stuende im Kopf
   eine Luecke ohne Inhalt. "knapp" die letzten fuenf Minuten, "sperre" solange
   dieselbe Karte nicht abmeldet. */
.w-kopf-frist:empty { display: none; }
.w-kopf-frist.knapp  { color: var(--warn); font-weight: 600; }
.w-kopf-frist.sperre { color: var(--akzent); font-weight: 600; }
.w-kopf-letzt { margin-inline-start: auto; flex: 0 1 auto; white-space: nowrap;
                overflow: hidden; text-overflow: ellipsis; color: var(--tinte-still);
                font-size: clamp(.85rem, .7rem + .8cqi, 1.3rem); }
.w-kopf-letzt.still { color: var(--warn); font-weight: 600; }

/* Schmaler Feldkopf (Handy): Was nur Beiwerk ist, verschwindet zuerst. */
/* Flaches Feld: 1366x768, 1280x720, 1024x768 oder zwei Maschinen uebereinander.
   Der Karte wird der Platz knapp, also faellt weg, was anderswo auch steht:
   die Wertezeile (Masse, Kommission, Material) und der lange Fortschrittstext.
   Gemessen am 21.09.2026 - vorher ragten Text und Werkstueck aus der Karte. */
@container feld (block-size < 40rem) {
    .m-warte-neben { display: none; }      /* "Bereit" allein reicht */
    .m-warte-rad { inline-size: min(6rem, 18cqb); }
    .w-teil { padding: var(--a3) var(--a4); gap: var(--a2); }
    .w-teil-name { -webkit-line-clamp: 1; line-clamp: 1;
                   font-size: clamp(1rem, .8rem + 1.5 * var(--s), 2.2rem); }
    .w-teil-id { font-size: clamp(.9rem, .78rem + .8 * var(--s), 1.5rem); }
    .w-werte { display: none; }
    .w-stand-kreis { inline-size: clamp(2rem, 1.5rem + 1.8 * var(--s), 3.4rem); }
    .w-stand-wort { font-size: clamp(.85rem, .7rem + .7 * var(--s), 1.4rem); }
    .w-achtung { padding: var(--a1) var(--a3);
                 font-size: clamp(.9rem, .78rem + .7 * var(--s), 1.5rem); }
    .w-stueck-bild { max-block-size: 30cqb; }
    .w-fortschritt-neben { display: none; }
}
/* Noch flacher (1280x720 und darunter): Das Teil davor weicht ganz, seine
   Zeile bekommt die Hoehe. */
@container feld (block-size < 32rem) {
    .w-raster { grid-template-rows: auto minmax(0, 1fr) 0 auto; }
    .w-vorher { display: none; }
    .w-teil-oben { display: none; }
}

/* Der Feldkopf wird schmal, sobald zwei Maschinen nebeneinander stehen: Was
   nur Beiwerk ist, verschwindet zuerst, damit der Maschinenname ganz dasteht. */
@container kachel (inline-size < 62rem) {
    .w-kopf-letzt { display: none; }
}
@container kachel (inline-size < 48rem) {
    .w-kopf { gap: var(--a3); padding-inline: var(--a4); }
    .w-kopf-person small, .m-verzoegert { display: none; }
}
@container kachel (inline-size < 30rem) {
    .w-kopf-person { display: none; }   /* der Maschinenname geht vor */
}


/* Schmales Feld (Handy, oder Monitor hochkant): Das Teil bleibt oben, die
   Liste rueckt darunter und zeigt nur so viele Zeilen, wie hinpassen. */
/* Schmales Feld (Handy, oder Monitor hochkant): eine Spalte, das Teil davor
   entfaellt, die Liste zeigt nur, was hineinpasst. */
@container feld (inline-size < 52rem) {
    .w-raster {
        grid-template-columns: minmax(0, 1fr);
        grid-template-rows: auto minmax(0, 1.5fr) minmax(0, 1fr) auto;
        grid-template-areas: "auftrag" "jetzt" "liste" "zahlen";
    }
    .w-vorher { display: none; }
    .w-auftrag { gap: var(--a3); }
    .w-auftrag-kunde, .w-fortschritt-neben, .w-marke { display: none; }
    /* Das Werkstueck bleibt neben dem Text stehen, nur schmaler: Untereinander
       passt beides nicht in die halbe Handyhoehe. Der Zustand darueber. */
    .w-teil-haupt { grid-template-columns: minmax(0, 1fr) minmax(0, 7.5rem);
                    grid-template-areas: "stand stand" "text bild";
                    align-content: safe center; gap: var(--a2) var(--a3); }
    .w-stand { grid-area: stand; grid-auto-flow: column; justify-content: start;
               align-items: center; gap: var(--a3); }
    .w-teil-bild { grid-area: bild; }
    .w-teil-text { grid-area: text; }
    .w-stueck-bild { max-block-size: 16cqb; }
    /* Am Handy zaehlen Name, Nummer und Kantenzahl. Masse, Kommission und
       Material fliegen raus, sonst schneidet die Karte unten ab. */
    .w-werte { display: none; }
    .w-achtung { font-size: clamp(.9rem, .78rem + .6 * var(--s), 1.3rem);
                 padding: var(--a1) var(--a3); }
    .w-teil { padding: var(--a3); gap: var(--a2); }
    /* Das Zahnrad richtet sich sonst nach der ganzen Feldhoehe und stoesst in
       das schmale Raster. */
    .w-buehne .m-warte-rad { inline-size: min(7rem, 22cqb); }
    .w-zahlen { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    /* Die Beschriftung bleibt, sie sagt erst, was die Zahl bedeutet. Sie
       rutscht unter die Zahl und wird klein - vier Kacheln im Zweierraster
       haben dafuer Platz. */
    .w-zahl { flex-wrap: wrap; row-gap: 0; }
    .w-zahl > span { flex: 1 0 100%; font-size: var(--s-mini); }
    .w-kurve-feld { display: none; }        /* am Handy fehlt die Breite dafür */
}


.m-leer, .m-laden { display: grid; place-items: center; min-block-size: 45dvb;
                    color: var(--tinte-still); font-size: 1.15em; }
/* Meldungen der letzten Stunde als Zeichen oben rechts (statt einer Fusszeile) */
.m-meldungen { display: inline-flex; align-items: center; gap: .3em; white-space: nowrap;
               color: var(--warn); font-weight: 680; font-variant-numeric: tabular-nums;
               & .ic { inline-size: 1.1em; block-size: 1.1em; } }
/* Anhalten neben "Alle im Wechsel": nur das Symbol */
/* Zurücksetzen der Wechsel-Füllung ohne Übergang (fortschrittSetzen()).
   Der Selektor nennt beide Klassen, damit er die Regel in .m-reiter-knopf
   ohne !important schlaegt. */
.m-reiter-knopf.dran.m-sprung::before { transition: none; }

/* --------------------------------------------------------------------------
   Monitor am Handy (schmal, oder quer und flach; gleiche Bedingung wie HANDY
   im Skript). Eine Kopfzeile: Marke, Probebetrieb, Uhr, Menü. Die Reiter
   weichen einem Blatt von unten, die Fusszeile entfällt (Vollbild braucht es
   am Handy nicht, Anhalten und Meldungen stehen im Blatt). So bleibt die ganze
   Höhe für das Feld.
   ----------------------------------------------------------------------- */
.m-kopf { position: relative; }
.m-menue { display: none; }
@media (max-width: 40rem), (max-height: 30rem) and (pointer: coarse) {
    .m-kopf { padding: var(--a2) var(--a2) var(--a2) var(--a4); gap: var(--a3); }
    .m-marke img { block-size: 1.6rem; }
    .m-rechts { gap: var(--a2); }
    .m-reiter, .m-meldungen { display: none; }   /* beides steht im Blatt */
    .m-menue {
        display: grid; place-items: center; flex: none;
        inline-size: 44px; block-size: 44px; border-radius: var(--r-rund);
        border: 1px solid var(--rand); background: var(--hell); color: var(--tinte);
        box-shadow: var(--tiefe-1); cursor: pointer;
        & .ic { inline-size: 1.35rem; block-size: 1.35rem; }
    }

    /* ⚠ Ein Fernseher ist kein Handy im Querformat, faellt hier aber in dieselbe
       Regel: Er meldet einen groben Zeiger (Fernbedienung), und mit der
       Adressleiste des Browsers bleiben nur 453 Pixel Hoehe, also unter den
       30 rem. Damit verschwanden die Maschinenreiter, und im Vollbild kamen sie
       wieder (Mirko, 22.09.2026). Auf einem Fernseher ist Platz in der Breite,
       nur nicht in der Hoehe - die Reiter bleiben also oben.

       Das Kennzeichen kommt nicht aus geratenen Massen, sondern vom
       Fernseherknopf: monitor.php setzt body.tv, wenn er gedrueckt ist. */
    body.tv {
        & .m-reiter, & .m-meldungen { display: flex; }
        & .m-menue { display: none; }
    }
}

.m-blatt {
    position: fixed; inset: auto 0 0; margin: 0;
    inline-size: 100%; max-inline-size: 36rem; margin-inline: auto;
    max-block-size: 85dvb; overflow-y: auto; overscroll-behavior: contain;
    padding: var(--a2) var(--a4) calc(var(--a4) + env(safe-area-inset-bottom));
    border: 1px solid var(--rand); border-block-end: 0;
    border-radius: var(--r-l) var(--r-l) 0 0;
    background: var(--glas-satt); backdrop-filter: var(--unschaerfe);
    -webkit-backdrop-filter: var(--unschaerfe);
    box-shadow: var(--tiefe-3); color: var(--tinte);
    &[open] { animation: blatt-rein .32s var(--feder) both; }
    &:focus { outline: none; }   /* bekommt beim Öffnen den Fokus, siehe monitor.php */
}
.m-blatt::backdrop { background: oklch(20% .02 285 / .38); }
@keyframes blatt-rein { from { transform: translateY(100%); } }
.m-blatt-griff { inline-size: 2.5rem; block-size: 4px; margin: 0 auto var(--a2);
                 border-radius: var(--r-rund); background: var(--rand); }
.m-blatt-kopf { display: flex; align-items: center; justify-content: space-between;
                & h2 { font-size: 1.15rem; font-weight: 680; letter-spacing: -.02em; } }
.m-blatt-zu {
    display: grid; place-items: center; inline-size: 44px; block-size: 44px;
    border: 0; border-radius: var(--r-rund); background: transparent; color: var(--tinte-leise);
    cursor: pointer; & .ic { inline-size: 1.25rem; block-size: 1.25rem; }
    &:hover { background: var(--glas); color: var(--tinte); }
}
.m-blatt-gruppe { margin: var(--a3) 0 var(--a1); font-size: var(--s-mini); font-weight: 650;
                  letter-spacing: .06em; text-transform: uppercase; color: var(--tinte-still); }
.m-blatt-zeile {
    display: flex; align-items: center; gap: var(--a3); inline-size: 100%;
    min-block-size: 3.5rem; padding: var(--a2) var(--a3); margin-block-end: 2px;
    border: 1px solid transparent; border-radius: var(--r);
    background: transparent; color: inherit; font: inherit; text-align: start; cursor: pointer;
    transition: background var(--tempo), border-color var(--tempo);
    &:hover { background: var(--glas); }
    &[aria-pressed="true"] {
        background: color-mix(in oklab, var(--farbe, var(--akzent)) 10%, var(--hell));
        border-color: color-mix(in oklab, var(--farbe, var(--akzent)) 35%, transparent);
    }
}
.m-blatt-symbol {
    display: grid; place-items: center; flex: none; inline-size: 2.5rem; block-size: 2.5rem;
    border-radius: var(--r-rund); color: var(--farbe, var(--akzent));
    background: color-mix(in oklab, var(--farbe, var(--akzent)) 14%, transparent);
    & svg { inline-size: 1.25rem; block-size: 1.25rem; fill: none; stroke: currentColor;
            stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
}
.m-blatt-text { flex: 1; min-inline-size: 0; display: grid; gap: 2px;
                & b { font-weight: 640; letter-spacing: -.015em; }
                & small { font-size: var(--s-klein); line-height: 1.35; color: var(--tinte-leise); } }
.m-blatt-haken { flex: none; inline-size: 1.3rem; block-size: 1.3rem; stroke-width: 2.4;
                 color: var(--farbe, var(--akzent)); opacity: 0; }
[aria-pressed="true"] > .m-blatt-haken { opacity: 1; }
.m-blatt-aktion {
    display: flex; align-items: center; justify-content: center; gap: var(--a2);
    inline-size: 100%; min-block-size: 44px; margin-block-start: var(--a3);
    border: 1px solid var(--rand); border-radius: var(--r-rund); background: var(--hell);
    color: var(--tinte); font: 620 1em/1 var(--schrift); cursor: pointer;
    & .ic { inline-size: 1.2em; block-size: 1.2em; }
}
.m-blatt-hinweis { margin-block-start: var(--a3); text-align: center;
                   color: var(--warn); font-weight: 650; font-size: var(--s-klein); }
@media (prefers-reduced-motion: reduce) {
    .m-blatt[open] { animation: none; }
}

/* Kurzer Hinweis unter dem Kopf (hinweisZeigen), zum Beispiel bei der fünften Maschine */
.m-hinweis {
    position: fixed; z-index: 30; inset-block-start: 5rem; inset-inline-start: 50%;
    translate: -50% 0; max-inline-size: calc(100% - 2rem); padding: .6em 1.1em;
    border-radius: var(--r-rund); background: var(--tinte); color: var(--hell);
    font-weight: 600; font-size: .85em; box-shadow: var(--tiefe-3);
    animation: einblenden .3s ease backwards;
}
/* ==========================================================================
   Bestätigungsfenster

   Ersetzt confirm() des Browsers. Ein natives <dialog>, damit Fokusfalle,
   Escape-Taste und Zugänglichkeit ohne eigene Bastelei funktionieren.
   ========================================================================== */

.frage {
    inline-size: min(100% - 2rem, 26rem);
    /* Der Browser zentriert Dialoge mit margin:auto - das globale
       "* { margin: 0 }" oben nimmt ihm das wieder weg. Hier zurückholen. */
    margin: auto;
    padding: 0;
    border: 1px solid var(--rand);
    border-radius: var(--r-l);
    background: var(--glas-satt);
    backdrop-filter: var(--unschaerfe);
    -webkit-backdrop-filter: var(--unschaerfe);
    box-shadow: var(--tiefe-3);
    color: var(--tinte);
}
.frage::backdrop {
    background: oklch(30% .04 285 / .32);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
}
/* Auf- und zufahren, statt einfach da zu sein */
.frage[open]           { animation: frage-auf .28s var(--feder); }
.frage[open]::backdrop { animation: einblenden .28s ease; }
@keyframes frage-auf {
    from { opacity: 0; transform: translateY(14px) scale(.96); }
}

.frage-inhalt { display: flex; flex-direction: column; gap: var(--a5); padding: var(--a5); }

.frage-kopf {
    display: flex; gap: var(--a4); align-items: flex-start;
    & h2 { font-size: 1.0625rem; margin-block-end: var(--a1); }
    & p  { line-height: 1.5; }
}
.frage-zeichen {
    display: grid; place-items: center; flex: none;
    inline-size: 2.5rem; block-size: 2.5rem;
    border-radius: var(--r-rund);
    background: var(--fehler-duft); color: var(--fehler);
    & .ic { inline-size: 1.25rem; block-size: 1.25rem; stroke-width: 2; }
}
.frage-knoepfe {
    display: flex; gap: var(--a2); justify-content: flex-end;
    & .knopf { flex: 1; }
}
@media (min-width: 26rem) { .frage-knoepfe .knopf { flex: 0 0 auto; min-inline-size: 7rem; } }

/* Roter Knopf mit Fuellung - nur hier, damit die Tragweite sichtbar ist */
.knopf.gefahr-voll {
    background: linear-gradient(160deg, oklch(62% .19 25), var(--fehler));
    border-color: transparent; color: var(--hell);
    box-shadow: 0 1px 2px oklch(45% .18 25/.25), 0 8px 20px -8px oklch(50% .2 25/.55);
    &:hover { box-shadow: 0 2px 4px oklch(45% .18 25/.3), 0 16px 32px -10px oklch(50% .2 25/.6); }
}

/* Logo auf der Anmeldeseite - hier ist Platz, also gross und mittig. */
/* PIN des Monitors: gross, mittig, mit Abstand zwischen den Ziffern. */
.pin-feld {
    font-size: 1.75rem; text-align: center; letter-spacing: .4em;
    font-variant-numeric: tabular-nums; padding-inline-start: .4em;
}
/* Monitor-PIN als vier Kästchen (monitor.php). Das echte Feld liegt unsichtbar
   darüber und nimmt jeden Tipp an; die Kästchen zeigen Punkte und wo es weitergeht.
   Erst mit .an (vom Skript), ohne Skript bleibt das normale Feld. */
.pin-kaesten { display: block; }
.pin-kasten { display: none; }
.pin-kaesten.an {
    position: relative; display: grid; grid-template-columns: repeat(4, 1fr);
    gap: var(--a3); max-inline-size: 18rem; margin-inline: auto;
    & .pin-feld { position: absolute; inset: 0; z-index: 1; inline-size: 100%; block-size: 100%;
                  opacity: 0; cursor: text; }
    & .pin-kasten {
        display: grid; place-items: center; aspect-ratio: 4 / 5;
        border: 1.5px solid color-mix(in oklab, var(--tinte-still) 45%, transparent);
        border-radius: var(--r); background: var(--hell);
        box-shadow: inset 0 1px 2px oklch(40% .05 285/.06);
        transition: border-color var(--tempo), box-shadow var(--tempo), transform var(--tempo);
    }
    & .pin-kasten.voll::after {
        content: ""; inline-size: .8rem; block-size: .8rem; border-radius: var(--r-rund);
        background: var(--tinte); animation: pin-punkt .22s var(--feder) both;
    }
    & .pin-kasten.dran { border-color: var(--akzent); box-shadow: 0 0 0 4px var(--akzent-duft); }
    &.falsch .pin-kasten { border-color: var(--fehler); }
    &.falsch { animation: pin-falsch .4s ease-in-out; }
}
@keyframes pin-punkt { from { transform: scale(0); } }
@keyframes pin-falsch { 20%, 60% { transform: translateX(-6px); } 40%, 80% { transform: translateX(6px); } }
@media (prefers-reduced-motion: reduce) {
    .pin-kaesten.an.falsch, .pin-kaesten.an .pin-kasten.voll::after { animation: none; }
}

.anmelde-logo {
    inline-size: 12rem; block-size: auto;
    margin-inline: auto; margin-block-end: var(--a3);
}

/* ============================================================= Zentro-Seite
   Werkbank für die API. Eigener Abschnitt, weil hier Dinge vorkommen, die es
   sonst nirgends in der App gibt: Rohdaten in Festbreitenschrift und eine
   Tabelle mit unbekannt vielen Spalten. Alles ueber dieselben Tokens. */

.einzeilig {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
    overflow-wrap: anywhere;
}

/* Der Endpunkt antwortet derzeit mit Fehler - kleiner roter Punkt am Reiter,
   damit man das sieht, bevor man ihn anklickt. */
.wahl-feld span.punkt-fehler {
    inline-size: .45rem; block-size: .45rem; min-block-size: 0; flex: 0 0 auto;
    padding: 0; border: 0; border-radius: var(--r-rund);
    background: var(--fehler); box-shadow: none;
}
.wahl-feld input:checked + span span.punkt-fehler { background: var(--hell); }

/* Feld, Vergleich, Wert. Am Handy untereinander, ab Tablet nebeneinander -
   der Wert bekommt den meisten Platz, die Feldnamen sind kurz. */
.filter-raster { display: grid; gap: var(--a3); }
@media (min-width: 40rem) {
    .filter-raster { grid-template-columns: 1fr 1fr 1.4fr; align-items: end; }
}

.ausklapp {
    margin-block-start: var(--a4);
    border-block-start: 1px solid var(--rand-innen);
    padding-block-start: var(--a3);
    & summary {
        cursor: pointer; list-style: none;
        font-size: var(--s-klein); font-weight: 570; color: var(--akzent);
        min-block-size: 44px; display: flex; align-items: center; gap: var(--a2);
        &::-webkit-details-marker { display: none; }
        &::before { content: "+"; font-weight: 700; font-size: 1.1em; line-height: 1; }
    }
    &[open] summary::before { content: "−"; }
    & > *:not(summary) { margin-block-start: var(--a3); }
    & textarea {
        font: var(--s-klein)/1.5 var(--schrift-fest);
        min-block-size: 9rem; resize: vertical;
    }
}

/* Kopfzeile der Antwort: Statuscode, Dauer, Größe, Anzahl. */
.a-kopf {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--a2) var(--a4);
}

/* Rohantwort. Bewusst Festbreitenschrift und scrollbar statt umgebrochen -
   in JSON ist die Einrückung die Struktur, ein Umbruch zerstört sie. */
.roh {
    margin: 0; max-block-size: 30rem; overflow: auto;
    padding: var(--a4);
    border: 1px solid var(--rand); border-radius: var(--r-s);
    background: var(--glas-satt);
    font: var(--s-klein)/1.55 var(--schrift-fest);
    color: var(--tinte);
}

/* Die Tabelle scrollt in sich selbst. Die Seite darf nie seitlich wandern,
   sonst ist am Handy die Navigation nicht mehr zu treffen. */
.tabelle-huelle {
    overflow-x: auto;
    border: 1px solid var(--rand); border-radius: var(--r-s);
    /* Schatten am Rand, solange seitlich noch etwas kommt. Die beiden
       "local"-Verläufe decken ihn ab, sobald man am Anfang bzw. Ende ist -
       dadurch sieht man ohne Beschriftung, dass die Tabelle weitergeht. */
    background:
        linear-gradient(to right, var(--glas-satt), transparent) left / 2rem 100% no-repeat local,
        linear-gradient(to left,  var(--glas-satt), transparent) right / 2rem 100% no-repeat local,
        radial-gradient(farthest-side at 0 50%, oklch(35% .07 285 / .16), transparent)
            left / .7rem 100% no-repeat scroll,
        radial-gradient(farthest-side at 100% 50%, oklch(35% .07 285 / .16), transparent)
            right / .7rem 100% no-repeat scroll,
        var(--glas-satt);
}
.api-tabelle {
    border-collapse: collapse; inline-size: max-content; min-inline-size: 100%;
    font-size: var(--s-klein);
    & th, & td {
        padding: var(--a2) var(--a3); text-align: start;
        border-block-end: 1px solid var(--rand-innen);
        white-space: nowrap; max-inline-size: 22rem;
        overflow: hidden; text-overflow: ellipsis;
    }
    & th {
        position: sticky; inset-block-start: 0; z-index: 1;
        background: var(--glas-satt);
        backdrop-filter: var(--unschaerfe);
        -webkit-backdrop-filter: var(--unschaerfe);
        font-weight: 600; color: var(--tinte-leise);
        font-size: var(--s-mini); letter-spacing: .01em;
    }
    & td { font-variant-numeric: tabular-nums; }
    & tbody tr:last-child :is(th, td) { border-block-end: 0; }
    & tbody tr:hover td { background: var(--akzent-duft); }
}

/* Der schreibende Teil ist abgesetzt: warmer Grund und roter Rand oben.
   Man soll beim Scrollen merken, dass hier etwas anderes passiert. */
.karte.schreibend {
    border-color: oklch(80% .08 25 / .5);
    background: linear-gradient(var(--fehler-duft), var(--glas) 5rem);
    & h2 .ic { color: var(--fehler); }
}

/* Kurze technische Bezeichner im Fließtext. */
code {
    font: .9em/1.4 var(--schrift-fest);
    background: var(--glas-dezent); border: 1px solid var(--rand-innen);
    border-radius: 5px; padding: .1em .35em;
}

/* Überschrift mit Zeichen davor. Ohne das eigene Flex bricht das Zeichen durch
   text-wrap: balance in eine eigene Zeile und steht dann über dem Titel. */
.kopfzeile h2 { display: flex; align-items: center; gap: var(--a2); text-wrap: nowrap; }
.kopfzeile h2 .ic { color: var(--akzent); }

/* ============================================================================
   Simulator - eine Teilenummer von Hand denselben Weg schicken wie der Pi.
   ========================================================================= */

/* Die Teilenummer ist das eine Feld, in das hier getippt wird. Entsprechend
   gross, mit Zahlenschrift: 236656 und 236856 duerfen sich nicht aehneln. */
/* Mit .feld davor, weil die Basisregel .feld :is(input, select, textarea)
   sonst gewinnt. Ohne den Vorsatz braeuchte es zwei !important. */
.feld .gross-eingabe {
    font-size: clamp(1.4rem, 1.1rem + 1.4vw, 2.1rem);
    font-weight: 620; letter-spacing: .01em;
    font-variant-numeric: tabular-nums;
    padding-block: var(--a3);
}

/* Kleine Schrift, aber volle Klickflaeche: 44 px gelten auch hier. Vorher
   stand min-block-size: 0 darin, dann waren diese Knoepfe 18 px hoch und mit
   dem Finger kaum zu treffen (gemessen 23.09.2026). */
.knopf.winzig { padding-inline: var(--a3); font-size: var(--s-mini);
                font-variant-numeric: tabular-nums; }

/* Der Weg in vier Schritten. Die Nummern stehen aussen an einer Linie,
   damit auf einen Blick erkennbar ist, wie weit ein Scan gekommen ist. */
.schritte {
    list-style: none; padding: 0; margin: 0;
    display: grid; gap: var(--a4);
    & > li { padding-inline-start: var(--a4);
             border-inline-start: 2px solid var(--rand-innen); }
    & > li > b { display: block; margin-block-end: var(--a2);
                 font-weight: 620; letter-spacing: -.015em; }
    & .werte { margin-block-start: var(--a1); }
}

/* Roher Rumpf, wie er ueber die Leitung ging. Bewusst unverschoenert. */
pre.code {
    margin-block-start: var(--a2);
    padding: var(--a3);
    background: oklch(97% .004 285); border: 1px solid var(--rand-innen);
    border-radius: var(--r-s);
    font: 500 var(--s-mini)/1.5 var(--schrift-fest);
    color: var(--tinte-leise);
    overflow-x: auto; white-space: pre;
}

/* --------------------------------------------------------------------------
   Die Hilfe (hilfe.php)

   Bewusst wenig: Der Text kommt als gewoehnliches HTML aus inc/hilfe/ und soll
   sich wie ein Buch lesen. Gestaltet wird nur, was das Lesen erleichtert -
   Zeilenlaenge, Abstaende, Tabellen, zwei Arten von Merkkaesten.
   ----------------------------------------------------------------------- */

 /* ⚠ min-inline-size: 0 an beiden Kindern. Ohne das bekommt ein Rasterkind
   seine Inhaltsbreite als Mindestbreite, und eine breite Tabelle im Text macht
   die ganze Seite waagrecht rollbar (23.09.2026 am Handy gesehen). */
.hilfe { display: grid; gap: var(--a5); align-items: start; min-inline-size: 0; }
.hilfe > * { min-inline-size: 0; }
/* Am Handy zuerst der Text, das Verzeichnis darunter: Sonst müsste man an
   dreizehn Kapiteln vorbeirollen, bevor der erste Satz kommt. */
.hilfe-inhalt { order: 2; }
.hilfe-text { order: 1; }
@media (min-width: 60rem) {
    .hilfe { grid-template-columns: 17rem minmax(0, 1fr); gap: var(--a6); }
    .hilfe-inhalt { order: 0; position: sticky; inset-block-start: var(--a5); }
    .hilfe-text { order: 0; }
}

.hilfe-inhalt {
    background: var(--glas); border: 1px solid var(--rand); border-radius: var(--r);
    padding: var(--a4); box-shadow: var(--tiefe-1);
    & ol { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--a1); counter-reset: kapitel; }
    & a {
        display: block; padding: var(--a2) var(--a3); border-radius: var(--r-s);
        text-decoration: none; color: var(--tinte); min-block-size: 44px;
        & strong { display: block; font-weight: 600; letter-spacing: -.01em; }
        & small { display: block; color: var(--tinte-leise); font-size: var(--s-mini); }
        &:hover { background: var(--glas-satt); }
        &[aria-current="page"] { background: var(--akzent); color: var(--hell);
                                 & small { color: oklch(100% 0 0 / .8); } }
    }
}
.hilfe-inhalt-marke {
    margin: 0 0 var(--a2); font-size: var(--s-mini); font-weight: 620;
    letter-spacing: .06em; text-transform: uppercase; color: var(--tinte-still);
}

.hilfe-text {
    /* Zeilenlaenge begrenzen: Ueber etwa 75 Zeichen findet das Auge die naechste
       Zeile nicht mehr zuverlaessig. */
    max-inline-size: 46rem;
    & h2 { margin-block: 0 var(--a4); }
    & h3 { margin-block: var(--a6) var(--a3); }
    & h4 { margin-block: var(--a5) var(--a2); font-size: var(--s-text); }
    & p { margin-block: 0 var(--a3); line-height: 1.65; }
    & ul, & ol { margin-block: 0 var(--a4); padding-inline-start: var(--a5); line-height: 1.6; }
    & li { margin-block-end: var(--a1); }
    & dl { margin-block: 0 var(--a4); }
    & dt { font-weight: 620; margin-block-start: var(--a3); }
    & dd { margin: 0 0 var(--a2); padding-inline-start: var(--a4);
           border-inline-start: 2px solid var(--rand-satt); color: var(--tinte-leise); line-height: 1.6; }
    & code { font-family: var(--schrift-fest); font-size: .92em;
             background: var(--glas-satt); border: 1px solid var(--rand);
             border-radius: var(--r-s); padding: .1em .35em; overflow-wrap: anywhere; }
    /* Tabellen sind hier die halbe Miete: fast jede Zahl steht in einer. */
    & table { inline-size: 100%; border-collapse: collapse; margin-block: 0 var(--a4);
              font-size: var(--s-klein); display: block; overflow-x: auto; }
    & th, & td { text-align: start; vertical-align: top; padding: var(--a2) var(--a3);
                 border-block-end: 1px solid var(--rand-satt); }
    & th { font-weight: 620; color: var(--tinte-leise); white-space: nowrap; }
    & tbody tr:last-child :is(th, td) { border-block-end: 0; }
}

/* Zwei Kaesten, mehr nicht: eine Warnung und ein Merksatz. */
.hilfe-text .hilfe-warnung, .hilfe-text .hilfe-merk {
    margin-block: 0 var(--a4); padding: var(--a3) var(--a4);
    border-inline-start: 4px solid currentColor; border-radius: 0 var(--r-s) var(--r-s) 0;
    line-height: 1.6;
}
.hilfe-text .hilfe-warnung { background: var(--warn-duft); color: var(--warn); }
.hilfe-text .hilfe-merk    { background: var(--akzent-duft); color: var(--akzent); }
.hilfe-text :is(.hilfe-warnung, .hilfe-merk) strong { color: inherit; }

/* ⚠ Umbrechen erlaubt und Knopftext kuerzbar: Zwei lange Kapitelnamen
   nebeneinander waren am Handy 27 Pixel zu breit und machten die ganze Seite
   waagrecht rollbar (23.09.2026 gemessen). */
.hilfe-weiter {
    display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--a3);
    margin-block-start: var(--a6); padding-block-start: var(--a4);
    border-block-start: 1px solid var(--rand-satt);
    & .knopf { min-inline-size: 0; max-inline-size: 100%;
               & span, & { overflow: hidden; text-overflow: ellipsis; } }
}

/* --------------------------------------------------------------------------
   Stoerungsband

   Es gibt es nur, weil dieser Bildschirm wochenlang unbeaufsichtigt laeuft:
   Ein toter Monitor sah bisher aus wie ein wartender.
   ----------------------------------------------------------------------- */

.m-stoerung {
    flex: none;
    background: var(--fehler); color: var(--hell);
    font: 640 clamp(1rem, .82rem + .8vw, 1.6rem)/1.25 var(--schrift);
    letter-spacing: -.02em; text-align: center;
    padding: var(--a3) var(--a5);
}

/* --------------------------------------------------------------- Zahlenleiste
   Die Werte des laufenden Betriebs, unten am Monitor: wie lange ein Teil vom
   Pi hierher braucht, wie schnell Server und Datenbank antworten.

   Immer sichtbar, kein Schalter (22.09.2026).

   `flex: none` in der Spalte des Koerpers - sie nimmt sich ihre Hoehe, statt
   ueber der Buehne zu liegen. Ueberlagert verdeckte sie die Liste, und der
   Monitor darf nicht scrollen, um sie sichtbar zu machen. */
.m-mess {
    flex: none;
    /* Ueber die ganze Breite verteilt statt links zusammengedraengt: Auf einem
       1920er Schirm blieben sonst zwei Drittel leer (Mirko, 22.09.2026). */
    display: flex; flex-wrap: wrap; align-items: center;
    justify-content: space-between;
    gap: var(--a2) var(--a4);
    padding: var(--a2) var(--a5);
    /* Dunkel mit heller Schrift: Der ganze Monitor ist hell, so liest sich die
       Leiste als Werkzeugebene und nicht als Teil der Werkstattanzeige - und
       sie tritt hinter die Zustandsfarben zurueck, die aus drei Metern wirken
       sollen (Mirko, 22.09.2026). */
    background: oklch(26% .03 285); color: oklch(92% .012 285);
    border-block-start: 1px solid oklch(38% .035 285);
    font: 500 var(--s-mini)/1.2 var(--schrift-fest);
}
/* Jeder Eintrag so breit wie sein Inhalt, die Abstaende dazwischen gleich
   (space-between an der Leiste). Gleich breite Spalten sahen nach Tabelle aus,
   obwohl die Inhalte sehr verschieden lang sind (Mirko, 22.09.2026).

   Damit es trotzdem nicht springt, reserviert jede Pille dort Breite, wo sich
   die Zahl aendert - siehe --mess-breite unten. Sonst rutschte die ganze Leiste,
   sobald ein Wert von "9 ms" auf "12 ms" wechselt. */
.m-mess-eintrag { display: flex; flex: none; align-items: baseline; gap: var(--a2); }
.m-mess-was { opacity: .78; letter-spacing: -.01em; }
.m-mess-wert {
    /* Nie umbrechen: Eine zweizeilige Pille machte die ganze Leiste hoeher.
       --mess-breite haelt Platz frei, damit wechselnde Zahlen nichts verschieben;
       gesetzt von messEintrag() in monitor.php, in ch (Ziffernbreiten).
       ⚠ Nicht --breite nennen: Das gibt es schon fuer die Seitenbreite (70rem),
       und CSS-Variablen vererben sich - die Pillen wurden dadurch 1120 px breit
       (22.09.2026 gemessen). */
    font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap;
    min-inline-size: var(--mess-breite, 0); text-align: center;
    border-radius: var(--r-rund); padding: .15em .5em;
    /* Der Wechsel der Ampel soll auffallen, ohne zu blinken. */
    transition: background-color .4s ease, color .4s ease;
    /* Auf dunklem Grund braucht die Ampel helle Toene, sonst verschwindet Rot.
       Der Grund bleibt die gedeckte Farbe, die Schrift wird hell. */
    background: oklch(38% .09 168); color: oklch(92% .12 168);
}
.m-mess-wert.warn   { background: oklch(40% .09 68); color: oklch(90% .13 80); }
.m-mess-wert.schlimm{ background: oklch(40% .13 22); color: oklch(90% .09 22); }
/* Kein Urteil, aber trotzdem eine Pille: Jeder Wert steht in einer, sonst
   wirkt einer davon wie vergessen. Gedeckt statt ampelfarbig. */
.m-mess-wert.aus    { background: oklch(34% .02 285); color: oklch(84% .012 285); }

/* Halter fuer den Verbindungspunkt. Er bleibt 7 px gross, bekommt aber eine
   Trefferflaeche fuer den Daumen. Kein Knopf mehr: Der Punkt zeigt nur noch
   an, ob der Server antwortet - die Zahlenleiste ist immer da (22.09.2026). */
.m-puls-halter {
    inline-size: 1.75rem; block-size: 1.75rem; flex: none;
    display: grid; place-items: center;
}

/* Die kleinen Knoepfe im Kopf: Fernsehermodus und Vollbild. Blass, solange sie
   aus sind - sie werden einmal gedrueckt, wenn der Schirm aufgehaengt wird, und
   danach nie wieder. */
.m-kopf-knopf {
    appearance: none; border: 0; background: none; padding: var(--a2);
    margin: calc(var(--a2) * -1); cursor: pointer; line-height: 0;
    display: inline-flex; align-items: center; color: inherit; opacity: .45;

    & .ic { inline-size: 1.25rem; block-size: 1.25rem; }
    &:hover, &:focus-visible { opacity: .9; }
    &[aria-pressed="true"] { opacity: 1; color: var(--akzent); }
    /* Solange geholt wird, dreht sich das Symbol - sonst fuehlt sich der Knopf
       tot an, weil der Abruf oft in 30 ms durch ist. */
    &.dreht { opacity: 1; color: var(--akzent);
              & .ic { animation: zahnrad .9s linear infinite; } }
}

@media (max-width: 40rem) {
    /* Am Handy nur die zwei Werte, die dort etwas aussagen: der Weg vom Pi und
       die Leitung zum Server. Alles andere bräche auf eine zweite Zeile um und
       nähme der Buehne die Hoehe - am 390 px breiten Schirm gemessen. */
    .m-mess { gap: var(--a1) var(--a3); padding: var(--a2) var(--a3); font-size: .7rem; }
    .m-mess-eintrag.nur-gross { display: none; }
}

/* Grosse Teilenummer in der Scanliste. Bisher stand dort class="teil-id gross",
   und .gross gab es nur fuer Symbole - die Zahl blieb auf Textgroesse. */
.teil-id.gross { font-size: var(--s-gross); }

/* ==========================================================================
   Marke, Urheber, Erklärtexte, Toasts
   ========================================================================== */

/* Das Logo trägt die Marke, nicht mehr Zeichen plus Schriftzug. Feste Höhe,
   damit die Kopfzeile nicht springt, während das SVG lädt.
   Das Gegenstück für den Monitor (.m-marke img) steht weiter oben beim Kopf. */
.marke img { block-size: 1.7rem; inline-size: auto; display: block; }

/* Urheberzeile. Bewusst zurückhaltend: LEHScan ist die Marke, mp media steht
   darunter wie ein Signet auf einem Möbelstück. */
.seiten-fuss {
    padding: var(--a6) var(--a4) var(--a4);
    display: flex; justify-content: center;
}
.urheber {
    display: inline-flex; align-items: center; gap: var(--a2);
    color: var(--tinte-still); text-decoration: none;
    font-size: var(--s-mini); letter-spacing: .01em;
    opacity: .8; transition: opacity var(--tempo);
    &:hover { opacity: 1; }
    & img { block-size: 1.5rem; inline-size: auto; display: block; }
}

/* --------------------------------------------------------------------------
   Erklärtexte

   Vorher waren das graue Absätze, die neben dem übrigen Text untergingen.
   Jetzt tragen sie ein Zeichen und eine eigene Fläche, damit man auf einen
   Blick sieht: Das ist eine Erklärung, keine Bedienung.
   ----------------------------------------------------------------------- */

.hinweis {
    display: flex; gap: var(--a3);
    background: color-mix(in oklab, var(--akzent-duft) 60%, transparent);
    border: 1px solid color-mix(in oklab, var(--akzent) 16%, transparent);
    border-radius: var(--r-s);
    padding: var(--a3) var(--a4);
    font-size: var(--s-klein); line-height: 1.55; color: var(--tinte-leise);

    & > .ic { flex: none; inline-size: 1.15rem; block-size: 1.15rem;
              color: var(--akzent); margin-block-start: .12em; }
    & p { margin: 0; }
    & p + p { margin-block-start: var(--a2); }
    & strong { color: var(--tinte); font-weight: 600; }
}

.hinweis.achtung {
    background: color-mix(in oklab, var(--warn-duft) 70%, transparent);
    border-color: color-mix(in oklab, var(--warn) 24%, transparent);
    & > .ic { color: var(--warn); }
}

/* --------------------------------------------------------------------------
   Toasts

   Fahren oben rechts ein, gehen von selbst wieder. Am Handy von oben über die
   volle Breite, weil rechts oben dort der Daumen nicht hinkommt und die
   Kopfzeile schmal ist.
   ----------------------------------------------------------------------- */

.toasts {
    position: fixed; z-index: 60;
    inset-block-start: calc(var(--nav) + var(--a3));
    inset-inline-end: var(--a4);
    display: flex; flex-direction: column; gap: var(--a2);
    inline-size: min(30rem, calc(100vw - 2 * var(--a4)));
    pointer-events: none;
}

.toast {
    pointer-events: auto;
    /* Gross genug, um es im Vorbeigehen zu lesen: Schrift wie der Fliesstext,
       halbfett, kräftiges Zeichen. Der Schliessen-Knopf hat 44 px zum Tippen. */
    display: flex; align-items: center; gap: var(--a3);
    background: var(--hell);
    border: 1px solid var(--rand-innen);
    border-inline-start: 5px solid var(--akzent);
    border-radius: var(--r);
    padding: var(--a2) var(--a1) var(--a2) var(--a4);
    min-block-size: 3.75rem;
    box-shadow: var(--tiefe-3);
    font-size: 1rem; font-weight: 560; line-height: 1.4; color: var(--tinte);

    opacity: 0; transform: translateX(1.5rem) scale(.98);
    transition: opacity .28s var(--feder), transform .28s var(--feder);

    &.da { opacity: 1; transform: none; }

    & > .ic { flex: none; inline-size: 1.6rem; block-size: 1.6rem; stroke-width: 2;
              color: var(--akzent); }
    & .toast-text { flex: 1; min-inline-size: 0; overflow-wrap: anywhere; padding-block: var(--a2); }
}

.toast.gut     { border-inline-start-color: var(--gut);    & > .ic { color: var(--gut); } }
.toast.warnung { border-inline-start-color: var(--warn);   & > .ic { color: var(--warn); } }
.toast.fehler  { border-inline-start-color: var(--fehler); & > .ic { color: var(--fehler); } }

.toast-weg {
    flex: none; display: grid; place-items: center; inline-size: 44px; block-size: 44px;
    border: 0; background: none; cursor: pointer; border-radius: var(--r-rund);
    color: var(--tinte-still); line-height: 0;
    transition: color var(--tempo), background var(--tempo);
    & .ic { inline-size: 1.2rem; block-size: 1.2rem; stroke-width: 2.2; }
    &:hover { color: var(--tinte); background: var(--glas-dezent); }
    &:focus-visible { outline: 2px solid var(--akzent); outline-offset: 1px; }
}

@media (max-width: 34rem) {
    .toasts {
        inset-block-start: var(--a3);
        inset-inline: var(--a3);
        inline-size: auto;
    }
    .toast { transform: translateY(-1rem) scale(.98); }
}

@media (prefers-reduced-motion: reduce) {
    .toast { transition: opacity .01ms; transform: none; }
}

/* --------------------------------------------------------------------------
   Kamerawahl im Simulator

   Vorher steckte in der Pille eine zweite Pille, weil die Beschreibung ein
   eigener span war. Jetzt eine ruhige Karte pro Kamera mit Kennung und
   Maschine untereinander - das ist auch am Handy noch lesbar.
   ----------------------------------------------------------------------- */

.kamera-wahl {
    display: grid; gap: var(--a2);
    grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
}

.kamera-karte {
    /* position: relative ist Pflicht: Das Feld liegt in einem fieldset.feld, und
       dort gilt `input { inline-size: 100% }`. Ohne Bezugspunkt hing das
       unsichtbare Radio in der Seite und schob sie 475 px nach rechts hinaus
       (gemessen 21.09.2026). Klein und im Fluss statt versteckt, damit es
       anklickbar und für Vorleseprogramme erreichbar bleibt. */
    position: relative; display: block;
    & input { position: absolute; inset: 0; inline-size: 1px; block-size: 1px;
              opacity: 0; pointer-events: none; }

    & .kamera-inhalt {
        display: flex; align-items: center; gap: var(--a3);
        min-block-size: 3.4rem; padding: var(--a3) var(--a4);
        border: 1px solid var(--rand); border-radius: var(--r-s);
        background: var(--glas-dezent);
        cursor: pointer; transition: border-color var(--tempo),
                                     background var(--tempo), box-shadow var(--tempo);
    }
    & .ic { flex: none; inline-size: 1.35rem; block-size: 1.35rem; color: var(--tinte-still); }
    & .kamera-text { display: grid; gap: 1px; min-inline-size: 0; }
    & b { font-weight: 620; letter-spacing: -.01em;
          font-family: var(--schrift-fest); font-size: .9em; }
    & small { color: var(--tinte-leise); font-size: var(--s-mini);
              overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

    &:hover .kamera-inhalt { border-color: var(--tinte-still); }

    & input:checked + .kamera-inhalt {
        border-color: var(--akzent); background: var(--akzent-duft);
        box-shadow: inset 0 0 0 1px var(--akzent);
        & .ic { color: var(--akzent); }
    }
    & input:focus-visible + .kamera-inhalt {
        outline: 2px solid var(--akzent); outline-offset: 2px;
    }
}

/* --------------------------------------------------------------------------
   Handy: sechs Menüpunkte passen nicht mehr nebeneinander

   Die untere Leiste hat feste Fächer, und beim sechsten Eintrag wurde der Text
   abgeschnitten. Auf schmalen Schirmen darf sie deshalb waagrecht rollen, mit
   einer Mindestbreite je Eintrag, damit nichts mehr zerquetscht wird.
   ----------------------------------------------------------------------- */

@media (max-width: 30rem) {
    .nav.nav-unten {
        overflow-x: auto; scrollbar-width: none;
        &::-webkit-scrollbar { display: none; }
        & a { flex: 0 0 auto; min-inline-size: 4.6rem; padding-inline: var(--a2); }
    }
}

/* Der Seiteninhalt braucht unten Platz für die Leiste, sonst liegt sie auf der
   letzten Karte. Der Wert wächst mit --nav mit. */
@media (max-width: 47.999rem) {
    .huelle { padding-block-end: calc(var(--nav) + var(--a4)); }
    .seiten-fuss { padding-block-end: var(--a3); }
}

/* --------------------------------------------------------------------------
   Schieberegler auf der Anmeldeseite

   Statt eines Bilderrätsels. Bedienbar mit Maus, Finger und Tastatur - niemand
   muss Ampeln auf Fotos anklicken. Er hält einfache Skripte auf; die eigentliche
   Sperre gegen Durchprobieren steht auf der Serverseite.
   ----------------------------------------------------------------------- */

.schieber {
    --anteil: 0%;
    user-select: none; -webkit-user-select: none;
}

.schieber-bahn {
    position: relative; overflow: hidden;
    block-size: 3rem; border-radius: var(--r-rund);
    background: var(--glas-dezent);
    border: 1px solid var(--rand);
    box-shadow: inset 0 1px 2px oklch(40% .05 285/.06);
    display: flex; align-items: center;
    touch-action: none;

    /* Gefüllter Teil hinter dem Griff, wächst mit */
    &::before {
        content: ""; position: absolute; inset-block: 0; inset-inline-start: 0;
        inline-size: var(--anteil);
        background: linear-gradient(90deg,
            color-mix(in oklab, var(--akzent) 18%, transparent),
            color-mix(in oklab, var(--akzent) 32%, transparent));
        transition: background var(--tempo);
    }
}

.schieber-text {
    position: absolute; inset-inline: 3.4rem var(--a4);
    text-align: center;
    font-size: var(--s-klein); font-weight: 550;
    color: var(--tinte-still); letter-spacing: -.005em;
    pointer-events: none;
    transition: opacity var(--tempo);
}

.schieber-griff {
    position: relative; z-index: 1;
    /* index.php setzt nur noch --griff-x auf dem Schieber. Ohne diese Zeile
       bleibt der Griff beim Ziehen stehen. */
    transform: translateX(var(--griff-x, 0px));
    inline-size: 2.6rem; block-size: 2.6rem; margin-inline-start: 4px;
    flex: none; border: 0; border-radius: var(--r-rund);
    background: var(--hell); box-shadow: var(--tiefe-1);
    color: var(--akzent); cursor: grab;
    display: grid; place-items: center;
    transition: box-shadow var(--tempo), background var(--tempo);
    & .ic { inline-size: 1.25rem; block-size: 1.25rem; stroke-width: 2.2; }
    &:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; }
}

.schieber.zieht .schieber-griff { cursor: grabbing; box-shadow: var(--tiefe-2); }
.schieber.zieht .schieber-text  { opacity: .4; }

.schieber.fertig {
    & .schieber-bahn { border-color: var(--gut); }
    & .schieber-bahn::before { background: var(--gut-duft); inline-size: 100%; }
    & .schieber-griff { background: var(--gut); color: var(--hell); cursor: default; }
    & .schieber-text { opacity: 0; }
}

/* Ohne Bewegung schnappt der Griff ohne Übergang, das ist gewollt: Ein
   ruckelnder Regler wäre schlimmer als ein springender. */
@media (prefers-reduced-motion: reduce) {
    .schieber-griff, .schieber-bahn::before { transition: none; }
}

/* --------------------------------------------------------------------------
   Meldungsliste

   Eine Zeile je Meldung, das Zeichen trägt die Schwere. Bewusst keine Karten:
   Es sind viele, und sie werden überflogen, nicht einzeln gelesen.
   ----------------------------------------------------------------------- */

.meldungs-liste { list-style: none; padding: 0; margin: 0; display: grid; gap: 1px; }

.meldungs-zeile {
    display: flex; align-items: flex-start; gap: var(--a3);
    padding: var(--a3) var(--a4);
    background: var(--glas-satt);
    backdrop-filter: var(--unschaerfe); -webkit-backdrop-filter: var(--unschaerfe);
    border: 1px solid var(--rand); border-block-end: 0;

    &:first-child { border-start-start-radius: var(--r); border-start-end-radius: var(--r); }
    &:last-child  { border-block-end: 1px solid var(--rand);
                    border-end-start-radius: var(--r); border-end-end-radius: var(--r); }

    & > .ic { flex: none; inline-size: 1.15rem; block-size: 1.15rem;
              margin-block-start: .15em; color: var(--tinte-still); }
    &.warnung > .ic { color: var(--warn); }
    &.fehler  > .ic { color: var(--fehler); }

    & .meldungs-text { min-inline-size: 0; overflow-wrap: anywhere; flex: 1 1 auto; }
    & a { color: var(--tinte-leise); }
}

.leer-hinweis {
    display: flex; align-items: center; gap: var(--a4);
    & > .ic { flex: none; inline-size: 1.6rem; block-size: 1.6rem; color: var(--gut); }
}

/* --------------------------------------------------------------------------
   Fotos von Fehllesungen: Vorschau rechts in der Zeile, gross im eigenen
   Fenster. Das Vorschaubild ist ein Knopf mit 44 px Mindesthöhe für den Finger.
   ----------------------------------------------------------------------- */
.fehlfoto-knopf {
    flex: none; margin-inline-start: auto; padding: 0; cursor: zoom-in;
    border: 1px solid var(--rand); border-radius: var(--r-s); overflow: hidden;
    background: var(--hell); box-shadow: var(--tiefe-1);
    & img { display: block; inline-size: 6rem; block-size: 4.5rem; min-block-size: 44px;
            object-fit: cover; }
    &:hover { box-shadow: var(--tiefe-2); }
}
.fehl-loeschen { flex: none; }
/* Am Handy: Foto und Löschknopf unter den Text, sonst bricht er neben dem Foto
   nach jedem Wort um. Ohne Foto passt der Knopf daneben. */
@media (max-width: 33rem) {
    .meldungs-zeile:has(.fehlfoto-knopf) {
        flex-wrap: wrap;
        & .meldungs-text { flex-basis: calc(100% - 1.15rem - var(--a3)); }
        & .fehlfoto-knopf { margin-inline-start: calc(1.15rem + var(--a3)); }
        & .fehl-loeschen { margin-inline-start: auto; align-self: flex-end; }
    }
}
.fotofenster {
    inline-size: min(100% - 2rem, 64rem); margin: auto; padding: var(--a3);
    border: 1px solid var(--rand); border-radius: var(--r-l);
    background: var(--glas-satt); box-shadow: var(--tiefe-3); color: var(--tinte);
    & img { display: block; inline-size: 100%; max-block-size: calc(100dvb - 9rem);
            object-fit: contain; border-radius: var(--r); background: #000; }
    & .knopfreihe { justify-content: flex-end; margin-block-start: var(--a3); }
}
.fotofenster::backdrop { background: oklch(20% .02 285 / .55); }

/* Einstellungen, Fotos von Fehllesungen: je Kamera eine Zeile mit zwei
   Schaltern. Auf schmalen Bildschirmen stehen die Schalter unter dem Namen. */
.fehlfoto-kamera {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--a2) var(--a5);
    padding-block: var(--a2); border-block-end: 1px solid var(--rand-innen, var(--rand));
}
.fehlfoto-kamera-name { flex: 1 1 12rem; min-inline-size: 0; }

/* Mitarbeiter: der Ausweis als QR-Code, gleich in der Liste und beim Bearbeiten.
   Im Browser gezeichnet wie auf der gedruckten Karte (design/qrcode.js). */
.ausweis-qr {
    flex: none; display: block; inline-size: 5rem; aspect-ratio: 1;
    background: #fff; border: 1px solid var(--rand); border-radius: var(--r-s);
    & svg { display: block; inline-size: 100%; block-size: 100%; }
    &.klein { inline-size: 2.75rem; border-radius: 6px; }
}
.ausweis-zeile { display: flex; align-items: center; gap: var(--a4); }

/* Mitarbeiter: Suche und Filter über der Liste, das Ausweis-Häkchen je Zeile. */
.ma-stand { margin-block-end: var(--a3); }
.ma-filter {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--a3);
    margin-block-end: var(--a4);
    & .ma-suchfeld { flex: 1 1 16rem; }
    & .knopf.aktiv { background: var(--akzent); color: var(--hell); }
}
.ma-liste {
    & .schalter { min-block-size: 44px; gap: var(--a2); font-size: var(--s-klein); font-weight: 600; }
    & .ma-ohne-ausweis { flex: none; display: grid; place-items: center; inline-size: 2.75rem; }
}
/* Schmal: Knöpfe unter den Namen, sonst bleibt für den Namen kein Platz. */
@media (max-width: 33rem) {
    .ma-liste li > div { flex: 1 1 0; }       /* Name neben QR, nicht darunter */
}

/* Listenzeilen mit Knöpfen (Maschinen, Kameras, Mitarbeiter): Auf schmalen
   Schirmen gehören Stift und Mülleimer unter den Text. Daneben bleibt zu wenig
   Platz, und sie stapelten sich übereinander (17.09.2026, Mirko). Eine Regel
   für alle Listen, damit es überall gleich aussieht. */
@media (max-width: 33rem) {
    .liste li:has(> .rechts .knopf.symbol) {
        flex-wrap: wrap;
        & > .rechts { flex: 1 0 100%; justify-content: flex-end; }
    }
}
/* Zahl mit Einheit: Das Feld ist schmal und rechtsbuendig, die Einheit steht
   daneben, nicht darunter (Projektdoku: "Die Einheit gehört an die Zahl"). */
/* Ein Dateifeld bringt seinen eigenen Knopf mit, ihm bekommt die Feldhoehe
   nicht. Der Knopf darin kommt vom Browser und sah als einziges Bedienelement
   fremd aus; er bekommt dieselbe Form wie unsere Knoepfe. Die Worte daneben
   ("keine Datei ausgewaehlt") setzt der Browser in seiner Sprache, daran kommt
   man nicht heran. */
input[type="file"] { min-block-size: 0; padding: var(--a2) var(--a3); cursor: pointer; }
input[type="file"]::file-selector-button {
    margin-inline-end: var(--a3); cursor: pointer;
    min-block-size: 36px; padding-inline: var(--a4);
    border: 1px solid var(--rand-satt); border-radius: var(--r-rund);
    background: var(--hell); color: var(--tinte);
    font: 570 var(--s-klein)/1 var(--schrift);
    transition: background var(--tempo), border-color var(--tempo);
}
input[type="file"]:hover::file-selector-button { border-color: var(--akzent); color: var(--akzent); }

.feld-zahl { display: flex; align-items: center; gap: var(--a2); }
.feld-zahl input[type="number"] { inline-size: 6rem; text-align: end;
                                  font-variant-numeric: tabular-nums; }
.feld-zahl small { color: var(--tinte-leise); }

/* Felder, die aus Zentro kommen: sichtbar nicht zum Tippen. */
.feld input[readonly] { background: transparent; border-style: dashed; color: var(--tinte-leise); }

/* Gruppen der Mitarbeiterliste: Zugang und Ausweis zuerst. */
.ma-gruppe + .ma-gruppe { margin-block-start: var(--a5); }
.ma-gruppe-titel { font-size: var(--s-klein); font-weight: 650; text-transform: uppercase;
                   letter-spacing: .06em; color: var(--tinte-leise); margin-block-end: var(--a2); }
.ma-fakt { display: flex; align-items: center; gap: .4em;
           & .ic { inline-size: .95em; block-size: .95em; flex: none; } }
/* .abschneiden setzt white-space: nowrap, die Ellipse greift auf einem
   Flex-Container aber nicht - der Text wurde am Handy hart geklippt
   ("Ausweis noch nie an einer Maschine g"). Schmal darf er umbrechen. */
@media (max-width: 33rem) {
    .ma-fakt { white-space: normal; }
}

/* --------------------------------------------------------------------------
   Monitor: Bewegung. Zahlen zählen verwischt hoch, Namen fliegen Buchstabe
   für Buchstabe herein, Funken bei An- und Abmeldung und Meilensteinen.
   ----------------------------------------------------------------------- */
.m-mess-eintrag { position: relative; }
.w-zahl .wirbelt, .m-gesamt b.wirbelt { display: inline-block; animation: zahl-wirbel .9s var(--feder); }
@keyframes zahl-wirbel {
    0%   { transform: translateY(-30%) rotateX(75deg) scale(1.25); opacity: .3; }
    55%  { transform: translateY(4%) rotateX(-12deg) scale(1.08); opacity: 1; }
    100% { filter: none; transform: none; }
}
/* "+1" steigt über der Zahl auf und verblasst */
.m-plus {
    position: absolute; inset-block-start: -.2em; inset-inline-end: -.2em;
    font: 800 clamp(1rem, .8rem + 1.2cqi, 1.9rem)/1 var(--schrift);
    color: var(--farbe, var(--akzent)); pointer-events: none;
    text-shadow: 0 2px 10px color-mix(in oklab, var(--farbe, var(--akzent)) 45%, transparent);
    animation: plus-steigt 1.7s cubic-bezier(.2, .8, .3, 1) forwards;
}
@keyframes plus-steigt {
    0%   { opacity: 0; transform: translateY(.4em) scale(.5); }
    18%  { opacity: 1; transform: translateY(-.3em) scale(1.25); }
    100% { opacity: 0; transform: translateY(-2.2em) scale(1); }
}
/* Buchstaben und Ziffern: aus der Unschärfe herein, gestaffelt */
.wort { display: inline-block; white-space: nowrap; }
.name-neu .b, .m-person-name .b {
    display: inline-block;
    animation: buchstabe-rein .6s var(--feder) backwards;
    animation-delay: calc(var(--i) * 32ms + 120ms);
}
@keyframes buchstabe-rein {
    from { opacity: 0; transform: translateY(.6em) rotate(-10deg) scale(1.3); }
}
.w-teil-name .b {
    display: inline-block;
    animation: name-fliegt .55s var(--feder) backwards;
    animation-delay: calc(var(--i) * 28ms + 60ms);
}
@keyframes name-fliegt {
    from { opacity: 0; transform: translateX(-.35em) scale(.9); }
}
/* Das Zeichen im Kreis springt einmal, bei FERTIG mit Funken (siehe funken()). */
.w-stand-kreis { animation: kreis-hopp .7s var(--feder) backwards; position: relative; }
@keyframes kreis-hopp { 0% { transform: scale(.4); opacity: 0; } 65% { transform: scale(1.12); } }
.w-teil-id .z, .m-meilenstein .z {
    display: inline-block;
    animation: ziffer-rollt .7s var(--feder) backwards;
    animation-delay: calc(var(--i) * 55ms + 150ms);
}
@keyframes ziffer-rollt {
    from { opacity: 0; transform: translateY(-.7em) rotateX(90deg); }
}
.w-teil-id { perspective: 500px; }

/* Funken: von der Mitte des Elternteils nach aussen */
/* Weiss statt Maschinenfarbe: Seit die Karte vollflaechig farbig ist, lag der
   Ring in derselben Farbe auf derselben Farbe und war unsichtbar - dieselbe
   Korrektur wie bei den Funken (22.09.2026). */
.m-person-rund { position: relative; animation: ring-puls-gross 1.6s ease-out 2; }
@keyframes ring-puls-gross {
    0%   { box-shadow: 0 0 0 0 oklch(100% 0 0 / .5); }
    100% { box-shadow: 0 0 0 1.6em transparent; }
}
.m-funken { position: absolute; inset: 0; pointer-events: none; }
.m-funken > span {
    position: absolute; inset-block-start: 50%; inset-inline-start: 50%;
    inline-size: .45em; block-size: .45em; margin: -.225em; border-radius: 50%;
    /* Weiss: Die Einblendungen sind jetzt vollflaechig farbig, in der
       Maschinenfarbe waeren die Funken unsichtbar. */
    background: var(--hell);
    opacity: 0;
    animation: funke 1.1s cubic-bezier(.15, .75, .3, 1) forwards;
    animation-delay: var(--v, 0ms);
}
.m-funken > span:nth-child(3n) { background: #fbbf24; }
/* Im Zustandskreis funkt es in der Zustandsfarbe, nicht in der Maschinenfarbe. */
.w-stand-kreis .m-funken > span:not(:nth-child(3n)) { background: var(--zustand); }
.m-funken > span:nth-child(3n+1) { inline-size: .3em; block-size: .3em; }
@keyframes funke {
    0%   { opacity: 1; transform: rotate(var(--w)) translateX(0) scale(1); }
    100% { opacity: 0; transform: rotate(var(--w)) translateX(var(--weit, 4em)) scale(.3); }
}

/* Meilenstein: gross über dem Feld, dann wieder weg (.m-feld ist der Bezug,
   position: relative steht oben im Block) */
.m-meilenstein {
    position: absolute; inset: 0; z-index: 5; display: grid; place-content: center;
    justify-items: center; gap: .2em; text-align: center; pointer-events: none;
    /* Vollflaechig in der Maschinenfarbe, Schrift weiss - dieselbe Sprache wie
       die An- und Abmeldung (Mirko, 22.09.2026: alle Einblendungen dieser Art
       gleich). Vorher ein fast weisser Schleier mit der Zahl in der
       Maschinenfarbe. Kein backdrop-filter mehr: Bei deckendem Grund bringt er
       nichts und kostet den Fire TV Stick Rechenzeit. */
    background: var(--farbe, var(--akzent)); color: var(--hell);
    border-radius: var(--r-l);
    animation: meilenstein 4.2s ease forwards;
    & b { font-size: clamp(3rem, 2rem + 8cqi, 9rem); font-weight: 800; line-height: 1;
          letter-spacing: -.05em; color: var(--hell); perspective: 600px; }
    & > span:last-child { font-size: clamp(1rem, .8rem + 1.2cqi, 2rem); font-weight: 650;
                          color: var(--hell); opacity: .85; }
    & .m-funken { font-size: clamp(1.4rem, 1rem + 2cqi, 3rem); }
}
@keyframes meilenstein {
    0% { opacity: 0; transform: scale(.85); } 10% { opacity: 1; transform: none; }
    85% { opacity: 1; } 100% { opacity: 0; transform: scale(1.04); }
}

@media (prefers-reduced-motion: reduce) {
    .w-zahl .wirbelt, .m-gesamt b.wirbelt, .name-neu .b, .m-person-name .b,
    .m-meilenstein .z, .m-person-rund, .w-teil-name .b, .w-teil-id .z,
    .w-stand-kreis { animation: none; }
    .m-plus, .m-funken, .m-meilenstein { display: none; }
}

/* Farbwahl: Farbfeld und Wert nebeneinander */
.farbwahl { display: flex; gap: var(--a2); align-items: center;
    & input[type=color] { flex: none; inline-size: 3rem; min-block-size: 44px; padding: 2px; cursor: pointer; }
    & input:not([type=color]) { font-family: ui-monospace, monospace; } }

@keyframes fuellung-haelt { 50% { opacity: .45; } }
@media (prefers-reduced-motion: reduce) {
    .m-reiter-knopf.dran::before { transition: none; animation: none; }
}

/* ------------------------------------------------------------------ Notizen
   Fehler, Wünsche und Fragen aus der Werkstatt (notizen.php). Bewusst ohne
   eigene Farben: Art und Stand tragen die vorhandenen Abzeichen, die Karten
   sind dieselben wie überall. */

/* Die Zahl der offenen Notizen am Symbol im Kopf. Sitzt am Knopf, nicht daneben,
   damit sie beim Umbruch nicht wegwandert. */
.kopf-zahl {
    position: absolute; inset-block-start: -.3rem; inset-inline-end: -.3rem;
    min-inline-size: 1.15rem; padding-inline: .3rem;
    border-radius: var(--r-rund);
    background: var(--fehler); color: var(--hell);
    font-size: .7rem; font-weight: 640; line-height: 1.2rem; text-align: center;
}
.buehne-knopf:has(.kopf-zahl) { position: relative; overflow: visible; }

/* Sieht aus wie eine Aufforderung, nicht wie eine Listenzeile: Akzentfarbe und
   volle Klickflaeche. Vorher war die Karte von einer Notiz in der Liste kaum zu
   unterscheiden (Mirko, 23.09.2026). */
.notiz-neu > summary {
    display: flex; align-items: center; gap: var(--a2); cursor: pointer;
    min-block-size: 44px; color: var(--akzent); font-weight: 600;
    & .ic { inline-size: 1.15rem; block-size: 1.15rem; color: var(--akzent);
            transition: transform var(--tempo); }
    &:hover { color: var(--akzent-hell); }
}
.notiz-neu[open] > summary { color: var(--tinte); margin-block-end: var(--a2); }
/* Aufgeklappt wird aus dem Plus ein Kreuz - das Zeichen dreht sich sichtbar. */
.notiz-neu[open] > summary .ic { transform: rotate(45deg); }
.notiz-arten {
    display: flex; flex-wrap: wrap; gap: var(--a2);
    border: 0; padding: 0; margin: 0;
    & legend { padding: 0; margin-block-end: var(--a1); }
}
.notiz-art-wahl {
    & input { position: absolute; opacity: 0; pointer-events: none; }
    & span {
        display: inline-flex; align-items: center; gap: var(--a2);
        min-block-size: 44px; padding-inline: var(--a4);
        border: 1px solid var(--rand); border-radius: var(--r-rund);
        background: var(--glas-dezent); color: var(--tinte-leise); cursor: pointer;
    }
    & .ic { inline-size: 1.1rem; block-size: 1.1rem; }
    & input:checked + span { background: var(--akzent); border-color: var(--akzent); color: var(--hell); }
    & input:focus-visible + span { outline: 2px solid var(--akzent); outline-offset: 2px; }
}

/* minmax(0, 1fr): Ohne die Begrenzung waechst die Spalte auf die Mindestbreite
   des Titels (white-space: nowrap) und zieht am Handy die ganze Seite auf
   480 px auseinander. */
.notiz-liste { list-style: none; margin: 0; padding: 0; display: grid;
               grid-template-columns: minmax(0, 1fr); gap: var(--a2); }
.notiz-zeile > a {
    display: flex; align-items: center; gap: var(--a3);
    padding: var(--a3) var(--a4);
    background: var(--glas); border: 1px solid var(--rand); border-radius: var(--r);
    color: inherit; text-decoration: none;
    &:hover { background: var(--glas-satt); }
    & > .ic { flex: none; color: var(--tinte-leise); }
    & > .abzeichen { flex: none; }
}
.notiz-zeile-text { flex: 1 1 auto; min-inline-size: 0;
    & strong { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}
/* Erledigtes bleibt lesbar, tritt aber zurück. Ausgegraut wäre falsch, das sieht
   nach einem Fehler aus - hier ist es nur nicht mehr dringend. */
.notiz-zeile.erledigt > a { background: transparent; }
.notiz-zeile.erledigt .notiz-zeile-text strong { font-weight: 500; color: var(--tinte-leise); }

.notiz-kopf { display: flex; flex-wrap: wrap; align-items: center; gap: var(--a2); }
.notiz-titel { margin-block: var(--a2) 0; }
.notiz-text { margin-block: var(--a3) 0; white-space: pre-line; }
.notiz-foto img { max-inline-size: min(100%, 30rem); block-size: auto; border-radius: var(--r-s); }

.notiz-kommentare { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--a2); }
.notiz-kommentar {
    position: relative; padding: var(--a3) var(--a4);
    & p { margin-block: var(--a1) 0; white-space: pre-line; }
}
.notiz-kommentar-weg { position: absolute; inset-block-start: var(--a2); inset-inline-end: var(--a2); }
