/* ===================================================================
   ADMIN — Designsystem
   Umsetzung von .ai/BRANDBOOK-ADMIN.md

   Gilt nur für das Backend (/admin, Login, Onboarding, Installer).
   Das Restaurant-Frontend nutzt app.css und bleibt unberührt.

   Aufbau, in dieser Reihenfolge:
     1. Token      — Farbe, Schrift, Abstand, Geometrie
     2. Basis      — Reset, Typografie
     3. Layout     — Sidebar, Hauptbereich
     4. Flächen    — Karten, Abschnitte, Raster
     5. Listen     — Zeilen, leere Zustände
     6. Formulare  — Felder, Raster, Aktionen
     7. Aktionen   — Buttons
     8. Zustand    — Badges, Meldungen
     9. Bereiche   — Dashboard, Module, Domains, Zeiten, Baukasten
    10. Responsiv

   Eine Regel steht genau einmal. Wer etwas ändern will, ändert sie dort —
   nicht weiter unten mit einer zweiten Regel.
   =================================================================== */


/* === 1. TOKEN ===================================================== */

.admin,
.admin-auth {
  /* Neutrale — warmes Grau */
  --c-bg: #f4f4f2;
  --c-surface: #ffffff;
  --c-surface-sunk: #fafaf8;
  --c-border: #e3e3df;
  --c-border-strong: #c9c9c3;
  --c-text: #1c1b19;
  --c-text-muted: #6b6862;

  /* Primär — Paprika */
  --c-primary: #c0392b;
  --c-primary-hover: #9c2d22;
  --c-primary-soft: #fbeae7;
  --c-primary-ring: rgba(192, 57, 43, .25);

  /* Signal */
  --c-success: #1e7a4b;
  --c-success-soft: #e6f3ec;
  --c-warning: #b4700e;
  --c-warning-soft: #fcf1dd;
  --c-danger: #8e1f16;
  --c-danger-soft: #f7e4e2;

  /* Sidebar — Kohle */
  --c-nav: #22211e;
  --c-nav-text: #a8a49c;
  --c-nav-text-on: #ffffff;
  --c-nav-hover: #2e2c28;

  /* Schrift — genau zwei */
  --font-ui: "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system, sans-serif;
  --font-mono: ui-monospace, "Cascadia Mono", "Segoe UI Mono", Consolas, monospace;

  /* Größen */
  --t-2xl: 28px;
  --t-xl: 20px;
  --t-lg: 17px;
  --t-md: 15px;
  --t-sm: 13px;

  /* Abstand — alles ein Vielfaches von 4 */
  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 24px;
  --s-6: 32px;
  --s-7: 48px;

  /* Geometrie */
  --control-h: 40px;
  --r-control: 8px;
  --r-card: 12px;
  --r-pill: 999px;

  --shadow-bar: 0 -1px 0 var(--c-border), 0 -8px 24px rgba(28, 27, 25, .06);
  --sidebar-w: 256px;
}


/* === 2. BASIS ===================================================== */

.admin *,
.admin-auth *,
.admin *::before,
.admin-auth *::before,
.admin *::after,
.admin-auth *::after {
  box-sizing: border-box;
}

body.admin,
body.admin-auth {
  margin: 0;
  background: var(--c-bg);
  color: var(--c-text);
  font-family: var(--font-ui);
  font-size: var(--t-md);
  font-weight: 400;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

/* Die drei Subtypen. Mehr gibt es nicht.
   Titel    = 600 / --c-text
   Text     = 400 / --c-text
   Sekundär = 400 / --c-text-muted                                  */

.admin h1,
.admin h2,
.admin h3,
.admin strong,
.admin-auth h1,
.admin-auth h2,
.admin-auth h3,
.admin-auth strong {
  font-weight: 600;
  color: var(--c-text);
  margin: 0;
  line-height: 1.3;
}

.admin h1 { font-size: var(--t-2xl); line-height: 1.25; letter-spacing: -.01em; }
.admin h2 { font-size: var(--t-xl); }
.admin h3 { font-size: var(--t-lg); }

.admin p,
.admin li,
.admin td,
.admin-auth p {
  margin: 0;
}

/* Sekundär — Hilfetexte, Meta, Zeitstempel.
   :is(.admin, .admin-auth) hält Backend und Anmelde-/Installationsseiten auf
   demselben System. Ohne diesen gemeinsamen Geltungsbereich driften Login,
   Onboarding und Installer wieder aus dem Design heraus. */
:is(.admin, .admin-auth) :is(small, .form-note, .hint, .row-note, .eyebrow) {
  display: block;
  font-size: var(--t-sm);
  font-weight: 400;
  color: var(--c-text-muted);
  line-height: 1.45;
}

/* Die Augenbraue ist ein Sekundärtext, keine vierte Stufe:
   kein Uppercase, kein Letter-Spacing, keine Extrafarbe. */
:is(.admin, .admin-auth) .eyebrow {
  margin-bottom: var(--s-1);
}

.admin a,
.admin-auth a {
  color: var(--c-primary);
  text-decoration: none;
}

.admin a:hover,
.admin-auth a:hover {
  text-decoration: underline;
}

/* Zahlen stehen untereinander */
.admin .price-pill,
.admin .kpi-card strong,
.admin table,
.admin time,
.admin input[type="number"],
.admin input[type="time"],
.admin input[type="date"] {
  font-variant-numeric: tabular-nums;
}

:is(.admin, .admin-auth) :is(code, .code-area, .snippet-preview) {
  font-family: var(--font-mono);
  font-size: var(--t-sm);
}

:is(.admin, .admin-auth) code {
  background: var(--c-surface-sunk);
  border: 1px solid var(--c-border);
  border-radius: var(--s-1);
  padding: 2px var(--s-2);
  color: var(--c-text);
  word-break: break-all;
}

:is(.admin, .admin-auth) :is(.icon, .nav-icon) {
  width: 18px;
  height: 18px;
  flex: none;
  stroke: currentColor;
  stroke-width: 1.75;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Muss vor allen Komponenten stehen: sonst überschreibt ein späteres
   display:flex/inline-flex das hidden-Attribut und versteckte Elemente
   (Speicherleiste, "Ungespeicherte Änderungen") werden trotzdem sichtbar. */
.admin [hidden],
.admin-auth [hidden] {
  display: none !important;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}


/* === 3. LAYOUT ==================================================== */

body.admin {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  min-height: 100vh;
}

/* --- Sidebar --- */

/* min-width:0 ist Pflicht: als Grid-Element würde die Sidebar sonst nie
   schmaler werden als ihr Inhalt. Auf Mobile ist die Navigation eine breite
   waagerechte Leiste — ohne diese Zeile schiebt sie die ganze Seite auf und
   der Inhalt läuft rechts aus dem Bild. */
.admin-sidebar {
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
  background: var(--c-nav);
  color: var(--c-nav-text);
  padding: var(--s-5);
  position: sticky;
  top: 0;
  height: 100vh;
  min-width: 0;
  overflow-y: auto;
}

.admin-sidebar-header {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}

.admin-brand {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  color: var(--c-nav-text-on);
}

.admin-brand:hover {
  text-decoration: none;
}

.admin-brand-mark {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  flex: none;
  border-radius: var(--r-control);
  background: var(--c-primary);
  color: #fff;
  font-weight: 600;
  font-size: var(--t-lg);
}

.admin-brand strong {
  display: block;
  color: var(--c-nav-text-on);
  font-size: var(--t-md);
}

.admin-brand small {
  color: var(--c-nav-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 160px;
}

/* Restaurant-Umschalter (nur Agentur) */
.admin-context-switcher {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

/* Bedienelemente auf dunklem Grund. Die Geometrie bleibt exakt gleich —
   nur die Farbe kehrt sich um. Erhöhte Spezifität, damit die Grundregeln
   aus Abschnitt 6/7 nicht gewinnen. */
/* background-COLOR, nicht die Kurzschreibweise background!
   "background: <farbe>" setzt alle background-* auf ihren Ausgangswert zurück,
   also auch background-repeat auf "repeat" und die Position auf "0 0". Der
   Pfeil aus der Basisregel kachelte dadurch über das ganze Feld — das waren
   die Zickzack-Linien über dem Restaurantnamen. */
.admin .admin-context-switcher select {
  width: 100%;
  background-color: var(--c-nav-hover);
  background-repeat: no-repeat;
  background-position: right var(--s-3) center;
  border-color: #45423c;
  color: var(--c-nav-text-on);
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%23a8a49c' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m4 6 4 4 4-4'/%3E%3C/svg%3E");
}

.admin .admin-context-switcher select:hover {
  border-color: #5c584f;
}

/* --- Navigation --- */

.admin-nav {
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
  flex: 1;
}

.nav-group {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
}

.nav-group h2 {
  font-size: var(--t-sm);
  font-weight: 600;
  color: #78746c;
  margin-bottom: var(--s-2);
  padding: 0 var(--s-3);
}

.admin-sidebar nav a {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: var(--control-h);
  padding: 0 var(--s-3);
  border-radius: var(--r-control);
  color: var(--c-nav-text);
  font-weight: 400;
}

.admin-sidebar nav a:hover {
  background: var(--c-nav-hover);
  color: var(--c-nav-text-on);
  text-decoration: none;
}

/* Der aktive Punkt ist der einzige Farbakzent der Sidebar */
.admin-sidebar nav a.is-active {
  background: var(--c-primary);
  color: #fff;
  font-weight: 600;
}

.admin-sidebar nav a.is-active:hover {
  background: var(--c-primary-hover);
}

.admin-sidebar-footer {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding-top: var(--s-4);
  border-top: 1px solid #35322d;
}

.admin-sidebar-footer form {
  display: contents;
}

.admin .admin-sidebar-footer .button {
  width: 100%;
  justify-content: flex-start;
  background: transparent;
  border-color: #45423c;
  color: var(--c-nav-text);
}

.admin .admin-sidebar-footer .button:hover {
  background: var(--c-nav-hover);
  border-color: #5c584f;
  color: var(--c-nav-text-on);
}

/* --- Hauptbereich --- */

/* Regel B: zwischen zwei Blöcken liegen immer 24px.
   Niemand vergibt Außenabstände von Hand. */
.admin-main {
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
  padding: var(--s-6);
  max-width: 1180px;
  width: 100%;
  min-width: 0;
}

.admin-main > * {
  margin: 0;
}

.admin-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s-4);
  flex-wrap: wrap;
  padding-bottom: var(--s-5);
  border-bottom: 1px solid var(--c-border);
}

.admin-header-actions {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex-wrap: wrap;
}

.admin-header-actions form {
  display: contents;
}


/* === 4. FLÄCHEN =================================================== */

/* Kante statt Schatten. Das ist der Unterschied zwischen
   "Werkzeug" und "generierte Landingpage". */
.admin-card,
.admin-panel,
.admin-form,
.empty-state,
.settings-card,
.module-card,
.order-card,
.kpi-card,
.option-card,
.choice,
.design-choice,
.hours-preview-card,
.module-compat-card,
.template-catalog-card {
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-card);
  padding: var(--s-5);
}

/* Regel A: Innenabstand ist überall 24px, kompakt 16px. */
.admin-card.compact,
.admin-panel.compact,
.empty-state.compact {
  padding: var(--s-4);
}

/* Auswahlkarten sind immer kompakt: sie tragen eine Entscheidung, keinen
   Inhalt. 24px Polsterung um einen Radioknopf und zwei Zeilen Text lässt ein
   Raster aus zehn Karten unnötig auseinanderlaufen. */
:is(.admin, .admin-auth) :is(.option-card, .choice, .design-choice, .template-catalog-card) {
  padding: var(--s-4);
}

/* Karten stapeln ihren Inhalt mit einem einzigen Abstand */
.admin-card,
.admin-panel,
.settings-card,
.module-card,
.order-card {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

.admin-card > *,
.admin-panel > * {
  margin: 0;
}

/* Titelzeile einer Karte: Titel links, Aktion rechts */
.admin-toolbar,
.panel-heading {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s-4);
  flex-wrap: wrap;
}

.admin-toolbar > div,
.panel-heading > div {
  min-width: 0;
}

/* Nicht "flex: none": das entspricht flex:0 0 auto, die Aktionsgruppe nähme
   dann ihre volle Inhaltsbreite ein und könnte nie schrumpfen — auf schmalen
   Bildschirmen schiebt sie damit die ganze Seite auf. Sie darf schrumpfen und
   umbrechen; nach rechts hält sie das space-between des Toolbars. */
.admin-toolbar .admin-header-actions,
.panel-heading .admin-header-actions {
  flex: 0 1 auto;
  min-width: 0;
}

.section-heading {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
}

.section-heading p:not(.eyebrow) {
  color: var(--c-text-muted);
  font-size: var(--t-sm);
  max-width: 68ch;
}

.admin-section {
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
}

/* Raster — ein Gutter für alles */
.admin-grid,
.settings-grid,
.module-grid,
.option-grid,
.kpi-grid,
.screen-grid,
.choice-grid,
.design-choice-grid,
.template-catalog,
.module-compat-grid {
  display: grid;
  gap: var(--s-4);
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}

.admin-grid.two,
.dashboard-layout {
  display: grid;
  gap: var(--s-4);
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
}

.admin-grid.three {
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}

.admin-card.wide,
.admin-panel.wide {
  grid-column: 1 / -1;
}


/* === 5. LISTEN ==================================================== */

/* Eine Liste ist eine Fläche mit Haarlinien — nicht ein Stapel Karten.
   Karten-im-Karten-Stapel war ein Hauptgrund für die Unruhe. */
.admin-list,
.compact-list,
.special-hours-list,
.endpoint-list,
.timeline-list,
.detail-list {
  display: flex;
  flex-direction: column;
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-card);
  overflow: hidden;
}

.admin-row,
.record-row,
.compact-list > *,
.timeline-list > div,
.detail-list > div,
.endpoint-list > li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  padding: var(--s-4) var(--s-5);
  border-top: 1px solid var(--c-border);
  min-width: 0;
}

.admin-list > :first-child,
.compact-list > :first-child,
.special-hours-list > :first-child,
.endpoint-list > :first-child,
.timeline-list > :first-child,
.detail-list > :first-child {
  border-top: 0;
}

/* Titelzeile einer Liste. Steht ein Titel samt Erklärsatz in der Liste
   ("Tische", "Protokoll", "Sperrzeiten"), ist er die Überschrift der Fläche
   und bekommt dieselbe Polsterung wie eine Zeile. Ohne diese Regel klebt er
   ohne jeden Abstand an der Kante — die Liste hat selbst keine Polsterung,
   die tragen ihre Zeilen. */
.admin-list > :is(h2, h3) {
  padding: var(--s-5) var(--s-5) 0;
}

.admin-list > :is(p, .form-note) {
  padding: var(--s-2) var(--s-5) var(--s-4);
}

/* Der Erklärsatz gehört zum Titel: keine Trennlinie dazwischen, wohl aber
   vor der ersten Zeile darunter (die trägt sie ohnehin). */
.admin-list > :is(h2, h3) + :is(p, .form-note) {
  border-top: 0;
}

.admin-row > div,
.detail-list > div > *,
.timeline-list > div > * {
  min-width: 0;
}

.admin-row p,
.special-hours-card p {
  font-size: var(--t-sm);
  color: var(--c-text-muted);
}

.row-actions {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex: none;
  flex-wrap: wrap;
}

.row-actions form {
  display: contents;
}

/* Unterpunkt: eingerückt */
.child-row {
  padding-left: var(--s-6);
}

/* Speisekarte: die Kategorie führt ihre Gerichte an. Die ruhende Fläche
   gehört deshalb der Kategoriezeile — nicht den Gerichten. Andersherum wäre
   die halbe Liste grau und die Gliederung auf den Kopf gestellt. */
.category-row {
  background: var(--c-surface-sunk);
}

/* Eine Zeile, die schon in einer Karte sitzt, bringt weder Polsterung noch
   Trennlinie mit — sonst polstert die Karte doppelt. */
.admin-row.flat {
  padding: 0;
  border-top: 0;
}

.detail-list > div,
.timeline-list > div {
  flex-direction: row;
  align-items: baseline;
}

.detail-list > div > span:first-child,
.timeline-list > div > span:first-child {
  color: var(--c-text-muted);
  font-size: var(--t-sm);
  flex: none;
}

/* Leerer Zustand — Pflicht bei jeder Liste */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-2);
  text-align: center;
  padding: var(--s-6) var(--s-5);
  background: var(--c-surface-sunk);
  border: 1px dashed var(--c-border-strong);
}

.empty-state p {
  color: var(--c-text-muted);
  font-size: var(--t-sm);
  max-width: 46ch;
}

.empty-state .button {
  margin-top: var(--s-2);
}

/* Steht die leere Liste in einem .admin-list, hat sie keinen zweiten Rahmen */
.admin-list > .empty-state {
  border: 0;
  border-radius: 0;
}


/* === 6. FORMULARE ================================================= */

.admin-form,
.sectioned-form,
.seo-form,
.special-hours-form,
.hours-page-form {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

/* Ein Knopf direkt im Formular wird nicht über die ganze Breite gezogen.
   .admin-form ist ein Spalten-Flex, und dessen Standard (align-items:stretch)
   macht aus "Domain hinzufügen" sonst einen randlosen Balken. */
.admin-form > .button,
.admin-form > button {
  align-self: flex-start;
}

/* Ein Formular in einer Karte zeichnet keinen zweiten Kasten. Ohne diese
   Regel entsteht überall Karte-in-Karte — einer der Gründe, warum das alte
   Backend so unruhig wirkte. */
.admin-card .admin-form,
.admin-panel .admin-form,
.login-card .admin-form,
.admin-row .admin-form {
  background: none;
  border: 0;
  border-radius: 0;
  padding: 0;
}

.admin-form h2,
.admin-form h3 {
  margin-bottom: var(--s-1);
}

/* Label über dem Feld — nie Platzhalter statt Label.
   Umbruch-Zeile statt Spalte: Beschriftung und Zusätze wie "Pflichtfeld"
   stehen dadurch nebeneinander, das Feld bricht darunter auf volle Breite.
   Das Markup <label>Name <span class="required">…</span><input></label>
   funktioniert so ohne Wrapper-Element. */
.admin label,
.admin-auth label {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--t-md);
  font-weight: 400;
  color: var(--c-text);
  min-width: 0;
}

/* Das Feld nimmt die Zeile unter seiner Beschriftung ein — außer, es trägt
   .inline-control oder ist eine Dateiauswahl. Beide behalten ihre Breite und
   stehen neben der Beschriftung. */
.admin label > input:not([type="checkbox"]):not([type="radio"]):not([type="color"]):not([type="file"]):not(.inline-control),
.admin label > select,
.admin label > textarea,
.admin-auth label > input:not([type="checkbox"]):not([type="radio"]):not([type="color"]):not([type="file"]):not(.inline-control),
.admin-auth label > select,
.admin-auth label > textarea {
  flex: 1 0 100%;
}

/* Farbwähler bleiben ein Quadrat neben ihrer Beschriftung — sie sind eine
   Auswahl, kein Textfeld, und dürfen nicht über die Zeile laufen. */
.admin label > input[type="color"] {
  margin-left: auto;
}

/* --- Die Kerngeometrie: alles Bedienbare ist gleich gebaut --- */

.admin input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]),
.admin select,
.admin textarea,
.admin .button,
.admin button,
.admin-auth input:not([type="checkbox"]):not([type="radio"]),
.admin-auth select,
.admin-auth textarea,
.admin-auth .button,
.admin-auth button {
  font-family: var(--font-ui);
  font-size: var(--t-md);
  line-height: 1.4;
  height: var(--control-h);
  padding: 0 var(--s-3);
  border: 1px solid var(--c-border-strong);
  border-radius: var(--r-control);
  background: var(--c-surface);
  color: var(--c-text);
  transition: border-color .12s ease, background-color .12s ease, box-shadow .12s ease;
}

/* Die volle Feldbreite steht bewusst in einer eigenen Regel — sie ist der
   Normalfall, aber kein Naturgesetz. Wer ein Feld in eine Zeile stellt
   (Uhrzeiten im Wochenplan) oder es seine natürliche Breite behalten lässt
   (Dateiauswahl), setzt .inline-control und muss keine Spezifitätsschlacht
   gegen eine Regel führen, die noch Rahmen und Höhe mitbringt. */
:is(.admin, .admin-auth) :is(input, select, textarea):not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]):not(.inline-control) {
  width: 100%;
}

.admin textarea,
.admin-auth textarea {
  height: auto;
  min-height: 96px;
  padding: var(--s-3);
  resize: vertical;
  line-height: 1.55;
}

/* Felder, die in einer Zeile neben anderen Bedienelementen stehen. */
:is(.admin, .admin-auth) .inline-control {
  flex: none;
  width: auto;
}

/* Uhrzeiten stehen zu zweit in einer Zeile und sind überall gleich breit. */
.admin input.inline-control[type="time"] {
  width: 116px;
}

.admin select,
.admin-auth select {
  appearance: none;
  padding-right: var(--s-6);
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%236b6862' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m4 6 4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--s-3) center;
  cursor: pointer;
}

.admin input:hover,
.admin select:hover,
.admin textarea:hover {
  border-color: #a9a69f;
}

/* Fokus ist immer sichtbar. Wer mit Tab navigiert, muss sehen, wo er steht. */
.admin :is(input, select, textarea, button, a):focus-visible,
.admin-auth :is(input, select, textarea, button, a):focus-visible {
  outline: none;
  border-color: var(--c-primary);
  box-shadow: 0 0 0 3px var(--c-primary-ring);
}

.admin a:focus-visible {
  border-radius: var(--s-1);
}

.admin input::placeholder,
.admin textarea::placeholder {
  color: var(--c-text-muted);
  opacity: 1;
}

.admin input:disabled,
.admin select:disabled,
.admin textarea:disabled {
  background: var(--c-surface-sunk);
  color: var(--c-text-muted);
  cursor: not-allowed;
}

/* Kontrollkästchen und Radios sind klein und stehen neben ihrem Text */
:is(.admin, .admin-auth) :is(input[type="checkbox"], input[type="radio"]) {
  width: 18px;
  height: 18px;
  flex: none;
  margin: 0;
  accent-color: var(--c-primary);
  cursor: pointer;
}

:is(.admin, .admin-auth) :is(label.check, .choice-row label) {
  flex-direction: row;
  align-items: center;
  gap: var(--s-2);
  min-height: var(--control-h);
  cursor: pointer;
}

/* Eine Reihe gleichartiger Kästchen (Ruhetage) bricht um, statt zu quetschen. */
:is(.admin, .admin-auth) .choice-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
}

.admin input[type="color"] {
  width: var(--control-h);
  height: var(--control-h);
  padding: var(--s-1);
  border: 1px solid var(--c-border-strong);
  border-radius: var(--r-control);
  background: var(--c-surface);
  cursor: pointer;
}

/* --- Feldraster --- */

/* Ohne Zusatz passt sich das Raster der Breite an (zwei bis drei Felder
   nebeneinander, auf schmalen Schirmen eines). .two/.three erzwingen eine
   feste Spaltenzahl, wenn die Felder inhaltlich zusammengehören. */
.form-grid,
.settings-grid.form-grid {
  display: grid;
  gap: var(--s-4);
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

.form-grid.two,
.option-grid.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.form-grid.three,
.option-grid.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }

@media (max-width: 720px) {
  .form-grid.two,
  .form-grid.three,
  .option-grid.two,
  .option-grid.three { grid-template-columns: 1fr; }
}

/* --- Hilfe, Pflicht, Fehler --- */

.required {
  color: var(--c-text-muted);
  font-size: var(--t-sm);
  font-weight: 400;
}

.inline-error {
  display: block;
  font-size: var(--t-sm);
  color: var(--c-danger);
}

.has-error input,
.has-error select,
.has-error textarea {
  border-color: var(--c-danger);
}

/* --- Aktionszeile --- */

.form-actions,
.hours-actions-bar,
.head-actions {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex-wrap: wrap;
}

.form-actions-end {
  justify-content: flex-end;
}

.status-form,
.inline-edit-form {
  display: flex;
  align-items: flex-end;
  gap: var(--s-3);
  flex-wrap: wrap;
}

.inline-edit-form label {
  flex: 1 1 140px;
}

/* Eine Zeile zum Bearbeiten (Kategorien): die Felder stehen in einem Raster,
   damit sie über alle Zeilen hinweg untereinander stehen. Ein Flex-Umbruch
   ergäbe pro Zeile eine andere Spaltenbreite — genau das lässt eine Liste
   ausgefranst wirken. Die Aktionen sitzen rechts, auf Feldhöhe. */
.admin-row.category-editor {
  align-items: flex-end;
  gap: var(--s-3);
}

.category-editor .inline-edit-form {
  display: grid;
  grid-template-columns: minmax(140px, 1.4fr) minmax(160px, 2fr) 104px auto auto;
  align-items: end;
  flex: 1 1 auto;
  min-width: 0;
}

/* Das Kontrollkästchen steht auf der Höhe der Eingabefelder, nicht darüber. */
.category-editor .inline-edit-form label.check {
  align-self: end;
}

.category-editor > form:last-child {
  display: flex;
  align-items: flex-end;
  flex: none;
}

@media (max-width: 1100px) {
  .category-editor .inline-edit-form {
    grid-template-columns: minmax(140px, 1fr) minmax(140px, 1fr);
  }
}

@media (max-width: 720px) {
  .category-editor .inline-edit-form {
    grid-template-columns: 1fr;
  }

  .admin-row.category-editor {
    align-items: stretch;
  }

  .category-editor > form:last-child {
    justify-content: flex-start;
  }
}

/* Ein zweites Formular in derselben Karte — "Seite löschen" neben dem
   Bearbeiten-Formular — ist eine Fußzeile: abgetrennt, rechtsbündig, hohl.
   Ohne diese Regel steht der Löschknopf mitten im Formularfluss und sieht aus
   wie ein weiterer Bearbeitungsschritt. */
.admin-card > form.nested-form:last-child,
.admin-panel > form.nested-form:last-child {
  display: flex;
  justify-content: flex-end;
  padding-top: var(--s-4);
  border-top: 1px solid var(--c-border);
}

/* Klebende Speicherleiste bei langen Formularen */
.sticky-save,
.hours-save-bar {
  position: sticky;
  bottom: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  margin: 0 calc(-1 * var(--s-6)) calc(-1 * var(--s-6));
  background: var(--c-surface);
  border-top: 1px solid var(--c-border);
  box-shadow: var(--shadow-bar);
}


/* === 7. AKTIONEN ================================================== */

.admin .button,
.admin-auth .button,
.admin button,
.admin-auth button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  width: auto;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  text-decoration: none;
}

.admin .button:hover {
  text-decoration: none;
}

/* Gefüllt = Hauptaktion. Genau eine pro Bildschirm. */
.admin .button-primary,
.admin-auth .button-primary {
  background: var(--c-primary);
  border-color: var(--c-primary);
  color: #fff;
}

.admin .button-primary:hover,
.admin-auth .button-primary:hover {
  background: var(--c-primary-hover);
  border-color: var(--c-primary-hover);
}

/* Weiß mit Rand = alles Übrige */
.admin .button-secondary,
.admin-auth .button-secondary {
  background: var(--c-surface);
  border-color: var(--c-border-strong);
  color: var(--c-text);
}

.admin .button-secondary:hover,
.admin-auth .button-secondary:hover {
  background: var(--c-surface-sunk);
  border-color: #a9a69f;
}

/* Hohl = pass auf. Destruktives ist NIE gefüllt — sonst sieht
   "Löschen" aus wie "Speichern". */
.admin .button-danger {
  background: var(--c-surface);
  border-color: var(--c-danger);
  color: var(--c-danger);
}

.admin .button-danger:hover {
  background: var(--c-danger);
  border-color: var(--c-danger);
  color: #fff;
}

/* Quadratisch, nur Symbol — dieselbe Geometrie wie jedes andere Bedienelement.
   Nur Knöpfe stehen hier, keine Hüllen: .hours-row-action ist ein <div> und
   bekam als Treffer dieser Regel einen zweiten 40×40-Rahmen um den Knopf. */
.admin .icon-button,
.admin .hours-remove,
.admin .hours-add {
  width: var(--control-h);
  height: var(--control-h);
  padding: 0;
  flex: none;
  background: var(--c-surface);
  border: 1px solid var(--c-border-strong);
  color: var(--c-text-muted);
}

.admin .icon-button:hover,
.admin .hours-add:hover {
  background: var(--c-surface-sunk);
  border-color: #a9a69f;
  color: var(--c-text);
}

/* Rot nur, wo wirklich etwas entfernt wird. Ein "+" darf beim Hover nicht
   nach Löschen aussehen. */
.admin .icon-button-danger:hover,
.admin .hours-remove:hover {
  background: var(--c-danger-soft);
  border-color: var(--c-danger);
  color: var(--c-danger);
}

.admin .button:disabled,
.admin button:disabled {
  opacity: .5;
  cursor: not-allowed;
}


/* === 8. ZUSTAND =================================================== */

/* Ein Badge beschreibt einen Zustand, niemals eine Meinung. */
.status-badge,
.module-status,
.price-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-1) var(--s-3);
  border-radius: var(--r-pill);
  background: var(--c-surface-sunk);
  border: 1px solid var(--c-border);
  color: var(--c-text-muted);
  font-size: var(--t-sm);
  font-weight: 400;
  white-space: nowrap;
  flex: none;
}

.status-badge.status-success,
.module-status.status-success {
  background: var(--c-success-soft);
  border-color: transparent;
  color: var(--c-success);
}

.status-badge.status-warning {
  background: var(--c-warning-soft);
  border-color: transparent;
  color: var(--c-warning);
}

.status-badge.status-danger {
  background: var(--c-danger-soft);
  border-color: transparent;
  color: var(--c-danger);
}

.price-pill {
  background: var(--c-surface);
  border-color: var(--c-border-strong);
  color: var(--c-text);
  font-weight: 600;
}

/* Meldung — farbige Kante links, ruhige Fläche */
.alert {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  padding: var(--s-4);
  padding-left: var(--s-4);
  border: 1px solid var(--c-border);
  border-left: 3px solid var(--c-text-muted);
  border-radius: var(--r-control);
  background: var(--c-surface);
  font-size: var(--t-md);
  color: var(--c-text);
}

.alert-success {
  border-left-color: var(--c-success);
  background: var(--c-success-soft);
  border-color: transparent;
  border-left-color: var(--c-success);
}

.alert-warning {
  background: var(--c-warning-soft);
  border-color: transparent;
  border-left: 3px solid var(--c-warning);
}

.alert-error {
  background: var(--c-danger-soft);
  border-color: transparent;
  border-left: 3px solid var(--c-danger);
}

/* Tabs — aktiv ist eine Paprika-Unterkante, keine Kachel */
.admin-tabs {
  display: flex;
  gap: var(--s-5);
  border-bottom: 1px solid var(--c-border);
}

.admin-tabs a {
  padding: 0 0 var(--s-3);
  color: var(--c-text-muted);
  font-weight: 400;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}

.admin-tabs a:hover {
  color: var(--c-text);
  text-decoration: none;
}

.admin-tabs a.is-active {
  color: var(--c-text);
  font-weight: 600;
  border-bottom-color: var(--c-primary);
}


/* === 9. BEREICHE ================================================== */

/* --- Dashboard: Kennzahl = Zahl + Label. Sonst nichts. --- */

.kpi-card {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  color: var(--c-text);
}

.kpi-card:hover {
  border-color: var(--c-border-strong);
  text-decoration: none;
}

.kpi-label {
  font-size: var(--t-sm);
  color: var(--c-text-muted);
}

.kpi-card strong {
  font-size: var(--t-2xl);
  line-height: 1.2;
}

.quick-actions {
  display: flex;
  gap: var(--s-2);
  flex-wrap: wrap;
}

/* --- Einstellungen: Karten, die irgendwohin führen --- */

.settings-card {
  color: var(--c-text);
}

.settings-card:hover {
  border-color: var(--c-border-strong);
  text-decoration: none;
}

.card-icon {
  display: grid;
  place-items: center;
  width: var(--control-h);
  height: var(--control-h);
  border-radius: var(--r-control);
  background: var(--c-primary-soft);
  color: var(--c-primary);
}

.settings-card p {
  color: var(--c-text-muted);
  font-size: var(--t-sm);
}

/* Der Verweis sitzt am Kartenfuß — über alle Karten hinweg auf einer Höhe. */
.card-link {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin-top: auto;
  padding-top: var(--s-2);
  color: var(--c-primary);
  font-weight: 600;
}

/* --- Bestellungen --- */

.order-items {
  background: var(--c-surface-sunk);
}

.order-items > li {
  display: block;
  padding: var(--s-2) var(--s-4);
  font-size: var(--t-sm);
  color: var(--c-text-muted);
}

/* --- Module --- */

/* Modulkarten brauchen Breite: Titel und Zustands-Badge müssen in eine
   Zeile passen, sonst rutscht das Badge bei manchen Karten darunter und
   das Raster franst aus. */
.module-grid {
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}

.module-card .panel-heading {
  flex-wrap: nowrap;
  align-items: center;
}

.module-card .panel-heading h2 {
  min-width: 0;
}

/* Die Steuerung sitzt unten und ist über alle Karten hinweg auf gleicher
   Höhe — dafür schiebt margin-top:auto sie an den Kartenfuß. */
.module-actions {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  margin-top: auto;
  padding-top: var(--s-4);
  border-top: 1px solid var(--c-border);
}

.module-card p {
  color: var(--c-text-muted);
  font-size: var(--t-sm);
}

.is-incompatible {
  opacity: .55;
}

/* --- Domains: die Anleitung liest sich wie ein Rezept --- */

.domain-steps,
.plain-steps {
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
  list-style: none;
  counter-reset: step;
  margin: 0;
  padding: 0;
}

.domain-steps > li,
.plain-steps > li {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  counter-increment: step;
  padding-left: var(--s-7);
  position: relative;
}

.domain-steps > li::before,
.plain-steps > li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 0;
  display: grid;
  place-items: center;
  width: var(--control-h);
  height: var(--control-h);
  border-radius: var(--r-pill);
  background: var(--c-primary-soft);
  color: var(--c-primary);
  font-weight: 600;
  font-size: var(--t-sm);
}

.domain-steps p {
  color: var(--c-text-muted);
  font-size: var(--t-sm);
}

.dns-table {
  width: 100%;
  border-collapse: collapse;
  border: 1px solid var(--c-border);
  border-radius: var(--r-control);
  overflow: hidden;
}

.dns-table th,
.dns-table td {
  padding: var(--s-3) var(--s-4);
  text-align: left;
  border-top: 1px solid var(--c-border);
  font-weight: 400;
}

.dns-table tr:first-child th,
.dns-table tr:first-child td {
  border-top: 0;
}

.dns-table th {
  background: var(--c-surface-sunk);
  color: var(--c-text-muted);
  font-size: var(--t-sm);
  width: 34%;
}

.code-area,
.snippet-preview {
  display: block;
  padding: var(--s-4);
  background: var(--c-surface-sunk);
  border: 1px solid var(--c-border);
  border-radius: var(--r-control);
  overflow-x: auto;
  white-space: pre;
  color: var(--c-text);
}

/* --- Auswahlkarten (Design, Module, Onboarding) --- */

/* Eine Auswahlkarte ist ein <label>. Für Labels gilt weiter oben
   align-items:center — in einer Spalte zentriert das jedes Kind: der
   Radioknopf schwebte mittig über der Karte, die Vorschaufläche schrumpfte
   auf Textbreite, der Titel stand zentriert. Jede Auswahlkarte stellt die
   Ausrichtung deshalb ausdrücklich wieder her. */
:is(.admin, .admin-auth) :is(.option-card, .design-choice, .choice, .template-catalog-card) {
  display: flex;
  align-items: stretch;
  text-align: left;
  cursor: pointer;
  position: relative;
}

/* Karte ohne Vorschaufläche: Kästchen links, Text daneben. */
:is(.admin, .admin-auth) :is(.option-card, .choice) {
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: flex-start;
  gap: var(--s-3);
}

/* flex-basis 0: ohne sie misst der Textblock seine natürliche Breite, passt
   damit nicht mehr neben das Kästchen und bricht darunter um — der Radioknopf
   stand dann allein über dem Text. */
:is(.admin, .admin-auth) :is(.option-card, .choice) > span {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  flex: 1 1 0;
  min-width: 0;
}

/* Das Kästchen steht auf der ersten Textzeile — nicht darüber, nicht mittig
   neben einem dreizeiligen Text. */
:is(.admin, .admin-auth) :is(.option-card, .choice) > input {
  margin-top: 3px;
}

/* Karte mit Vorschaufläche: Bild, darunter Titelzeile mit Auswahlknopf,
   darunter der Erklärtext. */
:is(.admin, .admin-auth) :is(.design-choice, .template-catalog-card) {
  flex-direction: column;
  gap: var(--s-3);
}

/* Titelzeile einer Auswahlkarte: Auswahlknopf und Name in einer Zeile. */
:is(.admin, .admin-auth) .choice-head {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  min-width: 0;
}

:is(.admin, .admin-auth) :is(.design-choice, .template-catalog-card) .status-badge {
  align-self: flex-start;
}

.option-card:hover,
.choice:hover,
.template-catalog-card:hover,
.design-choice:hover {
  border-color: var(--c-border-strong);
}

/* Ausgewählt: Paprika-Rahmen, keine Füllung — der Inhalt bleibt lesbar.
   :has(:checked) markiert die Auswahl sofort beim Klick, nicht erst nach dem
   Speichern; die is-active-Klassen bleiben als serverseitige Entsprechung. */
.option-card.is-active,
.option-card.is-selected,
.design-choice.is-active,
.choice.is-active,
.template-catalog-card.is-active,
:is(.admin, .admin-auth) :is(.option-card, .choice, .design-choice, .template-catalog-card):has(:checked) {
  border-color: var(--c-primary);
  box-shadow: 0 0 0 1px var(--c-primary);
}

.option-card p,
.design-choice p {
  font-size: var(--t-sm);
  color: var(--c-text-muted);
}

/* Feldgruppe (Template-Einstellungen): der Browser-Standard-Fieldset bringt
   eine eigene Kante und eine eingebettete Legende mit — beides passt nicht
   ins System. Wir bauen daraus eine ruhige Gruppe mit Überschrift. */
/* Feldgruppen gelten für JEDES fieldset im Backend, nicht nur für die
   Template-Einstellungen. Der Browser-Standard bringt eine gekerbte Kante
   und eine in die Linie eingelassene Legende mit — beides gehört nicht ins
   System. Daraus wird eine ruhige Gruppe: Trennlinie oben, Legende als
   normale Überschrift darüber.
   Kein eigenes Raster hier — das übernimmt .form-grid / .option-grid innen. */
:is(.admin, .admin-auth) fieldset {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  border: 0;
  border-top: 1px solid var(--c-border);
  margin: 0;
  padding: var(--s-5) 0 0;
  min-width: 0;
}

/* Die erste Gruppe einer Karte braucht keine Trennlinie nach oben. */
:is(.admin, .admin-auth) fieldset:first-of-type {
  border-top: 0;
  padding-top: 0;
}

/* Kein float: die Legende ist eine gewöhnliche Blocküberschrift. Ein
   gefloatetes legend schiebt das nachfolgende Raster aus der Karte heraus. */
:is(.admin, .admin-auth) fieldset > legend {
  display: block;
  width: 100%;
  padding: 0;
  margin-bottom: var(--s-4);
  font-size: var(--t-lg);
  font-weight: 600;
  color: var(--c-text);
}

/* Auch hier steht die Beschriftung über dem Feld. Nebeneinander in einer
   Rasterspalte klebte der Farbwähler am rechten Rand — direkt neben der
   Beschriftung der nächsten Spalte, die er dann zu beschriften schien. */
/* flex-wrap:nowrap ist hier Pflicht: Labels dürfen umbrechen (Grundregel), in
   einer Spalte bricht der Umbruch aber in eine zweite SPALTE — das Feld landete
   dadurch neben seiner Beschriftung statt darunter. */
.admin .template-field {
  flex-direction: column;
  flex-wrap: nowrap;
  align-items: flex-start;
  gap: var(--s-2);
}

.admin .template-field > input[type="color"] {
  margin-left: 0;
}

.admin .template-field > select {
  flex: none;
  width: 100%;
}

/* Was eine Vorlage zeigt: Name, darunter der Zustand. */
.module-compat-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-2);
}

/* Redaktionelle Texte (Claim, Wirtszitat, Herkunft) brauchen die ganze Zeile —
   sie gehören nicht in eine 220px-Rasterspalte neben einen Farbwähler. */
.option-grid > label.is-full {
  grid-column: 1 / -1;
}

/* Vorschaufläche einer Template-Karte: ruhige Platzhalterfläche mit fester
   Proportion, damit die Karten im Raster gleich hoch bleiben.
   width:100% ist Pflicht — ohne sie schrumpft die Fläche auf die Breite ihrer
   Beschriftung und die Karten franst das Raster aus. */
.template-preview,
.design-choice-visual {
  display: grid;
  place-items: center;
  width: 100%;
  aspect-ratio: 16 / 10;
  border-radius: var(--r-control);
  background: var(--c-surface-sunk);
  border: 1px solid var(--c-border);
  color: var(--c-text-muted);
  font-size: var(--t-sm);
  text-align: center;
  padding: var(--s-3);
}

/* --- Design-Seite --- */

/* Das Designformular ist der Seiteninhalt: seine Abschnitte stehen wie überall
   sonst 24px auseinander. Ohne diese Regel klebten die Karten aneinander —
   das Formular war ein blanker Block ohne Abstände. */
.design-builder {
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
}

/* Vorschau des Frontends. Sie zeigt die Farben des Restaurants, nicht die des
   Backends — deshalb ist sie die einzige Fläche im Admin, die fremde Farben
   trägt. Sie bleibt trotzdem eine Karte: 1px Kante, 12px Radius, kein Schatten. */
.design-preview-large {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(200px, 1fr);
  gap: var(--s-5);
  padding: var(--s-6);
  border: 1px solid var(--c-border);
  border-radius: var(--r-card);
  background: var(--restaurant-bg, var(--c-surface-sunk));
  color: var(--restaurant-text, var(--c-text));
}

.design-preview-large > div {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  align-items: flex-start;
  min-width: 0;
}

.admin .design-preview-large h2 {
  color: var(--restaurant-text, var(--c-text));
}

.design-preview-large p {
  color: var(--restaurant-text, var(--c-text));
  opacity: .75;
  max-width: 52ch;
}

/* Der Knopf in der Vorschau ist keine Schaltfläche des Backends, sondern ein
   Bild davon, wie der Knopf auf der Website aussieht. */
.design-preview-large > div > span {
  display: inline-flex;
  align-items: center;
  min-height: var(--control-h);
  padding: 0 var(--s-4);
  border-radius: var(--r-control);
  background: var(--restaurant-primary, var(--c-primary));
  color: #fff;
  font-weight: 600;
}

.design-preview-large aside {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  align-self: start;
  padding: var(--s-4);
  border-radius: var(--r-control);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  color: var(--c-text);
}

.design-preview-large aside small {
  color: var(--c-text-muted);
}

@media (max-width: 720px) {
  .design-preview-large {
    grid-template-columns: 1fr;
    padding: var(--s-5);
  }
}

.color-dots {
  display: flex;
  gap: var(--s-1);
}

/* Jedes Kind ist ein Farbpunkt — im Onboarding sind das <i>, nicht <span>.
   Ein Selektor auf den Elementnamen ließ die Punkte dort unsichtbar werden. */
.color-dots > * {
  display: block;
  width: 20px;
  height: 20px;
  border-radius: var(--r-pill);
  border: 1px solid var(--c-border);
}

.color-controls {
  display: flex;
  gap: var(--s-3);
  flex-wrap: wrap;
}

/* --- Öffnungszeiten --- */

/* Die Seite ist ein Formular, keine Karte: Wochenplan und Vorschau stehen
   nebeneinander, die Speicherleiste klebt darunter. */
.hours-page-form {
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
}

.hours-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(240px, 300px);
  gap: var(--s-5);
  align-items: start;
}

/* margin-left:auto: bricht die Titelzeile um, bleiben die Knöpfe rechts —
   ohne das rutschen sie unter die Überschrift und stehen dort links. */
.hours-head-actions {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin-left: auto;
  flex-wrap: wrap;
}

/* Die Wochenliste ist die Fläche der Karte selbst — sie zieht sich über deren
   ganze Breite und trennt die Tage mit Haarlinien. Ein eigener Rahmen ergäbe
   eine Karte in der Karte. */
.hours-workspace {
  overflow: hidden;
}

.hours-workspace > .hours-week-list {
  border: 0;
  border-radius: 0;
  border-top: 1px solid var(--c-border);
  margin: 0 calc(-1 * var(--s-5)) calc(-1 * var(--s-5));
}

.hours-week-list {
  display: flex;
  flex-direction: column;
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-card);
  overflow: hidden;
}

/* Ausrichtung oben: bei zwei Zeitfenstern (Mittagspause) sollen Tagesname,
   Status und "+" auf Höhe des ersten Fensters stehen, nicht in der Mitte
   zwischen beiden. */
.hours-week-row {
  display: flex;
  align-items: flex-start;
  gap: var(--s-4);
  padding: var(--s-4) var(--s-5);
  border-top: 1px solid var(--c-border);
  flex-wrap: wrap;
}

.hours-week-list > :first-child {
  border-top: 0;
}

.hours-day-name {
  width: 140px;
  flex: none;
  padding-top: var(--s-2);
}

.hours-status-toggle {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  width: 132px;
  flex: none;
}

.admin .hours-status-toggle label {
  flex-direction: row;
  align-items: center;
  gap: var(--s-2);
  min-height: 0;
  font-size: var(--t-sm);
  cursor: pointer;
}

.hours-slots {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  flex: 1;
  min-width: 0;
}

.hours-slot {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex-wrap: wrap;
}

/* "Von" und "Bis" stehen neben dem Feld, nicht darüber: in einer Zeile, die
   sich pro Tag mehrfach wiederholt, wäre eine Beschriftung über jedem Feld
   dreimal dasselbe Wort in voller Textgröße. */
.admin .hours-slot label {
  flex: none;
  flex-direction: row;
  align-items: center;
  gap: var(--s-2);
}

.hours-slot label > span {
  font-size: var(--t-sm);
  color: var(--c-text-muted);
}


.hours-slot-separator {
  color: var(--c-text-muted);
  flex: none;
}

.hours-row-action {
  display: flex;
  flex: none;
}

.hours-week-row.is-closed .hours-slots {
  opacity: .45;
  pointer-events: none;
}

.closed-note {
  color: var(--c-text-muted);
  font-size: var(--t-sm);
}

/* Vorschau: was der Gast auf der Website sehen wird. */
.hours-preview-card {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  position: sticky;
  top: var(--s-5);
}

.hours-preview-card > p:not(.eyebrow) {
  color: var(--c-text-muted);
  font-size: var(--t-sm);
}

.hours-public-list {
  display: flex;
  flex-direction: column;
  margin-top: var(--s-2);
}

.hours-public-list > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  padding: var(--s-2) 0;
  border-top: 1px solid var(--c-border);
}

.hours-public-list > div:first-child {
  border-top: 0;
}

.hours-public-list span {
  color: var(--c-text-muted);
  font-size: var(--t-sm);
  flex: none;
}

.hours-public-list strong {
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* Die Speicherleiste sagt links, was ansteht, und hält rechts die Knöpfe. */
.hours-save-bar {
  justify-content: space-between;
}

.hours-save-bar > span {
  color: var(--c-text-muted);
  font-size: var(--t-sm);
}

.hours-save-bar > div {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}

/* Sonderzeiten sind Zeilen einer Liste, keine Karten in einer Liste. */
.special-hours-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  padding: var(--s-4) var(--s-5);
  border-top: 1px solid var(--c-border);
  min-width: 0;
}

@media (max-width: 1100px) {
  .hours-layout {
    grid-template-columns: 1fr;
  }

  .hours-preview-card {
    position: static;
  }
}

/* --- Baukasten / Seiten-Editor --- */

.builder {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

.builder-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  padding: var(--s-3) var(--s-4);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-card);
  flex-wrap: wrap;
}

.builder-bar-actions,
.builder-devices {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}

.builder-body {
  display: grid;
  gap: var(--s-4);
  grid-template-columns: 240px minmax(0, 1fr) 280px;
  align-items: start;
}

.builder-library,
.builder-inspector,
.builder-outline,
.builder-canvas,
.builder-preview,
.builder-blocks,
.builder-presets,
.builder-revisions {
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-card);
  padding: var(--s-4);
}

.builder-canvas {
  min-height: 420px;
  background: var(--c-surface-sunk);
}

@media (max-width: 1100px) {
  .builder-body { grid-template-columns: 1fr; }
}

/* --- Designer -------------------------------------------------------
   Drei Spalten: Bereiche, Einstellungen, echte Seite. Die Vorschau ist die
   größte Fläche des Bildschirms — sie ist die Antwort auf jede Frage, die
   der Wirt hier stellt.                                                  */

/* Der Designer ist die einzige Seite, die die volle Breite braucht: Links die
   Einstellungen, rechts eine Website in Originalbreite. Die 1180px-Bahn des
   Backends würde die Vorschau auf Tabletmaß eindampfen. */
.admin-main:has(.designer) {
  max-width: none;
}

.designer {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  min-height: 0;
}

.designer-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  flex-wrap: wrap;
}

/* Die drei Stufen. Nicht drei Knöpfe nebeneinander, sondern eine Leiste mit
   Unterkante wie die Tabs im Rest des Backends — wer sie kennt, kennt sie. */
.designer-levels {
  display: flex;
  gap: var(--s-5);
  border-bottom: 1px solid var(--c-border);
}

.admin .designer-level {
  display: block;
  height: auto;
  padding: 0 0 var(--s-3);
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  background: none;
  color: var(--c-text-muted);
  font-weight: 400;
  text-align: left;
  margin-bottom: -1px;
}

.admin .designer-level small {
  display: block;
  color: inherit;
  opacity: .8;
}

.admin .designer-level[aria-selected="true"] {
  color: var(--c-text);
  font-weight: 600;
  border-bottom-color: var(--c-primary);
}

.designer-bar-actions {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex-wrap: wrap;
}

.designer-body {
  display: grid;
  grid-template-columns: 148px minmax(280px, 360px) minmax(0, 1fr);
  gap: var(--s-4);
  align-items: start;
  min-height: 0;
}

/* Code braucht Platz. In der Expertenstufe bekommt die Einstellungsspalte
   deshalb mehr Breite — eine 340px-Spalte, in der man HTML schreiben soll, ist
   eine Zumutung, und die Vorschau bleibt trotzdem groß genug zum Beurteilen. */
.designer[data-level="experte"] .designer-body {
  grid-template-columns: 148px minmax(440px, 620px) minmax(0, 1fr);
}

/* Bereichsleiste */
.designer-rail {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  position: sticky;
  top: var(--s-5);
}

.admin .designer-tab {
  justify-content: flex-start;
  gap: var(--s-3);
  width: 100%;
  border: 0;
  background: none;
  color: var(--c-text-muted);
  font-weight: 400;
  text-align: left;
}

/* Das Icon steht für den Bereich, der Text sagt, welcher es ist. Icon ohne
   Text wäre ein Rätsel — siehe Brandbook, Abschnitt 7. */
.admin .designer-tab .icon { flex: none; }

.admin .designer-tab span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.admin .designer-tab:hover {
  background: var(--c-surface);
  color: var(--c-text);
}

.admin .designer-tab.is-active {
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  color: var(--c-text);
  font-weight: 600;
}

/* Einstellungen */
.designer-panel {
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-card);
  padding: var(--s-5);
  max-height: calc(100vh - 220px);
  overflow-y: auto;
}

.designer-section { display: none; }
.designer-section.is-active {
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
}

.designer-fields {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

.designer-field {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
}

/* Farbe: Beschriftung links, Farbfeld rechts. In einer Spalte von acht Feldern
   liest sich das schneller als acht Labels über acht Quadraten. */
.admin .designer-color {
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
}

.designer-empty {
  color: var(--c-text-muted);
  font-size: var(--t-sm);
}

/* Vorlagen und Presets */
.designer-templates,
.designer-presets {
  display: grid;
  gap: var(--s-2);
}

.admin .designer-template,
.admin .designer-preset {
  display: grid;
  gap: var(--s-1);
  height: auto;
  padding: var(--s-3) var(--s-4);
  text-align: left;
  justify-items: start;
  background: var(--c-surface);
  border: 1px solid var(--c-border-strong);
  border-radius: var(--r-control);
  color: var(--c-text);
  font-weight: 400;
  white-space: normal;
}

.admin .designer-template strong,
.admin .designer-preset strong { font-weight: 600; }

.admin .designer-template small,
.admin .designer-preset small { color: var(--c-text-muted); }

.admin .designer-template:hover,
.admin .designer-preset:hover { border-color: #a9a69f; }

.designer-template:has(:checked),
.admin .designer-preset.is-active {
  border-color: var(--c-primary);
  box-shadow: 0 0 0 1px var(--c-primary);
}

.designer-template input { position: absolute; opacity: 0; pointer-events: none; }

.designer-swatches {
  display: flex;
  gap: var(--s-1);
}

.designer-swatches i {
  display: block;
  width: 20px;
  height: 20px;
  border-radius: var(--r-pill);
  border: 1px solid var(--c-border);
}

/* Vorschau: die echte Seite */
.designer-preview {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  position: sticky;
  top: var(--s-5);
}

.designer-preview-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  flex-wrap: wrap;
}

.designer-pages,
.designer-devices {
  display: flex;
  gap: var(--s-2);
}

.admin .designer-pages .button.is-active,
.admin .designer-devices .icon-button.is-active {
  border-color: var(--c-primary);
  color: var(--c-primary);
  background: var(--c-primary-soft);
}

.designer-quickedit {
  font-size: var(--t-sm);
  color: var(--c-text-muted);
}

/* Die Bühne.

   Das iframe rendert in echter Gerätebreite (--stage-w) und wird als Ganzes
   verkleinert (--stage-scale). Ein "Desktop"-Vorschaufenster, das nur 600px
   breit ist, zeigt sonst das Handy-Layout der Seite — also genau das, was der
   Wirt gerade NICHT prüfen wollte. Lieber klein und richtig als groß und
   falsch. */
.designer-frame {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  height: calc(100vh - 210px);
  min-height: 460px;
  padding: var(--s-4);
  background: var(--c-surface-sunk);
  border: 1px solid var(--c-border);
  border-radius: var(--r-card);
  overflow: hidden;
}

/* Die Hülle ist so groß, wie die Seite *erscheint* (verkleinert) — deshalb
   zentriert sie sich wie jedes normale Element. Die Bühne darin hat die echte
   Gerätebreite und wird von oben links herunterskaliert.

   Der Umweg ist nötig: Ein 1440px breites Element in einem 950px breiten
   Rahmen mittig auszurichten und *danach* zu skalieren, hängt vom
   Transformationsursprung ab und schiebt es zuverlässig aus dem Bild. Layout
   erst, Maßstab zuletzt. */
.designer-shell {
  width: calc(var(--stage-w, 1440px) * var(--stage-scale, 1));
  height: calc(var(--stage-h, 900px) * var(--stage-scale, 1));
  flex: none;
  border-radius: var(--r-control);
  overflow: hidden;
  border: 1px solid var(--c-border);
  background: #fff;
}

.designer-stage {
  width: var(--stage-w, 1440px);
  height: var(--stage-h, 900px);
  transform: scale(var(--stage-scale, 1));
  transform-origin: top left;
  background: #fff;
}

.designer-frame iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
  background: #fff;
}

/* Ein Handy sieht auch im Backend aus wie ein Handy. */
.designer-frame[data-device="phone"] .designer-shell { border-radius: 22px; }

.designer-scale {
  position: absolute;
  bottom: var(--s-3);
  left: var(--s-3);
  padding: var(--s-1) var(--s-3);
  border-radius: var(--r-pill);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  color: var(--c-text-muted);
  font-size: var(--t-sm);
  font-variant-numeric: tabular-nums;
}

.designer-frame-note {
  position: absolute;
  top: var(--s-3);
  right: var(--s-3);
  padding: var(--s-1) var(--s-3);
  border-radius: var(--r-pill);
  background: var(--c-text);
  color: var(--c-bg);
  font-size: var(--t-sm);
}

/* Bildfeld: Vorschau, wählen, entfernen. Das Bild wird sofort hochgeladen —
   die Live-Vorschau lädt die echte Seite und kann nur zeigen, was schon auf dem
   Server liegt. */
.designer-image {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

.designer-image-label {
  font-size: var(--t-md);
}

.designer-image-preview {
  border: 1px solid var(--c-border);
  border-radius: var(--r-control);
  overflow: hidden;
  background: var(--c-surface-sunk);
}

.designer-image-preview img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 180px;
  object-fit: cover;
}

.designer-image-actions {
  display: flex;
  gap: var(--s-2);
  flex-wrap: wrap;
}

/* Das Dateifeld liegt unsichtbar im Knopf — ein nacktes <input type="file">
   sieht in jedem Browser anders aus und passt in kein Designsystem. */
.admin .designer-image-actions label.button {
  cursor: pointer;
}

.designer-image-status.is-error {
  color: var(--c-danger);
}

/* Ein eigener Abschnitt im Designer. */
.designer-sections {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

.designer-block {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  padding: var(--s-4);
  border: 1px solid var(--c-border);
  border-radius: var(--r-card);
  background: var(--c-surface-sunk);
}

.designer-block .admin-toolbar {
  align-items: center;
  flex-wrap: nowrap;
}

.designer-block small {
  color: var(--c-text-muted);
}

.admin .designer-block input,
.admin .designer-block textarea,
.admin .designer-block select {
  background: var(--c-surface);
}

/* --- Aufbau der Seite ------------------------------------------------
   Die Legende: woraus die Seite besteht, von oben nach unten. Bausteine der
   Vorlage und eigene Abschnitte stehen in *einer* Liste — sonst müsste der
   Wirt zwei Ordnungen im Kopf behalten.                                  */

.designer-pagetabs {
  display: flex;
  gap: var(--s-2);
  flex-wrap: wrap;
}

.admin .designer-pagetabs .button.is-active {
  border-color: var(--c-primary);
  background: var(--c-primary-soft);
  color: var(--c-primary);
}

.designer-structure {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

/* Kopf- und Fußzeile stehen fest. Sie werden gezeigt, damit die Legende
   vollständig ist — aber sie lassen sich nicht verschieben, weil eine Seite
   ohne Kopf keine Seite mehr wäre. */
.designer-fixed {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-4);
  border: 1px dashed var(--c-border-strong);
  border-radius: var(--r-control);
  color: var(--c-text-muted);
  font-size: var(--t-sm);
}

.designer-fixed small { margin-left: auto; }

.designer-items {
  display: flex;
  flex-direction: column;
}

.designer-item {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--c-border);
  border-radius: var(--r-control);
  background: var(--c-surface);
  margin-bottom: 2px;
}

.designer-item.is-custom {
  border-color: var(--c-primary);
  border-left-width: 3px;
}

/* Ausgeblendet heißt: steht noch in der Liste, aber nicht auf der Seite.
   Durchgestrichen statt weg — sonst sucht der Wirt es später vergeblich. */
.designer-item.is-off .designer-item-name strong {
  text-decoration: line-through;
  color: var(--c-text-muted);
}

.designer-item.is-off { background: var(--c-surface-sunk); }

/* Wer in der Vorschau auf den Rand eines Bausteins klickt, landet hier. Ohne
   das kurze Aufleuchten sucht man die Zeile in einer langen Liste. */
.designer-item.is-focus {
  border-color: var(--c-primary);
  box-shadow: 0 0 0 3px var(--c-primary-soft);
}

.designer-item-head {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-2) var(--s-3);
}

.designer-item-grip {
  color: var(--c-text-muted);
  cursor: grab;
}

.designer-item-name {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1;
}

.designer-item-name small {
  color: var(--c-primary);
  font-size: var(--t-sm);
}

.designer-item-actions {
  display: flex;
  gap: var(--s-1);
  flex: none;
}

.admin .designer-item-actions .icon-button {
  width: 32px;
  height: 32px;
}

.designer-item-bg {
  padding: var(--s-3);
  border-top: 1px solid var(--c-border);
  background: var(--c-surface-sunk);
}

/* Der Einfügepunkt zwischen zwei Elementen: eine dünne Linie mit einem „+“ in
   der Mitte. Leise, bis die Maus in der Nähe ist — eine Liste voller Knöpfe
   liest sich sonst wie ein Formular. Sichtbar wird sie beim Überfahren der
   Zeile, beim Tastatur-Fokus und solange der Wähler an ihr offen steht. */
.admin .designer-insert {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  width: 100%;
  height: auto;
  min-height: 0;
  padding: var(--s-1) var(--s-3) var(--s-2);
  border: 0;
  background: none;
  color: var(--c-primary);
  font-size: var(--t-sm);
  font-weight: 500;
  opacity: 0;
  transition: opacity .12s ease;
}

/* Die Linie läuft durch, das „+“ sitzt darauf. */
.admin .designer-insert::before,
.admin .designer-insert::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--c-primary);
  opacity: .35;
}

.designer-insert-plus {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  flex: none;
  border-radius: 999px;
  background: var(--c-primary);
  color: #fff;
}

.designer-insert-plus svg { width: 14px; height: 14px; }

.designer-item:hover .designer-insert,
.designer-item:focus-within .designer-insert,
.designer-insert:hover,
.designer-insert:focus-visible,
.designer-insert.is-open {
  opacity: 1;
}

/* Der Knopf unter der Liste ist kein Zwischenraum, sondern ein Ziel — der
   bleibt sichtbar. */
.admin .designer-structure > .designer-insert {
  opacity: 1;
  padding: var(--s-3);
}

/* --- Der Einfüge-Wähler ----------------------------------------------
   Er steht dort, wo der Abschnitt landen wird. Deshalb sieht er aus wie ein
   Platzhalter in der Liste und nicht wie ein Dialog. */

.designer-picker {
  margin: var(--s-2) 0 var(--s-3);
  padding: var(--s-3);
  border: 2px dashed var(--c-primary);
  border-radius: var(--r-control);
  background: var(--c-primary-soft);
}

.designer-picker-head {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin-bottom: var(--s-3);
}

.designer-picker-head strong { flex: 1; }

/* Im Wähler zählt die Wahl, nicht die Erklärung: Symbol und Name, zwei Spalten.
   Fünf ausführliche Karten untereinander wären länger als die halbe Liste — man
   verlöre die Stelle aus den Augen, um die es gerade geht. */
.designer-picker .designer-add {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.admin .designer-picker .designer-add-card {
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-2);
  background: var(--c-surface);
}

.designer-picker .designer-add-card small { display: none; }

/* --- Abschnitte hinzufügen: Karten statt einer Knopfreihe ------------- */

.designer-add {
  display: grid;
  gap: var(--s-2);
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}

.admin .designer-add-card {
  display: grid;
  justify-items: start;
  gap: var(--s-1);
  height: auto;
  padding: var(--s-3);
  border: 1px solid var(--c-border-strong);
  border-radius: var(--r-control);
  background: var(--c-surface);
  color: var(--c-text);
  text-align: left;
  font-weight: 400;
  white-space: normal;
}

.admin .designer-add-card:hover {
  border-color: var(--c-primary);
  background: var(--c-primary-soft);
}

.designer-add-icon {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: var(--r-control);
  background: var(--c-primary-soft);
  color: var(--c-primary);
}

.admin .designer-add-card strong { font-weight: 600; }
.admin .designer-add-card small { color: var(--c-text-muted); }

/* --- Hintergrund-Editor ---------------------------------------------- */

.designer-bg {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}

.designer-bg-fields {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  padding-top: var(--s-3);
  border-top: 1px solid var(--c-border);
}

.designer-bg-fields [data-bg-image] {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}

/* Quickedit-Dialog */
.designer-modal {
  width: min(560px, calc(100% - 2rem));
  padding: var(--s-5);
  border: 1px solid var(--c-border);
  border-radius: var(--r-card);
  background: var(--c-surface);
  color: var(--c-text);
}

.designer-modal::backdrop {
  background: rgba(28, 27, 25, .45);
}

.designer-modal-body {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  margin: var(--s-4) 0;
}

.designer-modal-body:empty {
  margin: 0;
}

/* Wege zu den Stellen, an denen der Inhalt wirklich gepflegt wird:
   Speisekarte, Öffnungszeiten, Stammdaten. */
.designer-modal-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-bottom: var(--s-4);
}

.designer-modal .alert {
  margin-top: var(--s-4);
}

.designer-help summary {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  cursor: pointer;
  font-weight: 600;
}

.designer-help > *,
.designer-section > .detail-list {
  margin-top: var(--s-3);
}

.designer-help code,
.designer-section code {
  word-break: break-word;
}

/* Bausteine zum Einsetzen: kleine Knöpfe, die Code an die Cursorstelle
   schreiben. Wer HTML kann, spart sich Tipparbeit — wer es nicht kann, kommt
   trotzdem zu einem funktionierenden Baustein. */
.designer-snips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}

.admin .designer-snips .button {
  height: auto;
  min-height: 32px;
  padding: var(--s-1) var(--s-3);
  font-size: var(--t-sm);
  font-weight: 400;
}

/* Ein überschreibbarer Baustein: Titelzeile mit „Original einfügen“ und
   „Zurücksetzen“, darunter das Codefeld. */
.designer-override {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  padding: var(--s-4);
  border: 1px solid var(--c-border);
  border-radius: var(--r-card);
  background: var(--c-surface-sunk);
}

.designer-override .code-area {
  background: var(--c-surface);
  min-height: 200px;
  resize: vertical;
  /* Zeilenumbruch statt Seitwärtsscrollen: Wer eine lange Zeile HTML schreibt,
     soll sie lesen können, ohne zu scrollen. */
  white-space: pre-wrap;
  word-break: break-word;
}

/* Die beiden Knöpfe stehen nebeneinander, nicht übereinander. */
.designer-override .admin-toolbar {
  align-items: center;
  flex-wrap: nowrap;
  gap: var(--s-2);
}

.designer-override .admin-header-actions {
  flex-wrap: nowrap;
}

.admin .designer-override .button {
  white-space: nowrap;
}

.admin .designer-section .alert .icon {
  flex: none;
  margin-top: 2px;
  color: var(--c-primary);
}

.admin .designer-section h3 {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}

@media (max-width: 1280px) {
  .designer-body { grid-template-columns: 132px minmax(0, 1fr); }

  /* Auf schmalen Schirmen wandert die Vorschau unter die Einstellungen —
     sie bleibt sichtbar, nur nicht mehr daneben. */
  .designer-preview {
    grid-column: 1 / -1;
    position: static;
  }

  .designer-frame { height: 70vh; }
  .designer-panel { max-height: none; }
}

@media (max-width: 720px) {
  .designer-body { grid-template-columns: 1fr; }

  .designer-rail {
    flex-direction: row;
    overflow-x: auto;
    position: static;
  }

  .admin .designer-tab { width: auto; white-space: nowrap; }
}


/* --- Onboarding / Login --- */

body.admin-auth {
  display: grid;
  place-items: center;
  min-height: 100vh;
  padding: var(--s-5);
}

.login-card {
  width: 100%;
  max-width: 440px;
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-card);
  padding: var(--s-6);
}

/* Beim Anmelden gibt es genau eine Handlung — der Knopf nimmt die volle
   Breite ein, damit sie nicht gesucht werden muss. */
.login-card .button-primary {
  width: 100%;
  margin-top: var(--s-2);
}

.login-card .form-note {
  text-align: center;
}

/* Installer und Onboarding tragen mehr Felder als ein Login — sie brauchen
   Breite, sonst quetscht sich das Formular in eine 440px-Spalte. */
.login-card.wide {
  max-width: 720px;
}

.onboarding-progress {
  display: flex;
  gap: var(--s-2);
}

.onboarding-progress > * {
  flex: 1;
  height: 4px;
  border-radius: var(--r-pill);
  background: var(--c-border);
}

.onboarding-progress > .is-active,
.onboarding-progress > .is-done {
  background: var(--c-primary);
}

/* --- Auslastung über den Tag --- */

/* Ein Balken je Zeitfenster, von unten gefüllt — so wie es das Markup
   vorgibt (Füllhöhe in Prozent, Uhrzeit darunter). Die alte Regel zeichnete
   waagerechte 8px-Streifen: die Füllhöhe lief ins Leere und die Uhrzeiten
   lagen quer über den Balken. */
.load-chart {
  display: flex;
  align-items: stretch;
  gap: var(--s-1);
  height: 180px;
  overflow-x: auto;
}

.load-bar {
  position: relative;
  display: flex;
  align-items: flex-end;
  flex: 1 1 0;
  min-width: 32px;
  height: calc(100% - 24px);
  background: var(--c-surface-sunk);
  border: 1px solid var(--c-border);
  border-radius: var(--r-control);
}

.load-bar > span {
  display: block;
  width: 100%;
  border-radius: var(--r-control);
  background: var(--c-primary);
}

.load-bar > span.is-full {
  background: var(--c-danger);
}

.load-bar small {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  padding-top: var(--s-1);
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* --- Upload --- */

/* Auch hier: kein Umbruch in einer Spalte — sonst landet das Dateifeld als
   zweite Spalte neben der Beschriftung und läuft aus der Karte heraus. */
.admin .upload-box {
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-6);
  border: 1px dashed var(--c-border-strong);
  border-radius: var(--r-card);
  background: var(--c-surface-sunk);
  text-align: center;
}

/* Ein Dateifeld ist so breit wie sein Inhalt, nicht so breit wie die Karte. */
.admin .upload-box > input[type="file"] {
  flex: none;
  width: auto;
  max-width: 100%;
  padding: var(--s-1) var(--s-2);
  background: var(--c-surface);
}


/* === 10. RESPONSIV ================================================ */

@media (max-width: 960px) {
  body.admin {
    grid-template-columns: 1fr;
  }

  .admin-sidebar {
    position: static;
    height: auto;
    padding: var(--s-4);
  }

  /* Auf Mobile wird die Navigation waagerecht und scrollt —
     kein Hamburger, der eine Ebene versteckt. */
  .admin-nav {
    flex-direction: row;
    gap: var(--s-4);
    overflow-x: auto;
    padding-bottom: var(--s-2);
  }

  .nav-group {
    flex-direction: row;
    gap: var(--s-1);
    flex: none;
  }

  .nav-group h2 {
    display: none;
  }

  .admin-sidebar nav a {
    white-space: nowrap;
  }

  .admin-sidebar-footer {
    flex-direction: row;
  }

  .admin-main {
    padding: var(--s-4);
  }

  .sticky-save,
  .hours-save-bar {
    margin: 0 calc(-1 * var(--s-4)) calc(-1 * var(--s-4));
  }

  .admin-header {
    align-items: flex-start;
  }

  .hours-day-name {
    width: 100%;
  }
}

@media (max-width: 560px) {
  .admin-row,
  .record-row {
    flex-direction: column;
    align-items: stretch;
  }

  .row-actions {
    justify-content: flex-start;
  }

  .admin h1 { font-size: 24px; }

  .quick-actions .button,
  .form-actions .button {
    flex: 1 1 100%;
  }
}
