/* Login-Seite app.tappr.ch — "Vor dem Öffnen".
 *
 * Eigene Handschrift, bewusst anders als die Admin-Eingangstuer: hell, warm,
 * grosszuegig, ein Bild aus dem Lokal statt aus dem Leitstand.
 *
 * WICHTIG — Theme:
 * Diese Seite steht FEST auf hell (data-theme="light" hart im HTML, kein
 * theme.js, kein localStorage-Bootstrap). Die Hell/Dunkel-Wahl aus dem
 * Backoffice darf die Eingangstuer nicht umfaerben. Flaechen sind zusaetzlich
 * als feste Hex-Werte gesetzt — siehe Memory "Inverse Surfaces dark-safe".
 *
 * Klassen-Prefix .lo-* damit nichts mit den .auth-*-Styles aus app.css
 * kollidiert, die die anderen Auth-Seiten weiterverwenden.
 */

:root {
  --lo-cream: #FAF7F1;
  --lo-card: #FFFFFF;
  --lo-ink: #1A1714;
  --lo-ink-2: #4A443E;
  /* Nicht heller: der Fliesstext unter dem Titel muss auf Creme lesbar
     bleiben — #6F675E liegt bei ~5:1. */
  --lo-mute: #6F675E;
  --lo-line: #E7E1D7;
  --lo-red: #E94E2D;
  --lo-ease: cubic-bezier(0.23, 1, 0.32, 1);
}

body {
  background: var(--lo-cream) !important;
  color: var(--lo-ink);
  min-height: 100vh;
}

/* ─────────────── Buehne ─────────────── */

.lo-shell {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  min-height: 100vh;
  min-height: 100dvh;
}

/* Spiegelbild zur Admin-Seite: das Bild liegt links ueber die Mitte hinaus
   und wird per SVG-Kurve zurueckgeschnitten (Vorbild Fresha). Der Pfad steckt
   im HTML in objectBoundingBox-Einheiten und skaliert mit dem Element. */
.lo-stage {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 58%;
  overflow: hidden;
  background: #EFE9DF;
  clip-path: url(#lo-curve);
}

.lo-stage img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  animation: lo-stage-in 1400ms var(--lo-ease) both;
}

@keyframes lo-stage-in {
  from { transform: scale(1.05); opacity: 0; }
  to   { transform: scale(1);    opacity: 1; }
}

/* Kein Verlauf an der Schnittkante — die Kurve soll scharf stehen.
   Unten bleibt die Abdunklung, damit die Zeile traegt. */
.lo-stage::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 42%, rgba(38, 28, 20, 0.6) 100%);
  pointer-events: none;
}

.lo-stage-caption {
  position: absolute;
  left: clamp(28px, 4vw, 60px);
  /* links von der Schnittkante bleiben: unten schwingt die Kurve am
     weitesten nach links (auf 77,5% der Bildbreite). */
  right: 30%;
  bottom: clamp(28px, 4vw, 56px);
  z-index: 1;
  color: #FFFDF9;
  animation: lo-rise 700ms var(--lo-ease) 380ms both;
}

/* Fraunces bleibt sonst der Landing-Page vorbehalten. Hier steht sie bewusst
   nur auf dem Bild — die Eingangstuer ist der einzige Marken-Moment im
   Backoffice, das Arbeits-UI dahinter bleibt DM Sans. */
.lo-stage-caption p {
  margin: 0;
  max-width: 22ch;
  font-family: 'Fraunces', Georgia, serif;
  font-style: italic;
  font-weight: 400;
  font-size: clamp(24px, 2.6vw, 34px);
  line-height: 1.22;
  letter-spacing: -0.01em;
  text-shadow: 0 1px 24px rgba(30, 20, 12, 0.35);
}

.lo-stage-caption .lo-kicker {
  display: block;
  margin-bottom: 12px;
  color: rgba(255, 253, 249, 0.78);
}

.lo-kicker {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--lo-mute);
}

/* ─────────────── Formularseite ─────────────── */

.lo-form-col {
  grid-column: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(28px, 5vw, 76px);
  background: var(--lo-cream);
}

.lo-form {
  width: 100%;
  max-width: 392px;
}

.lo-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: clamp(28px, 6vh, 54px);
}

.lo-brand .lo-mark {
  width: 32px;
  height: 32px;
  border-radius: 9px;
  background: var(--lo-red);
  color: #FFFFFF;
  display: grid;
  place-items: center;
  font-weight: 700;
  font-size: 16px;
  letter-spacing: -0.5px;
}

.lo-brand .lo-wordmark {
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.2px;
  color: var(--lo-ink);
}

.lo-brand .lo-scope {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--lo-mute);
  background: #F1ECE3;
  border-radius: 5px;
  padding: 4px 8px;
}

.lo-title {
  font-size: 30px;
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.15;
  color: var(--lo-ink);
  margin: 0 0 8px;
}

.lo-sub {
  font-size: 14px;
  line-height: 1.55;
  color: var(--lo-mute);
  margin: 0 0 clamp(20px, 4vh, 30px);
}

/* Bot-Schutz. Nur Luft drumherum — an fremden Widgets herumzuschrauben
   raecht sich beim naechsten Update. */
.cf-turnstile {
  margin-top: 18px;
  min-height: 65px;
}

/* AGB-Zustimmung auf der Betriebsnamen-Seite (Google-Registrierung). */
.lo-agb {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 13px;
  line-height: 1.45;
  color: var(--lo-ink-2);
  cursor: pointer;
}
.lo-agb input[type="checkbox"] {
  margin-top: 2px;
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  accent-color: var(--lo-red);
}
.lo-agb a { color: var(--lo-red); }

/* ─────────────── Google-Weg ─────────────── */

.lo-or {
  position: relative;
  text-align: center;
  margin: 22px 0 16px;
}
.lo-or::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 1px;
  background: var(--lo-line);
}
.lo-or span {
  position: relative;
  padding: 0 12px;
  background: var(--lo-cream);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--lo-mute);
}

.lo-google-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  min-height: 46px;
  padding: 0 16px;
  border: 1px solid var(--lo-line);
  border-radius: 9px;
  background: var(--lo-card);
  color: var(--lo-ink);
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
  transition: transform 160ms var(--lo-ease), border-color 160ms var(--lo-ease),
              background-color 160ms var(--lo-ease);
}
.lo-google-btn:hover { border-color: #D9D1C4; background: #FFFDF9; }
.lo-google-btn:active { transform: scale(0.985); }
.lo-google-btn:focus-visible {
  outline: none;
  border-color: rgba(233, 78, 45, 0.6);
  box-shadow: 0 0 0 3px rgba(233, 78, 45, 0.13);
}

.lo-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: 24px;
  font-size: 13px;
}

.lo-foot a {
  color: var(--lo-ink-2);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 160ms var(--lo-ease), border-color 160ms var(--lo-ease);
}
.lo-foot a:hover { color: var(--lo-red); border-bottom-color: var(--lo-red); }

.lo-foot .lo-version {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--lo-mute);
}

/* ─────────────── Formular ─────────────── */

.lo-form .tappr-form-error {
  margin: 0 0 18px;
  padding: 11px 14px;
  border: 1px solid #F2CEC3;
  border-left-width: 2px;
  border-radius: 8px;
  background: #FCEDE8;
  color: #A03418;
  font-size: 13px;
  line-height: 1.45;
  display: none;
}
.lo-form .tappr-form-error.is-visible {
  display: block;
  animation: lo-rise 240ms var(--lo-ease) both;
}

.lo-form .label {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0;
  color: var(--lo-ink-2);
}

.lo-form .input,
.lo-form .otp-input {
  background: var(--lo-card);
  border: 1px solid var(--lo-line);
  border-radius: 9px;
  color: var(--lo-ink);
  transition: border-color 160ms var(--lo-ease), box-shadow 160ms var(--lo-ease);
}

.lo-form .input:hover,
.lo-form .otp-input:hover { border-color: #D9D1C4; }

.lo-form .input:focus,
.lo-form .otp-input:focus {
  outline: none;
  border-color: rgba(233, 78, 45, 0.6);
  box-shadow: 0 0 0 3px rgba(233, 78, 45, 0.13);
}

.lo-form .input-with-icon .icon-left { color: var(--lo-mute); }
.lo-form .input-toggle {
  color: var(--lo-mute);
  border-radius: 7px;
  transition: color 160ms var(--lo-ease), background-color 160ms var(--lo-ease);
}
.lo-form .input-toggle:hover { color: var(--lo-ink); background: #F1ECE3; }

.lo-form .tappr-btn--primary {
  background: var(--lo-red);
  border-color: var(--lo-red);
  color: #FFFFFF;
  border-radius: 9px;
  font-weight: 600;
  box-shadow: 0 1px 2px rgba(90, 40, 20, 0.12);
  transition: transform 140ms var(--lo-ease), background-color 140ms ease,
              color 140ms ease, border-color 140ms ease;
}

/* Zeigen: der Knopf kippt auf weiss. Das vorherige brightness(1.05) war
   auf Orange praktisch unsichtbar — 5% Helligkeit sieht niemand.
   Die Schrift wird dunkel statt orange: Orange auf Weiss liegt bei 3,8:1
   und reisst die 4,5:1-Vorgabe (CLAUDE.md, Kontrast). Der orange Rand
   haelt die Marke, ohne die Lesbarkeit zu opfern.
   Nur mit echtem Zeiger — auf dem Handy bliebe der Zustand nach dem
   Antippen kleben, der Knopf saehe dann dauerhaft weiss aus. */
@media (hover: hover) and (pointer: fine) {
  .lo-form .tappr-btn--primary:hover {
    background: #FFFFFF;
    color: var(--lo-ink);
    border-color: var(--lo-red);
  }
}

/* Druck: 0.985 war zu zaghaft, um als Antwort durchzugehen. */
.lo-form .tappr-btn--primary:active { transform: scale(0.97); }

.lo-form .tappr-btn--primary:focus-visible {
  outline: 2px solid var(--lo-red);
  outline-offset: 2px;
}

/* Waehrend der Pruefung: Kreisel plus "Wird geprueft" statt nur gesperrt.
   Die Basisregel setzt gesperrte Knoepfe auf 50% Deckkraft — das liest
   sich wie kaputt, nicht wie beschaeftigt. Hier also volle Deckkraft. */
.lo-form .tappr-btn--primary.is-loading[disabled] {
  opacity: 1;
  cursor: progress;
}
.lo-form .tappr-btn--primary.is-loading::before {
  content: "";
  width: 15px;
  height: 15px;
  border: 2px solid rgba(255, 255, 255, 0.4);
  border-top-color: #FFFFFF;
  border-radius: 50%;
  animation: lo-spin 620ms linear infinite;
}
@keyframes lo-spin { to { transform: rotate(360deg); } }

.lo-form .otp-input {
  height: 54px;
  font-family: var(--font-mono);
  font-size: 21px;
}

.lo-form .step-back {
  font-size: 12px;
  color: var(--lo-mute);
  margin-bottom: 18px;
}
.lo-form .step-back:hover { color: var(--lo-ink); }

.tappr-form-root[data-step="2fa"] .step-2fa {
  display: block;
  animation: lo-rise 260ms var(--lo-ease) both;
}

/* ─────────────── Auftritt ─────────────── */

@keyframes lo-rise {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.lo-form > * { animation: lo-rise 460ms var(--lo-ease) both; }
.lo-form > *:nth-child(1) { animation-delay: 40ms; }
.lo-form > *:nth-child(2) { animation-delay: 100ms; }
.lo-form > *:nth-child(3) { animation-delay: 150ms; }
.lo-form > *:nth-child(4) { animation-delay: 195ms; }

/* ─────────────── Schmale Fenster ─────────────── */

@media (max-width: 900px) {
  .lo-shell { grid-template-columns: 1fr; }
  /* Hochkant liegt das Bild oben quer — dieselbe Kurve um 90 Grad gedreht.
   *
   * relative, NICHT static: Bild und Bildtext liegen absolut IM Buehnen-
   * kasten. Mit static verliert der Kasten seine Ankerfunktion, beide
   * rechnen dann gegen die ganze Seite — das Bild wurde 880px hoch statt
   * 290 (und zeigte damit einen zufaelligen Ausschnitt eines hochkant
   * gestreckten Fotos), der Bildtext rutschte an den unteren Seitenrand,
   * weisse Schrift auf Creme. Beides gemessen am 04.08.2026. */
  .lo-stage {
    position: relative;
    width: auto;
    min-height: 32vh;
    clip-path: url(#lo-curve-h);
  }
  .lo-form-col { grid-column: 1; }
  .lo-stage::after {
    background: linear-gradient(180deg, transparent 30%, rgba(38, 28, 20, 0.65) 100%);
  }
  .lo-stage-caption {
    right: clamp(28px, 8vw, 60px);
    bottom: clamp(40px, 8vw, 70px);
  }
  .lo-stage-caption p { font-size: 22px; }
  .lo-form-col { padding: clamp(26px, 7vw, 44px) clamp(20px, 6vw, 40px) 46px; }
}

/* ─────────────── Handy ───────────────
 *
 * Kein Foto (Owner-Entscheid 04.08.2026): auf einem Handy war es ein
 * 290px hoher Streifen ohne erkennbares Motiv — ein Drittel des Schirms
 * fuer Deko, das den Rest unter die Kante schob. Stattdessen traegt die
 * Schrift den Auftritt, und alles steht ohne Scrollen da.
 * Der Desktop bleibt unangetastet. */
@media (max-width: 767px) {
  .lo-stage { display: none; }

  /* oben statt mittig — sonst steht das Formular auf hohen Geraeten
     in der Mitte und der Daumen muss hoch. */
  .lo-form-col {
    align-items: flex-start;
    padding: 28px 20px 32px;
  }

  /* Enger gestellt: dieselben Abstaende wie am Desktop kosten hier
     rund 90px und damit den Unterschied zwischen "passt" und "scrollen". */
  .lo-brand { margin-bottom: 20px; }
  .lo-title { font-size: 25px; }
  .lo-sub { margin-bottom: 16px; }
  .lo-form .tappr-form-error { margin-bottom: 12px; }
  .cf-turnstile { margin-top: 12px; }
  .lo-or { margin: 14px 0 12px; }
  .lo-foot { margin-top: 16px; }

  /* Tippziele auf 44px (CLAUDE.md). Das Auge im Passwortfeld war 32px,
     der Fuss-Link 21px hoch — beides zu klein fuer einen Daumen. */
  .lo-form .input-toggle {
    min-width: 44px;
    min-height: 44px;
  }
  .lo-foot a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
}

@media (max-width: 380px) {
  .lo-form .otp-input { height: 46px; font-size: 18px; }
  .otp-row { gap: 6px; }
  .lo-title { font-size: 24px; }
}

@media (prefers-reduced-motion: reduce) {
  .lo-stage img,
  .lo-stage-caption,
  .lo-form > *,
  .lo-form .tappr-form-error.is-visible,
  .tappr-form-root[data-step="2fa"] .step-2fa {
    animation: none;
  }
  .lo-form .tappr-btn--primary:active { transform: none; }
}
