/* ============================================================
   Trainingsplan-Planer (workouts/plans/)
   ============================================================
   Wochenraster (Woche x Mo..So) mit Drag-&-Drop-Platzierung von
   Bike-, Swim-, Lauf- und Kraft-Workouts. Farben/Radien kommen aus
   tokens.css (--ds-*).
   ============================================================ */

.tp-planner {
    /* Sport-Akzente: klar unterscheidbare Farbtoene, zusaetzlich traegt jede
       Kachel ihr Sport-Icon (Farbe allein ist nie das einzige
       Unterscheidungsmerkmal). Kraft bekommt einen Stahlton - bewusst kein
       weiterer Buntton, damit er sich neben Rad/Schwimmen/Laufen nicht als
       vierte Ausdauersportart liest. */
    --tp-bike: #285180;
    --tp-bike-soft: #e8eff8;
    --tp-swim: #0f7f8c;
    --tp-swim-soft: #e2f4f6;
    --tp-run: #6f42c1;
    --tp-run-soft: #efe9fb;
    --tp-strength: #4a5568;
    --tp-strength-soft: #eceef2;
    /* Notizen: bewusst kein Sport-Ton, damit sie sich nicht wie eine vierte
       Sportart lesen. */
    --tp-note: var(--ds-warning, #dd9a2e);
    --tp-note-soft: var(--ds-warning-soft, #fff8e8);
    /* Schluesseleinheit: ein Gold-/Bernsteinton, aber NICHT der Notiz-Ton - die
       Markierung sitzt auf einer Sportkachel, die ihre Sportfarbe behaelt. Sie
       traegt deshalb keinen eigenen Hintergrund, nur Stern, Ring und Stern-Knopf
       (Farbe ist hier nie das einzige Merkmal). */
    --tp-key: #c8860d;

    --tp-cell-min-h: 104px;
    --tp-gap: 8px;

    /* Klebe-Offset des Wochenkopfes. --tp-topbar spiegelt style.css:--topbar-height
       (die Variable dort ist auf :root definiert und hier nur der Rueckfallwert). */
    --tp-topbar: var(--topbar-height, 54px);
    --tp-stick-top: calc(var(--tp-topbar) + 8px);
}

/* style.css setzt `overflow-x: hidden` zweimal (auf `.content`, das auch das
   <body> traegt, und auf `main.content`). Beide werden dadurch zu Scroll-
   Containern und `position: sticky` bleibt darin wirkungslos. `overflow-x: clip`
   schneidet identisch ab, erzeugt aber keinen Scrollport. Nur fuer diese View
   gescoped; Browser ohne :has()/clip ignorieren die Regel und bekommen eine
   normale, nicht klebende Leiste (kein Layoutbruch). */
body.content:has(.tp-planner),
body:has(.tp-planner) main.content {
    overflow-x: clip;
}

/* ---------- Kopfkarte des Planers ---------- */

/* Optik nach dem Referenz-Design der Tokens (nutrition/product_list.html):
   eine dunkle Verlaufskarte, oben Titel und Aktionen, darunter die Planfelder
   als helle Steuerelemente auf demselben Verlauf.

   Planer UND Athletenansicht (plan_viewer.html) benutzen diese Karte - derselbe
   Plan soll fuer Coach und Athlet nicht zwei Gestalten haben. Der Unterschied
   sind allein die Abschnitte: der Planer traegt zusaetzlich .tp-hero-body mit
   den Eingabefeldern, die Athletenansicht statt dessen die Sportverteilung. */
.tp-hero {
    background: linear-gradient(135deg, var(--ds-primary) 0%, var(--ds-secondary) 100%);
    border-radius: var(--ds-radius-lg);
    box-shadow: var(--ds-shadow-md);
    margin-bottom: 16px;
    overflow: hidden;
}

.tp-hero-top {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 1.5rem;
    padding: 1.6rem 2rem;
}

.tp-hero-title {
    color: var(--ds-white);
    font-size: 1.9rem;
    font-weight: 700;
    margin: 0;
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.tp-hero-subtitle {
    color: rgba(255, 255, 255, 0.75);
    font-size: 0.95rem;
    margin: 0.4rem 0 0;
}

.tp-hero-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.75rem;
}

.tp-hero-actions .btn { white-space: nowrap; }

/* Hauptaktion in den Farben des Login-Knopfes (auth/templates/login.html) -
   derselbe Griff, den das Referenz-Design fuer den hervorgehobenen Knopf auf
   dem Verlauf nutzt. Ein .btn-primary (#20324d) staende hier zu nah am
   Hintergrund und waere ausgerechnet leiser als die Sekundaerknoepfe. */
.tp-btn-cta {
    --bs-btn-font-weight: 600;
    --bs-btn-bg: var(--ds-warning);
    --bs-btn-border-color: var(--ds-warning);
    --bs-btn-color: var(--ds-secondary);
    --bs-btn-hover-bg: var(--ds-warning-dark);
    --bs-btn-hover-border-color: var(--ds-warning-dark);
    --bs-btn-hover-color: var(--ds-secondary);
    --bs-btn-active-bg: var(--ds-warning-dark);
    --bs-btn-active-border-color: var(--ds-warning-dark);
    --bs-btn-active-color: var(--ds-secondary);
}

/* Statuszeile des Planers ("Speichern …", Fehlermeldungen). Die Bootstrap-
   Textfarben (text-success/-danger) waeren auf dem dunklen Verlauf zu dunkel,
   deshalb faerbt das JS ueber Klassen, die hier aufgehellt werden. */
.tp-status {
    font-size: 0.85rem;
    color: rgba(255, 255, 255, 0.8);
}

.tp-status.text-success { color: #7ee2a0 !important; }
.tp-status.text-danger  { color: #ff9b9b !important; }
.tp-status.text-warning { color: #ffd68a !important; }

.tp-dirty-badge {
    display: none;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--ds-secondary);
    background: var(--ds-warning);
    border-radius: 999px;
    padding: 0.25rem 0.7rem;
    white-space: nowrap;
}

.tp-planner.is-dirty .tp-dirty-badge { display: inline-block; }

/* Planfelder auf dem Verlauf: helle Beschriftung, durchscheinende Felder. */
.tp-hero-body {
    padding: 1rem 2rem 1.25rem;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.tp-hero-body .form-label {
    font-size: 0.8rem;
    font-weight: 700;
    margin-bottom: 2px;
    color: rgba(255, 255, 255, 0.65);
}

/* background-COLOR statt der Kurzform: die Kurzform wuerde den Pfeil des
   <select> mit ausknipsen, den Bootstrap als Hintergrundbild einsetzt. */
.tp-hero-body .form-control,
.tp-hero-body .form-select {
    background-color: rgba(255, 255, 255, 0.1);
    border-color: rgba(255, 255, 255, 0.2);
    color: var(--ds-white);
}

/* Bootstraps Pfeil ist dunkelgrau (#343a40) und auf dem Verlauf unsichtbar. */
.tp-hero-body .form-select {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
}

.tp-hero-body .form-control::placeholder {
    color: rgba(255, 255, 255, 0.45);
}

.tp-hero-body .form-control:focus,
.tp-hero-body .form-select:focus {
    background-color: rgba(255, 255, 255, 0.16);
    border-color: rgba(255, 255, 255, 0.45);
    color: var(--ds-white);
    box-shadow: none;
}

/* Bootstrap hellt gesperrte Felder auf - auf dem Verlauf wuerden sie dadurch
   heller wirken als die bedienbaren. Hier andersherum: gedimmt statt aufgehellt. */
.tp-hero-body .form-control:disabled,
.tp-hero-body .form-select:disabled {
    background-color: rgba(255, 255, 255, 0.05);
    color: rgba(255, 255, 255, 0.55);
}

/* Das Aufklapp-Menue eines <select> zeichnet das Betriebssystem, nicht die
   Karte - ohne eigene Farbe staende dort weisse Schrift auf Weiss. */
.tp-hero-body .form-select option {
    background: #2c323b;
    color: #ffffff;
}

/* Planbeschreibung als Spoiler (<details>): das Label ist der Klick-Kopf, der
   Chevron dreht beim Oeffnen. Monospace, weil dort meist HTML-Code steht. */
.tp-description > summary {
    cursor: pointer;
    list-style: none;
    user-select: none;
}
.tp-description > summary::-webkit-details-marker { display: none; }
.tp-description > summary:hover { color: var(--ds-white); }
.tp-description[open] > summary { margin-bottom: 0.35rem; }
.tp-description-chevron {
    font-size: 0.65rem;
    margin-right: 0.3rem;
    transition: transform 0.15s ease;
}
.tp-description[open] .tp-description-chevron { transform: rotate(90deg); }
.tp-description textarea {
    font-family: var(--bs-font-monospace, monospace);
    min-height: 12rem;
    resize: vertical;
}

/* Shop-Block (Verkauf im oeffentlichen Shop): Schalter, Slug-Feld mit fester
   URL-Basis davor und die daraus entstehende oeffentliche Adresse. */
.tp-shop {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 0.5rem 1.25rem;
    padding: 0.6rem 0.75rem;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.04);
}
.tp-shop .form-check { margin-bottom: 0.2rem; }
.tp-shop .form-check-label {
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--ds-white);
}
.tp-shop-slug { flex: 1 1 22rem; min-width: 0; }
.tp-shop-slug .input-group-text {
    font-size: 0.75rem;
    background-color: rgba(255, 255, 255, 0.06);
    border-color: rgba(255, 255, 255, 0.2);
    color: rgba(255, 255, 255, 0.6);
    max-width: 55%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    display: block;
}
.tp-shop-info {
    flex: 1 1 100%;
    font-size: 0.8rem;
    color: rgba(255, 255, 255, 0.7);
    word-break: break-all;
}
.tp-shop-info a { color: var(--ds-white); }
.tp-shop-info .tp-shop-warn { color: #ffc107; }
.tp-shop-info .tp-shop-ok { color: #75d99a; }
.tp-field-hint {
    font-size: 0.75rem;
    color: rgba(255, 255, 255, 0.55);
    margin-top: 0.25rem;
}

.tp-hero-totals {
    padding: 0.9rem 2rem 1.1rem;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
}

/* Summenkacheln auf dem Verlauf - dieselbe Aufteilung wie in der
   Athletenansicht, nur durchscheinend statt hell. */
.tp-hero .tp-total {
    background: rgba(255, 255, 255, 0.08);
    border-color: rgba(255, 255, 255, 0.14);
}

.tp-hero .tp-total .tp-total-label { color: rgba(255, 255, 255, 0.6); }
.tp-hero .tp-total .tp-total-value { color: var(--ds-white); }

/* Sportverteilung der Athletenansicht, ebenfalls auf dem Verlauf. Der linke
   Balken behaelt seine Sportfarbe - er ist die Bruecke zu den Kacheln im
   Raster und traegt hier die einzige Aussage, die Farbe machen soll. */
.tp-hero .tp-sport-split { border-top-color: rgba(255, 255, 255, 0.12); }

.tp-hero .tp-sport-pill {
    background: rgba(255, 255, 255, 0.08);
    /* Nur drei Seiten: der linke Balken traegt die Sportfarbe und wird weiter
       unten je data-sport gesetzt - eine Kurzform 'border-color' wuerde ihn
       ueberschreiben. */
    border-top-color: rgba(255, 255, 255, 0.14);
    border-right-color: rgba(255, 255, 255, 0.14);
    border-bottom-color: rgba(255, 255, 255, 0.14);
    color: var(--ds-white);
}

.tp-hero .tp-sport-pill small { color: rgba(255, 255, 255, 0.6); }

@media (max-width: 767.98px) {
    .tp-hero-top { padding: 1.1rem 1rem; }
    .tp-hero-body { padding: 0.9rem 1rem 1rem; }
    .tp-hero-totals { padding: 0.8rem 1rem 1rem; }
    .tp-hero-title { font-size: 1.5rem; }
    .tp-hero-actions { width: 100%; }
    .tp-hero-actions .btn { flex: 1 1 auto; }
}

/* ---------- Kopfleiste der Athletenansicht ---------- */

/* Die Karte selbst ist .tp-hero (siehe oben) - hier steht nur noch, was es im
   Planer nicht gibt. */

/* Verteilung der Einheiten auf die Sportarten. Bewusst Pillen statt eines
   Balkendiagramms: gefragt ist "wieviel Schwimmen steckt drin", nicht eine
   Flaechenvergleich auf zwei Prozent genau - und die Zahl steht ohnehin dabei. */
.tp-sport-split {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--ds-border-soft);
}

.tp-sport-pill {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    font-size: 0.75rem;
    color: var(--ds-text);
    background: var(--ds-surface-alt);
    /* Der linke Balken traegt die Sportfarbe - derselbe Griff wie an den Kacheln
       im Raster, damit Kopf und Kalender ohne Legende zusammenfinden. */
    border: 1px solid var(--ds-border-soft);
    border-left: 4px solid var(--ds-border);
    border-radius: var(--ds-radius-sm);
    padding: 3px 9px;
}

.tp-sport-pill[data-sport="bike"] { border-left-color: var(--tp-bike); }
.tp-sport-pill[data-sport="swim"] { border-left-color: var(--tp-swim); }
.tp-sport-pill[data-sport="run"] { border-left-color: var(--tp-run); }
.tp-sport-pill[data-sport="strength"] { border-left-color: var(--tp-strength); }

.tp-sport-pill strong { font-variant-numeric: tabular-nums; }
.tp-sport-pill small { color: var(--ds-muted); }

.tp-totals {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.tp-total {
    background: var(--ds-surface-alt);
    border: 1px solid var(--ds-border-soft);
    border-radius: var(--ds-radius-sm);
    padding: 6px 12px;
    min-width: 104px;
}

.tp-total .tp-total-label {
    display: block;
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--ds-muted);
    white-space: nowrap;
}

/* Das Icon vor der Beschriftung ist reine Wiedererkennung (dasselbe Icon wie an
   der Kachel und im Wochenkopf) und darf die Grossschreibung nicht mitmachen. */
.tp-total .tp-total-label .bi { text-transform: none; }

.tp-total .tp-total-value {
    font-size: 1.05rem;
    font-weight: 700;
    line-height: 1.2;
}

/* ---------- Zweispaltiges Layout: Bibliothek + Kalender ---------- */

.tp-layout {
    display: grid;
    grid-template-columns: 300px minmax(0, 1fr);
    gap: 16px;
    align-items: start;
}

@media (max-width: 991.98px) {
    .tp-layout { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- Bibliothek ---------- */

.tp-library {
    background: var(--ds-surface);
    border-radius: var(--ds-radius-lg);
    box-shadow: var(--ds-shadow-sm);
    padding: 12px;
}

@media (min-width: 992px) {
    .tp-library {
        position: sticky;
        top: 124px;
        max-height: calc(100vh - 150px);
        display: flex;
        flex-direction: column;
    }
}

.tp-library-list {
    overflow-y: auto;
    /* clip statt hidden waere hier falsch: die Liste SOLL scrollen. */
    margin-top: 8px;
    padding-right: 4px;
    min-height: 120px;
}

@media (min-width: 992px) {
    .tp-library-list { flex: 1 1 auto; }
}

@media (max-width: 991.98px) {
    .tp-library-list { max-height: 320px; }
}

.tp-lib-card {
    border: 1px solid var(--ds-border-soft);
    border-left: 4px solid var(--ds-border);
    border-radius: var(--ds-radius-sm);
    background: var(--ds-surface);
    padding: 8px 10px;
    margin-bottom: 6px;
    cursor: grab;
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.tp-lib-card:hover {
    box-shadow: var(--ds-shadow-sm);
    transform: translateY(-1px);
}

.tp-lib-card:active { cursor: grabbing; }
.tp-lib-card.is-dragging { opacity: 0.45; }
/* Ohne Schreibrecht ist die Karte nicht ziehbar, nur anklickbar (Infokarte). */
.tp-lib-card[draggable="false"] { cursor: pointer; }
.tp-lib-card:focus-visible {
    outline: 2px solid var(--ds-primary, #153043);
    outline-offset: 2px;
}

.tp-lib-card[data-sport="bike"] { border-left-color: var(--tp-bike); }
.tp-lib-card[data-sport="swim"] { border-left-color: var(--tp-swim); }
.tp-lib-card[data-sport="run"] { border-left-color: var(--tp-run); }
.tp-lib-card[data-sport="strength"] { border-left-color: var(--tp-strength); }

.tp-lib-title {
    font-size: 0.85rem;
    font-weight: 700;
    line-height: 1.25;
    /* break-word statt anywhere: anywhere senkt die min-content-Breite und
       laesst benachbarte Rasterspalten kollabieren. */
    overflow-wrap: break-word;
}

.tp-lib-meta {
    font-size: 0.72rem;
    color: var(--ds-muted);
}

/* ---------- Ordner in der Bibliothek ---------- */

.tp-folder {
    border: 1px solid var(--ds-border-soft);
    border-radius: var(--ds-radius-sm);
    margin-bottom: 6px;
    background: var(--ds-surface-alt);
}

.tp-folder-head {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 8px;
    cursor: pointer;
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--ds-text);
    /* Eigener Pfeil (siehe ::before) statt des Browser-Dreiecks. */
    list-style: none;
}

.tp-folder-head::-webkit-details-marker { display: none; }

.tp-folder-head::before {
    content: "\f054";                 /* fa-chevron-right */
    font-family: "Font Awesome 6 Free";
    font-weight: 900;
    font-size: 0.7rem;
    color: var(--ds-muted);
    transition: transform 0.15s ease;
}

.tp-folder[open] > .tp-folder-head::before { transform: rotate(90deg); }

.tp-folder-head:hover { background: var(--ds-surface-soft); }

.tp-folder-name {
    margin-right: auto;
    overflow-wrap: break-word;
}

.tp-folder-count {
    background: var(--ds-surface);
    border: 1px solid var(--ds-border-soft);
    border-radius: 10px;
    padding: 0 6px;
    font-size: 0.68rem;
    font-weight: 600;
    color: var(--ds-muted);
}

.tp-folder-body {
    padding: 6px;
    background: var(--ds-surface);
    border-top: 1px solid var(--ds-border-soft);
    border-radius: 0 0 var(--ds-radius-sm) var(--ds-radius-sm);
}

.tp-folder-body .tp-lib-card:last-child { margin-bottom: 0; }

/* Gruppenueberschrift im Picker-Modal (dort ohne Aufklappen - die Liste ist
   kurz genug, und ein Klick soll direkt das Workout waehlen). */
.tp-picker-group {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--ds-muted);
    margin: 10px 2px 4px;
}

.tp-picker-list > .tp-picker-group:first-child { margin-top: 0; }

/* ---------- Leiste ueber dem Kalender ---------- */

/* Reine Ansichtssteuerung (Sportfilter, Zuklappen, Dichte, Wochensprung). Sie
   scrollt bewusst MIT: oben am Rand haengen soll nur der Wochenkopf - er sagt,
   wo man gerade ist, und das braucht man beim Scrollen staendig. Die Leiste
   dagegen holt man sich einmal und dann laenger nicht wieder; dauerhaft klebend
   hat sie dem Raster nur Platz weggenommen. */
.tp-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    background: var(--ds-surface);
    border: 1px solid var(--ds-border-soft);
    border-radius: var(--ds-radius-lg);
    box-shadow: var(--ds-shadow-sm);
    padding: 8px 10px;
    margin-bottom: 12px;
}

.tp-toolbar-group {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
}

.tp-toolbar-label {
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    font-weight: 700;
    color: var(--ds-muted);
}

/* Schalter der Leiste. Bewusst kein .btn: ein Filterchip ist ein Zustand, kein
   Befehl, und soll sich auch so lesen. */
.tp-chip {
    border: 1px solid var(--ds-border);
    background: var(--ds-surface);
    color: var(--ds-muted);
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.3;
    padding: 3px 10px;
    white-space: nowrap;
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.tp-chip:hover { border-color: var(--ds-accent); color: var(--ds-accent); }

.tp-chip.active {
    background: var(--ds-primary);
    border-color: var(--ds-primary);
    color: #fff;
}

/* Der aktive Sportchip traegt seine Sportfarbe - dieselbe, die die Kacheln im
   Raster tragen. So ist ohne Lesen klar, welcher Knopf zu welcher Spalte gehoert. */
.tp-chip[data-tp-view-sport="bike"].active { background: var(--tp-bike); border-color: var(--tp-bike); }
.tp-chip[data-tp-view-sport="swim"].active { background: var(--tp-swim); border-color: var(--tp-swim); }
.tp-chip[data-tp-view-sport="run"].active { background: var(--tp-run); border-color: var(--tp-run); }
.tp-chip[data-tp-view-sport="strength"].active { background: var(--tp-strength); border-color: var(--tp-strength); }

/* Ein abgewaehlter Chip bleibt sichtbar, aber ersichtlich aus - durchgestrichen
   waere zuviel, ein blosser Graustich zu leise. */
.tp-chip[data-tp-view-sport]:not(.active) {
    border-style: dashed;
    opacity: 0.7;
}

.tp-week-jump {
    width: auto;
    min-width: 150px;
    font-size: 0.75rem;
}

/* Der Hinweis auf den aktiven Filter erscheint nur, wenn wirklich gefiltert wird
   (Klasse setzt das JS am Wurzelelement). Er muss sein, weil der Filter auch die
   Summen beschneidet - eine halbe Wochenbilanz ohne Ansage waere eine Falle. */
.tp-filter-hint { display: none; }

.tp-planner.is-filtered .tp-filter-hint {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    font-size: 0.75rem;
    color: var(--ds-warning-dark, #c98a24);
    background: var(--tp-note-soft);
    border: 1px solid var(--tp-note);
    border-radius: 999px;
    padding: 2px 10px;
}

@media (max-width: 991.98px) {
    .tp-toolbar-group.ms-auto { margin-left: 0 !important; }
}

/* ---------- Kalender ---------- */

.tp-calendar { min-width: 0; }

.tp-week {
    background: var(--ds-surface);
    border-radius: var(--ds-radius-lg);
    box-shadow: var(--ds-shadow-sm);
    margin-bottom: 14px;
    /* clip statt hidden: `hidden` machte die Karte zum Scroll-Container, und darin
       bliebe der klebende Wochenkopf wirkungslos - dieselbe Falle wie bei .content
       (siehe Dateikopf). Abgeschnitten wird identisch, die runden Ecken bleiben.
       Nebenwirkung ist erwuenscht: der Kopf klebt genau solange, wie seine Woche
       im Bild ist, und wandert am Wochenende wieder mit hinaus. */
    overflow: clip;
}

.tp-week-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    background: var(--ds-primary);
    color: #fff;
    /* Klebt direkt unter dem Seitenkopf - als einziges Element der Seite: wer in
       Woche 9 nach unten scrollt, soll immer noch sehen, in welcher Woche er
       gerade ist und was sie traegt. Die Kalenderleiste darueber scrollt weg
       (siehe .tp-toolbar), ihre Hoehe geht deshalb nicht in den Offset ein. */
    position: sticky;
    top: var(--tp-stick-top);
    z-index: 2;
}

@media (max-width: 991.98px) {
    /* Unveraendert: auf schmalen Schirmen sitzt der Kopf ganz oben. */
    .tp-week-head { top: 0; }
}

/* Zuklapp-Knopf ganz links - vor dem Titel, weil er auf die ganze Zeile wirkt. */
.tp-week-toggle {
    border: 0;
    background: transparent;
    color: #fff;
    line-height: 1;
    padding: 2px 4px;
    border-radius: 4px;
    opacity: 0.85;
}

.tp-week-toggle:hover { background: rgba(255, 255, 255, 0.15); opacity: 1; }
.tp-week-toggle .bi,
.tp-week-toggle .fa-solid { transition: transform 0.15s ease; display: inline-block; }
.tp-week.is-collapsed .tp-week-toggle .bi,
.tp-week.is-collapsed .tp-week-toggle .fa-solid { transform: rotate(-90deg); }

.tp-week-title {
    font-weight: 700;
    font-size: 0.95rem;
    white-space: nowrap;
}

/* Wochenlast als Balken: die Periodisierung ueber die Wochen ist damit im
   Vorbeiscrollen lesbar, ohne Zahlen zu vergleichen. Die Hoehe traegt keine
   Aussage, nur die Breite - deshalb ein Balken und keine Flaeche. Die genaue
   Groesse samt Einheit steht im title-Attribut.
   `margin-right: auto` steht hier statt am Titel, damit der Balken den freien
   Platz der Zeile fuellt und die Statistik rechts buendig bleibt. */
.tp-week-load {
    flex: 1 1 90px;
    min-width: 60px;
    max-width: 260px;
    height: 6px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.18);
    margin-right: auto;
    overflow: hidden;
}

.tp-week-load-bar {
    display: block;
    height: 100%;
    border-radius: inherit;
    background: var(--ds-warning);
}

/* Eine leere Woche bleibt bewusst ohne Balken - die Luecke ist die Aussage. */

.tp-week-dates {
    font-size: 0.75rem;
    opacity: 0.8;
    font-weight: 400;
    margin-left: 8px;
}

.tp-week-stats {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    font-size: 0.76rem;
    opacity: 0.95;
}

.tp-week-actions .btn {
    --bs-btn-padding-y: 1px;
    --bs-btn-padding-x: 6px;
    --bs-btn-font-size: 0.75rem;
    color: #fff;
    border-color: rgba(255, 255, 255, 0.45);
}

.tp-week-actions .btn:hover {
    background: rgba(255, 255, 255, 0.15);
    color: #fff;
}

/* Das Raster scrollt bei Bedarf in SICH (nicht die Seite): style.css kappt
   horizontalen Seiten-Overflow ohnehin. */
.tp-week-body { overflow-x: auto; }

/* Zugeklappt bleibt nur der Kopf mit seinen Zahlen stehen. Das JS baut den Koerper
   gar nicht erst - diese Regel ist die Absicherung, falls doch etwas darin landet. */
.tp-week.is-collapsed { margin-bottom: 6px; }
.tp-week.is-collapsed .tp-week-body { display: none; }
.tp-week.is-collapsed .tp-week-head { position: static; }

.tp-week-grid {
    display: grid;
    grid-template-columns: repeat(7, minmax(132px, 1fr));
    gap: 1px;
    background: var(--ds-border-soft);
    min-width: 100%;
}

.tp-day {
    background: var(--ds-surface);
    min-height: var(--tp-cell-min-h);
    padding: 6px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.tp-day.is-weekend { background: var(--ds-surface-alt); }

.tp-day.is-dropzone {
    outline: 2px dashed var(--ds-accent);
    outline-offset: -3px;
    background: var(--ds-accent-light);
}

.tp-day-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    font-size: 0.72rem;
    color: var(--ds-muted);
    border-bottom: 1px solid var(--ds-border-soft);
    padding-bottom: 3px;
}

.tp-day-name { font-weight: 700; color: var(--ds-text); }

/* Die Tagessumme kann seit den Distanzen mehrteilig sein ("1:30 h · 42,5 km") und
   darf dann umbrechen, statt den Wochentag aus der Zeile zu draengen. */
.tp-day-sum {
    font-variant-numeric: tabular-nums;
    text-align: right;
    overflow-wrap: anywhere;
}

/* Gefilterte Tage: sagt an, dass hier mehr steht, als zu sehen ist. Ohne das
   sieht ein ausgefilterter Tag aus wie ein Ruhetag. */
.tp-day-hidden {
    font-size: 0.68rem;
    color: var(--ds-muted);
    font-style: italic;
    border: 1px dashed var(--ds-border-soft);
    border-radius: var(--ds-radius-sm);
    padding: 1px 5px;
    text-align: center;
}

/* Schiebt die Knopfzeile ans Zellenende, egal wieviel darueber steht - das
   `margin-top: auto` sass frueher am Knopf selbst und wuerde jetzt nur noch
   den ersten von beiden ausrichten. */
.tp-day-actions {
    margin-top: auto;
    display: flex;
    align-items: stretch;
    gap: 4px;
}

.tp-day-add {
    border: 1px dashed var(--ds-border);
    background: transparent;
    color: var(--ds-muted);
    border-radius: var(--ds-radius-sm);
    font-size: 0.72rem;
    padding: 2px 4px;
    flex: 1 1 auto;
    min-width: 0;
    opacity: 0;
    transition: opacity 0.15s ease;
}

/* Der Notiz-Knopf traegt nur sein Icon und bleibt deshalb schmal - die Breite
   soll dem Workout-Knopf gehoeren, der die haeufigere Aktion ist. */
.tp-day-add-note { flex: 0 0 auto; }

/* Ist die Zelle voll, steht der Hinweis an der Stelle des Workout-Knopfs und
   nimmt dessen Breite ein - der Notiz-Knopf bleibt daneben bedienbar. */
.tp-day-actions .tp-item-full {
    flex: 1 1 auto;
    min-width: 0;
    align-self: center;
}

.tp-day:hover .tp-day-add,
.tp-day:focus-within .tp-day-add { opacity: 1; }

.tp-day-add:hover {
    border-style: solid;
    border-color: var(--ds-accent);
    color: var(--ds-accent);
}

.tp-day-add-note:hover {
    border-color: var(--tp-note);
    color: var(--tp-note);
}

/* Touch-Geraete kennen kein :hover - dort immer sichtbar lassen. */
@media (hover: none) {
    .tp-day-add { opacity: 1; }
}

/* ---------- Platzierte Workout-Kachel ---------- */

.tp-item {
    border-radius: var(--ds-radius-sm);
    border: 1px solid var(--ds-border-soft);
    border-left: 4px solid var(--ds-border);
    padding: 5px 6px;
    cursor: grab;
    position: relative;
    font-size: 0.76rem;
    line-height: 1.25;
}

.tp-item:active { cursor: grabbing; }
.tp-item.is-dragging { opacity: 0.4; }

.tp-item[data-sport="bike"] {
    border-left-color: var(--tp-bike);
    background: var(--tp-bike-soft);
}

.tp-item[data-sport="swim"] {
    border-left-color: var(--tp-swim);
    background: var(--tp-swim-soft);
}

.tp-item[data-sport="run"] {
    border-left-color: var(--tp-run);
    background: var(--tp-run-soft);
}

.tp-item[data-sport="strength"] {
    border-left-color: var(--tp-strength);
    background: var(--tp-strength-soft);
}

.tp-item.is-missing {
    border-left-color: var(--ds-danger);
    background: var(--ds-danger-soft);
}

/* Schluesseleinheit: Ring um die ganze Kachel, damit sie im vollen Raster auch
   dann auffaellt, wenn der Blick nicht am Titel haengt. Der linke Sportbalken
   bleibt unangetastet - die Sportart bleibt die erste Information. */
.tp-item.is-key {
    border-color: var(--tp-key);
    box-shadow: inset 0 0 0 1px var(--tp-key);
}

/* Steht in der Kopfzeile neben der Sportart (frueher vor dem Titel). */
.tp-key-star {
    color: var(--tp-key);
    flex: 0 0 auto;
}

/* ---------- Kopfzeile der Kachel: Sportart + Knoepfe ---------- */

/* Erste von drei Lagen (siehe training_plan_planner.js:buildItemEl). Sie traegt
   die Sportart im Klartext und rechts die Knopfreihe - dadurch bleibt die
   Titelzeile darunter frei. Bewusst nowrap: braeche die Zeile um, stuenden die
   Knoepfe unter der Sportart statt neben ihr. */
.tp-item-head {
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    gap: 4px;
    min-width: 0;
    font-size: 0.66rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    line-height: 1.4;
}

/* Der Name der Sportart traegt ihren Farbton - denselben wie der linke Balken der
   Kachel. Mit dem Icon sind das drei Merkmale (Wort, Form, Farbe), von denen
   keines allein tragen muss. */
.tp-item-type {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    min-width: 0;
    /* Lange Namen kuerzen, statt die Knoepfe aus der Zeile zu schieben. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--ds-muted);
}

.tp-item[data-sport="bike"] .tp-item-type { color: var(--tp-bike); }
.tp-item[data-sport="swim"] .tp-item-type { color: var(--tp-swim); }
.tp-item[data-sport="run"] .tp-item-type { color: var(--tp-run); }
.tp-item[data-sport="strength"] .tp-item-type { color: var(--tp-strength); }
/* Zeigt die Platzierung ins Leere, ist das die wichtigste Aussage der Kachel. */
.tp-item.is-missing .tp-item-type { color: var(--ds-danger); }

/* Die Knopfreihe sitzt am rechten Rand DER KOPFZEILE, nicht absolut ueber der
   Kachel: dadurch braucht der Titel keine reservierte Einrueckung mehr, und in
   der Athletenansicht faellt die Reihe ersatzlos weg. */
.tp-item-actions {
    display: flex;
    align-items: center;
    gap: 1px;
    margin-left: auto;
    flex: 0 0 auto;
}

/* .tp-item-copy und .tp-item-remove benutzt auch die NOTIZ-Kachel, wo sie
   weiterhin absolut oben rechts sitzen (buildNoteEl). Deshalb wird die absolute
   Lage hier gezielt fuer die Knopfreihe der Workout-Kachel zurueckgenommen,
   statt sie an den Klassen selbst zu aendern. */
.tp-item-actions > button {
    position: static;
    top: auto;
    right: auto;
}

/* Stern-Knopf: erster Platz in der Knopfreihe (dann Kopieren, dann das X). Er
   kommt - anders als die beiden anderen - nur an der Workout-Kachel vor und
   braucht deshalb gar keine absolute Lage. */
.tp-item-key {
    border: 0;
    background: transparent;
    color: var(--ds-muted);
    line-height: 1;
    font-size: 0.72rem;
    padding: 2px 3px;
    border-radius: 4px;
}

.tp-item-key.is-on { color: var(--tp-key); }

.tp-item-key:hover {
    background: var(--tp-key);
    color: #fff;
}

/* Zweite Lage: der Titel bekommt die volle Breite der Kachel. Die frueher noetige
   Reserve fuer die Knoepfe entfaellt - sie stehen jetzt in der Kopfzeile. */
.tp-item-title {
    font-weight: 700;
    overflow-wrap: break-word;
    margin-top: 1px;
}

/* Dritte Lage: die Kennzahlen, durch eine Linie vom Titel abgesetzt. Die Linie
   entsteht nur, wenn darunter auch etwas steht (siehe buildItemEl bzw. die
   gleiche Bedingung in plan_viewer.html). */
.tp-item-sep {
    margin: 4px 0 3px;
    border: 0;
    border-top: 1px solid currentColor;
    color: var(--ds-border);
    opacity: 0.6;
}

.tp-item-meta {
    color: var(--ds-muted);
    font-size: 0.7rem;
    display: flex;
    flex-wrap: wrap;
    /* Spaltenabstand groesser als Zeilenabstand: die Kennzahlen sind eine
       Aufzaehlung in einer Zeile, keine Liste untereinander. */
    gap: 1px 8px;
    font-variant-numeric: tabular-nums;
}

.tp-item-note {
    margin-top: 2px;
    font-size: 0.68rem;
    font-style: italic;
    color: var(--ds-muted);
    overflow-wrap: break-word;
}

/* ---------- Intervall-Vorschau (Bike/Lauf/Swim) ---------- */

/* Die Silhouette eines Workouts: Kachel im Raster, Karte in der Bibliothek und
   Zeile im Picker-Dialog zeigen dasselbe Bild. Die Balkenkoordinaten kommen
   serverseitig als Prozentwerte eines 100x100-viewBox (siehe
   workouts/interval_preview.py) und werden per preserveAspectRatio="none" auf
   die jeweilige Breite gestreckt - die Hoehe steht deshalb hier und nur hier. */
.tp-profile {
    display: block;
    width: 100%;
    height: 18px;
    margin-top: 4px;
    overflow: visible;
}

.tp-profile rect { shape-rendering: crispEdges; }

/* Gestrichelte Referenzlinie (Bike: 100 %FTP, Lauf: 100 %SP). */
.tp-profile-threshold {
    stroke: rgba(15, 20, 30, 0.3);
    stroke-width: 1;
    stroke-dasharray: 3 3;
}

/* In Bibliothek und Picker steht die Vorschau in einer Liste, die man
   ueberfliegt - dort reicht ein flacheres Bild. */
.tp-lib-card .tp-profile,
.tp-picker-row .tp-profile { height: 15px; }

/* Die Picker-Zeile ist ein Flex-Container; ohne Breitenangabe im Textblock
   haette das SVG (width: 100%) keinen Bezug. */
.tp-picker-row > span {
    display: block;
    flex: 1 1 auto;
    min-width: 0;
}

/* Sieben Intensitaetsstufen (Spec Phase 4 §9) - dieselben Farben wie im
   Builder-Chart und in den Vorschauen der Workout-Verwaltung
   (bike_workouts_manage.html / run_workouts_manage.html). Eigene Klassennamen,
   weil der Planer deren workout_list.css nicht laedt. */
.tp-zone-1 { fill: #64748b; }
.tp-zone-2 { fill: #2563eb; }
.tp-zone-3 { fill: #16a34a; }
.tp-zone-4 { fill: #65a30d; }
.tp-zone-5 { fill: #f59e0b; }
.tp-zone-6 { fill: #ea580c; }
.tp-zone-7 { fill: #dc2626; }

/* Schwimmen hat FUENF Stufen und eine eigene Palette - dieselben Farben wie die
   Saeulen im Schwimm-Builder-Chart (swim_builder_chart.html: .int-1 .. .int-5).
   Bewusst nicht mit .tp-zone-* zusammengelegt: Stufe 5 heisst beim Schwimmen
   etwas anderes als beim Radfahren, gleiche Farbe waere eine falsche Fährte. */
.tp-swim-zone-1 { fill: #808080; }
.tp-swim-zone-2 { fill: #2A4D7F; }
.tp-swim-zone-3 { fill: #58A7A9; }
.tp-swim-zone-4 { fill: #D8A32A; }
.tp-swim-zone-5 { fill: #D83C3C; }

.tp-item-remove {
    position: absolute;
    top: 2px;
    right: 2px;
    border: 0;
    background: transparent;
    color: var(--ds-muted);
    line-height: 1;
    padding: 1px 3px;
    border-radius: 4px;
}

.tp-item-remove:hover {
    background: var(--ds-danger);
    color: #fff;
}

/* Kopieren sitzt links neben dem X: gleicher Anker, nur weiter innen. Etwas
   kleiner als das X, damit das Kopier-Icon (fa-copy) die schmale Kachel
   optisch nicht dominiert. */
.tp-item-copy {
    position: absolute;
    top: 2px;
    right: 18px;
    border: 0;
    background: transparent;
    color: var(--ds-muted);
    line-height: 1;
    font-size: 0.72rem;
    padding: 2px 3px;
    border-radius: 4px;
}

.tp-item-copy:hover {
    background: var(--ds-accent);
    color: #fff;
}

.tp-item-full {
    font-size: 0.7rem;
    color: var(--ds-muted);
    text-align: center;
    padding: 2px;
}

/* ---------- Freie Tagesnotiz ---------- */

/* Bewusst anders geschnitten als eine Workout-Kachel: gestrichelter Rand und
   ein Notiz-Icon statt eines Sport-Icons. Eine Notiz ist keine Einheit, und das
   soll man sehen, ohne den Text zu lesen. */
.tp-note {
    border-radius: var(--ds-radius-sm);
    border: 1px dashed var(--tp-note);
    border-left: 4px solid var(--tp-note);
    background: var(--tp-note-soft);
    padding: 5px 6px;
    cursor: grab;
    position: relative;
    font-size: 0.76rem;
    line-height: 1.25;
}

.tp-note:active { cursor: grabbing; }
.tp-note.is-dragging { opacity: 0.4; }

/* Einfuegelinie beim Umsortieren per Drag & Drop (training_plan_planner.js:
   onCellDragOver): zeigt, ob die gezogene Kachel vor oder hinter der unter dem
   Cursor landet. Als Pseudo-Element in der Luecke zwischen den Kacheln (gap der
   .tp-day: 4px), damit sich das Raster beim Ziehen nicht verschiebt. Beide
   Kacheln sind position: relative. */
.tp-item.is-drop-before::before,
.tp-item.is-drop-after::after,
.tp-note.is-drop-before::before,
.tp-note.is-drop-after::after {
    content: "";
    position: absolute;
    left: -2px;
    right: -2px;
    height: 3px;
    border-radius: 2px;
    background: var(--ds-accent);
    pointer-events: none;
}

.tp-item.is-drop-before::before,
.tp-note.is-drop-before::before { top: -4px; }

.tp-item.is-drop-after::after,
.tp-note.is-drop-after::after { bottom: -4px; }

.tp-note.is-drop-before::before,
.tp-note.is-drop-after::after { background: var(--tp-note); }

.tp-note-title {
    font-weight: 700;
    overflow-wrap: break-word;
    padding-right: 36px;
}

/* Lange Notizen kuerzen statt die Zeile in die Hoehe zu treiben - der volle
   Text steht im title-Attribut und im Bearbeiten-Dialog. */
.tp-note-body {
    margin-top: 2px;
    font-size: 0.7rem;
    color: var(--ds-muted);
    overflow-wrap: break-word;
    white-space: pre-line;
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* ---------- Kompaktes Raster ---------- */

/* Ein Zwischenschritt zwischen "alles offen" und "alles zugeklappt": die Kacheln
   verlieren ihre Kennzahlen- und Notizzeilen und behalten nur Sportfarbe, Icon
   und Titel. Damit passen gut doppelt so viele Wochen auf den Schirm, und die
   Struktur des Blocks (welcher Tag traegt was) bleibt trotzdem lesbar. */
.tp-planner.is-compact {
    --tp-cell-min-h: 66px;
}

.tp-planner.is-compact .tp-item,
.tp-planner.is-compact .tp-note {
    padding: 2px 5px;
    font-size: 0.72rem;
}

.tp-planner.is-compact .tp-item-body,
.tp-planner.is-compact .tp-item-sep,
.tp-planner.is-compact .tp-note-body,
.tp-planner.is-compact .tp-attachments,
.tp-planner.is-compact .tp-day-hidden { display: none; }

/* Die Kopfzeile bleibt auch im dichten Raster stehen - eine Zeile Grossbuchstaben
   ist billig, und sie traegt die Knoepfe. Sie rueckt nur enger zusammen. */
.tp-planner.is-compact .tp-item-head {
    font-size: 0.6rem;
    line-height: 1.2;
}

/* Der Titel bleibt einzeilig und wird gekuerzt - im kompakten Raster zaehlt, DASS
   an dem Tag eine Radeinheit steht; der volle Titel steht im Tooltip. */
.tp-planner.is-compact .tp-item-title,
.tp-planner.is-compact .tp-note-title {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Die Silhouette bleibt im dichten Raster stehen, nur flacher: sie sagt auf einen
   Blick, ob der Tag eine Grundlagen- oder eine Intervalleinheit traegt - genau die
   Frage, die man sich beim Ueberblick ueber viele Wochen stellt. */
.tp-planner.is-compact .tp-profile {
    height: 11px;
    margin-top: 2px;
}

.tp-planner.is-compact .tp-week-grid { grid-template-columns: repeat(7, minmax(104px, 1fr)); }
.tp-planner.is-compact .tp-week { margin-bottom: 8px; }

/* ---------- Workout-Beschreibung im Item-Dialog ---------- */

/* Der Dialog zeigt beim Klick auf eine Kachel das ganze Workout: Kennzahlen,
   Profil und darunter jedes Intervall in einer Zeile. Kompakt heisst hier: eine
   Zeile je Intervall statt aufklappbarer Karten wie im Viewer - wer das Workout
   bearbeiten will, ist mit "Workout oeffnen" einen Klick entfernt. */

.tp-detail-metrics {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 6px;
    margin-bottom: 8px;
}

.tp-detail-metric {
    display: inline-flex;
    align-items: baseline;
    gap: 4px;
    padding: 2px 8px;
    border: 1px solid var(--ds-border-soft);
    border-radius: 999px;
    background: var(--ds-surface-alt);
    font-size: 0.75rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.tp-detail-metric-label {
    color: var(--ds-muted);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    font-size: 0.65rem;
}

/* Das Profil ist hier die Uebersicht ueber das ganze Workout und darf deshalb
   deutlich hoeher sein als auf der Kachel. */
.tp-detail-profile {
    padding: 6px 8px;
    border: 1px solid var(--ds-border-soft);
    border-radius: var(--ds-radius-sm);
    background: var(--ds-surface-alt);
    margin-bottom: 10px;
}

.tp-detail-profile .tp-profile {
    height: 96px;
    margin-top: 0;
}

.tp-detail-description {
    font-size: 0.82rem;
    color: var(--ds-text);
    white-space: pre-line;
    margin-bottom: 10px;
}

.tp-detail-heading {
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--ds-muted);
    margin-bottom: 4px;
}

.tp-detail-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.tp-detail-row {
    border: 1px solid var(--ds-border-soft);
    border-radius: var(--ds-radius-sm);
    background: var(--ds-surface);
    padding: 6px 8px;
}

.tp-detail-row-head {
    display: flex;
    align-items: flex-start;
    gap: 8px;
}

/* Die Nummer haelt die Reihenfolge fest - sie ist beim Nachfragen am Becken oder
   am Telefon die kuerzeste Verstaendigung ("Satz 3"). */
.tp-detail-index {
    flex: 0 0 auto;
    min-width: 18px;
    height: 18px;
    border-radius: 4px;
    background: var(--ds-surface-alt);
    border: 1px solid var(--ds-border-soft);
    color: var(--ds-muted);
    font-size: 0.68rem;
    font-weight: 700;
    line-height: 16px;
    text-align: center;
}

.tp-detail-row-main { min-width: 0; }

.tp-detail-row-title {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 0.82rem;
    font-weight: 700;
    overflow-wrap: break-word;
}

.tp-detail-row-summary {
    font-size: 0.78rem;
    color: var(--ds-text);
    font-variant-numeric: tabular-nums;
    overflow-wrap: break-word;
}

/* Farbpunkt der Intensitaetsstufe. Die Palette liegt weiter oben bei der
   Vorschau (.tp-zone-* / .tp-swim-zone-*) und faerbt dort SVG-Balken ueber
   'fill' - hier ist es ein span, deshalb zusaetzlich 'background'. */
.tp-detail-dot {
    flex: 0 0 auto;
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
}

.tp-detail-dot.tp-zone-1 { background: #64748b; }
.tp-detail-dot.tp-zone-2 { background: #2563eb; }
.tp-detail-dot.tp-zone-3 { background: #16a34a; }
.tp-detail-dot.tp-zone-4 { background: #65a30d; }
.tp-detail-dot.tp-zone-5 { background: #f59e0b; }
.tp-detail-dot.tp-zone-6 { background: #ea580c; }
.tp-detail-dot.tp-zone-7 { background: #dc2626; }
.tp-detail-dot.tp-swim-zone-1 { background: #808080; }
.tp-detail-dot.tp-swim-zone-2 { background: #2A4D7F; }
.tp-detail-dot.tp-swim-zone-3 { background: #58A7A9; }
.tp-detail-dot.tp-swim-zone-4 { background: #D8A32A; }
.tp-detail-dot.tp-swim-zone-5 { background: #D83C3C; }

/* Zusatzfelder (Trittfrequenz, Pausen, Tempo ...) - eingerueckt auf die Hoehe
   des Titels, damit die Nummernspalte frei bleibt. */
.tp-detail-field {
    margin-left: 26px;
    font-size: 0.74rem;
    color: var(--ds-muted);
}

.tp-detail-field-label {
    font-weight: 600;
    margin-right: 5px;
}

.tp-detail-segments {
    margin: 4px 0 0 26px;
    padding-left: 8px;
    border-left: 2px solid var(--ds-border-soft);
}

.tp-detail-segments-head {
    font-size: 0.66rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--ds-muted);
}

.tp-detail-segment {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 0.75rem;
    font-variant-numeric: tabular-nums;
}

.tp-detail-segment-note {
    color: var(--ds-muted);
    font-style: italic;
}

.tp-detail-segment-note::before { content: "\2013\00a0"; }

/* Schmal (Telefon): Die Notiz bekaeme als eigene Flex-Spalte die halbe Breite, und
   der Abschnittstext braeche eng um ("1 km — 100–" / "103 %SP"). Darunter in eine
   eigene Zeile, buendig mit dem Text, ohne Gedankenstrich - die Zeile selbst trennt
   schon. Grid statt flex-wrap: der Text ist ein anonymer Textknoten; mit flex-wrap
   rutschte ein langer Text ganz unter den Punkt. Der Punkt sitzt auf der ersten
   Textzeile, auch wenn der Text umbricht. Gilt fuer Planer-Dialog, Plan-Viewer und Shop. */
@media (max-width: 575.98px) {
    .tp-detail-segment {
        display: grid;
        grid-template-columns: 8px minmax(0, 1fr);
        column-gap: 5px;
        row-gap: 0;
        align-items: start;
    }

    .tp-detail-segment > .tp-detail-dot {
        margin-top: calc((1.5em - 8px) / 2);
    }

    .tp-detail-segment-note {
        grid-column: 2;
    }

    .tp-detail-segment-note::before { content: none; }
}

.tp-detail-note {
    margin: 3px 0 0 26px;
    font-size: 0.74rem;
    font-style: italic;
    color: var(--ds-muted);
    overflow-wrap: break-word;
}

.tp-detail-hint {
    font-size: 0.8rem;
    color: var(--ds-muted);
    padding: 10px 0;
}

/* Trennt die Beschreibung des Workouts von den Feldern DIESER Platzierung -
   oberhalb steht, was in jedem Plan gleich ist, unterhalb, was nur hier gilt. */
.tp-detail-sep {
    margin: 14px 0 12px;
    border: 0;
    border-top: 1px solid var(--ds-border);
    opacity: 0.7;
}

/* ---------- Picker-Modal ---------- */

.tp-picker-list {
    max-height: 52vh;
    overflow-y: auto;
}

.tp-picker-row {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    text-align: left;
    border: 1px solid var(--ds-border-soft);
    border-left: 4px solid var(--ds-border);
    border-radius: var(--ds-radius-sm);
    background: var(--ds-surface);
    padding: 8px 10px;
    margin-bottom: 6px;
}

.tp-picker-row[data-sport="bike"] { border-left-color: var(--tp-bike); }
.tp-picker-row[data-sport="swim"] { border-left-color: var(--tp-swim); }
.tp-picker-row[data-sport="run"] { border-left-color: var(--tp-run); }
.tp-picker-row[data-sport="strength"] { border-left-color: var(--tp-strength); }
.tp-picker-row:hover { background: var(--ds-surface-alt); }

.tp-empty {
    color: var(--ds-muted);
    font-size: 0.8rem;
    text-align: center;
    padding: 18px 8px;
}

/* ---------- Read-only Viewer ---------- */

/* Die Woche ist dort ein <details>, ihr Kopf das <summary> - Zuklappen ohne eine
   Zeile JavaScript. Das Browser-Dreieck weicht dem eigenen Chevron links. */
.tp-viewer details.tp-week > summary.tp-week-head {
    cursor: pointer;
    list-style: none;
}

.tp-viewer summary.tp-week-head::-webkit-details-marker { display: none; }
.tp-viewer details.tp-week:not([open]) > .tp-week-head { position: static; }
.tp-viewer details.tp-week:not([open]) .tp-week-toggle .bi,
.tp-viewer details.tp-week:not([open]) .tp-week-toggle .fa-solid { transform: rotate(-90deg); }
.tp-viewer details.tp-week:not([open]) { margin-bottom: 6px; }

/* Der Chevron ist im Viewer ein <span> und braucht seine eigene Groesse. */
.tp-viewer .tp-week-toggle { font-size: 0.85rem; }

.tp-viewer .tp-day-add,
.tp-viewer .tp-day-actions { display: none; }
.tp-viewer .tp-item,
.tp-viewer .tp-note { cursor: default; }
.tp-viewer .tp-item-remove,
.tp-viewer .tp-item-copy,
/* Der Stern-KNOPF ist ein Schalter und hat im Viewer nichts zu suchen; der
   Stern VOR dem Titel (.tp-key-star) bleibt - er ist die Aussage. */
.tp-viewer .tp-item-key { display: none; }
/* Im Viewer gibt es keinen Dialog, der den vollen Text nachreicht - dort steht
   die Notiz deshalb ungekuerzt. */
.tp-viewer .tp-note-body {
    display: block;
    overflow: visible;
}

/* ---------- Druck ---------- */

/* Ein Trainingsplan wird ausgedruckt und an die Pinnwand gehaengt - dafuer muss
   er ohne Bedienelemente auskommen, seine Farbflaechen behalten und darf keine
   Woche ueber den Seitenrand reissen. */
@media print {
    .tp-toolbar,
    .tp-library,
    .tp-hero-actions,
    .tp-week-actions,
    .tp-day-actions,
    #tpAddWeekBtn { display: none !important; }

    /* Klebende Elemente drucken sich sonst auf jeder Seite erneut. */
    .tp-week-head,
    .tp-library { position: static !important; }

    .tp-layout { display: block; }

    .tp-week,
    .tp-day { break-inside: avoid; page-break-inside: avoid; }

    .tp-week,
    .tp-hero { box-shadow: none; }

    /* Ohne das druckt der Browser die Sportfarben der Kacheln weiss. */
    .tp-item,
    .tp-note,
    .tp-week-head,
    .tp-sport-pill,
    .tp-total {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }

    /* Der dunkle Verlauf der Planer-Kopfkarte frisst eine halbe Patrone - im
       Ausdruck genuegt der Inhalt auf Weiss. */
    .tp-hero { background: none !important; color: #000; }
    .tp-hero-title,
    .tp-hero .tp-total .tp-total-value { color: #000 !important; }
    /* Auf Weiss gedruckt waeren die hellen Schriften des Verlaufs unlesbar. Der
       Ausdruck ist bei der Athletenansicht kein Nebenschauplatz - dafuer gibt es
       den Druckknopf im Kopf. */
    .tp-hero-subtitle,
    .tp-hero .tp-total .tp-total-label,
    .tp-hero .tp-sport-pill small { color: #444 !important; }
    .tp-hero .tp-sport-pill {
        color: #000 !important;
        background: none !important;
        /* Linke Kante ausgenommen - sie ist die Sportfarbe (siehe oben) und
           druckt dank print-color-adjust mit. */
        border-top-color: #bbb !important;
        border-right-color: #bbb !important;
        border-bottom-color: #bbb !important;
    }
    .tp-hero .tp-total {
        background: none !important;
        border-color: #bbb !important;
    }
    .tp-hero .tp-sport-split { border-top-color: #bbb !important; }
}
