/* =========================================================================
   Lorveé Kitchen — Website
   Konzept: "Die Seite IST ein Rezept."
   Dark first — dieselbe Welt wie die App: Salbeigrün auf fast schwarzem
   Grund, Gold als Ablauf-Zustand. Die Farbwerte sind NICHT neu erfunden,
   sondern die der App (siehe CLAUDE.md und privacy.html).
   Das Essen ist das einzig Helle auf der Seite — genau wie in der App.
   ========================================================================= */

/* --- Fraunces, selbst gehostet: keine Fremdserver, kein Cookie-Banner ---- */
@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url("fonts/fraunces-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url("fonts/fraunces-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --- Ersatzschriften auf Fraunces-Maß gebracht ---------------------------
   Die Überschriften stehen bis zum Eintreffen von Fraunces in der System-
   Serifenschrift — und die baut breiter: dieselbe Zeile brauchte am Rechner
   drei statt zwei Zeilen, und beim Wechsel sprang die halbe Seite um eine
   Überschriftenhöhe nach oben (CLS 0,27). size-adjust staucht die Ersatz-
   schrift auf die gemessene Breite von Fraunces, dann bricht sie an
   denselben Stellen um und der Wechsel bleibt unsichtbar.
   Zwei Blöcke, weil die Maße je Ersatzschrift verschieden sind: Apple-Geräte
   nehmen New York, Windows Georgia. Wo keine von beiden liegt, greift wie
   bisher die unangepasste Systemschrift. */
@font-face {
  font-family: "Fraunces Ersatz";
  src: local("New York");
  size-adjust: 92.3%;
}
@font-face {
  font-family: "Fraunces Ersatz 2";
  src: local("Georgia");
  size-adjust: 76.4%;
}

:root {
  /* --- Grundflächen. Drei Ebenen, damit Tiefe ohne Schatten entsteht. -- */
  --bg: #101210;
  --bg-raised: #161916;
  --bg-card: #1b1f1b;
  --bg-lift: #21261f;

  /* --- Schrift auf dunklem Grund --------------------------------------- */
  --fg: oklch(0.94 0.01 155);
  --fg-dim: oklch(0.94 0.01 155 / 0.66);
  /* 0.42 sah ruhiger aus, lag aber gemessen bei 3,55–3,59 : 1 auf allen vier
     Grundflächen — unter den 4,5 : 1, die WCAG für Fließtext fordert. Und
     --fg-faint trägt keine Dekoration, sondern Inhalt: Quellenangabe,
     Zutaten-Erklärungen, Rezept-Metazeile, Fußzeile. Der kleinste Wert, der
     auf der hellsten Fläche (--bg-lift) noch trägt, ist 0.52; 0.55 hält
     Abstand zur Grenze und ergibt 4,90 (bg-lift) bis 5,36 (bg). Die
     Abstufung bleibt: 14,9 (fg) › 6,8 (fg-dim) › 5,1 (fg-faint). */
  --fg-faint: oklch(0.94 0.01 155 / 0.55);

  /* --- Marke. Zwei Werte, weil Salbei bei L .45 auf Dunkel als TEXT zu
         kontrastarm wäre: --brand füllt, --brand-soft schreibt. --------- */
  --brand: oklch(0.45 0.085 158);
  --brand-soft: oklch(0.68 0.075 158);
  --brand-lift: oklch(0.78 0.07 158);
  --brand-mist: oklch(0.9 0.035 156);
  --brand-veil: oklch(0.45 0.085 158 / 0.16);

  /* --- Zustandsfarbe „läuft ab". Das Gold der App, nicht neu erfunden. - */
  --gold: #f5c542;
  --gold-bright: #ffdc6b;
  --gold-veil: oklch(0.82 0.15 88 / 0.14);

  --border: oklch(0.94 0.01 155 / 0.1);
  --border-strong: oklch(0.94 0.01 155 / 0.18);

  /* --- Schatten auf Dunkel: tiefer, weicher, nie als einziges Mittel --- */
  --shadow-near: 0 1px 2px oklch(0 0 0 / 0.4);
  --shadow-mid: 0 14px 32px -16px oklch(0 0 0 / 0.7);
  --shadow-far: 0 36px 74px -32px oklch(0 0 0 / 0.85);

  /* --- Schrift ------------------------------------------------------ */
  --font-display:
    "Fraunces", "Fraunces Ersatz", "Fraunces Ersatz 2", ui-serif, "New York",
    Georgia, serif;
  --font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI",
    system-ui, sans-serif;
  --font-mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace;

  /* Editoriale Skala ×1.333 */
  --t-micro: 0.6875rem;
  --t-mono: 0.75rem;
  --t-small: 0.875rem;
  --t-body: clamp(1.0625rem, 0.99rem + 0.28vw, 1.1875rem);
  --t-lead: clamp(1.25rem, 1.06rem + 0.85vw, 1.6rem);
  --t-h3: clamp(1.5rem, 1.2rem + 1.3vw, 2.1rem);
  --t-h2: clamp(2.1rem, 1.5rem + 2.7vw, 3.9rem);
  --t-display: clamp(2.9rem, 1.1rem + 8.1vw, 8.4rem);
  --t-numeral: clamp(3.2rem, 1.4rem + 8vw, 9rem);

  /* --- Rhythmus. Bewusst ungleich — kein uniformes Padding ---------- */
  --gap-hair: 0.375rem;
  --gap-tight: 0.75rem;
  --gap: 1.25rem;
  --gap-wide: 2.25rem;
  /* Deutlich enger als zuvor (5–11 rem): Die Abschnitte standen so weit
     auseinander, dass zwischen zwei Aussagen jeweils ein halber Bildschirm
     Leere lag. Der Rhythmus bleibt ungleich, nur die Grundeinheit ist
     kleiner. */
  --section-y: clamp(3.5rem, 2.25rem + 5vw, 7rem);
  --section-y-tight: clamp(2.5rem, 1.75rem + 3vw, 4rem);
  --shell: min(100% - 2.5rem, 74rem);
  --shell-narrow: min(100% - 2.5rem, 42rem);

  /* Radien deutlich größer als zuvor (18/26 war zu zaghaft, ds-geschmacks-
     profil #5 fordert weiche, großzügige Rundungen). */
  --radius-sm: 14px;
  --radius: 22px;
  --radius-lg: 34px;
  --radius-xl: 48px;
  --radius-pill: 999px;

  /* Der Schüsselrand — ein breiter, flacher Bogen. Er kommt auf der
     ganzen Seite GENAU EINMAL vor (Zutaten-Abschnitt). Alle anderen
     gebogenen Kanten haben eigene Formen: Welle, S-Kurve, einseitige
     Schwünge, schiefe Schalen. Dieselbe Kurve überall wäre wieder ein
     Muster, und genau das will das Design-System nicht (#8). */
  --bowl: 50% 50% 0 0 / clamp(2.5rem, 6vw, 6rem) clamp(2.5rem, 6vw, 6rem) 0 0;

  /* --- Easing. Eigene Kurven (ds-motion), keine ease-in-out-Defaults - */
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-out-back: cubic-bezier(0.34, 1.32, 0.64, 1);
  --ease-in-out: cubic-bezier(0.76, 0, 0.24, 1);

  /* Federn statt geratener Bézier-Kurven. Eine kubische Bézier hat nur zwei
     Kontrollpunkte und kann eine gedämpfte Schwingung deshalb nur andeuten.
     `linear()` nimmt beliebig viele Stützstellen — hier eine abgetastete
     Federgleichung, inklusive Überschwingen und Auspendeln. Kostet null
     Kilobyte Laufzeit, weil es eine reine CSS-Kurve ist.
     Verfügbar seit Safari 17.2, in allen Evergreens.
     --spring:      deutliches Überschwingen, für Zustandswechsel (Chip an)
     --spring-soft: knapp über 1, für Druckpunkt und Hover                  */
  --ease-spring: linear(
    0, 0.006, 0.025, 0.101, 0.539, 0.83, 0.946, 1.017, 1.041, 1.034, 1.007,
    0.999, 0.998, 1
  );
  --ease-spring-soft: linear(0, 0.28, 0.63, 0.86, 0.97, 1.01, 1);
  --dur-fast: 180ms;
  --dur: 380ms;
  --dur-slow: 640ms;
}

/* Registriert, damit der Trefferring seinen Füllstand ANIMIEREN kann:
   Ein conic-gradient über eine gewöhnliche Custom Property springt, weil
   der Browser sie nur als Zeichenkette kennt. Mit Typangabe wird sie
   interpolierbar. */
@property --ratio {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}

/* =========================== Reset / Grund =============================== */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  background: var(--bg);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-sans);
  font-size: var(--t-body);
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* NICHT overflow-x: hidden — das setzt implizit overflow-y: auto, macht
     den Body zum Scroll-Container und hebelt damit jedes position: sticky
     aus (die Bildsequenz blieb dadurch nicht stehen). `clip` schneidet
     genauso ab, erzeugt aber keinen Scroll-Container. */
  overflow-x: clip;
}

/* Feines Korn, damit die dunkle Fläche nicht tot wirkt. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 400;
  pointer-events: none;
  opacity: 0.038;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
}

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

::selection {
  background: var(--brand);
  color: var(--fg);
}

/* Fokusring — auf JEDEM interaktiven Element. Auswahlkriterium, nicht Nachtrag. */
:focus-visible {
  outline: 2.5px solid var(--brand-lift);
  outline-offset: 3px;
  border-radius: 4px;
}

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

.skip-link {
  position: absolute;
  left: 50%;
  top: 0.5rem;
  translate: -50% -160%;
  z-index: 500;
  padding: 0.7rem 1.2rem;
  background: var(--brand);
  color: var(--fg);
  border-radius: var(--radius-pill);
  font: 600 var(--t-small) / 1 var(--font-sans);
  text-decoration: none;
  transition: translate var(--dur) var(--ease-out-expo);
}
.skip-link:focus-visible {
  translate: -50% 0;
}

/* ============================ Typografie ================================= */

.shell {
  width: var(--shell);
  margin-inline: auto;
}
.shell-narrow {
  width: var(--shell-narrow);
  margin-inline: auto;
}

.kicker {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0 0 var(--gap);
  font: 500 var(--t-mono) / 1 var(--font-mono);
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--brand-soft);
}
.kicker::before {
  content: "";
  width: 1.6rem;
  height: 1px;
  background: currentColor;
  flex: none;
}

h1,
h2,
h3 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.02;
  letter-spacing: -0.022em;
  margin: 0;
  /* SOFT/WONK sind die Achsen, die Fraunces seinen Charakter geben —
     ohne sie wäre es nur eine weitere Serif. */
  font-variation-settings: "SOFT" 24, "WONK" 1, "opsz" 110;
  text-wrap: balance;
}

h2 {
  font-size: var(--t-h2);
}
h3 {
  font-size: var(--t-h3);
  line-height: 1.14;
}

/* Zwei-Ton-Headline: GENAU ein Wort bricht aus (ds-geschmacksprofil #7). */
.breakout {
  color: var(--brand-soft);
  font-style: italic;
  font-variation-settings: "SOFT" 60, "WONK" 1, "opsz" 130;
}
/* Der Schlusspunkt sitzt in der Maske des letzten Wortes, damit er nicht auf
   eine eigene Zeile rutscht — er gehört aber zum Satz, nicht zum Ausbruch. */
.breakout .pt {
  color: var(--fg);
  font-style: normal;
}

p {
  margin: 0 0 var(--gap);
  max-width: 62ch;
}
.lead {
  font-size: var(--t-lead);
  line-height: 1.44;
  color: var(--fg-dim);
  max-width: 34ch;
}

a {
  color: var(--brand-soft);
  text-underline-offset: 0.22em;
  text-decoration-thickness: 1px;
}
a:hover {
  color: var(--brand-lift);
}

/* ============================= Buttons =================================== */

.btn {
  --btn-bg: var(--brand);
  --btn-fg: oklch(0.98 0.01 155);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 0.95rem 1.7rem;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font: 600 1rem / 1 var(--font-sans);
  letter-spacing: -0.01em;
  text-decoration: none;
  cursor: pointer;
  overflow: hidden;
  isolation: isolate;
  box-shadow: var(--shadow-mid);
  transition:
    transform var(--dur-fast) var(--ease-spring-soft),
    box-shadow var(--dur) var(--ease-out-expo),
    background var(--dur) var(--ease-out-expo);
}
.btn:hover {
  --btn-bg: var(--brand-soft);
  --btn-fg: #0e120e;
  transform: translateY(-2px);
  box-shadow: var(--shadow-far);
}
/* `.is-pressed` kommt von touchstart. Auf iOS gibt es kein verlässliches
   Hover, und `:active` feuert dort erst, wenn der Browser entschieden hat,
   dass die Berührung kein Scrollen wird — das sind spürbare Millisekunden.
   Der Druckpunkt ist auf einer Touch-Seite die einzige Rückmeldung, die
   überhaupt ankommt; er muss sofort da sein. */
.btn:active,
.btn.is-pressed {
  transform: translateY(0) scale(0.965);
}

/* Sheen — Jakobs einzige Handnotiz im Referenzmaterial ("Sheen very cool").
   Deshalb genau EIN Element pro Screen: der primäre CTA. */
.btn--sheen::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    100deg,
    transparent 38%,
    oklch(1 0 0 / 0.3) 50%,
    transparent 62%
  );
  translate: -110% 0;
}
.btn--sheen:hover::after,
.btn--sheen:focus-visible::after {
  animation: sheen 750ms var(--ease-out-expo);
}
@keyframes sheen {
  to {
    translate: 110% 0;
  }
}

.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--fg);
  box-shadow: inset 0 0 0 1.5px var(--border-strong);
}
.btn--ghost:hover {
  --btn-bg: var(--bg-card);
  --btn-fg: var(--fg);
  box-shadow: inset 0 0 0 1.5px var(--brand-soft);
}

/* ============================ Kopfzeile ================================== */

/* Eine schwebende Kapsel statt einer Leiste, die am Rand klebt: Nichts auf
   dieser Seite berührt die Kante (ds-geschmacksprofil #4). Ganz oben ist
   sie unsichtbar und lässt die Schlagzeile atmen; sobald gescrollt wird,
   materialisiert sie sich als Glaskapsel. Übergänge laufen nur über
   Farbe, Schatten und Unschärfe — die Geometrie bleibt stehen, damit
   nichts umbricht. */
.masthead {
  position: fixed;
  inset: clamp(0.5rem, 1.2vw, 0.9rem) 0 auto 0;
  z-index: 300;
  width: min(100% - 1.5rem, 76rem);
  margin-inline: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap);
  padding: 0.42rem 0.42rem 0.42rem 1.15rem;
  border-radius: var(--radius-pill);
  background: transparent;
  border: 1px solid transparent;
  transition:
    border-color var(--dur) var(--ease-out-expo),
    box-shadow var(--dur) var(--ease-out-expo),
    background var(--dur) var(--ease-out-expo);
}
.masthead[data-lifted="true"] {
  background: oklch(0.21 0.008 152 / 0.66);
  /* Blur NUR auf fixed/sticky-Ebenen — nie auf Content-Karten. */
  backdrop-filter: blur(20px) saturate(1.5);
  border-color: var(--border);
  box-shadow:
    0 1px 0 oklch(1 0 0 / 0.05) inset,
    0 18px 40px -24px oklch(0 0 0 / 0.9);
}

/* Die Fortschrittslinie ist thematisch: das Rezept schreitet voran. Sie
   liegt jetzt IN der Kapsel, sonst hinge sie frei im Nichts. */
.masthead__progress {
  position: absolute;
  inset: auto 1.15rem 0.3rem 1.15rem;
  height: 2px;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, var(--brand), var(--brand-lift));
  transform-origin: 0 50%;
  scale: var(--read-progress, 0) 1;
  opacity: 0;
  transition: opacity var(--dur) var(--ease-out-expo);
}
.masthead[data-lifted="true"] .masthead__progress {
  opacity: 1;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font: 600 1.02rem / 1 var(--font-display);
  font-variation-settings: "SOFT" 30, "WONK" 1;
  letter-spacing: -0.02em;
  color: var(--fg);
  text-decoration: none;
}
/* Freigestelltes Markenzeichen, KEIN App-Icon: Das quadratische Icon trägt
   eine salbeifarbene Außenfläche, die bei abgerundeter Darstellung als
   grüner Rand stehen blieb. mark.png ist der Glyph allein, voll transparent
   — deshalb hier auch bewusst kein border-radius. */
.brand img {
  width: 30px;
  height: 30px;
}
.brand em {
  font-style: normal;
  color: var(--brand-soft);
}

.masthead__nav {
  display: flex;
  align-items: center;
  gap: clamp(0.85rem, 2vw, 1.9rem);
}
.masthead__nav a:not(.btn) {
  font: 500 var(--t-small) / 1 var(--font-sans);
  color: var(--fg-dim);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-out-expo);
}
.masthead__nav a:not(.btn):hover {
  color: var(--brand-soft);
}
.masthead__nav a.btn {
  padding: 0.6rem 1.15rem;
  font-size: var(--t-small);
}
@media (max-width: 40rem) {
  .masthead__nav a:not(.btn) {
    display: none;
  }
}

/* ============================= Fußzeile ================================== */

.colophon {
  position: relative;
  background: var(--bg-raised);
  border-top: 1px solid var(--border);
  color: var(--fg);
  /* Bewusst KEINE Kurve: Direkt darüber liegt der Tellerrand des
     Schlussfotos. Zwei gebogene Kanten hintereinander würden sich
     gegenseitig entwerten — die Fußzeile ist die Ruhe danach. */
  border-radius: var(--radius-xl) var(--radius-xl) 0 0;
  padding: var(--section-y-tight) 0 2.5rem;
}
.colophon a {
  color: var(--fg-dim);
  text-decoration: none;
}
.colophon a:hover {
  color: var(--brand-soft);
  text-decoration: underline;
}
.colophon__grid {
  display: grid;
  gap: var(--gap-wide);
  grid-template-columns: 1fr;
  padding-bottom: var(--gap-wide);
  border-bottom: 1px solid var(--border);
}
@media (min-width: 48rem) {
  .colophon__grid {
    grid-template-columns: 1.4fr 1fr 1fr;
  }
}
.colophon h2 {
  font-size: 1.35rem;
  margin-bottom: 0.6rem;
}
.colophon__note {
  color: var(--fg-faint);
  font-size: var(--t-small);
  max-width: 32ch;
  margin: 0;
}
.colophon__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.55rem;
  font-size: var(--t-small);
}
.colophon__label {
  font: 500 var(--t-mono) / 1 var(--font-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg-faint);
  margin-bottom: 0.9rem;
}
.colophon__base {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
  justify-content: space-between;
  padding-top: 1.4rem;
  font-size: var(--t-micro);
  color: var(--fg-faint);
}

/* ====================== Bewegungsreduktion (Pflicht) ===================== */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0ms !important;
    transition-duration: 1ms !important;
    animation-timeline: auto !important;
    scroll-behavior: auto !important;
  }
}
