/* ═══════════════════════════════════════════════════════════════════
   KARTENSPRACHE — GETEILT zwischen beiden Bäumen (29.07.).
   Vorher lebte dieser Block nur in (frontend)/globals.css: auf letshygge
   standen .card-data & Co. nackt im Markup („cards render ugly", Torben).
   Importiert von (frontend)/layout.tsx UND sites/[site]/layout.tsx.
   Farben laufen über --color-*-Token — jede Site bringt ihre Palette mit
   (siteTheme.ts). Regeln und Begründungen: docs/design-language.md.
   ═══════════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════════════════
   KARTEN — eine gemeinsame Sprache (Torben, 2026-07-28)
   ═══════════════════════════════════════════════════════════════════════
   Die Karten sind über Monate entstanden und griffen je nach Entstehungszeit
   andere Werte: Radius 6/12/18, Rahmen mal 0.5px Stone (dunkel) mal 1px
   Border (hell), Fläche mal surface mal bg, Innenabstand 0/18/20/28. Ab hier
   gilt EIN Satz Variablen, abgeleitet aus der Karte „Ort & Umgebung“, die als
   Vorbild dient.

   Drei Stufen, wie mit Torben festgelegt:
     .card-data   Zahlen und Listen   → Fläche + Haarlinie + Innenabstand
     .card-media  Bild bis zur Kante  → randlos, nur der Radius klammert
     .card-tool   Spiel/Werkzeug      → eigene Welt, dunkler Grund erlaubt
*/
:root {
  --card-radius:      var(--radius-lg);      /* 18px — der Wert der Vorbildkarte */
  --card-surface:     var(--color-surface);
  --card-hairline:    0.5px solid var(--color-border);
  /* Getrennt nach Achsen, damit Kopf und Fuß ihre Trennlinie bis an den Rand
     ziehen können und `.card-roomy` nur zwei Variablen überschreibt. */
  --card-pad-x:       22px;
  --card-pad-y:       20px;
  --card-gap-section: 20px;                  /* Luft über einer Trennlinie */
  /* Feste Zeilenhöhe des Rasters — die einzige Zusage, die „alle Karten gleich
     hoch" wirklich einlöst. Karten mit mehr Inhalt spannen über card-h2. */
  --card-row:         480px;
  /* KEINE Schatten: das HAVGUS-System sagt „depth through color only".
     Tiefe entsteht über Fläche und Randfarbe, nicht über Weichzeichner. */
  --card-lift-border: var(--color-teal);
  --card-lift-bg:     var(--color-foam);
}

.card-data,
.card-media,
.card-tool {
  border-radius: var(--card-radius);
  overflow: hidden;
  height: 100%;
  display: flex;
  flex-direction: column;
  /* Nur Randfarbe und Fläche bewegen sich beim Überfahren — kein Schatten,
     das System sagt „depth through color only". Sanft, wie festgelegt. */
  transition: transform 0.35s ease, border-color 0.35s ease, background-color 0.35s ease;
}

.card-data {
  background: var(--card-surface);
  border: var(--card-hairline);
  padding: var(--card-pad-y) var(--card-pad-x);
}
.card-roomy { --card-pad-x: 32px; --card-pad-y: 28px; }

.card-media { background: transparent; border: none; padding: 0; }
.card-tool  { border: var(--card-hairline); padding: 0; }

/* Sobald eine Karte gegliedert ist (Kopf, Bild, Körper, Fuß), verwalten diese
   Teile ihren Abstand selbst — sonst läge Polster auf Polster und die
   Trennlinien könnten nicht bis an den Rand laufen. */
.card-data:has(> .card-head),
.card-data:has(> .card-figure),
.card-data:has(> .card-main) { padding: 0; }

/* ── Der Kopf: Titel links, Reiter rechts ─────────────────────────────
   Reiter gehören AUSSCHLIESSLICH hierher (Torben, 28.07.). Damit hat jede
   Karte dieselbe Lesekante: Was bin ich? → Welche Ansicht? → Inhalt.
   Passen Titel und Reiter nicht nebeneinander, rutschen die Reiter in eine
   zweite Zeile — immer noch im Kopf, nie in den Inhalt. */
.card-head {
  flex: none;
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap;
  padding: 12px var(--card-pad-x);
  border-bottom: var(--card-hairline);
}
/* Nebeneinander müssen die Titel auf einer Linie liegen und die Bilder an
   derselben Stelle beginnen (Torben, 28.07., Badewasser neben Luft & Pollen):
   ein Kopf MIT Reitern ist ~65px hoch, einer ohne nur ~43px — also bekommen
   alle Köpfe die Reiterhöhe. Mobil stapeln die Karten, dort wäre die Luft
   nur Verschnitt. */
@media (min-width: 640px) {
  .card-head { min-height: 62px; }
}
.card-title {
  font-family: var(--font-mono, monospace);
  font-size: 10px; font-weight: 600; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--color-teal);
  margin: 0; white-space: nowrap;
}

/* ── Das Bild ─────────────────────────────────────────────────────────
   EINE Behandlung für alle Karten (Torben, 28.07.: „hero image wird zu
   verschieden gehandhabt"). Vorher standen 16/9, 16/8, 16/7 und 4/3
   nebeneinander. Jetzt gilt:
     schmale Karte → Bild unter dem Kopf, ein Drittel der Kartenhöhe
     breite Karte  → Bild links, Text rechts (.card-split)
   Weil die Kartenhöhe feststeht, ist ein Anteil verlässlicher als ein
   Seitenverhältnis: das Bild kann die Karte nie sprengen. */
.card-figure {
  position: relative;
  /* Ein Drittel, nicht 40%: gemessen schnitten Text-Karten (Badewasser,
     Luft, Tierwelt) sonst 18-63px Inhalt ab, und in Karten wird nicht
     gerollt. */
  flex: 0 0 33%;
  min-height: 0;
  overflow: hidden;
  background: var(--color-foam);
}
.card-figure img,
.card-figure > span > img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; display: block;
}
/* Einspaltig ist die Karte nicht höhengebunden — dort trägt das Bild wieder
   ein Seitenverhältnis, sonst fiele der Anteil auf null. */
@media (max-width: 639px) {
  .card-figure { flex: none; aspect-ratio: 16 / 9; }
}

/* Bildanteile über dem Drittel — für Karten, deren Text kurz ist:
   tall (45%) für Badewasser und Luft & Pollen, hero (60%) für 2×2-Karten wie
   die Tierwelt, wo zwei Zeilen Text sonst 500px Leere hinterlassen. */
.card-figure.card-figure-tall { flex: 0 0 45%; }
.card-figure.card-figure-hero { flex: 0 0 60%; }

/* Lead-Split: die führende 2×1-Karte (Denkmalschutz) trägt Bild links,
   Inhalt rechts — das Ort-&-Umgebung-Muster. Unter 1024px stapelt es:
   Bild oben im Querformat, Inhalt darunter. */
@media (min-width: 1024px) {
  .card-split-lead { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); }
  .card-split-lead > .card-figure { flex: none; height: 100%; }
}
@media (max-width: 1023px) {
  .card-split-lead > .card-figure { flex: none; aspect-ratio: 16 / 9; }
}

/* KI-Kennzeichnung auf Kartenbildern — stand dreimal kopiert in
   BadevandBadge, LuftPollenCard und SpeciesCard. */
.card-ai-badge {
  position: absolute; top: 10px; left: 10px;
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 8px; border-radius: 999px;
  background: rgba(28, 43, 46, 0.62); color: #F0EDE6;
  font-family: var(--font-body, sans-serif);
  font-size: 9px; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase;
}

/* Breite Karten: Bild links, Inhalt rechts — das Muster der Karte
   „Ort & Umgebung", die Torben als Vorbild benannt hat.
   NUR ab drei Spalten (Torben, 28.07.): in einer Zweierkarte wäre die
   Bildhälfte etwa so breit wie hoch, und fast alle Bilder sind Querformat —
   sie würden beschnitten oder wirkten gequetscht. Erst über drei Spalten ist
   die Hälfte breiter als hoch. Schmaler gestapelt: Bild oben, Text darunter. */
.card-split > .card-main { display: flex; flex-direction: column; min-height: 0; }
@media (min-width: 1024px) {
  .card-split.card-w3,
  .card-split.card-w4 {
    display: grid;
    /* Das Bild bekommt etwas mehr als die Hälfte — Querformat braucht Breite. */
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    align-items: stretch;
  }
  .card-split.card-w3 > .card-figure,
  .card-split.card-w4 > .card-figure { flex: none; aspect-ratio: auto; height: 100%; }
}

/* Immer sichtbar, unabhängig vom Reiter — sitzt zwischen Bild und Ansichten. */
.card-lead {
  flex: none;
  /* Knapp gehalten: der Himmelskarte fehlten gemessen 6px — der Vorspann ist
     Beiwerk vor den Ansichten, nicht deren Konkurrent. */
  padding: 10px var(--card-pad-x) 0;
  display: flex; flex-direction: column; gap: 8px;
}

/* NIEMALS in der Karte rollen (Torben, 28.07.). Eine Karte zeigt eine
   Zusammenfassung — passt etwas nicht, wird gekürzt (.card-clamp-*), die Liste
   begrenzt, der Inhalt auf Reiter verteilt oder die Karte bekommt mit card-h2
   zwei Zeilen. Eine Rollleiste in einer Karte versteckt Inhalt hinter einer
   Geste, die auf einer Kachel niemand erwartet. */
.card-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  padding: 16px var(--card-pad-x);
}

/* Kürzen statt rollen. */
.card-clamp-1, .card-clamp-2, .card-clamp-3, .card-clamp-4 {
  display: -webkit-box; -webkit-box-orient: vertical; overflow: hidden;
}
.card-clamp-1 { -webkit-line-clamp: 1; }
.card-clamp-2 { -webkit-line-clamp: 2; }
.card-clamp-3 { -webkit-line-clamp: 3; }
.card-clamp-4 { -webkit-line-clamp: 4; }
.card-foot {
  flex: none; margin-top: auto;
  padding: 13px var(--card-pad-x) 16px;
  border-top: var(--card-hairline);
}

/* Anheben nur dort, wo ein Klick folgt — und nur mit echter Maus.
   Auf Touch bleibt alles ruhig, sonst klebt der Hover-Zustand. */
@media (hover: hover) and (pointer: fine) {
  a:hover > .card-data,
  a:hover > .card-media,
  .card-interactive:hover {
    transform: translateY(-2px);
    border-color: var(--card-lift-border);
  }
  a:hover > .card-data { background: var(--card-lift-bg); }
}

/* Trennlinie zwischen Abschnitten innerhalb des Körpers. */
.card-section {
  border-top: var(--card-hairline);
  margin-top: var(--card-gap-section);
  padding-top: 18px;
}
.card-footer { margin-top: auto; padding-top: 18px; }

/* ── Bewegung ─────────────────────────────────────────────────────────
   Karten haben BEWUSST keine eigene Auftrittsanimation mehr (Torben, 28.07.:
   „bin mir nicht sicher ob der fade effect in den karten noch sinn macht" —
   er macht keinen). Die Seite deckt Abschnitte bereits einmalig über
   MotionReveals auf; eine zweite Welle innerhalb des aufgedeckten Abschnitts
   war doppelte Bewegung an derselben Stelle. Bewegung bleibt dort, wo sie
   etwas beantwortet: beim Überfahren und beim Reiterwechsel. */

@media (prefers-reduced-motion: reduce) {
  .card-data, .card-media, .card-tool { transition: none; }
}

/* ── Raster ───────────────────────────────────────────────────────────
   1 Spalte mobil, 2 ab 640px, 3 ab 1024px — und 4 erst ab 1920px. Der
   Schwellwert lag bei 1600px; dort wirkten die vier Karten zu schmal
   (Torben, 28.07.). Bei 1920px und 1800px Rasterbreite ist eine Karte
   rund 438px breit statt 378px. `dense` füllt Löcher hinter breiten Karten. */
.card-grid {
  display: grid;
  gap: 16px;
  grid-auto-flow: dense;
  /* minmax(0, 1fr), nicht 1fr: `1fr` bedeutet `minmax(auto, 1fr)` und lässt
     sich von einem breiten Kind aufblähen — auf 375px wurde die Spalte so
     519px breit und die ganze Seite rollte seitlich. */
  grid-template-columns: minmax(0, 1fr);
  /* ALLE Karten gleich hoch, nicht nur die einer Reihe (Torben, 28.07.).
     `1fr` konnte das nicht: in einem Raster ohne feste Höhe richtet sich
     jede Zeile nach ihrem höchsten Kind, Zeile 1 wurde 618px, Zeile 2 nur
     474px. Eine feste Zeilenhöhe ist die einzige Zusage, die hält — was
     nicht hineinpasst, rollt im Körper der Karte. */
  grid-auto-rows: var(--card-row);
}
/* Auf dem Telefon ist alles einspaltig; eine erzwungene Einheitshöhe
   erzeugte dort nur Leerflächen. */
@media (max-width: 639px) {
  .card-grid { grid-auto-rows: auto; }
}
.card-h2 { grid-row: span 2; }

/* Ohne das gewinnt der Inhalt gegen die Zeilenhöhe: Rasterkinder haben von
   Haus aus `min-height: auto`, also mindestens ihre Inhaltshöhe, und wachsen
   über die Zeile hinaus. Genau daran waren die Blogkarten 540px statt 360px. */
.card-grid > * { min-height: 0; }

/* Vollbild-Medienkarte: das Bild IST die Karte, Text liegt darauf.
   Höhe aus der Rasterzeile — mobil, wo es keine feste Zeile gibt, aus einem
   Querformat-Verhältnis (fast alle Aufnahmen sind Querformat). */
.card-media-full {
  position: relative; display: block;
  height: 100%; overflow: hidden;
  border-radius: var(--card-radius);
  text-decoration: none;
  transition: transform 0.35s ease;
}
@media (max-width: 639px) {
  .card-media-full { height: auto; aspect-ratio: 16 / 10; }
}
@media (hover: hover) and (pointer: fine) {
  .card-media-full:hover { transform: translateY(-2px); }
}
@media (prefers-reduced-motion: reduce) {
  .card-media-full { transition: none; }
}

@media (min-width: 640px)  { .card-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .card-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1920px) { .card-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* Breitenklassen greifen erst, wenn es überhaupt Spalten gibt. */
@media (min-width: 640px)  { .card-w2, .card-w3, .card-w4 { grid-column: span 2; } }
@media (min-width: 1024px) { .card-w3, .card-w4 { grid-column: span 3; } }
@media (min-width: 1920px) { .card-w4 { grid-column: span 4; } }

/* Nur das Kartenraster darf auf sehr breiten Schirmen über 1280px hinaus —
   Text, Hero und Landkarte behalten ihr ruhiges Maß. */
@media (min-width: 1920px) {
  /* `max-width` allein genügt nicht: der umgebende .container deckelt schon
     bei 1440px, das Raster blieb bei 1344px stehen und die vier Karten waren
     wieder 324px schmal — genau das Gegenteil der Absicht. Deshalb bricht das
     Raster hier aus dem Container aus und zentriert sich selbst. */
  .card-grid-wide {
    position: relative;
    left: 50%;
    transform: translateX(-50%);
    width: min(1800px, 100vw - 6rem);
    max-width: none;
  }
}

/* ── Reiter ───────────────────────────────────────────────────────────
   Sitzen immer im Kopf. Der aktive Reiter ist deutlich abgesetzt: gefüllt
   in Ink auf hellem Grund (Torben, 28.07.: „active tab must descriminate").
   Vorher trug er nur eine hellere Fläche und war kaum zu unterscheiden. */
.card-seg {
  position: relative; display: flex; gap: 2px;
  padding: 3px; border-radius: 999px;
  background: var(--color-bg); border: var(--card-hairline);
  flex: 0 1 auto; min-width: 0;
}
.card-seg button {
  position: relative; flex: 1 1 auto; min-width: 0;
  min-height: 30px; padding: 0 11px;
  background: none; border: none; cursor: pointer;
  font-family: var(--font-mono, monospace); font-size: 9.5px; letter-spacing: 0.1em;
  text-transform: uppercase;
  /* Ink mit Deckkraft statt --color-stone: „stone" ist je Theme mal Text-,
     mal Rahmenton — auf letshygge (#d8d3ca) waren inaktive Reiter unsichtbar
     (Torben, 30.07.). Relativ zu Ink liest es sich in jeder Palette. */
  color: color-mix(in srgb, var(--color-ink, #1C2B2E) 55%, transparent);
  white-space: nowrap; border-radius: 999px;
  transition: color 0.3s ease, background-color 0.3s ease;
  -webkit-tap-highlight-color: transparent;
}
@media (hover: hover) and (pointer: fine) {
  .card-seg button:hover { color: var(--color-ink); }
}
.card-seg button[aria-pressed='true'] {
  color: var(--color-bg);
  background: var(--color-ink);
  font-weight: 700;
}
.card-seg button:focus-visible { outline: 2px solid var(--color-teal); outline-offset: 2px; }

/* Ansichten liegen übereinander und blenden ineinander über. Das geht erst,
   seit die Kartenhöhe feststeht: vorher hätte eine überlagerte Ansicht die
   Karte immer auf ihre höchste Fassung aufgeblasen. */
/* Trägt der Körper die Ansichten, polstern die Ansichten selbst — sonst läge
   Polster auf Polster. */
.card-body.card-views { padding: 0; }
.card-views { position: relative; }
.card-views > [data-view] {
  position: absolute; inset: 0;
  overflow: hidden;
  /* 14/10 statt 16/16: Badewasser und Tierwelt fehlten gemessen 6px. */
  padding: 14px var(--card-pad-x) 10px;
  opacity: 0; visibility: hidden; transform: translateY(6px);
  transition: opacity 0.3s ease, transform 0.3s ease, visibility 0s linear 0.3s;
}
.card-views > [data-view][data-active='true'] {
  opacity: 1; visibility: visible; transform: none;
  transition: opacity 0.3s ease, transform 0.3s ease, visibility 0s;
}
@media (prefers-reduced-motion: reduce) {
  .card-views > [data-view] { transition: none; }
  .card-seg button { transition: none; }
}

/* ── Mobil ────────────────────────────────────────────────────────────
   Auf dem Telefon gilt das Gegenteil der Desktop-Regel: die Karte hat KEINE
   feste Höhe (siehe Raster), also kann die Ansicht nicht absolut liegen — sie
   hätte keinen Bezugsrahmen und die Karte fiele auf null zusammen. Hier
   liegen die Ansichten wieder im selben Rasterfeld, die inaktive mit Höhe 0.
   Das Überblenden bleibt, nur das Verschieben entfällt. */
@media (max-width: 639px) {
  :root { --card-pad-x: 18px; --card-pad-y: 18px; }

  /* Mobil hat die Karte keine feste Höhe — dort darf der Inhalt einfach
     wachsen, gekürzt wird trotzdem. */
  .card-body { overflow: visible; }

  /* Vier Reiter passen nicht nebeneinander auf 375px. Statt sie zu quetschen
     (unlesbar) oder umzubrechen (zwei Zeilen Kopf) rollt die Leiste seitlich —
     sie bleibt eine Zeile und bleibt im Kopf. */
  /* nowrap hält Titel und Reiter in einer Zeile — beide müssen dafür
     schrumpfen dürfen, sonst drückt ihre Mindestbreite die Karte auseinander. */
  .card-head { flex-wrap: nowrap; }
  .card-head > * { min-width: 0; }
  .card-seg {
    width: 100%; overflow-x: auto;
    scrollbar-width: none; -ms-overflow-style: none;
    scroll-snap-type: x proximity;
  }
  .card-seg::-webkit-scrollbar { display: none; }
  .card-seg button {
    flex: 1 0 auto;
    min-height: 38px;          /* Daumengröße statt Mausgröße */
    font-size: 10px; padding: 0 14px;
    scroll-snap-align: center;
  }
  /* Titel darf schrumpfen, damit die Reiterleiste Platz bekommt. */
  .card-title { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
}

/* Zwischen Telefon und Desktop bleibt die feste Höhe, aber die Reiter dürfen
   in eine zweite Kopfzeile rutschen — auf einer Zweierkarte bei 700px steht
   neben dem Titel sonst zu wenig Platz. */
@media (min-width: 640px) and (max-width: 1023px) {
  .card-head { flex-wrap: wrap; }
  .card-seg { flex: 1 1 100%; }
}

/* ── Glas-Kappe der Bildkarten ─────────────────────────────────────────
   Kompakt im Ruhezustand (Datum · Titel · Weiterlesen), damit das Bild die
   Karte trägt — die volle Kappe deckte über die Hälfte des Motivs (Torben,
   30.07.). Auszug und Zitat fahren beim Überfahren aus; auf Touch führt der
   Tipp ohnehin zum Beitrag, dort steht alles. */
.card-cap {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 12px 18px 14px;
  background: rgba(28, 43, 46, 0.38);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-top: 0.5px solid rgba(240, 237, 230, 0.18);
}
.card-cap-more {
  max-height: 0; opacity: 0; overflow: hidden;
  transition: max-height 0.35s ease, opacity 0.35s ease;
}
@media (hover: hover) and (pointer: fine) {
  a:hover .card-cap-more { max-height: 7em; opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .card-cap-more { transition: none; }
}
