/* ============================================================
   sharemagazines — Base
   ------------------------------------------------------------
   Reset, Schriften, Textstile, Layout-Grundlagen.
   Setzt tokens.css voraus:

     <link rel="stylesheet" href="tokens.css">
     <link rel="stylesheet" href="base.css">
     <body data-theme="dark">

   Enthält KEINE Komponenten. Buttons, Chips, Cards und Labels
   liegen jeweils in /components.

   Alle Werte ziehen aus tokens.css. Wo das nicht möglich war,
   steht es im Abschnitt „Ohne Token-Grundlage" am Ende — mit
   Begründung und offener Entscheidung.
   ============================================================ */

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&family=Outfit:wght@700;800&display=swap');

/* ------------------------------------------------------------
   1. Reset
   ------------------------------------------------------------ */

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

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

body,
h1, h2, h3, h4, h5, h6,
p, figure, blockquote, dl, dd {
  margin: 0;
}

/* Die Zurücksetzung für Listen mit role="list".
   ------------------------------------------------------------
   :where() NIMMT DER REGEL IHRE SPEZIFITÄT. Vorher stand hier
   `ul[role="list"]` — Element plus Attribut, spezifischer als
   jede einzelne Klasse. Eine Komponente, die ihrer Liste
   Padding gibt, verlor es damit lautlos, egal in welcher
   Reihenfolge die Dateien geladen sind. Der einzige Ausweg war
   `ul.klasse` in jeder betroffenen Komponente; im
   Tablet-Prototyp ist das am 04.09.2026 dreimal passiert
   (Inhalte-Overlay, Shortcuts, Einstellungsliste).

   Mit :where() zählt die Regel als Spezifität 0 — sie wirkt
   weiter als Zurücksetzung, aber jede Klasse gewinnt gegen sie.
   Das ist genau das, was eine Zurücksetzung tun soll. */
:where(ul[role="list"], ol[role="list"]) {
  list-style: none;
  margin: 0;
  padding: 0;
}

img,
picture,
video,
canvas,
svg {
  display: block;
  max-width: 100%;
}

input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}

a {
  color: inherit;
}

/* ------------------------------------------------------------
   2. Body
   ------------------------------------------------------------ */

body {
  font-family: var(--font-family-inter);
  font-size: var(--font-size-small-text);
  line-height: var(--line-height-small-text);
  font-weight: var(--font-weight-regular);
  color: var(--text-primary);
  background-color: var(--surface-primary);
  min-height: 100vh;
}

/* ------------------------------------------------------------
   3. Textstile
   ------------------------------------------------------------
   Die Klassen setzen Familie, Größe und Zeilenhöhe. Das Gewicht
   ist bewusst NICHT mitgesetzt: In Figma existieren die
   Body-Stile in mehreren Gewichten (Regular / Medium / Bold),
   und welches gilt, hängt vom Einsatzort ab — Status-Labels sind
   Medium, Button-Labels Bold, Fließtext Regular.

   Gewicht deshalb über .weight-* dazusetzen. Überschriften haben
   ein festes Gewicht und bringen es selbst mit.

   Die Größen sind responsiv: die Tokens wechseln bei 768 und
   1200 px. Hier steht keine Media Query — die liegt in tokens.css.
   ------------------------------------------------------------ */

.h1,
h1 {
  font-family: var(--font-family-display);
  font-size: var(--font-size-h1);
  line-height: var(--line-height-h1);
  font-weight: var(--font-weight-extrabold);
}

.h2,
h2 {
  font-family: var(--font-family-display);
  font-size: var(--font-size-h2);
  line-height: var(--line-height-h2);
  font-weight: var(--font-weight-bold);
}

.h3,
h3 {
  font-family: var(--font-family-display);
  font-size: var(--font-size-h3);
  line-height: var(--line-height-h3);
  font-weight: var(--font-weight-bold);
}

.large-text {
  font-family: var(--font-family-inter);
  font-size: var(--font-size-large-text);
  line-height: var(--line-height-large-text);
}

.medium-text {
  font-family: var(--font-family-inter);
  font-size: var(--font-size-medium-text);
  line-height: var(--line-height-medium-text);
}

.small-text {
  font-family: var(--font-family-inter);
  font-size: var(--font-size-small-text);
  line-height: var(--line-height-small-text);
}

.extra-small-text {
  font-family: var(--font-family-inter);
  font-size: var(--font-size-extra-small-text);
  line-height: var(--line-height-extra-small-text);
}

/* title text — Karten-Titel. Folgt small → medium über die
   Breakpoints (14 / 18 / 20). */
.title-text {
  font-family: var(--font-family-inter);
  font-size: var(--font-size-title-text);
  line-height: var(--line-height-title-text);
  font-weight: var(--font-weight-bold);
}

/* Bottom Navigation — der eigene Textstil ist am 28.08.2026 aus
   Figma entfernt worden (kam nirgends vor). Geblieben ist die
   Gewichtsunterscheidung; die Größe kommt aus einem Standard-Stil,
   welcher ist offen (SKILL.md §7). Bis dahin erbt .nav-label die
   Größe der Umgebung und setzt nur das Gewicht. */
.nav-label {
  font-family: var(--font-family-inter);
  font-weight: var(--font-weight-regular);
}

.nav-label--active {
  font-weight: var(--font-weight-bold);
}

/* Gewicht */
.weight-regular { font-weight: var(--font-weight-regular); }
.weight-medium  { font-weight: var(--font-weight-medium); }
.weight-bold    { font-weight: var(--font-weight-bold); }

/* Letter-Spacing für „small text bold" (1%). Bewusst als eigene
   Klasse statt auf .small-text: ob die Regular-Variante dieselbe
   Laufweite hat, ist nicht geklärt. Button-Labels in small und
   Warning-Buttons nutzen sie. */
.tracking-small-bold { letter-spacing: var(--letter-spacing-small-text-bold); }

/* Textfarben */
/* ------------------------------------------------------------
   Treffer-Hervorhebung in Suchergebnissen (§6)
   ------------------------------------------------------------
   Das Suchwort im Fundstellen-Text. Semantisch <mark>, damit es
   auch ohne CSS und für Screenreader eine Auszeichnung bleibt.

     … Prüfer der <mark>Bank</mark> fanden …

   FLÄCHE IST blue-label-stroke, NICHT blue-label-fill. Der
   Unterschied entscheidet, ob es die Hervorhebung überhaupt gibt:
   blue-label-fill liegt in Light 1,01:1 über surface-primary,
   also unsichtbar. blue-label-stroke hält 2,28:1 in Dark und
   1,20:1 in Light — und es ist mit KEINEM Surface-Token
   identisch, fällt also auf keiner Fläche auf 1,00:1. Deshalb
   braucht die Hervorhebung, anders als der Chip (§5), keine
   Karten-Variante.

   ZWEI SIGNALE, WEIL EINES NICHT TRÄGT. Auf dieser Fläche fällt
   text-description auf 2,96:1 in Dark und 3,90:1 in Light —
   beides unter 4,5. Das ausgezeichnete Wort wechselt deshalb auf
   text-primary: 7,47:1 in Dark, 12,53:1 in Light, gegen 6,74:1
   bzw. 4,68:1 in der Umgebung.

   Das ist der Kern der Sache: eine Fläche, die man sieht, ist
   dunkel oder satt genug, dass grauer Text darauf nicht mehr
   lesbar ist. Beides gleichzeitig geht nicht — also trägt der
   Helligkeitssprung im TEXT, und die Fläche verstärkt. Damit
   hängt die Auszeichnung auch nicht an Farbe allein (WCAG 1.4.1).

   Kein Radius, kein Padding — die Fläche liegt eng an den Glyphen
   wie in Figma. Padding würde die Zeilenhöhe der Fundstelle
   auseinandertreiben.
   ------------------------------------------------------------ */

mark,
.treffer {
  background-color: var(--blue-label-stroke);
  color: var(--text-primary);
  border-radius: 0;
  padding: 0;
}

.text-primary     { color: var(--text-primary); }
.text-accent      { color: var(--text-accent); }
.text-description { color: var(--text-description); }

/* ------------------------------------------------------------
   4. Layout
   ------------------------------------------------------------ */

/* Seitenrand. Skaliert bewusst nicht mit dem Breakpoint —
   Luft auf großen Screens entsteht über .content, nicht über
   größere Ränder. */
.screen {
  padding-inline: var(--layout-screen-margin);
}

/* Lesespalte. Ab Tablet zentriert, damit Zeilen nicht zu lang
   werden. */
.content {
  max-width: var(--content-max-width);
  margin-inline: auto;
}

/* Sektionsabstand — Design Rules §11.1 */
.section + .section {
  margin-top: var(--space-2xl);
}

/* Stapel mit gleichmäßigem Abstand */
.stack       { display: flex; flex-direction: column; }
.stack-2xs   { gap: var(--space-2xs); }
.stack-xs    { gap: var(--space-xs); }
.stack-sm    { gap: var(--space-sm); }
.stack-md    { gap: var(--space-md); }
.stack-lg    { gap: var(--space-lg); }
.stack-xl    { gap: var(--space-xl); }
.stack-2xl   { gap: var(--space-2xl); }

/* Flächen */
.surface-primary   { background-color: var(--surface-primary); }
.surface-secondary { background-color: var(--surface-secondary); }
.surface-card      { background-color: var(--surface-card); }

/* Touch-Target-Helfer. Setzt die Untergrenze von 44px durch.
   Vergrößert die Hit-Area, ohne die sichtbare Größe zu ändern.
   Das unsichtbare Padding zählt NIE als Layoutabstand —
   Abstände zu Nachbarelementen ab Textkante messen. */
.touch-target {
  position: relative;
}

.touch-target::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  min-width: var(--touch-target-min);
  min-height: var(--touch-target-min);
  width: 100%;
  height: 100%;
}

/* ------------------------------------------------------------
   5. Hilfsklassen
   ------------------------------------------------------------ */

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

/* Markiert im Prototyp, was noch fehlt. Sichtbar, damit es beim
   Review nicht untergeht — siehe AGENTS.md Abschnitt 9. */
[data-todo] {
  outline: var(--outline-active) dashed var(--red-label-text);
  outline-offset: var(--space-2xs);
  min-height: var(--space-2xl);
}

[data-todo]::before {
  content: 'TODO: ' attr(data-todo);
  display: block;
  padding: var(--space-xs);
  font-size: var(--font-size-extra-small-text);
  color: var(--red-label-text);
}

/* ============================================================
   6. OHNE TOKEN-GRUNDLAGE
   ------------------------------------------------------------
   Zwei Werte ließen sich nicht aus dem Design System ableiten.
   Sie stehen hier sichtbar getrennt, damit sie nicht als
   gesetzt gelten.
   ============================================================ */

:root {
  /* Lesespalte. Die Design Rules §0 nennen eine Spanne von
     640–720px, keinen festen Wert. Hier ist die Obergrenze
     gesetzt. Wenn ihr euch auf eine Zahl festlegt, gehört sie
     als Token nach oben. */
  --content-max-width: 720px;
}

/* Tastatur-Fokus — neutraler Ring, 2px, Offset 4.
   Am 24.08.2026 gegen Figma geprüft: Primary, Ghost, alle Größen,
   Icon-Buttons und Links tragen denselben Ring in text-primary.

   REGEL: Der Ring folgt der sichtbaren Hover-/Press-Fläche, nicht
   der Hit-Area. Unsichtbares Padding vergrößert die Touch-Fläche,
   aber nie den Ring.

   Diese Regel greift nur, wenn die Border-Box mit der sichtbaren
   Fläche zusammenfällt — outline-offset misst ab Border-Box. Wer
   die Hit-Area über echtes Padding auf einem äußeren Element
   herstellt, bekommt den Ring um die unsichtbare Fläche. Dafür
   das Muster darunter nutzen, oder besser .touch-target verwenden:
   dessen ::after-Overlay vergrößert die Hit-Area, ohne die
   Border-Box anzufassen — dann stimmt der Ring von allein. */
:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}

/* Für Komponenten mit äußerem Padding-Wrapper: Ring vom Wrapper
   nehmen und an das sichtbare Element hängen.
   <button class="hit-area"><span class="focus-target">…</span></button> */
.hit-area:focus-visible {
  outline: none;
}

.hit-area:focus-visible > .focus-target {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}

/* AUSNAHME: Bedienelemente, die auf einem Bild liegen — etwa der
   Favoriten-Stern auf einem Cover. Dort ist kein Untergrund
   garantiert, und ein weißer Ring auf hellem Cover verschwindet.
   Der Abstand wird deshalb mit surface-primary gefüllt: der Ring
   liegt dann immer auf Dunkel.

   Gilt NUR für diesen Fall. Karten, Buttons und Chips liegen auf
   surface-primary oder surface-card — dort reicht der einfache
   Ring. Nicht großflächig anwenden. */
.on-image:focus-visible {
  box-shadow: 0 0 0 var(--focus-ring-offset) var(--surface-primary);
}
