/*
 * Designsystem des Content Workers.
 *
 * Ausgelagert aus layouts/base.html.twig, damit interne Seiten und die
 * Tester-Ansicht dieselbe Sprache teilen — und damit der Browser die Datei
 * einmal cacht statt sie in jede Seite einzubetten (zuvor 69 KB pro Aufruf).
 *
 * Seitenspezifisches CSS gehoert weiterhin in den styles-Block der Views.
 */

:root {
    font-family: "Inter", system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
    --fg: #141414;
    --fg-muted: rgba(20, 20, 20, 0.65);
    --bg: #fffbf4;
    --accent: #4f01ff;
    --accent-hover: #3a00cc;
    --brand: #c5f403;
    --card-bg: rgba(255, 255, 255, 0.95);
    --shadow: 0 12px 26px rgba(20, 20, 20, 0.08);
    /* Job Hub und seine Toasts teilen sich diese Breite — sonst laufen sie auseinander. */
    --job-hub-width: min(400px, 92vw);
}

* { box-sizing: border-box; }

body { margin: 0; color: var(--fg); background: var(--bg); min-height: 100vh; font-family: inherit; }

a { color: var(--fg); font-weight: 500; text-decoration: none; transition: color 120ms ease; }
a:hover, a:focus { color: var(--accent); }

.topbar {
    position: sticky;
    top: 0;
    z-index: 100;
    backdrop-filter: blur(14px);
    background: rgba(255, 251, 244, 0.9);
    border-bottom: 1px solid rgba(20, 20, 20, 0.06);
}

.topbar__inner { width: 100%; display: flex; align-items: center; justify-content: space-between; padding: 1rem 4vw; }

/* Sticky-Kopfbereiche (Review-Filter, Audio-Check-Filter): Der Block klebt bei
   top:5.5rem, die Topbar ist aber niedriger — durch die Lücke dazwischen scrollte
   bisher die Liste sichtbar durch. Der Deckstreifen zieht die Blockfläche in
   Seitenhintergrundfarbe nach oben und schließt sie. Er reicht bewusst weit unter
   die Topbar hinein; die liegt mit z-index 100 darüber und verdeckt den Rest,
   sodass die exakte Topbar-Höhe egal ist (auch bei umbrechender Navigation). */
/* Sticky-Kopfbereiche (Review-Filter, Audio-Check-Filter) docken exakt an der
   Unterkante der Topbar an. Ein fester Wert erzeugte dort eine Lücke, durch die
   die Liste sichtbar durchscrollte; --topbar-h wird per JS aus der echten
   Topbar-Höhe gesetzt (siehe unten), das -1px verhindert Sub-Pixel-Spalten. */
.sticky-head { top: calc(var(--topbar-h, 4.25rem) - 1px); }

.topbar__brand {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    font-weight: 700;
    font-size: 1.1rem;
    color: var(--fg);
}

.topbar__brand img {
    width: 1.5rem;
    height: 1.5rem;
    display: block;
}

.topbar__nav { display: flex; align-items: center; gap: 0.75rem; }

.topbar__nav-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.55rem 1.1rem;
    border-radius: 18px;
    font-weight: 600;
    font-size: 0.95rem;
    color: var(--fg);
    background: rgba(255, 255, 255, 0.8);
    border: 1px solid rgba(20, 20, 20, 0.08);
    transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}

.topbar__nav-link:hover,
.topbar__nav-link:focus {
    background: #fff;
    border-color: rgba(20, 20, 20, 0.16);
}


.form-actions {
    display: flex;
    justify-content: flex-start;
    gap: 0.75rem;
    margin-top: 1.25rem;
    align-items: center;
}

.form-actions--end {
    justify-content: flex-end;
}

.form-actions--split {
    justify-content: space-between;
}

.link--danger {
    color: #dc2626;
    font-weight: 400;
}

.link--danger:hover,
.link--danger:focus {
    color: #b91c1c;
}

.topbar__user-menu { position: relative; }
button.topbar__nav-link { box-shadow: none; transform: none; }
button.topbar__nav-link:hover, button.topbar__nav-link:focus { box-shadow: none; transform: none; color: var(--accent); }

.topbar__user-dropdown {
    position: absolute; top: calc(100% + 10px); right: 0;
    background: #fff; border: 1px solid rgba(20,20,20,0.1); border-radius: 16px;
    box-shadow: 0 8px 28px rgba(0,0,0,0.13); padding: 1rem 1.1rem;
    min-width: 230px; z-index: 200; white-space: nowrap;
    opacity: 0; pointer-events: none; transform: translateY(-6px);
    transition: opacity 140ms ease, transform 140ms ease;
}
.topbar__user-menu:hover .topbar__user-dropdown,
.topbar__user-menu:focus-within .topbar__user-dropdown {
    opacity: 1; pointer-events: auto; transform: translateY(0);
}
.topbar__user-info { padding-bottom: 0.75rem; margin-bottom: 0.75rem; border-bottom: 1px solid rgba(20,20,20,0.08); }
.topbar__user-email { font-size: 0.88rem; font-weight: 600; color: var(--fg); display: block; }
.topbar__user-role { font-size: 0.75rem; color: var(--fg-muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 0.2rem; display: block; }
.topbar__user-logout {
    display: flex; align-items: center; gap: 0.4rem; width: 100%;
    font-size: 0.88rem; font-weight: 500; color: #b91c1c !important;
    padding: 0.45rem 0.5rem; border-radius: 8px; transition: background 120ms ease;
}
.topbar__user-logout:hover { background: rgba(185,28,28,0.07); color: #b91c1c !important; }

.shell { width: 100%; padding: 2.5rem 4vw 5rem; }

.page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1.75rem;
}

.page-header__title {
    margin: 0;
    font-size: 1.9rem;
    font-weight: 600;
}

.page-header__subtitle {
    margin: 0.4rem 0 0;
    color: var(--fg-muted);
    font-size: 0.95rem;
}

@media (max-width: 720px) {
    .page-header {
        flex-direction: column;
    }
}

.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1.75rem; }

.dashboard-stats { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.card--table-sm { padding: 1.25rem; gap: 1rem; }
.text-truncate { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: inline-block; }

.card { background: var(--card-bg); border-radius: 22px; padding: 1.75rem; border: 1px solid rgba(20, 20, 20, 0.04); box-shadow: var(--shadow); display: flex; flex-direction: column; gap: 1.1rem; min-width: 0; }

.card h3 {
    margin: 0 0 0.75rem;
    font-size: 1.2rem;
    font-weight: 600;
    color: var(--accent);
}

.card__header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1rem;
    flex-wrap: wrap;
}

.card__header h2 {
    margin: 0;
    font-size: 1.45rem;
    font-weight: 600;
}

.card__header p {
    margin: 0.25rem 0 0;
}

.card--workflow {
    margin-bottom: 2rem;
    padding: 1.5rem;
    gap: 0.9rem;
}

.card--status {
    gap: 1.3rem;
}

.dashboard-team-progress {
    display: flex;
    flex-direction: column;
    gap: 1.4rem;
    margin-bottom: 2rem;
}
.team-progress-list {
    display:flex;
    flex-direction:column;
    gap:1.2rem;
}
.card--info { margin-top: 2rem; }
.team-progress {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
    padding: 1.6rem 1.75rem;
}
.team-progress__header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 0.75rem;
}
.team-progress__headline {
    margin: 0;
    font-size: 1.2rem;
    font-weight: 600;
    color: var(--accent);
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.6rem;
}
.team-progress__vce-stamp {
    font-size: 0.72rem;
    color: var(--fg-muted);
    white-space: nowrap;
    align-self: flex-start;
    padding-top: 0.2rem;
}
.team-progress__vce-stamp--empty {
    opacity: 0.5;
}
.team-progress__chip {
    display: inline-flex;
    align-items: center;
    padding: 0.2rem 0.6rem;
    border-radius: 999px;
    background: rgba(79, 1, 255, 0.12);
    color: var(--accent);
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    font-family: "JetBrains Mono", "SFMono-Regular", "Menlo", "Consolas", "Liberation Mono", monospace;
}
.team-progress__workflows {
    display: grid;
    gap: 1.1rem;
}
@media (min-width: 720px) {
    .team-progress__workflows {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}
.team-progress__section {
    display:flex;
    flex-direction:column;
    gap:0.8rem;
    padding:1rem 1.1rem;
    border-radius:16px;
    border:1px solid rgba(255, 255, 255, 0.4);
    background: rgba(255, 255, 255, 0.55);
    box-shadow: inset 0 0 0 1px rgba(20, 20, 20, 0.02);
}
.team-progress__section--review {
    background: rgba(34, 197, 94, 0.14);
    border-color: rgba(22, 101, 52, 0.18);
}
.team-progress__section--studio {
    background: rgba(124, 58, 237, 0.14);
    border-color: rgba(91, 33, 182, 0.22);
}
.team-progress__section-header {
    display:flex;
    justify-content:space-between;
    align-items:center;
    gap:0.6rem;
}
.team-progress__section-header h3 {
    margin:0;
    font-size:0.9rem;
    text-transform:uppercase;
    letter-spacing:0.04em;
    color: var(--fg-muted);
}
.team-progress__section-percent {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--fg);
}
.team-progress__metric {
    margin: 0;
    font-size: 1.15rem;
    font-weight: 600;
    color: var(--fg);
}
.team-progress__meta {
    margin: 0;
    color: var(--fg-muted);
    font-size: 0.95rem;
}
.team-progress__bar {
    position: relative;
    height: 0.55rem;
    background: rgba(255, 255, 255, 0.45);
    border-radius: 999px;
    overflow: hidden;
}
.team-progress__bar-fill {
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    width: 0%;
    border-radius: 999px;
    background: var(--accent);
    transition: width 220ms ease;
}
.team-progress__section--review .team-progress__bar { background: rgba(34, 197, 94, 0.22); }
.team-progress__section--review .team-progress__bar-fill { background: #16a34a; }
.team-progress__section--studio .team-progress__bar { background: rgba(124, 58, 237, 0.22); }
.team-progress__section--studio .team-progress__bar-fill { background: #7c3aed; }
.team-progress__percent {
    margin: 0;
    font-size: 0.9rem;
    color: var(--fg-muted);
}
.team-progress__lang-list {
    display:flex;
    flex-direction:column;
    gap:0.75rem;
}
.team-progress__lang {
    display:flex;
    flex-direction:column;
    gap:0.55rem;
    padding:0.75rem 0.85rem;
    border-radius:12px;
    background: rgba(255, 255, 255, 0.72);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.35);
}
.team-progress__lang-head {
    display:flex;
    justify-content:space-between;
    align-items:center;
    gap:0.6rem;
}
.team-progress__lang-label {
    font-weight:600;
    font-size:0.95rem;
    letter-spacing:0.05em;
    text-transform:uppercase;
    color: var(--fg);
}
.team-progress__lang-percent {
    font-weight:600;
    font-size:0.9rem;
    color: var(--fg);
}
.team-progress__lang-metric {
    margin:0;
    font-size:0.95rem;
    color: var(--fg);
}
.team-progress__lang-meta {
    margin:0;
    font-size:0.85rem;
    color: var(--fg-muted);
}
.team-progress__lang-empty {
    margin:0;
    font-size:0.9rem;
    color: var(--fg-muted);
    font-style: italic;
}
.team-progress__actions {
    margin-top: 1rem;
    display:flex;
    gap:0.5rem;
    flex-wrap:wrap;
}
.team-progress__actions .btn { align-self:flex-start; }

.status-grid {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.status-grid__panel {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}


.variant-status { display:grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap:0.6rem; }
.variant-status__card { background: rgba(79, 1, 255, 0.04); border: 1px solid rgba(20, 20, 20, 0.06); border-radius: 14px; padding: 0.65rem 0.9rem; display:flex; flex-direction:column; gap:0.35rem; }
.variant-status__header { display:flex; flex-wrap:wrap; gap:0.35rem; font-weight:700; font-size:0.82rem; color: var(--accent); align-items:baseline; margin-bottom:0.1rem; }
.variant-status__header span { color: var(--fg-muted); font-weight:500; }
.variant-status__lang { display:flex; align-items:flex-start; gap:0.5rem; }
.variant-status__lang-label { font-weight:700; font-size:0.72rem; text-transform:uppercase; color: var(--fg-muted); min-width:40px; flex-shrink:0; padding-top:0.1rem; }
.variant-status__stack { display:flex; flex:1; flex-direction:column; gap:0.25rem; }
.variant-status__labels { display:flex; flex-wrap:wrap; gap:0.35rem; }
.vs-label { font-size:0.72rem; font-weight:600; white-space:nowrap; }
.vs-label--need_mt  { color: #b91c1c; }
.vs-label--mt_ready { color: #1d4ed8; }
.vs-label--stale    { color: #b45309; }
.vs-label--reviewed { color: #166534; }
.vs-label--completed { color: #166534; }
.vs-label--completed_with_errors { color: #92400e; }
.vs-label--failed   { color: #991b1b; }
.vs-label--default  { color: var(--fg-muted); }
.variant-status__bar { display:flex; width:100%; border-radius:999px; overflow:hidden; height:5px; gap:1px; }
.vs-seg { height:100%; border-radius:999px; min-width:2px; }
.vs-seg--need_mt  { background: rgba(248, 113, 113, 0.7); }
.vs-seg--mt_ready { background: rgba(96, 165, 250, 0.75); }
.vs-seg--stale    { background: rgba(251, 191, 36, 0.7); }
.vs-seg--reviewed { background: rgba(34, 197, 94, 0.65); }
.vs-seg--completed { background: rgba(34, 197, 94, 0.65); }
.vs-seg--completed_with_errors { background: rgba(251, 191, 36, 0.7); }
.vs-seg--failed   { background: rgba(220, 38, 38, 0.65); }
.vs-seg--default  { background: rgba(79, 1, 255, 0.2); }

.status-badge { display:inline-flex; align-items:center; justify-content:center; padding:0.15rem 0.55rem; border-radius:999px; font-size:0.78rem; font-weight:600; letter-spacing:0.01em; white-space:nowrap; }
.status-badge--need_mt { background: rgba(248, 113, 113, 0.2); color: #b91c1c; }
.status-badge--mt_ready { background: rgba(96, 165, 250, 0.24); color: #1d4ed8; }
.status-badge--stale { background: rgba(251, 191, 36, 0.24); color: #b45309; }
.status-badge--reviewed { background: rgba(34, 197, 94, 0.22); color: #166534; }
.status-badge--completed { background: rgba(34, 197, 94, 0.22); color: #166534; }
.status-badge--completed_with_errors { background: rgba(251, 191, 36, 0.24); color: #92400e; }
.status-badge--failed { background: rgba(220, 38, 38, 0.18); color: #991b1b; }
.status-badge--default { background: rgba(79, 1, 255, 0.12); color: var(--accent); }
/* Grau fuer „noch nichts passiert" — ein Entwurf ist kein Zustand, der Farbe
   verdient. Damit werden die drei Laufzustaende unterscheidbar: grau =
   Entwurf, gruen = laeuft, lila = abgeschlossen. */
.status-badge--muted { background: rgba(20, 20, 20, 0.08); color: var(--fg-muted); }

@media (max-width: 700px) {
    .variant-status { grid-template-columns: 1fr; }
}

.card--form { max-width: 960px; width: 100%; margin: 0 auto; gap: 1.2rem; }

table { width: 100%; border-collapse: collapse; font-size: 0.95rem; overflow: hidden; border-radius: 16px; }
th, td { padding: 0.8rem 1rem; border-bottom: 1px solid rgba(20, 20, 20, 0.08); text-align: left; }
th { background: rgba(79, 1, 255, 0.08); color: var(--accent); font-weight: 600; }

.table-sm { width: 100%; border-collapse: collapse; font-size: 0.85rem; table-layout: fixed; }
.table-sm th, .table-sm td { padding: 0.6rem 0.75rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-bottom: 1px solid rgba(20, 20, 20, 0.08); text-align: left; }
.table-sm td { font-size: 0.82rem; }
.table-sm th { background: rgba(79, 1, 255, 0.12); color: var(--accent); font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.03em; }
.table-sm--runs th:nth-child(1), .table-sm--runs td:nth-child(1) { width: 34%; }
.table-sm--runs th:nth-child(2), .table-sm--runs td:nth-child(2) { width: 18%; }
.table-sm--runs th:nth-child(3), .table-sm--runs td:nth-child(3) { width: 12%; }
.table-sm--runs th:nth-child(4), .table-sm--runs td:nth-child(4) { width: 10%; }
.table-sm--runs th:nth-child(5), .table-sm--runs td:nth-child(5) { width: 10%; }
.table-sm--runs th:nth-child(6), .table-sm--runs td:nth-child(6) { width: 16%; }
.table-sm--errors th:nth-child(1), .table-sm--errors td:nth-child(1) { width: 46%; }
.table-sm--errors th:nth-child(2), .table-sm--errors td:nth-child(2) { width: 18%; }
.table-sm--errors th:nth-child(3), .table-sm--errors td:nth-child(3) { width: 18%; }
.table-sm--errors th:nth-child(4), .table-sm--errors td:nth-child(4) { width: 18%; }

.tag {
    display: inline-block;
    padding: 0.15rem 0.75rem;
    border-radius: 18px;
    font-size: 0.72rem;
    font-weight: 600;
    background: rgba(79, 1, 255, 0.12);
    color: var(--accent);
}

button, .button, .btn { white-space: nowrap; display: inline-flex; align-items: center; justify-content: center; gap: 0.35rem; padding: 0.8rem 1.5rem; border-radius: 18px; border: none; font-size: 0.96rem; font-weight: 600; cursor: pointer; color: #fff; background: var(--accent); box-shadow: 0 8px 18px rgba(79, 1, 255, 0.18); transition: transform 120ms ease, box-shadow 120ms ease; text-decoration: none; }
button.is-loading, input.is-loading { opacity: 0.65; cursor: default; pointer-events: none; }
.btn--sm { padding: 0.55rem 1.1rem; font-size: 0.85rem; }

/*
 * Quadratischer Icon-Knopf — eine Handlung, ein Symbol, 32 px.
 *
 * Entstanden im Studio-Workflow (Löschen, Notiz, im Review öffnen) und von dort
 * hierher gezogen, als die Sprachtest-Verwaltung dieselben Knöpfe brauchte: Als
 * zweite Kopie im Template wäre schon die nächste Anpassung nur an einer der
 * beiden Stellen angekommen.
 *
 * Ohne Schatten und ohne Anheben beim Überfahren — anders als `.btn`. Diese
 * Knöpfe stehen zu mehreren am Zeilenende; drei schwebende Pillen dort ziehen
 * mehr Aufmerksamkeit auf sich als die Zeile, um die es geht.
 *
 * Ein Symbol allein trägt keinen Namen: Jeder Icon-Knopf braucht `aria-label`
 * (für Vorlesesoftware) UND `data-tip` (für alle anderen).
 */
.icon-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; padding: 0;
    border-radius: 8px; border: 1px solid rgba(15, 23, 42, 0.13);
    background: transparent; color: var(--fg-muted);
    cursor: pointer; box-shadow: none; transform: none; text-decoration: none;
}
.icon-btn:hover, .icon-btn:focus {
    background: rgba(15, 23, 42, 0.06); color: var(--fg);
    border-color: rgba(15, 23, 42, 0.22); box-shadow: none; transform: none;
}
.icon-btn:disabled {
    opacity: .28; cursor: not-allowed;
    border-color: rgba(15, 23, 42, 0.1); color: var(--fg-muted); background: transparent;
}
/* Zurücknehmbar, aber folgenreich: rot getönt, nicht rot gefüllt. Gefüllt stünde
   die gefährlichste Handlung optisch vor den harmlosen daneben. */
.icon-btn--danger { border-color: rgba(220, 38, 38, 0.2); color: #991b1b; background: rgba(220, 38, 38, 0.05); }
.icon-btn--danger:hover:not(:disabled), .icon-btn--danger:focus:not(:disabled) {
    background: rgba(220, 38, 38, 0.12); border-color: rgba(220, 38, 38, 0.35);
    box-shadow: none; transform: none;
}
/* Trägt etwas Eigenes (eine Notiz liegt vor) — Gelb als Hinweis, nicht als Warnung. */
.icon-btn--note { border-color: rgba(250, 204, 21, 0.60); color: #92400e; background: rgba(254, 243, 199, 0.5); }
.icon-btn--note:hover, .icon-btn--note:focus {
    background: rgba(254, 243, 199, 0.9); border-color: rgba(250, 204, 21, 0.7);
    box-shadow: none; transform: none;
}

/*
 * Tooltip: was dieses Symbol tut, in einem Satz.
 *
 * Statt `title`: Das native Sprechblasenfenster erscheint erst nach rund einer
 * Sekunde, lässt sich nicht gestalten, bricht lange Sätze nicht um und
 * erscheint auf Tastaturfokus gar nicht. Genau hier trägt es aber die ganze
 * Erklärung — bei einem Symbol ohne Beschriftung ist der Satz die Beschriftung.
 *
 * WICHTIG: `title` am selben Element weglassen, sonst stehen beide da.
 *
 * Reines CSS, `pointer-events: none` — die Blase fängt nie einen Klick ab.
 * Kurze Verzögerung, damit sie beim Überstreichen einer Knopfreihe nicht
 * aufblitzt.
 */
[data-tip] { position: relative; }
[data-tip]::after {
    content: attr(data-tip);
    position: absolute; bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%);
    z-index: 40;
    width: max-content; max-width: 16rem;
    padding: .45rem .6rem;
    border-radius: 8px;
    background: rgba(17, 17, 17, 0.94); color: #fff;
    font-size: .78rem; font-weight: 400; line-height: 1.45; text-align: left;
    white-space: normal; text-transform: none; letter-spacing: 0;
    opacity: 0; visibility: hidden;
    transition: opacity 120ms ease 350ms, visibility 0s linear 470ms;
    pointer-events: none;
}
[data-tip]:hover::after, [data-tip]:focus-visible::after {
    opacity: 1; visibility: visible;
    transition: opacity 120ms ease 350ms, visibility 0s linear 350ms;
}
/* Am rechten Rand rechtsbündig: mittig zentriert ragte die Blase dort aus dem
   Panel und wurde abgeschnitten. */
[data-tip][data-tip-align="right"]::after { left: auto; right: 0; transform: none; }
[data-tip][data-tip-align="left"]::after { left: 0; right: auto; transform: none; }
/* Unterhalb, wo über dem Element kein Platz ist (erste Zeile einer Liste). */
[data-tip][data-tip-place="below"]::after { bottom: auto; top: calc(100% + 8px); }

/*
 * Dieselbe Blase, aber am <body> statt am Knopf — die Fassung, die tatsächlich
 * zu sehen ist, sobald JavaScript läuft (layouts/base.html.twig setzt dafür
 * `has-js-tips`).
 *
 * WARUM überhaupt zwei Fassungen: Ein `::after` lebt im Kasten seines
 * Elements. Steht das in einem Scroll-Container — und die Sprachtabelle steht
 * in `overflow-x: auto` —, wird die Blase abgeschnitten, und zwar OBEN wie
 * unten: Sobald eine Achse scrollt, verliert die andere `visible`. Kein
 * `z-index` kommt dagegen an; Beschneiden ist keine Frage der Reihenfolge.
 *
 * Die JS-Fassung hängt am <body>, liegt also in keinem Container, und ihre
 * Position wird beim Überfahren gerechnet (inklusive Anstoßen an den
 * Fensterrand). Die CSS-Fassung bleibt als Rückfall für Seiten ohne
 * JavaScript — dort ist eine gelegentlich beschnittene Erklärung besser als
 * gar keine.
 */
.tip-bubble {
    position: fixed; top: 0; left: 0; z-index: 200;
    max-width: 18rem;
    padding: .45rem .6rem;
    border-radius: 8px;
    background: rgba(17, 17, 17, 0.94); color: #fff;
    font-size: .78rem; font-weight: 400; line-height: 1.45; text-align: left;
    opacity: 0; visibility: hidden;
    transition: opacity 120ms ease;
    pointer-events: none;
}
.tip-bubble--on { opacity: 1; visibility: visible; }
html.has-js-tips [data-tip]::after { content: none; }

/*
 * Ein <a class="btn"> ist ein Knopf, kein Link.
 *
 * Die globale Regel `a:hover { color: var(--accent) }` hat höhere Spezifität
 * (0,1,1) als `.btn` (0,1,0) und färbte deshalb beim Überfahren die Schrift
 * violett — auf dem violetten Knopf also unsichtbar. Betraf jeden farbigen
 * Knopf, der als Link ausgezeichnet ist (u. a. "Neues Set" unter /admin/sets).
 */
a.btn:hover, a.btn:focus,
a.button:hover, a.button:focus { color: #fff; }

a.btn--ghost:hover, a.btn--ghost:focus,
a.button.button-outline:hover, a.button.button-outline:focus { color: var(--accent); }

/*
 * Vertikaler Rhythmus zwischen den Blöcken einer Seite.
 *
 * `.card` bringt selbst kein margin mit, und `.shell` keinen Fluss-Abstand —
 * aufeinanderfolgende Blöcke standen deshalb bündig aneinander. Erfasst sind
 * alle Kombinationen aus Karte und Kartengitter; INNERHALB eines Gitters
 * greift die Regel nicht, weil das seinen eigenen gap mitbringt.
 *
 * `form` zählt mit: Ein Formular ist im Seitenfluss nur die durchsichtige
 * Hülle seiner Karten (Build-Check-Vorschau: die „Create check"-Karte steckt
 * im <form>) — ohne die Zeile klebte sie bündig an der Coverage-Karte.
 */
.card + .card,
.card + .stats-grid,
.card + form,
form + .card,
.stats-grid + .card,
.stats-grid + .stats-grid { margin-top: 1.5rem; }

/* Gap-Container neutralisieren den Karten-Rhythmus: Sie bringen ihren
   eigenen Abstand mit, und der Geschwister-Margin drückt sonst jede Karte
   außer der ersten nach unten — im Dashboard-Grid stand die erste Karte
   dadurch sichtbar höher als der Rest. JEDES neue Grid mit .card-Kindern
   muss hier in die Liste. */
.stats-grid > .card + .card,
.dashboard-stats > .card + .card,
.set-grid > .card + .card { margin-top: 0; }

/*
 * Block INNERHALB einer Karte.
 *
 * Eine Karte in einer Karte stapelt Ebenen, die es nicht gibt: zweimal Weiß,
 * zweimal Schatten, zweimal großer Radius. Verschachtelte Blöcke bekommen
 * deshalb nur einen feinen grauen Rand — dasselbe Muster, das die
 * Set-Hub-Seiten bisher per Inline-Style benutzen.
 *
 * Standard ist NEUTRAL. Die getönten Varianten sind Ausnahmen für einzelne
 * hervorgehobene Blöcke; flächig eingesetzt färben sie die ganze Seite ein.
 */
.panel {
    border: 1px solid rgba(20, 20, 20, 0.10);
    border-radius: 14px;
    padding: 1.1rem 1.25rem;
}

/* Zurückhaltend gefüllt — für Zahlen und Hinweise, die zusammengehören. */
.panel--muted { background: rgba(20, 20, 20, 0.03); border-color: transparent; }

/* Hervorgehoben — derzeit ungenutzt und mit Bedacht NICHT wieder einsetzen:
   Seit 26.08.2026 trägt die violette Tönung eine Bedeutung (Anzeigefläche,
   siehe .set-hub-head). Ein getöntes Panel mitten auf der weißen Arbeitsfläche
   widerspräche dem. Wer hier etwas hervorheben will, nimmt .panel--muted. */
.panel--accent { background: rgba(79, 1, 255, 0.04); border-color: rgba(79, 1, 255, 0.12); }
.panel > :first-child { margin-top: 0; }
.panel > :last-child { margin-bottom: 0; }
.panel h3 { margin: 0 0 0.6rem; font-size: 1.05rem; font-weight: 600; color: var(--accent); }
/* margin-bottom: Der Kopfblock (Titel + Intro) braucht Luft zum Inhalt darunter —
   ohne sie klebt der Introtext an der ersten Tabellen- oder Befundzeile. */
.panel__header { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; flex-wrap: wrap; margin-bottom: 1rem; }

/* Gleicher vertikaler Rhythmus wie zwischen Karten. */
.panel + .panel,
.panel + .stats-grid,
.stats-grid + .panel,
.panel + form > .panel:first-child,
form + .panel { margin-top: 1.25rem; }
.stats-grid > .panel + .panel { margin-top: 0; }

/*
 * Filterleiste eines Reiters: sitzt zwischen Reiterleiste und Inhalt und
 * ändert, welchen Ausschnitt der Reiter zeigt.
 *
 * Bewusst NICHT wie die Reiter gestaltet. Zwei Reihen gleich aussehender
 * Pillen — eine für Navigation, eine für Filterung — waren nicht
 * unterscheidbar: Man sah nicht, was womit umgeschaltet wird.
 */
.filterbar {
    display: flex; align-items: center; gap: .75rem; flex-wrap: wrap;
    padding: .6rem .9rem; margin: 0 0 1.5rem;
    border-radius: 12px;
    background: rgba(20, 20, 20, 0.035);
    border: 1px solid rgba(20, 20, 20, 0.06);
    font-size: .9rem;
}
.filterbar__label { font-weight: 600; color: var(--fg-muted); }
.filterbar__hint { font-size: .85rem; }
.filterbar__actions { margin-left: auto; }

/*
 * Karten-Korpus (cards/_body.html.twig) — geteilt zwischen Tester-Ansicht und
 * Admin-Kartenansicht, damit beide DIESELBE Karte zeigen. Auf Lesebreite
 * begrenzt: Die Tester-Spalte ist 44rem, und die Redaktion soll exakt das
 * Bild der Tester sehen, auch auf einem breiten Monitor.
 */
/*
 * Kriterienbriefing über der Karte — in beiden Ansichten gleich. Je Kriterium
 * ein Satz statt nur eines Etiketts: „Naturalness" allein verrät nicht, dass
 * auch Tempo und eine zu laute Atmo darunterfallen, und genau daran blieben
 * zwei Muttersprachlerinnen hängen, ohne es melden zu können.
 *
 * EIN Raster für die ganze Box statt eines je Zeile: Spalten richten sich nur
 * innerhalb desselben Rasters aus. Vorher war jede Zeile ihr eigener
 * Flex-/Grid-Container, deshalb begannen die Sätze je nach Pillenbreite an
 * verschiedenen Stellen.
 */
/*
 * Worauf zu achten ist — Text auf der Fläche, kein getönter Kasten.
 *
 * Als Box stand sie ÜBER der Überschrift und trug einen eigenen Hintergrund:
 * Man las erst die Prüfkriterien und erfuhr danach, wofür. Jetzt steht sie
 * unter Überschrift und Kontext, wo man sie braucht, und tritt optisch
 * zurück — sie ist Beiwerk zur Karte, nicht selbst eine.
 *
 * Das Raster bleibt: Zwei Spalten, an der Grundlinie ausgerichtet. Genau
 * darum ging es beim letzten Mal — saubere Spalten, keine Tabelle.
 */
.criteria {
    display: grid;
    grid-template-columns: max-content 1fr;
    align-items: baseline;
    gap: .35rem .6rem;
    margin: .9rem 0 1.5rem;
}
/* display:contents löst den Absatz als Kasten auf — seine beiden Kinder werden
   direkte Zellen des EINEN Rasters. Genau das richtet die Spalten aus. */
.criteria__item { display: contents; }
.criteria__note { grid-column: 1 / -1; margin: 0; }
.criteria__hint { color: var(--fg-muted); font-size: .92rem; }

@media (max-width: 30rem) {
    /* Auf dem Telefon reicht die Breite für zwei Spalten nicht. */
    .criteria { grid-template-columns: 1fr; gap: .1rem; }
    .criteria__item { display: block; margin: 0 0 .5rem; }
}

/* Kartenart und ihre Erklärung gehören zusammen — kein Abstand dazwischen. */
/* Die Erklärung gehört zur Überschrift, darf ihr aber nicht ankleben. */
.cardhead { margin: 0 0 .75rem; }
.cardhead__hint { margin: 0 0 .5rem; color: var(--fg-muted); line-height: 1.6; }
.cardhead__hint:last-of-type { margin-bottom: 1.75rem; }

.cardbody { max-width: 44rem; }
/* Panels des Korpus tragen ihre Füllung selbst: Im Admin liegen sie auf der
   weißen Arbeitsfläche (unsichtbar), im Tester-Frontend auf dem Seitengrund. */
.cardbody .panel { background: var(--card-bg, #fff); }
/*
 * Urteil je Aufnahme: zwei Daumen an der Zeile, die sie meinen.
 *
 * Sie ersetzen das frühere Urteil über die ganze Karte samt der Rückfrage
 * „welche Aufnahme?" mit bis zu 24 Nummern-Chips — die Frage beantwortet der
 * Ort des Daumens von selbst. Groß genug für den Finger (40 px), weil die
 * Ansicht auch auf dem Tablet bedient wird.
 */
.judge { display: inline-flex; align-items: center; gap: .4rem; flex: 0 0 auto; }
.judge__form { display: contents; }
.thumb {
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; padding: 0;
    border-radius: 12px; border: 1px solid rgba(20, 20, 20, 0.18);
    background: #fff; box-shadow: none; cursor: pointer;
}
.thumb--up { color: #1f7a4d; }
.thumb--down { color: #b4401f; }
.thumb:hover, .thumb:focus { box-shadow: none; filter: none; }
.thumb--up:hover, .thumb--up:focus { border-color: #1f7a4d; background: rgba(31, 122, 77, 0.08); color: #1f7a4d; }
.thumb--down:hover, .thumb--down:focus { border-color: #b4401f; background: rgba(180, 64, 31, 0.08); color: #b4401f; }
.thumb--up.thumb--on { background: #1f7a4d; border-color: #1f7a4d; color: #fff; }
.thumb--down.thumb--on { background: #b4401f; border-color: #b4401f; color: #fff; }

/*
 * Der Notizschritt öffnet sich UNTER seiner Zeile, nicht als Dialog: Wer
 * beschreibt, was an einer Aufnahme falsch ist, will beim Tippen nochmal
 * hineinhören — ein Dialog legt sich über genau den Player, den er braucht.
 */
.note {
    margin: .75rem 0 .25rem; padding: .75rem 0 .25rem 1rem;
    border-left: 3px solid #b4401f;
    display: flex; flex-direction: column; gap: .5rem;
}
/*
 * `display:flex` schlägt das `display:none`, das der Browser dem
 * hidden-Attribut gibt — eine Klassenregel gewinnt gegen das
 * UA-Stylesheet. Ohne diese Zeile stünde JEDER Notizschritt offen.
 */
.note[hidden] { display: none; }
.note__lead { margin: 0; font-weight: 600; }
.note__hint { margin: 0; font-size: .9rem; }
.note__cats { display: flex; gap: .4rem; flex-wrap: wrap; margin: 0; }
.note__cats label { cursor: pointer; gap: .35rem; }
.note textarea {
    width: 100%; padding: .5rem .7rem; border-radius: 10px; font: inherit;
    border: 1px solid rgba(20, 20, 20, .15);
}
.note__save { display: flex; gap: .6rem; margin: 0; }

/* Titel links, Sprachumschalter rechts — er gilt für die ganze Karte. */
/* Der Abstand zur Erklärung sitzt an der ZEILE, nicht an der Überschrift:
   Sie steckt seit dem Sprachumschalter in dieser Zeile, und ein margin auf
   ihr würde von der Zeile eingeschlossen statt darunter zu wirken. */
.cardhead__row {
    display: flex; align-items: center; justify-content: space-between;
    gap: 1rem; flex-wrap: wrap; margin: 0 0 .75rem;
}
.cardhead__row .cardhead { margin: 0; }

/*
 * Abschnittskarte: violett = Anzeige, weiß = Arbeitsfläche. Auf ihr ist
 * nichts zu tun, deshalb keine erhobene Karte und kein Schatten.
 */
.sectioncard {
    background: rgba(79, 1, 255, 0.04);
    border: 1px solid rgba(79, 1, 255, 0.12);
    border-radius: 18px; padding: 2.5rem 1.5rem; text-align: center;
    margin: 0 0 1.5rem;
}
.sectioncard:last-child { margin-bottom: 0; }

/*
 * Dropdown-Filter — die Form, die Studio und Review-Workflow schon benutzen.
 *
 * Aus dem Style-Block von review/index.html.twig hierher gehoben, damit beide
 * Listen dieselbe Leiste tragen statt zweier Kopien, die auseinanderlaufen.
 * Seitenspezifisches (Suche, Sortierknopf, Statistikleiste) bleibt dort.
 */
.review-filters { display: flex; flex-direction: column; gap: 1rem; }
.review-filters__row { display: flex; flex-wrap: wrap; gap: 1rem; align-items: flex-end; }
.review-filters__group {
    display: flex; flex-direction: column; gap: 0.35rem;
    flex: 0 0 auto; min-width: 0; transition: color 0.2s ease;
}
.review-filters__group label {
    font-weight: 700; font-size: 0.75rem; color: var(--fg-muted);
    text-transform: uppercase; letter-spacing: 0.08em; transition: color 0.2s ease;
}
.review-filters select {
    width: 100%; min-width: 0;
    border-radius: 18px; border: 1px solid rgba(79, 1, 255, 0.2);
    padding: 0.75rem 1rem; padding-right: 3rem; font-size: 1rem;
    background-color: #fff; min-height: 3rem; line-height: 1.25;
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
/* Ein gesetzter Filter faerbt sein Etikett — sonst uebersieht man, dass die
   Liste gefiltert ist, und haelt sie fuer vollstaendig. */
.review-filters__group.is-active label { color: var(--accent); }
.review-filters__group.is-active select {
    border-color: rgba(79, 1, 255, 0.42);
    box-shadow: 0 0 0 2px rgba(79, 1, 255, 0.12);
}

/* Frei stehende Filterleiste — im Review-Workflow liefert die umgebende
   .review-top den Abstand ueber ihren gap; hier steht die Leiste direkt auf
   der Tabelle und braucht ihn selbst. */
.review-filters--cards { margin-bottom: 1.25rem; }


/* Das vollstaendige Pruefprotokoll, aufklappbar. Zusammengeklappt ist es eine
   Zeile; aufgeklappt die Tabelle, die auch die Vorschau vor dem Einfrieren
   zeigt. */
.checklog { margin: .25rem 0 0; }
.checklog__toggle {
    cursor: pointer; display: inline-block; padding: .2rem 0;
    font-size: .88rem; font-weight: 600; color: var(--accent);
}
.checklog__toggle:hover { text-decoration: underline; }
.checklog[open] .checklog__toggle { margin-bottom: .5rem; }
/* Die Tabelle hat vier Spalten, die Notizen sind lang — auf schmalen Fenstern
   scrollt sie im Block statt ueber den Rahmen zu ragen. */
.checklog__table { overflow-x: auto; }
.checklog__table .table { font-size: .88rem; }
.checklog__findings { margin: .2rem 0 0; padding-left: 1.1rem; }
.checklog__findings li { margin: .1rem 0; }

/* Wer die Karte beurteilt hat — eine Zeile, kein Block. Die Befunde stehen an
   ihrer Aufnahme im Korpus; hier bleibt nur, was zu keiner Aufnahme gehoert. */
.judgedby { margin: 0 0 1rem; font-size: .92rem; }
/* Etikett auf eigener Zeile, die Namen darunter: Nebeneinander gesetzt wanderte
   die Zeile bei zwei langen Adressen ueber die halbe Breite, und das Etikett
   klebte am ersten Namen, als gehoere es nur zu ihm. */
.judgedby__label {
    display: block; margin-bottom: .3rem;
    font-size: .75rem; font-weight: 700; color: var(--fg-muted);
    text-transform: uppercase; letter-spacing: .08em;
}
.judgedby__list { display: flex; align-items: center; gap: .3rem .7rem; flex-wrap: wrap; }
.judgedby__who { display: inline-flex; align-items: center; gap: .4rem; }

/*
 * Entscheidung der Redaktion zu EINER Stelle.
 *
 * Eine Zeile je Aufnahme, nicht je Befundzeile: Repariert wird die Aufnahme,
 * einmal, egal wie viele Tester sie gemeldet haben. Die linke Kante trägt den
 * Stand — offen faellt auf, entschieden tritt zurueck.
 */
.decision {
    border-left: 3px solid rgba(20, 20, 20, 0.12);
    padding: .7rem 0 .7rem .9rem;
    margin: .6rem 0 0;
}
.decision--open { border-left-color: #b4401f; }
.decision--fixed { border-left-color: #2f7d3a; }
.decision--accepted { border-left-color: rgba(20, 20, 20, 0.25); }

.decision__head { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin-bottom: .35rem; }
/* Der Stand rechts: Er beantwortet die Frage, die man beim Ueberfliegen hat. */
.decision__state { margin-left: auto; }
.decision__note { margin: .2rem 0; font-size: .92rem; }
.decision__done { margin: .35rem 0 .5rem; font-size: .88rem; }

.decision__form { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin: .5rem 0 0; }
/* Das Feld nimmt den Rest der Zeile — eine Begruendung ist ein Satz, kein Wort. */
.decision__why { flex: 1 1 18rem; min-width: 0; font-size: .9rem; padding: .45rem .6rem; }
.decision__buttons { display: flex; gap: .4rem; flex: 0 0 auto; }

/*
 * Vergleichsfrage am Kartenende: Sie gilt der ganzen Karte, nicht einer
 * Aufnahme. Deshalb KEIN Player und keine Nummer — und ein eigener Rahmen,
 * damit sie sich nicht wie eine weitere Zeile liest.
 */
.cardquestion {
    margin: 1.25rem 0 0;
    padding: 1.1rem 1.25rem;
    background: var(--card-bg);
    border: 1px solid rgba(20, 20, 20, 0.10);
    border-radius: 14px;
}
.cardquestion__row {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: .75rem 1.25rem; flex-wrap: wrap;
}
.cardquestion__lead { margin: 0 0 .3rem; font-size: 1.02rem; font-weight: 600; }
.cardquestion__hint { margin: 0; color: var(--fg-muted); font-size: .9rem; line-height: 1.55; max-width: 34rem; }
/* Der Daumen bleibt oben bündig mit der Frage, auch wenn der Hinweis umbricht. */
.cardquestion__row .judge { flex: 0 0 auto; }

/*
 * Fortschritts-Zifferblatt (App\Services\Review\ProgressDial).
 * Grau, nicht im Akzent: Der Kreis orientiert, er fordert nicht — der Akzent
 * gehört dem Weiter-Knopf und den Kriterien-Etiketten.
 */
.dial { display: inline-block; flex: 0 0 auto; vertical-align: -.15em; }
.dial__off { fill: rgba(20, 20, 20, 0.14); }
.dial__on { fill: rgba(20, 20, 20, 0.55); }

/*
 * Liste der offenen Karten auf der Abschlussseite.
 *
 * Nummer und Stand rahmen den Namen ein: Nach der Nummer sucht man, wenn man
 * zurückwill, am Stand liest man ab, wie viel noch fehlt. Die ganze Zeile ist
 * das Ziel — ein Wortlink wäre auf dem Tablet zu klein.
 */
/* Die violette Abschnittskarte traegt den Kopf, die weisse Karte die Arbeit —
   dazwischen Luft, damit es zwei Bloecke bleiben und nicht ein langer wird. */
.openlist__head { margin: 0 0 .25rem; font-size: 1.15rem; }

.openlist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.openlist__item { border-top: 1px solid rgba(20, 20, 20, 0.08); }
.openlist__item:first-child { border-top: none; }
.openlist__link {
    display: flex; align-items: baseline; gap: .5rem 1rem; flex-wrap: wrap;
    padding: .7rem .25rem; font-weight: 400;
}
.openlist__link:hover, .openlist__link:focus { background: rgba(79, 1, 255, 0.05); }
.openlist__no { font-variant-numeric: tabular-nums; color: var(--fg-muted); font-size: .9rem; min-width: 5.5rem; }
.openlist__title { font-weight: 600; }
.openlist__state { margin-left: auto; color: var(--fg-muted); font-size: .88rem; }

/* Nur für Hilfstechnik — der Daumen trägt sonst nur ein Symbol. */
.visually-hidden {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/*
 * Quelltext-Umschalter: leiser Textknopf am Kopf der Karte, rechtsbündig.
 *
 * Als gefüllte Pille stand er in einer Reihe mit den Play-Knöpfen und dem
 * Urteil, obwohl er nur eine Hilfestellung ist — und zwischen zwei Boxen
 * (Quiz-Frage / Antworten) gehörte er sichtbar zu keiner. Die globale
 * `button`-Regel färbt und polstert alles, deshalb wird hier jede ihrer
 * Eigenschaften ausdrücklich zurückgenommen.
 */
.cardbody__source { display: flex; justify-content: flex-end; margin: 0 0 .5rem; }
.cardbody__source button {
    background: none; border: 0; box-shadow: none;
    padding: .2rem 0; border-radius: 0;
    color: var(--fg-muted); font-size: .85rem; font-weight: 500;
    text-decoration: underline; text-underline-offset: 3px;
    text-decoration-color: rgba(20, 20, 20, 0.25);
}
.cardbody__source button:hover,
.cardbody__source button:focus {
    color: var(--accent); text-decoration-color: currentColor; box-shadow: none;
}

.cardlines { display: flex; flex-direction: column; }
/*
 * Die Rinne links ist IMMER da, auch ohne Markierung — sie ist der Platz,
 * an dem die laufende Zeile gekennzeichnet wird. Reserviert man sie erst
 * beim Abspielen, rückt der ganze Zeileninhalt bei jedem Wechsel um ihre
 * Breite hin und her, und bei durchlaufenden Karten wandert dieser Sprung
 * mit dem Ton nach unten.
 *
 * Rechts derselbe Abstand: Die Rinne allein ließ den Text aus der Mitte
 * nach rechts gedrängt aussehen — sichtbar wird sie nur an der laufenden
 * Zeile, ihr Platzbedarf aber an jeder.
 */
/* Wird eine Zeile ueber ihren Anker angesprungen — der Notnagel ohne
   JavaScript nach dem Speichern, in der Redaktionsansicht der Sprung auf eine
   Nummer —, legt der Browser sie buendig an die Fensteroberkante und damit
   unter die klebende Leiste. `scroll-margin-top` haelt deren Hoehe frei
   (--topbar-h, per JS gesetzt).
   Den Sprung nach dem Speichern loest das NICHT: Auf kurzen Karten reicht die
   Seitenhoehe nicht, um die Zeile nach oben zu holen, und der Browser scrollt
   bis zum Anschlag. Dafuer bringt die Umleitung die Scrollposition zurueck
   (tester/layout.html.twig). */
.cardline { position: relative; border-top: 1px solid rgba(20, 20, 20, 0.08); padding: .9rem .75rem;
    scroll-margin-top: calc(var(--topbar-h, 0px) + 1.25rem); }
.cardline:first-child { border-top: none; padding-top: 0; }
.cardline:last-child { padding-bottom: 0; }
.cardline__head { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.cardline__no { color: var(--fg-muted); font-variant-numeric: tabular-nums; font-size: .9rem; }
.cardline__speaker { color: var(--fg-muted); font-size: .85rem; }
.cardline__mark { margin-left: auto; display: flex; align-items: center; gap: .35rem; color: var(--fg-muted); font-size: .9rem; cursor: pointer; }

/*
 * Zeilen-Referenz und Sprung nach Review/Studio — nur in der Redaktion (im
 * Tester-Frontend sind die Adressen nicht gesetzt, siehe cards/_body).
 *
 * Leise: Sie steht unter der Kopfzeile, in kleiner Schrift, ohne Rahmen. Die
 * Bedienung dieser Karte sind Play und das Urteil; eine dritte Optik, die mit
 * ihnen konkurriert, hätte genau die Aufmerksamkeit abgezogen, die dem Hören
 * gilt. Die Kennung selbst als <code>, damit sie sich sauber kopieren lässt.
 */
.lineref { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin: .15rem 0 .35rem; font-size: .8rem; }
.lineref__id { color: var(--fg-muted); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; overflow-wrap: anywhere; }
.lineref a { color: var(--fg-muted); text-decoration: underline; text-underline-offset: 2px; }
.lineref a:hover { color: var(--fg); }

/*
 * Der Player klebt am oberen Rand SEINER Zeile: Beim Langformat bleibt er
 * sichtbar, während man den Text darunter mitliest; bei kurzen Zeilen wirkt
 * sticky schlicht nicht. --topbar-h setzt das interne Layout per JS, im
 * Tester-Frontend greift der Fallback 0.
 */
/*
 * Player UND Daumen in einer Zeile: Die Bewertung klebt damit mit ihrer
 * Aufnahme. Auf der 4400-Zeichen-Geschichte ist das der Unterschied zwischen
 * „immer erreichbar" und „ganz oben, längst aus dem Blick".
 */
.cardline__audio {
    position: sticky; top: calc(var(--topbar-h, 0px) + .4rem); z-index: 2;
    background: var(--card-bg, #fff); padding: .35rem 0;
    display: flex; align-items: center; gap: .6rem;
}
.cardline__audio audio { flex: 1 1 auto; min-width: 0; display: block; }
/*
 * Die Dauer für Aufnahmen, die nichts vorladen (Langformat, ~21 MB je
 * Fassung — siehe Cards\Recording). Der Player zeigt dort „0:00 / 0:00", bis
 * jemand auf Play drückt; wie lang eine Geschichte ist, muss man aber VORHER
 * wissen. `flex: 0 0 auto` und tabellarische Ziffern, damit die Zahl den
 * Player nicht staucht und zwischen den Zeilen nicht springt.
 */
.cardline__duration { flex: 0 0 auto; font-size: .85rem; font-variant-numeric: tabular-nums; }

/*
 * Laufende Zeile: Kante statt Fläche — violette FLÄCHEN sind der Anzeige
 * vorbehalten (siehe .set-hub-head).
 *
 * Als eigenes Element in der reservierten Rinne, nicht als `box-shadow:
 * inset` auf der Zeile: Der klebende Player darunter bringt einen eigenen
 * deckenden Hintergrund mit und strich die Innenkante auf seiner Höhe weg —
 * die Markierung sah aus, als hätte sie ein Loch. Das Element liegt über
 * dem Player (z-index 3 gegen dessen 2) und läuft deshalb ununterbrochen
 * durch die ganze Zeile.
 */
.cardline::before {
    content: ''; position: absolute; z-index: 3;
    left: 0; top: 0; bottom: 0; width: 3px; border-radius: 3px;
    background: transparent;
}
.cardline--playing::before { background: var(--accent); }

/*
 * pre-line: Absatzumbrüche der Texte MÜSSEN erhalten bleiben. Langformat-
 * Zeilen sind ganze Geschichten (Set 72250: 4400 Zeichen in einer Zeile) —
 * ohne die Regel kollabieren die Umbrüche zu Leerzeichen, und der Tester
 * bekommt eine unlesbare Textwand, während er zwanzig Minuten mitliest.
 * pre-line statt pre: Umbrüche bleiben, überflüssige Leerzeichen fallen weg,
 * und der Text bricht normal am Spaltenrand um.
 *
 * Die Regel sitzt auf den TEXTEN, nicht auf ihrem Container. Auf dem
 * Container zählte auch der Zeilenumbruch, der im Markup zwischen Ziel- und
 * Quelltext-Span steht: Beim Umschalten erschien die Quelle dadurch eine
 * Zeile tiefer und eingerückt statt an derselben Stelle.
 */
.cardline__text { font-size: 1.05rem; margin-top: .35rem; line-height: 1.6; }
.cardline__target,
.cardline__source { white-space: pre-line; }
/*
 * Quelltext ERSETZT den Zieltext — kein zweiter Text darunter, kein Sprung.
 * Kursiv, damit auf einen Blick klar ist, dass man gerade NICHT die zu
 * prüfende Sprache liest; graue Schrift allein war dafür zu leise.
 */
.cardline__source { display: none; color: var(--fg-muted); font-style: italic; }
.cardbody--source .cardline__source { display: inline; }
.cardbody--source .cardline__target { display: none; }

/*
 * Aktionsleiste am unteren Fensterrand — Urteil (Tester) bzw. Navigation
 * (Redaktion) stehen immer an derselben Stelle, egal wie lang die Karte ist.
 * position:sticky statt fixed: klebt am Viewport-Boden, bis das Seitenende
 * erreicht ist, respektiert die Containerbreite und überdeckt nichts.
 * env(safe-area-inset-bottom) hält Abstand zur Home-Geste auf dem Telefon.
 */
.actionbar {
    position: sticky; bottom: 0; z-index: 5;
    display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
    margin-top: 1.25rem;
    padding: .6rem 0 calc(.6rem + env(safe-area-inset-bottom));
    background: var(--card-bg, #fff);
    border-top: 1px solid rgba(20, 20, 20, 0.1);
}
.actionbar__spacer { flex: 1 1 auto; }

/*
 * Tastenlegende — dasselbe Muster wie in der Review-Oberfläche
 * (review/index.html.twig): eine eigene, leise Zeile mit <kbd>-Chips, statt
 * den Buchstaben im Knopftext zu unterstreichen. Die Unterstreichung sah aus
 * wie ein Link und verunstaltete die Beschriftung.
 */
.kb-hint {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
    gap: .4rem 1.1rem; margin: .6rem 0 0;
    font-size: .72rem; color: var(--fg-muted); letter-spacing: .02em;
}
.kb-hint__item { display: inline-flex; align-items: center; gap: 3px; }
/*
 * Urteils-Anzeige — geteilt zwischen Admin-Kartenansicht („Urteile der Tester")
 * und Tester-Frontend („Your answer"). Farbige Kante links statt Fläche:
 * beanstandet muss sich beim Überfliegen von „in Ordnung" unterscheiden, und
 * violette FLÄCHEN sind der Anzeige vorbehalten (siehe .set-hub-head).
 */
.verdicts { display: flex; flex-direction: column; gap: .9rem; }
.verdict { border-left: 3px solid rgba(20, 20, 20, 0.12); padding: .1rem 0 .1rem .9rem; }
.verdict--flag { border-left-color: #b4401f; }
.verdict--ok { border-left-color: #1f7a4d; }

.verdict__head { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.verdict__who { font-weight: 600; }
.verdict__when { color: var(--fg-muted); font-size: .85rem; margin-left: auto; }

.verdict__finding { margin-top: .5rem; }
/* Der Satz des Muttersprachlers ist der Inhalt — größer als die Etiketten
   darüber und nicht ausgegraut. */
.verdict__comment { margin: .3rem 0 0; font-size: 1.02rem; }
.verdict__line { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .8rem; color: var(--fg-muted); }
.verdict__empty { margin: .4rem 0 0; color: var(--fg-muted); font-size: .9rem; }

.kb-hint kbd {
    background: rgba(15, 23, 42, 0.07); border-radius: 4px;
    padding: .05rem .35rem; font-family: inherit; font-size: .7rem;
    color: var(--fg); line-height: 1.5;
}

/* Segmentierter Schalter: eine Auswahl, sichtbar zusammengehörig. */
.segmented {
    display: inline-flex; border-radius: 999px; overflow: hidden;
    border: 1px solid rgba(79, 1, 255, 0.22); background: #fff;
}
/* Die Regeln entstanden für Links; im Tester sind die Segmente <button>.
   Der breite Knopf-Stil weiter oben (Zeile ~501: Akzentgrund, 18px Radius,
   Schatten) griff dort mit — das inaktive Segment sah aus wie ein zweites
   aktives, und das aktive wie eine Pille IN der Pille. Die Rundung macht der
   Rahmen (`overflow: hidden`), nicht das Segment. */
.segmented__option {
    padding: .3rem .8rem; font-size: .88rem; font-weight: 500;
    font-family: inherit; background: none; border: 0; cursor: pointer;
    border-radius: 0; box-shadow: none;
    color: var(--fg); text-decoration: none; line-height: 1.6;
    border-right: 1px solid rgba(79, 1, 255, 0.14);
}
.segmented__option:hover, .segmented__option:focus {
    transform: none; box-shadow: none;
}
.segmented__option:last-child { border-right: none; }
.segmented__option:hover { background: rgba(79, 1, 255, 0.08); color: var(--accent); }
.segmented__option--active,
.segmented__option--active:hover { background: var(--accent); color: #fff; }

/*
 * Formulare sind reine Hüllen ohne eigene Optik: Der Abstand muss durch sie
 * hindurch, sonst klebt die erste Karte im Formular am Block darüber.
 */
.card + form > .card:first-child,
.stats-grid + form > .card:first-child,
form + .card { margin-top: 1.5rem; }

/* Schatten-Hover. Beim Fokus nur, wenn er von der Tastatur kommt (:focus-visible): Ein per
   Klick oder Skript fokussierter Knopf sah sonst schon aus wie überfahren, und die Maus
   bewirkte sichtbar nichts mehr — so geschehen im Löschdialog des Studios. */
button:hover, button:focus-visible,
.button:hover, .button:focus-visible,
.btn:hover, .btn:focus-visible {
    transform: translateY(-1px);
    box-shadow: 0 10px 22px rgba(79, 1, 255, 0.22);
}

.button.button-outline, .btn--ghost { background: rgba(79, 1, 255, 0.12); color: var(--accent); border: 1px solid rgba(79, 1, 255, 0.28); box-shadow: none; }
/* Status pill that is also the lock/unlock toggle (state + button in one) */
.status-toggle { display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.45rem 0.85rem; border-radius: 999px; font-size: 0.85rem; font-weight: 600; line-height: 1; cursor: pointer; border: 1px solid transparent; background: transparent; box-shadow: none; transition: background 120ms ease, border-color 120ms ease; }
.status-toggle:hover, .status-toggle:focus { box-shadow: none; transform: none; }
.status-toggle svg { width: 13px; height: 13px; flex-shrink: 0; }
.status-toggle--open { background: rgba(34, 197, 94, 0.12); color: #166534; border-color: rgba(34, 197, 94, 0.4); }
.status-toggle--open:hover, .status-toggle--open:focus { background: rgba(34, 197, 94, 0.2); border-color: rgba(34, 197, 94, 0.55); color: #166534; }
.status-toggle--locked { background: rgba(220, 38, 38, 0.1); color: #b91c1c; border-color: rgba(220, 38, 38, 0.38); }
.status-toggle--locked:hover, .status-toggle--locked:focus { background: rgba(220, 38, 38, 0.18); border-color: rgba(220, 38, 38, 0.5); color: #b91c1c; }
/* Schatten in dunklem Rotbraun statt im Knopfrot: Rot als Schatten wirkt auf Weiß wie ein
   rosa Schleier statt wie Tiefe. */
.btn--danger { background: #dc2626; box-shadow: 0 6px 14px rgba(127, 29, 29, 0.22); }
.btn--danger:hover,
.btn--danger:focus-visible { box-shadow: 0 10px 22px rgba(127, 29, 29, 0.3); }

/*
 * Formregel für den Hover von Knöpfen:
 *  - Größere Knöpfe, deren Ecken nicht voll gerundet sind (Standard-`.btn`), bekommen
 *    den Schatten-Hover (Anheben + Schatten, globale Regel oben).
 *  - Nur voll gerundete Pillen (Radius = halbe Höhe, z. B. `.btn--sm`) sind flach:
 *    `.btn--flat` — kein Schatten, kein Anheben, beim Überfahren nur dunkler gefüllt.
 *    Gleiches Prinzip wie `.icon-btn`.
 * `.btn--flat` nimmt nur die Bewegung raus; die Farbe kommt aus einer Variante
 * (`.btn--ghost`, `.btn--danger`, `.btn--note`). Steht bewusst hinter der globalen
 * `.btn:hover`-Regel, sonst gewänne deren Schatten.
 */
.btn--flat { box-shadow: none; transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease; }
.btn--flat:hover, .btn--flat:focus { box-shadow: none; transform: none; }
.btn--flat:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
/* Dunkler nur bei :hover und Tastatur-Fokus, nicht bei jedem :focus: Ein Dialog, der seinen
   Knopf beim Öffnen fokussiert, zeigte sonst schon den Hover-Zustand — und das Überfahren
   mit der Maus änderte sichtbar nichts mehr. */
.btn--ghost.btn--flat:hover, .btn--ghost.btn--flat:focus-visible { background: rgba(79, 1, 255, 0.2); }
.btn--danger.btn--flat:hover, .btn--danger.btn--flat:focus-visible { background: #b91c1c; }
.btn--danger.btn--flat:focus-visible { outline-color: #b91c1c; }
/* Gelb wie `.icon-btn--note`: gehört zu einer Notiz — Hinweis, keine Warnung. */
.btn--note { background: rgba(250, 204, 21, 0.22); color: #92400e; border: 1px solid rgba(217, 160, 6, 0.45); }
.btn--note:hover, .btn--note:focus-visible { background: rgba(250, 204, 21, 0.42); border-color: rgba(217, 160, 6, 0.6); color: #78350f; }

.text-muted { color: var(--fg-muted); font-size: 0.85rem; }

footer { color: var(--fg-muted); margin-top: 3rem; }

.alert { padding: 0.85rem 1rem; border-radius: 14px; font-weight: 600; margin-bottom: 1.25rem; }
.alert--error { background: rgba(220, 38, 38, 0.12); color: #7f1d1d; }
.alert--success { background: rgba(22, 163, 74, 0.12); color: #14532d; }
.alert--info { background: rgba(59, 130, 246, 0.12); color: #1e3a8a; }
.alert ul { margin: 0.5rem 0 0 1.1rem; padding: 0; font-weight: 500; }
.alert ul li { margin-bottom: 0.25rem; }

.entity-card { display: flex; flex-direction: column; gap: 1.75rem; min-width: 0; }
.entity-card__header { display:flex; justify-content: space-between; align-items:flex-start; gap:1rem; flex-wrap:wrap; }
.entity-card__badge {
    display:inline-flex;
    align-items:center;
    gap:0.4rem;
    padding:0.4rem 0.9rem;
    border-radius:18px;;
    background: rgba(79, 1, 255, 0.12);
    color: var(--accent);
    font-weight:600;
    letter-spacing:0.02em;
}
.entity-form { display:flex; flex-direction:column; gap:1.5rem; }
.entity-form__grid { display:grid; grid-template-columns:repeat(auto-fit, minmax(240px,1fr)); gap:1.25rem 1.5rem; border:none; padding:0; margin:0; }
.entity-form__field { display:flex; flex-direction:column; gap:0.55rem; font-weight:600; }
.entity-form__field input,
.entity-form__field select,
.entity-form__field textarea { font-weight:500; }
.entity-form__label { font-weight:600; font-size:0.95rem; }
.entity-form__field--full { grid-column:1 / -1; }
.entity-form__textarea { min-height:160px; resize:vertical; }
.entity-form__notes { min-height:120px; }
.entity-form__readonly { background: rgba(20,20,20,0.04); cursor:not-allowed; }
.entity-form__actions { display:flex; justify-content:flex-end; gap:0.75rem; flex-wrap:wrap; }
.entity-form__meta { font-size:0.9rem; color:var(--fg-muted); }

.entity-form__delete {
    all: unset;
    margin-right: auto;
    font-size: 0.95rem;
    font-weight: 400;
    color: #dc2626;
    cursor: pointer;
    border-radius: 0;
}

.entity-form__delete:hover,
.entity-form__delete:focus {
    color: #b91c1c;
    text-decoration: underline;
    background: none;
    box-shadow: none;
    border: none;
    transform: none;
}

.entity-form__delete:focus-visible {
    outline: none;
}

.lang-manager { display:flex; flex-direction:column; gap:0.75rem; }
.lang-manager__list { display:flex; flex-wrap:wrap; gap:0.5rem; min-height:2rem; }
.lang-manager__add { display:flex; flex-wrap:wrap; gap:0.5rem; align-items:center; }
.lang-manager__add input { flex:1 1 200px; }
.lang-manager__hint { margin:0; font-size:0.8rem; }
.lang-chip { display:inline-flex; align-items:center; gap:0.4rem; padding:0.35rem 0.75rem; border-radius:999px; background: rgba(79, 1, 255, 0.12); color: var(--accent); font-weight:600; font-size:0.85rem; }
.lang-chip__remove { border:none; background:transparent; color:inherit; font-size:1rem; line-height:1; cursor:pointer; padding:0; width:1.25rem; height:1.25rem; display:flex; align-items:center; justify-content:center; border-radius:50%; transition: background 120ms ease, color 120ms ease; }
.lang-chip__remove:hover,
.lang-chip__remove:focus { background: rgba(79, 1, 255, 0.2); color: var(--accent); }

.dialog-backdrop { position:fixed; inset:0; background:rgba(15,23,42,0.45); display:flex; align-items:center; justify-content:center; z-index:200; padding:1rem; }
.lang-delete-modal { background:#fff; border-radius:18px; padding:1.5rem; width:min(420px, 100%); display:flex; flex-direction:column; gap:0.9rem; box-shadow:0 20px 36px rgba(15, 23, 42, 0.25); }
.lang-delete-modal h2 { margin:0; font-size:1.3rem; }
.lang-delete-modal p { margin:0; font-size:0.95rem; color:var(--fg-muted); }
.lang-delete-modal__input { width:100%; border:1px solid rgba(20,20,20,0.12); border-radius:14px; padding:0.65rem 1rem; font-size:0.95rem; }
.lang-delete-modal__actions { display:flex; justify-content:flex-end; gap:0.75rem; }

.dropzone {
    border: 2px dashed rgba(79, 1, 255, 0.3);
    border-radius: 18px;
    padding: 1.75rem;
    background: rgba(79, 1, 255, 0.05);
    text-align: center;
    transition: border-color 120ms ease, background 120ms ease, color 120ms ease;
    cursor: pointer;
}
.dropzone:hover,
.dropzone.is-dragover {
    border-color: var(--accent);
    background: rgba(79, 1, 255, 0.12);
    color: var(--accent);
}
.dropzone input[type="file"] {
    display: none;
}

.badge-set { background: rgba(79, 1, 255, 0.12); color: var(--accent); }

.tag--lang { background: rgba(79,1,255,0.12); color: var(--accent); }
.tag--character { background: rgba(34,197,94,0.18); color: #166534; }
.tag--status-reviewed { background: rgba(34,197,94,0.18); color: #166534; }

/* Chips: gemeinsame Status-Pillen für Review UND Audio-Check. Lagen bisher nur
   lokal in review/index.html.twig — hier zentral, damit beide Oberflächen
   dieselbe Optik teilen (das Review überschreibt sie lokal wertgleich). */
.chip { display:inline-flex; align-items:center; gap:0.3rem; border-radius:999px; padding:0.25rem 0.55rem; font-size:0.7rem; font-weight:600; text-transform:uppercase; letter-spacing:0.02em; background:rgba(15,23,42,0.08); color:#1f2937; }
.chip--summary { background:rgba(79,1,255,0.12); color:var(--accent); }
.chip--gender { background:rgba(124,58,237,0.12); color:#5b21b6; }
.chip--status-need_mt { background:rgba(248,113,113,0.18); color:#b91c1c; }
.chip--status-mt_ready { background:rgba(96,165,250,0.18); color:#1d4ed8; }
.chip--status-stale { background:rgba(251,191,36,0.18); color:#b45309; }
.chip--status-reviewed { background:rgba(34,197,94,0.16); color:#166534; }
.chip--status-error { background:rgba(220,38,38,0.18); color:#991b1b; }
.tag--status-mt_ready { background: rgba(59,130,246,0.18); color: #1d4ed8; }
.tag--status-stale { background: rgba(251, 191, 36, 0.24); color: #b45309; }
.tag--status-need_mt { background: rgba(234,88,12,0.18); color: #9a3412; }
.tag--status-disabled { background: rgba(107,114,128,0.18); color: #374151; }
.tag--status-error { background: rgba(220,38,38,0.18); color: #991b1b; }
.tag--layout-todo { background: rgba(79,1,255,0.16); color: var(--accent); }
.tag--layout-generating { background: rgba(59,130,246,0.16); color: #1d4ed8; }
.tag--layout-ready { background: rgba(34,197,94,0.18); color: #166534; }
.tag--layout-error { background: rgba(220,38,38,0.18); color: #991b1b; }
.tag--info { background: rgba(15, 23, 42, 0.1); color: #1f2937; }

/* Flat inline SVG icons (replace emoji glyphs). 1em + currentColor → inherit local styling. */
.rlr-ic { width:1em; height:1em; display:inline-block; vertical-align:-0.125em; flex:none; }
.rlr-ic--spin { animation:rlr-spin 0.8s linear infinite; }
@keyframes rlr-spin { to { transform:rotate(360deg); } }
.chip .rlr-ic { margin-right:0.25rem; }

.auth-body {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg);
}

.auth-body .shell {
    min-height: 100vh;
    width: 100%;
    padding: 0 4vw;
    display: flex;
    align-items: center;
    justify-content: center;
}

.auth-card { width: min(420px, 92vw); background: rgba(255, 255, 255, 0.95); border-radius: 24px; padding: 2.75rem 2.5rem 2.25rem; box-shadow: 0 18px 40px rgba(20, 20, 20, 0.1); border: 1px solid rgba(20, 20, 20, 0.04); display: flex; flex-direction: column; gap: 1.7rem; }

.auth-card__header { display: flex; align-items: center; gap: 0.75rem; }
.auth-card__header h1 { margin: 0; font-size: 1.5rem; }
.auth-intro { margin: 0; color: var(--fg-muted); }
.auth-form { display: flex; flex-direction: column; gap: 1rem; }
.form-field { display: flex; flex-direction: column; gap: 0.35rem; }
.form-field label { font-weight: 600; }
.auth-alert { padding: 0.85rem 1rem; border-radius: 12px; font-weight: 500; }
.auth-alert--error { background: rgba(220, 38, 38, 0.12); color: #7f1d1d; }
.auth-alert--success { background: rgba(34, 197, 94, 0.12); color: #166534; }
.auth-hint { margin: 0; text-align: center; font-size: 0.9rem; color: var(--fg-muted); }
.auth-hint a { color: var(--accent); text-decoration: none; }
.auth-hint a:hover, .auth-hint a:focus { text-decoration: underline; }

.admin-status-doc { display:grid; grid-template-columns:minmax(120px, 160px) 1fr; gap:0.35rem 1rem; margin:1rem 0 0; padding:0; }
.admin-status-doc dt { font-weight:700; text-transform:uppercase; font-size:0.82rem; color: var(--accent); }
.admin-status-doc dd { margin:0; font-size:0.85rem; color: var(--fg-muted); }

.job-hub {
    position: fixed;
    bottom: 1.5rem;
    right: 1.5rem;
    z-index: 140;
    width: var(--job-hub-width);
    font-size: 0.92rem;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.job-hub__toggle {
    display: inline-flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    width: 100%;
    padding: 0.75rem 1rem;
    background: rgba(255, 255, 255, 0.95);
    border: 1px solid rgba(20, 20, 20, 0.12);
    border-radius: 999px;
    box-shadow: var(--shadow);
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--fg);
    cursor: pointer;
    transition: transform 120ms ease, box-shadow 120ms ease, border-color 120ms ease;
}

.job-hub__toggle:hover,
.job-hub__toggle:focus {
    transform: translateY(-1px);
    border-color: rgba(79, 1, 255, 0.25);
    box-shadow: var(--shadow);
}

.job-hub__toggle span {
    display: inline-flex;
    align-items: center;
}

.job-hub__label {
    gap: 0.5rem;
}

/* inline-flex + feste Höhe: sonst sitzt die Zahl im min-width-Feld links und
   durch das Zeilenhöhen-Padding leicht zu hoch. */
.job-hub__badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.5rem;
    height: 1.5rem;
    padding: 0 0.4rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 700;
    line-height: 1;
    background: rgba(79, 1, 255, 0.12);
    color: var(--accent);
    transition: background 120ms ease, color 120ms ease;
}

.job-hub__badge--active {
    background: var(--accent);
    color: #fff;
}

.job-hub__badge--idle {
    background: rgba(22, 163, 74, 0.14);
    color: #166534;
}

.job-hub__panel {
    display: none;
    flex-direction: column;
    gap: 0.9rem;
    background: rgba(255, 255, 255, 0.97);
    border: 1px solid rgba(20, 20, 20, 0.1);
    border-radius: 20px;
    box-shadow: 0 16px 32px rgba(20, 20, 20, 0.14);
    padding: 1rem;
    /* Wächst mit dem Inhalt bis zur Kappung — auf kleinen Fenstern greift vh zuerst. */
    max-height: min(70vh, 560px);
}

.job-hub__panel[aria-hidden="false"] {
    display: flex;
}

.job-hub__jobs {
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    /* Scroll-Container nach rechts über das Panel-Padding hinausziehen und den
       Betrag als Innenabstand zurückgeben: die Scrollbar liegt damit in der
       rechten Rinne, die Karten behalten links wie rechts denselben Rand. */
    margin-right: -0.85rem;
    padding-right: 0.85rem;
    scrollbar-width: thin;
    scrollbar-color: rgba(20, 20, 20, 0.22) transparent;
}

/* Eigene schlanke Scrollbar statt macOS-Overlay: nimmt fixen Platz ein und
   wächst beim Hover nicht über die Einträge. */
.job-hub__jobs::-webkit-scrollbar {
    width: 7px;
}

.job-hub__jobs::-webkit-scrollbar-track {
    background: transparent;
}

.job-hub__jobs::-webkit-scrollbar-thumb {
    background: rgba(20, 20, 20, 0.18);
    border-radius: 999px;
}

.job-hub__jobs::-webkit-scrollbar-thumb:hover {
    background: rgba(20, 20, 20, 0.32);
}

/* Kein Kasten-im-Kasten: Details laufen flach in der Karte weiter,
   nur eine Haarlinie trennt sie vom Kopfbereich. */
.job-card__details {
    margin-top: 0.85rem;
    padding: 0.85rem 0 0.1rem;
    border-top: 1px solid rgba(79, 1, 255, 0.16);
}

.job-card__details[hidden] {
    display: none;
}

.job-card__detail-meta {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 0.45rem 0.9rem;
    font-size: 0.84rem;
    color: var(--fg-muted);
}

.job-card__detail-meta span {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
    overflow-wrap: anywhere;
    word-break: break-word;
}

.job-card__detail-meta span strong {
    font-weight: 600;
    font-size: 0.86rem;
    color: var(--fg);
}

/* Die Run-ID ist ein reines Datenfeld — schlichter Text, keine Aktion. */
.job-card__run-id {
    word-break: break-all;
}


.job-card__detail-errors {
    margin: 0.6rem 0 0;
    font-size: 0.82rem;
    color: #991b1b;
}

.job-card__detail-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 0.75rem;
}

.job-card__detail-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.45rem 0.85rem;
    border-radius: 999px;
    border: 1px solid rgba(79, 1, 255, 0.2);
    background: rgba(79, 1, 255, 0.08);
    color: var(--accent);
    font-size: 0.82rem;
    font-weight: 600;
    text-decoration: none;
}

.job-card__detail-link:hover,
.job-card__detail-link:focus {
    background: rgba(79, 1, 255, 0.16);
}

.job-card__detail-cancel {
    border: none;
    border-radius: 999px;
    background: rgba(220, 38, 38, 0.16);
    color: #991b1b;
    padding: 0.45rem 0.85rem;
    font-size: 0.82rem;
    font-weight: 600;
    cursor: pointer;
}

.job-card__detail-cancel:hover,
.job-card__detail-cancel:focus {
    background: rgba(220, 38, 38, 0.28);
}

.job-card__detail-cancel[disabled] {
    opacity: 0.6;
    cursor: progress;
}

.job-hub__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

.job-hub__header h2 {
    font-size: 1rem;
    margin: 0;
}

/* Icon-Close wie in den Modals (vgl. .review-modal__close) */
.job-hub__close {
    border: none;
    background: none;
    color: var(--fg-muted);
    cursor: pointer;
    font-size: 1.6rem;
    line-height: 1;
    padding: 0.2rem 0.5rem;
    border-radius: 8px;
}

.job-hub__close:hover,
.job-hub__close:focus {
    background: rgba(15, 23, 42, 0.06);
    color: var(--fg);
}

/* Kein eigener Scroller — gescrollt wird ausschließlich .job-hub__jobs */
.job-hub__list {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.job-hub__empty {
    margin: 0;
    color: var(--fg-muted);
    text-align: center;
}

/* Karten liegen in einem Scroll-Bereich — Drop-Shadows würden an dessen Kanten
   abgeschnitten. Elevation leistet allein das Panel; die Karten arbeiten flach
   mit Border und Hintergrund-Tint. */
.job-card {
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
    background: rgba(255, 255, 255, 0.92);
    border: 1px solid rgba(20, 20, 20, 0.1);
    border-radius: 16px;
    padding: 0.75rem 0.9rem;
    cursor: pointer;
    transition: background 160ms ease, border-color 160ms ease;
}

.job-card:focus {
    outline: none;
    border-color: rgba(79, 1, 255, 0.4);
}

.job-card:hover {
    border-color: rgba(79, 1, 255, 0.25);
    background: rgba(79, 1, 255, 0.03);
}

.job-card--active {
    background: rgba(79, 1, 255, 0.08);
    border-color: rgba(79, 1, 255, 0.32);
}

.job-card__row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.75rem;
}

.job-card__row--header {
    align-items: center;
}

.job-card__info {
    display: flex;
    align-items: center;
    gap: 0.65rem;
}

.job-card__type {
    font-weight: 600;
    font-size: 0.95rem;
}

.job-card__status {
    font-size: 0.8rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 0.25rem 0.55rem;
    border-radius: 999px;
}

.job-card__chevron {
    width: 12px;
    height: 8px;
    display: inline-block;
    flex-shrink: 0;
    color: rgba(15, 23, 42, 0.45);
    background-color: currentColor;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23000' d='M1.41.59 6 5.17 10.59.59 12 2l-6 6-6-6z'/%3E%3C/svg%3E") center / 12px 8px no-repeat;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23000' d='M1.41.59 6 5.17 10.59.59 12 2l-6 6-6-6z'/%3E%3C/svg%3E") center / 12px 8px no-repeat;
    transition: transform 160ms ease, color 160ms ease;
}

.job-card:hover .job-card__chevron {
    color: var(--accent);
}

.job-card--active .job-card__chevron {
    transform: rotate(180deg);
    color: var(--accent);
}

.job-card__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.2rem 0.75rem;
    color: var(--fg-muted);
    font-size: 0.82rem;
}

.job-card__meta-errors {
    color: #991b1b;
    font-weight: 600;
}

.job-card__progress {
    position: relative;
    height: 6px;
    background: rgba(79, 1, 255, 0.12);
    border-radius: 999px;
    overflow: hidden;
}

.job-card__progress-bar {
    position: absolute;
    inset: 0;
    background: var(--accent);
    width: 0%;
    transition: width 180ms ease;
}

/* Läuft ohne zählbaren Fortschritt: wandernder Balken statt Dauer-0-%-Track. */
.job-card__progress--indeterminate .job-card__progress-bar {
    width: 38%;
    transition: none;
    animation: job-progress-slide 1.5s ease-in-out infinite;
}

@keyframes job-progress-slide {
    0%   { transform: translateX(-100%); }
    100% { transform: translateX(263%); }
}

@media (prefers-reduced-motion: reduce) {
    .job-card__progress--indeterminate .job-card__progress-bar {
        animation: none;
        width: 100%;
        opacity: 0.45;
    }
}

.job-card__step {
    font-size: 0.8rem;
    color: var(--accent);
    font-weight: 600;
}

.job-card--queued .job-card__status,
.job-card--pending .job-card__status { background: rgba(59, 130, 246, 0.1); color: #1e40af; }
.job-card--running .job-card__status { background: rgba(79, 1, 255, 0.15); color: var(--accent); }
.job-card--completed .job-card__status { background: rgba(34, 197, 94, 0.15); color: #166534; }
.job-card--completed_with_errors .job-card__status { background: rgba(251, 191, 36, 0.18); color: #b45309; }
.job-card--failed .job-card__status { background: rgba(220, 38, 38, 0.18); color: #991b1b; }
.job-card--cancelled .job-card__status { background: rgba(120, 113, 108, 0.14); color: #57534e; }

/* Verwaist: aktiver Status ohne Update seit STALE_CUTOFF — überschreibt die Status-Farbe */
.job-card--stale { border-color: rgba(217, 119, 6, 0.35); }
.job-card--stale .job-card__status { background: rgba(217, 119, 6, 0.14); color: #b45309; }

.job-card__detail-error-list {
    margin: 0.65rem 0 0;
    padding-left: 1.1rem;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    font-size: 0.82rem;
    color: #991b1b;
}

/* Roter Punkt am Toggle: seit dem letzten Öffnen ist ein Job fehlgeschlagen */
.job-hub__toggle--attention {
    position: relative;
}

.job-hub__toggle--attention::after {
    content: '';
    position: absolute;
    top: -3px;
    right: -3px;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: #dc2626;
    border: 2px solid #fff;
}

.job-toast {
    cursor: pointer;
}

.job-hub__system-toggle {
    border: none;
    background: none;
    padding: 0.4rem 0.2rem;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--fg-muted);
    cursor: pointer;
    text-align: left;
}

.job-hub__system-toggle:hover,
.job-hub__system-toggle:focus {
    color: var(--accent);
}

.job-hub__system-list {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    padding-top: 0.5rem;
    border-top: 1px solid rgba(20, 20, 20, 0.08);
}

/* Die globalen button-Styles (violetter CTA-Glow + Hover-Lift) passen nicht in das
   kompakte Hub-Panel — und Schatten im Scroll-Bereich würden abgeschnitten.
   Alle Hub-Buttons daher explizit flach halten. */
.job-hub__close,
.job-hub__system-toggle,
.job-card__detail-link,
.job-card__detail-cancel {
    box-shadow: none;
}

.job-hub__close:hover, .job-hub__close:focus,
.job-hub__system-toggle:hover, .job-hub__system-toggle:focus,
.job-card__detail-link:hover, .job-card__detail-link:focus,
.job-card__detail-cancel:hover, .job-card__detail-cancel:focus {
    box-shadow: none;
    transform: none;
}

.job-hub__archive-link {
    display: block;
    margin-top: 0.6rem;
    padding-top: 0.6rem;
    border-top: 1px solid rgba(20, 20, 20, 0.08);
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--fg-muted);
    text-decoration: none;
}

.job-hub__archive-link:hover,
.job-hub__archive-link:focus {
    color: var(--accent);
}

/* ── Global Loader ── */
.pmo-loader { position:fixed; inset:0; background:rgba(255,255,255,0.78); backdrop-filter:blur(4px); z-index:9999; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:1rem; }
.pmo-loader[hidden] { display:none; }
.pmo-loader__spinner-wrap { position:relative; width:3.5rem; height:3.5rem; display:flex; align-items:center; justify-content:center; }
.pmo-loader__spinner { position:absolute; inset:0; width:100%; height:100%; border:3px solid rgba(79,1,255,0.15); border-top-color:var(--accent); border-radius:50%; animation:pmo-spin 0.75s linear infinite; }
.pmo-loader__pct { position:relative; font-size:0.72rem; font-weight:700; color:var(--accent); line-height:1; pointer-events:none; }
.pmo-loader__label { font-size:0.95rem; font-weight:600; color:var(--accent); margin:0; }
@keyframes pmo-spin { to { transform:rotate(360deg); } }

.job-toast-stack {
    position: fixed;
    right: 1.5rem;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    width: var(--job-hub-width);
    z-index: 150;
    pointer-events: none;
}

.job-toast {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    border-radius: 16px;
    border: 1px solid rgba(20, 20, 20, 0.08);
    box-shadow: 0 18px 32px rgba(15, 23, 42, 0.18);
    padding: 0.85rem 1rem;
    opacity: 0;
    transform: translateY(8px);
    animation: job-toast-in 160ms ease forwards;
    pointer-events: auto;
}

@keyframes job-toast-in {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: translateY(0); }
}

.job-toast__title {
    margin: 0;
    font-size: 0.92rem;
    font-weight: 600;
}

.job-toast__body {
    margin: 0;
    font-size: 0.82rem;
    color: var(--fg-muted);
}

.job-toast--success { border-left: 4px solid rgba(34,197,94,0.9); background: rgba(209, 250, 229, 0.96); color: #166534; }
.job-toast--warning { border-left: 4px solid rgba(234,179,8,0.9); background: rgba(254, 243, 199, 0.96); color: #92400e; }
.job-toast--error { border-left: 4px solid rgba(220,38,38,0.9); background: rgba(254, 226, 226, 0.96); color: #991b1b; }

@media (max-width: 720px) {
    .job-hub {
        right: 1rem;
        left: 1rem;
        width: auto;
    }

    .job-toast-stack {
        right: 1rem;
        left: 1rem;
        width: auto;
    }
}

.subnav {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin: 0 0 1.5rem;
    flex-wrap: wrap;
}

.subnav__link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    padding: 0.55rem 1.1rem;
    border-radius: 999px;
    border: 1px solid transparent;
    background: rgba(79, 1, 255, 0.08);
    color: var(--accent);
    font-weight: 600;
    font-size: 0.92rem;
    transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}

.subnav__link:hover,
.subnav__link:focus {
    background: rgba(79, 1, 255, 0.16);
}

.subnav__link--active {
    background: var(--accent);
    color: #fff;
    border-color: rgba(79, 1, 255, 0.32);
}

/* Set hub: full-width header band on top, then ONE card holding nav + content */
.set-layout { display: flex; flex-direction: column; gap: 1.25rem; }

/* Header band — the selected set sits above all content */
/* Anzeigefläche, keine Arbeitsfläche: Das Kopfband sagt nur, WAS man gerade
   ansieht (Set bzw. Test) — geklickt und entschieden wird darunter. Die
   violette Tönung trennt beides sichtbar; weiße Flächen sind die, auf denen
   gearbeitet wird. Deshalb auch flach statt mit Schatten. */
.set-hub-head { background: rgba(79, 1, 255, 0.04); border-radius: 18px; padding: 1rem 1.5rem; border: 1px solid rgba(79, 1, 255, 0.12); display: flex; justify-content: space-between; align-items: center; gap: 0.75rem 1.5rem; flex-wrap: wrap; }
.set-hub-head__title { display: flex; align-items: center; gap: 0.7rem; flex-wrap: wrap; }
.set-hub-head__title .set-id-pill { font-size: 1rem; padding: 0.3rem 0.8rem; letter-spacing: 0.02em; }
.set-hub-head__name { font-size: 1.5rem; font-weight: 700; line-height: 1.1; }
.set-hub-head__locked { border-radius: 999px; padding: 0.15rem 0.5rem; font-size: 0.68rem; font-weight: 700; background: rgba(248, 113, 113, 0.2); color: #b91c1c; text-transform: uppercase; letter-spacing: 0.03em; }
.set-hub-head__meta { text-align: right; font-size: 0.9rem; display: flex; flex-direction: column; gap: 0.2rem; }
.set-hub-head__meta strong { font-weight: 700; }
.set-hub-head__meta-warn { color: #b45309; font-weight: 600; }

/* Body card — nav rail and content share one surface */
.set-shell { background: var(--card-bg); border-radius: 22px; border: 1px solid rgba(20, 20, 20, 0.04); box-shadow: var(--shadow); display: flex; align-items: stretch; overflow: hidden; }
.set-shell__nav { flex-shrink: 0; width: 220px; padding: 1.75rem 1.5rem; display: flex; flex-direction: column; gap: 0.3rem; }
.set-shell__body { flex: 1 1 auto; min-width: 0; padding: 1.75rem 2rem 1.75rem 2rem; }

.set-nav__link { display: block; padding: 0.55rem 0.9rem; border-radius: 12px; font-weight: 600; font-size: 0.92rem; color: var(--accent); text-decoration: none; transition: background 120ms ease, color 120ms ease; }
.set-nav__link:hover,
.set-nav__link:focus { background: rgba(79, 1, 255, 0.08); }
.set-nav__link--active { background: var(--accent); color: #fff; }

@media (max-width: 760px) {
    .set-shell { flex-direction: column; }
    .set-shell__nav { width: 100%; flex-direction: row; flex-wrap: wrap; padding-bottom: 0; }
    .set-shell__body { padding: 1.5rem; }
    .set-hub-head__meta { text-align: left; }
}

.quick-actions {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.quick-actions__intro {
    margin: 0;
    color: var(--fg-muted);
    font-size: 0.9rem;
}

.quick-action {
    border: 1px solid rgba(20, 20, 20, 0.08);
    border-radius: 14px;
    padding: 0.7rem 0.85rem;
    background: rgba(255, 255, 255, 0.9);
}

.quick-action > summary {
    cursor: pointer;
    list-style: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    width: 100%;
}

.quick-action__summary {
    display:flex;
    justify-content:space-between;
    align-items:flex-start;
    gap:1rem;
    width:100%;
}

.quick-action__summary-text {
    display:flex;
    flex-direction:column;
    gap:0.25rem;
}

.quick-action__summary-title {
    font-size:0.98rem;
    font-weight:600;
}

.quick-action__summary-subtitle {
    font-size:0.85rem;
    color: var(--fg-muted);
}

.quick-action__summary-meta {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.78rem;
    color: var(--fg-muted);
}

.status-dot {
    width: 0.6rem;
    height: 0.6rem;
    border-radius: 50%;
    background: rgba(20,20,20,0.18);
    display: inline-block;
}

.status-dot--ok { background: rgba(34,197,94,0.9); }
.status-dot--warning { background: rgba(234,179,8,0.9); }
.status-meta { font-size:0.75rem; color: var(--fg-muted); font-weight:500; }
.status-meta--error { color:#b91c1c; font-weight:600; }

.quick-action > summary::-webkit-details-marker {
    display: none;
}

.quick-action > summary::after {
    content: '';
    width: 12px;
    height: 8px;
    margin-left: 0.5rem;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%234f01ff' d='M1.41.59 6 5.17 10.59.59 12 2l-6 6-6-6z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 12px 8px;
    transition: transform 160ms ease;
    display: inline-block;
    transform-origin: center;
}

.quick-action[open] > summary::after {
    transform: rotate(180deg);
}

.quick-action[open] > summary {
    color: var(--accent);
}

.quick-action__content {
    margin-top:0.85rem;
    padding-top:0.9rem;
    border-top:1px solid rgba(20, 20, 20, 0.08);
    display:flex;
    flex-direction:column;
    gap:0.9rem;
}

.quick-action__description {
    margin:0;
    font-size:0.9rem;
    color: var(--fg-muted);
}

.quick-action__form {
    margin-top: 0;
    display: flex;
    flex-direction: column;
    gap: 0.65rem;
    align-items: flex-start;
}

.quick-action__row {
    display: flex;
    gap: 0.65rem;
    flex-wrap: wrap;
}

.quick-action__row--tts {
    align-items: flex-end;
}

.quick-action__row--inline {
    align-items: center;
    gap: 0.65rem;
}

.quick-action__field {
    flex: 1 1 160px;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

.quick-action__field--stretch {
    flex: 2 1 240px;
}

.quick-action__field--full {
    flex: 1 1 100%;
}

.quick-action__field--medium {
    flex: 1 1 220px;
}

.quick-action__field--compact {
    flex: 0 0 120px;
    max-width: 120px;
}

.quick-action__field--compact input {
    text-align: center;
    padding-inline: 0.6rem;
}

.quick-action__label {
    font-size: 0.85rem;
    font-weight: 600;
}

.quick-action__actions {
    display:flex;
    align-items:center;
    gap:0.75rem;
    flex-wrap:wrap;
}

.quick-action__lang-options {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    padding: 0.25rem 0;
}

.quick-action__lang-option {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.4rem 0.75rem;
    border-radius: 999px;
    border: 1px solid rgba(79, 1, 255, 0.18);
    background: rgba(79, 1, 255, 0.05);
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--accent);
}

.quick-action__lang-option input[type="checkbox"] {
    width: 0.95rem;
    height: 0.95rem;
}

.quick-action__lang-option:hover,
.quick-action__lang-option:focus-within {
    border-color: rgba(79, 1, 255, 0.45);
    background: rgba(79, 1, 255, 0.12);
}

.quick-action__lang-option--disabled {
    opacity: 0.6;
    border-style: dashed;
    cursor: not-allowed;
}

.quick-action__lang-option--disabled input[type="checkbox"] {
    cursor: not-allowed;
}

.quick-action__lang-note {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    background: rgba(107, 114, 128, 0.18);
    color: #374151;
    border-radius: 999px;
    padding: 0.15rem 0.5rem;
    margin-left: 0.4rem;
}

.quick-action__field label {
    font-size: 0.85rem;
    font-weight: 600;
}

.quick-action__cast-options {
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
    padding: 0.35rem 0;
}

.quick-action__cast-options--disabled {
    opacity: 0.6;
}

.quick-action__cast-group {
    border: 1px solid rgba(79, 1, 255, 0.18);
    border-radius: 18px;
    padding: 0.55rem 0.75rem;
    background: rgba(79, 1, 255, 0.05);
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.quick-action__cast-group-label {
    margin: 0;
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--accent);
}

.quick-action__cast-list {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
}

.quick-action__help {
    margin: 0;
    color: var(--fg-muted);
    font-size: 0.8rem;
}

.quick-action__status {
    font-size: 0.82rem;
    margin: 0;
}

.quick-action__form .btn {
    align-self: flex-start;
}

.quick-action__status--success { color: #166534; }
.quick-action__status--error { color: #991b1b; }

.quick-action__hint {
    margin: 0;
    font-size: 0.8rem;
    color: var(--fg-muted);
}

.quick-action__hint--warning { color: #b45309; }

.quick-action__input--readonly {
    background: rgba(148, 163, 184, 0.12);
    border: 1px solid rgba(148, 163, 184, 0.4);
    color: #0f172a;
}

.section__header { display: flex; justify-content: space-between; align-items: center; gap: 1.5rem; margin-bottom: 2rem; }
.section__header h1 { margin: 0; font-size: 1.9rem; font-weight: 600; }
.section__header p { margin: 0.35rem 0 0; color: var(--fg-muted); }

.filter-form { display: flex; gap: 0.75rem; flex-wrap: wrap; margin-bottom: 1.5rem; }
.filter-form input, .filter-form select { flex: 1 1 240px; }
.table__meta { margin-top:0.25rem; font-size:0.85rem; color: var(--fg-muted); }
.table__meta--error { color:#b91c1c; }
.table__meta-row td { border-top:none; background: rgba(255, 243, 243, 0.6); }
.entity-status { display:flex; gap:0.5rem; flex-wrap:wrap; margin-bottom:0.6rem; }
.entity-section-grid { display:grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap:1rem; margin-bottom:1.5rem; }
.entity-section { background: rgba(79, 1, 255, 0.06); border-radius:16px; padding:1rem 1.1rem; display:flex; flex-direction:column; gap:0.75rem; }
.entity-section__title { margin:0; font-size:1.05rem; font-weight:600; color: var(--accent); }
.entity-section p { margin:0; white-space:pre-wrap; }
.entity-audio { margin-top:1.5rem; padding:1.1rem; border-radius:16px; background: rgba(15, 23, 42, 0.05); display:flex; flex-direction:column; gap:0.75rem; }
.entity-audio audio { width:100%; max-width:420px; }
.entity-audio__meta { font-size:0.82rem; color: var(--fg-muted); display:flex; flex-wrap:wrap; gap:0.75rem; }
.entity-meta-grid { margin-top:1.5rem; display:grid; gap:0.6rem; font-size:0.9rem; color:var(--fg-muted); grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.entity-meta-grid--compact { margin-top:0.75rem; }
.entity-meta-grid--wide { grid-template-columns: 1fr; }
.entity-meta__label { display:block; font-weight:600; color: rgba(20, 20, 20, 0.72); }
.entity-meta__value { display:block; margin-top:0.15rem; }
.quick-inline-form { display:inline-flex; align-items:center; }
.entity-card__header-actions { display:flex; gap:0.6rem; align-items:center; flex-wrap:wrap; justify-content:flex-end; }
.entity-toolbar { display:flex; gap:0.75rem; flex-wrap:wrap; margin-bottom:1.25rem; }
.entity-subsection { margin-top:2rem; padding:1.25rem 1.35rem; border-radius:18px; background: rgba(79, 1, 255, 0.04); display:flex; flex-direction:column; gap:1rem; border:1px solid rgba(79, 1, 255, 0.08); }
.entity-subsection__header { display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:0.75rem; }
.entity-subsection table { width:100%; border-collapse:collapse; font-size:0.9rem; }
.entity-subsection th, .entity-subsection td { padding:0.65rem 0.75rem; border-bottom:1px solid rgba(20,20,20,0.08); text-align:left; }
.entity-subsection th { font-size:0.78rem; text-transform:uppercase; letter-spacing:0.03em; color: var(--accent); background: rgba(79, 1, 255, 0.08); }
.entity-subsection tr:last-child td { border-bottom:none; }
.entity-subsection tr.is-current { background: rgba(79, 1, 255, 0.08); }
.mono { font-family: "SFMono-Regular", "JetBrains Mono", Menlo, Consolas, "Liberation Mono", monospace; letter-spacing: 0.01em; }
.set-id-pill { display:inline-flex; align-items:center; font-family: "SFMono-Regular", "JetBrains Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size:0.7rem; font-weight:600; letter-spacing:0.03em; background:rgba(79,1,255,0.1); color:var(--accent); border-radius:999px; padding:0.15rem 0.55rem; white-space:nowrap; vertical-align:middle; }

.pagination { display:flex; justify-content:center; align-items:center; gap:0.55rem; flex-wrap:wrap; margin-top:1.5rem; }
.pagination__link { font-size:0.85rem; font-weight:600; color: var(--accent); text-decoration:none; padding:0.35rem 0.65rem; border-radius:999px; border:1px solid transparent; }
.pagination__link:hover,
.pagination__link:focus { border-color: rgba(79, 1, 255, 0.18); background: rgba(79, 1, 255, 0.08); }
.pagination__link--disabled { color: var(--fg-muted); border-color: transparent; pointer-events:none; }
.pagination__page { font-size:0.85rem; padding:0.35rem 0.65rem; border-radius:999px; border:1px solid rgba(79, 1, 255, 0.18); color: var(--accent); text-decoration:none; font-weight:600; display:inline-flex; align-items:center; justify-content:center; }
.pagination__page:hover,
.pagination__page:focus { border-color: rgba(79, 1, 255, 0.35); background: rgba(79, 1, 255, 0.08); }
.pagination__page--current { background: var(--accent); color:#fff; border-color: var(--accent); cursor:default; }
.pagination__ellipsis { font-size:0.85rem; color: var(--fg-muted); padding:0.3rem 0.4rem; }
.table__actions { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.section__actions { display: flex; gap: 0.75rem; align-items: center; flex-wrap: wrap; justify-content: flex-end; }
.form-grid { display: flex; flex-direction: column; gap: 1.05rem; }

.form-field input,
.form-field textarea,
.form-field select,
input, select, textarea { border: 1px solid rgba(20, 20, 20, 0.12); border-radius: 16px; padding: 0.85rem 1.1rem; font-size: 1rem; font-family: inherit; background: rgba(255, 255, 255, 0.9); transition: border-color 120ms ease, box-shadow 120ms ease; }
input[type="hidden"] { display: none !important; padding: 0; border: none; background: none; }

select, .review-filter__control {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 2.5rem;
    background-color: #fff;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%234f01ff' d='M1.41.59 6 5.17 10.59.59 12 2l-6 6-6-6z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 1rem center;
    background-size: 12px 8px;
}

.studio-filter {
    min-width: 200px;
    width: auto;
    padding-right: 2.5rem;
}

.studio-filter:disabled {
    background-color: rgba(15, 23, 42, 0.05);
    color: rgba(15, 23, 42, 0.45);
    cursor: not-allowed;
}

input:focus, select:focus, textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(79, 1, 255, 0.18); }
.form-checkbox { display: inline-flex; align-items: center; gap: 0.6rem; font-weight: 500; }
/* Mittig zur Schrift statt auf ihrer Grundlinie: Inline gesetzt sitzt ein
   Kaestchen auf der Baseline und wirkt neben einem Knopf verrutscht. Die Groesse
   folgt der Schrift der Beschriftung — in einer kleinen Zeile ein kleines
   Kaestchen. */
.form-checkbox input[type="checkbox"],
.form-checkbox input[type="radio"] {
    width: 1.05em; height: 1.05em; margin: 0; flex: 0 0 auto; border-radius: 6px;
}

table input, table select { width: 100%; }
/* The broad `input` rules above (border/padding/width:100%) are meant for text fields,
   not radios/checkboxes — without this reset they render as full-width boxed controls. */
input[type="radio"], input[type="checkbox"],
table input[type="radio"], table input[type="checkbox"] {
    width: auto; border: none; border-radius: 0; padding: 0; background: none; box-shadow: none; transition: none;
    /* Angehakt in der Hausfarbe statt im Chrome-Blau. `accent-color` faerbt das
       native Element, ohne es nachzubauen — Tastatur, Vorlesehilfen und das
       Verhalten auf dem Telefon bleiben unangetastet. Gilt fuer die ganze
       Anwendung: Das Blau stand ueberall, nicht nur im Sprachtest. */
    accent-color: var(--accent);
}
input[type="radio"]:focus-visible, input[type="checkbox"]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

@media (max-width: 900px) {
    .topbar__inner { padding: 1rem 6vw; flex-wrap: wrap; gap: 0.75rem; }
    .topbar__nav { flex-wrap: wrap; justify-content: center; width: 100%; }
    .shell { padding: 2.5rem 6vw 4rem; }
    .card { border-radius: 18px; padding: 1.5rem; }
    table { display: block; overflow-x: auto; }
}
