/* ═══════════════════════════════════════════════════════════════════════════
   VICore — MOBILE / RESPONSIVE LAYER
   ---------------------------------------------------------------------------
   WICHTIG: Diese Datei wird als LETZTES Stylesheet eingebunden.
   Regeln stehen in `max-width`-Media-Queries (oder im Desktop-Guard
   `min-width:1024px`, der nur einen bestehenden Bug repariert).
   → Desktop ab 1024px bleibt dadurch konstruktionsbedingt unverändert.

   EINE AUSNAHME (Feedback #6, 08.09.2026): alles, was an `body.vim-active`,
   `body.vim-desktop` oder `body.vim-frame` hängt, steht BEWUSST ohne Media
   Query. Welche Schale läuft, entscheidet allein mobile.js (`mobilAktiv`) — eine
   zweite Kontextabfrage im Stylesheet war genau der Grund, warum die Schale auf
   Tablets nie sichtbar wurde. CSS folgt der Klasse, es urteilt nicht mit.

   Breakpoints (vereinheitlicht):
     • Mobile  : ≤ 767px
     • Tablet  : 768–1023px   → wie Mobile-Navigation (Drawer), aber mehr Platz
     • Desktop : ≥ 1024px     → unverändert
   ═══════════════════════════════════════════════════════════════════════════ */


/* ═══════════════════════════════════════════════════════════════════════════
   DESKTOP-GUARD (≥1024px) — repariert Bug: body{flex-direction:column} @≤1100px
   stapelte die 100vh-Sidebar über den Inhalt. Ab 1024px IMMER nebeneinander.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (min-width: 1024px) {
  body { flex-direction: row; }
  .main { flex-direction: column; }
  .sidebar { position: relative; transform: none; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   TABLET + MOBILE (≤1023px) — einheitliche Offcanvas-Navigation
   Behebt die „tote Zone 769–860px": Drawer UND Hamburger ab derselben Grenze.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 1023px) {
  /* App füllt volle Breite, Sidebar liegt als Drawer darüber */
  body { flex-direction: row; }

  .sidebar {
    position: fixed;
    left: 0; top: 0; bottom: 0;
    height: 100vh; height: 100dvh;
    width: 280px;
    max-width: 86vw;
    transform: translateX(-100%);
    transition: transform .22s cubic-bezier(.4,0,.2,1);
    z-index: 1600;
    box-shadow: 0 0 40px rgba(0,0,0,.28);
    border-right: none;
  }
  .sidebar.open { transform: translateX(0); }
  .sidebar-resize { display: none !important; }
  /* Auf Mobile nie eingeklappt — der Drawer zeigt immer die volle Navigation */
  .sidebar.is-collapsed { width: 280px; }
  .sidebar-collapse-btn { display: none !important; }

  /* Hamburger + Backdrop sichtbar machen */
  .sidebar-toggle {
    display: inline-flex !important;
    align-items: center; justify-content: center;
    width: 42px; height: 42px;
    flex-shrink: 0;
    background: var(--white, #fff);
    border: 1px solid var(--border, #D8D2C4);
    border-radius: var(--radius-lg);
    color: var(--text-primary, #263029);
    cursor: pointer;
  }
  .sidebar-toggle:active { background: var(--vi-sand, #EFF2F1); }

  .sidebar-backdrop {
    position: fixed; inset: 0;
    background: rgba(14,32,24,.45);
    z-index: 1500;
  }
  .sidebar-backdrop.open { display: block !important; }

  .main { margin-left: 0 !important; width: 100%; }

  /* Kompakte Topbar: Hamburger + Titel + primäre Aktion */
  .topbar {
    padding: 8px 12px;
    gap: 10px;
    min-height: 54px;
  }
  /* Platzfresser ausblenden: Datenimport-Button (Header-Suche entfällt; Suche jetzt nur Seitenleiste) */
  .topbar-right .topbar-btn:not(.topbar-btn-primary) { display: none !important; }
  /* Header-Uhr kompakt (nur Icon + Uhrzeit); Objektkontext-Chip regelt Breite per Flex selbst */
  .topbar-clock .tc-main { display: none; }
  .topbar-objctx-na { display: none; }

  .content { padding: 16px 14px; }

  /* Seitenkopf / Cockpit-Kopf gestapelt */
  .page-header,
  .cockpit-topbar { flex-direction: column; align-items: stretch; gap: 12px; }

  /* Objekt-Picker volle Breite */
  .vi-obj-picker-wrap,
  .vi-obj-picker-sm { width: 100% !important; }
  .cockpit-topbar-right { flex-direction: column; align-items: stretch; gap: 10px; }
  .cockpit-topbar-right > * { width: 100%; }

  /* Touch-Targets: mind. ~44px Höhe für klickbare Kernelemente */
  .nav-item,
  .topbar-btn,
  .vi-btn-primary,
  .btn-primary,
  .btn-secondary { min-height: 44px; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   MOBILE (≤767px) — Karten statt Tabellen, Fullscreen-Modale, Bottom-Nav
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 767px), (max-height: 540px) and (pointer: coarse) {

  .content { padding: 14px 12px 84px; } /* Platz unten für Bottom-Nav */
  .breadcrumb { display: none; }

  /* ── VORGÄNGE: div-Grid-„Tabelle" → Karten ───────────────────────────── */
  .cases-table-header { display: none !important; }
  .cases-list { display: flex; flex-direction: column; gap: 10px; }
  .cases-row {
    display: flex !important;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 10px;
    padding: 14px;
    border: 1px solid var(--border, #D8D2C4);
    border-radius: var(--radius-xl);
    background: var(--white, #fff);
    box-shadow: 0 1px 3px rgba(0,0,0,.04);
    width: auto;
  }
  .cases-row > div { width: auto !important; min-width: 0; padding: 0; }
  .cases-col-number    { order: 1; font-family: var(--vi-font-mono, monospace); font-size: var(--text-xs); color: var(--muted, #5F6B66); }
  .cases-col-actions   { order: 2; margin-left: auto; }
  .cases-col-title     { order: 3; flex: 1 0 100%; }
  .cases-col-title .cases-row-title { font-size: var(--text-base); font-weight: 600; line-height: 1.3; }
  .cases-col-status    { order: 4; }
  .cases-col-priority  { order: 5; }
  .cases-col-object    { order: 6; flex: 1 0 100%; font-size: var(--text-sm); color: var(--vi-ink-70, #3A4441); }
  .cases-col-category  { order: 7; flex: 1 0 100%; font-size: var(--text-xs); color: var(--muted, #5F6B66); }
  .cases-col-owner       { order: 6; flex: 1 0 100%; }
  .cases-col-next-action { order: 8; flex: 1 0 100%; font-size: var(--text-xs); }
  /* Bestehende Desktop-Schmalregeln blenden Objekt/Kategorie/Priorität/Besitzer aus — in der Karte zeigen */
  .cases-col-object,
  .cases-col-category,
  .cases-col-priority,
  .cases-col-owner { display: block !important; }
  .cases-col-owner .cases-owner-select { max-width: 100%; }
  /* Titel-Stift auf Mobile dauerhaft sichtbar (kein Hover) */
  .cases-title-edit { opacity: 1; }
  /* Objektzelle in der Karte: Name prominent, Kontext/Adresse sekundär darunter */
  .cases-col-object { display: block !important; }
  .cases-col-object .cases-obj-name { font-weight: 600; font-size: var(--text-md); -webkit-line-clamp: 2; }
  .cases-col-object .cases-obj-meta { font-size: var(--text-xs); color: var(--muted, #5F6B66); white-space: normal; }

  /* Filter/Suchleiste der Vorgänge kompakt stapeln.
     ID-Präfix nötig: #page-vorgaenge-Regeln setzen flex:1 1 280px etc. — im
     Column-Layout würde die flex-basis sonst zur (riesigen) HÖHE. */
  #page-vorgaenge .cases-filter-bar,
  .cases-toolbar { flex-direction: column; align-items: stretch; gap: 10px; }
  #page-vorgaenge .cases-filter-group,
  #page-vorgaenge .cases-filter-search,
  #page-vorgaenge .cases-filter-category { flex: 0 0 auto; min-width: 0; width: 100%; }
  .cases-toolbar > * { width: 100%; }

  /* ── DOKUMENTE: echtes <table> → Block-Karten ────────────────────────── */
  .dok-table thead { display: none; }
  .dok-table,
  .dok-table tbody,
  .dok-table tr,
  .dok-table td { display: block; width: auto; }
  .dok-table tr {
    border: 1px solid var(--border, #D8D2C4);
    border-radius: var(--radius-xl);
    padding: 12px 14px;
    margin-bottom: 10px;
    background: var(--white, #fff);
    box-shadow: 0 1px 3px rgba(0,0,0,.04);
  }
  .dok-table td { border: none !important; padding: 2px 0; }
  .dok-table td:nth-child(2) { font-size: var(--text-base); font-weight: 600; color: var(--vi-ink, #141A17); padding-bottom: 4px; }
  .dok-table td:last-child { padding-top: 8px; display: flex; gap: 14px; }

  /* Generische Tabellen-Fallbacks: wenigstens scrollbar statt abgeschnitten */
  .data-table-wrapper,
  .table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

  /* ── MODALE: nahezu Fullscreen, sticky Header, scrollbarer Body ──────── */
  .modal-overlay { align-items: stretch; justify-content: stretch; padding: 0; }
  .modal,
  .modal-content,
  .modal-content-large {
    width: 100% !important;
    max-width: 100% !important;
    height: 100vh; height: 100dvh;
    max-height: 100vh; max-height: 100dvh;
    border-radius: 0 !important;
    display: flex; flex-direction: column;
    animation: none;
  }
  /* SAFE AREA FÜR DIE BESTANDSDIALOGE (22.08.2026). `.modal-content` läuft mobil
     als Vollbildfläche über den ganzen Schirm — damit liegt sein Kopf unter dem
     Cutout und seine Aktionsleiste in der Gestenleiste. Die 117 Bestandsdialoge
     einzeln anzufassen wäre weder machbar noch nötig: sie teilen sich diesen
     einen Rahmen, also gehört der Schutz hierher.
     Nur Kopf und Aktionsleiste bekommen den Inset — NICHT zusätzlich der Body,
     sonst entstünde der doppelte Abstand (§14). */
  .modal-header {
    position: sticky; top: 0;
    background: var(--white, #fff);
    z-index: 3;
    padding: calc(14px + var(--app-safe-top)) 16px 14px;
  }
  .modal-close { width: 40px; height: 40px; font-size: 24px; display: flex; align-items: center; justify-content: center; }
  .modal-body { flex: 1 1 auto; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 16px; }
  /* Aktionsleisten unten gut erreichbar */
  .modal-body .form-actions,
  .modal .modal-actions {
    position: sticky; bottom: 0;
    background: var(--white, #fff);
    padding: 12px 0 calc(4px + var(--app-safe-bottom));
    margin-top: 8px;
    border-top: 1px solid var(--border, #D8D2C4);
    display: flex; gap: 10px;
  }
  .modal-body .form-actions > button,
  .modal .modal-actions > button { flex: 1; min-height: 46px; }

  /* Der zentrale Dialograhmen (.modal-content > .modal-footer, vi-canonical.css)
     wurde von der Regel darüber nicht erfasst. Drei Knöpfe nebeneinander
     brauchen dort mehr Platz als ein Telefon hat; bei justify-content:flex-end
     und flex-wrap:nowrap rutscht der erste Knopf aus dem Rahmen und ist wegen
     overflow:hidden nicht mehr erreichbar. Deshalb: umbrechen lassen, Knöpfe
     dürfen schrumpfen, Innenabstand reduziert. */
  .modal-content .modal-footer,
  .vi-dlg .modal-footer,
  .vi-dlg-actions {
    flex-wrap: wrap;
    gap: 8px;
    padding: 12px 14px calc(12px + var(--app-safe-bottom));
  }
  .modal-content .modal-footer > button,
  .vi-dlg .modal-footer > button,
  .vi-dlg-actions > button {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 46px;
    white-space: nowrap;
  }
  /* Ein Abstandshalter darf auf schmalen Schirmen keine Zeile erzwingen. */
  .vi-dlg .modal-footer .vi-dlg-spacer { display: none; }

  /* ── FORMULARE: einspaltig, iOS-Zoom verhindern (≥16px) ──────────────── */
  /* .form-row ist ein Grid (style.css) — flex-direction greift dort nicht.
     Einspaltig über die Spaltendefinition, sonst quetschen sich zwei Felder
     nebeneinander (gemessen auf 412 px: „Stadt" neben „Nutzungsart"). */
  .form-row, .form-row-3, .form-row-2 {
    display: grid; grid-template-columns: 1fr; gap: 12px;
  }
  .form-group { width: 100%; }
  .form-input, .form-select, .form-textarea,
  .modal input, .modal select, .modal textarea,
  input[type="text"], input[type="email"], input[type="number"],
  input[type="date"], input[type="search"], input[type="password"], select, textarea {
    font-size: var(--text-base) !important;
  }

  /* ── KPI / Cockpit: kompakt, gut scannbar ────────────────────────────── */
  .cockpit-kpi-bar { grid-template-columns: repeat(2, minmax(0,1fr)); gap: 10px; }

  /* Generische Karten-Grids einspaltig */
  .card-grid, .objekt-cards, .cockpit-grid { grid-template-columns: 1fr; }

  /* Tab-Leisten horizontal scrollbar (Vorgangsdetail etc.) */
  .case-tabs-nav, .abs-tabs, .vi-tabs, .tabs-nav {
    overflow-x: auto; -webkit-overflow-scrolling: touch; flex-wrap: nowrap;
  }
  .case-tabs-nav::-webkit-scrollbar, .abs-tabs::-webkit-scrollbar { height: 0; }

}

/* Die frühere Bottom-Leiste `#vi-bottomnav` (.vi-bottomnav/.vi-bn-item) ist am
   22.08.2026 aus index.html entfernt worden; ihre CSS-Reste wurden am selben Tag
   mit dem Neuaufbau der mobilen Informationsarchitektur gelöscht. Die mobile
   Navigation ist ausschließlich `.vim-nav` in der App-Schale — es darf keine
   zweite Bottom-Navigation und kein „Sicherungs-CSS" dafür geben. */


/* ═══════════════════════════════════════════════════════════════════════════
   PAKET 4 — Mobile UX & A11y (Ergänzungen, ≤1023px)
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 1023px) {
  /* Touch-Targets für KLEINE Aktionen (Icon-/Tabellen-/Inline-Buttons) — ≥40px Tap-Fläche.
     Optik bleibt klein (kein visuelles Aufblähen), aber der berührbare Bereich wird größer. */
  .btn-icon, .btn-icon-small, .icon-btn, .cases-row-action,
  .btn-edit, .btn-del, .obj-row-act, .cmp-icon-btn, .eco-icon-btn,
  .case-task-action-btn, .doc-act-btn, .wk-tchip, .btn-icon.sm {
    min-width: 40px; min-height: 40px;
    display: inline-flex; align-items: center; justify-content: center;
  }
  /* Kleine Buttons / Custom-Status-Dropdown bekommen ausreichende Höhe */
  .btn-sm, .csd-btn, .vi-ctx-chip-btn, .wk-vbtn, .wk-adv-btn { min-height: 36px; }
  /* Tabellen-Aktionszellen vertikal mittig + genug Platz */
  td.table-actions, .table-actions { white-space: nowrap; }

  /* Datenlastige Tabellen: horizontal scrollen statt abschneiden.
     Deckt die TATSÄCHLICH verwendeten Wrapper-Klassen ab (nicht nur generische). */
  .cx-wl-wrap, .obj-table-wrap, .doc-table-wrap, .pruef-table-wrap,
  .data-table-wrapper,
  .table-scroll, .stamm-table-wrap, .wk-wl-wrap {
    overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%;
  }
  /* Tabellen darin behalten ihre Mindestbreite → scrollen, statt zu zerquetschen */
  .cx-wl-wrap > table, .obj-table-wrap > table, .pruef-table-wrap > table,
  .data-table-wrapper > table {
    min-width: 640px;
  }
}

/* Skip-Link & Screenreader-Utility (immer aktiv, nicht nur mobil) */
.sr-only {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
.skip-link {
  position: fixed; top: 8px; left: 8px; z-index: 14000;
  transform: translateY(-160%); transition: transform .15s ease;
  background: var(--vi-green, #147352); color: var(--color-surface);
  padding: 10px 16px; border-radius: var(--radius-md); font-weight: 600; font-size: var(--text-sm);
  text-decoration: none; box-shadow: 0 4px 16px rgba(0,0,0,.25);
}
.skip-link:focus { transform: translateY(0); outline: 2px solid var(--color-surface); outline-offset: 2px; }


/* ═══════════════════════════════════════════════════════════════════════════
   VICore — DEDIZIERTE MOBILE ARBEITSOBERFLÄCHE  (#vi-mobile / .vim-*)
   ---------------------------------------------------------------------------
   Eigene, vom Desktop UNABHÄNGIGE App-Schale für die Vor-Ort-Nutzung.
   • Aktiv, sobald `body.vim-active` steht — das entscheidet mobile.js (Telefon
     und Tablet als Vorgabe, jedes Gerät auf ausdrückliche Wahl). Ohne die Klasse
     bleibt hier alles wirkungslos, der Desktop ist dann unverändert.
   • Vollständig unter #vi-mobile / .vim- gekapselt → keine Desktop-Regeln
     werden überschrieben (außer dem bewussten Ausblenden der Desktop-Schale bei
     aktiver Schale, das die alte, unzuverlässige Mobil-Navigation ersetzt).
   ═══════════════════════════════════════════════════════════════════════════ */

/* Standard: Mobil-Schale unsichtbar (Desktop ist führend). */
#vi-mobile { display: none; }

/* `body.vim-active` IST DIE GANZE BEDINGUNG (Feedback #6, 08.09.2026).
   Bis hierher stand dieses Tor in `@media (max-width: 767px), (max-height: 540px)
   and (pointer: coarse)` — zeichengleich mit `MOBIL_KONTEXT` in mobile.js. Das war
   eine ZWEITE Kontextmechanik neben der in JS, und sie kannte den Tablet-Kontext
   (768–1279 px mit grobem Zeiger) nicht: auf jedem Tablet bootete die Schale und
   setzte `vim-active` — und blieb trotzdem `display:none`. Sichtbar war das
   Desktop-Chrome, und der Ansichts-Umschalter, der in der Schale wohnte, war
   unerreichbar. Wer hier je wieder eine Breitenabfrage ergänzt, baut denselben
   Fehler nach: mobile.js entscheidet, das Stylesheet folgt.
   Das GATE über `body.vim-active` bleibt: nur wenn die Mobil-App erfolgreich
   gebootet hat (sonst bleibt der Desktop als Fallback sichtbar — nie ein leerer
   Screen). */
body.vim-active .sidebar,
body.vim-active .main,
body.vim-active .sidebar-backdrop { display: none !important; }

body.vim-active #vi-mobile { display: flex; }
body.vim-active { overflow: hidden; }

/* ── DIE SCHALE AUF EINEM DESKTOP-BILDSCHIRM: zentrierte Gerätespalte ────────
   Wählt ein Verwalter am PC die mobile Ansicht, wird sie NICHT über 2000 px
   gezogen — Kopfzeile, Listenzeilen und Bottom-Navigation behalten die Maße, für
   die sie entworfen wurden. `--vim-frame-l/-w/-inset` sind die EINE Quelle für die
   Lage; die Schale UND die eingebettete Modulseite (.main) folgen beide ihnen.
   Auf Telefon und Tablet stehen sie auf Vollfläche, es ändert sich dort nichts.

   GRENZE, bewusst in Kauf genommen: die fünf eigenen Ansichten der Schale (Start ·
   Tickets · Erfassen · Fällig · Mehr) sind .vim-Markup und sitzen in 480 px genau
   richtig. Eine EINGEBETTETE Modulseite (body.vim-embed) richtet sich dagegen nach
   Media Queries, und die sehen das echte Fenster (z. B. 1600 px) — sie rendert in
   der Spalte also ihr Desktop-Layout und scrollt darin waagerecht (der Inhalt hat
   dafür bereits `overflow: auto`). Am echten Telefon und Tablet tritt das nicht auf.
   Sauber wäre eine Container-Query-Umstellung des Mobilblocks; das ist ein eigener
   Umbau und gehört nicht in diese Änderung. */
body.vim-active { --vim-frame-l: 0px; --vim-frame-w: 100%; --vim-frame-inset: 0px; }
body.vim-active.vim-frame {
  --vim-frame-w: 480px;
  --vim-frame-l: calc(50vw - 240px);
  --vim-frame-inset: var(--space-5, 20px);
  background: var(--gray-200, #E7EAE8);
}
body.vim-active.vim-frame #vi-mobile {
  top: var(--vim-frame-inset); bottom: var(--vim-frame-inset);
  border: 1px solid var(--gray-300, #D8DFDC);
  border-radius: var(--radius-lg, 12px);
  box-shadow: 0 18px 48px rgba(14, 32, 24, .18);
}


/* ═══════════════════════════════════════════════════════════════════════════
   DIALOGE ÜBER DER SCHALE
   ---------------------------------------------------------------------------
   Der Singleton #modal-overlay des Alt-Dialogsystems trägt z-index:100
   (style.css:1829) und lag damit UNTER der Mobil-Schale (#vi-mobile, z-index
   1000): jede zentrale Anlege-Aktion („+ Objekt", „+ Rechnung" …) öffnete sich
   unsichtbar dahinter. Genau deshalb stand in mobile.js jahrelang „Objekte
   werden am PC angelegt" — das Symptom wurde umgangen, nicht die Ursache.
   Nur bei aktiver Schale anheben, auf die Dialogebene des einheitlichen
   Systems (vi-dialog.css: --vdlg-z-dialog). Desktop bleibt unberührt.
   ═══════════════════════════════════════════════════════════════════════════ */
body.vim-active #modal-overlay,
body.vim-active .modal-overlay { z-index: var(--vdlg-z-dialog, 6000); }
/* ── Schalen-Grundgerüst ──────────────────────────────────────────────────── */
#vi-mobile {
  /* Lage aus den Rahmen-Variablen: auf Telefon und Tablet die volle Fläche, auf
     einem Desktop-Bildschirm die zentrierte Gerätespalte. EINE Positionierung. */
  position: fixed; top: 0; bottom: 0;
  left: var(--vim-frame-l, 0px); width: var(--vim-frame-w, 100%);
  z-index: 1000;
  flex-direction: column;
  background: var(--bg-primary, #FAFBFA);
  color: var(--text-primary, #141A17);
  font-family: var(--vi-font-ui, 'Inter', system-ui, sans-serif);
  font-size: var(--text-base); line-height: 1.45;
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
}
#vi-mobile *, #vi-mobile *::before, #vi-mobile *::after { box-sizing: border-box; }
#vi-mobile button { font-family: inherit; }

/* Kopfzeile */
/* Kopfzeile.
   WICHTIG: `height` + `padding-top: env(safe-area-inset-top)` vertragen sich mit
   `box-sizing: border-box` NICHT — der Inset frisst dann die Höhe auf und der
   Inhalt (Zurück · Objektauswahl · Aktualisieren) wird auf Geräten mit Notch /
   Dynamic Island abgeschnitten. Deshalb `min-height` MIT eingerechnetem Inset
   und `height: auto`: die Leiste wächst um genau den Systembereich. */
.vim-top {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 6px;
  height: auto;
  min-height: calc(54px + var(--app-safe-top));
  padding: 0 10px;
  padding-top: var(--app-safe-top);
  padding-left: max(10px, var(--app-safe-left));
  padding-right: max(10px, var(--app-safe-right));
  /* Header schlank & HELL — der Objektkontext ist das prominente Element, nicht
     der Modulname. Diese Regel ist die EINZIGE Definition der Kopffläche; die
     frühere zweite `.vim-top`-Regel weiter unten setzte `height: 54px` OHNE
     Safe-Area und hätte den Inset auf Notch-Geräten wieder aufgefressen. */
  background: var(--bg-secondary, #fff); color: var(--text-primary, #141A17);
  box-shadow: 0 1px 0 var(--vi-border, #D8DFDC);
  position: relative; z-index: 2;
}
.vim-top .vim-title {
  flex: 1 1 auto; min-width: 0;
  font-family: var(--vi-font-display, 'Inter', system-ui, sans-serif);
  font-weight: 700; font-size: var(--text-lg); letter-spacing: .2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.vim-icon-btn {
  flex: 0 0 auto;
  width: 42px; height: 42px; border: none; background: transparent;
  color: var(--color-surface); border-radius: var(--radius-lg); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: var(--text-xl); line-height: 1;
}
.vim-icon-btn:active { background: rgba(255,255,255,.16); }
.vim-icon-btn[hidden] { display: none; }
/* Links Zurück (klein), rechts Aktualisieren — beide gleich breit, damit die Objektauswahl mittig bleibt */
.vim-back { flex: 0 0 auto; width: 40px; }
.vim-back.vim-back-off { visibility: hidden; }   /* keine Historie → unsichtbar, aber Platz bleibt reserviert */
.vim-top-action { flex: 0 0 auto; width: 40px; padding: 0; }

/* Scroll-Bereich.
   Der untere Freiraum kommt aus der GEMESSENEN Höhe der Bottom-Nav (--vim-nav-h,
   gesetzt in syncShellMetrics) plus Safe-Area — kein fester Pixelwert, der bei
   größerer Schriftstufe oder anderer Gerätehöhe nicht mehr passt. */
.vim-view {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  overflow-x: hidden;
  padding: 12px 14px 22px;
  padding-left: max(14px, var(--app-safe-left));
  padding-right: max(14px, var(--app-safe-right));
}
.vim-view > *:first-child { margin-top: 0; }
/* Zusätzlicher Freiraum NUR, wenn der schwebende Knopf wirklich steht. */
body.vim-has-fab .vim-view { padding-bottom: 96px; }

/* ── BOTTOM-NAVIGATION ──────────────────────────────────────────────────────
   Fünf feste Plätze: Start · Tickets · Erfassen · Fällig · Mehr.
   • Safe-Area unten (iPhone Home-Indicator) UND seitlich (Landscape/Notch).
   • Trefferfläche ≥ 48 px, unabhängig von der ViCore-Schriftstufe: Icongröße und
     Zeilenhöhe sind in px festgelegt, das Label darf schrumpfen, nie umbrechen.
   • Die Leiste ist Teil des Flex-Layouts der Schale (kein `position:fixed`) —
     dadurch kann sie weder von Browser-Chrome noch von der PWA-Leiste überdeckt
     noch abgeschnitten werden, und `100dvh` verschiebt sie nicht.
   ────────────────────────────────────────────────────────────────────────── */
.vim-nav {
  flex: 0 0 auto;
  display: flex;
  background: var(--bg-secondary, #fff);
  border-top: 1px solid var(--vi-border, #D8DFDC);
  padding-bottom: var(--app-safe-bottom);
  padding-left: var(--app-safe-left);
  padding-right: var(--app-safe-right);
  box-shadow: 0 -2px 14px rgba(20,30,22,.07);
  position: relative; z-index: 3;
}
.vim-nav-item {
  position: relative;
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; min-height: 56px; padding: 6px 2px 5px;
  border: none; background: none; cursor: pointer; border-radius: 0;
  color: var(--text-muted, #5F6B66);
  font-size: var(--text-xxs); font-weight: 600; letter-spacing: 0; line-height: 1.15;
}
/* Label nie umbrechen/überlaufen lassen — auch bei „Erfassen" auf 320 px.
   WICHTIG: nur das LABEL kürzen. Die frühere Fassung `.vim-nav-item > span`
   traf auch den Icon-Wrapper — und dessen `overflow: hidden` schnitt das
   Ticket-Badge an der Ecke ab (8 px rechts, 5 px oben, gemessen 22.08.2026). */
.vim-nav-label { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Der Icon-Wrapper ist der Bezugsrahmen des Badges — er darf NIE beschneiden. */
.vim-nav-ic {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  overflow: visible;
}
/* Badge mit Anzahl OFFENER Tickets — sitzt rechts oben am Icon */
/* Rechts am Icon verankert, damit ein breiteres Badge („12", „99+") nach LINKS
   wächst und auch auf 320 px innerhalb seiner Zeile bleibt — bei fester
   linker Kante lief es sonst in den Nachbarplatz. */
.vim-nav-badge {
  position: absolute; top: -5px; right: -10px; left: auto;
  min-width: 18px; height: 18px; padding: 0 5px;
  display: flex; align-items: center; justify-content: center;
  background: var(--color-danger); color: var(--color-surface);
  font-size: var(--text-xxs); font-weight: 800; line-height: 1;
  border-radius: var(--radius-md); border: 2px solid var(--bg-secondary, #fff);
  box-shadow: 0 1px 3px rgba(0,0,0,.25);
}
.vim-nav-badge[hidden] { display: none; }
.vim-nav-item svg { width: 23px; height: 23px; stroke-width: 1.7; }
.vim-nav-item.active { color: var(--vi-green, #147352); }
.vim-nav-item.active svg { stroke-width: 2.2; }
/* Aktiver Zustand zusätzlich als Fläche — Farbe allein ist auf hellen Displays
   im Sonnenlicht zu schwach und für Farbfehlsichtige nicht eindeutig. */
.vim-nav-item.active::before {
  content: ''; position: absolute; top: 0; left: 12%; right: 12%; height: 3px;
  border-radius: 0 0 3px 3px; background: var(--vi-green, #147352);
}
.vim-nav-item:active { background: var(--bg-tertiary, #EFF2F1); }

/* Zentraler Knopf „Erfassen": hervorgehoben, aber gleicher Platz in der Leiste —
   professionell in der ViCore-CI, keine schwebende Consumer-App-Kugel. */
.vim-nav-capture { color: var(--vi-green-deep, #0F5C42); font-weight: 750; }
.vim-nav-capture-ic {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 30px; border-radius: var(--radius-lg);
  background: var(--vi-green, #147352); color: var(--color-surface);
}
.vim-nav-capture-ic svg { width: 20px; height: 20px; stroke-width: 2.6; }
.vim-nav-capture:active .vim-nav-capture-ic { background: var(--vi-green-deep, #0F5C42); }
.vim-nav-capture::before { content: none; }

/* ── SCHWEBENDE ELEMENTE: EIN Offset für alle ───────────────────────────────
   Alles, was frei über der Oberfläche schwebt, muss oberhalb der Bottom-Navigation
   UND oberhalb der Gestenleiste liegen. Maßgeblich ist `--vim-nav-h` — die in
   syncShellMetrics() GEMESSENE Höhe der Leiste, die ihren Safe-Area-Anteil bereits
   enthält. Deshalb hier NICHT zusätzlich `--app-safe-bottom` addieren; das wäre
   der doppelte Abstand, den Anforderung §6/§14 ausdrücklich ausschließt.
   Wer künftig ein schwebendes Bedienelement ergänzt, nimmt diese Regel — keine
   eigene Sonderpositionierung. */
body.vim-active .toast,
body.vim-active #toast-root { bottom: calc(var(--vim-nav-h, 60px) + 14px); }
/* Uploadstatus (VIPhoto, public/vi-photo.css) gehört auf dieselbe Höhe wie der
   Toast — er lag bisher ÜBER der Bottom-Nav und verdeckte sie während des
   gesamten Uploads (gemeldet 11.09.2026). Die Regel steht hier und nicht in
   vi-photo.css, weil die Schale ihre Maße kennt und die Komponente nicht. */
body.vim-active .vip-up { bottom: calc(var(--vim-nav-h, 60px) + 14px + var(--app-safe-bottom, 0px)); }

/* Schnellbutton der übrigen Bereiche (Objekte, Abnahmen …) */
.vim-fab {
  position: absolute; right: 16px;
  bottom: calc(var(--vim-nav-h, 60px) + 14px);
  z-index: 5;
  display: inline-flex; align-items: center; gap: 8px;
  height: 52px; padding: 0 20px 0 18px;
  border: none; border-radius: var(--radius-pill); cursor: pointer;
  background: var(--vi-green, #147352); color: var(--color-surface);
  font-size: var(--text-base); font-weight: 700;
  box-shadow: 0 8px 22px rgba(14,32,24,.32);
}
.vim-fab:active { background: var(--vi-green-deep, #0F5C42); transform: translateY(1px); }
.vim-fab svg { width: 20px; height: 20px; stroke-width: 2.4; }
.vim-fab[hidden] { display: none; }
.vim-ha-create {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: min(100%, 320px); min-height: 48px; margin: 16px auto 0;
}
.vim-ha-create svg { width: 19px; height: 19px; }

/* ── Bausteine ────────────────────────────────────────────────────────────── */
.vim-sec {
  display: flex; align-items: center; justify-content: space-between;
  margin: 18px 2px 8px;
}
.vim-sec:first-child { margin-top: 4px; }
/* Satzschreibung, nicht gesperrte Versalien: Abschnittsüberschriften einer
   Arbeitsfläche dürfen nicht lauter sein als die Daten, die sie beschriften
   (Produktdesignsystem — Versalien nur in Navigations-Abschnittsüberschriften). */
.vim-sec h2 {
  margin: 0; font-family: var(--vi-font-display, system-ui, sans-serif);
  font-size: var(--text-sm); font-weight: 700; letter-spacing: .1px;
  color: var(--text-secondary, #3A4441);
}
/* Tippziel: 24 px waren zu klein fuer den Daumen (UX-Phase 8 §18) — der Link
   behaelt sein Aussehen, bekommt aber die Mindesthoehe eines Bedienelements. */
.vim-sec .vim-sec-link { font-size: var(--text-sm); font-weight: 600; color: var(--vi-green, #147352); background: none; border: none; cursor: pointer;
  min-height: 40px; display: inline-flex; align-items: center; padding: 4px 6px; }

/* Sekundärer Link-Knopf innerhalb eines Formulars (z. B. „Zählerwechsel melden") —
   unauffällig, kein Button-Rahmen, führt in einen NEUEN Sheet statt das Formular zu ersetzen. */
.vim-link-btn, button.vim-sec-link {
  font-size: var(--text-sm); font-weight: 650; color: var(--vi-green, #147352);
  background: none; border: none; cursor: pointer; padding: 6px 2px;
}

/* Abschnittsüberschrift INNERHALB eines Formulars/Sheets (z. B. „Ausbau"/„Einbau"
   im Zählerwechsel-Formular) — gleiche Typografie wie .vim-sec h2, ohne dessen Flex-Kopfzeile. */
.vim-h3 {
  font-family: var(--vi-font-display, system-ui, sans-serif);
  font-size: var(--text-sm); font-weight: 700; letter-spacing: .1px;
  color: var(--text-secondary, #3A4441);
}

.vim-card {
  background: var(--bg-secondary, #fff);
  border: 1px solid var(--vi-border, #D8DFDC);
  border-radius: var(--vi-r-lg, 14px);
  box-shadow: var(--shadow-sm, 0 1px 3px rgba(40,30,20,.06));
  padding: 14px;
}
.vim-card + .vim-card { margin-top: 10px; }

/* Tappbare Listenzeile */
.vim-row {
  display: flex; align-items: center; gap: 12px;
  width: 100%; text-align: left;
  background: var(--bg-secondary, #fff);
  border: 1px solid var(--vi-border, #D8DFDC);
  border-radius: var(--vi-r-lg, 14px);
  padding: 13px 14px; margin-bottom: 9px;
  cursor: pointer; min-height: 60px;
  box-shadow: var(--shadow-sm, 0 1px 3px rgba(40,30,20,.05));
  -webkit-tap-highlight-color: transparent;
}
.vim-row:active { background: var(--bg-tertiary, #EFF2F1); }
.vim-row-main { flex: 1 1 auto; min-width: 0; }
.vim-row-title {
  font-weight: 650; font-size: var(--text-base); color: var(--text-primary, #141A17);
  display: flex; align-items: center; gap: 7px;
  /* SICHERUNG (11.09.2026): Die Ellipse hängt an `.vim-rt-text` — gibt ein Aufrufer
     den Titel NACKT hinein, wird daraus ein anonymes Flex-Element ohne Schrumpf- und
     Umbruchmöglichkeit (`.vim-row` ist ein <button> und erbt `white-space: nowrap`).
     Gemessen am Wartungsdetail: 508 px Inhalt in 305 px Platz, der Arbeitsbereich
     scrollte waagerecht. `overflow: hidden` hält den Überlauf IN der Karte; die
     saubere Lösung bleibt der Textträger (Wächter: mobile_vokabular_ui §U). */
  min-width: 0; overflow: hidden;
}
.vim-row-title .vim-rt-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vim-row-sub {
  margin-top: 3px; font-size: var(--text-xs); color: var(--text-secondary, #3A4441);
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.vim-row-sub .vim-dot { width: 3px; height: 3px; border-radius: 50%; background: var(--text-muted, #aaa); flex: 0 0 auto; }
.vim-row-chevron { flex: 0 0 auto; color: var(--text-muted, #b3ada0); font-size: var(--text-xl); line-height: 1; }
.vim-row-num { font-family: var(--vi-font-mono, monospace); font-size: var(--text-xxs); color: var(--text-muted, #5F6B66); }

/* Wartungs-/Prüfungs-Karte (Mobile): fachlich verdichtet, kompakt, max. 2 Zeilen Titel.
   Titel = Bauteil/Anlage – Prüf-/Wartungsart · Chips · Objekt · klein „Leistungsbereich · Firma" · Fälligkeit. */
.vim-row-maint { align-items: flex-start; }
/* Titel max. 2 Zeilen: geerbtes `white-space: nowrap` des Buttons explizit aufheben (sonst kein Umbruch). */
.vim-row.vim-row-maint .vim-mt-title {
  font-weight: 650; font-size: var(--text-md); line-height: 1.28; color: var(--text-primary, #141A17);
  white-space: normal; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
  max-height: 2.56em;                          /* harte Obergrenze = 2 Zeilen (Fallback, falls Clamp inaktiv) */
}
.vim-mt-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.vim-mt-chips:empty { display: none; }
.vim-mt-obj {
  margin-top: 6px; font-size: var(--text-xs); color: var(--text-secondary, #3A4441);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;          /* langer Standort sauber gekürzt, keine Überbreite */
}
.vim-mt-meta {
  margin-top: 2px; font-size: var(--text-xxs); color: var(--text-muted, #5F6B66);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;          /* lange Firma sauber kürzen */
}
.vim-mt-due { margin-top: 5px; font-size: var(--text-xs); font-weight: 600; color: var(--text-secondary, #3A4441); }
/* Bezeichnungschip — NUR noch für reine Etiketten (Rolle, Bezugsart, Auftragsart).
   Jeder ZUSTAND und jeder HANDLUNGSBEDARF kommt seit der UX-Phase 8 aus der
   Bausteinschicht (`.vic-st` / `.vic-at`), damit dasselbe Wort auf beiden
   Plattformen dieselbe Farbe trägt. Die früheren Zustandsvarianten
   (`-due/-over/-done/-open/-wait/-neutral/-nodoc/-defect/-dot`) hatten damit
   keinen Erzeuger mehr und sind entfallen. */
.vim-pill {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px; border-radius: var(--radius-pill);
  background: var(--bg-tertiary, #EFF2F1); color: var(--text-secondary, #3A4441);
  font-size: var(--text-xxs); font-weight: 700; line-height: 1.5;
  white-space: nowrap;
}

/* Prioritäts-Punkt */
.vim-prio { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; display: inline-block; }

/* Medium-Badge (Energie) */
.vim-medium { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: var(--radius-sm); font-size: var(--text-xxs); font-weight: 700; background: var(--bg-tertiary, #EFF2F1); color: var(--text-secondary, #3A4441); }
.vim-medium-inline { flex: 0 0 auto; }

/* Zählerkarte (Mobile): Titel oben, danach PROMINENT die aktive Zähler-Nr., darunter MaLo · letzter Stand.
   Der Nutzer erkennt den konkreten Zähler ohne die Karte zu öffnen. */
.vim-meter { align-items: flex-start; }
.vim-meter .vim-row-title { white-space: normal; overflow-wrap: anywhere; }
.vim-meter .vim-row-title .vim-rt-text { white-space: normal; }
.vim-znr {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 8px;
  margin-top: 7px; padding: 6px 10px; border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--vi-green, #147352) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--vi-green, #147352) 22%, transparent);
}
.vim-znr-l { font-size: var(--text-xxs); font-weight: 700; letter-spacing: .01em; color: var(--text-muted, #5F6B66); }
.vim-znr-v { font-family: var(--vi-font-mono, monospace); font-size: var(--text-base); font-weight: 800; color: var(--vi-green-dark, #0d5a2e); overflow-wrap: anywhere; }
.vim-znr-none { font-family: inherit; font-size: var(--text-sm); font-weight: 700; color: var(--vi-warning-strong, #9a6a12); }
.vim-znr-chg { margin-left: auto; font-size: var(--text-xxs); font-weight: 700; color: var(--text-secondary, #3A4441); white-space: nowrap; }
.vim-meter-meta { margin-top: 6px; overflow-wrap: anywhere; }
.vim-meter-ctx { margin-top: 3px; font-size: var(--text-xxs); color: var(--text-muted, #5F6B66); overflow-wrap: anywhere; }

/* ── STARTSCHIRM (22.08.2026) ───────────────────────────────────────────────
   Die frühere Startseite bestand aus einem Full-Width-Knopf „Ticket melden",
   vier Zählzeilen (meist mit „0") und einer zusätzlichen Erfolgskarte — viel
   Fläche, wenig Arbeitsnutzen. Ersetzt durch: kompaktes Aktionsraster →
   „Jetzt wichtig" (nur echte Auffälligkeiten) → „Als Nächstes" (Arbeitsliste).
   Die Klassen .vim-stats, .vim-stat, .vim-cta und .vim-hw sind ersatzlos entfallen.
   ────────────────────────────────────────────────────────────────────────── */

/* B · Schnellaktionen: 2×2-Raster, kompakt — keine Karten, keine Schatten */
.vim-qa { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 2px 0 4px; }
.vim-qa-b {
  display: flex; align-items: center; gap: 9px;
  min-height: 52px; padding: 0 12px; cursor: pointer; text-align: left;
  background: var(--bg-secondary, #fff); border: 1px solid var(--vi-border, #D8DFDC);
  border-radius: var(--vi-r-md, 12px); color: var(--text-primary, #141A17);
  font-size: var(--text-md); font-weight: 650;
}
.vim-qa-b svg { width: 20px; height: 20px; flex: 0 0 auto; stroke-width: 1.8; color: var(--vi-green, #147352); }
.vim-qa-b span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vim-qa-b:active { background: var(--vi-green-soft, #EDF7F2); border-color: var(--vi-green, #147352); }

/* C · „Jetzt wichtig" — nur echte Auffälligkeiten, sonst EINE ruhige Zeile */
.vim-nowlist { display: flex; flex-direction: column; gap: 6px; }
.vim-now {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  min-height: 48px; padding: 0 12px; cursor: pointer;
  border: 1px solid var(--vi-border, #D8DFDC); border-left-width: 3px;
  border-radius: var(--vi-r-md, 12px); background: var(--bg-secondary, #fff);
  font-size: var(--text-md); font-weight: 650; color: var(--text-primary, #141A17);
}
.vim-now svg { width: 18px; height: 18px; flex: 0 0 auto; }
.vim-now span { flex: 1 1 auto; min-width: 0; }
.vim-now.is-urgent { border-left-color: var(--color-danger); }
.vim-now.is-urgent svg { color: var(--color-danger); }
.vim-now.is-today  { border-left-color: var(--color-warning-ink); }
.vim-now.is-today svg { color: var(--color-warning-ink); }
.vim-now:active { background: var(--bg-tertiary, #EFF2F1); }
/* Ruhezustand: eine Zeile, keine Erfolgskarte */
.vim-calm {
  display: flex; align-items: center; gap: 9px;
  padding: 11px 12px; border-radius: var(--vi-r-md, 12px);
  background: var(--vi-green-soft, #EDF7F2); color: var(--vi-success, #2E7D43);
  font-size: var(--text-md); font-weight: 600;
}
.vim-calm svg { width: 18px; height: 18px; flex: 0 0 auto; }
.vim-calm-quiet { background: var(--bg-tertiary, #EFF2F1); color: var(--text-secondary, #3A4441); font-weight: 500; }

/* E · Zuletzt verwendete Objektbereiche (vorhandener Verlauf, kein neues Tracking) */
.vim-recent { display: flex; flex-wrap: wrap; gap: 7px; }
.vim-recent-b {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 40px; padding: 0 12px; cursor: pointer;
  border: 1px solid var(--vi-border, #D8DFDC); border-radius: var(--radius-pill);
  background: var(--bg-secondary, #fff); color: var(--text-secondary, #3A4441);
  font-size: var(--text-sm); font-weight: 600; max-width: 100%;
}
.vim-recent-b svg { width: 15px; height: 15px; flex: 0 0 auto; }
.vim-recent-b span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vim-recent-b:active { background: var(--bg-tertiary, #EFF2F1); }

/* ── ARBEITSLISTE „FÄLLIG" ──────────────────────────────────────────────────
   Zwei Filterebenen (Typ · Zeitraum), darunter Zeilen in fester Rangfolge:
   Typ → Tätigkeit → Ort → Frist → Zusatz. Eine Zeile = eine Fläche mit
   Trennrahmen, KEINE Karte in der Karte, keine Alarmoptik am Normaltermin.
   ────────────────────────────────────────────────────────────────────────── */
/* Ebene 1 (Typ) steht optisch über Ebene 2 (Zeitraum): gleiche Bauform, aber
   ruhiger Grund und etwas mehr Luft darunter — man sieht die Staffelung, ohne
   dass zwei gleich laute Leisten übereinander stehen. */
.vim-seg-typ { margin-bottom: 8px; background: transparent; padding: 0; gap: 6px; }
.vim-seg-typ button {
  min-height: 38px; border: 1px solid var(--vi-border, #D8DFDC); border-radius: var(--radius-pill);
  background: var(--bg-secondary, #fff); font-size: var(--text-sm); padding: 0 13px;
}
.vim-seg-typ button.active {
  background: var(--vi-green-soft, #EDF7F2); border-color: var(--vi-green, #147352);
  color: var(--vi-green-deep, #0F5C42); box-shadow: none;
}
.vim-flist { margin-top: 10px; }

/* Gruppenüberschrift unter „Alle" — ordnet, ohne einen zweiten Rahmen zu bauen */
.vim-fq-group {
  display: flex; align-items: center; gap: 8px;
  margin: 14px 2px 7px; font-size: var(--text-xs); font-weight: 750; letter-spacing: .3px;
  text-transform: uppercase; color: var(--text-muted, #5F6B66);
}
.vim-fq-group:first-child { margin-top: 2px; }
.vim-fq-group b {
  font-weight: 750; font-size: var(--text-xxs); padding: 1px 7px; border-radius: var(--radius-pill);
  background: var(--bg-tertiary, #EFF2F1); color: var(--text-secondary, #3A4441);
}
.vim-fq-group::after { content: ''; flex: 1 1 auto; height: 1px; background: var(--vi-border, #D8DFDC); }

/* Hinweiszeile: Überfälliges, das der gewählte Zeitraum nicht zeigt */
.vim-fq-alert {
  display: flex; align-items: center; gap: 9px; width: 100%; cursor: pointer; text-align: left;
  min-height: 44px; padding: 9px 12px; margin-bottom: 10px;
  border: 1px solid #E7C3BD; border-radius: var(--vi-r-md, 12px);
  background: #FCF2F0; color: #8A2A1D; font-size: var(--text-sm); font-weight: 650;
}
.vim-fq-alert svg { width: 18px; height: 18px; flex: 0 0 auto; stroke-width: 1.8; }
.vim-fq-alert span { min-width: 0; }
.vim-fq-alert-go { margin-left: auto; white-space: nowrap; font-weight: 700; }

/* Eintrag */
.vim-fq {
  display: grid; grid-template-columns: 1fr auto; align-items: end; gap: 10px;
  width: 100%; text-align: left; cursor: pointer;
  padding: 11px 12px; margin-bottom: 7px;
  background: var(--bg-secondary, #fff); border: 1px solid var(--vi-border, #D8DFDC);
  border-left-width: 3px; border-left-color: var(--vi-border, #D8DFDC);
  border-radius: var(--vi-r-md, 12px);
}
.vim-fq:active { background: var(--bg-tertiary, #EFF2F1); }
/* Nur echte Überfälligkeit bekommt die rote Kante; ein Posten im Toleranzfenster
   ist terminlich vorbei, aber fachlich noch nicht überfällig → ruhige Kante. */
.vim-fq.is-overdue { border-left-color: var(--color-danger); }
.vim-fq.is-past    { border-left-color: #C99A2E; }
.vim-fq-main { min-width: 0; display: flex; flex-direction: column; gap: 3px; }

/* 1 · Typ — Icon + Wort, klein und farbcodiert */
.vim-fq-type {
  display: inline-flex; align-items: center; gap: 5px; align-self: flex-start;
  font-size: var(--text-xxs); font-weight: 750; letter-spacing: .2px;
  padding: 2px 8px 2px 6px; border-radius: var(--radius-pill);
  background: var(--bg-tertiary, #EFF2F1); color: var(--text-secondary, #3A4441);
}
.vim-fq-type svg { width: 13px; height: 13px; flex: 0 0 auto; stroke-width: 2; }
.vim-fq-type i { font-style: normal; }
/* Nummer und Statuswort in derselben Kachel wie die Art (Anf. 2): die Zeile muss
   den Auftrag identifizieren, nicht nur seine Gattung nennen. Beides tritt
   optisch hinter Art und Titel zurueck — es ordnet ein, es schreit nicht. */
.vim-fq-type u { text-decoration: none; font-variant-numeric: tabular-nums; opacity: .85; }
.vim-fq-type u::before { content: "·"; margin: 0 4px; opacity: .55; }
.vim-fq-type em { font-style: normal; opacity: .85; }
.vim-fq-type em::before { content: "·"; margin: 0 4px; opacity: .55; }
.vim-fq-type-auftrag  { background: #EAF2FA; color: #1F5C93; }
.vim-fq-type-wartung  { background: #F1ECF7; color: #5C4A86; }
.vim-fq-type-pruefung { background: var(--green-50); color: #1F6B48; }
.vim-fq-type-aufgabe  { background: #F3EDD3; color: #6E5E1A; }
.vim-fq-type-wv       { background: #F4F1EC; color: #6B5A44; }
.vim-fq-type-ablesung { background: #E9F3F5; color: #1F6473; }

/* 2 · Tätigkeit  3 · Ort  4 · Frist  5 · Zusatz — absteigendes Gewicht */
/* `white-space: nowrap` erbte die Zeile von der Schale — Titel und Objektetikett
   wurden dadurch hart abgeschnitten statt umzubrechen: „Campus Graphisches Viertel ·
   Zähler 2005…". Gerade das Objektetikett muss vollständig lesbar sein, es ist auf
   beiden Plattformen dasselbe Wort (UX-Phase 8 §14). Also: umbrechen, nicht kürzen. */
.vim-fq-title { font-size: var(--text-md); font-weight: 650; line-height: 1.3; color: var(--text-primary, #141A17); overflow-wrap: anywhere; white-space: normal; }
.vim-fq-obj { font-size: var(--text-xs); line-height: 1.35; color: var(--text-secondary, #3A4441); overflow-wrap: anywhere; white-space: normal; }
.vim-fq-due { font-size: var(--text-xs); font-weight: 600; color: var(--text-muted, #5F6B66); overflow-wrap: anywhere; white-space: normal; }
.vim-fq-due.is-over  { color: var(--color-danger-ink); font-weight: 750; }
.vim-fq-due.is-today { color: var(--color-warning-ink); font-weight: 750; }
.vim-fq-extra { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; margin-top: 1px; }
.vim-fq-flag { font-size: var(--text-xxs); font-weight: 650; padding: 1px 6px; border-radius: var(--radius-sm); background: var(--color-warning-soft); color: var(--color-warning-ink); }
.vim-fq-meta { font-size: var(--text-xxs); color: var(--text-muted, #5F6B66); }
.vim-fq-go {
  flex: 0 0 auto; white-space: nowrap; padding-bottom: 1px;
  font-size: var(--text-xs); font-weight: 700; color: var(--vi-green, #147352);
}
/* Sehr schmale Geräte (≈320 px): die Aktion rutscht unter den Inhalt, statt den
   Titel auf zwei Zeichen zu quetschen. Die Seite scrollt nie waagerecht. */
@media (max-width: 359px) {
  .vim-fq { grid-template-columns: 1fr; }
  .vim-fq-go { justify-self: end; }
}
/* Energie-Arbeitskontext (Mandant → Objekt → Verbrauchsstelle → Zähler) */
.vim-enctx {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 8px 10px; margin-bottom: 10px;
  border-radius: var(--vi-r-md, 12px); background: var(--bg-tertiary, #EFF2F1);
  font-size: var(--text-xs); color: var(--text-secondary, #3A4441);
}
/* „Auswahl“ beschriftet die Zeile als Verfeinerung INNERHALB des Objektkontexts —
   sie ist kein zweiter Objektfilter (Feedback #3 §1.2). */
.vim-enctx-lbl { flex: 0 0 auto; font-size: var(--text-xxs); font-weight: 700; letter-spacing: .3px; color: var(--text-muted, #5F6B66); }
.vim-enctx-path { flex: 1 1 auto; min-width: 0; font-weight: 650; color: var(--text-primary, #141A17); overflow-wrap: anywhere; }
.vim-enctx-path i { font-style: normal; color: var(--text-muted, #5F6B66); padding: 0 3px; }
.vim-enctx-btn {
  flex: 0 0 auto; min-height: 32px; padding: 0 10px; cursor: pointer;
  border: 1px solid var(--vi-border, #D8DFDC); border-radius: var(--radius-pill);
  background: var(--bg-secondary, #fff); color: var(--vi-green, #147352);
  font-size: var(--text-xs); font-weight: 700;
}

/* Schnellerfassung („+ Erfassen") — Liste im angedockten Bottom Sheet */
.vim-caplist { display: flex; flex-direction: column; }
.vim-cap {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  min-height: 60px; padding: 10px 4px; cursor: pointer;
  border: none; background: none; border-bottom: 1px solid var(--vi-border, #EFEBE2);
  border-radius: 0; justify-content: flex-start;
}
.vim-cap:last-child { border-bottom: none; }
.vim-cap:active { background: var(--bg-tertiary, #EFF2F1); }
.vim-cap[disabled] { opacity: .55; cursor: default; }
.vim-cap-ic {
  flex: 0 0 auto; width: 40px; height: 40px; border-radius: var(--radius-lg);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--vi-green-soft, #EDF7F2); color: var(--vi-green, #147352);
}
.vim-cap-ic svg { width: 20px; height: 20px; stroke-width: 1.8; }
.vim-cap-txt { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.vim-cap-l { font-size: var(--text-base); font-weight: 650; color: var(--text-primary, #141A17); }
.vim-cap-h { font-size: var(--text-xs); color: var(--text-muted, #5F6B66); }
.vim-cap-now { flex: 0 0 auto; font-size: var(--text-xxs); font-weight: 700; color: var(--vi-green, #147352); }
.vim-cap-ctx {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  min-height: 44px; margin-bottom: 6px; padding: 0 10px; cursor: pointer;
  border: 1px solid var(--vi-border, #D8DFDC); border-radius: var(--vi-r-md, 12px);
  background: var(--bg-tertiary, #EFF2F1); justify-content: flex-start;
}
.vim-cap-ctx svg { width: 17px; height: 17px; flex: 0 0 auto; color: var(--text-secondary, #3A4441); }
/* Das Erfassen-Sheet verdeckt die Kopfzeile — hier steht der Objektbezug allein.
   Deshalb der VOLLE Pfad (Objekt › Etage › Raum) und Platz für zwei Zeilen. */
.vim-cap-ctx-txt {
  flex: 1 1 auto; min-width: 0; font-size: var(--text-md); font-weight: 650; line-height: 1.28;
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow-wrap: anywhere;
}
.vim-cap-ctx-act { flex: 0 0 auto; font-size: var(--text-xs); font-weight: 700; color: var(--vi-green, #147352); }

/* ── Buttons ──────────────────────────────────────────────────────────────── */
.vim-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 48px; padding: 0 18px; border-radius: var(--vi-r-md, 10px);
  font-size: var(--text-base); font-weight: 650; cursor: pointer; border: 1px solid transparent;
  width: 100%;
}
.vim-btn-primary { background: var(--vi-green, #147352); color: var(--color-surface); }
.vim-btn-primary:active { background: var(--vi-green-deep, #0F5C42); }
.vim-btn-secondary { background: var(--bg-secondary, #fff); color: var(--text-primary, #141A17); border-color: var(--border-default, #D8DFDC); }
.vim-btn-secondary:active { background: var(--bg-tertiary, #EFF2F1); }
.vim-btn-ghost { background: transparent; color: var(--vi-green, #147352); }
.vim-btn-danger { background: var(--vi-error, #C0392C); color: var(--color-surface); }
.vim-btn[disabled] { opacity: .55; pointer-events: none; }
.vim-btn-row { display: flex; gap: 10px; }
.vim-btn-row .vim-btn { width: auto; flex: 1 1 0; }
/* Aktion am Fuß eines Akkordeon-Abschnitts (z. B. „Neue E-Mail" in der Kommunikation) */
.vim-acc-action { margin-top: 10px; }

/* ── Formulare ────────────────────────────────────────────────────────────── */
.vim-field { margin-bottom: 15px; }
.vim-label { display: block; font-size: var(--text-xs); font-weight: 700; color: var(--text-secondary, #3A4441); margin-bottom: 6px; }
.vim-label .vim-req { color: var(--vi-error, #C0392C); }
.vim-input, .vim-textarea, .vim-select {
  width: 100%; min-height: 50px; padding: 12px 14px;
  border: 1px solid var(--border-default, #D8DFDC); border-radius: var(--vi-r-md, 10px);
  background: var(--bg-secondary, #fff); color: var(--text-primary, #141A17);
  font-size: var(--text-base); /* ≥16px → kein iOS-Auto-Zoom */ font-family: inherit;
  appearance: none; -webkit-appearance: none;
}
.vim-input:focus, .vim-textarea:focus, .vim-select:focus {
  outline: none; border-color: var(--vi-green, #147352);
  box-shadow: 0 0 0 3px var(--vi-green-soft, #EDF7F2);
}
.vim-textarea { min-height: 96px; resize: vertical; line-height: 1.5; }
.vim-select { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%235C574E' stroke-width='2.4'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 14px center; padding-right: 38px; }
.vim-hint { font-size: var(--text-xs); color: var(--text-muted, #5F6B66); margin-top: 5px; }

/* Read-only Angaben in mobilen Masken — EINE Optik:
   „Gemeldet durch" (automatisch ermittelt) und die Fakten „Turnus" / „Nächste
   Fälligkeit" im Erfassen-Sheet (AP 1.3: der Techniker sieht vor dem Speichern,
   wann es wieder dran ist — dieselbe Angabe wie am Desktop). */
.vim-reporter, .vim-fact { display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 10px 14px;
  border: 1px dashed var(--vi-border, #DAD6CC); border-radius: var(--vi-r-md, 10px);
  background: var(--bg-tertiary, #F4F2EE); color: var(--text-secondary, #3A4441); font-weight: 650; font-size: var(--text-md); }
.vim-reporter-tag { margin-left: auto; font-size: var(--text-xxs); font-weight: 700; letter-spacing: .01em;
  color: var(--text-muted, #5F6B66); background: var(--color-surface); border: 1px solid var(--vi-border, #E3E0D8); border-radius: var(--radius-pill); padding: 2px 8px; }

/* Segmented control (z. B. Offen/Alle/Erledigt) */
.vim-seg { display: flex; gap: 0; background: var(--bg-tertiary, #EFF2F1); border-radius: var(--vi-r-md, 10px); padding: 3px; }
/* Vier Filter auf 320–360 px: die Leiste darf in sich schieben statt umzubrechen
   oder Beschriftungen abzuschneiden. Die SEITE scrollt dabei nie waagerecht. */
.vim-seg-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.vim-seg-scroll::-webkit-scrollbar { display: none; }
.vim-seg-scroll button { flex: 0 0 auto; white-space: nowrap; }
.vim-seg button {
  flex: 1 1 0; min-height: 40px; border: none; background: transparent; cursor: pointer;
  font-size: var(--text-sm); font-weight: 650; color: var(--text-secondary, #3A4441); border-radius: var(--radius-md); white-space: nowrap; padding: 0 6px;
}
.vim-seg button.active { background: var(--bg-secondary, #fff); color: var(--vi-green, #147352); box-shadow: var(--shadow-sm, 0 1px 3px rgba(40,30,20,.1)); }

/* Zählerstände · Medien-Kachelraster (Objekt → Medium → Zähler, Stufe 2): bricht
   in mehrere Zeilen um, NIE waagerechtes Scrollen. „Alle" ist die erste Kachel. */
.vim-med-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 10px; margin: 4px 0 6px; }
.vim-med-tile {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  min-height: 88px; padding: 12px 8px; cursor: pointer; text-align: center;
  background: var(--bg-secondary, #fff); border: 1px solid var(--vi-border, #D8DFDC);
  border-radius: var(--vi-r-lg, 14px); color: var(--text-primary, #141A17);
}
.vim-med-tile-ic { font-size: 24px; line-height: 1; }
.vim-med-tile-label { font-size: var(--text-sm); font-weight: 700; }
.vim-med-tile-count { font-size: var(--text-xs); font-weight: 600; color: var(--text-secondary, #3A4441); }
.vim-med-tile:active { background: var(--vi-green-soft, #EDF7F2); border-color: var(--vi-green, #147352); }

/* Gruppenüberschrift der „Alle"-Ansicht (nach Medium gegliedert). */
.vim-group-head {
  margin: 14px 2px 6px; font-size: var(--text-xs); font-weight: 700; text-transform: none;
  color: var(--text-secondary, #3A4441);
}
.vim-group-head:first-child { margin-top: 4px; }

/* ── Vorgänge-Filterleiste (kompakt/ausklappbar): Suche · Segment · „Filter"-Panel ──
   (Objektfilter = globaler Kontext in der Kopfzeile, KEIN zweiter Filter hier.) */
/* „Filter"-Umschalter + Panel */
.vim-cf-toggle {
  display: flex; align-items: center; gap: 8px; width: 100%; min-height: 42px; padding: 8px 13px; margin-top: 10px;
  border: 1px solid var(--border-default, #D8DFDC); border-radius: var(--vi-r-md, 10px);
  background: var(--bg-secondary, #fff); cursor: pointer; font-size: var(--text-md); font-weight: 650; color: var(--text-secondary, #3A4441);
}
.vim-cf-toggle.open { border-color: var(--vi-green, #147352); color: var(--vi-green, #147352); }
.vim-cf-badge { min-width: 20px; height: 20px; padding: 0 6px; display: inline-flex; align-items: center; justify-content: center; background: var(--vi-green, #147352); color: var(--color-surface); font-size: var(--text-xxs); font-weight: 800; border-radius: var(--radius-lg); }
.vim-cf-caret { margin-left: auto; transition: transform .18s ease; color: var(--text-muted, #5F6B66); }
.vim-cf-toggle.open .vim-cf-caret { transform: rotate(180deg); }
.vim-cf-panel { display: none; margin-top: 8px; padding: 12px 13px; border: 1px solid var(--vi-border, #D8DFDC); border-radius: var(--vi-r-lg, 14px); background: var(--bg-secondary, #fff); }
.vim-cf-panel.open { display: block; }
.vim-cf-switch { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: var(--text-md); font-weight: 600; color: var(--text-primary, #141A17); padding: 6px 0 12px; }
.vim-cf-switch input { width: 20px; height: 20px; flex: 0 0 auto; accent-color: var(--vi-green, #147352); }
.vim-cf-field { margin-bottom: 12px; }
.vim-cf-field:last-of-type { margin-bottom: 6px; }
.vim-cf-reset { width: 100%; min-height: 40px; margin-top: 4px; border: 1px solid var(--border-default, #D8DFDC); border-radius: var(--vi-r-md, 10px); background: var(--bg-tertiary, #EFF2F1); color: var(--text-secondary, #3A4441); font-size: var(--text-sm); font-weight: 650; cursor: pointer; }

/* „Pille zum Wählen" (Ergebnis-Auswahl Wartung) */
.vim-choice { display: flex; flex-direction: column; gap: 8px; }
.vim-choice button {
  display: flex; align-items: center; gap: 12px; width: 100%; min-height: 52px; padding: 10px 14px;
  border: 1.5px solid var(--border-default, #D8DFDC); border-radius: var(--vi-r-md, 10px);
  background: var(--bg-secondary, #fff); color: var(--text-primary, #141A17); cursor: pointer;
  font-size: var(--text-base); font-weight: 600; text-align: left;
  /* AUSDRÜCKLICH LINKSBÜNDIG (07.09.2026). `button, .btn` in design-system.css setzt
     `justify-content: center` und `white-space: nowrap`; diese Regel deklarierte beides
     nicht und erbte deshalb die Zentrierung — Icon und Beschriftung standen als Block
     in der Mitte, bei jeder Zeile an einer anderen Stelle. Wer `display:flex` an einem
     <button> setzt, muss die Ausrichtung mitsetzen. */
  justify-content: flex-start; white-space: normal;
}
/* Icon-Spalte: feste Breite, damit ALLE Beschriftungen an derselben Kante beginnen. */
.vim-choice button .vim-choice-ic {
  width: 22px; height: 22px; flex: 0 0 22px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-muted, #5F6B66);
}
.vim-choice button .vim-choice-ic svg { width: 22px; height: 22px; display: block; }
.vim-choice button .vim-choice-t { flex: 1 1 auto; min-width: 0; }
/* Die FARBE kommt aus der Bedeutung der Zeile, nicht aus dem Zeichen — und sie steht
   dauerhaft am Icon, nicht erst in der Auswahl. */
.vim-choice button.defect .vim-choice-ic { color: var(--vi-warning, #C8880F); }
.vim-choice button.fail .vim-choice-ic { color: var(--vi-error, #C0392C); }
.vim-choice button.sel { border-color: var(--vi-green, #147352); background: var(--vi-green-soft, #EDF7F2); }
.vim-choice button.sel .vim-choice-ic { color: var(--vi-green, #147352); }
.vim-choice button.sel.defect { border-color: var(--vi-warning, #C8880F); background: var(--vi-warning-soft, #FBF0DA); }
.vim-choice button.sel.defect .vim-choice-ic { color: var(--vi-warning, #C8880F); }
.vim-choice button.sel.fail { border-color: var(--vi-error, #C0392C); background: var(--vi-error-soft, #FBE8E5); }
.vim-choice button.sel.fail .vim-choice-ic { color: var(--vi-error, #C0392C); }


/* ══ AKTIONSZEILE · das mobile Aktions-Bauteil (Feedback #6 §2, 08.09.2026) ═══
   Erzeuger: `actHtml` / `actGroup` in mobile.js. Verwendet von Ticket, Wartung,
   Auftrag und Vorgangsakte — vorher trug jede dieser Listen zentrierte
   `vim-btn`-Blöcke mit Schriftzeichen als Symbolersatz (✉ 📷 ✓ ↩ → +).

   Bewusst DIESELBE Geometrie wie `.vim-choice` darüber (Icon-Spalte 22 px, 12 px
   Abstand, 10/14 Polster, Radius `--vi-r-md`): eine Auswahl und eine Aktion sehen
   gleich gebaut aus, sie unterscheiden sich nur im Zustand. Wer hier eine neue
   Geometrie erfindet, bricht genau die Konsistenz, die Feedback #6 verlangt.

   DREI TÖNE, mehr nicht:
     (ohne)     die alltägliche Aktion
     .is-primary die EINE Hauptaktion einer Liste — höchstens eine je Gruppe
     .is-quiet   nachrangig; mobil sind das die Verwaltungsaktionen (Vorgang) */
/* Gruppenüberschrift — GLEICHE Typografie wie jede andere Abschnittsüberschrift
   der Schale (.vim-sec h2): Satzschreibung, text-sm, 700. Versalien wären hier die
   einzige Ausnahme im ganzen Bildschirm gewesen. */
.vim-act-h {
  margin: 18px 2px 8px;
  font-family: var(--vi-font-display, system-ui, sans-serif);
  font-size: var(--text-sm); font-weight: 700; letter-spacing: .1px;
  color: var(--text-primary, #141A17);
}
.vim-acts { display: flex; flex-direction: column; gap: 8px; }

/* Zeilensymbol in Listen — dieselbe Familie wie die Aktionszeile, nur kleiner.
   Ersetzt die Schriftzeichen ✓ 🔔 ✉ ❓, die in Aufgaben, Wiedervorlagen und dem
   Rückfrage-Banner als Symbolersatz standen (Feedback #6 §2, projektweit). */
.vim-rowic {
  display: inline-flex; width: 15px; height: 15px; vertical-align: -2px;
  color: var(--text-muted, #5F6B66);
}
.vim-rowic svg { width: 15px; height: 15px; display: block; }
.vim-rowic.is-ok { color: var(--vi-green, #147352); }
.vim-act {
  display: flex; align-items: center; gap: 12px; width: 100%; min-height: 56px; padding: 10px 14px;
  border: 1.5px solid var(--border-default, #D8DFDC); border-radius: var(--vi-r-md, 10px);
  background: var(--bg-secondary, #fff); color: var(--text-primary, #141A17); cursor: pointer;
  font-family: inherit; font-size: var(--text-base); font-weight: 600; text-align: left;
  /* Wie bei .vim-choice ausdrücklich mitgesetzt — sonst erbt der <button> die
     Zentrierung aus design-system.css und die Symbolspalte wandert je Zeile. */
  justify-content: flex-start; white-space: normal;
  transition: background .12s ease, transform .08s ease;
}
.vim-act-ic {
  width: 22px; height: 22px; flex: 0 0 22px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-muted, #5F6B66);
}
.vim-act-ic svg { width: 22px; height: 22px; display: block; }
.vim-act-t { flex: 1 1 auto; min-width: 0; }
.vim-act-sub {
  display: block; margin-top: 2px;
  font-size: var(--text-xs); font-weight: 400; color: var(--text-muted, #5F6B66);
}
.vim-act:active { background: var(--bg-tertiary, #EFF2F1); transform: scale(.99); }
.vim-act[disabled] { opacity: .5; pointer-events: none; }

.vim-act.is-primary {
  background: var(--vi-green, #147352); border-color: var(--vi-green, #147352);
  color: var(--color-surface);
}
.vim-act.is-primary .vim-act-ic,
.vim-act.is-primary .vim-act-sub { color: var(--color-surface); opacity: .82; }
.vim-act.is-primary:active { background: var(--vi-green-deep, #0F5C42); }

.vim-act.is-quiet {
  border-color: var(--border-light, #E7E3DA); background: transparent;
  color: var(--text-secondary, #3A4441); font-weight: 500;
}
.vim-act.is-quiet:active { background: var(--bg-tertiary, #EFF2F1); }

/* Such-Eingabe */
/* Mobile Suchfeld: eigene Höhe (48 px Touchziel, 16 px Schrift gegen iOS-Zoom), aber
   DIESELBEN Design-Tokens wie das zentrale Primitive `.vi-search` — Rahmen, Rahmenfarbe,
   Fokusfarbe, Radius, Icon-Farbe und Placeholder kommen aus einer Quelle
   (public/css/design-system.css). Keine zweite Suchfeld-Optik. */
.vim-search { position: relative; margin-bottom: 12px; }
.vim-search input {
  width: 100%; min-height: 48px; padding: 12px 14px 12px 42px;
  border: 1px solid var(--search-border, #D8DFDC); border-radius: var(--search-radius, 8px);
  background: var(--search-bg, #fff); color: var(--search-ink, #141A17);
  font-size: var(--text-base); font-family: var(--font-body, inherit);
  -webkit-appearance: none; appearance: none;
  transition: border-color var(--transition, 150ms ease), box-shadow var(--transition, 150ms ease);
}
.vim-search input::placeholder { color: var(--search-placeholder, #5F6B66); }
.vim-search input:focus { outline: none; border-color: var(--search-border-focus, #147352); box-shadow: var(--search-ring, 0 0 0 3px rgba(20,115,82,.24)); }
.vim-search input::-webkit-search-decoration,
.vim-search input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; display: none; }
.vim-search svg { position: absolute; left: 13px; top: 50%; transform: translateY(-50%); width: 19px; height: 19px; stroke: var(--search-icon, #5F6B66); }

/* Objekt-Kontext-Chip */
/* Objekt-/Standort-Auswahl als VOLLBREITES, feld-artiges Element (nicht als kleine Pille) */
.vim-objchip {
  display: flex; align-items: center; gap: 9px; width: 100%;
  min-height: 50px; padding: 12px 14px; border-radius: var(--vi-r-md, 10px); cursor: pointer;
  background: var(--bg-secondary, #fff); border: 1px solid var(--border-default, #D8DFDC);
  font-size: var(--text-base); font-weight: 600; color: var(--text-primary, #141A17); text-align: left;
}
.vim-objchip:active { background: var(--bg-tertiary, #EFF2F1); }
.vim-objchip.is-set { border-color: var(--vi-green-soft, #EDF7F2); background: #F3F8F4; }
.vim-objchip svg { width: 19px; height: 19px; flex: 0 0 auto; stroke: var(--vi-green, #147352); }
.vim-objchip .vim-objchip-txt { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vim-objchip .vim-objchip-ph { color: var(--text-muted, #5F6B66); font-weight: 500; }
.vim-objchip .vim-objchip-x, .vim-objchip .vim-objchip-caret { flex: 0 0 auto; margin-left: auto; color: var(--text-muted, #5F6B66); font-size: var(--text-base); }

/* LESE-Raster vorhandener Fotos (Ticketdetail: bereits hochgeladene Anhaenge).
   Das ERFASSEN von Fotos gehoert nicht mehr hierher — Auswahldialog, Kamera,
   Miniaturen und Zaehler kommen zentral aus public/vi-photo.css (.vip-*). */
.vim-photos { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 8px; margin-top: 10px; }
.vim-photo { position: relative; aspect-ratio: 1; border-radius: var(--radius-lg); overflow: hidden; background: var(--bg-tertiary, #EFF2F1); border: 1px solid var(--vi-border, #D8DFDC); padding: 0; cursor: pointer; }
.vim-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Upload-Fortschritt */
.vim-progress { height: 8px; border-radius: var(--radius-pill); background: var(--bg-tertiary, #EFF2F1); overflow: hidden; margin-top: 10px; }
.vim-progress > span { display: block; height: 100%; background: var(--vi-green, #147352); width: 0; transition: width .2s ease; }

/* Key-Value-Liste (Detailansichten) */
.vim-kv { display: flex; flex-direction: column; gap: 0; }
.vim-kv-row { display: flex; gap: 12px; padding: 11px 0; border-bottom: 1px solid var(--vi-border, #D8DFDC); }
.vim-kv-row:last-child { border-bottom: none; }

/* Dokumentzeile mit PDF-Aktion: Name links, Aktion rechts. Die Schaltflaeche ist bewusst
   >=44 px hoch (Touch-Mindestgroesse) und bricht auf schmalen Geraeten unter den Namen. */
.vim-doc-row { align-items: center; flex-wrap: wrap; }
/* Dokumentzeile = „ansehen". Ganze Zeile ist die Trefferfläche (≥48 px);
   der frühere <a target="_blank"> ist am 22.08.2026 entfallen — er führte
   in den Browser statt in ViCore. */
.vim-doc-open {
  display: flex; align-items: center; gap: 8px;
  flex: 1 1 auto; min-width: 0; min-height: 48px;
  padding: 6px 0; cursor: pointer; text-align: left;
  border: none; background: none; border-radius: 0;
  color: inherit; font: inherit; justify-content: flex-start;
}
.vim-doc-open:active { background: var(--bg-tertiary, #EFF2F1); }
.vim-doc-open .vim-kv-v { display: block; min-width: 0; }
.vim-doc-open .vim-subtle { display: block; }
.vim-doc-sign {
  flex: 0 0 auto; min-height: 40px; padding: 0 12px;
  border: 1px solid var(--vi-border, #D8DFDC); border-radius: var(--radius-md);
  background: var(--color-surface, #fff); color: var(--color-forest, #0C6647);
  font: inherit; font-size: var(--text-sm); font-weight: 600; cursor: pointer;
}
.vim-doc-sign:active { background: var(--color-green-50, #EEF6F1); }
.vim-kv-k { flex: 0 0 40%; font-size: var(--text-sm); font-weight: 600; color: var(--text-secondary, #3A4441); }
.vim-kv-v { flex: 1 1 auto; font-size: var(--text-md); color: var(--text-primary, #141A17); word-break: break-word; }

/* Banner (Plausibilitätswarnung etc.) */
.vim-banner { display: flex; gap: 10px; padding: 12px 14px; border-radius: var(--vi-r-md, 10px); font-size: var(--text-sm); line-height: 1.4; margin-bottom: 14px; }
.vim-banner-warn { background: var(--vi-warning-soft, #FBF0DA); color: #6e4d12; }
.vim-banner-info { background: var(--vi-info-soft, #E5EFF4); color: var(--color-info-ink); }
.vim-banner b { font-weight: 750; }

/* Akkordeon (Vorgangsdetail) */
.vim-acc { border: 1px solid var(--vi-border, #D8DFDC); border-radius: var(--vi-r-lg, 14px); overflow: hidden; margin-bottom: 10px; background: var(--bg-secondary, #fff); }
.vim-acc-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; width: 100%; padding: 14px; border: none; background: none; cursor: pointer; font-size: var(--text-base); font-weight: 650; color: var(--text-primary, #141A17); text-align: left; }
.vim-acc-head .vim-acc-caret { transition: transform .18s ease; color: var(--text-muted, #5F6B66); }
.vim-acc.open .vim-acc-caret { transform: rotate(180deg); }
.vim-acc-body { padding: 0 14px 14px; display: none; }
.vim-acc.open .vim-acc-body { display: block; }
.vim-acc-count { font-size: var(--text-xs); font-weight: 700; color: var(--text-muted, #5F6B66); background: var(--bg-tertiary, #EFF2F1); border-radius: var(--radius-pill); padding: 1px 9px; }

/* Sekundärzeile in Detail-Listen (Fälligkeit, Datum, Bearbeiter …) — nie über den Rand */
.vim-subtle { color: var(--text-muted, #5F6B66); font-size: var(--text-xxs); margin-top: 2px; line-height: 1.35; overflow-wrap: anywhere; }
.vim-subtle a { text-decoration: none; }
/* E-Mail-Vorschau (Kommunikation) — kurzer Anriss, max. 3 Zeilen */
.vim-mailsnip { margin-top: 5px; font-size: var(--text-sm); color: var(--text-secondary, #3A4441); line-height: 1.4; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
/* „Zähler"-Leiste im Vorgangskopf: Anzahl je Bereich (offen/gesamt) — scrollt horizontal statt umzubrechen-über-Rand */
.vim-countrow { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.vim-countchip { display: inline-flex; align-items: baseline; gap: 4px; padding: 4px 9px; border-radius: var(--radius-pill);
  background: var(--bg-tertiary, #EFF2F1); color: var(--text-secondary, #3A4441);
  font-size: var(--text-xs); font-weight: 600; white-space: nowrap; }
.vim-countchip b { font-size: var(--text-xs); font-weight: 800; color: var(--text-primary, #141A17); }
.vim-countchip.is-zero { opacity: .5; }
.vim-countchip.is-hot { background: var(--vi-green, #147352); color: var(--color-surface); }
.vim-countchip.is-hot b { color: var(--color-surface); }

/* Mehr-Liste */
.vim-linklist { display: flex; flex-direction: column; gap: 0; background: var(--bg-secondary, #fff); border: 1px solid var(--vi-border, #D8DFDC); border-radius: var(--vi-r-lg, 14px); overflow: hidden; }
.vim-link { display: flex; align-items: center; gap: 13px; width: 100%; min-height: 56px; padding: 13px 15px; border: none; background: none; cursor: pointer; font-size: var(--text-base); font-weight: 600; color: var(--text-primary, #141A17); text-align: left; border-bottom: 1px solid var(--vi-border, #D8DFDC); }
.vim-link:last-child { border-bottom: none; }
.vim-link:active { background: var(--bg-tertiary, #EFF2F1); }
.vim-link svg { width: 21px; height: 21px; flex: 0 0 auto; stroke: var(--vi-green, #147352); }
.vim-link .vim-link-chevron { margin-left: auto; color: var(--text-muted, #b3ada0); font-size: 20px; }
.vim-link.danger { color: var(--vi-error, #C0392C); }
.vim-link.danger svg { stroke: var(--vi-error, #C0392C); }

/* Zustände: Laden / Leer / Fehler */
.vim-loading, .vim-empty, .vim-err { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; padding: 48px 24px; text-align: center; color: var(--text-secondary, #3A4441); }
.vim-empty-ic { font-size: 38px; opacity: .55; }
.vim-empty-title { font-size: var(--text-base); font-weight: 700; color: var(--text-primary, #141A17); }
.vim-empty-sub { font-size: var(--text-sm); }
.vim-spinner { width: 34px; height: 34px; border-radius: 50%; border: 3px solid var(--bg-tertiary, #EFF2F1); border-top-color: var(--vi-green, #147352); animation: vimSpin .7s linear infinite; }
@keyframes vimSpin { to { transform: rotate(360deg); } }

/* ── Bottom-Sheet (Ticket erstellen, Stand erfassen, Erledigt melden …) ────── */
.vim-sheet {
  position: fixed; inset: 0; z-index: 1100; display: none; flex-direction: column;
  background: var(--bg-primary, #FAFBFA);
}
.vim-sheet.open { display: flex; animation: vimSheetUp .22s cubic-bezier(.2,.7,.3,1); }
@keyframes vimSheetUp { from { transform: translateY(8%); opacity: .4; } to { transform: translateY(0); opacity: 1; } }

/* ── ANGEDOCKTES BOTTOM SHEET (kurze Auswahl) ───────────────────────────────
   Dieselbe Komponente wie die Vollbildmaske, nur unten angedockt: der Nutzer
   behält die Seite im Blick. Für „+ Erfassen" und den Statuswechsel.
   Die Höhe ist begrenzt (85 dvh); der Inhalt scrollt in sich.
   ────────────────────────────────────────────────────────────────────────── */
.vim-sheet-bottom {
  display: none; flex-direction: column; justify-content: flex-end;
  background: rgba(12, 26, 20, .42);
  animation: none;
}
.vim-sheet-bottom.open { display: flex; animation: vimSheetFade .16s ease-out; }
@keyframes vimSheetFade { from { background: rgba(12,26,20,0); } to { background: rgba(12,26,20,.42); } }
.vim-sheet-panel {
  display: flex; flex-direction: column;
  max-height: 85vh; max-height: 85dvh;
  background: var(--bg-primary, #FAFBFA);
  border-radius: var(--vi-r-xl, 18px) var(--vi-r-xl, 18px) 0 0;
  overflow: hidden;
  box-shadow: 0 -10px 34px rgba(12,26,20,.28);
  animation: vimSheetSlide .22s cubic-bezier(.2,.7,.3,1);
  padding-left: var(--app-safe-left);
  padding-right: var(--app-safe-right);
}
@keyframes vimSheetSlide { from { transform: translateY(14px); } to { transform: translateY(0); } }
/* Im angedockten Sheet steht der Kopf ruhig auf heller Fläche — die grüne
   Vollflächen-Kopfzeile gehört der Vollbildmaske. */
/* Das angedockte Sheet liegt unten — hier gibt es keinen Top-Inset zu beachten. */
.vim-sheet-bottom .vim-sheet-head {
  padding-top: 0; height: auto; min-height: 52px;
  background: var(--bg-primary, #FAFBFA); color: var(--text-primary, #141A17);
  border-bottom: 1px solid var(--vi-border, #EFEBE2);
}
.vim-sheet-bottom .vim-icon-btn { color: var(--text-secondary, #3A4441); }
.vim-sheet-bottom .vim-icon-btn:active { background: var(--bg-tertiary, #EFF2F1); }
.vim-sheet-bottom .vim-sheet-body {
  padding: 10px 16px 16px;
  padding-bottom: calc(16px + var(--app-safe-bottom));
}
/* Gleiche Regel wie bei .vim-top: Safe-Area DARF die Kopfhöhe nicht auffressen. */
.vim-sheet-head {
  flex: 0 0 auto; display: flex; align-items: center; gap: 8px;
  height: auto; min-height: calc(56px + var(--app-safe-top));
  padding: 0 8px 0 6px;
  padding-top: var(--app-safe-top);
  background: var(--vi-green, #147352); color: var(--color-surface);
}
.vim-sheet-head .vim-sheet-title { flex: 1 1 auto; font-weight: 700; font-size: var(--text-lg); font-family: var(--vi-font-display, system-ui, sans-serif); }
.vim-sheet-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; overflow-x: hidden; padding: 16px 16px 24px; }
.vim-sheet-actions {
  flex: 0 0 auto; display: flex; gap: 10px; padding: 12px 16px;
  padding-bottom: calc(12px + var(--app-safe-bottom));
  border-top: 1px solid var(--vi-border, #D8DFDC); background: var(--bg-secondary, #fff);
}
.vim-sheet-actions .vim-btn { flex: 1 1 0; width: auto; }

/* Erfolgs-Ansicht nach Speichern */
.vim-success { display: flex; flex-direction: column; align-items: center; gap: 16px; padding: 40px 24px; text-align: center; }
.vim-success-ic { width: 72px; height: 72px; border-radius: 50%; background: var(--vi-success-soft, #EDF7F2); color: var(--vi-success, #2E7D43); display: flex; align-items: center; justify-content: center; font-size: 38px; }
.vim-success-title { font-size: 20px; font-weight: 700; }
.vim-success-sub { font-size: var(--text-md); color: var(--text-secondary, #3A4441); }

/* dezenter Inline-Hinweis im Listenkopf */
.vim-listmeta { font-size: var(--text-xs); color: var(--text-muted, #5F6B66); margin: 0 2px 10px; }


/* ═══════════════════════════════════════════════════════════════════════════
   MOBILE v2 — globaler Objektkontext, schlanker Header, Ticketkarte, Heute-wichtig,
   Foto-Workflow (Kamera + Galerie), In-App-Kamera
   ═══════════════════════════════════════════════════════════════════════════ */

/* Die frühere zweite `.vim-top`-Regel (Hintergrund/Schatten/`height: 54px`) ist am
   22.08.2026 in die EINE Definition weiter oben aufgegangen. Ihre harte Höhe hätte
   den Safe-Area-Inset überschrieben — die Kopfzeile wäre auf Geräten mit Notch/
   Dynamic Island zu niedrig gewesen und ihr Inhalt abgeschnitten. */
.vim-top .vim-title { color: var(--text-primary, #141A17); font-size: var(--text-lg); }
/* Zurück + Aktualisieren als hübsche, abgestimmte runde Icon-Buttons (passend zur Objektauswahl-Pille) */
.vim-top .vim-back, .vim-top .vim-top-action {
  width: 40px; height: 40px; border-radius: 50%;
  background: #EAF3EC; border: 1px solid var(--vi-green-soft, #EDF7F2);
  color: var(--vi-green-deep, #0F5C42);
  transition: background .12s ease, transform .08s ease;
}
.vim-top .vim-back svg { width: 22px; height: 22px; stroke-width: 2.4; }
.vim-top .vim-top-action svg { width: 19px; height: 19px; stroke-width: 2.3; }
.vim-top .vim-back:active, .vim-top .vim-top-action:active { background: var(--vi-green-soft, #EDF7F2); transform: scale(.92); }
.vim-top .vim-back.vim-back-off { visibility: hidden; }
/* Zentraler mobiler Objektfilter — ZWEIZEILIG, sobald unterhalb der Objektebene
   gefiltert wird: Zeile 1 = OBJEKT (fester Anker, IMMER sichtbar), Zeile 2 = die
   aktuelle Unterebene (Gebäude › Etage › Raum). Ein nacktes „EG" ohne sein Objekt
   darf hier nie stehen — siehe objCtxLabel() in mobile.js.
   Die Pille bleibt bei 42 px: beide Zeilen zusammen messen ~33 px, die Kopfzeile
   wächst also NICHT (`height` → `min-height`, damit sie bei großer Systemschrift
   trotzdem nachgeben kann statt den Text abzuschneiden). */
.vim-objctx {
  flex: 1 1 auto; min-width: 0; display: flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 42px; padding: 3px 14px; cursor: pointer;
  border: 1px solid var(--vi-green-soft, #EDF7F2); border-radius: var(--radius-pill);
  background: #EAF3EC; color: var(--vi-green-deep, #0F5C42);
  font-weight: 750; font-size: var(--text-base);
}
.vim-objctx.is-active { background: var(--vi-green, #147352); border-color: var(--vi-green, #147352); color: var(--color-surface); }
/* Feedback #3 §1.2: Zurücksetzen auf „Alle Objekte“ braucht EINEN Fingertipp.
   Eigener Knopf NEBEN der Pille — innerhalb wäre es ein Knopf im Knopf, und jeder
   Tipp würde stattdessen den Objektwähler öffnen. Farbe folgt dem Kopf (hell),
   nicht der aktiven Pille. */
.vim-objctx-clear { width: 36px; height: 36px; color: var(--text-secondary, #3A4441); }
.vim-objctx-clear svg { width: 18px; height: 18px; stroke-width: 2.2; }
.vim-objctx-clear:active { background: var(--bg-tertiary, #EFF2F1); }
.vim-objctx-clear[hidden] { display: none; }
.vim-objctx-ic { display: flex; flex: 0 0 auto; }
.vim-objctx-ic svg { width: 19px; height: 19px; }
.vim-objctx-name {
  flex: 0 1 auto; min-width: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; line-height: 1.16;
}
/* Jede Zeile kürzt für sich — so bleibt die Objektzeile lesbar, auch wenn die
   Unterebene lang ist (und umgekehrt). */
.vim-objctx-obj { display: block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Zeile 2 ist zweigeteilt: der Vorspann (Gebäude/Etage) weicht bei Platzmangel
   per Ellipse zurück, die TIEFSTE Ebene (der Raum) bleibt vollständig lesbar.
   Genau umgekehrt zur normalen Ellipse — sonst stünde am Ende „Haus B › 1. Ober…"
   und die eigentliche Auswahl wäre weg. */
.vim-objctx-sub { display: flex; align-items: baseline; justify-content: center; max-width: 100%; min-width: 0; }
.vim-objctx-sublead { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vim-objctx-subleaf { flex: 0 0 auto; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vim-objctx-sub[hidden] { display: none; }
/* Einzeilig (Filter steht auf der Objektebene): der Objektname IST die Auswahl. */
.vim-objctx-obj { font-size: var(--text-base); font-weight: 750; }
/* Zweizeilig: Objekt = übergeordneter Kontext (kleiner, leicht zurückgenommen),
   Unterebene = die aktuelle Auswahl (prominenter). */
.vim-objctx.has-sub .vim-objctx-obj { font-size: var(--text-xs); font-weight: 650; opacity: .88; letter-spacing: .1px; }
.vim-objctx.has-sub .vim-objctx-sub { font-size: var(--text-base); font-weight: 800; }
.vim-objctx-caret { flex: 0 0 auto; opacity: .85; font-size: var(--text-sm); }
/* Sehr schmale Geräte (≈320–374 px): Innenabstand und Schrift leicht zurücknehmen,
   damit der Objektname möglichst ohne Ellipse passt — die Ellipse bleibt das
   letzte Netz, nicht der Normalfall. */
@media (max-width: 374px) {
  .vim-objctx { padding: 3px 10px; gap: 6px; }
  .vim-objctx-obj { font-size: var(--text-base); }
  .vim-objctx.has-sub .vim-objctx-obj { font-size: var(--text-xxs); }
  .vim-objctx.has-sub .vim-objctx-sub { font-size: var(--text-md); }
  .vim-objctx-caret { font-size: var(--text-xs); }
}
.vim-subtitle {
  flex: 0 0 auto; padding: 9px 16px 0; background: var(--bg-primary, #FAFBFA);
  font-size: var(--text-sm); font-weight: 700; letter-spacing: .1px; color: var(--text-secondary, #3A4441);
}
.vim-subtitle:empty { display: none; }

/* Ticketkarte: Titel + Priorität-Flag, Status/Objekt/Alter/Zuständiger/Fotos,
   Nr. dezent — darunter die drei Aktionen für unterwegs (Öffnen · Foto · Status). */
.vim-tkcard {
  display: block; width: 100%; text-align: left;
  background: var(--bg-secondary, #fff); border: 1px solid var(--vi-border, #D8DFDC);
  border-left-width: 4px; border-radius: var(--vi-r-md, 12px); margin-bottom: 8px;
  overflow: hidden; -webkit-tap-highlight-color: transparent;
}
.vim-tkcard-open {
  display: block; width: 100%; text-align: left; cursor: pointer;
  border: none; background: none; border-radius: 0; padding: 11px 13px 9px;
}
.vim-tkcard-open:active { background: var(--bg-tertiary, #EFF2F1); }
/* Aktionszeile: gleichwertige Schaltflächen, jede mit ausreichender Trefferfläche */
.vim-tkacts { display: flex; border-top: 1px solid var(--vi-border, #EFEBE2); }
.vim-tkact {
  flex: 1 1 0; min-height: 44px; border: none; border-radius: 0; cursor: pointer;
  background: none; color: var(--vi-green, #147352);
  font-size: var(--text-sm); font-weight: 700;
  border-left: 1px solid var(--vi-border, #EFEBE2);
}
.vim-tkact:first-child { border-left: none; }
.vim-tkact:active { background: var(--vi-green-soft, #EDF7F2); }
.vim-tkcard-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
/* Feedback #3 §2.2: Ein Tickettitel ist die Meldung. Abgeschnitten
   („Einbruchmeldeanlage geht nicht mehr scharf zu scha…“) ist er wertlos — mobil
   gibt es keinen Hover, der den Rest zeigt. Er bricht deshalb um, die Karte
   wächst mit; `white-space: normal` hebt das geerbte `nowrap` des Buttons auf. */
.vim-tkcard-title {
  font-weight: 650; font-size: var(--text-base); line-height: 1.3; color: var(--text-primary, #141A17);
  white-space: normal; overflow-wrap: anywhere; min-width: 0;
}
.vim-tkcard-head { align-items: flex-start; }
/* Auch der Zeilentitel (Listen/Detail) darf umbrechen statt zu kappen. */
.vim-row-title .vim-rt-text.vim-rt-wrap { white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere; }
.vim-prioflag { flex: 0 0 auto; font-size: var(--text-xxs); font-weight: 750; white-space: nowrap; padding: 3px 9px; border-radius: var(--radius-pill); }
/* Der Meldungsstatus steht auf einer eigenen Zeile und bleibt gut lesbar — die
   Plakette selbst ist die gemeinsame StatusBadge (`.vic-st`), nur etwas größer.
   `.vim-bigstatus` mit Inline-Hex ist entfallen (UX-Phase 8 §14). */
.vim-tkcard-status { margin-top: 9px; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.vim-tkcard-status .vic-st { font-size: var(--text-sm); padding: 5px 11px; }
.vim-tkcard-status .vic-st-dot { width: 8px; height: 8px; }
.vim-tkcard-sub { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 8px; }
.vim-chip-soft { font-size: var(--text-xs); color: var(--text-secondary, #3A4441); background: var(--bg-tertiary, #EFF2F1); border-radius: var(--radius-sm); padding: 2px 8px; white-space: nowrap; }
.vim-chip-warn { background: var(--color-warning-soft); color: var(--color-warning-ink); font-weight: 650; }
/* Das Objekt ist die erste Frage jeder Verwaltungsarbeit — es steht als erster
   Chip und trägt etwas mehr Gewicht als die übrigen Angaben. Es darf umbrechen:
   „Salomonstr. 10 · Atelier" ist länger als ein Statuswort, aber unverzichtbar. */
.vim-chip-obj {
  font-weight: 650; color: var(--text-primary, #141A17);
  background: var(--vi-green-soft, #EDF7F2);
  white-space: normal; overflow-wrap: anywhere;
}
.vim-tkcard-num { margin-top: 7px; font-family: var(--vi-font-mono, monospace); font-size: var(--text-xxs); color: var(--text-muted, #a39c8e); letter-spacing: .3px; }

/* Schlanke Meldungs-Detailansicht: Sachverhalt, Aktionen, Mehr-Menü */
.vim-muted { color: var(--text-secondary, #5F6B66); }
.vim-tkd-title { font-weight: 700; font-size: var(--text-base); line-height: 1.3; color: var(--text-primary, #141A17); }
.vim-tkd-desc { white-space: pre-wrap; font-size: var(--text-md); line-height: 1.5; color: var(--text-primary, #141A17); margin-top: 6px; }
.vim-tkd-desc.vim-muted { font-style: italic; }
.vim-tkd-actions { margin-top: 18px; }
/* Die erste Gruppenüberschrift braucht keinen zusätzlichen Vorlauf — der Block
   bringt ihn schon mit. */
.vim-tkd-actions > .vim-act-h:first-child { margin-top: 0; }
/* (Entfallen am 23.08.2026) Das eingeklappte „Mehr“-Menü des Ticket-Details ist
   aufgelöst: Vorgang erstellen/zuordnen/öffnen stehen jetzt als reguläre Aktionen
   in .vim-tkd-actions — Kernaktionen verstecken sich nicht hinter einem Aufklapper. */

/* (Entfallen am 23.08.2026) Die getrennten Foto-/Galerie-Buttons und die halbe
   In-App-Kamera der Mobil-Schale sind ersatzlos gestrichen. Beides liegt jetzt
   zentral in public/vi-photo.css + public/vi-photo.js und wird von Mobil-Schale,
   Desktop, Abnahme-Feldapp, Fotodokumentation und Portal gemeinsam genutzt. */

/* Objekt-Zuweisung im Ticketdetail (mobil) */
.vim-objassign { display: flex; align-items: center; gap: 8px; width: 100%; min-height: 46px; padding: 10px 12px; border: 1px solid var(--border-default, #D8DFDC); border-radius: var(--vi-r-md, 10px); background: var(--bg-secondary, #fff); cursor: pointer; font-size: var(--text-md); color: var(--text-primary, #141A17); text-align: left; }
.vim-objassign.is-empty { border-style: dashed; color: var(--vi-warning, #9a6a16); background: #FCF6E8; }
.vim-objassign svg { width: 18px; height: 18px; flex: 0 0 auto; }
.vim-objassign .vim-objassign-txt { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── Ticket-Detail: Statuskarte + Kommunikationsnachrichten ─────────────────
   Die Karte trägt seit der UX-Phase 8 KEINE eigene Zustandsfarbe mehr: Zustand
   und Handlungsbedarf stehen als Plaketten darin (`.vic-st` / `.vic-at`) und
   färben sich dort — dieselbe Farbe wie in jeder Desktop-Liste. Eine zusätzlich
   getönte Fläche wäre ein drittes Farbvokabular für dieselbe Aussage. */
.vim-statuscard {
  border-radius: var(--vi-r-lg, 14px); padding: 13px 15px; margin-bottom: 6px;
  background: var(--bg-tertiary, #EFF2F1);
}
.vim-statuscard-label { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.vim-statuscard-label .vic-st { font-size: var(--text-sm); padding: 5px 11px; }
.vim-statuscard-hint { font-size: var(--text-sm); margin-top: 6px; line-height: 1.4; color: var(--text-secondary, #3A4441); }

.vim-msg { border: 1px solid var(--vi-border, #D8DFDC); border-radius: var(--radius-lg); padding: 10px 12px; margin-bottom: 8px; background: var(--bg-secondary, #fff); }
.vim-msg-in { border-left: 3px solid var(--vi-green, #147352); background: #F3F8F4; }
.vim-msg-out { border-left: 3px solid var(--vi-info, #31708F); }
.vim-msg-head { display: flex; justify-content: space-between; gap: 8px; font-size: var(--text-xs); font-weight: 700; color: var(--text-secondary, #3A4441); }
.vim-msg-date { font-weight: 500; color: var(--text-muted, #5F6B66); white-space: nowrap; }
/* Fotos AM Ereignis (Feedback #3 §4.4) — „3 Foto(s) ergänzt“ ohne Bild ist unbrauchbar. */
.vim-msg-atts { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
.vim-msg-att { padding: 0; border: none; background: none; cursor: pointer; line-height: 0; }
.vim-msg-att img { width: 58px; height: 58px; object-fit: cover; border-radius: var(--radius-md); border: 1px solid var(--vi-border, #D8DFDC); display: block; }
.vim-msg-att-doc { line-height: 1.3; font-size: var(--text-xs); font-weight: 600; color: var(--vi-green-deep, #0F5C42);
  border: 1px solid var(--vi-border, #D8DFDC); border-radius: var(--radius-md); padding: 5px 9px; }
/* Abschlussnotiz (§2.5): die fachlich wesentliche Aussage eines geschlossenen Tickets. */
.vim-closing { border: 1px solid var(--vi-border, #D8DFDC); border-left: 3px solid var(--vi-green, #147352);
  border-radius: var(--vi-r-md, 12px); padding: 10px 12px; background: var(--bg-secondary, #F7F9F8); margin-bottom: 10px; }
.vim-closing-h { font-size: var(--text-xxs); font-weight: 700; color: var(--vi-green-deep, #0F5C42); margin-bottom: 4px; }
.vim-closing-body { font-size: var(--text-md); line-height: 1.45; white-space: pre-wrap; color: var(--text-primary, #141A17); }

.vim-msg-body { margin-top: 4px; font-size: var(--text-md); white-space: pre-wrap; color: var(--text-primary, #141A17); }

/* Aktualisieren-Button (Header, oben rechts) */
.vim-top-action svg { width: 21px; height: 21px; }
.vim-spin svg { animation: vimSpin .65s linear; transform-origin: 50% 50%; }

/* ── Objektbaum-Picker (mobil): ausklappbare Hierarchie + Typ-Chips ─────────── */
/* Aktueller Objektfilter im geöffneten Wähler — hier ungekürzt, damit die
   kompakte Kopfzeile kürzen DARF, ohne Information zu verlieren. */
.vim-objpick-cur {
  display: flex; align-items: flex-start; gap: 8px; margin: 0 0 10px;
  padding: 9px 11px; border-radius: var(--vi-r-md, 12px);
  background: var(--vi-green-soft, #EDF7F2); border: 1px solid var(--vi-border, #D8DFDC);
  font-size: var(--text-sm); font-weight: 650; line-height: 1.35; color: var(--text-primary, #141A17);
}
.vim-objpick-cur svg { width: 16px; height: 16px; flex: 0 0 auto; margin-top: 1px; color: var(--vi-green, #147352); }
.vim-objpick-cur span { min-width: 0; overflow-wrap: anywhere; }
.vim-tree { display: block; }
/* §5.1: Einrückung = Hierarchie — dieselbe Regel wie am Desktop (20 px je Ebene
   + dezente Astlinie). Vorher waren es 16 px ohne Linie; bei Liegenschaft →
   Objekt → Gebäude → Etage → Raum wirkten Geschwister und Kinder fast gleich weit
   eingerückt, und mobil gibt es keinen Hover, der die Zugehörigkeit nachreicht. */
.vim-tree-row {
  --obj-indent-base: 8px;
  --obj-indent-step: 20px;
  --obj-depth: 0;
  display: flex; align-items: stretch;
  padding-left: calc(var(--obj-indent-base) + var(--obj-depth) * var(--obj-indent-step));
  border-bottom: 1px solid var(--vi-border, #EFEBE2);
  background-image: repeating-linear-gradient(to right,
    var(--vi-border, #E4E9E7) 0, var(--vi-border, #E4E9E7) 1px,
    transparent 1px, transparent var(--obj-indent-step));
  background-position: calc(var(--obj-indent-base) + 10px) 0;
  background-size: calc(var(--obj-depth) * var(--obj-indent-step)) 100%;
  background-repeat: no-repeat;
}
.vim-tree-row[style*="--obj-depth:0"] { background-image: none; }
.vim-tree-caret { flex: 0 0 auto; width: 40px; min-height: 52px; border: none; background: none; cursor: pointer; color: var(--text-muted, #5F6B66); font-size: var(--text-base); display: flex; align-items: center; justify-content: center; transition: transform .15s ease; }
.vim-tree-caret.open { transform: rotate(90deg); }
.vim-tree-leaf { width: 40px; cursor: default; }
.vim-tree-pick { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 9px; border: none; background: none; cursor: pointer; padding: 11px 12px 11px 2px; text-align: left; min-height: 52px; -webkit-tap-highlight-color: transparent; }
.vim-tree-pick:active { background: var(--bg-tertiary, #EFF2F1); }
.vim-tree-all { width: 100%; padding-left: 14px; border-bottom: 1px solid var(--vi-border, #D8DFDC); }
.vim-tree-search { width: 100%; padding-left: 14px; border-bottom: 1px solid var(--vi-border, #EFEBE2); align-items: center; }
.vim-tree-searchmain { flex: 1 1 auto; min-width: 0; }
.vim-tree-name { flex: 1 1 auto; min-width: 0; font-size: var(--text-base); font-weight: 600; color: var(--text-primary, #141A17); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vim-tree-search .vim-tree-name { display: block; }
.vim-tree-path { display: block; font-size: var(--text-xxs); color: var(--text-muted, #5F6B66); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: 1px; }
.vim-typechip { flex: 0 0 auto; font-size: var(--text-xxs); font-weight: 700; padding: 2px 8px; border-radius: var(--radius-pill); border: 1px solid transparent; white-space: nowrap; }
/* Objektwechsler mobil: Favoriten-Abschnitt (ein-/ausklappbar) + Favoriten-Stern */
.vim-tree-group { padding: 12px 14px 5px; font-size: var(--text-xxs); font-weight: 700; letter-spacing: .02em; color: var(--text-muted, #5F6B66); text-transform: none; background: var(--bg-secondary, #FAF8F3); }
.vim-tree-fold { display: flex; align-items: center; gap: 6px; width: 100%; min-height: 40px; padding: 10px 14px; border: none; text-align: left; font-family: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.vim-tree-fold:active { background: var(--bg-tertiary, #EFF2F1); }
.vim-tree-foldc { display: inline-flex; transition: transform .15s ease; }
.vim-tree-foldc.open { transform: rotate(90deg); }
.vim-tree-foldn { font-weight: 600; color: var(--vi-border, #A9B3AF); }
.vim-tree-fav { flex: 0 0 auto; width: 46px; border: none; background: none; cursor: pointer; font-size: var(--text-lg); line-height: 1; color: var(--vi-border, #D8D2C4); -webkit-tap-highlight-color: transparent; }
.vim-tree-fav.is-on { color: var(--color-gold); }
/* Unterelement an dieser Zeile anlegen (Mandant -> ... -> Raum). Dezent, aber mit
   vollem Touch-Ziel (48 px) und deutlich vom Zeilen-Tap getrennt. */
.vim-tree-add {
  flex: 0 0 auto; width: 48px; min-height: 52px;
  border: none; border-left: 1px solid var(--vi-border, #EFEBE2); background: none;
  cursor: pointer; font-size: var(--text-xl); line-height: 1; font-weight: 400;
  color: var(--vi-green, #147352);
  display: flex; align-items: center; justify-content: center;
  -webkit-tap-highlight-color: transparent;
}
.vim-tree-add:active { background: var(--bg-tertiary, #EFF2F1); }

/* Objektübersicht mobil: dieselbe Datenmenge wahlweise als Struktur oder
   visuelle Kartenbibliothek. Der Umschalter bleibt kompakt, die Karte nutzt
   bewusst die volle Inhaltsbreite (eine Karte je Zeile). */
.vim-obj-viewbar { display: flex; justify-content: flex-end; margin: 0 0 10px; }
.vim-obj-view-switch {
  display: inline-flex; align-items: center; gap: 2px;
  padding: 3px; border: 1px solid var(--vi-border, #D8DFDC);
  border-radius: var(--vi-r-md, 10px); background: var(--bg-tertiary, #EFF2F1);
}
.vim-obj-view-switch button {
  min-height: 36px; padding: 0 13px; border: 0; border-radius: var(--radius-sm);
  background: transparent; color: var(--text-secondary, #3A4441);
  font-size: var(--text-sm); font-weight: 700; line-height: 1; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.vim-obj-view-switch button.active {
  background: var(--bg-secondary, #fff); color: var(--vi-green-deep, #0F5C42);
  box-shadow: var(--shadow-sm, 0 1px 3px rgba(40,30,20,.1));
}
.vim-obj-view-switch button:focus-visible {
  outline: 2px solid var(--vi-green, #147352); outline-offset: 2px;
}
.vim-object-card-grid {
  display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px;
  width: 100%; min-width: 0;
}
#vi-mobile .vim-object-card-grid > .obj-card-link {
  display: block; width: 100%; max-width: none; min-width: 0; margin: 0;
}
#vi-mobile .vim-object-card-grid .obj-card-link:focus-visible {
  outline: 3px solid var(--vi-green, #147352); outline-offset: 3px;
}
#vi-mobile .vim-object-card-grid .obj-card-link:active { transform: translateY(1px); }

@media (prefers-reduced-motion: reduce) {
  #vi-mobile .vim-object-card-grid .obj-card-link { transition: none; }
}

/* Wartungs-Detail (Mobile) — kompakte Summary + prominente Primaeraktion */
.vim-mtd-head { margin-bottom: 4px; }
.vim-mtd-title { font-size: var(--text-lg); font-weight: 700; color: var(--text-primary, #141A17); line-height: 1.3; }
.vim-mtd-obj { margin-top: 8px; font-size: var(--text-sm); color: var(--text-secondary, #3A4441); }
.vim-mtd-cta { margin-top: 14px; }

/* ═══════════════════════════════════════════════════════════════════════════
   EINGEBETTETE MODULSEITE ("mobil erreichbar")  ·  body.vim-embed
   ---------------------------------------------------------------------------
   Ein noch nicht mobil optimiertes Modul verlässt die App NICHT mehr. Die
   reguläre (responsive) Modulseite läuft in dem Band zwischen Kopfzeile und
   Bottom-Nav; die Schale wird dabei zum reinen Rahmen. Dadurch bleiben
   Objektkontext, Zurück und der Wechsel in jedes andere Modul jederzeit
   erreichbar — es gibt keine Navigations-Sackgasse mehr.

   Stapelordnung: #vi-mobile hat z-index:1000 und erzeugt einen eigenen
   Stacking-Context; die Modulseite muss deshalb DARUNTER liegen (999) und wird
   allein durch ihre Position im Band sichtbar. Der mittlere Bereich der Schale
   ist transparent und pointer-events:none, damit Tippen auf der Seite ankommt.
   ═══════════════════════════════════════════════════════════════════════════ */
body.vim-active.vim-embed #vi-mobile {
  background: transparent;
  pointer-events: none;
}
body.vim-active.vim-embed .vim-top,
body.vim-active.vim-embed .vim-subtitle,
body.vim-active.vim-embed .vim-nav,
body.vim-active.vim-embed .vim-sheet-host { pointer-events: auto; }

/* Arbeitsbereich der Feld-App bleibt als unsichtbarer Platzhalter stehen,
   damit die Bottom-Nav unten verankert bleibt (flex:1 wirkt weiter). */
body.vim-active.vim-embed .vim-view { visibility: hidden; }
body.vim-active.vim-embed .vim-fab { display: none !important; }

body.vim-active.vim-embed .main {
  display: flex !important;
  flex-direction: column;
  position: fixed;
  /* --vim-top-h ist die GEMESSENE Unterkante der Schalen-Kopfzeile (also inklusive
     eines etwaigen Rahmen-Versatzes); unten muss der Versatz addiert werden. */
  top: var(--vim-top-h, 84px);
  bottom: calc(var(--vim-frame-inset, 0px) + var(--vim-nav-h, 60px));
  left: var(--vim-frame-l, 0px); right: auto;
  width: var(--vim-frame-w, 100%);
  /* .main traegt global min-height:100vh (style.css) - das wuerde die Seite unter
     die Bottom-Nav schieben. Im Band bestimmen top/bottom die Hoehe. */
  height: auto;
  min-height: 0;
  margin: 0 !important;
  z-index: 999;
  overflow: hidden;
  background: var(--bg-primary, #FAFBFA);
}
/* Die Desktop-Topbar entfällt: Objektauswahl, Zurück und Aktualisieren stehen
   bereits in der Kopfzeile der Schale. Zwei Kopfzeilen übereinander wären genau
   der halb funktionierende Zwischenzustand, den es nicht geben darf. */
body.vim-active.vim-embed .main > .topbar { display: none !important; }
body.vim-active.vim-embed .sidebar,
body.vim-active.vim-embed .sidebar-backdrop { display: none !important; }

/* Der Inhalt scrollt in sich. Kein Platzhalter für die alte Bottom-Nav nötig;
   horizontales Scrollen bleibt möglich, wo es fachlich nötig ist (große Tabellen
   bringen ihre eigenen overflow-x-Wrapper mit), statt Inhalt abzuschneiden. */
body.vim-active.vim-embed .main > .content {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  -webkit-overflow-scrolling: touch;
  padding: 8px 12px 24px;
}
/* Der kleine Schirm gehört dem Inhalt: das Eigenpolster der Seite entfällt —
   den Abstand nach oben gibt bereits das Polster des Arbeitsbereichs. */
body.vim-active.vim-embed .vi-page { padding-top: 0; }
/* Der Modulkopf wiederholte nur, was die Kopfzeile der Schale bereits sagt
   („ENERGIE · COCKPIT“ → „Energie“ → Tab „Cockpit“). Drei Ebenen für dieselbe
   Aussage sind auf 390 px verschenkte Höhe — der Titel entfällt hier, die
   Primaeraktion des Moduls bleibt selbstverstaendlich erreichbar. */
body.vim-active.vim-embed .vmod-head-main { display: none; }
body.vim-active.vim-embed .vmod-head {
  padding-top: 0; padding-bottom: 0; min-height: 0; border-bottom: none;
}
body.vim-active.vim-embed .vmod-head .vmod-action { margin: 10px 0 2px; }

/* Modul-Chrome (Modulkopf + Tab-Leiste) bleibt sichtbar und scrollt mit —
   die Ebene-2-Navigation des Moduls geht mobil nicht verloren. */
body.vim-active.vim-embed .vmod-tabs-wrap,
body.vim-active.vim-embed .vmod-subviews {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
}

/* ── UX-Phase 8 §19: der Kopfstapel wird flach ───────────────────────────
   Auf 360 px standen bis zu 449 px Bedienung über dem ersten Datensatz:
   Ansichtsschalter und Modulaktionen brachen auf vier Zeilen um (164 px),
   darunter Tableiste, Filterzeile, Suchleiste und Werkzeugleiste. Der erste
   Bildschirm zeigte damit Bedienung statt Bestand.

   Die Antwort ist NICHT, etwas wegzulassen: jede dieser Leisten wird zu EINER
   quer scrollbaren Zeile. Alles bleibt erreichbar, nur eben nebeneinander
   statt untereinander. Gilt für alle Module gleich — es ist die gemeinsame
   Schale, nicht eine Modulregel. */
body.vim-active.vim-embed .vmod-head-side,
body.vim-active.vim-embed .vif-l1,
body.vim-active.vim-embed .vi-tbl-tools {
  flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch;
  scrollbar-width: none; max-width: 100%; min-width: 0;
}
body.vim-active.vim-embed .vmod-head-side::-webkit-scrollbar,
body.vim-active.vim-embed .vif-l1::-webkit-scrollbar,
body.vim-active.vim-embed .vi-tbl-tools::-webkit-scrollbar { display: none; }
body.vim-active.vim-embed .vmod-head-side > *,
body.vim-active.vim-embed .vif-l1 > *,
body.vim-active.vim-embed .vi-tbl-tools > * { flex: 0 0 auto; }
/* Die Werkzeugleiste behält Trefferzahl UND Aktionen in einer Zeile. */
body.vim-active.vim-embed .vi-tbl-toolbar { flex-wrap: nowrap; align-items: center; }
body.vim-active.vim-embed .vi-tbl-count { flex: 0 0 auto; }
/* `min-width: 0` ist Pflicht: ohne sie kann ein Flex-Element nicht unter seine
   Inhaltsbreite schrumpfen — die Leiste schöbe die Seite quer aus dem Bild. */
body.vim-active.vim-embed .vi-tbl-tools { flex: 1 1 auto; min-width: 0; justify-content: flex-end; }
/* Zeilenhöhe und Spaltenwahl steuern die TABELLE. Auf dem Telefon rendert
   VITable Karten (`_cardsHtml`) — beide Regler hätten dort nichts zu regeln. */
body.vim-active.vim-embed .vi-tbl-tools > [onclick*="_density"],
body.vim-active.vim-embed .vi-tbl-tools > [onclick*="_colMenu"] { display: none; }

/* ── UX-Phase 8 §19b: dieselbe Regel für die Leisten, die es 2026 dazugab ──
   GEMESSEN am 05.09.2026 (390 × 844, Wartungen und Eingänge): bis zur ersten
   Datenzeile standen 402 bzw. 388 px Bedienung. Der dicke Brocken war die
   FILTERLEISTE mit 98 px — sie brach auf ZWEI Zeilen um (Suche, darunter
   „Weitere Filter" und Sortierung), weil §19 nur `.vif-l1` erfasste und die
   Leiste selbst (`.vif-bar`) nie erreichte. Die Ansichtsumschalter der
   Eingänge (`.vif-views`) waren sogar hart abgeschnitten: 366 px sichtbar bei
   701 px Inhalt, ohne jede Scrollmöglichkeit — der Rest war unerreichbar.

   Es wird wieder NICHTS weggelassen, nur nebeneinander gelegt. Die Suche
   behält ihre Mindestbreite (der Platzhalter darf nicht abschneiden), die
   Filter stehen rechts daneben und sind einen Wisch entfernt. */
body.vim-active.vim-embed .vif-bar,
body.vim-active.vim-embed .vif-views,
body.vim-active.vim-embed .gb-l1 {
  flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch;
  scrollbar-width: none; max-width: 100%; min-width: 0;
}
body.vim-active.vim-embed .vif-bar::-webkit-scrollbar,
body.vim-active.vim-embed .vif-views::-webkit-scrollbar,
body.vim-active.vim-embed .gb-l1::-webkit-scrollbar { display: none; }
body.vim-active.vim-embed .vif-bar > *,
body.vim-active.vim-embed .vif-views > *,
body.vim-active.vim-embed .gb-l1 > * { flex: 0 0 auto; }
/* Die Suche bleibt das flexible Element — sie füllt, was übrig ist, und behält
   ihre Untergrenze. Ohne diese Zeile schrumpfte sie in der nowrap-Reihe auf
   ihre Basisbreite und stünde als schmaler Stummel neben den Filtern. */
/* In einer SCROLLENDEN Zeile darf die Suche nicht schrumpfen — sonst ist sie das
   einzige nachgiebige Element und fällt auf ihre Lupe zusammen (gemessen: 40 px).
   Sie bekommt eine feste, daumenfreundliche Breite, alles Weitere liegt daneben. */
body.vim-active.vim-embed .vif-bar > .vi-search.vif-search { flex: 0 0 240px; min-width: 240px; }
/* Die Fachsichtzeile des Gebäudebetriebs trägt mobil keine eigene Polsterung —
   die Schale setzt den Abstand zwischen den Ebenen bereits. */
body.vim-active.vim-embed .gb-l1 { padding-top: 0; padding-bottom: 0; }

/* ── Tippziele: 32 px sind eine Mausgröße ────────────────────────────────
   Statuschips, Ansichtsschalter, gespeicherte Sichten und die Fachsicht
   standen mobil auf `--control-h-sm` (32 px) — am Zeigegerät richtig, mit dem
   Daumen zu klein. Sie gehen auf die oberste Stufe DERSELBEN Höhenleiter
   (`--control-h-lg`, 40 px); eine eigene Touch-Höhe zu erfinden wäre die
   siebte Leiter, gegen die Regel 10A geschrieben wurde. */
body.vim-active.vim-embed .vif-pill,
body.vim-active.vim-embed .vif-view,
body.vim-active.vim-embed .vif-saved-btn,
body.vim-active.vim-embed .gb-sicht-sel,
body.vim-active.vim-embed .vi-tbl-tool,
body.vim-active.vim-embed .vi-tbl-act { min-height: var(--control-h-lg); }

/* ═══════════════════════════════════════════════════════════════════════════
   NAVIGATIONSPANEL ("Mehr") — vollständiges ViCore-Modulmenü
   ---------------------------------------------------------------------------
   Füllt die Schale (Kopfzeile und Bottom-Nav bleiben stehen). Ruhige, flache
   Zeilen statt Karten in Karten; die Gliederung ist dieselbe wie in der
   Desktop-Seitenleiste, weil sie aus derselben Konfiguration stammt.
   ═══════════════════════════════════════════════════════════════════════════ */
.vim-np { padding: 0 0 10px; }
/* Das Menue IST die Seite: der 14-px-Rand des Arbeitsbereichs entfaellt, damit die
   Zeilen randlos stehen und keine Karten-in-Karten-Optik entsteht. */
.vim-view.vim-nav-mode { padding: 0 0 calc(18px + var(--app-safe-bottom)); }
/* Globale Button-Radien der App hier bewusst neutralisieren - Navigationszeilen
   sind Listeneintraege, keine Schaltflaechen. */
.vim-np-mod, .vim-np-tab, .vim-np-act, .vim-np-user { border-radius: 0; }
/* Auch die globale Button-Zentrierung: Navigationszeilen sind linksbuendig. */
.vim-np-mod, .vim-np-tab, .vim-np-act, .vim-np-user { justify-content: flex-start; }

.vim-np-searchbar {
  position: sticky; top: 0; z-index: 4;
  background: var(--bg-primary, #FAFBFA);
  padding: 10px 12px 8px;
  border-bottom: 1px solid var(--vi-border, #D8DFDC);
}
.vim-np-search {
  display: flex; align-items: center; gap: 8px;
  background: var(--bg-secondary, #fff);
  border: 1px solid var(--vi-border, #D8DFDC);
  border-radius: var(--radius-lg); padding: 0 12px; height: 42px;
}
.vim-np-search svg { width: 18px; height: 18px; flex: 0 0 auto; color: var(--text-muted, #5F6B66); }
.vim-np-search input {
  flex: 1 1 auto; min-width: 0; height: 100%;
  border: none; outline: none; background: none;
  font: inherit; font-size: var(--text-base); color: var(--text-primary, #141A17);
}
.vim-np-search input::-webkit-search-cancel-button { -webkit-appearance: none; }

.vim-np-sec {
  padding: 18px 16px 6px;
  font-size: var(--text-xxs); font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-muted, #5F6B66);
}

/* Modulzeile (Gruppenkopf oder Einzelmodul) */
.vim-np-mod {
  display: flex; align-items: center; gap: 12px;
  width: 100%; min-height: 52px; padding: 10px 14px;
  border: none; border-top: 1px solid var(--vi-border, #D8DFDC);
  background: var(--bg-secondary, #fff);
  color: var(--text-primary, #141A17);
  font: inherit; font-size: var(--text-base); font-weight: 650;
  text-align: left; cursor: pointer;
}
.vim-np-group:last-of-type .vim-np-mod,
.vim-np-mod.is-single:last-of-type { border-bottom: 1px solid var(--vi-border, #D8DFDC); }
.vim-np-mod:active { background: var(--bg-tertiary, #EFF2F1); }
.vim-np-ic { flex: 0 0 auto; display: flex; color: var(--vi-green, #147352); }
.vim-np-ic svg { width: 21px; height: 21px; }
.vim-np-modname { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vim-np-count {
  flex: 0 0 auto; min-width: 20px; height: 20px; padding: 0 6px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-lg); background: var(--bg-tertiary, #EFF2F1);
  color: var(--text-muted, #5F6B66); font-size: var(--text-xxs); font-weight: 700;
}
.vim-np-caret {
  flex: 0 0 auto; color: var(--text-muted, #5F6B66); font-size: 19px; line-height: 1;
  transition: transform .18s ease;
}
.vim-np-group.is-open > .vim-np-mod .vim-np-caret { transform: rotate(90deg); }
.vim-np-group.is-current > .vim-np-mod { box-shadow: inset 3px 0 0 var(--vi-green, #147352); }
.vim-np-mod.is-single.is-active { box-shadow: inset 3px 0 0 var(--vi-green, #147352); color: var(--vi-green, #147352); }

/* Tabs eines Moduls (Ebene 2) — eingerückt, flach, keine Box in der Box */
.vim-np-tabs { display: none; background: var(--bg-primary, #FAFBFA); }
.vim-np-group.is-open > .vim-np-tabs { display: block; }
.vim-np-tab {
  display: flex; align-items: center;
  width: 100%; min-height: 48px; padding: 9px 14px 9px 47px;
  border: none; border-top: 1px solid var(--vi-border, #D8DFDC);
  background: none; color: var(--text-primary, #141A17);
  font: inherit; text-align: left; cursor: pointer;
}
.vim-np-tab:active { background: var(--bg-tertiary, #EFF2F1); }
.vim-np-tab.is-active { box-shadow: inset 3px 0 0 var(--vi-green, #147352); background: var(--bg-tertiary, #EFF2F1); }
.vim-np-tab.is-active .vim-np-tabname { color: var(--vi-green, #147352); font-weight: 700; }
.vim-np-tabtxt { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.vim-np-tabname {
  display: flex; align-items: center; gap: 6px; flex-wrap: nowrap;
  font-size: var(--text-md); font-weight: 600; min-width: 0;
}
.vim-np-tabsub {
  font-size: var(--text-xs); line-height: 1.35; color: var(--text-muted, #5F6B66);
  /* Eine Zeile mit Auslassungszeichen - line-clamp schnitt in der Flex-Spalte
     hart am Rand ab, weil das Kind kein min-width:0 hatte. */
  min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.vim-np-chip {
  flex: 0 0 auto;
  padding: 1px 6px; border-radius: var(--radius-sm);
  background: rgba(20,115,82,.10); color: var(--vi-green, #147352);
  font-size: 10px; font-weight: 700; letter-spacing: .02em; text-transform: none;
}
.vim-np-chip.is-soft { background: var(--bg-tertiary, #EFF2F1); color: var(--text-muted, #5F6B66); }
.vim-np-empty { padding: 28px 16px; text-align: center; color: var(--text-muted, #5F6B66); font-size: var(--text-md); }

/* Konto & App */
.vim-np-user {
  display: flex; align-items: center; gap: 12px;
  width: 100%; min-height: 60px; padding: 10px 14px;
  border: none; border-top: 1px solid var(--vi-border, #D8DFDC); border-bottom: 1px solid var(--vi-border, #D8DFDC);
  background: var(--bg-secondary, #fff); color: var(--text-primary, #141A17);
  font: inherit; text-align: left; cursor: pointer;
}
.vim-np-user:active { background: var(--bg-tertiary, #EFF2F1); }
.vim-np-av {
  flex: 0 0 auto; width: 36px; height: 36px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--vi-green, #147352); color: var(--color-surface); font-size: var(--text-sm); font-weight: 700;
}
.vim-np-usertxt { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.vim-np-acts { margin-top: 10px; }
.vim-np-act {
  display: flex; align-items: center; gap: 12px;
  width: 100%; min-height: 50px; padding: 10px 14px;
  border: none; border-top: 1px solid var(--vi-border, #D8DFDC);
  background: var(--bg-secondary, #fff); color: var(--text-primary, #141A17);
  font: inherit; font-size: var(--text-md); font-weight: 600; text-align: left; cursor: pointer;
}
.vim-np-acts .vim-np-act:last-child { border-bottom: 1px solid var(--vi-border, #D8DFDC); }
.vim-np-act:active { background: var(--bg-tertiary, #EFF2F1); }
.vim-np-act svg { width: 20px; height: 20px; flex: 0 0 auto; color: var(--text-muted, #5F6B66); }
.vim-np-act.is-danger { color: var(--color-danger); }
.vim-np-act.is-danger svg { color: var(--color-danger); }
.vim-np-foot { padding: 18px 16px 6px; text-align: center; color: var(--text-muted, #5F6B66); font-size: var(--text-xs); }

@media (prefers-reduced-motion: reduce) {
  .vim-np-caret { transition: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   EINGEBETTETE MODULSEITE — Doppelungen und Höhe (UI-Welle §24/§42/§48)
   ---------------------------------------------------------------------------
   Die Schale nennt oben bereits Modul und Tab („Gebäudebetrieb · Anlagen").
   Der Seitentitel der Modulseite wiederholte das ein zweites Mal und kostete
   auf einem quer gehaltenen Telefon (390 px Bildhöhe) den Platz, der für die
   erste Datenzeile fehlte. Die Primäraktion bleibt — sie ist keine Wiederholung.
   ═══════════════════════════════════════════════════════════════════════════ */
body.vim-active.vim-embed .vi-pagetitle { display: none; }
/* Bleibt nur noch die Aktion, rückt sie an den rechten Rand ohne leere Kopfzeile. */
body.vim-active.vim-embed .vi-pagehead { min-height: 0; }
body.vim-active.vim-embed .vi-pagehead:not(:has(.vi-pagehead__r > *)) { display: none; }

/* Telefon im QUERFORMAT: nur ~390 px Bildhöhe. Hier zählt jede Zeile — die
   Ansichts- und Kennzahlenleisten treten zusätzlich zurück. */
@media (max-height: 540px) and (pointer: coarse) {
  body.vim-active.vim-embed .vmod-head { display: none; }
  body.vim-active.vim-embed .vi-metricbar { display: none; }
  body.vim-active.vim-embed .vmod-subviews { padding-top: 0; padding-bottom: 0; }
}

/* Telefon quer: die Schalen-Kopfzeile tritt zurück. 54 px Kopf plus Untertitel
   sind bei 390 px Bildhöhe ein Siebtel des Bildes, das dauerhaft nichts zeigt.
   Bedienbarkeit bleibt: die Knöpfe behalten 40 px Trefffläche. */
@media (max-height: 540px) and (pointer: coarse) {
  .vim-top { min-height: calc(44px + var(--app-safe-top)); }
  .vim-subtitle { padding-top: 2px; padding-bottom: 2px; font-size: var(--text-xs); }
  .vim-nav { --vim-nav-pad: 2px; }
  /* Die Schnellerfassung stand quer in ZWEI Reihen à 52 px und schob die Arbeit
     aus dem Bild (UX-Phase 8 §18). Quer ist Breite da, Höhe nicht: eine Reihe.
     Die Trefffläche bleibt bei 44 px. */
  .vim-qa { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
  .vim-qa-b { min-height: 44px; padding: 0 8px; font-size: var(--text-sm); gap: 6px; }
}


/* Feedback #3 §8.3: „Ohne Frist“ ist ein ehrlicher Hinweis, keine Warnung —
   deshalb ruhig und ohne Farbfläche. */
.vim-hint-quiet { background: transparent; border: none; padding: 0 2px 6px; color: var(--text-muted, #5F6B66); font-size: var(--text-xs); }


/* ── ANSICHTS-SCHALTER Mobil ⇄ Desktop (UX-Phase 8 §22–§24 · Feedback #6) ─────
   EIN Knopf, zwei Wirte (Desktop-Topbar und Schalen-Kopfzeile), immer im Bild.
   Ersatzlos entfallen sind am 08.09.2026 die Vorgänger: das Segment-Paar
   „Mobil │ Desktop" im „Mehr"-Menü (.vim-layout / .vim-layout-b / .vim-np-sech)
   und die schwebende Rückweg-Pille (.vim-return-pill).
   „Dezent" heißt hier konkret: kleiner als jede Fachaktion daneben, ohne
   Farbfläche, ohne Beschriftung — der Knopf trägt das Symbol seines ZIELS und
   nennt es im Titel. Die Trefffläche bleibt ≥34 px, mobil in einer 42-px-Zeile. */

/* Desktop-Topbar: übernimmt .topbar-icon-btn unverändert; nur das Symbol wird auf
   das Maß der übrigen Kopfzeilen-Symbole gebracht (dort .topbar-btn-icon). */
.vi-layout-btn svg { width: 16px; height: 16px; opacity: .8; }

/* Kopfzeile der Schale: bewusst RUHIGER als „Zurück" und „Aktualisieren" — das
   sind runde, grün getönte Fachaktionen; ein Ansichtswechsel ist keine. */
.vim-top .vim-layout-btn {
  width: 34px; height: 34px; border-radius: 50%;
  background: transparent; border: 1px solid transparent;
  color: var(--text-muted, #5F6B66);
  transition: background .12s ease, transform .08s ease;
}
.vim-top .vim-layout-btn svg { width: 18px; height: 18px; }
.vim-top .vim-layout-btn:active { background: var(--bg-tertiary, #EFF2F1); transform: scale(.92); }

/* Erteilter Auftrag in der mobilen Meldung (Anf. 21) — dieselbe Aussage wie im
   Desktop-Band .tk2-auftrag, in der Formensprache der Schale. */
.vim-tkwo { padding: 12px 14px; }
.vim-tkwo-stand { font-weight: 600; color: var(--vim-ink, #14603F); margin-bottom: 8px; }
.vim-tkwo-z { display: grid; grid-template-columns: 1fr auto; gap: 2px 8px; width: 100%;
  padding: 8px 0; background: none; border: 0; border-top: 1px solid rgba(0,0,0,.07); text-align: left; font: inherit; color: inherit; }
.vim-tkwo-z:first-of-type { border-top: 0; }
.vim-tkwo-nr { font-variant-numeric: tabular-nums; font-weight: 600; }
.vim-tkwo-t { grid-column: 1; }
.vim-tkwo-m { grid-column: 1; font-size: 12px; opacity: .75; }
.vim-tkwo-z .vim-row-chevron { grid-column: 2; grid-row: 1 / span 3; align-self: center; }
.vim-tkwo-at { margin-top: 8px; padding: 6px 8px; border-radius: 6px; font-weight: 600; font-size: 12px; }
.vim-tkwo-at-need { background: #FDF6E7; color: #8A5B08; }
.vim-tkwo-at-crit { background: #FDECEC; color: #96261F; }
