/* ===========================================================================
   Maurice' Haus Planer · Gestaltung

   Zuerst für das Smartphone gebaut, dann nach oben erweitert. Das ist hier
   nicht kosmetisch: Wer auf der Baustelle steht und nachsieht, wann der
   Estrich fertig ist, hat ein Telefon in der Hand und keinen Bildschirm.

   Farben stehen ausschließlich als Variablen. Es gibt einen hellen und einen
   dunklen Satz; welcher gilt, entscheidet die Systemeinstellung, und der
   Schalter in der Kopfzeile überschreibt das über data-thema am <html>.
   =========================================================================== */

/* Die Farben kommen aus dem Logo, nicht aus dem Bauch: Dessen prägender Ton
   ist ein sattes Orange (#f07000, Sättigung 100 %) auf fast schwarzer Kontur,
   dazu das Holz des Schilds. Genau das ist hier die Grundlage.

   Ein Hinweis zum Orange: Weiß darauf erreicht bei #f07000 nur gut 3:1 an
   Kontrast -- für Flächen und große Schrift genügt das, für kleine Schrift
   nicht. Deshalb gibt es zwei Töne: --akzent für Flächen und Balken,
   --akzent-lesbar für Orange AUF hellem Grund. */
:root {
  --grund:        #f6f5f3;
  --flaeche:      #ffffff;
  --flaeche-2:    #efedea;
  --flaeche-3:    #e4e1dc;
  --rand:         #dcd8d2;
  --rand-stark:   #bdb7ae;
  --text:         #1d2229;
  --text-leise:   #5f6570;
  --text-sehr-leise: #8d939d;

  --akzent:       #ec7409;      /* die Markenfarbe, für Flächen */
  --akzent-tief:  #c25a00;      /* Verlaufsende, gedrückte Knöpfe */
  --akzent-lesbar:#b35400;      /* Orange als Textfarbe auf Hell */
  --akzent-weich: #fdefe0;
  --akzent-text:  #ffffff;

  --holz:         #a8763f;      /* das Schild im Logo */
  --tiefe:        #1b222c;      /* die Kontur im Logo */

  --gut:          #2f8a4e;
  --gut-weich:    #e4f3e9;
  --warnung:      #c8811a;
  --warnung-weich:#fbf0dc;
  --schlecht:     #c9433b;
  --schlecht-weich:#fae4e2;

  /* Absperrband. Ein Baustellenmotiv, das hier tatsächlich etwas bedeutet:
     Es markiert überall dasselbe -- „hier geht es nicht weiter". */
  --band-gelb:    repeating-linear-gradient(-45deg,
                    #f5c518 0 14px, #1b222c 14px 28px);
  --band-orange:  repeating-linear-gradient(-45deg,
                    var(--akzent) 0 12px, var(--tiefe) 12px 24px);

  --verlauf-akzent: linear-gradient(135deg, #f79021, var(--akzent) 55%, var(--akzent-tief));
  --verlauf-kopf:   linear-gradient(180deg,
                      color-mix(in srgb, var(--akzent) 5%, var(--flaeche)),
                      var(--flaeche) 70%);

  --schatten:     0 1px 2px rgba(28,20,10,.05), 0 4px 12px rgba(28,20,10,.05);
  --schatten-hoch:0 8px 30px rgba(28,20,10,.18);
  --schatten-akzent: 0 4px 16px color-mix(in srgb, var(--akzent) 34%, transparent);
  --radius:       14px;
  --radius-klein: 9px;

  /* Die Stapelordnung, an einer Stelle und mit Namen.

     TEUER GELERNT: Die Zahlen standen verstreut in den Regeln, und genau
     daran ist es gescheitert. Die Lightbox lag auf 300, jedes Fenster auf
     100, die Meldungen auf 200. Wer ein Bild geöffnet hatte und
     „Bearbeiten" drückte, bekam das Fenster HINTER das Bild gelegt --
     samt Löschen-Knopf, samt Rückfrage, samt der Meldung „Gelöscht".
     Zu sehen war: Man drückt, und es passiert nichts.

     Dialoge, Lightbox und Willkommensschirm liegen deshalb jetzt auf
     DERSELBEN Ebene. Sie hängen alle in #dialoge, also entscheidet die
     Reihenfolge darin -- was zuletzt geöffnet wurde, steht oben. Das
     stimmt in beide Richtungen und ohne dass jemand Zahlen abwägen muss. */
  --z-schleier:    70;
  --z-spalten:     80;    /* Navigation und Seitenleiste */
  --z-kopf:        90;
  --z-gezogen:    240;    /* die Karte, die gerade am Zeiger haengt */
  --z-ablage:     250;    /* der Schleier beim Hineinziehen von Dateien */
  --z-fenster:    300;    /* alles Modale in #dialoge */
  --z-meldung:    500;    /* Meldungen stehen über allem, auch über einem Bild */

  --kopf-hoehe:   56px;
  /* Was die Kopfzeile WIRKLICH belegt. Der Geraeterand oben (Notch, Insel)
     kommt als Polsterung dazu -- und weil alles hier border-box rechnet,
     wuerde `height: var(--kopf-hoehe)` den Inhalt darum zusammenquetschen
     und der Platz darunter waere um denselben Betrag falsch berechnet. In
     Safari hochkant ist der Rand 0, in der Querlage und als App auf dem
     Startbildschirm nicht. */
  --kopf-gesamt:  calc(var(--kopf-hoehe) + env(safe-area-inset-top));
  /* 214px reichten, solange jeder Menüpunkt ein Wort war. Seit die Punkte in
     Gruppen mit eingerücktem Rand stehen und „Daten rund ums Haus" darunter
     ist, bricht der längste sonst in zwei Zeilen um -- und ein zweizeiliger
     Eintrag zwischen sieben einzeiligen sieht nach Versehen aus. 244px ist
     die gemessene Schwelle, ab der es einzeilig bleibt. */
  --nav-breite:   244px;
  --strahl-breite:302px;

  --schrift: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
             "Helvetica Neue", Arial, sans-serif;
  --schrift-zahl: "SF Mono", "Segoe UI Mono", "Roboto Mono", Menlo, Consolas, monospace;
}

/* Dunkel: Die Grautöne bekommen einen warmen Stich, damit das Orange nicht
   wie ein Fremdkörper in kaltem Blaugrau sitzt. Das Orange selbst wird
   heller -- auf dunklem Grund wirkt derselbe Ton sonst matt und schmutzig. */
@media (prefers-color-scheme: dark) {
  :root:not([data-thema="hell"]) {
    --grund:        #16171a;
    --flaeche:      #1e2024;
    --flaeche-2:    #262930;
    --flaeche-3:    #31353d;
    --rand:         #363a43;
    --rand-stark:   #4c5159;
    --text:         #eceae7;
    --text-leise:   #a7a8ac;
    --text-sehr-leise: #797b81;

    --akzent:       #ff8c2b;
    --akzent-tief:  #e06f0c;
    --akzent-lesbar:#ffa051;
    --akzent-weich: #37240f;
    --akzent-text:  #1a1205;

    --holz:         #c2914f;
    --tiefe:        #0e1116;

    --gut:          #4caf72;
    --gut-weich:    #16301e;
    --warnung:      #e0a33f;
    --warnung-weich:#332711;
    --schlecht:     #e5695f;
    --schlecht-weich:#3a1d1b;

    --verlauf-akzent: linear-gradient(135deg, #ffa04d, var(--akzent) 55%, var(--akzent-tief));
    --verlauf-kopf:   linear-gradient(180deg,
                        color-mix(in srgb, var(--akzent) 7%, var(--flaeche)),
                        var(--flaeche) 70%);

    --schatten:     0 1px 2px rgba(0,0,0,.34), 0 4px 14px rgba(0,0,0,.28);
    --schatten-hoch:0 10px 36px rgba(0,0,0,.55);
    --schatten-akzent: 0 4px 18px color-mix(in srgb, var(--akzent) 26%, transparent);
  }
}

:root[data-thema="dunkel"] {
  --grund:        #16171a;
  --flaeche:      #1e2024;
  --flaeche-2:    #262930;
  --flaeche-3:    #31353d;
  --rand:         #363a43;
  --rand-stark:   #4c5159;
  --text:         #eceae7;
  --text-leise:   #a7a8ac;
  --text-sehr-leise: #797b81;
  --akzent:       #ff8c2b;
  --akzent-tief:  #e06f0c;
  --akzent-lesbar:#ffa051;
  --akzent-weich: #37240f;
  --akzent-text:  #1a1205;
  --holz:         #c2914f;
  --tiefe:        #0e1116;
  --gut:          #4caf72;
  --gut-weich:    #16301e;
  --warnung:      #e0a33f;
  --warnung-weich:#332711;
  --schlecht:     #e5695f;
  --schlecht-weich:#3a1d1b;
  --verlauf-akzent: linear-gradient(135deg, #ffa04d, var(--akzent) 55%, var(--akzent-tief));
  --verlauf-kopf:   linear-gradient(180deg,
                      color-mix(in srgb, var(--akzent) 7%, var(--flaeche)),
                      var(--flaeche) 70%);
  --schatten:     0 1px 2px rgba(0,0,0,.34), 0 4px 14px rgba(0,0,0,.28);
  --schatten-hoch:0 10px 36px rgba(0,0,0,.55);
  --schatten-akzent: 0 4px 18px color-mix(in srgb, var(--akzent) 26%, transparent);
}

* { box-sizing: border-box; }

/* Wischen im Chatverlauf darf die SEITE nicht mitziehen. Genau daran faehrt
   auf iOS die Adresszeile ein -- und was sie beim Einfahren mit dem Layout
   macht, steht bei `.ansicht.voll`. `contain` haelt die Bewegung in dem
   Kasten, in dem sie angefangen hat. */
html, body { overscroll-behavior-y: none; }

/* TEUER GELERNT: `hidden` im HTML setzt `display: none` -- aber nur über die
   eingebaute Regel des Browsers, und die hat die schwächste Stärke, die es
   gibt. Jede eigene Regel mit `display` schlägt sie. Ein `<div class="xy"
   hidden>` mit `.xy { display: flex }` steht also sichtbar da.
   Genau das ist passiert: Die Auswahlleiste des Chats stand als leerer
   orangener Balken über dem Eingabefeld. Betroffen waren außerdem der
   Budgetstand in der Kopfzeile, die Ungelesen-Perle, der Ablegebereich und
   das Logo, solange es noch nicht geladen war.
   Diese eine Zeile erledigt das ein für alle Mal. */
[hidden] { display: none !important; }

html, body {
  margin: 0; padding: 0;
  background: var(--grund);
  color: var(--text);
  font-family: var(--schrift);
  font-size: 15px;
  line-height: 1.5;
  -webkit-text-size-adjust: 100%;
  overscroll-behavior-y: none;
}

h1, h2, h3, h4 { margin: 0 0 .5em; line-height: 1.25; font-weight: 600; }
h1 { font-size: 1.4rem; }
h2 { font-size: 1.12rem; }
h3 { font-size: 1rem; }
p  { margin: 0 0 .8em; }
a  { color: var(--akzent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* --------------------------------------------------------------- Kopfzeile */
/* z-index über der Navigation (80): Das Absperrband ragt unter die
   Kopfzeile, und die Navigation hat einen eigenen Hintergrund -- lag sie
   darüber, schnitt sie das Band auf ihrer Breite ab. Genau so sah es aus:
   links dünner als rechts. */
.kopf {
  position: sticky; top: 0; z-index: var(--z-kopf);
  height: var(--kopf-gesamt);
  display: flex; align-items: center; gap: 10px;
  padding: 0 12px;
  padding-top: env(safe-area-inset-top);
  background: var(--verlauf-kopf);
  border-bottom: 1px solid var(--rand);
}
/* Ein schmales Absperrband schließt die Kopfzeile ab -- der eine Ort, an dem
   das Baustellenmotiv dauerhaft sichtbar sein darf, ohne aufdringlich zu
   werden. Drei Pixel genügen dafür. */
.kopf::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -3px; height: 3px;
  background: var(--band-orange);
  background-size: 24px 24px;
  opacity: .85;
  pointer-events: none;   /* liegt über der Navigation, darf aber nichts abfangen */
}

.marke { display: flex; align-items: center; gap: 9px; color: var(--text); flex-shrink: 0; }
.marke:hover { text-decoration: none; }
/* Nur die Höhe wird vorgegeben; die Breite ergibt sich aus dem Bild. Damit
   bleibt jedes Seitenverhältnis erhalten, ohne dass es hier stehen muss.
   Auf dem Telefon bleibt es klein -- daneben müssen noch der Budgetstand
   und die Nutzerkachel Platz finden, und die sind dort wichtiger. Ab
   Tablet wächst es mit der Kopfzeile mit (siehe weiter unten). */
.logo { height: 30px; width: auto; max-width: 165px; display: block; }
.marke-text { font-size: 1.05rem; letter-spacing: -.01em; white-space: nowrap; }
.marke-text strong { font-weight: 700; }
.marke-text span { color: var(--text-leise); font-weight: 400; }

.kopf-budget {
  margin-left: auto; display: flex; align-items: baseline; gap: 6px;
  padding: 5px 11px; border-radius: 999px;
  background: var(--flaeche-2); color: var(--text);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.kopf-budget:hover { text-decoration: none; background: var(--flaeche-3); }
.kopf-budget-zahl { font-weight: 700; font-size: .98rem; }
.kopf-budget-text { font-size: .74rem; color: var(--text-leise); }
/* Die Ideen stehen abgesetzt hinter einem Strich -- sie sind eine andere
   Sorte Zahl als die davor und duerfen nicht mit ihr verschwimmen. */
.kopf-budget-ideen {
  font-size: .72rem; color: var(--text-leise);
  padding-left: 8px; margin-left: 2px; border-left: 1px solid var(--rand);
}
/* Auf dem Telefon nicht. GEMESSEN bei 375 px Fensterbreite: Die Kachel
   waechst von 117 auf 228 px, die Kopfzeile von 453 auf 564 -- und
   .kopf-rechts mit Nutzerkachel und Abmelden rutscht aus dem Bild. Eine
   Zahl mehr ist es nicht wert, den Abmeldeknopf unerreichbar zu machen;
   auf der Uebersicht und in den Finanzen steht sie ohnehin. */
@media (max-width: 640px) { .kopf-budget-ideen { display: none; } }
.kopf-budget.knapp .kopf-budget-zahl { color: var(--warnung); }
.kopf-budget.drueber .kopf-budget-zahl { color: var(--schlecht); }

.plantreue { font-size: .72rem; padding: 1px 6px; border-radius: 999px; font-weight: 600; }
.plantreue.gut     { background: var(--gut-weich);     color: var(--gut); }
.plantreue.schlecht{ background: var(--schlecht-weich);color: var(--schlecht); }

.kopf-rechts { display: flex; align-items: center; gap: 4px; margin-left: 8px; }

.knopf-flach {
  background: none; border: 0; cursor: pointer;
  color: var(--text-leise); font-size: 1.05rem;
  padding: 7px 9px; border-radius: var(--radius-klein);
  line-height: 1; font-family: inherit;
}
.knopf-flach:hover { background: var(--flaeche-2); color: var(--text); }

.nutzer-kachel {
  display: flex; align-items: center; gap: 7px;
  padding: 5px 10px 5px 7px; border-radius: 999px;
  background: var(--flaeche-2); color: var(--text);
  font-size: .84rem; max-width: 150px;
}
.nutzer-kachel:hover { text-decoration: none; background: var(--flaeche-3); }
.nutzer-kachel span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.punkt { width: 9px; height: 9px; border-radius: 50%; background: var(--akzent); flex-shrink: 0; }

/* ------------------------------------------------------------------ Rahmen */
.rahmen {
  display: grid;
  grid-template-columns: 1fr;
  min-height: calc(100vh - var(--kopf-hoehe));
  min-height: calc(100svh - var(--kopf-gesamt));
}

/* ------------------------------------------------------------- Navigation */
.navigation {
  position: fixed; top: 0; bottom: 0; left: 0; z-index: var(--z-spalten);
  width: 254px; padding: 14px 10px;
  padding-top: calc(var(--kopf-hoehe) + 14px + env(safe-area-inset-top));
  background: var(--flaeche);
  border-right: 1px solid var(--rand);
  transform: translateX(-100%);
  transition: transform .22s ease;
  overflow-y: auto;
}
.navigation.offen { transform: translateX(0); box-shadow: var(--schatten-hoch); }

.navigation a {
  display: flex; align-items: center; gap: 11px;
  padding: 11px 13px; margin-bottom: 2px;
  border-radius: var(--radius-klein);
  color: var(--text-leise); font-size: .93rem; font-weight: 500;
}
.navigation a:hover { background: var(--flaeche-2); color: var(--text); text-decoration: none; }
.navigation a.aktiv {
  background: var(--akzent-weich); color: var(--akzent-lesbar); font-weight: 700;
  position: relative;
}
/* Der aktive Eintrag bekommt links einen kurzen Balken in der Markenfarbe --
   deutlicher als eine reine Flächenfärbung, ohne zusätzliche Fläche. */
.navigation a.aktiv::before {
  content: ""; position: absolute; left: 0; top: 20%; bottom: 20%;
  width: 3px; border-radius: 0 3px 3px 0; background: var(--verlauf-akzent);
}
.navigation .zeichen { width: 20px; text-align: center; font-size: 1rem; flex-shrink: 0; }

/* Die vier Schritte -- dieselben wie im Ablaufdiagramm der Anleitung und in
   denselben Farben. Der Streifen links ist bewusst schmal: Er soll die
   Gruppen trennen, nicht das Menü bunt machen. Sechzehn Einträge in einer
   Reihe sind eine Liste, in der man sucht; vier Gruppen zu je drei bis vier
   sind eine Ordnung, die man sich merkt. */
.nav-gruppe {
  margin-top: 15px; padding-left: 9px;
  border-left: 2px solid var(--nav-farbe);
}
.nav-titel {
  display: block; padding: 0 4px 5px;
  font-size: .68rem; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--nav-farbe);
}
.nav-gruppe.reden       { --nav-farbe: var(--akzent-lesbar); }
.nav-gruppe.entscheiden { --nav-farbe: var(--holz); }
.nav-gruppe.tun         { --nav-farbe: var(--gut); }
/* Die Ablage ist der leise Teil -- was hier steht, sieht man nach, wenn man
   etwas belegen muss. Eine fünfte Farbe wäre eine zu viel. */
.nav-gruppe.nachweisen  { --nav-farbe: var(--text-sehr-leise); }
.nav-gruppe a { padding-left: 9px; }

/* Der Kalender gehört in keine der Gruppen -- er wird aus allen gespeist.
   Deshalb steht er oben für sich, mit Rahmen statt Farbstreifen. */
.nav-einzeln {
  flex-wrap: wrap; row-gap: 1px;
  margin: 10px 0 2px;
  border: 1px solid var(--rand); background: var(--flaeche-2);
}
.nav-einzeln:hover { border-color: var(--rand-stark); }
.nav-notiz {
  flex-basis: 100%; padding-left: 31px;
  font-size: .71rem; font-weight: 500; color: var(--text-sehr-leise);
}
.navigation a.aktiv .nav-notiz { color: inherit; opacity: .8; }

.nav-schluss {
  margin-top: 16px; padding-top: 10px; border-top: 1px solid var(--rand);
}
.perle {
  margin-left: auto; min-width: 19px; height: 19px; padding: 0 5px;
  border-radius: 999px; background: var(--akzent); color: #fff;
  font-size: .7rem; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}

/* --------------------------------------------------------------- Ansicht */
.ansicht { padding: 16px 14px 80px; min-width: 0; }

/* ------------------------------------------------------------- Zeitstrahl */
.zeitstrahl {
  position: fixed; top: 0; bottom: 0; right: 0; z-index: var(--z-spalten);
  width: min(90vw, 340px); padding: 14px;
  padding-top: calc(var(--kopf-hoehe) + 10px + env(safe-area-inset-top));
  background: var(--flaeche); border-left: 1px solid var(--rand);
  transform: translateX(100%); transition: transform .22s ease;
  overflow-y: auto;
}
.zeitstrahl.offen { transform: translateX(0); box-shadow: var(--schatten-hoch); }
.zeitstrahl-kopf { display: flex; align-items: center; justify-content: space-between; }
.zeitstrahl-kopf h2 { margin: 0; font-size: .8rem; text-transform: uppercase;
  letter-spacing: .06em; color: var(--text-sehr-leise); }

.schleier {
  position: fixed; inset: 0; z-index: var(--z-schleier);
  background: rgba(10,14,20,.5); backdrop-filter: blur(2px);
}

.nur-breit { display: none; }

/* --------------------------------------------------------- Ab Tablet */
@media (min-width: 860px) {
  /* Die Kopfzeile wird höher, damit das Logo Luft bekommt. Weil überall
     var(--kopf-hoehe) steht, ziehen die klebenden Spalten von selbst nach. */
  :root { --kopf-hoehe: 118px; }
  .logo { height: 100px; max-width: 560px; }
  .marke-text { font-size: 1.5rem; }

  .rahmen { grid-template-columns: var(--nav-breite) minmax(0, 1fr); }
  .navigation {
    position: sticky; top: var(--kopf-gesamt); align-self: start;
    height: calc(100vh - var(--kopf-hoehe));
    height: calc(100svh - var(--kopf-gesamt));
    width: auto; transform: none; padding-top: 14px; box-shadow: none;
  }
  .ansicht { padding: 22px 26px 60px; }
  .nur-schmal { display: none !important; }
  .nur-breit { display: initial; }
}

@media (min-width: 1240px) {
  :root { --kopf-hoehe: 134px; }
  .logo { height: 116px; max-width: 640px; }
}

/* ------------------------------------------------- Ab großem Bildschirm */
@media (min-width: 1240px) {
  .rahmen { grid-template-columns: var(--nav-breite) minmax(0, 1fr) var(--strahl-breite); }
  .zeitstrahl {
    position: sticky; top: var(--kopf-gesamt); align-self: start;
    height: calc(100vh - var(--kopf-hoehe));
    height: calc(100svh - var(--kopf-gesamt));
    width: auto; transform: none; padding-top: 16px; box-shadow: none;
  }
  /* Auf großen Schirmen steht der Verlauf ohnehin da; der Schalter wäre
     dann nur ein Knopf, der etwas ausblendet, das niemand stört. */
  .zeitstrahl.zu { display: none; }
}

/* ------------------------------------------------------------------ Karten */
.karte {
  background: var(--flaeche); border: 1px solid var(--rand);
  border-radius: var(--radius); padding: 15px;
  margin-bottom: 14px; box-shadow: var(--schatten);
}
.karte-kopf {
  display: flex; align-items: center; gap: 10px;
  margin: -3px 0 12px;
}
.karte-kopf h2, .karte-kopf h3 { margin: 0; flex: 1; min-width: 0; }
.karte.schmal { padding: 12px; }

.gitter { display: grid; gap: 14px; }
@media (min-width: 700px)  { .gitter.zwei { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1000px) { .gitter.drei { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 700px)  { .gitter.vier { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .gitter.vier { grid-template-columns: repeat(4, 1fr); } }

/* ---------------------------------------------------------------- Kennzahl */
.kennzahl { display: flex; flex-direction: column; gap: 3px; }
.kennzahl .wert {
  font-size: 1.5rem; font-weight: 700; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.kennzahl .bezeichnung {
  font-size: .74rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text-sehr-leise); font-weight: 600;
}
.kennzahl .zusatz { font-size: .8rem; color: var(--text-leise); }
.wert.gut { color: var(--gut); }
.wert.warnung { color: var(--warnung); }
.wert.schlecht { color: var(--schlecht); }

/* --------------------------------------------------------- Budgetbalken */
.balken {
  display: flex; height: 30px; border-radius: var(--radius-klein);
  overflow: hidden; background: var(--flaeche-3); margin: 10px 0 8px;
}
.balken-teil {
  display: flex; align-items: center; justify-content: center;
  font-size: .7rem; font-weight: 700; color: #fff; min-width: 2px;
  overflow: hidden; white-space: nowrap;
  transition: width .35s ease;
}
.balken-teil:hover { filter: brightness(1.12); }
.balken-rest { background: transparent; }

.legende { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: .8rem; }
.legende-punkt {
  display: inline-flex; align-items: center; gap: 6px; color: var(--text-leise);
}
.legende-punkt i { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }
.legende-punkt b { color: var(--text); font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------------ Knöpfe */
.knopf {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 9px 15px; border-radius: var(--radius-klein);
  border: 1px solid var(--rand-stark); background: var(--flaeche);
  color: var(--text); font-size: .89rem; font-weight: 600;
  font-family: inherit; cursor: pointer; white-space: nowrap;
}
.knopf:hover { background: var(--flaeche-2); text-decoration: none; }
.knopf:disabled { opacity: .5; cursor: not-allowed; }
.knopf.haupt {
  background: var(--verlauf-akzent); border-color: transparent;
  color: var(--akzent-text); box-shadow: var(--schatten-akzent);
  transition: transform .12s ease, filter .12s ease, box-shadow .12s ease;
}
.knopf.haupt:hover {
  filter: brightness(1.07); transform: translateY(-1px);
  box-shadow: 0 6px 20px color-mix(in srgb, var(--akzent) 42%, transparent);
}
.knopf.haupt:active { transform: translateY(0); filter: brightness(.96); }
.knopf.gefahr { color: var(--schlecht); border-color: var(--schlecht); }
.knopf.gefahr:hover { background: var(--schlecht-weich); }
.knopf.klein { padding: 5px 10px; font-size: .8rem; }
.knopf.breit { width: 100%; }
.knopf-reihe { display: flex; flex-wrap: wrap; gap: 8px; }

/* ---------------------------------------------------------------- Formulare */
/* Auf die Klasse und nicht auf <label>: Ein Feld, in dem keine Eingabe steckt,
   die ein Label beschriften könnte -- der Fließtext-Editor -- ist ein <div>.
   Warum, steht bei App.feld in core.js. Aussehen soll beides gleich. */
.feld { display: block; margin-bottom: 12px; }
.feld > span.beschriftung {
  display: block; font-size: .78rem; font-weight: 600;
  color: var(--text-leise); margin-bottom: 5px;
}
.feld > span.hinweis {
  display: block; font-size: .75rem; color: var(--text-sehr-leise); margin-top: 4px;
}

input[type=text], input[type=number], input[type=date], input[type=datetime-local],
input[type=email], input[type=url], input[type=password], input[type=search],
select, textarea {
  width: 100%; padding: 0 12px;
  /* Eine feste Höhe für alle. Ohne das sind Auswahlfelder je nach Browser
     zwei bis vier Pixel niedriger als Eingabefelder -- nebeneinander sieht
     das aus, als hätte jemand nicht hingesehen. */
  height: 42px; line-height: normal;
  border: 1px solid var(--rand-stark); border-radius: var(--radius-klein);
  background: var(--flaeche); color: var(--text);
  font-family: inherit; font-size: 16px; /* unter 16px zoomt iOS beim Tippen */
  transition: border-color .15s ease, box-shadow .15s ease;
}
textarea { height: auto; padding: 10px 12px; }
/* Das eigene Dreieck am Auswahlfeld -- das vom Betriebssystem sitzt je nach
   Browser woanders und passt farblich nie. */
select {
  appearance: none; -webkit-appearance: none;
  padding-right: 34px; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, var(--text-leise) 50%),
                    linear-gradient(135deg, var(--text-leise) 50%, transparent 50%);
  background-position: calc(100% - 18px) 18px, calc(100% - 13px) 18px;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
input[type=color] { height: 42px; padding: 4px; cursor: pointer; }
input[type=file] {
  height: auto; padding: 9px 12px; cursor: pointer;
  background: var(--flaeche-2);
}
@media (min-width: 860px) {
  input[type=text], input[type=number], input[type=date], input[type=datetime-local],
  input[type=email], input[type=url], input[type=password], input[type=search],
  select, textarea { font-size: .92rem; }
}
input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--akzent); outline-offset: -1px; border-color: var(--akzent);
}
textarea { resize: vertical; min-height: 78px; line-height: 1.5; }
input[type=checkbox] { width: 17px; height: 17px; accent-color: var(--akzent); }

/* align-items: end -- so stehen die Felder auf einer Linie, auch wenn über
   dem einen ein Hinweis steht und über dem anderen nicht. */
.feld-reihe { display: grid; gap: 12px; align-items: end; }
@media (min-width: 620px) { .feld-reihe.zwei { grid-template-columns: 1fr 1fr; } }
@media (min-width: 620px) { .feld-reihe.drei { grid-template-columns: 1fr 1fr 1fr; } }
.feld-reihe .feld { margin-bottom: 0; }

/* Abschnitt innerhalb eines Formulars. Gliedert lange Masken, ohne sie in
   Karten zu zerlegen. */
.formularteil {
  margin: 18px 0 14px; padding: 14px;
  background: var(--flaeche-2); border-radius: var(--radius-klein);
  border: 1px solid var(--rand);
}
.formularteil > h3 {
  margin: 0 0 12px; font-size: .82rem; text-transform: uppercase;
  letter-spacing: .05em; color: var(--akzent-lesbar); font-weight: 700;
  display: flex; align-items: center; gap: 8px;
}
.formularteil > h3::after {
  content: ""; flex: 1; height: 1px;
  background: linear-gradient(to right,
    color-mix(in srgb, var(--akzent) 35%, transparent), transparent);
}
.formularteil > *:last-child { margin-bottom: 0; }

/* Betragsfelder sollen ins Auge fallen -- sie sind meist der Grund, warum
   jemand die Maske überhaupt öffnet. */
.feld.betrag input {
  font-size: 1.05rem; font-weight: 700; font-variant-numeric: tabular-nums;
  border-color: color-mix(in srgb, var(--akzent) 45%, var(--rand-stark));
  background: color-mix(in srgb, var(--akzent) 5%, var(--flaeche));
}

/* ------------------------------------------------------------------ Marken */
.marke-chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 9px; border-radius: 999px;
  font-size: .74rem; font-weight: 600;
  background: var(--flaeche-3); color: var(--text-leise);
  white-space: nowrap;
}
.marke-chip.gut     { background: var(--gut-weich);      color: var(--gut); }
.marke-chip.warnung { background: var(--warnung-weich);  color: var(--warnung); }
.marke-chip.schlecht{ background: var(--schlecht-weich); color: var(--schlecht); }
.marke-chip.akzent  { background: var(--akzent-weich);   color: var(--akzent); }
/* Ein Chip, der nur einordnet und nicht ruft -- „noch nie da", „das bist du". */
.marke-chip.leise {
  background: transparent; color: var(--text-sehr-leise);
  border: 1px solid var(--rand); font-weight: 500;
}

/* ------------------------------------------------------------ Gästeliste
   Die Einladezeile: Adresse, Name, Haken, Knopf -- auf breiten Schirmen in
   einer Reihe, auf dem Telefon untereinander. */
.einlade-zeile {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px;
  margin: 12px 0 0;
}
/* Der Hinweis zur Adresse. Steht unter der ganzen Zeile, damit er das
   Adressfeld nicht hoeher macht als die uebrigen -- siehe einstellungen.js. */
.einlade-hinweis {
  margin: 6px 0 0; padding-bottom: 14px;
  border-bottom: 1px solid var(--rand);
}
.einlade-zeile > .feld:first-child { flex: 2 1 240px; }
.einlade-zeile > .feld { flex: 1 1 150px; margin: 0; }
/* Haken und Knopf sollen auf der Linie der Eingabefelder MITTIG sitzen, nicht
   nur mit ihnen unten abschliessen. Ein Feld ist 42 Pixel hoch, der Knopf 37,
   der Haken 28 -- bei reiner Unterkantenausrichtung liegen ihre Mitten
   entsprechend 3 und 7 Pixel tiefer, und genau das sieht schief aus. Die
   gemeinsame Mindesthoehe rueckt alle drei auf dieselbe Mitte. */
.einlade-zeile .haken,
.einlade-zeile > .knopf {
  min-height: 42px; display: inline-flex; align-items: center;
  padding-bottom: 0;
}
.haken {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: .86rem; color: var(--text-leise); cursor: pointer;
  white-space: nowrap;
}
.haken input { width: 16px; height: 16px; margin: 0; }
.chip-reihe { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 5px; }

/* ------------------------------------------------------------------- Listen */
.liste { display: flex; flex-direction: column; gap: 8px; }
.listen-eintrag {
  display: flex; align-items: center; gap: 11px;
  padding: 11px 13px; background: var(--flaeche);
  border: 1px solid var(--rand); border-radius: var(--radius-klein);
  cursor: pointer;
}
.listen-eintrag:hover { border-color: var(--rand-stark); background: var(--flaeche-2); }
.listen-eintrag .haupt { flex: 1; min-width: 0; }
.listen-eintrag .titel {
  font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.listen-eintrag .unter {
  font-size: .79rem; color: var(--text-leise);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.listen-eintrag .betrag {
  font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.farbstreifen { width: 4px; align-self: stretch; border-radius: 2px; flex-shrink: 0; }

/* -------------------------------------------------------------------- Chat
   Sprechblasen statt Zeilen: eigene Nachrichten rechts in der Akzentfarbe,
   fremde links mit Avatar. Aufeinanderfolgende Nachrichten derselben Person
   rücken zusammen und verlieren die Wiederholung von Name und Bild -- ohne
   das wird ein lebhafter Verlauf zur Namensspalte. */

/* TEUER GELERNT: Hier stand 'height: calc(100vh - kopfhoehe - 44px)'. Diese
   Rechnung kennt aber nur die Kopfzeile -- über dem Chat sitzt noch eine
   Überschrift, und die zählte niemand mit. Ergebnis: Die Eingabezeile lag
   57 Pixel UNTER dem Bildschirmrand, der Sendeknopf war schlicht nicht
   erreichbar. Deshalb wird die Höhe jetzt nicht mehr gerechnet: Die Ansicht
   wird zur Flex-Spalte, und der Chat nimmt sich, was übrig ist. */
/* UND NOCH EINMAL DASSELBE, auf dem Telefon -- in zwei Anlaeufen, und der
   erste war falsch:

   `100vh` ist auf iOS die Hoehe OHNE die ein- und ausfahrenden
   Safari-Leisten, also mehr als tatsaechlich zu sehen ist. Der Chat war
   damit um die Hoehe der Adresszeile zu lang, und man musste erst scrollen,
   um schreiben zu koennen.

   Daraufhin stand hier `100dvh`. Das ist die Hoehe, die GERADE da ist -- und
   genau das war der Fehler: Sie aendert sich, WAEHREND man wischt. Die
   Leiste faehrt ein, das Mass waechst, das Layout wird laenger, die Seite
   wird scrollbar, und die Kopfzeile rutscht nach oben aus dem Bild. Aus
   „Eingabezeile nicht zu sehen" wurde „alles zu hoch gerutscht".

   `100svh` ist die Hoehe mit AUSGEFAHRENEN Leisten. Sie ist die kleinste und
   bleibt beim Wischen stehen. Die Seite ist damit nie laenger als das Bild,
   die Leisten haben keinen Grund einzufahren, und nichts verschiebt sich.
   Ein Streifen bleibt ungenutzt, wenn die Leisten doch einmal weg sind --
   das ist der Preis, und er ist der richtige: Ein Layout, das stillsteht,
   ist mehr wert als eines, das jeden Pixel ausnutzt und dabei wackelt.

   Abgezogen wird `--kopf-gesamt` und nicht `--kopf-hoehe`: Der Geraeterand
   oben gehoert zur Kopfzeile und muss unten fehlen.

   Die vh-Zeile bleibt als Rueckfallebene darueber stehen. */
.ansicht.voll {
  display: flex; flex-direction: column;
  height: calc(100vh - var(--kopf-hoehe));
  height: calc(100svh - var(--kopf-gesamt));
  padding-bottom: 0;
  overflow: hidden;
}
.ansicht.voll > div { display: flex; flex-direction: column; min-height: 0; flex: 1; }

/* Der Kopf über dem Chat -- kompakt, damit möglichst viel Platz für den
   Verlauf bleibt. */
.chat-kopf {
  flex-shrink: 0;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-bottom: 12px;
}
.chat-kopf h1 { margin: 0 0 2px; }
.chat-kopf p { margin: 0; }

/* Auf dem Telefon zaehlt jede Zeile fuer das Gespraech. Ueberschrift und
   Erklaerung nehmen dort zusammen 65 von rund 660 Pixeln -- ein Zehntel des
   Bildes fuer einen Satz, den man einmal liest und danach nie wieder. Der
   Menuepunkt heisst ohnehin „Brainstorming"; wo man ist, weiss man.
   Die Erklaerung steht weiterhin in der Hilfe. */
@media (max-width: 620px) {
  .chat-kopf { margin-bottom: 8px; gap: 8px; }
  .chat-kopf h1 { font-size: 1.25rem; }
  .chat-kopf p { display: none; }
  .ansicht.voll { padding-top: 10px; }
  /* Der Hinweis unter der Eingabezeile ebenso: drei Merksaetze, von denen
     zwei (Enter, Umschalt+Enter) auf einem Telefon gar nicht zutreffen. */
  .chat-hinweis { display: none; }
}

.chat-rahmen {
  display: flex; flex-direction: column;
  flex: 1; min-height: 0;
  background: var(--flaeche);
  border: 1px solid var(--rand);
  border-radius: var(--radius);
  box-shadow: var(--schatten);
  overflow: hidden;
}

.chat-verlauf {
  flex: 1; min-height: 0; overflow-y: auto;
  overscroll-behavior: contain;
  padding: 14px 12px 16px;
  display: flex; flex-direction: column; gap: 2px;
  overscroll-behavior: contain;
  scroll-behavior: smooth;
  /* Ein Hauch Farbe im Hintergrund, damit die Blasen darauf sitzen und
     nicht im Nichts schweben. */
  background:
    radial-gradient(ellipse 80% 60% at 50% 0%,
      color-mix(in srgb, var(--akzent) 5%, transparent), transparent 70%),
    var(--flaeche-2);
}

.nachricht {
  display: flex; gap: 9px; position: relative;
  padding: 1px 4px; max-width: 100%;
  animation: blase-herein .22s cubic-bezier(.2, .8, .3, 1);
}
@keyframes blase-herein {
  from { opacity: 0; transform: translateY(6px) scale(.985); }
}
@media (prefers-reduced-motion: reduce) {
  .nachricht { animation: none; }
  .chat-verlauf { scroll-behavior: auto; }
}

.nachricht.eigen { flex-direction: row-reverse; }
.nachricht.folge { margin-top: -1px; }
.nachricht.folge .avatar { visibility: hidden; }
.nachricht.folge .nachricht-wer { display: none; }

.avatar {
  width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-weight: 700; font-size: .78rem;
  align-self: flex-end; margin-bottom: 2px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .16);
  letter-spacing: .02em;
}

.nachricht-koerper { min-width: 0; max-width: min(78%, 620px); }
.nachricht.eigen .nachricht-koerper { align-items: flex-end; }

.blase {
  position: relative;
  padding: 8px 13px 7px;
  border-radius: 17px;
  background: var(--flaeche);
  border: 1px solid var(--rand);
  box-shadow: 0 1px 2px rgba(16, 24, 40, .04);
}
.nachricht.eigen .blase {
  background: var(--akzent); border-color: transparent; color: var(--akzent-text);
  box-shadow: 0 2px 10px color-mix(in srgb, var(--akzent) 28%, transparent);
}
/* Die Ecke zum Absender hin wird bei der letzten Nachricht einer Folge
   eckiger -- das ist der kleine Kniff, der eine Blasenkette zusammenhält. */
.nachricht:not(.folge-oben) .blase { border-bottom-left-radius: 6px; }
.nachricht.eigen:not(.folge-oben) .blase {
  border-bottom-left-radius: 17px; border-bottom-right-radius: 6px;
}

.nachricht-wer {
  font-weight: 700; font-size: .78rem; margin-bottom: 2px;
  letter-spacing: .01em;
}
.nachricht.eigen .nachricht-wer { display: none; }

.nachricht-text {
  white-space: pre-wrap; word-break: break-word;
  font-size: .94rem; line-height: 1.45;
}
.nachricht-text a { word-break: break-all; text-decoration: underline; }
.nachricht.eigen .nachricht-text a { color: #fff; }

.nachricht-fuss {
  display: flex; align-items: center; gap: 6px;
  margin-top: 3px; font-size: .68rem;
  color: var(--text-sehr-leise);
}
.nachricht.eigen .nachricht-fuss {
  justify-content: flex-end; color: rgba(255, 255, 255, .72);
}
.nachricht.geloescht .blase { background: var(--flaeche-2); border-style: dashed; }
.nachricht.geloescht .nachricht-text { color: var(--text-sehr-leise); font-style: italic; }

/* Ausgewählt für die Ausgliederung als Idee */
.nachricht.gewaehlt .blase {
  outline: 2px solid var(--akzent); outline-offset: 2px;
}
.nachricht.gewaehlt::before {
  content: "💡"; position: absolute; top: 50%; transform: translateY(-50%);
  left: -2px; font-size: .8rem; z-index: 2;
}
.nachricht.eigen.gewaehlt::before { left: auto; right: -2px; }

.reaktionen {
  display: flex; flex-wrap: wrap; gap: 4px;
  margin-top: 5px;
}
.nachricht.eigen .reaktionen { justify-content: flex-end; }
.reaktion {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px; border-radius: 999px; font-size: .76rem;
  background: var(--flaeche-2); border: 1px solid var(--rand);
  cursor: pointer; transition: transform .12s ease, border-color .12s ease;
  line-height: 1.4;
}
.reaktion:hover { transform: translateY(-1px); border-color: var(--rand-stark); }
.reaktion.eigen {
  background: var(--akzent-weich); border-color: var(--akzent); color: var(--akzent);
  font-weight: 700;
}

.nachricht-werkzeuge {
  position: absolute; top: -13px; z-index: 3;
  display: none; gap: 1px; padding: 3px;
  background: var(--flaeche); border: 1px solid var(--rand);
  border-radius: 999px; box-shadow: var(--schatten-hoch);
}
.nachricht .nachricht-werkzeuge { right: 12px; }
.nachricht.eigen .nachricht-werkzeuge { right: auto; left: 12px; }
.nachricht:hover .nachricht-werkzeuge,
.nachricht:focus-within .nachricht-werkzeuge { display: flex; }
.nachricht-werkzeuge button {
  border: 0; background: none; cursor: pointer; padding: 4px 7px;
  font-size: .9rem; border-radius: 999px; color: var(--text-leise);
  line-height: 1;
}
.nachricht-werkzeuge button:hover { background: var(--flaeche-2); transform: scale(1.15); }

/* Auf Telefonen gibt es kein Überfahren mit der Maus -- dort sind die
   Werkzeuge dauerhaft sichtbar, aber zurückhaltend. */
@media (hover: none) {
  .nachricht-werkzeuge { display: flex; opacity: .5; top: -11px; }
  .nachricht-koerper { max-width: 84%; }
}

.chat-eingabe {
  flex-shrink: 0;
  display: flex; gap: 10px; align-items: flex-end;
  padding: 12px 14px;
  padding-bottom: calc(12px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--rand);
  background: var(--flaeche);
}
.chat-eingabe textarea {
  flex: 1; min-height: 52px; max-height: 200px; resize: none;
  padding: 15px 18px; border-radius: 26px;
  border: 1px solid var(--rand-stark);
  background: var(--flaeche-2);
  font-size: .95rem; line-height: 1.45;
  transition: border-color .15s ease, box-shadow .15s ease, background .15s ease;
}
.chat-eingabe textarea:focus {
  outline: none; border-color: var(--akzent);
  background: var(--flaeche);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--akzent) 18%, transparent);
}

/* Der Sendeknopf. Bewusst groß, farbig und mit Beschriftung -- ein blasses
   Pfeilchen übersieht man, und genau das ist passiert. */
.chat-senden {
  height: 52px; flex-shrink: 0;
  padding: 0 22px; border-radius: 26px; border: 0; cursor: pointer;
  background: var(--verlauf-akzent); color: var(--akzent-text);
  font-size: .95rem; font-weight: 700; font-family: inherit;
  display: flex; align-items: center; gap: 8px;
  box-shadow: var(--schatten-akzent);
  transition: transform .12s ease, filter .12s ease, box-shadow .12s ease;
}
.chat-senden:hover {
  filter: brightness(1.08); transform: translateY(-1px);
  box-shadow: 0 6px 22px color-mix(in srgb, var(--akzent) 45%, transparent);
}
.chat-senden:active { transform: translateY(0) scale(.97); }
.chat-senden .pfeil { font-size: 1.05rem; line-height: 1; }

/* Auf schmalen Geräten nur das Zeichen -- dort zählt jeder Millimeter für
   das Eingabefeld. */
@media (max-width: 620px) {
  .chat-senden { padding: 0; width: 52px; justify-content: center; }
  .chat-senden .beschriftung { display: none; }
  .chat-eingabe { padding: 10px; gap: 8px; }
  .chat-verlauf { padding: 10px 8px 12px; }
}

/* Hinweis unter der Eingabe */
.chat-hinweis {
  flex-shrink: 0; padding: 0 16px 8px;
  font-size: .72rem; color: var(--text-sehr-leise);
  background: var(--flaeche);
}
@media (max-width: 620px) { .chat-hinweis { display: none; } }

.tag-trenner {
  display: flex; align-items: center; gap: 12px; margin: 16px 2px 10px;
  font-size: .72rem; color: var(--text-sehr-leise); font-weight: 700;
  text-transform: uppercase; letter-spacing: .07em;
}
.tag-trenner::before, .tag-trenner::after {
  content: ""; flex: 1; height: 1px;
  background: linear-gradient(to right, transparent, var(--rand), transparent);
}

/* ------------------------------------------------------------------ Galerie
   Justiertes Raster: gleich hohe Zeilen, Bilder behalten ihr Seitenverhältnis
   und füllen die Breite gemeinsam aus. Das gelingt allein über flex-grow
   proportional zum Seitenverhältnis -- ohne Rechnerei in JavaScript und ohne
   dass beim Größerziehen des Fensters etwas springt. */

.galerie { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 6px; }
/* Ohne diesen Füller zöge die letzte Zeile ihre Bilder über die volle
   Breite auseinander -- sie wären dann deutlich größer als alle anderen. */
.galerie-fueller { flex-grow: 999999; content: ""; }

.galerie-element {
  position: relative; margin: 0; height: 190px;
  border-radius: 10px; overflow: hidden; cursor: pointer;
  background: var(--flaeche-2);
}
.galerie-element img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform .32s cubic-bezier(.2, .8, .3, 1);
}
.galerie-element:hover img { transform: scale(1.045); }
.galerie-element::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(0, 0, 0, .5), transparent 45%);
  opacity: 0; transition: opacity .2s ease;
}
.galerie-element:hover::after,
.galerie-element:has(figcaption)::after { opacity: 1; }

.galerie-element figcaption {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  padding: 16px 10px 8px; color: #fff; font-size: .78rem; font-weight: 600;
  display: flex; align-items: baseline; gap: 7px;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .6);
}
.galerie-element figcaption > span:first-child {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
.galerie-wer {
  margin-left: auto; flex-shrink: 0;
  font-size: .7rem; font-weight: 500; opacity: .85;
}
.galerie-video {
  position: absolute; top: 50%; left: 50%; z-index: 2;
  transform: translate(-50%, -50%);
  width: 46px; height: 46px; border-radius: 50%;
  background: rgba(0, 0, 0, .48); backdrop-filter: blur(3px);
  color: #fff; font-size: 1.1rem;
  display: flex; align-items: center; justify-content: center;
  padding-left: 3px; pointer-events: none;
}

@media (max-width: 620px) { .galerie-element { height: 130px; } }

/* --------------------------------------------------------------- Lightbox */
.lightbox {
  position: fixed; inset: 0; z-index: var(--z-fenster);
  display: flex; flex-direction: column;
  background: rgba(8, 10, 14, .95);
  backdrop-filter: blur(6px);
  animation: aufblenden .18s ease;
}
@keyframes aufblenden { from { opacity: 0; } }

.lightbox-kopf {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px; padding-top: calc(12px + env(safe-area-inset-top));
  flex-shrink: 0;
}
.lightbox-schliessen {
  border: 0; background: rgba(255, 255, 255, .12); color: #fff;
  width: 36px; height: 36px; border-radius: 50%; cursor: pointer;
  font-size: 1rem; line-height: 1;
}
.lightbox-schliessen:hover { background: rgba(255, 255, 255, .24); }

.lightbox-mitte {
  flex: 1; min-height: 0;
  display: flex; align-items: center; gap: 8px; padding: 0 8px;
}
.lightbox-buehne {
  flex: 1; min-width: 0; height: 100%;
  display: flex; align-items: center; justify-content: center;
}
.lightbox-buehne img, .lightbox-buehne video {
  max-width: 100%; max-height: 100%;
  object-fit: contain; border-radius: 8px;
  box-shadow: 0 12px 48px rgba(0, 0, 0, .5);
}
/* Heranholen: Rad, zwei Finger, Doppeltipp. `touch-action: none` muss sein --
   sonst nimmt der Browser die zwei Finger fuer sich und zoomt die ganze
   Seite statt des Bildes. Keine Uebergangszeit: Beim Ziehen wuerde das Bild
   dem Finger hinterherlaufen. */
.lightbox-buehne img {
  touch-action: none; cursor: zoom-in;
  transform-origin: center center;
  will-change: transform;
}
.lightbox-buehne img.gezoomt { cursor: grab; border-radius: 0; }
.lightbox-buehne img.gezoomt:active { cursor: grabbing; }
.lightbox-pfeil {
  flex-shrink: 0; border: 0; cursor: pointer;
  width: 46px; height: 46px; border-radius: 50%;
  background: rgba(255, 255, 255, .12); color: #fff;
  font-size: 1.6rem; line-height: 1;
  display: flex; align-items: center; justify-content: center;
}
.lightbox-pfeil:hover:not(:disabled) { background: rgba(255, 255, 255, .26); }
.lightbox-pfeil:disabled { opacity: .2; cursor: default; }

.lightbox-infos {
  display: flex; align-items: flex-start; gap: 12px; flex-wrap: wrap;
  padding: 14px 18px; padding-bottom: calc(14px + env(safe-area-inset-bottom));
  color: #fff; flex-shrink: 0;
  background: rgba(0, 0, 0, .3);
}
.lightbox-infos .verweis {
  background: rgba(255, 255, 255, .12); border-color: transparent; color: #fff;
}
.lightbox-infos .knopf {
  background: rgba(255, 255, 255, .14); border-color: transparent; color: #fff;
}
.lightbox-infos .knopf:hover { background: rgba(255, 255, 255, .26); }

@media (max-width: 620px) {
  .lightbox-pfeil { display: none; }   /* auf dem Telefon wird gewischt */
  .lightbox-infos { font-size: .85rem; }
}

/* -------------------------------------------------------------- Editor */
.editor {
  border: 1px solid var(--rand-stark); border-radius: var(--radius-klein);
  background: var(--flaeche); overflow: hidden;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.editor:focus-within {
  border-color: var(--akzent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--akzent) 16%, transparent);
}

.editor-leiste {
  display: flex; flex-wrap: wrap; align-items: center; gap: 1px;
  padding: 5px 6px; background: var(--flaeche-2);
  border-bottom: 1px solid var(--rand);
  position: sticky; top: 0; z-index: 2;
}
.editor-knopf {
  min-width: 30px; height: 30px; padding: 0 7px;
  border: 0; border-radius: 6px; background: none; cursor: pointer;
  color: var(--text-leise); font-size: .88rem; font-family: inherit;
  display: flex; align-items: center; justify-content: center;
  transition: background .12s ease, color .12s ease;
}
.editor-knopf:hover { background: var(--flaeche-3); color: var(--text); }
.editor-knopf.aktiv {
  background: var(--akzent-weich); color: var(--akzent-lesbar); font-weight: 700;
}
.editor-trenner {
  width: 1px; height: 18px; background: var(--rand); margin: 0 4px;
}

.editor-flaeche {
  padding: 14px 16px; outline: none; overflow-y: auto; max-height: 60vh;
  font-size: .95rem; line-height: 1.6;
}
.editor-flaeche:empty::before,
.editor-flaeche:has(> p:only-child:empty)::before {
  content: attr(data-platzhalter); color: var(--text-sehr-leise); pointer-events: none;
}
.editor-flaeche.ablegen {
  background: var(--akzent-weich);
  outline: 2px dashed var(--akzent); outline-offset: -6px;
}
.editor-laedt {
  display: inline-block; padding: 3px 9px; border-radius: 6px;
  background: var(--flaeche-3); color: var(--text-leise);
  font-size: .82rem; font-style: italic;
}

/* Inhalt -- im Editor und in der Anzeige gleich */
.editor-flaeche, .formatiert { word-break: break-word; }
.editor-flaeche > *:first-child, .formatiert > *:first-child { margin-top: 0; }
.editor-flaeche > *:last-child, .formatiert > *:last-child { margin-bottom: 0; }

.editor-flaeche h1, .formatiert h1,
.editor-flaeche h2, .formatiert h2,
.editor-flaeche h3, .formatiert h3,
.editor-flaeche h4, .formatiert h4 {
  margin: 1.1em 0 .4em; line-height: 1.3; font-weight: 700;
}
.editor-flaeche h3, .formatiert h3 { font-size: 1.08rem; color: var(--akzent-lesbar); }
.editor-flaeche p, .formatiert p { margin: 0 0 .7em; }
.editor-flaeche ul, .formatiert ul,
.editor-flaeche ol, .formatiert ol { margin: 0 0 .7em; padding-left: 1.4em; }
.editor-flaeche li, .formatiert li { margin-bottom: .25em; }

.editor-flaeche blockquote, .formatiert blockquote {
  margin: .8em 0; padding: 2px 0 2px 14px;
  border-left: 3px solid var(--akzent); color: var(--text-leise);
}
.editor-flaeche pre, .formatiert pre {
  background: var(--flaeche-2); padding: 10px 12px; border-radius: 8px;
  overflow-x: auto; font-family: var(--schrift-zahl); font-size: .84rem;
}
.editor-flaeche code, .formatiert code {
  background: var(--flaeche-2); padding: 1px 5px; border-radius: 4px;
  font-family: var(--schrift-zahl); font-size: .86em;
}
.editor-flaeche hr, .formatiert hr {
  border: 0; height: 4px; margin: 1.2em 0; border-radius: 2px;
  background: var(--band-gelb); background-size: 20px 20px; opacity: .45;
}

.editor-flaeche img, .formatiert img {
  max-width: 100%; height: auto; border-radius: 10px;
  margin: .5em 0; display: block; box-shadow: var(--schatten);
}
.formatiert img { cursor: zoom-in; transition: transform .2s ease; }
.formatiert img:hover { transform: scale(1.01); }

.editor-flaeche table, .formatiert table {
  border-collapse: collapse; width: 100%; margin: .8em 0; font-size: .89rem;
}
.editor-flaeche th, .formatiert th,
.editor-flaeche td, .formatiert td {
  border: 1px solid var(--rand); padding: 7px 10px; text-align: left;
  vertical-align: top;
}
.editor-flaeche th, .formatiert th {
  background: var(--flaeche-2); font-weight: 700; font-size: .82rem;
}
.formatiert table { display: block; overflow-x: auto; }

/* Ein eingefügtes YouTube-Video: Standbild mit Titel darunter.
   Über `figure` und nicht über eine Klasse -- die Säuberung räumt Attribute
   an figure ab, eine Klasse hielte also nur bis zum nächsten Speichern. */
.editor-flaeche figure, .formatiert figure { margin: .8em 0; max-width: 420px; }
.editor-flaeche figure img, .formatiert figure img { margin: 0; }
.editor-flaeche figcaption, .formatiert figcaption {
  font-size: .85rem; color: var(--text-leise); margin-top: 5px; line-height: 1.35;
}

/* ------------------------------------------------------------- YouTube
   Die Karte im Chat und in der Linksammlung. Das Standbild kommt aus dieser
   Anwendung, nicht von Google -- siehe routes_media.py. */
.yt-karte {
  display: flex; align-items: center; gap: 10px;
  max-width: 400px; padding: 6px; margin-top: 6px;
  border: 1px solid var(--rand); border-radius: var(--radius-klein);
  background: var(--flaeche-2); color: inherit; text-decoration: none;
  transition: border-color .12s ease, background .12s ease;
}
.yt-karte:hover { border-color: var(--akzent); background: var(--flaeche-3); }
.yt-bild { position: relative; flex: 0 0 120px; line-height: 0; }
.yt-bild img {
  width: 120px; height: 68px; object-fit: cover;
  border-radius: 5px; display: block; margin: 0; box-shadow: none;
}
.yt-knopf {
  position: absolute; inset: 0; display: flex;
  align-items: center; justify-content: center;
  color: #fff; font-size: 1.15rem; text-shadow: 0 1px 7px rgba(0, 0, 0, .75);
}
.yt-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.yt-titel {
  font-size: .86rem; font-weight: 600; line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}

/* --------------------------------------------------- Auswahl mit Suche */
.suchauswahl { position: relative; }
.suchauswahl input { width: 100%; }
.suchauswahl-liste {
  position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 40;
  max-height: 280px; overflow-y: auto;
  background: var(--flaeche); border: 1px solid var(--rand-stark);
  border-radius: var(--radius-klein); box-shadow: var(--schatten-hoch);
}
.suchauswahl-eintrag {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 12px; cursor: pointer; font-size: .9rem;
}
.suchauswahl-eintrag:hover, .suchauswahl-eintrag.markiert {
  background: var(--akzent-weich);
}
.suchauswahl-leer {
  padding: 12px; color: var(--text-sehr-leise); font-size: .86rem; text-align: center;
}

/* ------------------------------------------------------------- Blocker */
.blocker-eintrag {
  display: flex; align-items: center; gap: 11px;
  padding: 11px 13px 11px 5px;
  background: var(--flaeche); border: 1px solid var(--rand);
  border-radius: var(--radius-klein); cursor: pointer;
  position: relative; overflow: hidden;
}
.blocker-eintrag:hover { border-color: var(--rand-stark); }
/* Offene harte Blocker bekommen das Absperrband -- sie sind der Grund,
   warum etwas nicht weitergeht. */
.blocker-eintrag.hart::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 9px;
  background: var(--band-gelb); background-size: 22px 22px;
}
.blocker-eintrag.weich::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 9px;
  background: var(--warnung); opacity: .55;
}
.blocker-eintrag.gefallen::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 9px;
  background: var(--gut);
}
.blocker-eintrag.gefallen { opacity: .62; }
.blocker-eintrag.gefallen .titel { text-decoration: line-through; }
.blocker-eintrag .haupt { flex: 1; min-width: 0; margin-left: 8px; }

/* Der Hinweis an einer gesperrten Idee oder Aufgabe */
.gesperrt-hinweis {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 13px; margin-bottom: 12px;
  border-radius: var(--radius-klein);
  background: var(--warnung-weich); color: var(--text);
  border: 1px solid color-mix(in srgb, var(--warnung) 40%, transparent);
  font-size: .88rem;
}
.gesperrt-hinweis .band { width: 5px; height: 30px; flex-shrink: 0; }

/* Ein Streifen quer über eine Karte, deren Vorhaben blockiert ist */
.karte.gesperrt { position: relative; }
.karte.gesperrt::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 4px;
  border-radius: var(--radius) var(--radius) 0 0;
  background: var(--band-gelb); background-size: 24px 24px;
}

/* ------------------------------------------------------------ Mailansicht */
.mail-inhalt { margin-top: 4px; }
.mail-rahmen {
  width: 100%; height: 320px; border: 1px solid var(--rand);
  border-radius: var(--radius-klein); background: #fff; display: block;
}
.mail-text {
  white-space: pre-wrap; word-break: break-word;
  max-height: 44vh; overflow: auto; padding: 12px;
  background: var(--flaeche-2); border-radius: var(--radius-klein);
  font-size: .9rem; line-height: 1.55;
}
/* Der Hinweis auf nicht geladene Bilder. Fast jede Werbemail enthält ein
   unsichtbares Bild, das beim Öffnen meldet, wer wann gelesen hat. */
.mail-bildhinweis {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 8px 12px; margin-bottom: 8px;
  background: var(--warnung-weich); color: var(--text);
  border: 1px solid color-mix(in srgb, var(--warnung) 40%, transparent);
  border-radius: var(--radius-klein); font-size: .84rem;
}

/* --------------------------------------------------------------- Urheber
   Wer etwas beigetragen hat. Steht überall gleich, damit man die Angabe
   nicht sucht, sondern kennt. Farbe und Kürzel sind dieselben wie im Chat. */
.urheber {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: .78rem; color: var(--text-leise);
  max-width: 100%; min-width: 0;
}
.urheber-zeichen {
  width: 22px; height: 22px; flex-shrink: 0; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-weight: 700; font-size: .6rem; letter-spacing: .02em;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
}
.urheber-name {
  font-weight: 600; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.urheber-zeit { color: var(--text-sehr-leise); white-space: nowrap; }
.urheber-zeit::before { content: "· "; }

/* Etwas größer, wo der Urheber die Hauptaussage ist */
.urheber.gross { font-size: .85rem; }
.urheber.gross .urheber-zeichen { width: 28px; height: 28px; font-size: .7rem; }

/* -------------------------------------------------------- Linksammlung */
/* Das Einwurffeld steht oben und ist immer da -- kein Knopf, der erst einen
   Dialog öffnet. Wer einen Link teilen will, hat ihn in der Zwischenablage. */
.karte.einwurf {
  border-color: color-mix(in srgb, var(--akzent) 32%, var(--rand));
  background: var(--verlauf-kopf);
}
.einwurf-reihe { display: grid; gap: 10px; }
@media (min-width: 720px) { .einwurf-reihe { grid-template-columns: 1fr 1fr; } }

/* Umschalter der Besorgungen: nach Termin oder nach Laden. Eigene Klasse
   und nicht die der Tor-Ansicht -- die sitzt in der Seitenleiste und hat
   dort andere Masse. Zwei Dinge, die gleich aussehen, aber verschieden
   heissen, lassen sich getrennt aendern. */
.material-sicht { flex: 0 0 auto; }
.material-sicht button.aktiv {
  background: var(--akzent-weich);
  border-color: color-mix(in srgb, var(--akzent) 40%, var(--rand));
  color: var(--akzent-lesbar);
  font-weight: 600;
}

/* Die Wahl der Arbeitsweise: zwei Karten nebeneinander, die gewaehlte
   hervorgehoben. Kein Auswahlfeld -- die Entscheidung faellt einmal pro
   Installation und verdient mehr Platz als eine Zeile in einer Liste. */
.modus-wahl {
  flex: 1 1 220px; display: flex; flex-direction: column; gap: 4px;
  align-items: flex-start; text-align: left;
  padding: 12px 14px; height: auto; white-space: normal;
}
.modus-wahl.aktiv {
  background: var(--akzent-weich);
  border-color: color-mix(in srgb, var(--akzent) 45%, var(--rand));
}
.modus-wahl.aktiv strong { color: var(--akzent-lesbar); }

/* Unterpunkte: eine schlichte Abhakliste. Erledigtes bleibt stehen und wird
   nur durchgestrichen -- weg waere es aus der Liste UND aus dem Blick, und
   dann fehlt der Beleg, dass es getan wurde. */
.todo-liste { display: flex; flex-direction: column; gap: 2px; margin: 6px 0; }
.todo-zeile {
  display: flex; align-items: center; gap: 9px;
  padding: 5px 8px; border-radius: var(--radius-klein);
}
.todo-zeile:hover { background: var(--flaeche-2); }
.todo-zeile input { width: 16px; height: 16px; margin: 0; flex: 0 0 auto; }
.todo-zeile.erledigt span { text-decoration: line-through; color: var(--text-sehr-leise); }

/* ------------------------------------------------------------------ Brett
   Spalten sind Buckets. Waagerecht rollend und NICHT umbrechend: Ein Brett,
   dessen Spalten in die naechste Zeile springen, ist kein Brett mehr --
   dann steht Bad neben Kueche und darunter wieder Bad, und die Ordnung, um
   derentwillen es das Brett gibt, ist weg. Auf dem Telefon rollt man eben. */
.brett {
  display: flex; gap: 12px; align-items: flex-start;
  overflow-x: auto; padding-bottom: 10px;
  scroll-snap-type: x proximity;
}
.brett-spalte {
  flex: 0 0 270px; scroll-snap-align: start;
  background: var(--flaeche-2); border: 1px solid var(--rand);
  border-radius: var(--radius); padding: 10px;
  display: flex; flex-direction: column; gap: 8px;
  /* TEUER GELERNT: Hier stand nur die Rechnung. Auf einem kurzen Bildschirm
     -- Telefon quer, kleines Fenster -- wird sie negativ, der Browser
     klemmt sie auf 0, und die Spalten fallen auf Kopfhoehe zusammen: Das
     Brett ist da, die Karten sind unsichtbar. Die Untergrenze verhindert
     das; bei viel Platz gewinnt weiterhin die Rechnung. */
  max-height: max(260px, calc(100vh - var(--kopf-gesamt) - 220px));
}
/* Ein Spaltenkopf, der sich oeffnen laesst, muss danach aussehen. */
.brett-kopf.klickbar { cursor: pointer; border-radius: var(--radius-klein); }
.brett-kopf.klickbar:hover { background: var(--flaeche-3); }

.brett-punkt {
  width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto;
}
.brett-kopf {
  display: flex; align-items: center; gap: 8px;
  font-weight: 600; font-size: .92rem;
}
.brett-stapel {
  display: flex; flex-direction: column; gap: 8px;
  overflow-y: auto; min-height: 40px;
}
.brett-karte {
  background: var(--flaeche); border: 1px solid var(--rand);
  border-radius: var(--radius-klein); padding: 10px 11px;
  cursor: pointer; box-shadow: var(--schatten);
}
.brett-karte:hover { border-color: var(--rand-stark); }
.brett-karte.fertig { opacity: .55; }
.brett-karte.fertig .brett-titel { text-decoration: line-through; }
.brett-titel { font-size: .9rem; line-height: 1.35; margin-bottom: 6px; }
.brett-marken { display: flex; flex-wrap: wrap; gap: 4px; }
.brett-marken .marke-chip { font-size: .68rem; padding: 1px 7px; }
.brett-plus { width: 100%; justify-content: center; color: var(--text-leise); }

/* --------------------------------------------------------------- Ziehen
   Die Karte bleibt an ihrem Platz und wird blass; was am Zeiger haengt, ist
   eine Kopie. So sieht man WOHER die Karte kommt und wohin sie geht -- eine
   Karte, die beim Anfassen verschwindet, laesst einen raten. */
.brett-karte { touch-action: manipulation; }
.brett-karte.wird-gezogen { opacity: .35; }
.brett-karte-schatten {
  position: fixed; z-index: var(--z-gezogen); pointer-events: none;
  margin: 0; transform: rotate(1.5deg);
  box-shadow: 0 10px 26px rgba(0, 0, 0, .28);
  background: var(--flaeche); border: 1px solid var(--akzent);
  border-radius: var(--radius-klein); padding: 10px 11px;
}
/* Waehrend eines Zuges darf die Beruehrung nicht mehr rollen -- sonst
   nimmt der Browser die Bewegung fuer sich und die Karte klebt fest. */
.brett.zieht { touch-action: none; }
.brett.zieht .brett-spalte { transition: background .12s; }
.brett-spalte.zielspalte {
  background: var(--akzent-weich);
  border-color: color-mix(in srgb, var(--akzent) 50%, var(--rand));
}
/* Die Anlege-Spalte: gestrichelt und ohne Fuellung, damit sie als Platz
   erkennbar ist und nicht als Stapel mit null Karten. */
.brett-neu {
  background: transparent; border-style: dashed;
  align-items: stretch; justify-content: flex-start;
}
/* Eine Karte, die sich oeffnen laesst, muss danach aussehen. */
.karte.klickbar { cursor: pointer; }
.karte.klickbar:hover { border-color: var(--rand-stark); }

.brett-neu-knopf {
  width: 100%; justify-content: center; padding: 14px 10px;
  color: var(--text-leise); font-weight: 600;
}
.brett-neu:hover { border-color: var(--akzent); }
.brett-neu:hover .brett-neu-knopf { color: var(--akzent-lesbar); }

/* ------------------------------------------------------------ Logo-Vorschau
   Zeigt das Logo so, wie es im Kopf erscheint -- auf einem karierten Grund,
   damit man bei einem freigestellten PNG sieht, wo das Bild aufhoert und wo
   der Hintergrund durchscheint. Ohne das haelt man einen weissen Rand fuer
   Teil des Logos und sucht den Fehler beim Hochladen. */
.logo-kasten {
  display: flex; align-items: center; justify-content: center;
  min-height: 84px; padding: 12px; margin: 10px 0;
  border: 1px solid var(--rand); border-radius: var(--radius-klein);
  background-color: var(--flaeche-2);
  background-image:
    linear-gradient(45deg, var(--flaeche-3) 25%, transparent 25%),
    linear-gradient(-45deg, var(--flaeche-3) 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, var(--flaeche-3) 75%),
    linear-gradient(-45deg, transparent 75%, var(--flaeche-3) 75%);
  background-size: 16px 16px;
  background-position: 0 0, 0 8px, 8px -8px, -8px 0;
}
.logo-vorschau { max-width: 100%; max-height: 90px; display: block; }

/* Ein Satz, der eine Folge ankuendigt, die man nicht zurueckdrehen kann --
   hier: dass etwas Privates gleich gemeinsamer Bestand wird. Kein Kasten,
   kein Ausrufezeichen; nur die Farbe, die im Portal ueberall Vorsicht
   bedeutet, damit der Satz gelesen und nicht ueberblaettert wird. */
.warnton {
  color: var(--warnung);
  border-left: 3px solid var(--warnung);
  padding-left: 10px;
}

/* ---------------------------------------------------- Abschnitt im Reiter
   Benennt eine einzelne Kartengruppe, ohne sie in eine größere Karte zu
   stecken -- gleiche Sprache wie die Überschrift in .formularteil (klein,
   akzent-lesbar, dünner Strich nach rechts), nur als eigenständiger Block
   zwischen Karten. Setzt hier das ausgehende Abo von den eingehenden
   Kalendern darüber ab und liefert zugleich die trennende Luft. */
.abschnitt-titel {
  display: flex; align-items: center; gap: 8px;
  margin: 24px 2px 10px;
  font-size: .82rem; text-transform: uppercase;
  letter-spacing: .05em; font-weight: 700;
  color: var(--akzent-lesbar);
}
.abschnitt-titel::after {
  content: ""; flex: 1; height: 1px;
  background: linear-gradient(to right,
    color-mix(in srgb, var(--akzent) 35%, transparent), transparent);
}

/* -------------------------------------------------- Ausgehende Kalender-Karte
   Die übrigen Kalenderkarten LESEN einen fremden Kalender (eingehend). Diese
   eine GIBT den eigenen Kalender aus (ausgehend) -- die Gegenrichtung. Sie
   steht darum als Letztes und trägt denselben warm getönten Rand wie schon
   .karte.einwurf. Bewusst keine Flächenfüllung und kein zweites Band: die
   Karte enthält selbst einen .merksatz mit orangem Band, ein zweites daneben
   würde nur verwirren. Alle Farben über Tokens -- gilt in Hell und Dunkel. */
.karte.ausgehend {
  border-color: color-mix(in srgb, var(--akzent) 32%, var(--rand));
}

.link-vorschau {
  display: flex; align-items: flex-start; gap: 11px;
  margin-top: 12px; padding: 11px 13px;
  background: var(--flaeche); border: 1px solid var(--rand);
  border-radius: var(--radius-klein);
  animation: herein .18s ease;
}

.link-gitter { display: grid; gap: 12px; }
@media (min-width: 720px)  { .link-gitter { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1200px) { .link-gitter { grid-template-columns: 1fr 1fr 1fr; } }

.link-karte {
  background: var(--flaeche); border: 1px solid var(--rand);
  border-radius: var(--radius); padding: 14px;
  display: flex; flex-direction: column; gap: 8px;
  transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease;
}
.link-karte:hover {
  border-color: color-mix(in srgb, var(--akzent) 45%, var(--rand));
  transform: translateY(-2px); box-shadow: var(--schatten);
}
.link-haupt { display: flex; align-items: center; gap: 11px; color: var(--text); }
.link-haupt:hover { text-decoration: none; }
.link-haupt:hover .link-titel { color: var(--akzent-lesbar); }
.link-titel {
  font-weight: 700; line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
/* Kein Zeichen von einem fremden Dienst holen -- das würde jedem Aufruf
   verraten, welche Seiten hier gesammelt werden. Der erste Buchstabe
   genügt zum Auseinanderhalten. */
.link-kuerzel {
  width: 40px; height: 40px; flex-shrink: 0; border-radius: 11px;
  background: var(--verlauf-akzent); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 1.05rem;
  box-shadow: var(--schatten-akzent);
}
.link-kommentar {
  margin: 0; font-size: .87rem; color: var(--text-leise);
  font-style: italic; line-height: 1.45;
}
.link-fuss {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: auto; padding-top: 6px; border-top: 1px solid var(--rand);
}

/* -------------------------------------------------------------- Bauakte */
.bauakte-gitter { display: grid; gap: 12px; }
@media (min-width: 680px)  { .bauakte-gitter { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1120px) { .bauakte-gitter { grid-template-columns: 1fr 1fr 1fr; } }
.bauakte-gitter .feld { margin-bottom: 0; }
/* Mehrzeilige Felder brauchen die volle Breite, sonst wird der Text zur Säule. */
.bauakte-gitter .feld.breit { grid-column: 1 / -1; }

/* ---------------------------------------------------------------- Hilfe */
.hilfe { max-width: 1020px; margin: 0 auto; }

.hilfe-kopf { text-align: center; padding: 6px 0 22px; }
.hilfe-logo {
  max-width: min(460px, 82%); height: auto; display: block; margin: 0 auto 14px;
  /* Ein warmer Schein hinter dem Logo -- er nimmt die Markenfarbe auf,
     ohne dass dafür ein zweites Bild nötig wäre. */
  filter: drop-shadow(0 6px 24px color-mix(in srgb, var(--akzent) 30%, transparent));
}
.hilfe-untertitel { font-size: 1.05rem; color: var(--text-leise); margin: 0; }

.hilfe-kurz {
  background: var(--verlauf-kopf);
  border: 1px solid var(--rand); border-radius: var(--radius);
  padding: 18px 20px; margin-bottom: 22px;
  position: relative; overflow: hidden;
}
.hilfe-kurz::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 4px;
  background: var(--band-orange); background-size: 24px 24px;
}
.hilfe-kurz p:last-child { margin-bottom: 0; }

.hilfe-gitter { display: grid; gap: 14px; }
@media (min-width: 760px)  { .hilfe-gitter { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1180px) { .hilfe-gitter { grid-template-columns: 1fr 1fr 1fr; } }

.hilfe-bereich {
  background: var(--flaeche); border: 1px solid var(--rand);
  border-radius: var(--radius); padding: 16px;
  display: flex; flex-direction: column; gap: 8px;
  transition: border-color .15s ease, transform .15s ease;
}
.hilfe-bereich:hover {
  border-color: color-mix(in srgb, var(--akzent) 45%, var(--rand));
  transform: translateY(-2px);
}
.hilfe-bereich-kopf { display: flex; align-items: flex-start; gap: 11px; }
.hilfe-bereich-kopf h3 { margin: 0; }
.hilfe-zeichen {
  width: 38px; height: 38px; flex-shrink: 0; border-radius: 11px;
  background: var(--verlauf-akzent); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.05rem; box-shadow: var(--schatten-akzent);
}
.hilfe-bereich p { margin: 0; color: var(--text-leise); }
.hilfe-punkte {
  margin: 0; padding-left: 18px; font-size: .84rem;
  color: var(--text-leise); display: flex; flex-direction: column; gap: 5px;
}
.hilfe-punkte li::marker { color: var(--akzent); }
.hilfe-bereich .knopf { align-self: flex-start; margin-top: auto; }

.hilfe-abschnitt { margin-top: 26px; }

/* -------------------------------------------------- Hilfe als Willkommen */
.hilfe-schirm {
  position: fixed; inset: 0; z-index: var(--z-fenster);
  display: flex; align-items: center; justify-content: center;
  padding: 0;
  background: rgba(20, 14, 6, .55);
  /* Der unscharfe Hintergrund -- die Anwendung bleibt sichtbar, tritt aber
     hinter den Schirm zurück. */
  backdrop-filter: blur(9px) saturate(.85);
  -webkit-backdrop-filter: blur(9px) saturate(.85);
  /* NICHT hier scrollen: Sonst wächst der Kasten über den Schirm hinaus, die
     klebende Fußleiste hängt an seinem unteren Ende statt am Bildrand -- und
     der Inhalt läuft sichtbar unter ihr weiter. Gescrollt wird eine Ebene
     tiefer, im Inhaltsbereich des Kastens. */
  overflow: hidden;
  animation: schirm-auf .22s ease;
}
@media (min-width: 760px) { .hilfe-schirm { padding: 34px 20px; } }
@keyframes schirm-auf { from { opacity: 0; } }
.hilfe-schirm.geht { opacity: 0; transition: opacity .18s ease; }

.hilfe-schirm-kasten {
  position: relative;
  background: var(--grund);
  width: 100%; max-width: 1080px;
  max-height: 100%;
  display: flex; flex-direction: column;      /* Inhalt oben, Fuß unten */
  border-radius: 0;
  box-shadow: var(--schatten-hoch);
  overflow: hidden;                            /* die Rundung greift auch beim Scrollen */
  animation: schirm-herein .28s cubic-bezier(.2, .8, .3, 1);
}
@media (min-width: 760px) {
  .hilfe-schirm-kasten { border-radius: 20px; }
}

/* Der scrollende Teil. Er endet über der Fußleiste, deshalb kann nichts
   mehr darunter durchlaufen. */
.hilfe-schirm-inhalt {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 24px 18px 8px;
  overscroll-behavior: contain;
}
@media (min-width: 760px) { .hilfe-schirm-inhalt { padding: 30px 30px 10px; } }
@keyframes schirm-herein {
  from { opacity: 0; transform: translateY(18px) scale(.985); }
}
@media (prefers-reduced-motion: reduce) {
  .hilfe-schirm, .hilfe-schirm-kasten { animation: none; }
}

.hilfe-schliessen {
  position: absolute; top: 12px; right: 12px; z-index: 3;
  width: 36px; height: 36px; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--rand); background: var(--flaeche);
  color: var(--text-leise); font-size: 1rem; line-height: 1;
}
.hilfe-schliessen:hover { background: var(--flaeche-2); color: var(--text); }

/* Fest am unteren Rand des Kastens -- kein sticky mehr nötig, weil der
   Inhalt daneben scrollt und nicht darunter. */
.hilfe-fuss {
  flex-shrink: 0;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 14px 18px;
  padding-bottom: calc(14px + env(safe-area-inset-bottom));
  background: var(--flaeche); border-top: 1px solid var(--rand);
}
@media (min-width: 760px) { .hilfe-fuss { padding: 16px 30px; } }
.hilfe-haken {
  display: flex; align-items: center; gap: 9px; cursor: pointer;
  font-size: .88rem; color: var(--text-leise); user-select: none;
}
.hilfe-haken:hover { color: var(--text); }

/* ------------------------------------------------------- Dateien ablegen */
/* Deckt nur den Inhaltsbereich ab, nicht Navigation und Verlauf: Wer Dateien
   hereinzieht, zielt auf die Seite -- die Navigation dabei zu verdecken
   nimmt ihm die Orientierung und sieht aus, als sei die ganze Anwendung
   blockiert. Die Ränder folgen denselben Variablen wie das Seitenraster. */
.ablage-schleier {
  position: fixed; z-index: var(--z-ablage);
  top: var(--kopf-gesamt); left: 0; right: 0; bottom: 0;
  background: color-mix(in srgb, var(--akzent) 22%, rgba(10, 14, 20, .72));
  backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;
}
@media (min-width: 860px)  { .ablage-schleier { left: var(--nav-breite); } }
@media (min-width: 1240px) { .ablage-schleier { right: var(--strahl-breite); } }
.ablage-hinweis {
  padding: 26px 40px; border-radius: 18px;
  border: 3px dashed rgba(255, 255, 255, .75);
  color: #fff; font-size: 1.2rem; font-weight: 700;
}

.auswahl-leiste {
  position: sticky; bottom: 0; z-index: 20;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 11px 13px; margin-top: 8px;
  background: var(--akzent-weich); border: 1px solid var(--akzent);
  border-radius: var(--radius-klein);
}

/* ------------------------------------------------------------------ Dialog */
.dialog-huelle {
  position: fixed; inset: 0; z-index: var(--z-fenster);
  display: flex; align-items: flex-end; justify-content: center;
  background: rgba(10,14,20,.55); backdrop-filter: blur(3px);
  padding: 0;
}
@media (min-width: 700px) { .dialog-huelle { align-items: center; padding: 24px; } }

/* Kopf und Fuß stehen, nur die Mitte rollt.
 *
 * TEUER GELERNT: Hier scrollte der GANZE Dialog (`overflow-y: auto` am
 * `.dialog`). Bei einem langen Formular stand „Speichern" damit weit
 * unterhalb des Bildschirms -- beim Ideen-Dialog nachgemessen 2077 Pixel
 * hoch, der Knopf bei 2287. Wer das Formular ausfüllt, sieht nie, dass es
 * einen Knopf gibt, und sucht ihn erst, wenn er fertig ist.
 *
 * Deshalb: Der Dialog ist eine Spalte aus drei Teilen. Kopf und Fuß bleiben
 * stehen, der Körper dazwischen rollt. Der Fuß ist damit IMMER sichtbar --
 * vor dem Scrollen, währenddessen und danach. */
.dialog {
  background: var(--flaeche); width: 100%; max-width: 640px;
  max-height: 92vh; overflow: hidden;
  display: flex; flex-direction: column;
  border-radius: 16px 16px 0 0; box-shadow: var(--schatten-hoch);
}
@media (min-width: 700px) { .dialog { border-radius: var(--radius); } }
.dialog.breit { max-width: 900px; }

/* Der Kopf trägt die Markenfarbe -- ein Dialog ohne Kante wirkt wie ein
   Kasten, der zufällig aufgegangen ist. */
.dialog-kopf {
  flex: 0 0 auto;
  display: flex; align-items: flex-start; gap: 12px;
  padding: 16px 18px 14px;
  background: var(--verlauf-kopf);
  border-bottom: 1px solid var(--rand);
  position: relative;
}
.dialog-kopf::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 3px;
  background: var(--verlauf-akzent);
}
.dialog-kopf h2 { margin: 0; flex: 1; }

.dialog-koerper {
  flex: 1 1 auto; overflow-y: auto; padding: 16px 18px;
  overscroll-behavior: contain;
}

.dialog-fuss {
  flex: 0 0 auto;
  display: flex; gap: 8px; justify-content: flex-end; flex-wrap: wrap;
  padding: 12px 18px; padding-bottom: calc(12px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--rand);
  background: var(--flaeche);
  /* Eine feine Kante nach oben, damit man sieht, dass darüber noch etwas
     liegt, wenn der Körper gerollt ist. */
  box-shadow: 0 -6px 12px -8px rgba(20, 14, 8, .22);
}
.dialog-fuss .links { margin-right: auto; }

/* Eingaben, die zur Entscheidung gehören, stehen mit im festen Fuß --
   zusammen mit dem Knopf, den sie beeinflussen. Sie nehmen die ganze
   Breite und drängen die Knöpfe in die Zeile darunter. */
.dialog-fussleiste {
  flex: 1 1 100%;
  padding-bottom: 10px; margin-bottom: 2px;
  border-bottom: 1px solid var(--rand);
}
.dialog-fussleiste .feld-reihe { margin: 0; }
.dialog-fussleiste .feld { margin: 0; }
.dialog-fussleiste .feld > span:first-child { font-size: .78rem; }
.dialog-fussleiste input, .dialog-fussleiste select { padding: 7px 9px; }

/* Der Fortschritt beim PDF-Druck. Steht im Fuß neben den Knöpfen, damit
   niemand rätselt, ob überhaupt etwas passiert. */
.dialog-arbeit {
  flex: 1 1 100%; display: flex; align-items: center; gap: 10px;
  font-size: .84rem; color: var(--text-leise);
}
.arbeit-balken {
  flex: 1; height: 6px; border-radius: 3px; overflow: hidden;
  background: var(--flaeche-3);
}
.arbeit-balken span {
  display: block; height: 100%; width: 38%; border-radius: 3px;
  background: var(--verlauf-akzent);
  animation: arbeit-wandern 1.15s ease-in-out infinite;
}
@keyframes arbeit-wandern {
  0%   { margin-left: -38%; }
  100% { margin-left: 100%; }
}

/* --------------------------------------------------------------- Meldungen */
.meldungen {
  position: fixed; z-index: var(--z-meldung); right: 14px; bottom: 14px;
  bottom: calc(14px + env(safe-area-inset-bottom));
  display: flex; flex-direction: column; gap: 8px;
  max-width: min(94vw, 400px);
}
.meldung {
  padding: 11px 14px; border-radius: var(--radius-klein);
  background: var(--flaeche); border: 1px solid var(--rand);
  border-left: 3px solid var(--akzent);
  box-shadow: var(--schatten-hoch); font-size: .88rem;
  animation: herein .2s ease;
}
.meldung.gut     { border-left-color: var(--gut); }
.meldung.fehler  { border-left-color: var(--schlecht); }
.meldung.warnung { border-left-color: var(--warnung); }
@keyframes herein { from { opacity: 0; transform: translateY(8px); } }

/* ------------------------------------------------------------- Zeitstrahl */
/* Die Listen der alten Seitenleiste (.strahl …) sind mit ihr verschwunden.
   Dort stehen jetzt ausschließlich die Tore. Warnungen, was ansteht und der
   Verlauf haben ihren eigenen Bereich -- jedes dort, wo man ohnehin
   nachsieht. */

/* Ein Kasten für das, was man gelesen haben muss, bevor man klickt --
   nicht kleingedruckt, sondern abgesetzt. Der Streifen links greift das
   Absperrband auf: dasselbe Zeichen wie überall, „hier aufpassen".

   NICHT '.hinweis' nennen: So heißt bereits die Beschriftung unter jedem
   Eingabefeld (App.feld, siehe core.js). Eine Regel dieses Namens hätte
   jedem Hilfetext im ganzen Portal einen Rahmen und ein graues Feld
   verpasst -- gesehen, nicht vermutet. */
.merksatz {
  position: relative;
  margin: 12px 0;
  padding: 12px 14px 12px 18px;
  border: 1px solid var(--rand);
  border-radius: var(--radius-klein);
  background: var(--flaeche-2);
  overflow: hidden;
}
.merksatz::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 6px;
  background: var(--band-orange);
}
.merksatz > p { margin: 0; font-size: .86rem; line-height: 1.5; }
.merksatz > p + p { margin-top: 8px; }
.merksatz.warnung {
  border-color: color-mix(in srgb, var(--warnung) 40%, var(--rand));
  background: var(--warnung-weich);
}
.merksatz.warnung::before { background: var(--band-gelb); }

/* ------------------------------------------------------------- Kleinkram */
.laden { display: flex; align-items: center; gap: 10px; padding: 30px; color: var(--text-leise); }
.laden-klein { padding: 12px 0; color: var(--text-sehr-leise); font-size: .84rem; }
.kreisel {
  width: 15px; height: 15px; border: 2px solid var(--rand-stark);
  border-top-color: var(--akzent); border-radius: 50%;
  animation: drehen .7s linear infinite; display: inline-block;
}
@keyframes drehen { to { transform: rotate(360deg); } }

.leer {
  text-align: center; padding: 40px 20px; color: var(--text-sehr-leise);
  position: relative;
}
.leer .zeichen { font-size: 2.2rem; display: block; margin-bottom: 8px; opacity: .55; }
/* Leere Bereiche bekommen oben ein Stück Absperrband: „hier ist noch
   nichts, hier wird noch gearbeitet". */
.leer::before {
  content: ""; position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  width: min(180px, 60%); height: 5px; border-radius: 3px;
  background: var(--band-gelb); background-size: 28px 28px; opacity: .5;
}

/* ------------------------------------------------------------ Absperrband */
.band {
  height: 8px; border-radius: 4px;
  background: var(--band-gelb); background-size: 28px 28px;
}
.band.schmal { height: 5px; }

/* Ein Hinweis, der etwas blockiert. Das Motiv sitzt links als Kante. */
.sperre {
  position: relative; padding-left: 16px;
  border-radius: var(--radius-klein); overflow: hidden;
}
.sperre::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 8px;
  background: var(--band-gelb); background-size: 22px 22px;
}

.leise { color: var(--text-leise); }
.sehr-leise { color: var(--text-sehr-leise); }
.klein { font-size: .82rem; }
.zahl { font-variant-numeric: tabular-nums; font-family: var(--schrift-zahl); }
.rechts { text-align: right; }
.mittig { text-align: center; }
.wachsen { flex: 1; }
.abstand-oben { margin-top: 16px; }
.nichts-umbrechen { white-space: nowrap; }

.werkzeugleiste {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  margin-bottom: 14px;
}
.werkzeugleiste .suche { flex: 1; min-width: 160px; }

.reiter { display: flex; gap: 2px; border-bottom: 1px solid var(--rand); margin-bottom: 16px;
  overflow-x: auto; scrollbar-width: none; }
.reiter::-webkit-scrollbar { display: none; }
.reiter button {
  border: 0; background: none; cursor: pointer; font-family: inherit;
  padding: 10px 14px; font-size: .88rem; font-weight: 600;
  color: var(--text-leise); border-bottom: 2px solid transparent;
  white-space: nowrap;
}
.reiter button:hover { color: var(--text); }
.reiter button.aktiv { color: var(--akzent); border-bottom-color: var(--akzent); }

table.tabelle { width: 100%; border-collapse: collapse; font-size: .87rem; }
table.tabelle th {
  text-align: left; font-size: .73rem; text-transform: uppercase;
  letter-spacing: .04em; color: var(--text-sehr-leise);
  padding: 7px 9px; border-bottom: 1px solid var(--rand); font-weight: 600;
}
table.tabelle td { padding: 9px; border-bottom: 1px solid var(--rand); }
table.tabelle tr:last-child td { border-bottom: 0; }
table.tabelle tr.klickbar { cursor: pointer; }
table.tabelle tr.klickbar:hover td { background: var(--flaeche-2); }
.tabelle-rahmen { overflow-x: auto; margin: 0 -15px; padding: 0 15px; }

/* Verweise zwischen Objekten */
.verweise { display: flex; flex-wrap: wrap; gap: 6px; }
.verweis {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 9px; border-radius: 999px; font-size: .79rem;
  background: var(--flaeche-2); border: 1px solid var(--rand); color: var(--text);
}
.verweis:hover { border-color: var(--akzent); text-decoration: none; }
.verweis button { border: 0; background: none; cursor: pointer; color: var(--text-sehr-leise);
  padding: 0 0 0 2px; font-size: .9rem; line-height: 1; }
.verweis button:hover { color: var(--schlecht); }

/* --------------------------------------------- Mehrfachauswahl in Medien */
/* Der Haken sitzt auf der Kachel und ist unsichtbar, solange niemand
   auswaehlt. Ihn dauerhaft zu zeigen hiesse, jede Galerie mit Bedienung zu
   ueberziehen, die man fast nie braucht. */
.galerie-haken {
  position: absolute; top: 8px; left: 8px; z-index: 2;
  width: 24px; height: 24px; border-radius: 50%;
  display: none; align-items: center; justify-content: center;
  background: rgba(10, 14, 20, .55); border: 2px solid #fff;
  color: #fff; font-size: .8rem; line-height: 1;
  backdrop-filter: blur(2px);
}
.auswahl-an .galerie-haken { display: flex; }
.auswahl-an .galerie-element { cursor: pointer; }
.auswahl-an .galerie-element.gewaehlt img { filter: brightness(.62); }
.auswahl-an .galerie-element.gewaehlt {
  outline: 3px solid var(--akzent); outline-offset: -3px; border-radius: 8px;
}
.galerie-element.gewaehlt .galerie-haken {
  background: var(--akzent); border-color: #fff;
}

/* Die Leiste klebt oben unter der Kopfzeile: Wer bei Foto 180 auswaehlt,
   soll nicht nach oben rollen muessen, um zu loeschen. */
.medien-auswahl {
  position: sticky; top: var(--kopf-gesamt); z-index: 6;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin: 0 0 12px; padding: 10px 12px;
  border-radius: var(--radius-klein);
  background: var(--akzent-weich); border: 1px solid var(--akzent);
  font-size: .88rem;
}
.medien-auswahl[hidden] { display: none; }

/* ------------------------------------------------- Vorhandenes anhängen */
.anhaengen-chips { display: flex; flex-wrap: wrap; gap: 5px; margin: 10px 0; }
.chip {
  padding: 4px 10px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--rand); background: var(--flaeche);
  color: var(--text-leise); font-size: .78rem; font-family: inherit;
}
.chip:hover { border-color: var(--rand-stark); color: var(--text); }
.chip.aktiv {
  background: var(--akzent-weich); border-color: var(--akzent);
  color: var(--akzent-lesbar); font-weight: 700;
}

/* Feste Höhe, damit das Fenster beim Tippen nicht springt: Zwei Treffer und
   vierzig Treffer sähen sonst wie zwei verschiedene Fenster aus, und der
   Knopf darunter wanderte unter dem Finger weg. */
.anhaengen-liste {
  display: flex; flex-direction: column; gap: 3px;
  height: min(46vh, 340px); overflow-y: auto;
  padding: 4px; border: 1px solid var(--rand);
  border-radius: var(--radius-klein); background: var(--flaeche-2);
}
.anhaengen-treffer {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px 10px; border: 1px solid transparent; cursor: pointer;
  border-radius: var(--radius-klein); background: none;
  color: var(--text); font-family: inherit; font-size: .88rem; text-align: left;
}
.anhaengen-treffer:hover { background: var(--flaeche-3); }
.anhaengen-treffer.gewaehlt {
  background: var(--akzent-weich); border-color: var(--akzent);
}
.anhaengen-zeichen { font-size: 1.05rem; flex-shrink: 0; }
.anhaengen-titel { display: block; font-weight: 600; }
.anhaengen-haken { color: var(--akzent-lesbar); opacity: 0; flex-shrink: 0; }
.anhaengen-treffer.gewaehlt .anhaengen-haken { opacity: 1; }

.anhaengen-korb-rahmen { margin-top: 10px; }
.anhaengen-korb { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 5px; }
.anhaengen-korb .verweis { cursor: pointer; }
.anhaengen-korb .verweis:hover { border-color: var(--schlecht); }

/* Die Einwurf-Fläche. Sie zeigt sich erst, wenn wirklich etwas darüber
   hängt -- ein gestrichelter Rahmen, der immer da ist, sieht nach einem
   unfertigen Formular aus. */
.einwurf-flaeche.bereit {
  outline: 2px dashed var(--akzent); outline-offset: -5px;
  background: var(--akzent-weich);
}
.einwurf-hinweis { margin: 8px 0 0; }
.raum-anhaenge { margin-top: 18px; }
.raum-anhaenge h3 { margin: 0 0 7px; }
.raum-anhaenge .verweise { margin-bottom: 8px; }

/* Netzplan / Abhängigkeiten */
.netz-zeile { display: flex; align-items: stretch; gap: 10px; margin-bottom: 7px; }
.netz-titel { width: 168px; flex-shrink: 0; font-size: .84rem; padding: 5px 0; }
.netz-spur { flex: 1; position: relative; background: var(--flaeche-2);
  border-radius: 5px; min-height: 27px; overflow: hidden; }
.netz-block {
  position: absolute; top: 3px; bottom: 3px; border-radius: 4px;
  display: flex; align-items: center; padding: 0 7px;
  font-size: .72rem; color: #fff; font-weight: 600; overflow: hidden;
  white-space: nowrap; cursor: pointer;
}
.netz-heute { position: absolute; top: 0; bottom: 0; width: 2px; background: var(--schlecht); z-index: 3; }

@media (max-width: 620px) {
  .netz-titel { width: 108px; font-size: .78rem; }
}

/* Druckausgabe: Navigation und Verlauf weg, alles andere fließend */
@media print {
  .kopf, .navigation, .zeitstrahl, .meldungen, .schleier { display: none !important; }
  .rahmen { display: block; }
  .ansicht { padding: 0; }
  .karte { box-shadow: none; break-inside: avoid; }
}

/* --------------------------------------------------- Material im Arbeitspaket
   Eine Liste zum Abhaken, keine Notiz. Auf der Baustelle lautet die Frage
   nicht "haben wir das aufgeschrieben", sondern "ist das Zeug DA". */
.material-zeile {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 2px; border-bottom: 1px solid var(--rand);
}
.material-zeile:last-child { border-bottom: 0; }
.material-zeile.besorgt > div:not(.wachsen) { opacity: .5; }
.material-zeile.besorgt .wachsen > div:first-child {
  text-decoration: line-through; color: var(--text-leise);
}
.material-zeile input[type="checkbox"] { width: 18px; height: 18px; flex: none; }
.material-neu { border-top: 1px dashed var(--rand-stark); border-bottom: 0; }
.material-eingaben { display: flex; gap: 6px; flex-wrap: wrap; }
.material-eingaben input { flex: 1 1 120px; min-width: 0; padding: 6px 8px; }
.material-eingaben input:first-child { flex: 2 1 200px; }
.warnung-text { color: var(--warnung); font-weight: 600; }

/* ------------------------------------------------------------- Skizzenbrett
   Eine freie Fläche zum Zeichnen. Gezeichnet wird in SVG, damit jeder Strich
   später noch anfassbar bleibt -- und damit eine Skizze vom Telefon im PDF
   gestochen scharf ist. */
.skizzen-gitter {
  display: grid; gap: 14px; margin-top: 14px;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
}
.skizze-kachel {
  display: block; text-decoration: none; color: inherit;
  background: var(--flaeche); border: 1px solid var(--rand);
  border-radius: var(--radius); overflow: hidden; box-shadow: var(--schatten);
  transition: transform .12s ease, box-shadow .12s ease;
}
.skizze-kachel:hover { transform: translateY(-2px); box-shadow: var(--schatten-hoch); }
.skizze-vorschau {
  aspect-ratio: 16 / 10; background: #fff; display: flex;
  align-items: center; justify-content: center; overflow: hidden;
  border-bottom: 1px solid var(--rand);
}
.skizze-vorschau svg { width: 100%; height: 100%; }
.skizze-fuss { padding: 9px 11px; }
.skizze-fuss .titel { font-weight: 600; }

.skizze-titel {
  font-weight: 600; font-size: 1.02rem; max-width: 320px;
  border: 1px solid transparent; background: transparent; padding: 5px 8px;
}
.skizze-titel:hover, .skizze-titel:focus {
  border-color: var(--rand); background: var(--flaeche);
}

.skizze-leiste {
  display: flex; flex-wrap: wrap; gap: 14px; align-items: center;
  padding: 9px 11px; margin-bottom: 10px;
  background: var(--flaeche); border: 1px solid var(--rand);
  border-radius: var(--radius-klein);
}
.skizze-gruppe { display: flex; gap: 5px; align-items: center; }
.skizze-farbe {
  width: 26px; height: 26px; border-radius: 50%; cursor: pointer;
  border: 2px solid var(--rand); padding: 0;
}
.skizze-farbe.aktiv { border-color: var(--tiefe); transform: scale(1.15); }

.skizze-brett {
  background: var(--flaeche-2); border: 1px solid var(--rand);
  border-radius: var(--radius); padding: 10px; overflow: auto;
}
.skizze-flaeche {
  width: 100%; max-height: 68vh; background: #fff; display: block;
  border-radius: var(--radius-klein); box-shadow: var(--schatten);
  /* Ohne das rollt das Telefon die Seite, statt zu zeichnen. */
  touch-action: none; cursor: crosshair;
}
.skizze-flaeche .gewaehlt {
  outline: 2px dashed var(--akzent); outline-offset: 3px;
}

/* Eine Skizze, die im Chat auftaucht: gezeigt, nicht beschrieben.
   Ein nackter Pfad sagt niemandem etwas. */
.chat-anhaenge { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }

/* Ein Bild in der Unterhaltung. Grosszuegig, aber nicht bildschirmfuellend:
   Man soll erkennen, was drauf ist, ohne dass eine Nachricht den ganzen
   Verlauf verdraengt. Fuers Genaue gibt es den Klick. */
.chat-bild {
  max-width: min(320px, 100%); max-height: 260px;
  width: auto; height: auto; object-fit: cover;
  border-radius: var(--radius-klein); border: 1px solid var(--rand);
  cursor: zoom-in; display: block;
  transition: border-color .12s ease, transform .12s ease;
}
.chat-bild:hover { border-color: var(--akzent); transform: scale(1.005); }

/* Was mitgeschickt wird, bevor es abgeschickt ist. */
.chat-anhang-leiste {
  flex-shrink: 0; display: flex; flex-wrap: wrap; gap: 8px;
  padding: 10px 14px 0;
}
.chat-anhang-kachel { position: relative; }
.chat-anhang-kachel img {
  width: 74px; height: 74px; object-fit: cover; display: block;
  border-radius: var(--radius-klein); border: 1px solid var(--rand);
}
.chat-anhang-kachel button {
  position: absolute; top: -6px; right: -6px;
  width: 22px; height: 22px; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--rand); background: var(--flaeche);
  color: var(--text-leise); font-size: .72rem; line-height: 1;
  display: flex; align-items: center; justify-content: center;
}
.chat-anhang-kachel button:hover { color: var(--schlecht); border-color: var(--schlecht); }

.chat-bild-knopf {
  flex-shrink: 0; width: 52px; height: 52px; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--rand-stark); background: var(--flaeche-2);
  font-size: 1.25rem; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  transition: border-color .12s ease, background .12s ease;
}
.chat-bild-knopf:hover { border-color: var(--akzent); background: var(--flaeche); }

/* Wer eine Datei ueber den Verlauf zieht, zielt auf den Chat. */
.chat-rahmen.nimmt-an {
  outline: 2px dashed var(--akzent); outline-offset: -6px;
  background: var(--akzent-weich);
}
.skizze-anhang {
  display: flex; align-items: center; gap: 10px; text-decoration: none;
  color: inherit; background: var(--flaeche); border: 1px solid var(--rand);
  border-radius: var(--radius-klein); padding: 6px 12px 6px 6px;
  max-width: 300px; transition: border-color .12s ease;
}
.skizze-anhang:hover { border-color: var(--akzent); }
.skizze-anhang-bild {
  width: 68px; height: 46px; flex: none; overflow: hidden;
  background: #fff; border: 1px solid var(--rand); border-radius: 5px;
}
.skizze-anhang-bild svg { width: 100%; height: 100%; }
.skizze-anhang-text .titel { font-weight: 600; font-size: .86rem; }

/* --------------------------------------------------- Ablauf als Flussdiagramm
   Von oben nach unten: Was oben steht, muss fertig sein, bevor das darunter
   losgehen kann. Die Zeilen sind Stufen, keine Tage -- nur so zeigt JEDER
   Pfeil nach unten, und nur dann liest sich der Plan wie ein Weg. */
.ablauf {
  position: relative; padding: 8px 4px 4px;
  overflow-x: auto; overflow-y: visible;
}
.ablauf-pfeile {
  position: absolute; inset: 0; pointer-events: none; overflow: visible;
  color: var(--rand-stark);
}
.ablauf-pfeil {
  fill: none; stroke: var(--rand-stark); stroke-width: 2;
}
.ablauf-pfeil.wartet {
  stroke: var(--warnung); stroke-dasharray: 6 4; color: var(--warnung);
}

.ablauf-zeile {
  display: flex; flex-wrap: wrap; gap: 14px 18px;
  justify-content: center; margin-bottom: 42px; position: relative; z-index: 1;
}
.ablauf-zeile:last-child { margin-bottom: 6px; }

.ablauf-kachel {
  display: flex; align-items: stretch; gap: 0; padding: 0;
  min-width: 190px; max-width: 260px; text-align: left; cursor: pointer;
  background: var(--flaeche); border: 1px solid var(--rand);
  border-radius: var(--radius-klein); box-shadow: var(--schatten);
  overflow: hidden; transition: transform .1s ease, box-shadow .1s ease;
}
.ablauf-kachel:hover {
  transform: translateY(-2px); box-shadow: var(--schatten-hoch);
}
.ablauf-kachel.fertig { opacity: .62; }
.ablauf-kachel.gesperrt { border-color: var(--warnung); }
.ablauf-streifen { width: 5px; flex: none; }
.ablauf-inhalt { padding: 8px 11px; min-width: 0; }
.ablauf-titel {
  font-weight: 600; font-size: .9rem; line-height: 1.3; word-break: break-word;
}
.ablauf-kachel.fertig .ablauf-titel { text-decoration: line-through; }
.ablauf-unter { font-size: .74rem; color: var(--text-leise); margin-top: 2px; }
.ablauf-zustand { font-size: .72rem; font-weight: 600; margin-top: 3px; }
.ablauf-material { font-size: .72rem; color: var(--text-sehr-leise); margin-top: 2px; }
.ablauf-material.fehlt { color: var(--warnung); font-weight: 600; }

/* Die Trennlinie zwischen Vergangenem und Kommendem. Absperrband, weil es
   im ganzen Portal dasselbe bedeutet: hier ist eine Grenze. */
.ablauf-heute {
  position: relative; z-index: 1; text-align: center; margin: 4px 0 30px;
}
.ablauf-heute::before {
  content: ""; position: absolute; left: 0; right: 0; top: 50%; height: 5px;
  transform: translateY(-50%); background: var(--band-gelb); opacity: .8;
  border-radius: 3px;
}
.ablauf-heute span {
  position: relative; background: var(--grund); padding: 2px 12px;
  font-size: .76rem; font-weight: 700; color: var(--text-leise);
  border-radius: 10px;
}

/* --------------------------------------------------------------- Anleitung
   Die ausführliche Fassung ist ein Lesetext, kein Bedienbildschirm. Sie
   bekommt deshalb eine begrenzte Zeilenbreite und etwas mehr Luft als der
   Rest der Anwendung -- ein Absatz über die volle Breite eines Monitors
   liest sich nicht. */
.anleitung-verzeichnis {
  display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 20px;
}
.anleitung-verzeichnis a {
  font-size: .84rem; padding: 6px 12px; border-radius: 20px;
  background: var(--flaeche-2); border: 1px solid var(--rand);
  color: var(--text-leise); text-decoration: none;
}
.anleitung-verzeichnis a:hover {
  border-color: color-mix(in srgb, var(--akzent) 50%, var(--rand));
  color: var(--text);
}

.anleitung-kapitel { margin-bottom: 20px; scroll-margin-top: 14px; }
.anleitung-kapitel h2 { display: flex; align-items: center; gap: 10px; }
.anleitung-nummer {
  width: 30px; height: 30px; flex-shrink: 0; border-radius: 9px;
  background: var(--verlauf-akzent); color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: .92rem; font-weight: 700;
}
.anleitung-einleitung { max-width: 62ch; color: var(--text-leise); }

/* Die Grafiken haben eine feste Breite in Bildpunkten. Auf dem Telefon
   passen sie nicht -- dort rollt der Kasten seitlich, statt das Bild auf
   Briefmarkengröße zu schrumpfen. */
.anleitung-bild { margin: 18px 0; }
.anleitung-bild-rolle {
  overflow-x: auto; padding: 14px 2px;
  background: var(--flaeche-2); border: 1px solid var(--rand);
  border-radius: var(--radius);
}
.anleitung-bild-rolle svg { display: block; margin: 0 auto; max-width: none; }
.anleitung-bild figcaption { margin-top: 7px; text-align: center; }

.anleitung-schritte {
  counter-reset: schritt; list-style: none; padding: 0;
  margin: 16px 0 0; max-width: 68ch;
}
.anleitung-schritte li {
  counter-increment: schritt; position: relative;
  padding: 0 0 16px 38px; border-left: 2px solid var(--rand);
  margin-left: 12px;
}
.anleitung-schritte li:last-child { border-left-color: transparent; padding-bottom: 0; }
.anleitung-schritte li::before {
  content: counter(schritt);
  position: absolute; left: -13px; top: -2px;
  width: 24px; height: 24px; border-radius: 50%;
  background: var(--flaeche); border: 2px solid var(--akzent);
  color: var(--akzent-lesbar); font-size: .74rem; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.anleitung-schritte li strong { display: block; margin-bottom: 3px; }
.anleitung-schritte li .klein { color: var(--text-leise); }

.anleitung-abschnitt { margin-top: 16px; max-width: 68ch; }
.anleitung-abschnitt h3 { margin: 0 0 4px; font-size: .98rem; }
.anleitung-abschnitt p { margin: 0; color: var(--text-leise); }
.anleitung-abschnitt code {
  background: var(--flaeche-2); border: 1px solid var(--rand);
  border-radius: 4px; padding: 1px 5px; font-size: .85em;
}

/* ------------------------------------------------------------ Besorgungen
   Zwei Spalten: links der Zeitstrahl, rechts die Liste. Auf dem Telefon wird
   daraus untereinander -- und der Zeitstrahl legt sich quer, weil senkrecht
   auf 375 Pixeln Breite die halbe Anzeige für sechs Marken draufginge. */
.besorgung { display: grid; gap: 18px; align-items: start; }
@media (min-width: 900px) {
  .besorgung { grid-template-columns: 210px 1fr; }
}

.besorgung-strahl {
  display: flex; flex-direction: row; gap: 8px;
  overflow-x: auto; padding-bottom: 6px;
}
@media (min-width: 900px) {
  .besorgung-strahl {
    flex-direction: column; gap: 0; overflow: visible;
    position: sticky; top: 14px;
    border-left: 2px solid var(--rand); padding: 4px 0 4px 0;
  }
}

.besorgung-marke {
  display: flex; align-items: center; gap: 9px;
  background: var(--flaeche-2); border: 1px solid var(--rand);
  border-radius: 20px; padding: 6px 13px; cursor: pointer;
  white-space: nowrap; text-align: left; color: var(--text-leise);
  font: inherit; font-size: .82rem;
}
.besorgung-marke:hover {
  border-color: color-mix(in srgb, var(--akzent) 50%, var(--rand));
  color: var(--text);
}
@media (min-width: 900px) {
  .besorgung-marke {
    background: none; border: none; border-radius: 0;
    padding: 9px 0 9px 16px; margin-left: -8px; white-space: normal;
  }
  .besorgung-marke:hover { background: var(--flaeche-2); border-radius: 8px; }
}
.besorgung-marke-text { display: flex; flex-direction: column; line-height: 1.25; }
.besorgung-marke-text .klein { display: none; }
@media (min-width: 900px) { .besorgung-marke-text .klein { display: block; } }

.besorgung-punkt {
  width: 11px; height: 11px; border-radius: 50%; flex-shrink: 0;
  box-shadow: 0 0 0 3px var(--grund);
}

.besorgung-gruppe { margin-bottom: 22px; scroll-margin-top: 12px; }
.besorgung-gruppe-kopf {
  display: flex; align-items: center; gap: 9px;
  font-size: 1rem; margin: 0 0 9px;
}

.besorgung-zeile {
  display: flex; align-items: flex-start; gap: 12px;
  background: var(--flaeche); border: 1px solid var(--rand);
  border-radius: var(--radius); padding: 11px 13px; margin-bottom: 8px;
}
/* Abgehaktes bleibt lesbar, tritt aber zurück. Durchgestrichen wird NICHT:
   Wer nachsehen will, was er gekauft hat, will es lesen können. */
.besorgung-zeile.erledigt { opacity: .55; }
.besorgung-haken { display: flex; align-items: center; padding-top: 2px; }
.besorgung-haken input { width: 20px; height: 20px; cursor: pointer; }

.besorgung-titel { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.besorgung-unter {
  display: flex; align-items: center; gap: 2px; flex-wrap: wrap;
  margin-top: 2px; font-size: .8rem; color: var(--text-leise);
}
.besorgung-paket {
  font-size: .8rem; padding: 0; color: var(--akzent-lesbar);
  text-decoration: underline; text-underline-offset: 2px;
}

.besorgung-rechts {
  display: flex; flex-direction: column; align-items: flex-end; gap: 5px;
  flex-shrink: 0; text-align: right;
}
.besorgung-frist {
  font-size: .8rem; font-weight: 600; color: var(--text-leise);
  font-variant-numeric: tabular-nums;
}
#gruppe-faellig .besorgung-frist { color: var(--schlecht); }
#gruppe-woche  .besorgung-frist { color: var(--warnung); }

/* ---------------------------------------------------------- Klappabschnitt
   Zum Freimachen des ersten Blicks -- nicht zum Verstecken. Der Kopf sieht
   deshalb wie ein Knopf aus und nicht wie eine Überschrift: Er soll zum
   Anklicken auffordern, nicht übersehen werden. */
.klappe {
  border: 1px solid var(--rand); border-radius: var(--radius);
  margin-top: 14px; background: var(--flaeche-2);
}
.klappe-kopf {
  /* Mindestens 44 Pixel hoch: Das ist die Fläche, die ein Daumen sicher
     trifft. Ein Klappkopf, den man dreimal antippen muss, ist schlimmer als
     gar keiner. */
  cursor: pointer; padding: 13px 14px; min-height: 44px; box-sizing: border-box;
  font-weight: 600; font-size: .92rem;
  list-style: none; display: flex; align-items: center; gap: 8px;
  color: var(--text-leise); user-select: none;
}
.klappe-kopf::-webkit-details-marker { display: none; }
.klappe-kopf::before {
  content: "›"; display: inline-block; font-size: 1.15rem; line-height: 1;
  transition: transform .15s ease; color: var(--akzent-lesbar);
}
.klappe[open] > .klappe-kopf::before { transform: rotate(90deg); }
.klappe-kopf:hover { color: var(--text); }
.klappe[open] > .klappe-kopf {
  border-bottom: 1px solid var(--rand); color: var(--text);
}
.klappe-koerper { padding: 4px 14px 14px; }
.klappe-koerper > h3:first-child { margin-top: 10px; }

/* Die Bauakte als aufklappbare Gruppen. Der Kopf behält das Aussehen einer
   Kartenüberschrift -- nur der Pfeil davor verrät, dass man ihn anklicken
   kann. Ein Formularkasten, der wie ein Knopf aussieht, wäre schlimmer. */
.bauakte-gruppe > .bauakte-kopf {
  cursor: pointer; list-style: none; user-select: none;
  margin: -2px 0 0; align-items: center;
}
.bauakte-kopf::-webkit-details-marker { display: none; }
.bauakte-kopf::before {
  content: "›"; font-size: 1.3rem; line-height: 1; margin-right: 9px;
  color: var(--akzent-lesbar); transition: transform .15s ease;
  display: inline-block; flex-shrink: 0;
}
.bauakte-gruppe[open] > .bauakte-kopf::before { transform: rotate(90deg); }
.bauakte-gruppe[open] > .bauakte-kopf { margin-bottom: 12px; }
.bauakte-gruppe:not([open]):hover { border-color: color-mix(in srgb, var(--akzent) 40%, var(--rand)); }

/* Eine Tageszelle im Kalender ist anklickbar -- das muss man sehen können,
   sonst sucht man wieder oben nach dem Knopf.

   Aussehen und Masse stehen hier und nicht mehr im JavaScript: Auf dem
   Telefon braucht dieselbe Zelle andere Werte, und eine Abfrage der
   Bildschirmbreite in JavaScript wüsste nichts davon, wenn jemand das Gerät
   dreht. */
.kalender-tag {
  min-height: 62px; padding: 3px 4px; border-radius: 6px;
  border: 1px solid transparent; background: var(--flaeche-2);
  cursor: pointer; transition: background .12s ease;
  min-width: 0;                      /* sonst drueckt der Inhalt die Spalte auf */
}
.kalender-tag:hover {
  background: color-mix(in srgb, var(--akzent) 12%, var(--flaeche-2));
}
.kalender-tag.heute { background: var(--akzent-weich); border-color: var(--akzent); }
.kalender-tag.fremd { opacity: .38; }

.kalender-termin {
  color: #fff; font-size: .67rem; padding: 1px 4px;
  border-radius: 3px; margin-top: 2px; cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Auf dem Telefon ist eine Spalte rund vierzig Pixel breit. Ein Titel passt
   dort nicht mehr hinein -- und abgeschnitten nach zwei Buchstaben ist er
   keine Auskunft, sondern nur ein farbiger Streifen mit Buchstabensalat.
   Also gleich ein sauberer Streifen: Man sieht, DASS an dem Tag etwas ist
   und in welcher Farbe. Was genau, steht darunter unter „Was ansteht" --
   vollständig und lesbar. */
@media (max-width: 560px) {
  .kalender-tag { min-height: 46px; padding: 2px; }
  .kalender-termin {
    height: 5px; padding: 0; margin-top: 3px; border-radius: 999px;
    font-size: 0;                    /* der Titel bleibt fuer Vorlesegeraete */
    text-indent: -9999px;
  }
  .monatsgitter { gap: 2px; }
}

/* Sanft rollen ist Zierde, nicht Aufgabe.
   TEUER GELERNT, zum zweiten Mal in derselben Woche -- beim ersten Mal waren
   es die Pfeile im Ablaufdiagramm: Was von einer Animation abhängt, läuft
   nicht immer. `scrollIntoView({behavior:"smooth"})` braucht laufende
   Bildwechsel; gibt es die gerade nicht, passiert GAR NICHTS, und ein Klick
   im Inhaltsverzeichnis führt ins Leere. Gemessen: smooth 0 Pixel, ohne
   Animation 4791.
   Deshalb springt das JavaScript nur noch, und das Rollen steht hier. Fällt es
   aus, springt die Seite -- das merkt niemand. */
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* ------------------------------------------------------------- Balkenplan
   Ein Raster: erste Spalte die Namen, der Rest die Zeit. Die Spalten sind
   nur Hintergrund -- gesetzt werden die Balken in Prozent über die ganze
   Breite, damit ein Termin auf seinem Tag sitzt und nicht am Wochenrand. */
.gantt-rolle { overflow-x: auto; padding-bottom: 4px; }
.gantt {
  display: grid; position: relative; font-size: .78rem;
  min-width: 620px;                 /* darunter wird jede Spalte ein Strich */
}
.gantt-kopf {
  grid-column: 1; padding: 5px 8px 5px 0; color: var(--text-leise);
  border-bottom: 1px solid var(--rand); font-weight: 600;
}
.gantt-spalte {
  padding: 5px 0; text-align: center; font-size: .68rem; color: var(--text-sehr-leise);
  border-bottom: 1px solid var(--rand); border-left: 1px dashed var(--rand);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.gantt-name {
  grid-column: 1; padding: 7px 8px 7px 0; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; display: flex; align-items: center;
  gap: 6px; border-bottom: 1px solid var(--flaeche-2);
}
.gantt-name.unter { padding-left: 14px; color: var(--text-leise); font-size: .74rem; }
.gantt-punkt { width: 9px; height: 9px; border-radius: 2px; flex-shrink: 0; }

.gantt-zeile {
  grid-column: 2 / -1; position: relative; height: 32px;
  border-bottom: 1px solid var(--flaeche-2);
  background: repeating-linear-gradient(90deg,
    transparent 0 calc(100% / var(--spalten, 12) - 1px),
    var(--flaeche-2) calc(100% / var(--spalten, 12) - 1px) calc(100% / var(--spalten, 12)));
}
.gantt-zeile.unter { height: 26px; }

.gantt-balken {
  position: absolute; top: 6px; height: 20px; border-radius: 5px;
  color: #fff; font-size: .7rem; line-height: 20px; padding: 0 7px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  border: none; font-family: inherit; text-align: left;
}
.gantt-balken.unter {
  top: 8px; height: 11px; border-radius: 3px; padding: 0; cursor: pointer;
  opacity: .82;
}
.gantt-balken.unter:hover { opacity: 1; box-shadow: 0 0 0 2px var(--akzent); }

/* Meilensteine als Raute -- ein Punkt in der Zeit hat keine Länge. */
.gantt-raute {
  position: absolute; top: 7px; width: 12px; height: 12px; margin-left: -6px;
  background: var(--warnung); transform: rotate(45deg); border-radius: 2px;
}
.gantt-raute-legende {
  width: 10px !important; height: 10px !important; background: var(--warnung);
  transform: rotate(45deg); border-radius: 2px !important;
}

.gantt-heute {
  position: absolute; top: 0; bottom: 0; width: 2px;
  background: var(--warnung); z-index: 2; pointer-events: none;
}
.gantt-heute::before {
  content: "heute"; position: absolute; top: -1px; left: 4px;
  font-size: .62rem; font-weight: 700; color: var(--warnung);
  background: var(--flaeche); padding: 0 3px; border-radius: 3px;
}

/* ------------------------------------------------------------------- Tore
   Senkrecht in der Seitenleiste: schmale Schiene links, Phasen und
   Torkarten rechts. Der Blick soll auf dem nächsten offenen Tor landen --
   deshalb hat genau das einen Rahmen und einen Schein, und sonst nichts. */
.tore { display: grid; grid-template-columns: 20px 1fr; column-gap: 12px; }

.tore-schiene { display: flex; justify-content: center; }
.tore-strich {
  display: block; width: 7px; border-radius: 4px; height: 100%;
  background: var(--rand-stark);
}
.tore-strich.fertig { background: var(--gut); }
.tore-strich.laeuft { background: linear-gradient(180deg, var(--akzent) 55%, var(--rand) 55%); }

.tore-phase {
  padding: 7px 0; min-height: 54px;
  display: flex; flex-direction: column; justify-content: center;
}
.tore-phase b { font-size: .88rem; }
.tore-phase small { font-size: .72rem; color: var(--text-leise); }
.tore-phase.spaeter b { color: var(--text-leise); }

.tore-knoten {
  display: flex; justify-content: center; align-items: center; position: relative;
}
.tore-knoten::before {
  content: ""; position: absolute; top: 0; bottom: 0; width: 7px;
  background: var(--rand-stark); border-radius: 4px;
}
.tore-knoten.fertig::before { background: var(--gut); }
.tore-knoten em {
  position: relative; z-index: 1; width: 20px; height: 20px; border-radius: 50%;
  background: var(--flaeche); border: 2px solid var(--rand-stark);
  display: flex; align-items: center; justify-content: center;
  font-style: normal; font-size: .58rem; font-weight: 700; color: var(--text-leise);
}
.tore-knoten.fertig em { background: var(--gut); border-color: var(--gut); color: #fff; }
.tore-knoten.naechstes em {
  border-color: var(--akzent); color: var(--akzent-lesbar);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--akzent) 22%, transparent);
}

.tore-karte {
  margin: 5px 0 9px; padding: 8px 11px;
  border: 1px solid var(--rand); border-radius: 8px; background: var(--flaeche);
}
.tore-karte.fertig { border-color: color-mix(in srgb, var(--gut) 55%, var(--rand)); }
.tore-karte.naechstes {
  border-color: var(--akzent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--akzent) 18%, transparent);
}
.tore-karte h4 {
  margin: 0; font-size: .78rem; display: flex; gap: 8px;
  justify-content: space-between; align-items: baseline;
}
.tore-karte.naechstes h4 { color: var(--akzent-lesbar); }
.tore-karte h4 .klein { color: var(--text-sehr-leise); font-weight: 400; white-space: nowrap; }

.tore-kriterien { list-style: none; padding: 0; margin: 6px 0 0; font-size: .76rem; }
.tore-kriterien li {
  display: flex; gap: 7px; align-items: flex-start; padding: 2px 0;
  color: var(--text);
}
.tore-kriterien li::before {
  content: ""; width: 12px; height: 12px; margin-top: 2px; flex: none;
  border: 1.5px solid var(--rand-stark); border-radius: 3px;
}
/* Eine Vorbedingung ist keine Arbeit -- man kann sie nicht abarbeiten,
   sondern nur warten, bis sie eintritt. Das Absperrband sagt das überall
   im Portal, also auch hier. */
.tore-kriterien li.bedingung::before {
  border-color: var(--warnung);
  background: var(--band-orange); background-size: 8px 8px;
}
.tore-kriterien li.ok { color: var(--text-leise); }
.tore-kriterien li.ok::before {
  background: var(--gut); border-color: var(--gut);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 6.5l2.5 2.5 4.5-5' fill='none' stroke='white' stroke-width='1.8'/%3E%3C/svg%3E");
}
.tore-stand {
  margin-top: 7px; font-size: .72rem; font-weight: 600; color: var(--akzent-lesbar);
}
.tore-karte.fertig .tore-stand { color: var(--gut); }

/* Das letzte Tor führt nicht in den nächsten Abschnitt, sondern ans Ende.
   Es bekommt einen Haken statt einer Nummer -- dahinter kommt nichts mehr. */
.tore-knoten.ende::before { display: none; }
.tore-knoten.ende em { font-size: .7rem; }

/* Fehlendes Material ist keine Bedingung und keine Arbeit, sondern ein
   Einkauf. Eigenes Zeichen, damit man auf einen Blick sieht, ob man warten
   oder losfahren muss. */
.tore-kriterien li.material::before {
  border-color: var(--holz); border-style: dashed;
}

/* Der Verlauf auf der Übersicht: zehn Zeilen, die man überfliegt. Ein
   Farbstreifen und volle Zeilenhöhe wie bei anklickbaren Einträgen wären hier
   ein Versprechen, das nichts einlöst -- diese Zeilen führen nirgendwohin. */
.listen-eintrag.schmal { padding: 6px 10px; cursor: default; }
.listen-eintrag.schmal:hover { background: none; border-color: var(--rand); }
.listen-eintrag.schmal .titel { font-size: .85rem; font-weight: 500; }

/* Der Umschalter über den Toren: herausgezoomt oder hereingezoomt. Zwei
   Knöpfe nebeneinander, schmal genug für die Seitenleiste. */
.tore-sicht { margin-bottom: 12px; }
.tore-sicht button { flex: 1; font-size: .78rem; padding: 6px 4px; }

/* ------------------------------------------------------------- Landeseite
   Das Einzige, was ein Fremder je zu sehen bekommt. Deshalb Logo, ein Satz,
   ein Knopf -- und sonst nichts, was verrät, was es hier zu holen gäbe. */
/* Die ganze Kopfzeile bleibt weg -- nicht nur ihr Inhalt.
   Übrig blieben sonst der Schriftzug und der Hell-Dunkel-Schalter über einer
   leeren Fläche: eine Leiste, die aussieht wie eine Anwendung, in der nichts
   geladen hat. Eine Landeseite hat keine Kopfzeile, sie IST eine. */
body.abgemeldet .kopf { display: none !important; }
body.abgemeldet .navigation,
body.abgemeldet .zeitstrahl,
body.abgemeldet #schleier { display: none !important; }
body.abgemeldet .rahmen { grid-template-columns: 1fr; }
body.abgemeldet .ansicht { padding-top: 0; }

/* ------------------------------------------------------- Vor der Antwort
   TEUER GELERNT: Bis /api/me geantwortet hatte, stand das volle Gerüst da --
   Kopfzeile, Menü mit allen Punkten, Seitenleiste -- und klappte danach zur
   Anmeldeseite zusammen. Das sah aus, als sei man drin gewesen und wieder
   hinausgeworfen worden.

   Daten waren nie zu sehen: Jeder Endpunkt antwortet ohne Sitzung mit 401,
   das Gerüst steht leer in der index.html. Zu sehen war das MENÜ -- die
   Namen der Bereiche. Trotzdem gehört das weg, und zwar hier in der CSS und
   nicht im JavaScript: So ist die Fläche schon vor dem ersten Bild leer und
   nicht erst, wenn ein Skript gelaufen ist.

   `visibility` statt `display`, damit die Anwendung beim Sichtbarwerden
   nicht springt: Der Platz ist schon eingenommen, er ist nur noch leer. */
body.pruefend .kopf,
body.pruefend .rahmen { visibility: hidden; }

.anmeldeseite {
  min-height: 62vh; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 18px;
  text-align: center; padding: 24px 16px 48px;
}
/* Originalgröße heißt Originalgröße. Begrenzt wird nur nach unten: Auf
   einem 375 Pixel breiten Telefon muss auch ein 710 Pixel breites Logo
   hineinpassen, sonst schiebt es die Seite seitlich weg. */
.anmelde-logo {
  max-width: 100%; height: auto;
  filter: drop-shadow(0 8px 30px color-mix(in srgb, var(--akzent) 28%, transparent));
}
.anmelde-schriftzug { font-size: 2.6rem; letter-spacing: -.02em; }
.anmelde-schriftzug strong { color: var(--akzent-lesbar); }

.anmelde-satz { color: var(--text-leise); max-width: 34ch; margin: 0; }

.anmelde-knopf {
  display: inline-flex; align-items: center; gap: 10px;
  font-size: 1rem; padding: 12px 22px; min-height: 48px;
}
.anmelde-g {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%;
  background: #fff; color: #4285f4; font-weight: 700; font-size: .95rem;
}

.anmelde-fehler {
  max-width: 46ch; padding: 11px 15px; border-radius: var(--radius);
  border: 1px solid var(--warnung); background: var(--flaeche-2);
  font-size: .86rem; color: var(--text); text-align: left;
}
