/*
 * KOTOBA — Landing Page (kotoba-app.de)
 *
 * Standalone CSS auf Bootstrap 5. Übernimmt die Manga-Identität der App:
 * Tusche auf Papier, Zinnoberrot (朱) als einziger Akzent, harte Rahmen
 * statt runder Karten, Halbton als Textur. Kein Tailwind.
 *
 * Farbtokens spiegeln src/styles/tokens.css — bewusst dupliziert, weil die
 * Landingpage ohne App-Bundle ausgeliefert wird und die Tokens dort nicht
 * verfügbar sind. Wer die App-Palette anpasst, zieht diese Datei mit.
 */

/*
 * Dark-first: die Basiswerte sind die dunkle Palette. Wer im Betriebssystem
 * explizit Light will, bekommt sie über die Media Query zurück. Ohne Aussage
 * (kein `prefers-color-scheme`) bleibt es dunkel — die App-Ästhetik ist
 * Tusche auf schwarzem Papier, hier folgt die Verkaufsseite dem gleichen
 * Bild statt sich an eine Systemeinstellung zu hängen.
 */
:root {
  color-scheme: dark light;

  /* Manga-Palette (Dark) — Tusche auf tiefem Papier. Standard. */
  --paper: #0b0b0f;
  --paper-2: #12121a;
  --paper-3: #1a1a24;
  --ink: #ececf1;
  --ink-2: #d2d2dc;
  --muted: #9a9aa8;
  --line: rgba(236, 236, 241, 0.14);
  --line-strong: rgba(236, 236, 241, 0.32);
  --accent: #e0533a; /* 朱 — Zinnoberrot, im Dunkel etwas gelupft */
  --accent-2: #c9351b;
  --accent-ink: #0b0b0f;
  --screentone: rgba(236, 236, 241, 0.06);

  /* Type — Systemschriften wie in der App: keine externe Abhängigkeit,
     schnelle Anzeige, keine Datenschutz-Debatte um Google Fonts. */
  --font-sans:
    system-ui, -apple-system, 'Segoe UI', 'Helvetica Neue', 'Inter', sans-serif;
  --font-jp:
    'Hiragino Mincho ProN', 'Yu Mincho', 'Noto Serif JP', 'Songti SC', 'STSong',
    serif;

  /* Rhythm */
  --radius-panel: 4px;
  --shadow-panel: 0 1px 0 rgba(236, 236, 241, 0.06);

  /*
   * Ein Rhythmus statt fuenf. Vorher hatte jede Sektion ihre eigene Zahl —
   * 4.5rem im Hero, 5rem in den Sektionen, 2rem im Footer — und die Karten
   * warfen ihren harten Schatten mal 4 px, mal 6 px weit. Das ist der
   * Unterschied zwischen „gestaltet" und „zusammengesetzt".
   */
  --space-section: clamp(4rem, 7vw, 6.5rem);
  --shadow-hard: 5px 5px 0 var(--ink);
  --shadow-hard-lift: 8px 8px 0 var(--ink);
  --nav-h: 4.5rem;
}

@media (prefers-color-scheme: light) {
  :root {
    --paper: #f6f1e7;
    --paper-2: #fbf7ee;
    --paper-3: #efe6d1;
    --ink: #16161a;
    --ink-2: #2b2b33;
    --muted: #6a6a75;
    --line: rgba(22, 22, 26, 0.14);
    --line-strong: rgba(22, 22, 26, 0.32);
    --accent: #c9351b;
    --accent-2: #a31f17;
    --accent-ink: #ffffff;
    --screentone: rgba(22, 22, 26, 0.06);
    --shadow-panel: 0 1px 0 rgba(22, 22, 26, 0.06);
  }
}

* {
  box-sizing: border-box;
}

/*
 * Sanftes Scrollen fuer die Ankerlinks im Kopf — und, wichtiger,
 * `scroll-padding-top`: Ohne das schiebt der Sprung die Ueberschrift
 * exakt unter die feste Kopfleiste, und man landet mitten im Fliesstext
 * ohne zu wissen, wo. Der Wert ist die Hoehe der Leiste plus Luft.
 */
html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 0.5rem);
}
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

html,
body {
  margin: 0;
  padding: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/*
 * Bootstrap-Reset überschreiben, wo es einen echten Look kostet:
 * Bootstrap-Buttons sind rund und blau, wir zeichnen sie mit Ink-Linie
 * und Zinnoberrot, ohne Bootstraps utility-Overrides einzeln zu jagen.
 */
a {
  color: var(--accent);
  text-decoration: none;
  transition: color 0.15s ease;
}
a:hover {
  color: var(--accent-2);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ====================================================================
   Layout-Schicht — ersetzt Bootstrap 5

   Bootstrap kostete 232 kB CSS und 80 kB JS. Benutzt wurden davon
   45 Utility-Klassen und KEINE einzige JS-Komponente: die Navbar
   klappt nicht auf (`d-none d-md-flex`), es gibt kein Dropdown, kein
   Modal, kein Carousel. 313 kB für ein Raster und ein paar Abstände.

   Hier steht dasselbe Raster in unter 200 Zeilen. Die Klassennamen
   bleiben Bootstrap-kompatibel, damit das Markup unverändert bleibt
   und niemand beim Lesen zweimal nachdenken muss.

   Diese Schicht steht ABSICHTLICH vor allen `.kt-`-Regeln: genau wie
   vorher, als Bootstrap vor `landing.css` geladen wurde. Die
   Komponenten-Regeln darunter gewinnen also weiterhin.
   ==================================================================== */

:root {
  /* Kurven statt der eingebauten. `ease` und `ease-out` aus der
     CSS-Spezifikation sind zu weich — sie starten zögerlich, und genau
     die ersten 50 ms schaut man beim Hover an. */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
}

.container {
  width: 100%;
  margin-inline: auto;
  padding-inline: 0.75rem;
}
@media (min-width: 576px) {
  .container {
    max-width: 540px;
  }
}
@media (min-width: 768px) {
  .container {
    max-width: 720px;
  }
}
@media (min-width: 992px) {
  .container {
    max-width: 960px;
  }
}
@media (min-width: 1200px) {
  .container {
    max-width: 1140px;
  }
}
@media (min-width: 1400px) {
  .container {
    max-width: 1320px;
  }
}

/*
 * Raster: Flexbox mit `gap` statt Bootstraps negativen Margins.
 * Die Spaltenbreite zieht ihren Anteil am Gutter selbst ab —
 * `Breite = Anteil − Gutter × (1 − Anteil)`. Über eine ganze Zeile
 * summiert sich das exakt auf 100 %, für jede Aufteilung, auch für
 * krumme wie 5/12 + 7/12.
 */
.row {
  --g: 0rem;
  display: flex;
  flex-wrap: wrap;
  gap: var(--g);
}
.row > * {
  width: 100%;
}
.g-4 {
  --g: 1.5rem;
}
.g-5 {
  --g: 3rem;
}

@media (min-width: 768px) {
  .col-md-6 {
    width: calc(50% - var(--g) * 0.5);
  }
}
@media (min-width: 992px) {
  .col-lg-4 {
    width: calc(33.33333% - var(--g) * 0.66667);
  }
  .col-lg-5 {
    width: calc(41.66667% - var(--g) * 0.58333);
  }
  .col-lg-6 {
    width: calc(50% - var(--g) * 0.5);
  }
  .col-lg-7 {
    width: calc(58.33333% - var(--g) * 0.41667);
  }
}

/* Flex- und Abstands-Utilities */
.d-flex {
  display: flex;
}
.d-none {
  display: none;
}
@media (min-width: 768px) {
  .d-md-flex {
    display: flex;
  }
}
.flex-wrap {
  flex-wrap: wrap;
}
.align-items-start {
  align-items: flex-start;
}
.align-items-center {
  align-items: center;
}
.align-items-stretch {
  align-items: stretch;
}
.justify-content-center {
  justify-content: center;
}
.justify-content-between {
  justify-content: space-between;
}
.gap-3 {
  gap: 1rem;
}
.gap-4 {
  gap: 1.5rem;
}

.m-0 {
  margin: 0;
}
.mt-2 {
  margin-top: 0.5rem;
}
.mt-3 {
  margin-top: 1rem;
}
.mt-4 {
  margin-top: 1.5rem;
}
.mt-5 {
  margin-top: 3rem;
}
.mb-3 {
  margin-bottom: 1rem;
}
.ms-2 {
  margin-left: 0.5rem;
}
.ms-3 {
  margin-left: 1rem;
}
.w-100 {
  width: 100%;
}
.h-100 {
  height: 100%;
}
.text-center {
  text-align: center;
}
.small {
  font-size: 0.875em;
}
.h5 {
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1.2;
}
.list-unstyled {
  padding-left: 0;
  list-style: none;
}

/* Navbar — nur das Skelett; das Aussehen macht `.kt-navbar`. */
.navbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
}
.navbar > .container {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
}
.navbar-brand {
  text-decoration: none;
}
.sticky-top {
  position: sticky;
  top: 0;
  z-index: 1020;
}

/* Tabelle */
.table {
  width: 100%;
  border-collapse: collapse;
  caption-side: bottom;
}
.table > :not(caption) > * > * {
  border-bottom: 1px solid var(--line);
}
.table-responsive {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.align-middle {
  vertical-align: middle;
}

/*
 * Knöpfe. `.btn` liefert nur Geometrie und das Druckgefühl — Farbe und
 * Rahmen kommen aus den `.kt-btn-*`-Regeln weiter unten.
 *
 * `:active` mit `scale(0.97)` ist kein Zierrat: Ohne die Rückmeldung
 * wirkt ein Knopf auf dem Handy tot, bis die neue Seite kommt. 100 ms
 * ist die Grenze, unterhalb derer eine Reaktion als „sofort" gilt.
 */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  font: inherit;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  user-select: none;
  border: 1px solid transparent;
  padding: 0.55rem 1.15rem;
  transition: transform 0.1s var(--ease-out);
}
/*
 * Der globale `a:hover` unterstreicht — und ein Knopf ist hier ein
 * `<a>`. Unter dem Zeiger bekam „Kostenlos starten" in der Kopfleiste
 * also eine Unterstreichung mitten durch die rote Flaeche. Die
 * Spezifitaet von `a:hover` (0,1,1) schlaegt `.btn` (0,1,0), deshalb
 * muss die Ausnahme selbst ein Zustand sein.
 */
.btn:hover,
.btn:focus,
.btn:active {
  text-decoration: none;
}
.btn:active {
  transform: scale(0.97);
}
.btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.btn-lg {
  font-size: 1.15rem;
}
/* Der Hero-CTA ist das wichtigste Element der Seite — er darf Fläche
   haben. Bootstraps `.btn-lg` kam hier nie an, weil die `.kt-`-Regeln
   ihr eigenes Padding setzen. */
.kt-btn-primary.btn-lg,
.kt-btn-outline.btn-lg {
  padding: 0.8rem 1.6rem;
}

/* Formular */
.form-label {
  display: inline-block;
}
.form-control,
.form-select {
  display: block;
  width: 100%;
  font: inherit;
  line-height: 1.5;
  appearance: none;
}
.form-select {
  /* Eigenes Chevron statt des System-Widgets: das Betriebssystem-Blau
     ist die einzige Farbe, die sich nicht aus den Tokens ergibt. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%239a9aa8' stroke-width='2' d='m2 5 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.75rem center;
  background-size: 14px;
  padding-right: 2.25rem !important;
}

/* --------------------------------------------------------------------
   Speicherhinweis (kein Cookie-Banner — siehe HTML)

   Sitzt fest oben, über dem Sticky-Header. Wenn er sichtbar ist, schiebt
   er sich vor die Navbar; nach dem "Verstanden"-Klick wird `hidden`
   gesetzt und er ist samt Platz weg (kein CSS-Layout-Trick, ein echter
   DOM-Zustand).
   -------------------------------------------------------------------- */
#kt-storage-notice {
  position: sticky;
  top: 0;
  z-index: 1050;
  background: color-mix(in srgb, var(--paper-2) 96%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--line);
  padding: 0.75rem 1rem;
}
.kt-storage-notice-body {
  max-width: 60rem;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}
.kt-storage-notice-body p {
  flex: 1;
  min-width: 15rem;
  margin: 0;
  color: var(--ink-2);
  font-size: 0.9rem;
  line-height: 1.45;
}
.kt-storage-notice-body a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 3px;
}
#kt-storage-notice-ok {
  padding: 0.4rem 1rem;
  font-size: 0.9rem;
  flex-shrink: 0;
}
@media (max-width: 575.98px) {
  .kt-storage-notice-body p {
    font-size: 0.85rem;
  }
}

/* --------------------------------------------------------------------
   Navbar (sticky top)
   -------------------------------------------------------------------- */
/*
 * `space-between` verteilt bei vier Kindern (Marke, Navigation, Anmelden,
 * CTA) drei gleich große Lücken — die Navigation stand dadurch einsam in
 * der Mitte. `margin-right: auto` sammelt sie neben der Marke ein und
 * schiebt die beiden Aktionen als Paar an den rechten Rand.
 */
.kt-navbar .kt-nav {
  margin-right: auto;
  margin-left: 2.5rem;
}
.kt-navbar {
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter: saturate(180%) blur(10px);
  -webkit-backdrop-filter: saturate(180%) blur(10px);
  border-bottom: 1px solid var(--line);
  padding: 0.75rem 0;
}

.kt-brand {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--ink) !important;
}
.kt-brand:hover {
  text-decoration: none;
  color: var(--ink) !important;
}
.kt-brand-glyph {
  font-family: var(--font-jp);
  font-weight: 700;
  color: var(--accent);
  font-size: 1.25rem;
  line-height: 1;
}
.kt-brand-glyph.small {
  font-size: 0.9em;
}
/* Shishi-Logo im Header: konstante Größe, unabhängig vom SVG-Aspekt.
   Die SVG von /public/sensei hat ein weites viewBox — ohne fixe Höhe
   würde sie sich mit dem Header aufblähen. */
.kt-brand-logo {
  width: 36px;
  height: 36px;
  display: block;
  flex-shrink: 0;
}
.kt-brand-word {
  font-size: 0.95rem;
}

.kt-nav a {
  color: var(--ink-2);
  font-weight: 500;
  font-size: 0.95rem;
}
.kt-nav a:hover {
  color: var(--accent);
  text-decoration: none;
}
/*
 * Der aktive Abschnitt. Ein feiner Strich darunter statt Fettung oder
 * Farbwechsel: Fettung veraendert die Textbreite und laesst die ganze
 * Leiste bei jedem Abschnitt neu springen.
 */
.kt-nav a {
  position: relative;
  padding-block: 0.35rem;
  transition: color 0.15s ease;
}
.kt-nav a::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.22s var(--ease-out);
}
.kt-nav a[data-active] {
  color: var(--ink);
}
.kt-nav a[data-active]::after {
  transform: scaleX(1);
}

/* --------------------------------------------------------------------
   Buttons — Ink + Zinnoberrot statt Bootstraps Blau
   -------------------------------------------------------------------- */
.kt-btn-primary {
  background: var(--accent);
  color: var(--accent-ink);
  border: 1.5px solid var(--accent);
  border-radius: var(--radius-panel);
  font-weight: 600;
  letter-spacing: 0.01em;
  padding: 0.55rem 1.15rem;
  transition:
    transform 0.1s var(--ease-out),
    background-color 0.15s ease,
    border-color 0.15s ease,
    box-shadow 0.15s var(--ease-out);
  box-shadow: 0 2px 0 var(--accent-2);
}
.kt-btn-primary:hover,
.kt-btn-primary:focus {
  background: var(--accent-2);
  color: var(--accent-ink);
  border-color: var(--accent-2);
}
/*
 * Der Lift nur, wo es einen echten Zeiger gibt. Auf dem Handy löst ein
 * Tap `:hover` mit aus und der Knopf bleibt danach angehoben stehen —
 * er sieht dann aus, als sei er noch gedrueckt.
 */
@media (hover: hover) and (pointer: fine) {
  .kt-btn-primary:hover {
    transform: translateY(-1px);
    box-shadow: 0 3px 0 var(--accent-2);
  }
}
/* Eigene Druck-Rückmeldung statt `.btn:active { scale }`: Der Knopf
   sinkt in seinen Schlagschatten. Passt zum harten Manga-Rahmen. */
.kt-btn-primary:active {
  transform: translateY(1px);
  box-shadow: 0 1px 0 var(--accent-2);
}

.kt-btn-outline {
  background: transparent;
  color: var(--ink);
  border: 1.5px solid var(--ink);
  border-radius: var(--radius-panel);
  font-weight: 600;
  padding: 0.55rem 1.15rem;
  transition:
    background-color 0.15s ease,
    color 0.15s ease,
    transform 0.1s var(--ease-out);
}
.kt-btn-outline:hover,
.kt-btn-outline:focus {
  background: var(--ink);
  color: var(--paper);
}

.kt-btn-ghost {
  background: transparent;
  color: var(--ink-2);
  border: none;
  font-weight: 500;
  padding: 0.55rem 0.75rem;
}
.kt-btn-ghost:hover {
  color: var(--accent);
  background: transparent;
}

/* --------------------------------------------------------------------
   Typografie
   -------------------------------------------------------------------- */
/*
 * Die Ueberzeile stand in Mincho — einer Serifenschrift mit harten,
 * dreieckigen Serifen. In Versalien, klein und eng gesperrt wird daraus
 * ein kantiger Block, und auf Windows faellt sie ausserdem auf eine noch
 * haertere Systemserife zurueck.
 *
 * Jetzt dieselbe Grotesk wie der Fliesstext, dafuer weiter gesperrt: Was
 * eine Ueberzeile leisten muss — leise sein und trotzdem gliedern —
 * leistet die Sperrung, nicht die Schriftart. Der Strich davor ist die
 * Panelkante des Manga-Rasters und wiederholt sich in jeder Sektion.
 */
.kt-eyebrow {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  font-family: var(--font-sans);
  color: var(--accent);
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-size: 0.7rem;
  margin: 0 0 1.1rem;
}
.kt-eyebrow::before {
  content: '';
  flex: 0 0 auto;
  width: 1.5rem;
  height: 2px;
  background: currentColor;
}
/* Zentrierte Sektionen: der Strich steht dann auf beiden Seiten. */
.text-center > .kt-eyebrow,
.kt-eyebrow.text-center {
  justify-content: center;
}
.text-center > .kt-eyebrow::after,
.kt-eyebrow.text-center::after {
  content: '';
  flex: 0 0 auto;
  width: 1.5rem;
  height: 2px;
  background: currentColor;
}
.kt-h1 {
  font-size: clamp(2.1rem, 4.6vw, 3.6rem);
  line-height: 1.1;
  font-weight: 700;
  color: var(--ink);
  letter-spacing: -0.02em;
  margin: 0 0 1.25rem;
}
.kt-h2 {
  font-size: clamp(1.6rem, 3vw, 2.4rem);
  line-height: 1.2;
  font-weight: 700;
  color: var(--ink);
  letter-spacing: -0.015em;
  margin: 0 0 1rem;
}
/*
 * Sumi-Strich unter dem Schluesselwort.
 *
 * Vorher ein Verlauf im Hintergrund, der bei 78 % der Zeilenhoehe ansetzte:
 * Das klebte an der Grundlinie und schnitt jede Unterlaenge — das „g" in
 * „anfaengst" lag mitten im Strich.
 *
 * `text-decoration` kann dasselbe, aber mit einem Abstand, den man in em
 * angibt: Der Strich waechst mit der Schriftgroesse mit, statt sich mit
 * jeder Ueberschrift neu zu verschieben. `skip-ink: none` haelt ihn
 * durchgehend, so wie ein Pinselzug es waere.
 */
.kt-accent {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-decoration-thickness: 0.075em;
  text-underline-offset: 0.19em;
  text-decoration-skip-ink: none;
}
.kt-lead {
  font-size: 1.125rem;
  color: var(--ink-2);
  max-width: 40rem;
  margin: 0 0 1rem;
}
.kt-section-lead {
  font-size: 1.05rem;
  color: var(--ink-2);
  max-width: 44rem;
  margin: 0 0 0.5rem;
}
.kt-note {
  color: var(--muted);
  font-size: 0.9rem;
  max-width: 44rem;
  line-height: 1.65;
}
/*
 * `text-center` zentriert die Zeilen INNERHALB des Blocks — der Block
 * selbst blieb mit seinen 44rem am linken Rand kleben. Genau so stand der
 * Preis-Hinweis unter den Tarifen: mittig gesetzt, aber sichtbar zu weit
 * links. Ein zentrierter Textblock braucht beides.
 */
.kt-note.text-center,
.kt-section-lead.text-center,
.kt-lead.text-center {
  margin-inline: auto;
}
.kt-note a {
  color: var(--muted);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* --------------------------------------------------------------------
   Sektionsraster
   -------------------------------------------------------------------- */
.kt-section {
  padding: var(--space-section) 0;
  border-bottom: 1px solid var(--line);
}
/*
 * Ueberzeile, Ueberschrift und Vorspann als ein Block: Der Abstand zwischen
 * ihnen ist immer derselbe, der Abstand zum Inhalt darunter immer groesser
 * als der zwischen ihnen. Das ist die einzige Regel, die eine Seite
 * ruhig aussehen laesst — Naehe bedeutet Zusammengehoerigkeit.
 */
.kt-section > .container > .kt-section-lead,
.kt-section > .container > .row > * > .kt-section-lead {
  margin-bottom: 0;
}
.kt-section-alt {
  background: var(--paper-2);
}
.kt-hero-meta {
  color: var(--muted);
  font-size: 0.95rem;
  margin: 0;
}
.kt-hero-meta li {
  white-space: nowrap;
}
/* Trennpunkt in Zinnoberrot — der Akzent der Seite, in der kleinsten
   Dosis, die es gibt. */
.kt-dot {
  color: var(--accent);
  padding: 0 0.15rem;
}

/* --------------------------------------------------------------------
   Hero
   -------------------------------------------------------------------- */
.kt-hero {
  padding: calc(var(--space-section) * 0.85) 0 var(--space-section);
  position: relative;
  overflow: hidden;
}
.kt-hero::before {
  /* Sumi-Ecken: zwei feine Zierlinien oben rechts, damit die
     leere Ecke des Heros nicht wie ein Rand aussieht, sondern
     wie das obere Panel eines Manga-Kapitels. */
  content: '';
  position: absolute;
  top: 3rem;
  right: 2rem;
  width: 3.5rem;
  height: 3.5rem;
  border-top: 2px solid var(--ink);
  border-right: 2px solid var(--ink);
  opacity: 0.5;
  pointer-events: none;
}

/* --------------------------------------------------------------------
   Panel + SpeechBubble (Manga-Primitives)
   -------------------------------------------------------------------- */
.kt-panel {
  position: relative;
  background: var(--paper-2);
  border: 2px solid var(--ink);
  border-radius: var(--radius-panel);
  padding: 1.5rem;
  box-shadow: var(--shadow-hard);
}
.screentone {
  background-image: radial-gradient(var(--screentone) 1px, transparent 1.4px);
  background-size: 6px 6px;
  background-position: 0 0;
}
.kt-panel-tag {
  position: absolute;
  top: -0.75rem;
  left: 1rem;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-jp);
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  padding: 0.2rem 0.6rem;
  border-radius: 2px;
  z-index: 1;
}
/*
 * Das Zeichen steht in der Zeile, nicht darüber: Die beiden Eselsbrücken-
 * Panels sollen sich zeilenweise vergleichen lassen, und eine eigene
 * Glyphenzeile würde die Fassungen auseinanderziehen.
 */
.kt-glyph-inline {
  font-family: var(--font-jp);
  font-size: 1.5rem;
  line-height: 1;
  margin-right: 0.5rem;
  color: var(--accent);
  vertical-align: -0.15em;
}
.kt-hero-panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  padding: 2rem 1.5rem 1.25rem;
}
.kt-hero-panel img {
  width: 100%;
  max-width: 320px;
  height: auto;
  display: block;
}
.kt-bubble {
  position: relative;
  background: var(--paper);
  border: 2px solid var(--ink);
  border-radius: 20px;
  padding: 0.85rem 1.15rem;
  font-family: var(--font-jp);
  font-weight: 600;
  color: var(--ink);
  text-align: center;
  font-size: 0.95rem;
  max-width: 90%;
  margin: 0;
}
.kt-bubble::before {
  content: '';
  position: absolute;
  top: -12px;
  left: 50%;
  transform: translateX(-50%);
  border: 8px solid transparent;
  border-top: 0;
  border-bottom: 12px solid var(--ink);
}
.kt-bubble::after {
  content: '';
  position: absolute;
  top: -8px;
  left: 50%;
  transform: translateX(-50%);
  border: 6px solid transparent;
  border-top: 0;
  border-bottom: 10px solid var(--paper);
}

/* --------------------------------------------------------------------
   Feature-Karten (Warum KOTOBA)
   -------------------------------------------------------------------- */
.kt-feature-card {
  background: var(--paper-2);
  border: 1.5px solid var(--line-strong);
  border-radius: var(--radius-panel);
  padding: 1.5rem 1.4rem;
  height: 100%;
  position: relative;
  transition:
    transform 0.18s var(--ease-out),
    border-color 0.18s ease,
    box-shadow 0.18s var(--ease-out);
}
/*
 * Sechs formgleiche Karten in einem sauberen 3x2-Raster sind das
 * Erkennungszeichen jeder generierten Verkaufsseite. Das Gegenmittel liegt
 * hier schon bereit: Ein Manga liest sich als Folge nummerierter Panels,
 * und der Halbton wechselt von Panel zu Panel.
 *
 * `japanese-informal` ist ein vordefinierter CSS-Zählstil — 一, 二, 三 …
 * kommen aus dem Browser, nicht aus dem Markup. Am HTML ändert sich
 * nichts.
 */
#warum .row {
  counter-reset: kt-panel;
}
.kt-feature-card {
  counter-increment: kt-panel;
}
.kt-feature-card::after {
  content: counter(kt-panel, japanese-informal);
  position: absolute;
  top: 0.9rem;
  right: 1rem;
  font-family: var(--font-jp);
  font-size: 0.95rem;
  color: var(--line-strong);
  line-height: 1;
  pointer-events: none;
}
#warum .row > :nth-child(even) .kt-feature-card {
  background-image: radial-gradient(var(--screentone) 1px, transparent 1.4px);
  background-size: 6px 6px;
}
@media (hover: hover) and (pointer: fine) {
  .kt-feature-card:hover {
    transform: translateY(-3px);
    border-color: var(--accent);
    box-shadow: var(--shadow-hard);
  }
}
.kt-feature-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  background: var(--accent);
  color: var(--accent-ink);
  font-family: var(--font-jp);
  font-weight: 700;
  font-size: 1.35rem;
  border-radius: var(--radius-panel);
  margin-bottom: 1rem;
  line-height: 1;
}
.kt-feature-card h3 {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 0.4rem;
}
.kt-feature-card p {
  color: var(--ink-2);
  margin: 0;
  font-size: 0.95rem;
}

/* --------------------------------------------------------------------
   Vergleich Anki vs. KOTOBA
   -------------------------------------------------------------------- */
/*
 * Der Umbau hier hat vier Ursachen, und alle vier waren dasselbe Problem:
 * Die Tabelle sah unfair aus, obwohl das Argument fair ist.
 *
 * 1. Die Zeilenbeschriftung stand ZENTRIERT, beide Inhaltsspalten links.
 *    Ein zentrierter Text neben linksbuendigem hat keine gemeinsame Kante,
 *    und das Auge liest die fehlende Kante als Unordnung.
 * 2. Die Spalten waren 30 / 20 / 50 breit. Die Anki-Spalte brach dadurch
 *    fast jede Zeile um, die KOTOBA-Spalte fast keine — eine Tabelle, die
 *    zwei Dinge vergleicht, muss beiden gleich viel Platz geben, sonst
 *    argumentiert das Layout mit und wirkt geschoenter als der Text.
 * 3. Die rote Kante der KOTOBA-Spalte begann erst unter dem Kopf. Eine
 *    senkrechte Linie, die nach zwei Zentimetern aussetzt, liest sich als
 *    Fehler, nicht als Gestaltung.
 * 4. Jede Zeile hatte einen durchgehenden Trennstrich ueber alle drei
 *    Spalten — daraus wurde eine Leiter statt einer Tabelle.
 */
.kt-compare {
  border: 2px solid var(--ink);
  background: var(--paper);
  margin: 0;
  min-width: 44rem;
  border-collapse: separate;
  border-spacing: 0;
  box-shadow: var(--shadow-hard);
}
.kt-compare th,
.kt-compare td {
  padding: 1rem 1.15rem;
  vertical-align: top;
  text-align: left;
  color: var(--ink-2);
  line-height: 1.55;
  border-bottom: 1px solid var(--line);
}
.kt-compare tbody tr:last-child > * {
  border-bottom: none;
}
.kt-compare thead th {
  background: var(--ink);
  color: var(--paper);
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: 0.02em;
  border-bottom: none;
  vertical-align: middle;
  padding-block: 0.85rem;
}
/* Gleich breite Vergleichsspalten — das ist der eigentliche Fix.
   Nur ab Tablet: Auf dem Handy stehen die Zellen untereinander (siehe
   unten) und muessen die volle Breite bekommen. Eine feste Prozentbreite
   schlaegt dort sonst das `width: auto` der Stapel-Regeln, weil sie
   spezifischer ist — genau das hat die Zellen erst auf drei Woerter
   pro Zeile zusammengequetscht. */
@media (min-width: 768px) {
  .kt-compare thead th:first-child {
    width: 24%;
  }
  .kt-compare .kt-col-anki {
    width: 38%;
  }
  .kt-compare .kt-col-kotoba {
    width: 38%;
  }
}

.kt-compare tbody th {
  background: var(--paper-2);
  color: var(--ink);
  font-weight: 600;
  font-size: 0.95rem;
}
.kt-compare .kt-col-anki {
  color: var(--muted);
}
.kt-compare .kt-col-kotoba {
  color: var(--ink);
  background: color-mix(in srgb, var(--accent) 7%, var(--paper));
  box-shadow: inset 2px 0 0 var(--accent);
  font-weight: 500;
}
/* Der Kopf traegt die Kante mit, damit die Senkrechte durchlaeuft. */
.kt-compare thead .kt-col-kotoba {
  background: var(--accent);
  color: var(--accent-ink);
  box-shadow: inset 2px 0 0 var(--accent);
}
.kt-compare thead .kt-col-kotoba .kt-brand-glyph {
  color: var(--accent-ink);
  margin-right: 0.35rem;
}
/* Zeile unter dem Zeiger hervorheben: Bei zehn Zeilen ueber die volle
   Breite verliert man sonst die Spur. Nur mit echtem Zeiger — auf dem
   Handy bliebe die zuletzt getippte Zeile markiert stehen. */
@media (hover: hover) and (pointer: fine) {
  .kt-compare tbody tr {
    transition: background-color 0.15s ease;
  }
  .kt-compare tbody tr:hover > th,
  .kt-compare tbody tr:hover > td {
    background: color-mix(in srgb, var(--ink) 4%, var(--paper-2));
  }
  .kt-compare tbody tr:hover > .kt-col-kotoba {
    background: color-mix(in srgb, var(--accent) 12%, var(--paper));
  }
}
.table-responsive {
  padding: 0 0 0.5rem;
}

/*
 * Auf dem Handy wird aus der Tabelle ein Stapel Panels — eines je
 * Kriterium, mit beiden Antworten untereinander.
 *
 * Der Grund ist kein aesthetischer: Drei Spalten auf 390 px brauchen
 * waagerechtes Scrollen, und dann liegt ausgerechnet die KOTOBA-Spalte
 * ausserhalb des Bildes. Eine Vergleichstabelle, deren dritte Spalte man
 * suchen muss, vergleicht nichts.
 *
 * Die Spaltenkoepfe kommen als `::before` zurueck — dieselbe Information,
 * nur pro Zeile statt pro Tabelle. Am Markup aendert sich nichts.
 */
@media (max-width: 767.98px) {
  .kt-compare {
    min-width: 0;
    display: block;
    border: none;
    box-shadow: none;
    background: transparent;
  }
  .kt-compare thead {
    display: none;
  }
  .kt-compare tbody,
  .kt-compare tr {
    display: block;
  }
  .kt-compare tr {
    border: 2px solid var(--ink);
    box-shadow: var(--shadow-hard);
    background: var(--paper);
    margin-bottom: 1.5rem;
  }
  .kt-compare tr:last-child {
    margin-bottom: 0;
  }
  .kt-compare th,
  .kt-compare td {
    display: block;
    width: auto;
    padding: 0.85rem 1rem;
  }
  .kt-compare tbody th {
    background: var(--ink);
    color: var(--paper);
    border-bottom: none;
    letter-spacing: 0.02em;
  }
  .kt-compare .kt-col-anki,
  .kt-compare .kt-col-kotoba {
    padding-top: 0.65rem;
  }
  .kt-compare .kt-col-anki::before,
  .kt-compare .kt-col-kotoba::before {
    display: block;
    margin-bottom: 0.3rem;
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
  }
  .kt-compare .kt-col-anki::before {
    content: 'Anki';
    color: var(--muted);
  }
  .kt-compare .kt-col-kotoba::before {
    content: 'KOTOBA';
    color: var(--accent);
  }
  .kt-compare tbody tr:last-child > .kt-col-kotoba {
    border-bottom: none;
  }
}

/* --------------------------------------------------------------------
   Preise
   -------------------------------------------------------------------- */
/* Der Knopf wird nach unten geschoben, damit beide Tarifkarten ihren CTA
   auf derselben Linie haben — sonst haengt der kuerzere Tarif in der Luft
   und die beiden Karten wirken wie zwei verschiedene Bausteine.
   Den Mindestabstand traegt die Liste: `margin-top: auto` faellt in der
   volleren Karte auf 0 zusammen, der Knopf klebte dort sonst am letzten
   Listenpunkt. */
.kt-price > .btn {
  margin-top: auto;
}
.kt-price-list {
  margin-bottom: 1.5rem;
}
.kt-price {
  position: relative;
  background: var(--paper-2);
  border: 1.5px solid var(--line-strong);
  border-radius: var(--radius-panel);
  padding: 1.75rem 1.5rem;
  display: flex;
  flex-direction: column;
  height: 100%;
}
.kt-price-free {
  background: var(--paper);
  border-color: var(--ink);
  border-width: 2px;
}
.kt-price-featured {
  background: var(--paper);
  border: 2px solid var(--accent);
  box-shadow: var(--shadow-hard);
  transform: translateY(-4px);
}
.kt-ribbon {
  position: absolute;
  top: -0.85rem;
  right: 1rem;
  background: var(--accent);
  color: var(--accent-ink);
  font-family: var(--font-jp);
  font-weight: 700;
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  padding: 0.25rem 0.65rem;
  border-radius: 2px;
}
.kt-price-tag {
  font-family: var(--font-jp);
  font-weight: 700;
  color: var(--accent);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-size: 0.78rem;
  margin: 0 0 0.35rem;
}
.kt-price-name {
  font-size: 1.35rem;
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 0.75rem;
  letter-spacing: -0.01em;
}
.kt-price-amount {
  display: flex;
  align-items: baseline;
  gap: 0.45rem;
  margin: 0 0 1rem;
  padding-bottom: 1rem;
  border-bottom: 1px dashed var(--line-strong);
}
.kt-amount {
  font-size: 2.1rem;
  font-weight: 700;
  color: var(--ink);
  letter-spacing: -0.02em;
}
.kt-per {
  color: var(--muted);
  font-size: 0.9rem;
}
.kt-price-list {
  list-style: none;
  padding: 0;
  margin: 0 0 auto;
  flex: 1;
}
.kt-price-list li {
  position: relative;
  padding: 0.4rem 0 0.4rem 1.5rem;
  color: var(--ink-2);
  font-size: 0.95rem;
  border-bottom: 1px solid var(--line);
}
.kt-price-list li:last-child {
  border-bottom: none;
}
.kt-price-list li::before {
  content: '✓';
  position: absolute;
  left: 0;
  top: 0.4rem;
  color: var(--accent);
  font-weight: 700;
}

/* --------------------------------------------------------------------
   Hero — Store-Zeile ("Auch als App — iOS · Android")
   -------------------------------------------------------------------- */
.kt-hero-storeline {
  margin: 1.25rem 0 0;
  color: var(--muted);
  font-size: 0.92rem;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.kt-hero-storelink {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  color: var(--ink-2);
  font-weight: 600;
  text-decoration: none;
  padding: 0.1rem 0.25rem;
  border-radius: 3px;
  transition:
    color 0.15s ease,
    background 0.15s ease;
}
.kt-hero-storelink:hover {
  color: var(--accent);
  text-decoration: none;
}
/* Highlight des passenden Stores in der Hero-Zeile: ein dezenter
   Zinnoberrot-Punkt links, sobald wir wissen, worauf die Person surft. */
:root[data-platform='ios'] .kt-hero-storelink[data-store='ios'],
:root[data-platform='android'] .kt-hero-storelink[data-store='android'] {
  color: var(--accent);
}

/* --------------------------------------------------------------------
   App-Sektion — Store-Badges
   -------------------------------------------------------------------- */
.kt-stores {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin: 0.5rem 0 1.25rem;
}
.kt-store-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 12rem;
  padding: 0.75rem 1.15rem;
  background: var(--ink);
  color: var(--paper);
  border: 2px solid var(--ink);
  border-radius: 8px;
  text-decoration: none;
  transition:
    transform 0.12s var(--ease-out),
    box-shadow 0.15s var(--ease-out),
    background-color 0.15s ease;
  box-shadow: 4px 4px 0 var(--accent-2);
}
.kt-store-badge:hover,
.kt-store-badge:focus {
  color: var(--paper);
  text-decoration: none;
}
@media (hover: hover) and (pointer: fine) {
  .kt-store-badge:hover {
    transform: translateY(-2px);
    box-shadow: 6px 6px 0 var(--accent-2);
  }
}
.kt-store-badge:active {
  transform: translateY(1px);
  box-shadow: 2px 2px 0 var(--accent-2);
}
.kt-store-icon {
  flex: 0 0 auto;
}
.kt-store-copy {
  display: flex;
  flex-direction: column;
  line-height: 1.1;
}
.kt-store-pre {
  font-size: 0.7rem;
  opacity: 0.75;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.kt-store-name {
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0.01em;
}

/*
 * Plattform-Hervorhebung.
 *
 * Auf iOS/Android wird der jeweils passende Badge größer und mit einem
 * Zinnoberrot-Rahmen versehen; der andere bleibt sichtbar (schmaler und
 * gedämpft), damit man auch für Partner/Familie den anderen Store öffnen
 * kann. Auf Desktop (`data-platform="desktop"` oder gar keins) bleiben
 * beide gleichwertig.
 */
:root[data-platform='ios'] .kt-store-ios,
:root[data-platform='android'] .kt-store-android {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
  box-shadow: 6px 6px 0 var(--ink);
  transform: translateY(-2px);
}
:root[data-platform='ios'] .kt-store-ios:hover,
:root[data-platform='android'] .kt-store-android:hover {
  color: var(--accent-ink);
  background: var(--accent-2);
  transform: translateY(-4px);
}
:root[data-platform='ios'] .kt-store-android,
:root[data-platform='android'] .kt-store-ios {
  opacity: 0.5;
}
:root[data-platform='ios'] .kt-store-android:hover,
:root[data-platform='android'] .kt-store-ios:hover {
  opacity: 1;
}

.kt-stores-hint {
  color: var(--muted);
  font-size: 0.9rem;
  margin: 0.5rem 0 0;
  max-width: 30rem;
}

/* --------------------------------------------------------------------
   Kontakt
   -------------------------------------------------------------------- */
.kt-contact-list {
  margin: 1.5rem 0 0;
  padding: 0;
}
.kt-contact-list li {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--line);
  font-size: 0.98rem;
}
.kt-contact-label {
  font-family: var(--font-jp);
  font-weight: 700;
  color: var(--accent);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: 0.75rem;
  min-width: 4rem;
}

.kt-contact-panel {
  background: var(--paper);
  border: 2px solid var(--ink);
  border-radius: var(--radius-panel);
  padding: 1.75rem 1.5rem;
  box-shadow: 6px 6px 0 var(--ink);
}
.kt-contact-panel .form-label {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink-2);
  letter-spacing: 0.02em;
  margin-bottom: 0.35rem;
}
.kt-contact-panel .form-control,
.kt-contact-panel .form-select {
  background: var(--paper-2);
  color: var(--ink);
  border: 1.5px solid var(--line-strong);
  border-radius: var(--radius-panel);
  padding: 0.55rem 0.75rem;
  font-size: 0.95rem;
  transition:
    border-color 0.15s ease,
    box-shadow 0.15s ease;
}
.kt-contact-panel .form-control::placeholder {
  color: var(--muted);
  opacity: 1;
}
.kt-contact-panel .form-control:focus,
.kt-contact-panel .form-select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
  outline: none;
}
.kt-hint {
  color: var(--muted);
  font-size: 0.85rem;
  margin: 0;
  text-align: center;
}

/* Honigtopf gegen Formular-Bots. Nicht `display: none` — manche Bots
   überspringen genau das und füllen nur sichtbare Felder aus. Aus dem
   Blickfeld schieben wirkt zuverlässiger. */
.kt-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Rückmeldung nach dem Absenden. Leer, bis etwas zu sagen ist — und
   `role="status"` im Markup, damit ein Screenreader es vorliest, ohne
   dass der Fokus springt. */
.kt-contact-status {
  font-size: 0.9rem;
  margin: 0.75rem 0 0;
  text-align: center;
}
.kt-contact-status:empty {
  display: none;
}
.kt-contact-status[data-tone='ok'] {
  color: var(--accent);
}
.kt-contact-status[data-tone='error'] {
  color: #e5484d;
}

/* --------------------------------------------------------------------
   FAQ

   Der Abschnitt existiert nicht aus Deko-Gründen: Im Kopf der Seite
   steht ein `FAQPage`-JSON-LD mit sechs Fragen. Googles Richtlinie
   verlangt, dass ausgezeichneter Inhalt auf der Seite auch sichtbar
   ist — sechs Fragen nur im Markup sind ein Verstoß, im schlimmsten
   Fall mit Verlust aller Rich Results. Ausserdem ist genau dieser Text
   das, woraus ein KI-Assistent zitiert, wenn jemand fragt „womit lerne
   ich Japanisch".

   Gebaut mit `<details name>`: Das Betriebssystem kann Akkordeon von
   sich aus, exklusiv aufklappbar, tastaturbedienbar, durchsuchbar per
   Strg+F. Kein JavaScript, keine ARIA-Handarbeit.
   -------------------------------------------------------------------- */
/* Mittig gesetzt: Der Abschnitt hat keine zweite Spalte neben sich, und
   eine 48rem breite Liste am linken Rand einer 1320px-Seite laesst die
   rechte Haelfte leer aussehen. */
/* Der zentrierte Sektionskopf faerbt auf alles darunter ab — die
   FAQ-Zeilen bleiben aber linksbuendig lesbar. */
.kt-faq {
  max-width: 48rem;
  margin: 2.5rem auto 0;
  border-top: 1.5px solid var(--line-strong);
  text-align: left;
}
.kt-faq-item {
  border-bottom: 1.5px solid var(--line-strong);
}
.kt-faq-item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.1rem 0.25rem;
  cursor: pointer;
  list-style: none;
  font-weight: 600;
  font-size: 1.05rem;
  color: var(--ink);
  transition: color 0.15s ease;
}
.kt-faq-item summary::-webkit-details-marker {
  display: none;
}
.kt-faq-item summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
@media (hover: hover) and (pointer: fine) {
  .kt-faq-item summary:hover {
    color: var(--accent);
  }
}
/*
 * Der Winkel ist die einzige Bewegung hier — und die einzige, die ohne
 * Hack laeuft: `<summary>` bleibt gerendert, auch wenn zu ist. Den
 * Inhalt selbst aufzuklappen wäre eine Höhen-Animation, und die
 * kostet Layout auf jedem Frame für eine Geste, die man dreimal im
 * Leben macht.
 */
.kt-faq-chevron {
  flex: 0 0 auto;
  color: var(--accent);
  transition: transform 0.18s var(--ease-out);
}
.kt-faq-item[open] .kt-faq-chevron {
  transform: rotate(180deg);
}
.kt-faq-answer {
  margin: 0;
  padding: 0 0.25rem 1.35rem;
  color: var(--ink-2);
  max-width: 44rem;
}

/* --------------------------------------------------------------------
   Abschluss-CTA
   -------------------------------------------------------------------- */
.kt-cta {
  padding: var(--space-section) 0;
  background: var(--ink);
  color: var(--paper);
  text-align: center;
}
.kt-cta .kt-h2 {
  color: var(--paper);
}
/*
 * `.kt-note` ist für die hellen Sektionen gebaut und holt sich `--muted` —
 * ein gedämpftes Grau, das auf Papier funktioniert. Auf der Tuschefläche der
 * CTA steht es dunkelgrau auf fast schwarz und ist praktisch unlesbar.
 *
 * Dieselbe Rechnung wie bei `.kt-cta-lead` eine Zeile weiter oben: gedämpft,
 * aber ausgehend von der hellen Seite. Der Link darin bleibt etwas heller
 * als der Fließtext, sonst verschwindet er im Absatz.
 */
.kt-cta .kt-note {
  color: color-mix(in srgb, var(--paper) 78%, var(--ink));
}
.kt-cta .kt-note a {
  color: var(--paper);
}

/* --------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------- */
.kt-footer {
  padding: 2rem 0;
  background: var(--paper-2);
  color: var(--muted);
  font-size: 0.9rem;
  border-top: 1px solid var(--line);
}
.kt-footer a {
  color: var(--muted);
}
.kt-footer a:hover {
  color: var(--accent);
}
.kt-footer-nav {
  display: flex;
  gap: 1.25rem;
  flex-wrap: wrap;
}

/* Community-Marken — im Header neben den Knöpfen und im Footer. Gefüllte Markenzeichen statt gestrichelter
   Icons — anders erkennt sie niemand. Ruhig gefärbt wie der Rest der
   Fußzeile, erst beim Überfahren volle Deckkraft. */
.kt-social {
  display: flex;
  align-items: center;
  gap: 0.9rem;
}

.kt-social a {
  display: inline-flex;
  color: inherit;
  opacity: 0.65;
  transition: opacity 0.15s ease;
}

.kt-social a:hover,
.kt-social a:focus-visible {
  opacity: 1;
}

/* --------------------------------------------------------------------
   Themenseiten (/kanji-lernen, /jlpt-vorbereitung …)

   Dieselbe Hülle wie die Landingpage, aber ein Textkopf statt eines
   Heros mit Bild: Auf einer Seite, die etwas erklärt, ist die erste
   Antwort das Bild.
   -------------------------------------------------------------------- */
.kt-hero-topic {
  padding-bottom: calc(var(--space-section) * 0.7);
}
.kt-h1-topic {
  font-size: clamp(1.9rem, 3.6vw, 2.9rem);
  max-width: 22ch;
}

/* Brotkrümel: klein, leise, aber vorhanden. Auf einer Unterseite ist
   „wo bin ich, und wie komme ich zurück" die erste Frage. */
.kt-crumbs {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.8rem;
  color: var(--muted);
  margin-bottom: 1.25rem;
  letter-spacing: 0.02em;
}
.kt-crumbs a {
  color: var(--muted);
}
.kt-crumbs a:hover {
  color: var(--accent);
}

/*
 * Der Antwortabsatz direkt unter der Einleitung.
 *
 * Er steht abgesetzt, weil er einen eigenen Zweck hat: Er beantwortet
 * die Frage der Überschrift in 40 bis 60 Wörtern, vollständig und ohne
 * den Rest der Seite. Das ist die Form, die Suchmaschinen als Auszug
 * nehmen und aus der KI-Assistenten zitieren — und, ganz unabhängig
 * davon, die Form, die jemand liest, der wirklich nur die Antwort will.
 */
.kt-answer {
  border-left: 3px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 5%, transparent);
  padding: 1rem 1.25rem;
  margin: 1.5rem 0 0;
  max-width: 46rem;
  font-size: 1.02rem;
  color: var(--ink);
  line-height: 1.65;
}

/* Fließtextblöcke der Themenseiten. */
.kt-prose {
  max-width: 46rem;
  color: var(--ink-2);
}
.kt-prose p {
  margin: 0 0 1.15rem;
  line-height: 1.75;
}
.kt-prose p:last-child {
  margin-bottom: 0;
}
.kt-prose strong {
  color: var(--ink);
}
.kt-plainlist {
  list-style: none;
  padding: 0;
  margin: 0 0 1.15rem;
  display: grid;
  gap: 0.9rem;
}
.kt-plainlist li {
  padding-left: 1.1rem;
  border-left: 2px solid var(--line-strong);
  line-height: 1.7;
}

/*
 * Nummerierte Schritte. Die Ziffern stehen in einem Tuschequadrat statt
 * im Standard-Listenmarker — dieselbe Form wie die Panel-Nummern auf der
 * Startseite, damit eine Anleitung nicht wie ein Fremdkörper wirkt.
 */
.kt-steps {
  list-style: none;
  counter-reset: kt-step;
  padding: 0;
  margin: 0;
  max-width: 48rem;
  display: grid;
  gap: 2rem;
}
.kt-steps > li {
  counter-increment: kt-step;
  position: relative;
  padding-left: 3.5rem;
}
.kt-steps > li::before {
  content: counter(kt-step);
  position: absolute;
  left: 0;
  top: 0;
  width: 2.25rem;
  height: 2.25rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--ink);
  color: var(--paper);
  font-weight: 700;
  border-radius: var(--radius-panel);
}
.kt-steps h3 {
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--ink);
  margin: 0.25rem 0 0.5rem;
}
.kt-steps p {
  margin: 0;
  color: var(--ink-2);
  line-height: 1.7;
}

/*
 * Radikal → Kanji → Wort als drei Panels mit Pfeilen dazwischen.
 * Auf dem Handy wandern die Pfeile in die Senkrechte — ein Pfeil, der
 * nach rechts zeigt, während der nächste Schritt unten steht, ist
 * schlimmer als kein Pfeil.
 */
.kt-chain {
  display: flex;
  align-items: stretch;
  gap: 1rem;
  flex-wrap: wrap;
}
.kt-chain-step {
  flex: 1 1 15rem;
  background: var(--paper);
  border: 2px solid var(--ink);
  border-radius: var(--radius-panel);
  box-shadow: var(--shadow-hard);
  padding: 1.5rem 1.35rem;
}
.kt-chain-glyph {
  display: block;
  font-family: var(--font-jp);
  font-size: clamp(2.4rem, 5vw, 3.2rem);
  line-height: 1;
  color: var(--accent);
  margin-bottom: 0.85rem;
}
.kt-chain-step h3 {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 0.6rem;
}
.kt-chain-step p {
  margin: 0;
  color: var(--ink-2);
  line-height: 1.65;
  font-size: 0.95rem;
}
.kt-chain-arrow {
  align-self: center;
  color: var(--accent);
  font-size: 1.5rem;
  flex: 0 0 auto;
}
@media (max-width: 991.98px) {
  .kt-chain {
    flex-direction: column;
  }
  .kt-chain-arrow {
    align-self: flex-start;
    margin-left: 1.35rem;
    transform: rotate(90deg);
  }
}

/* Eine Tabelle ohne Gegenüberstellung — dieselbe Hülle, aber ohne die
   Zinnoberrot-Spalte, die bei einem Vergleich Partei ergreift. */
.kt-compare-simple thead th {
  background: var(--ink);
  color: var(--paper);
}
.kt-compare-simple tbody th {
  white-space: nowrap;
}

/* Die aktuelle Seite in der Themen-Navigation: markiert, nicht verlinkt.
   Ein Link auf die Seite, auf der man steht, ist eine Sackgasse. */
.kt-nav-current {
  position: relative;
  padding-block: 0.35rem;
  color: var(--ink);
  font-weight: 600;
  font-size: 0.95rem;
}
.kt-nav-current::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--accent);
}

.kt-cta-lead {
  max-width: 40rem;
  margin: 0 auto 1.75rem;
  color: color-mix(in srgb, var(--paper) 78%, var(--ink));
  line-height: 1.7;
}

/* Querverweise in der Fußzeile — auf jeder Seite alle anderen Themen.
   Das ist die Verdrahtung, die aus fünf Einzelseiten ein Themencluster
   macht; ohne sie hängt jede an einem einzigen Link von der Startseite. */
.kt-footer-topics {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  padding-bottom: 1.25rem;
  margin-bottom: 1.25rem;
  border-bottom: 1px solid var(--line);
}
.kt-footer-topics a {
  color: var(--ink-2);
  font-weight: 500;
}
.kt-footer-topics a:hover {
  color: var(--accent);
}

/* Themenkacheln auf der Startseite. */
.kt-topic-card {
  display: block;
  height: 100%;
  background: var(--paper);
  border: 1.5px solid var(--line-strong);
  border-radius: var(--radius-panel);
  padding: 1.4rem 1.35rem;
  color: var(--ink-2);
  text-decoration: none;
  transition:
    transform 0.18s var(--ease-out),
    border-color 0.18s ease,
    box-shadow 0.18s var(--ease-out);
}
.kt-topic-card h3 {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 0.5rem;
}
.kt-topic-card p {
  margin: 0;
  font-size: 0.92rem;
  line-height: 1.6;
}
.kt-topic-card:hover {
  text-decoration: none;
  color: var(--ink-2);
}
@media (hover: hover) and (pointer: fine) {
  .kt-topic-card:hover {
    transform: translateY(-3px);
    border-color: var(--accent);
    box-shadow: var(--shadow-hard);
  }
}
.kt-topic-card::after {
  content: ' →';
  color: var(--accent);
  font-weight: 700;
}

/* --------------------------------------------------------------------
   Erklärgrafiken der Themenseiten

   Alle vier sind reines CSS beziehungsweise Inline-SVG: kein Bild, kein
   Request, scharf in jeder Auflösung und in beiden Themes. Und alle vier
   erklären etwas, das im Fließtext daneben nur behauptet würde — genau
   das ist die Bedingung, unter der eine Grafik hier stehen darf.
   -------------------------------------------------------------------- */

/*
 * 1) Furigana zum Anschauen.
 *
 * Die ganze Manga-Seite hängt an einem Satz: „Über dem Kanji steht die
 * Lesung." Wer noch nie welche gesehen hat, weiss danach genauso wenig.
 * Zwei Sprechblasen mit demselben Satz — einmal mit, einmal ohne —
 * erledigen das in einer Sekunde.
 *
 * `<ruby>` ist dafür das richtige Element und kein Trick: Browser setzen
 * die Lesung von sich aus über das Zeichen, Screenreader lesen sie mit,
 * und Suchmaschinen sehen den Satz trotzdem als zusammenhängenden Text.
 */
.kt-ruby-demo {
  display: grid;
  gap: 1.5rem;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  max-width: 46rem;
}
.kt-ruby-card {
  background: var(--paper);
  border: 2px solid var(--ink);
  border-radius: var(--radius-panel);
  box-shadow: var(--shadow-hard);
  padding: 1.5rem 1.35rem 1.25rem;
}
.kt-ruby-card h3 {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 1rem;
}
.kt-ruby-line {
  font-family: var(--font-jp);
  font-size: 1.5rem;
  line-height: 2.4;
  color: var(--ink);
  margin: 0;
}
.kt-ruby-line rt {
  font-size: 0.42em;
  color: var(--accent);
  font-weight: 600;
  /* Etwas Luft zwischen Lesung und Zeichen — ohne sitzt die Furigana
     auf dem Kanji und beide werden unleserlich. */
  transform: translateY(0.35em);
}
.kt-ruby-de {
  margin: 1rem 0 0;
  padding-top: 0.85rem;
  border-top: 1px dashed var(--line-strong);
  font-size: 0.88rem;
  color: var(--muted);
}

/*
 * 2) Die Bauteil-Formel: Kanji = Bedeutungsteil + Lautteil.
 *
 * Der Absatz daneben sagt „寺 wird ji gelesen, und 時 auch". Das Zeichen
 * zweimal nebeneinander zu sehen, einmal im Ganzen und einmal einzeln
 * hervorgehoben, ist der Moment, in dem es klickt.
 */
.kt-formula {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 1rem 1.25rem;
  background: var(--paper);
  border: 2px solid var(--ink);
  border-radius: var(--radius-panel);
  box-shadow: var(--shadow-hard);
  padding: 1.5rem 1.5rem 1.35rem;
  max-width: 46rem;
}
.kt-formula-part {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  min-width: 5.5rem;
}
.kt-formula-glyph {
  font-family: var(--font-jp);
  font-size: clamp(2.4rem, 5vw, 3.4rem);
  line-height: 1;
  color: var(--ink);
}
.kt-formula-part small {
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  color: var(--muted);
  text-align: center;
  line-height: 1.4;
}
/* Der Lautteil trägt das Zinnoberrot — in beiden Zeichen dieselbe Farbe,
   damit das Auge die Wiederholung von selbst findet. */
.kt-formula-part.is-sound .kt-formula-glyph,
.kt-formula-sound {
  color: var(--accent);
}
.kt-formula-part.is-sound small {
  color: var(--accent);
}
.kt-formula-op {
  font-size: 1.5rem;
  color: var(--muted);
  flex: 0 0 auto;
  align-self: center;
}

/*
 * 3) Die Vergessenskurve.
 *
 * Die einzige Grafik der Seite, die eine Behauptung belegt statt sie zu
 * illustrieren: Man sieht, dass jede Wiederholung die Kurve zurück nach
 * oben setzt UND dass der nächste Abfall flacher verläuft — deshalb die
 * wachsenden Abstände. In Worten braucht das drei Absätze.
 *
 * Der Strich zeichnet sich beim Einscrollen. `stroke-dashoffset` ist eine
 * der wenigen Eigenschaften ausserhalb von transform/opacity, die
 * Browser auf der GPU animieren — und die Bewegung ist zweckgebunden:
 * Sie folgt der Leserichtung der Zeit.
 */
.kt-curve {
  background: var(--paper);
  border: 2px solid var(--ink);
  border-radius: var(--radius-panel);
  box-shadow: var(--shadow-hard);
  padding: 1.5rem 1.35rem 1.15rem;
  max-width: 46rem;
}
.kt-curve svg {
  display: block;
  width: 100%;
  height: auto;
}
.kt-curve-axis {
  stroke: var(--line-strong);
  stroke-width: 1.5;
}
.kt-curve-threshold {
  stroke: var(--line-strong);
  stroke-width: 1.5;
  stroke-dasharray: 5 5;
}
.kt-curve-label {
  fill: var(--muted);
  font-size: 11px;
  font-family: system-ui, sans-serif;
  letter-spacing: 0.06em;
}
.kt-curve-decay {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2.5;
  stroke-linecap: round;
}
.kt-curve-jump {
  stroke: var(--ink);
  stroke-width: 1.5;
  stroke-dasharray: 3 3;
  opacity: 0.55;
}
.kt-curve-dot {
  fill: var(--accent);
  stroke: var(--paper);
  stroke-width: 2.5;
}
/*
 * `pathLength="1"` im Markup normiert jede Kurve auf die Laenge 1 —
 * damit braucht das CSS die echte Streckenlaenge nicht zu kennen und
 * niemand muss sie nachrechnen, wenn sich ein Kontrollpunkt aendert.
 */
.js-reveal .kt-curve-decay {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}
.js-reveal [data-reveal].is-in .kt-curve-decay {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 0.55s var(--ease-out);
}
/* Die vier Abschnitte zeichnen sich nacheinander — sie stellen ja auch
   eine Abfolge in der Zeit dar, keinen gleichzeitigen Zustand. */
.js-reveal [data-reveal].is-in .kt-curve-decay:nth-of-type(1) {
  transition-delay: 0.15s;
}
.js-reveal [data-reveal].is-in .kt-curve-decay:nth-of-type(2) {
  transition-delay: 0.6s;
}
.js-reveal [data-reveal].is-in .kt-curve-decay:nth-of-type(3) {
  transition-delay: 1.05s;
}
.js-reveal [data-reveal].is-in .kt-curve-decay:nth-of-type(4) {
  transition-delay: 1.5s;
}
.js-reveal .kt-curve-jump,
.js-reveal .kt-curve-dot {
  opacity: 0;
  transition: opacity 0.3s ease;
}
.js-reveal [data-reveal].is-in .kt-curve-jump {
  opacity: 0.55;
  transition-delay: 0.55s;
}
.js-reveal [data-reveal].is-in .kt-curve-dot {
  opacity: 1;
  transition-delay: 0.5s;
}
.kt-curve-caption {
  margin: 1rem 0 0;
  font-size: 0.85rem;
  color: var(--muted);
  line-height: 1.6;
}

/*
 * 4) Die JLPT-Leiter.
 *
 * Die Tabelle darüber nennt die Zahlen, aber „100 gegen 2.000" liest
 * sich wie ein Faktor zwei, solange es Ziffern sind. Als Balken sieht
 * man den Faktor zwanzig.
 *
 * Wächst per `scaleX` statt per `width`: Breite löst Layout aus, eine
 * Transformation nicht.
 */
.kt-ladder {
  display: grid;
  gap: 0.9rem;
  max-width: 46rem;
}
.kt-ladder-row {
  display: grid;
  grid-template-columns: 2.5rem 1fr auto;
  align-items: center;
  gap: 0.9rem;
}
.kt-ladder-level {
  font-weight: 700;
  color: var(--ink);
  font-size: 0.95rem;
}
.kt-ladder-track {
  height: 1.5rem;
  background: color-mix(in srgb, var(--ink) 7%, transparent);
  border-radius: 2px;
  overflow: hidden;
}
.kt-ladder-bar {
  display: block;
  height: 100%;
  background: var(--accent);
  transform-origin: left center;
  transform: scaleX(var(--share));
}
.js-reveal .kt-ladder-bar {
  transform: scaleX(0);
}
.js-reveal [data-reveal].is-in .kt-ladder-bar {
  transform: scaleX(var(--share));
  transition: transform 0.7s var(--ease-out);
  transition-delay: calc(var(--bar-i, 0) * 90ms);
}
.kt-ladder-count {
  font-size: 0.85rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.kt-ladder-caption {
  margin: 1.25rem 0 0;
  font-size: 0.85rem;
  color: var(--muted);
  max-width: 44rem;
}

@media (prefers-reduced-motion: reduce) {
  .js-reveal .kt-curve-decay {
    stroke-dasharray: none;
    stroke-dashoffset: 0;
  }
  .js-reveal .kt-curve-jump {
    opacity: 0.55;
  }
  .js-reveal .kt-curve-dot {
    opacity: 1;
  }
  .js-reveal .kt-ladder-bar {
    transform: scaleX(var(--share));
  }
}

/* --------------------------------------------------------------------
   Einblenden beim Scrollen

   Zweck, nicht Zierrat: Die Seite ist ein Stapel Manga-Panels, und ein
   Panel, das beim Blaettern erscheint, ist genau das Bild. Drei Regeln
   halten es davon ab, zur ueblichen Fade-up-Tapete zu werden:

   - Der HERO ist ausgenommen. Was beim Laden schon da ist, animiert
     nicht: Das kostet den LCP und laesst die Seite langsamer wirken,
     als sie ist.
   - EINMAL, nicht bei jedem Vorbeiscrollen. Ein Abschnitt, der beim
     Zurueckscrollen erneut aufblendet, wirkt kaputt.
   - Kurz und flach: 12 px Weg, 480 ms. Was weiter fliegt, wartet man ab,
     statt es zu lesen.

   Die Klasse `js-reveal` setzt das Skript am Seitenende. Ohne JavaScript
   greift keine einzige Regel hier — dann steht alles einfach da.
   -------------------------------------------------------------------- */
.js-reveal [data-reveal] {
  opacity: 0;
  transform: translateY(12px);
  transition:
    opacity 0.48s var(--ease-out),
    transform 0.48s var(--ease-out);
  transition-delay: calc(var(--reveal-i, 0) * 55ms);
  will-change: opacity, transform;
}
.js-reveal [data-reveal].is-in {
  opacity: 1;
  transform: none;
  will-change: auto;
}
@media (prefers-reduced-motion: reduce) {
  .js-reveal [data-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* --------------------------------------------------------------------
   Kleinere Bildschirme
   -------------------------------------------------------------------- */
@media (max-width: 767.98px) {
  .kt-navbar .kt-nav {
    display: none !important;
  }
  .kt-navbar .kt-btn-ghost {
    display: none;
  }
  .kt-hero {
    padding: 3rem 0 3.5rem;
  }
  .kt-hero::before {
    display: none;
  }
  .kt-section {
    padding: 3.5rem 0;
  }
  .kt-hero-panel {
    margin-top: 2rem;
  }
  .kt-price-featured {
    transform: none;
  }
  .kt-cta {
    padding: 3rem 0;
  }
}

/*
 * Reduced motion heisst weniger Bewegung, nicht gar keine Übergänge.
 * Vorher stand hier `* { transition-duration: 0.001ms }` — das nahm auch
 * die Farbwechsel mit, und die *helfen* beim Verstehen: Ein Link, der
 * hart umspringt, sieht nach einem Fehler aus.
 *
 * Also: Verschiebungen und Schatten-Sprünge fallen weg, Farbe und
 * Deckkraft bleiben weich.
 */
@media (prefers-reduced-motion: reduce) {
  * {
    transition-property:
      color, background-color, border-color, opacity !important;
    animation-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .kt-btn-primary:hover,
  .kt-btn-primary:active,
  .kt-feature-card:hover,
  .kt-store-badge:hover,
  .btn:active {
    transform: none !important;
  }
}
