/* ==========================================================================
   app.css — Layout und Komponenten
   ==========================================================================

   Enthält keinen Farbwert und keine literale Länge: beides kommt aus
   tokens.css über var(). `font-family` steht hier nur als var(--font-…) oder
   als `inherit` (Formularelemente erben die Schrift sonst nicht). Prüfbar mit

     grep -nE '#[0-9a-fA-F]{3,6}|[0-9]+(px|pt|em)' public/assets/app.css

   Was dieser Befehl findet, sind Kommentare — keine Deklarationen.

   Zwei bewusste Ausnahmen von der var()-Regel:
   - Die Haltepunkte der Media Queries. CSS erlaubt in `@media (max-width: …)`
     keine Custom Property, der Wert muss dort literal stehen. Es ist ein
     Haltepunkt, in rem, an allen Stellen derselbe und kommentiert.
   - Prozent- und Sekundenwerte in @keyframes und bei width/height in Prozent:
     sie beschreiben ein Verhältnis, keine Größe, und gehören nicht in ein Token.

   Gestaltungsentscheidungen, die hier durchgehalten werden:
   - Kopf und Fuß sind Ink-Navy-Flächen, dazwischen liegt Cream
   - Überschriften in Fraunces, mit einem kurzen Gold-Strich darunter
   - Eyebrow-Label in IBM Plex Mono, versal und gesperrt, vor der Überschrift
   - Zeilen mit Haarlinie statt Karten mit Schatten (Register, nicht Dashboard)
   - Werte aus dem Register in --font-value mit tabular-nums
   - Zustand immer über Farbe UND Form UND Text, nie über Farbe allein
   ========================================================================== */

/* == Grundlagen =========================================================== */

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

html {
  /* Mobile Safari vergrößert Text im Querformat sonst eigenmächtig. */
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-text);
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  /* Verhindert seitliches Wackeln, wenn eine lange Zeile doch mal breiter ist
     als der Viewport. */
  overflow-wrap: break-word;
}

/* Überschriften tragen die Serife, der Fließtext nicht. Fraunces hat eine
   opsz-Achse: font-optical-sizing sorgt dafür, dass die große Variante im
   Aufmacher feinere Striche bekommt als die kleine in der Karte — das ist der
   Grund, diese Schrift zu nehmen, und es kostet nichts. */
h1, h2, h3 {
  margin: 0;
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--heading);
}
h1 { font-size: var(--fs-h1); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); font-weight: var(--fw-bold); }

p { margin: 0; }

/* Verweise werden nicht über die Farbe erkennbar gemacht, sondern über die
   Unterstreichung — Gold hätte auf Cream nur 2.14:1 und wäre als alleiniges
   Merkmal weder sichtbar noch nach 1.4.1 zulässig. Also: Text bleibt in der
   Textfarbe, die Linie darunter ist golden, beim Überfahren wird beides
   kräftiger. */
a {
  color: var(--text);
  text-decoration-color: var(--rule-brand);
  text-decoration-thickness: var(--border);
  text-underline-offset: var(--space-1);
}
a:hover {
  color: var(--action-ink);
  text-decoration-color: var(--action-ink);
  text-decoration-thickness: var(--border-mark);
}

/* Sichtbarer Fokus, überall, mit dem Doppelring aus tokens.css. Kein
   `outline: none` in dieser Datei — und es soll auch keins dazukommen. */
:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius);
}
/* Auf den Ink-Navy-Flächen wäre der dunkle Ring unsichtbar. Dort Gold.
   .masthead und .site-footer sind immer dunkel und stehen deshalb mit in der
   Liste — auch ohne dass die Seite sie zusätzlich als .on-dark auszeichnet. */
.on-dark :focus-visible,
.panel :focus-visible,
.masthead :focus-visible,
.site-footer :focus-visible { box-shadow: var(--focus-ring-dark); }

/* Nur für Screenreader. Wird gebraucht, weil der Zustand einer Stufe in der
   Belegspur grafisch als Form dargestellt wird — die Form muss auch als Wort
   vorliegen. */
.sr-only {
  position: absolute;
  width: var(--border);
  height: var(--border);
  padding: 0;
  margin: calc(var(--border) * -1);
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Sprunglink zum Inhalt — sichtbar erst bei Tastaturfokus. */
.skip {
  position: absolute;
  left: var(--space-3);
  top: calc(var(--space-8) * -1);
  z-index: 10;
  padding: var(--space-2) var(--space-3);
  background: var(--surface);
  border: var(--border) solid var(--rule-strong);
  border-radius: var(--radius);
  text-decoration: none;
  transition: top var(--dur-fast) var(--ease);
}
.skip:focus { top: var(--space-3); }


/* == Werte aus dem Register =============================================== */

/* Monospace bedeutet in dieser UI: das ist eine belegte Angabe. Diese Regel
   ist älter als das jetzige Aussehen — IBM Plex Mono übernimmt sie nur. */
.value {
  font-family: var(--font-value);
  font-variant-numeric: tabular-nums;
  font-size: 0.9em;   /* Plex Mono läuft groß; ohne das steht es neben der
                         Source Sans zu wuchtig */
  letter-spacing: 0;
}

/* Feldlabel im Stil eines Formblatts. */
.label {
  display: block;
  font-family: var(--font-value);
  font-size: var(--fs-label);
  font-weight: var(--fw-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-3);
}

/* Eyebrow: die kleine versale Zeile über einer Überschrift. Sagt, worum es im
   folgenden Abschnitt geht, bevor die Überschrift es ausspricht. Sage statt
   Gold, weil sie klein gesetzt ist und Gold dort mit 2.14:1 nicht mehr
   lesbar wäre. */
.eyebrow {
  display: block;
  font-family: var(--font-value);
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-medium);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--space-3);
}
.eyebrow--gold { color: var(--action-ink); }
.on-dark .eyebrow,
.panel .eyebrow { color: var(--on-dark-accent); }

/* Der Gold-Strich unter einer Überschrift. Kurz, nicht über die volle Breite:
   er markiert den Anfang eines Abschnitts, er unterstreicht keinen Satz. */
.headline,
.hero h1,
.section > h2,
.page-head > div > h1 {
  position: relative;
  padding-bottom: var(--space-3);
}
.headline::after,
.hero h1::after,
.section > h2::after,
.page-head > div > h1::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: var(--rule-len);
  height: var(--border-brand);
  background: var(--rule-brand);
}


/* == Seitengerüst ========================================================= */

/* Kopf und Fuß sind dieselbe dunkle Fläche und klammern die Seite. */
.masthead {
  background: var(--surface-dark);
  color: var(--on-dark);
  border-bottom: var(--border-brand) solid var(--rule-brand);
}
.masthead-inner {
  max-width: var(--w-page);
  margin: 0 auto;
  padding: var(--space-3) var(--space-4);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}
.wordmark {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin-right: auto;
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-tight);
  color: var(--on-dark);
  text-decoration: none;
}
/* Das Signaturzeichen im Kleinen: eine gefüllte Marke wie die der Belegspur. */
.wordmark::before {
  content: "";
  align-self: center;
  width: var(--space-2);
  height: var(--space-2);
  background: var(--on-dark-accent);
  flex: none;
}
.wordmark span {
  font-family: var(--font-value);
  font-size: var(--fs-xs);
  font-weight: var(--fw-normal);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--on-dark-2);
}

.page {
  max-width: var(--w-page);
  margin: 0 auto;
  padding: var(--space-6) var(--space-4) var(--space-8);
}
.page--narrow { max-width: var(--w-form); }
.page--wide   { max-width: var(--w-wide); }

.page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3);
  margin-bottom: var(--space-6);
}
.page-head > :first-child { margin-right: auto; }
.page-head p { color: var(--text-2); font-size: var(--fs-sm); }

.prose { max-width: var(--measure); color: var(--text); }
.prose + .prose { margin-top: var(--space-3); }

.stack        { display: grid; gap: var(--space-4); }
.stack--tight { display: grid; gap: var(--space-2); }
.stack--wide  { display: grid; gap: var(--space-7); }
.row-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
}


/* == Fläche =============================================================== */

.sheet {
  background: var(--surface);
  border: var(--border) solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.sheet-head {
  padding: var(--space-4);
  border-bottom: var(--border) solid var(--rule);
}
.sheet-body { padding: var(--space-5); }

/* Fläche für den Fehlerfall. Eigene Variante statt .notice zusätzlich auf
   .sheet: die beiden bringen unterschiedliches Innenmaß und Layout mit und
   würden sich gegenseitig überschreiben. */
.sheet--alert {
  border-color: var(--danger);
  border-left-width: var(--space-1);
  background: var(--danger-soft);
  color: var(--danger-ink);
}
.sheet--alert h2 { color: var(--danger-ink); }
.sheet--alert h2::after { background: var(--danger); }
.sheet--alert .prose { color: var(--danger-ink); }

/* Dunkler Abschnitt mitten auf der Seite — für den einen Absatz, der die
   Seite trägt. Sparsam einsetzen, sonst verliert er die Wirkung. */
.panel {
  background: var(--surface-dark);
  color: var(--on-dark);
  border-radius: var(--radius);
  padding: var(--space-6) var(--space-5);
}
.panel h2, .panel h3 { color: var(--on-dark); }
.panel p { color: var(--on-dark-2); }
.panel .prose { color: var(--on-dark-2); }
.panel a { color: var(--on-dark); text-decoration-color: var(--on-dark-accent); }
.panel a:hover { color: var(--on-dark-accent); text-decoration-color: var(--on-dark-accent); }
.panel .value { color: var(--on-dark); }


/* == Schaltflächen ======================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  /* Mindestens 44px Trefferfläche für den Daumen — hier über die
     Zeilenhöhe plus Innenabstand erreicht, nicht über eine feste Höhe, damit
     die Schaltfläche mit der Schriftgröße mitwächst. */
  min-height: calc(var(--space-6) + var(--space-3));
  padding: var(--space-2) var(--space-5);
  font-family: inherit;
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-label);
  border: var(--border) solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
  text-decoration: none;
  transition: background-color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
.btn:disabled, .btn[aria-disabled="true"] {
  cursor: not-allowed;
  opacity: 0.55;
}

/* Die Goldfläche allein hebt sich von Cream nur mit 2.14:1 ab — der Umriss
   der Schaltfläche käme also nicht an. Der Rahmen in --action-line hält die
   Grenze mit 3.31:1; die Beschriftung in Ink-Navy steht bei 7.73:1. */
.btn--primary {
  background: var(--action);
  border-color: var(--action-line);
  color: var(--on-action);
}
.btn--primary:hover:not(:disabled) {
  background: var(--action-line);
  border-color: var(--action-ink);
}

.btn--secondary {
  background: var(--surface);
  border-color: var(--rule-strong);
  color: var(--text);
}
.btn--secondary:hover:not(:disabled) {
  background: var(--action-soft);
  border-color: var(--action-line);
}

/* Der zweite Teil des CTA-Paars: ein Textlink mit Pfeil, keine zweite
   Schaltfläche. Der Pfeil rückt beim Überfahren nach — die einzige Bewegung
   in diesem Bauteil, und sie fällt bei prefers-reduced-motion weg. */
.btn--quiet {
  background: none;
  border-color: transparent;
  color: var(--action-ink);
  padding-inline: var(--space-2);
  min-height: auto;
  text-decoration: underline;
  text-decoration-color: var(--rule-brand);
  text-underline-offset: var(--space-1);
}
.btn--quiet::after {
  content: "\2192";   /* → */
  transition: transform var(--dur-fast) var(--ease);
}
.btn--quiet:hover:not(:disabled) {
  color: var(--heading);
  text-decoration-color: var(--action-line);
}
.btn--quiet:hover:not(:disabled)::after { transform: translateX(var(--space-1)); }

/* Auf dunklem Grund: die sekundäre Schaltfläche kann nicht weiß bleiben. */
.on-dark .btn--secondary,
.panel .btn--secondary,
.masthead .btn--secondary {
  background: transparent;
  border-color: var(--on-dark-accent);
  color: var(--on-dark);
}
.on-dark .btn--secondary:hover:not(:disabled),
.panel .btn--secondary:hover:not(:disabled),
.masthead .btn--secondary:hover:not(:disabled) {
  background: var(--on-dark-accent);
  color: var(--on-action);
}
.on-dark .btn--quiet,
.panel .btn--quiet,
.masthead .btn--quiet {
  color: var(--on-dark-accent);
  text-decoration-color: var(--on-dark-accent);
}
.on-dark .btn--quiet:hover:not(:disabled),
.panel .btn--quiet:hover:not(:disabled),
.masthead .btn--quiet:hover:not(:disabled) { color: var(--on-dark); }

.btn--block { width: 100%; }


/* == Formulare ============================================================ */

.field { display: grid; gap: var(--space-2); }

.field-input,
.field select {
  width: 100%;
  min-height: calc(var(--space-6) + var(--space-3));
  padding: var(--space-2) var(--space-3);
  font-family: inherit;
  font-size: var(--fs-base);
  color: var(--text);
  background: var(--surface);
  border: var(--border) solid var(--rule-strong);
  border-radius: var(--radius);
}
.field-input:hover { border-color: var(--action-line); }
/* Datum und Dateigröße sind Werte aus dem Register — auch im Eingabefeld. */
.field-input[type="date"] { font-family: var(--font-value); }

.field-hint {
  font-size: var(--fs-xs);
  color: var(--text-2);
  max-width: var(--measure);
}
.field-error {
  font-size: var(--fs-sm);
  color: var(--danger-ink);
}
.field-input[aria-invalid="true"] { border-color: var(--danger); }

.field--check {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-2) var(--space-3);
  align-items: start;
  padding: var(--space-3);
  border: var(--border) solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface-tint);
}
.field--check input {
  width: var(--space-4);
  height: var(--space-4);
  margin: 0;
  accent-color: var(--action-line);
}
.field--check .field-hint { grid-column: 2; }

.form-footer {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
  margin-top: var(--space-2);
}
.required { color: var(--danger-ink); }


/* == Meldungen ============================================================ */

.notice {
  display: grid;
  gap: var(--space-1);
  padding: var(--space-3) var(--space-4);
  border: var(--border) solid var(--rule-strong);
  border-left-width: var(--space-1);
  border-radius: var(--radius);
  background: var(--surface);
  font-size: var(--fs-sm);
}
.notice[hidden] { display: none; }
.notice strong { font-weight: var(--fw-bold); }

.notice--error {
  border-color: var(--danger);
  background: var(--danger-soft);
  color: var(--danger-ink);
}
/* Hinweis ohne Zustand. Bewusst neutral getönt und nicht in Sage: sonst sähe
   ein Hinweis genauso aus wie die Meldung "Protokoll liegt vor", und die
   Farbe würde einen Zustand behaupten, den es nicht gibt. Die Kante in Sage
   sagt "von uns", die Fläche sagt nichts. */
.notice--info {
  border-color: var(--accent);
  background: var(--muted-soft);
  color: var(--text);
}
.notice--done {
  border-color: var(--done);
  background: var(--done-soft);
  color: var(--done-ink);
}
.notice--working {
  border-color: var(--progress);
  background: var(--progress-soft);
  color: var(--progress-ink);
}


/* == Statusmarke ==========================================================
   Farbe UND Form UND Wort — das Konzept bleibt, nur die Farben sind neu:
   Gold für läuft, Sage für fertig, Ziegelrot für fehlgeschlagen, gedämpftes
   Ink-Navy für Entwurf. Die Form steckt weiter in ::before: gefüllte Fläche
   für erledigt, Ring für läuft, gestrichelt für noch nicht begonnen, Kerbe
   für fehlgeschlagen. So bleibt die Anzeige im Schwarzweiß-Ausdruck und für
   Farbfehlsichtige lesbar. */

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-3) var(--space-1) var(--space-2);
  border: var(--border) solid currentColor;
  border-radius: var(--radius-pill);
  font-family: var(--font-value);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  letter-spacing: 0;
  white-space: nowrap;
}
.badge::before {
  content: "";
  width: var(--space-2);
  height: var(--space-2);
  flex: none;
  background: currentColor;
}

.badge--draft {
  color: var(--muted);
  background: var(--muted-soft);
}
/* Entwurf: gestrichelter Umriss statt gefüllter Marke — noch kein Beleg. */
.badge--draft::before {
  background: none;
  border: var(--border) dashed currentColor;
}

.badge--working {
  color: var(--progress-ink);
  background: var(--progress-soft);
}
/* Läuft: Ring, nicht gefüllt. */
.badge--working::before {
  background: none;
  border: var(--border-mark) solid currentColor;
  border-radius: var(--radius-pill);
}

.badge--done {
  color: var(--done-ink);
  background: var(--done-soft);
}
.badge--failed {
  color: var(--danger-ink);
  background: var(--danger-soft);
}
/* Fehlgeschlagen: gefüllte Marke mit Kerbe — auch ohne Farbe unterscheidbar. */
.badge--failed::before {
  clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 60%, 0 100%);
}

/* Auf dunklem Grund kippen die getönten Flächen; dort trägt der Text die
   aufgehellte Ableitung und der Rahmen bleibt. */
.on-dark .badge, .panel .badge { background: transparent; }
.on-dark .badge--draft,   .panel .badge--draft   { color: var(--on-dark-2); }
.on-dark .badge--working, .panel .badge--working { color: var(--on-dark-accent); }
.on-dark .badge--done,    .panel .badge--done    { color: var(--done-lift); }
.on-dark .badge--failed,  .panel .badge--failed  { color: var(--danger-lift); }


/* == Meeting-Liste ========================================================
   Zeilen mit Haarlinie, keine Karten. */

.records {
  list-style: none;
  margin: 0;
  padding: 0;
  background: var(--surface);
  border: var(--border) solid var(--rule);
  border-radius: var(--radius);
}
.record { border-top: var(--border) solid var(--rule); }
.record:first-child { border-top: 0; }

.record-link {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--space-1) var(--space-4);
  padding: var(--space-4);
  color: inherit;
  text-decoration: none;
  /* Die Zeile bekommt beim Überfahren einen Gold-Balken am linken Rand statt
     einer Flächenfärbung — dasselbe Zeichen wie unter den Überschriften. */
  border-left: var(--border-brand) solid transparent;
}
.record-link:hover {
  background: var(--surface-tint);
  border-left-color: var(--rule-brand);
}
.record-link:hover .record-title { text-decoration: underline; }

.record-title {
  font-size: var(--fs-base);
  font-weight: var(--fw-bold);
  color: var(--heading);
}
.record-meta {
  grid-column: 1;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-4);
  font-size: var(--fs-xs);
  color: var(--text-2);
}
.record-meta .value { color: var(--text-2); }
.record-state {
  grid-column: 2;
  grid-row: 1 / span 2;
  align-self: center;
  display: grid;
  justify-items: end;
  gap: var(--space-1);
}
.record-progress {
  font-family: var(--font-value);
  font-size: var(--fs-xs);
  color: var(--text-2);
}

/* Mobil (unter 34rem ≈ 544px): der Status wandert unter den Titel, damit der
   Titel die ganze Breite hat. Haltepunkt literal, weil Media Queries keine
   Custom Properties erlauben. */
@media (max-width: 34rem) {
  .record-link { grid-template-columns: 1fr; }
  .record-state {
    grid-column: 1;
    grid-row: auto;
    justify-items: start;
    margin-top: var(--space-1);
  }
}


/* == Filterleiste =========================================================
   Die Statusfilter der Tenant-Übersicht. Links und keine Schaltflächen: jeder
   Stand ist eine eigene Adresse, die sich weitergeben und neu laden lässt.

   Der aktive Filter trägt aria-current="page" — und wird darüber auch
   gestaltet, nicht über eine zusätzliche Klasse. Ein Zustand, den der
   Screenreader kennt und das Auge nicht, wäre ein halber Zustand, und
   umgekehrt genauso. */

.filterbar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
}
.filterbar a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: var(--border) solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  font-size: var(--fs-sm);
  color: var(--text);
  text-decoration: none;
  transition: border-color var(--dur-fast) var(--ease);
}
.filterbar a:hover { border-color: var(--action-line); }
.filterbar a[aria-current="page"] {
  border-color: var(--action-line);
  background: var(--action-soft);
  font-weight: var(--fw-bold);
}
.filterbar .value { color: var(--text-2); }
.filterbar a[aria-current="page"] .value { color: var(--action-ink); }


/* == Leerer Zustand ======================================================= */

.blank {
  display: grid;
  gap: var(--space-4);
  justify-items: start;
  padding: var(--space-7) var(--space-5);
  background: var(--surface);
  border: var(--border) dashed var(--rule-strong);
  border-radius: var(--radius);
}
.blank p { max-width: var(--measure); color: var(--text-2); }


/* == Belegspur ============================================================
   Das Signaturelement. Eine senkrechte Haarlinie mit gestempelten Marken,
   jede mit dem Zeitstempel, den die API wirklich liefert. Wo die API keinen
   liefert, steht kein erfundener — dort steht ein Strich.

   Dieselbe Spur trägt den Chunk-Upload und die Verarbeitung. */

.trail {
  list-style: none;
  margin: 0;
  padding: 0;
}

.trail-step {
  position: relative;
  display: grid;
  grid-template-columns: var(--trail-mark) 1fr auto;
  gap: var(--space-1) var(--trail-gap);
  padding-bottom: var(--space-5);
}
.trail-step:last-child { padding-bottom: 0; }

/* Das Linienstück unter der Marke. Beim letzten Schritt entfällt es, damit
   die Spur endet statt ins Leere zu laufen. */
.trail-step::before {
  content: "";
  position: absolute;
  left: calc(var(--trail-mark) / 2 - var(--border) / 2);
  top: var(--space-4);
  bottom: 0;
  width: var(--border);
  background: var(--rule-strong);
}
.trail-step:last-child::before { display: none; }
/* Noch nicht erreichte Abschnitte: gestrichelt, wie eine Bleistiftlinie. */
.trail-step[data-state="wait"]::before {
  background: linear-gradient(var(--rule-strong) 50%, transparent 0);
  background-size: var(--border) var(--space-2);
}

.trail-mark {
  width: var(--trail-mark);
  height: var(--trail-mark);
  margin-top: var(--space-1);
  border: var(--border-mark) solid var(--rule-strong);
  background: var(--surface);
  flex: none;
}

.trail-body { min-width: 0; }
.trail-name {
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  color: var(--heading);
}
.trail-note {
  font-size: var(--fs-xs);
  color: var(--text-2);
}
.trail-time {
  font-family: var(--font-value);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-xs);
  color: var(--text-2);
  white-space: nowrap;
  margin-top: var(--space-1);
}

/* -- Zustände der Spur -- */

/* erledigt: gefüllte Marke, Sage */
.trail-step[data-state="done"] .trail-mark {
  background: var(--done);
  border-color: var(--done);
}
.trail-step[data-state="done"]::before { background: var(--done); }

/* läuft: Ring in Gold */
.trail-step[data-state="active"] .trail-mark {
  background: var(--surface);
  border-color: var(--action-line);
  border-radius: var(--radius-pill);
  box-shadow: 0 0 0 var(--space-1) var(--progress-soft);
}
.trail-step[data-state="active"] .trail-name { color: var(--progress-ink); }

/* wartet: gestrichelte Marke, Bleistift */
.trail-step[data-state="wait"] .trail-mark {
  border-style: dashed;
  border-color: var(--rule-strong);
}
.trail-step[data-state="wait"] .trail-name { color: var(--text-2); }

/* fehlgeschlagen: gefüllte Marke mit Kerbe */
.trail-step[data-state="failed"] .trail-mark {
  background: var(--danger);
  border-color: var(--danger);
  clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 55%, 0 100%);
}
.trail-step[data-state="failed"] .trail-name { color: var(--danger-ink); }

/* Auf dunkler Fläche */
.panel .trail-name, .on-dark .trail-name { color: var(--on-dark); }
.panel .trail-note, .on-dark .trail-note,
.panel .trail-time, .on-dark .trail-time { color: var(--on-dark-2); }
.panel .trail-mark, .on-dark .trail-mark { background: var(--surface-dark); }
.panel .trail-step[data-state="done"] .trail-mark,
.on-dark .trail-step[data-state="done"] .trail-mark {
  background: var(--done-lift);
  border-color: var(--done-lift);
}

/* Der Puls markiert die eine laufende Stufe. Bei prefers-reduced-motion
   entfällt er über --dur-base = 0 nicht von selbst — deshalb hier explizit
   an die Dauer gekoppelt und in der Media Query abgeschaltet. Erkennbar
   bleibt die Stufe dann am Ring, an der Farbe und am Wort "läuft". */
@media (prefers-reduced-motion: no-preference) {
  .trail-step[data-state="active"] .trail-mark {
    animation: trail-pulse 1.8s var(--ease) infinite;
  }
}
@keyframes trail-pulse {
  0%, 100% { box-shadow: 0 0 0 var(--space-1) var(--progress-soft); }
  50%      { box-shadow: 0 0 0 var(--space-2) var(--progress-soft); }
}

/* Mobil: Zeitstempel unter den Text, damit lange Stufennamen nicht auf
   zwei Zeichen zusammengequetscht werden. */
@media (max-width: 34rem) {
  .trail-step { grid-template-columns: var(--trail-mark) 1fr; }
  .trail-time { grid-column: 2; margin-top: 0; }
}


/* == Fortschrittsbalken (Upload) ========================================== */

.meter {
  display: grid;
  gap: var(--space-2);
}
.meter-track {
  height: var(--space-2);
  background: var(--surface-sunk);
  border-radius: var(--radius-pill);
  overflow: hidden;
}
.meter-fill {
  height: 100%;
  width: 0;
  background: var(--progress);
  border-radius: var(--radius-pill);
  transition: width var(--dur-base) var(--ease);
}
.meter-fill[data-state="done"] { background: var(--done); }
.meter-fill[data-state="failed"] { background: var(--danger); }
.meter-caption {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-2);
  font-family: var(--font-value);
  font-size: var(--fs-xs);
  color: var(--text-2);
}


/* == Definitionsliste im Formblatt-Stil =================================== */

.facts {
  display: grid;
  grid-template-columns: minmax(min-content, max-content) 1fr;
  gap: var(--space-3) var(--space-5);
  margin: 0;
  font-size: var(--fs-sm);
}
.facts dt {
  font-family: var(--font-value);
  font-size: var(--fs-label);
  font-weight: var(--fw-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-3);
  padding-top: var(--space-1);
}
.facts dd { margin: 0; color: var(--text); }

/* Die Frage-Antwort-Variante: die Frage ist ein Satz, kein Feldname — also
   in der Textschrift und nicht versal. */
.facts--qa {
  grid-template-columns: 1fr;
  gap: var(--space-2);
  font-size: var(--fs-base);
}
.facts--qa dt {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: var(--fs-h3);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-tight);
  text-transform: none;
  color: var(--heading);
  padding-top: var(--space-4);
}
.facts--qa dt:first-child { padding-top: 0; }
.facts--qa dd {
  color: var(--text);
  max-width: var(--measure);
  padding-bottom: var(--space-3);
  border-bottom: var(--border) solid var(--rule);
}

@media (max-width: 34rem) {
  .facts { grid-template-columns: 1fr; gap: var(--space-1); }
  .facts dd { padding-bottom: var(--space-2); }
}


/* == Öffentliche Seiten (Start, Preise, Kontakt) ==========================
   Neue Komponenten, aber kein neues Token: alles unten benutzt ausschliesslich
   Werte aus tokens.css. Die Startseite soll aussehen wie die App, in die sie
   führt — nicht wie eine Werbeseite davor. */

.site-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-value);
  font-size: var(--fs-xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}
.site-nav a {
  color: var(--on-dark-2);
  text-decoration: none;
  padding: var(--space-2);
}
.site-nav a:hover {
  color: var(--on-dark-accent);
  text-decoration: underline;
  text-decoration-color: var(--on-dark-accent);
}
.site-nav .btn { text-transform: none; }

/* Aufmacher. Einspaltig und linksbündig — kein zentrierter Werbeblock: die
   Seite behauptet Nachprüfbarkeit, und die liest sich als Dokument. */
.hero {
  display: grid;
  gap: var(--space-4);
  max-width: var(--measure);
  padding-block: var(--space-4) var(--space-6);
}
.hero h1 {
  font-size: var(--fs-display);
  line-height: var(--lh-display);
  font-weight: var(--fw-bold);
}
.hero .row-actions { margin-top: var(--space-2); }

.lede {
  font-size: var(--fs-lede);
  line-height: var(--lh-base);
  color: var(--text-2);
}

/* Der eine Satz, auf dem das Produkt steht. Hervorgehoben über den
   Gold-Strich am linken Rand, nicht über eine größere Schrift. */
.claim {
  padding: var(--space-5);
  border-left: var(--border-brand) solid var(--rule-brand);
  background: var(--surface);
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: var(--fs-lg);
  line-height: var(--lh-base);
  color: var(--text);
  max-width: var(--measure);
}

.section { display: grid; gap: var(--space-5); }
.section + .section { margin-top: var(--space-6); }

/* Drei Merkmale nebeneinander, unter 48rem gestapelt. auto-fit statt fester
   Spaltenzahl: dann bricht es von selbst um, ohne zweiten Haltepunkt. */
.features {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}
.feature { display: grid; gap: var(--space-2); align-content: start; }
.feature h3 { font-size: var(--fs-h3); }
.feature p { font-size: var(--fs-sm); color: var(--text-2); }


/* -- Karte ----------------------------------------------------------------
   Cream-Fläche mit Haarlinie in Ink-Navy bei 10 %. Beim Überfahren wird die
   Linie golden — dafür der etwas dunklere --action-line, weil reines Gold
   auf Cream mit 2.14:1 unter der 3:1-Schwelle für Zustandsgrenzen läge.
   Zusätzlich zur Farbe kommt oben eine Gold-Kante dazu: eine Zustandsänderung
   soll nicht allein am Farbton hängen. */

.cards {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
}

.card {
  display: grid;
  gap: var(--space-3);
  align-content: start;
  position: relative;
  padding: var(--space-5);
  background: var(--surface-tint);
  border: var(--border) solid var(--rule);
  border-radius: var(--radius);
  transition: border-color var(--dur-fast) var(--ease);
}
.card::before {
  content: "";
  position: absolute;
  inset: calc(var(--border) * -1) calc(var(--border) * -1) auto;
  height: var(--border-brand);
  background: var(--rule-brand);
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease);
}
.card:hover, .card:focus-within {
  border-color: var(--action-line);
}
.card:hover::before, .card:focus-within::before { opacity: 1; }

.card h3 { font-size: var(--fs-h3); }
.card p  { color: var(--text-2); font-size: var(--fs-sm); }
.card > .row-actions { margin-top: auto; padding-top: var(--space-2); }

/* Tarif-Karte. Der Preis ist ein Wert aus dem Register wie jeder andere —
   also IBM Plex Mono mit tabular-nums, nur groß. */
.card--plan .plan-price {
  font-family: var(--font-value);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-figure);
  font-weight: var(--fw-medium);
  line-height: var(--lh-tight);
  color: var(--heading);
}
.card--plan .plan-period {
  font-family: var(--font-value);
  font-size: var(--fs-xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-2);
}
.card--plan .plan-quota {
  font-family: var(--font-value);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-sm);
  color: var(--accent);
}
.card--plan ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-2);
  font-size: var(--fs-sm);
  color: var(--text-2);
}
.card--plan li {
  display: grid;
  grid-template-columns: var(--space-4) 1fr;
  gap: var(--space-2);
}
.card--plan li::before {
  content: "";
  width: var(--space-2);
  height: var(--space-2);
  margin-top: calc(var(--space-2) + var(--border));
  background: var(--rule-brand);
}

/* Die hervorgehobene Karte trägt die Gold-Kante dauerhaft — plus ein Wort,
   damit die Hervorhebung nicht nur farbig ist. */
.card--marked { border-color: var(--action-line); }
.card--marked::before { opacity: 1; }
.card-flag {
  position: absolute;
  top: 0;
  right: var(--space-4);
  transform: translateY(-50%);
  padding: var(--space-1) var(--space-2);
  background: var(--action);
  color: var(--on-action);
  font-family: var(--font-value);
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-medium);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
}


/* -- Prozess-Schritte -----------------------------------------------------
   Nummerierte Karten für die Pipeline. Die Ziffer kommt aus dem Zähler der
   Liste, nicht aus dem HTML — dann stimmt sie auch, wenn ein Schritt
   dazukommt. Sie steht groß in Fraunces, damit die 4.58:1 des Teal die
   3:1-Schwelle für große Schrift sicher halten. */

.steps {
  list-style: none;
  counter-reset: step;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
}
.step {
  counter-increment: step;
  display: grid;
  gap: var(--space-2);
  align-content: start;
  padding: var(--space-5);
  background: var(--surface-tint);
  border: var(--border) solid var(--rule);
  border-top: var(--border-brand) solid var(--rule-brand);
  border-radius: var(--radius);
}
.step::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: var(--fs-figure);
  font-weight: var(--fw-heavy);
  line-height: 1;
  letter-spacing: var(--tracking-tight);
  color: var(--accent-strong);
}
.step h3 { font-size: var(--fs-h3); }
.step p  { font-size: var(--fs-sm); color: var(--text-2); }


/* -- Fuß ------------------------------------------------------------------ */

.site-footer {
  margin-top: var(--space-8);
  background: var(--surface-dark);
  color: var(--on-dark-2);
  border-top: var(--border-brand) solid var(--rule-brand);
}
.site-footer-inner {
  max-width: var(--w-page);
  margin: 0 auto;
  padding: var(--space-6) var(--space-4);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  align-items: center;
  font-family: var(--font-value);
  font-size: var(--fs-xs);
  color: var(--on-dark-2);
}
.site-footer-inner nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-left: auto;
}
.site-footer-inner a {
  color: var(--on-dark);
  text-decoration-color: var(--on-dark-accent);
}
.site-footer-inner a:hover {
  color: var(--on-dark-accent);
  text-decoration-color: var(--on-dark-accent);
}

/* Honeypot des Kontaktformulars.
   Nicht `display: none` und nicht `hidden`: manche Bots erkennen beides und
   lassen das Feld dann aus. So bleibt es im Layout vorhanden, aber ausserhalb
   des Sichtfelds — und `tabindex="-1"` plus `aria-hidden` halten es aus der
   Tastatur-Reihenfolge und von Screenreadern fern, damit es niemand versehentlich
   ausfüllt, der die Seite nicht sieht. */
.honeypot {
  position: absolute;
  left: var(--offscreen);
  width: var(--space-4);
  height: var(--space-4);
  overflow: hidden;
}
