/* Kribo Design-Theme – Tokens + Bausteine. Spezifikation: docs/design/ */

/* ---- Schriften (gebündelt, offline) ---- */
@font-face{font-family:'Bricolage Grotesque';font-weight:600;font-display:swap;src:url('fonts/bricolage-600.ttf') format('truetype')}
@font-face{font-family:'Bricolage Grotesque';font-weight:700;font-display:swap;src:url('fonts/bricolage-700.ttf') format('truetype')}
@font-face{font-family:'Bricolage Grotesque';font-weight:800;font-display:swap;src:url('fonts/bricolage-800.ttf') format('truetype')}
@font-face{font-family:'Hanken Grotesk';font-weight:400;font-display:swap;src:url('fonts/hanken-400.ttf') format('truetype')}
@font-face{font-family:'Hanken Grotesk';font-weight:500;font-display:swap;src:url('fonts/hanken-500.ttf') format('truetype')}
@font-face{font-family:'Hanken Grotesk';font-weight:600;font-display:swap;src:url('fonts/hanken-600.ttf') format('truetype')}
@font-face{font-family:'Hanken Grotesk';font-weight:700;font-display:swap;src:url('fonts/hanken-700.ttf') format('truetype')}

/* ---- Tokens (Light) ---- */
:root{
  color-scheme:light;
  --kri-paper:#F6EEDD; --kri-surface:#FFFBF3; --kri-tint:#F3E4CC;
  /* --kri-primary (hell #123A46 / dunkel #8FD3CC weiter unten) ist auf Android zusätzlich hartcodiert
     in Platforms/Android/MainActivity.cs (native Polsterung der Statusleiste, siehe Kommentar dort) —
     bei einer Änderung hier auch dort nachziehen. */
  --kri-ink:#23201A; --kri-ink2:#6E655A; --kri-primary:#123A46; --kri-line:#E4D8C2; --kri-card-border:transparent;
  /* Sekundärer Text/Icon-Ton AUF --kri-primary (Sidebar, Drawer, mobile App-Bar). Muss ein eigener
     Token sein: --kri-primary wechselt zwischen dunklem Petrol (hell) und hellem Mint (dunkel), ein
     festes Creme-rgba() wäre im Dunkelmodus Creme auf Mint (~1.3:1) und praktisch unlesbar. */
  --kri-on-primary-soft:#B1B8B0; --kri-on-primary-veil:rgba(255,255,255,.08); --kri-on-primary-line:rgba(255,255,255,.14);
  --kri-accent:#FA6A1E; --kri-accent-soft:#FCE0C6; --kri-accent-text:#AE480A;
  --kri-teal:#12A594; --kri-yellow:#F6B60B; --kri-pink:#EC5A86;
  --kri-ok:#2FA05E; --kri-warn:#D99400; --kri-danger:#E0492F; --kri-danger-text:#B83A22;
  --kri-display:'Bricolage Grotesque', system-ui, sans-serif;
  --kri-sans:'Hanken Grotesk', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --kri-mono:ui-monospace, Consolas, monospace;
  --kri-shadow:drop-shadow(0 6px 15px rgba(60,40,20,.14));
  /* Kantige Neigung: EINE zentrale Stellschraube. --kri-skew = Basis-Eckversatz in px.
     Die drei Stufen leiten sich davon ab und geben den Flächen etwas Unregelmässigkeit.
     Neigung global ändern? Nur --kri-skew anpassen. Ganz gerade? --kri-skew:0. */
  --kri-skew:5px;
  --kri-skew-s:calc(var(--kri-skew) * .4);
  --kri-skew-m:var(--kri-skew);
  --kri-skew-l:calc(var(--kri-skew) * 1.3);
}
/* ---- Tokens (Dark) ---- */
/* bewusst dupliziert (Media-Query + data-theme), synchron halten: der Media-Query-Block greift für
   System-Dunkelmodus ohne explizite Nutzerwahl, der data-theme-Block für die manuelle Umschaltung
   (kriboTheme.toggle setzt data-theme direkt) — beide müssen dieselben Werte tragen. */
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){
  color-scheme:dark;
  --kri-paper:#14100A; --kri-surface:#241D14; --kri-tint:#342A1D;
  --kri-ink:#F8F1E6; --kri-ink2:#C8BBA6; --kri-primary:#8FD3CC; --kri-line:#4A3E2D; --kri-card-border:#4A3E2D;
  /* --kri-primary ist hier ein HELLES Mint → der Ton darauf muss dunkel sein, ebenso die Schleier. */
  --kri-on-primary-soft:#2F3B35; --kri-on-primary-veil:rgba(0,0,0,.08); --kri-on-primary-line:rgba(0,0,0,.16);
  --kri-accent:#FF864B; --kri-accent-soft:#43301A; --kri-accent-text:#FF864B;
  --kri-teal:#3CC6B4; --kri-yellow:#F7C948; --kri-pink:#F58AAB; --kri-danger-text:#FF8A70;
  --kri-shadow:drop-shadow(0 8px 20px rgba(0,0,0,.6));
}}
/* bewusst dupliziert (Media-Query + data-theme), synchron halten — siehe Kommentar am Media-Query-Block
   oben. */
:root[data-theme="dark"]{
  color-scheme:dark;
  --kri-paper:#14100A; --kri-surface:#241D14; --kri-tint:#342A1D;
  --kri-ink:#F8F1E6; --kri-ink2:#C8BBA6; --kri-primary:#8FD3CC; --kri-line:#4A3E2D; --kri-card-border:#4A3E2D;
  /* --kri-primary ist hier ein HELLES Mint → der Ton darauf muss dunkel sein, ebenso die Schleier. */
  --kri-on-primary-soft:#2F3B35; --kri-on-primary-veil:rgba(0,0,0,.08); --kri-on-primary-line:rgba(0,0,0,.16);
  --kri-accent:#FF864B; --kri-accent-soft:#43301A; --kri-accent-text:#FF864B;
  --kri-teal:#3CC6B4; --kri-yellow:#F7C948; --kri-pink:#F58AAB; --kri-danger-text:#FF8A70;
  --kri-shadow:drop-shadow(0 8px 20px rgba(0,0,0,.6));
}

/* ---- Basis ---- */
body{font-family:var(--kri-sans);background:var(--kri-paper);color:var(--kri-ink)}
/* Barrierefreier Standard-Link (überschreibt Template-Blau aus app.css) */
a{color:var(--kri-accent-text)}
.kri-display{font-family:var(--kri-display)}
.kri-center{min-height:100dvh;display:flex;align-items:center;justify-content:center;padding:24px}
.kri-stack{display:flex;flex-direction:column;gap:16px}


/* ---- Eigener Datepicker (Kribo-Stil) ---- */
.kri-dp-field{display:flex;align-items:center;justify-content:space-between;gap:10px;cursor:pointer;text-align:left}
.kri-dp-field .kri-dp-placeholder{color:var(--kri-ink2)}
.kri-dp-backdrop{position:fixed;inset:0;z-index:40}
.kri-dp-pop{position:absolute;z-index:41;top:calc(100% + 6px);left:0;min-width:300px;background:var(--kri-surface);border:1px solid var(--kri-line);padding:14px;clip-path:polygon(0 var(--kri-skew-s),100% 0,100% calc(100% - var(--kri-skew-s)),0 100%)}
.kri-dp-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}
.kri-dp-title{font-family:var(--kri-display);font-weight:700;font-size:15px;text-transform:capitalize}
.kri-dp-nav{background:var(--kri-tint);color:var(--kri-primary);border:none;cursor:pointer;width:32px;height:32px;font-size:18px;line-height:1;display:flex;align-items:center;justify-content:center;clip-path:polygon(0 8%,100% 0,100% 92%,0 100%)}
.kri-dp-nav:hover{filter:brightness(.96)}
.kri-dp-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}
.kri-dp-wd{text-align:center;font-family:var(--kri-mono);font-size:11px;color:var(--kri-ink2);padding:4px 0}
.kri-dp-day{aspect-ratio:1;border:none;background:transparent;color:var(--kri-ink);font-family:var(--kri-sans);font-size:14px;cursor:pointer;clip-path:polygon(0 8%,100% 0,100% 92%,0 100%)}
.kri-dp-day:hover{background:var(--kri-tint)}
.kri-dp-day--today{box-shadow:inset 0 0 0 1.5px var(--kri-primary)}
.kri-dp-day--sel{background:var(--kri-accent);color:#241206;font-weight:700}
.kri-dp-foot{display:flex;justify-content:space-between;gap:8px;margin-top:10px}

/* ---- Ausleih-Belegungskalender (LendingAvailabilityCalendar) ---- */
.kri-lending-day--booked{box-shadow:inset 0 0 0 1.5px var(--kri-danger-text);color:var(--kri-danger-text)}
.kri-lending-legend{display:inline-block;width:12px;height:12px;box-shadow:inset 0 0 0 1.5px var(--kri-danger-text)}
.kri-lending-legend--selected{background:var(--kri-accent);box-shadow:none}

/* ---- Eigentums-Report (druckbar) ---- */
.kri-report-onlyprint{display:none}
.kri-report-owner{font-family:var(--kri-display);font-weight:700;font-size:16px;margin:14px 0 4px}
.kri-report-list{margin:0 0 8px;padding-left:20px}
.kri-report-list li{margin:3px 0}
@media print{
  .kri-sidebar,.kri-top,.kri-footer,.kri-no-print,.kri-dash-aside{display:none !important}
  .kri-shell,.kri-main-col,.kri-workspace{display:block;height:auto;overflow:visible}
  .kri-report-onlyprint{display:block;font-family:var(--kri-display);font-weight:800;font-size:22px;margin:0 0 14px}
  .kri-card{clip-path:none;border:1px solid #ccc} /*ok*/
  body{background:#fff}
}

/* ---- Termin-Datum-Badge ---- */
.kri-event-date{flex:none;width:52px;text-align:center;background:var(--kri-accent-soft);color:var(--kri-accent-text);padding:6px 0;clip-path:polygon(0 var(--kri-skew-s),100% 0,100% calc(100% - var(--kri-skew-s)),0 100%)}
.kri-event-day{display:block;font-family:var(--kri-display);font-weight:800;font-size:20px;line-height:1}
.kri-event-mon{display:block;font-family:var(--kri-mono);font-size:11px;text-transform:uppercase;margin-top:2px}

/* ---- Laden-Schnellauswahl (Chips) ---- */
.kri-store-chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
.kri-chip{font-family:var(--kri-sans);font-size:13px;font-weight:600;padding:5px 12px;border:none;cursor:pointer;background:var(--kri-tint);color:var(--kri-primary);clip-path:polygon(0 var(--kri-skew-s),100% 0,100% calc(100% - var(--kri-skew-s)),0 100%)}
.kri-chip:hover{filter:brightness(.97)}
.kri-chip--on{background:var(--kri-accent);color:#241206}
.kri-chip:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--kri-primary)}

/* ---- Kompakte Vorschau-Karten (Übersicht: Einkaufsliste/Ausgaben) ---- */
.kri-card--compact{padding:16px 18px 8px}
.kri-card--compact .kri-member{padding:5px 0;line-height:1.25}
/* letzter Listeneintrag: kein zusätzlicher Abstand nach unten */
.kri-card--compact .kri-member:last-child{padding-bottom:0}

/* ---- Filter-Leiste über Listen ---- */
.kri-filters{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin-bottom:16px}
.kri-filter{font-family:var(--kri-sans);font-size:14px;padding:8px 12px;border:none;background:var(--kri-surface);color:var(--kri-ink);clip-path:polygon(0 var(--kri-skew-s),100% 0,100% calc(100% - var(--kri-skew-s)),0 100%)}
.kri-filter:focus{outline:none;box-shadow:inset 0 0 0 2px var(--kri-primary)}
.kri-filter-search{flex:1;min-width:160px}

/* ---- Karte ---- */
.kri-card{background:var(--kri-surface);color:var(--kri-ink);padding:26px;border:1px solid var(--kri-card-border);clip-path:polygon(0 var(--kri-skew-m),100% 0,100% calc(100% - var(--kri-skew-m)),0 100%)}
/* Form-Varianten (seeded via Tilt.Quad) – MÜSSEN nach .kri-card stehen, sonst überschreibt
   .kri-cards clip-path die Varianz und alle Karten sehen gleich aus. */
.kri-q1{clip-path:polygon(0 var(--kri-skew-m),100% 0,100% calc(100% - var(--kri-skew-m)),0 100%)}
.kri-q2{clip-path:polygon(0 0,100% var(--kri-skew-m),100% 100%,0 calc(100% - var(--kri-skew-m)))}
.kri-q3{clip-path:polygon(0 var(--kri-skew-s),100% 0,100% calc(100% - var(--kri-skew-l)),0 100%)}
.kri-q4{clip-path:polygon(0 0,100% var(--kri-skew-l),100% calc(100% - var(--kri-skew-s)),0 100%)}
.kri-q5{clip-path:polygon(0 var(--kri-skew-l),100% var(--kri-skew-s),100% 100%,0 calc(100% - var(--kri-skew-m)))}
/* Karten mit schwebendem Kontextmenü (z. B. Mitglieder-Kebab): clip-path erzeugt einen
   Clipping-Kontext, der position:absolute-Kindelemente (.kri-menu) am Kartenrand abschneidet.
   Diese Variante verzichtet auf den Eck-Anschnitt, damit das Menü vollständig sichtbar bleibt;
   die Karte bleibt eckig/rechteckig (kein border-radius, weiterhin kantig). Muss nach den
   .kri-qN-Regeln stehen, um deren clip-path zuverlässig zu überschreiben. */
.kri-card--overflow-visible{clip-path:none;overflow:visible} /*ok*/
.kri-title{font-family:var(--kri-display);font-weight:800;font-size:22px;letter-spacing:-.01em;margin:0 0 4px;color:var(--kri-ink)}
.kri-muted{color:var(--kri-ink2);font-size:14px;margin:0 0 18px}
/* Karten-Untertitel (SectionCard-Komponente) — bislang an 48 Stellen als
   <h2 class="kri-title" style="font-size:18px"> von Hand nachgebaut. */
.kri-card-title{font-family:var(--kri-display);font-weight:800;letter-spacing:-.01em;margin:0 0 4px;color:var(--kri-ink);font-size:18px}

/* ---- Formularfeld ---- */
.kri-field{margin-bottom:14px}
.kri-field > label{display:block;font-size:13px;font-weight:600;margin-bottom:6px;color:var(--kri-ink)}
.kri-input{width:100%;font-family:var(--kri-sans);font-size:15px;padding:14px 16px;border:none;background:var(--kri-tint);color:var(--kri-ink);
  clip-path:polygon(0 var(--kri-skew-s),100% 0,100% calc(100% - var(--kri-skew-s)),0 100%)}
.kri-field:nth-of-type(even) .kri-input{clip-path:polygon(0 0,100% var(--kri-skew-s),100% 100%,0 calc(100% - var(--kri-skew-s)))}
.kri-input::placeholder{color:var(--kri-ink2)}
/* Datums-/Zeitfelder ins Theme ziehen: Höhe wie Textfelder, Picker-Icon dezent (folgt via color-scheme) */
.kri-input[type="date"],.kri-input[type="datetime-local"],.kri-input[type="time"]{min-height:49px;font-family:var(--kri-sans)}
.kri-input::-webkit-calendar-picker-indicator{cursor:pointer;opacity:.6;transition:opacity .15s}
.kri-input::-webkit-calendar-picker-indicator:hover{opacity:1}
/* barrierefreier Fokus trotz clip-path: inset-Ring bleibt sichtbar */
.kri-input:focus{outline:none;box-shadow:inset 0 0 0 2px var(--kri-primary)}

/* ---- Buttons ---- */
.kri-btn{font-family:var(--kri-sans);font-weight:600;font-size:15px;padding:13px 28px;border:none;cursor:pointer;
  color:#241206;background:var(--kri-accent);clip-path:polygon(0 0,100% var(--kri-skew-l),100% 100%,0 calc(100% - var(--kri-skew-l)));transition:filter .15s}
.kri-btn:hover{filter:brightness(.96)}
.kri-btn:disabled{opacity:.6;cursor:not-allowed}
.kri-btn:focus-visible{outline:none;box-shadow:inset 0 0 0 2px rgba(0,0,0,.55)}
.kri-btn--full{width:100%}
/* bewusster Alias: Primär-Stil ist der kri-btn-Default (siehe .kri-btn oben); die Klasse existiert nur,
   damit Markup, das eine Aktion ausdrücklich als primär kennzeichnen will, das lesbar tun kann. */
.kri-btn--primary{}
/* Sekundär: gefüllte Fläche (kein Rahmen) – clip-path würde einen Rahmen kappen.
   Tint-Hintergrund + dunkler Text = kantig UND kontraststark (WCAG AA). */
.kri-btn--secondary{background:var(--kri-tint);color:var(--kri-primary);border:none;clip-path:polygon(0 var(--kri-skew-m),100% 0,100% calc(100% - var(--kri-skew-m)),0 100%)}
.kri-btn--secondary:hover{filter:brightness(.97)}
.kri-btn--secondary:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--kri-primary)}
/* Ghost: reiner Text-Button – keine Fläche, daher kein clip-path nötig. */
.kri-btn--ghost{background:transparent;color:var(--kri-accent-text);border:none;clip-path:none;padding:8px 12px} /*ok*/
/* Danger: gefüllte Signalfläche (z. B. destruktive Primäraktion in einem Dialog) — exakt dieselbe
   Farbkombination wie .kri-toast--danger (dort bereits WCAG-AA-geprüft, ~4.8:1). */
.kri-btn--danger{background:var(--kri-danger);color:#1a0603}
/* Button-Varianz: benachbarte Buttons leicht unterschiedlich schräg (nth-of-type hat höhere
   Spezifität und überschreibt daher die Variant-clip-paths oben). Ghost bleibt ohne Fläche. */
.kri-btn:nth-of-type(even):not(.kri-btn--ghost){clip-path:polygon(0 0,100% var(--kri-skew-l),100% 100%,0 calc(100% - var(--kri-skew-l)))}
.kri-btn:nth-of-type(3n):not(.kri-btn--ghost){clip-path:polygon(0 var(--kri-skew-l),100% var(--kri-skew-s),100% calc(100% - var(--kri-skew-s)),0 100%)}

/* ---- Einladungscode-Chip ---- */
/* flex-wrap: Code (Mono 22px, letter-spacing) + Owner-Button "Neu generieren" passen auf 360px
   nach Karten-Padding nicht mehr nebeneinander (Button lief über den clip-path-Rand hinaus /
   erzeugte horizontales Scrollen). Der Button rutscht auf schmalen Screens in eine eigene Zeile. */
.kri-invite{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;background:var(--kri-accent-soft);
  padding:15px 17px;margin-top:8px;clip-path:polygon(0 0,100% var(--kri-skew-m),100% 100%,0 calc(100% - var(--kri-skew-m)))}
.kri-cap{font-family:var(--kri-mono);font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--kri-ink2)}
.kri-code{font-family:var(--kri-mono);font-size:22px;letter-spacing:.16em;color:var(--kri-primary);font-weight:700}

/* ---- Mitglieder / Avatar / Badge ---- */
.kri-member{display:flex;align-items:center;gap:12px;padding:8px 0;border-top:1px solid var(--kri-line)}
/* Kontextmenü (3-Punkte) für Zeilen-Aktionen, z. B. Mitglieder */
.kri-menu-wrap{position:relative;flex:none}
.kri-menu-trigger{padding:6px;min-width:0}
.kri-menu-scrim{position:fixed;inset:0;z-index:40}
.kri-menu{position:absolute;top:calc(100% + 4px);right:0;z-index:41;min-width:170px;background:var(--kri-surface);border:1px solid var(--kri-line);filter:var(--kri-shadow);display:flex;flex-direction:column;padding:4px}
.kri-menu-item{background:transparent;border:none;cursor:pointer;text-align:left;padding:9px 12px;font-size:14px;color:var(--kri-ink)}
.kri-menu-item:hover:not(:disabled){background:var(--kri-tint)}
.kri-menu-item:disabled{opacity:.5;cursor:default}
.kri-menu-item--danger{color:var(--kri-danger-text)}
/* Multiselect-Panel (z. B. Community-Auswahl je Widget): durchsuchbare Checkbox-Liste im
   selben schwebenden .kri-menu-Muster, nur breiter/scrollbar für viele Einträge. */
.kri-menu--list{width:240px;max-width:calc(100vw - 32px);max-height:260px;overflow-y:auto}
.kri-menu-search{width:100%;box-sizing:border-box}
.kri-menu-check{display:flex;align-items:center;gap:8px;padding:9px 8px;font-size:13.5px;cursor:pointer;min-height:36px}
.kri-menu-check:hover{background:var(--kri-tint)}
.kri-menu-check input{flex:none;width:18px;height:18px}
.kri-avatar{width:40px;height:40px;background:var(--kri-tint);color:var(--kri-primary);display:flex;align-items:center;justify-content:center;
  font-family:var(--kri-display);font-weight:800;clip-path:polygon(0 var(--kri-skew-m),100% 0,100% calc(100% - var(--kri-skew-m)),0 100%)}
.kri-avatar--teal{background:var(--kri-teal);color:#0c211d} .kri-avatar--pink{background:var(--kri-pink);color:#2a0d16} .kri-avatar--yellow{background:var(--kri-yellow);color:#3a2a00}
.kri-badge{font-family:var(--kri-mono);font-size:11.5px;font-weight:600;padding:4px 11px;clip-path:polygon(0 var(--kri-skew-s),100% 0,100% calc(100% - var(--kri-skew-s)),0 100%)}
.kri-badge--owner{background:var(--kri-accent);color:#241206} .kri-badge--score{background:var(--kri-tint);color:var(--kri-primary)}
/* Signalbadge (z. B. "gesperrt") — dieselbe Farbkombination wie .kri-btn--danger/.kri-toast--danger. */
.kri-badge--danger{background:var(--kri-danger);color:#1a0603}

/* ---- Kategorie-Farben (Feature-Kennzeichnung: Einkaufsliste/Aufgaben/Ausgaben/Pinnwand) ---- */
:root{
  --kri-cat-shopping:var(--kri-teal); --kri-cat-chores:var(--kri-yellow);
  --kri-cat-expenses:var(--kri-pink); --kri-cat-pinboard:var(--kri-primary);
}
.kri-cat--shopping{--kri-cat:var(--kri-cat-shopping)} .kri-cat--chores{--kri-cat:var(--kri-cat-chores)}
.kri-cat--expenses{--kri-cat:var(--kri-cat-expenses)} .kri-cat--pinboard{--kri-cat:var(--kri-cat-pinboard)}
[class*="kri-cat--"]:not(.kri-dashboard){border-left:4px solid var(--kri-cat)}

/* ---- Overlay / Dialog ---- */
.kri-overlay{position:fixed;inset:0;background:rgba(20,16,10,.55);display:flex;align-items:center;justify-content:center;
  padding:20px;z-index:1000}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .kri-overlay{background:rgba(0,0,0,.65)}}
:root[data-theme="dark"] .kri-overlay{background:rgba(0,0,0,.65)}
.kri-dialog{background:var(--kri-surface);color:var(--kri-ink);padding:24px;filter:var(--kri-shadow);border:1px solid var(--kri-card-border);
  clip-path:polygon(0 var(--kri-skew-m),100% 0,100% calc(100% - var(--kri-skew-m)),0 100%);max-width:420px;width:100%;max-height:90vh;overflow:auto}
.kri-dialog-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:20px;flex-wrap:wrap}

/* ---- Toast ---- */
.kri-toast{position:fixed;left:50%;bottom:24px;transform:translateX(-50%);padding:13px 20px;font-family:var(--kri-sans);
  font-size:14px;font-weight:600;max-width:90vw;filter:var(--kri-shadow);z-index:1100;background:var(--kri-surface);color:var(--kri-ink);clip-path:polygon(0 0,100% var(--kri-skew-m),100% 100%,0 calc(100% - var(--kri-skew-m)));
  display:flex;align-items:center;gap:14px}
.kri-toast--ok{background:var(--kri-ok);color:#0f2916}
.kri-toast--warn{background:var(--kri-warn);color:#3a2600}
.kri-toast--danger{background:var(--kri-danger);color:#1a0603}
.kri-toast-close{background:none;border:0;padding:0;margin:0;color:inherit;font:inherit;font-weight:700;line-height:1;cursor:pointer;flex-shrink:0}

/* ---- Detail-Modal (Kleinanzeigen-artiges Item-Detail, siehe DetailModal.razor) ---- */
.kri-detail-modal{max-width:560px;padding:0;overflow:hidden}
.kri-detail-modal-head{position:relative}
.kri-detail-modal-photo{width:100%;height:260px;object-fit:cover;display:block;background:var(--kri-tint)}
.kri-detail-modal-photo--empty{display:flex;align-items:center;justify-content:center}
.kri-detail-modal-close{position:absolute;top:10px;right:10px;background:var(--kri-surface);padding:6px 12px;filter:var(--kri-shadow)}
.kri-detail-modal-body{padding:20px 24px}
.kri-detail-modal-titlerow{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:8px}
.kri-detail-modal-price{font-family:var(--kri-mono);font-weight:700;font-size:17px;color:var(--kri-primary);white-space:nowrap}
.kri-detail-modal-badges{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:12px}
.kri-detail-modal-description{white-space:pre-wrap;margin:0 0 14px}
.kri-detail-modal-meta{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:4px;font-size:13px;color:var(--kri-ink2)}
.kri-detail-modal-actions{padding:0 24px 20px}

/* ---- Leerer Zustand / Ladezustand / Fehler ---- */
.kri-empty{text-align:center;color:var(--kri-ink2);padding:36px 16px}
.kri-loading{display:flex;align-items:center;justify-content:center;gap:12px;padding:24px;color:var(--kri-ink2)}
.kri-spinner{width:22px;height:22px;border:3px solid var(--kri-tint);border-top-color:var(--kri-accent);border-radius:50%;
  animation:kri-spin .8s linear infinite}
@keyframes kri-spin{to{transform:rotate(360deg)}} /*ok*/
@media (prefers-reduced-motion:reduce){.kri-spinner{animation:none;border-top-color:var(--kri-tint)}}
.kri-error{color:var(--kri-danger-text);font-size:13.5px;margin:8px 0}

/* ---- Grosse Touch-Checkbox (Einkaufsliste) ---- */
.kri-check{appearance:none;width:26px;height:26px;min-width:26px;border:1.8px solid var(--kri-ink2);background:var(--kri-surface);
  cursor:pointer;position:relative;flex-shrink:0}
.kri-check:checked{background:var(--kri-primary);border-color:var(--kri-primary)}
/* Häkchenfarbe bewusst var(--kri-surface) statt hartcodiertem #fff: --kri-primary kippt im
   Dunkelmodus auf helles Mint (#8FD3CC) — weiss darauf wäre nur noch ~1.7:1. --kri-surface ist
   in beiden Modi das Gegenstück zu --kri-primary (hell auf dunklem Petrol, dunkel auf hellem Mint)
   und bleibt so in beiden Modi kontrastreich. Analog zum --kri-on-primary-*-Muster oben. */
.kri-check:checked::after{content:"";position:absolute;left:7px;top:2px;width:6px;height:12px;
  border:solid var(--kri-surface);border-width:0 2.5px 2.5px 0;transform:rotate(45deg)} /*ok*/
.kri-check:focus-visible{outline:none;box-shadow:0 0 0 3px var(--kri-accent-soft)}

/* ---- Checkbox-Trefferfläche: Kästchen bleibt visuell 26px, das umschliessende <label>
   vergrössert die tatsächliche Tippfläche auf 44px, ohne die Optik zu verändern (Einkaufsliste). ---- */
.kri-check-wrap{display:flex;align-items:center;justify-content:center;min-width:44px;min-height:44px;flex-shrink:0}
.kri-check-wrap label{display:flex;align-items:center;justify-content:center;cursor:pointer}

/* ---- Beschriftetes Kontrollkästchen (CheckboxField-Komponente) — ersetzt das bislang an jeder
   Einsatzstelle wiederholte style="display:flex;align-items:center;gap:10px;cursor:pointer". ---- */
.kri-check-label{display:flex;align-items:center;gap:10px;cursor:pointer}

/* ---- Echtes Disclosure ("Mehr Optionen") — button mit aria-expanded/aria-controls, kein reines
   CSS-Aufklappen (Einkaufsliste: Menge/Aktion/Foto). ---- */
.kri-more-options{margin:10px 0}
.kri-more-toggle{display:flex;align-items:center;gap:6px;background:none;border:none;padding:8px 0;
  color:var(--kri-accent-text);font:inherit;font-weight:600;cursor:pointer}
.kri-more-chevron{flex-shrink:0}
.kri-more-body{padding:4px 0 0}

/* ---- Kompakte, zusammenhängende Liste (Einkaufsliste) — Trennlinien statt Karten+Abstand,
   das entfernt den Zwischenraum zwischen Einträgen vollständig. ---- */
.kri-shop-list{padding:0}
.kri-shop-row{display:flex;align-items:center;gap:14px;padding:14px 26px;border-bottom:1px solid var(--kri-line)}
.kri-shop-row:last-child{border-bottom:none}
.kri-shop-main{flex:1;min-width:0;cursor:pointer}
.kri-shop-meta{margin:2px 0 0;font-size:12.5px}
.kri-shop-thumb{object-fit:cover;flex-shrink:0;border:1px solid var(--kri-line)}
.kri-shop-sale-badge{display:inline-flex;margin-left:8px;padding:2px 8px;font-size:11.5px;font-weight:600;
  min-height:0;vertical-align:middle}
.kri-shop-edit{flex:1;min-width:0}

/* ---- Icon-Knöpfe (Bearbeiten/Löschen): 44px Trefferfläche bei kompakter Optik. ---- */
.kri-icon-btn{display:flex;align-items:center;justify-content:center;width:44px;height:44px;flex-shrink:0;
  background:none;border:none;color:var(--kri-ink2);cursor:pointer;padding:0}
.kri-icon-btn:hover{color:var(--kri-accent-text)}
.kri-icon-btn--danger:hover{color:var(--kri-danger-text)}
.kri-icon-btn:focus-visible{outline:none;box-shadow:0 0 0 3px var(--kri-accent-soft)}

/* ---- Schnellerfassung: nur auf Mobile sichtbar (siehe Media-Query unten), auf Desktop bleibt
   das bestehende Formular in .kri-dash-aside die einzige Erfassung. ---- */
.kri-shop-quickadd-wrap{display:none}

/* ---- Formularvalidierung ---- */
.kri-invalid{border-color:var(--kri-danger)!important;color:var(--kri-danger-text)}
.kri-input.kri-invalid{box-shadow:inset 0 0 0 1.6px var(--kri-danger)}
.kri-validation{color:var(--kri-danger-text);font-size:12.5px;margin:4px 0 0}

@media (prefers-reduced-motion:reduce){*{transition:none!important}}

/* ---- Mobile: Schräglagen dämpfen ---- */
@media (max-width:480px){
  /* Datepicker-Popup an die Feldbreite binden: min-width:300px ist breiter als der Inhaltsbereich
     einer Karte auf einem 360px-Display (~260px). Das Popup lief rechts heraus und wurde vom
     clip-path der umgebenden .kri-card abgeschnitten (letzte Wochenspalte fehlte). */
  .kri-dp-pop{min-width:0;left:0;right:0;padding:12px}
}

/* ---- Touch-Ziele sichern (docs/design/index.md: ≥44px) ----
   Breakpoint bewusst 900px statt 480px: das mobile Chrome (App-Bar/Bottom-Bar/Drawer, siehe unten)
   ist bis 900px aktiv — zwischen 481 und 900px (Phone quer, kleine Tablets) griff diese Regel
   bislang gar nicht. .kri-check ist bewusst ausgenommen (eigene, bereits 26px grosse Fläche). */
@media (max-width:900px){
  .kri-btn{min-height:44px}
  .kri-dp-nav{min-width:44px;min-height:44px}
  .kri-chip{min-height:44px;box-sizing:border-box;display:inline-flex;align-items:center}
  .kri-seg-btn{min-height:44px}
  .kri-menu-trigger{min-width:44px;min-height:44px}
  .kri-detail-modal-close{min-width:44px;min-height:44px;display:flex;align-items:center;justify-content:center}
}

/* === Dashboard-Layout (Desktop: Maske+Diagramm neben Liste; Mobile: gestapelt) === */
.kri-dashboard{max-width:1180px;margin:0 auto;padding:24px}
.kri-dash-head{display:flex;align-items:center;gap:10px;margin:0 0 18px}
.kri-dash-grid{display:grid;gap:20px;grid-template-columns:1fr}
.kri-dash-aside{display:flex;flex-direction:column;gap:20px;min-width:0}
.kri-dash-main{min-width:0}
@media (min-width:960px){
  .kri-dash-grid{grid-template-columns:minmax(300px,360px) 1fr;align-items:start}
}
/* Einspaltig (Mobile/schmales Tablet): IMMER der Hauptinhalt zuerst, die Nebenspalte
   (Hinzufügen-Formular, Filter, Diagramm) danach. Verhindert, dass die Desktop-Linke
   auf Mobile den eigentlichen Inhalt nach unten drückt. Seiten mit main-first im DOM
   bleiben unverändert (order 0 vs 1 ist dort deckungsgleich). */
@media (max-width:959.98px){
  .kri-dash-main{order:0}
  .kri-dash-aside{order:1}
}

/* === Bespoke Balken-Diagramm (kri-Design, hell/dunkel-fähig) === */
.kri-chart-rows{display:flex;flex-direction:column;gap:10px}
.kri-chart-row{display:grid;grid-template-columns:96px 1fr auto;align-items:center;gap:10px}
.kri-chart-label{font-size:13px;color:var(--kri-ink2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.kri-chart-track{height:16px;background:var(--kri-tint);clip-path:polygon(0 12%,100% 0,100% 88%,0 100%)}
.kri-chart-bar{height:100%;min-width:3px;clip-path:polygon(0 12%,100% 0,100% 88%,0 100%);transition:width .35s ease}
.kri-chart-value{font-size:13px;font-weight:700;color:var(--kri-ink);white-space:nowrap}
.kri-chart-empty{color:var(--kri-ink2);font-size:13.5px;margin:0}

/* === Footer (global) === */
/* Obere Kante bewusst schräg (Ausnahme) – analog zur Topbar. */
.kri-footer{position:relative;background:var(--kri-surface);color:var(--kri-ink2);font-size:13px;padding:28px 24px 16px;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px;clip-path:polygon(0 12px,100% 0,100% 100%,0 100%)}
.kri-footer a{color:var(--kri-accent-text);text-decoration:none;font-weight:600}
.kri-footer a:hover{text-decoration:underline}
.kri-footer-brand{display:inline-flex;align-items:center;gap:6px;font-family:var(--kri-display);font-weight:800;color:var(--kri-ink)}
.kri-footer-brand svg{flex:none}
.kri-footer-brand .kri-dot{color:var(--kri-yellow)}
.kri-footer-links{display:flex;gap:16px;flex-wrap:wrap;align-items:center}
.kri-footer-muted{color:var(--kri-ink2)}

/* === Landingpage (ausgeloggt) === */
.kri-landing{max-width:1100px;margin:0 auto;padding:24px}
.kri-hero{text-align:center;padding:56px 16px 40px}
.kri-hero-title{font-family:var(--kri-display);font-weight:800;font-size:clamp(34px,6vw,60px);line-height:1.05;color:var(--kri-ink);margin:0 0 14px}
.kri-hero-accent{color:var(--kri-accent)}
.kri-hero-sub{font-size:clamp(16px,2.2vw,20px);color:var(--kri-ink2);max-width:640px;margin:0 auto 26px}
.kri-hero-cta{display:inline-flex;gap:12px;flex-wrap:wrap;justify-content:center}
.kri-features{display:grid;gap:18px;grid-template-columns:1fr;margin:24px 0 8px}
@media (min-width:760px){.kri-features{grid-template-columns:repeat(3,1fr)}}
.kri-feature{padding:22px;background:var(--kri-surface);clip-path:polygon(0 var(--kri-skew-l),100% 0,100% calc(100% - var(--kri-skew-l)),0 100%)}
.kri-feature-ico{width:40px;height:40px;display:flex;align-items:center;justify-content:center;background:var(--kri-accent-soft);color:var(--kri-accent-text);margin-bottom:12px;clip-path:polygon(0 0,100% var(--kri-skew-s),100% 100%,0 calc(100% - var(--kri-skew-s)))}
.kri-feature-title{font-family:var(--kri-display);font-weight:700;font-size:18px;color:var(--kri-ink);margin:0 0 6px}
.kri-feature-text{color:var(--kri-ink2);font-size:14px;margin:0}

/* === Übersichts-Dashboard (eingeloggt) === */
.kri-kpis{display:flex;gap:18px;flex-wrap:wrap}
.kri-kpi{display:flex;flex-direction:column}
.kri-kpi-num{font-family:var(--kri-display);font-weight:800;font-size:22px;color:var(--kri-ink);line-height:1}
.kri-kpi-num--credit{color:var(--kri-teal)}
.kri-kpi-num--debt{color:var(--kri-danger-text)}
.kri-kpi-label{font-size:12px;color:var(--kri-ink2);margin-top:3px}

/* === Startseiten-Widgets (Dashboard) === */
/* min(280px,100%) statt 280px: sonst ist die Spur auf sehr schmalen Geräten (320px Viewport →
   ~272px Inhaltsbreite) breiter als der Container und die Seite scrollt waagrecht. */
.kri-dash-widgets{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(280px,100%),1fr));gap:16px}
.kri-widget{padding:18px 20px;display:flex;flex-direction:column}
.kri-widget--lg{grid-column:span 2}
@media (max-width:640px){.kri-widget--lg{grid-column:span 1}}
.kri-widget-head{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin-bottom:12px}
.kri-widget-title{font-family:var(--kri-display);font-weight:800;font-size:16px;color:var(--kri-ink)}
.kri-widget-open{font-size:12.5px;font-weight:600;color:var(--kri-accent-text);text-decoration:none;white-space:nowrap}
.kri-widget-kpi{margin:2px 0 4px}
.kri-widget-kpi .kri-kpi-num{font-size:34px}
.kri-widget-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px}
.kri-widget-list--cols2{display:grid;grid-template-columns:1fr 1fr;gap:0 24px}
@media (max-width:640px){.kri-widget-list--cols2{grid-template-columns:1fr}}
.kri-widget-item{border-bottom:1px solid var(--kri-line)}
.kri-widget-item:last-child{border-bottom:none}
.kri-widget-list--cols2 .kri-widget-item{border-bottom:1px solid var(--kri-line)}
.kri-widget-item-link{display:flex;align-items:center;gap:10px;text-decoration:none;color:inherit;padding:8px 0;min-height:40px}
.kri-widget-item-link:hover .kri-widget-item-title,.kri-widget-item-link:hover .kri-widget-item-sub{color:var(--kri-accent-text)}
.kri-widget-item-link input[type="checkbox"]{flex:none;margin:0}
.kri-widget-item-main{display:flex;flex-direction:column;min-width:0;flex:1 1 auto;gap:1px}
.kri-widget-item-title{font-weight:600;color:var(--kri-ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.kri-widget-item-sub{font-size:12px;color:var(--kri-ink2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.kri-widget-item-meta{font-family:var(--kri-mono);font-size:12px;color:var(--kri-ink2);white-space:nowrap;margin-left:auto;flex:none}
.kri-widget-kpi-wrap{display:flex;flex-direction:column;gap:12px}
.kri-widget-kpi-rows{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:0}
.kri-widget-kpi-row-link{display:flex;align-items:center;justify-content:space-between;gap:10px;text-decoration:none;color:inherit;font-size:13px;padding:6px 0;border-bottom:1px solid var(--kri-line)}
.kri-widget-kpi-rows li:last-child .kri-widget-kpi-row-link{border-bottom:none}
.kri-widget-kpi-row-link:hover .kri-widget-kpi-row-name{color:var(--kri-accent-text)}
.kri-widget-kpi-row-name{font-weight:600;color:var(--kri-ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.kri-widget-kpi-row-val{font-family:var(--kri-mono);font-size:12.5px;color:var(--kri-ink2);white-space:nowrap}
.kri-widget-kpi-row-val--credit{color:var(--kri-teal)}
.kri-widget-kpi-row-val--debt{color:var(--kri-danger-text)}
.kri-empty-hero{text-align:center;padding:56px 20px;max-width:520px;margin:0 auto}
.kri-empty-hero .kri-title{margin-bottom:8px}
.kri-empty-hero .kri-btn{margin-top:18px}

/* Segment-Umschalter (Widget-Größe klein/groß) */
.kri-seg{display:inline-flex;border:1px solid var(--kri-line)}
.kri-seg-btn{background:transparent;color:var(--kri-ink2);border:none;padding:5px 12px;font-size:12.5px;font-weight:600;cursor:pointer}
.kri-seg-btn.is-active{background:var(--kri-accent);color:#241206}

/* ============================================================
   NEUE APP-SHELL (Sidebar links · Topbar+Workspace rechts)
   ============================================================ */
/* Aus dem früheren Shell-Layout übernommen (siehe docs/decisions.md): der Theme-Umschalter erscheint
   in .kri-top-actions (MainLayout.razor) sowie im ausgeloggten Zustand, die Fehlerleiste ist global
   verankert (MainLayout.razor, id="blazor-error-ui"). */
.kri-theme-toggle{color:var(--kri-paper);font-size:14px;padding:8px 12px}
/* Textfarbe fest (nicht var(--kri-paper)): --kri-warn (#D99400) ändert sich zwischen den Modi nicht,
   --kri-paper aber schon — im Hellmodus wäre das Creme-auf-Amber nur ~2.2:1 (AA-Fail). Der feste
   dunkle Ton trägt in beiden Modi, analog zu .kri-toast--warn (dort korrekt #3a2600). */
#blazor-error-ui{background:var(--kri-warn);color:#3a2600;bottom:0;box-shadow:0 -1px 2px rgba(0,0,0,0.2);box-sizing:border-box;display:none;left:0;padding:0.6rem 1.25rem 0.7rem 1.25rem;position:fixed;width:100%;z-index:1000}
#blazor-error-ui .dismiss{cursor:pointer;position:absolute;right:0.75rem;top:0.5rem;color:#3a2600}
/* Desktop: Shell füllt genau den Viewport, nur der Workspace scrollt → Sidebar bleibt fix. */
.kri-shell{display:flex;height:100dvh;overflow:hidden;background:var(--kri-paper)}

/* Sidebar (dunkel, kontextuell) */
.kri-sidebar{width:288px;flex:none;height:100dvh;overflow-y:auto;background:var(--kri-primary);color:var(--kri-paper);display:flex;flex-direction:column;padding:16px 12px;gap:14px;clip-path:polygon(0 0,100% 0,calc(100% - 20px) 100%,0 100%)}
.kri-side-brand{display:flex;align-items:center;gap:8px;font-family:var(--kri-display);font-weight:800;font-size:20px;color:var(--kri-paper);text-decoration:none;padding:6px 8px}
.kri-side-brand svg{flex:none}
.kri-side-brand .kri-dot{color:var(--kri-yellow)}
.kri-side-cap{font-size:11px;letter-spacing:.5px;text-transform:uppercase;color:var(--kri-on-primary-soft)}

/* Haushalt-Umschalter */
.kri-switcher{position:relative}
.kri-switcher-summary{list-style:none;cursor:pointer;display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;border:none;font-family:inherit;background:var(--kri-on-primary-veil);padding:10px 12px;clip-path:polygon(0 var(--kri-skew-s),100% 0,100% calc(100% - var(--kri-skew-s)),0 100%)}
.kri-switcher-name{font-size:15px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--kri-paper)}
.kri-switcher-menu{position:absolute;left:0;right:0;top:calc(100% + 4px);z-index:20;background:var(--kri-surface);border:1px solid var(--kri-line);clip-path:polygon(0 0,100% var(--kri-skew-m),100% 100%,0 calc(100% - var(--kri-skew-m)));padding:6px;max-height:320px;overflow:auto}
.kri-switcher-item{display:block;padding:9px 10px;clip-path:polygon(0 var(--kri-skew-s),100% 0,100% calc(100% - var(--kri-skew-s)),0 100%);color:var(--kri-ink);text-decoration:none;font-size:14px}
.kri-switcher-item:hover{background:var(--kri-tint)}
.kri-switcher-item--active{background:var(--kri-accent-soft);color:var(--kri-accent-text);font-weight:600}
.kri-switcher-sep{height:1px;background:var(--kri-line);margin:6px 4px}

/* Sidebar-Navigation */
.kri-side-nav{display:flex;flex-direction:column;gap:2px}
.kri-side-link{display:flex;align-items:center;gap:12px;padding:10px 12px;clip-path:polygon(0 var(--kri-skew-s),100% 0,100% calc(100% - var(--kri-skew-s)),0 100%);color:var(--kri-paper);text-decoration:none;font-family:var(--kri-sans);font-weight:600;font-size:14px}
.kri-side-nav .kri-side-link:nth-child(2){clip-path:polygon(0 0,100% var(--kri-skew-m),100% 100%,0 calc(100% - var(--kri-skew-m)))}
.kri-side-nav .kri-side-link:nth-child(3){clip-path:polygon(0 var(--kri-skew-m),100% 0,100% calc(100% - var(--kri-skew-m)),0 100%)}
.kri-side-nav .kri-side-link:nth-child(4){clip-path:polygon(0 0,100% var(--kri-skew-m),100% 100%,0 calc(100% - var(--kri-skew-m)))}
.kri-side-nav .kri-side-link:nth-child(5){clip-path:polygon(0 var(--kri-skew-l),100% 0,100% calc(100% - var(--kri-skew-l)),0 100%)}
.kri-side-link:hover{background:var(--kri-on-primary-veil)}
.kri-side-link.active{background:var(--kri-accent);color:#241206}
.kri-side-link svg{flex:none}

/* Nutzer unten */
.kri-side-foot{margin-top:auto;border-top:1px solid var(--kri-on-primary-line);padding-top:12px}
.kri-side-user{display:flex;align-items:center;gap:10px;padding-right:22px}
.kri-side-user .kri-avatar{width:32px;height:32px;font-size:13px}
.kri-side-uname{flex:1;min-width:0;font-size:13px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--kri-paper)}
.kri-side-logout{background:none;border:none;color:var(--kri-on-primary-soft);cursor:pointer;padding:6px;display:flex;align-items:center}
.kri-side-logout:hover{color:var(--kri-paper)}

/* Rechte Spalte: Topbar (hell) + Workspace + Footer */
.kri-main-col{flex:1;min-width:0;min-height:0;display:flex;flex-direction:column}
/* Untere Kante bewusst schräg (Ausnahme, unabhängig vom --kri-skew-Standard) – die Diagonale
   entsteht aus dem Farbunterschied Surface/Paper, ohne separate Linie. */
.kri-top{position:relative;height:60px;flex:none;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:0 24px;background:transparent}
.kri-top::before{content:"";position:absolute;inset:0;background:var(--kri-surface);clip-path:polygon(0 0,100% 0,100% 100%,0 calc(100% - 12px));pointer-events:none}
.kri-crumb{font-size:13px;color:var(--kri-ink2);min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.kri-crumb-cur{color:var(--kri-ink);font-weight:600}
.kri-crumb-sep{color:var(--kri-line);margin:0 4px}
.kri-top-actions{display:flex;align-items:center;gap:8px}
/* LanguageSwitcher.razor rendert ein <select class="kri-input kri-lang-select"> — die Feldoptik kommt
   bereits von .kri-input, diese Regel verschmälert nur die Breite in der schmalen Filterleiste/Karte
   (an .kri-filter orientiert statt einer vollbreiten .kri-input-Spalte). */
.kri-lang-select{width:auto;min-width:150px;padding:8px 12px}
.kri-top .kri-theme-toggle{color:var(--kri-ink2)}
.kri-workspace{flex:1;min-width:0;min-height:0;overflow-y:auto}

/* Icon-Größen zentral (die SVGs tragen selbst keine width/height mehr). */
.kri-side-link svg,.kri-side-logout svg{width:18px;height:18px;flex:none}

/* Benachrichtigungsportal (Glocke) */
.kri-bell{position:relative}
.kri-bell-btn{position:relative;padding:8px;display:flex;align-items:center;justify-content:center}
.kri-bell-btn svg{width:20px;height:20px}
/* Textfarbe fest dunkel statt #fff: weiss auf --kri-danger (#E0492F) liegt nur bei ~4.07:1 (AA-Fail
   bei so kleiner Schrift), verschärft durch die 10px-Schrift. #1a0603 ist der bereits etablierte
   dunkle Ton der Danger-Toasts (.kri-toast--danger, ~4.8:1) — Design verbietet weissen Text auf
   Signalflächen (docs/design/index.md). Schrift zusätzlich auf 11px angehoben. */
.kri-bell-badge{position:absolute;top:2px;right:2px;min-width:16px;height:16px;padding:0 3px;background:var(--kri-danger,#d33);color:#1a0603;font-size:11px;font-weight:700;display:flex;align-items:center;justify-content:center;line-height:1}
.kri-highlight{outline:2px solid var(--kri-accent);outline-offset:2px;transition:outline-color 2s ease}
.kri-bell-menu{position:absolute;right:0;top:calc(100% + 6px);z-index:30;width:320px;max-width:calc(100vw - 24px);background:var(--kri-surface);border:1px solid var(--kri-line);clip-path:polygon(0 0,100% var(--kri-skew-m),100% 100%,0 calc(100% - var(--kri-skew-m)));max-height:400px;overflow-y:auto}
.kri-bell-item{display:block;padding:10px 14px;border-bottom:1px solid var(--kri-line);color:var(--kri-ink);text-decoration:none}
.kri-bell-item:last-child{border-bottom:none}
.kri-bell-item:hover{background:var(--kri-tint)}
.kri-bell-item-head{display:flex;align-items:center;justify-content:space-between;gap:8px;font-weight:600;font-size:14px}

/* Mobile-Chrome ist auf dem Desktop ausgeblendet; die Media-Query unten aktiviert es. */
.kri-mtopbar,.kri-btabs,.kri-drawer,.kri-drawer-scrim{display:none}

/* ============================================================
   MOBILE (<900px): Sidebar → schlanke App-Bar oben +
   Bottom-Tab-Bar (native App-Muster) + Drawer für den Rest.
   Desktop bleibt unverändert.
   ============================================================ */
@media (max-width:900px){
  /* Shell wird zum normalen Dokument-Fluss; nur der Body scrollt. */
  .kri-shell{display:block;height:auto;overflow:visible}
  .kri-sidebar{display:none}
  .kri-top{display:none}                 /* Desktop-Breadcrumb-Leiste aus */
  /* Platz für die fixe Bottom-Bar (inkl. Home-Indicator) gehört an die GANZE Spalte, nicht an den
     Workspace: der Footer steht im Fluss NACH dem Workspace und lag sonst hinter der Tab-Bar. */
  .kri-main-col{min-height:100dvh;padding-bottom:calc(64px + env(safe-area-inset-bottom))}
  .kri-workspace{overflow:visible}

  /* App-Bar oben: Hamburger · Kontext-Titel · Theme (dunkel, sticky).
     Höhe MUSS den oberen Safe-Area-Inset dazurechnen: box-sizing ist global border-box, die Höhe wäre
     sonst die Gesamthöhe INKLUSIVE Polsterung. Unter der Statusleiste/Notch blieben dann nur wenige
     Pixel für den Inhalt — der Text sitzt korrekt, aber der Hintergrund endet mitten darin. */
  .kri-mtopbar{display:flex;position:sticky;top:0;z-index:30;align-items:center;gap:8px;
    height:calc(56px + env(safe-area-inset-top));
    padding:0 8px;padding-top:env(safe-area-inset-top);background:var(--kri-primary);color:var(--kri-paper)}
  .kri-mtb-btn{display:flex;align-items:center;justify-content:center;width:44px;height:44px;flex:none;
    background:none;border:none;color:var(--kri-paper);cursor:pointer;padding:0}
  .kri-mtb-btn svg{width:22px;height:22px}
  .kri-mtb-title{flex:1;min-width:0;font-family:var(--kri-display);font-weight:800;font-size:17px;
    color:var(--kri-paper);text-decoration:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:center}

  /* Bottom-Tab-Bar: 4 Kern-Ziele + „Mehr", daumen-erreichbar, fix. */
  .kri-btabs{display:flex;position:fixed;left:0;right:0;bottom:0;z-index:30;
    background:var(--kri-surface);border-top:1px solid var(--kri-line);
    padding-bottom:env(safe-area-inset-bottom)}
  .kri-btab{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;justify-content:center;
    gap:3px;min-height:60px;padding:8px 2px;background:none;border:none;cursor:pointer;
    color:var(--kri-ink2);text-decoration:none;font:inherit}
  .kri-btab svg{width:22px;height:22px}
  .kri-btab-label{max-width:100%;font-size:11px;font-weight:600;line-height:1;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .kri-btab.active{color:var(--kri-accent-text)}

  /* Einkaufsliste (mobil): schmalere Zeile (weniger Polsterung) gibt den Platz für einen kleinen
     Zwischenraum zwischen den Einträgen frei, ohne die Zeilenzahl pro Bildschirm zu verringern.
     Der Zwischenraum war zuvor unsichtbar: .kri-shop-row hatte keinen eigenen Hintergrund und lag
     in einer .kri-card mit background:var(--kri-surface) – die 6px-Lücke zeigte exakt dieselbe
     Farbe wie die Zeile. Fix: Liste auf --kri-tint (deutlicherer Farbabstand zu --kri-surface als
     --kri-paper, in beiden Farbmodi geprüft), Zeilen auf --kri-surface – die Lücke zeigt jetzt das
     dunklere Tint durch. Trennlinie entfernt: Linie UND Lücke wäre eine Abgrenzung zu viel. */
  .kri-card.kri-shop-list{background:var(--kri-tint)}
  .kri-shop-row{padding:6px 14px;gap:10px;margin-bottom:6px;background:var(--kri-surface);border-bottom:none}
  .kri-shop-row:last-child{margin-bottom:0}

  /* Schnellerfassung: angeheftet direkt über der Bottom-Tab-Bar (deren Gesamthöhe 60px+Safe-Area
     beträgt, siehe .kri-btabs/.kri-btab oben), damit man beim Einkaufen unten weitertippen kann,
     ohne an der ganzen Liste vorbeizuscrollen. --kri-shop-list-bottom-gap reserviert dafür Platz
     am Ende der Liste, damit der letzte Eintrag nicht dauerhaft dahinter verschwindet. */
  .kri-cat--shopping{--kri-shop-list-bottom-gap:80px}
  /* Schnellerfassung-Wrapper: fix über der Tab-Leiste, enthält die Eingabezeile UND den
     aufklappbaren Mehr-Optionen-Bereich (Menge/Aktion/Foto) darüber — beides bleibt angeheftet,
     kein Sprung/Navigation (vormals ein <a href="#...">, siehe Bugfix). */
  .kri-shop-quickadd-wrap{display:block;position:fixed;left:0;right:0;
    bottom:calc(60px + env(safe-area-inset-bottom));z-index:29;
    background:var(--kri-surface);border-top:1px solid var(--kri-line)}
  .kri-shop-quickadd{display:flex;gap:6px;align-items:center;padding:10px 12px}
  .kri-shop-quickadd input{flex:1;min-width:0;min-height:44px}
  /* Winkel + Beschriftung statt Drei-Punkte-Symbol: sagt, WAS aufklappt (Formularbereich), nicht nur
     DASS etwas passiert — Drei-Punkte ist die Konvention für ein Überlaufmenü mit Aktionen, hier aber
     klappt ein Formularbereich auf (Bottom-Sheet-Konvention: Winkel oben=zu, unten=offen). Trefferfläche
     bleibt bei min. 44x44px, wächst in der Breite nur so viel wie das Wort "Mehr" braucht. */
  .kri-shop-quickadd-more-btn{display:flex;align-items:center;justify-content:center;gap:3px;
    min-width:44px;height:44px;flex-shrink:0;background:none;border:none;color:var(--kri-ink2);
    cursor:pointer;padding:0 6px;font:inherit;font-size:12px;font-weight:600;white-space:nowrap}
  .kri-shop-quickadd-more-label{flex-shrink:0}
  .kri-shop-quickadd-btn{flex-shrink:0;min-height:44px;padding:0 14px}
  /* Aufgeklappter Bereich: eigenes Scrollen statt Inhalt abzuschneiden, wenn er auf kleinen
     Bildschirmen höher würde als sinnvoll Platz bleibt (Tastatur eingeblendet etc.). */
  .kri-quickadd-more{max-height:38vh;overflow-y:auto;padding:10px 12px 0}
  /* Zusammenfassung der zugeklappten "Mehr"-Angaben — erscheint nur, wenn Laden/Menge/Aktion/Foto
     gesetzt sind, sonst kein leerer Platzhalter, der nur Höhe kostet. */
  .kri-shop-quickadd-summary{padding:6px 12px 0;font-size:12.5px}

  /* Drawer (voller Nav-Umfang) + abdunkelnder Scrim. */
  .kri-drawer-scrim{display:block;position:fixed;inset:0;z-index:40;background:rgba(0,0,0,.5);
    opacity:0;pointer-events:none;transition:opacity .2s ease}
  .kri-drawer-scrim.is-open{opacity:1;pointer-events:auto}
  /* Der Drawer liegt über die volle Höhe (top:0), also auch unter Statusleiste und Home-Indicator —
     beide Insets gehören deshalb in die Polsterung, sonst klebt der Schliessen-Knopf im Notch. */
  /* visibility:hidden zusätzlich zu aria-hidden im geschlossenen Zustand: reines transform verschiebt
     den Drawer nur ausserhalb des Viewports, alle Links darin blieben tastaturfokussierbar (Fokus
     landete im Unsichtbaren). Die transition-delay lässt beim Schliessen erst die Slide-out-Animation
     ablaufen, bevor visibility greift; beim Öffnen wird sofort sichtbar (delay 0). */
  .kri-drawer{display:flex;flex-direction:column;gap:12px;position:fixed;top:0;bottom:0;left:0;z-index:41;
    width:min(86vw,320px);background:var(--kri-primary);color:var(--kri-paper);overflow-y:auto;
    padding:calc(12px + env(safe-area-inset-top)) 12px calc(12px + env(safe-area-inset-bottom));
    transform:translateX(-100%);visibility:hidden;transition:transform .22s ease,visibility 0s linear .22s}
  .kri-drawer.is-open{transform:translateX(0);visibility:visible;transition:transform .22s ease,visibility 0s linear 0s}
  .kri-drawer-head{display:flex;align-items:center;justify-content:space-between}
  /* Touch-Ziele ≥44px (docs/design/index.md). Die Padding-Werte der Desktop-Sidebar ergeben nur
     ~40px bzw. ~30px für die Icon-Knöpfe — auf dem Touchscreen zu klein. */
  .kri-drawer .kri-side-link,.kri-drawer .kri-switcher-summary{min-height:44px}
  .kri-drawer .kri-switcher-item{min-height:44px;display:flex;align-items:center}
  .kri-side-logout,.kri-bell-btn{min-width:44px;min-height:44px;justify-content:center}
  .kri-drawer .kri-side-nav{flex-direction:column}
  .kri-drawer-tools{display:flex;align-items:center;gap:8px;padding:4px 4px 0;border-top:1px solid var(--kri-on-primary-line)}
  .kri-quick-edit{border-top:1px solid var(--kri-on-primary-line);padding-top:8px}
  .kri-quick-toggle{width:100%;background:none;border:none;cursor:pointer;font:inherit;text-align:left}
  .kri-quick-panel{display:flex;flex-direction:column;gap:6px;padding:8px 4px 4px}
  .kri-quick-item{display:flex;align-items:center;gap:10px;padding:8px 8px;color:var(--kri-paper);
    background:var(--kri-on-primary-veil);cursor:pointer;font-size:14px}
  .kri-quick-item input{width:20px;height:20px;flex:none}
  .kri-quick-item input:disabled{opacity:.4}
  .kri-quick-panel .kri-btn{margin-top:4px}
}

@media (prefers-reduced-motion:reduce){
  .kri-drawer,.kri-drawer-scrim{transition:none}
}

/* === Feed-Redesign === */

/* Feed-Spalte: die Lesebreite gehört EINMAL um die ganze Liste, nicht je Kartentyp. Vorher trug nur
   die Beitragskarte ein eigenes max-width — dadurch lief die Aktivitäts-Spur über die volle Breite und
   die Datumstrenner noch weiter links, drei verschiedene Kanten in einer Liste. Jetzt richten sich
   Beiträge, Aktivitätszeilen, Tagesüberschriften und "Neu seit"-Trenner an derselben Spalte aus
   (schmale Screens: automatisch volle Breite). */
.kri-feed-col{width:100%;max-width:600px;margin:0 auto}

/* Beitragskarte (FeedPostCard, docs/specs/newsfeed.md „Zwei Spuren"): padding:0 auf der Karte selbst
   (zwei Klassen = höhere Spezifität als .kri-card allein, überschreibt dessen 26px-Basis ohne sie
   anzufassen). Kopf/Text/Fusszeile holen sich ihr Padding stattdessen aus .kri-feed-post-pad; das
   Medium (.kri-feed-post-media) bleibt aussen vor und reicht dadurch bis an den (kantig
   beschnittenen) Kartenrand — "edge-to-edge" innerhalb der Karte. Die Breite kommt aus .kri-feed-col. */
.kri-card.kri-feed-post{padding:0}
.kri-feed-post-pad{padding:16px 20px}
.kri-feed-post-media{display:block;width:100%;height:auto;max-height:60vh;object-fit:cover}
/* Kurzer Text ohne Bild/Titel: getönter Statusblock im Stil eines Facebook-Status statt nacktem
   Fliesstext — Schwelle (~80 Zeichen) sitzt in FeedPostCard.IsShortStatus. */
.kri-feed-post-status{background:var(--kri-tint);padding:26px 20px;margin:0 20px}
.kri-feed-post-status p{font-family:var(--kri-display);font-weight:700;font-size:19px;line-height:1.35;margin:0;color:var(--kri-ink)}
/* Längerer Text ohne Bild: kein Statusblock (bei mehreren Zeilen zu dominant), aber trotzdem grösser/
   luftiger als die alte, stets kompakte Fassung. */
.kri-feed-post-text{font-size:16px;line-height:1.5}

/* Aktivitäts-Spur (ActivityEntryRow): kleines Modul-Symbol vor dem Beschreibungssatz, sowohl in der
   Kopfzeile als auch in jeder gruppierten Fortsetzungszeile (siehe ActivityEntryRow.FeatureIcon). */
.kri-activity-feature-icon{display:flex;flex:none;color:var(--kri-primary)}

/* Einladen-Schritt direkt nach dem Anlegen: der Code gross und monospaced, damit man ihn vorlesen und
   abtippen kann, ohne ihn zu entziffern. Eine Community ohne Mitglieder ist der haeufigste Grund, warum
   Kribo nach dem ersten Anlegen liegen bleibt — deshalb steht der Code hier statt in den Einstellungen. */
.kri-invite-code{font-family:var(--kri-mono);font-size:26px;font-weight:700;letter-spacing:.12em;
  padding:10px 12px;background:var(--kri-tint);color:var(--kri-ink);text-align:center;
  clip-path:polygon(0 var(--kri-skew-s),100% 0,100% calc(100% - var(--kri-skew-s)),0 100%)}

/* Auswahl der Community-Art beim Anlegen: eine Zeile je Art mit Name und einem Satz Erklärung. Als
   echte Radiogruppe (role/aria-checked im Markup), damit Tastatur und Screenreader sie als Auswahl
   erkennen — optisch aber Karten statt Radiopunkte, weil die Erklärung mitgelesen werden soll. */
.kri-type-option{display:flex;flex-direction:column;gap:2px;width:100%;text-align:left;
  padding:10px 12px;background:var(--kri-tint);border:1px solid var(--kri-line);color:var(--kri-ink);
  font:inherit;cursor:pointer}
.kri-type-option:hover{filter:brightness(.97)}
.kri-type-option:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--kri-primary)}
.kri-type-option--on{border-color:var(--kri-primary);box-shadow:inset 0 0 0 1px var(--kri-primary)}
.kri-type-option-name{font-weight:600;font-size:14px}
.kri-type-option-hint{font-size:12.5px;color:var(--kri-ink2)}

/* Navigations-Vorschau beim Anlegen: zeigt in derselben Reihenfolge wie die spätere Seitenleiste
   (ModuleNavOrder), welche Einträge die Community bekommt. Dunkler Grund wie die echte Sidebar, damit
   der Bezug sofort klar ist — es ist eine Vorschau, keine zweite Modulliste. */
.kri-nav-preview{margin-top:12px;padding:12px;background:var(--kri-sidebar-bg,#123A46)}
.kri-nav-preview .kri-cap{color:#cfe6e2}
.kri-nav-preview-list{display:flex;flex-direction:column;gap:2px}
.kri-nav-preview-item{padding:5px 8px;color:#f2efe6;font-size:13px;
  clip-path:polygon(0 var(--kri-skew-s),100% 0,100% calc(100% - var(--kri-skew-s)),0 100%)}
.kri-nav-preview-item:nth-child(odd){background:rgba(255,255,255,.06)}

/* Listenkarte: dieselbe Karte, aber mit dem Innenabstand einer Zeile statt dem einer Seite. Die
   26px-Basis von .kri-card ist für eigenständige Blöcke gedacht; in einer Liste kurzer Einträge
   (Termine, Ankündigungen, Buchungen) macht sie jede Kachel dreimal so hoch wie ihr Inhalt.
   Gleiche Werte wie .kri-activity-row/.kri-feed-post-pad, damit Listen überall gleich dicht sind. */
.kri-card--compact{padding:14px 18px}

/* Blubbel am Navigationseintrag „Neuigkeiten": Zahl der Einträge seit dem letzten Besuch der
   Feed-Seite. Sitzt rechts in der Zeile (margin-left:auto), damit die Beschriftungen aller Einträge
   auf derselben Kante beginnen — ein Blubbel direkt hinter dem Wort würde die Zeile ausbeulen.
   Akzentfarbe mit festem dunklem Text wie die übrigen Kennzeichen: die Sidebar ist in beiden Themes
   dunkel, eine themenabhängige Farbe wäre dort in einem der beiden Fälle unlesbar. */
.kri-nav-badge{margin-left:auto;flex:none;min-width:20px;padding:1px 6px;
  background:var(--kri-accent);color:#241206;font-family:var(--kri-mono);font-size:11px;font-weight:700;
  text-align:center;line-height:18px;
  clip-path:polygon(0 var(--kri-skew-s),100% 0,100% calc(100% - var(--kri-skew-s)),0 100%)}

/* Symbol-Schaltfläche in der Feed-Fusszeile (Reagieren, Kommentieren, Im Modul öffnen): Symbol statt
   Wort, weil drei ausgeschriebene Aktionen je Karte mehr Platz brauchen als der Inhalt darüber. Die
   Beschriftung lebt in aria-label/title weiter — ein Symbol ohne zugänglichen Namen wäre für
   Screenreader ein leerer Knopf.
   Mindestens 32px hoch/breit: darunter wird das Ziel auf einem Touchscreen unzuverlässig (WCAG 2.5.8
   nennt 24px als Untergrenze, Kribo liegt bewusst darüber). */
.kri-icon-btn{display:inline-flex;align-items:center;gap:6px;min-width:32px;min-height:32px;
  padding:6px 8px;background:none;border:none;color:var(--kri-ink2);font:inherit;font-size:13px;
  cursor:pointer;text-decoration:none}
.kri-icon-btn:hover:not(:disabled){color:var(--kri-ink);background:var(--kri-tint)}
.kri-icon-btn:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--kri-primary)}
.kri-icon-btn:disabled{opacity:.5;cursor:default}
/* Aktiver Zustand: es gibt bereits ein Gespräch. Gefüllte Sprechblase + kräftigere Farbe, damit sich
   „drei Kommentare" auf einen Blick von „noch keiner" unterscheidet — die Zahl allein ist im
   Listen-Überflug zu leise. */
.kri-icon-btn--on{color:var(--kri-primary);font-weight:600}

/* Eigener Status an einem Inserat („Interesse angemeldet") — gehört zu dessen Kennzeichnung oben,
   nicht in die Aktionszeile, wo er wie eine Beschriftung der Nachbarschaltfläche wirkte.
   Farben wie .kri-badge--owner/.kri-chip--on: Akzent mit FESTEM dunklem Text. Nicht var(--kri-primary)
   als Hintergrund — die Variable ist im hellen Design dunkel (#123A46) und im dunklen hell (#8FD3CC),
   eine einzelne Textfarbe darauf wäre in einem der beiden Modi unlesbar. */
.kri-badge--on{background:var(--kri-accent);color:#241206}

/* Umfrage-Option in der Inhaltskarte (FeedContentCard, docs/specs/newsfeed.md „Dritte Spur"): Balken für
   den Stimmenanteil liegt HINTER Text und Zahl (position:absolute + z-index-Reihenfolge), damit der Text
   immer auf dem Hintergrund der Karte lesbar bleibt statt auf einer Farbfläche zu verschwinden. Als
   <button> anklickbar, wenn abstimmen erlaubt ist, sonst als <div> mit identischem Aussehen — die Karte
   soll sich für Gäste und bei geschlossener Umfrage nicht optisch verändern, nur nicht reagieren. */
.kri-poll-option{position:relative;display:flex;align-items:center;gap:10px;width:100%;
  padding:10px 12px;background:var(--kri-tint);border:1px solid var(--kri-line);
  color:var(--kri-ink);font:inherit;text-align:left;cursor:default;overflow:hidden}
button.kri-poll-option{cursor:pointer}
button.kri-poll-option:hover:not(:disabled){filter:brightness(.97)}
button.kri-poll-option:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--kri-primary)}
.kri-poll-option--mine{border-color:var(--kri-primary)}
.kri-poll-option-bar{position:absolute;left:0;top:0;bottom:0;background:var(--kri-accent);opacity:.35;
  transition:width .2s ease}
.kri-poll-option-text{position:relative;flex:1;min-width:0;font-size:14px;font-weight:600}
.kri-poll-option-count{position:relative;flex:none;font-family:var(--kri-mono);font-size:13px;color:var(--kri-ink2)}

/* Innenabstand der Aktivitätszeile — identisch zu .kri-feed-post-pad, damit Avatar, Text und
   Drei-Punkte-Menü beider Spuren auf derselben senkrechten Linie sitzen. Gilt auch auf /activity
   (community-lokaler Verlauf): dieselbe Art Liste soll nicht zwei Abstände haben. */
.kri-activity-row{padding:16px 20px}

/* Profil-Kopf (ProfileSheet.razor): grösserer Avatar, bleibt in der projektweiten Skew-Form
   (.kri-avatar/clip-path) — bewusst NICHT rund, siehe FeedPostCard-Klassenkommentar zur
   Avatar-Konsistenz. */
.kri-profile-avatar--lg{width:104px;height:104px;font-size:34px}

/* "Bietet an"-Karten (ProfileSheet.razor): gruppiert nach Community, kompakte Kachel mit
   Modul-Icon/Titel/Preis statt der früheren flachen .kri-member-Liste. */
.kri-offer-card{display:flex;align-items:center;gap:10px;padding:10px 12px;background:var(--kri-tint);
  color:var(--kri-ink);text-decoration:none;clip-path:polygon(0 var(--kri-skew-s),100% 0,100% calc(100% - var(--kri-skew-s)),0 100%)}
.kri-offer-card:hover{filter:brightness(.97)}
.kri-offer-card:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--kri-primary)}
.kri-offer-card-title{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:600}
.kri-offer-card-price{flex:none;font-family:var(--kri-mono);font-size:12.5px;color:var(--kri-ink2)}

/* Messenger (docs/specs/messenger.md).

   Gesprächszeile: derselbe Aufbau wie .kri-offer-card (kantig beschnittene Kachel, Tint-Hintergrund),
   aber mit Avatar und zweizeiliger Mitte. Kein Vorschautext — der Server kennt ihn nicht. */
.kri-conv-row{display:flex;align-items:center;gap:12px;padding:10px 12px;background:var(--kri-tint);
  color:var(--kri-ink);text-decoration:none;
  clip-path:polygon(0 var(--kri-skew-s),100% 0,100% calc(100% - var(--kri-skew-s)),0 100%)}
.kri-conv-row:hover{filter:brightness(.97)}
.kri-conv-row:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--kri-primary)}
.kri-conv-main{flex:1;min-width:0}
.kri-conv-name{font-size:15px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.kri-conv-meta{display:flex;align-items:center;gap:8px;font-family:var(--kri-mono);font-size:12px;
  color:var(--kri-ink2)}

/* Nachricht. Eigene Nachrichten rechts, fremde links — die Schrägung spiegelt mit, damit die Kante
   jeweils zur Sprechrichtung zeigt. Die Farbe der eigenen Blase ist --kri-accent (NICHT --kri-primary:
   das ist im Hellmodus dunkel und im Dunkelmodus hell, eine einzige Textfarbe darauf wäre in einem der
   beiden Modi unlesbar — siehe Kontrast-Linter). */
.kri-msg{max-width:78%;margin-bottom:8px;padding:10px 13px;background:var(--kri-tint);color:var(--kri-ink);
  clip-path:polygon(0 var(--kri-skew-s),100% 0,100% calc(100% - var(--kri-skew-s)),0 100%)}
.kri-msg--mine{margin-left:auto;background:var(--kri-accent);color:#241206;
  clip-path:polygon(0 0,100% var(--kri-skew-s),100% 100%,0 calc(100% - var(--kri-skew-s)))}
.kri-msg-body{font-size:15px;line-height:1.45;white-space:pre-wrap;overflow-wrap:anywhere}
.kri-msg-time{margin-top:4px;font-family:var(--kri-mono);font-size:11.5px;opacity:.72}

/* Bild-Anhang in einer Nachricht (docs/specs/messenger.md). Kantig beschnitten wie alles Übrige, und mit
   fester Maximalhöhe: Ein hochkantiges Handyfoto würde sonst den halben Verlauf einnehmen. */
.kri-msg-image{display:block;max-width:100%;max-height:320px;margin-bottom:6px;object-fit:cover;
  clip-path:polygon(0 var(--kri-skew-s),100% 0,100% calc(100% - var(--kri-skew-s)),0 100%)}

/* Sprachnachricht und Datei-Anhang (docs/specs/messenger.md). Das <audio>-Element bekommt volle Breite,
   damit die Bedienleiste des Browsers nicht abgeschnitten wird. */
.kri-msg-audio{display:block;width:100%;min-width:220px;margin-bottom:6px}
.kri-msg-file{display:flex;align-items:center;gap:8px;width:100%;margin-bottom:6px;padding:8px 10px;
  border:none;cursor:pointer;font-family:var(--kri-sans);font-size:14px;text-align:left;
  background:var(--kri-tint);color:var(--kri-ink);
  clip-path:polygon(0 var(--kri-skew-s),100% 0,100% calc(100% - var(--kri-skew-s)),0 100%)}
.kri-msg-file:hover{filter:brightness(.97)}
.kri-msg-file:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--kri-primary)}
.kri-msg-file-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Eingabe bleibt beim Scrollen unten stehen. Der Scrollbereich ist .kri-workspace (nicht das
   Dokument), deshalb genuegt sticky. Der Hintergrund MUSS deckend sein — sonst scrollt der
   Verlauf sichtbar durch die Eingabe hindurch. Der negative Innenabstand unten gleicht das
   Padding von .kri-dashboard aus, damit unter der Leiste kein heller Streifen stehen bleibt. */
.kri-composer{position:sticky;bottom:0;z-index:2;margin-top:14px;padding:10px 0 24px;
  margin-bottom:-24px;background:var(--kri-paper)}
.kri-pending{position:relative;max-width:240px}
.kri-pending-x{position:absolute;top:2px;right:2px}

/* Antworten und Reaktionen im Messenger.
   Das Zitat sitzt IN der Blase und nicht darüber: Es gehört zur Antwort, nicht zum Verlauf — sonst läse
   es sich wie eine eigene Nachricht. */
.kri-msg-quote {
    border-left: 3px solid var(--kri-line);
    padding: 4px 8px;
    margin-bottom: 6px;
    font-size: 0.86rem;
    color: var(--kri-ink2);
    background: var(--kri-tint);
}

.kri-msg-foot {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 4px;
}

/* Die Aktionen sind bewusst leise: Sie stehen an jeder Nachricht und dürfen deshalb nicht um
   Aufmerksamkeit bitten. Beim Überfahren werden sie deutlich. */
.kri-msg-act {
    background: none;
    border: none;
    padding: 0 3px;
    cursor: pointer;
    color: var(--kri-ink2);
    opacity: 0.55;
    font-size: 0.95rem;
    line-height: 1;
}

.kri-msg-act:hover:not(:disabled),
.kri-msg-act:focus-visible {
    opacity: 1;
    color: var(--kri-ink);
}

.kri-reaction-picker {
    display: flex;
    gap: 2px;
    margin-top: 4px;
    padding: 3px;
    background: var(--kri-tint);
    border: 1px solid var(--kri-line);
}

.kri-reaction-choice {
    background: none;
    border: none;
    cursor: pointer;
    padding: 3px 5px;
    font-size: 1.1rem;
    line-height: 1;
}

.kri-reaction-choice:hover:not(:disabled) {
    background: var(--kri-surface);
}

.kri-reactions {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-top: 4px;
}

.kri-reaction {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 1px 6px;
    background: var(--kri-tint);
    border: 1px solid var(--kri-line);
    cursor: pointer;
    font-size: 0.85rem;
    line-height: 1.4;
    color: var(--kri-ink);
}

/* Die eigene Reaktion ist abgesetzt — ohne das weiss man nach einem Neuladen nicht mehr, ob der Daumen
   von einem selbst kam, und drückt ihn ein zweites Mal. */
.kri-reaction--mine {
    border-color: var(--kri-accent);
}

.kri-reaction-count {
    font-variant-numeric: tabular-nums;
    color: var(--kri-ink2);
}

.kri-reply-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 8px;
    margin-bottom: 6px;
    background: var(--kri-tint);
    border-left: 3px solid var(--kri-accent);
}

.kri-reply-text {
    flex: 1;
    font-size: 0.86rem;
    color: var(--kri-ink2);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Weiterleiten. Der Hinweis steht klein über der Nachricht — er ist eine Herkunftsangabe, keine Aussage. */
.kri-msg-forwarded {
    font-size: 0.78rem;
    color: var(--kri-ink2);
    margin-bottom: 3px;
}

.kri-forward-box {
    padding: 8px;
    margin-bottom: 8px;
    background: var(--kri-tint);
    border-left: 3px solid var(--kri-accent);
}

.kri-forward-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 6px;
    font-size: 0.88rem;
    color: var(--kri-ink2);
}

.kri-forward-list {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.kri-forward-target {
    padding: 4px 10px;
    background: var(--kri-surface);
    border: 1px solid var(--kri-line);
    color: var(--kri-ink);
    cursor: pointer;
    font-size: 0.88rem;
}

.kri-forward-target:hover:not(:disabled) {
    border-color: var(--kri-accent);
}

/* Frist für verschwindende Nachrichten. */
.kri-disappearing {
    margin-top: 14px;
    max-width: 340px;
}

.kri-disappearing label {
    display: block;
    font-size: 0.86rem;
    color: var(--kri-ink2);
    margin-bottom: 4px;
}

.kri-disappearing-hint {
    margin: 5px 0 0;
    font-size: 0.8rem;
}

/* Gruppen im Messenger. Eine Gruppe hat kein Gesicht — das Bild irgendeines Mitglieds zu zeigen wäre
   irreführend, deshalb ein neutrales Zeichen in derselben Grösse wie ein Profilbild. */
.kri-group-avatar {
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--kri-tint);
    border: 1px solid var(--kri-line);
    font-size: 1.2rem;
}

.kri-member-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 8px;
    background: var(--kri-surface);
    border: 1px solid var(--kri-line);
    cursor: pointer;
}

.kri-member-row:hover {
    border-color: var(--kri-accent);
}

/* Systemereignisse in Gruppen: keine Blase, sondern eine ruhige Zeile in der Mitte. Sie sind Vorgänge,
   keine Aussagen von jemandem. */
.kri-msg-system {
    align-self: center;
    text-align: center;
    font-size: 0.82rem;
    color: var(--kri-ink2);
    padding: 3px 10px;
    margin: 2px 0;
}

/* Absender über einer fremden Gruppennachricht — in 1:1 überflüssig, dort gibt es nur eine Gegenseite. */
.kri-msg-sender {
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--kri-ink2);
    margin-bottom: 2px;
}

/* Nicht belegte Urheberschaft. Deutlich, aber ohne den Inhalt zu verstecken: Die Nachricht soll sichtbar
   als zweifelhaft dastehen, nicht verschwinden. */
.kri-msg-unverified {
    display: inline-block;
    font-size: 0.78rem;
    color: var(--kri-danger-text);
    border: 1px solid var(--kri-danger);
    padding: 1px 6px;
    margin-bottom: 4px;
}

/* Gruppenverwaltung unter dem Verlauf. */
.kri-group-box {
    margin-top: 18px;
    padding: 12px;
    background: var(--kri-tint);
    border: 1px solid var(--kri-line);
}

/* Zustellungszustände an eigenen Nachrichten. Gelesen wird hervorgehoben, zugestellt bleibt ruhig —
   der Unterschied zwischen „angekommen" und „gesehen" soll sichtbar sein, ohne zu drängen. */
.kri-msg-tick {
    font-size: 0.8rem;
    color: var(--kri-ink2);
    opacity: 0.7;
    letter-spacing: -1px;
}

.kri-msg-tick--read {
    color: var(--kri-teal);
    opacity: 1;
}

/* Anrufe (docs/specs/calls.md) — Klingelbanner, "Anruf läuft"-Leiste (beide MainLayout) und das
   Anruffenster selbst (MessagesCall.razor, unter CallLayout). */
.kri-call-banner {
    position: fixed;
    top: 12px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 1200;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 18px;
    background: var(--kri-surface);
    border: 1px solid var(--kri-line);
    filter: var(--kri-shadow);
    max-width: calc(100vw - 24px);
    clip-path: polygon(0 0, 100% var(--kri-skew-m), 100% 100%, 0 calc(100% - var(--kri-skew-m)));
}

.kri-call-banner-name {
    font-weight: 700;
    margin-right: 6px;
}

.kri-call-banner-actions {
    display: flex;
    gap: 8px;
}

/* Eigener Button statt eines Links: die ganze Zeile ist der Klick-Bereich, kein <a> mit Ziel-URL. */
.kri-call-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    padding: 10px 16px;
    margin-bottom: 12px;
    background: var(--kri-tint);
    border: 1px solid var(--kri-line);
    color: var(--kri-ink);
    font: inherit;
    text-align: left;
    cursor: pointer;
    clip-path: polygon(0 var(--kri-skew-s), 100% 0, 100% calc(100% - var(--kri-skew-s)), 0 100%);
}

.kri-call-bar:hover {
    filter: brightness(.97);
}

.kri-call-bar-hint {
    color: var(--kri-ink2);
    font-size: 0.85rem;
}

.kri-call-window {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    text-align: center;
    max-width: 320px;
}

.kri-call-name {
    font-size: 1.4rem;
    margin: 0;
}

.kri-call-state {
    color: var(--kri-ink2);
    margin: 0;
}

.kri-call-actions {
    display: flex;
    gap: 12px;
    margin-top: 10px;
}
