/* ICS Door-to-Door – Oberfläche
   ---------------------------------------------------------------------------
   Der Arbeitsbereich ist immer zweispaltig: LINKS die Haushalte des gewählten
   Hauses, RECHTS alles zum gewählten Haushalt (Fortschritt, Ausgang, Kunde,
   Verlauf). Nur die Verpackung wechselt mit der Geräteausrichtung:

   • Querformat (>= 900px): zwei schmale Panels an den Kartenrändern, die Karte
                            läuft dazwischen durch.
   • Hochformat (< 900px):  dieselben zwei Spalten in einem Bottom-Sheet mit
                            Griff (halb / ganz / zu).

   Gestaltungsprinzip: ruhige Flächen, Haarlinien statt Rahmen, Bedeutung über
   Icon-Chips statt über Farbflächen. Jede Kachel trägt links ein Icon im
   abgerundeten Quadrat – im Ruhezustand grau, aktiv in der Farbe der Sache.
   Primäre Touchziele bleiben bei mindestens 44px.
*/

:root {
  --ink: #0f172a;
  --ink-2: #475569;
  --muted: #94a3b8;
  --line: #e6ebf2;
  --line-soft: #f1f5f9;
  --bg: #f6f8fb;
  --card: #ffffff;
  --accent: #2563eb;

  --topbar-h: 46px;
  --wp-l: 236px;             /* linkes Panel: Haushalte */
  --wp-r: 336px;             /* rechtes Panel: Detail */
  --r-tile: 12px;
  --r-field: 10px;
  --shadow-tile: 0 1px 1.5px rgba(15, 23, 42, .03);
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  margin: 0; padding: 0;
  height: 100%;
  overflow: hidden;             /* kein Seiten-Scroll – nur Panels scrollen */
  overscroll-behavior: none;
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto, sans-serif;
  font-size: 14px;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body { display: flex; flex-direction: column; }

button, input, textarea, select { font: inherit; color: inherit; }
svg { display: block; }

/* ===========================================================================
   Kopfzeile
   =========================================================================== */

.topbar {
  flex: 0 0 auto;
  height: calc(var(--topbar-h) + var(--safe-top));
  padding: var(--safe-top) 12px 0;
  display: flex; align-items: center; gap: 14px;
  background: #0b1220; color: #f8fafc;
  box-shadow: inset 0 -1px 0 rgba(255, 255, 255, .07);
  z-index: 30;
}

.brand {
  display: flex; align-items: center; gap: 7px;
  font-weight: 700; letter-spacing: .08em; font-size: 12.5px;
  color: #7dd3fc; flex: 0 0 auto;
}
/* Das angemeldete Konto. Als Schild neben der Marke statt als Zeile irgendwo
   in den Einstellungen: die beiden Konten sehen sonst identisch aus, und ein
   Ausgang im falschen fällt erst Wochen später auf. */
.brand-konto {
  max-width: 12ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  padding: 2px 7px; border-radius: 999px;
  background: rgba(125, 211, 252, .14);
  color: #bae6fd; font-weight: 600; font-size: 11px; letter-spacing: .02em;
  text-transform: lowercase;
}

.tabs { display: flex; gap: 2px; background: rgba(255, 255, 255, .07); padding: 3px; border-radius: 10px; }
.tab {
  appearance: none; border: 0; background: transparent;
  color: #b5c2d3; font-size: 13px; font-weight: 600;
  padding: 6px 16px; border-radius: 7px; cursor: pointer; min-height: 30px;
  transition: background .15s, color .15s;
}
.tab.active { background: #f8fafc; color: #0b1220; }

/* Dringlichkeits-Zähler am Followup-Tab. Sitzt wie eine Benachrichtigung oben
   rechts an der Beschriftung; die Farbe kommt aus dem Skript (--fu-badge) und
   sagt, wie nah der nächste Termin ist. Weiße Zahl auf allen vier Stufen: Rot,
   Orange und Grün tragen sie sicher, Gelb bekommt darum dunkle Schrift. */
.tab { position: relative; }
.tab-badge {
  position: absolute; top: -1px; right: 1px;
  min-width: 17px; height: 17px; padding: 0 4px; border-radius: 999px;
  background: var(--fu-badge, #dc2626); color: var(--fu-badge-ink, #fff);
  font-size: 10.5px; font-weight: 700; line-height: 17px; text-align: center;
  font-variant-numeric: tabular-nums;
  --fu-ring: #0f172a;                    /* Rand in Kopfzeilenfarbe, damit er absetzt */
  box-shadow: 0 0 0 2px var(--fu-ring);
}
.tab.active .tab-badge { --fu-ring: #f8fafc; }
/* Platz für den Zähler, damit er nicht auf der Beschriftung sitzt – aber nur,
   solange er wirklich da ist. */
.tab:has(.tab-badge:not([hidden])) { padding-right: 26px; }

/* Fünf Minuten vor dem Termin (oder überfällig) schlägt der Zähler Alarm: er
   pocht, glüht und schickt einen Ring nach außen. Das ist der Moment, in dem
   man losgehen muss – da darf der Punkt aus dem Augenwinkel auffallen, auch
   wenn gerade die Karte offen ist. Der Rand bleibt über --fu-ring erhalten,
   sonst verlöre der Zähler beim Wechsel auf den aktiven Tab seine Kante. */
.tab-badge--alarm {
  animation: fu-alarm-beat 1.4s ease-in-out infinite;
}
.tab-badge--alarm::after {
  content: ''; position: absolute; inset: -3px;
  border-radius: 999px; border: 2px solid var(--fu-badge, #dc2626);
  animation: fu-alarm-ring 1.4s ease-out infinite;
  pointer-events: none;
}
/* Zwei kurze Schläge, dann Ruhe – ein Herzschlag fällt im Augenwinkel stärker
   auf als ein gleichmäßiges Pulsieren und nutzt sich langsamer ab. */
@keyframes fu-alarm-beat {
  0%       { transform: scale(1);
             box-shadow: 0 0 0 2px var(--fu-ring), 0 0 0 0 rgba(220, 38, 38, 0); }
  11%      { transform: scale(1.35);
             box-shadow: 0 0 0 2px var(--fu-ring), 0 0 16px 6px rgba(220, 38, 38, .95); }
  22%      { transform: scale(1.06);
             box-shadow: 0 0 0 2px var(--fu-ring), 0 0 9px 3px rgba(220, 38, 38, .5); }
  33%      { transform: scale(1.32);
             box-shadow: 0 0 0 2px var(--fu-ring), 0 0 16px 6px rgba(220, 38, 38, .95); }
  52%      { transform: scale(1);
             box-shadow: 0 0 0 2px var(--fu-ring), 0 0 7px 2px rgba(220, 38, 38, .4); }
  100%     { transform: scale(1);
             box-shadow: 0 0 0 2px var(--fu-ring), 0 0 0 0 rgba(220, 38, 38, 0); }
}
/* Der Ring läuft mit dem ersten Schlag nach außen und ist danach weg. */
@keyframes fu-alarm-ring {
  0%   { transform: scale(.9); opacity: .95; border-width: 2.5px; }
  40%  { transform: scale(2.4); opacity: 0; border-width: 1px; }
  100% { transform: scale(2.4); opacity: 0; border-width: 1px; }
}
/* Ohne Bewegung bleibt das Glühen – auffällig, aber still. */
@media (prefers-reduced-motion: reduce) {
  .tab-badge--alarm { animation: none; box-shadow: 0 0 0 2px var(--fu-ring), 0 0 12px 3px rgba(220, 38, 38, .85); }
  .tab-badge--alarm::after { animation: none; opacity: .55; }
}

.topbar-right { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.stat-chip { font-size: 12px; color: #7d8da3; white-space: nowrap; font-variant-numeric: tabular-nums; }
.stat-chip b { color: #e8eef6; font-weight: 600; }

/* ---- Kopfzeile auf dem Telefon: zwei Zeilen ------------------------------
   Acht Tabs brauchen 554px, ein Telefon hat 390. Nebeneinander mit Marke und
   Tageskachel lagen Season, Rechner und Einstellungen schlicht außerhalb des
   Bildschirms – nicht angeschnitten, sondern unerreichbar.
   Gelöst ohne Änderung am HTML: die Leiste darf umbrechen, die Tabs bekommen
   die volle Breite der zweiten Zeile und scrollen darin waagerecht. Weil sie
   zusammen immer breiter sind als der Bildschirm, steht an einer Kante stets
   ein angeschnittener Tab – das ist der Hinweis, dass es weitergeht. Dazu
   scrollt main.js den aktiven Tab in die Mitte. */
@media (max-width: 640px) {
  .topbar {
    height: auto;
    min-height: calc(var(--topbar-h) + var(--safe-top));
    flex-wrap: wrap;
    gap: 0 10px;
    padding: var(--safe-top) 10px 0;
  }
  .tabs {
    order: 2;                              /* zweite Zeile, unter Marke + Kachel */
    flex: 0 0 100%;
    /* Bis an beide Bildschirmkanten, damit der angeschnittene Tab nicht in
       einem Innenabstand endet und wie ein Fehler aussieht. */
    margin: 3px -10px 0;
    width: calc(100% + 20px);
    border-radius: 0;
    background: transparent;
    /* Der Innenabstand oben/unten hält Platz für den Followup-Zähler und
       seinen Alarmring: overflow-x macht auch die Y-Achse beschneidend. */
    padding: 6px 10px;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;        /* kein Zurückwischen der Seite */
  }
  .tabs::-webkit-scrollbar { display: none; }
  .tab {
    flex: 0 0 auto;
    min-height: 40px;                      /* Daumenziel statt 30px */
    padding: 9px 14px;
    font-size: 13.5px;
  }
  .tab-badge { top: 2px; right: 3px; }
  /* Beides war früher weggeblendet, um Platz für die einzeilige Leiste zu
     schaffen. Die erste Zeile ist jetzt frei – die Tageszahl ist unterwegs die
     meistgelesene Zahl der App und gehört sichtbar. */
  .brand span { display: inline; }
  .stat-chip { display: inline; font-size: 12.5px; }
  .brand { padding: 3px 0; }
}

/* ===========================================================================
   Ansichten
   =========================================================================== */

.views { flex: 1 1 auto; position: relative; min-height: 0; }
.view { display: none; position: absolute; inset: 0; }
.view.active { display: block; }

/* Die Karte ist die EINZIGE Ansicht, die nie auf `display:none` fällt.

   Sie zeichnet auf einer WebGL-Fläche (renderingType VECTOR). Ein Kasten mit
   `display:none` hat 0×0 Pixel, und eine WebGL-Fläche ohne Maße ist für den
   Browser eine, die niemand mehr braucht: er kassiert ihren Zeichenkontext ein
   – auf dem iPhone schon nach Sekunden, wenn das Gerät knapp an Speicher ist.
   Zurück auf dem Kartentab stand dann das letzte Bild da und ließ sich nicht
   mehr schieben. Genau das Einfrieren, das nur ein Neuladen behoben hat.

   Also bleibt sie im Layout stehen und wird nur unsichtbar geschaltet:
   `visibility` nimmt sie aus dem Bild UND aus der Trefferprüfung (nichts
   darin ist anklickbar oder anspringbar), lässt ihr aber ihre Größe – und
   damit den Zeichenkontext. Gerechnet wird deshalb nichts: eine Karte, die
   niemand bewegt, zeichnet auch kein neues Bild.

   Die ID schlägt `.view` wie `.view.active`, beide Regeln oben laufen hier also
   ins Leere. Der zweite Halt für denselben Fall steht in main.js
   (karteHeilen): verliert die Fläche den Kontext trotzdem – im Hintergrund
   liegende App, Speichernot –, wird die Karte neu aufgebaut. */
#view-map { display: block; }
/* Auch alles DARIN, nicht nur die Hülle: `visibility` vererbt sich zwar, ein
   Kind darf sich mit `visibility: visible` aber wieder hervorholen – und genau
   das tut der Arbeitsbereich (`.work.open`, siehe weiter unten). Ohne die
   zweite Zeile klebte ein offenes Haus über der Übersicht. Die ID sorgt dafür,
   dass diese Regel gewinnt. */
#view-map:not(.active),
#view-map:not(.active) * { visibility: hidden; }

.map-area { position: absolute; inset: 0; }
#map { position: absolute; inset: 0; background: #dde4ed; }

/* Kartenausfall: Google Maps kommt über das Netz, und unterwegs kommt es
   manchmal nicht. Statt einer grauen Fläche, über die man rätselt (und wegen
   der man die App neu startet), steht dann hier, was los ist und was trotzdem
   geht. main.js hängt den Kasten ein und nimmt ihn wieder weg, sobald die Karte
   steht – siehe kartenFehlerZeigen. */
.map-fehler {
  position: absolute; z-index: 18;
  left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: min(320px, calc(100% - 32px));
  display: flex; flex-direction: column; align-items: center; gap: 9px;
  padding: 20px 18px; border-radius: 16px; text-align: center;
  background: #fff; color: var(--ink-2);
  box-shadow: 0 8px 28px rgba(15, 23, 42, .18), 0 2px 6px rgba(15, 23, 42, .08);
}
.map-fehler strong { font-size: 15px; font-weight: 650; color: var(--ink); }
.map-fehler span { font-size: 13px; line-height: 1.5; color: var(--ink-2); }
.map-fehler-btn {
  appearance: none; border: 0; cursor: pointer; margin-top: 3px;
  padding: 9px 16px; border-radius: 11px;
  background: var(--accent); color: #fff; font-size: 13px; font-weight: 600;
}
.map-fehler-btn:active { transform: scale(.97); }

/* ---- Control Panel (Kartensteuerung) ------------------------------------
   Liegt mittig unten über der Karte und besteht nur noch aus dem Joystick
   (Zoom, Drehen, Standort) – die Straßensuche schaltet sich daneben. Mittig statt am Rand, damit es im Hoch- wie im Querformat mit
   beiden Daumen erreichbar ist; die Position folgt dem Arbeitsbereich (siehe
   die body.work-*-Regeln weiter unten). */

.map-controls {
  position: absolute; z-index: 19;
  left: 50%; bottom: calc(var(--safe-bottom) + 16px);
  transform: translateX(-50%);
  display: flex; align-items: center; gap: 9px;
  transition: left .2s ease, bottom .26s cubic-bezier(.32, .72, 0, 1), opacity .2s;
}
/* Ein `hidden`-Attribut muss stärker sein als jede display-Regel einer Klasse.
   Der Browser bringt dafür nur `[hidden] { display: none }` mit – und das
   verliert gegen jedes `.klasse { display: flex }`. Genau daran hing der
   Straßensuche-Knopf: main.js setzte `hidden = true`, `.map-ctrl { display:
   flex }` zeigte ihn trotzdem. Einmal zentral geklärt, statt es je Element
   nachzutragen (.str-panel und .pop-plz taten das bereits). */
[hidden] { display: none !important; }

.map-ctrl {
  appearance: none; border: 1px solid rgba(15, 23, 42, .06); cursor: pointer;
  width: 46px; height: 46px; border-radius: 14px; flex: 0 0 auto;
  background: #fff; color: var(--ink-2);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 4px 14px rgba(15, 23, 42, .16), 0 1px 3px rgba(15, 23, 42, .08);
  transition: transform .12s ease;
}
.map-ctrl:active { transform: scale(.93); }
/* Läuft die Ortung, trägt der Knopf dieselbe Farbe wie der Punkt auf der Karte. */
.map-ctrl.active { color: var(--accent); }

/* Joystick: runder Hebel mit zwei Achsen, die Auslenkung bestimmt das Tempo.
   Hoch/runter zoomt, links/rechts dreht die Karte, ein Druck in die Mitte holt
   den Standort. Er ist größer als die runden Knöpfe und ragt aus der Reihe
   nach oben wie nach unten heraus – die vier Hinweise sitzen an seinen Rändern,
   damit man auch ohne Erklärung sieht, wohin sich der Knopf ziehen lässt. */
.map-ctrl.joystick {
  width: 104px; height: 104px; border-radius: 50%;
  position: relative; padding: 0;
  cursor: grab; touch-action: none;
}
/* Der Joystick ist jetzt DIE Steuerung und muss mittig unter dem Daumen liegen –
   auch dann, wenn die Straßensuche daneben eingeschaltet ist. Deshalb hängt
   deren Knopf NEBEN der Reihe statt in ihr: sonst schöbe er den Joystick um
   seine halbe Breite aus der Mitte, je nachdem, ob der Schalter an ist. */
#ctrlStrasse { position: absolute; left: calc(100% + 9px); top: 50%; transform: translateY(-50%); }
#ctrlStrasse:active { transform: translateY(-50%) scale(.93); }

.map-ctrl.joystick:active { transform: none; }   /* nicht das ganze Pad stauchen */
.map-ctrl.joystick.dragging { border-color: rgba(37, 99, 235, .35); cursor: grabbing; }
.joy-hint {
  position: absolute; width: 15px; height: 15px; color: #b3bfcf;
  pointer-events: none; user-select: none; z-index: 1;
}
.joy-up    { top: 7px;    left: 50%; transform: translateX(-50%); }
.joy-down  { bottom: 7px; left: 50%; transform: translateX(-50%); }
/* Beide Dreh-Pfeile sind dasselbe Bild; der linke wird gespiegelt, damit er
   in die andere Richtung zeigt. */
.joy-left  { left: 8px;   top: 50%;  transform: translateY(-50%) scaleX(-1); }
.joy-right { right: 8px;  top: 50%;  transform: translateY(-50%); }
.joy-knob {
  position: absolute; left: 50%; top: 50%;
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 2px 7px rgba(15, 23, 42, .3);
  transform: translate(-50%, -50%);
  transition: transform .14s cubic-bezier(.2, .8, .3, 1);
  display: flex; align-items: center; justify-content: center;
}
/* Das Fadenkreuz im Knopf. Es ersetzt den früheren Standort-Knopf: nur daran
   ist zu sehen, dass ein Druck in die Mitte den Standort holt. Blass, solange
   nichts läuft – sobald die Ortung steht, leuchtet es voll, wie vorher der
   Knopf seine Farbe wechselte. */
.joy-me {
  width: 20px; height: 20px; color: #fff; opacity: .58;
  pointer-events: none; transition: opacity .18s ease;
}
.map-ctrl.joystick.active .joy-me { opacity: 1; }
/* Während die Ortung läuft, pulst das Fadenkreuz. Das ist die Antwort auf den
   Tipp: ein Fix kann draußen Sekunden dauern, und ohne sichtbares „ich suche"
   hält man den Knopf für kaputt und drückt weiter. */
@keyframes joy-sucht { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }
.map-ctrl.joystick.sucht .joy-me { animation: joy-sucht 1s ease-in-out infinite; }
.map-ctrl.joystick.dragging .joy-knob {
  transition: none;
  box-shadow: 0 2px 10px rgba(15, 23, 42, .4), 0 0 0 5px rgba(37, 99, 235, .22);
}
/* Kurzer Druck in die Mitte = Standort. Der Knopf blitzt einmal auf, damit der
   Tipp sichtbar ankommt – sonst passierte scheinbar nichts, bis die Ortung da ist. */
@keyframes joy-tap { from { box-shadow: 0 2px 7px rgba(15, 23, 42, .3), 0 0 0 0 rgba(37, 99, 235, .35); }
                     to   { box-shadow: 0 2px 7px rgba(15, 23, 42, .3), 0 0 0 16px rgba(37, 99, 235, 0); } }
.joy-knob.tapped { animation: joy-tap .45s ease-out; }

/* ---- Eigener Standort ----
   Blauer Punkt, bewusst rund und ohne Spitze: er ist keine Nadel, sondern zeigt,
   wo man selbst steht. Nadeln hängen mit der Unterkante am Ort – der Punkt wird
   um seine halbe Höhe nach unten geschoben, damit seine MITTE auf dem Standort
   sitzt. Der Ring darum pulst langsam, damit er zwischen den Nadeln auffällt. */

.me-dot {
  position: relative;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--accent);
  border: 3px solid #fff;
  box-shadow: 0 2px 8px rgba(15, 23, 42, .45);
  transform: translateY(50%);
  pointer-events: none;
}
.me-dot::after {
  content: ''; position: absolute; inset: -3px;
  border-radius: 50%; background: rgba(37, 99, 235, .35);
  animation: me-pulse 2s ease-out infinite;
}
@keyframes me-pulse {
  0%   { transform: scale(1);   opacity: .55; }
  70%  { transform: scale(2.6); opacity: 0; }
  100% { transform: scale(2.6); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .me-dot::after { animation: none; opacity: 0; }
}

/* ---- Nadeln ---- */

.pin {
  position: relative;
  width: 32px; height: 32px; border-radius: 50% 50% 50% 4px;
  transform: rotate(-45deg);
  background: var(--pin-color, #64748b);
  border: 2.5px solid #fff;
  box-shadow: 0 3px 9px rgba(15, 23, 42, .42);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
}
/* Offene Nadel: weiß gefüllt. Weil der Rand aller Nadeln ebenfalls weiß ist,
   bekäme sie sonst gar keine Kontur – der dunkle Ring übernimmt das. */
.pin.offen {
  box-shadow: 0 0 0 1.5px rgba(15, 23, 42, .55), 0 3px 9px rgba(15, 23, 42, .42);
}
/* Die Zahl steht auf der Farbe des Ausgangs – die reicht von hellem Followup-Gelb
   bis zum fast schwarzen „Übersprungen". Welche Schriftfarbe darauf lesbar ist,
   rechnet pinInk() je Nadel aus (--pin-ink); die Blasen behalten ihre dunkle
   Schrift, deren Rampe hält überall dieselbe Helligkeit. */
.pin span {
  transform: rotate(45deg);
  color: var(--pin-ink, var(--ink)); font-size: 12.5px; font-weight: 700; letter-spacing: -.01em;
  font-variant-numeric: tabular-nums;
}
.pin.selected {
  width: 40px; height: 40px; z-index: 10;
  box-shadow: 0 0 0 4px rgba(37, 99, 235, .45), 0 5px 14px rgba(15, 23, 42, .45);
}
.pin.selected span { font-size: 14px; }
/* Am Finger: gestrichelter Ring und ein Hauch größer. Der Unterschied muss aus
   dem Augenwinkel erkennbar sein – man schaut beim Ziehen auf die Karte, nicht
   auf den Knopf, den man gerade gedrückt hat. */
.pin.ziehbar {
  cursor: grab;
  outline: 2.5px dashed var(--accent); outline-offset: 3px;
}
.pin.ziehbar:active { cursor: grabbing; }
/* Während ein Haus am Finger hängt, tritt der Rest der Karte zurück – sonst
   greift man im Gedränge die falsche Nadel. */
body.move-mode .pin:not(.ziehbar), body.move-mode .cluster { opacity: .45; }

/* ---- Straßensuche: getroffene Nadeln ----
   Eine Nadel, die zur laufenden Suche gehört, trägt ihre HAUSNUMMER statt der
   Ausgangszahl (die wäre bei einem Treffer ohnehin null) und einen blauen Ring.
   Der Ring liegt außen um die Nadel und muss die Kontur der offenen Nadel
   überleben – deshalb beides in EINEM box-shadow, sonst gewinnt die letzte
   Regel und die weiße Nadel verliert ihre dunkle Kontur. */
.pin.treffer {
  box-shadow: 0 0 0 1.5px rgba(15, 23, 42, .55), 0 0 0 4.5px rgba(37, 99, 235, .5),
              0 3px 9px rgba(15, 23, 42, .42);
  z-index: 8;
}
.pin.treffer.selected {
  box-shadow: 0 0 0 4px rgba(37, 99, 235, .45), 0 5px 14px rgba(15, 23, 42, .45);
}
/* Ein Treffer, an dem schon jemand war, wird beschriftet wie die anderen – die
   Hausnummer ist das, wonach man auf der Straße sucht. Der blaue Ring bleibt
   aber den offenen: er sagt „hier musst du noch hin". Der erledigte bekommt nur
   einen hellen Saum, damit erkennbar bleibt, dass er zur Suche gehört. */
.pin.treffer.erledigt {
  box-shadow: 0 0 0 3px rgba(255, 255, 255, .85), 0 3px 9px rgba(15, 23, 42, .42);
}
.pin.treffer.erledigt.selected {
  box-shadow: 0 0 0 4px rgba(37, 99, 235, .45), 0 5px 14px rgba(15, 23, 42, .45);
}
/* Die Nummer sitzt in der um -45° gedrehten Nadel und muss zurückgedreht werden
   wie die Ausgangszahl auch. Drei Zeichen („12a") passen nur eine Stufe kleiner
   in die 32px-Nadel – darunter wird nicht mehr verkleinert, sondern der Rest
   abgeschnitten: „1…" wäre keine Hausnummer mehr. */
.pin-nr {
  transform: rotate(45deg);
  color: var(--pin-ink, var(--ink));
  font-size: 12.5px; font-weight: 700; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  max-width: 26px; overflow: hidden; text-overflow: clip; white-space: nowrap;
}
.pin-nr.lang { font-size: 10px; letter-spacing: -.04em; }

/* Vorschlag, kein Haus: halbdurchsichtig und gestrichelt umrandet. Beides
   zusammen – Durchsichtigkeit allein läse sich auf einer hellen Luftaufnahme
   wie eine blasse, aber echte Nadel. Der Strichrand sagt „hier ist noch
   nichts". Beim Ziehen wird sie kurz voll deckend: dann ist sie in der Hand.
   Der greifbare Bereich bleibt die volle Nadel, damit sie sich im Gehen
   treffen lässt. */
.pin.geist {
  opacity: .5;
  background: #fff;
  border-style: dashed; border-color: #475569;
  box-shadow: 0 2px 6px rgba(15, 23, 42, .3);
  cursor: grab;
}
.pin.geist .pin-nr { color: #334155; }
.pin.geist:active { opacity: .95; cursor: grabbing; }
.pin.selected .pin-nr { font-size: 14px; max-width: 33px; }
.pin.selected .pin-nr.lang { font-size: 11.5px; }

/* ---- Straßensuche: das Panel über der Karte ----
   Liegt oben links unter der Kopfzeile, nicht mittig: die Mitte gehört der
   Karte, und der Daumen kommt von unten. Es deckt höchstens die obere Hälfte
   ab, damit immer noch Karte zu sehen ist – man sucht ja, um dort hinzugehen.
   z-index unter dem Bottom-Sheet (20) und unter dem Popup (40): das Panel ist
   Auskunft, die Arbeit am Haus ist wichtiger. */
.str-panel {
  position: absolute; z-index: 18;
  top: 12px; left: 12px;
  width: min(330px, calc(100% - 24px));
  max-height: min(52vh, 460px);
  display: flex; flex-direction: column;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-tile);
  box-shadow: 0 10px 30px rgba(15, 23, 42, .22), 0 2px 6px rgba(15, 23, 42, .1);
  overflow: hidden;
}
.str-panel[hidden] { display: none; }

.str-kopf {
  display: flex; align-items: center; gap: 7px;
  padding: 9px 8px 9px 11px;
  border-bottom: 1px solid var(--line-soft);
}
.str-kopf strong { flex: 1 1 auto; font-size: 13px; font-weight: 650; min-width: 0; }
.str-ic { display: flex; flex: 0 0 auto; color: var(--muted); }
.str-x {
  appearance: none; border: 0; cursor: pointer; flex: 0 0 auto;
  width: 32px; height: 32px; border-radius: 9px;
  background: var(--line-soft); color: var(--ink-2);
  display: flex; align-items: center; justify-content: center;
}
.str-x:active { background: #e2e8f0; }

/* PLZ (schmal, mit Fadenkreuz darin) · Straße (der Rest) · Lupe. Eine Zeile,
   weil das Panel schmal ist und drei Zeilen davon die halbe Karte kosteten. */
.str-form {
  display: grid; grid-template-columns: 96px minmax(0, 1fr) 40px;
  gap: 6px; padding: 9px 10px;
}
.str-form input {
  appearance: none; width: 100%; min-width: 0;
  padding: 8px 10px; min-height: 38px;
  border: 1px solid var(--line); border-radius: 9px; background: #fff;
  font: inherit; font-size: 15px; color: var(--ink);
}
.str-form input:focus { outline: none; border-color: var(--accent); }
.str-plz { position: relative; min-width: 0; }
.str-plz input { padding-right: 30px; font-variant-numeric: tabular-nums; }
/* Das Fadenkreuz sitzt IM Feld: eine eigene Spalte dafür ginge von der Straße ab,
   und die trägt den längeren Text. */
.str-auto {
  position: absolute; right: 3px; top: 50%; transform: translateY(-50%);
  appearance: none; border: 0; cursor: pointer;
  width: 28px; height: 28px; border-radius: 7px;
  background: transparent; color: var(--muted);
  display: flex; align-items: center; justify-content: center;
}
.str-auto:active { background: var(--line-soft); color: var(--accent); }
.str-go {
  appearance: none; cursor: pointer;
  border: 1px solid var(--accent); border-radius: 9px;
  background: var(--accent); color: #fff;
  display: flex; align-items: center; justify-content: center;
}
.str-go:active { background: #1d4ed8; }

.str-hint {
  margin: 0; padding: 2px 12px 12px;
  font-size: 12px; line-height: 1.45; color: var(--muted);
}

.str-liste { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 0 6px 4px; }
.str-gruppe {
  position: sticky; top: 0; z-index: 1;
  padding: 6px 6px 3px;
  background: var(--card);
  font-size: 11px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted);
}
/* Eine Zeile = eine Hausnummer. Ganze Zeile tippbar, weil man sie im Gehen
   trifft; die Notiz daneben bricht nicht um, sonst wären es zwei Zeilen je
   Nummer und man sähe vier statt neun. */
.str-zeile {
  appearance: none; width: 100%; text-align: left; cursor: pointer;
  display: flex; align-items: baseline; gap: 9px;
  padding: 7px 8px; border: 0; border-radius: 8px;
  background: transparent; color: var(--ink); font: inherit;
}
.str-zeile:active { background: var(--line-soft); }
.str-zeile.aktiv { background: #eaf2ff; }
.str-nr {
  flex: 0 0 auto; min-width: 34px;
  font-size: 14.5px; font-weight: 700; font-variant-numeric: tabular-nums;
}
/* Der Punkt trägt die Farbe des Ausgangs (bzw. Weiß für offen, den Adressstatus
   für „ohne Nadel"). Weiß braucht eine Kontur, sonst ist er auf der weißen Karte
   ein Loch. */
.str-punkt {
  flex: 0 0 auto; align-self: center;
  width: 9px; height: 9px; border-radius: 999px;
  background: var(--c, #94a3b8);
  box-shadow: inset 0 0 0 1px rgba(15, 23, 42, .28);
}
/* Die Notiz aus der Excel: eine Zelle je Tabellenspalte, alle gleich breit.
   Gleiche Breite ist der ganze Punkt – nur so steht dieselbe Spalte in jeder
   Zeile untereinander und lässt sich senkrecht lesen. Zahlen mit fester
   Ziffernbreite, damit auch „2" und „11" auf derselben Kante sitzen. */
.nz {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr);
  gap: 6px; min-width: 0; font-variant-numeric: tabular-nums;
}
.nz-c { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Der Stand steht IMMER da, auch bei „offen" (dann leer): sonst wäre die Zeile
   verschieden breit und das Notizraster darüber verschoben – genau das, was
   hier verhindert werden soll. */
.str-stand {
  flex: 0 0 auto; align-self: center; width: 76px; text-align: right;
  font-size: 10.5px; font-weight: 600; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Erledigt und ohne Nadel stehen leiser: die Zeile, die man sucht, ist die
   offene. Sichtbar bleiben sie trotzdem – deshalb gedämpft und nicht grau. */
.str-zeile.str-erledigt .str-nr, .str-zeile.str-ohneNadel .str-nr { font-weight: 600; color: var(--ink-2); }
.str-zeile.str-ohneNadel { font-style: italic; }
.str-zeile.str-ohneNadel .str-stand { color: #e11d48; font-style: normal; }
.str-notiz {
  flex: 1 1 auto; min-width: 0;
  font-size: 11.5px; color: var(--ink-2);
}
.str-fuss {
  margin: 0; padding: 6px 12px 10px;
  border-top: 1px solid var(--line-soft);
  font-size: 11.5px; color: var(--muted);
}

/* Gebündelte Nadeln (herausgezoomt): Zahl der AUSGÄNGE in der Gegend, eingefärbt
   nach der Abschlussquote darauf – 1 Abschluss je 10 bearbeiteten Haushalten ist
   grün, je 100 (oder gar keiner) rot (rot → bernstein → grün, siehe clusterT).
   Die Rampe hält überall dieselbe Helligkeit, darum trägt die Zahl die dunkle
   Textfarbe und keinen Schatten: so bleibt sie auf jedem Zwischenton gleich gut
   lesbar. Weiß wäre auf Bernstein und Grün durchgefallen. --fill kommt aus dem
   Skript, der graue Vorgabewert gilt für Gegenden ohne einen einzigen Ausgang. */
/* Die Blase hängt wie jede Nadel mit ihrer Unterkante am Ort – die halbe Höhe
   zurück, damit ihre MITTE auf der Lage sitzt. Ohne das säße sie um ihren
   halben Durchmesser darüber, und der ist je nach Größe verschieden: zwei
   Blasen übereinander kämen sich damit näher als gerechnet (siehe
   BLASEN_VERSATZ in main.js). */
.cluster {
  --fill: #cbd5e1;
  transform: translateY(50%);
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--fill);
  box-shadow: 0 0 0 2px #fff, 0 3px 10px rgba(15, 23, 42, .42);
  color: var(--ink); font-weight: 700; letter-spacing: -.01em;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}

/* ===========================================================================
   Arbeitsbereich – Querformat: zwei Panels an den Kartenrändern
   =========================================================================== */

.work {
  position: absolute; inset: 0; z-index: 18;
  pointer-events: none;               /* die Lücke gehört der Karte */
  opacity: 0; visibility: hidden;
  transition: opacity .16s ease, visibility .16s ease;
}
.work.open { opacity: 1; visibility: visible; }

.work-cols { display: flex; justify-content: space-between; height: 100%; }

.wp {
  pointer-events: auto;
  background: var(--card);
  display: flex; flex-direction: column;
  min-height: 0;
}
.wp-left  { width: var(--wp-l); border-right: 1px solid var(--line); box-shadow:  8px 0 28px rgba(15, 23, 42, .08); }
.wp-right { width: var(--wp-r); border-left:  1px solid var(--line); box-shadow: -8px 0 28px rgba(15, 23, 42, .08); }

.sheet-grip { display: none; }
/* Zurück von der Detail- auf die Listenseite: gibt es nur auf dem Telefon,
   wo die beiden Spalten hintereinander liegen. Mit .icon-btn davor, weil die
   spätere Regel .icon-btn{display:flex} sonst gewinnt – der Knopf stand damit
   auch am Schreibtisch da, wo er nichts tut. */
.icon-btn.wp-back { display: none; }

/* Kopf eines Panels: bleibt beim Scrollen stehen. */
.wp-head {
  flex: 0 0 auto;
  border-bottom: 1px solid var(--line);
  padding: 9px 10px;
  display: flex; align-items: center; gap: 7px;
  min-height: 50px;
}
.wp-title { flex: 1 1 auto; min-width: 0; }
.wp-title strong {
  display: block; font-size: 14.5px; font-weight: 650; letter-spacing: -.005em; line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.wp-title small {
  display: block; font-size: 11.5px; color: var(--muted); margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.wp-scroll {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  background: #fbfcfe;                /* Kacheln heben sich als Weiß darauf ab */
}
.wp-foot {
  flex: 0 0 auto; border-top: 1px solid var(--line-soft);
  padding: 8px 10px calc(8px + var(--safe-bottom));
}

/* ===========================================================================
   Eingabefelder mit Icon
   =========================================================================== */

.ifield { position: relative; margin-bottom: 7px; }
.ifield:last-child { margin-bottom: 0; }

.ifield-ic {
  position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  display: flex; color: #a5b2c4; pointer-events: none;
  transition: color .15s;
}
.ifield input, .ifield textarea {
  width: 100%; display: block; appearance: none;
  border: 1px solid var(--line); border-radius: var(--r-field);
  background: #fff; color: var(--ink);
  padding: 9px 11px 9px 38px; min-height: 40px;
  font-size: 13.5px;
  transition: border-color .15s, box-shadow .15s;
}
.ifield textarea { min-height: 74px; padding-top: 10px; resize: vertical; line-height: 1.45; }
.ifield-area .ifield-ic { top: 13px; transform: none; }
.ifield input::placeholder, .ifield textarea::placeholder { color: #aab6c6; }
.ifield input:focus, .ifield textarea:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, .12);
}
.ifield:focus-within .ifield-ic { color: var(--accent); }

/* Kompakte Variante für die Adresse im Panelkopf. */
.wp-head .ifield { flex: 1 1 auto; margin: 0; min-width: 0; }
.ifield-sm .ifield-ic { left: 9px; }
.ifield-sm input {
  min-height: 36px; padding: 7px 9px 7px 32px;
  font-size: 13px; font-weight: 600;
}
.a-nr {
  flex: 0 0 50px; width: 50px; text-align: center; appearance: none;
  border: 1px solid var(--line); border-radius: var(--r-field); background: #fff;
  min-height: 36px; padding: 7px 4px; font-size: 13px; font-weight: 600;
  transition: border-color .15s, box-shadow .15s;
}
.a-nr:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(37, 99, 235, .12); }
.a-nr::placeholder { color: #aab6c6; font-weight: 500; }

/* Adresse im Panelkopf: Straße und Nummer in einer Zeile, die PLZ darunter.
   Nebeneinander bliebe vom Straßennamen in der 236px-Spalte zu wenig übrig. */
.wp-adresse { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.wp-adresse-zeile { display: flex; align-items: center; gap: 7px; min-width: 0; }

/* Zweite Zeile im Panelkopf: der Adresszusatz („Hinterhaus", „links") als
   Eingabe, daneben PLZ und Ort zum Lesen. Bewusst eine Stufe leiser als Straße
   und Nummer – die meisten Häuser haben keinen. */
.a-zus {
  flex: 1 1 auto; min-width: 0; appearance: none;
  border: 1px solid var(--line); border-radius: var(--r-field); background: #fff;
  min-height: 30px; padding: 5px 8px;
  font: inherit; font-size: 12px; color: var(--ink-2);
  transition: border-color .15s;
}
.a-zus:focus { outline: none; border-color: var(--accent); color: var(--ink); }
.a-zus::placeholder { color: #b6c1cf; }

/* Die PLZ kommt aus der Karte, nicht aus der Tastatur: kein Feld, sondern eine
   ruhige Angabe unter der Adresse. Solange keine bekannt ist, steht dort
   nichts (hidden) – ein leerer Rahmen wäre eine Aufforderung zum Tippen. */
.a-plz {
  flex: 0 0 auto; align-self: flex-start;   /* nicht auf Spaltenbreite ziehen */
  /* 32px = die Texteinrückung des Straßenfelds (Platz für sein Icon): die PLZ
     steht damit genau unter dem Straßennamen, nicht unter dem Icon. */
  color: var(--muted); padding-left: 32px;
  font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums;
  letter-spacing: .01em; white-space: nowrap;
}
.a-plz[hidden] { display: none; }
/* In der zweiten Zeile steht die PLZ NEBEN dem Feld – die Einrückung, die sie
   unter den Straßennamen schob, gilt dort nicht mehr. */
.wp-adresse-zeile .a-plz { padding-left: 0; margin-left: auto; align-self: center; }

/* ===========================================================================
   Knöpfe
   =========================================================================== */

.icon-btn {
  appearance: none; border: 1px solid var(--line); background: #fff; cursor: pointer;
  width: 34px; height: 34px; border-radius: 10px; flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center; color: var(--ink-2);
  transition: background .15s, color .15s, border-color .15s;
}
.icon-btn:active { background: var(--line-soft); }

/* Der gesonderte Ausgang „Übersprungen" im Panelkopf: als Icon-Knopf getarnt,
   aber mit demselben Ein/Aus wie die Ausgangskacheln – gesetzt füllt er sich
   mit seiner Farbe, damit man den Zustand sieht, ohne nach unten zu schauen. */
.skip-btn.on {
  background: var(--c); border-color: var(--c); color: #fff;
}
.skip-btn.on:active { background: var(--c); opacity: .85; }

.btn {
  appearance: none; cursor: pointer;
  border: 1px solid var(--line); background: #fff; color: var(--ink);
  border-radius: var(--r-tile); padding: 8px 12px; min-height: 38px;
  font-size: 13px; font-weight: 600;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  transition: background .15s, border-color .15s, color .15s;
}
.btn:active { background: var(--line-soft); }
.btn.block { width: 100%; }
.btn.dashed { border-style: dashed; border-color: #d5dde8; color: var(--ink-2); background: transparent; }
.btn.dashed:active { background: #fff; border-color: var(--accent); color: var(--accent); }
.btn.ghost-danger {
  color: #e11d48; border-color: transparent; background: transparent;
  font-weight: 500; min-height: 34px; font-size: 12.5px;
}
.btn.ghost-danger:active { background: #fff1f2; }
/* Der eine bejahende Knopf einer Maske. Gefüllt, damit in einer Reihe gleich
   aussehender Knöpfe erkennbar bleibt, welcher der Hauptweg ist. */
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.primary:active { background: #1d4ed8; border-color: #1d4ed8; }
.btn.ghost { background: transparent; }
.btn[disabled] { opacity: .6; cursor: default; }
/* Verschieben ist ein ZUSTAND, kein Befehl: gedrückt bleibt der Knopf gefüllt,
   solange die Nadel am Finger hängt. Ohne das sähe man nicht, warum die Karte
   sich plötzlich anders anfühlt. */
.btn.move-btn.on {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
.btn.move-btn.on:active { background: #1d4ed8; }

/* ===========================================================================
   Haushaltsliste (linkes Panel) – nach Etagen gruppiert
   =========================================================================== */

/* Kopfzeile des Panels: Etagen-Stepper links, Fortschritt rechts. */
.floor-ctrl {
  position: sticky; top: 0; z-index: 2;
  display: flex; align-items: center; gap: 5px;
  padding: 8px 9px; background: #fbfcfe;
  border-bottom: 1px solid var(--line-soft);
}
.floor-ctrl-label {
  display: flex; align-items: center; gap: 5px; margin-right: auto;
  font-size: 10px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--muted);
}
.floor-ctrl-label svg { color: #b3bfcf; }

.fstep {
  appearance: none; cursor: pointer; flex: 0 0 auto;
  width: 28px; height: 28px; border-radius: 9px;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
  display: flex; align-items: center; justify-content: center;
  transition: background .15s, color .15s, border-color .15s;
}
.fstep:active:not([disabled]):not([aria-disabled="true"]) { background: var(--line-soft); }
/* Zwei Arten von „geht nicht": wirklich gesperrt (nichts anzufassen) und nur
   gerade nicht erlaubt. Das Zweite sieht gleich aus, nimmt den Tipp aber an –
   sonst erführe man auf dem Telefon nie, WARUM es nicht geht. */
.fstep[disabled],
.fstep[aria-disabled="true"] { opacity: .35; cursor: default; }
.fstep-val {
  min-width: 20px; text-align: center;
  font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums;
}

.wpl-count {
  letter-spacing: 0; font-size: 11px; font-weight: 600; color: var(--ink-2);
  background: var(--line-soft); padding: 2px 8px; border-radius: 999px;
  font-variant-numeric: tabular-nums; margin-left: 6px;
}

/* ---- Zonen: „Nicht zugeordnet" plus je eine pro Etage ---- */

.zones { padding: 7px 0 10px; display: flex; flex-direction: column; gap: 8px; }

.zone-head {
  display: flex; align-items: center; gap: 6px;
  padding: 0 10px 5px;
}
.zone-name {
  font-size: 11px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--ink-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.zone-count {
  font-size: 10.5px; font-weight: 600; color: var(--muted);
  background: var(--line-soft); border-radius: 999px; padding: 1px 7px;
  font-variant-numeric: tabular-nums; margin-right: auto;
}
/* „hierher einsortieren" und „+ Haushalt" je Zone. */
.zone-btn {
  appearance: none; cursor: pointer; flex: 0 0 auto;
  width: 26px; height: 26px; border-radius: 8px;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
  display: flex; align-items: center; justify-content: center;
  transition: background .15s, color .15s, border-color .15s;
}
.zone-btn:active { background: var(--line-soft); }
.zone-btn[data-assign] { border-color: #bcd4ff; color: var(--accent); background: #f6faff; }
.zone-btn[data-assign]:active { background: #e8f1ff; }

/* Der Rumpf einer Zone ist zugleich das Ablegeziel beim Ziehen. */
.zone-body { border-radius: var(--r-tile); transition: background .12s; }
.zone-body.over { background: #eef5ff; box-shadow: inset 0 0 0 1.5px #bcd4ff; }

/* Die Zonenknöpfe gibt es zweimal (siehe zone() in main.js): im Kopf für Maus
   und Stift, im Raster für den Daumen. Am Schreibtisch gilt die Kopffassung. */
.zone-acts { display: flex; align-items: center; gap: 5px; }
.zone-acts-grid { display: none; }

/* „leer" steht seit der Telefonfassung als Feld IM Raster, nicht daneben. */
.hh-list > .zone-empty { grid-column: 1 / -1; }
.zone-empty {
  margin: 0; padding: 9px 10px;
  border: 1px dashed #dbe3ee; border-radius: var(--r-tile);
  font-size: 11.5px; color: #b3bfcf; text-align: center;
}
/* Die Ablage hebt sich leicht ab – sie ist keine Etage, sondern ein Zwischenlager. */
.zone-loose .zone-name { color: var(--muted); }
.zone-flat .zone-count { margin-right: auto; }

/* Etagen-Kürzel in Kopfzeile und Übersicht. */
.floor-pill {
  flex: 0 0 auto; display: inline-flex; align-items: center;
  height: 17px; padding: 0 6px; border-radius: 5px; margin-right: 6px;
  background: var(--line-soft); color: var(--ink-2);
  font-size: 10.5px; font-weight: 700; letter-spacing: .02em;
}
.wp-title small { display: flex; align-items: center; }
.wp-title small .wp-addr { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Haushalte als kleine Kacheln, zwei nebeneinander (wie in 3086_vodafone) –
   nur Icon und Name. Wird das Panel zu schmal (Hochformat), fällt das Raster
   von selbst auf eine Spalte zurück. */
.hh-list {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: 5px; padding: 0 9px;
}

.hh-row {
  display: flex; align-items: center; gap: 7px;
  width: 100%; min-width: 0; text-align: left; cursor: pointer;
  border: 1px solid var(--line); border-radius: 10px;
  background: #fff; padding: 5px 7px; min-height: 32px;
  box-shadow: var(--shadow-tile);
  transition: border-color .15s, background .15s, box-shadow .15s;
  /* Senkrecht scrollt die Liste, waagerecht kommt die Geste bei uns an
     (Umsortieren per Wisch – siehe initHhDrag in main.js). */
  touch-action: pan-y;
  /* Die ganze Fläche ist Ziehgriff → iOS-Callout beim Halten unterbinden. */
  -webkit-touch-callout: none; -webkit-user-select: none; user-select: none;
}
.hh-row:active { background: var(--line-soft); }
.hh-row.on {
  border-color: var(--accent); background: #f6faff;
  box-shadow: 0 0 0 3px rgba(37, 99, 235, .1);
}
/* Die Zeile, die gerade gezogen wird, bleibt als blasser Platzhalter stehen. */
.hh-row.dragging { opacity: .32; }

/* Der Klon, der am Finger hängt. */
/* ---- Mülleimer -----------------------------------------------------------
   Steht nur da, solange ein Haushalt in der Luft ist. Fest am unteren
   Bildschirmrand und an `body` gehängt: aus einem Panel heraus wäre er im
   Hochformat nicht erreichbar, und dauerhaft sichtbar lüde er zu Versehen ein. */
.hh-muell {
  position: fixed; z-index: 59;
  left: 50%; bottom: calc(var(--safe-bottom) + 18px);
  transform: translate(-50%, 14px);
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 11px 18px; border-radius: 16px;
  background: var(--card); color: #b91c1c;
  border: 1.5px dashed rgba(185, 28, 28, .45);
  box-shadow: 0 8px 26px rgba(15, 23, 42, .22);
  font-size: 12px; font-weight: 650; text-align: center;
  opacity: 0; pointer-events: none;   /* getroffen wird über die Geometrie */
  transition: opacity .14s ease, transform .14s ease,
              background .14s ease, border-color .14s ease;
}
.hh-muell.da { opacity: 1; transform: translate(-50%, 0); }
/* Finger drüber: aus der gestrichelten Andeutung wird ein festes Ziel. */
.hh-muell.drueber {
  background: #fef2f2; border-style: solid; border-color: #dc2626;
  transform: translate(-50%, 0) scale(1.06);
}
/* Der gezogene Klon tritt dabei zurück – sonst verdeckt er das Ziel, auf das
   er gerade zielt. */
.hh-ghost.vorm-muell { opacity: .5; }

.hh-ghost {
  position: fixed; z-index: 60; pointer-events: none;
  margin: 0; opacity: .96;
  border-color: var(--accent);
  box-shadow: 0 10px 26px rgba(15, 23, 42, .26), 0 0 0 3px rgba(37, 99, 235, .12);
  transform: scale(1.02);
}

/* Icon-Chip mit der Farbe des Ausgangs – ohne Ausgang bleibt er neutral. */
.hh-ic {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 7px;
  display: flex; align-items: center; justify-content: center;
  color: var(--c);
  background: #f1f5f9;
  background: color-mix(in srgb, var(--c) 13%, #fff);
}
.hh-ic.idle { background: var(--line-soft); color: #b9c4d2; }

.hh-name, .hh-kurz {
  flex: 1 1 auto; min-width: 0;
  font-weight: 600; font-size: 12.5px; line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Die Kurzform steht im Markup immer daneben und wird auf dem Telefon
   eingeblendet – ein Umschalten in CSS überlebt das Drehen des Geräts, eine
   Entscheidung beim Zeichnen nicht (siehe kurzName in main.js). */
.hh-kurz { display: none; }

/* ---- Mehrfachauswahl ---- */

/* Kästchen an der Stelle des Ausgangs-Icons, solange die Mehrfachauswahl läuft. */
.hh-pick {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 7px;
  display: flex; align-items: center; justify-content: center;
  border: 1.5px solid #cbd5e1; background: #fff; color: #fff;
}
.hh-row.picked { border-color: var(--accent); background: #f6faff; }
.hh-row.picked .hh-pick { background: var(--accent); border-color: var(--accent); }
.hh-row.picked .hh-name, .hh-row.picked .hh-kurz { color: var(--accent); }

/* Umschalter in der Etagen-Zeile. */
.msel-toggle.on { border-color: var(--accent); background: #eaf2ff; color: var(--accent); }

/* Zeile darunter: Anzahl, Alle/Keine, kurzer Hinweis. */
.msel {
  display: flex; align-items: center; flex-wrap: wrap; gap: 5px;
  margin: 0 9px 2px; padding: 6px 8px;
  border: 1px solid #bcd4ff; border-radius: var(--r-tile); background: #f6faff;
}
.msel-n {
  font-size: 11px; font-weight: 700; color: var(--accent);
  font-variant-numeric: tabular-nums; margin-right: auto;
}
.msel-btn {
  appearance: none; cursor: pointer; flex: 0 0 auto;
  padding: 3px 8px; border-radius: 999px;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
  font-size: 11px; font-weight: 600;
}
.msel-btn:active { background: var(--line-soft); }
.msel-btn[disabled] { opacity: .4; cursor: default; }
.msel-hint { flex: 1 0 100%; font-size: 10.5px; line-height: 1.3; color: var(--muted); }

.hh-flags { display: flex; gap: 3px; flex: 0 0 auto; }
/* Eine Marke je GRUPPE statt je Indikator, mit ihrem Stand: zehn einzelne
   Icons wären in einer Listenzeile nicht mehr auseinanderzuhalten. */
.hh-flag {
  height: 20px; padding: 0 5px; border-radius: 6px; gap: 3px;
  display: flex; align-items: center; justify-content: center;
  background: #eef2f7; color: #64748b;
}
.hh-flag-n { font-size: 10.5px; font-weight: 600; letter-spacing: -.02em; }
/* Vollständig = das grüne Signal, das die Marke früher immer hatte. */
.hh-flag.voll { background: #e7f8ee; color: #15803d; }

/* ===========================================================================
   Abschnitte im rechten Panel
   =========================================================================== */

.sec { padding: 12px; border-bottom: 1px solid var(--line-soft); }
.sec:last-child { border-bottom: 0; }
.sec > h3 {
  margin: 0 0 8px; font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .09em; color: var(--muted);
}

/* Gemeinsamer Icon-Chip für Fortschritts- und Ausgangskacheln. */
.tile-l { display: none; }
.tile-ic {
  flex: 0 0 auto; width: 30px; height: 30px; border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  background: var(--line-soft); color: #a5b2c4;
  transition: background .15s, color .15s;
}

/* Beide Kachelreihen sind reine Icon-Knöpfe: die Beschriftung hängt in
   title/aria-label. So braucht der Fortschritt nur eine und der Ausgang nur
   zwei Reihen. */
.check, .out-btn {
  appearance: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); border-radius: var(--r-tile);
  background: #fff; padding: 5px; min-height: 44px;
  box-shadow: var(--shadow-tile);
  transition: border-color .15s, background .15s;
}
.check:active, .out-btn:active { background: var(--line-soft); }

/* ---- Fortschritt: zwei Gruppen („Daten", „Kunde"), je im selben Raster wie
       die Ausgänge darunter ---- */

/* Der Gruppenkopf ist bewusst kein Knopf: die Gruppe ist die FRAGE, geantwortet
   wird in den Kacheln darunter. Ein Kopf, der sechs Häkchen auf einmal setzt,
   wäre an der Tür zu leicht versehentlich getroffen. */
.cgroup + .cgroup { margin-top: 10px; }
.cgroup-head {
  display: flex; align-items: center; gap: 6px; margin: 0 2px 5px;
  font-size: 11.5px; font-weight: 600; color: var(--muted);
  text-transform: uppercase; letter-spacing: .04em;
}
.cgroup-ic { display: flex; color: #94a3b8; }
.cgroup-l { flex: 1 1 auto; }
/* Der Stand steht rechts und ist die einzige Zahl im Abschnitt — er beantwortet
   „wie weit bin ich hier", ohne dass man Kacheln zählen muss. */
.cgroup-n {
  flex: 0 0 auto; font-variant-numeric: tabular-nums; letter-spacing: 0;
  padding: 1px 6px; border-radius: 999px; background: #eef2f7; color: #64748b;
}
.cgroup.voll .cgroup-n { background: #e7f8ee; color: #15803d; }
.cgroup.voll .cgroup-ic { color: #16a34a; }

.checks { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.check.on { border-color: #b7ebcb; background: #f4fdf7; }
.check.on .tile-ic { background: #16a34a; color: #fff; }

/* ---- Ausgänge: drei je Reihe (wie in 3086_vodafone). Sechs reguläre Ausgänge
       ergeben glatte 3 · 3; „Übersprungen" steht gesondert oben im Kopf. ---- */

.outcomes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }

.out-btn.on {
  /* Rückfall zuerst, danach die color-mix-Variante für neuere Browser. */
  background: #f8fafc; color: var(--ink); border-color: #cbd5e1;
  background: color-mix(in srgb, var(--c) 6%, #fff);
  color: color-mix(in srgb, var(--c) 74%, #0f172a);
  border-color: color-mix(in srgb, var(--c) 42%, #fff);
}
.out-btn.on .tile-ic { background: var(--c); color: #fff; }

/* ---- Verlauf ---- */

.hist { display: flex; flex-direction: column; gap: 2px; }
.hist-row { display: flex; align-items: center; gap: 9px; padding: 4px 0; }
.hist-ic {
  flex: 0 0 auto; width: 24px; height: 24px; border-radius: 7px;
  display: flex; align-items: center; justify-content: center;
  color: var(--c);
  background: #f1f5f9;
  background: color-mix(in srgb, var(--c) 12%, #fff);
}
.hist-label {
  flex: 1 1 auto; font-size: 12.5px; font-weight: 500; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hist-time { flex: 0 0 auto; font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.hist-x {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  color: #cbd5e1; padding: 4px; border-radius: 6px; flex: 0 0 auto;
  display: flex; align-items: center;
}
.hist-x:active { color: #e11d48; background: #fff1f2; }

/* ---- Leerzustände ---- */

.empty { padding: 30px 20px; text-align: center; color: var(--muted); }
.empty svg { color: #cdd7e3; margin: 0 auto 10px; }
.empty p { margin: 0 0 4px; font-size: 13.5px; font-weight: 600; color: var(--ink-2); }
.empty small { font-size: 12px; line-height: 1.5; display: block; }

/* ===========================================================================
   Übersicht
   =========================================================================== */

.list-wrap {
  position: absolute; inset: 0;
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: 16px 16px calc(26px + var(--safe-bottom));
}
/* ---- Filterleiste der Übersicht ----
   Bleibt beim Scrollen oben stehen: bei achthundert Häusern ist der Weg zurück
   nach oben sonst weiter als der zur Karte. Ausgänge und Indikatoren sind
   Icon-Kacheln in der Farbe ihrer Sache – aktiv wird die Fläche eingefärbt,
   inaktiv bleibt nur der graue Umriss. */
.lf {
  position: sticky; top: 0; z-index: 3;
  max-width: 760px; margin: 0 auto 10px; padding: 8px 10px 6px;
  background: #fff; border: 1px solid var(--line); border-radius: 14px;
  box-shadow: 0 2px 10px rgba(15, 23, 42, .06);
}
.lf-row {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  margin-bottom: 6px;
}
.lf-label {
  font-size: 10.5px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--muted); margin-right: 2px;
}
.lf-label:not(:first-child) { margin-left: 6px; }
.lf-chips { display: flex; align-items: center; flex-wrap: wrap; gap: 4px; }

.lf-ic {
  appearance: none; cursor: pointer;
  width: 34px; height: 34px; border-radius: 10px;
  border: 1px solid var(--line); background: #fff; color: #94a3b8;
  display: flex; align-items: center; justify-content: center;
  transition: background .15s, border-color .15s, color .15s;
}
/* Schmaler Strich zwischen „Daten" und „Kunde" in der Filterleiste — in einer
   durchgehenden Reihe aus zehn Icons findet man das gesuchte sonst nicht. */
.lf-sep { flex: 0 0 auto; align-self: stretch; width: 1px; background: var(--line); margin: 3px 3px; }
.lf-ic.on { background: var(--c); border-color: var(--c); color: #fff; }
.lf-ic:active { border-color: var(--c); color: var(--c); }
.lf-ic.on:active { color: #fff; }

.lf-chip {
  appearance: none; cursor: pointer;
  min-height: 30px; padding: 5px 11px; border-radius: 999px;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
  font-size: 12.5px; font-weight: 600;
  transition: background .15s, border-color .15s, color .15s;
}
.lf-chip.on { background: var(--ink); border-color: var(--ink); color: #fff; }

/* Tag-Wähler: sieht aus wie ein Chip, ist aber ein echtes Datumsfeld – auf dem
   iPad öffnet das den Systemkalender. */
.lf-date {
  display: inline-flex; align-items: center; min-height: 30px;
  padding: 0 8px; border-radius: 999px;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
}
.lf-date.on { border-color: var(--ink); background: var(--ink); color: #fff; }
.lf-date input {
  appearance: none; border: 0; background: transparent; color: inherit;
  font-size: 12.5px; font-weight: 600; min-width: 108px; padding: 3px 0;
}
.lf-date input:focus { outline: none; }
.lf-date.on input::-webkit-calendar-picker-indicator { filter: invert(1); }

.lf-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding-top: 2px; font-size: 11.5px; color: var(--muted);
}
.lf-foot b { color: var(--ink-2); }
.lf-reset {
  appearance: none; cursor: pointer; border: 0; background: transparent;
  padding: 4px 2px; font-size: 12px; font-weight: 600; color: var(--accent);
}

.ov-house {
  background: #fff; border: 1px solid var(--line); border-radius: 14px;
  margin: 0 auto 10px; max-width: 760px; overflow: hidden;
  box-shadow: var(--shadow-tile);
}
.ov-head {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border-bottom: 1px solid var(--line-soft); cursor: pointer;
}
.ov-pin {
  flex: 0 0 auto; width: 28px; height: 28px; border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  color: var(--c);
  background: #f1f5f9;
  background: color-mix(in srgb, var(--c) 12%, #fff);
}
.ov-head .ov-addr { flex: 1 1 auto; font-weight: 650; font-size: 14px; }
.ov-head .ov-count { font-size: 12px; color: var(--muted); }
.ov-chev { color: #cbd5e1; display: flex; }

.ov-hh {
  display: flex; align-items: center; gap: 9px; padding: 7px 12px;
  border-bottom: 1px solid var(--line-soft); font-size: 13px;
}
.ov-hh:last-child { border-bottom: 0; }
.ov-hh .hh-ic { width: 26px; height: 26px; border-radius: 8px; }
.ov-hh .ov-name { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ov-kurz { display: none; }
/* Ausgang und Uhrzeit sind ein Paar: auf dem Telefon umbricht die Zeile, und
   getrennt landete die Uhrzeit allein in der zweiten – eine Zeile für vier
   Zeichen. Als eine Einheit wechseln beide zusammen. */
.ov-out { display: flex; align-items: center; gap: 9px; flex: 0 0 auto; }
.ov-badge {
  font-size: 11.5px; font-weight: 600; padding: 3px 9px; border-radius: 999px; white-space: nowrap;
  background: #f1f5f9; color: var(--ink-2);
  background: color-mix(in srgb, var(--c) 12%, #fff);
  color: color-mix(in srgb, var(--c) 78%, #0f172a);
}
.ov-time { font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ===========================================================================
   Kunden – die Abschlussliste
   =========================================================================== */

.kd-sum {
  display: flex; align-items: center; gap: 8px;
  max-width: 760px; margin: 0 auto 10px;
  font-size: 11px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--muted);
}
.kd-sum b { color: var(--ink-2); font-weight: 700; }
.kd-today {
  letter-spacing: 0; text-transform: none; font-weight: 600; font-size: 11.5px;
  background: #e7f8ee; color: #15803d; padding: 2px 9px; border-radius: 999px;
}
.kd-today b { color: inherit; }

/* Geld: zwei Zahlen nebeneinander – was noch kommen kann und was durch ist.
   Der Balken darunter ist ihr Verhältnis, nicht noch eine dritte Aussage. */
.kd-money {
  max-width: 760px; margin: 0 auto 10px; padding: 12px 14px;
  background: #fff; border: 1px solid var(--line); border-radius: 14px;
  box-shadow: var(--shadow-tile);
}
.kd-money-grid { display: flex; gap: 14px; }
.kd-money-cell { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.kd-money-l {
  font-size: 11px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--muted);
}
.kd-money-n {
  font-size: 22px; font-weight: 700; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums; line-height: 1.2;
}
.kd-money-cell--sicher .kd-money-n { color: #15803d; }
.kd-money-s { font-size: 11.5px; color: var(--muted); }
.kd-meter {
  display: block; height: 8px; margin-top: 10px;
  border-radius: 999px; background: var(--line-soft); overflow: hidden;
}
.kd-meter i { display: block; height: 100%; background: #15803d; border-radius: 999px; }
.kd-money-note { margin: 8px 0 0; font-size: 11.5px; line-height: 1.45; color: var(--muted); }

.kd-card {
  background: #fff; border: 1px solid var(--line); border-radius: 14px;
  margin: 0 auto 10px; max-width: 760px; overflow: hidden;
  box-shadow: var(--shadow-tile);
}

.kd-main {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 12px; cursor: pointer;
}
/* Der Haken trägt die Abschlussfarbe – dieselbe wie die Nadel auf der Karte. */
.kd-ic {
  flex: 0 0 auto; width: 30px; height: 30px; border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  color: #15803d; background: #e7f8ee;
}
.kd-body { flex: 1 1 auto; min-width: 0; }
.kd-name {
  display: block; font-weight: 650; font-size: 14px; line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.kd-where {
  display: block; font-size: 11.5px; color: var(--muted); margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.kd-time {
  flex: 0 0 auto; font-size: 11.5px; color: var(--muted);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* Kontaktzeile: Telefon und E-Mail als Direktwahl-Chips. */
.kd-foot {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  padding: 0 12px 11px 52px;
}
.kd-chip {
  display: inline-flex; align-items: center; gap: 6px;
  max-width: 100%; min-height: 32px; padding: 5px 11px;
  border: 1px solid var(--line); border-radius: 999px;
  background: #fbfcfe; color: var(--ink-2);
  font-size: 12.5px; font-weight: 500; text-decoration: none;
  transition: background .15s, border-color .15s, color .15s;
}
.kd-chip svg { flex: 0 0 auto; color: #a5b2c4; }
.kd-chip span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kd-chip:active { background: #eef4ff; border-color: #bcd4ff; color: var(--accent); }
.kd-chip:active svg { color: var(--accent); }
.kd-foot .hh-flags { margin-left: auto; }

.kd-note {
  margin: 0 12px 11px 52px; padding: 8px 10px;
  background: #fbfcfe; border: 1px solid var(--line-soft); border-radius: 10px;
  font-size: 12.5px; line-height: 1.45; color: var(--ink-2);
  white-space: pre-wrap; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}

/* Auf schmalen Geräten rücken Kontakte und Notiz unter das Icon. */
@media (max-width: 560px) {
  .kd-foot, .kd-note { padding-left: 12px; margin-left: 12px; }
  .kd-note { margin-right: 12px; }
}

/* ===========================================================================
   Statistik
   ---------------------------------------------------------------------------
   Ruhige Karten, dünne Marken, haarfeine Raster – die Daten sind das Einzige,
   was laut sein darf. Balken sind schlank (10px) und wachsen aus einer festen
   Grundlinie; das Datenende ist mit 4px gerundet, die Grundlinie bleibt eckig.
   =========================================================================== */

.s-hero, .s-kpis, .s-card, .s-range { max-width: 760px; margin: 0 auto 10px; }

/* Karten nebeneinander (Ausgänge | Abrechnungen), darunter der Trichter über
   beide Spalten. Alle drei sind schmale Zeilenlisten und verschenken einzeln die
   halbe Breite; zu dritt in EINER Reihe bliebe umgekehrt für Beschriftung und
   Balken zu wenig übrig. Die Karten darin geben ihre eigene Breitenbegrenzung
   ab – die übernimmt hier der Rahmen. Gleiche Höhe je Reihe (stretch), sonst
   steht die kürzere Karte als Stufe daneben. */
.s-duo {
  max-width: 760px; margin: 0 auto 10px;
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
}
.s-duo > .s-card { max-width: none; margin: 0; }
/* Über beide Spalten – für den Trichter, der die beiden Karten darüber
   zusammenfasst und dessen Stufen die längsten Beschriftungen tragen. */
.s-duo > .s-card--wide { grid-column: 1 / -1; }
/* Enger als das bleibt für Balken und Beschriftung zu wenig übrig – dann lieber
   alle drei untereinander, in derselben Reihenfolge: Ausgänge, Abrechnungen,
   Trichter. */
@media (max-width: 720px) {
  .s-duo { grid-template-columns: 1fr; }
}

/* ---- Zeitraum: von–bis über der ganzen Auswertung ---- */
.s-range {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  background: #fff; border: 1px solid var(--line); border-radius: 14px;
  padding: 10px 12px; box-shadow: var(--shadow-tile);
}
.s-range-l {
  display: flex; align-items: center; gap: 5px; flex: 0 0 auto;
  font-size: 10px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--muted);
}
.s-range-l svg { color: #b3bfcf; }
.s-range-f {
  display: inline-flex; align-items: center; gap: 6px; min-height: 32px;
  padding: 0 9px; border-radius: 999px;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
}
.s-range-f > span { font-size: 11px; font-weight: 600; color: var(--muted); }
.s-range-f input {
  appearance: none; border: 0; background: transparent; color: inherit;
  font-size: 12.5px; font-weight: 600; min-width: 108px; padding: 4px 0;
  font-variant-numeric: tabular-nums;
}
.s-range-f input:focus { outline: none; }
/* Ein gefülltes Feld hebt sich ab – sonst sieht man dem leeren Platzhalter
   „TT.MM.JJJJ" nicht an, ob der Zeitraum überhaupt greift. Die Klasse setzt
   syncRangeBar: das value-ATTRIBUT taugt nicht als Merkmal, weil der Wert nur
   noch als Eigenschaft gesetzt wird (die Leiste wird nicht mehr neu gebaut). */
.s-range-f.on { border-color: var(--accent); background: #f6faff; color: var(--accent); }
.s-range-info {
  margin-left: auto; font-size: 11.5px; color: var(--muted);
  font-variant-numeric: tabular-nums;
}
/* Schnellwahl: Heute · Woche · Insgesamt. Dieselbe Sprache wie die Zeitchips
   im Filter der Übersicht, damit man sie wiedererkennt. */
.s-range-chips { display: flex; gap: 5px; flex: 0 0 auto; }
.s-range-c {
  appearance: none; cursor: pointer; flex: 0 0 auto;
  padding: 6px 12px; border-radius: 999px;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
  font-size: 12px; font-weight: 600;
  transition: background .15s, color .15s, border-color .15s;
}
.s-range-c:active { background: var(--line-soft); }
.s-range-c.on { background: var(--ink); border-color: var(--ink); color: #fff; }

/* ---- Leitzahl: genau eine pro Ansicht ---- */
.s-hero {
  background: #fff; border: 1px solid var(--line); border-radius: 14px;
  padding: 16px 16px 18px; box-shadow: var(--shadow-tile);
  display: flex; flex-direction: column;
}
.s-hero-label {
  font-size: 10px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--muted);
}
.s-hero-val {
  /* Proportionale Ziffern: tabular-nums lässt große Zahlen locker wirken. */
  font-size: 48px; line-height: 1.05; font-weight: 650; letter-spacing: -.02em;
  color: var(--ink); margin: 6px 0 2px;
}
.s-hero-sub { font-size: 12.5px; color: var(--ink-2); }
/* Zweite Zeile unter der Leitzahl: dieselbe Frage für die Abschlüsse, bei denen
   das Geld wirklich kommt. Abgesetzt durch eine feine Linie, damit sie nicht
   mit der Zeile darüber zu einem Absatz verschwimmt. Der Punkt links trägt das
   Grün, das „Geld sicher" im ganzen Programm hat.
   Den früheren Fortschrittsbalken gibt es hier nicht mehr: er zeigte die
   Prozentquote, und die ist seit 27.08.2026 durch ihren Kehrwert ersetzt –
   „24 Türen" hat keine Skala, die sich füllen ließe. */
.s-hero-sicher {
  display: flex; align-items: center; gap: 7px;
  margin-top: 11px; padding-top: 10px; border-top: 1px solid var(--line-soft);
  font-size: 12.5px; color: var(--ink-2);
}
.s-hero-sicher b { color: var(--ink); font-weight: 650; font-variant-numeric: tabular-nums; }
.s-hero-dot {
  flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%; background: #15803d;
}

/* ---- Kennzahlen-Reihe ---- */
/* Fünf Kacheln: auto-fit statt fester Spaltenzahl, damit die Reihe je nach
   Breite von fünf auf drei oder zwei umbricht, ohne dass eine Kachel ihren Wert
   abschneidet. */
.s-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); gap: 8px; }
.s-kpi {
  background: #fff; border: 1px solid var(--line); border-radius: 12px;
  padding: 11px 12px; box-shadow: var(--shadow-tile);
  display: flex; flex-direction: column; gap: 1px; min-width: 0;
}
.s-kpi-v { font-size: 19px; font-weight: 650; line-height: 1.15; letter-spacing: -.01em; }
/* Umbrechen statt abschneiden: „Produktiv unterwegs" passt in einer Fünferreihe
   auf dem iPad nicht in eine Zeile, und ein gestutztes Kachel-Label ist wertlos. */
.s-kpi-l { font-size: 11.5px; font-weight: 600; line-height: 1.25; color: var(--ink-2); }
.s-kpi-s {
  font-size: 10.5px; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ---- Karten ---- */
.s-card {
  background: #fff; border: 1px solid var(--line); border-radius: 14px;
  padding: 14px; box-shadow: var(--shadow-tile);
}
.s-h {
  margin: 0; font-size: 10px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--muted);
}
.s-sub { margin: 5px 0 13px; font-size: 12px; line-height: 1.45; color: var(--ink-2); }
/* Fußzeile einer Karte: der Satz, der die Zahlen darüber einordnet (die
   Vergleichsquote unter den Abrechnungen). Abgesetzt wie „Geld sicher" unter der
   Leitzahl – mit einer feinen Linie, damit er nicht als weitere Datenzeile
   gelesen wird. */
.s-note {
  margin: 13px 0 0; padding-top: 10px; border-top: 1px solid var(--line-soft);
  font-size: 11.5px; line-height: 1.45; color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.s-note b { color: var(--ink-2); font-weight: 650; }
/* Die Abrechnungskarte hat zwei Stufen und ist damit kürzer als die Ausgänge
   daneben; nebeneinander wird sie auf deren Höhe gezogen. Die Fußzeile setzt
   sich dabei ans untere Ende, statt mitten in der Karte zu schweben – ihre
   Linie liest sich dann als Kartenfuß und nicht als abgerissene Trennung. */
.s-card--abr { display: flex; flex-direction: column; }
.s-card--abr .s-note { margin-top: auto; }

/* Gemeinsame Balkenspur. Die Spur ist eine hellere Stufe derselben Fläche,
   der Balken selbst trägt die Farbe. */
.s-track {
  flex: 1 1 auto; min-width: 40px; height: 10px; border-radius: 999px;
  background: var(--line-soft); overflow: hidden; display: block;
}
.s-track i { display: block; height: 100%; border-radius: 0 4px 4px 0; }

/* ---- Trichter ---- */
.fn { display: flex; flex-direction: column; }
.fn-row { display: flex; align-items: center; gap: 10px; }
.fn-label {
  /* Breit genug für die längste Stufe („Entscheider angetroffen"). */
  flex: 0 0 152px; min-width: 0; font-size: 12.5px; font-weight: 600; line-height: 1.2;
}
.fn-label small {
  display: block; font-size: 10.5px; font-weight: 400; color: var(--muted); margin-top: 1px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.fn-n {
  flex: 0 0 34px; text-align: right; font-size: 13.5px; font-weight: 650;
  font-variant-numeric: tabular-nums;
}
.fn-pct {
  flex: 0 0 42px; text-align: right; font-size: 11.5px; color: var(--muted);
  font-variant-numeric: tabular-nums;
}
/* Übergangsquote zwischen zwei Stufen. */
.fn-step {
  display: flex; align-items: center; gap: 5px;
  margin: 3px 0 3px 162px; padding: 1px 0;
  font-size: 11px; font-weight: 600; color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.fn-arrow { color: #cbd5e1; }

/* ---- Ausgangsverteilung ---- */
.s-rows { display: flex; flex-direction: column; gap: 9px; }
.s-row { display: flex; align-items: center; gap: 9px; }
.s-ic {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  color: var(--c);
  background: #f1f5f9;
  background: color-mix(in srgb, var(--c) 13%, #fff);
}
.s-label {
  flex: 0 0 116px; min-width: 0; font-size: 12.5px; font-weight: 500;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.s-n {
  flex: 0 0 28px; text-align: right; font-size: 13px; font-weight: 650;
  font-variant-numeric: tabular-nums;
}
.s-pct {
  flex: 0 0 42px; text-align: right; font-size: 11.5px; color: var(--muted);
  font-variant-numeric: tabular-nums;
}
/* „davon Geld sicher" hängt unter dem Abschluss: eingerückt und leiser, damit
   auf einen Blick zu sehen ist, dass es eine Teilmenge der Zeile darüber ist
   und keine siebte Klasse (sonst summierten sich die Anteile nicht auf 100 %). */
.s-row--unter { margin-top: -2px; padding-left: 13px; }
.s-row--unter .s-label { color: var(--ink-2); font-weight: 400; }
.s-row--unter .s-n { font-weight: 550; }
/* Kleiner und nur umrandet: ein zweiter voller Farbklecks in derselben Farbe
   ließe die beiden Zeilen gleichrangig aussehen. */
.s-ic--unter {
  width: 22px; height: 22px; border-radius: 7px;
  background: transparent; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c) 32%, #fff);
}

/* ---- Durststrecken: Türen zwischen zwei Abschlüssen ---- */
/* Einklappbare Karte. Die Liste wächst mit jedem Abschluss um eine Zeile und
   schöbe aufgeklappt alles darunter aus dem Bild – zugeklappt bleibt sie eine
   Zeile mit der einen Zahl, für die man sie öffnet.
   Das Polster sitzt an Kopf und Rumpf statt an der Karte: sonst ließe sich die
   zugeklappte Karte nur auf der Schrift antippen, nicht auf ihrer ganzen
   Fläche. */
.s-fold { padding: 0; }
.s-fold > summary {
  cursor: pointer; list-style: none;
  display: flex; align-items: center; gap: 9px; padding: 14px;
  border-radius: 14px;
}
.s-fold > summary::-webkit-details-marker { display: none; }
.s-fold > summary:hover { background: var(--line-soft); }
.s-fold[open] > summary { border-radius: 14px 14px 0 0; }
.s-fold > summary .s-h { flex: 0 0 auto; }
/* Die Kurzfassung für den zugeklappten Zustand. Auf schmalen Geräten darf sie
   abschneiden – die Überschrift daneben muss stehen bleiben. */
.s-fold-sum {
  flex: 1 1 auto; min-width: 0; font-size: 11.5px; color: var(--ink-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.s-fold-ic { flex: 0 0 auto; color: var(--muted); font-size: 12px; transition: transform .15s ease; }
.s-fold[open] .s-fold-ic { transform: rotate(180deg); }
.s-fold-body { padding: 0 14px 14px; }

/* Die laufende Strecke fest über der Liste. Sie beantwortet eine andere Frage
   als die Rangfolge darunter („wie lang kann es werden") – nämlich „wie lang
   ist es JETZT" –, und die soll man nicht erst suchen müssen. */
.du-jetzt {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 7px;
  margin-bottom: 12px; padding: 9px 11px; border-radius: 10px;
  background: #fffbeb; border: 1px solid #fde68a;
}
.du-jetzt-l {
  flex: 0 0 auto; font-size: 9.5px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: #92400e;
}
.du-jetzt-n {
  font-size: 19px; font-weight: 650; line-height: 1.1; color: #7c2d12;
  font-variant-numeric: tabular-nums;
}
.du-jetzt-t { font-size: 11.5px; color: #92400e; margin-left: -3px; }
/* Nimmt die ganze zweite Zeile, sobald es eng wird – Datum, Rang und Schnitt
   stehen sonst halb abgeschnitten neben der Zahl. */
.du-jetzt-m { flex: 1 1 100%; font-size: 10.5px; line-height: 1.4; color: #92400e; }

.du-rows { display: flex; flex-direction: column; gap: 10px; }
/* Dieselbe Strecke wie oben, hier an ihrem Platz nach Länge: erst der Vergleich
   mit den anderen sagt, ob das gerade normal ist oder die schlimmste Strecke
   bisher. Ihre Rangnummer behält sie – sie ist die Nummer, die die Zeile
   „Aktuell" nennt, und eine Lücke in der Zählung sähe nach einem Fehler aus. */
.du-row--jetzt {
  margin: -4px -6px; padding: 4px 6px; border-radius: 8px;
  background: #fffbeb; box-shadow: inset 0 0 0 1px #fde68a;
}
.du-row--jetzt .du-rank { color: #b45309; font-weight: 700; }
.du-row--jetzt .du-n { color: #7c2d12; font-weight: 700; }
.du-row { display: flex; align-items: flex-start; gap: 9px; }
.du-rank {
  flex: 0 0 18px; text-align: right; line-height: 16px;
  font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums;
}
.du-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.du-head { display: flex; align-items: center; gap: 8px; }
.du-n {
  flex: 0 0 30px; text-align: right; font-size: 13px; font-weight: 650;
  font-variant-numeric: tabular-nums;
}
/* Datum, Dauer und die Adresse, an der es wieder klappte. Darf umbrechen: eine
   abgeschnittene Adresse ist hier wertlos, und zwei Zeilen sind kein Schaden. */
.du-meta { font-size: 10.5px; line-height: 1.4; color: var(--muted); overflow-wrap: anywhere; }
/* Merker für die angeschnittenen Strecken (laufend oder vor dem ersten
   Abschluss) – sagt in Worten, was der hellere Balken andeutet; die Farbe
   allein trägt es nicht. Er sitzt IN der Textzeile: als Chip hinter dem Balken
   verkürzte er dessen Spur, und die Balken zweier Zeilen wären nicht mehr
   vergleichbar. */
.du-flag {
  /* Nicht umbrechen: sonst reißt der helle Hintergrund auf dem Telefon mitten
     im Wort ab. Passt er nicht mehr, rutscht er als Ganzes in die nächste
     Zeile. */
  display: inline-block; white-space: nowrap;
  padding: 1px 5px; border-radius: 5px; font-weight: 700;
  color: #92400e; background: #fef3c7;
}
.du-row--roh .du-n { font-weight: 550; color: var(--ink-2); }

/* ---- Beste Uhrzeit: potenzielle Kunden je halbe Stunde ---- */
/* Eine Zeilentabelle wie „Ausgänge", nur mit Zeitspalte statt Icon. Eigene
   Spaltenbreiten, weil hier zwei Zahlen nebeneinander stehen (Türen und
   Quote) und „11:30–12:00" breiter ist als ein Ausgangsname. */
/* Maßauswahl: sieben Knöpfe (potenzielle Kunden + die sechs Ausgänge). Wie die
   Zeitraum-Schnellwahl gebaut, nur mit Farbpunkt – der Punkt ist dieselbe
   Farbe, die der Balken danach trägt. Sie brechen um statt zu scrollen: eine
   waagerecht scrollende Reihe verbirgt auf dem Telefon die Hälfte der Auswahl. */
.tz-chips { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 12px; }
.tz-chip {
  appearance: none; cursor: pointer; flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 11px; border-radius: 999px;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
  font-size: 12px; font-weight: 600;
  transition: background .15s, color .15s, border-color .15s;
}
.tz-chip i { width: 9px; height: 9px; border-radius: 999px; flex: 0 0 auto; }
.tz-chip:active { background: var(--line-soft); }
.tz-chip.on { background: var(--ink); border-color: var(--ink); color: #fff; }
/* Der Punkt braucht auf dem dunklen Knopf einen hellen Rand, sonst verliert
   sich ein dunkles Rot (Ungeeignet) im Schwarz. */
.tz-chip.on i { box-shadow: 0 0 0 1.5px rgba(255, 255, 255, .85); }

.tz-kopf { margin: 0 0 11px; font-size: 12.5px; color: var(--ink-2); }
.tz-kopf b { color: var(--ink); }
.tz-hint { color: var(--muted); }
.tz-rows { display: flex; flex-direction: column; gap: 5px; }
/* Der Innenabstand liegt auf JEDER Zeile, nicht nur auf der hervorgehobenen:
   sonst bräuchte die beste Zeile einen negativen Außenrand, um ihre Tönung
   über die Kante zu ziehen – und der schob die Tabelle um 7px über den
   Kartenrand hinaus (auf dem Telefon sichtbar als waagerechtes Scrollen). */
.tz-row { display: flex; align-items: center; gap: 9px; padding: 3px 7px; }
.tz-t {
  flex: 0 0 94px; font-size: 12.5px; font-variant-numeric: tabular-nums;
  display: flex; align-items: center; gap: 4px;
}
.tz-t b { color: #b45309; font-size: 11px; }        /* ★ der besten Halbstunde */
.tz-n {
  flex: 0 0 38px; text-align: right; font-size: 12.5px;
  color: var(--ink-2); font-variant-numeric: tabular-nums;
}
.tz-q {
  flex: 0 0 50px; text-align: right; font-size: 13px; font-weight: 650;
  font-variant-numeric: tabular-nums;
}
/* Kopfzeile: dieselben Spalten, damit die Zahlen unter ihrer Überschrift stehen. */
.tz-head, .tz-head .tz-t, .tz-head .tz-n, .tz-head .tz-q {
  font-size: 9.5px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted);
}
.tz-legend {
  flex: 1 1 auto; min-width: 40px; font-size: 9.5px; font-weight: 600;
  letter-spacing: .02em; text-transform: none; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tz-legend-l + .tz-legend-h::before { content: ' · '; }
/* Der Strich sitzt auf dem Tagesschnitt – „über/unter" ohne Kopfrechnen.
   Er muss auf BEIDEN Untergründen lesbar sein: liegt die Quote über dem
   Schnitt, steht er im dunklen Balken, sonst auf der hellen Spur. Also weiß
   mit dünnem dunklem Hof statt einfach dunkel – ein dunkler Strich wäre im
   Balken unsichtbar, genau bei den guten Zeiten. Die Spur bleibt beschnitten
   (.s-track), damit der Balken ihrer runden Kante folgt. */
.tz-track { position: relative; height: 9px; }
.tz-track u {
  position: absolute; top: 0; bottom: 0; left: var(--tz-avg);
  width: 1px; background: rgba(255, 255, 255, .95);
  box-shadow: 0 0 0 .5px rgba(15, 23, 42, .45);
}
/* Zu wenige Türen: graue Schrift, dazu ein schraffierter Balken (gesetzt im
   Skript). Kein opacity auf der ganzen Zeile – die Uhrzeit soll lesbar
   bleiben, nur ihr Gewicht soll verschwinden. Den Stern trägt sie nie. */
.tz-thin .tz-t, .tz-thin .tz-n, .tz-thin .tz-q { color: var(--muted); }
.tz-thin .tz-q { font-weight: 500; }
.tz-best { background: #eff6ff; border-radius: 8px; }

/* ---- Verlauf ---- */
.tr-legend { display: flex; gap: 14px; margin-bottom: 10px; }
.tr-key { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--ink-2); }
.tr-key i { width: 10px; height: 10px; border-radius: 3px; flex: 0 0 auto; }

/* Höhe schließt das Achsenband ein, damit nichts abgeschnitten wird. */
.tr-plot { display: flex; align-items: flex-end; gap: 4px; height: 148px; }
.tr-col {
  flex: 1 1 0; min-width: 0; height: 100%;
  display: flex; flex-direction: column; align-items: center;
}
.tr-stack {
  flex: 1 1 auto; width: 100%; max-width: 24px; align-self: center;
  display: flex; flex-direction: column; justify-content: flex-end;
  position: relative; gap: 2px;                 /* 2px Flächenlücke im Stapel */
}
.tr-seg { display: block; width: 100%; }
.tr-cap { border-radius: 4px 4px 0 0; }         /* gerundetes Datenende oben */
.tr-max {
  position: absolute; top: -15px; left: 50%; transform: translateX(-50%);
  font-size: 10px; font-weight: 650; color: var(--ink-2);
}
.tr-x {
  flex: 0 0 auto; height: 18px; line-height: 18px;
  font-size: 9.5px; color: var(--muted); font-variant-numeric: tabular-nums;
}

/* Tabellen-Zwilling: jeder Wert ist auch ohne Diagramm lesbar. */
.s-table { margin-top: 12px; border-top: 1px solid var(--line-soft); padding-top: 10px; }
.s-table summary {
  cursor: pointer; font-size: 11.5px; font-weight: 600; color: var(--ink-2);
  list-style: none; display: flex; align-items: center; gap: 6px;
}
.s-table summary::-webkit-details-marker { display: none; }
.s-table summary::before { content: '▸'; color: var(--muted); }
.s-table[open] summary::before { content: '▾'; }
.s-table table { width: 100%; border-collapse: collapse; margin-top: 9px; }
.s-table th, .s-table td {
  text-align: right; padding: 4px 6px; font-size: 11.5px;
  font-variant-numeric: tabular-nums; border-bottom: 1px solid var(--line-soft);
}
.s-table th { color: var(--muted); font-weight: 600; }
.s-table th:first-child, .s-table td:first-child { text-align: left; }

/* ===========================================================================
   Season: ein Monat, zwei Zahlen
   =========================================================================== */
/* Helle Karte wie der Rest der App (die dunkle Tacho-Karte ist am 27.08.2026
   gefallen). Zu sehen ist immer genau EIN Monat; durch die übrigen führen die
   Pfeile in der Kopfzeile. Auf der Karte stehen zwei Zahlen und ein Kalender –
   keine Legende, keine Nebenzahlen, keine Erklärung. */

.se-card {
  max-width: 560px; margin: 0 auto 12px;
  background: var(--card); border: 1px solid var(--line); border-radius: 20px;
  padding: 16px; box-shadow: var(--shadow-tile); color: var(--ink);
}

.se-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.se-monat {
  font-size: 13px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase;
}
/* Wie die Tagesschritte im Verlauf gebaut – dieselbe Geste, dieselbe Form. */
.se-nav {
  appearance: none; cursor: pointer; flex: 0 0 auto;
  width: 34px; height: 34px; border-radius: 999px;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
  display: flex; align-items: center; justify-content: center;
}
.se-nav:active { background: var(--line-soft); }
.se-nav:disabled { opacity: .3; cursor: default; }
/* Es gibt nur EIN Chevron im Symbolsatz – der Rückwärtspfeil ist dasselbe,
   gedreht. */
.se-nav[data-se-nav="1"] svg { transform: rotate(180deg); }

/* Die beiden Zahlen, um die es geht. Nebeneinander und gleich groß: keine ist
   die wichtigere, und untereinander stünde die zweite unter der Falz. */
.se-zahlen { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin: 16px 0 4px; }
.se-z { display: flex; flex-direction: column; min-width: 0; }
.se-z-v {
  font-size: 46px; line-height: 1; font-weight: 700; letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}
.se-z-l {
  margin-top: 5px;
  font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted);
}

/* ---- Der Monat als Kalender ----------------------------------------------
   Sieben Spalten, Montag bis Sonntag. Ein fortlaufender Streifen wäre kürzer,
   aber dann stünden die Sonntage verstreut – im Raster liegen sie in EINER
   Spalte, und dass sie ausgenommen sind, erklärt sich ohne einen Satz dazu. */
.se-gitter {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 5px;
  margin-top: 16px;
}
.se-wt {
  text-align: center; padding-bottom: 2px;
  font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted);
}
.se-wt--so { color: #cbd5e1; }

/* In den Feldern steht die Zahl, auf die der Umschalter zeigt: die Punkte des
   Tages oder seine Zähler – und seit dem 02.09.2026 IMMER, auch die Null. Vorher
   trug das Feld nur einen Zähler, sonst nichts, und seine Punktzahl steckte
   allein in der Farbe; seit die Punkte in Zwanzigerschritten bis fünfzehn laufen,
   trägt keine Farbskala das mehr. Welcher Tag ein Feld ist, sagt seine Stelle im
   Kalender. */
.se-tag {
  aspect-ratio: 1; border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums;
  background: var(--se-bg, #fff); color: var(--se-fg, var(--ink));
  box-shadow: inset 0 0 0 1px var(--se-li, var(--line));
  cursor: default;
}
/* Die Felder vor dem Ersten: nur Platzhalter, damit der Erste auf seinem
   Wochentag sitzt. */
.se-tag--luecke { background: none; box-shadow: none; }

/* Rot → Gelb → Grün über die ganze Punkteskala (02.09.2026 so bestellt): 0 ganz
   rot, 4 zwischen Rot und Gelb, 7–8 die gelbe Mitte, ab 12 grün. Vorher lief
   die Rampe von Weiß nach Dunkelgrün, in EINEM Farbton – bei fünf Stufen ging
   das, bei sechzehn nicht mehr: sechzehn Grüntöne sind auf einem Kalenderfeld
   nicht auseinanderzuhalten, ein Rot dagegen erkennt man aus dem Augenwinkel.
   Ein leerer Tag ist damit auch nicht mehr nur „weniger", sondern rot.

   Die Töne sind GEDÄMPFT („die farben sollen etwas dezenter sein", 02.09.2026):
   die Buntheit auf 55 %, die Helligkeit zur Mitte gezogen. Die reinen Farben
   nahmen als Kalenderwand das ganze Blatt ein, vor allem im Orange-Gelb-Band.
   Der Farbton trägt die Aussage – die Grellheit muss sie nicht mittragen.

   DIESE SECHZEHN ZEILEN SIND ERZEUGT, NICHT GESETZT: `tools/season-rampe.py`
   interpoliert in OKLCH zwischen vier Stützstellen (#d92d20 · #f5c518 bei 7,5 ·
   #3ab54a bei 12 · #15803d bei 15) und dämpft anschließend. Eine Mischung in
   sRGB liefe durch matschige Zwischentöne und spränge ausgerechnet in der Mitte
   in der Helligkeit; in OKLCH sind die Schritte gleich groß, so wie das Auge sie
   sieht. Auch die Schrift kommt von dort: je Stufe ein dunkler Ton DESSELBEN
   Farbtons statt Schwarz, gesucht als hellste Stufe mit noch 4,5:1 (die Zahl ist
   14px und damit kein „großer Text" im Sinne der WCAG); schlechtester Wert der
   Reihe 4,50:1.

   Wer eine Stützstelle verschiebt, lässt das Skript laufen und ersetzt den Block
   – einzelne Werte nachzubessern zerstört die Gleichmäßigkeit der Reihe. */
.se-tag[data-s="0"]  { --se-bg: #d2786a; --se-fg: #4c110b; --se-li: #c05b4e; }
.se-tag[data-s="1"]  { --se-bg: #d68167; --se-fg: #571e0b; --se-li: #c46548; }
.se-tag[data-s="2"]  { --se-bg: #d98a65; --se-fg: #5c2506; --se-li: #c76f44; }
.se-tag[data-s="3"]  { --se-bg: #db9465; --se-fg: #602d00; --se-li: #c87941; }
.se-tag[data-s="4"]  { --se-bg: #dc9e66; --se-fg: #5d3000; --se-li: #c98341; }
.se-tag[data-s="5"]  { --se-bg: #dca86a; --se-fg: #603800; --se-li: #c98e44; }
.se-tag[data-s="6"]  { --se-bg: #dbb16f; --se-fg: #624000; --se-li: #c79849; }
.se-tag[data-s="7"]  { --se-bg: #dabb77; --se-fg: #5d4300; --se-li: #c5a351; }
.se-tag[data-s="8"]  { --se-bg: #d0c078; --se-fg: #564700; --se-li: #bba753; }
.se-tag[data-s="9"]  { --se-bg: #bebe75; --se-fg: #4c4b00; --se-li: #a7a751; }
.se-tag[data-s="10"] { --se-bg: #aabc75; --se-fg: #3c4902; --se-li: #91a653; }
.se-tag[data-s="11"] { --se-bg: #94ba79; --se-fg: #29470d; --se-li: #79a45a; }
.se-tag[data-s="12"] { --se-bg: #7db87f; --se-fg: #17491d; --se-li: #5fa263; }
.se-tag[data-s="13"] { --se-bg: #77ae7c; --se-fg: #063e14; --se-li: #599860; }
.se-tag[data-s="14"] { --se-bg: #71a478; --se-fg: #023913; --se-li: #548e5e; }
.se-tag[data-s="15"] { --se-bg: #6b9a74; --se-fg: #002d0e; --se-li: #4f855b; }

/* Der Umschalter über dem Kalender: Aktivität oder Zähler. Dieselben Chips wie
   die Zeitraum-Schnellwahl im Statistik-Tab – es ist dieselbe Geste (aus zwei
   Sichten auf dieselben Daten eine wählen), also dieselbe Form. */
.se-um { display: flex; gap: 5px; margin-top: 14px; }
.se-um-c {
  appearance: none; cursor: pointer; flex: 0 0 auto;
  padding: 6px 12px; border-radius: 999px;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
  font-size: 12px; font-weight: 600;
  transition: background .15s, color .15s, border-color .15s;
}
.se-um-c:active { background: var(--line-soft); }
.se-um-c.on { background: var(--ink); border-color: var(--ink); color: #fff; }

/* Sonn- und Feiertage: kein Arbeitstag, also auch kein leeres Feld, das nach
   Versäumnis aussieht. Grau statt Rampe. Beide sehen gleich aus, weil sie
   dasselbe bedeuten; WELCHER Tag es ist, sagt der Hinweis.

   Das Grau greift aber NUR bei Stufe 0 – daher der Attributwert in der Regel,
   und nicht bloß die Klasse. Punkte bringt ein freier Tag keine, in der Spalte
   „Aktivität" steht dort also immer eine blasse Null. Ein ZÄHLER dagegen, der
   an einem Sonntag zustande kam, ist ein echter Zähler (er steckt auch in der
   Kopfzahl) – in der Spalte „Zähler" bekommt das Feld deshalb seine Farbe wie
   jedes andere, samt der Schrift, die darauf lesbar ist. */
.se-tag--frei[data-s="0"] { --se-bg: var(--line-soft); --se-fg: #cbd5e1; --se-li: transparent; }
/* Tage, die noch kommen: da steht nichts, weil noch nichts sein KANN. */
.se-tag--offen { opacity: .4; }

/* ---- Die Auswertung unter dem Kalender -----------------------------------
   Eine nackte Liste: links die Frage, rechts die Zahl. Keine Balken, keine
   Anteile – die Karte darüber ist die Übersicht, das hier das Nachschlagewerk.
   Die drei Gruppen (Aufwand je Zähler · Umfang · Lauf) trennt eine feine Linie
   statt einer Überschrift; ihre Zugehörigkeit erklärt sich aus den Zeilen. */
.se-card--liste { padding: 12px 14px 14px; }
/* Fünf Kategorien (27.08.2026). Die Überschrift ist klein, leise und gesperrt –
   dieselbe Sprache wie die Abschnittsmarken im Statistik-Tab. Sie soll
   gliedern, nicht die Werte übertönen. */
.se-gruppe + .se-gruppe { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line); }
.se-gh {
  margin: 0 0 7px;
  font-size: 10px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted);
}
/* Dreierreihen statt Zeilen (27.08.2026): dreizehn Werte untereinander sind zwei
   Bildschirme, dieselben dreizehn in Kacheln ein halber – und darum ging es,
   „alles auf einen Blick". Feste drei Spalten, nicht auto-fit: so stehen die
   Kacheln aller Kategorien untereinander in einer Flucht, auch wenn eine
   Kategorie nur zwei Werte hat. Der Wert oben und groß, die Beschriftung klein
   darunter – gesucht wird die Zahl. */
/* Feste drei Spalten für ALLE Kategorien – so fluchten die Kacheln über die
   ganze Karte hinweg. Eine Kategorie mit sieben Werten (Schnitt) füllt damit von
   selbst drei Reihen: 3 · 3 · 1. */
.se-kacheln { display: grid; gap: 7px; grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* Kacheln, die paarweise zusammengehören (Geld: Betrag → Stundenlohn, einmal
   sicher, einmal potenziell). Im Dreierraster rutschte das zweite Paar
   auseinander; zu zweit steht jeder Stundenlohn neben seinem Betrag. */
.se-kacheln--paare { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.se-k {
  display: flex; flex-direction: column; gap: 1px; min-width: 0;
  padding: 9px 10px; border-radius: 11px;
  background: var(--line-soft);
  cursor: default;
}
.se-k-v {
  font-size: 16px; font-weight: 700; line-height: 1.15; letter-spacing: -.01em;
  color: var(--ink); font-variant-numeric: tabular-nums;
}
/* Umbrechen statt abschneiden: „Türen je Zähler" passt auf dem Telefon nicht in
   eine Zeile, und ein gestutztes Kachel-Label ist wertlos. */
.se-k-l { font-size: 10.5px; font-weight: 600; line-height: 1.25; color: var(--ink-2); }

@media (max-width: 460px) {
  .se-z-v { font-size: 38px; }
  .se-tag { border-radius: 7px; font-size: 11px; }
  .se-um-c { padding: 6px 11px; min-height: 34px; }
  .se-gitter { gap: 4px; }
  .se-k { padding: 8px 8px; border-radius: 9px; }
  .se-k-v { font-size: 14.5px; }
  .se-k-l { font-size: 10px; }
  .se-kacheln { gap: 6px; }
  .se-gh { font-size: 9.5px; }
}

/* ===========================================================================
   Followups: Terminzeile, Termin-Blatt, Liste
   =========================================================================== */

/* ---- Aus der Auswertung genommen -----------------------------------------
   Ein KLEINER Schalter am Fuß der Spalte – einmal unter der Haushaltskarte,
   einmal unter dem Treppenhaus fürs ganze Haus (02.09.2026: „dieser schalter
   soll ganz unten kleiner sein"). Vorher war es eine breite Zeile mit zwei
   Textzeilen; die erklärte sich beim ersten Mal und stand danach für immer im
   Weg. Die Erklärung ist in den Hinweis gewandert.

   Klein heißt leise, nicht unsichtbar: angeschaltet wird die Pille deutlich
   rot. Eine Auswertung, aus der stillschweigend etwas fehlt, ist schlimmer als
   ein Knopf zu viel. */
.sec-wertung { padding-top: 2px; }
.aw-btn {
  appearance: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 10px; border-radius: 999px;
  border: 1px dashed var(--line); background: #fff; color: var(--ink-2);
  font-size: 11px; font-weight: 600; line-height: 1.3;
}
.aw-btn:active { background: var(--line-soft); }
.aw-btn svg { flex: 0 0 auto; color: var(--muted); }
.aw-btn.on {
  border-style: solid; border-color: #fca5a5; background: #fef2f2; color: #b91c1c;
}
.aw-btn.on svg { color: #dc2626; }

/* Die Nadel eines ausgeschlossenen Hauses behält Farbe und Zahl – bearbeitet
   ist bearbeitet – und tritt nur zurück: blasser, mit gestricheltem Ring statt
   des weißen Randes. So bleibt sie auf der Karte auffindbar, sieht aber nicht
   mehr aus wie eine Nadel, die in der Gegendbewertung mitredet. */
.pin.aus {
  opacity: .55;
  border-style: dashed;
  box-shadow: 0 0 0 1.5px rgba(185, 28, 28, .55), 0 2px 6px rgba(15, 23, 42, .3);
}

/* Die Kachel im Treppenhaus bleibt in ihrer Ausgangsfarbe – bearbeitet ist
   bearbeitet –, tritt aber zurück. Der Hinweis am Knopf nennt den Grund. */
.hh-row--aus { opacity: .45; }
.hh-row--aus .hh-name, .hh-row--aus .hh-kurz { text-decoration: line-through; }

/* Dieselbe Aussage als Marke in der Kundenkarte. Rot statt der Spartenfarbe:
   sie sagt nicht, WAS es war, sondern dass es nicht mitzählt. */
.kd-sparte--aus { --c: #b91c1c; }

/* ---- Sparten eines Abschlusses -------------------------------------------
   Zwei Knöpfe unter den Ausgangs-Kacheln, sichtbar nur bei einem Abschluss:
   Strom, Gas – oder beides, und dann sind es zwei Zähler an einer Tür
   (02.09.2026). Bewusst KEINE eigene Sektion mit Überschrift: die Sparte
   gehört zum Ausgang und nicht neben ihn, genauso wie die Terminzeile darunter
   zum Followup gehört.

   Angeschaltet ist der Knopf voll in seiner Farbe. Die beiden Töne sind
   dunkler gewählt, als man Strom und Gas malen würde (#a16207 statt eines
   hellen Bernstein): auf dem angeschalteten Knopf steht weiße Schrift, und die
   hellen Töne kamen dabei nicht über 3:1. */
.sp-line { display: flex; align-items: center; gap: 6px; margin-top: 8px; flex-wrap: wrap; }
.sp-btn {
  appearance: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 5px;
  padding: 6px 11px; border-radius: 999px;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
  font-size: 12px; font-weight: 600;
  transition: background .15s, color .15s, border-color .15s;
}
.sp-btn:active { background: var(--line-soft); }
.sp-btn svg { color: var(--c); }
.sp-btn.on { background: var(--c); border-color: var(--c); color: #fff; }
.sp-btn.on svg { color: #fff; }
/* „2 Zähler" steht nur da, wenn wirklich beides an ist – die Zahl ist der
   ganze Zweck des Doppelklicks und soll nicht erst im Season-Tab auftauchen. */
.sp-note {
  font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted);
}

/* Dieselbe Aussage im Kunden-Tab, aber als bloße Marke am Namen: dort wird
   nachgeschlagen, nicht geschaltet. Nur Farbe und Wort, kein Rahmen – die Karte
   hat schon genug Kästen. */
.kd-name--sp { display: flex; align-items: center; gap: 6px; }
/* Der Name muss für sich abschneiden können, sonst schiebt ein langer Name die
   Marken aus der Karte. */
.kd-name-t { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kd-sparte {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 3px;
  color: var(--c); font-size: 10px; font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase;
}

/* Zeile unter den Ausgangs-Knöpfen: der Termin des Followups. Der farbige
   Streifen links ist die Dringlichkeit – dieselbe Skala wie am Tab-Zähler. */
.fu-line {
  appearance: none; cursor: pointer; width: 100%; margin-top: 8px;
  display: flex; align-items: center; gap: 8px;
  padding: 9px 11px; border-radius: 11px; text-align: left;
  border: 1px solid var(--line); background: #fff; color: var(--ink);
  border-left: 4px solid var(--fu-c, var(--line));
  font-size: 12.5px;
}
.fu-line:active { background: var(--line-soft); }
.fu-line svg { color: var(--fu-c, var(--muted)); flex: 0 0 auto; }
.fu-line-t { font-weight: 700; font-variant-numeric: tabular-nums; }
.fu-line-r { margin-left: auto; color: var(--ink-2); font-size: 11.5px; }
.fu-line--leer { border-style: dashed; color: var(--ink-2); }

/* ---- Termin-Blatt ---- */
.fu-modal {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(15, 23, 42, .55);
  display: flex; align-items: center; justify-content: center; padding: 18px;
}
.fu-modal[hidden] { display: none; }
.fu-sheet {
  width: 100%; max-width: 380px;
  background: #fff; border-radius: 18px; padding: 16px;
  box-shadow: 0 18px 50px rgba(15, 23, 42, .35);
  padding-bottom: calc(16px + var(--safe-bottom));
}
.fu-sheet h3 { margin: 0; font-size: 15px; }
.fu-hint { margin: 3px 0 12px; font-size: 12px; color: var(--muted); }
/* Schnellwahl: die vier Fälle, die an der Tür wirklich vorkommen. */
.fu-quick { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 11px; }
.fu-quick button {
  appearance: none; cursor: pointer;
  padding: 6px 11px; border-radius: 999px;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
  font-size: 12px; font-weight: 600;
}
.fu-quick button:active { background: var(--line-soft); }
.fu-fields { display: flex; gap: 8px; }
.fu-f {
  flex: 1 1 0; display: flex; flex-direction: column; gap: 3px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted);
}
.fu-f input {
  appearance: none; width: 100%; min-height: 40px; padding: 0 10px;
  border: 1px solid var(--line); border-radius: 11px; background: #fff;
  color: var(--ink); font-size: 14px; font-weight: 600;
  letter-spacing: 0; text-transform: none; font-variant-numeric: tabular-nums;
}
.fu-f input:focus { outline: none; border-color: var(--accent); }
.fu-vorschau {
  display: flex; align-items: center; gap: 7px;
  margin: 11px 0 13px; font-size: 12.5px; color: var(--ink-2);
}
.fu-vorschau i { width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto; }
.fu-actions { display: flex; gap: 7px; }
.fu-btn {
  appearance: none; cursor: pointer; flex: 1 1 auto;
  min-height: 42px; padding: 0 12px; border-radius: 12px;
  font-size: 13px; font-weight: 700; border: 1px solid var(--line);
}
.fu-btn--ghost { background: #fff; color: var(--ink-2); }
.fu-btn--ok { background: var(--accent); border-color: var(--accent); color: #fff; flex: 1.3 1 auto; }
.fu-btn--ok:disabled { opacity: .45; cursor: default; }

/* ---- Liste ---- */
.fu-tag {
  letter-spacing: 0; text-transform: none; font-weight: 600; font-size: 11.5px;
  background: var(--line-soft); color: var(--ink-2); padding: 2px 9px; border-radius: 999px;
}
.fu-tag b { color: inherit; }
.fu-tag--weg { background: #fdeaea; color: #b91c1c; }
.fu-tag--heute { background: #fff4d6; color: #92610a; }

.fu-legend {
  display: flex; flex-wrap: wrap; gap: 12px;
  max-width: 760px; margin: 0 auto 10px;
  font-size: 11px; color: var(--ink-2);
}
.fu-key { display: flex; align-items: center; gap: 6px; }
.fu-key i { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; }

.fu-card {
  background: #fff; border: 1px solid var(--line); border-radius: 14px;
  margin: 0 auto 10px; max-width: 760px; overflow: hidden;
  box-shadow: var(--shadow-tile);
  border-left: 5px solid var(--fu-c, #94a3b8);
}
.fu-card--weg { background: #fffafa; }
.fu-main { display: flex; align-items: center; gap: 10px; padding: 11px 12px; cursor: pointer; }
.fu-dot {
  flex: 0 0 auto; width: 11px; height: 11px; border-radius: 50%;
  background: var(--fu-c, #94a3b8);
}
.fu-when {
  flex: 0 0 auto; display: flex; flex-direction: column; align-items: flex-end; gap: 1px;
  font-variant-numeric: tabular-nums;
}
.fu-when b { font-size: 12.5px; color: var(--ink); }
.fu-when small { font-size: 11px; color: var(--ink-2); }
.fu-card--weg .fu-when small { color: #b91c1c; font-weight: 600; }

.fu-row-act { display: flex; gap: 7px; padding: 0 12px 11px; }
.fu-mini {
  appearance: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 11px; border-radius: 999px;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
  font-size: 12px; font-weight: 600;
}
.fu-mini:active { background: var(--line-soft); }

/* ---- Arbeitstag: Tagesprotokoll aus Arbeitsblöcken und Pausen ----
   Ein Tag von der ersten bis zur letzten Tür: erst als Streifen im
   Längenverhältnis, darunter dieselben Abschnitte als lesbare Zeilen. Farbe
   trägt nie allein – jede Zeile nennt Art und Dauer im Klartext. */

.dl-bar { display: flex; align-items: center; gap: 7px; margin-bottom: 12px; }
.dl-step {
  appearance: none; cursor: pointer; flex: 0 0 auto;
  width: 32px; height: 32px; border-radius: 999px;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
  display: flex; align-items: center; justify-content: center;
}
.dl-step:active { background: var(--line-soft); }
.dl-step:disabled { opacity: .35; cursor: default; }
/* Es gibt nur EIN Chevron im Symbolsatz – der Rückwärtspfeil ist dasselbe,
   gedreht. */
.dl-step[data-dl-step="-1"] svg { transform: rotate(180deg); }
.dl-date {
  appearance: none; min-height: 32px; padding: 0 11px;
  border: 1px solid var(--line); border-radius: 999px; background: #fff;
  color: var(--ink); font-size: 12.5px; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.dl-date:focus { outline: none; border-color: var(--accent); }
.dl-day { font-size: 11.5px; color: var(--muted); }

.dl-kpis {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 8px; margin-bottom: 13px;
}
.dl-k {
  background: var(--line-soft); border-radius: 10px; padding: 8px 6px;
  display: flex; flex-direction: column; align-items: center; gap: 2px; text-align: center;
}
.dl-k-v { font-size: 14px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.dl-k-l { font-size: 9.5px; color: var(--muted); letter-spacing: .02em; }
/* Woraus der Score besteht – Häuser und Haushalte stehen im Tagesprotokoll
   sonst nirgends, und die Summe allein sagt nicht, welche Hälfte sie trägt. */
.dl-k-s {
  font-size: 9px; line-height: 1.25; color: var(--muted); opacity: .8;
  font-variant-numeric: tabular-nums;
}

/* Der Streifen: Breite = Anteil an der Zeit zwischen erster und letzter Tür. */
.dl-strip {
  display: flex; height: 16px; border-radius: 999px; overflow: hidden;
  background: var(--line-soft); gap: 1px;
}
.dl-seg { display: block; height: 100%; min-width: 2px; }
.dl-arbeit { background: #3b82f6; position: relative; overflow: hidden; }
/* Was innerhalb eines Arbeitsblocks passiert ist: die Zwischenzeit vor einem
   Abschluss (grün) oder vor einer hereingekommenen Jahresabrechnung (violett,
   dieselbe Farbe wie die Karte „Abrechnungen" in der Statistik). Absolut im
   Block gesetzt statt als eigenes Streifenstück – so kann eine Marke eine
   Mindestbreite haben, ohne das Längenverhältnis des Tages zu verschieben.
   Beide Töne sind heller als das Blau darunter: der Unterschied trägt auch
   ohne Farbwahrnehmung. */
.dl-mark { position: absolute; top: 0; bottom: 0; min-width: 4px; border-radius: 1px; }
.dl-mark--abschluss { background: #4ade80; }
.dl-mark--abrechnung { background: #c084fc; }
.dl-mark--gespraech { background: #f87171; }
/* Pause: schraffiert statt einfarbig – so ist sie auch ohne Farbunterschied
   als Lücke zu erkennen. */
.dl-pause {
  background: repeating-linear-gradient(135deg, #cbd5e1 0 4px, #e2e8f0 4px 8px);
}
/* Seit dem 10.09.2026 trägt eine Pause ihre Farbe: grün, wenn an ihrem Rand ein
   Abschluss steht, rot bei einem Gespräch ohne Unterschrift (siehe pausenArt in
   main.js). Die Schraffur bleibt in beiden Fällen – das Muster sagt weiterhin
   „hier wurde nicht gearbeitet", die Farbe sagt WARUM. An der Rechnung ändert
   sie nichts: auch eine grüne Pause ist keine produktive Zeit. */
.dl-pause--abschluss {
  background: repeating-linear-gradient(135deg, #4ade80 0 4px, #dcfce7 4px 8px);
}
.dl-pause--abrechnung {
  background: repeating-linear-gradient(135deg, #c084fc 0 4px, #ede9fe 4px 8px);
}
.dl-pause--gespraech {
  background: repeating-linear-gradient(135deg, #f87171 0 4px, #fee2e2 4px 8px);
}
.dl-scale {
  display: flex; justify-content: space-between; margin: 5px 1px 12px;
  font-size: 10px; color: var(--muted); font-variant-numeric: tabular-nums;
}

.dl-rows { display: flex; flex-direction: column; gap: 4px; }
.dl-row {
  display: flex; align-items: center; gap: 9px;
  padding: 7px 9px; border-radius: 9px; background: #f8fafc;
  font-size: 12px; color: var(--ink);
}
.dl-row-p { background: transparent; border: 1px dashed var(--line); color: var(--ink-2); }
.dl-time { flex: 0 0 auto; font-variant-numeric: tabular-nums; font-weight: 600; }
.dl-time i { font-style: normal; color: var(--muted); margin: 0 3px; }
.dl-tag-a, .dl-tag-p {
  flex: 0 0 auto; font-size: 10px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; padding: 2px 7px; border-radius: 999px;
}
.dl-tag-a { background: #dbeafe; color: #1d4ed8; }
.dl-tag-p { background: var(--line-soft); color: var(--ink-2); }
/* Die gefärbte Pause in der Zeilenliste: Marke, Rahmen und der Grund daneben
   in derselben Farbe wie ihr Stück im Streifen. Der Text trägt die Aussage,
   die Farbe nur die Wiedererkennung. */
.dl-row-p--abschluss  { border-color: #a7e8c3; background: #f7fdfa; }
.dl-row-p--abrechnung { border-color: #ddd0fb; background: #fcfaff; }
.dl-row-p--gespraech  { border-color: #f9c9c9; background: #fffafa; }
.dl-tag-p--abschluss  { background: #dcfce7; color: #15803d; }
.dl-tag-p--abrechnung { background: #ede9fe; color: #6d28d9; }
.dl-tag-p--gespraech  { background: #fee2e2; color: #b91c1c; }
.dl-row-p--abschluss  .dl-n { color: #15803d; }
.dl-row-p--abrechnung .dl-n { color: #6d28d9; }
.dl-row-p--gespraech  .dl-n { color: #b91c1c; }
.dl-n { flex: 1 1 auto; color: var(--ink-2); font-variant-numeric: tabular-nums; }
/* Die Marken des Blocks in Worten, mit ihrem Farbpunkt davor. Ein Block ohne
   Marken lässt die Spanne ganz weg (:empty) – die Zeile sieht dann aus wie
   bisher. */
.dl-marks { display: flex; align-items: center; gap: 9px; flex: 0 0 auto; }
.dl-marks:empty { display: none; }
.dl-mk {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; font-weight: 650; font-variant-numeric: tabular-nums;
}
.dl-mk::before {
  content: ''; width: 7px; height: 7px; border-radius: 2px; background: currentColor;
}
.dl-mk--abschluss { color: #15803d; }
.dl-mk--abrechnung { color: #6d28d9; }
.dl-mk--gespraech { color: #b91c1c; }
.dl-dur { flex: 0 0 auto; font-weight: 700; font-variant-numeric: tabular-nums; }
/* Die Lücke, die den Block beendet hat – im Tabellen-Zwilling hervorgehoben. */
.dl-gap { color: var(--ink-2); }
.dl-empty { padding: 14px 2px; color: var(--ink-2); }
.dl-empty p { margin: 0 0 4px; font-size: 13px; font-weight: 600; color: var(--ink); }
.dl-empty small { font-size: 11.5px; color: var(--muted); }
.dl-foot { margin: 11px 0 0; font-size: 11px; color: var(--muted); text-align: right; }

/* ---- Tempo: die Türen des Tages als steigende Kurve ---- */
/* Sitzt in der Arbeitstag-Karte zwischen den Kacheln und dem Tagesstreifen.
   Der Graph kommt fertig bemaßt aus dem Skript (Pixel, kein skaliertes
   viewBox – sonst schrumpft die Beschriftung auf dem Telefon mit); den
   seitlichen Rand des Zeichenfeldes gibt TP_PAD auch dem Streifen darunter,
   damit beide dieselbe Zeitachse zeigen. Hier steht nur, was Farbe und
   Schriftgrad angeht. */
.tp-legend { flex-wrap: wrap; gap: 8px 14px; }
/* Die Klasse ist ein Kurvenstück, kein Block – der Schlüssel darum ein Strich. */
.tp-key i { width: 16px; height: 3px; border-radius: 2px; }
.tp-key b { font-weight: 650; color: var(--ink-2); font-variant-numeric: tabular-nums; }
/* Heute nicht vorgekommen: bleibt stehen, tritt aber zurück – die Legende ist
   die Skala und nicht die Liste der zufällig heute benutzten Farben. */
.tp-key-off { opacity: .45; }

.tp-plot { width: 100%; min-height: 168px; }
.tp-svg { display: block; overflow: visible; }
.tp-grid { stroke: var(--line-soft); stroke-width: 1; shape-rendering: crispEdges; }
.tp-base { stroke: var(--line); stroke-width: 1; shape-rendering: crispEdges; }
.tp-tick { font-size: 9.5px; fill: var(--muted); font-variant-numeric: tabular-nums; }
.tp-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
/* Der Ring in Flächenfarbe hält den Punkt lesbar, wo er die Kurve kreuzt. */
.tp-end { font-size: 11px; font-weight: 650; fill: var(--ink-2); }
/* Bildunterschrift der Kurve – der Abstand nach unten trennt sie vom Streifen. */
.tp-foot { margin: 8px 0 12px; font-size: 11.5px; color: var(--ink-2); }

@media (max-width: 560px) {
  .fn-label { flex-basis: 124px; }
  .fn-step { margin-left: 134px; }
  .s-label { flex-basis: 92px; }
  /* Sieben Kacheln nebeneinander wären auf dem Telefon je 40px breit. Zu dritt
     gehen sechs davon glatt auf – die siebte (der Score) nimmt die letzte Zeile
     ganz und steht als Tagessumme unter dem, woraus sie sich errechnet. */
  .dl-kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .dl-k-sum { grid-column: 1 / -1; }
  .dl-n { display: none; }
  /* Ausnahme: der Grund einer gefärbten Pause. Er muss auch auf dem Telefon
     lesbar bleiben – die Farbe allein trägt die Aussage nicht. Neben Uhrzeit,
     Marke und Dauer sind keine 80px mehr frei, also nimmt er die zweite Zeile.
     Eine graue Pause hat keinen Grund; ihre leere Spalte bleibt weg, damit die
     Zeile so flach bleibt wie bisher. */
  .dl-row { flex-wrap: wrap; }
  .dl-row-p .dl-n { display: block; order: 9; flex: 1 0 100%; font-size: 11px; }
  .dl-row-p .dl-n:empty { display: none; }
  /* Dasselbe für die Marken eines Arbeitsblocks: neben Uhrzeit, Marke und Dauer
     ist kein Platz, in einer zweiten Zeile schon. */
  .dl-marks { order: 9; flex: 1 0 100%; }
  .tp-plot { min-height: 140px; }
}

/* Querformat: das Control Panel rückt in die Mitte des FREI bleibenden
   Kartenstreifens zwischen den beiden Panels. */
body.work-open .map-controls { left: calc(50% + (var(--wp-l) - var(--wp-r)) / 2); }

/* Dasselbe für die Straßensuche: sie liegt oben links und damit genau da, wo bei
   offenem Haus die Haushaltsliste steht (beide z-index 18, .work steht später im
   Markup und gewänne). Sie rückt also rechts daneben, statt zu verschwinden –
   man arbeitet die Liste ja Nummer für Nummer ab. */
body.work-open .str-panel { left: calc(var(--wp-l) + 12px); }
.str-panel { transition: left .2s ease, opacity .18s ease; }
/* Auf dem Telefon steht statt des Sheets das Popup über allem – dahinter wäre
   das Panel nur noch ein Schatten. */
body.pop-open .str-panel { opacity: 0; pointer-events: none; }
@media (prefers-reduced-motion: reduce) { .str-panel { transition: none; } }

/* ===========================================================================
   Hochformat: dieselben zwei Spalten in einem Bottom-Sheet
   =========================================================================== */

@media (max-width: 899px) {
  /* Hier ist der Arbeitsbereich ein Sheet von UNTEN – oben links steht nichts
     im Weg, das Panel muss also nicht ausweichen. */
  body.work-open .str-panel { left: 12px; }

  .work {
    top: auto; left: 0; right: 0; bottom: 0;
    height: 60%;
    background: var(--card);
    border-top: 1px solid var(--line);
    border-radius: 20px 20px 0 0;
    box-shadow: 0 -10px 34px rgba(15, 23, 42, .16);
    display: flex; flex-direction: column;
    pointer-events: auto;
    opacity: 1; visibility: visible;      /* Sichtbarkeit läuft über transform */
    transform: translateY(100%);
    transition: transform .26s cubic-bezier(.32, .72, 0, 1), height .26s cubic-bezier(.32, .72, 0, 1);
  }
  .work.open { transform: translateY(0); }
  .work.full { height: calc(100% - 8px); }

  .work-cols { flex: 1 1 auto; min-height: 0; }

  .wp-left  { flex: 0 0 40%; width: 40%; box-shadow: none; }
  .wp-right { flex: 1 1 auto; width: auto; border-left: 1px solid var(--line); box-shadow: none; }

  /* Griff zum Vergrößern/Verkleinern */
  .sheet-grip {
    display: block; appearance: none; border: 0; cursor: pointer;
    width: 100%; height: 22px; background: transparent; flex: 0 0 auto;
    position: relative; touch-action: none;
  }
  .sheet-grip::before {
    content: ''; position: absolute; left: 50%; top: 8px; transform: translateX(-50%);
    width: 40px; height: 4px; border-radius: 3px; background: #d3dbe5;
  }

  /* Control Panel über das Sheet schieben statt darunter verstecken. Der
     Joystick schrumpft dabei, damit die Reihe in den freien Streifen passt. */
  body.work-open .map-controls { left: 50%; bottom: calc(60% + 12px); }
  body.work-open .map-ctrl.joystick { width: 86px; height: 86px; }
  body.work-full .map-controls { opacity: 0; pointer-events: none; }
}

/* ===========================================================================
   Telefon: aus zwei Spalten werden zwei Seiten
   ===========================================================================
   Im 390px-Sheet blieben von den beiden Spalten 156px für die Haushaltsliste
   und 234px für das Detail – darin war das Straßenfeld 37px breit, die
   Etagensteuerung lief seitlich heraus. Beides bekommt hier die volle Breite;
   `detail` am .work schiebt von der Liste auf das Detail.

   Verschoben statt ausgeblendet: display:none würde die Scrollhöhe der Liste
   verwerfen, und man stünde nach jedem Haushalt wieder bei Nummer eins. */
@media (max-width: 640px) {
  .work { overflow: hidden; }             /* die zweite Seite bleibt draußen */
  .work-cols {
    width: 200%;
    transform: translateX(0);
    transition: transform .24s cubic-bezier(.32, .72, 0, 1);
  }
  .work.detail .work-cols { transform: translateX(-50%); }
  .wp-left, .wp-right {
    flex: 0 0 50%;                        /* 50% von 200% = volle Sheet-Breite */
    width: 50%;
    border: 0;
    box-shadow: none;
  }
  .icon-btn.wp-back { display: inline-flex; }
  .wp-back svg { transform: rotate(180deg); }
}

@media (max-width: 1160px) {
  /* Neun Tabs brauchen ab hier engere Polster, sonst schiebt die Leiste die
     Tageszahl aus dem Bild. Die Schwelle hängt an der Anzahl der Tabs – kommt
     einer dazu, muss sie mit nach oben (zuletzt der Import-Tab, dazu das
     Kontoschild in der Marke). */
  .tab { padding: 6px 11px; font-size: 12.5px; }
}

/* Nur noch der Zwischenbereich, in dem die Leiste EINZEILIG bleibt und trotzdem
   neun Tabs tragen muss. Unter 640px übernimmt die zweizeilige Kopfzeile (siehe
   oben) – dort ist wieder Platz für Marke und Tageszahl, weil die Tabs eine
   eigene Zeile haben. Die alten Stufen bei 620 und 460px sind damit hinfällig:
   sie haben Text weggenommen, um Platz zu schaffen, den es jetzt gibt. */
@media (min-width: 641px) and (max-width: 1040px) {
  .stat-chip { display: none; }
  .tab { padding: 6px 9px; }
}

/* Querformat auf schmaleren Fenstern: Panels etwas zusammenziehen. */
@media (min-width: 900px) and (max-width: 1120px) {
  :root { --wp-l: 208px; --wp-r: 304px; }
}

/* ===========================================================================
   Toast – kurze Rückmeldung, die den Ablauf nicht unterbricht
   =========================================================================== */

#toast {
  position: fixed; left: 50%; bottom: 32px; z-index: 60;
  transform: translate(-50%, 12px);
  /* Ohne max-content bemisst sich die Breite am Platz RECHTS von left:50%, also
     an der halben Bildbreite – „Standort wird gesucht …" brach dadurch mitten im
     Satz um. Die Obergrenze bleibt, der Text bestimmt nur den Rest. */
  width: max-content; max-width: min(90vw, 380px);
  padding: 10px 16px; border-radius: 999px;
  background: rgba(15, 23, 42, .92); color: #fff;
  font-size: 14px; font-weight: 600; text-align: center;
  box-shadow: 0 6px 22px rgba(15, 23, 42, .35);
  opacity: 0; pointer-events: none;                 /* schluckt keinen Kartentipp */
  transition: opacity .16s ease, transform .16s ease;
}
#toast.show { opacity: 1; transform: translate(-50%, 0); }
/* Bei offenem Popup stehen unten die Fußknöpfe. Die Rückmeldung rutscht darüber,
   statt genau den Knopf zu verdecken, den sie kommentiert. */
body.pop-open #toast { bottom: 104px; }
/* Dasselbe auf der Karte: dort liegt unten der Joystick (104 px hoch), und
   ausgerechnet seine Meldungen dürfen ihn nicht zudecken. */
body.view-map #toast { bottom: calc(var(--safe-bottom) + 172px); }
body.view-map.pop-open #toast { bottom: 104px; }

/* ===========================================================================
   Anmeldung (views/login.ejs)
   ===========================================================================
   Eine eigene Seite, keine Schicht über der App mehr: seit es Konten gibt,
   entscheidet der Server, wer die Häuser überhaupt zu sehen bekommt. Die
   Klassennamen sind die des früheren Sperrbildschirms geblieben. */

.lock {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  background: #0b1220;
}
.lock[hidden] { display: none; }

.lock-box {
  width: min(340px, 100%);
  display: flex; flex-direction: column; gap: 10px;
  text-align: center;
}
.lock-brand {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  font-weight: 700; letter-spacing: .14em; font-size: 13px;
  color: #7dd3fc; margin-bottom: 10px;
}
.lock-label {
  font-size: 12px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: #7d8da3; text-align: left;
}
.lock-input {
  appearance: none; width: 100%;
  padding: 13px 15px; border-radius: var(--r-field);
  border: 1px solid rgba(255, 255, 255, .14);
  background: rgba(255, 255, 255, .06); color: #f8fafc;
  font-size: 17px;                                  /* < 16px zoomt iOS beim Fokus */
  letter-spacing: .1em;
}
/* Der Benutzername ist Text und kein Passwort – gesperrte Zeichen würden ihn
   nur schwerer lesbar machen. */
.lock-input--text { letter-spacing: normal; }
.lock-input:focus { outline: none; border-color: #38bdf8; background: rgba(255, 255, 255, .1); }
.lock-go {
  appearance: none; border: 0; cursor: pointer;
  padding: 13px 15px; border-radius: var(--r-field); min-height: 46px;
  background: var(--accent); color: #fff; font-size: 15px; font-weight: 600;
}
.lock-go:active { transform: scale(.985); }
.lock-err { margin: 2px 0 0; color: #fca5a5; font-size: 13px; font-weight: 600; }
.lock-err[hidden] { display: none; }
.lock-note { margin: 14px 0 0; color: #64748b; font-size: 12px; line-height: 1.5; }
/* Der Weg zur jeweils anderen Seite (Anmelden ↔ Konto anlegen). Ruhig gehalten:
   wer hier steht, will sich in aller Regel anmelden – der Wechsel ist der
   seltenere Fall und muss ihn nicht überstrahlen. */
.lock-alt { margin: 12px 0 0; color: #64748b; font-size: 12.5px; }
.lock-alt a { color: #38bdf8; font-weight: 600; text-decoration: none; }
.lock-alt a:hover { text-decoration: underline; }

.lock.shake .lock-box { animation: lock-shake .3s ease; }
@keyframes lock-shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-7px); }
  55% { transform: translateX(6px); }
  80% { transform: translateX(-3px); }
}
@media (prefers-reduced-motion: reduce) {
  .lock.shake .lock-box { animation: none; }
}

/* ===========================================================================
   Einstellungen
   =========================================================================== */

.set-group { margin: 0 0 18px; }
.set-h {
  margin: 0 0 8px; padding: 0 2px;
  font-size: 11.5px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted);
}
.set-row {
  appearance: none; width: 100%; text-align: left; cursor: pointer;
  display: flex; align-items: flex-start; gap: 11px;
  padding: 13px 14px; margin-bottom: 8px;
  border: 1px solid var(--line); border-radius: var(--r-tile);
  background: var(--card); box-shadow: var(--shadow-tile);
  color: var(--ink);
}
.set-row:active { background: var(--line-soft); }
.set-ic {
  flex: 0 0 auto; width: 32px; height: 32px; border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  background: var(--line-soft); color: var(--ink-2);
}
.set-row--warn .set-ic { background: #fef2f2; color: #dc2626; }
/* Zeile mit Eingabefeld statt Tippfläche – nur das Feld selbst reagiert. */
.set-row--static { cursor: default; }
.set-row--static:active { background: var(--card); }
.set-num {
  flex: 0 0 auto; margin-left: auto; align-self: center;
  display: inline-flex; align-items: baseline; gap: 5px;
  font-size: 12px; color: var(--muted);
}
.set-num input {
  width: 62px; padding: 7px 8px; text-align: right;
  border: 1px solid var(--line); border-radius: 9px; background: #fff;
  font: inherit; font-size: 15px; font-weight: 650; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.set-num input:focus { outline: none; border-color: var(--accent); }
.set-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; }

/* Farbskala der Blasen: der Streifen zeigt die Kurve, die beiden Zahlen darunter
   stehen an ihren Enden. Ohne den Streifen wären es zwei nackte Felder, und man
   müsste sich merken, welches davon das grüne Ende ist. */
.skala-bar {
  height: 10px; margin: 8px 0 2px; border-radius: 999px;
  box-shadow: inset 0 0 0 1px rgba(15, 23, 42, .08);
}
.skala-felder { display: flex; align-items: flex-end; gap: 12px; }
.skala-feld {
  display: flex; flex-direction: column; gap: 4px;
  font-size: 12px; color: var(--muted);
}
/* Das rote Ende sitzt am rechten Rand – auf derselben Seite wie im Streifen. */
.skala-feld--rot { margin-left: auto; align-items: flex-end; text-align: right; }
.skala-feld input {
  width: 82px; padding: 7px 8px; text-align: right;
  border: 1px solid var(--line); border-radius: 9px; background: #fff;
  font: inherit; font-size: 15px; font-weight: 650; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.skala-feld input:focus { outline: none; border-color: var(--accent); }
/* Ein/Aus-Regler am rechten Rand einer Einstellungszeile. Getippt wird die
   ganze Zeile (siehe .set-row--switch) – der Regler zeigt nur den Zustand,
   er ist kein eigenes Ziel. */
.set-row--switch { align-items: center; }
.set-switch {
  flex: 0 0 auto; margin-left: auto; align-self: center;
  width: 44px; height: 26px; border-radius: 999px;
  background: #cbd5e1; position: relative;
  transition: background .18s ease;
}
.set-switch i {
  position: absolute; top: 3px; left: 3px;
  width: 20px; height: 20px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(15, 23, 42, .3);
  transition: transform .18s cubic-bezier(.2, .8, .3, 1);
}
.set-switch.on { background: var(--accent); }
.set-switch.on i { transform: translateX(18px); }
@media (prefers-reduced-motion: reduce) {
  .set-switch, .set-switch i { transition: none; }
}
.set-title { font-size: 14.5px; font-weight: 600; }
.set-sub { font-size: 12.5px; line-height: 1.45; color: var(--ink-2); }
.set-note {
  margin: 6px 2px 0; font-size: 12px; line-height: 1.45; color: var(--muted);
}

/* ===========================================================================
   Rechner: Eingabe → Formel → Ergebnis, untereinander
   =========================================================================== */

.rc-card {
  padding: 14px; border: 1px solid var(--line); border-radius: var(--r-tile);
  background: var(--card); box-shadow: var(--shadow-tile);
}
.rc-lab {
  display: block; margin: 0 2px 6px;
  font-size: 11.5px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted);
}
.rc-var {
  font-style: italic; font-weight: 700; text-transform: none;
  letter-spacing: 0; color: var(--accent);
}
.rc-in, .rc-out {
  width: 100%; padding: 12px 13px;
  border: 1px solid var(--line); border-radius: 11px; background: #fff;
  font: inherit; font-size: 24px; font-weight: 650; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.rc-in:focus { outline: none; border-color: var(--accent); }
/* Getippt, aber keine Zahl – nur ein Hinweis, kein Fehler mit Text. */
.rc-in--bad { border-color: #fca5a5; }

/* Die Formel steht zwischen den beiden Feldern und erklärt den Sprung. */
.rc-formel {
  display: flex; align-items: center; gap: 7px;
  margin: 10px 0; padding: 9px 11px;
  border-radius: 10px; background: var(--line-soft);
  font-size: 12.5px; line-height: 1.4; color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.rc-ic { flex: 0 0 auto; display: flex; color: var(--muted); }

.rc-outrow { display: flex; align-items: stretch; gap: 8px; }
.rc-out {
  flex: 1 1 auto; min-width: 0; cursor: pointer;
  background: var(--line-soft); color: var(--accent);
}
.rc-out:focus { outline: none; }
.rc-copy {
  appearance: none; flex: 0 0 auto; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 0 15px; border: 0; border-radius: 11px;
  background: var(--accent); color: #fff;
  font: inherit; font-size: 14px; font-weight: 600;
}
.rc-copy:active { filter: brightness(.92); }
.rc-copy:disabled { background: var(--line); color: var(--muted); cursor: default; }

/* ---- Die Faktoren der Formel ----
   Änderbar, aber bewusst leiser als der Rechner darüber: dort tippt man täglich
   eine Zahl, hier alle paar Monate. */
.rc-fak {
  margin-top: 12px; padding: 12px 14px 10px;
  border: 1px solid var(--line); border-radius: var(--r-tile); background: var(--card);
}
.rc-fak-kopf { display: flex; align-items: center; gap: 8px; margin-bottom: 9px; }
.rc-fak-h {
  flex: 1 1 auto;
  font-size: 11.5px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted);
}
.rc-fak-std {
  appearance: none; cursor: pointer; flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: 5px;
  padding: 6px 10px; border: 1px solid var(--line); border-radius: 9px;
  background: #fff; color: var(--ink-2);
  font: inherit; font-size: 12px; font-weight: 600;
}
.rc-fak-std:active { background: var(--line-soft); }
.rc-fak-std[hidden] { display: none; }   /* sonst gewinnt display:inline-flex */

.rc-fak-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(92px, 1fr)); gap: 8px; }
.rc-fak-f { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.rc-fak-f > span { font-size: 12px; font-weight: 600; color: var(--muted); }
.rc-fak-f input {
  width: 100%; padding: 9px 10px;
  border: 1px solid var(--line); border-radius: 10px; background: #fff;
  /* 16px, weil iOS bei kleinerer Schrift in Eingabefeldern hineinzoomt. */
  font: inherit; font-size: 16px; font-weight: 650; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.rc-fak-f > span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rc-fak-f input:focus { outline: none; border-color: var(--accent); }
/* Getippt, aber keine brauchbare Zahl – gerechnet wird derweil mit dem letzten
   gültigen Wert weiter, und beim Verlassen steht der wieder im Feld. */
.rc-fak-f input.rc-bad { border-color: #fca5a5; }
/* Derselbe Preis in Cent – im Gespräch heißt er „30,98", im Feld steht 0,3098. */
.rc-fak-ct { font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }

/* ---- Versorger: ein Name für einen Satz Werte ---- */
.rc-tarife { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line-soft); }
.rc-tarif-neu { display: flex; gap: 8px; margin: 8px 0 10px; }
.rc-tarif-neu input {
  flex: 1 1 auto; min-width: 0; padding: 9px 11px;
  border: 1px solid var(--line); border-radius: 10px; background: #fff;
  font: inherit; font-size: 16px; color: var(--ink);   /* 16px: sonst zoomt iOS */
}
.rc-tarif-neu input:focus { outline: none; border-color: var(--accent); }
.rc-tarif-neu input::placeholder { color: #aab6c6; }
.rc-tarif-save {
  appearance: none; cursor: pointer; flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 0 14px; border: 0; border-radius: 10px;
  background: var(--accent); color: #fff;
  font: inherit; font-size: 14px; font-weight: 600;
}
.rc-tarif-save:active { filter: brightness(.92); }
.rc-tarif-save:disabled { background: var(--line); color: var(--muted); cursor: default; }

.rc-tarif-liste { display: flex; flex-direction: column; gap: 6px; }
.rc-tarif {
  display: flex; align-items: stretch; gap: 6px;
  border: 1px solid var(--line); border-radius: 10px; background: #fff;
  overflow: hidden;
  min-height: 44px;                  /* im Gehen mit dem Daumen zu treffen */
}
/* Der eingesetzte Versorger – erkennbar, ohne dass er sich vordrängt. */
.rc-tarif.aktiv { border-color: var(--accent); background: #f5f8ff; }
.rc-tarif-b {
  appearance: none; cursor: pointer; flex: 1 1 auto; min-width: 0;
  display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap;
  padding: 9px 11px; border: 0; background: none; text-align: left; font: inherit;
}
.rc-tarif-b:active { background: var(--line-soft); }
.rc-tarif-n {
  font-size: 14px; font-weight: 650; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
}
.rc-tarif-w { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.rc-tarif.aktiv .rc-tarif-n { color: var(--accent); }
.rc-tarif-x {
  appearance: none; cursor: pointer; flex: 0 0 auto;
  width: 44px; border: 0; border-left: 1px solid var(--line-soft);
  background: none; color: #aab6c6;
  display: flex; align-items: center; justify-content: center;
}
.rc-tarif-x:active { background: var(--line-soft); color: #dc2626; }
.rc-tarif-leer { margin: 8px 2px 0; font-size: 12px; line-height: 1.45; color: var(--muted); }

/* Schmales Hochformat: der Knopf rutscht unter das Ergebnis, sonst bleibt für
   die Zahl kaum etwas übrig. */
@media (max-width: 420px) {
  .rc-outrow { flex-direction: column; }
  .rc-copy { justify-content: center; padding: 12px; }
}

/* ===========================================================================
   Kunden: Storno-/Sicher-Schieber und Archiv
   =========================================================================== */

/* Zustand der Karte. Der farbige Balken links ist die eigentliche Aussage –
   die Fläche bleibt hell, damit die Schrift lesbar bleibt. */
.kd-card--storno {
  border-color: #fecaca;
  background: linear-gradient(90deg, #dc2626 0 4px, #fef2f2 4px);
}
.kd-card--sicher {
  border-color: #bbf7d0;
  background: linear-gradient(90deg, #15803d 0 4px, #f0fdf5 4px);
}
/* Nacharbeit: der Abschluss steht, aber es fehlt noch etwas – was, steht in den
   Todos darunter. */
.kd-card--nacharbeit {
  border-color: #fde68a;
  background: linear-gradient(90deg, #d97706 0 4px, #fffbeb 4px);
}

/* Schieber, Provision und Archiv in einer Zeile. Auf schmalen Geräten ist dafür
   kein Platz – dann rutscht das Feld mit dem Archivknopf in die zweite Zeile,
   statt den Schieber unbedienbar schmal zu quetschen. */
.kd-actions {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  padding: 9px 11px 11px; border-top: 1px solid var(--line-soft);
}

/* Provision: der Betrag, der an diesem Abschluss hängt – direkt neben dem
   Schieber, weil beide dieselbe Frage beantworten: kommt das Geld an? */
.kd-prov { position: relative; flex: 0 0 auto; margin-left: auto; }
.kd-prov-cur {
  position: absolute; left: 9px; top: 50%; transform: translateY(-50%);
  font-size: 12.5px; color: #a5b2c4; pointer-events: none;
}
.kd-prov input {
  width: 106px; appearance: none; text-align: right;
  border: 1px solid var(--line); border-radius: 10px; background: #fff;
  min-height: 34px; padding: 6px 10px 6px 22px;
  font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums;
  transition: border-color .15s, box-shadow .15s;
}
.kd-prov input::placeholder { color: #aab6c6; font-weight: 500; }
.kd-prov input:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, .12);
}
/* Storniert: der Betrag ist weg. Durchgestrichen statt versteckt – man soll
   sehen, um wie viel es ging. */
.kd-card--storno .kd-prov input { color: var(--muted); text-decoration: line-through; }

.deal {
  flex: 1 1 auto; min-width: 0;
  display: flex; align-items: center; gap: 7px;
  touch-action: pan-y;                        /* senkrecht scrollen bleibt möglich */
}
.deal-end {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  /* Nachgeben statt herauslaufen: die drei Beschriftungen plus Bahn brauchen
     309px, eine 360px-Karte bietet 289 – ungebremst schob „Geld sicher" über
     den Kartenrand hinaus, und die Karte schneidet mit overflow:hidden ab.
     Mit 0 1 auto schrumpfen sie stattdessen mit Auslassungszeichen. */
  flex: 0 1 auto; min-width: 0; padding: 3px 2px;
  font-size: 11.5px; font-weight: 700; letter-spacing: .01em;
  color: var(--muted); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.deal-end--storno { color: #f0a3a3; }
.deal-end--nacharbeit { color: #e2bd8a; }
.deal-end--sicher { color: #93cbab; }
.deal[data-state="storno"] .deal-end--storno,
.deal[data-preview="storno"] .deal-end--storno { color: #dc2626; }
.deal[data-state="nacharbeit"] .deal-end--nacharbeit,
.deal[data-preview="nacharbeit"] .deal-end--nacharbeit { color: #b45309; }
.deal[data-state="sicher"] .deal-end--sicher,
.deal[data-preview="sicher"] .deal-end--sicher { color: #15803d; }

/* Breite gedeckelt: ungedeckelt zieht sich die Bahn über die ganze Karte, und
   auf einem breiten Bildschirm liegt die Raste dann über hundert Pixel weit weg
   – der Schieber fühlt sich dann kaputt an, weil ein normaler Zug nichts tut.
   160px ergeben rund 68px Weg je Seite: weit genug gegen Verrutschen, kurz
   genug für eine Daumenbewegung.
   Der Verlauf zeigt die vier Rasten: rot ganz links (Storno), gelb auf einem
   Viertel (Nacharbeit), neutral in der Mitte (offen), grün rechts (sicher). */
.deal-track {
  position: relative; flex: 1 1 auto; min-width: 96px; max-width: 160px; height: 30px;
  border-radius: 999px;
  background: linear-gradient(90deg, #fee2e2, #fef3c7 25%, #eef2f7 46%, #eef2f7 54%, #dcfce7);
  box-shadow: inset 0 1px 2px rgba(15, 23, 42, .07);
}
/* Die Raste für Nacharbeit sitzt zwischen zwei Enden und hat keine Beschriftung
   daneben – ein feiner Strich auf der Bahn zeigt, wo sie liegt. */
/* Genau dort, wo der Knopf einrastet: Mitte minus halber Weg, und der Weg ist
   (Bahn − Knopf)/2 bei 24px Knopf. */
.deal-track::before {
  content: ''; position: absolute; left: calc(25% + 6px); top: 8px; bottom: 8px;
  width: 2px; margin-left: -1px; border-radius: 1px; background: rgba(180, 83, 9, .35);
}
.deal-knob {
  position: absolute; top: 3px; left: 50%; margin-left: -12px;
  width: 24px; height: 24px; border-radius: 50%;
  background: #fff; border: 1px solid rgba(15, 23, 42, .1);
  box-shadow: 0 1px 4px rgba(15, 23, 42, .28);
  cursor: grab; touch-action: none;
  transition: transform .16s cubic-bezier(.2, .8, .3, 1), background .16s;
}
.deal.dragging .deal-knob { transition: none; cursor: grabbing; }
.deal[data-state="storno"] .deal-knob,
.deal[data-preview="storno"] .deal-knob { background: #dc2626; border-color: #dc2626; }
.deal[data-state="nacharbeit"] .deal-knob,
.deal[data-preview="nacharbeit"] .deal-knob { background: #d97706; border-color: #d97706; }
.deal[data-state="sicher"] .deal-knob,
.deal[data-preview="sicher"] .deal-knob { background: #15803d; border-color: #15803d; }

.kd-arch {
  appearance: none; cursor: pointer; flex: 0 0 auto;
  width: 34px; height: 34px; border-radius: 10px;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
  display: flex; align-items: center; justify-content: center;
}
.kd-arch:active { background: var(--line-soft); }

.kd-switch { display: flex; gap: 4px; margin: 0 0 10px; }
.kd-sw {
  appearance: none; cursor: pointer; flex: 1 1 0;
  padding: 8px 10px; min-height: 38px; border-radius: 10px;
  border: 1px solid var(--line); background: #fff;
  font-size: 13px; font-weight: 600; color: var(--ink-2);
}
.kd-sw.on { background: var(--ink); border-color: var(--ink); color: #fff; }
.kd-sw span { opacity: .6; margin-left: 4px; font-variant-numeric: tabular-nums; }

.kd-tag { font-size: 12px; }
.kd-tag--sicher b { color: #15803d; }
.kd-tag--storno b { color: #dc2626; }
.kd-tag--nacharbeit { letter-spacing: 0; text-transform: none; }
.kd-tag--nacharbeit b { color: #b45309; }
/* Ausgeklammerte Abschlüsse stehen weiter in der Liste, aber in keiner Summe.
   Damit stimmt die Kopfzahl nicht mehr mit der Zahl der Karten überein – genau
   dafür ist diese Marke da: sie erklärt die Lücke, statt sie entstehen zu
   lassen. Nicht rot wie ein Storno (da ist Geld geplatzt), sondern grau: hier
   ist nichts schiefgegangen, es wird nur nichts gezählt. */
.kd-tag--aus { letter-spacing: 0; text-transform: none; color: var(--muted); }
.kd-tag--aus b { color: var(--ink-2); }

/* ---- Todos zur Nacharbeit ---- */

.kd-todos {
  padding: 9px 11px 11px; border-top: 1px solid var(--line-soft);
  background: rgba(255, 251, 235, .6);
}
.kd-todo-head {
  font-size: 11px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: #b45309; margin-bottom: 6px;
}
.kd-todo { display: flex; align-items: center; gap: 8px; padding: 3px 0; }
.kd-todo-box {
  appearance: none; cursor: pointer; flex: 0 0 auto;
  width: 26px; height: 26px; border-radius: 8px;
  border: 1px solid var(--line); background: #fff; color: transparent;
  display: flex; align-items: center; justify-content: center;
  transition: background .15s, border-color .15s, color .15s;
}
.kd-todo.done .kd-todo-box { background: #15803d; border-color: #15803d; color: #fff; }
.kd-todo-text {
  flex: 1 1 auto; min-width: 0; font-size: 13px; line-height: 1.4;
  overflow-wrap: anywhere;
}
.kd-todo.done .kd-todo-text { color: var(--muted); text-decoration: line-through; }
.kd-todo-x {
  appearance: none; cursor: pointer; flex: 0 0 auto;
  width: 30px; height: 30px; border-radius: 8px; border: 0;
  background: transparent; color: var(--muted);
  display: flex; align-items: center; justify-content: center;
}
.kd-todo-x:active { background: var(--line-soft); color: #dc2626; }

.kd-todo-add { display: flex; gap: 6px; margin-top: 7px; }
.kd-todo-add input {
  flex: 1 1 auto; min-width: 0; appearance: none;
  border: 1px solid var(--line); border-radius: 10px; background: #fff;
  min-height: 34px; padding: 6px 10px; font-size: 13px;
  transition: border-color .15s, box-shadow .15s;
}
.kd-todo-add input::placeholder { color: #aab6c6; }
.kd-todo-add input:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, .12);
}
.kd-todo-add button {
  appearance: none; cursor: pointer; flex: 0 0 auto;
  width: 34px; height: 34px; border-radius: 10px;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
  display: flex; align-items: center; justify-content: center;
}
.kd-todo-add button:active { background: var(--line-soft); }

.empty-inline {
  padding: 26px 12px; text-align: center;
  font-size: 13px; color: var(--muted);
}

/* ===========================================================================
   Import: Excel einlesen, Gebiete
   ===========================================================================
   Zwei Blöcke untereinander in denselben Karten wie die Einstellungen
   (.set-group / .set-h): oben die Datei mit ihrer Spaltenzuordnung, unten die
   Liste der eingelesenen Gebiete. */

/* Der Dateiname ist ein Eigenname und darf nicht in Versalien stehen wie die
   sonstigen Überschriften – „AUSBAUGEBIETE-2026.XLSX" ist nicht der Name der
   Datei, die der Nutzer gerade ausgesucht hat. */
.set-h--datei {
  display: flex; align-items: center; gap: 6px;
  text-transform: none; letter-spacing: 0;
  font-size: 13.5px; color: var(--ink);
  overflow: hidden;
}
.set-h--datei span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.imp-h-ic { display: inline-flex; flex: 0 0 auto; color: var(--muted); }

/* Ablagefläche und Knopf in einem. Gestrichelt, weil sie etwas AUFNIMMT –
   ein voller Rahmen sähe aus wie eine Karte mit Inhalt. */
.imp-drop {
  appearance: none; width: 100%; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  padding: 28px 18px;
  border: 1.5px dashed var(--line); border-radius: var(--r-tile);
  background: var(--card); color: var(--ink);
  transition: border-color .15s, background .15s;
}
.imp-drop:active, .imp-drop.over { border-color: var(--accent); background: #f0f9ff; }
.imp-drop[disabled] { cursor: default; opacity: .65; }
.imp-drop strong { font-size: 14.5px; font-weight: 600; }
.imp-drop-ic { color: var(--accent); }
.imp-drop-sub { font-size: 12.5px; color: var(--muted); }

/* Blattwahl und Kopfzeilen-Haken. Zwei kleine Regler, die nebeneinander
   passen, solange Platz ist. */
.imp-kopf {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px 18px;
  margin-bottom: 12px;
}
.imp-check {
  display: flex; align-items: center; gap: 8px;
  font-size: 13px; color: var(--ink-2); cursor: pointer;
  min-height: 38px;                    /* Untergrenze für dichte Zweitkontrollen */
}
.imp-check input { width: 17px; height: 17px; accent-color: var(--accent); }

/* Die drei Zuordnungen. Auf breiten Fenstern nebeneinander, auf dem Telefon
   untereinander – drei Auswahlfelder in einer 390px-Zeile sind unlesbar. */
.imp-zu {
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
.imp-feld { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.imp-feld > span {
  font-size: 11.5px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--muted);
}
.imp-sel {
  appearance: none; width: 100%; min-width: 0;
  padding: 9px 30px 9px 11px; min-height: 40px;
  border: 1px solid var(--line); border-radius: 10px; background: #fff;
  font: inherit; font-size: 14px; color: var(--ink);
  /* Eigener Pfeil, damit das Feld auf iOS nicht aussieht wie aus 2010. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 8px center; background-size: 16px;
  text-overflow: ellipsis;
}
.imp-sel:focus { outline: none; border-color: var(--accent); }

/* Weitere Spalten in die Notiz. Eine geordnete Liste, keine Häkchenreihe: die
   Reihenfolge ist Teil der Aussage, und man muss sie sehen und ändern können. */
.imp-notiz { margin-top: 14px; }
.imp-notiz-lab {
  display: block; margin-bottom: 6px;
  font-size: 11.5px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--muted);
}
.imp-notiz-liste {
  list-style: none; margin: 0 0 8px; padding: 0;
  display: flex; flex-direction: column; gap: 6px;
}
.imp-notiz-liste li {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 8px 6px 6px; min-height: 40px;
  border: 1px solid var(--line); border-radius: 10px; background: var(--card);
}
.imp-notiz-n {
  flex: 0 0 auto; width: 20px; height: 20px; border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
  background: var(--line-soft); color: var(--ink-2);
  font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.imp-notiz-t {
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 13px;
}
.imp-nb {
  appearance: none; cursor: pointer; flex: 0 0 auto;
  width: 28px; height: 28px; border-radius: 8px;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
  display: flex; align-items: center; justify-content: center;
}
.imp-nb:active { background: var(--line-soft); }
.imp-nb[disabled] { opacity: .35; cursor: default; }
/* Der Pfeil ist derselbe Winkel wie überall in der App, nur gedreht – ein
   eigenes Icon für hoch und runter wäre zweimal dieselbe Form. */
.imp-nb svg { transform: rotate(-90deg); }
.imp-nb--ab svg { transform: rotate(90deg); }
.imp-nb--weg { color: #e11d48; }
.imp-nb--weg svg { transform: none; }
.imp-notiz .set-note code {
  padding: 1px 5px; border-radius: 5px;
  background: var(--line-soft); color: var(--ink-2);
  font-size: 11.5px;
}
.imp-notiz-v { color: var(--ink-2); }
.imp-adr-notiz {
  color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  max-width: 34ch;
}

/* Vorschau: genau die drei Spalten, die übernommen werden. Links ausgerichtet –
   das sind Namen, keine Zahlen (.s-table stellt sonst alles rechtsbündig). */
.imp-vorschau table, .imp-liste table { table-layout: auto; }
.imp-vorschau th, .imp-vorschau td,
.imp-liste th, .imp-liste td { text-align: left; font-size: 12.5px; padding: 6px 8px; }
.imp-vorschau .num, .imp-liste .num { text-align: right; }
.imp-vorschau td { color: var(--ink); }
.imp-vorschau td:empty::after { content: '—'; color: var(--line); }

/* Breite Tabellen scrollen in sich, statt am Rand abgeschnitten zu werden. */
.imp-vorschau, .imp-liste { overflow-x: auto; }
.imp-liste { max-height: 60vh; overflow-y: auto; }
/* Der Kopf bleibt beim Scrollen stehen – ohne ihn ist ab Zeile 30 nicht mehr
   zu sehen, welche Spalte der Zusatz ist. */
.imp-liste thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--bg); box-shadow: inset 0 -1px 0 var(--line-soft);
}
/* Eine Zeile der Adressliste: Adresse, Ort, Stand, Knöpfe. Die beiden ersten
   Spalten tragen jeweils eine zweite, kleinere Zeile (Zusatz bzw. Hinweis) –
   die erklärt, warum eine Zeile unsicher ist, ohne eine Spalte zu kosten. */
.imp-adr { font-weight: 600; }
.imp-adr small, .imp-stand small {
  display: block; font-weight: 400; font-size: 11px; color: var(--muted);
  line-height: 1.35; margin-top: 1px;
}
.imp-ort { color: var(--ink-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
.imp-stand { white-space: nowrap; }
.imp-punkt {
  display: inline-block; width: 8px; height: 8px; border-radius: 999px;
  background: var(--c, #94a3b8); margin-right: 6px; vertical-align: 0;
}
.imp-tun { white-space: nowrap; }
/* .icon-btn ist display:flex und nähme sonst je eine eigene Zeile – in einer
   Tabellenzelle sollen die zwei Knöpfe nebeneinander stehen. */
.imp-tun .icon-btn { display: inline-flex; width: 30px; height: 30px; margin-left: 4px; }

/* Filterreiter über der Liste. Der farbige Punkt ist derselbe wie in der
   Zeile – so ist ohne Lesen klar, welcher Reiter welche Zeilen zeigt. */
.imp-reiter { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 10px; }
.imp-reiter-b {
  appearance: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 11px; min-height: 34px; border-radius: 999px;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
  font-size: 12.5px; font-weight: 600;
}
.imp-reiter-b[data-filter]:not([data-filter="alle"])::before {
  content: ''; width: 8px; height: 8px; border-radius: 999px; background: var(--c, #94a3b8);
}
.imp-reiter-b span { color: var(--muted); font-variant-numeric: tabular-nums; }
.imp-reiter-b.aktiv { background: var(--ink); border-color: var(--ink); color: #fff; }
.imp-reiter-b.aktiv span { color: rgba(255, 255, 255, .7); }

/* Fortschritt des Nadel-Laufs. Der Balken ist die einzige Stelle der App mit
   einer laufenden Anzeige – bei ein paar tausend Adressen dauert das Minuten,
   und ohne ihn sähe es aus, als hinge die App. */
.imp-lauf {
  padding: 13px 14px; border: 1px solid var(--line); border-radius: var(--r-tile);
  background: var(--card); box-shadow: var(--shadow-tile);
}
.imp-balken {
  height: 8px; border-radius: 999px; background: var(--line-soft); overflow: hidden;
}
.imp-balken span {
  display: block; height: 100%; border-radius: 999px; background: var(--accent);
  transition: width .4s ease;
}
.imp-lauf-zeile {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px;
  margin-top: 9px; font-size: 12.5px; color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.imp-lauf-zahlen { display: flex; flex-wrap: wrap; gap: 4px 12px; margin-left: auto; }
.imp-lauf-zahlen b { color: var(--c, var(--ink)); font-weight: 700; }
.imp-warn { color: #b45309; }

/* Der Ort in der Übersicht. Er steht IN der Adresszeile, direkt hinter der
   Hausnummer: „Drosselweg 2" gibt es in Calw und in Karlsruhe, und ohne ihn
   sind das zwei gleich aussehende Zeilen (genau das ist beim Vodafone-Import
   passiert). Innerhalb von .ov-addr, damit das Flex-Verhalten der Zeile
   unverändert bleibt und nur der Text länger wird. */
.ov-ort { margin-left: 7px; color: var(--muted); font-size: 12px; font-weight: 500; }

.imp-zaehler {
  float: right; text-transform: none; letter-spacing: 0;
  font-weight: 600; color: var(--ink-2);
}

.imp-suche { position: relative; margin-bottom: 4px; }
.imp-suche-ic {
  position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  display: flex; color: var(--muted); pointer-events: none;
}
.imp-suche input {
  appearance: none; width: 100%;
  padding: 10px 12px 10px 35px; min-height: 40px;
  border: 1px solid var(--line); border-radius: 10px; background: #fff;
  font: inherit; font-size: 15px; color: var(--ink);
}
.imp-suche input:focus { outline: none; border-color: var(--accent); }
.imp-suche input::-webkit-search-cancel-button { cursor: pointer; }

/* ---------------------------------------------------------------------------
   Hausnummern in einer Straße
   ---------------------------------------------------------------------------
   Zwei Felder und ein Knopf. Am Schreibtisch in einer Zeile – die PLZ ist
   fünfstellig und braucht keine halbe Breite –, auf dem Telefon rutscht der
   Knopf unter die Felder (siehe Telefon-Abschnitt am Dateiende). */
.hnr-form {
  display: grid; gap: 10px 12px;
  grid-template-columns: 130px minmax(0, 1fr) auto;
  align-items: end;
  margin-bottom: 10px;
}
.hnr-form input {
  appearance: none; width: 100%; min-width: 0;
  padding: 9px 11px; min-height: 40px;
  border: 1px solid var(--line); border-radius: 10px; background: #fff;
  font: inherit; font-size: 15px; color: var(--ink);
}
.hnr-form input:focus { outline: none; border-color: var(--accent); }
/* Das Fadenkreuz sitzt IM PLZ-Feld – „PLZ automatisch" macht dasselbe von
   allein, der Knopf ist der Weg für den einen Fall dazwischen. */
.hnr-plz-feld { position: relative; display: block; }
#hnrPlz { font-variant-numeric: tabular-nums; padding-right: 34px; }
.hnr-auto {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  appearance: none; border: 0; cursor: pointer;
  width: 30px; height: 30px; border-radius: 8px;
  background: transparent; color: var(--muted);
  display: flex; align-items: center; justify-content: center;
}
.hnr-auto:active { background: var(--line-soft); color: var(--accent); }
.hnr-go { min-height: 40px; white-space: nowrap; }

/* Trifft die Eingabe mehrere Straßen („am" → Am Sandfeld, Am Wald), bekommt
   jede ihre eigene Tabelle: eine durchgehende Nummernfolge über zwei Straßen
   hinweg wäre eine Liste, der man nicht ansieht, wo man hin soll. */
.hnr-gruppe { margin-top: 14px; }
.hnr-str-h {
  display: flex; align-items: baseline; gap: 8px;
  margin: 0; font-size: 13.5px; font-weight: 600; color: var(--ink);
}
.hnr-str-h span {
  font-size: 11.5px; font-weight: 600; color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* Eine einzelne Straße scrollt in sich, mit stehendem Kopf – 40 Nummern
   schöben sonst den Rest des Tabs aus dem Bild. Sind es mehrere Straßen, wird
   nicht gedeckelt: dann scrollt die Seite, und die Straßenüberschriften bleiben
   die Gliederung. Ein Kasten im Kasten im Kasten liest sich nicht. */
.hnr-liste { overflow-x: auto; }
.hnr-liste--voll { max-height: 60vh; overflow: auto; }
.hnr-liste table { table-layout: auto; }
.hnr-liste th, .hnr-liste td { text-align: left; font-size: 12.5px; padding: 6px 8px; }
.hnr-liste .num { text-align: right; }
.hnr-liste--voll thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--bg); box-shadow: inset 0 -1px 0 var(--line-soft);
}
/* Die Nummer ist das, wonach gesucht wird – sie darf breiter und fetter stehen
   als der Rest der Zeile und niemals umbrechen. */
.hnr-nr {
  font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums;
  white-space: nowrap; width: 1%;
}
/* Mehrere Notizen (aufgeteiltes Haus) stehen untereinander, nicht kommagetrennt:
   in einer Import-Notiz stecken schon Kommas, ein weiteres wäre nicht zu lesen. */
.hnr-notiz .nz { color: var(--ink-2); line-height: 1.4; }
.hnr-notiz .nz + .nz { margin-top: 3px; }
/* In der breiten Tabelle darf eine Zelle nicht unter die Lesbarkeit schrumpfen –
   lieber scrollt die Tabelle waagerecht (das kann .hnr-liste bereits). */
.hnr-notiz .nz { grid-auto-columns: minmax(34px, 1fr); }
.hnr-leer { color: var(--muted); font-style: normal; opacity: .7; }
/* Stand: derselbe Punkt wie in der Adressliste darunter (.imp-punkt), damit die
   beiden Tabellen dieselbe Sprache sprechen. Bricht nie um – die Spalte ist
   schmal und ihre Wörter sind kurz. */
.hnr-stand { white-space: nowrap; color: var(--ink-2); }
/* „offen" ist weiß – auf weißem Grund wäre der Punkt ein Loch. Eine Kontur nur
   hier, nicht am .imp-punkt allgemein: in der Adressliste darunter gibt es
   keinen weißen Stand. */
.hnr-stand .imp-punkt { box-shadow: inset 0 0 0 1px rgba(15, 23, 42, .28); }
.hnr-stand small {
  display: block; font-size: 10.5px; color: var(--muted);
  line-height: 1.35; margin-top: 1px; white-space: normal;
}
.hnr-tun { white-space: nowrap; }
/* Die offene Zeile ist die, um die es geht – sie trägt die kräftige Nummer, die
   übrigen treten zurück. */
.hnr-erledigt .hnr-nr, .hnr-ohneNadel .hnr-nr { font-weight: 600; color: var(--ink-2); }
.hnr-ohneNadel { background: #fff8f8; }
.hnr-ohneNadel .hnr-stand { color: #e11d48; font-weight: 600; }

.imp-aktionen { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.imp-aktionen .btn { flex: 1 1 auto; justify-content: center; min-height: 42px; }

/* ===========================================================================
   Telefon: Daumenziele und Lesbarkeit
   ===========================================================================
   Steht bewusst am DATEIENDE: die Größen hier korrigieren Werte, die weiter
   oben für Maus und Stift gesetzt sind, und müssen sie überschreiben.

   Zwei Maßstäbe: interaktive Elemente mindestens 40px hoch (unterwegs wird mit
   dem Daumen getippt, oft im Gehen), Schrift mindestens 10,5px. Beides wurde
   an einem 390px-Gerät nachgemessen, nicht geschätzt. */
@media (max-width: 640px) {

  /* ---- Arbeitsbereich ---- */
  .icon-btn { width: 40px; height: 40px; }
  .a-nr { min-height: 42px; }
  .street input, .ifield input { min-height: 42px; }
  .fstep { width: 38px; height: 38px; }
  .zone-btn { width: 38px; height: 38px; }
  /* ---- Haushaltskacheln: vier je Reihe, Kurzform statt Name ----
     Der volle Name kostete die Breite von zwei Kacheln und gab dafür wenig
     zurück: „Wohneinheit 38" heißt nur deshalb so, weil der Haushalt keinen
     anderen Namen hat, und der Wortteil steht auf jeder Kachel des Hauses.
     Übrig bleibt die Zahl – die unterscheidet. Ein Nachname bleibt stehen,
     „Schulz" und „Meyer" passen in die 46px Textbreite, längere werden
     abgeschnitten; der volle Name steht im Kopf des Details, sobald der
     Haushalt offen ist, und im title der Kachel.
     Ergebnis: ein Haus mit 58 Haushalten passt auf einen Bildschirm statt auf
     drei. 82px als Mindestmaß, damit auch ein 360px-Telefon noch vier Spalten
     bekommt; darunter fällt das Raster von selbst auf drei zurück. */
  .hh-list { grid-template-columns: repeat(auto-fill, minmax(82px, 1fr)); }
  .hh-row .hh-name { display: none; }
  .hh-row .hh-kurz { display: block; }
  /* Dieselbe Kurzform in der Übersicht: dort gewinnt sie keine Spalte, aber
     die Zeile bleibt einzeilig, statt für den Namen umzubrechen. */
  .ov-hh .ov-name { display: none; }
  .ov-hh .ov-kurz { display: block; }
  .hist-x { width: 36px; height: 36px; padding: 0; justify-content: center; }
  .msel-btn, .btn { min-height: 40px; }
  /* „Haus löschen" ist bewusst leise gehalten (randlos, dünn) und wäre mit
     34px zu knapp zum Treffen. 38px sind tippbar, ohne dass der Knopf lauter
     wird – Höhe trägt hier keine Aufmerksamkeit, Farbe und Gewicht tun es. */
  .btn.ghost-danger { min-height: 38px; }

  /* ---- Übersicht: Filterleiste ---- */
  .lf-ic { width: 40px; height: 40px; }
  .lf-chip { min-height: 38px; padding: 8px 13px; }
  .lf-date { min-height: 38px; }
  .lf-date input { padding: 8px 0; }

  /* ---- Übersicht: Haushaltszeile bricht nur um, wenn sie muss ----
     Einzeilig teilen sich Icon, Etagenschild, Name, Ausgang und Uhrzeit 317px.
     Fest sind davon 224 plus Abstände – für lange Namen blieb bei 390px 42px
     („Haush…"), bei 360px 20px („H."). Der erzwungene Umbruch reparierte das,
     kostete aber JEDE Zeile 70px Höhe, auch die kurzen: sechs Haushalte je
     Bildschirm. Jetzt umbricht der Flex-Behälter von selbst – „Haushalt 10"
     bleibt einzeilig, ein langer Name schiebt Ausgang und Uhrzeit hinunter.
     Wichtig dabei: dem Namen KEINE Mindestbreite geben. Flexbox bricht anhand
     der Inhaltsbreite um, und eine Mindestbreite hebt genau die an – 96px
     hätten jede Zeile mit „Nicht angetroffen" umgebrochen, auch die mit
     „Haushalt 7". Geschrumpft wird der Name dadurch nicht: passt er auf die
     erste Zeile, bekommt er seine volle Breite; passt er nicht, wandert der
     Ausgang hinunter und der Name hat die Zeile für sich. */
  .ov-hh { flex-wrap: wrap; gap: 2px 7px; padding: 5px 10px 6px; }
  .ov-hh .hh-ic { width: 24px; height: 24px; }
  .ov-hh .ov-name { font-weight: 600; }
  /* Bleibt auf seiner Zeile ganz rechts, gleich ob erste oder zweite. */
  .ov-hh .ov-out { margin-left: auto; gap: 7px; }
  .ov-badge { font-size: 10.5px; padding: 2px 7px; }
  /* Die Karte selbst gibt die 6px an die Zeilen weiter, statt sie am Rand
     stehen zu lassen – das sind zwei Zeichen mehr Name je Zeile. */
  .list-wrap { padding-left: 10px; padding-right: 10px; }
  .ov-house { margin-bottom: 8px; }
  .ov-head { padding: 8px 10px; gap: 8px; }
  .ov-pin { width: 26px; height: 26px; }

  /* ---- Followups ---- */
  .fu-mini { min-height: 38px; }
  /* Die schnellen Termine im Blatt waren 28px hoch – beim Nachmessen erst jetzt
     aufgefallen, weil das Blatt nur bei fälligem Followup von selbst aufgeht. */
  .fu-quick button { min-height: 36px; }

  /* ---- Kunden ---- */
  /* Enger als auf dem Schreibtisch: die drei Beschriftungen und die Bahn
     brauchen zusammen mehr, als eine 360px-Karte hergibt. Schmalere Bahn und
     kleinere Schrift bringen die Reihe unter, ohne dass etwas wegfällt. */
  .deal { gap: 5px; }
  .deal-end { padding: 13px 4px; font-size: 11px; letter-spacing: 0; }
  .deal-track { min-width: 76px; }
  .kd-arch { width: 40px; height: 40px; }
  .kd-prov input, .kd-money input { min-height: 40px; }
  /* Telefon- und E-Mail-Chip sind Direktwahl – die werden im Gehen getroffen. */
  .kd-chip { min-height: 38px; }
  /* Das Kästchen eines Todos ist mit 26px das kleinste Ziel der App. */
  .kd-todo-box { width: 34px; height: 34px; }
  .kd-todo-x { width: 34px; height: 34px; }
  .kd-todo-add input, .kd-todo-add button { min-height: 36px; }
  /* „Eugen-Geck-Straße 11A · 7. OG" braucht 186px und hat 166. Abgeschnitten
     fiele als Erstes die Etage weg – also genau die Angabe, wegen der man auf
     die Karte schaut. Statt Auslassungszeichen darf die Zeile deshalb umbrechen;
     die kleinere Schrift hält die meisten Adressen weiter einzeilig. */
  .kd-where { font-size: 11px; white-space: normal; overflow: visible; }

  /* Der Griff des Sheets wird gezogen, nicht getippt – 22px sind dafür zu
     wenig Angriffsfläche, wenn das Telefon in einer Hand liegt. */
  .sheet-grip { height: 34px; }
  .sheet-grip::before { top: 14px; width: 48px; }

  /* ---- Statistik ---- */
  .s-range-c { min-height: 38px; }
  .tz-chip { min-height: 38px; }
  .dl-step { width: 38px; height: 38px; }
  .dl-date, #stVon, #stBis { min-height: 38px; }
  .s-table summary { min-height: 38px; }
  /* Fünf Spalten mit einer Adresse darin brauchen 357px, ein 360er-Telefon
     bietet der Tabelle 330. Erst die Polster zusammenziehen – das holt die
     meisten Tage herein – und was dann noch übersteht, wird waagerecht
     scrollbar statt abgeschnitten. Vorher war die Spalte „seit vorher"
     schlicht nicht erreichbar. */
  .s-table { overflow-x: auto; }
  .s-table th, .s-table td { padding: 4px 3px; }

  /* Schrift, die auf dem Schreibtisch als Beiwerk durchgeht, ist unterwegs
     schlicht nicht mehr lesbar. */
  .tz-head, .tz-head .tz-t, .tz-head .tz-n, .tz-head .tz-q, .tz-legend,
  .tp-tick, .tr-x, .dl-k-l { font-size: 10.5px; }
  /* Dieselbe Untergrenze für die Abschnittsmarken. Sie stehen in Versalien mit
     weitem Sperrsatz – da fällt ein halbes Pixel optisch nicht auf, unter 10,5
     verlieren sie unterwegs aber die Kontur. */
  .s-h, .s-range-l, .s-hero-label, .tr-max, .dl-scale span, .dl-tag-a, .dl-tag-p,
  .se-z-l, .sec > h3 { font-size: 10.5px; }
  .dl-k-s { font-size: 10px; }
  .tp-tick { font-size: 10.5px; }
  /* Der Maßname passt hier nicht in die Spalte und stünde abgeschnitten da –
     der aktive Knopf darüber sagt dasselbe in voller Länge. */
  .tz-legend-l { display: none; }
  .tz-legend-l + .tz-legend-h::before { content: none; }
  /* „Entsch. abwesend" braucht 102px – lieber ein kürzerer Balken als ein
     abgeschnittener Ausgangsname. */
  .s-label { flex-basis: 108px; }

  /* ---- Straßensuche über der Karte ----
     Volle Breite minus Rand: auf 390px wären 330px Panel und 60px Karte daneben
     ein Streifen, der nichts zeigt. Etwas flacher als am Schreibtisch, damit
     unter dem Panel noch Karte steht. */
  .str-panel { top: 8px; left: 8px; width: calc(100% - 16px); max-height: 46vh; }
  .str-form input { min-height: 42px; font-size: 16px; }
  .str-zeile { padding: 9px 8px; }
  .str-nr { font-size: 15px; }
  .str-notiz { font-size: 12px; }

  /* ---- Hausnummern in einer Straße ----
     Der Knopf zieht in eine eigene Zeile unter die Felder: nebeneinander
     bliebe „Hausnummern zeigen" auf 390px zwischen PLZ und Straße stecken.
     16px Schrift in den Feldern, sonst zoomt iOS beim Hineintippen. */
  .hnr-form { grid-template-columns: 110px minmax(0, 1fr); }
  .hnr-form input { min-height: 42px; font-size: 16px; }
  .hnr-go { grid-column: 1 / -1; min-height: 44px; }
  /* Die Notiz aus der Tabelle ist der lange Teil der Zeile – sie darf umbrechen,
     die Nummer daneben nie. */
  .hnr-liste th, .hnr-liste td { font-size: 13px; }
  .hnr-notiz span { font-size: 12.5px; }

  /* ---- Einstellungen ---- */
  .set-num input,
  .skala-feld input { min-height: 42px; }
}

/* ===========================================================================
   Telefon im Querformat: flaches Fenster
   ===========================================================================
   Das Sheet misst 60% der Kartenansicht. Im Hochformat sind das rund 460px,
   im Querformat aber nur 200 – und die gehen für Straßenzeile, Etagenstepper
   und „Haus löschen" schon vollständig drauf. Von den Haushalten war dort
   nichts mehr zu sehen: genau die Liste, für die man das Haus geöffnet hat.

   Deshalb ist das Sheet auf flachen Fenstern von vornherein fast ganz offen.
   Ein Streifen Karte bleibt stehen, damit erkennbar ist, wo man steht, und der
   Griff verkleinert es wie gewohnt. Die Höhengrenze liegt über den 390px eines
   quer gehaltenen Telefons und unter der Höhe eines aufrechten. */
@media (max-width: 899px) and (max-height: 560px) {
  .work { height: 88%; }

  /* Bei 88% Sheet läge die Kartensteuerung im oberen Kartenstreifen und
     überdeckte ihn ganz – bei offenem Arbeitsbereich hat sie hier nichts mehr
     zu suchen. Ohne Auswahl steht sie unverändert da. */
  body.work-open .map-controls { opacity: 0; pointer-events: none; }

  /* „Haus löschen" belegt eine ganze Zeile für den Knopf, den man am seltensten
     braucht. Bleiben tut er – nur flacher, damit die Zeilen darüber den Platz
     bekommen. Unter 34px wäre er im Gehen nicht mehr sicher zu treffen. */
  .wp-foot { padding-top: 6px; padding-bottom: 6px; }
  .btn.ghost-danger { min-height: 34px; }
}

/* ===========================================================================
   Enge Kacheln: Haushalte und Ausgänge auf dem Telefon
   ===========================================================================
   Gilt für BEIDE Telefonlagen – hochkant (≤640px) und quer (flaches Fenster).
   Deshalb eine eigene Regel mit Komma statt zweimal dieselben Werte: gemeinsam
   ist beiden Lagen nicht die Breite, sondern der knappe senkrechte Platz.

   Was hier passiert, ist in beiden Fällen dasselbe: die Kacheln bekommen ihre
   Größe von dem, was sie zeigen, statt vom verfügbaren Raster.

   - Haushaltskacheln standen in 45px-Schritten (40 hoch, 5 Abstand). Bei 58
     Haushalten in einem Haus war das Sheet fast nur noch Scrollen. 36 plus 4
     sind 40er-Schritte, gut drei Kacheln mehr je Bildschirm. Unter 36px wird
     die Kachel im Gehen unsicher – das ist die Untergrenze, nicht der Wunsch.
   - Die Zonenabstände tragen keine Angabe: die Köpfe trennen schon durch
     Versalien und Zähler.
   - Fortschritt und Ausgang sind reine Icon-Knöpfe. Im Sheet wurde daraus je
     Kachel eine 113px breite Fläche für ein 19px-Zeichen, und die sechs
     Ausgänge brauchten zwei Reihen – mit den Abschnittspolstern 210px, bevor
     der erste Kundenwert kam. Sechs in einer Reihe sind je 56px breit, immer
     noch breiter als hoch und breiter als eine Tastaturtaste. Der Fortschritt
     bleibt dreispaltig und füllt die Reihe darüber. */
@media (max-width: 640px), (max-width: 899px) and (max-height: 560px) {
  .hh-row { min-height: 36px; padding: 4px 8px; gap: 6px; }
  .hh-list { gap: 4px; }
  .zones { padding: 5px 0 8px; gap: 6px; }
  .zone-head { padding: 0 9px 4px; }
  .zone-empty { padding: 6px 10px; }

  .sec { padding: 9px 12px; }
  .sec > h3 { margin-bottom: 6px; }
  .checks, .outcomes { gap: 5px; }
  .outcomes { grid-template-columns: repeat(6, 1fr); }
  .check, .out-btn { min-height: 40px; padding: 4px; }
  .tile-ic { width: 26px; height: 26px; border-radius: 8px; }
}

/* ===========================================================================
   Telefon hochkant: ein eigenes Layout, kein geschrumpftes Panel
   ===========================================================================
   Alles davor macht die Schreibtischansicht kleiner. Hier bekommt das Telefon
   eine eigene Ordnung, weil dort eine andere Frage zählt: nicht „was steht
   alles zu diesem Haushalt", sondern „welche Tür als Nächstes, und wie ging
   sie aus". Zwei Entscheidungen tragen das:

   1. DIE LISTE IST EIN FARBRASTER. Die Kachel trägt nicht mehr nur ein
      farbiges Icon, sondern selbst die Farbe ihres Ausgangs. Ein Treppenhaus
      liest sich damit als Bild – grün steht der Abschluss, grau die nicht
      angetroffene Tür, weiß die unbearbeitete –, ohne dass man Zeile für Zeile
      lesen muss. Die Etagenköpfe bleiben beim Scrollen stehen (wie die
      Buchstaben in einem Adressbuch), der Etagenstepper scrollt weg: unterwegs
      zählt, in welcher Etage man liest, nicht wie viele das Haus hat.

   2. DAS AUSGANGSRASTER LIEGT UNTEN UND BLEIBT DORT. Es ist der Grund, warum
      man einen Haushalt überhaupt öffnet, und der Daumen erreicht den unteren
      Rand des Sheets als Erstes. Als `position: sticky; bottom: 0` steht es
      immer da, gleich wie weit oben man in den Kundendaten liest – und weil es
      im Fluss bleibt, verdeckt es nichts. Sechs beschriftete Kacheln, drei je
      Reihe: die Beschriftung, weil sich „nicht angetroffen", „Absage" und
      „ungeeignet" als reine Icons im Gehen zu leicht verwechseln. */
@media (max-width: 640px) {

  /* ---- Liste: das Treppenhaus als Farbraster ---- */
  .floor-ctrl { position: static; }
  .zones { gap: 2px; padding-top: 0; }
  /* Der Etagenkopf bleibt stehen, solange seine Etage im Bild ist. Halbdurch-
     sichtig, damit erkennbar bleibt, dass darunter weitergescrollt wird. */
  .zone-head {
    position: sticky; top: 0; z-index: 2;
    padding: 5px 9px 4px;
    background: rgba(251, 252, 254, .93);
    -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  }
  /* Neun Etagenköpfe zu 44px sind 400px, die keinem Haushalt gehören. Auf dem
     Telefon trägt der Kopf deshalb nur noch Etage und Anzahl – die beiden
     Knöpfe stehen als letzte Kachel im Raster, wo Platz für 38px ist. Damit
     ist der Kopf halb so hoch UND die Knöpfe sind größer als vorher. */
  .zone-acts-head { display: none; }
  .zone-acts-grid { display: flex; gap: 4px; }
  .zone-btn { width: 38px; height: 38px; }
  .zone-acts-grid .zone-btn[data-add-hh] { border-style: dashed; }
  /* Eine leere Etage soll keine drei Zeilen kosten: „leer" lässt die letzte
     Spalte für die Knöpfe frei (-2 zählt von rechts, gilt also auch bei drei
     Spalten auf schmalen Geräten). */
  .hh-list > .zone-empty { grid-column: 1 / -2; padding: 6px 10px; }
  .zone-body { padding-bottom: 6px; }

  /* Die Kachel in der Farbe ihres Ausgangs. Zuerst der Rückfall für Browser
     ohne color-mix, danach die Mischung. */
  .hh-row {
    justify-content: center; gap: 5px; padding: 4px 6px; min-height: 38px;
    box-shadow: none;
    border-color: #e3e9f1; background: #fff;
    border-color: color-mix(in srgb, var(--c) 36%, #fff);
    background: color-mix(in srgb, var(--c) 12%, #fff);
  }
  /* Ohne Ausgang bleibt die Kachel weiß – das freie Feld im Raster ist die
     Arbeit, die noch aussteht. */
  .hh-row.idle { border-color: var(--line); background: #fff; }
  /* Das Icon braucht keine eigene Fläche mehr, die Kachel ist schon farbig. */
  .hh-row .hh-ic, .hh-row .hh-ic.idle {
    width: auto; height: auto; background: none; color: var(--c);
  }
  .hh-row.idle .hh-ic { color: #b9c4d2; }
  .hh-kurz {
    flex: 0 1 auto; text-align: center;
    color: #334155;
    color: color-mix(in srgb, var(--c) 72%, #0f172a);
  }
  .hh-row.idle .hh-kurz { color: var(--ink-2); }
  /* Auswahl und Mehrfachauswahl schlagen die Ausgangsfarbe – sie sagen etwas
     über das Jetzt, die Farbe nur etwas über das Gewesene. */
  .hh-row.on {
    border-color: var(--accent);
    box-shadow: 0 0 0 2.5px rgba(37, 99, 235, .14);
  }
  .hh-row.picked { border-color: var(--accent); background: #eaf2ff; }
  .hh-row .hh-pick { width: 20px; height: 20px; border-radius: 6px; }

  /* ---- Detail: Kundendaten oben, Ausgang unten ---- */
  .wp-right .wp-scroll { display: flex; flex-direction: column; }
  .sec-fortschritt { order: 1; }
  .sec-kunde       { order: 2; }
  .sec-verlauf     { order: 3; border-bottom: 0; }
  .sec-ausgang {
    order: 4;
    position: sticky; bottom: 0; z-index: 3;
    margin-top: auto;                    /* bei kurzem Inhalt an den Fuß */
    background: #fff; border-top: 1px solid var(--line); border-bottom: 0;
    box-shadow: 0 -8px 20px rgba(15, 23, 42, .06);
    padding: 8px 12px calc(9px + var(--safe-bottom));
  }
  /* Die Überschrift ist hier entbehrlich: die Kacheln tragen ihre Namen. */
  .sec-ausgang > h3 { display: none; }

  .outcomes { grid-template-columns: repeat(3, 1fr); gap: 6px; }
  .out-btn {
    flex-direction: column; gap: 3px; min-height: 54px; padding: 7px 3px;
    justify-content: center;
  }
  /* Farbiges Zeichen auch im Ruhezustand: sechs feste Farben, die man nach
     ein paar Tagen trifft, ohne die Beschriftung zu lesen. */
  .out-btn .tile-ic {
    width: 22px; height: 22px; border-radius: 0;
    background: none; color: var(--c);
  }
  .tile-l {
    display: block; font-size: 10.5px; font-weight: 600; line-height: 1.15;
    text-align: center; color: var(--ink-2);
    /* „Abschließbar" ist das längste Wort auf einer Kachel und passt bei der
       jetzigen Schriftgröße knapp. Umbrechen statt überlaufen: die Kachel darf
       in die Höhe wachsen (min-height), aus der Reihe fallen darf sie nicht. */
    overflow-wrap: anywhere; hyphens: auto;
  }
  .out-btn.on { box-shadow: 0 0 0 2px color-mix(in srgb, var(--c) 20%, #fff); }
  .out-btn.on .tile-ic { background: none; color: var(--c); }
  .out-btn.on .tile-l { color: color-mix(in srgb, var(--c) 74%, #0f172a); }

  /* Der Fortschritt ist Zwischenstand, kein Abschluss: dieselbe Dreiteilung,
     aber flacher und mit dem Wort neben dem Zeichen. */
  .checks { grid-template-columns: repeat(3, 1fr); gap: 6px; }
  /* Der Gruppenkopf kostet auf dem Telefon zwei Zeilen Höhe, die die Kacheln
     besser gebrauchen können – also schmal und ohne Versalien-Sperrung. */
  .cgroup + .cgroup { margin-top: 7px; }
  .cgroup-head { margin-bottom: 3px; font-size: 10.5px; letter-spacing: .02em; }
  .cgroup-n { padding: 0 5px; }
  .check { min-height: 42px; gap: 7px; padding: 4px 6px; }
  .check .tile-ic { width: 22px; height: 22px; border-radius: 0; background: none; }
  .check .tile-l { font-size: 11px; }
  .check.on .tile-ic { background: none; color: #16a34a; }
  .check.on .tile-l { color: #15803d; }
}

/* ===========================================================================
   Telefon: das Haus als Tabelle in einem Popup
   ===========================================================================
   Am Schreibtisch bleibt der Arbeitsbereich, wie er ist – zwei Panels an den
   Kartenrändern. Auf dem Telefon tritt an seine Stelle ein Popup: oben die
   Adresse, darunter das Haus als Tabelle (eine Zeile je Etage, ein Quadrat je
   Haushalt), unten „+ Zeile". Tippt man ein Quadrat an, zeigt dieselbe Karte
   das Detail; ein gesetzter Ausgang bringt einen zurück in die Tabelle.

   Gestalterisch bewusst zurückgenommen: keine Rahmen um Felder, keine
   Überschriften, kein Panel-Grau. Farbe tragen nur die Zellen – und die
   bedeutet etwas (den Ausgang). Alles andere ist Weiß, Abstand und ein
   einziges Grau. */
.hh-pop { display: none; }

@media (max-width: 640px) {
  /* Das Sheet hat auf dem Telefon ausgedient – die Tabelle kann alles, was
     seine Listenseite konnte, und das Detail zieht mit ins Popup. */
  .work { display: none; }
  body.work-open .map-controls { left: 50%; bottom: calc(var(--safe-bottom) + 16px); }
  body.pop-open .map-controls { opacity: 0; pointer-events: none; }

  .hh-pop:not([hidden]) {
    position: fixed; inset: 0; z-index: 40;
    display: flex; align-items: flex-end; justify-content: center;
    padding: calc(14px + var(--safe-top)) 8px calc(10px + var(--safe-bottom));
  }
  /* Nur die Karte des Popups nimmt Berührungen an, die Fläche daneben nicht.
     Ohne das lag über der ganzen Karte eine Tippfläche: ein Wisch darüber hat
     das Haus geschlossen, statt die Karte zu schieben – man musste zweimal
     wischen und hielt die Karte für hängen geblieben. Jetzt schiebt der erste
     Wisch, das Haus bleibt offen, und ein bloßer TIPP daneben geht an die
     Google-Karte, wo mapClicked() die Auswahl schließt. Dieselbe Wirkung, ohne
     die Geste zu verschlucken – und im Verschiebe-Modus liegt die Nadel damit
     frei zum Anfassen. */
  .hh-pop { pointer-events: none; }
  .pop-card { pointer-events: auto; }

  /* Verschiebe-Modus: das Popup rückt zusammen, damit überhaupt Karte da ist,
     auf der sich ziehen lässt – auch die Detailseite, die sonst 97% hoch ist. */
  body.move-mode .pop-card,
  body.move-mode .pop-card.pop-detail { height: auto; max-height: 42%; }
  .pop-card {
    width: 100%; max-width: 520px; max-height: 100%;
    display: flex; flex-direction: column; min-height: 0;
    background: #fff; border-radius: 22px; overflow: hidden;
    box-shadow: 0 24px 64px rgba(15, 23, 42, .3);
  }
  /* Das Detail nimmt die volle Höhe: nur dann steht sein Ausgangsraster
     wirklich unten am Daumen und nicht in der Mitte des Bildschirms. */
  .pop-card.pop-detail { height: 100%; }
  /* Achtung: weiter oben steht für die zwei Seiten des Sheets
     `.wp-right { flex: 0 0 50% }`. Im Popup ist die Karte der Flex-Behälter –
     aus 50% Breite würden dort 50% HÖHE, und das Ausgangsraster stünde in der
     Mitte des Bildschirms. */
  .pop-card .wp-right { flex: 1 1 auto; width: auto; height: auto; min-height: 0; border: 0; box-shadow: none; }

  /* ---- Kopf: die Adresse IST die Überschrift ---- */
  .pop-head { display: flex; align-items: center; gap: 8px; padding: 12px 12px 6px; }
  /* Umbruch erlaubt: mit dem Adresszusatz sind es drei Felder, und auf 390px
     bliebe vom Straßennamen sonst nichts übrig. Zeile eins ist die Anschrift,
     Zeile zwei der Zusatz mit PLZ und Ort. */
  .pop-addr { flex: 1 1 auto; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; min-width: 0; }
  /* 16px, weil iOS bei kleinerer Schrift in Eingabefeldern hineinzoomt. */
  .pop-street, .pop-nr {
    border: 0; background: transparent; padding: 4px 0; min-height: 40px;
    font: inherit; font-size: 16px; font-weight: 650; color: var(--ink);
    letter-spacing: -.01em;
  }
  .pop-street { flex: 1 1 auto; min-width: 0; }
  .pop-nr { flex: 0 0 auto; width: 58px; }
  .pop-street:focus, .pop-nr:focus, .pop-zus:focus { outline: 0; box-shadow: 0 2px 0 var(--accent); }
  .pop-zus {
    flex: 1 1 55%; min-width: 0; order: 3;
    border: 0; background: transparent; padding: 2px 0; min-height: 30px;
    font: inherit; font-size: 13px; font-weight: 600; color: var(--ink-2);
  }
  .pop-zus::placeholder { color: #b6c1cf; font-weight: 500; }
  /* Die PLZ steht hinter der Hausnummer, eine Stufe leiser als die Adresse –
     sie ist Auskunft, nicht Überschrift. */
  .pop-plz {
    flex: 0 0 auto; order: 4; color: var(--muted);
    font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }
  .pop-plz[hidden] { display: none; }
  .pop-x {
    appearance: none; cursor: pointer; flex: 0 0 auto;
    width: 38px; height: 38px; border-radius: 12px; border: 0;
    background: var(--line-soft); color: var(--ink-2);
    display: flex; align-items: center; justify-content: center;
  }
  .pop-x:active { background: #e2e8f0; }

  /* ---- Die Tabelle ---- */
  .pop-body { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 6px 12px 12px; }
  /* ---- Das Haus ----
     Breiter als der Rumpf → es scrollt waagerecht. Schmaler → es steht mittig,
     statt links zu kleben. Dach oben, Bodenlinie unter dem Erdgeschoss, alles
     darunter liegt sichtbar unter der Erde. */
  .haus { width: max-content; min-width: 60%; margin: 0 auto; }
  /* Mit leichtem Überstand, wie ein Dach ihn hat. */
  .haus-dach {
    display: block; width: calc(100% + 12px); margin-left: -6px;
    height: 26px; color: #c3cddb;
  }
  .haus-dach polygon { fill: currentColor; }
  .haus-wand {
    display: flex; flex-direction: column; gap: 6px;
    padding: 7px 7px 8px;
    background: #eef2f7;
    border: 1px solid #dfe6ef; border-top: 0;
  }
  /* Die Erde: eine kräftige Linie, an der das Haus aufsitzt. */
  .haus-boden {
    height: 5px; border-radius: 3px; background: #c3cddb;
    margin: 0 -8px;
  }
  /* Unter der Erde: gedämpft, mit schrägen Streifen wie ein Schnitt durchs
     Erdreich. Die Zellen darin bleiben normal lesbar. */
  .haus-keller {
    display: flex; flex-direction: column; gap: 6px;
    padding: 7px; margin: 0 6px;
    border: 1px solid #e2e8f0; border-top: 0;
    border-radius: 0 0 10px 10px;
    background: repeating-linear-gradient(45deg, #f1f5f9 0 6px, #eef2f7 6px 12px);
  }
  .htab-row { display: flex; align-items: center; gap: 6px; }
  /* Das Etagenkürzel bleibt am linken Rand stehen, wenn eine lange Zeile
     waagerecht gescrollt wird – sonst wüsste man nicht mehr, wo man ist. */
  /* Die Stockwerknummer. Sie bleibt am linken Rand stehen, wenn eine lange
     Zeile waagerecht gescrollt wird – sonst wüsste man nicht mehr, in welchem
     Stockwerk man liest. Dunkler als ein Beiwerk, weil sie die Zeile benennt. */
  /* Die Stockwerknummer ist zugleich der Knopf „das hier ist das Erdgeschoss".
     Sie nimmt deshalb die ganze Zeilenhöhe ein – 26×14 wären zum Treffen zu
     wenig, 26×Zellhöhe reicht. */
  .htab-rl {
    appearance: none; border: 0; padding: 0; cursor: pointer;
    position: sticky; left: 0; z-index: 1; flex: 0 0 auto; align-self: stretch;
    display: flex; align-items: center; justify-content: flex-end;
    width: 26px; background: transparent; white-space: nowrap;
    font: inherit; font-size: 12px; font-weight: 700; color: var(--ink-2);
    font-variant-numeric: tabular-nums;
  }
  /* Das Erdgeschoss ist die Bezugszeile – es trägt seinen Namen kräftiger. */
  .htab-row.eg > .htab-rl { color: var(--accent); }
  .htab-row.ug > .htab-rl { color: var(--muted); }

  /* Knöpfe am Dach und unter der Erde: leise, gestrichelt, gleiche Sprache wie
     das „+" am Zeilenende. */
  .haus-first, .haus-last { display: flex; justify-content: center; gap: 6px; padding: 0 0 4px; }
  .haus-last { padding: 6px 0 0; }
  .haus-add, .haus-del {
    appearance: none; cursor: pointer; display: flex; align-items: center; gap: 5px;
    min-height: 36px; padding: 0 12px; border-radius: 12px;
    border: 1px dashed #d3dce8; background: #fff; color: #8c99ab;
    font-size: 12px; font-weight: 600;
  }
  .haus-del { padding: 0 10px; }
  .haus-add:active, .haus-del:active { color: var(--accent); border-color: #bcd4ff; background: #f6faff; }
  .haus-add[disabled], .haus-del[disabled],
  .haus-add[aria-disabled="true"], .haus-del[aria-disabled="true"] { opacity: .4; cursor: default; }

  /* --kante rechnet popTabelle aus (Breite) und passeZellenAnHoehe korrigiert
     sie nach (Höhe): so groß wie möglich, ohne dass das Haus scrollen muss. */
  .haus { --kante: 54px; }
  .htab-c {
    appearance: none; cursor: pointer; flex: 0 0 auto;
    width: var(--kante); height: var(--kante); border-radius: 15px; padding: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
    border: 1px solid #e3e9f1; background: #fff;
    border-color: color-mix(in srgb, var(--c) 38%, #fff);
    background: color-mix(in srgb, var(--c) 13%, #fff);
    transition: transform .12s, box-shadow .12s, border-color .12s;
    -webkit-touch-callout: none; -webkit-user-select: none; user-select: none;
  }
  .htab-c.idle { border-color: var(--line); background: #fff; }
  /* In der Tür steht NUR ihr Ausgang. Das Zeichen wächst mit der Zelle mit –
     die Kantenlänge ändert sich je nach Haus (siehe --kante), ein fest
     gesetztes Icon wäre mal verloren und mal zu groß. */
  .htab-ic {
    display: flex; align-items: center; justify-content: center;
    width: 56%; height: 56%; color: var(--c);
  }
  .htab-ic svg { width: 100%; height: 100%; }
  .htab-c.idle .htab-ic { color: #c6d0dd; }
  /* Der zuletzt geöffnete Haushalt bleibt erkennbar – man kommt aus ihm zurück. */
  .htab-c.on { border-color: var(--accent); box-shadow: 0 0 0 2.5px rgba(37, 99, 235, .15); }

  /* Ziehen: Original blass, Klon am Finger, Ziel eingedrückt. */
  .htab-c.dragging { opacity: .25; }
  .htab-c.ziel { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(37, 99, 235, .2); transform: scale(.92); }
  .htab-ghost {
    position: fixed; z-index: 60; pointer-events: none; margin: 0;
    transform: scale(1.08);
    box-shadow: 0 14px 34px rgba(15, 23, 42, .32);
  }
  /* Über dem Eimer tritt der Klon zurück, damit das Ziel sichtbar bleibt. */
  .htab-ghost.vorm-muell { opacity: .5; }

  /* Hinzufügen: gestrichelt, weil es kein Haushalt ist, sondern ein leerer
     Platz, der einer werden kann. Rechts in der Zeile eine Spalte, unter der
     Tabelle eine Zeile. */
  .htab-plus {
    appearance: none; cursor: pointer;
    border: 1px dashed #d3dce8; background: #fff; color: #a7b3c4;
    display: flex; align-items: center; justify-content: center;
  }
  .htab-plus:active { background: #f8fafc; color: var(--accent); border-color: #bcd4ff; }
  .htab-plus { flex: 0 0 auto; width: var(--kante); height: var(--kante); border-radius: 15px; }

  /* ---- Aufbau-Blatt: zwei Zahlen, ein Bild, ein Knopf ---- */
  .pop-body.auf { padding: 10px 18px 16px; }
  .auf-frage { margin: 2px 0 12px; font-size: 15px; font-weight: 650; color: var(--ink); }
  .auf-vor {
    appearance: none; border: 0; background: transparent; cursor: pointer;
    display: block; width: 168px; margin: 0 auto 16px; padding: 0;
  }
  .auf-vor:active .auf-wand { background: #eef4ff; border-color: #bcd4ff; }
  .auf-tipp {
    display: block; margin-top: 7px; white-space: nowrap; text-align: center;
    font-size: 10.5px; font-weight: 600; letter-spacing: .01em; color: var(--accent);
  }
  .auf-vor .haus-dach { height: 14px; }
  .auf-wand {
    display: flex; flex-direction: column; gap: 3px; padding: 5px;
    background: #f8fafc; border: 1px solid #e2e8f0; border-top: 0;
  }
  .auf-r { display: flex; gap: 3px; justify-content: center; }
  .auf-r i { display: block; width: 12px; height: 12px; border-radius: 3px; background: #dbe3ee; }
  .auf-zeile {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 9px 0; border-bottom: 1px solid var(--line-soft);
  }
  .auf-l { font-size: 13px; font-weight: 500; color: var(--ink-2); }
  .auf-step { display: flex; align-items: center; gap: 4px; flex: 0 0 auto; }
  .auf-b {
    appearance: none; cursor: pointer; width: 40px; height: 40px; border-radius: 13px;
    border: 1px solid var(--line); background: #fff; color: var(--ink-2);
    display: flex; align-items: center; justify-content: center;
  }
  .auf-b:active { background: var(--line-soft); }
  .auf-b[disabled] { opacity: .35; cursor: default; }
  .auf-v { min-width: 30px; text-align: center; font-size: 16px; font-weight: 700; font-variant-numeric: tabular-nums; }
  .auf-ok {
    appearance: none; cursor: pointer; width: 100%; margin-top: 16px;
    min-height: 48px; border-radius: 15px; border: 0;
    background: var(--accent); color: #fff; font-size: 14.5px; font-weight: 650;
  }
  .auf-ok:active { filter: brightness(.94); }
  .auf-skip {
    appearance: none; cursor: pointer; width: 100%; margin-top: 6px; min-height: 38px;
    border: 0; background: transparent; color: var(--muted); font-size: 12.5px; font-weight: 500;
  }

  /* ---- Fuß: Zählstand links, das Seltene rechts ---- */
  .pop-foot {
    flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between;
    gap: 8px; padding: 6px 10px 10px; border-top: 1px solid var(--line-soft);
  }
  .pop-count { font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; padding-left: 4px; }
  .pop-foot .btn.ghost-danger { min-height: 36px; }
  /* Seit „Verschieben" dazugekommen ist, stehen hier drei Dinge. Der Zählstand
     ist das Unwichtigste davon und rückt in eine eigene Zeile, wenn es eng wird –
     die beiden Knöpfe bleiben zusammen und behalten ihre Daumengröße. */
  .pop-foot { flex-wrap: wrap; }
  /* Erste Zeile: Zählstand links, Wertungsschalter rechts – beides sagt, WIE
     das Haus dasteht. Darunter die beiden Knöpfe, die etwas TUN, in voller
     Daumengröße. Die beiden oberen stecken in .pop-status und nicht bloß in
     derselben Flex-Zeile: sonst rutscht „Verschieben" mit hoch, sobald die
     Beschriftung des Schalters ein paar Pixel kürzer wird, und der Fuß baut
     sich je nach Zustand anders auf. */
  .pop-status {
    flex: 1 1 100%; order: -1;
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
  }
  .pop-count { flex: 0 1 auto; }
  .pop-foot .btn { flex: 1 1 0; min-height: 38px; justify-content: center; }
  .pop-foot .btn.move-btn { font-size: 12.5px; }
}

/* ===========================================================================
   Hochkant-Sperre
   ===========================================================================
   Die App soll auf dem Telefon aufrecht bleiben. Das Manifest sagt das mit
   `"orientation": "portrait"` – nur hält sich daran allein die INSTALLIERTE App
   unter Android/Chromium. iOS wertet das Feld überhaupt nicht aus, weder in der
   Lasche noch vom Home-Bildschirm, und in einer gewöhnlichen Browser-Lasche
   greift es nirgends. `screen.orientation.lock()` hilft auch nicht weiter: das
   verlangt Vollbild und fehlt auf iOS ganz.

   Eine Webseite kann das Gerät also nicht am Drehen hindern. Was sie kann, ist
   sich quer zu verweigern – und genau das tut diese Schicht.

   Die Abgrenzung läuft über die Höhe, nicht über die Breite: quer gehalten hat
   ein Telefon 320–430px Höhe, ein iPad dagegen 768 und mehr. Zusammen mit
   `pointer: coarse` trifft die Regel damit Telefone und lässt Tablet und
   Schreibtisch in Ruhe – dort ist Querformat ausdrücklich weiter erlaubt.
   Dieselbe 560px-Grenze wie beim flachen Sheet weiter oben. */

.hochkant { display: none; }

@media (orientation: landscape) and (max-height: 560px) and (pointer: coarse) {
  .hochkant {
    position: fixed; inset: 0;
    /* Über allem, auch über dem Sperrbildschirm (100): quer soll man nicht
       einmal das Passwort eintippen müssen. */
    z-index: 120;
    display: flex; align-items: center; justify-content: center;
    background: #0b1220;
    /* Quer sitzt die Aussparung an der SEITE – dafür gibt es keine der beiden
       :root-Variablen, die env()-Werte stehen hier deshalb direkt. */
    padding: 20px calc(20px + env(safe-area-inset-right, 0px))
             20px calc(20px + env(safe-area-inset-left, 0px));
  }

  .hochkant-box {
    display: flex; flex-direction: column; align-items: center; gap: 9px;
    max-width: 420px; text-align: center;
  }
  .hochkant-box svg { color: #38bdf8; }
  .hochkant-box strong { color: #f8fafc; font-size: 16px; font-weight: 650; }
  .hochkant-box span { color: #94a3b8; font-size: 13px; line-height: 1.5; }

  /* Was darunter liegt, ruht: ohne das scrollt die Liste hinter der Schicht
     weiter mit, wenn der Finger sie streift. */
  body { overflow: hidden; }
}

/* ===========================================================================
   Foto: Zähler ablichten, drei Nummern zum Kopieren
   ===========================================================================
   Der Tab ist für eine Hand am Kundentisch gebaut: eine große Bühne, ein
   großer Auslöser, drei Zeilen mit Tippflächen, die man nicht verfehlen kann.
   Die Werte stehen in Tabellenziffern – bei einer Zählernummer entscheidet
   die Stelle, und proportionale Ziffern verwischen genau die. */

.foto-card {
  padding: 12px; border: 1px solid var(--line); border-radius: var(--r-tile);
  background: var(--card); box-shadow: var(--shadow-tile);
}

/* Die Bühne. 3:4 hochkant – so hält man das Telefon, und so passt eine
   Rechnungsseite hinein, ohne dass man sie drehen müsste. */
.foto-buehne {
  position: relative; overflow: hidden;
  aspect-ratio: 3 / 4; max-height: 58vh;
  border-radius: 11px; background: #0b1220;
  display: flex; align-items: center; justify-content: center;
}
.foto-buehne video, .foto-buehne img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.foto-buehne video[hidden], .foto-buehne img[hidden] { display: none; }

/* Nach dem Auslösen: flach, und das Bild GANZ zu sehen (contain statt cover).
   Beim Zielen darf beschnitten werden, beim Prüfen nicht – sonst fehlt am Rand
   womöglich genau die Zeile, gegen die man die Zahl halten will. */
.foto-card--klein .foto-buehne { aspect-ratio: auto; height: 27vh; background: #0f172a; }
.foto-card--klein .foto-buehne img { object-fit: contain; }

/* Der Rahmen ist eine Zielhilfe, keine Beschneidung: gelesen wird immer das
   ganze Bild. Er sagt nur, wo die Nummer ungefähr liegen sollte, damit man
   nicht aus zwei Metern auf einen Zählerschrank hält. */
.foto-rahmen {
  position: absolute; inset: 16% 8%;
  border: 2px dashed rgba(255, 255, 255, .5); border-radius: 10px;
  pointer-events: none;
}
.foto-rahmen[hidden] { display: none; }

/* Was über dem Bild liegt: „Liest …", Kamerafehler, Startmeldung. */
.foto-lage {
  position: absolute; inset: 0; z-index: 2;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 9px;
  padding: 20px; text-align: center;
  background: rgba(11, 18, 32, .72); color: #e2e8f0;
  font-size: 14px; font-weight: 600;
}
.foto-lage[hidden] { display: none; }
.foto-lage-sub { font-size: 12.5px; font-weight: 500; color: #94a3b8; }
.foto-lage--liest { flex-direction: row; gap: 11px; }

.foto-spin {
  width: 19px; height: 19px; flex: 0 0 auto;
  border: 2.4px solid rgba(226, 232, 240, .28); border-top-color: #e2e8f0;
  border-radius: 50%; animation: foto-dreh .7s linear infinite;
}
@keyframes foto-dreh { to { transform: rotate(360deg); } }
/* Wer Bewegung abgestellt hat, bekommt ein Pulsieren statt eines Rades – ganz
   ohne Rückmeldung wüsste man nicht, ob überhaupt etwas läuft. */
@media (prefers-reduced-motion: reduce) {
  .foto-spin { animation: foto-puls 1.1s ease-in-out infinite; border-top-color: rgba(226, 232, 240, .28); }
  @keyframes foto-puls { 50% { opacity: .35; } }
}

/* Auslöser und Datei-Umweg. */
.foto-leiste { display: flex; gap: 8px; margin-top: 10px; }

.foto-shot {
  appearance: none; flex: 1 1 auto; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  /* Hoch genug, um im Sitzen mit dem Daumen sicher getroffen zu werden. */
  min-height: 52px; padding: 0 18px;
  border: 0; border-radius: 12px;
  background: var(--accent); color: #fff;
  font: inherit; font-size: 16px; font-weight: 650;
}
.foto-shot:active { filter: brightness(.92); }
.foto-shot:disabled { background: var(--line); color: var(--muted); cursor: default; }
/* Nach dem Lesen ist derselbe Knopf der Weg zurück zum Livebild – er soll dann
   nicht mehr wie die Hauptsache aussehen, das sind jetzt die drei Zeilen. */
.foto-shot--neu { background: var(--card); color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); }
.foto-shot--neu:active { background: var(--line-soft); }

.foto-datei {
  flex: 0 0 auto; cursor: pointer;
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 52px; padding: 0 15px;
  border: 1px solid var(--line); border-radius: 12px; background: var(--card);
  color: var(--ink-2); font-size: 14px; font-weight: 600;
}
.foto-datei:active { background: var(--line-soft); }

/* ---- Die drei Zeilen ---- */

.foto-werte { margin-top: 12px; display: flex; flex-direction: column; gap: 8px; }

/* Vier Spalten: Symbol, Feld, Kreuz, Kopieren. Das Kreuz steht neben dem Feld
   und nicht in einem Menü – „von Hand löschen" darf kein Suchspiel sein. */
.foto-zeile {
  display: grid; grid-template-columns: auto 1fr auto auto; align-items: center;
  gap: 3px 10px; padding: 10px 12px;
  border: 1px solid var(--line); border-radius: var(--r-tile);
  background: var(--card); box-shadow: var(--shadow-tile);
  color: var(--ink); font: inherit;
}
.foto-zeile--kopiert { border-color: #86efac; background: #f0fdf4; }

/* Frisch aus dem letzten Foto: einmal kurz aufleuchten. Bei drei Feldern, von
   denen das zweite Foto nur eines füllt, sieht man sonst nicht, welches. */
.foto-zeile--frisch { animation: foto-neu 1.6s ease-out; }
@keyframes foto-neu {
  0%, 35% { border-color: var(--accent); background: #eff6ff; }
  100%    { border-color: var(--line); background: var(--card); }
}
@media (prefers-reduced-motion: reduce) { .foto-zeile--frisch { animation: none; border-color: var(--accent); } }

.foto-ic { display: flex; grid-row: span 2; color: var(--muted); }
.foto-zeile--kopiert .foto-ic { color: #16a34a; }

.foto-lab {
  grid-column: 2; display: flex; align-items: center; gap: 7px;
  font-size: 11.5px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--muted);
}
/* „bestätigt": das zweite Foto liest denselben Wert. Eine stille Bestätigung
   ist mehr wert als sie aussieht – sie ersetzt das Vergleichen von Hand. */
/* Die Beschriftung bricht nicht um: „BISHERIGE KUNDENNUMMER" neben dem Häkchen
   ergäbe sonst eine zweizeilige Zeile, und dann stehen die drei Felder
   unterschiedlich hoch nebeneinander. */
.foto-lab-txt { white-space: nowrap; }
.foto-best {
  display: inline-flex; align-items: center; gap: 3px; flex: 0 0 auto;
  letter-spacing: 0; text-transform: none; font-size: 10.5px; color: #16a34a;
}

/* Das Feld ist ein Eingabefeld, sieht aber nicht danach aus: kein Rahmen, kein
   Kasten. Es soll gelesen werden wie ein Ergebnis und sich trotzdem antippen
   und ändern lassen. */
.foto-wert {
  grid-column: 2; min-width: 0; width: 100%;
  padding: 1px 0; border: 0; background: transparent;
  font: inherit; font-size: 21px; font-weight: 650; line-height: 1.3;
  color: var(--ink); font-variant-numeric: tabular-nums;
  text-overflow: ellipsis;
}
.foto-wert:focus { outline: none; }
/* Beim Bearbeiten eine Grundlinie – sonst weiß man nicht, ob der Cursor sitzt. */
.foto-wert:focus { box-shadow: inset 0 -2px 0 -1px var(--accent); }
.foto-wert::placeholder { font-size: 14px; font-weight: 500; color: var(--muted); }

.foto-x, .foto-kop {
  grid-row: span 2; display: flex; cursor: pointer;
  align-items: center; justify-content: center;
  width: 38px; height: 38px; border: 0; border-radius: 10px;
  background: var(--line-soft); color: var(--ink-2);
}
.foto-x { grid-column: 3; background: transparent; color: var(--muted); }
.foto-x:active { background: var(--line-soft); }
.foto-kop { grid-column: 4; }
.foto-kop:active { filter: brightness(.95); }
.foto-x:disabled, .foto-kop:disabled { opacity: .3; cursor: default; }
.foto-zeile--kopiert .foto-kop { background: #dcfce7; color: #16a34a; }

/* Der abweichende Vorschlag. Er sitzt UNTER dem Feld und ersetzt nichts – der
   alte Wert steht weiter oben und bleibt, bis jemand „Übernehmen" tippt. */
.foto-abw {
  grid-column: 2 / -1; display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  margin-top: 6px; padding-top: 7px; border-top: 1px dashed var(--line);
  font-size: 12.5px; color: var(--ink-2);
}
.foto-abw-txt { flex: 1 1 auto; min-width: 0; }
.foto-abw-txt strong { font-weight: 700; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.foto-abw-ja {
  appearance: none; cursor: pointer; flex: 0 0 auto;
  padding: 6px 11px; border: 0; border-radius: 8px;
  background: var(--accent); color: #fff; font: inherit; font-size: 12.5px; font-weight: 650;
}
.foto-abw-ja:active { filter: brightness(.92); }
.foto-abw-nein {
  appearance: none; cursor: pointer; flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border: 0; border-radius: 8px;
  background: transparent; color: var(--muted);
}
.foto-abw-nein:active { background: var(--line-soft); }

/* Stutzig, nicht falsch: der Wert bleibt stehen und bleibt kopierbar. Die App
   weiß nicht, was auf dem Papier steht – sie weiß nur, dass eine MaLo elf
   Ziffern hat. Also ein Hinweis zum Nachsehen, keine Sperre. */
.foto-zeile--stutzig { border-color: #fcd34d; background: #fffbeb; }
.foto-zeile--stutzig .foto-ic { color: #d97706; }
.foto-warn {
  grid-column: 2 / -1; display: flex; align-items: center; gap: 5px;
  margin-top: 3px; font-size: 12px; font-weight: 600; color: #b45309;
}
.foto-warn svg { flex: 0 0 auto; }

.foto-fuss { display: flex; align-items: center; gap: 10px; margin-top: 2px; }
.foto-alles {
  appearance: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 7px;
  padding: 9px 13px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--card); color: var(--ink-2);
  font: inherit; font-size: 13.5px; font-weight: 600;
}
.foto-alles:active { background: var(--line-soft); }

/* „Alles leeren" ist der Gegenpol zum Sammeln: er steht sichtbar da, aber nicht
   als Hauptknopf – man tippt ihn einmal je Kunde, nicht einmal je Foto. */
.foto-leeren {
  appearance: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 9px 12px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--card); color: var(--ink-2);
  font: inherit; font-size: 13.5px; font-weight: 600;
}
.foto-leeren:active { background: #fef2f2; border-color: #fecaca; color: #b91c1c; }

.foto-merk {
  display: flex; align-items: flex-start; gap: 6px;
  margin-top: 8px; color: var(--muted);
}
.foto-merk svg { flex: 0 0 auto; margin-top: 2px; }

.foto-dauer { margin-left: auto; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }

.foto-fehler {
  display: flex; align-items: flex-start; gap: 9px;
  padding: 12px 13px; border: 1px solid #fecaca; border-radius: var(--r-tile);
  background: #fef2f2; color: #b91c1c; font-size: 13.5px; line-height: 1.45;
}
.foto-fehler svg { flex: 0 0 auto; margin-top: 1px; }

/* ---- Schnell oder genau ---- */

.foto-gang { display: flex; gap: 8px; margin-top: 14px; }
.foto-gang-btn {
  appearance: none; flex: 1 1 0; cursor: pointer; text-align: left;
  display: flex; flex-direction: column; gap: 2px;
  padding: 10px 12px;
  border: 1px solid var(--line); border-radius: var(--r-tile);
  background: var(--card); color: var(--ink-2); font: inherit;
}
.foto-gang-btn.active {
  border-color: var(--accent); color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--accent);
}
.foto-gang-name { font-size: 14px; font-weight: 650; }
.foto-gang-hint { font-size: 11.5px; line-height: 1.35; color: var(--muted); }
