/*
 * FuF Gruppenreise-Kalkulator - Design-Layer
 *
 * Wird nach bootstrap.min.css geladen und uebersteuert Bootstrap per Custom
 * Properties, statt es zu ersetzen. Bootstrap bleibt zustaendig fuer das
 * JS-Verhalten (Modal, Collapse, Tab) und die Utility d-none.
 *
 * Grundlage: docs/design-handoff/DESIGN.md und die Mockups darunter.
 */

/* ========================================================================
 * 1. Schrift
 * ======================================================================== */

/* Source Sans 3 ist ein Variable Font: eine Datei je Subset deckt 400-700 ab. */
@font-face {
    font-family: 'Source Sans 3';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url('/assets/fonts/source-sans-3-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

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

/* ========================================================================
 * 2. Design-Tokens
 * ======================================================================== */

:root {
    /* Farben */
    --fuf-brown-900: #3D2817; /* Kopfleiste, Fliesstext */
    --fuf-brown-700: #5C4A3A; /* Labels */
    --fuf-brown-500: #7A6651; /* Sekundaertext */
    --fuf-brown-400: #8A7762; /* Hilfetext, Tabellenkoepfe */
    --fuf-green-700: #1A3D2A;
    --fuf-green-600: #2D5A3D; /* Primaer: Buttons, Links, aktive Tabs, positive Werte */
    --fuf-green-100: #E6EFE9; /* gruene Chips, Highlight-KPI */
    --fuf-orange-600: #E76F1E; /* Akzent: Neue Reise, Uebernehmen, Kinder-Icon */
    --fuf-orange-100: #FCE3D0;
    --fuf-amber-700: #B45309; /* Warnhinweise, Abweichung nach unten */
    --fuf-amber-500: #F5B547; /* Akzent auf dunklem Grund */
    --fuf-amber-100: #FAEEDA; /* Chips Manuell, Kurabgabe-Box */
    --fuf-red-700: #9B2C2C; /* Loeschen, Defizit */
    --fuf-red-100: #FBE9E4; /* Defizit-KPI */
    --fuf-sand-50: #FDFBF7; /* Section-Header, Zebra */
    --fuf-sand-100: #F6F1E7; /* Input-Suffix, Summenzeilen */
    --fuf-sand-200: #F3EFE6; /* Seitenhintergrund */
    --fuf-sand-300: #EFE8DA; /* feine Trennlinien */
    --fuf-sand-400: #E2D9C8; /* Card-Rahmen */
    --fuf-sand-500: #D4CBB9; /* Input-Rahmen */

    /* Auf dunklem Grund */
    --fuf-on-dark: #F5EFE0;
    --fuf-on-dark-dim: rgba(245, 239, 224, .3);

    /* Typografie */
    --fuf-font-body: 'Source Sans 3', system-ui, sans-serif;
    --fuf-font-display: Georgia, serif;

    /* Form */
    --fuf-radius-card: 12px;
    --fuf-radius-control: 8px;
    --fuf-radius-chip: 999px;

    /* Mobile-first (RESPONSIVE.md Regel 1 und 3). Die Desktop-Masse stehen in
     * Abschnitt 18 hinter @media (min-width: 992px). 16px ist keine Geschmacks-
     * frage: darunter zoomt iOS Safari beim Fokus in das Feld hinein. */
    --fuf-control-height: 48px;
    --fuf-control-font: 16px;
    --fuf-touch: 48px;
    /* Hoehe der Bottom-Bar samt Home-Indicator-Leiste. Das Seitenende haelt
     * diesen Platz frei, sonst verdeckt die Bar seine letzte Zeile. */
    --fuf-bar-space: calc(64px + env(safe-area-inset-bottom));
    /* Kalkulationszeile ab 901 px: Kategorie, Endpreis, Verkaufspreis,
       Einnahmen, Chevron. Als Token, weil Raster und Zeile es brauchen. */
    --fuf-calc-cols: minmax(0, 1.6fr) minmax(0, 1fr) minmax(0, 1.2fr) minmax(0, 1fr) 24px;

    /* Bootstrap-Mapping */
    --bs-body-bg: var(--fuf-sand-200);
    --bs-body-color: var(--fuf-brown-900);
    --bs-body-font-family: var(--fuf-font-body);
    --bs-primary: var(--fuf-green-600);
    --bs-link-color: var(--fuf-green-600);
    --bs-link-hover-color: var(--fuf-green-700);
    --bs-border-color: var(--fuf-sand-400);
    --bs-border-radius: var(--fuf-radius-control);
}

/* ========================================================================
 * 3. Grundlagen
 * ======================================================================== */

body {
    margin: 0;
    font-family: var(--fuf-font-body);
    background: var(--fuf-sand-200);
    color: var(--fuf-brown-900);
}

/* Bootstrap setzt .bg-light auf ein kaltes Grau - hier soll Sand gelten. */
body.bg-light {
    background: var(--fuf-sand-200) !important;
}

a {
    color: var(--fuf-green-600);
}

a:hover {
    color: var(--fuf-green-700);
}

h1, h2, h3 {
    color: var(--fuf-brown-900);
}

.fuf-display {
    font-family: var(--fuf-font-display);
    font-weight: 500;
}

h1.fuf-display {
    font-size: 28px;
    margin: 0;
}

.help {
    font-size: 12px;
    color: var(--fuf-brown-400);
}

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

.fuf-pos {
    color: var(--fuf-green-600);
    font-weight: 700;
}

.fuf-neg {
    color: var(--fuf-red-700);
    font-weight: 700;
}

/* ========================================================================
 * 4. App-Shell
 * ======================================================================== */

.app-shell {
    min-height: 100vh;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    background: var(--fuf-sand-200);
}

/* Die Kopfleiste ist der Baustein mit dem groessten Unterschied zwischen Handy
 * und Desktop: 52 px mit Zurueck-Pfeil, Reisename und Menue-Icon gegen 64 px mit
 * Wortmarke, Navigation und Benutzerblock. Hier stehen die Handy-Werte, die
 * Rueckstellung folgt unten in @media (min-width: 992px). */
.app-header {
    background: var(--fuf-brown-900);
    /* feine vertikale Holzmaserung */
    background-image: repeating-linear-gradient(90deg,
    rgba(0, 0, 0, .08) 0px, rgba(0, 0, 0, .08) 1px,
    transparent 1px, transparent 4px,
    rgba(255, 255, 255, .04) 4px, rgba(255, 255, 255, .04) 5px,
    transparent 5px, transparent 9px);
    border-bottom: 3px solid var(--fuf-green-600);
    padding: 0 8px;
    height: 52px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 4px;
    /* Kopfleiste und Umschalter bleiben zusammen stehen - auf einer 3.000 px
     * langen Seite ist der Weg zurueck sonst ein Scrollmarathon. */
    position: sticky;
    top: 0;
    z-index: 40;
}

.app-brand {
    display: flex;
    align-items: center;
    gap: 12px;
    text-decoration: none;
    flex-shrink: 0;
    margin-left: 6px;
}

.app-brand img {
    height: 22px;
    width: auto;
}

/* Neben Reisename und Menue-Icon ist fuer die Wortmarke kein Platz. */
.app-brand span {
    display: none;
    font-family: var(--fuf-font-display);
    font-size: 17px;
    color: var(--fuf-on-dark);
    border-left: 1px solid var(--fuf-on-dark-dim);
    padding-left: 12px;
    white-space: nowrap;
}

.app-header-left {
    display: flex;
    align-items: center;
    gap: 4px;
    min-width: 0;
    flex-grow: 1;
}

/* Zurueck-Pfeil und Reisename treten an die Stelle des Logos, sobald eine Reise
 * offen ist; app.js setzt die Klasse in showEditorSection(). */
.app-head-back,
.app-head-title {
    display: none;
}

body.is-trip-view .app-brand {
    display: none;
}

body.is-trip-view .app-head-back {
    display: flex;
    align-items: center;
    justify-content: center;
    width: var(--fuf-touch);
    height: var(--fuf-touch);
    flex-shrink: 0;
    border-radius: var(--fuf-radius-control);
    color: var(--fuf-on-dark);
}

body.is-trip-view .app-head-title {
    display: block;
    min-width: 0;
    flex-grow: 1;
    font-size: 15px;
    font-weight: 700;
    color: #FFFFFF;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* `Neue Reise` im Kopf gilt nur fuer die Liste - in der Reiseansicht traegt
   die Bottom-Bar Kennzahl und Speichern, und ein Plus daneben waere die
   falsche Aktion am falschen Ort. */
body.is-trip-view .app-head-new {
    display: none;
}

.app-menu-btn {
    width: var(--fuf-touch);
    height: var(--fuf-touch);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: var(--fuf-radius-control);
    background: transparent;
    color: var(--fuf-on-dark);
    cursor: pointer;
}

/* Das Menue ist dasselbe Markup wie die Desktop-Kopfleiste - offcanvas-lg
 * schiebt es unter lg als Panel herein. Der Panelgrund traegt dieselbe
 * Holzmaserung, damit die hellen Schriftfarben von .app-nav und .app-user
 * ohne zweite Farbwelt weiterpassen. */
.app-menu {
    --bs-offcanvas-width: 280px;
    --bs-offcanvas-padding-x: 14px;
    --bs-offcanvas-padding-y: 12px;
    --bs-offcanvas-color: var(--fuf-on-dark);
    --bs-offcanvas-bg: var(--fuf-brown-900);
    --bs-offcanvas-border-width: 0;
    background-image: repeating-linear-gradient(90deg,
    rgba(0, 0, 0, .08) 0px, rgba(0, 0, 0, .08) 1px,
    transparent 1px, transparent 4px,
    rgba(255, 255, 255, .04) 4px, rgba(255, 255, 255, .04) 5px,
    transparent 5px, transparent 9px);
}

.app-menu .offcanvas-header {
    justify-content: space-between;
    border-bottom: 1px solid var(--fuf-on-dark-dim);
}

.app-menu .offcanvas-title {
    font-family: var(--fuf-font-display);
    font-size: 17px;
    font-weight: 500;
    /* h1, h2, h3 tragen global das Braun der Fliesstextfarbe - auf dem dunklen
       Panel waere die Ueberschrift damit unsichtbar. */
    color: var(--fuf-on-dark);
}

.app-menu .offcanvas-body {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.app-nav {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.app-nav a,
.app-nav button {
    display: flex;
    align-items: center;
    gap: 12px;
    min-height: var(--fuf-touch);
    padding: 0 12px;
    border: 0;
    border-radius: var(--fuf-radius-control);
    background: transparent;
    font: inherit;
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
    color: var(--fuf-on-dark);
    cursor: pointer;
    white-space: nowrap;
}

.app-nav a:hover,
.app-nav button:hover {
    background: rgba(255, 255, 255, .08);
    color: #FFFFFF;
}

.app-nav .is-active {
    color: #FFFFFF;
    background: rgba(255, 255, 255, .12);
}

/* Im Menue steht der Benutzer als eigene Zeile unten, nicht als Anhaengsel
 * rechts neben der Navigation - die Trennlinie zeigt deshalb nach oben. */
.app-user {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 4px;
    padding-top: 12px;
    border-top: 1px solid var(--fuf-on-dark-dim);
}

.app-avatar {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: var(--fuf-amber-500);
    color: var(--fuf-brown-900);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 13px;
    flex-shrink: 0;
}

.app-user-meta {
    display: flex;
    flex-direction: column;
    line-height: 1.2;
    min-width: 0;
    flex-grow: 1;
}

.app-user-meta .app-user-email {
    font-size: 13px;
    color: #FFFFFF;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.app-user-meta .app-user-role {
    font-size: 11px;
    color: var(--fuf-amber-500);
    letter-spacing: .6px;
    text-transform: uppercase;
}

.app-icon-link {
    width: var(--fuf-touch);
    height: var(--fuf-touch);
    border: 0;
    border-radius: var(--fuf-radius-control);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--fuf-on-dark);
    background: rgba(255, 255, 255, .1);
    cursor: pointer;
}

.app-icon-link:hover {
    background: rgba(255, 255, 255, .18);
    color: #FFFFFF;
}

.app-main {
    padding: 20px 16px;
    display: flex;
    flex-direction: column;
    gap: 20px;
    flex-grow: 1;
}

/* Ab lg die Kopfleiste aus DESIGN.md: Wortmarke, Navigation, Neue Reise und
 * Benutzerblock in einer 64-px-Zeile. offcanvas-lg gibt das Panel hier von
 * selbst auf; display: contents loest zusaetzlich seine beiden Huellen auf,
 * damit die vier Bausteine direkte Flex-Kinder der Kopfleiste bleiben und in
 * derselben Reihenfolge stehen wie vor dem Umbau. */
@media (min-width: 992px) {
    .app-header {
        height: 64px;
        padding: 0 32px;
        gap: 12px;
        position: static;
        z-index: auto;
    }

    .app-header-left {
        gap: 28px;
        flex-grow: 0;
    }

    .app-brand {
        margin-left: 0;
    }

    .app-brand img {
        height: 34px;
    }

    .app-brand span {
        display: inline;
    }

    .app-menu-btn,
    body.is-trip-view .app-head-back,
    body.is-trip-view .app-head-title {
        display: none;
    }

    body.is-trip-view .app-brand {
        display: flex;
    }

    .app-menu,
    .app-menu .offcanvas-body {
        display: contents;
    }

    .app-nav {
        flex-direction: row;
        gap: 4px;
        /* 12 px Abstand der Kopfleiste plus 16 px ergeben die 28 px zur
           Wortmarke wie gehabt; auto schiebt Neue Reise und Benutzerblock ans
           rechte Ende. */
        margin: 0 auto 0 16px;
    }

    .app-nav a,
    .app-nav button {
        min-height: 0;
        gap: 8px;
        padding: 8px 14px;
    }

    .app-user {
        margin-top: 0;
        padding-top: 0;
        border-top: 0;
        padding-left: 12px;
        border-left: 1px solid var(--fuf-on-dark-dim);
    }

    .app-main {
        padding: 28px 32px;
    }
}

.app-footer {
    padding: 14px 32px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 12px;
    color: var(--fuf-brown-400);
    border-top: 1px solid var(--fuf-sand-400);
    margin-top: auto;
}

.app-footer a {
    text-decoration: none;
    font-weight: 600;
}

.app-footer-links {
    display: flex;
    gap: 14px;
}

/* ========================================================================
 * 5. Raster
 *
 * Bootstrap besitzt .row (Flex-Grid). Das Grid des Designs heisst deshalb
 * .fuf-grid, sonst kollidieren die beiden.
 * ======================================================================== */

.fuf-grid {
    display: grid;
    gap: 14px 16px;
}

/* Mobile first: jedes Raster steht auf dem Handy in einer Spalte. Die
   Spaltenzahl kommt erst ab 901 px dazu (Block am Ende dieses Abschnitts),
   weil vier Spuren auf 390 px keine 90 px breit waeren. */
.fuf-grid-2,
.fuf-grid-eck,
.fuf-grid-room,
.fuf-grid-calc {
    grid-template-columns: minmax(0, 1fr);
}

/* Kennzahl-Kacheln sind die Ausnahme: sie stehen schon auf dem Handy 2 x 2,
   wie RESPONSIVE.md es vorgibt. Eine Kachel traegt nur Beschriftung, Zahl und
   einen Hilfstext - das passt auf 390 px auch in eine halbe Zeile, und vier
   Kacheln uebereinander schieben den ersten Abschnitt aus dem Bild.

   Die Betraege bleiben dabei genau. RESPONSIVE.md erlaubt sie mobil ohne
   Nachkommastellen, aber die Formatierung haengt an einer Stelle in app.js;
   eine breitenabhaengige zweite Variante liefe beim Resize auseinander und
   gewinnt bei 390 px kaum Platz. */
.fuf-grid-3,
.fuf-grid-4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

/* Drei Kacheln in zwei Spuren lassen unten eine Luecke - die dritte nimmt
   deshalb beide Spuren. Ab 901 px stehen wieder alle drei nebeneinander. */
.fuf-grid-3 > :last-child {
    grid-column: span 2;
}

/* Anmeldungen: CSV-Dropzone links, Manuell-Formular rechts - erst ab 1101 px,
   Rueckstellung in Abschnitt 15a. */
.fuf-grid-intake {
    grid-template-columns: minmax(0, 1fr);
    align-items: stretch;
}

/* Seitenkopf ueber einer Liste: Titel und Hilfetext links, Suche rechts */
.page-head {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 16px;
}

.page-head-text {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.page-head .in-search {
    width: 100%;
    min-width: 0;
}

/* Planungsseite: Inhalt, darunter die Spalte mit dem Panel. Ab 1101 px steht
   sie daneben und bleibt beim Scrollen stehen; unter lg steckt sie ohnehin im
   Sheet (Abschnitt 5c). */
.pg {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 20px;
    align-items: start;
}

.pg-side {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

@media (min-width: 1101px) {
    .pg {
        grid-template-columns: minmax(0, 1fr) 340px;
    }

    .pg-side {
        position: sticky;
        top: 76px;
    }
}

/* Die Spaltenzahl der Raster und der zweizeilige Seitenkopf. 901 px statt der
   Bootstrap-Grenze, weil darunter schon die Feldbeschriftungen umbrechen. */
@media (min-width: 901px) {
    .fuf-grid-2 {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

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

    .fuf-grid-3 > :last-child {
        grid-column: auto;
    }

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

    /* Eckdaten: Name breiter als die beiden Datumsfelder */
    .fuf-grid-eck {
        grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr);
    }

    /* Unterkunft: Kategorie, Anzahl, Preis/Nacht, Summe */
    .fuf-grid-room {
        grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr);
    }

    /* Kalkulationszeile: Kategorie, Endpreis, Verkaufspreis, Einnahmen, Chevron.
       Das Mass steckt in --fuf-calc-cols, weil die Zeile selbst es in ihrer
       Rueckstellung (Abschnitt 15b) noch einmal braucht - sie setzt mobil ein
       eigenes Raster und muss hier auf genau dieses Mass zurueck. */
    .fuf-grid-calc {
        grid-template-columns: var(--fuf-calc-cols);
    }

    .page-head {
        flex-direction: row;
        align-items: flex-end;
    }
}

/* ========================================================================
 * 5b. Planungsseite: Kopfbereich, Sticky-Spalte, Panel
 * ======================================================================== */

/* Der Reisekopf sitzt randlos ueber der Seite. Die negativen Margins heben
   das Padding von .app-main auf, damit die weisse Flaeche bis an die Kanten
   reicht wie im Mockup.

   Auf dem Handy bleibt davon nur der Umschalter: Zurueck-Pfeil und Reisename
   stehen eine Etage hoeher in der App-Kopfleiste, die Kennzahl zieht mit
   Schritt 3 in die Bottom-Bar. Kopfleiste (52 px) und Umschalter kleben
   zusammen, zusammen rund 100 px. */
.trip-head {
    margin: -20px -16px 0 -16px;
    padding: 4px 14px 5px 14px;
    background: #FFFFFF;
    border-bottom: 1px solid var(--fuf-sand-400);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0;
    position: sticky;
    top: 52px;
    z-index: 30;
    transition: padding .15s, box-shadow .15s;
}

.trip-head.is-scrolled {
    box-shadow: 0 6px 14px -6px rgba(61, 40, 23, .25);
}

.trip-head-right {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-grow: 1;
    min-width: 0;
}

/* Die Meta-Zeile steht mobil unter dem Sticky-Bereich und scrollt mit; im
   Kopf selbst haette sie die feste Zone auf 135 px aufgeblaeht. */
.trip-meta-m {
    padding: 10px 2px 0 2px;
}

/* Breadcrumb, Ueberschrift, Kennzahl, Zurueck-Pfeil und Kopf-Speichern gehoeren
   auf dem Handy nicht in den Kopf. Auf dem Desktop haengen Pfeil, Kennzahl und
   Speichern am gescrollten Zustand - ungescrollt stehen Breadcrumb und
   Sticky-Panel dafuer bereit. */
.trip-head-text,
.trip-head-back,
.trip-head-kpi,
#trip-save-btn-head {
    display: none;
}

.trip-head-back {
    width: var(--fuf-touch);
    height: var(--fuf-touch);
    border-radius: var(--fuf-radius-control);
    border: 1px solid var(--fuf-sand-500);
    color: var(--fuf-brown-700);
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.trip-head-back:hover {
    background: var(--fuf-sand-50);
    color: var(--fuf-brown-900);
}

.trip-head-kpi {
    align-items: baseline;
    gap: 8px;
    white-space: nowrap;
}

.trip-head-kpi b {
    font-family: var(--fuf-font-display);
    font-size: 17px;
    color: var(--fuf-green-600);
    font-variant-numeric: tabular-nums;
}

.trip-head-kpi b.fuf-neg {
    color: var(--fuf-red-700);
    font-weight: 500;
}

.trip-head-title {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}

.trip-head-title h1 {
    margin: 0;
    font-family: var(--fuf-font-display);
    font-size: 24px;
    font-weight: 500;
}

.bc {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    color: var(--fuf-brown-500);
}

.bc a {
    text-decoration: none;
    font-weight: 600;
}

/* Mobil ist der Umschalter ein Segmented Control ueber die volle Breite: zwei
   gleich breite Segmente auf sandfarbenem Grund, das aktive weiss. Ein
   Unterstrich-Umschalter braeuchte eine Kante, auf der er sitzt - die gibt es
   in einer 50-px-Zeile nicht. */
.nav-tabs.trip-tabs {
    width: 100%;
    border-bottom: 0;
    background: var(--fuf-sand-200);
    border-radius: var(--fuf-radius-control);
    padding: 3px;
    gap: 3px;
    margin-bottom: 0;
}

.nav-tabs.trip-tabs .nav-item {
    flex: 1 1 0;
    min-width: 0;
}

.nav-tabs.trip-tabs .nav-link {
    width: 100%;
    justify-content: center;
    /* Regel 3 verlangt 48 px; die Segmente sind ueber 180 px breit, und
       3 + 44 + 3 px unter der 52-px-Kopfleiste ergeben die rund 100 px aus
       RESPONSIVE.md. */
    min-height: 44px;
    padding: 4px 8px;
    border-bottom-color: transparent;
    border-radius: 6px;
}

.nav-tabs.trip-tabs .nav-link.active {
    background: #FFFFFF;
    box-shadow: 0 1px 2px rgba(61, 40, 23, .12);
    border-bottom-color: transparent;
}

/* Ab lg der Reisekopf aus DESIGN.md: Breadcrumb und Ueberschrift links, Tabs
   rechts auf der Unterkante, und beim Scrollen eine 52-px-Zeile mit
   Zurueck-Pfeil, Name, Kennzahl, Segment-Umschalter und Speichern. */
@media (min-width: 992px) {
    .trip-head {
        /* Der gap von .app-main wirkt nur zwischen dessen Kindern, also nicht
           zwischen diesem Kopf und dem Raster darunter. Die 24 px entsprechen
           dem padding-top des Rasters in Mockup 02. */
        margin: -28px -32px 24px -32px;
        padding: 18px 32px 0 32px;
        align-items: flex-end;
        gap: 24px;
        flex-wrap: wrap;
        /* Die App-Kopfleiste darueber scrollt normal weg, nur dieser Kopf
           bleibt. */
        top: 0;
    }

    .trip-head-right {
        align-items: flex-end;
        flex-grow: 0;
    }

    .trip-head-text {
        display: flex;
        flex-direction: column;
        gap: 6px;
        padding-bottom: 14px;
    }

    /* Gescrollt: eine Zeile, 52 px hoch. */
    .trip-head.is-scrolled {
        padding: 8px 32px;
        align-items: center;
        flex-wrap: nowrap;
    }

    .trip-head.is-scrolled .bc,
    .trip-head.is-scrolled #trip-editor-meta {
        display: none;
    }

    .trip-head.is-scrolled .trip-head-text {
        padding-bottom: 0;
        /* Der Name steht direkt neben dem Pfeil, nicht mittig zwischen Pfeil
           und Umschalter - space-between wuerde ihn sonst in die Mitte
           schieben. */
        margin-right: auto;
        min-width: 0;
    }

    .trip-head.is-scrolled .trip-head-title h1 {
        font-family: var(--fuf-font-body);
        font-size: 15px;
        font-weight: 700;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .trip-head.is-scrolled .trip-head-back,
    .trip-head.is-scrolled .trip-head-kpi {
        display: flex;
    }

    .trip-head.is-scrolled .trip-head-right {
        align-items: center;
    }

    /* Der Speichern-Knopf ist nur in der Planung sinnvoll - in der Abrechnung
       gibt es kein Formular, das er abschicken koennte. */
    .trip-head.is-scrolled:not(.is-abrechnung) #trip-save-btn-head {
        display: inline-flex;
    }

    /* Ungescrollt sitzen die Tabs auf der Unterkante des Kopfes, ihr eigener
       Rahmen entfaellt. Das Segmentkleid bekommen sie erst beim Scrollen. */
    .nav-tabs.trip-tabs {
        width: auto;
        background: transparent;
        border-radius: 0;
        padding: 0;
        gap: 0;
        margin-bottom: -1px;
    }

    .nav-tabs.trip-tabs .nav-item {
        flex: 0 1 auto;
    }

    .nav-tabs.trip-tabs .nav-link {
        width: auto;
        min-height: 0;
        padding: 12px 18px;
        border-radius: 0;
        border-bottom-color: transparent;
    }

    .nav-tabs.trip-tabs .nav-link.active {
        background: transparent;
        box-shadow: none;
        border-bottom-color: var(--fuf-green-600);
    }

    .trip-head.is-scrolled .nav-tabs.trip-tabs {
        background: var(--fuf-sand-200);
        border-radius: var(--fuf-radius-control);
        padding: 3px;
        margin-bottom: 0;
    }

    .trip-head.is-scrolled .nav-tabs.trip-tabs .nav-link {
        padding: 4px 14px;
        font-size: 13px;
        border-radius: 6px;
    }

    .trip-head.is-scrolled .nav-tabs.trip-tabs .nav-link.active {
        background: #FFFFFF;
        box-shadow: 0 1px 2px rgba(61, 40, 23, .12);
        border-bottom-color: transparent;
    }
}

.pg-main,
.pg-form {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

/* Sprungnavigation in der Sticky-Spalte */
/* Die Sprungnavigation entfaellt auf dem Handy: bei einer Spalte ist Scrollen
   schneller als eine Liste von Sprungzielen, und die Sections zeigen
   zugeklappt ohnehin ihre Zusammenfassung. Der Baum bleibt im DOM, damit
   renderJumpState und der Section-Observer unberuehrt weiterlaufen. */
.jump-card {
    background: #FFFFFF;
    border: 1px solid var(--fuf-sand-400);
    border-radius: var(--fuf-radius-card);
    padding: 10px;
    display: none;
    flex-direction: column;
    gap: 2px;
}

@media (min-width: 992px) {
    .jump-card {
        display: flex;
    }
}

.jump-title {
    padding: 4px 10px 6px 10px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .6px;
    text-transform: uppercase;
    color: var(--fuf-brown-400);
}

.jump-chip {
    margin-left: auto;
    font-size: 11px;
    padding: 1px 7px;
}

/* Kalkulationspanel in der Sticky-Spalte */
/* Mobile first: im Blatt ist das Panel kein Kaertchen - Rahmen, Grund und
   Innenabstand gehoeren dort dem Blatt selbst, sonst stuende eine Karte in
   einer Karte. Ab lg ist es die Karte der Sticky-Spalte. */
.pnl {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

@media (min-width: 992px) {
    .pnl {
        background: #FFFFFF;
        border: 1px solid var(--fuf-sand-400);
        border-radius: var(--fuf-radius-card);
        padding: 20px;
    }
}

.pnl-h {
    display: flex;
    align-items: center;
    gap: 8px;
}

.pnl-h h2 {
    margin: 0;
    font-size: 16px;
    font-weight: 700;
}

.pnl-box {
    background: var(--fuf-sand-100);
    border-radius: 10px;
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.pnl-box b {
    font-family: var(--fuf-font-display);
    font-size: 24px;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}

.pnl-lines {
    display: flex;
    flex-direction: column;
    gap: 9px;
    border-top: 1px solid var(--fuf-sand-300);
    padding-top: 12px;
}

.k-total {
    border-top: 1px dashed var(--fuf-sand-400);
    padding-top: 9px;
    font-weight: 700;
}

.pnl-bar {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.pnl-bar-track {
    display: flex;
    height: 10px;
    border-radius: 5px;
    overflow: hidden;
    background: var(--fuf-sand-300);
}

/* Die Breite der beiden Segmente setzt renderPanelBar(). */
.pnl-bar-track span {
    display: block;
    height: 100%;
    width: 0;
}

.pnl-bar-costs {
    background: var(--fuf-brown-900);
}

.pnl-bar-surplus {
    background: var(--fuf-green-600);
}

.pnl-bar-planned {
    background: var(--fuf-brown-900);
}

.pnl-bar-additional {
    background: var(--fuf-amber-700);
}

.pnl-bar-retention {
    background: var(--fuf-amber-500);
}

.pnl-bar-distributable {
    background: var(--fuf-green-600);
}

.pnl-bar-legend {
    display: flex;
    justify-content: space-between;
    font-size: 12px;
    color: var(--fuf-brown-500);
}

/* Vier Eintraege passen nicht mehr in eine Zeile. */
.pnl-bar-legend-wrap {
    flex-wrap: wrap;
    justify-content: flex-start;
    gap: 4px 12px;
}

.pnl-bar-key {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 2px;
    margin-right: 5px;
}

.pnl-green {
    background: var(--fuf-green-600);
    border-radius: 10px;
    padding: 14px 16px;
    color: var(--fuf-on-dark);
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.pnl-green-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
}

.pnl-green-head span {
    font-size: 13px;
    color: var(--fuf-amber-500);
    letter-spacing: 1px;
    text-transform: uppercase;
}

.pnl-green-head b {
    font-family: var(--fuf-font-display);
    font-size: 24px;
    font-weight: 500;
    color: #FFFFFF;
    font-variant-numeric: tabular-nums;
}

.pnl-green-line {
    display: flex;
    justify-content: space-between;
    font-size: 13px;
}

.pnl-note {
    text-align: center;
}

/* Hinweis auf ungespeicherte Aenderungen unter dem Speichern-Button */
#trip-dirty-note:not(:empty) {
    color: var(--fuf-orange-600);
    font-weight: 600;
}

/* Sagt, woher die Zahlen im Panel kommen: das Ergebnis der letzten Berechnung
   oder die Vorschau aus den Feldern. */
.pnl-state {
    margin-left: auto;
    font-size: 12px;
    font-weight: 700;
    color: var(--fuf-green-600);
    display: inline-flex;
    align-items: center;
    gap: 5px;
}

.pnl-state::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: currentColor;
}

.pnl-state-preview {
    color: var(--fuf-orange-600);
}

/* Defizit: die gruene Box wird braun, damit sie keinen Erfolg suggeriert. */
.pnl-green-bad {
    background: var(--fuf-brown-900);
}

.pnl-green-bad .pnl-green-head span {
    color: var(--fuf-amber-500);
}

/* Schalterzeile fuer eine Option, die kein Eingabefeld ist */
.opt-row {
    margin-top: 14px;
}

.opt-row .form-check {
    margin: 0;
    padding-left: 2.5em;
}

.opt-row .form-check-input {
    margin-left: -2.5em;
    margin-top: .15em;
}

.opt-row .form-check-label {
    display: flex;
    flex-direction: column;
    gap: 2px;
    cursor: pointer;
}

.opt-row .form-check-label b {
    font-size: 14px;
    color: var(--fuf-brown-900);
}

/* Sand-Box fuer eine zusammengehoerige Feldgruppe, etwa die Kurabgabe */
.box-sand {
    background: var(--fuf-sand-100);
    border-radius: 10px;
    padding: 12px 14px;
    align-items: end;
}

.box-sand-label {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding-bottom: 10px;
    min-width: 120px;
}

.box-sand-label b {
    font-size: 14px;
}

/* Kurabgabe: Beschriftung plus drei Felder - auf dem Handy untereinander */
.fuf-grid-spa {
    grid-template-columns: minmax(0, 1fr);
    gap: 12px;
}

@media (min-width: 901px) {
    .fuf-grid-spa {
        grid-template-columns: auto repeat(3, minmax(0, 1fr));
    }
}

/* Spaltenkopf in einem Raster, das keine Tabelle ist */
.col-head {
    font-size: 12px;
    color: var(--fuf-brown-400);
    font-weight: 700;
    letter-spacing: .6px;
    text-transform: uppercase;
}

/* Unterkunft, mobile first: aus den vier Spalten wird pro Kategorie eine
   Karte - Icon und Name, Zeile "Personen" mit - / + Stepper, Zeile
   "EUR / Nacht", darunter Summe mit Rechenweg als Hilfstext. So gibt es
   RESPONSIVE.md vor; der Stepper ist auf dem Handy wichtiger als am Desktop,
   weil Zahlen tippen nervt.

   Der Umbau haengt an `display: contents` ab 901 px - derselbe Griff wie beim
   Blatt in Schritt 3b. Die Huellen .room-row, .stepper und .room-sum-line
   loesen sich dort als Box auf, und die vier Zellen stehen wieder direkt im
   Raster. Was nur zur Karte gehoert - Beschriftungen, Stepper-Knoepfe,
   Rechenweg - ist ab 901 px `display: none`, sonst waeren es mehr als vier
   Rasterkinder pro Zeile und die Spalten verrutschten. */
.room-table {
    align-items: center;
    gap: 10px 16px;
}

/* Die Spaltenkoepfe beschreiben Spalten - in der Karte stehen die
   Beschriftungen an den Zeilen. */
.room-table .col-head {
    display: none;
}

/* Zwei Spuren: Beschriftung links, Bedienelement rechts. Kategoriezeile und
   Summenzeile nehmen beide. */
.room-row {
    display: grid;
    grid-template-columns: 62px minmax(0, 1fr);
    align-items: center;
    gap: 11px 10px;
    padding: 13px 14px;
    border: 1px solid var(--fuf-sand-400);
    border-radius: 10px;
}

.room-row > .room-cat,
.room-row > .room-sum-line {
    grid-column: 1 / -1;
}

.room-lbl {
    font-size: 13px;
    color: var(--fuf-brown-400);
}

.room-sum-line {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    min-width: 0;
    padding-top: 8px;
    border-top: 1px solid var(--fuf-sand-300);
}

.room-calc {
    min-width: 0;
}

/* Stepper: Minus, Feld, Plus mit zusammenlaufenden Kanten. Die Knoepfe sind
   48 px breit - Regel 3. */
.stepper {
    display: flex;
    min-width: 0;
}

.step {
    flex-shrink: 0;
    width: var(--fuf-touch);
    min-width: 48px;
    height: var(--fuf-control-height);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 1px solid var(--fuf-sand-500);
    background: var(--fuf-sand-100);
    color: var(--fuf-brown-700);
    cursor: pointer;
}

.step:first-child {
    border-radius: var(--fuf-radius-control) 0 0 var(--fuf-radius-control);
}

.step:last-child {
    border-radius: 0 var(--fuf-radius-control) var(--fuf-radius-control) 0;
}

.stepper .in {
    flex-grow: 1;
    min-width: 0;
    border-radius: 0;
    border-left: 0;
    border-right: 0;
}

/* Die Zahl steht mittig und fett, das Suffix entfaellt - "Personen" sagt es
   schon links, und auf 390 px ist der Platz besser in der Zahl angelegt. */
.stepper .in input {
    text-align: center;
    font-weight: 700;
}

.stepper .in .u {
    display: none;
}

/* Ab 901 px wieder das vierspaltige Raster. Der Block steht hier und nicht
   bei .fuf-grid-room in Abschnitt 5a: dort stuende er VOR diesen
   Definitionen, und bei gleicher Spezifitaet gewinnt die spaetere Regel.
   Genau daran ist der erste Versuch gescheitert - der Desktop zeigte drei
   Karten nebeneinander statt der Tabelle. Dieselbe Lehre wie in 3a. */
@media (min-width: 901px) {
    .room-table .col-head {
        display: revert;
    }

    /* Die drei Huellen loesen sich als Box auf, damit die vier Zellen wieder
       direkt im Raster stehen. Danach bleiben pro Zeile genau vier
       Rasterkinder: Kategorie, Anzahl-Feld, Preis-Feld, Summe. */
    .room-row,
    .stepper,
    .room-sum-line {
        display: contents;
    }

    /* `display: contents` loest die Huelle als Box auf, nicht als Treffer im
       Selektor: .room-row > .room-cat passt weiterhin, und das
       `grid-column: 1 / -1` der Karte liess die Kategoriezelle alle vier
       Spuren spannen. Dieselbe Lehre wie beim Blatt in 3b. */
    .room-row > .room-cat,
    .room-row > .room-sum-line {
        grid-column: auto;
    }

    /* Was nur zur Karte gehoert, verschwindet - sonst waeren es sieben
       Rasterkinder pro Zeile und die Spalten verrutschten. */
    .room-lbl,
    .step,
    .room-calc {
        display: none;
    }

    /* Das Anzahl-Feld ist wieder ein Feld wie jedes andere. */
    .stepper .in {
        border-radius: var(--fuf-radius-control);
        border-left: 1px solid var(--fuf-sand-500);
        border-right: 1px solid var(--fuf-sand-500);
    }

    .stepper .in input {
        text-align: left;
        font-weight: 400;
    }

    .stepper .in .u {
        display: flex;
    }
}

.room-cat {
    display: flex;
    align-items: center;
    gap: 10px;
}

.room-cat-text {
    display: flex;
    flex-direction: column;
}

.room-cat-text b {
    font-size: 14px;
}

.room-sum {
    text-align: right;
}

/* Mobile first: "Erwachsen ab" steht ueber dem Feld. Nebeneinander bricht die
   Beschriftung auf 390 px in zwei Zeilen und das Feld wird zusammengedrueckt. */
.room-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 10px;
    padding-top: 6px;
}

.room-foot label {
    flex: 1 0 100%;
}

@media (min-width: 901px) {
    .room-foot {
        flex-wrap: nowrap;
        gap: 10px;
    }

    .room-foot label {
        flex: 0 1 auto;
    }
}

.room-foot label {
    font-size: 13px;
    font-weight: 600;
    color: var(--fuf-brown-700);
}

.in-sm {
    width: 100%;
    height: var(--fuf-control-height);
}

/* Reservierte Zimmer, mobile first: je Typ eine Karte wie in der
   Unterkunft darueber - der Typ ueber die volle Breite, darunter Stepper und
   Entfernen-Knopf. Ab 901 px eine Zeile - der Stepper
   loest sich dort wie in der Unterkunftstabelle per `display: contents` auf,
   uebrig bleiben drei Rasterkinder: Typ, Anzahl, Entfernen. */
.room-res {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    margin-top: 16px;
    padding-top: 14px;
    border-top: 1px solid var(--fuf-sand-300);
}

.room-res-h {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.room-res-h b {
    font-size: 14px;
}

.room-res-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.room-res-list:empty {
    display: none;
}

.room-res-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 8px 10px;
    padding: 11px 12px;
    border: 1px solid var(--fuf-sand-400);
    border-radius: 10px;
}

.room-res-row > .room-res-type {
    grid-column: 1 / -1;
}

@media (min-width: 901px) {
    .room-res-h {
        flex-direction: row;
        align-items: baseline;
        gap: 10px;
    }

    /* Die Karte ist am Desktop nur noch eine Zeile im Formular. */
    .room-res-row {
        grid-template-columns: minmax(0, 1fr) 140px auto;
        padding: 0;
        border: 0;
        border-radius: 0;
    }

    .room-res-row > .room-res-type {
        grid-column: auto;
    }
}

/* Zusatzausgabe: Bezeichnung breit, Betrag schmal */
/* Mobile first: Bezeichnung und Betrag stehen untereinander. Nebeneinander
   nimmt der Betrag feste 180 px, und von 390 px bleiben der Bezeichnung
   keine 180 -- Feld und Beschriftung ragten heraus. */
.expense-row {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.expense-row .f {
    flex-grow: 1;
}

@media (min-width: 901px) {
    .expense-row {
        flex-direction: row;
        align-items: flex-end;
    }

    .expense-row .f-amount {
        flex-grow: 0;
        width: 180px;
    }
}

/* ========================================================================
 * 5c. Kalkulation als Blatt
 *
 * Dasselbe Panel, zwei Erscheinungsformen: unter lg ein Blatt, das vom
 * unteren Rand aufzieht, ab lg die rechte Sticky-Spalte. offcanvas-lg macht
 * beides aus einem Markup - wie das Menue in Abschnitt 4. Ab lg loesen sich
 * Huelle und Body per display: contents auf, damit .pnl wieder direktes Kind
 * von .pg-side ist und deren gap greift.
 * ======================================================================== */

.calc-sheet {
    --bs-offcanvas-height: auto;
    --bs-offcanvas-padding-x: 0;
    --bs-offcanvas-padding-y: 0;
    --bs-offcanvas-border-width: 0;
    --bs-offcanvas-bg: #FFFFFF;
    max-height: 85vh;
    border-radius: 18px 18px 0 0;
    box-shadow: 0 -10px 30px -10px rgba(61, 40, 23, .4);
}

.calc-sheet .offcanvas-header {
    padding: 0;
}

/* Der Grabber ist zugleich der Schliessen-Knopf und die Wischflaeche. Sichtbar
   sind 38 x 4 px wie im Mockup, treffen kann man die ganze Kopfzeile - so
   erfuellt das Ziel Regel 3, ohne dass der Balken klobig wird. */
.sheet-grab {
    width: 100%;
    height: 44px;
    padding: 0;
    border: 0;
    background: transparent;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    touch-action: none;
}

.sheet-grab::before {
    content: "";
    width: 38px;
    height: 4px;
    border-radius: 2px;
    background: var(--fuf-sand-400);
}

/* Der Inhalt scrollt, sobald er hoeher wird als max-height. Regel 6: der
   Innenabstand unten muss die Home-Indicator-Leiste mitnehmen. */
.calc-sheet .offcanvas-body {
    padding: 0 16px calc(18px + env(safe-area-inset-bottom)) 16px;
}

/* Teilnehmer und Naechte stehen im Panel bei jeder Breite nebeneinander - zwei
   kurze Zahlen, die untereinander nur das Blatt verlaengern wuerden. Das ist
   die Ausnahme von der einspaltigen Basis aus Abschnitt 5. */
.pnl .fuf-grid-2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 992px) {
    .calc-sheet,
    .calc-sheet .offcanvas-body {
        display: contents;
    }
}

/* ========================================================================
 * 5d. Bottom-Bar
 *
 * RESPONSIVE.md Regel 5: die wichtigste Zahl und die Hauptaktion unten, in
 * Daumenreichweite. Die Bar traegt beides und ersetzt unter lg, was auf dem
 * Desktop im Reisekopf und in der Sticky-Spalte steht. Ab lg ist sie weg.
 * ======================================================================== */

.trip-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    /* Unter dem Offcanvas (1045) und seinem Backdrop (1040) - das Blatt deckt
       die Bar zu, sobald es aufgezogen ist. */
    z-index: 1030;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 16px calc(8px + env(safe-area-inset-bottom)) 16px;
    background: #FFFFFF;
    border-top: 1px solid var(--fuf-sand-300);
    box-shadow: 0 -6px 20px -12px rgba(61, 40, 23, .35);
}

.trip-bar-kpi {
    flex-grow: 1;
    min-width: 0;
    min-height: var(--fuf-touch);
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: 1px;
    padding: 0;
    border: 0;
    background: transparent;
    text-align: left;
    cursor: pointer;
}

.trip-bar-kpi .help {
    display: flex;
    align-items: center;
    gap: 4px;
}

.trip-bar-kpi b {
    font-family: var(--fuf-font-display);
    font-size: 19px;
    color: var(--fuf-green-600);
    font-variant-numeric: tabular-nums;
}

.trip-bar-kpi b.fuf-neg {
    color: var(--fuf-red-700);
}

/* Der Speichern-Knopf nimmt nur seine Textbreite ein - der Rest der Zeile
   gehoert der Kennzahl. */
.trip-bar .btn {
    width: auto;
    flex-shrink: 0;
    padding: 0 20px;
}

/* Das Seitenende haelt den Platz der Bar frei. Ab lg ist --fuf-bar-space 0,
   die Zeile stimmt dann wieder mit .app-footer ueberein. Nur die
   Reiseansicht hat eine Bar - auf der Liste steht `Neue Reise` im Kopf. */
body.is-trip-view .app-footer {
    padding-bottom: calc(14px + var(--fuf-bar-space));
}

@media (min-width: 992px) {
    .trip-bar {
        display: none;
    }
}

/* ========================================================================
 * 6. Section-Card
 * ======================================================================== */

.sec {
    background: #FFFFFF;
    border: 1px solid var(--fuf-sand-400);
    border-radius: var(--fuf-radius-card);
    overflow: hidden;
}

/* Mobile first: der Kopf bricht um. Zugeklappt ist er alles, was von der
   Section zu sehen ist - ohne Umbruch schiebt ein Aktionsknopf den Chevron aus
   dem Bild und damit den einzigen Weg, den Abschnitt zu oeffnen. */
/* Mobile first: eine Section, die unter 901 px nur noch Karten traegt, ist
   selbst keine Karte mehr - sonst steht ein Rahmen im Rahmen. Die Reiseliste
   ist der einzige Fall; in mockups/06-mobil.html stehen die Karten direkt auf
   dem Sandgrund.

   Die Selektoren sind doppelt geschrieben (.sec.sec-cards statt .sec-cards),
   damit sie .sec und .sec > .tb unabhaengig von der Reihenfolge in der Datei
   schlagen. Ueber die Reihenfolge ist in Schritt 4 dreimal etwas
   schiefgegangen. */
.sec.sec-cards {
    background: transparent;
    border: 0;
    border-radius: 0;
    overflow: visible;
}

/* Ohne Huelle brauchen die Karten keinen Innenabstand - .app-main bringt ihn
   schon mit. */
.sec.sec-cards > .tb {
    padding: 0;
}

.sec.sec-cards > .sec-f {
    padding: 4px 2px 0 2px;
    background: transparent;
    border-top: 0;
}

@media (min-width: 901px) {
    .sec.sec-cards {
        background: #FFFFFF;
        border: 1px solid var(--fuf-sand-400);
        border-radius: var(--fuf-radius-card);
        overflow: hidden;
    }

    .sec.sec-cards > .sec-f {
        padding: 12px 20px;
        background: var(--fuf-sand-50);
        border-top: 1px solid var(--fuf-sand-300);
    }
}

.sec-h {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 12px;
    padding: 14px 20px;
    border-bottom: 1px solid var(--fuf-sand-300);
    background: var(--fuf-sand-50);
}

/* Titel und Chevron bilden die erste Zeile, Zusammenfassung und
   Aktionsknoepfe ruecken dahinter und landen beim Umbruch darunter - dort
   haben sie die volle Breite. Ohne den Sprung faellt der 48-px-Chevron allein
   in die zweite Zeile, sobald die Zusammenfassung daneben nicht mehr passt.
   Ab lg bricht nichts um, dann zaehlt die Reihenfolge des Markups wieder. */
.sec-h .sum,
.sec-h .btn {
    order: 1;
}

.sec-h h2 {
    margin: 0;
    font-size: 16px;
    font-weight: 700;
    flex-grow: 1;
}

.sec-h .sum {
    font-size: 13px;
    color: var(--fuf-brown-500);
}

@media (min-width: 992px) {
    .sec-h .sum,
    .sec-h .btn {
        order: 0;
    }
}

.sec-b {
    padding: 18px 20px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

/* Mobile first: Hinweis und Knopf stehen untereinander, der Knopf ueber die
   volle Breite. Nebeneinander passt "Verkaufspreise uebernehmen & neu
   berechnen" auf 375 px nicht - und .btn traegt white-space: nowrap. */
.sec-f {
    padding: 12px 20px;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    background: var(--fuf-sand-50);
    border-top: 1px solid var(--fuf-sand-300);
}

@media (min-width: 992px) {
    .sec-f {
        flex-direction: row;
        justify-content: space-between;
        align-items: center;
        gap: 0;
    }
}

/* Mobile first, Regel 3: zugeklappt ist der Chevron der Weg in den Abschnitt
   hinein, also braucht er 48 px. Auf dem Desktop bleibt er das 18-px-Icon von
   Mockup 02 - dort klappt man ohnehin selten zu. */
.chev {
    color: var(--fuf-brown-400);
    background: transparent;
    border: 0;
    display: inline-flex;
    align-items: center;
    min-width: var(--fuf-touch);
    min-height: var(--fuf-touch);
    cursor: pointer;
    padding: 0;
}

@media (min-width: 992px) {
    .chev {
        min-width: 0;
        min-height: 0;
    }
}

/* Im Section-Kopf sitzt er am rechten Rand, auch wenn die Zusammenfassung
   vorher umgebrochen ist. Ab lg bleibt kein freier Platz uebrig, den das auto
   aufnehmen koennte - h2 hat ihn schon. */
.sec-h .chev {
    justify-content: center;
    margin-left: auto;
}

.chev svg {
    transition: transform .15s ease;
}

/* Zugeklappt zeigt der Pfeil nach unten, so wie es Mockup 02 fuer die
   eingeklappten Kalkulationszeilen zeigt. */
.chev[aria-expanded="false"] svg {
    transform: rotate(180deg);
}

/* ========================================================================
 * 7. Felder
 * ======================================================================== */

.f {
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.f label {
    font-size: 13px;
    font-weight: 600;
    color: var(--fuf-brown-700);
    display: flex;
    align-items: center;
    gap: 6px;
}

.in {
    display: flex;
    align-items: center;
    height: var(--fuf-control-height);
    border: 1px solid var(--fuf-sand-500);
    border-radius: var(--fuf-radius-control);
    background: #FFFFFF;
    overflow: hidden;
}

.in:focus-within {
    border-color: var(--fuf-green-600);
    box-shadow: 0 0 0 3px rgba(45, 90, 61, .12);
}

.in input,
.in select,
.in textarea {
    border: 0;
    outline: 0;
    background: transparent;
    height: 100%;
    flex-grow: 1;
    min-width: 0;
    padding: 0 12px;
    font: inherit;
    font-size: var(--fuf-control-font);
    color: var(--fuf-brown-900);
}

/* Regel 8: Das Suffix traegt bereits einen Chevron. Ohne -webkit-appearance
 * zeichnet iOS Safari seinen eigenen daneben. */
.in select {
    appearance: none;
    -webkit-appearance: none;
    cursor: pointer;
}

.in .u {
    padding: 0 12px;
    height: 100%;
    display: flex;
    align-items: center;
    background: var(--fuf-sand-100);
    border-left: 1px solid var(--fuf-sand-400);
    color: var(--fuf-brown-500);
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
}

.in .p {
    padding-left: 12px;
    color: #9A8770;
    display: flex;
    align-items: center;
}

/* Geaenderter, noch nicht gespeicherter Wert */
.in.is-dirty {
    border-color: var(--fuf-orange-600);
    box-shadow: 0 0 0 3px rgba(231, 111, 30, .15);
}

/* ========================================================================
 * 8. Kennzahlen
 * ======================================================================== */

.kpi {
    background: #FFFFFF;
    border: 1px solid var(--fuf-sand-400);
    border-radius: var(--fuf-radius-card);
    padding: 14px 18px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.kpi span {
    font-size: 12px;
    color: var(--fuf-brown-400);
    font-weight: 600;
    letter-spacing: .6px;
    text-transform: uppercase;
}

.kpi b {
    font-family: var(--fuf-font-display);
    font-size: 24px;
    font-weight: 500;
    color: var(--fuf-brown-900);
    font-variant-numeric: tabular-nums;
}

.kpi-good {
    background: var(--fuf-green-100);
    border-color: #B9D3C2;
}

.kpi-good b {
    color: var(--fuf-green-700);
}

.kpi-bad {
    background: var(--fuf-red-100);
    border-color: #E9C9C2;
}

.kpi-bad b {
    color: var(--fuf-red-700);
}

/* Zeile im Kalkulationspanel */
.k {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    font-size: 14px;
    color: var(--fuf-brown-700);
}

.k b {
    color: var(--fuf-brown-900);
    font-variant-numeric: tabular-nums;
}

.cl {
    display: flex;
    justify-content: space-between;
    font-size: 13px;
    color: var(--fuf-brown-700);
    padding: 3px 0;
}

.cl b {
    color: var(--fuf-brown-900);
    font-variant-numeric: tabular-nums;
}

/* ========================================================================
 * 8b. Kalkulationszeilen
 *
 * Je Kategorie eine Zeile mit Endpreis, Verkaufspreis und Einnahmen,
 * aufgeklappt der Rechenweg zweispaltig.
 * ======================================================================== */

.calc-wrap {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

/* Die Spaltenkoepfe beschreiben Spalten - mobil gibt es keine. */
.calc-head {
    display: none;
}

@media (min-width: 901px) {
    .calc-head {
        display: grid;
        padding: 6px 16px 0 16px;
        gap: 12px;
    }
}

.calc-rows {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.calc-row {
    border: 1px solid var(--fuf-sand-400);
    border-radius: 10px;
    overflow: hidden;
}

/* Mobile first: die Zeile bricht auf zwei um - oben Kategorie und berechneter
   Endpreis, darunter Verkaufspreis-Feld mit Abweichung und Einnahmen. Der
   Chevron steht rechts ueber beide Zeilen. So gibt es RESPONSIVE.md vor;
   fuenf Spalten waeren auf 390 px je 70 px breit. */
.calc-row-head {
    grid-template-columns: minmax(0, 1fr) minmax(0, auto) 44px;
    grid-template-areas:
        "cat   price chev"
        "sales rev   chev";
    align-items: center;
    padding: 12px 16px;
    gap: 10px 12px;
    background: #FFFFFF;
}

.calc-row-head > :nth-child(1) {
    grid-area: cat;
}

.calc-row-head > :nth-child(2) {
    grid-area: price;
}

.calc-row-head > .calc-sales {
    grid-area: sales;
}

.calc-row-head > .calc-cell.calc-r {
    grid-area: rev;
}

.calc-row-head > .chev {
    grid-area: chev;
}

/* Ab 901 px zurueck auf das Raster aus Abschnitt 5a. Der Block steht hier und
   nicht dort: bei gleicher Spezifitaet gewinnt die spaetere Regel, und
   .calc-row-head steht in der Datei hinter .fuf-grid-calc. Deshalb auch das
   Token - so gibt es das Spaltenmass nur einmal. */
@media (min-width: 901px) {
    .calc-row-head {
        grid-template-columns: var(--fuf-calc-cols);
        grid-template-areas: none;
        gap: 12px;
    }

    .calc-row-head > :nth-child(1),
    .calc-row-head > :nth-child(2),
    .calc-row-head > .calc-sales,
    .calc-row-head > .calc-cell.calc-r,
    .calc-row-head > .chev {
        grid-area: auto;
    }
}

/* Die aufgeklappte Zeile hebt sich vom Rest ab, so wie in Mockup 02. */
.calc-row.is-open .calc-row-head {
    background: var(--fuf-sand-50);
}

.calc-cell {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.calc-cell b {
    font-size: 14px;
}

.calc-r {
    text-align: right;
}

.calc-cell.calc-r {
    align-items: flex-end;
}

.calc-sales {
    display: flex;
    align-items: center;
    gap: 8px;
}

.calc-sales-input {
    font-weight: 700;
}

.calc-dev {
    font-size: 11px;
    font-weight: 700;
    white-space: nowrap;
}

.calc-dev-down {
    color: var(--fuf-amber-700);
}

.calc-dev-up {
    color: var(--fuf-green-600);
}

.calc-body {
    border-top: 1px solid var(--fuf-sand-300);
    padding: 10px 16px 12px 16px;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 0 32px;
}

@media (min-width: 901px) {
    .calc-body {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

.calc-col {
    display: flex;
    flex-direction: column;
}

.cl-total {
    font-weight: 700;
    border-top: 1px solid var(--fuf-sand-300);
    margin-top: 4px;
    padding-top: 6px;
}

.cl-note {
    border-top: 1px solid var(--fuf-sand-300);
    margin-top: 4px;
    padding-top: 6px;
}

/* Herleitung des gemittelten Erwachsenenpreises. Steht ueber den beiden Spalten
 * des Rechenwegs und ist als Sand-Box abgesetzt, weil es eine Vorstufe ist und
 * kein weiterer Schritt der Preiskette. */
.calc-avg {
    grid-column: 1 / -1;
    background: var(--fuf-sand-100);
    border-radius: 10px;
    padding: 8px 12px 10px 12px;
    margin-bottom: 12px;
}

.calc-avg-head {
    font-size: 12px;
    font-weight: 600;
    color: var(--fuf-brown-700);
    margin-bottom: 4px;
}

.calc-avg .cl-total {
    border-top-color: var(--fuf-sand-400);
}

.calc-hint {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.calc-empty,
.calc-placeholder {
    margin: 0;
    padding: 18px;
    border: 1px dashed var(--fuf-sand-400);
    border-radius: 10px;
    text-align: center;
    font-size: 13px;
    color: var(--fuf-brown-400);
}

/* ========================================================================
 * 9. Sprungnavigation
 * ======================================================================== */

.jump {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 10px;
    border-radius: var(--fuf-radius-control);
    font-size: 13px;
    color: var(--fuf-brown-700);
    text-decoration: none;
}

.jump:hover {
    background: var(--fuf-sand-50);
    color: var(--fuf-brown-900);
}

.jump.is-active {
    background: var(--fuf-green-100);
    color: var(--fuf-green-700);
    font-weight: 600;
}

.jump .dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--fuf-sand-500);
    flex-shrink: 0;
}

.jump .dot.is-set {
    background: var(--fuf-green-600);
}

/* ========================================================================
 * 10. Tabelle
 * ======================================================================== */

/* Mobile first: eine Tabelle ist auf dem Handy keine Tabelle, sondern eine
   Liste von Bloecken - pro Zeile ein Block, pro Zelle eine Zeile aus
   Spaltenbeschriftung und Wert. Die Beschriftung kommt aus data-col am <td>,
   die erste Zelle traegt statt dessen .tb-head und wird die Ueberschrift des
   Blocks. Waagerecht scrollen muss dafuer niemand.

   Das Attribut heisst data-col und nicht data-label, weil der
   Bearbeiten-Knopf der Zusatzausgaben schon ein data-label fuer seinen
   Handler traegt.

   Die Rueckstellung zur echten Tabelle steht am Ende dieses Abschnitts und
   nicht in einem eigenen Block weiter unten: eine mobile Regel gehoert an
   denselben Ort wie die Definition, die sie ueberschreibt - sonst gewinnt die
   Definition. */
.tb {
    display: block;
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
}

/* Die Spaltenkoepfe stehen als Beschriftung in den Zellen, die Kopfzeile
   selbst hat auf dem Handy keine Aufgabe. */
.tb thead {
    display: none;
}

.tb tbody,
.tb tfoot {
    display: block;
}

.tb tr {
    display: block;
    padding: 12px 0;
    border-bottom: 1px solid var(--fuf-sand-300);
}

.tb tbody tr:last-child {
    border-bottom: 0;
}

.tb th {
    text-align: left;
    font-size: 12px;
    color: var(--fuf-brown-400);
    letter-spacing: .6px;
    text-transform: uppercase;
    padding: 0 12px 8px 12px;
    border-bottom: 2px solid var(--fuf-sand-400);
    font-weight: 700;
}

.tb td {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    min-width: 0;
    padding: 3px 0;
    border-bottom: 0;
}

/* Die leeren Fuellzellen der Summenzeilen fallen weg - als Block waeren sie
   eine leere Zeile mitten im Stapel. */
.tb td:empty {
    display: none;
}

.tb td[data-col]::before {
    content: attr(data-col);
    flex-shrink: 0;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .6px;
    text-transform: uppercase;
    color: var(--fuf-brown-400);
}

/* Ueberschrift des Blocks: volle Breite, kein Wert daneben. */
.tb td.tb-head {
    display: block;
    padding: 0 0 6px 0;
    font-weight: 700;
    font-size: 15px;
}

/* Aktionsspalte: keine Beschriftung, die Knoepfe stehen rechts. */
.tb td.tb-act {
    justify-content: flex-end;
    padding-top: 8px;
}

/* Tabelle ohne polsterndes Elternteil - Reiseliste, geplante Kosten und die
   beiden Zimmerkarten. Als Bloecke stiessen sie sonst an die Kante. */
.sec > .tb,
.sec > .collapse > .tb,
.room-card .tb {
    padding: 0 20px 14px 20px;
}

.tb .r,
.tb th.r {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Die Summenzeile bleibt eine Zeile: Beschriftung links, Betrag rechts. */
.tb tfoot tr,
.tb tr.sum-row {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 4px 12px;
    padding: 10px 12px;
    border-bottom: 0;
    border-radius: 8px;
    background: var(--fuf-sand-100);
    font-weight: 700;
}

.tb tfoot td,
.tb tr.sum-row td {
    background: var(--fuf-sand-100);
    border-bottom: 0;
    font-weight: 700;
}

.tb-empty td {
    color: var(--fuf-brown-400);
    text-align: center;
    justify-content: center;
}

/* Pfeil, der die Sortierspalte markiert */
.tb-sort {
    color: var(--fuf-green-600);
}

/* Erste Zeile einer Zelle als Titel, zweite als Hilfstext darunter */
.tb-title {
    font: inherit;
    font-weight: 700;
    font-size: 15px;
    color: var(--fuf-brown-900);
    background: transparent;
    border: 0;
    padding: 0;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
}

.tb-title:hover {
    color: var(--fuf-green-700);
    text-decoration: underline;
}

.tb-sub {
    display: block;
}

/* Rueckerstattung, mobile first: "gezahlt ... - Anteil ..." stehen als eine
   Hilfstext-Zeile unter dem Namen, die Erstattung darunter rechts. So gibt es
   RESPONSIVE.md vor, und der Block wird pro Anmeldung eine Zeile kuerzer. */
.tb-refund tbody tr {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    column-gap: 10px;
}

.tb-refund tbody td.tb-head {
    flex: 1 0 100%;
}

.tb-refund tbody td.refund-paid,
.tb-refund tbody td.refund-share {
    flex: 0 0 auto;
    padding-top: 0;
}

.tb-refund tbody td.refund-paid::before,
.tb-refund tbody td.refund-share::before {
    font-size: 13px;
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
}

.tb-refund tbody td[data-col="Erstattung"] {
    flex: 1 0 100%;
}

/* Teilnehmer einer Anmeldung, mobile first: Name fett mit dem Preis rechts
   daneben, darunter Geburtsdatum mit Alter und der Kategorie-Chip in einer
   Zeile. So gibt es RESPONSIVE.md vor. Die Reihenfolge kommt aus `order`, der
   Umbruch daraus, dass der Name die erste Zeile fuellt.

   Die Spaltenbeschriftungen entfallen hier: ein Datum, ein Chip und ein Betrag
   sagen selbst, was sie sind, und drei Beschriftungen je Teilnehmer machen aus
   der Liste wieder eine Tabelle. */
.tb-regs tbody tr {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    column-gap: 10px;
}

.tb-regs tbody td.tb-head {
    order: 1;
    flex: 1 1 auto;
    padding-bottom: 0;
}

.tb-regs tbody td[data-col="Preis"] {
    order: 2;
}

.tb-regs tbody td.reg-date {
    order: 3;
}

.tb-regs tbody td[data-col="Kategorie"] {
    order: 4;
}

.tb-regs tbody td[data-col]::before {
    content: none;
}

/* Reiseliste, mobile first: aus der Zeile wird eine Karte wie in
   mockups/06-mobil.html - Name als Ueberschrift, Zeitraum und Teilnehmer als
   eine Zeile mit Icons, Ueberschuss abgesetzt darunter, Aktionen zuletzt.
   Die Spalte "ID" entfaellt, wie RESPONSIVE.md es vorgibt.

   Status-Chip und Filter-Chip-Leiste aus dem Mockup entfallen ersatzlos: es
   gibt keinen Reisestatus im Datenmodell und keinen Filter in der Liste -
   dieselbe Begruendung wie beim Status-Chip in Schritt 2. */
.tb-trips tbody tr {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    column-gap: 14px;
    padding: 13px 14px;
    margin-bottom: 10px;
    /* Ohne die Huelle aus 4i steht die Karte auf dem Seitenhintergrund und
       braucht ihr Weiss selbst - vorher erbte sie es von der .sec. */
    background: #FFFFFF;
    border: 1px solid var(--fuf-sand-400);
    border-bottom: 1px solid var(--fuf-sand-400);
    border-radius: 10px;
}

.tb td.tb-col-id {
    display: none;
}

.tb-trips tbody td.tb-head {
    flex: 1 0 100%;
}

/* Zeitraum und Teilnehmer stehen nebeneinander in einer Hilfstext-Zeile. */
.tb-trips tbody td.tb-trip-meta {
    flex: 0 0 auto;
    align-items: center;
    gap: 5px;
    padding: 0;
    font-size: 13px;
    color: var(--fuf-brown-400);
}

/* "4 Naechte" haengt sonst als eigene Zeile in der Karte. */
.tb-trips tbody td.tb-trip-meta .tb-sub {
    display: inline;
}

.tb-trips tbody td.tb-trip-meta .tb-sub::before {
    content: "· ";
}

/* Der Ueberschuss ist die Zahl, um die es geht - eigene Zeile mit Trennlinie. */
.tb-trips tbody td.tb-trip-sum {
    flex: 1 0 100%;
    justify-content: flex-end;
    margin-top: 9px;
    padding: 7px 0 0 0;
    border-top: 1px solid var(--fuf-sand-300);
    font-weight: 700;
}

.tb-trips tbody td.tb-trip-sum::before {
    margin-right: auto;
}

.tb-trips tbody td.tb-act {
    flex: 1 0 100%;
    justify-content: flex-start;
}

/* Die Icons gehoeren zur Karte, nicht zur Tabelle. */
.tb-ico {
    flex-shrink: 0;
    color: var(--fuf-brown-400);
}

/* Ab 901 px wieder eine echte Tabelle - dieselbe Grenze wie bei den Rastern
   in Abschnitt 5a. Die feste Spaltenbreite steht hier und nicht in der Basis,
   weil width auf einem Block wirkt, auf einer Tabellenzelle aber nur als
   Vorschlag. */
@media (min-width: 901px) {
    .tb {
        display: table;
    }

    .tb thead {
        display: table-header-group;
    }

    .tb tbody {
        display: table-row-group;
    }

    .tb tfoot {
        display: table-footer-group;
    }

    .tb tr,
    .tb tbody tr:last-child,
    .tb tfoot tr,
    .tb tr.sum-row {
        display: table-row;
        padding: 0;
        border-bottom: 0;
        border-radius: 0;
        background: transparent;
        font-weight: 400;
    }

    .tb td,
    .tb td.tb-head,
    .tb td.tb-act {
        display: table-cell;
        padding: 11px 12px;
        border-bottom: 1px solid var(--fuf-sand-300);
        vertical-align: middle;
    }

    /* Schrift nur an der Blockueberschrift zurueckstellen, nicht an .tb td:
       eine Zelle traegt manchmal selbst eine Klasse (#1 in der Reiseliste und
       die Plan-Spalten der Zimmerkarte sind .help), und .tb td schlaegt eine
       einzelne Klasse in der Spezifitaet. */
    .tb td.tb-head {
        font-weight: 400;
        font-size: inherit;
    }

    .tb td:empty {
        display: table-cell;
    }

    .tb td[data-col]::before {
        content: none;
    }

    .sec > .tb,
    .sec > .collapse > .tb,
    .room-card .tb {
        padding: 0;
    }

    /* Tabelle ohne .sec-b dazwischen: die Karte bringt keine Innenabstaende
     * mit. Die Kopfzeile braucht Luft nach oben, die Zellen fluchten mit der
     * Fusszeile. */
    .sec > .tb th {
        padding: 14px 20px 8px 20px;
    }

    .sec > .tb td {
        padding: 11px 20px;
    }

    .tb tfoot td,
    .tb tr.sum-row td {
        background: var(--fuf-sand-100);
        border-bottom: 0;
        font-weight: 700;
    }

    /* Reiseliste: schmale ID-Spalte, feste Aktionsspalte */
    .tb-col-id {
        width: 60px;
    }

    .tb-col-action {
        width: 200px;
    }

    .tb-refund tbody tr {
        display: table-row;
    }

    .tb-refund tbody td.tb-head,
    .tb-refund tbody td.refund-paid,
    .tb-refund tbody td.refund-share,
    .tb-refund tbody td[data-col="Erstattung"] {
        display: table-cell;
    }

    .tb-regs tbody tr {
        display: table-row;
    }

    .tb-regs tbody td.tb-head,
    .tb-regs tbody td[data-col="Preis"],
    .tb-regs tbody td.reg-date,
    .tb-regs tbody td[data-col="Kategorie"] {
        order: 0;
    }

    .tb-trips tbody tr {
        display: table-row;
        padding: 0;
        margin-bottom: 0;
        background: transparent;
        border: 0;
        border-radius: 0;
    }

    .tb td.tb-col-id,
    .tb-trips tbody td.tb-head,
    .tb-trips tbody td.tb-trip-meta,
    .tb-trips tbody td.tb-trip-sum,
    .tb-trips tbody td.tb-act {
        display: table-cell;
    }

    .tb-trips tbody td.tb-trip-meta,
    .tb-trips tbody td.tb-trip-sum {
        margin-top: 0;
        padding: 11px 20px;
        border-top: 0;
        font-size: inherit;
        font-weight: 400;
        color: inherit;
    }

    /* "4 Naechte" steht am Desktop wieder unter dem Zeitraum. Ohne diese
       Rueckstellung rutscht es in die Zeile und verschiebt die ganze
       Tabelle - 5.627 Pixel Unterschied bei 1440 px. */
    .tb-trips tbody td.tb-trip-meta .tb-sub {
        display: block;
    }

    .tb-trips tbody td.tb-trip-meta .tb-sub::before {
        content: none;
    }

    .tb-ico {
        display: none;
    }
}

/* ========================================================================
 * 11. Chips
 * ======================================================================== */

.chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    border-radius: var(--fuf-radius-chip);
    padding: 3px 10px;
    font-size: 12px;
    font-weight: 700;
    white-space: nowrap;
}

/* Filter-Chip: derselbe Koerper, aber anklickbar und mit Aktivzustand */
button.chip-btn {
    border: 1px solid var(--fuf-sand-400);
    background: var(--fuf-sand-200);
    color: var(--fuf-brown-700);
    cursor: pointer;
    transition: background .12s, color .12s, border-color .12s;
}

button.chip-btn:hover {
    border-color: var(--fuf-sand-500);
}

button.chip-btn.is-active {
    background: var(--fuf-sand-300);
    border-color: var(--fuf-brown-400);
    color: var(--fuf-brown-900);
}

.c-green {
    background: var(--fuf-green-100);
    color: var(--fuf-green-700);
}

.c-amber {
    background: var(--fuf-amber-100);
    color: #7A4A12;
}

.c-brown {
    background: var(--fuf-sand-300);
    color: var(--fuf-brown-900);
}

.c-grey {
    background: var(--fuf-sand-200);
    color: var(--fuf-brown-700);
    border: 1px solid var(--fuf-sand-400);
}

.c-orange {
    background: var(--fuf-orange-100);
    color: #8A3E0B;
}

.c-red {
    background: var(--fuf-red-100);
    color: var(--fuf-red-700);
}

/* ========================================================================
 * 12. Buttons
 *
 * .btn gehoert auch Bootstrap. Die Kollision ist gewollt: so erben noch nicht
 * umgebaute Buttons bereits die neue Form, statt als Fremdkoerper zu wirken.
 * Die Modifier .btn-p/.btn-a/.btn-o/.btn-g/.btn-d kollidieren nicht.
 * ======================================================================== */

.btn {
    height: var(--fuf-touch);
    padding: 0 16px;
    border-radius: var(--fuf-radius-control);
    font: inherit;
    font-size: 14px;
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
}

.btn-p {
    background: var(--fuf-green-600);
    color: #FFFFFF;
    border: 0;
}

.btn-p:hover {
    background: var(--fuf-green-700);
    color: #FFFFFF;
}

.btn-a {
    background: var(--fuf-orange-600);
    color: #FFFFFF;
    border: 0;
}

.btn-a:hover {
    background: #CF5F14;
    color: #FFFFFF;
}

.btn-o {
    background: #FFFFFF;
    color: var(--fuf-green-600);
    border: 1px solid var(--fuf-green-600);
}

.btn-o:hover {
    background: var(--fuf-green-100);
    color: var(--fuf-green-700);
}

.btn-g {
    background: #FFFFFF;
    color: var(--fuf-brown-700);
    border: 1px solid var(--fuf-sand-500);
    font-weight: 600;
}

.btn-g:hover {
    background: var(--fuf-sand-50);
    color: var(--fuf-brown-900);
}

.btn-d {
    background: #FFFFFF;
    color: var(--fuf-red-700);
    border: 1px solid #E0B4B4;
    font-weight: 600;
}

.btn-d:hover {
    background: var(--fuf-red-100);
    color: var(--fuf-red-700);
}

.btn-s {
    height: var(--fuf-touch);
    padding: 0 12px;
    font-size: 13px;
}

.btn-lg-save {
    height: var(--fuf-touch);
    font-size: 15px;
}

/* Button in der Kopfleiste - im Menuepanel ueber die volle Breite. */
.btn-hdr {
    height: var(--fuf-touch);
    width: 100%;
}

.btn:disabled,
.btn.disabled {
    opacity: .5;
    cursor: not-allowed;
}

/* Icon-only */
.ib {
    width: var(--fuf-touch);
    height: var(--fuf-touch);
    border-radius: var(--fuf-radius-control);
    border: 1px solid var(--fuf-sand-500);
    background: #FFFFFF;
    color: var(--fuf-brown-500);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    padding: 0;
}

.ib:hover {
    background: var(--fuf-sand-50);
    color: var(--fuf-brown-900);
}

.ib-danger {
    color: var(--fuf-red-700);
}

.ib:disabled {
    opacity: .45;
    cursor: not-allowed;
}

.fuf-actions {
    display: inline-flex;
    gap: 6px;
    align-items: center;
}

/* ========================================================================
 * 13. Tabs
 * ======================================================================== */

.nav-tabs {
    border-bottom: 1px solid var(--fuf-sand-400);
    gap: 4px;
}

.nav-tabs .nav-link {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    border: 0;
    border-bottom: 3px solid transparent;
    border-radius: 0;
    background: transparent;
    color: var(--fuf-brown-500);
    font-weight: 600;
    font-size: 15px;
    padding: 10px 16px;
}

.nav-tabs .nav-link:hover {
    border-color: transparent;
    color: var(--fuf-brown-900);
    background: transparent;
    isolation: auto;
}

.nav-tabs .nav-link.active {
    color: var(--fuf-green-700);
    background: transparent;
    border-bottom-color: var(--fuf-green-600);
}

/* ========================================================================
 * 14. Leerzustand
 * ======================================================================== */

.fuf-empty {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 16px 20px;
    border: 2px dashed #C9BFAA;
    border-radius: var(--fuf-radius-card);
    background: var(--fuf-sand-50);
}

.fuf-empty-icon {
    width: 40px;
    height: 40px;
    border-radius: 10px;
    background: var(--fuf-orange-100);
    color: var(--fuf-orange-600);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.fuf-empty-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex-grow: 1;
}

.fuf-empty-text b {
    font-size: 15px;
}

/* ========================================================================
 * 15. Anmeldungen
 * ======================================================================== */

/* CSV-Dropzone. Das Dateifeld bleibt ein echtes <input type="file">, nur
 * abgeblendet - erreichbar ueber das <label> und ueber Drag & Drop. */
/* Mobile first: aus der Ziehflaeche wird ein Datei-Knopf. Ziehen gibt es auf
   dem Handy nicht, also auch keinen gestrichelten Rahmen und kein Icon -
   `CSV auswaehlen` und `Importieren` stehen als zwei Knoepfe ueber die volle
   Breite untereinander. So gibt es RESPONSIVE.md vor. */
.dropzone {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    padding: 0;
    border: 0;
    background: transparent;
    transition: border-color .12s, background .12s;
}

@media (min-width: 901px) {
    .dropzone {
        flex-direction: row;
        align-items: center;
        gap: 14px;
        padding: 16px;
        border: 2px dashed var(--fuf-sand-500);
        border-radius: 10px;
        background: var(--fuf-sand-50);
    }
}

.dropzone.is-over {
    border-color: var(--fuf-green-600);
    background: var(--fuf-green-100);
}

/* Icon und Zieh-Zeile gehoeren zur Flaeche, nicht zum Knopf - unter 901 px
   sind sie weg. Die Ausblendung steht hier und nicht oben beim .dropzone-Block:
   bei gleicher Spezifitaet gewinnt die spaetere Regel, und das ist diese
   Definition. Dieselbe Lehre wie in 3a. */
.dropzone-icon {
    display: none;
    width: 40px;
    height: 40px;
    border-radius: 10px;
    background: var(--fuf-green-100);
    color: var(--fuf-green-600);
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

@media (min-width: 901px) {
    .dropzone-icon {
        display: flex;
    }
}

.dropzone-text {
    display: flex;
    flex-direction: column;
    gap: 3px;
    flex-grow: 1;
    min-width: 0;
}

.dropzone-text b {
    font-size: 14px;
}

.dropzone-drag {
    display: none;
    font-size: 14px;
}

/* Nur das Inline-Label in der Zieh-Zeile ist ein Link. Als
   `.dropzone-text label` traf die Regel auch den Datei-Knopf und schlug
   dessen eigene Regel in der Spezifitaet. */
.dropzone-drag label {
    color: var(--fuf-green-600);
    text-decoration: underline;
    cursor: pointer;
}

/* Der Datei-Knopf ist ein .btn und darf die Unterstreichung des Inline-Labels
   nicht erben. */
.dropzone-pick {
    justify-content: center;
    cursor: pointer;
}

@media (min-width: 901px) {
    .dropzone-drag {
        display: revert;
    }

    .dropzone-pick {
        display: none;
    }
}

.dropzone-input {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    border: 0;
}

/* Manuell-Formular */
.reg-manual {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 14px 16px;
    border: 1px solid var(--fuf-sand-400);
    border-radius: 10px;
}

.reg-manual-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.reg-manual-head b {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .6px;
    text-transform: uppercase;
    color: var(--fuf-brown-400);
}

/* Mobile first: die Felder stehen untereinander. Nebeneinander bleiben von
   390 px fuer "Geburtsdatum" keine 150 px, und die feste Breite der
   Kategoriespalte macht das Feld daneben unbrauchbar schmal. */
.reg-manual-row {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

@media (min-width: 901px) {
    .reg-manual-row {
        flex-direction: row;
    }
}

.reg-manual-row .f {
    flex-grow: 1;
    min-width: 0;
}

/* In der Spalte ist flex-basis die Hoehe, nicht die Breite - ohne
   Ruecksetzung stand das Kategoriefeld 170 px hoch da. */
.reg-manual-row .f-cat,
.reg-manual-row .f-date {
    flex: 0 0 auto;
}

@media (min-width: 901px) {
    .reg-manual-row .f-cat {
        flex: 0 0 170px;
    }

    .reg-manual-row .f-date {
        flex: 0 0 150px;
    }
}

/* Die Teilnehmerzeilen liegen in einem eigenen Container, brauchen also ihren
 * eigenen Abstand - der gap der Karte greift nur eine Ebene hoeher. */
.reg-manual-participants {
    display: flex;
    flex-direction: column;
    gap: 10px;
}


.reg-manual-foot {
    display: flex;
    gap: 6px;
    align-items: center;
}

.reg-manual-foot .btn {
    margin-left: auto;
}

/* Filter und Suche ueber der Liste. Mobile first: untereinander, die
   Chip-Leiste darf waagerecht scrollen. Nebeneinander stand das Suchfeld auf
   390 px halb ausserhalb. */
.reg-controls {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
}

.reg-filters {
    display: flex;
    gap: 4px;
    overflow-x: auto;
}

@media (min-width: 901px) {
    .reg-controls {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
    }

    .reg-filters {
        overflow-x: visible;
    }
}

.reg-controls .in-search {
    width: 100%;
    min-width: 0;
}

.reg-no-match {
    padding: 14px 4px;
}

/* Liste der Anmeldungen */
.reg-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.reg-item {
    border: 1px solid var(--fuf-sand-400);
    border-radius: 10px;
    overflow: hidden;
}

/* Mobile first: Umschalter und Chevron teilen die erste Zeile, die
   Aktionsknoepfe stehen darunter rechts. Alle drei nebeneinander lassen dem
   Umschalter auf 390 px so wenig Breite, dass die Chips in eine schmale
   Spalte fallen. */
.reg-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    background: #FFFFFF;
}

@media (min-width: 901px) {
    .reg-row {
        flex-wrap: nowrap;
    }
}

/* Aufgeklappte Anmeldung hebt sich ab. Die Aktionsknoepfe stehen neben dem
 * Umschalter, nicht darin - ein Button im Button waere ungueltiges Markup. */
.reg-item:has(> .collapse.show) .reg-row {
    background: var(--fuf-sand-50);
}

/* Mobile first: der Name steht oben, Chips und Betrag brechen darunter um.
   Auf einer Zeile schoben sie sich gegenseitig aus dem Bild - RESPONSIVE.md
   sagt dazu nur "die Chips brechen um". */
.reg-row-main {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 10px;
    /* flex-basis 0 statt auto: mit auto ist die Wunschbreite die des Inhalts,
       und der Chevron rutschte in eine eigene Zeile. */
    flex: 1 1 0;
    order: 1;
    min-width: 0;
    padding: 12px 0 12px 16px;
    background: transparent;
    border: 0;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
}

@media (min-width: 901px) {
    .reg-row-main {
        flex-wrap: nowrap;
        flex: 1 1 auto;
        gap: 10px;
    }
}

.reg-row .chev {
    order: 2;
    padding: 0 16px;
    align-self: stretch;
}

/* Die feste Mindestbreite richtet die Namen am Desktop aneinander aus. Auf
   390 px war sie die Ursache dafuer, dass Chips und Betrag herausragten. */
.reg-name {
    font-size: 15px;
    font-weight: 700;
    flex: 1 0 100%;
    min-width: 0;
}

@media (min-width: 901px) {
    .reg-name {
        flex: 0 1 auto;
        min-width: 190px;
    }
}

.reg-amount {
    margin-left: auto;
    font-size: 15px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--fuf-green-600);
}

.reg-amount-none {
    color: var(--fuf-brown-400);
    font-weight: 600;
}

.reg-actions {
    display: inline-flex;
    gap: 6px;
    flex: 1 0 100%;
    order: 3;
    justify-content: flex-end;
    padding: 0 16px 10px 16px;
}

@media (min-width: 901px) {
    .reg-actions {
        flex: 0 0 auto;
        padding: 0 0 0 8px;
    }

    /* Die Reihenfolge fuer die zweizeilige Kopfzeile zurueckstellen. Ohne das
       zieht `order` auch am Desktop den Chevron vor die Aktionsknoepfe --
       2.739 Pixel Unterschied bei 1440 px. Dieselbe Falle wie beim
       `order`-Sprung im Section-Kopf in 3d. */
    .reg-row-main,
    .reg-row .chev,
    .reg-actions {
        order: 0;
    }
}

.reg-body {
    border-top: 1px solid var(--fuf-sand-300);
    padding: 6px 16px 12px 16px;
    background: #FFFFFF;
}

.reg-body .tb {
    font-size: 13px;
}

/* Mobile first: die beiden Hilfstexte stehen untereinander. Nebeneinander
   bleiben je 180 px, und beide sind ganze Saetze. */
.reg-body-foot {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding-top: 10px;
}

@media (min-width: 901px) {
    .reg-body-foot {
        flex-direction: row;
        justify-content: space-between;
        align-items: center;
        gap: 12px;
    }
}

.reg-age {
    margin-left: 8px;
}

.reg-date {
    font-variant-numeric: tabular-nums;
}

@media (min-width: 1101px) {
    .fuf-grid-intake {
        grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
    }
}

/* ========================================================================
 * 15b. Zimmerbedarf
 * ======================================================================== */

.room-card {
    border: 1px solid var(--fuf-sand-400);
    border-radius: 10px;
    overflow: hidden;
}

.room-card-h {
    padding: 10px 14px;
    background: var(--fuf-sand-50);
    border-bottom: 1px solid var(--fuf-sand-300);
    font-weight: 700;
    font-size: 14px;
}

.room-card .tb {
    font-size: 14px;
}

/* Belegung je Zimmertyp: Balken und Zahl "angemeldet/reserviert" in einer
   Zelle. Anders als frueher bleibt der Balken auf dem Handy stehen - er ist
   jetzt die Aussage und keine Wiederholung der Zahl. Die Huelle .room-fill ist
   ein eigenes Flex-Element, damit die Zelle am Desktop table-cell bleiben
   kann. */
.tb td.room-fill-cell {
    display: block;
}

.room-fill {
    display: flex;
    align-items: center;
    gap: 12px;
}

.room-fill .bar {
    flex: 1 1 auto;
    min-width: 0;
}

.room-fill-num {
    flex-shrink: 0;
    min-width: 3.5em;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.room-fill-num.is-over {
    color: var(--fuf-red-700);
}

@media (min-width: 901px) {
    .tb td.room-fill-cell {
        display: table-cell;
        width: 60%;
    }
}

/* Die Breite kommt als Inline-Style aus dem Renderer - sie ist ein
 * Datenwert, kein Stil. Ohne Zustand (keine Reservierungen) zeigt der Balken
 * den Anteil an der groessten Kategorie; mit Reservierungen die Belegung:
 * teilweise gelb (Zimmer frei), genau voll gruen, Ueberlauf rot. */
.bar {
    display: block;
    height: 8px;
    background: var(--fuf-sand-300);
    border-radius: 4px;
    overflow: hidden;
}

.bar > span {
    display: block;
    height: 100%;
    background: var(--fuf-green-600);
}

.bar.is-partial > span {
    background: var(--fuf-amber-500);
}

.bar.is-full > span {
    background: var(--fuf-green-600);
}

.bar.is-over > span {
    background: var(--fuf-red-700);
}

.cat-ist {
    white-space: nowrap;
}

.cat-ist .chip {
    margin-left: 6px;
    padding: 1px 6px;
}

/* ========================================================================
 * 15c. Abrechnung
 * ======================================================================== */

/* KPI mit Vergleichswert: Ist gross, Abweichung daneben, Plan klein darunter */
/* Mobile first: die Abweichung rutscht unter die Zahl, wenn sie nicht
   danebenpasst. In der halben Zeile aus 4c ist neben "-11.649,80 €" kein
   Platz mehr fuer "-13.784,20 €", und .kpi-dev traegt white-space: nowrap. */
.kpi-line {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 8px;
}

.kpi-dev {
    font-size: 12px;
    font-weight: 700;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    color: var(--fuf-brown-400);
}

.kpi-dev-bad {
    color: var(--fuf-amber-700);
}

.kpi-dev-good {
    color: var(--fuf-green-600);
}

/* Erfassungszeile fuer eine zusaetzliche Ausgabe */
/* Mobile first: Bezeichnung, Betrag und Knopf stehen untereinander -- das ist
   der wichtigste Handy-Vorgang, und nebeneinander ueberlagerten sich auf
   390 px die Feldbeschriftungen. `flex: 0 0 170px` waere in der Spalte
   ausserdem eine Hoehe, nicht eine Breite; dieselbe Falle wie beim
   Kategoriefeld in 4f. */
.expense-form {
    display: flex;
    flex-direction: column;
    /* .box-sand setzt align-items: end, damit Beschriftung und Feld in der
       Zeile auf einer Grundlinie stehen. In der Spalte ist das die Querachse:
       die Felder wurden rechtsbuendig und nur so breit wie ihr Inhalt. */
    align-items: stretch;
    gap: 12px;
}

.expense-form .f {
    flex-grow: 1;
    min-width: 0;
}

@media (min-width: 901px) {
    .expense-form {
        flex-direction: row;
        align-items: end;
    }

    .expense-form .f-amount {
        flex: 0 0 170px;
    }
}

.tb-actions {
    display: inline-flex;
    gap: 6px;
}

/* Gesamtabrechnung als Rechenkette statt Tabelle */
.chain {
    gap: 0;
}

.chain-row {
    padding: 9px 0;
    font-size: 15px;
}

.chain-row + .chain-row {
    border-top: 1px solid var(--fuf-sand-300);
}

.chain-total {
    padding: 10px 12px;
    margin-top: 6px;
    font-size: 15px;
    font-weight: 700;
    background: var(--fuf-sand-100);
    border-radius: 8px;
}

.chain-surplus {
    padding: 12px 14px;
    margin-top: 8px;
    font-size: 16px;
    font-weight: 700;
    background: var(--fuf-green-600);
    border-radius: 8px;
    color: var(--fuf-on-dark);
}

.chain-surplus b {
    color: #FFFFFF;
    font-family: var(--fuf-font-display);
    font-size: 22px;
}

/* Ein Defizit gehoert nicht auf Gruen. Gleiche Behandlung wie im
 * Kalkulationspanel der Planung (.pnl-green-bad). */
.chain-surplus-bad {
    background: var(--fuf-brown-900);
}

.chain-surplus-bad span {
    color: var(--fuf-amber-500);
}

/* Rueckerstattung: Einbehalt links, Herleitung rechts - erst ab 1101 px,
   Rueckstellung am Ende dieses Abschnitts */
.fuf-grid-refund {
    grid-template-columns: minmax(0, 1fr);
    align-items: stretch;
}

.box-amber {
    background: var(--fuf-amber-100);
    border: 1px solid #E8CFA4;
    border-radius: 10px;
    padding: 14px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

/* Mobile first: eine Spalte. Zwei Spuren standen hier bei jeder Breite -- der
   Block ist beim Umdrehen der Queries in 3a uebersehen worden, weil er nie in
   einem max-width-Block stand. Auf 390 px blieben je 170 px, und
   "Gesamteinnahmen (Billing) 2.321,40 €" stand bis an die Kante. */
.refund-calc {
    border: 1px solid var(--fuf-sand-400);
    border-radius: 10px;
    padding: 12px 16px;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 4px 32px;
    align-content: center;
}

.refund-calc .cl-total {
    font-size: 15px;
}

@media (min-width: 901px) {
    .refund-calc {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .refund-calc .cl-total {
        grid-column: span 2;
    }
}


.refund-formula {
    margin-left: 8px;
    font-weight: 400;
}

@media (min-width: 1101px) {
    .fuf-grid-refund {
        grid-template-columns: 220px minmax(0, 1fr);
    }
}

/* ========================================================================
 * 15d. Wechsel zwischen Planung und Abrechnung
 * ======================================================================== */

/* Zaehler am inaktiven Tab - der eigentliche Grund hinueberzuwechseln. */
.tab-chip {
    font-size: 10px;
    padding: 1px 6px;
    margin-left: 2px;
}

.nav-link.active .tab-chip {
    display: none;
}

/* a) Volle Zeile am Seitenende */
.switch-cta {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 14px 18px;
    background: #FFFFFF;
    border: 1px solid var(--fuf-sand-400);
    border-radius: var(--fuf-radius-card);
    text-decoration: none;
    color: inherit;
}

.switch-cta:hover {
    border-color: var(--fuf-sand-500);
    color: inherit;
}

.switch-cta-icon {
    width: 42px;
    height: 42px;
    border-radius: 10px;
    background: var(--fuf-green-100);
    color: var(--fuf-green-600);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.switch-cta-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex-grow: 1;
    min-width: 0;
}

.switch-cta-text b {
    font-size: 15px;
}

.switch-cta-label {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .6px;
    text-transform: uppercase;
    color: var(--fuf-brown-400);
}

/* Der ganze Block ist der Link; der Knopf darin ist nur Optik, sonst saesse
   ein interaktiver Knoten im anderen. */
.switch-cta-btn {
    pointer-events: none;
    flex-shrink: 0;
}

/* Mobile first: eine Zeile mit Icon, Titel, Stand und Pfeil. "Anderer Bereich"
   und "Oeffnen" kosten die Breite, die der Stand braucht - vom Knopf bleibt
   das Pfeil-Quadrat. Ab lg ist es wieder die Karte aus DESIGN.md. */
.switch-cta-label,
.switch-cta-word {
    display: none;
}

.switch-cta-btn {
    min-width: var(--fuf-touch);
    padding: 0;
}

@media (min-width: 992px) {
    .switch-cta-label,
    .switch-cta-word {
        display: inline;
    }

    .switch-cta-btn {
        min-width: 0;
        padding: 0 16px;
    }
}

.switch-cta-back .switch-cta-text {
    text-align: right;
}

/* b) Letzter Eintrag der Sprungnavigation, hinter einer Trennlinie: er zeigt,
   dass das kein Abschnitt dieser Seite mehr ist. */
.jump-sep {
    display: block;
    height: 1px;
    background: var(--fuf-sand-300);
    margin: 6px 4px;
}

.jump-switch {
    font-weight: 700;
    color: var(--fuf-green-600);
}

.jump-switch:hover {
    color: var(--fuf-green-700);
}

.jump-switch-count {
    margin-left: auto;
    font-size: 11px;
}

/* Hinweis in der Abrechnung, solange die Planung ungespeichert ist */
.stale-note {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    border-radius: 10px;
    background: var(--fuf-amber-100);
    border: 1px solid #E8CFA4;
    color: #7A4A12;
    font-size: 13px;
}

.stale-note svg {
    flex-shrink: 0;
}

.stale-note .btn {
    margin-left: auto;
    flex-shrink: 0;
}

/* ========================================================================
 * 16. Modals
 * ======================================================================== */

.modal-content {
    border: 1px solid var(--fuf-sand-400);
    border-radius: 14px;
    overflow: hidden;
}

.modal-header {
    background: var(--fuf-sand-50);
    border-bottom: 1px solid var(--fuf-sand-300);
    padding: 16px 20px;
    align-items: flex-start;
}

.modal-title-group {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

h2.modal-title {
    margin: 0;
    font-family: var(--fuf-font-display);
    font-size: 20px;
    font-weight: 500;
}

.modal-title-group .help {
    font-size: 13px;
}

/* Mobile first: das Blatt nutzt die Breite, der Rand darf schmaler sein als im
   zentrierten Dialog. */
.modal-body {
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

@media (min-width: 992px) {
    .modal-body {
        padding: 18px 22px;
    }
}

/* Suche und Aktion im Kopf des Benutzer-Modals. Mobile first untereinander -
   nebeneinander bleiben dem Suchfeld auf 390 px keine 200 px. */
.modal-toolbar {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
}

@media (min-width: 992px) {
    .modal-toolbar {
        flex-direction: row;
        justify-content: space-between;
        align-items: center;
        gap: 12px;
    }
}

.modal-toolbar .in-search {
    width: 100%;
    min-width: 0;
}

/* Meldungsbox fuer Benutzer- und Einladungs-Modal */
.status-note {
    font-size: 13px;
    padding: 10px 14px;
    border-radius: 10px;
    background: var(--fuf-sand-100);
    color: var(--fuf-brown-700);
}

.status-note.is-ok {
    background: var(--fuf-green-100);
    color: var(--fuf-green-700);
    font-weight: 600;
}

.status-note.is-error {
    background: var(--fuf-red-100);
    color: var(--fuf-red-700);
    font-weight: 600;
}

/* Benutzerzeile: Initialen-Kreis vor der E-Mail */
.user-cell {
    display: flex;
    align-items: center;
    gap: 10px;
}

.user-avatar {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: var(--fuf-green-100);
    color: var(--fuf-brown-900);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    font-weight: 700;
    flex-shrink: 0;
}

/* Globale Settings: zwei beschriftete Gruppen */
#settings-form {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.settings-group {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.settings-group-split {
    border-top: 1px solid var(--fuf-sand-300);
    padding-top: 14px;
}

.settings-group-label {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .6px;
    text-transform: uppercase;
    color: var(--fuf-brown-400);
}

/* Mobile first: die Knopfleiste sitzt am unteren Rand des Blattes und teilt
   sich die Breite. Bootstrap haelt sie ueber .modal-fullscreen-lg-down
   ausserhalb des scrollenden .modal-body, sie bleibt also stehen.
   Regel 6: unter der Leiste liegt auf dem iPhone die Home-Indicator-Leiste. */
.modal-footer {
    background: var(--fuf-sand-50);
    border-top: 1px solid var(--fuf-sand-300);
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom)) 16px;
    flex-wrap: nowrap;
    gap: 8px;
}

/* Die Knoepfe teilen sich die Zeile zu gleichen Teilen. Bootstrap gibt
   .modal-footer > * eine eigene Margin; sie bleibt stehen, damit der Desktop
   unberuehrt ist, und faellt neben dem gap kaum ins Gewicht. */
.modal-footer > .btn {
    flex: 1 1 0;
    min-width: 0;
}

@media (min-width: 992px) {
    .modal-footer {
        flex-wrap: wrap;
        padding: 12px 20px;
    }

    .modal-footer > .btn {
        flex: 0 0 auto;
    }
}

/* Die Modals bringen ihre eigenen Abstaende mit - der Rest kommt aus .tb. */
.modal-body > .tb {
    margin: 0;
}

/* ========================================================================
 * 17. Bootstrap-Varianten-Bruecke
 *
 * --bs-primary allein genuegt nicht: Bootstrap 5.3 faerbt Buttons ueber
 * eigene --bs-btn-*-Properties je Variante, und der Fokusring von
 * .form-control ist fest verdrahtet. Ohne diese Bruecke bleiben noch nicht
 * umgebaute Controls und die Auth-Seiten Bootstrap-blau.
 * ======================================================================== */

.btn-primary,
.btn-success {
    --bs-btn-color: #FFFFFF;
    --bs-btn-bg: var(--fuf-green-600);
    --bs-btn-border-color: var(--fuf-green-600);
    --bs-btn-hover-color: #FFFFFF;
    --bs-btn-hover-bg: var(--fuf-green-700);
    --bs-btn-hover-border-color: var(--fuf-green-700);
    --bs-btn-active-color: #FFFFFF;
    --bs-btn-active-bg: var(--fuf-green-700);
    --bs-btn-active-border-color: var(--fuf-green-700);
    --bs-btn-disabled-color: #FFFFFF;
    --bs-btn-disabled-bg: var(--fuf-green-600);
    --bs-btn-disabled-border-color: var(--fuf-green-600);
    --bs-btn-focus-shadow-rgb: 45, 90, 61;
}

.btn-outline-primary,
.btn-outline-success {
    --bs-btn-color: var(--fuf-green-600);
    --bs-btn-border-color: var(--fuf-green-600);
    --bs-btn-hover-color: var(--fuf-green-700);
    --bs-btn-hover-bg: var(--fuf-green-100);
    --bs-btn-hover-border-color: var(--fuf-green-600);
    --bs-btn-active-color: var(--fuf-green-700);
    --bs-btn-active-bg: var(--fuf-green-100);
    --bs-btn-active-border-color: var(--fuf-green-600);
    --bs-btn-disabled-color: var(--fuf-green-600);
    --bs-btn-disabled-border-color: var(--fuf-green-600);
    --bs-btn-focus-shadow-rgb: 45, 90, 61;
}

.btn-outline-secondary {
    --bs-btn-color: var(--fuf-brown-700);
    --bs-btn-border-color: var(--fuf-sand-500);
    --bs-btn-hover-color: var(--fuf-brown-900);
    --bs-btn-hover-bg: var(--fuf-sand-50);
    --bs-btn-hover-border-color: var(--fuf-sand-500);
    --bs-btn-active-color: var(--fuf-brown-900);
    --bs-btn-active-bg: var(--fuf-sand-100);
    --bs-btn-active-border-color: var(--fuf-sand-500);
    --bs-btn-disabled-color: var(--fuf-brown-500);
    --bs-btn-disabled-border-color: var(--fuf-sand-500);
    --bs-btn-focus-shadow-rgb: 122, 102, 81;
}

.btn-outline-danger {
    --bs-btn-color: var(--fuf-red-700);
    --bs-btn-border-color: #E0B4B4;
    --bs-btn-hover-color: var(--fuf-red-700);
    --bs-btn-hover-bg: var(--fuf-red-100);
    --bs-btn-hover-border-color: #E0B4B4;
    --bs-btn-active-color: var(--fuf-red-700);
    --bs-btn-active-bg: var(--fuf-red-100);
    --bs-btn-active-border-color: #E0B4B4;
    --bs-btn-disabled-color: var(--fuf-red-700);
    --bs-btn-disabled-border-color: #E0B4B4;
    --bs-btn-focus-shadow-rgb: 155, 44, 44;
}

.btn-outline-warning {
    --bs-btn-color: var(--fuf-amber-700);
    --bs-btn-border-color: #E8C98F;
    --bs-btn-hover-color: var(--fuf-amber-700);
    --bs-btn-hover-bg: var(--fuf-amber-100);
    --bs-btn-hover-border-color: #E8C98F;
    --bs-btn-active-color: var(--fuf-amber-700);
    --bs-btn-active-bg: var(--fuf-amber-100);
    --bs-btn-active-border-color: #E8C98F;
    --bs-btn-focus-shadow-rgb: 180, 83, 9;
}

/* Fokusring: Bootstrap verdrahtet hier feste Blauwerte. */
.form-control:focus,
.form-select:focus,
.form-check-input:focus {
    border-color: var(--fuf-green-600);
    box-shadow: 0 0 0 3px rgba(45, 90, 61, .15);
}

.form-check-input:checked {
    background-color: var(--fuf-green-600);
    border-color: var(--fuf-green-600);
}

.form-control,
.form-select {
    border-color: var(--fuf-sand-500);
    color: var(--fuf-brown-900);
}

.form-label {
    font-size: 13px;
    font-weight: 600;
    color: var(--fuf-brown-700);
}

/* Bootstrap-Tabellen, solange sie noch nicht auf .tb umgestellt sind */
.table {
    --bs-table-striped-bg: var(--fuf-sand-50);
    --bs-table-hover-bg: var(--fuf-sand-100);
    --bs-table-border-color: var(--fuf-sand-300);
}

.card {
    border-color: var(--fuf-sand-400);
    border-radius: var(--fuf-radius-card);
}

.card-header {
    background: var(--fuf-sand-50);
    border-bottom-color: var(--fuf-sand-300);
    font-weight: 700;
}

.text-muted {
    color: var(--fuf-brown-500) !important;
}

.text-success {
    color: var(--fuf-green-600) !important;
}

.text-danger {
    color: var(--fuf-red-700) !important;
}

/* ========================================================================
 * 18. Mobile first
 *
 * Grundlage: docs/design-handoff/RESPONSIVE.md, Schritt 1. Die Werte ausserhalb
 * dieses Abschnitts sind die Handy-Werte; hier stehen nur die Rueckstellungen
 * fuer den Desktop. Wer eine Groesse aendert, aendert also zuerst die mobile.
 *
 * Seit Schritt 3 hat die Datei keine @media (max-width: ...) mehr. Die
 * Spaltenlayouts, die vorher so geschaltet wurden, stehen jetzt einspaltig in
 * der Basis; ihre Spaltenzahl kommt in @media (min-width: 901px) bzw.
 * (min-width: 1101px) direkt beim Baustein dazu.
 *
 * Seit Schritt 2 stehen groessere Rueckstellungen nicht mehr hier, sondern in
 * einem eigenen @media (min-width: 992px) direkt beim Baustein - fuer die
 * Kopfleiste in Abschnitt 4, fuer Reisekopf und Umschalter in Abschnitt 5b.
 * Hier bleiben nur die Tokens und die Einzelmasse, die zu keinem Baustein
 * gehoeren.
 * ======================================================================== */

/* Regel 1: Felder ausserhalb von .in - Suche, Datei, freistehende Eingaben.
 * Checkbox, Radio und Range haben keine Textzeile und bleiben unberuehrt. */
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="hidden"]),
select,
textarea {
    font-size: var(--fuf-control-font);
}

/* Regel 3: mindestens 8px zwischen zwei Touch-Zielen. Bei 6px trifft der
 * Daumen zwischen Bearbeiten und Loeschen regelmaessig daneben. */
.reg-actions,
.tb-actions {
    gap: 8px;
}

@media (min-width: 992px) {
    :root {
        --fuf-control-height: 42px;
        --fuf-control-font: 15px;
        --fuf-touch: 34px;
        --fuf-bar-space: 0px;
    }

    /* Was sich nicht auf ein Token abbilden laesst, weil die Desktop-Werte
     * je Button abweichen. */
    .btn {
        height: 40px;
    }

    .btn-lg-save {
        height: 46px;
    }

    .btn-hdr {
        height: 38px;
        width: auto;
    }

    .trip-head-back {
        width: 32px;
        height: 32px;
    }

    .in-sm {
        width: 110px;
        height: 36px;
    }

    .page-head .in-search,
    .modal-toolbar .in-search {
        width: 260px;
        flex-shrink: 0;
    }

    .reg-controls .in-search {
        width: 240px;
        height: 36px;
        flex-shrink: 0;
    }
}

/* Regel 2: Die Zahlenfelder sind type="text", also markiert app.js unbrauchbare
 * Eingaben selbst. Der Rahmen sitzt am .in-Wrapper, nicht am input - dort ist
 * er sichtbar. */
.in:has(input.is-invalid) {
    border-color: var(--fuf-red-700);
}

.in:has(input.is-invalid):focus-within {
    box-shadow: 0 0 0 3px rgba(155, 44, 44, .12);
}
