/* =========================================================
   Klar — Rezepte, Varianten, Zutaten und Behälter
   ----------------------------------------------------------
   Rezeptkarten in beiden Darstellungen, Variantendetail,
   Zutatenliste, Editor und die Behälterauswahl.

   Aus ``klar-patterns.css`` herausgelöst, damit Rezepte und
   Tagebuch nicht dieselbe Datei teilen.

   Die Maße stammen aus den wirksamen Konzeptregeln
   (``referenz/styles.css``, dann ``referenz/klar/klar.css``),
   gemessen mit ``Planung/Klar-Messskripte/stilvergleich.py``.
   Wo diese Datei bewusst abweicht, steht der Grund daneben —
   sonst nirgends.

   Symbolgrößen stehen **nicht** hier, sondern zentral in
   ``klar-icons.css``: eine Glyphe folgt ``font-size``, ein
   ``<svg>`` folgt ``width``. Übriggebliebene ``font-size``-Regeln
   auf ehemaligen ``<i>``-Symbolen sind deshalb entfernt und
   dürfen nicht zurückkommen.
   ========================================================= */

/* ---------------------------------------------------------- Seitenrhythmus
   Die Rezeptstrecke legt ihren Seiteninhalt in eine Hülle
   (``[data-recipe-search-page]``, ``[data-recipe-variant-detail]``,
   ``[data-recipe-editor-page]``), weil Suchskript und Editor einen
   gemeinsamen Anker brauchen. ``.app-container`` verteilt seine
   21 px aber nur zwischen **direkten** Kindern — und das war nach
   dem Einzug der Hülle genau eines. Ergebnis: Überschrift,
   Reiterband, Suchfeld und Abschnitt klebten aneinander.

   ``display: contents`` löst die Hülle als Kasten auf: ihre Kinder
   werden zu Kindern von ``.app-container`` und erben dessen
   Abstand, ohne dass der Wert hier ein zweites Mal steht. Die
   Hülle bleibt im DOM, die Skripte finden sie weiterhin. */

.app-container > [data-recipe-search-page],
.app-container > [data-recipe-variant-detail],
.app-container > [data-recipe-editor-page] {
  display: contents;
}

/* ``.app-container > *`` setzt ``min-width: 0`` — das trifft jetzt
   die aufgelöste Hülle statt ihrer Kinder. Also hier noch einmal,
   eine Ebene tiefer, sonst sprengt ein langer Rezeptname die
   Spalte. */
.app-container > [data-recipe-search-page] > *,
.app-container > [data-recipe-variant-detail] > *,
.app-container > [data-recipe-editor-page] > * {
  min-width: 0;
}

/* ---------------------------------------------------------- hidden
   Hier stand eine Zeile, die ``[hidden]`` für vier Komponenten
   dieser Datei zurückholte: ``[hidden] { display: none }`` gehört
   dem Browser, und jede Autorenregel mit ``display`` schlägt sie —
   wegen der Herkunft, nicht wegen der Spezifität. Der Bildwähler
   stand deshalb als leerer Knopf in der Seite, die Rechenzeile als
   leerer getönter Kasten, und der Endgewichtsblock blieb im
   Portionsmodus stehen.

   ``base.css`` trägt die Regel jetzt **einmal** für alle, mit
   ``!important``. Die vier Zeilen hier sind damit wirkungslos und
   weg. Wer die zentrale Regel je entfernt, holt sich alle vier
   Fehler zurück — ``Planung/Klar-Messskripte/pruef_versteckt.py``
   sagt es dann sofort. */

/* ---------------------------------------------------------- recipe cards
   Recipes *and* variants share the toggle, so they share the
   two presentations too. */

.app-main .recipe-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.app-main .recipe-card {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  text-align: left;
  border: 1px solid var(--line);
  background: var(--surface);
  border-radius: var(--round);
  overflow: hidden;
  padding: 0;
  min-width: 0;
  color: inherit;
  text-decoration: none;
}

.app-main .recipe-cover {
  height: 105px;
  background: var(--tint);
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

/* Die zwei blassen Kreise des Konzepts. Sie sind der Grund, warum
   die Kachel im Entwurf nicht wie eine leere Fläche mit Symbol
   aussieht — 1 px Linie in 13 % Akzent, mehr nicht. */
.app-main .recipe-cover::before,
.app-main .recipe-cover::after {
  content: "";
  position: absolute;
  border: 1px solid color-mix(in srgb, var(--accent) 13%, transparent);
  width: 100px;
  height: 100px;
  border-radius: 50%;
  right: -35px;
  top: -32px;
  pointer-events: none;
}

.app-main .recipe-cover::after {
  right: 30px;
  top: 50px;
  width: 85px;
  height: 85px;
}

.app-main .recipe-cover img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.app-main .recipe-info {
  padding: 14px 13px;
  min-width: 0;
}

.app-main .recipe-info strong {
  display: block;
  font-size: var(--text-base);
  line-height: 1.5;
  overflow-wrap: anywhere;
}

/* 12 px, nicht 11: ``styles.css`` setzt ``.recipe-info small`` erst
   auf 11 px und dann ein zweites Mal auf 12 px — die spätere Regel
   gewinnt. Genau so eine Zeile ist gemeint, wenn es heißt, die
   Textgrößen stimmen nicht. */
.app-main .recipe-info small {
  display: block;
  color: var(--muted);
  font-size: var(--text-sm);
  margin-top: 6px;
  overflow-wrap: anywhere;
}

.app-main .recipe-list {
  display: grid;
  gap: 0;
  border-top: 1px solid var(--line);
}

.app-main .recipe-list .recipe-card {
  flex-direction: row;
  align-items: center;
  border: 0;
  border-bottom: 1px solid var(--line);
  background: transparent;
  border-radius: 0;
  padding: 10px 0;
  gap: 12px;
}

/* Der Pfeil der Listenzeile ist im Konzept ein Pseudo-Element mit
   dem Zeichen ``›``, kein Symbol aus dem Satz. Als Markup wäre er
   ein zweites, leicht anderes Zeichen an derselben Stelle — und
   das Suchskript müsste ihn beim Tippen mitbauen. */
.app-main .recipe-list .recipe-card::after {
  content: "›";
  color: var(--muted);
  font-size: 23px;
  line-height: 1;
  padding: 0 8px;
  flex-shrink: 0;
}

.app-main .recipe-list .recipe-cover {
  width: 52px;
  height: 52px;
  flex-shrink: 0;
  border-radius: 13px;
}

.app-main .recipe-list .recipe-cover::before,
.app-main .recipe-list .recipe-cover::after {
  display: none;
}

.app-main .recipe-list .recipe-info {
  flex: 1;
  padding: 0;
}

/* ---------------------------------------------------------- recipe detail */

.app-main .detail-hero {
  padding: 25px;
  background: var(--hero);
  color: var(--hero-ink);
  border-radius: var(--round);
  display: flex;
  align-items: center;
  gap: 20px;
  min-width: 0;
}

.app-main .detail-hero > div {
  min-width: 0;
}

.app-main .detail-hero h2 {
  font-size: var(--text-2xl);
  overflow-wrap: anywhere;
}

.app-main .detail-hero p {
  font-size: var(--text-sm);
  margin-top: 6px;
  line-height: 1.5;
}

.app-main .ingredient {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 13px 0;
  border-bottom: 1px solid var(--line);
  font-size: var(--text-base);
  min-width: 0;
}

.app-main .ingredient:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}

.app-main .ingredient > span:last-child {
  color: var(--muted);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.app-main .recipe-ingredient {
  align-items: flex-start;
  gap: 12px;
  padding: 14px 0;
}

.app-main .recipe-ingredient > div {
  min-width: 0;
  flex: 1;
}

.app-main .recipe-ingredient strong {
  font-size: var(--text-base);
  overflow-wrap: anywhere;
}

.app-main .recipe-ingredient > span {
  font-size: var(--text-xs);
  white-space: nowrap;
  padding-top: 2px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* A plain vegetable needs no invented brand, and no empty line
   where a brand would have been. */
.app-main .ingredient-brand {
  display: block;
  font-size: var(--text-2xs);
  color: var(--muted);
  margin-top: 4px;
}

.app-main .ingredient-nutrients {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 9px;
  align-items: baseline;
  margin-top: 5px;
  font-size: var(--text-2xs);
  color: var(--muted);
}

.app-main .ingredient-nutrients > .macro-line {
  margin: 0;
  font-size: var(--text-2xs);
  gap: 4px 8px;
}

.app-main .ingredient-nutrients .macro-line i {
  display: none;
}

/* ---------------------------------------------------------- recipe editor */

.app-main .editor-ingredient {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 74px;
  gap: 10px;
  align-items: center;
  min-height: 88px;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
  position: relative;
  overflow: hidden;
  background: var(--surface);
}

/* --- Wischen nach links legt das Entfernen frei -----------------
   Swipe und Long-Press werden im Varianteneditor gemeinsam
   ausgewertet. ``touch-action: pan-y`` lässt vertikales Scrollen
   beim Browser, während horizontale Bewegungen der Zeile folgen.

   Rot ist dieser einen Aktion vorbehalten, und es erscheint erst,
   wenn die Fläche offen ist. Die Breite ist die des Tagebuchs, weil
   es dieselbe Geste ist. */

.app-main .editor-ingredient.is-open {
  background: var(--surface);
}

.app-main .editor-ingredient > *:not([data-ingredient-swipe-action]) {
  transition: transform 0.18s var(--ease);
  transform: translateX(var(--ingredient-swipe-x, 0px));
}

.app-main .editor-ingredient.is-open {
  --ingredient-swipe-x: -82px;
}

.app-main .editor-ingredient.is-swiping > *:not([data-ingredient-swipe-action]) {
  transition: none;
}

.app-main .ingredient-delete {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 82px;
  border: 0;
  background: var(--danger);
  color: #fff;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  font-size: var(--text-xs);
  visibility: hidden;
}

.app-main .editor-ingredient.is-open .ingredient-delete {
  visibility: visible;
}

/* Beim Umsortieren hebt sich die Zeile aus der Liste heraus; ein
   ``overflow: hidden`` schnitte sie dabei ab. */
.app-main .editor-ingredient.is-dragging,
.app-main [data-ingredient-list].is-reordering .editor-ingredient {
  overflow: visible;
}

.app-main .editor-ingredient:last-of-type {
  border-bottom: 0;
}

.app-main .editor-ingredient .entry-content {
  padding: 0;
  min-width: 0;
  touch-action: pan-y;
}

.app-main .editor-ingredient strong {
  font-size: 13px;
  display: block;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.app-main .editor-ingredient .ingredient-brand {
  font-size: 11px;
  color: var(--muted);
  display: block;
  margin-top: 4px;
}

.app-main .editor-ingredient .ingredient-nutrients {
  display: flex;
  flex-wrap: nowrap;
  justify-content: flex-start;
  gap: 16px;
  margin-top: 9px;
  font-size: 11px;
  line-height: 1.5;
  white-space: nowrap;
}

.app-main .editor-ingredient .ingredient-nutrients > span {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.app-main .editor-ingredient .ingredient-nutrients b {
  color: var(--ink);
  font-weight: 650;
}

.app-main .editor-ingredient .ingredient-energy svg {
  width: 11px;
  height: 13px;
  color: var(--muted);
}

.app-main .editor-ingredient .ingredient-carbs {
  color: #3f918a;
}

.app-main .editor-ingredient .ingredient-protein {
  color: #ad7a43;
}

.app-main .ingredient-amount {
  display: flex;
  align-items: center;
  gap: 4px;
  width: 74px;
  min-height: 44px;
  margin-top: 24px;
  padding: 0 7px;
  border: 1px solid var(--line);
  border-radius: 11px;
  background: var(--bg);
}

.app-main .ingredient-amount input {
  /* Genau die 16 px der Referenz, als Token: unter 16 px zoomt iOS beim
     Fokus in das Feld hinein, und ``--text-16`` wächst im Gegensatz zu
     einem harten Pixelwert mit der Textvergrößerung mit. */
  font-size: var(--text-16);
  width: 100%;
  min-width: 0;
  border: 0;
  padding: 9px 0;
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  /* Abweichung mit Grund: das Konzept gibt dem Feld keine
     Mindesthöhe und landet bei ~39 px. UIUX.md verlangt
     Touchziele möglichst ab 44 px, und ein Mengenfeld ist das
     meistbenutzte Ziel dieser Seite. */
  min-height: 44px;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.app-main .ingredient-amount > span {
  flex: 0 0 auto;
  font-size: 10px;
  color: var(--muted);
  text-align: left;
}

.app-main .editor-ingredient .ingredient-more {
  position: absolute;
  top: 0;
  right: 0;
  width: 36px;
  height: 32px;
  min-width: 36px;
  min-height: 32px;
  padding: 6px;
  border: 0;
  background: transparent;
  color: var(--muted);
}

/* Sichtbar 32 px wie im Konzept, anfassbar größer wie in UIUX.md:
   „Kleine visuelle Icons dürfen große unsichtbare Touchflächen
   besitzen." Die Fläche wächst über das Raster hinaus, nicht das
   Raster über das Konzept hinaus.

   39 px, nicht 44: nach rechts endet die Zeile am Knopf und wird
   seit der Wischgeste beschnitten (``overflow: hidden`` weiter
   oben), nach links liegen genau die 7 px Rasterlücke frei —
   danach begänne das Mengenfeld, und eine Fläche, die ihm Tipser
   wegnimmt, wäre schlechter als eine kleine. Senkrecht sind es die
   vollen 44 px. */
.app-main .editor-ingredient .ingredient-more::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 0;
  width: 39px;
  height: 44px;
  transform: translateY(-50%);
}

/* --- Zutaten umsortieren (langer Druck, dann schieben) ---------
   Die Gesten selbst stehen in ``recipe-variant-editor.js``. Sie
   waren nach dem Umbau ohne Wirkung: das Skript setzt
   ``--ingredient-drag-y`` auf der gezogenen Zeile, und keine Regel
   las die Variable mehr. Diese vier Regeln sind, was davon
   sichtbar ist — mehr braucht es nicht, weil die Nachbarzeilen
   ihre Verschiebung direkt als ``style.transform`` bekommen. */

.app-main .editor-ingredient {
  transform: translateY(var(--ingredient-drag-y, 0px));
}

.app-main [data-ingredient-list].is-reordering {
  user-select: none;
}

.app-main .editor-ingredient.is-dragging {
  position: relative;
  z-index: 8;
  border-radius: 12px;
  background: var(--surface);
  box-shadow: var(--shadow-md);
  cursor: grabbing;
}

/* Während des Ziehens darf die Seite nicht mitscrollen und der
   Text nicht markiert werden — sonst zieht man beim zweiten Versuch
   eine Auswahl statt einer Zeile. */
html.is-ingredient-reordering-active,
html.is-ingredient-reordering-active body {
  user-select: none;
  -webkit-user-select: none;
  overscroll-behavior: contain;
}

/* Der Abstand des Konzepts zwischen Zutatenliste und den beiden
   Knöpfen darunter (dort als ``style="margin-top:14px"``). */
.app-main [data-ingredient-list] + .hint {
  margin-top: 14px;
}

.app-main .panel > .action-pair {
  margin-top: 14px;
}

.app-main .tare-result {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  font-size: var(--text-sm);
  background: var(--tint);
  color: var(--accent);
  padding: 13px;
  border-radius: 12px;
  margin-top: 9px;
  font-variant-numeric: tabular-nums;
  flex-wrap: wrap;
}

/* ---------------------------------------------------------- containers */

.app-main .container-row {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 16px 0;
  width: 100%;
  border: 0;
  border-bottom: 1px solid var(--line);
  background: transparent;
  text-align: left;
  color: inherit;
  text-decoration: none;
  min-height: 60px;
}

.app-main .container-row:last-child {
  border-bottom: 0;
}

.app-main .container-row > div {
  flex: 1;
  min-width: 0;
}

.app-main .container-row strong {
  font-size: var(--text-base);
  display: block;
  overflow-wrap: anywhere;
}

.app-main .container-row small {
  font-size: var(--text-xs);
  display: block;
  color: var(--muted);
  margin-top: 6px;
}

.app-main .container-photo {
  width: 66px;
  height: 64px;
  object-fit: contain;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 13px;
  flex-shrink: 0;
}

/* Kein Bild: dieselbe Fläche, ein Symbol darin statt eines Fotos.
   Der Platz bleibt gleich, damit die Liste nicht springt. */
.app-main span.container-photo {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--accent);
}

.app-main .container-hero {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--round);
  padding: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 200px;
}

.app-main .container-hero img {
  width: 100%;
  max-height: 210px;
  object-fit: contain;
}


/* The container is chosen by its picture. */
.app-main .container-select {
  display: flex;
  align-items: center;
  width: 100%;
  text-align: left;
  padding: 10px;
  gap: 12px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--surface);
  font-size: var(--text-base);
  color: inherit;
  text-decoration: none;
  min-height: 70px;
}

.app-main .container-select img {
  width: 50px;
  height: 50px;
  object-fit: contain;
  border-radius: 9px;
  flex-shrink: 0;
}

/* Der Platzhalter für „kein Bild" hat dasselbe Maß wie das Bild,
   damit Name und Leergewicht nicht je nach Behälter woanders
   beginnen. */
.app-main .container-select .container-photo {
  flex: 0 0 50px;
  width: 50px;
  height: 50px;
  border-radius: 9px;
  border: 0;
}

.app-main .container-select > span {
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
}

.app-main .container-select > svg {
  flex: 0 0 17px;
}

.app-main .container-none.is-selected {
  border-color: var(--accent);
  background: var(--tint);
  color: var(--accent);
}

.app-main .container-select small {
  display: block;
  font-size: var(--text-xs);
  color: var(--muted);
  margin-top: 5px;
}

/* ``klar-icons.css`` schiebt **jedes** ``svg`` in einer
   ``.container-select`` mit ``margin-left:auto`` ans Ende — das ist
   für den nachgestellten Pfeil richtig und für ein Ersatzbild
   falsch. Das Ersatzbild steht deshalb hier wieder an seinem
   Platz. */
.app-main .container-select .container-photo svg {
  margin-left: 0;
  width: 22px;
  height: 22px;
}

/* Die Vorschau des Editors füllt denselben Rahmen wie das
   Ersatzbild, damit die Zeile beim Wechsel des Behälters nicht
   springt. */
.app-main .container-select .container-photo img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  border-radius: inherit;
}

/* Der Haken zeigt die geltende Wahl. Das Konzept kennt ihn nicht,
   weil sein Wähler keinen Zustand hat; hier ist einer gespeichert,
   und ein Wähler, der ihn verschweigt, lässt zweimal wählen. */
.app-main .container-select__check {
  visibility: hidden;
  color: var(--accent);
}

.app-main .container-select.is-selected {
  border-color: var(--accent);
}

.app-main .container-select.is-selected .container-select__check {
  visibility: visible;
}

/* ``.image-options`` ist im Konzept die Reihe der Beispielbilder.
   Produktiv steht dort die Vorschau des **echten** Uploads —
   dieselbe Form, echte Daten (UMFANG.md: keine Beispielbild-Demo
   als Uploadersatz). */
.app-main .image-options {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.app-main .image-options button {
  border: 2px solid transparent;
  border-radius: 12px;
  background: #fff;
  width: 70px;
  height: 66px;
  padding: 5px;
}

.app-main .image-options button.is-selected {
  border-color: var(--accent);
}

.app-main .image-options img {
  height: 100%;
  width: 100%;
  object-fit: contain;
}

/* ---------------------------------------------------------- narrow phones */

@media (max-width: 350px) {
  .app-main .detail-hero {
    padding: 18px;
    gap: 14px;
  }
  .app-main .editor-ingredient {
    grid-template-columns: minmax(0, 1fr) 54px 32px;
  }
}
