/*
    Globales CSS für Clocky, eingebunden in Components/App.razor.

    Warum global und nicht Blazor CSS Isolation:
    Scoped CSS hängt sein Scope-Attribut nur an Elemente, die in der eigenen .razor-Datei stehen.
    Alles, was eine MudBlazor-Komponente selbst rendert, bekommt es nicht — eine Regel auf
    Class="..." an einem MudIconButton greift also schlicht nicht. Dazu kommt: die beiden
    vorhandenen .razor.css-Dateien (MainLayout, NavMenu) stylen .page/.sidebar/.navbar-toggler,
    also Blazor-Template-Reste, die es in dieser Oberfläche nicht gibt. Es war hier nie verifiziert,
    dass Scoped CSS ankommt.

    wwwroot/app.css gab es einmal parallel dazu, war in App.razor aber nie verlinkt und damit
    wirkungslos — gelöscht in #99, statt die ~100 Zeilen Bootstrap-Reste scharfzuschalten.

    Farben kommen aus den Theme-Variablen, die MudThemeProvider setzt, damit hell und dunkel
    automatisch stimmen und eine Palettenänderung hier nichts nachzuziehen hat.
*/

/* ---------------------------------------------------------------------------
   Analyseblöcke (StatisticsPanel)

   Eine Ansicht für alle Breiten. Keine Breakpoints: die kompakte Fassung ist
   auch auf einem großen Bildschirm die bessere, und Clocky wird fast nur am
   Handy benutzt.
   --------------------------------------------------------------------------- */

.stats-heading {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 12px;
}

/* Die Kopfzahlen: gearbeitet, Soll, Differenz. */
.stats-figures {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
}

.stats-figure {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    padding-left: 12px;
    border-left: 1px solid var(--mud-palette-lines-default);
}

.stats-figure:first-child {
    padding-left: 0;
    border-left: none;
}

.stats-label {
    font-size: 0.6875rem;
    line-height: 1.2;
    color: var(--mud-palette-text-secondary);
}

.stats-value {
    font-size: 1.125rem;
    font-weight: 600;
    line-height: 1.25;
    letter-spacing: -0.01em;
    white-space: nowrap;
    /* Gleich breite Ziffern, sonst tanzen die Zahlen beim Aktualisieren. */
    font-variant-numeric: tabular-nums;
}

.stats-value.is-positive {
    color: var(--mud-palette-success);
}

.stats-value.is-negative {
    color: var(--mud-palette-error);
}

.stats-caption {
    display: block;
    margin-top: 6px;
    font-size: 0.6875rem;
    line-height: 1.2;
    color: var(--mud-palette-text-secondary);
}

/* --- Prognose ----------------------------------------------------------------
   Durch eine Linie abgesetzt statt durch eine Fläche: die Prognose ist eine
   andere Art von Zahl als die darüber, aber kein anderer Block.
   --------------------------------------------------------------------------- */

.stats-forecast {
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--mud-palette-lines-default);
}

.stats-forecast-label {
    display: block;
    margin-bottom: 8px;
    font-size: 0.6875rem;
    line-height: 1.2;
    color: var(--mud-palette-text-secondary);
}

.stats-forecast-figures {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
}

/* ---------------------------------------------------------------------------
   Kalender (Monatsübersicht)
   --------------------------------------------------------------------------- */

.calendar-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 8px;
}

.calendar-header,
.calendar-week {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 3px;
}

.calendar-header {
    margin-bottom: 6px;
}

.calendar-week {
    margin-bottom: 3px;
}

.calendar-header-cell {
    text-align: center;
    font-size: 0.6875rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
}

.calendar-day-container {
    min-width: 0;
    /* Quadratisch: auf 390 px ergeben sieben Spalten rund 46 px und damit ein
       Ziel, das man mit dem Daumen trifft. */
    aspect-ratio: 1 / 1;
}

.calendar-day {
    /* Auch als <button>: keine Browser-Optik, die Fläche kommt aus DayPalette. */
    appearance: none;
    -webkit-appearance: none;
    margin: 0;
    font: inherit;
    width: 100%;
    height: 100%;
    padding: 4px;
    border-radius: 8px;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    overflow: hidden;
}

.calendar-day.is-clickable {
    cursor: pointer;
}

.calendar-day.is-clickable:active {
    filter: brightness(0.94);
}

.calendar-day-number {
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1;
    text-align: left;
}

.calendar-day-note {
    font-size: 0.625rem;
    line-height: 1.1;
    text-align: right;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-variant-numeric: tabular-nums;
    opacity: 0.85;
    min-width: 0;
}

/* Abwesenheiten stehen als Symbol dort, wo bei erfassten Tagen die Zahl steht.
   "Feiertag" passte als Wort nicht in die knapp 38 px Textbreite einer Zelle.
   Zeit und Symbol bekommen je eine eigene Zeile (#148) — in einer gemeinsamen Zeile blieb von der
   Zeit nur die erste Ziffer übrig, weil Zeit, Halbtags-Markierung und Symbol sich eine Zeilenbreite
   von knapp 38 px teilen mussten. */
.calendar-day-mark {
    margin-top: auto;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 1px;
}

.calendar-day-icon-row {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 1px;
    line-height: 1;
}

.calendar-day-half {
    font-size: 0.625rem;
    line-height: 1;
}

/* MudIcon bringt seine eigene Größe mit, und selbst Size.Small ist in einer
   46-px-Zelle zu groß. Die Farbe erbt es aus der Zelle. */
.calendar-day-icon-row .mud-icon-root {
    width: 0.9375rem;
    height: 0.9375rem;
    font-size: 0.9375rem;
}

.calendar-day-empty {
    width: 100%;
    height: 100%;
}

/* Die Legende liegt jetzt hinter dem Info-Icon statt über dem Raster. */
.calendar-legend {
    padding: 8px 14px;
}

.calendar-legend-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 4px 0;
    font-size: 0.8125rem;
    white-space: nowrap;
}

.calendar-legend-swatch {
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    border-radius: 4px;
    /* Trägt bei Abwesenheiten dasselbe Symbol wie die Zelle, damit man beides
       an einer Stelle nachschlagen kann. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.calendar-legend-swatch .mud-icon-root {
    width: 0.8125rem;
    height: 0.8125rem;
    font-size: 0.8125rem;
}

/* ---------------------------------------------------------------------------
   Wochenübersicht

   Eine Zeile je Tag statt einer Karte mit vier Feldern. Farben und Symbole
   kommen aus derselben Quelle wie im Kalender — dieselben Tage dürfen nicht
   unterschiedlich aussehen, nur weil man sie anders gruppiert.
   --------------------------------------------------------------------------- */

.week-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.week-day {
    /* Auch als <button>: keine Browser-Optik, die Fläche kommt aus DayPalette. */
    appearance: none;
    -webkit-appearance: none;
    margin: 0;
    font: inherit;
    width: 100%;
    padding: 10px 12px;
    border-radius: 10px;
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: baseline;
    gap: 2px 10px;
    text-align: left;
}

.week-day.is-clickable {
    cursor: pointer;
}

.week-day.is-clickable:active {
    filter: brightness(0.96);
}

.week-day.is-today {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: -1px;
}

.week-day-date {
    font-size: 0.875rem;
    font-weight: 600;
    display: flex;
    align-items: baseline;
    gap: 6px;
    min-width: 0;
}

.week-day-today {
    font-size: 0.625rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    opacity: 0.75;
}

.week-day-main {
    justify-self: end;
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 1rem;
    font-weight: 600;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.week-day-main .mud-icon-root {
    width: 1rem;
    height: 1rem;
    font-size: 1rem;
}

.week-day-detail {
    grid-column: 1 / -1;
    font-size: 0.75rem;
    line-height: 1.3;
    opacity: 0.8;
}

/* ---------------------------------------------------------------------------
   Zeiterfassung

   Die laufende Zeit ist der Grund, warum man diese Seite öffnet. Sie bekommt
   den Platz, der Rest ist Beleg.
   --------------------------------------------------------------------------- */

.clock-hero {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    text-align: center;
    padding: 4px 0 16px;
}

.clock-state {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.8125rem;
    color: var(--mud-palette-text-secondary);
}

.clock-state .mud-icon-root {
    width: 1rem;
    height: 1rem;
    font-size: 1rem;
}

.clock-value {
    font-size: 2.75rem;
    font-weight: 600;
    line-height: 1.1;
    letter-spacing: -0.02em;
    /* Ohne feste Ziffernbreite springt die Uhr bei jedem Sekundenwechsel. */
    font-variant-numeric: tabular-nums;
}

.clock-value.is-running {
    color: var(--mud-palette-success);
}

.clock-value.is-break {
    color: var(--mud-palette-warning);
}

.clock-meta {
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
}

.clock-actions {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* Pausen: eine Zeile je Pause statt einer Tabelle mit vier Spalten. */
.break-list {
    display: flex;
    flex-direction: column;
}

.break-row {
    display: grid;
    grid-template-columns: auto auto 1fr;
    align-items: baseline;
    gap: 10px;
    padding: 7px 0;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    font-size: 0.875rem;
}

.break-row:last-child {
    border-bottom: none;
}

.break-span {
    font-variant-numeric: tabular-nums;
}

.break-duration {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.break-note {
    text-align: right;
    font-size: 0.6875rem;
    color: var(--mud-palette-text-secondary);
}

/* ---------------------------------------------------------------------------
   App-Bar

   Die Uhr in der Leiste. Vorher ein umrandeter Button mit dem Text
   "Arbeitszeit: 07:32:15" — in einer flachen Leiste aufgesetzt, und wegen der
   Sekunden änderte er jede Sekunde seine Breite.
   --------------------------------------------------------------------------- */

.mud-appbar {
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.appbar-clock {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 12px;
    border-radius: 999px;
    cursor: pointer;
    font-size: 0.9375rem;
    font-weight: 600;
    line-height: 1;
    /* Feste Ziffernbreite, damit die Leiste beim Ticken nicht wandert. */
    font-variant-numeric: tabular-nums;
    background-color: var(--mud-palette-background-gray);
}

.appbar-clock .mud-icon-root {
    width: 1.125rem;
    height: 1.125rem;
    font-size: 1.125rem;
}

.appbar-clock.is-running {
    color: var(--mud-palette-success);
}

.appbar-clock.is-break {
    color: var(--mud-palette-warning);
}

/* Der Zustand im Menü — ein Block statt einer Reihe deaktivierter Menüeinträge. */
.appbar-clock-summary {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 10px 16px 12px;
    min-width: 190px;
}

.appbar-clock-summary-value {
    font-size: 1.5rem;
    font-weight: 600;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
}

.appbar-clock-summary-value.is-running {
    color: var(--mud-palette-success);
}

.appbar-clock-summary-value.is-break {
    color: var(--mud-palette-warning);
}

/* Die Marke, sichtbar nur solange niemand angemeldet ist — siehe AppBar.razor. */
.appbar-brand {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.appbar-brand-text {
    font-weight: 600;
}


/* ---------------------------------------------------------------------------
   Überstunden — Saldo-Verlauf (nur wenn Überstunden nicht verfallen)
   --------------------------------------------------------------------------- */

.balance-chart-head {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 6px;
}

.balance-chart-head-label {
    font-size: 0.6875rem;
    color: var(--mud-palette-text-secondary);
}

.balance-chart-head-value {
    font-size: 1rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.balance-chart-head-value.is-positive {
    color: var(--mud-palette-success);
}

.balance-chart-head-value.is-negative {
    color: var(--mud-palette-error);
}

/* preserveAspectRatio="none" ist hier in Ordnung: es wird kein Text im SVG gezeichnet,
   und die Strichstärken hält vector-effect="non-scaling-stroke" konstant. */
.balance-chart-svg {
    width: 100%;
    height: 100px;
    display: block;
}

.balance-chart-zero {
    stroke: var(--mud-palette-lines-default);
    stroke-width: 1;
    stroke-dasharray: 2 3;
    vector-effect: non-scaling-stroke;
}

.balance-chart-line {
    fill: none;
    stroke: var(--mud-palette-primary);
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.balance-chart-dot {
    fill: var(--mud-palette-primary);
}

.balance-chart-months {
    display: grid;
    gap: 2px;
    margin-top: 4px;
}

.balance-chart-months span {
    text-align: center;
    font-size: 0.625rem;
    line-height: 1;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   Überstunden — Monatswerte

   Bewusst kein SVG: <text> ist in Razor ein reserviertes Konstrukt, dessen Tag
   beim Rendern verschwindet — ein <tspan> ohne <text>-Eltern zeichnet nichts,
   und genau daran ist die Beschriftung zweimal unsichtbar geblieben. Als
   HTML-Raster sind die Schriftgrößen außerdem echte CSS-Größen und werden nicht
   durch eine viewBox skaliert.
   --------------------------------------------------------------------------- */

.monthly-bars-grid {
    display: grid;
    gap: 2px;
    align-items: end;
}

.monthly-bar-col {
    appearance: none;
    -webkit-appearance: none;
    background: none;
    border: none;
    margin: 0;
    padding: 4px 0 6px;
    font: inherit;
    color: inherit;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    border-radius: 6px;
    cursor: pointer;
}

.monthly-bar-col.is-selected {
    background: var(--mud-palette-action-default-hover);
}

/* Am eigenen Balken statt in einer Kopfzeile — die genaue Höhe kommt inline aus der
   Komponente, weil sie von der Balkenhöhe abhängt. */
.monthly-bar-value {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    font-size: 0.625rem;
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.02em;
}

.monthly-bar-value.is-positive {
    color: var(--mud-palette-success);
}

.monthly-bar-value.is-negative {
    color: var(--mud-palette-error);
}

.monthly-bar-value.is-expired {
    color: var(--mud-palette-text-secondary);
}

/* Ein Monat ohne Abweichung ist eine echte Aussage und steht deshalb da — aber er soll die
   Monate mit Inhalt nicht überstimmen. */
.monthly-bar-value.is-zero {
    color: var(--mud-palette-text-secondary);
    font-weight: 400;
    opacity: 0.7;
}

/* Die Nulllinie liegt in der Mitte: darüber wächst ein Plus, darunter ein Minus.
   Höher als die Balken maximal werden, damit die Zahl über der Spitze noch Platz hat. */
.monthly-bar-plot {
    position: relative;
    width: 100%;
    height: 104px;
    display: block;
}

.monthly-bar-plot::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    border-top: 1px dashed var(--mud-palette-lines-default);
}

.monthly-bar-fill {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    width: 70%;
    max-width: 20px;
    /* Ein Monat mit Inhalt bleibt sichtbar, auch wenn er neben einem großen Ausschlag
       rechnerisch fast nichts ergibt. */
    min-height: 3px;
    border-radius: 3px;
}

.monthly-bar-fill.is-positive {
    bottom: 50%;
    background: var(--mud-palette-success);
}

.monthly-bar-fill.is-negative {
    top: 50%;
    background: var(--mud-palette-error);
}

/* Keine Füllung heißt: war da, ist es nicht mehr. Dieselbe Regel wie im Kalender,
   siehe docs/specs/2026-07-28-mobile-first-design.md. Durchgezogen statt gestrichelt:
   auf 20 px Breite zerfiel eine gestrichelte Kontur in einzelne Striche und sah aus
   wie ein Darstellungsfehler. */
.monthly-bar-fill.is-expired {
    bottom: 50%;
    background: none;
    border: 1.5px solid var(--mud-palette-success);
    opacity: 0.75;
}

/* Nur leicht abgesetzt: der laufende Monat ist noch nicht fertig, aber er ist auch die Zahl,
   wegen der man die Seite öffnet — ihn am blassesten zu zeichnen wäre verkehrt herum. */
.monthly-bar-fill.is-current {
    opacity: 0.8;
}

.monthly-bar-month {
    font-size: 0.625rem;
    line-height: 1;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.monthly-bar-col.is-selected .monthly-bar-month {
    color: var(--mud-palette-text-primary);
    font-weight: 600;
}

/* Immer eine Zahl im Blick, auch ohne Auswahl. */
.chart-readout {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 2px 8px;
    margin-bottom: 8px;
    min-height: 34px;
}

.chart-readout-month {
    font-size: 0.875rem;
    font-weight: 600;
}

.chart-readout-detail {
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
}

/* Welche Regel greift, direkt am Diagramm — nicht nur im Seitenkopf. */
.chart-rule {
    display: block;
    margin-top: 10px;
    font-size: 0.7rem;
    line-height: 1.35;
    color: var(--mud-palette-text-secondary);
}

/* ---------------------------------------------------------------------------
   Überstunden — Monatsliste

   Eine Zeile je Monat statt einer Tabelle mit sechs Spalten. MudTable stapelt
   die Spalten auf schmalen Schirmen untereinander — aus sechs Spalten wurden
   dort sechs Zeilen je Monat, also über siebzig Zeilen für ein Jahr.
   --------------------------------------------------------------------------- */

.balance-list {
    display: flex;
    flex-direction: column;
}

.balance-row {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: baseline;
    gap: 2px 10px;
    padding: 9px 4px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.balance-row:last-child {
    border-bottom: none;
}

.balance-month {
    display: flex;
    align-items: baseline;
    gap: 8px;
    font-size: 0.875rem;
    font-weight: 600;
    min-width: 0;
}

.balance-tag {
    font-size: 0.625rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--mud-palette-text-secondary);
}

/* Verfallen ist keine Warnung — es ist die Regel, die der Nutzer selbst eingestellt hat.
   Deshalb dieselbe zurückhaltende Auszeichnung wie die anderen Tags, nur mit Umriss. */
.balance-tag.is-expired {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 4px;
    padding: 0 4px;
}

.balance-main {
    justify-self: end;
    font-size: 1rem;
    font-weight: 600;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.balance-main.is-positive {
    color: var(--mud-palette-success);
}

.balance-main.is-negative {
    color: var(--mud-palette-error);
}

.balance-detail {
    grid-column: 1 / -1;
    font-size: 0.75rem;
    line-height: 1.3;
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
}

/* Erklärtexte hinter einem Info-Icon — dasselbe Muster wie die Kalenderlegende. */
.info-popover {
    padding: 12px 16px;
    max-width: 300px;
}

/* ---------------------------------------------------------------------------
   Dashboard

   Schnellzugriffe: auf dem Handy liegt die Navigation hinter dem Menüknopf.
   --------------------------------------------------------------------------- */

.quick-links {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 6px;
}

.quick-link {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px;
    border-radius: 10px;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
    background-color: var(--mud-palette-background-gray);
}

.quick-link .mud-icon-root {
    width: 1.25rem;
    height: 1.25rem;
    font-size: 1.25rem;
    color: var(--mud-palette-primary);
}

/* Arbeitstage in den Einstellungen: zwei feste Spalten, damit die Liste als
   Woche lesbar bleibt und nicht nach Wortlänge umbricht. */
.settings-days {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0 8px;
}

/* ---------------------------------------------------------------------------
   Jahreszahlen (Dashboard)

   Das Dashboard ist die Seite, auf der man landet — sie darf etwas hermachen.
   Der Akzent bleibt trotzdem sparsam: die Zahlen sind der Inhalt, nicht die
   Flächen um sie herum.
   --------------------------------------------------------------------------- */

.year-hero {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    text-align: center;
    padding: 22px 16px 24px;
    border-radius: 14px;
    color: var(--mud-palette-primary-text);
    background: linear-gradient(135deg,
        var(--mud-palette-primary) 0%,
        var(--mud-palette-primary-darken) 100%);
}

.year-hero-label {
    font-size: 0.75rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    opacity: 0.85;
}

.year-hero-value {
    font-size: 2.375rem;
    font-weight: 600;
    line-height: 1.1;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
}

.year-hero-meta {
    font-size: 0.8125rem;
    opacity: 0.85;
}

.tile-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
}

.tile {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 14px;
    border-radius: 12px;
    background-color: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    min-width: 0;
}

.tile-label {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.6875rem;
    line-height: 1.2;
    color: var(--mud-palette-text-secondary);
}

.tile-label .mud-icon-root {
    width: 0.875rem;
    height: 0.875rem;
    font-size: 0.875rem;
    color: var(--mud-palette-primary);
}

.tile-value {
    font-size: 1.375rem;
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: -0.01em;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.tile-meta {
    font-size: 0.6875rem;
    color: var(--mud-palette-text-secondary);
}

/* Rekorde: Bezeichnung links, Wert rechts, Datum darunter. */
.record-list {
    display: flex;
    flex-direction: column;
}

.record-row {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: baseline;
    gap: 2px 10px;
    padding: 8px 0;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.record-row:last-child {
    border-bottom: none;
}

.record-label {
    font-size: 0.875rem;
}

.record-value {
    justify-self: end;
    font-size: 1rem;
    font-weight: 600;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.record-meta {
    grid-column: 1 / -1;
    font-size: 0.6875rem;
    color: var(--mud-palette-text-secondary);
}

.record-meta:empty {
    display: none;
}

/* Umschalter Jahr / Gesamt — zwei Knöpfe in einer Spur, kein MudBlazor-Bauteil,
   damit die Optik zum Rest passt statt zum Framework. */
.summary-switch {
    display: flex;
    gap: 2px;
    padding: 3px;
    border-radius: 999px;
    background-color: var(--mud-palette-background-gray);
    /* Mit jedem Jahr wird die Spur länger — irgendwann passt sie nicht mehr auf
       ein Handy, also scrollt sie waagerecht statt umzubrechen. */
    overflow-x: auto;
    scrollbar-width: none;
}

.summary-switch::-webkit-scrollbar {
    display: none;
}

/* --- Das Perioden-Deck --------------------------------------------------------
   Alle geladenen Perioden nebeneinander, eine je Bildschirmbreite. Das Wischen
   macht der Browser über Scroll-Snap, mit der richtigen Physik — Touch-Events
   über den Circuit wären für eine Bewegung, die dem Finger folgt, zu langsam.

   Welche Periode eingerastet ist, meldet period-deck.js zurück; das kann CSS
   nicht, und der Umschalter soll zeigen, wo man ist (#187).
   ---------------------------------------------------------------------------- */

.summary-deck {
    display: flex;
    /* Abstand zwischen den Seiten: ohne ihn stoßen zwei Perioden aneinander und
       das Wischen liest sich, als rutschte eine Zahlenkolonne, statt dass ein
       Blatt weitergeht. Im Ruhezustand liegt der Abstand außerhalb des Bildes. */
    gap: 24px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    /* Keine Leiste: das Deck wird gewischt, nicht gezogen. Am Desktop bleibt der
       Umschalter die Bedienung. */
    scrollbar-width: none;
}

.summary-deck::-webkit-scrollbar {
    display: none;
}

.summary-deck-item {
    /* Genau eine Breite je Periode. Wo ein Abschnitt einrastet, rechnet das Modul
       aus seiner tatsächlichen Position statt aus index × Breite — sonst liefe
       der Abstand oben mit jedem Schritt weiter aus der Rechnung. */
    flex: 0 0 100%;
    min-width: 0;
    scroll-snap-align: start;
}

.summary-switch-option {
    appearance: none;
    -webkit-appearance: none;
    border: none;
    margin: 0;
    padding: 6px 16px;
    border-radius: 999px;
    font: inherit;
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1.2;
    cursor: pointer;
    color: var(--mud-palette-text-secondary);
    background-color: transparent;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    flex: 0 0 auto;
}

.summary-switch-option.is-active {
    color: var(--mud-palette-primary-text);
    background-color: var(--mud-palette-primary);
}

/* Ring plus Legende nebeneinander: der Ring zeigt das Verhältnis, die Legende
   die Zahlen. Einer allein kann beides nicht. */
.day-mix {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
}

.day-mix-chart {
    flex: 0 0 auto;
}

.day-mix-legend {
    flex: 1 1 150px;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.day-mix-row {
    display: grid;
    grid-template-columns: 10px 1fr auto;
    align-items: center;
    gap: 8px;
    font-size: 0.8125rem;
}

.day-mix-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
}

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

.day-mix-value {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* --- Urlaubsbalken -----------------------------------------------------------
   Zwei Töpfe in einem Balken, der Übertrag links: die Füllung frisst ihn zuerst,
   und damit ist die Verbrauchsreihenfolge zu sehen statt behauptet (#151).

   Getrennt wird über Fläche und Ton, nicht über einen zweiten Farbton — das
   Theme hat genau einen Akzent, und ein zweiter wäre einer zu viel. Die 2-px-
   Lücke trägt die Trennung notfalls allein.

   Die Breiten kommen als flex-grow aus den Tagen selbst, es wird nirgends ein
   Prozentwert gerechnet.
   --------------------------------------------------------------------------- */

.vacation-bar {
    display: flex;
    gap: 2px;
    height: 8px;
}

.vacation-bar-zone {
    display: flex;
    flex-basis: 0;
    overflow: hidden;
    border-radius: 999px;
    background-color: var(--mud-palette-lines-default);
}

/* Jede Zone mindestens so breit, dass ihre Beschriftung darunter lesbar bleibt.
   Darunter stimmt der Balken nicht mehr genau proportional — das ist der bessere
   Fehler: ein abgeschnittenes „Übertr…" erklärt nichts, und 5 von 35 Tagen wären
   auf dem Handy sonst 50 px breit.

   Die Werte gelten für Zone und Beschriftung gleichermaßen, sonst liegt das Label
   nicht mehr unter seiner Zone. */
.vacation-bar-zone.is-carry-over,
.vacation-bar-legend > span.is-carry-over {
    min-width: 5rem;
}

.vacation-bar-zone.is-annual,
.vacation-bar-legend > span.is-annual {
    min-width: 6.75rem;
}

/* Der eigene Topf: ein Hauch des Akzents hinter der Zone, damit sie als etwas
   anderes zu lesen ist als der Jahresanspruch daneben. */
.vacation-bar-zone.is-carry-over {
    background-color: var(--mud-palette-primary-hover);
}

.vacation-bar-seg {
    flex-basis: 0;
}

.vacation-bar-seg.is-used {
    background-color: var(--mud-palette-primary);
}

.is-carry-over .vacation-bar-seg.is-used {
    background-color: var(--mud-palette-primary-lighten);
}

/* Über dem Kontingent: dieselbe Aussage wie vorher, nur am gefüllten Abschnitt
   statt am ganzen Balken. */
.vacation-bar-seg.is-over {
    background-color: var(--mud-palette-error);
}

/* Schraffur statt Fläche: verfallene Tage waren da und sind weg. Eine volle
   Fläche würde sie wie genutzte Tage aussehen lassen. */
.vacation-bar-seg.is-expired {
    background-image: repeating-linear-gradient(
        135deg,
        var(--mud-palette-text-disabled) 0 2px,
        transparent 2px 4px
    );
}

/* Die Beschriftung liegt unter ihrer Zone, weil sie dieselben Wachstumsfaktoren
   benutzt. */
.vacation-bar-legend {
    display: flex;
    gap: 2px;
    margin-top: 4px;
    font-size: 0.6875rem;
    line-height: 1.2;
    color: var(--mud-palette-text-secondary);
}

.vacation-bar-legend > span {
    flex-basis: 0;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Die Aufmerksamkeits-Kachel auf dem Dashboard: anders als WorkSummary löst sie beim Antippen
   etwas aus, deshalb die Button-Optik statt reiner Information. */
.attention-tile {
    display: flex;
    align-items: center;
    width: 100%;
}

.attention-tile-open {
    appearance: none;
    -webkit-appearance: none;
    margin: 0;
    font: inherit;
    text-align: left;
    border: none;
    border-radius: 8px;
    cursor: pointer;
    background-color: var(--mud-palette-warning-hover);
    padding: 1rem;
}

.attention-tile-open:active {
    filter: brightness(0.94);
}

.attention-tile-chevron {
    margin-left: auto;
}

.attention-tile-clear {
    background-color: var(--mud-palette-success-hover);
}

/* ---------------------------------------------------------------------------
   Abgemeldet-Landingscreen (Dashboard.razor)

   Clocky hat keine eigene Login-Seite — "Anmelden" geht direkt zu Entra ID.
   Das hier ist damit der einzige gestaltbare Moment vor der Anmeldung.
   --------------------------------------------------------------------------- */

.login-landing {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    max-width: 380px;
    margin: 3rem auto 0;
    padding: 2.25rem 1.5rem 2.5rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 14px;
}

.login-landing-title {
    margin-top: 1.25rem;
    font-weight: 600;
}

.login-landing-lede {
    margin-top: 0.5rem;
    margin-bottom: 1.75rem;
}

/* ---------------------------------------------------------------------------
   ClockyLogo: Farbe und optionale Zeiger-Rotation

   Das SVG zeichnet mit currentColor, nicht mit var(--mud-palette-primary): auf einem gefüllten
   Primary-Knopf hätten Strich und Hintergrund sonst dieselbe Farbe und das Zeichen wäre
   unsichtbar. Die Standardfarbe steht deshalb hier, und wer die Farbe seines Kontexts braucht,
   hängt .clocky-logo-inherit an.
   --------------------------------------------------------------------------- */

.clocky-logo {
    color: var(--mud-palette-primary);
}

.clocky-logo-inherit {
    color: inherit;
}

@keyframes clocky-hand-spin {
    to {
        transform: rotate(360deg);
    }
}

.clocky-logo-hand-spin {
    /* Entspricht dem x1/y1-Drehpunkt des <line>-Elements im 100x100-viewBox von ClockyLogo. */
    transform-origin: 50px 50px;
    animation: clocky-hand-spin 1s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
    .clocky-logo-hand-spin {
        animation: none;
    }
}

/* ---------------------------------------------------------------------------
   ClockyLoader: das eine Wartezeichen (#130)

   Die Seitenvariante steht mittig und bekommt Luft nach oben — sie ersetzt Spinner, die vorher
   linksbündig an der Stelle klebten, an der der Inhalt beginnen würde.
   --------------------------------------------------------------------------- */

/* Der Loader erscheint erst nach einer Verzögerung, und zwar ohne Timer im C#: er steht sofort
   im DOM, ist aber 300 ms lang unsichtbar. Kommt die Antwort vorher — der Normalfall — wird er
   entfernt, bevor er je zu sehen war. Genau das ist der Unterschied zwischen "ruhig" und
   "blitzt bei jedem Klick".

   300 ms, weil darunter ein Ladeanzeiger die Wartezeit nicht erklärt, sondern nur Unruhe
   hinzufügt; ab etwa einer Sekunde braucht man ihn dagegen wirklich. */
.clocky-loader {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
    padding: 2.5rem 1rem;
    opacity: 0;
    animation: clocky-loader-appear 200ms ease-out 300ms forwards;
}

@keyframes clocky-loader-appear {
    to {
        opacity: 1;
    }
}

/* Im Panel waagerecht und schmal: das Panel bringt sein eigenes Padding mit, und der Loader darf
   nicht höher werden als der Inhalt, den er ersetzt. */
.clocky-loader-panel {
    flex-direction: row;
    justify-content: flex-start;
    gap: 0.5rem;
    padding: 0;
}

.clocky-loader-label {
    font-size: 0.875rem;
    color: var(--mud-palette-text-secondary);
}

/* ---------------------------------------------------------------------------
   Nachladen: der alte Inhalt bleibt stehen

   Beim Jahreswechsel auf dem Dashboard wurden alle Kacheln erst entfernt und sofort wieder
   aufgebaut — das las sich als Zucken, nicht als Laden. Wer schon etwas anzuzeigen hat, zeigt es
   weiter und macht es blass, statt es abzureißen: die Seite behält ihre Höhe, nichts springt,
   und die alte Zahl bleibt lesbar, bis die neue sie ersetzt.
   --------------------------------------------------------------------------- */

.is-refreshing {
    opacity: 0.45;
    /* Dieselben 300 ms Verzögerung wie beim Loader, und aus demselben Grund: ohne sie ist das
       Dimmen selbst ein Blitzen — die Deckkraft fällt und ist sofort wieder oben. Eine schnelle
       Antwort soll die Zahlen austauschen und sonst nichts tun.

       Das Zurückspringen auf volle Deckkraft ist bewusst ohne Übergang: die Klasse verschwindet
       mit den neuen Daten, und die sollen sofort scharf sein. */
    transition: opacity 150ms ease-out 300ms;
    /* Während des Nachladens sind die Zahlen von gestern - nicht anklickbar machen. */
    pointer-events: none;
}

/* ---------------------------------------------------------------------------
   Reconnect-Overlay (#116)

   blazor.web.js schaltet components-reconnect-show/-failed/-rejected auf
   #components-reconnect-modal um. Ohne eine dieser Klassen ist die Verbindung intakt und das
   Overlay bleibt unsichtbar.
   --------------------------------------------------------------------------- */

#components-reconnect-modal {
    display: none;
    position: fixed;
    inset: 0;
    /* MudBlazors höchstes klassenbasiertes Element (.mud-scroll-to-top) liegt bei 100; einzelne
       JS-gesteuerte Overlays (Snackbar, Popover) setzen inline noch höhere Werte. 9999 gewinnt
       unabhängig davon, was gerade offen ist, wenn der Circuit abbricht. */
    z-index: 9999;
    align-items: center;
    justify-content: center;
    background-color: rgba(0, 0, 0, .55);
}

#components-reconnect-modal.components-reconnect-show,
#components-reconnect-modal.components-reconnect-failed,
#components-reconnect-modal.components-reconnect-rejected {
    display: flex;
}

.reconnect-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    max-width: 320px;
    padding: 2rem 1.5rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 14px;
    background-color: var(--mud-palette-surface);
}

.reconnect-attempting,
.reconnect-failed,
.reconnect-rejected {
    display: none;
    margin-top: 1.25rem;
}

#components-reconnect-modal.components-reconnect-show .reconnect-attempting,
#components-reconnect-modal.components-reconnect-failed .reconnect-failed,
#components-reconnect-modal.components-reconnect-rejected .reconnect-rejected {
    display: block;
}

.reconnect-button {
    appearance: none;
    -webkit-appearance: none;
    margin-top: 0.75rem;
    padding: 8px 20px;
    border: none;
    border-radius: 999px;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
    color: var(--mud-palette-primary-text);
    background-color: var(--mud-palette-primary);
}

.reconnect-button:active {
    filter: brightness(0.94);
}

/* ---------------------------------------------------------------------------
   Settings: persistenter Speichern-Balken (#126)

   Der Button lebt außerhalb des scrollenden Formulars, fest am unteren Bildschirmrand —
   sonst verschwindet er beim Bearbeiten eines Feldes weiter oben aus dem sichtbaren Bereich.
   --------------------------------------------------------------------------- */

.settings-page {
    /* Reserviert Platz, damit der letzte Inhalt (der Info-Alert) nicht hinter der
       fixen Leiste verschwindet. Etwas großzügiger als deren Höhe (Button + Padding + Safe-Area). */
    padding-bottom: 128px;
}

/* --- Fehleranzeige -------------------------------------------------------------
   Mittig und ruhig: wer hier landet, hat schon genug Aufregung. Die technischen
   Angaben stecken in einem zugeklappten <details> — da, wenn man sie braucht,
   und sonst nicht im Weg.
   ------------------------------------------------------------------------------ */

.error-panel {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 48px 16px;
}

.error-panel-icon {
    width: 48px;
    height: 48px;
    margin-bottom: 16px;
    color: var(--mud-palette-text-disabled);
}

.error-panel-headline {
    margin-bottom: 6px;
}

.error-panel-detail {
    max-width: 34ch;
}

.error-panel-details {
    width: 100%;
    max-width: 30rem;
    margin-top: 40px;
    text-align: left;
}

.error-panel-details > summary {
    cursor: pointer;
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
    /* Der Standardmarker ist auf dem Handy winzig; die eigene Zeile ist leichter zu treffen. */
    padding: 8px 0;
}

/* Beschriftung und Wert untereinander statt nebeneinander: die Werte sind lang
   (Trace-Kennungen, Ausnahmemeldungen) und würden zweispaltig zerbrechen. */
.error-panel-facts {
    margin: 8px 0 0;
    font-size: 0.75rem;
}

.error-panel-facts dt {
    color: var(--mud-palette-text-secondary);
}

.error-panel-facts dd {
    margin: 0 0 10px;
    /* Kennungen brechen sonst aus dem Bild heraus. */
    overflow-wrap: anywhere;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* Die laufende Fassung, klein und am Ende der Seite. Sie steht dort für den einen
   Moment, in dem jemand wissen will, was gerade läuft — und sonst im Weg wäre. */
.settings-version {
    padding: 0 16px 8px;
    font-size: 0.6875rem;
    line-height: 1.2;
    color: var(--mud-palette-text-disabled);
    text-align: center;
}

.settings-save-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    /* Deutlich unter dem Reconnect-Overlay (9999, siehe dort) — ein Circuit-Abbruch auf dieser
       Seite muss weiterhin Vorrang haben. */
    z-index: 10;
    /* env(safe-area-inset-bottom) braucht viewport-fit=cover in App.razor, sonst 0 — hält den
       Button auf iPhones mit Home-Indicator von dessen Geste fern statt direkt daran zu kleben. */
    padding: 12px 16px calc(16px + env(safe-area-inset-bottom));
    background-color: var(--mud-palette-surface);
    border-top: 1px solid var(--mud-palette-lines-default);
}
