/* =========================================================================
   SecondBrain — Gestaltung der LibreChat-Anmeldeseite ("Nebel")
   Angelegt 11.09.2026.

   WOZU. LibreChat hat fuer die Anmeldeseite keinen Konfigurations-Slot:
   weder fuer Ueberschrift noch fuer Untertitel, Farben oder Layout. Der
   interface:-Block der librechat.yaml kennt nur agents, marketplace,
   bookmarks, presets und parameters — nichts davon betrifft /login. Alles
   Gestalterische geht deshalb ueber diese Datei.

   WIE SIE INS BILD KOMMT. Ueber einen eigenen Mount auf
   dist/assets/secondbrain-login.css und eine <link>-Zeile, die
   patch-index.py in die index.html schreibt. NICHT von Hand eintragen:
   patch-index.py erzeugt die index.html bei jedem Lauf komplett neu aus
   der Image-Vorlage, eine handgeschriebene Zeile waere beim naechsten
   "docker compose pull" still verschwunden.

   KEIN NEUES MARKUP. Jede Regel arbeitet auf dem Markup, das der fertige
   Client ausliefert. Die Selektoren sind am Bundle nachgelesen
   (assets/index.<hash>.js, Komponente AuthLayout und das Login-Formular),
   nicht geraten.

   ZWEI FALLEN, DIE HIER SCHON ZUGESCHLAGEN HABEN:

   1. Diese Datei wird auf JEDER Seite geladen, nicht nur auf /login — die
      index.html ist die der ganzen Anwendung. Darum haengt jede Regel an
      :has(.w-authPageWidth). Diese Klasse (width:370px) vergibt LibreChat
      ausschliesslich an die Auth-Karte. Ohne diese Klammer wuerde die
      Rasterregel auch das Chatfenster umbauen.

   2. Tailwind-Utilities haben Spezifitaet (0,1,0), ein blosses "main h1"
      nur (0,0,2) — und verliert. Jede Regel hier ist deshalb an eine
      Klasse verankert. Wo LibreChat mit peer-Varianten arbeitet
      (Spezifitaet (0,3,0)), wird seine Mechanik NICHT ersetzt, sondern
      nur umgefaerbt; siehe den Abschnitt Eingabefelder.
   ========================================================================= */

:root{
  --sb-green:4 120 87;        /* green-700    — die vorhandene Buttonfarbe */
  --sb-green-deep:6 95 70;    /* green-800                                */
  --sb-petrol:18 110 107;     /* accent-primary hell, war schon im System */
  --sb-petrol-lit:65 167 157; /* accent-primary dunkel                    */
  --sb-navy:1 9 26;           /* Grund der Logokachel                     */
  --sb-warm:181 129 78;       /* ergaenzt: gedecktes Messing              */
  --sb-ground:12 56 58;       /* Petrol-Grund, helles Thema               */
  --sb-panel:max(420px,46%);  /* Breite der Formularspalte — eine Zahl,   */
                              /* zwei Stellen: Raster und Panelflaeche.   */
  --sb-feld:249 250 250;      /* Fuellung der Eingabefelder — DECKEND,    */
                              /* Begruendung im Abschnitt Eingabefelder.  */
  --sb-fehler:185 28 28;      /* red-700                                  */
}
html.dark{
  --sb-ground:1 9 26;
  --sb-feld:24 29 36;
  --sb-fehler:248 113 113;    /* red-400 — auf dunklem Grund lesbar       */
}

/* --- Farbebene 1: die drei tragenden Felder ----------------------------
   Bewegt wird ausschliesslich die background-position; die Felder selbst
   haben keine Kante. Zwei Ebenen mit teilerfremden Laufzeiten (26 s und
   34 s, je alternierend) — die Gesamtstellung kehrt erst nach gut zwoelf
   Minuten wieder, es gibt also keine wahrnehmbare Wiederholung.        */
body:has(.w-authPageWidth){background-color:rgb(var(--sb-ground))}
body:has(.w-authPageWidth)::before{
  content:'';position:fixed;inset:0;pointer-events:none;
  background-repeat:no-repeat;
  background-image:
    radial-gradient(circle at 50% 50%, rgba(4,120,87,.92)   0%, rgba(4,120,87,0)   64%),
    radial-gradient(circle at 50% 50%, rgba(18,110,107,.88) 0%, rgba(18,110,107,0) 62%),
    radial-gradient(circle at 50% 50%, rgba(1,9,26,.78)     0%, rgba(1,9,26,0)     66%);
  background-size:96% 92%, 88% 100%, 104% 96%;
  background-position:12% 24%, 70% 14%, 42% 88%;
  filter:blur(22px);
  animation:sb-mesh-1 26s ease-in-out infinite alternate;
}

/* --- Farbebene 2: Aufhellung und der warme Akzent ---------------------- */
#root:has(.w-authPageWidth)::before{
  content:'';position:fixed;inset:0;pointer-events:none;
  background-repeat:no-repeat;
  background-image:
    radial-gradient(circle at 50% 50%, rgba(65,167,157,.40) 0%, rgba(65,167,157,0) 60%),
    radial-gradient(circle at 50% 50%, rgba(181,129,78,.32) 0%, rgba(181,129,78,0) 58%);
  background-size:72% 76%, 62% 58%;
  background-position:30% 66%, 78% 40%;
  filter:blur(26px);
  animation:sb-mesh-2 34s ease-in-out infinite alternate;
}
html.dark #root:has(.w-authPageWidth)::before{
  background-image:
    radial-gradient(circle at 50% 50%, rgba(65,167,157,.30) 0%, rgba(65,167,157,0) 60%),
    radial-gradient(circle at 50% 50%, rgba(181,129,78,.24) 0%, rgba(181,129,78,0) 58%);
}

@keyframes sb-mesh-1{
    0%{background-position:12% 24%, 70% 14%, 42% 88%}
   30%{background-position:26% 10%, 56% 32%, 24% 74%}
   62%{background-position: 6% 40%, 80% 20%, 58% 94%}
  100%{background-position:20% 28%, 62%  6%, 34% 78%}
}
@keyframes sb-mesh-2{
    0%{background-position:30% 66%, 78% 40%}
   40%{background-position:16% 48%, 62% 60%}
  100%{background-position:40% 76%, 86% 28%}
}

/* --- Raster --------------------------------------------------------------
   Der AuthLayout-Container ist im Original ein Flex-Stapel: Logoblock
   (mt-6 h-10 = 64 px) im Fluss, darunter main mit flex-grow. Das zentriert
   das Formular in dem, was nach dem Logo uebrig bleibt — 32 px unterhalb
   der Fenstermitte, und der Logoblock klebt oben am Rand.

   Hier wird daraus ein Raster. Ab 900 px hat es vier Zeilen
   (1fr auto auto 1fr): Logo und Formular sitzen in den beiden mittleren
   und werden dadurch GEMEINSAM zentriert — ohne eine einzige feste
   Verschiebung in Pixeln, die beim naechsten Schriftwechsel nicht mehr
   passt.
   ------------------------------------------------------------------------ */
.min-h-screen.flex-col:has(.w-authPageWidth){
  display:grid;
  grid-template-columns:1fr;
  grid-template-rows:auto 1fr;
  background:transparent;
  isolation:isolate;
  position:relative;
  z-index:1;
}

/* Stapelordnung, bewusst gesetzt statt der DOM-Reihenfolge ueberlassen:
       body::before    Farbebene 1        (fixed, ohne z-index)
       #root::before   Farbebene 2        (fixed, ohne z-index)
       body::after     Formularspalte     z-index 0
       .min-h-screen   AuthLayout         z-index 1, isolate
         ::after       Grain              z-index 2
         Karte                            z-index 3
         Logo                             z-index 4
         Fusszeile                        z-index 5
   Das Grain liegt damit ueber Farbe und Spalte, aber UNTER der Karte —
   sonst liegt Korn auf dem Text, den jemand lesen soll. */

.min-h-screen.flex-col:has(.w-authPageWidth) > .mt-6{
  grid-column:1;grid-row:1;z-index:4;
  margin-top:0;height:auto;width:auto;
  align-self:end;justify-self:center;
  padding-top:clamp(2.5rem,9vh,5.5rem);
  padding-bottom:1.75rem;
}
.min-h-screen.flex-col:has(.w-authPageWidth) > .mt-6 img{
  height:58px;width:58px;border-radius:15px;
  box-shadow:0 12px 32px -14px rgba(1,9,26,.6);
}
/* Bei isFetching wickelt LibreChat den Logoblock in einen zusaetzlichen
   div.animate-logo-blink. Dann ist NICHT .mt-6 das Rasterkind, sondern
   der Wrapper — sonst faellt das Logo waehrend des Ladens aus dem Raster. */
.min-h-screen.flex-col:has(.w-authPageWidth) > .animate-logo-blink{
  grid-column:1;grid-row:1;z-index:4;
  align-self:end;justify-self:center;
}
.min-h-screen.flex-col:has(.w-authPageWidth) > .animate-logo-blink > .mt-6{
  margin-top:0;height:auto;width:auto;
  padding-top:clamp(2.5rem,9vh,5.5rem);padding-bottom:1.75rem;
}
.min-h-screen.flex-col:has(.w-authPageWidth) > .animate-logo-blink img{
  height:58px;width:58px;border-radius:15px;
  box-shadow:0 12px 32px -14px rgba(1,9,26,.6);
}

.min-h-screen.flex-col:has(.w-authPageWidth) > main{
  grid-column:1;grid-row:2;
  align-items:start;
  position:relative;     /* ohne z-index: erzeugt KEINEN eigenen Stapel- */
}                        /* kontext, die Karte bleibt damit auf Ebene 3  */

@media (min-width:900px){
  .min-h-screen.flex-col:has(.w-authPageWidth){
    grid-template-columns:1fr var(--sb-panel);
    grid-template-rows:1fr auto auto 1fr;
  }
  .min-h-screen.flex-col:has(.w-authPageWidth) > .mt-6,
  .min-h-screen.flex-col:has(.w-authPageWidth) > .animate-logo-blink{
    grid-column:2;grid-row:2;align-self:end;padding-top:0;
  }
  .min-h-screen.flex-col:has(.w-authPageWidth) > .animate-logo-blink > .mt-6{
    padding-top:0;
  }
  .min-h-screen.flex-col:has(.w-authPageWidth) > main{
    grid-column:2;grid-row:3;align-self:start;
  }

  /* Die Formularspalte: eine durchgehende Milchglasscheibe ueber der
     Farbe. Sie ist es, die das Thema traegt — die Farbflaeche links
     bleibt in hell wie dunkel dieselbe, nur die Arbeitsseite kippt. */
  body:has(.w-authPageWidth)::after{
    content:'';position:fixed;top:0;right:0;bottom:0;
    width:var(--sb-panel);z-index:0;pointer-events:none;
    background:rgba(252,253,253,.90);
    backdrop-filter:blur(24px) saturate(120%);
    -webkit-backdrop-filter:blur(24px) saturate(120%);
    box-shadow:inset 1px 0 0 rgba(255,255,255,.5),
               -44px 0 90px -44px rgba(1,9,26,.5);
  }
  html.dark body:has(.w-authPageWidth)::after{
    background:rgba(10,14,20,.86);
    box-shadow:inset 1px 0 0 rgba(255,255,255,.06),
               -44px 0 90px -44px rgba(0,0,0,.75);
  }
}

/* --- Formularkarte ------------------------------------------------------ */
main > .w-authPageWidth{
  position:relative;z-index:3;
  width:min(400px,calc(100vw - 2.5rem));
  max-width:400px;
  padding:2.25rem 2rem 2rem;
  border-radius:20px;
  overflow:visible;
  background:rgba(255,255,255,.86);
  border:1px solid rgba(255,255,255,.55);
  box-shadow:0 26px 64px -30px rgba(1,9,26,.5),
             0 2px 6px -2px rgba(1,9,26,.12);
  backdrop-filter:blur(18px) saturate(135%);
  -webkit-backdrop-filter:blur(18px) saturate(135%);
}
html.dark main > .w-authPageWidth{
  background:rgba(13,18,24,.78);
  border-color:rgba(255,255,255,.10);
  box-shadow:0 30px 72px -32px rgba(0,0,0,.78),
             0 2px 6px -2px rgba(0,0,0,.4);
}
@media (min-width:900px){
  /* Auf der Scheibe braucht die Karte keinen zweiten Glaseffekt: Glas auf
     Glas liest sich als Schmutz. */
  main > .w-authPageWidth{
    background:transparent;border-color:transparent;box-shadow:none;
    backdrop-filter:none;-webkit-backdrop-filter:none;
    padding:0;width:min(370px,calc(100vw - 2.5rem));
  }
}

/* --- Ueberschrift und die zwei Zeilen darunter --------------------------
   Einen Untertitel gibt es im AuthLayout nicht als Element — die h1 ist
   das einzige Textfeld, und ihr Inhalt kommt aus einer fest verdrahteten
   Route-Map im Bundle ({"/login": "com_auth_welcome_back"}). Die zweite
   und dritte Zeile entstehen deshalb per ::after.
   Neutral gehalten, ohne Praxisnamen: die Seite ist oeffentlich
   erreichbar, jeder kann sie lesen.                                      */
main .w-authPageWidth h1{
  margin-bottom:0;
  font-size:1.5rem;line-height:1.95rem;letter-spacing:-.012em;
  font-weight:600;
}
main .w-authPageWidth h1::after{
  content:"Interner Wissensassistent\A Bitte mit den Praxiszugangsdaten anmelden.";
  display:block;white-space:pre-line;
  margin-top:.6rem;
  font-size:.875rem;line-height:1.5;font-weight:400;letter-spacing:0;
  color:rgb(var(--text-secondary));
}
main .w-authPageWidth form{margin-top:1.9rem}

/* --- Eingabefelder ------------------------------------------------------
   LibreChats Floating-Label bleibt UNANGETASTET. Es arbeitet ueber
   peer-Varianten (.peer:placeholder-shown ~ .peer-placeholder-shown\:…),
   Spezifitaet (0,3,0); es umzubauen haette !important auf einem halben
   Dutzend Eigenschaften gebraucht und waere beim naechsten LibreChat-
   Update als Erstes gebrochen.

   WARUM DIE FUELLUNG DECKEND IST — das hat einen Vorfall hinter sich.
   Beide Felder tragen die Klasse .webkit-dark-styles:

       .webkit-dark-styles, .webkit-dark-styles:focus{
         background-clip:content-box;
         -webkit-box-shadow:inset 0 0 0 50vh #fff }

   Der 50vh grosse inset-Schatten ist LibreChats GANZER Autofill-Schutz;
   eine eigene :-webkit-autofill-Regel gibt es im Bundle-CSS nicht. Er
   fuellt das Feld deckend weiss und uebermalt damit, was Chrome bei
   gespeicherten Zugangsdaten sonst gelb hinterlegt.

   Am 11.09.2026 hat die erste Fassung dieser Datei genau diesen Schatten
   im Fokus ueberschrieben — mit dem Fokusring, der ja auch ein box-shadow
   ist. Was uebrig blieb, war der eigene Hintergrund, den
   background-clip:content-box nur noch im INNEREN malt: ohne Padding,
   ohne Rundung. Das Feld wurde beim Anklicken zum eckigen weissen Kasten,
   das Nachbarfeld blieb rund. Und der Autofill-Schutz war still mit weg.

   Darum hier: background-clip zurueck auf border-box, der fremde Schatten
   wird abgeschaltet statt versehentlich verdraengt, die Fuellung ist eine
   eigene deckende Farbe — und der Autofill-Fall bekommt eine eigene
   Regel, die Ring UND Fuellung in einem box-shadow zusammenfasst.

   Deckend hat einen zweiten Grund: das Label stanzt den Feldrand aus, auf
   dem es sitzt. Mit einer durchscheinenden Fuellung gibt es keine Farbe,
   mit der sich etwas ausstanzen laesst — es bliebe ein Kaestchen im Feld
   stehen.
   ------------------------------------------------------------------------ */
main .w-authPageWidth form input{
  height:3rem;
  /* links 1.25rem: start-3 (.75) + px-2 (.5) des Labels. So beginnt der
     eingegebene Text an derselben Kante wie der Platzhaltertext. */
  padding:0 1.25rem;
  border-radius:14px;
  border:1px solid rgba(var(--sb-navy),.16);
  background-color:rgb(var(--sb-feld));
  background-clip:border-box;   /* .webkit-dark-styles setzt content-box  */
  box-shadow:none;              /* dessen inset-Fuellung hier abschalten  */
  color:rgb(var(--text-primary));
  font-size:1rem;
  transition:border-color .18s ease,box-shadow .18s ease;
}
/* Die kritischen Eigenschaften stehen hier NOCH EINMAL, obwohl sie oben
   schon gesetzt sind. Das ist kein Versehen: ".dark .webkit-dark-styles"
   hat Spezifitaet (0,2,0) und schlaegt damit die Grundregel oben (0,1,3).
   Erst dieser Block kommt mit (0,2,3) darueber. Wer hier etwas streicht,
   holt im dunklen Thema den eckigen Kasten zurueck. */
html.dark main .w-authPageWidth form input{
  border-color:rgba(255,255,255,.14);
  background-color:rgb(var(--sb-feld));
  background-clip:border-box;
  box-shadow:none;
  -webkit-text-fill-color:rgb(var(--text-primary));
}
/* Platz fuer den Sichtbarkeitsknopf. Nicht ueber [type=password] gehen:
   sobald jemand das Auge drueckt, wird der Typ "text" und die Regel
   faellt weg — der Text liefe dann unter den Knopf. */
main .w-authPageWidth form input#password,
main .w-authPageWidth form input[autocomplete="current-password"]{
  padding-right:3.25rem;
}

/* Zeigen statt verschwinden: im Ruhezustand zurueckhaltend, beim
   Ueberfahren etwas deutlicher, im Fokus in der Akzentfarbe. */
main .w-authPageWidth form input:hover{
  border-color:rgba(var(--sb-navy),.30);
}
html.dark main .w-authPageWidth form input:hover{
  border-color:rgba(255,255,255,.26);
}
main .w-authPageWidth form input:focus{
  outline:none;
  border-color:rgb(var(--sb-petrol));
  background-color:rgb(var(--sb-feld));   /* ausdruecklich gleich wie Ruhe */
  background-clip:border-box;
  box-shadow:0 0 0 3px rgba(var(--sb-petrol),.16);
}
html.dark main .w-authPageWidth form input:focus{
  border-color:rgb(var(--sb-petrol-lit));
  background-color:rgb(var(--sb-feld));
  background-clip:border-box;          /* gegen .dark .webkit-dark-styles:focus */
  box-shadow:0 0 0 3px rgba(var(--sb-petrol-lit),.18);
  -webkit-text-fill-color:rgb(var(--text-primary));
}

/* Autofill. Chrome faerbt gespeicherte Zugangsdaten eigenmaechtig ein und
   laesst sich nur ueber einen deckenden inset-Schatten uebermalen. Der
   Fokusring muss im SELBEN box-shadow stehen, sonst verdraengt eines das
   andere — genau der Fehler, der oben beschrieben ist. */
main .w-authPageWidth form input:-webkit-autofill,
main .w-authPageWidth form input:-webkit-autofill:hover{
  -webkit-box-shadow:inset 0 0 0 50vh rgb(var(--sb-feld));
  -webkit-text-fill-color:rgb(var(--text-primary));
  caret-color:rgb(var(--text-primary));
  background-clip:border-box;
  border-radius:14px;
}
main .w-authPageWidth form input:-webkit-autofill:focus{
  -webkit-box-shadow:inset 0 0 0 50vh rgb(var(--sb-feld)),
                     0 0 0 3px rgba(var(--sb-petrol),.16);
}
html.dark main .w-authPageWidth form input:-webkit-autofill,
html.dark main .w-authPageWidth form input:-webkit-autofill:hover{
  background-clip:border-box;
  -webkit-text-fill-color:rgb(var(--text-primary));
}
html.dark main .w-authPageWidth form input:-webkit-autofill:focus{
  background-clip:border-box;
  -webkit-text-fill-color:rgb(var(--text-primary));
  -webkit-box-shadow:inset 0 0 0 50vh rgb(var(--sb-feld)),
                     0 0 0 3px rgba(var(--sb-petrol-lit),.18);
}

/* Fehlerzustand. LibreChat setzt aria-invalid, gestaltet es aber nicht —
   im Bundle-CSS gibt es dazu keine einzige Regel. Sichtbar ist der Fehler
   bisher nur an der Textmeldung unter dem Feld. */
main .w-authPageWidth form input[aria-invalid="true"]{
  border-color:rgba(var(--sb-fehler),.7);
}
main .w-authPageWidth form input[aria-invalid="true"]:focus{
  border-color:rgb(var(--sb-fehler));
  background-clip:border-box;
  box-shadow:0 0 0 3px rgba(var(--sb-fehler),.16);
}
html.dark main .w-authPageWidth form input[aria-invalid="true"]{
  border-color:rgba(var(--sb-fehler),.75);
}
html.dark main .w-authPageWidth form input[aria-invalid="true"]:focus{
  border-color:rgb(var(--sb-fehler));   /* sonst gewinnt der Petrol-Rand */
  background-clip:border-box;
  box-shadow:0 0 0 3px rgba(var(--sb-fehler),.2);
}

/* Das Label traegt dieselbe Farbe wie die Fuellung: im Ruhezustand steht
   es IM Feld und verschwindet darin, angehoben stanzt es den Rand aus. */
main .w-authPageWidth form label{
  background-color:rgb(var(--sb-feld));
  border-radius:4px;
}

/* Fokus fuer alles, was kein Eingabefeld ist. */
main .w-authPageWidth a:focus-visible,
main .w-authPageWidth button:focus-visible{
  outline:none;border-radius:14px;
  box-shadow:0 0 0 3px rgba(var(--sb-petrol),.3);
}
html.dark main .w-authPageWidth a:focus-visible,
html.dark main .w-authPageWidth button:focus-visible{
  box-shadow:0 0 0 3px rgba(var(--sb-petrol-lit),.3);
}

/* --- Knopf: die vorhandene Farbe bleibt die Hauptfarbe der Seite ------- */
main .w-authPageWidth form button[type=submit]{
  height:3rem;margin-top:1.6rem;border:0;border-radius:14px;
  background:linear-gradient(180deg,
             rgb(var(--sb-green)) 0%, rgb(var(--sb-green-deep)) 100%);
  box-shadow:0 12px 26px -14px rgba(var(--sb-green-deep),.85);
  transition:filter .18s ease,box-shadow .18s ease,transform .1s ease;
}
main .w-authPageWidth form button[type=submit]:hover{filter:brightness(1.08)}
main .w-authPageWidth form button[type=submit]:active{transform:translateY(1px)}

/* --- Grain --------------------------------------------------------------
   Nimmt der Farbflaeche das Sterile: aus Farbe wird Material. SVG-Rauschen
   als Data-URI — kein externer Aufruf, kein Bild, kein Fremdskript. Die
   Anmeldeseite ist oeffentlich erreichbar und gehoert zu einem System mit
   Patientendaten; hier wird nichts nachgeladen.                          */
.min-h-screen.flex-col:has(.w-authPageWidth)::after{
  content:'';position:absolute;inset:0;z-index:2;pointer-events:none;
  opacity:.15;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:180px 180px;
}
html.dark .min-h-screen.flex-col:has(.w-authPageWidth)::after{
  opacity:.19;mix-blend-mode:soft-light;
}

/* Fusszeile (Theme-Umschalter) bleibt unten links, aber ueber der Farbe. */
.min-h-screen.flex-col:has(.w-authPageWidth) > .absolute.bottom-0.left-0{
  z-index:5;margin:1rem;
}

/* Ohne Bewegung bleibt der Verlauf stehen — es verschwindet nichts,
   nur die Zeit. */
@media (prefers-reduced-motion:reduce){
  body:has(.w-authPageWidth)::before,
  #root:has(.w-authPageWidth)::before{animation:none}
}
