:root {
  --green: #1b4332;
  --green-light: #2d6a4f;
  --accent: #e0532f;
  --bg: #f4f6f4;
  --text: #1c1c1c;
  --muted: #5f6b63;
  --border: #d5ddd7;
  --error: #b42318;
  /* Farbe hat Bedeutung (Spec Abschnitt 4): Grau = Entwurf, Gelb = wartet, Grün = online,
     Rot = gesperrt. Die Ampel im Kopf der Visitenkarte benutzt genau diese vier. */
  --grau: #9aa79f;
  --gelb: #d8b657;
  --gruen: var(--green-light);
  /* Standort: zwei Farben, eine Bedeutung. Der helle Ton traegt Rahmen und Blockgrund,
     der kraeftige das Abzeichen - ein weisses Symbol braucht dunklen Grund, sonst ist es
     auf dem Handy in der Sonne nicht zu sehen. Ein dritter Zustand kommt nicht dazu:
     wartende Aufnahmen bleiben gelb (Gestaltungsregeln, Spec 4). */
  --ort-ja: #bcdcc8;
  --ort-nein: #edc9c9;
  --ort-ja-kraeftig: #2d6a4f;
  --ort-nein-kraeftig: #b42318;
  --rot: var(--error);
}
* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { margin: 0; background: var(--bg); color: var(--text); font: 18px/1.45 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; }
/* Randlos heisst: die Seite reicht unter die Systemleisten. Die Einfassungen halten
   Inhalt davor - unten die Navigationsleiste, seitlich die Aussparungen im Querformat. */
/* Grundwert zuerst, die Einfassungen erst im @supports: kennt ein WebView env() nicht,
   ist das ganze calc() ungueltig und die Deklaration faellt weg - dann verloere #app auch
   seine seitlichen 20 px und .top seine 28 px oben. minSdk ist 21. */
#app { max-width: 540px; margin: 0 auto; padding: 0 20px 48px; }
.top { padding: 28px 0 20px; border-bottom: 1px solid var(--border); margin-bottom: 20px; }
@supports (padding: env(safe-area-inset-bottom)) {
  #app {
    padding: 0 calc(20px + env(safe-area-inset-right)) calc(48px + env(safe-area-inset-bottom))
             calc(20px + env(safe-area-inset-left));
  }
  .top { padding: calc(28px + env(safe-area-inset-top)) 0 20px; }
}
.eyebrow { margin: 0; text-transform: uppercase; letter-spacing: .12em; font-size: 12px; color: var(--muted); }
h1 { margin: 4px 0 0; font-size: 28px; line-height: 1.15; color: var(--green); }
h2 { font-size: 18px; margin: 28px 0 12px; }
.step { margin: 0 0 16px; color: var(--muted); font-size: 14px; }
label { display: block; font-weight: 600; margin-bottom: 8px; }
input[type="text"], input[type="tel"], input[type="date"] {
  width: 100%; font: inherit; padding: 14px; border: 1px solid var(--border); border-radius: 10px; background: #fff;
}
/* Das Textfeld war das einzige Eingabefeld ohne Breite - es stand schmal in der Spalte. */
textarea {
  width: 100%; font: inherit; padding: 14px; border: 1px solid var(--border); border-radius: 10px;
  background: #fff; color: var(--text); resize: vertical;
}
input:focus, textarea:focus { outline: 3px solid rgba(45, 106, 79, .35); border-color: var(--green-light); }
/* Sprachwahl als Knopfgruppe: gruen heisst „in dieser Sprache steht schon ein Text". */
.lang-knoepfe { display: flex; gap: 8px; margin-bottom: 10px; }
.lang-knopf {
  flex: 1; min-height: 44px; font: inherit; font-weight: 600; font-size: 15px; padding: 10px 12px;
  border-radius: 10px; border: 2px solid var(--border); background: #fff; color: var(--muted); cursor: pointer;
}
.lang-knopf[aria-pressed="true"] { border-color: var(--green); color: var(--green); }
.lang-knopf.gefuellt { background: #f1f7f2; }
/* Kompakter Knopf in Zeilen und Karten - dieselbe Trefferflaeche, weniger Platz. */
.klein-knopf {
  min-height: 44px; font: inherit; font-weight: 600; font-size: 15px; padding: 10px 14px;
  border-radius: 10px; cursor: pointer;
}
.big { display: block; width: 100%; padding: 16px; border-radius: 12px; font: inherit; font-weight: 600; text-align: center; margin-top: 16px; cursor: pointer; }
.primary { background: var(--green); color: #fff; border: 0; }
a.big { text-decoration: none; }
.secondary { background: #fff; color: var(--green); border: 2px solid var(--green); }
.link { background: none; border: 0; color: var(--green-light); font: inherit; text-decoration: underline; padding: 8px 0; cursor: pointer; }
/* Alles, was man antippt, sieht auch danach aus: .knopf ersetzt die unterstrichenen
   Textlinks im Inneren der App. Rot heisst loeschen oder entfernen - ausnahmslos. */
.knopf {
  min-height: 44px; font: inherit; font-weight: 600; font-size: 15px; padding: 10px 14px;
  border-radius: 10px; border: 2px solid var(--border); background: #fff; color: var(--green);
  cursor: pointer;
}
.knopf.rot { border-color: var(--error); color: var(--error); }
.knopf.breit { display: block; width: 100%; margin-bottom: 10px; text-align: center; }
/* Runder Profilknopf oben rechts. */
.ikon.rund { border-radius: 999px; }
/* Solange die Nummer fehlt, ist das der Hauptknopf: gross, gruen, mit dem WhatsApp-Zeichen. */
.wa-knopf { display: flex; align-items: center; justify-content: center; gap: 10px; margin-bottom: 16px; }
#profil .identity { justify-content: flex-start; margin-bottom: 14px; font-size: 16px; }
#profil label { margin-top: 14px; }
#profil .lang-switch { margin-bottom: 6px; }
/* ---------- Kundenstimmen ---------- */
/* In der Liste steht nur der Satz mit Name und Ort; geschrieben wird im Blatt. */
.zitate { display: flex; flex-direction: column; gap: 10px; margin-bottom: 10px; }
.zitat { background: #fff; border: 1px solid var(--border); border-radius: 12px; padding: 12px 14px;
         display: flex; align-items: flex-start; gap: 10px; }
.zitat-schau { flex: 1; min-width: 0; }
.zitat-satz { margin: 0 0 2px; font-size: 16px; overflow-wrap: anywhere; }
.zitat-wer { margin: 0; color: var(--muted); font-size: 14px; }
.zitat .fassungen { flex-basis: 100%; }
/* Foto im Blatt der Kundenstimme: Kachel, Hinweis, rotes Entfernen. */
.zitat-bildzeile { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.zitat-bildzeile .wp-neu { flex: none; width: 72px; height: 72px; aspect-ratio: auto;
                           background-size: cover; background-position: center; }
.zitat-bildzeile .wp-neu.hat-bild { border-style: solid; border-color: var(--green); color: transparent; }
.zitat-bildzeile .hint { flex: 1; min-width: 0; margin: 0; }
/* Name und Hauptbild nebeneinander: das Bild klein, mit Stift-Ecke, zum Antippen. */
.name-zeile { display: flex; align-items: flex-end; gap: 12px; }
.name-feld { flex: 1; min-width: 0; }
.wp-avatar { flex: none; width: 72px; height: 72px; border-radius: 12px; border: 2px solid var(--green);
             background: #e6ebe7; padding: 0; position: relative; overflow: hidden; cursor: pointer; }
.wp-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.wp-avatar-stift { position: absolute; right: 0; bottom: 0; width: 26px; height: 26px;
                   background: var(--green); color: #fff; display: flex; align-items: center;
                   justify-content: center; border-radius: 10px 0 0 0; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); border: 0; }
.error { color: var(--error); margin: 8px 0 0; font-size: 15px; }
.banner { position: fixed; left: 12px; right: 12px; bottom: calc(12px + env(safe-area-inset-bottom)); background: #fff; border: 1px solid var(--error); border-radius: 10px; padding: 12px 14px; box-shadow: 0 6px 20px rgba(0,0,0,.12); }
.banner.ok { border-color: var(--green-light); color: var(--green); }
.muted { color: var(--muted); }
.identity { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin: 0 0 8px; font-size: 15px; color: var(--muted); }
.identity-actions { display: flex; gap: 14px; flex: none; }
.identity-confirm { margin: -2px 0 10px; }

.uploads { list-style: none; margin: 16px 0 0; padding: 0; }
.uploads li { background: #fff; border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; margin-bottom: 8px; font-size: 14px; }
.uploads .row { display: flex; justify-content: space-between; gap: 8px; }
.uploads .name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.uploads progress { width: 100%; height: 6px; margin-top: 6px; accent-color: var(--green-light); }
.uploads .failed { color: var(--error); }
.uploads .retry { margin-left: 8px; }

/* Die Sprachnamen stehen ausgeschrieben; auf schmalen Geräten darf die Zeile umbrechen. */
.top-row { display: flex; justify-content: space-between; align-items: center; gap: 8px; flex-wrap: wrap; }
.lang-switch { display: flex; gap: 4px; flex-wrap: wrap; justify-content: flex-end; }
.lang-switch .lang { font: inherit; font-size: 12px; font-weight: 600; padding: 4px 10px; border-radius: 999px; border: 1px solid var(--border); background: #fff; color: var(--muted); cursor: pointer; white-space: nowrap; }
/* Schmales Gerät: die Namen passen nicht mehr neben die Kopfzeile. Dann bekommt der
   Umschalter eine eigene Zeile und verteilt sich darin, statt rechts zu kleben. */
@media (max-width: 460px) {
  .lang-switch { width: 100%; justify-content: space-between; }
}
.lang-switch .lang[aria-pressed="true"] { background: var(--green); border-color: var(--green); color: #fff; }
/* Vor der Anmeldung ist der Umschalter ausgerechnet fuer den da, der die App nicht liest
   und sie umstellen muss, BEVOR er seinen Namen tippt: dort gilt die 44-px-Regel. */
#lang-anmeldung .lang { min-height: 44px; padding: 8px 14px; font-size: 14px; }

.picker { position: fixed; inset: 0; background: var(--bg); z-index: 1000; display: flex; flex-direction: column; }
/* Ortssuche ueber der Karte. */
.picker-suche { display: flex; gap: 8px; margin-bottom: 8px; }
.picker-suche input { flex: 1; min-width: 0; }
.picker-treffer { list-style: none; margin: 0 0 8px; padding: 0; max-height: 34vh; overflow-y: auto;
                  border: 1px solid var(--border); border-radius: 10px; background: #fff; }
.picker-treffer li + li { border-top: 1px solid var(--border); }
.picker-treffer button { display: block; width: 100%; text-align: left; font: inherit; font-size: 15px;
                         min-height: 44px; padding: 10px 12px; border: 0; background: none;
                         color: var(--text); cursor: pointer; }
.picker-bar { padding: 12px 16px; font-size: 14px; background: #fff; border-bottom: 1px solid var(--border); }
#picker-map { flex: 1; min-height: 200px; }
.picker-actions { display: flex; gap: 12px; padding: 12px 16px calc(12px + env(safe-area-inset-bottom)); background: #fff; border-top: 1px solid var(--border); }
.picker-actions .big { margin-top: 0; }
.picker .error { padding: 0 16px; }
.danger { color: var(--error); }
.confirm { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; font-size: 15px; }

/* Geöffneter Stapel: gestrichelter Rahmen um das Raster seiner Fotos. */
.stack-open { background: none; border: 2px dashed var(--green-light); border-radius: 12px; padding: 8px; overflow: visible; }
.stack-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; font-size: 13px; color: var(--muted); padding: 0 2px 8px; }
/* „Mach ein Projekt daraus" sitzt zwischen der Zahl und dem Schliessen-Kreuz. */
.stack-zu-projekt { margin-left: auto; border: 2px solid var(--green); background: #fff; color: var(--green); }
.stack-x { background: none; border: 0; font: inherit; font-size: 22px; line-height: 1; color: var(--muted); padding: 0 4px; cursor: pointer; }
/* Dreier-Raster wie die Hauptliste (.liste), nur enger: der Rahmen nimmt schon Platz weg. */
.liste.stack-grid { gap: 8px; } /* schlaegt .liste (12px): der Rahmen nimmt schon Platz weg */

/* Ziehen: angehobene Kachel, Klon am Zeiger, markiertes Ziel. Der Klon hängt in .drag-host;
   der Wirt selbst ist kein Raster und fängt keine Klicks. Die Regeln der Kachel (.kachel,
   .karte) hängen an keinem Elternteil und greifen im Klon von selbst. */
.dragging { opacity: .35; }
.drag-host { position: fixed; inset: 0; display: block; z-index: 1200; pointer-events: none; }
.drag-clone { border-radius: 12px; box-shadow: 0 10px 26px rgba(0, 0, 0, .3); opacity: .92; }
.drop-target { outline: 3px solid var(--accent); outline-offset: 2px; border-radius: 12px; }

/* Info-Modal (der Standort-Picker liegt mit z-index 1000 darüber). */
.modal { position: fixed; inset: 0; z-index: 900; background: rgba(28, 28, 28, .45); display: flex; align-items: flex-end; justify-content: center; padding: 12px; }
.modal-card {
  position: relative; width: 100%; max-width: 420px; max-height: 88vh; overflow-y: auto; background: #fff;
  border-radius: 16px; padding: 16px 16px calc(16px + env(safe-area-inset-bottom)); box-shadow: 0 -6px 30px rgba(0, 0, 0, .25);
}
.modal-card h2 { margin: 0 30px 12px 0; font-size: 18px; }
.modal-x { position: absolute; top: 8px; right: 10px; background: none; border: 0; font: inherit; font-size: 26px; line-height: 1; color: var(--muted); padding: 4px 8px; cursor: pointer; }
.modal-thumb { width: 100%; aspect-ratio: 4 / 3; background: #e6ebe7; border-radius: 10px; overflow: hidden; margin-bottom: 12px; }
.modal-thumb img { width: 100%; height: 100%; object-fit: contain; display: block; }
.modal-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin-bottom: 10px; }
.modal-row input { flex: 1 1 160px; }
.modal-row .secondary { padding: 10px 16px; border-radius: 10px; cursor: pointer; }
.modal-loc { justify-content: space-between; font-size: 14px; color: var(--muted); }
/* Standort im Detail-Modal (14.9.2026): ein farbiger Kasten statt einer grauen Zeile -
   „No location" stand vorher so klein da wie alles andere. Heller Grund in der Farbe des
   Rahmens, Symbol links, darunter die Quelle bzw. der Satz, was ohne Standort fehlt. */
.loc-block {
  display: flex; align-items: center; gap: 10px; margin-bottom: 10px;
  padding: 12px; border-radius: 12px; border: 1px solid transparent;
}
.loc-block-ja { background: var(--ort-ja); border-color: var(--ort-ja-kraeftig); }
.loc-block-nein { background: var(--ort-nein); border-color: var(--ort-nein-kraeftig); }
.loc-block-ikon {
  flex: 0 0 auto; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center;
  border-radius: 999px; color: #fff;
}
.loc-block-ja .loc-block-ikon { background: var(--ort-ja-kraeftig); }
.loc-block-nein .loc-block-ikon { background: var(--ort-nein-kraeftig); }
.loc-block-ikon svg { width: 20px; height: 20px; }
.loc-block-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.loc-block-wort { font-weight: 600; font-size: 16px; color: var(--text); }
.loc-block-hinweis { font-size: 14px; color: var(--text); }
/* Der Knopf darunter geht ueber die volle Breite: ohne Standort ist er der Hauptknopf
   dieses Fensters, mit Standort derselbe Knopf in weiss (modal.js setzt die Klasse). */
.modal-loc .primary, .modal-loc .knopf { flex: 1 1 100%; min-height: 52px; border-radius: 12px; font-weight: 600; cursor: pointer; }
.modal-loc .primary { border: 0; }
.modal-actions { justify-content: flex-end; margin-bottom: 0; }
.hint { margin: 0 0 10px; font-size: 13px; color: var(--green-light); }
@media (min-width: 560px) { .modal { align-items: center; } }

/* Galerie: kein dritter Knopf, sondern ein Textlink in voller Breite unter den zwei
   Hauptknöpfen – hoch genug zum Treffen mit dem Daumen. */
.galerie { display: block; width: 100%; margin-top: 10px; min-height: 44px; padding: 12px 0; text-align: center; cursor: pointer; }

/* ---------- Hauptliste „Projekte“ ----------
   Eine Karte je Eintrag: Bild links (96 px, Spec Abschnitt 4), Text rechts, Knöpfe darunter.
   Grün heißt „gehört zu einem Projekt“ – sonst weiß. */
/* Drei Spalten: Bildmaterial steht als Quadrat darin, alles mit einem Vorgang (Projekt,
   Projektstapel, laufender Upload, aufgeklappte Fotos) nimmt die ganze Zeile. */
.liste { list-style: none; margin: 0; padding: 0; display: grid;
         grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; align-items: start; }
.liste > .karte, .liste > .stack-open { grid-column: 1 / -1; }
.kachel { position: relative; border-radius: 12px; overflow: hidden; border: 1px solid var(--border);
          background: #e6ebe7; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.kachel-bild { aspect-ratio: 1; cursor: pointer; }
.kachel-bild img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Ein Stapel sieht aus wie mehrere Blaetter uebereinander. */
.kachel-stapel { box-shadow: 3px -3px 0 -1px #fff, 4px -4px 0 0 var(--border); }
.kachel .karte-zahl { left: 6px; right: auto; }
/* Die Plus-Kachel: ein Feld des Rasters wie jedes Foto, nur leer und gestrichelt. Der Knopf
   fuellt sie ganz aus - die Trefferflaeche ist die Kachel, nicht nur das Zeichen. */
.kachel-neu { border: 2px dashed var(--border); background: #fff; }
.kachel-neu-knopf { display: flex; width: 100%; aspect-ratio: 1; align-items: center; justify-content: center;
                    border: 0; background: none; color: var(--green); padding: 0; cursor: pointer; }
/* Trefferflaeche 44x44 (Regel: Symbolknoepfe >= 44 px). Sichtbar bleibt der Kreis mit
   34 px: das Padding gehoert zur Flaeche, background-clip laesst es durchsichtig. Deshalb
   sitzt der Knopf 1 px statt 6 px vom Rand - der Kreis steht optisch wie zuvor. Der
   Schatten kommt als drop-shadow statt als box-shadow: box-shadow folgte dem 44-px-Kasten
   und zeichnete einen Ring um nichts. */
.kachel-stift { position: absolute; right: 1px; top: 1px; width: 44px; height: 44px; border-radius: 999px;
                border: 0; background: rgba(255, 255, 255, .92); background-clip: content-box;
                color: var(--green);
                display: flex; align-items: center; justify-content: center; padding: 5px; cursor: pointer;
                filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .25)); }
/* position: relative traegt den Stift in der Ecke - .kachel-stift sitzt auf der Karte an
   derselben Stelle wie auf einer Kachel. */
.karte {
  position: relative;
  display: grid; grid-template-columns: 96px 1fr; grid-template-areas: "bild text" "bild knoepfe";
  gap: 6px 12px; min-height: 96px; padding: 10px;
  background: #fff; border: 1px solid var(--border); border-radius: 12px;
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}
.karte.gruen { border-color: var(--green); background: #f1f7f2; }
/* Standort-Rahmen (11.9.2026): hellgruen, wenn das Bildmaterial Koordinaten hat, sonst
   hellrot - die Regel dahinter steht in liste.js (ort). Auf der Projektkarte bleibt Gruen
   der Hintergrund („gehoert zu einem Projekt"), der Rahmen gehoert dem Standort. Beide
   Zustaende sind 3 px breit (14.9.2026: 2 px gingen im Sonnenlicht unter), damit beim
   Wechsel nichts springt. */
.kachel.ort-ja, .karte.ort-ja { border: 3px solid var(--ort-ja); }
.kachel.ort-nein, .karte.ort-nein { border: 3px solid var(--ort-nein); }
/* Das Abzeichen unten links im Vorschaubild (ortzeichen.js): Stecknadel = mit Standort,
   durchgestrichene Stecknadel = ohne. Es sagt dasselbe wie der Rahmen noch einmal in Form -
   Farbe allein ist nicht selbsterklaerend. Das Wort dazu steht im aria-label der Kachel. */
.ort-abzeichen {
  position: absolute; left: 6px; bottom: 6px; width: 22px; height: 22px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 999px; color: #fff; box-shadow: 0 0 0 1px rgba(255, 255, 255, .7);
  pointer-events: none;
}
.ort-abzeichen-ja { background: var(--ort-ja-kraeftig); }
.ort-abzeichen-nein { background: var(--ort-nein-kraeftig); }
/* Die Zahl der Fotos rueckt eine Zeile hoch: unten sitzt jetzt das Abzeichen. Nach rechts
   auszuweichen reicht nicht - „12 photos" ist auf dem 96-px-Vorschaubild fast so breit wie
   das Bild selbst und laege dann auf dem Abzeichen. Die Seite behaelt jede Zahl: in der
   Kachel links, auf der Projektkarte rechts. */
.kachel .karte-zahl, .karte-bild .karte-zahl { bottom: 34px; }
/* Legende unter den Reitern: dieselben zwei Farben als Punkte, dahinter die Worte. Sie
   steht nur da, wenn eine Kachel ohne Standort zu sehen ist (app.js). */
.ort-legende { margin: 0 0 10px; font-size: 13px; color: var(--muted); }
.ort-punkt { display: inline-block; width: 10px; height: 10px; border-radius: 999px; margin-right: 5px; vertical-align: baseline; }
.ort-punkt-ja { background: var(--ort-ja-kraeftig); }
.ort-punkt-nein { background: var(--ort-nein-kraeftig); }
#kartenblick-map { flex: 1; min-height: 200px; }
.karte-bild { grid-area: bild; position: relative; width: 96px; height: 96px; border-radius: 10px; overflow: hidden; background: #e6ebe7; cursor: pointer; }
.karte-bild img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Mehr als ein Foto: zwei versetzte Kanten dahinter, wie bei den freien Stapeln im Raster. */
.karte-bild.stapel { box-shadow: 3px -3px 0 -1px #fff, 4px -4px 0 0 var(--border); }
.karte-zahl { position: absolute; right: 6px; bottom: 6px; background: rgba(28, 28, 28, .78); color: #fff; font-size: 12px; font-weight: 600; padding: 3px 8px; border-radius: 999px; }
.karte-text { grid-area: text; display: flex; flex-direction: column; gap: 2px; min-width: 0; padding-right: 40px; }
.karte-titel { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.karte-status { color: var(--green); font-weight: 600; font-size: 15px; }
.karte-unter { color: var(--muted); font-size: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.karte-knoepfe { grid-area: knoepfe; display: flex; flex-wrap: wrap; align-items: flex-end; align-self: end; gap: 8px; }
/* Nebenknöpfe: weiß mit grünem Rand, mindestens 52 px hoch. Der einzige Hauptknopf des
   Bildschirms steht oben („Foto aufnehmen“). */
.karte-knopf { flex: 1 1 auto; min-height: 52px; font: inherit; font-weight: 600; padding: 12px 14px; border-radius: 12px; border: 2px solid var(--green); background: #fff; color: var(--green); cursor: pointer; }
/* Gelb heißt „wartet“: die Aufnahme liegt noch auf dem Handy. */
.karte.wartet { border-color: #d8b657; }
.karte.wartet .karte-bild img { opacity: .72; }
.karte.wartet .karte-unter { color: #8a5f0c; }
/* Aufgeklappte Fotos haengen unter ihrer Karte statt sie zu ersetzen: derselbe gestrichelte
   Rahmen wie bisher, nur eingerueckt und dicht darunter - so sieht man, wozu sie gehoeren. */
.stack-open { margin-top: -4px; margin-left: 34px; }
.karte:not(.gruen) + .stack-open { border-color: var(--border); }
/* Die drei Wege im Blatt hinter der Plus-Kachel: Zeichnung und Wort nebeneinander, volle
   Breite, mindestens 52 px hoch (Spec Abschnitt 4). Der Kamera-Weg ist der Hauptknopf des
   Bildschirms - gruen gefuellt; die anderen zwei sind Nebenknoepfe. */
.neu-knopf { display: flex; width: 100%; align-items: center; gap: 12px; min-height: 52px;
             margin-bottom: 10px; padding: 12px 16px; border-radius: 12px;
             font: inherit; font-weight: 600; text-align: left;
             border: 2px solid var(--green); background: #fff; color: var(--green); cursor: pointer; }
.neu-knopf svg { flex: none; }
.neu-knopf.haupt { background: var(--green); color: #fff; }
/* Der Rueckweg: ein Textlink, aber breit genug zum Treffen mit dem Daumen. */
.link.breit { display: block; width: 100%; text-align: center; min-height: 44px; }

/* ---------- Reiter und Familien ---------- */
.tabs { display: flex; gap: 8px; margin: 4px 0 16px; }
.tab { flex: 1; font: inherit; font-weight: 600; padding: 12px; border-radius: 12px; border: 2px solid var(--border); background: #fff; color: var(--muted); cursor: pointer; }
.tab[aria-selected="true"] { border-color: var(--green); color: var(--green); }
/* Knopfzeile mit Fragezeichen daneben; der Erklärtext klappt darunter auf. */
.pane-row { display: flex; align-items: center; gap: 10px; margin-top: 16px; }
.pane-row .big { flex: 1; margin-top: 0; }
.help-btn { flex: none; width: 40px; height: 40px; border-radius: 50%; border: 2px solid var(--green); background: #fff; color: var(--green); font: inherit; font-weight: 700; font-size: 18px; line-height: 1; cursor: pointer; }
.help-btn[aria-expanded="true"] { background: var(--green); color: #fff; }
.modal-card h2 .help-btn { width: 28px; height: 28px; font-size: 14px; vertical-align: middle; margin-left: 4px; }
.help { margin: 10px 0 0; padding: 10px 12px; border-radius: 10px; background: #eef4ef; font-size: 14px; line-height: 1.4; color: var(--text); white-space: pre-line; }
.modal-card .help { margin: 0 0 12px; }
.stock { background: #fff; border: 1px solid var(--border); border-radius: 12px; padding: 12px 14px; display: flex; flex-direction: column; gap: 8px; }
.stock-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 14px; color: var(--muted); }
.coins { display: flex; gap: 5px; }
.coin { width: 22px; height: 30px; border-radius: 4px; border: 2px solid var(--green); background: #dcebdd; display: inline-block; }
.coin.used { border-style: dashed; background: transparent; opacity: .4; }
.coin.small { width: 12px; height: 16px; border-width: 1.5px; }
.star { color: #b9821a; font-size: 24px; line-height: 1; }
.star.dim { opacity: .3; }
.star.small { font-size: 16px; }
.stock .progress { margin-left: auto; font-variant-numeric: tabular-nums; }
.stock .credit { font-weight: 600; color: var(--text); }
.families { list-style: none; margin: 16px 0 0; padding: 0; }
.families li { display: flex; align-items: center; gap: 10px; background: #fff; border: 1px solid var(--border); border-radius: 12px; padding: 12px 14px; margin-bottom: 8px; cursor: pointer; }
.families .fam-name { flex: 1; min-width: 0; }
.families .fam-name b { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.families .fam-name small { color: var(--muted); }
.pill { font-size: 12px; font-weight: 600; padding: 4px 9px; border-radius: 999px; background: #eef1ee; color: var(--muted); white-space: nowrap; }
.pill.wait { background: #f3e7cc; color: #8a5f0c; }
.pill.ok { background: #dcebdd; color: var(--green); }
.pill.bad { background: #f4dcd8; color: var(--error); }
.pill.done { background: var(--green); color: #fff; }
.pill.outline { background: transparent; border: 1.5px solid var(--green); color: var(--green); }
.levels { display: flex; flex-direction: column; gap: 8px; margin: 14px 0 6px; }
.level { display: flex; align-items: center; gap: 8px; min-height: 44px; font: inherit; font-weight: 600; text-align: left; padding: 12px 14px; border-radius: 12px; border: 2px solid var(--border); background: #fff; cursor: pointer; }
.level[aria-pressed="true"] { border-color: var(--green); background: #f1f7f2; }
.level:disabled { opacity: .5; cursor: default; }
.level .level-price { margin-left: auto; color: var(--muted); font-weight: 400; font-variant-numeric: tabular-nums; }
.level .level-note { color: var(--error); font-size: 12px; font-weight: 400; }
.checklist { margin-top: 8px; }
.check { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--border); font-size: 15px; }
.check .yn button { font: inherit; padding: 6px 12px; border-radius: 999px; border: 1.5px solid var(--border); background: #fff; color: var(--muted); cursor: pointer; }
.check .yn button + button { margin-left: 4px; }
.check .yn button[aria-pressed="true"] { border-color: var(--green); background: var(--green); color: #fff; }
.status-text { margin: 12px 0 6px; font-weight: 600; }

/* Reiter „Webpage": Bild-Kacheln (eigene Seite und Auswahl), Kundenstimmen, Fassungen. */
.bild-kachel { display: inline-block; width: 96px; margin: 4px; position: relative; }
.bild-kachel img { width: 96px; height: 96px; object-fit: cover; border-radius: 8px; }
.bild-kachel button { font: inherit; padding: 2px 6px; }
.bilder-reihe { display: flex; flex-wrap: wrap; }
/* ---------- Bilder der Visitenkarte ---------- */
/* Kleinbilder in drei Spalten; das erste ist das Hauptbild. Umsortiert wird mit dem Finger
   (drag.js: halten, dann ziehen), deshalb keine Pfeilknöpfe mehr. */
.wp-bilder { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.wp-kachel { position: relative; margin: 0; aspect-ratio: 1; border-radius: 10px; overflow: hidden;
             background: #e6ebe7; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.wp-kachel img { width: 100%; height: 100%; object-fit: cover; display: block; }
.wp-kachel:first-child { outline: 2px solid var(--green); outline-offset: -2px; }
/* Der Griff sagt „hier anfassen": sechs Punkte, wie überall sonst auch. */
.kachel-griff {
  position: absolute; right: 6px; bottom: 6px; width: 22px; height: 22px; border-radius: 6px;
  background-color: rgba(255, 255, 255, .92);
  background-image: radial-gradient(currentColor 1.4px, transparent 1.5px);
  background-size: 7px 7px; background-position: 4px 4px; color: var(--muted);
}
/* Entfernen ist rot, auch wenn es nur ein Kreuz ist. */
.kachel-weg {
  position: absolute; right: 4px; top: 4px; width: 32px; height: 32px; border-radius: 999px;
  border: 2px solid var(--error); background: rgba(255, 255, 255, .92); color: var(--error);
  font: inherit; font-size: 18px; font-weight: 700; line-height: 1; cursor: pointer; padding: 0;
}
.wp-kachel .kachel-wort { position: absolute; left: 0; right: 0; bottom: 0; margin: 0;
  background: rgba(28, 28, 28, .62); color: #fff; font-size: 12px; padding: 3px 0; }
/* Neues Bild: leere Kachel mit gestricheltem Rand und einem Plus. */
.wp-neu {
  aspect-ratio: 1; border: 2px dashed var(--border); border-radius: 10px; background: transparent;
  color: var(--green); font: inherit; font-size: 30px; font-weight: 600; cursor: pointer;
}
/* Kopf des Reiters „Webpage": Adresse gross, QR-Code als Bild, Ampel mit Statuswort. */
.wp-kopf { background: #fff; border: 1px solid var(--border); border-radius: 12px; padding: 12px 14px;
          margin-bottom: 18px; display: flex; flex-direction: column; gap: 10px; }
/* Adresse und die zwei Symbolknöpfe in einer Zeile; die Adresse kürzt, die Knöpfe bleiben. */
.wp-adresse { display: flex; align-items: center; gap: 8px; }
.url-zeile { flex: 1; min-width: 0; font-weight: 600; font-size: 16px; color: var(--green);
             overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Symbolknopf: 44 px ist die kleinste Trefferfläche, die wir zulassen. */
.ikon { flex: none; width: 44px; height: 44px; border-radius: 10px; background: #fff;
        border: 2px solid var(--green); color: var(--green); display: flex; align-items: center;
        justify-content: center; padding: 0; cursor: pointer; }
.ikon.rot { border-color: var(--error); color: var(--error); }
/* Adresse ändern: Nebenknopf im Kopf, nicht breiter als sein Wort. */
.wp-kopf .knopf { align-self: flex-start; }
/* Die Vorschau im Blatt liest sich wie die Adresse im Kopf, bricht aber um statt zu kürzen. */
#slug-vorschau { margin: 8px 0 0; white-space: normal; overflow-wrap: anywhere; }
/* Eine Zeile für alle Rückmeldungen des Kopfes: „Kopiert" grau, Fehler rot. */
.melden { margin: 0; font-size: 15px; color: var(--muted); }
.melden.fehler { color: var(--error); }
/* Löschen und Entfernen sind überall ein roter Knopf, nie ein unterstrichener Link. */
.danger { background: #fff; color: var(--error); border: 2px solid var(--error); }
/* Eine Adresse hat keine Leerzeichen: ohne Umbruch im Wort schiebt sie schmale Geräte auf. */
.url-gross { margin: 0 0 8px; font-size: 22px; line-height: 1.25; font-weight: 600; color: var(--green); overflow-wrap: anywhere; word-break: break-word; }
.wp-kopf .hint { margin: 0; }
/* Frühere Adressen: ein Slug darf 40 Zeichen haben, mit der Domain ergibt das ein Wort ohne
   Trennstelle. Ohne Umbruch schöbe es die Karte und damit die Seite in die Breite. */
#wp-weiterleitungen { overflow-wrap: anywhere; }
.ampel-zeile { display: flex; align-items: center; gap: 10px; margin: 0; }
.ampel-zeile .status-text { margin: 0; }
.ampel { flex: none; width: 12px; height: 12px; border-radius: 50%; background: var(--grau); }
.ampel-draft { background: var(--grau); }
.ampel-submitted { background: var(--gelb); }
.ampel-approved { background: var(--gruen); }
.ampel-blocked { background: var(--rot); }

.zitat { border: 1px solid var(--border); border-radius: 10px; padding: 10px; margin: 8px 0; display: grid; gap: 6px; }
.fassung { display: grid; gap: 4px; margin-top: 6px; }
.lang-select { margin-bottom: 6px; }

/* ---------- Projekt-Modal ----------
   Abschnitte statt einer langen Feldliste (Nutzerwunsch 9.9.2026, „the buttons in Details
   seem scattered and uneven"): Familie, Standort, Ofen, Status, Fotos - jeder mit kleiner
   grauer Großbuchstaben-Überschrift und feiner Linie darüber. Innerhalb eines Abschnitts
   8 px zwischen den Feldern, zwischen den Abschnitten 20 px. Alles Antippbare ist
   mindestens 44 px hoch; 52 px bleibt dem einen Hauptknopf „Speichern" vorbehalten. */
#projekt-modal .abschnitt {
  display: grid; gap: 8px; margin-top: 20px; padding-top: 12px;
  border-top: 1px solid var(--border);
}
#projekt-modal .abschnitt-titel {
  margin: 0; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .12em;
  color: var(--muted);
}
/* Ein Feld ist Beschriftung plus Eingabe: die zwei gehören eng zusammen (4 px), erst zum
   nächsten Feld sind es die 8 px des Abschnitts. */
#projekt-modal .feld { display: grid; gap: 4px; }
#projekt-modal label { margin: 0; font-size: 15px; }
/* Die Grundschrift bleibt auch in den Eingaben stehen (18 px, Gestaltungsregeln): 44 px
   Hoehe kommen aus Polsterung und min-height, nicht aus kleinerer Schrift. */
#projekt-modal input { min-height: 44px; padding: 8px 12px; }
#projekt-modal .levels { margin: 0; }
/* Der Kopf: Titel und darunter klein das Statuswort - offen, beauftragt oder gebaut. */
#projekt-modal h2 { margin: 0 30px 0 0; }
#projekt-modal .statuswort { margin: 2px 0 0; font-size: 13px; font-weight: 600; letter-spacing: .04em; color: var(--muted); }

/* Fußleiste: sie steht beim Scrollen unten und trägt den einen Hauptknopf. Die Karte gibt
   ihre untere Polsterung an sie ab, damit unter der Leiste nichts durchscheint. */
#projekt-modal .modal-card { padding-bottom: 0; }
.modal-fuss {
  position: sticky; bottom: 0; z-index: 1; background: #fff; border-top: 1px solid var(--border);
  margin: 20px -16px 0; padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
}
.modal-fuss .big, #projekt-modal .abschnitt .big { margin-top: 0; }
.modal-fuss .error, .modal-fuss .melden { margin: 0 0 8px; }
/* „Löschen" steht rechts unter dem Hauptknopf, links davon nichts. */
.modal-fuss .modal-actions { margin: 8px 0 0; }

/* Kleine Standortkarte: nur zum Ansehen, deshalb keine Zeigerhand und kein Zoomen.
   position/z-index sperren Leaflets eigene Ebenen ein: seine Kacheln (z-index 400) und die
   Nachweiszeile (800) malten sonst ueber die stehende Fussleiste und fingen den Tipp auf
   „Speichern“ ab, sobald die Karte beim Scrollen hinter die Leiste laeuft. */
.projekt-karte { position: relative; z-index: 0; height: 160px; border-radius: 10px; overflow: hidden; background: #e6ebe7; border: 1px solid var(--border); }
#projekt-standort-leer { margin: 0; }
/* „Standort ändern" ist ein Nebenknopf, kein Hauptknopf: volle Breite direkt unter der
   Karte, 44 px hoch, Zeichen und Wort nebeneinander (Symbole nur mit Wort, Spec 4).
   Halb und rechts stand er schief in der Spalte (Nutzerwunsch 9.9.2026). */
.standort-knopf {
  display: flex; width: 100%; margin: 0; align-items: center; justify-content: center; gap: 8px;
  border: 2px solid var(--green); background: #fff; color: var(--green);
}
.standort-knopf svg { flex: none; }

/* Statusknöpfe: gefüllt heißt gesetzt (Grün = gehört zu einem Projekt). Schalterpaare
   stehen als Zweier-Raster - zwei gleich breite Knöpfe, nie einer breiter als der andere. */
.projekt-status { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 8px; }
/* Kleiner als ein Hauptknopf und mit Zeichen: es sind Schalter, keine Hauptaktionen. */
.status-knopf {
  min-height: 44px; display: flex; align-items: center; justify-content: center; gap: 8px;
  font: inherit; font-weight: 600; font-size: 15px; padding: 10px;
  border-radius: 10px; border: 2px solid var(--green); background: #fff; color: var(--green); cursor: pointer;
}
.status-knopf[aria-pressed="true"] { background: var(--green); color: #fff; }
.status-knopf:disabled { opacity: .5; cursor: default; }
/* Feld mit Fragezeichen daneben: das Zeichen bleibt so gross wie die Trefferflaeche
   der uebrigen Symbolknoepfe (44 px), das Feld nimmt den Rest. */
.feld-mit-hilfe { display: flex; gap: 8px; align-items: center; }
.feld-mit-hilfe input { flex: 1; min-width: 0; }
.feld-mit-hilfe .ikon { font-weight: 700; font-size: 18px; color: var(--green); }
/* Gesetzt bleibt gesetzt: ein gefuellter Knopf verblasst nicht, nur weil er nicht mehr zu
   bedienen ist. Sonst sehen "gebaut" und "nicht gebaut" gleich grau aus (Demo 9.9.2026). */
.status-knopf[aria-pressed="true"]:disabled { opacity: 1; }
/* Rückfragezeile bündig unter ihrem Schalterpaar: so hoch wie die Schalter, die Frage
   links, „Ja" und „Nein" als zwei gleich breite kleine Knöpfe rechts. */
#projekt-modal .confirm { min-height: 44px; margin: 0; gap: 8px; }
#projekt-modal .confirm > span:first-child { flex: 1 1 0; min-width: 0; }
#projekt-modal .confirm .knopf { flex: 0 0 72px; padding: 10px 8px; text-align: center; }

/* Fotokacheln zum Anhaken: der grüne Rahmen und das Wort darunter sagen „gewählt". */
#projekt-fotos .bild-kachel { border: 2px solid var(--border); border-radius: 10px; padding: 3px; background: #fff; cursor: pointer; }
#projekt-fotos .bild-kachel.gewaehlt { border-color: var(--green); background: #f1f7f2; }
#projekt-fotos .bild-kachel img { width: 86px; height: 86px; } /* 96 - 2*2 Rahmen - 2*3 Polsterung */
/* Dasselbe Standort-Abzeichen wie in der Hauptliste; hier sitzt es unten links am Bild,
   das Wort „gewaehlt" steht darunter. */
#projekt-fotos .bild-kachel .ort-abzeichen { left: 6px; bottom: 24px; }
.kachel-wort { display: block; min-height: 18px; font-size: 12px; font-weight: 600; color: var(--green); text-align: center; }

/* Versionszeile ganz unten: klein und grau, sie soll nichts wegnehmen. */
.version { margin: 32px 0 0; text-align: center; font-size: 11px; color: var(--muted); }

/* Die feste Zeile über der Liste: sie steht ruhig da und blinkt nicht. Gelb heißt „wartet",
   grün heißt „geht gerade raus" - dieselbe Sprache wie beim Rest der Seite. */
.offline-zeile {
  margin: 0 0 8px; padding: 8px 12px; border-radius: 8px;
  background: #fff4d6; color: #5c4400; border: 1px solid #f0dda5;
  font-size: 14px; line-height: 1.35;
}
.offline-zeile.sendet { background: #e4f2e8; color: #1b4332; border-color: #bcdcc7; }
/* „Wartet auf Netz": die Karte steht da, aber der Server weiss noch nichts davon. Gestrichelt
   statt farbig - es ist kein Fehler, nur ein Zwischenstand (Task 14, Ruling 1). */
.karte.wartet-netz { border-style: dashed; }
.karte-uhr { font-size: 13px; margin-left: 4px; opacity: .85; }
.liste-stand { margin: -4px 0 8px; }
/* Eine Kachel, die gerade rausgeht: der Balken sitzt unten in der Karte. */
.karte.wartet progress { width: 100%; height: 4px; grid-column: 1 / -1; }

/* ---------- Reiter „Chat" (Aufgabe 6) ---------- */
.tab-punkt { display: inline-block; min-width: 18px; height: 18px; margin-left: 6px; border-radius: 9px; background: #c0392b; color: #fff; font-size: 12px; line-height: 18px; text-align: center; padding: 0 4px; }
.chat-liste { list-style: none; margin: 0; padding: 0; }
.chat-liste li { display: grid; grid-template-columns: 1fr auto; gap: 4px 8px; padding: 12px 8px; border-bottom: 1px solid #ddd; cursor: pointer; }
.chat-liste .titel { grid-column: 1; font-weight: 600; }
.chat-liste .vorschau { grid-column: 1; color: #555; font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-liste .chat-eintrag-punkt { grid-row: 1 / span 2; align-self: center; display: inline-block; min-width: 18px; height: 18px; border-radius: 9px; background: #c0392b; color: #fff; font-size: 12px; line-height: 18px; text-align: center; padding: 0 4px; }
.chat-faden { display: flex; flex-direction: column; height: calc(100vh - 140px); }
.chat-kopf { display: flex; align-items: center; gap: 8px; padding: 8px; border-bottom: 1px solid #ddd; }
.chat-kopf b { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-nachrichten { list-style: none; margin: 0; padding: 8px; flex: 1 1 0; overflow-y: auto; }
.blase { max-width: 85%; margin: 4px 0; padding: 8px 10px; border-radius: 12px; background: #eee; word-wrap: break-word; }
.blase.eigene { margin-left: auto; background: #d9f0d3; }
.blase.wartet { opacity: .6; }
/* Fix-Runde 1 (Aufgabe 7): endgueltig gescheitert (nicht mehr "wartet", nie angekommen) -
   ein roter Rand statt des gedaempften Gelb-Grau von .wartet, dieselbe Farbe wie der
   Löschen-Knopf (.blase-loeschen). */
.blase.fehler { border: 1px solid #c0392b; }
.blase.fehler time { color: #c0392b; }
.blase.geloescht { color: #888; font-style: italic; }
.blase .absender { font-size: 13px; color: #555; }
.blase .buero { font-size: 12px; background: #333; color: #fff; border-radius: 4px; padding: 0 4px; margin-left: 4px; }
.blase img { display: block; max-width: 100%; border-radius: 8px; margin-top: 4px; cursor: pointer; }
.blase time { display: block; font-size: 12px; color: #777; text-align: right; }
/* Zweischritt-Löschen (kein confirm()): erst Kontextmenü/langes Drücken zeigt diesen Knopf
   in genau der einen Blase, erst ein Tipp darauf löscht wirklich (Fix-Runde 1). */
.blase-loeschen { display: block; width: 100%; margin-top: 6px; padding: 6px; border: 0; border-radius: 8px; background: #c0392b; color: #fff; font: inherit; font-size: 14px; cursor: pointer; }
.chat-form { display: grid; grid-template-columns: auto 1fr auto; gap: 6px; padding: 8px; border-top: 1px solid #ddd; align-items: end; }
.chat-form textarea { min-height: 44px; resize: none; }
.chat-foto { font-size: 24px; cursor: pointer; padding: 6px; }
.chat-lightbox { position: fixed; inset: 0; z-index: 1200; background: rgba(0,0,0,.9); display: flex; align-items: center; justify-content: center; }
.chat-lightbox img { max-width: 100%; max-height: 100%; }
.chat-name { padding: 12px; display: grid; gap: 8px; }

/* Datenschutz: Einwilligungs-Haken (Familie, Kundenstimme, Veroeffentlichung). Das ganze
   Etikett ist die Tippflaeche; der Kasten gross genug fuer einen Daumen. */
.einwilligung { display: flex; gap: 10px; align-items: flex-start; margin: 12px 0; font-size: 14px; line-height: 1.4; cursor: pointer; }
.einwilligung[hidden] { display: none; }
.einwilligung input[type="checkbox"] { flex: 0 0 auto; width: 22px; height: 22px; margin: 0; }
