/*
 * The recipe.
 *
 * Owned by recipe-view.js, so it is loaded by every screen that renders one —
 * Tonight, the recipe screen, and the saved library.
 *
 * The shape is a printed manifest: ingredients as a table you can check down one
 * column, salt/fat/acid/heat as four tiles, and the method as numbered prose.
 * Under the Deck it sat on whatever ground its caller was wearing, and every
 * tile painted that ground so the 1px gaps between them could read as rules.
 * There is one field now, so the tiles are simply a card divided by hairlines.
 */

.recipe { padding-inline: var(--gutter); }

/*
 * The recipe supplies its own gutter, so the shared primitives must not add
 * theirs on top. `.rows`, `.lab` and `.banner` all carry
 * `margin-inline: var(--gutter)` for use directly on a screen; inside here that
 * doubled to 32px and left the ingredient card visibly narrower than the
 * balance grid beside it. `.banner` was the one this list missed: the stale-day
 * notice sat 16px in from every card under it, which is exactly the misalignment
 * the eye is best at catching.
 */
.recipe .rows { margin-inline: 0; }
.recipe .lab { margin-inline: 0; }
.recipe .banner { margin-inline: 0; }

.recipe__title {
  margin-bottom: var(--s2);
  max-width: 22ch;
  font-size: var(--text-xl);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.03em;
  text-wrap: balance;
  overflow-wrap: break-word;
}

/*
 * Time, servings and diners on one line, with the flag chips beside them.
 *
 * The line is rendered whenever the flags are settable, because a chip can
 * appear here later without a remount — so it collapses while it holds nothing
 * rather than leaving its own bottom margin behind as a gap under the title.
 */
.recipe__facts:empty { display: none; }
.recipe__facts {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s2);
  margin-bottom: var(--s4);
  font-size: var(--text-base);
  color: var(--ink-2);
}

/* Why this dish was chosen. Tinted rather than filled, because it is the good
   news — not an alert banner with a warning triangle. Nothing here is wrong. */
.recipe__rescue {
  display: inline-block;
  margin-bottom: var(--s5);
  padding: 5px 10px;
  border-radius: var(--radius-tag);
  background: var(--warn-sunk);
  color: var(--warn);
  font-size: var(--text-sm);
  font-weight: 600;
}

/* ─── The manifest ────────────────────────────────────────────────────────── */

/*
 * A recipe row has three columns to align and a taller line than a Kitchen row,
 * so it takes more vertical padding than the shared default. The 58px ceiling
 * that used to have to be lifted here belongs to `.item` now — the one row with
 * a measured density floor to hold — rather than to every list in the product.
 */
.recipe .rows .row {
  display: flex;
  align-items: baseline;
  gap: var(--s3);
  padding: 10px var(--s4);
}

.recipe .row__body { flex: 1; min-width: 0; }
.recipe .row__title {
  font-size: var(--text-base);
  font-weight: 400;
  letter-spacing: 0;
  white-space: normal;      /* an ingredient may wrap; it has the room */
  text-overflow: clip;
}
.recipe .row__meta { margin-top: 2px; }

.recipe .row__aside {
  font-size: var(--text-sm);
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/*
 * Where it lives — rendered only when this recipe actually knows, so the column
 * is 62px of table or nothing at all, never 62px of blank. See recipe-view.js.
 * Right-aligned so it reads straight down.
 */
.recipe .wh {
  flex-shrink: 0;
  min-width: 62px;
  text-align: right;
  font-size: var(--text-xs);
  color: var(--ink-2);
}

/* Something that needs eating leads the eye, without a bullet. */
.recipe .row.is-expiring .row__title { color: var(--warn); font-weight: 600; }

/* ─── Salt, fat, acid, heat ───────────────────────────────────────────────── */

/* `.grid-cells` in app.css supplies the tiling: white cells with 1px hairline
   gaps, rounded as one card. */
.recipe__balance { margin: 0; }

/*
 * A recipe missing one of the four notes leaves an odd cell count, and the empty
 * slot showed the grid's own hairline ground as a solid grey block where a cell
 * should be. The last one spans instead, which reads as a wide note rather than
 * as a hole.
 */
.recipe__balance-row:last-child:nth-child(odd) { grid-column: 1 / -1; }

.recipe__balance-row dt {
  margin-bottom: 3px;
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.01em;
  color: var(--ink-2);
}
.recipe__balance-row dd {
  margin: 0;
  font-size: var(--text-sm);
  line-height: 1.4;
  color: var(--ink);
  text-wrap: pretty;
}

/* ─── Method ──────────────────────────────────────────────────────────────── */

/*
 * The step number is not decoration on this screen. It is the thing you re-find
 * after looking away at the pan, at arm's length, in a bright kitchen — so it
 * sits at body size in tabular figures rather than shrinking to a footnote.
 * Secondary ink still keeps it behind the instruction itself.
 */
.recipe__steps li::marker {
  font-size: var(--text-base);
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
}
.recipe__steps { padding-left: 1.6em; }

/*
 * Cook mode: the forty minutes, rather than the thirty seconds.
 *
 * A step is a 44px row that ticks. The alternative is holding "I am on step
 * four" in your head while your hands are busy, on the one surface in this
 * product read from a distance with a phone propped against a canister — so the
 * step text takes a reading size rather than the body step, and a done step
 * steps back rather than disappearing.
 */
.recipe__step {
  display: block;
  width: 100%;
  min-height: var(--tap);
  padding: var(--s2) var(--s2) var(--s2) 0;
  text-align: left;
  font-size: var(--text-md);
  font-weight: 400;
  line-height: 1.45;
  color: var(--ink);
  text-wrap: pretty;
}
.recipe__step:hover { color: var(--tint); }

/* Done is a colour and a rule through it, not a disappearance: the step you
   just did is the one you are most likely to want to re-read.
   `--ink-2`, not `--ink-3`: a step number is text, and 3.00:1 is not a text
   ratio — which the contrast guard says out loud. */
.recipe__steps li.is-done::marker { color: var(--ink-2); }
.recipe__steps li.is-done .recipe__step-text {
  color: var(--ink-2);
  text-decoration: line-through;
}

/* ─── The stale-day notice ────────────────────────────────────────────────── */

/*
 * `.banner` is a flex ROW with a gap, which is right when it carries a mark and
 * a sentence. This one carries a sentence and the way out of it, so it stacks —
 * a 44px control sharing a baseline row with three lines of text is neither
 * readable nor reachable.
 */
.recipe__stale {
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s3);
}

/*
 * The tint is the promise that a thing can be acted on (DESIGN.md → Overview),
 * and this is the one control in the block — so it keeps the promise rather
 * than dressing itself in the notice's warn ink. The attention notice already
 * settled this: its own buttons are tinted on their own coloured ground.
 *
 * A white slug rather than a filled tint: the notice is standing information,
 * not the screen's commitment, and that job is already taken by "I cooked this"
 * further down.
 */
.recipe__stale-action {
  background: var(--card);
  color: var(--tint);
  font-weight: 600;
}
.recipe__stale-action:hover:not(:disabled) { background: var(--card); opacity: 0.88; }

/* ─── How it went ─────────────────────────────────────────────────────────── */

/*
 * A note is a sentence, not a row name: it wraps, and it does not want the
 * semibold, tightened, single-line treatment `.row__title` gives a thing in the
 * kitchen. (The ingredient rows above already relax the same class.)
 */
.recipe__history .row__title { white-space: normal; text-overflow: clip; }
.recipe__history .row__meta { font-variant-numeric: tabular-nums; }

/*
 * The score reads from the figure, not from a colour — see ratingChip().
 *
 * The separation between the score and its denominator is weight and ink level,
 * never opacity: `--ink-2` faded to 60% on the recessed chip ground measures
 * about 2:1, which is under even the mark floor, and "/5" is text.
 */
.chip--rating { gap: 0; font-variant-numeric: tabular-nums; }
.chip--rating .chip__figure { font-size: var(--text-sm); font-weight: 600; color: var(--ink); }
.chip--rating.chip--expired .chip__figure { color: inherit; }

/* ─── Actions and flags ───────────────────────────────────────────────────── */

/* The method section above already ends on its own `--s6`; a second one here
   opened a 48px hole between the last step and the commitment. */
.recipe__actions {
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  margin-top: var(--s2);
}
.recipe__actions .btn { min-height: 50px; }

/* Favourite and ban are states you toggle, not actions you fire, so they are
   pills rather than buttons. */
.recipe__flags {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  margin-top: var(--s6);
  padding-top: var(--s4);
  border-top: 1px solid var(--hair);
}
/* The rule above already opens the block; `.lab`'s own s6 on top of it put the
   heading adrift from the pills it names. */
.recipe__flags .lab { margin-top: 0; margin-bottom: 0; }
.recipe__flags .chip--toggle[data-flag='banned'][aria-pressed='true'] {
  background: var(--gone);
  border-color: var(--gone);
  color: var(--reversed-ink);
}
.recipe__flags .chip--toggle:disabled { opacity: 0.5; cursor: wait; }

/* One column below the narrowest phones: two cells at 320px leave about 20
   characters a line, which is not a sentence. */
@media (max-width: 360px) {
  .recipe__balance { grid-template-columns: 1fr; }
}
