/* EventAI Design System v1.0 — Primitive
   ==========================================================================
   Die Bausteine, die auf jeder Seite vorkommen: Flaechen, Schrift, Buttons,
   Statusabzeichen, Eingabefelder. Grundlage ist ausschliesslich tokens.css —
   in dieser Datei steht kein einziger fester Farbwert und keine feste
   Groesse ausser 1px-Linien.

   Was hier *nicht* steht: Galerie, Event Cards, Device Cards, Analytics.
   Das sind zusammengesetzte Ansichten und gehoeren in eigene Dateien.

   Reihenfolge
     1. Grundlage
     2. Typografie
     3. Layout
     4. Cards
     5. Buttons
     6. Status Badges
     7. Formulare
     8. Bilder
     9. Dialoge
   ========================================================================== */


/* 1. Grundlage ------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  font-weight: var(--weight-regular);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

[x-cloak] { display: none !important; }

/* Ein einziger Fokusstil fuer die ganze Plattform. :focus-visible statt
   :focus, damit ein Mausklick keinen Ring hinterlaesst, die Tastatur aber
   immer einen. Der Ring liegt aussen (outline-offset), damit er auch auf
   einer farbigen Flaeche sichtbar bleibt. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Der erste Tabstopp jeder Seite. Sichtbar nur fuer die Tastatur — wer mit
   der Maus kommt, sieht ihn nie, wer sich durchtabbt, muss nicht erst durch
   die ganze Navigation. */
.skip-link {
  position: absolute;
  top: var(--space-2);
  left: var(--space-2);
  z-index: var(--z-toast);
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  color: var(--color-text);
  font-size: var(--text-small);
  font-weight: var(--weight-semibold);
  text-decoration: none;
  transform: translateY(calc(-100% - var(--space-4)));
  transition: transform var(--duration-hover) var(--ease-out);
}
.skip-link:focus-visible { transform: none; }

/* Icons kommen aus einem SVG-Sprite und erben Farbe und Groesse vom Text:
   1.25em, damit ein Icon neben 14px-Schrift genauso sitzt wie neben 16px.
   flex: none, weil ein Icon in einer engen Zeile nie zusammengedrueckt
   werden darf — dann ist es unkenntlich. */
.icon {
  width: 1.25em;
  height: 1.25em;
  flex: none;
}
.icon--sm { width: 1em; height: 1em; }

/* Die Wortmarke. Steht in components.css und nicht bei einer einzelnen
   Ansicht, weil sie inzwischen an vier Stellen vorkommt: Startseite,
   Galerie, Anmeldung und Betreiberzentrale. Ein Baustein, der in vier
   Ansichten auftaucht, ist ein Primitiv. */
.brandmark {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--color-text);
  font-size: var(--text-h3);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-heading);
  text-decoration: none;
}
.brandmark:hover { color: var(--color-text); }
.brandmark__icon {
  width: 1.15em;
  height: 1.15em;
  flex: none;
  color: var(--color-primary);
}

/* Hinweiszeile. Farbe traegt die Aussage nie allein - jede Zeile hat ein
   Symbol und Text. */
.hinweis {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  margin: 0;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  font-size: var(--text-small);
}
.hinweis--info    { background: var(--color-primary-soft); color: var(--color-primary-ink); }
.hinweis--warnung { background: var(--color-warning-soft); color: var(--color-warning-ink); }
.hinweis--fehler  { background: var(--color-error-soft);   color: var(--color-error-ink); }

/* Filterknopf, rund. Ebenfalls in mehreren Ansichten: Galerie und
   Zentrale. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 40px;
  padding: var(--space-2) var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  color: var(--color-text-muted);
  font: inherit;
  font-size: var(--text-small);
  font-weight: var(--weight-medium);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--duration-hover) var(--ease-out),
              border-color var(--duration-hover) var(--ease-out),
              color var(--duration-hover) var(--ease-out);
}
.chip:hover { border-color: var(--color-border-strong); color: var(--color-text); }
.chip--aktiv {
  background: var(--color-primary-strong);
  border-color: transparent;
  color: var(--color-text-on-fill);
}
.chip--aktiv:hover { color: var(--color-text-on-fill); }

/* Der Umschalter fuer helles und dunkles Erscheinungsbild zeigt immer das
   Ziel, nicht den Zustand. */
.themetoggle__sun  { display: none; }
.themetoggle__moon { display: block; }
:root[data-theme="dark"] .themetoggle__sun  { display: block; }
:root[data-theme="dark"] .themetoggle__moon { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .themetoggle__sun  { display: block; }
  :root:not([data-theme="light"]) .themetoggle__moon { display: none; }
}

/* Sichtbar nur fuer Screenreader. Fuer Beschriftungen, die im Bild stehen
   und deshalb nicht als Text vorkommen. */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}


/* 2. Typografie ------------------------------------------------------------ */
.t-display, .t-hero, .t-h1, .t-h2, .t-h3 {
  margin: 0;
  font-weight: var(--weight-semibold);
  line-height: var(--leading-heading);
  letter-spacing: var(--tracking-heading);
  text-wrap: balance;
}
.t-display {
  font-size: var(--text-display);
  line-height: var(--leading-display);
  letter-spacing: var(--tracking-display);
  font-weight: var(--weight-bold);
}
.t-hero {
  font-size: var(--text-hero);
  line-height: var(--leading-display);
  letter-spacing: var(--tracking-display);
  font-weight: var(--weight-bold);
}
.t-h1 { font-size: var(--text-h1); }
.t-h2 { font-size: var(--text-h2); }
.t-h3 { font-size: var(--text-h3); font-weight: var(--weight-medium); }

.t-body    { font-size: var(--text-body);    line-height: var(--leading-body); margin: 0; }
.t-small   { font-size: var(--text-small);   line-height: var(--leading-tight); margin: 0; }
.t-caption { font-size: var(--text-caption); line-height: var(--leading-tight); margin: 0; }

/* Das Label ueber einer Kennzahl. Grossbuchstaben brauchen Laufweite,
   sonst kleben sie. */
.t-label {
  font-size: var(--text-caption);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caption);
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin: 0;
}

/* Zahlen, die sich laufend aendern (Queue, Temperatur, Besucher), duerfen
   beim Aendern nicht springen. */
.t-numeric {
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-heading);
}

.t-muted  { color: var(--color-text-muted); }
.t-subtle { color: var(--color-text-subtle); }

a { color: var(--color-primary-ink); text-underline-offset: 0.2em; }
a:hover { color: var(--color-accent-ink); }


/* 3. Layout ---------------------------------------------------------------- */
.page {
  max-width: var(--content-width);
  margin-inline: auto;
  padding-inline: var(--page-padding);
  padding-block: var(--space-7) var(--space-9);
}
.page--narrow { max-width: var(--content-narrow); }

/* Der senkrechte Rhythmus einer Seite. Grosszuegig, wie festgelegt. */
.stack       { display: flex; flex-direction: column; gap: var(--space-5); }
.stack--tight { gap: var(--space-3); }
.stack--loose { gap: var(--space-7); }

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

/* Das Raster: 12 Spalten auf dem Desktop, 8 auf dem Tablet, 4 mobil. Wer
   eine Card ueber mehrere Spalten legt, nutzt --span. */
.grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--gutter);
}
@media (min-width: 640px)  { .grid { grid-template-columns: repeat(8, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .grid { grid-template-columns: repeat(12, minmax(0, 1fr)); } }

.grid > * { grid-column: span 4; }
@media (min-width: 640px)  { .grid > [data-span-tablet="4"]  { grid-column: span 4; }
                             .grid > [data-span-tablet="8"]  { grid-column: span 8; } }
@media (min-width: 1024px) { .grid > [data-span="3"]  { grid-column: span 3; }
                             .grid > [data-span="4"]  { grid-column: span 4; }
                             .grid > [data-span="6"]  { grid-column: span 6; }
                             .grid > [data-span="8"]  { grid-column: span 8; }
                             .grid > [data-span="12"] { grid-column: span 12; } }


/* 4. Cards ----------------------------------------------------------------- */
.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: var(--space-5);
}
.card--lg   { border-radius: var(--radius-lg);   padding: var(--space-6); }
.card--hero { border-radius: var(--radius-hero); padding: var(--space-7); box-shadow: var(--shadow-lg); }

/* Eine Card, die sich anklicken laesst, hebt sich beim Ueberfahren an.
   Das ist der einzige Hover-Effekt der Plattform, der nicht eine
   Zustandsaenderung erklaert, sondern Anfassbarkeit — deshalb sehr klein. */
.card--interactive {
  cursor: pointer;
  transition:
      transform   var(--duration-hover) var(--ease-spring),
      box-shadow  var(--duration-hover) var(--ease-out),
      border-color var(--duration-hover) var(--ease-out);
}
.card--interactive:hover,
.card--interactive:focus-within {
  transform: translateY(var(--lift-hover));
  box-shadow: var(--shadow-md);
  border-color: var(--color-border-strong);
}

/* Die Kennzahl-Card aus dem Dashboard. Label oben, Zahl gross, Hinweis
   klein — keine Tabelle. */
.stat { display: flex; flex-direction: column; gap: var(--space-1); }
.stat__value {
  font-size: var(--text-h2);
  font-weight: var(--weight-semibold);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-heading);
}
.stat__note { font-size: var(--text-small); color: var(--color-text-muted); }


/* 5. Buttons ---------------------------------------------------------------
   Vier Sorten, eine Groessenskala. Die Mindesthoehe von 44px ist keine
   Optik, sondern die Touch-Flaeche aus den Accessibility-Vorgaben — am
   Geraet steht jemand mit nassen Fingern vor einem Tablet. */
.btn {
  --btn-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--btn-height);
  padding-inline: var(--space-5);
  border: 1px solid transparent;
  border-radius: var(--radius-button);
  font: inherit;
  font-size: var(--text-small);
  font-weight: var(--weight-semibold);
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition:
      transform   var(--duration-hover) var(--ease-spring),
      box-shadow  var(--duration-hover) var(--ease-out),
      background  var(--duration-hover) var(--ease-out),
      border-color var(--duration-hover) var(--ease-out),
      color       var(--duration-hover) var(--ease-out);
}
.btn--lg { --btn-height: 56px; padding-inline: var(--space-6); font-size: var(--text-body); }
.btn--sm { --btn-height: 36px; padding-inline: var(--space-4); font-size: var(--text-caption); }

.btn:disabled, .btn[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

/* Primaer: Verlauf Indigo zu Violett, beim Ueberfahren 2px Lift und ein
   leichter Glow — der Glow ist Farbe, die aus dem Button austritt, kein
   zweiter Schatten. */
.btn--primary {
  background: var(--gradient-primary);
  color: var(--color-text-on-fill);
  box-shadow: var(--shadow-sm);
}
.btn--primary:hover:not(:disabled) {
  transform: translateY(var(--lift-hover));
  box-shadow: var(--glow-primary);
}
.btn--primary:active:not(:disabled) { transform: translateY(0); box-shadow: var(--shadow-sm); }

/* Akzent: der eine, herausgehobene Handlungsaufruf pro Ansicht.
   Die Fuellung ist --color-accent-strong, nicht --color-accent: Weiss auf
   dem hellen Coral haette nur 2,97:1. */
.btn--accent {
  background: var(--color-accent-strong);
  color: var(--color-text-on-fill);
  box-shadow: var(--shadow-sm);
}
.btn--accent:hover:not(:disabled) {
  transform: translateY(var(--lift-hover));
  box-shadow: var(--glow-accent);
}

.btn--secondary {
  background: var(--color-surface);
  border-color: var(--color-border-strong);
  color: var(--color-text);
}
.btn--secondary:hover:not(:disabled) {
  border-color: var(--color-primary);
  color: var(--color-primary-ink);
  transform: translateY(var(--lift-hover));
  box-shadow: var(--shadow-sm);
}

.btn--ghost {
  background: transparent;
  color: var(--color-text-muted);
  padding-inline: var(--space-3);
}
.btn--ghost:hover:not(:disabled) {
  background: var(--overlay-hover);
  color: var(--color-text);
}

.btn--danger {
  background: var(--color-error-strong);
  color: var(--color-text-on-fill);
}
.btn--danger:hover:not(:disabled) { transform: translateY(var(--lift-hover)); box-shadow: var(--shadow-md); }

/* Ein runder Schalter fuer ein einzelnes Icon — Herz, Download, Mehr.
   Traegt immer ein aria-label, weil er keinen Text hat. */
.btn--icon {
  --btn-height: 44px;
  width: var(--btn-height);
  padding: 0;
  border-radius: var(--radius-pill);
}


/* 6. Status Badges ---------------------------------------------------------
   Vier Zustaende. Farbe allein traegt die Aussage nicht — jeder Badge hat
   auch Text, damit er ohne Farbwahrnehmung funktioniert. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  font-size: var(--text-caption);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.01em;
  white-space: nowrap;
}
.badge__dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; }

.badge--live      { background: var(--color-success-soft); color: var(--color-success-ink); }
.badge--preparing { background: var(--color-warning-soft); color: var(--color-warning-ink); }
.badge--offline   { background: var(--color-error-soft);   color: var(--color-error-ink); }
.badge--finished  { background: var(--color-neutral-soft); color: var(--color-neutral-ink); }

/* Reifegrad eines Themes je Ausfuehrungsprofil. Dieselben vier Farben wie
   oben, weil sie dasselbe meinen: fertig, in Arbeit, kaputt, ruht. Der
   Text steht immer daneben — siehe themes/reife.py. */
.badge--production   { background: var(--color-success-soft); color: var(--color-success-ink); }
.badge--candidate    { background: var(--color-warning-soft); color: var(--color-warning-ink); }
.badge--experimental { background: var(--color-neutral-soft); color: var(--color-neutral-ink); }
.badge--blocked      { background: var(--color-error-soft);   color: var(--color-error-ink); }

/* Aufzaehlung ohne Punkte, fuer Begruendungen unter einem Badge. */
.liste--blank { list-style: none; margin: var(--space-1) 0 0; padding: 0; }

/* Nur "Live" pulsiert. Der Punkt selbst bleibt ruhig; nur ein Ring darum
   laeuft nach aussen — ein blinkender Punkt zieht das Auge staendig weg,
   ein auslaufender Ring nur beim Wechsel. */
.badge--live .badge__dot { position: relative; }
.badge--live .badge__dot::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: currentColor;
  animation: pulse-ring 2s var(--ease-out) infinite;
}
@keyframes pulse-ring {
  0%   { transform: scale(1);   opacity: 0.7; }
  70%  { transform: scale(2.6); opacity: 0; }
  100% { transform: scale(2.6); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .badge--live .badge__dot::after { animation: none; }
}


/* 7. Formulare -------------------------------------------------------------
   Sehr grosse Eingabefelder, wenig Linien. Die Beschriftung steht ueber
   dem Feld, nicht darin — ein Platzhalter als Beschriftung verschwindet
   beim Tippen genau dann, wenn man ihn braucht. */
.field { display: flex; flex-direction: column; gap: var(--space-2); }

.field__label {
  font-size: var(--text-small);
  font-weight: var(--weight-medium);
  color: var(--color-text);
}
.field__hint { font-size: var(--text-small); color: var(--color-text-muted); }

.input, .select, .textarea {
  width: 100%;
  min-height: 56px;
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  color: var(--color-text);
  font: inherit;
  font-size: var(--text-body);
  transition: border-color var(--duration-hover) var(--ease-out),
              box-shadow   var(--duration-hover) var(--ease-out);
}
.textarea { min-height: 120px; resize: vertical; line-height: var(--leading-body); }

.input::placeholder, .textarea::placeholder { color: var(--color-text-subtle); }

.input:hover, .select:hover, .textarea:hover { border-color: var(--color-text-subtle); }

.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--color-focus);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-focus) 22%, transparent);
}

/* Fehler: roter Rahmen *und* Text. Der Rahmen allein waere fuer
   Rot-Gruen-Blindheit unsichtbar. */
.field--error .input,
.field--error .select,
.field--error .textarea { border-color: var(--color-error); }
.field__error {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-small);
  font-weight: var(--weight-medium);
  color: var(--color-error-ink);
}


/* 8. Bilder ----------------------------------------------------------------
   Bilder sind der wichtigste Inhalt der Plattform. Deshalb: nie verzerren,
   nie ohne reservierten Platz laden (sonst springt das Layout, wenn ein
   Bild ankommt), und ein Platzhalter, der nicht nach Fehler aussieht. */
.media {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-md);
  background: var(--color-surface-sunken);
}
.media > img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.media--square    { aspect-ratio: 1 / 1; }
.media--portrait  { aspect-ratio: 3 / 4; }
.media--landscape { aspect-ratio: 3 / 2; }
.media--hero      { aspect-ratio: 21 / 9; border-radius: var(--radius-hero); }

/* Der Verlauf, auf dem Schrift ueber einem Bild steht. */
.media__scrim {
  position: absolute;
  inset: 0;
  background: var(--overlay-image);
  pointer-events: none;
}
.media__caption {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  padding: var(--space-4);
  color: #FFFFFF;
}


/* 9. Dialoge ---------------------------------------------------------------
   Zentriert, grosser Radius, unscharfer Hintergrund. backdrop-filter ist
   Zuckerguss: wo er fehlt, bleibt die abgedunkelte Flaeche und der Dialog
   funktioniert unveraendert. */
.dialog {
  padding: 0;
  border: none;
  max-width: min(560px, calc(100vw - 2 * var(--space-5)));
  background: var(--color-surface-raised);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  color: var(--color-text);
}
.dialog::backdrop {
  background: var(--overlay-scrim);
  backdrop-filter: blur(8px);
}
.dialog__body   { padding: var(--space-6); }
.dialog__footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-6) var(--space-6);
}
.dialog[open] { animation: dialog-in var(--duration-dialog) var(--ease-out); }
@keyframes dialog-in {
  from { opacity: 0; transform: translateY(8px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}
