/*
 * Mevit Rental – Design-Grundlage
 *
 * Enthält Reset, Design-Tokens und alle Bausteine, die sowohl im öffentlichen
 * Bereich als auch im Verwaltungsbereich vorkommen (Buttons, Formulare, Tabellen,
 * Badges, Kalender). Bereichsspezifisches liegt in site.css bzw. admin.css.
 */

/* ---------------------------------------------------------- Ausweichschrift */

/*
 * Inter kommt von fonts.bunny.net und ist beim ersten Aufruf noch nicht da.
 * Bis dahin steht Arial, und die läuft schmaler: Beim Austausch wurde jeder
 * Punkt der Kopfzeile breiter, die Zeile sprang, und eine Kategorie konnte in
 * die zweite Zeile rutschen – die Kopfzeile flackerte beim Laden. Diese
 * Arial ist auf die Maße von Inter gezogen (Werte wie in next/font), der
 * Austausch ändert damit nur noch die Form der Buchstaben, nicht ihren Platz.
 */
@font-face {
    font-family: "Inter Fallback";
    src: local("Arial"), local("ArialMT");
    size-adjust: 107.4%;
    ascent-override: 90.2%;
    descent-override: 22.48%;
    line-gap-override: 0%;
}

/* ---------------------------------------------------------------- Tokens */

:root {
    /* Markenfarben: tiefes Petrol als Basis, Schwarz als Akzent. */
    --brand-900: #0b2b33;
    --brand-800: #0f3a45;
    --brand-700: #14515f;
    --brand-600: #1a6b7d;
    --brand-500: #22879d;
    --brand-100: #dcf0f4;
    --brand-50: #f1fafb;

    /*
     * Der Akzent ist die Farbe der Handlungsknöpfe – „Suchen", „Anfragen",
     * „Bezahlen". Kein reines #000: Ein leicht ins Blaugraue gezogenes Schwarz
     * wirkt neben dem Petrol ruhiger und lässt Ränder und Schatten überhaupt
     * erst erkennbar bleiben.
     *
     * Wie überall hier gilt: größere Zahl = dunkler. `--accent-400` ist die
     * Ausnahme nach oben und dient dem Hover – bei einer schwarzen Fläche ist
     * „heller werden" die sichtbare Reaktion, „noch schwärzer" wäre keine.
     */
    --accent-700: #000000;
    --accent-600: #16181d;
    --accent-500: #23262d;
    --accent-400: #363b45;
    --accent-100: #e7e9ec;

    --ink-900: #10171c;
    --ink-800: #1d2830;
    --ink-700: #33434e;
    --ink-600: #4d6070;
    --ink-500: #6b7f8e;
    --ink-400: #93a5b1;
    --ink-300: #c2ced6;
    --ink-200: #dee6eb;
    --ink-100: #eef2f5;
    --ink-50: #f7f9fb;
    --white: #ffffff;

    --ok-700: #1c6b45;
    --ok-500: #22935d;
    --ok-100: #dcf4e8;
    --warn-700: #8a5a06;
    --warn-500: #d08b12;
    --warn-100: #fdf0d5;
    --bad-700: #9a2b30;
    --bad-500: #c9343b;
    --bad-100: #fbe3e4;
    --info-700: #23527c;
    --info-100: #dceaf7;

    /*
     * Diagrammfarben. Sie stehen **neben** der Markenreihe und nicht darin,
     * weil sie eine andere Prüfung bestehen müssen: Zwei Linien in einem
     * Diagramm müssen auch für Menschen mit einer Farbsehschwäche zwei Linien
     * bleiben. `--brand-600` und ein Grau daneben sahen für sie gleich aus
     * (ΔE 2,1 bei Deuteranopie) – als Knopffarbe ist das gleichgültig, als
     * Serienfarbe ist es der Unterschied zwischen einem Diagramm und einem
     * Knäuel.
     *
     * `--chart-1` ist deshalb ein etwas sattereres Petrol als `--brand-600`:
     * nah genug an der Marke, um dazuzugehören, und farbig genug, um nicht als
     * Grau gelesen zu werden. `--chart-2` ist sein Gegenpol – warm gegen kühl
     * trägt auch dann noch, wenn die Farbe selbst nicht ankommt.
     *
     * Wer eine dritte Serie braucht, würfelt keine Farbe dazu, sondern prüft
     * sie: Ein geratener Ton liegt fast sicher zu nah an einem der beiden.
     */
    --chart-1: #00789b;
    --chart-2: #b4573a;

    /*
     * Die Rampe für Größenvergleiche – Heatmap und Trichter. Eine Hue, von
     * hell nach dunkel, und **das helle Ende ist mit Absicht kein Hauch**:
     * Unter 2:1 gegen Weiß ist eine belegte Zelle von einer leeren nicht mehr
     * zu unterscheiden, und genau das soll eine Heatmap ja zeigen.
     */
    --scale-1: #74bfd0;
    --scale-2: #43a2b9;
    --scale-3: #1c85a0;
    --scale-4: #0c637e;
    --scale-5: #094355;
    /* Kein Wert – und deshalb keine Stufe der Rampe, sondern Grundfläche. */
    --scale-0: #f2f6f8;

    --radius-sm: 6px;
    --radius: 10px;
    --radius-lg: 16px;
    --radius-xl: 24px;

    --shadow-xs: 0 1px 2px rgba(16, 23, 28, .06);
    --shadow-sm: 0 1px 3px rgba(16, 23, 28, .08), 0 1px 2px rgba(16, 23, 28, .04);
    --shadow: 0 4px 16px rgba(16, 23, 28, .08), 0 1px 3px rgba(16, 23, 28, .05);
    --shadow-lg: 0 16px 40px rgba(16, 23, 28, .12), 0 4px 12px rgba(16, 23, 28, .06);

    --font-sans: "Inter", "Inter Fallback", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
        "Helvetica Neue", Arial, sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 24px;
    --space-6: 32px;
    --space-7: 48px;
    --space-8: 64px;

    --container: 1200px;
    --transition: 160ms cubic-bezier(.4, 0, .2, 1);
}

/* ----------------------------------------------------------------- Reset */

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
}

body {
    margin: 0;
    font-family: var(--font-sans);
    font-size: 16px;
    line-height: 1.6;
    color: var(--ink-800);
    background: var(--ink-50);
    -webkit-font-smoothing: antialiased;
}

/*
 * Deutsche Komposita sind lang: „Geschäftsbedingungen" allein misst auf einem
 * schmalen Telefon mehr als die Spalte breit ist, und eine Überschrift bricht
 * von sich aus nur an Leerzeichen. `hyphens: auto` trennt sie sauber – die
 * Sprache dafür steht im `lang="de"` des Dokuments. `overflow-wrap` ist die
 * Rückfallebene für Browser ohne deutsche Trennmuster: lieber hart umbrochen
 * als seitlich aus dem Bild geschoben.
 *
 * `anywhere` statt `break-word`, weil nur `anywhere` in die Mindestbreite des
 * Elements eingeht. Steht die Überschrift in einer Flexzeile – wie auf der
 * AGB-Seite neben der Fassungsnummer –, schrumpft sie mit `break-word` nie
 * unter die Breite ihres längsten Wortes und schöbe die Seite trotz erlaubtem
 * Umbruch auf. Für den Zeilenumbruch selbst verhalten sich beide gleich.
 */
h1, h2, h3, h4, h5, h6 {
    margin: 0 0 var(--space-3);
    line-height: 1.25;
    color: var(--ink-900);
    font-weight: 650;
    letter-spacing: -.011em;
    overflow-wrap: anywhere;
    hyphens: auto;
}

h1 { font-size: clamp(1.75rem, 1.3rem + 1.6vw, 2.5rem); }
h2 { font-size: clamp(1.35rem, 1.15rem + .7vw, 1.75rem); }
h3 { font-size: 1.2rem; }
h4 { font-size: 1.05rem; }

p { margin: 0 0 var(--space-4); }
p:last-child { margin-bottom: 0; }

a {
    color: var(--brand-600);
    text-decoration: none;
    transition: color var(--transition);
}

a:hover { color: var(--brand-800); text-decoration: underline; }

img { max-width: 100%; height: auto; display: block; }

hr {
    border: 0;
    border-top: 1px solid var(--ink-200);
    margin: var(--space-5) 0;
}

small { font-size: .8125rem; }

ul, ol { margin: 0 0 var(--space-4); padding-left: 1.25rem; }

code, kbd, pre { font-family: var(--font-mono); font-size: .875em; }

:focus-visible {
    outline: 3px solid var(--brand-500);
    outline-offset: 2px;
    border-radius: 3px;
}

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

/*
 * Die Animationen selbst kommen aus **animate.css** (`webroot/css/animate.min.css`,
 * MIT, Fassung 4.1.1) – eingebunden im Layout, ausgeliefert vom eigenen Server.
 * Was hier steht, sind die drei Dinge, die eine Bibliothek nicht mitbringen kann:
 * die Rücksicht auf abgestellte Bewegung, der Ausgangszustand des Einblendens und
 * die Dauer, mit der die Klassen hier laufen sollen.
 *
 * Eingesetzt wird sie auf zwei Wegen, und der Unterschied ist wichtig:
 *
 * 1. **Fest im Markup** (`class="animate__animated animate__fadeInDown"`) für
 *    alles, was beim Laden ohnehin auf dem Schirm steht – Flash-Meldungen, der
 *    Auftragszähler. Das läuft ohne JavaScript.
 * 2. **Über `data-animate`** für alles Weitere: `initReveal()` in `app.js` hängt
 *    die Klassen erst an, wenn das Element in den Blick scrollt. Ohne JavaScript
 *    passiert nichts – und genau deshalb steht der Ausgangszustand `opacity: 0`
 *    in einer Klasse, die **nur das Skript** vergibt (`.reveal-pending`). Stünde
 *    er fest im Stylesheet, wäre eine Seite ohne JavaScript leer.
 */

/*
 * Eine Sekunde ist für ein Einblenden zu lang – die Vorgabe von animate.css
 * meint größere Auftritte. Gesetzt wird die Variable der Bibliothek, damit
 * jede ihrer Klassen sie mitbekommt, statt Regel für Regel nachgezogen zu werden.
 */
:root {
    --animate-duration: .55s;
}

/*
 * Der Ausgangszustand des Einblendens. Vergeben wird die Klasse ausschließlich
 * von `initReveal()`, und zwar nur, wenn auch animiert werden wird: kein
 * JavaScript, kein `IntersectionObserver` oder abgestellte Bewegung heißt, dass
 * sie nie vergeben wird und der Inhalt schlicht dasteht.
 */
.reveal-pending {
    opacity: 0;
}

/*
 * Auf Papier gibt es kein Hereinscrollen. Was beim Drucken noch nicht in den
 * Blick gekommen war, trüge sonst weiter `opacity: 0` und käme als leere Fläche
 * aus dem Drucker – ausgerechnet im Kundenportal, wo ein Auftrag ausgedruckt
 * wird. animate.css nimmt seine eigenen Klassen im Druck ebenso zurück.
 */
@media print {
    .reveal-pending { opacity: 1 !important; }
}

/*
 * Wer Bewegung abgestellt hat, meint es ernst: Für manche Menschen löst sie
 * Übelkeit oder Schwindel aus. Abgeschaltet wird deshalb alles auf einmal und
 * nicht Regel für Regel – eine vergessene Animation macht die Rücksicht zunichte.
 *
 * animate.css bringt denselben Block für seine eigenen Klassen mit. Dieser hier
 * bleibt trotzdem stehen und steht bewusst *danach*: Er gilt für jede Animation
 * und jeden Übergang im Haus, auch für die, die nie eine `animate__`-Klasse
 * gesehen haben. `initReveal()` fragt zusätzlich selbst – eine Animation, die
 * auf 0,01 ms gestaucht wird, ist abgeschaltet, aber der Weg über `opacity: 0`
 * soll gar nicht erst beschritten werden.
 */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: .01ms !important;
        animation-delay: 0s !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }

    .btn:hover,
    .item-card:hover { transform: none; }
}

/*
 * Eine eigene Animation im Stil von animate.css: der Stempel, der einmal auf
 * das Papier fällt (das Siegel eines unterschriebenen Vertrags). Als
 * `animate__`-Klasse, damit `data-animate="stampIn"` und `playAnimation()`
 * sie genauso abspielen und aufräumen wie jede andere.
 */
.animate__stampIn { animation-name: stamp-in; }

@keyframes stamp-in {
    0% { opacity: 0; transform: scale(1.8) rotate(-12deg); }
    60% { opacity: 1; transform: scale(.94) rotate(-4deg); }
    80% { transform: scale(1.03) rotate(-4deg); }
    100% { opacity: 1; transform: scale(1) rotate(-4deg); }
}

/*
 * Laden, ohne zu springen.
 *
 * Solange eine Antwort unterwegs ist – Verfügbarkeit, Preis, Kalender –,
 * schimmert die Fläche, auf der sie gleich steht, und ihr bisheriger Inhalt
 * tritt etwas zurück. Vergeben wird `.is-loading` vom Skript, und zwar erst
 * nach einem Augenblick (`showLoading()` in `app.js`): Eine Antwort, die
 * schneller da ist, soll nicht erst flackern.
 *
 * Mit abgestellter Bewegung bleibt vom Schimmern ein stiller Schleier – die
 * Auskunft „lädt gerade" bleibt, nur ohne Bewegung.
 */
.is-loading { position: relative; }

.is-loading > * { opacity: .5; transition: opacity .15s ease; }

.is-loading::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    background: linear-gradient(100deg,
        transparent 20%, rgba(255, 255, 255, .6) 50%, transparent 80%);
    background-size: 200% 100%;
    animation: shimmer 1.1s linear infinite;
}

@keyframes shimmer {
    from { background-position: 150% 0; }
    to { background-position: -50% 0; }
}

/*
 * Der Platzhalter für eine Antwort, die es noch gar nicht gab: zwei graue
 * Zeilen in der Form der späteren Auskunft. Ohne ihn erschiene die erste
 * Verfügbarkeitsprüfung aus dem Nichts und schöbe alles darunter nach unten.
 */
.skeleton {
    display: block;
    height: .75rem;
    border-radius: 999px;
    background: var(--ink-200);
}

.skeleton + .skeleton { margin-top: 8px; }
.skeleton-short { width: 60%; }
.skeleton-lines { flex: 1; padding-top: 3px; }

.visually-hidden {
    position: absolute !important;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}

/* ------------------------------------------------------------- Utilities */

.container {
    width: 100%;
    max-width: var(--container);
    margin-inline: auto;
    padding-inline: var(--space-5);
}

/* Für Fließtextseiten – lange Zeilen lesen sich schlecht. */
.container-narrow { max-width: 820px; }

.stack > * + * { margin-top: var(--space-4); }
.stack-sm > * + * { margin-top: var(--space-2); }
.stack-lg > * + * { margin-top: var(--space-6); }

.row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    align-items: center;
}

.row-between { justify-content: space-between; }
.row-end { justify-content: flex-end; }
.row-top { align-items: flex-start; }

.grow { flex: 1 1 auto; min-width: 0; }
.muted { color: var(--ink-500); }
.strong { font-weight: 600; }
.nowrap { white-space: nowrap; }
.text-right { text-align: right; }
.text-center { text-align: center; }
.mono { font-family: var(--font-mono); font-size: .9em; }
.mt-0 { margin-top: 0; }
.mb-0 { margin-bottom: 0; }
.mt-4 { margin-top: var(--space-4); }
.mt-5 { margin-top: var(--space-5); }
.mt-6 { margin-top: var(--space-6); }

.lead {
    font-size: 1.0625rem;
    color: var(--ink-600);
    line-height: 1.65;
}

/* --------------------------------------------------------------- Buttons */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: 10px 18px;
    border: 1px solid transparent;
    border-radius: var(--radius);
    font: inherit;
    font-weight: 560;
    font-size: .9375rem;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition),
        color var(--transition), box-shadow var(--transition), transform var(--transition);
    white-space: nowrap;
}

/*
 * Der Knopf hebt sich beim Überfahren leicht an und legt einen Schatten
 * darunter – die Bewegung, die das Zeigegerät bestätigt, bevor geklickt wird.
 * Ein Pixel genügt dafür; alles darüber wirkt wie ein Sprung und lenkt vom
 * Text ab. Beim Drücken geht es zurück nach unten, damit der Klick sich wie
 * ein Druck anfühlt.
 */
.btn:hover { text-decoration: none; transform: translateY(-1px); box-shadow: var(--shadow-sm); }
.btn:active { transform: translateY(0); box-shadow: var(--shadow-xs); }

/* Geisterknöpfe liegen flach in der Fläche – ein Schatten ließe sie schweben. */
.btn-ghost:hover { transform: none; box-shadow: none; }

.btn:disabled,
.btn[aria-disabled="true"] {
    opacity: .55;
    cursor: not-allowed;
    transform: none;
}

.btn-primary {
    background: var(--brand-700);
    color: var(--white);
    box-shadow: var(--shadow-xs);
}
.btn-primary:hover { background: var(--brand-800); color: var(--white); }

.btn-accent {
    background-color: var(--accent-600);
    color: var(--white);
    box-shadow: var(--shadow-xs);
}
/* Heller statt dunkler – siehe `--accent-400`. */
.btn-accent:hover { background-color: var(--accent-400); color: var(--white); }

/*
 * Ein Lichtstreif zieht beim Überfahren über die Handlungsknöpfe – „Suchen",
 * „Anfragen", „Bezahlen". Ein Hintergrundbild über der Farbe und kein
 * Pseudo-Element: Das bräuchte `overflow: hidden` am Knopf, und das schnitte
 * den Zähler ab, der an manchem Knopf über den Rand ragt.
 *
 * Deshalb steht oben `background-color` statt `background`: Die Kurzform
 * löschte beim Überfahren genau dieses Bild. Mit abgestellter Bewegung bleibt
 * der Streif liegen, wo er ist – außerhalb des Knopfes.
 */
@media (prefers-reduced-motion: no-preference) {
    .btn-accent {
        background-image: linear-gradient(105deg,
            transparent 38%, rgba(255, 255, 255, .26) 50%, transparent 62%);
        background-size: 250% 100%;
        background-position: 130% 0;
        background-repeat: no-repeat;
    }

    .btn-accent:hover {
        background-position: -30% 0;
        transition: background-position .7s cubic-bezier(.3, .7, .3, 1), background-color var(--transition),
            box-shadow var(--transition), transform var(--transition);
    }
}

.btn-secondary {
    background: var(--white);
    border-color: var(--ink-300);
    color: var(--ink-800);
}
.btn-secondary:hover { border-color: var(--ink-400); background: var(--ink-50); color: var(--ink-900); }

.btn-ghost {
    background: transparent;
    color: var(--ink-600);
}
.btn-ghost:hover { background: var(--ink-100); color: var(--ink-900); }

.btn-danger {
    background: var(--white);
    border-color: var(--bad-500);
    color: var(--bad-700);
}
.btn-danger:hover { background: var(--bad-500); color: var(--white); }

.btn-sm { padding: 6px 12px; font-size: .8125rem; border-radius: var(--radius-sm); }
.btn-lg { padding: 14px 26px; font-size: 1rem; }
.btn-block { width: 100%; }
.btn-icon { padding: 8px; }

/*
 * 44 px sind eine Fingerkuppe, keine Bildschirmbreite – deshalb hängt die
 * Vergrößerung an `pointer: coarse` und nicht an einer Medienbreite. Ein
 * schmales Fenster am Rechner bleibt damit unverändert, ein Tablet in voller
 * Breite bekommt die größeren Ziele trotzdem. Betroffen sind nur die kleinen
 * Varianten; `.btn` selbst ist mit 41 px nah genug dran.
 */
@media (pointer: coarse) {
    .btn { padding: 12px 18px; }
    .btn-sm { padding: 12px 14px; }
    .btn-icon,
    .btn-sm.btn-icon { padding: 14px; }
}

.btn svg { width: 1.05em; height: 1.05em; flex: none; }

/* ------------------------------------------------------------- Formulare */

.field { margin-bottom: var(--space-4); }
.field:last-child { margin-bottom: 0; }

.field > label,
.label {
    display: block;
    margin-bottom: 6px;
    font-size: .875rem;
    font-weight: 560;
    color: var(--ink-700);
}

.field .help {
    display: block;
    margin-top: 5px;
    font-size: .8125rem;
    color: var(--ink-500);
}

/*
 * Ein Hinweis direkt am Feld – kein Fehler, sondern ein „bist du sicher?".
 * Er steht deshalb in Warnfarbe und nicht in Rot: Was er beschreibt, ist im
 * Regelfall ein Versehen, im Einzelfall aber richtig.
 */
.field-warning {
    margin: 6px 0 0;
    padding: 8px 10px;
    border-left: 3px solid var(--warn-500);
    background: var(--warn-100);
    border-radius: var(--radius-sm);
    font-size: .8125rem;
    color: var(--ink-700);
}

.check-row {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    margin-top: 8px;
    font-size: .8125rem;
    color: var(--ink-700);
    cursor: pointer;
}

.check-row input { margin-top: 2px; flex: none; }

/*
 * `hidden` heißt versteckt – auch wenn eine Regel weiter unten ein `display`
 * setzt.
 *
 * Das `[hidden] { display: none }` aus dem Browser-Stylesheet hat dieselbe
 * Spezifität wie eine Klassenregel und verliert deshalb gegen jedes spätere
 * `.irgendwas { display: flex }`. Das Element bleibt dann sichtbar, obwohl das
 * Attribut gesetzt ist – ein Fehler, den man im Code nicht sieht, weil dort
 * alles richtig aussieht. Hier ist `!important` genau am Platz: Es gibt keinen
 * Fall, in dem etwas Verstecktes doch angezeigt werden soll.
 */
[hidden] { display: none !important; }

input[type="text"],
input[type="email"],
input[type="password"],
input[type="tel"],
input[type="url"],
input[type="number"],
input[type="date"],
input[type="time"],
input[type="search"],
select,
textarea {
    width: 100%;
    padding: 10px 12px;
    border: 1px solid var(--ink-300);
    border-radius: var(--radius);
    background: var(--white);
    font: inherit;
    font-size: .9375rem;
    color: var(--ink-900);
    transition: border-color var(--transition), box-shadow var(--transition);
}

textarea { min-height: 110px; resize: vertical; line-height: 1.55; }

/*
 * Auf Touchgeräten 16 Pixel, und das ist keine Geschmacksfrage.
 *
 * Safari auf iOS zoomt beim Antippen **jedes** Feldes unter 16 Pixel in die
 * Seite hinein – und wieder heraus zoomt es nicht. Die 15 Pixel oben trafen
 * damit genau die Stellen, an denen es zählt: den Mietzeitraum auf der
 * Artikelseite, das Auftragsformular, jede Anmeldung. Der Kunde tippt ein
 * Datum ein und steht danach in einer um ein Drittel vergrößerten Seite.
 *
 * `pointer: coarse` und keine Breite: Der Zoom hängt am Eingabegerät, nicht
 * am Fenster – ein iPad quer ist breiter als mancher Laptop und zoomt
 * trotzdem. Wo mit der Maus getippt wird, bleibt es bei 15 Pixeln.
 */
@media (pointer: coarse) {
    input[type="text"], input[type="email"], input[type="password"],
    input[type="search"], input[type="tel"], input[type="url"],
    input[type="number"], input[type="date"], input[type="time"],
    input[type="datetime-local"], select, textarea {
        font-size: 1rem;
    }
}

select {
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%236b7f8e'%3E%3Cpath d='M4.2 6.2 8 10l3.8-3.8-1.1-1.1L8 7.8 5.3 5.1z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 16px;
    padding-right: 34px;
}

/*
 * Datums- und Zeitfelder bekommen dasselbe Kalender-/Uhrsymbol wie das
 * Auswahlfeld seinen Pfeil: Der Browser malt sonst ein graues Standardsymbol,
 * das neben den übrigen Feldern wie ein Fremdkörper wirkt. Das Symbol ist reine
 * Zier – bedient wird das Feld weiterhin vom Browser.
 */
input[type="date"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator {
    opacity: .55;
    cursor: pointer;
    padding: 2px;
    border-radius: var(--radius-sm);
    transition: opacity var(--transition), background var(--transition);
}

input[type="date"]:hover::-webkit-calendar-picker-indicator,
input[type="time"]:hover::-webkit-calendar-picker-indicator { opacity: 1; }

input[type="date"]::-webkit-calendar-picker-indicator:hover,
input[type="time"]::-webkit-calendar-picker-indicator:hover { background: var(--ink-100); }

/*
 * Die Ziffernblöcke der Zeiteingabe sollen beim Anspringen aussehen wie eine
 * Textmarkierung und nicht wie ein blauer Systemkasten.
 */
input[type="time"]::-webkit-datetime-edit-hour-field:focus,
input[type="time"]::-webkit-datetime-edit-minute-field:focus,
input[type="time"]::-webkit-datetime-edit-ampm-field:focus,
input[type="date"]::-webkit-datetime-edit-day-field:focus,
input[type="date"]::-webkit-datetime-edit-month-field:focus,
input[type="date"]::-webkit-datetime-edit-year-field:focus {
    background: var(--brand-100);
    color: var(--brand-800);
    border-radius: 3px;
    outline: none;
}

input:hover, select:hover, textarea:hover { border-color: var(--ink-400); }

input:focus, select:focus, textarea:focus {
    outline: none;
    border-color: var(--brand-500);
    box-shadow: 0 0 0 3px rgba(34, 135, 157, .16);
}

input[readonly], input:disabled, select:disabled, textarea:disabled {
    background: var(--ink-100);
    color: var(--ink-500);
    cursor: not-allowed;
}

.checkbox,
.radio {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    font-size: .9375rem;
    color: var(--ink-700);
    cursor: pointer;
    margin-bottom: var(--space-2);
}

.checkbox input,
.radio input {
    width: 18px;
    height: 18px;
    margin: 2px 0 0;
    flex: none;
    accent-color: var(--brand-600);
    cursor: pointer;
}

.checkbox label,
.radio label { cursor: pointer; margin: 0; font-weight: 400; }

/*
 * Sicherheitsabfrage (hCaptcha).
 *
 * Das Widget bringt seine eigene Größe mit (302 × 76 px) und lässt sich nicht
 * umstylen. Auf schmalen Bildschirmen darf es deshalb nicht die Seite breiter
 * machen als sie ist – lieber scrollt der Kasten selbst.
 */
.captcha-field { margin-top: var(--space-4); overflow-x: auto; }
.captcha-field .h-captcha { min-height: 78px; }

/*
 * Das unsichtbare Captcha (reCAPTCHA v3) hat keinen Inhalt außer einem
 * versteckten Feld – ohne diese Regel stünde trotzdem der Abstand eines
 * Formularfeldes im Formular, und niemand wüsste, wovon.
 */
.captcha-field.is-invisible { margin: 0; }
.captcha-field.is-invisible noscript { display: block; margin-top: var(--space-4); }

/* Umschalter für die Anzeigeoptionen im Admin */
.switch-row {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-3) 0;
    border-bottom: 1px solid var(--ink-100);
}
.switch-row:last-child { border-bottom: 0; }
.switch-row input { margin-top: 3px; width: 18px; height: 18px; accent-color: var(--brand-600); flex: none; }
.switch-row .switch-text { flex: 1; }
.switch-row .switch-text strong { display: block; font-size: .9375rem; color: var(--ink-800); font-weight: 560; }
.switch-row .switch-text span { display: block; font-size: .8125rem; color: var(--ink-500); line-height: 1.5; }

.field-grid {
    display: grid;
    gap: var(--space-4);
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.field-grid .span-2 { grid-column: span 2; }
@media (max-width: 640px) {
    .field-grid .span-2 { grid-column: span 1; }
}

/* Fehlerdarstellung von CakePHPs FormHelper */
.input.error input,
.input.error select,
.input.error textarea,
input.form-error, select.form-error, textarea.form-error {
    border-color: var(--bad-500);
    background: #fffafa;
}

.error-message {
    display: block;
    margin-top: 5px;
    font-size: .8125rem;
    font-weight: 500;
    color: var(--bad-700);
}

fieldset {
    border: 0;
    padding: 0;
    margin: 0 0 var(--space-5);
}

legend {
    padding: 0;
    margin-bottom: var(--space-3);
    font-size: .8125rem;
    font-weight: 650;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--ink-500);
}

/* ---------------------------------------------------------------- Karten */

.card {
    background: var(--white);
    border: 1px solid var(--ink-200);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}

/*
 * `flex-wrap: wrap`, weil rechts in der Kopfzeile fast immer ein Knopf steht.
 * Eine lange Überschrift wie „Allgemeine Geschäftsbedingungen" lässt sich nicht
 * beliebig schmal machen – ohne Umbruch schöbe sie den Knopf auf dem Telefon
 * aus dem Bild. Passt beides in eine Zeile, ändert sich nichts.
 */
.card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
    border-bottom: 1px solid var(--ink-200);
}

.card-header h2,
.card-header h3 { margin: 0; font-size: 1.0625rem; }

.card-body { padding: var(--space-5); }

/*
 * Eine Karte, die sich zuklappen lässt.
 *
 * Das ist ein `<details>` mit der Kartenkopfzeile als `<summary>`; das
 * Aufklappen, die Tastaturbedienung und die Screenreader-Semantik bringt der
 * Browser mit. Der eigene Marker ersetzt das voreingestellte Dreieck: Es steht
 * je nach Browser woanders und schöbe in einer Kopfzeile mit `space-between`
 * die Beschriftung aus der Flucht.
 *
 * `list-style: none` **und** `::-webkit-details-marker`: Safari hört bis heute
 * nur auf das zweite. Wer eines von beiden wegkürzt, hat auf der Hälfte der
 * Geräte zwei Pfeile nebeneinander.
 */
.card-collapsible > summary {
    cursor: pointer;
    list-style: none;
    user-select: none;
}

.card-collapsible > summary::-webkit-details-marker { display: none; }

.card-collapsible > summary::after {
    content: "";
    width: 9px;
    height: 9px;
    margin-left: auto;
    border-right: 2px solid var(--ink-400);
    border-bottom: 2px solid var(--ink-400);
    transform: rotate(45deg) translate(-2px, -2px);
    transition: transform var(--transition);
}

.card-collapsible[open] > summary::after { transform: rotate(-135deg) translate(-2px, -2px); }

.card-collapsible > summary:hover::after { border-color: var(--ink-600); }

/* Zugeklappt trägt die Kopfzeile keine Trennlinie – darunter kommt nichts. */
.card-collapsible:not([open]) > summary { border-bottom: 0; }
.card-body.tight { padding: var(--space-4); }
.card-footer {
    padding: var(--space-4) var(--space-5);
    border-top: 1px solid var(--ink-200);
    background: var(--ink-50);
    border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}

/* ---------------------------------------------------------------- Badges */

.badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: .75rem;
    font-weight: 600;
    line-height: 1.5;
    letter-spacing: .01em;
    white-space: nowrap;
    background: var(--ink-100);
    color: var(--ink-700);
}

.badge::before {
    content: "";
    width: 6px; height: 6px;
    border-radius: 50%;
    background: currentColor;
    flex: none;
}

.badge-plain::before { display: none; }

.badge-ok { background: var(--ok-100); color: var(--ok-700); }
.badge-warn { background: var(--warn-100); color: var(--warn-700); }
.badge-bad { background: var(--bad-100); color: var(--bad-700); }
.badge-info { background: var(--info-100); color: var(--info-700); }
.badge-brand { background: var(--brand-100); color: var(--brand-700); }
.badge-accent { background: var(--accent-100); color: var(--accent-700); }
.badge-neutral { background: var(--ink-100); color: var(--ink-600); }

/* -------------------------------------------------------------- Meldungen */

.message {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-4);
    border-radius: var(--radius);
    border: 1px solid transparent;
    font-size: .9375rem;
    margin-bottom: var(--space-4);
}

.message p { margin: 0; }
.message > svg { width: 20px; height: 20px; flex: none; margin-top: 1px; }

/* Icon im Fließtext – etwas kleiner als die Schrift, auf der Grundlinie. */
.icon-xs { width: 14px; height: 14px; vertical-align: -2px; }
.icon-sm { width: 16px; height: 16px; flex: none; }
.message.success { background: var(--ok-100); border-color: #b6e3cc; color: var(--ok-700); }
.message.error { background: var(--bad-100); border-color: #f2c4c6; color: var(--bad-700); }
.message.warning { background: var(--warn-100); border-color: #f0d9a8; color: var(--warn-700); }
.message.info { background: var(--info-100); border-color: #bcd6ec; color: var(--info-700); }

.flash-stack { position: relative; }

/*
 * Mit Skript werden die Meldungen zu Toasts oben rechts (`initToasts()`).
 * Ohne stehen sie, wo sie immer standen – die Klasse `is-toasts` vergibt
 * erst das Skript, dieselbe Richtung wie beim Einblenden.
 *
 * Sie liegen über der Kopfzeile: Wer gerade etwas abgeschickt hat, schaut
 * nach oben, und unten säße auf dem Handy der Preisbalken.
 */
.flash-stack.is-toasts {
    position: fixed;
    top: var(--space-4);
    right: var(--space-4);
    left: auto;
    z-index: 1100;
    width: min(420px, calc(100vw - 2 * var(--space-4)));
    max-width: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    pointer-events: none;
}

.flash-stack.is-toasts > .message {
    position: relative;
    margin: 0;
    padding-right: 44px;
    overflow: hidden;
    pointer-events: auto;
    box-shadow: var(--shadow-lg);
}

.toast-close {
    position: absolute;
    top: 8px;
    right: 8px;
    display: grid;
    place-items: center;
    width: 28px;
    height: 28px;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: inherit;
    font-size: 1.25rem;
    line-height: 1;
    cursor: pointer;
    opacity: .7;
}

.toast-close:hover,
.toast-close:focus-visible { opacity: 1; background: rgba(0, 0, 0, .06); }

/* Wie lange die Meldung noch steht – eine Leiste, die abläuft. */
.flash-stack.is-toasts > .message.is-timed::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 3px;
    background: currentColor;
    opacity: .3;
    transform-origin: left center;
    animation: toast-timer var(--toast-time, 6s) linear forwards;
}

.flash-stack.is-toasts > .message.is-paused::after { animation-play-state: paused; }

.flash-stack.is-toasts > .message.is-leaving { animation: toast-out .28s ease-in forwards; }

@keyframes toast-timer { to { transform: scaleX(0); } }

@keyframes toast-out {
    to { opacity: 0; transform: translateX(24px); }
}

/* -------------------------------------------------------------- Tabellen */

.table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

table.data {
    width: 100%;
    border-collapse: collapse;
    font-size: .9375rem;
}

table.data th,
table.data td {
    padding: var(--space-3) var(--space-4);
    text-align: left;
    border-bottom: 1px solid var(--ink-200);
    vertical-align: middle;
}

table.data thead th {
    font-size: .75rem;
    font-weight: 650;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--ink-500);
    background: var(--ink-50);
    border-bottom: 1px solid var(--ink-200);
    white-space: nowrap;
}

/*
 * Sortierbare Spaltenköpfe.
 *
 * Der Pfeil steht nur an der Spalte, nach der gerade sortiert wird – einer an
 * jeder Spalte wäre Rauschen, und welche gerade gilt, sähe man nicht mehr.
 * Dass sich die anderen überhaupt anklicken lassen, zeigt der Zeigefinger und
 * die Farbe beim Überfahren; ein dauerhaftes Doppelpfeilchen daneben hat noch
 * niemandem geholfen.
 *
 * `.asc`/`.desc` vergibt der PaginatorHelper an genau diesen einen Link.
 */
table.data thead th a {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: inherit;
}

table.data thead th a:hover { color: var(--brand-700); text-decoration: none; }
table.data thead th a.asc, table.data thead th a.desc { color: var(--brand-700); }

/*
 * Die Pfeile stehen als Pseudo-Element und damit außerhalb des Textflusses:
 * Ein Zeichen im Linktext würde von Screenreadern mitgelesen („Eingang
 * Dreieck") und beim Kopieren mitgenommen.
 */
table.data thead th a.asc::after { content: "\2191"; font-size: .875em; }
table.data thead th a.desc::after { content: "\2193"; font-size: .875em; }

table.data tbody tr { transition: background var(--transition); }
table.data tbody tr:hover { background: var(--brand-50); }
table.data tbody tr:last-child td { border-bottom: 0; }

table.data td.actions { text-align: right; white-space: nowrap; }
table.data td.num, table.data th.num { text-align: right; font-variant-numeric: tabular-nums; }

/*
 * Aus jeder Zeile eine Karte, sobald die Tabelle nicht mehr nebeneinander
 * passt.
 *
 * Bis dahin scrollte sie waagerecht, und von einem Auftrag mit zehn Spalten
 * waren zwei zu sehen. Die Klasse `is-stacked` und die Beschriftungen an den
 * Zellen vergibt `initStackableTables()` aus dem Tabellenkopf; ohne
 * JavaScript greift hier nichts und es bleibt beim Scrollen – dieselbe
 * Rückfallebene wie überall.
 *
 * Die Sortierzeile hat keinen eigenen Zustand: Oberhalb der Grenze sortiert
 * der Tabellenkopf, unterhalb die Zeile, und immer ist genau eine von beiden
 * zu sehen.
 */
.table-sort { display: none; }

@media (max-width: 760px) {
    .table-sort {
        display: flex;
        align-items: center;
        gap: var(--space-2);
        flex-wrap: wrap;
        padding: 0 0 var(--space-3);
        font-size: .8125rem;
    }

    .table-sort > span {
        font-size: .6875rem;
        font-weight: 650;
        text-transform: uppercase;
        letter-spacing: .06em;
        color: var(--ink-500);
    }

    .table-sort a {
        padding: 5px 10px;
        border: 1px solid var(--ink-200);
        border-radius: 999px;
        color: var(--ink-700);
        background: var(--white);
        white-space: nowrap;
    }

    .table-sort a:hover { text-decoration: none; border-color: var(--brand-500); }
    .table-sort a.asc, .table-sort a.desc { border-color: var(--brand-500); color: var(--brand-700); }
    .table-sort a.asc::after { content: " \2191"; }
    .table-sort a.desc::after { content: " \2193"; }

    /* Nichts mehr zu scrollen – der Rahmen darf den Karten nichts abschneiden. */
    .table-wrap:has(table.data.is-stacked) { overflow-x: visible; }

    table.data.is-stacked thead { display: none; }

    table.data.is-stacked,
    table.data.is-stacked tbody,
    table.data.is-stacked tfoot,
    table.data.is-stacked tr,
    table.data.is-stacked td {
        display: block;
        width: 100%;
    }

    table.data.is-stacked tbody tr {
        border: 1px solid var(--ink-200);
        border-radius: var(--radius);
        margin-bottom: var(--space-3);
        padding: var(--space-2) var(--space-3);
        background: var(--white);
    }

    /* Auf dem Handy gibt es keinen Mauszeiger – eine Hover-Farbe bliebe kleben. */
    table.data.is-stacked tbody tr:hover { background: var(--white); }
    table.data.is-stacked tbody tr:last-child { margin-bottom: 0; }

    /*
     * Beschriftung links in fester Breite, Wert rechts – und beide oben
     * ausgerichtet. Nebeneinander in einer Zeile bräche der Wert um die
     * Beschriftung herum, sobald er zwei Zeilen braucht, und das ist in diesen
     * Listen der Normalfall (Name über Nummer, Kunde über E-Mail).
     */
    table.data.is-stacked tbody td {
        display: grid;
        grid-template-columns: 7.5rem minmax(0, 1fr);
        gap: var(--space-3);
        align-items: start;
        padding: 5px 0;
        border-bottom: 0;
        /*
         * `.nowrap` hielt einen Mietzeitraum in einer Zeile, solange er eine
         * Tabellenspalte für sich hatte. In einer Karte bleiben davon zwei
         * Drittel der Breite, und aus „nicht umbrechen" wird „rechts
         * abschneiden" – vom Rückgabedatum war nichts mehr zu sehen.
         */
        white-space: normal;
    }

    table.data.is-stacked tbody td::before {
        content: attr(data-label);
        font-size: .6875rem;
        font-weight: 650;
        text-transform: uppercase;
        letter-spacing: .06em;
        color: var(--ink-500);
        line-height: 1.6;
    }

    /*
     * Rechtsbündig war eine Zahl nur, solange sie unter der nächsten stand.
     * In einer Karte steht sie allein und gehört an den Anfang ihrer Spalte.
     */
    table.data.is-stacked tbody td.num { text-align: left; }

    /* Ohne Beschriftung (Bild) über die volle Breite, ohne leere linke Spalte. */
    table.data.is-stacked tbody td:not([data-label]) { display: block; }

    table.data.is-stacked tbody td.actions {
        text-align: left;
        margin-top: var(--space-2);
        padding-top: var(--space-2);
        border-top: 1px solid var(--ink-100);
    }

    /* Die Summenzeilen tragen ihre Beschriftung im Text – Wort links, Betrag rechts. */
    table.data.is-stacked tfoot td {
        display: flex;
        justify-content: space-between;
        gap: var(--space-3);
        text-align: left;
        padding: 5px 0;
    }
}

.empty-state {
    padding: var(--space-7) var(--space-5);
    text-align: center;
    color: var(--ink-500);
}

.empty-state svg {
    width: 44px; height: 44px;
    margin-bottom: var(--space-3);
    color: var(--ink-300);
}

.empty-state h3 { color: var(--ink-700); }

/* ------------------------------------------------------------ Paginierung */

.paginator {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;
    padding: var(--space-4) 0 0;
}

.paginator ul {
    display: flex;
    gap: 4px;
    list-style: none;
    margin: 0;
    padding: 0;
}

.paginator li a,
.paginator li.active a,
.paginator li.disabled a {
    display: block;
    min-width: 34px;
    padding: 6px 10px;
    text-align: center;
    border: 1px solid var(--ink-200);
    border-radius: var(--radius-sm);
    background: var(--white);
    color: var(--ink-700);
    font-size: .875rem;
    text-decoration: none;
}

.paginator li a:hover { border-color: var(--brand-500); color: var(--brand-700); }
.paginator li.active a { background: var(--brand-700); border-color: var(--brand-700); color: var(--white); }
.paginator li.disabled a { opacity: .45; pointer-events: none; }

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

.calendar {
    --cal-gap: 4px;
}

.calendar-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
}

.calendar-months {
    display: grid;
    gap: var(--space-5);
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}

.calendar-month h4 {
    margin: 0 0 var(--space-3);
    font-size: .9375rem;
    font-weight: 650;
    color: var(--ink-800);
    text-align: center;
}

.calendar-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: var(--cal-gap);
}

.calendar-dow {
    font-size: .6875rem;
    font-weight: 650;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--ink-400);
    text-align: center;
    padding-bottom: 4px;
}

.calendar-day {
    position: relative;
    aspect-ratio: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-sm);
    font-size: .8125rem;
    font-weight: 550;
    font-variant-numeric: tabular-nums;
    border: 1px solid transparent;
    min-height: 34px;
}

.calendar-day .qty {
    font-size: .625rem;
    font-weight: 600;
    line-height: 1;
    opacity: .75;
    margin-top: 1px;
}

.calendar-day.is-blank { visibility: hidden; }

.calendar-day.is-free { background: var(--ok-100); color: var(--ok-700); }
.calendar-day.is-tight { background: var(--warn-100); color: var(--warn-700); }
.calendar-day.is-full { background: var(--bad-100); color: var(--bad-700); }
.calendar-day.is-past { background: var(--ink-100); color: var(--ink-400); }

.calendar-day.is-today { border-color: var(--brand-600); font-weight: 700; }

.calendar-day.in-range {
    outline: 2px solid var(--brand-600);
    outline-offset: -2px;
}

.calendar-legend {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4);
    margin-top: var(--space-5);
    padding-top: var(--space-4);
    border-top: 1px solid var(--ink-200);
    font-size: .8125rem;
    color: var(--ink-600);
}

.calendar-legend span {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.calendar-legend i {
    width: 14px; height: 14px;
    border-radius: 4px;
    display: inline-block;
}

.legend-free { background: var(--ok-100); border: 1px solid #b6e3cc; }
.legend-tight { background: var(--warn-100); border: 1px solid #f0d9a8; }
.legend-full { background: var(--bad-100); border: 1px solid #f2c4c6; }
.legend-past { background: var(--ink-100); border: 1px solid var(--ink-200); }

/*
 * Ruhetag, Feiertag, Betriebsferien: Die Farbe bleibt die der Verfügbarkeit –
 * frei ist frei –, darüber liegt eine Schraffur für „keine Übergabe".
 */
.calendar-day.is-closed,
.legend-closed {
    background-image: repeating-linear-gradient(135deg, transparent 0 5px, rgba(15, 23, 42, .09) 5px 7px);
}
.legend-closed { background-color: var(--ink-50, #f8fafc); border: 1px solid var(--ink-200); }

.calendar-loading { opacity: .45; pointer-events: none; transition: opacity var(--transition); }

/* ------------------------------------------------- Verfügbarkeitsergebnis */

.availability-result {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-4);
    border-radius: var(--radius);
    border: 1px solid transparent;
    font-size: .9375rem;
}

.availability-result .dot {
    width: 10px; height: 10px;
    border-radius: 50%;
    background: currentColor;
    margin-top: 7px;
    flex: none;
}

.availability-result strong { display: block; margin-bottom: 2px; }
.availability-result p { margin: 0; font-size: .875rem; opacity: .9; }

.availability-result.is-available { background: var(--ok-100); border-color: #b6e3cc; color: var(--ok-700); }
.availability-result.is-partial { background: var(--warn-100); border-color: #f0d9a8; color: var(--warn-700); }
.availability-result.is-unavailable { background: var(--bad-100); border-color: #f2c4c6; color: var(--bad-700); }
.availability-result.is-on_request { background: var(--info-100); border-color: #bcd6ec; color: var(--info-700); }

.availability-notices {
    margin: var(--space-2) 0 0;
    padding-left: 1.1rem;
    font-size: .8125rem;
}

/* --------------------------------------------------------- Staffelpreise */

/*
 * Vier Spalten passen auf einem Handy nicht mehr nebeneinander, ohne dass die
 * Beträge umbrechen. Statt eine Spalte zu verstecken – „Pro Miettag" ist die
 * einzige, die sich zwischen Stufen vergleichen lässt – scrollt die Tabelle
 * dort waagerecht, wie die Kategoriezeile in der Kopfzeile.
 */
.tier-table-wrap {
    overflow-x: auto;
    margin: 0 calc(var(--space-1) * -1);
    padding: 0 var(--space-1);
}

.tier-table {
    width: 100%;
    min-width: 280px;
    border-collapse: separate;
    border-spacing: 0;
    font-size: .9375rem;
}

/*
 * Die Überschriften dürfen umbrechen: „Preis gesamt" auf zwei Zeilen kostet
 * einmal Höhe, ein erzwungenes `nowrap` dagegen so viel Breite, dass die
 * Tabelle auf dem Handy schon in der Kopfzeile zu scrollen anfängt.
 */
.tier-table th {
    padding: 0 var(--space-3) var(--space-2);
    text-align: left;
    font-size: .6875rem;
    font-weight: 650;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--ink-500);
    border-bottom: 1px solid var(--ink-200);
}

.tier-table td {
    padding: var(--space-3);
    border-bottom: 1px solid var(--ink-100);
    vertical-align: middle;
}

.tier-table th:first-child, .tier-table td:first-child { padding-left: var(--space-2); }
.tier-table th:last-child, .tier-table td:last-child { padding-right: var(--space-2); }

.tier-table tr:last-child td { border-bottom: 0; }
.tier-table th.num, .tier-table td.num { text-align: right; font-variant-numeric: tabular-nums; }

/* Die Zeile hebt sich beim Überfahren ab – sie ist die Einheit, die gelesen
   wird, und über vier Spalten verliert man sonst leicht die Spur. */
.tier-table tbody tr:hover td { background: var(--ink-50); }

.tier-name {
    display: block;
    font-weight: 600;
    color: var(--ink-800);
}

/* Ab wann die Stufe gilt – unter ihrem Namen, nicht an seiner Stelle. */
.tier-condition {
    display: block;
    margin-top: 2px;
    font-size: .75rem;
    color: var(--ink-500);
}

/*
 * Die Preistreppe unter dem Stufennamen: je Stufe ein Balken, so lang wie ihr
 * Tagespreis im Verhältnis zum teuersten (`--share`, gerechnet in
 * `element/price_tiers`). Untereinander gelesen fallen die Balken ab – das
 * sieht man schneller, als man vier Beträge vergleicht.
 *
 * Die Balken wachsen nacheinander von links herein (`--step`). Weil die
 * Tabelle bei jeder Änderung von Zeitraum oder Menge neu kommt, wächst die
 * Treppe dann noch einmal – gewollt: Das Hervorheben der neuen Stufe soll
 * auffallen. Bei abgestellter Bewegung stehen sie sofort da (pauschaler Block
 * unter „Bewegung").
 */
.tier-bar {
    display: block;
    min-width: 72px;
    height: 6px;
    margin-top: var(--space-2);
    border-radius: 999px;
    background: var(--ink-100);
    overflow: hidden;
}

.tier-bar > span {
    display: block;
    width: var(--share, 100%);
    height: 100%;
    border-radius: inherit;
    background: linear-gradient(90deg, var(--brand-500), var(--brand-600));
    transform-origin: left center;
    animation: tier-grow .7s cubic-bezier(.2, .8, .2, 1) both;
    animation-delay: calc(var(--step, 0) * 90ms);
}

@keyframes tier-grow {
    from { transform: scaleX(0); }
}

/* Auf grünem Grund trägt der Balken die Farbe der Zeile. */
.tier-table tr.is-active .tier-bar { background: #c3e6d3; }
.tier-table tr.is-active .tier-bar > span { background: var(--ok-500); }

/*
 * Der Preis der ganzen Stufe: die Zahl, nach der gefragt wird. Beträge und die
 * Angabe darunter brechen nie um – „10,00" über „€" ist keine Zahl mehr, die
 * man liest. Wird es zu eng, scrollt lieber die Tabelle.
 */
.tier-total {
    display: block;
    font-size: 1.0625rem;
    font-weight: 700;
    white-space: nowrap;
    color: var(--ink-900);
    letter-spacing: -.01em;
}

/* Wofür dieser Betrag gilt – „3 Miettage". */
.tier-note {
    display: block;
    margin-top: 2px;
    font-size: .75rem;
    white-space: nowrap;
    color: var(--ink-500);
}

.tier-per-day {
    display: block;
    white-space: nowrap;
    color: var(--ink-700);
}

/* Auf grünem Grund tragen die Nebenzeilen die Farbe der Zeile mit; graue
   Schrift darauf sähe nach abgeschaltet aus. */
.tier-table tr.is-active td,
.tier-table tbody tr.is-active:hover td {
    background: var(--ok-100);
    color: var(--ok-700);
    border-bottom-color: #c3e6d3;
}

.tier-table tr.is-active .tier-name,
.tier-table tr.is-active .tier-total,
.tier-table tr.is-active .tier-per-day { color: inherit; }
.tier-table tr.is-active .tier-condition,
.tier-table tr.is-active .tier-note { color: inherit; opacity: .75; }

.tier-table tr.is-active td:first-child {
    border-radius: var(--radius-sm) 0 0 var(--radius-sm);
    box-shadow: inset 3px 0 0 var(--ok-500);
}

.tier-table tr.is-active td:last-child {
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

/*
 * Auf dem Telefon zählt jede Spalte: Vier davon passen nur dann ohne Scrollen
 * nebeneinander, wenn Schrift und Abstände mitgehen. Weggelassen wird keine –
 * „Pro Miettag" ist die einzige Zahl, die sich zwischen Stufen mit
 * verschiedenen Mindestdauern vergleichen lässt, und die Ersparnis ist der
 * Grund, warum überhaupt jemand hinsieht.
 */
@media (max-width: 560px) {
    .tier-table { font-size: .8125rem; }
    .tier-table th { font-size: .625rem; padding-bottom: var(--space-2); }
    .tier-table td { padding-top: var(--space-2); padding-bottom: var(--space-2); }
    .tier-table th, .tier-table td { padding-left: var(--space-1); padding-right: var(--space-1); }
    .tier-table th:first-child, .tier-table td:first-child { padding-left: var(--space-2); }
    .tier-table th:last-child, .tier-table td:last-child { padding-right: var(--space-2); }
    .tier-total { font-size: .9375rem; }
    .tier-condition, .tier-note { font-size: .6875rem; }
}

/* Durchgestrichener Grundpreis neben dem Staffelpreis */
.price-was {
    font-size: .9375rem;
    color: var(--ink-400);
    text-decoration: line-through;
}

.tier-hint {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    margin: 0;
    padding: var(--space-3);
    border-radius: var(--radius);
    background: var(--accent-100);
    color: var(--accent-700);
    font-size: .8125rem;
    line-height: 1.5;
}

.tier-hint svg { width: 16px; height: 16px; flex: none; margin-top: 2px; }

/* Staffelzeilen im Artikelformular */
.tier-rows { width: 100%; min-width: 480px; border-collapse: collapse; }

.tier-rows th {
    padding: 0 var(--space-2) var(--space-2);
    text-align: left;
    font-size: .75rem;
    font-weight: 650;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--ink-500);
}

.tier-rows td { padding: 4px var(--space-2); vertical-align: top; }
.tier-rows td input { font-size: .875rem; padding: 8px 10px; }
.tier-rows .col-num { width: 110px; }
.tier-rows .col-actions { width: 44px; text-align: right; }
.tier-rows tr.is-removed { display: none; }

/* ------------------------------------------------------------------ Print */

@media print {
    body { background: var(--white); }
    .no-print { display: none !important; }
}

/* -------------------------------------------------------- Suchvorschläge */

.search-field,
.quick-add { position: relative; }

.suggestions {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    z-index: 60;
    background: var(--white);
    border: 1px solid var(--ink-200);
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
    max-height: 380px;
    overflow-y: auto;
}

.suggestions:empty { display: none; }

.suggestion {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: 100%;
    padding: 10px var(--space-3);
    border: 0;
    border-bottom: 1px solid var(--ink-100);
    background: none;
    font: inherit;
    text-align: left;
    cursor: pointer;
    color: var(--ink-800);
    text-decoration: none;
}

.suggestion:last-child { border-bottom: 0; }
.suggestion:hover,
.suggestion.is-active { background: var(--brand-50); text-decoration: none; }

/*
 * Zwischenüberschrift einer Trefferart – nur in der Suche über alles, wo
 * Aufträge, Kunden und Artikel in einer Liste stehen. Sie ist kein Treffer und
 * deshalb weder anklickbar noch mit den Pfeiltasten erreichbar.
 */
.suggestion-group {
    padding: var(--space-2) var(--space-3) 4px;
    border-bottom: 1px solid var(--ink-100);
    background: var(--ink-50);
    font-size: .6875rem;
    font-weight: 650;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--ink-500);
}

.suggestion img,
.suggestion .s-thumb-empty {
    width: 40px; height: 40px;
    object-fit: cover;
    border-radius: var(--radius-sm);
    flex: none;
    background: var(--ink-100);
}

.suggestion .s-body { flex: 1; min-width: 0; }
.suggestion .s-name { display: block; font-weight: 550; font-size: .9375rem; }

.suggestion .s-excerpt {
    display: block;
    font-size: .8125rem;
    color: var(--ink-600);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.suggestion .s-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 10px;
    font-size: .75rem;
    color: var(--ink-500);
    margin-top: 2px;
}

/* Trennpunkt zwischen Kategorie, Standort und Übergabeart. */
.suggestion .s-meta span + span::before { content: "·"; margin-right: 10px; color: var(--ink-300); }

.suggestion .s-side {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 2px;
    flex: none;
    text-align: right;
}

.suggestion .s-price { font-size: .9375rem; font-weight: 650; color: var(--ink-900); white-space: nowrap; }
.suggestion .s-price-note,
.suggestion .s-stock { font-size: .6875rem; color: var(--ink-500); white-space: nowrap; }

.suggestion .s-availability {
    font-size: .6875rem;
    font-weight: 600;
    padding: 2px 7px;
    border-radius: 999px;
    white-space: nowrap;
}

.suggestion .s-availability.is-available { background: var(--ok-100); color: var(--ok-700); }
.suggestion .s-availability.is-partial { background: var(--warn-100); color: var(--warn-700); }
.suggestion .s-availability.is-unavailable { background: var(--bad-100); color: var(--bad-700); }
.suggestion .s-availability.is-on_request { background: var(--info-100); color: var(--info-700); }

/*
 * Auf der Startseite darf die Liste großzügiger sein – dort ist sie das
 * eigentliche Suchergebnis und nicht nur eine Abkürzung.
 */
.suggestions-rich .suggestion { padding: var(--space-3) var(--space-4); gap: var(--space-4); }

.suggestions-rich .suggestion img,
.suggestions-rich .suggestion .s-thumb-empty { width: 72px; height: 54px; }

.suggestions-rich .suggestion .s-name { font-size: 1rem; }

@media (max-width: 560px) {
    .suggestion .s-excerpt { display: none; }
    .suggestions-rich .suggestion img,
    .suggestions-rich .suggestion .s-thumb-empty { width: 48px; height: 40px; }
}

/*
 * Was getippt wurde, steht im Vorschlag fett – ohne den gelben Marker des
 * Browsers, der in einer Liste aus Namen wie ein Fehler aussähe.
 */
.suggestion mark { background: none; color: var(--brand-700); font-weight: 750; padding: 0; }

/* „Meintest du …?" über den Treffern einer Korrektur. */
.suggestion-correction {
    padding: var(--space-2) var(--space-3);
    border-bottom: 1px solid var(--ink-100);
    background: var(--warn-100);
    color: var(--warn-700);
    font-size: .8125rem;
    font-weight: 600;
}

/* Kategorie und Mietberater stehen über den Artikeln – ein Symbol statt Foto. */
.suggestion-advisor .s-thumb-empty,
.suggestion-category .s-thumb-empty {
    background: var(--brand-50) var(--suggestion-icon) center / 45% no-repeat;
}
.suggestion-category { --suggestion-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='3' width='7' height='7' rx='1'/%3E%3Crect x='14' y='3' width='7' height='7' rx='1'/%3E%3Crect x='3' y='14' width='7' height='7' rx='1'/%3E%3Crect x='14' y='14' width='7' height='7' rx='1'/%3E%3C/svg%3E"); }
.suggestion-advisor { --suggestion-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M9.5 9a2.5 2.5 0 1 1 3.5 2.3c-.6.3-1 .9-1 1.7'/%3E%3Ccircle cx='12' cy='17' r='.5'/%3E%3C/svg%3E"); }

/*
 * Die Chips im leeren Suchfeld: nebeneinander, umbrechend. Sie sind
 * `.suggestion` für die Tastatur, sehen aber aus wie Chips – die Regeln
 * oben (volle Breite, Linie unten) werden hier zurückgenommen.
 */
.suggestion-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    padding: var(--space-3);
    border-bottom: 1px solid var(--ink-100);
}
.suggestion-chips:last-child { border-bottom: 0; }

.suggestion.suggestion-chip {
    display: inline-flex;
    width: auto;
    padding: 6px 12px;
    border: 1px solid var(--ink-200);
    border-radius: 999px;
    font-size: .875rem;
    font-weight: 550;
    color: var(--ink-700);
}
.suggestion.suggestion-chip:last-child { border-bottom: 1px solid var(--ink-200); }
.suggestion.suggestion-chip:hover,
.suggestion.suggestion-chip.is-active { border-color: var(--brand-600); color: var(--brand-700); }

/* ------------------------------------------------------------ Fließtext */

/*
 * Ausgabe der Editor-Inhalte. Dieselben Regeln gelten im Editor selbst, damit
 * beim Schreiben zu sehen ist, was später auf der Seite steht.
 */
.prose { font-size: .9688rem; color: var(--ink-700); line-height: 1.7; }
.prose > :last-child { margin-bottom: 0; }
.prose p { margin-bottom: var(--space-3); }

.prose h2, .prose h3, .prose h4 {
    color: var(--ink-900);
    line-height: 1.3;
    margin: var(--space-5) 0 var(--space-2);
}

.prose h2 { font-size: 1.1875rem; }
.prose h3 { font-size: 1.0625rem; }
.prose h4 { font-size: .9688rem; }
.prose > :first-child { margin-top: 0; }

.prose ul, .prose ol { margin: 0 0 var(--space-3) 1.25rem; }
.prose li { margin-bottom: 4px; }
.prose ul { list-style: disc; }
.prose ol { list-style: decimal; }

.prose blockquote {
    margin: 0 0 var(--space-3);
    padding: var(--space-2) var(--space-4);
    border-left: 3px solid var(--brand-500);
    background: var(--ink-50);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.prose a { color: var(--brand-700); text-decoration: underline; }
.prose strong { color: var(--ink-900); font-weight: 650; }

/* --------------------------------------------------------- Dispositionshinweis */

/*
 * Steht über dem Vorgang – im Kundenportal wie in der Verwaltung. Bewusst
 * ruhiger als eine Warnung: es ist eine Information, kein Problem.
 */
.disposition-note {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    margin-bottom: var(--space-4);
    border: 1px solid var(--ink-200);
    border-left: 3px solid var(--brand-500);
    border-radius: var(--radius);
    background: var(--ink-50);
    font-size: .9375rem;
}

.disposition-note > svg { color: var(--brand-600); margin-top: 3px; }

/* ------------------------------------------------------ Umsatzsteuerhinweis */

/*
 * Die Begründung, warum neben einem Betrag keine Steuer steht. Sie gehört zum
 * Preis und nicht daneben – deshalb dieselbe zurückhaltende Größe wie die
 * übrigen Erläuterungen unter einer Summe.
 */
.vat-note {
    margin: var(--space-2) 0 0;
    font-size: .75rem;
    color: var(--ink-500);
}

/* ------------------------------------------------------ Uhrzeitauswahl */

/*
 * Das native Zeitfeld mit einer Auswahlliste daneben. Der eigene Knopf ersetzt
 * das Browsersymbol – zwei Uhren nebeneinander wären albern –, das Feld selbst
 * bleibt aber ein ganz normales `input[type="time"]`: tippbar, geprüft, und auf
 * dem Handy mit dem gewohnten Auswahlrad.
 */
.time-field { position: relative; }

.time-field input[type="time"] { padding-right: 40px; }

/* Das Browsersymbol weicht dem eigenen Knopf – aber nur dort, wo es ihn gibt. */
.time-field input[type="time"]::-webkit-calendar-picker-indicator {
    display: none;
}

.time-field-toggle {
    position: absolute;
    top: 50%;
    right: 6px;
    transform: translateY(-50%);
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    padding: 0;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--ink-500);
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}

.time-field-toggle svg { width: 18px; height: 18px; }
.time-field-toggle:hover { background: var(--ink-100); color: var(--ink-700); }
.time-field-toggle:focus-visible { outline: 2px solid var(--brand-600); outline-offset: 1px; }
.time-field-toggle[aria-expanded="true"] { background: var(--brand-50); color: var(--brand-700); }

.time-menu {
    position: absolute;
    z-index: 60;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    min-width: 128px;
    max-height: 232px;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 6px;
    background: var(--white);
    border: 1px solid var(--ink-200);
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.time-menu button {
    padding: 7px 10px;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    font: inherit;
    font-size: .9375rem;
    font-variant-numeric: tabular-nums;
    color: var(--ink-700);
    text-align: left;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}

.time-menu button:hover { background: var(--ink-100); color: var(--ink-900); }
.time-menu button:focus-visible { outline: 2px solid var(--brand-600); outline-offset: -2px; }

.time-menu button.is-active {
    background: var(--brand-50);
    color: var(--brand-700);
    font-weight: 600;
}

/* Der Rollbalken der Liste soll nicht schwerer wiegen als die Liste selbst. */
.time-menu::-webkit-scrollbar { width: 8px; }
.time-menu::-webkit-scrollbar-thumb { background: var(--ink-200); border-radius: 999px; }
.time-menu::-webkit-scrollbar-thumb:hover { background: var(--ink-300); }

/* --------------------------------------------------------- Filterleiste */

/*
 * Eine Filterleiste für die ganze Anwendung: die Listen der Verwaltung und
 * die Trefferliste des Katalogs. Sie stand einmal nur in `admin.css` – als
 * der Katalog seine eigene bekam, wäre das die zweite Fassung derselben
 * Sache gewesen.
 */
.filter-bar {
    display: flex;
    gap: var(--space-3);
    flex-wrap: wrap;
    align-items: flex-end;
    padding: var(--space-4);
    background: var(--white);
    border: 1px solid var(--ink-200);
    border-radius: var(--radius-lg);
    margin-bottom: var(--space-5);
}

.filter-bar .field { margin-bottom: 0; }
.filter-bar .field input, .filter-bar .field select { min-width: 180px; }

/*
 * Auf schmalen Geräten steht jedes Feld über die volle Breite.
 *
 * Nebeneinander blieben von drei Auswahllisten drei Stummel, und ein
 * `min-width: 180px` in einer umbrechenden Zeile schiebt die Leiste über den
 * Bildrand hinaus, statt umzubrechen.
 */
@media (max-width: 640px) {
    .filter-bar { flex-direction: column; align-items: stretch; }
    .filter-bar .field select, .filter-bar .field input { min-width: 0; width: 100%; }
}

/* ------------------------------------------------------ Karte eines Standorts */

/*
 * Steht in `base.css`, weil dieselbe Karte an der Abholinfo des Katalogs, im
 * Kundenportal und im Standortformular der Verwaltung erscheint. Hinweis und
 * Karte haben dieselbe Höhe: Ein Klick auf „Karte anzeigen" soll die Seite
 * nicht verschieben.
 */
.location-map { margin-top: var(--space-2); min-width: 0; }

.location-map-consent,
.location-map-frame {
    display: block;
    width: 100%;
    height: 200px;
    border: 1px solid var(--ink-200);
    border-radius: var(--radius);
}

.location-map-frame {
    /* Leaflets Ebenen tragen z-index bis 1000 – sie bleiben in ihrem Rahmen. */
    position: relative;
    z-index: 0;
    isolation: isolate;
}

.location-map-consent {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-3);
    text-align: center;
    background: var(--ink-50);
}

.location-map-consent svg { width: 22px; height: 22px; color: var(--brand-600); }
.location-map-consent p { margin: 0; max-width: 34ch; font-size: .8125rem; line-height: 1.5; color: var(--ink-600); }

.location-map-link {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-top: var(--space-1);
    font-size: .8125rem;
}

.location-map-link svg { width: 13px; height: 13px; }
