/* app.css — eigene CSS-Regeln über Tailwind hinaus.
 *
 * Tailwind (vorgebaut in css/tailwind.css) deckt fast alles ab. Hier nur Sachen, die mit Utility-Klassen
 * unschön werden: Scrollbar, Fokus-Outlines, Übergänge, Print-Styles.
 */

:root {
  /* Revi-Farbwelt aus dem Brand-Icon.
   * Akzent = Revi-Blau, Neutraltöne kühl und entsättigt, Karten weiß
   * mit weichem Schatten. Statusfarben (amber/rot/grün) bleiben Funktionsfarben. */
  --color-accent: #3161de;       /* Revi-Blau (Brand-Icon #3669E6→#31429B) */
  --color-accent-hover: #2a55c7;
  --color-accent-soft: #eaf0fc;
  --color-border: #e2e4ea;
  --color-border-soft: #eceef3;
  --color-text: #171b29;         /* Navy-Schwarz (Wortmarke) */
  --color-text-2: #5f6472;
  --color-text-muted: #9ba0ad;
  --color-page-bg: #f1f2f6;      /* Sidebar-/Rahmen-Fläche */
  --color-main-bg: #fafbfd;      /* Content-Fläche */
  --color-card-muted: #f6f7fa;   /* Kopfbänder, Zeilen-Hover, Fußzeilen */
  --color-navy: #0f1523;         /* dunkle Sidebar (nur mobile Projektliste) */
  --brand-grad: linear-gradient(160deg, #3669e6, #31429b);
  --shadow-card: 0 1px 2px rgba(23, 28, 45, 0.04), 0 6px 20px rgba(23, 28, 45, 0.03);
  --shadow-pill: 0 1px 2px rgba(23, 28, 45, 0.08), 0 3px 10px rgba(23, 28, 45, 0.05);
  --shadow-active: 0 1px 2px rgba(23, 28, 45, 0.04), 0 6px 18px rgba(23, 28, 45, 0.06);
}

/* Tailwinds Preflight setzt gray-200 als Default-Border — auf die kühle,
 * weichere Border-Farbe der neuen Farbwelt umziehen. Explizite
 * border-gray-*-Klassen gewinnen weiterhin per Spezifität. */
*, ::before, ::after { border-color: var(--color-border); }

/* Tailwind-Blau-Familie → Revi-Blau. Ein Mapping statt hunderter
 * Klassen-Umbenennungen: alle bestehenden blue-600-Buttons, aktiven Tabs,
 * Avatare und Fokus-Ringe tragen damit automatisch die Markenfarbe. */
.bg-blue-600 { background-color: var(--color-accent); }
.bg-blue-500 { background-color: var(--color-accent); }
.hover\:bg-blue-700:hover { background-color: var(--color-accent-hover); }
.text-blue-600 { color: var(--color-accent); }
.text-blue-700 { color: var(--color-accent-hover); }
.bg-blue-50 { background-color: var(--color-accent-soft); }
.focus\:border-blue-500:focus { border-color: var(--color-accent); }
.focus\:ring-blue-500:focus { --tw-ring-color: var(--color-accent); }
.border-blue-500 { border-color: var(--color-accent); }
.ring-blue-400 { --tw-ring-color: var(--color-accent); }

html {
  /* Redesign: Schrift insgesamt etwas größer (Tailwind rechnet in rem —
   * ein höherer Root-Wert skaliert die ganze UI proportional mit). */
  font-size: 17px;
}

html, body {
  height: 100%;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

body { background-color: var(--color-page-bg); }

/* App-Viewport: volle Höhe. dvh statt vh, damit die iOS-Adressleiste
 * nichts abschneidet (100vh ist auf iPhone höher als der sichtbare Bereich). */
.app-viewport { height: 100vh; }
@supports (height: 100dvh) { .app-viewport { height: 100dvh; } }

/* Scroll-Lock solange die Shell gemountet ist (js/shell.js setzt die
 * Klasse): Der Body scrollt/bounct NIE — nur <main data-page-content>.
 * Ohne das zieht iOS-Safari beim Rubber-Banding das ganze Fenster samt
 * Topbar + Bottom-Tabs mit. Login/Alt-Seiten (ohne Klasse) unberührt. */
body.has-shell {
  overflow: hidden;
  overscroll-behavior: none;
  /* Fallback für ältere iOS-Versionen ohne overscroll-behavior:
   * fixierter Body kann nicht rubber-banden. Höhe kommt vom .app-viewport. */
  position: fixed;
  inset: 0;
  width: 100%;
}
body.has-shell [data-page-content] {
  /* Content-Scroll endet am Rand, statt aufs Fenster durchzuschlagen. */
  overscroll-behavior-y: contain;
  -webkit-overflow-scrolling: touch;
}

/* Karten: weiß, 14px Radius, sehr weicher Schatten — gilt für alle Panels,
 * die als weiße Karte mit Border gebaut sind. */
.bg-white.border {
  border-color: var(--color-border-soft);
  box-shadow: var(--shadow-card);
}
.rounded-lg { border-radius: 14px !important; }
.rounded-md { border-radius: 10px !important; }

/* Initial-Hide: Layout-Slot wird erst sichtbar, wenn JS gerendert hat —
 * verhindert Flash of Unstyled Content. */
[data-app-shell]:not([data-rendered]),
[data-auth-shell]:not([data-rendered]) {
  visibility: hidden;
}

/* Sanfte Scrollbar (Webkit only — okay für v1). */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb {
  background: #d1d5db;
  border-radius: 5px;
}
::-webkit-scrollbar-thumb:hover { background: #9ca3af; }
::-webkit-scrollbar-track { background: transparent; }

/* Konsistenter Fokus-Ring. */
:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
  border-radius: 4px;
}

/* Active Nav Link */
.nav-link-active {
  background-color: rgb(239 246 255); /* blue-50 */
  color: var(--color-accent);
  font-weight: 500;
}

/* ============================================================
   Button-System — konsistente Aktionen statt nackter Text-Links
   ============================================================ */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.45rem 0.9rem;
  border-radius: 999px;
  font-size: 0.82rem;
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  transition: background-color 120ms, border-color 120ms, color 120ms, transform 80ms;
  white-space: nowrap;
  border: 1px solid transparent;
  user-select: none;
}
.btn:active { transform: translateY(0.5px); }
.btn:disabled { opacity: 0.55; cursor: not-allowed; }

.btn-primary {
  background-color: var(--color-accent);
  color: white;
  box-shadow: 0 1px 3px rgba(49, 97, 222, 0.35);
}
.btn-primary:hover:not(:disabled) { background-color: var(--color-accent-hover); }

.btn-secondary {
  background-color: white;
  color: var(--color-text);
  border-color: var(--color-border);
  box-shadow: 0 1px 2px rgba(23, 28, 45, 0.04);
}
.btn-secondary:hover:not(:disabled) {
  background-color: var(--color-card-muted);
  border-color: #d3d6de;
}

.btn-ghost {
  background-color: transparent;
  color: var(--color-text-2);
}
.btn-ghost:hover:not(:disabled) {
  background-color: #e9ebf0;
  color: var(--color-text);
}

.btn-danger {
  background-color: white;
  color: rgb(194 72 61);
  border-color: rgb(244 205 200);
}
.btn-danger:hover:not(:disabled) {
  background-color: rgb(251 234 232);
  border-color: rgb(228 152 143);
}

.btn-success {
  background-color: rgb(47 163 107);
  color: white;
  box-shadow: 0 1px 3px rgba(47, 163, 107, 0.35);
}
.btn-success:hover:not(:disabled) { background-color: rgb(37 138 89); }

/* Größen */
.btn-sm { padding: 0.25rem 0.625rem; font-size: 0.75rem; }
.btn-xs { padding: 0.125rem 0.5rem; font-size: 0.7rem; gap: 0.25rem; }

/* Icon-only Quadrat-Button */
.btn-icon {
  padding: 0.375rem;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  background-color: white;
  color: var(--color-text-2);
  border: 1px solid var(--color-border);
  cursor: pointer;
  transition: background-color 120ms, color 120ms, border-color 120ms;
  font-size: 0.75rem;
  line-height: 1;
}
.btn-icon:hover:not(:disabled) {
  background-color: var(--color-card-muted);
  border-color: #d3d6de;
  color: var(--color-text);
}
.btn-icon.btn-icon-danger:hover:not(:disabled) {
  background-color: rgb(254 242 242);
  border-color: rgb(248 113 113);
  color: rgb(220 38 38);
}
.btn-icon-sm { width: 24px; height: 24px; padding: 0.25rem; }

/* Mobile Projektliste (Off-Canvas) — seit Redesign v2 hell, im Stil der
 * Desktop-Sidebar. */
.ps-light {
  background: var(--color-page-bg);
  color: var(--color-text);
}

/* Dunkle Sidebar (Projektübersicht): Icon-Buttons transparent statt weiß,
 * sonst leuchten sie auf dem Navy-Hintergrund. (Seit Redesign v2 ungenutzt,
 * bleibt als Referenz für Self-Hoster-Anpassungen.) */
.sidebar-dark .btn-icon {
  background-color: transparent;
  border-color: rgba(255, 255, 255, 0.15);
  color: rgba(255, 255, 255, 0.65);
}
.sidebar-dark .btn-icon:hover:not(:disabled) {
  background-color: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.35);
  color: #fff;
}
.sidebar-dark .btn-icon.btn-icon-danger:hover:not(:disabled) {
  background-color: rgba(248, 113, 113, 0.15);
  border-color: rgba(248, 113, 113, 0.5);
  color: rgb(252 165 165);
}
.sidebar-dark .btn-secondary {
  background-color: rgba(255, 255, 255, 0.08);
  color: #fff;
  border-color: rgba(255, 255, 255, 0.2);
}
.sidebar-dark .btn-secondary:hover:not(:disabled) {
  background-color: rgba(255, 255, 255, 0.16);
  border-color: rgba(255, 255, 255, 0.35);
}

/* Stage-Action-Toolbar (group mit subtilem Background) */
.action-toolbar {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.125rem;
  background-color: rgb(249 250 251);
  border: 1px solid rgb(229 231 235);
  border-radius: 6px;
}

/* Sidebar-Ordnerbaum: Caret dreht bei offenem <details>, Aktionen nur bei
 * Hover. Bewusst CSS statt Tailwind-group — group vererbt sich in
 * verschachtelte <details> und würde alle Carets gleichzeitig drehen. */
details[open] > summary [data-caret] { transform: rotate(90deg); }

/* WebKit/Safari rendert bei <summary> zusätzlich einen NATIVEN
 * Aufklapp-Pfeil (list-style:none reicht dort nicht) — wir haben eigene
 * Carets, der native wäre doppelt und landet im Grid-Layout sogar in
 * einer eigenen Zeile. */
summary::-webkit-details-marker { display: none; }
summary::marker { content: ''; }
/* Höhe deckeln: die 24px-Icon-Buttons dürfen die Zeile beim Einblenden
 * nicht höher machen (sichtbares Hover-Ruckeln im Ordnerbaum). Die Box ist
 * 20px hoch (= Zeilenhöhe von text-sm), die Buttons überragen sie vertikal
 * zentriert — Klickfläche bleibt voll, Layout bleibt stabil. */
summary [data-hover-actions] { display: none; height: 1.25rem; }
summary:hover [data-hover-actions] { display: inline-flex; }

/* Touch-Geräte: Hover existiert nicht — Aktionen, die sonst nur bei
 * Maus-Hover erscheinen, sind hier immer sichtbar. */
@media (hover: none) {
  summary [data-hover-actions] { display: inline-flex; }
  .touch-reveal { opacity: 1 !important; }
}

/* Stage-Kopf (Projekte): mobil als 2x2-Raster —
 *   Name + Zähler | Freigeber
 *   Aktions-Buttons | Sichtbarkeits-Pill
 * ab md die gewohnte einzeilige Flex-Leiste. */
.stage-head {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}
@media (max-width: 767px) {
  .stage-head {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "title approvers"
      "actions visibility";
    column-gap: 0.5rem;
    row-gap: 0.5rem;
    align-items: center;
  }
  .stage-head .sh-title { grid-area: title; }
  .stage-head .sh-approvers { grid-area: approvers; }
  .stage-head .sh-actions { grid-area: actions; justify-self: start; }
  .stage-head .sh-visibility { grid-area: visibility; justify-self: end; }
}

/* Review-Kopf (Desktop, js/review/layout.js + Skeleton): Titel in voller
 * Breite — er bricht um und wird nie abgeschnitten. Darunter die
 * Werkzeugleiste; die Entscheidungs-Knöpfe stehen rechts und bekommen
 * etwas Luft (row-gap), wenn sie in die nächste Zeile rutschen. */
.rv-title { overflow-wrap: anywhere; line-height: 1.3; }
.rv-tools { row-gap: 0.75rem; }

/* Review mobil: Kommentar-Spalte als hochziehbares Bottom-Sheet über den
 * Bottom-Tabs (Frame.io-Muster). Eingeklappt schaut nur die Kopfzeile
 * (3.5rem) heraus; .sheet-open fährt das Sheet komplett hoch.
 * --rt-bottom-tabs setzt js/shell.js auf die Höhe der Tab-Leiste. */
@media (max-width: 767px) {
  [data-comments-panel] {
    position: fixed;
    left: 0;
    right: 0;
    bottom: var(--rt-bottom-tabs, 0px);
    z-index: 40;
    height: 72dvh;
    border-radius: 16px 16px 0 0;
    box-shadow: 0 -10px 30px rgba(0, 0, 0, 0.18);
    transform: translateY(calc(100% - 3.5rem));
    transition: transform 0.25s ease;
  }
  [data-comments-panel].sheet-open { transform: translateY(0); }
  [data-comments-panel].sheet-open [data-sheet-chevron] { transform: rotate(180deg); }
  /* Kopfzeile ist reine Griff-/Tipp-Fläche: kein Seiten-Scroll oder
   * Safari-Geste, die das Tippen als Wischen schluckt. */
  [data-comments-panel] [data-sheet-toggle] { touch-action: none; }
  /* Kommentarliste scrollt selbst und reicht den Schwung nicht weiter. */
  [data-comments-panel] [data-comments-list] {
    overscroll-behavior: contain;
    touch-action: pan-y;
    -webkit-overflow-scrolling: touch;
  }
  /* Die Review-Seite füllt den Bildschirm genau aus — <main> muss hier
   * nicht scrollen. Als zweiter Scroll-Container um das fixed Sheet herum
   * hat iOS die Wischgeste sonst an <main> statt an die Liste gegeben. */
  [data-page-content]:has([data-comments-panel]) { overflow: hidden; }

  /* Compose-Modus (Frame.io-Muster): beim Pin-Kommentar wird die Review-
   * Spalte ein Vollbild-Overlay. position:fixed ist der Kern — iOS schiebt
   * beim Tastatur-Öffnen das Dokument hoch, ein fixed-Element bleibt stehen,
   * das Video kann also nicht mehr aus dem Bild scrollen. Kopfzeile,
   * Player-Controls und Tab-Leiste weichen solange; nur der Composer
   * (Sheet, z-40) liegt darüber, seinen Platz reserviert js/review.js
   * (syncComposeSpace) als padding-bottom. */
  body.rt-composing [data-review-col] {
    position: fixed;
    inset: 0;
    /* Bei offener Tastatur auf den sichtbaren Ausschnitt legen (Vars setzt
     * js/shell.js) — sonst hängt die Spalte am Layout-Viewport und das Bild
     * rutscht oben raus, sobald iOS den Ausschnitt verschiebt. */
    top: var(--rt-vv-top, 0px);
    bottom: auto;
    height: var(--rt-vv-h, 100dvh);
    z-index: 35; /* über Header + Tab-Leiste (z-30), unter dem Sheet (z-40) */
    margin: 0;
    padding: 8px 8px 0;
    padding-top: max(8px, env(safe-area-inset-top));
    background: #f3f4f6;
  }
  body.rt-composing [data-mobile-head],
  body.rt-composing [data-bottom-tabs],
  body.rt-composing [data-player-controls],
  body.rt-composing #rev-upload-widget { display: none; }
  [data-comments-panel].sheet-compose {
    transform: translateY(0);
    height: auto;
    max-height: 65dvh;
    bottom: 0; /* Tab-Leiste ist im Compose-Modus weg */
  }
  [data-comments-panel].sheet-compose [data-sheet-toggle],
  [data-comments-panel].sheet-compose [data-comments-list] { display: none; }
  /* Mit Tastatur bleibt auf dem iPhone wenig Höhe — zwei Zeilen reichen,
   * der Rest gehört dem Bild/Video (Feld wächst nicht, scrollt intern). */
  [data-comments-panel].sheet-compose [data-comment-input] { height: 3.25rem; }
}

/* Bottom-Sheet: Floating-Menüs/Popovers ragen auf dem Handy aus dem
 * Bildschirm — diese Klasse zieht sie stattdessen als Sheet von unten auf.
 * !important, weil die Menüs ihre Position inline (top/left/right) setzen. */
/* Abdunkelung hinter mobilen Bottom-Sheets — Fokus aufs Sheet.
 * Wird von asMobileSheet() erzeugt und automatisch mit dem Sheet entfernt. */
.mobile-sheet-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  z-index: 55; /* unter .mobile-sheet (60), über allem anderen */
}

.mobile-sheet {
  position: fixed !important;
  top: auto !important;
  left: 0 !important;
  right: 0 !important;
  bottom: 0 !important;
  width: 100% !important;
  max-height: 70vh;
  max-height: 70dvh;
  overflow: auto;
  border-radius: 16px 16px 0 0 !important;
  box-shadow: 0 -8px 30px rgba(0, 0, 0, 0.25);
  padding-bottom: calc(0.5rem + env(safe-area-inset-bottom));
  z-index: 60;
}

/* Zeichnen-Toolbar am Handy: größere Touch-Ziele, umbrechen statt überlaufen */
@media (hover: none) {
  [data-annotation-toolbar] {
    flex-wrap: wrap;
    justify-content: center;
    max-width: calc(100% - 12px);
  }
  [data-annotation-toolbar] .annot-tool { width: 2.25rem; height: 2.25rem; }
  [data-annotation-toolbar] .annot-color { width: 1.6rem; height: 1.6rem; }
  [data-annotation-toolbar] [data-action] { padding: 0.45rem 0.7rem; }
}

/* iOS zoomt in Eingabefelder mit Schrift < 16px — auf dem Handy verhindern */
@media (hover: none) and (max-width: 767px) {
  input, select, textarea { font-size: 16px !important; }
}

/* Error-Banner */
.error-banner {
  background-color: rgb(251 234 232);
  border: 1px solid rgb(238 190 183);
  color: rgb(148 55 46);
  padding: 0.75rem 1rem;
  border-radius: 10px;
  font-size: 0.875rem;
}
.success-banner {
  background-color: rgb(233 245 239);
  border: 1px solid rgb(178 222 199);
  color: rgb(30 108 72);
  padding: 0.75rem 1rem;
  border-radius: 10px;
  font-size: 0.875rem;
}

/* ============================================================
   Redesign v2 — Komponenten (Pillen, Chips, Badge, Sidebar-Shell)
   ============================================================ */

/* Status-Pillen (Review offen / Revision offen / Freigegeben) —
 * ersetzen die bg-yellow-100/red-100/green-100-Kombis in den Views. */
.rt-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 0.72rem;
  font-weight: 600;
  border-radius: 999px;
  padding: 3px 10px;
  white-space: nowrap;
}
.rt-pill::before { content: ''; width: 6px; height: 6px; border-radius: 999px; flex: none; }
.rt-pill-review   { background: #fbf2dc; color: #c08a1d; }
.rt-pill-review::before   { background: #dfa83a; }
.rt-pill-revision { background: #fbeae8; color: #c2483d; }
.rt-pill-revision::before { background: #d6483c; }
.rt-pill-approved { background: #e9f5ef; color: #257a52; }
.rt-pill-approved::before { background: #2fa36b; }
.rt-pill-neutral  { background: #eceef3; color: #5f6472; }
.rt-pill-neutral::before  { background: #9ba0ad; }

/* Zähler-Pille (Listen-Header) */
.rt-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  border-radius: 999px;
  padding: 0 7px;
  font-size: 0.7rem;
  font-weight: 600;
  background: #eef0f4;
  color: var(--color-text-2);
  font-variant-numeric: tabular-nums;
}
.rt-count-amber { background: #fbf2dc; color: #c08a1d; }
.rt-count-red   { background: #fbeae8; color: #c2483d; }

/* Icon-Chips (Stat-Karten, Kunden-Initialen) */
.rt-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  flex: none;
  font-weight: 650;
}
.rt-chip-blue   { background: var(--color-accent-soft); color: var(--color-accent); }
.rt-chip-red    { background: #fbeae8; color: #c2483d; }
.rt-chip-green  { background: #e9f5ef; color: #2fa36b; }
.rt-chip-amber  { background: #fbf2dc; color: #c08a1d; }
.rt-chip-violet { background: #efedfb; color: #7c6bd6; }
.rt-chip-gray   { background: #eceef3; color: var(--color-text-2); }

/* Glossy Notification-Badge (Sidebar) — Farbverlauf mit Glanzpunkt,
 * dunklerem Rand und weichem Schlagschatten. */
.rt-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 21px;
  height: 21px;
  border-radius: 999px;
  padding: 0 6px;
  color: #fff;
  font-size: 0.68rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  background: radial-gradient(120% 120% at 30% 20%, #5585f4 0%, #3161de 55%, #2748b4 100%);
  box-shadow: 0 2px 6px rgba(43, 80, 197, 0.45),
    inset 0 1px 1px rgba(255, 255, 255, 0.35),
    inset 0 -1px 2px rgba(20, 40, 110, 0.35);
}

/* Muted Kartenfuß (Stat-Karten) */
.rt-card-foot {
  display: flex;
  align-items: center;
  gap: 6px;
  border-top: 1px solid var(--color-border-soft);
  background: #fbfcfe;
  padding: 7px 16px;
  font-size: 0.72rem;
  color: var(--color-text-2);
}

/* ---------- Globale Sidebar (Shell, Desktop) ---------- */
/* Drei Zonen: .gs-top fix, .gs-scroll (Kunden & Projekte) scrollt intern,
 * .gs-bottom fix. Die Sidebar selbst scrollt nie. */
/* display kommt aus dem Markup (hidden md:flex) — app.css lädt nach
 * tailwind.css und würde `hidden` sonst überstimmen. */
.gs-sidebar {
  position: relative;
  width: 264px;
  flex: none;
  flex-direction: column;
  background: var(--color-page-bg);
  border-right: 1px solid var(--color-border);
  padding: 14px 12px 12px;
  overflow: hidden;
}
/* Vom Nutzer ausgeblendet (Toggle in der Kopfzeile) — !important, weil
 * md:flex im Markup sonst gewinnt. Slim-Topbar zeigt dann den Öffnen-Knopf. */
.gs-sidebar.gs-side-hidden { display: none !important; }
/* Breiten-Griff an der rechten Kante (Drag = Breite ändern, persistiert) */
.gs-resizer {
  position: absolute;
  top: 0;
  right: -3px;
  width: 7px;
  height: 100%;
  cursor: col-resize;
  z-index: 10;
  touch-action: none;
}
.gs-resizer:hover, .gs-resizer.gs-resizing { background: rgba(49, 97, 222, 0.18); }

/* Kunden-Baum: Hover-Aktionen reservieren ihren Platz PERMANENT
 * (visibility statt display) — beim Drüberfahren verschiebt sich nichts,
 * weder vertikal noch horizontal. Überschreibt die generische
 * summary-Hover-Regel weiter oben. */
.gs-sidebar summary [data-hover-actions] {
  display: inline-flex;
  visibility: hidden;
  height: 22px;
  align-items: center;
}
.gs-sidebar summary:hover [data-hover-actions] { display: inline-flex; visibility: visible; }
@media (hover: none) {
  .gs-sidebar summary [data-hover-actions] { visibility: visible; }
}

/* Slim-Topbar (Desktop): Seitentitel links, Glocke rechts. */
.gs-slimbar {
  align-items: center;
  gap: 10px;
  padding: 10px 22px;
  border-bottom: 1px solid var(--color-border-soft);
  background: var(--color-main-bg);
}
.gs-main { background: var(--color-main-bg); }
.gs-top { flex: none; }
.gs-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: none;
  padding-bottom: 8px;
}
.gs-scroll::-webkit-scrollbar { display: none; }
.gs-bottom { flex: none; padding-top: 4px; }

.gs-label {
  display: flex;
  align-items: center;
  font-size: 0.8rem;
  font-weight: 500;
  color: #6e7380;
  padding: 15px 10px 8px;
}
.gs-label .gs-label-acts { margin-left: auto; display: flex; gap: 2px; }

.gs-item {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 11px;
  border-radius: 13px;
  margin-bottom: 2px;
  color: #3e4350;
  font-size: 0.86rem;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  user-select: none;
}
.gs-item:hover { background: #e9ebf0; }
.gs-item.gs-active {
  background: #fff;
  color: var(--color-text);
  font-weight: 600;
  box-shadow: var(--shadow-active);
}
.gs-item svg { color: #7e8492; }
.gs-item.gs-active svg { color: var(--color-text); }
.gs-item .rt-badge { margin-left: auto; }

.gs-sep {
  border: none;
  border-top: 1px solid var(--color-border);
  margin: 12px -12px 0;
  flex: none;
}

.gs-tree-group {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 11px;
  border-radius: 13px;
  cursor: pointer;
  margin-top: 2px;
  user-select: none;
}
.gs-tree-group:hover { background: #e9ebf0; }
.gs-tree-group b {
  font-size: 0.85rem;
  font-weight: 600;
  color: #3e4350;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gs-tree-group [data-tree-caret] { transition: transform 120ms; color: var(--color-text-muted); }
.gs-tree-group.gs-collapsed [data-tree-caret] { transform: rotate(-90deg); }

.gs-tree-kids {
  margin: 1px 2px 6px 22px;
  padding-left: 12px;
  border-left: 1px solid var(--color-border);
}
.gs-tree-proj {
  display: flex;
  align-items: center;
  padding: 8px 11px;
  border-radius: 12px;
  margin-bottom: 1px;
  font-size: 0.82rem;
  font-weight: 500;
  color: #4e5361;
  cursor: pointer;
  user-select: none;
}
.gs-tree-proj:hover { background: #e9ebf0; }
.gs-tree-proj.gs-active {
  background: #fff;
  color: var(--color-text);
  font-weight: 600;
  box-shadow: var(--shadow-active);
}
.gs-tree-proj span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.gs-mini {
  width: 26px;
  height: 26px;
  border-radius: 8px;
  border: none;
  background: none;
  color: #aeb2bd;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
}
.gs-mini:hover { background: #e7e9ef; color: var(--color-text-2); }

.gs-me {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 13px;
  cursor: pointer;
}
.gs-me:hover { background: #e9ebf0; }

/* ============ Globales Upload-Widget (js/upload-widget.js) ============
 * Karte unten rechts auf document.body — überlebt SPA-Navigation. Auf dem
 * Handy sitzt sie über den Bottom-Tabs (--rt-bottom-tabs aus shell.js). */
#rev-upload-widget {
  position: fixed;
  right: 14px;
  bottom: calc(var(--rt-bottom-tabs, 0px) + 14px);
  width: min(320px, calc(100vw - 28px));
  background: #fff;
  border: 1px solid var(--color-border);
  border-radius: 14px;
  box-shadow: var(--shadow-pill);
  z-index: 45; /* über Inhalt, unter Floating-Menüs (z-50) */
  overflow: hidden;
}
#rev-upload-widget .uw-head {
  padding: 8px 12px 6px;
  font-size: 12px;
  font-weight: 600;
  color: var(--color-text-2);
  border-bottom: 1px solid var(--color-border-soft);
}
#rev-upload-widget .uw-rows {
  max-height: 40vh;
  overflow-y: auto;
}
.uw-row {
  padding: 8px 12px 10px;
  border-bottom: 1px solid var(--color-border-soft);
}
.uw-row:last-child { border-bottom: none; }
.uw-line {
  display: flex;
  align-items: center;
  gap: 8px;
}
.uw-dir {
  flex: none;
  width: 12px;
  height: 12px;
  color: var(--color-text-muted);
}
.uw-name {
  flex: 1;
  min-width: 0;
  font-size: 12px;
  font-weight: 500;
  color: var(--color-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.uw-status {
  flex: none;
  font-size: 12px;
  font-weight: 600;
  color: var(--color-accent);
  font-variant-numeric: tabular-nums;
}
.uw-row[data-uw-state="done"] .uw-status { color: #16a34a; }
.uw-row[data-uw-state="error"] .uw-status { color: #dc2626; }
.uw-row[data-uw-state="cancelled"] .uw-status { color: var(--color-text-muted); }
.uw-x {
  flex: none;
  width: 22px;
  height: 22px;
  border: none;
  background: none;
  border-radius: 6px;
  color: var(--color-text-muted);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}
.uw-x:hover { background: var(--color-card-muted); color: #dc2626; }
.uw-x svg { width: 13px; height: 13px; }
/* Retry (↻) nur in fehlgeschlagenen Zeilen sichtbar */
.uw-retry { display: none; }
.uw-row[data-uw-state="error"] .uw-retry { display: inline-flex; }
.uw-retry:hover { background: var(--color-card-muted); color: #2563eb; }
.uw-bar {
  margin-top: 6px;
  height: 4px;
  border-radius: 999px;
  background: var(--color-border-soft);
  overflow: hidden;
}
.uw-fill {
  height: 100%;
  border-radius: 999px;
  background: var(--color-accent);
  transition: width 0.3s ease;
}
.uw-meta {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  margin-top: 4px;
  font-size: 11px;
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}
.uw-meta[hidden] { display: none; }
.uw-row[data-uw-state="done"] .uw-fill { background: #16a34a; }
.uw-row[data-uw-state="error"] .uw-fill { background: #dc2626; }
.uw-row[data-uw-state="cancelled"] .uw-fill { background: var(--color-text-muted); }

/* Versionsvergleich (js/review/compare.js): Seite darunter nicht scrollen */
body.rt-compare-open { overflow: hidden; }

/* Tastenkürzel-Übersicht (js/shell/shortcuts.js) */
.rt-kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  height: 22px;
  padding: 0 6px;
  border: 1px solid var(--color-border);
  border-bottom-width: 2px;
  border-radius: 6px;
  background: var(--color-card-muted);
  color: var(--color-text);
  font: 600 11px/1 ui-sans-serif, system-ui, sans-serif;
}

/* ==========================================================================
 * Skeletons (js/skeletons.js)
 * Beim ersten, kalten Aufruf einer View steht sofort die echte Seitenhülle:
 * Überschriften, Buttons, Stage-Köpfe — alles, was aus Profil/Cache schon
 * bekannt ist. Nur unbekannte Daten schimmern. Der Router malt das Skeleton
 * vor dem Modul-Import, die Views zeigen dieselben Bausteine statt „Lädt…".
 * ======================================================================== */

/* Schimmernder Platzhalter-Block. Größe über Tailwind-Utilities (h-4 w-40). */
.sk {
  display: block;
  position: relative;
  overflow: hidden;
  border-radius: 6px;
  background: #e7e9ee;
  flex: none;
}
.sk-round { border-radius: 999px; }
.sk-flat { border-radius: 0; }
.sk-input { height: 38px; }
.sk::after {
  content: '';
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.65) 50%, transparent 100%);
  animation: sk-shimmer 1.6s ease-in-out infinite;
}
/* Dunkle Fläche (Player-Bühne): Schimmer bleibt dezent. */
.sk-dark { background: #1f2329; }
.sk-dark::after { background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.08), transparent); }

/* Bekannte, aber noch nicht bedienbare Elemente (Buttons, Menüs): sehen aus
 * wie echt, reagieren nicht. Gedimmt werden sie über das disabled-Attribut
 * (.btn:disabled) — nicht über die Klasse, denn .sk-view bleibt an
 * Listen-Containern hängen, die später echte Buttons tragen. */
[data-sk-static] { pointer-events: none; user-select: none; }

/* Kein Flackern bei warmem Cache: das Skeleton wird erst nach 120 ms
 * sichtbar. Ist die View bis dahin da, sieht niemand ein Skeleton. */
.sk-view {
  animation: sk-reveal 0.15s ease-out 0.12s both;
}
@keyframes sk-shimmer { to { transform: translateX(100%); } }
@keyframes sk-reveal { from { opacity: 0; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .sk::after { animation: none; }
  .sk-view { animation: none; }
}
