/*
 * The capture panel on the recipe page.
 *
 * Written against Bootstrap's CSS variables rather than raw hex so the panel is
 * READY for a light/dark switch. There is no such switch yet -- nothing shipped
 * sets `data-bs-theme` or reads `prefers-color-scheme`, and DESIGN.md's dark
 * palette is still unimplemented -- so this is a promise about the day one
 * lands, not a description of today. Square corners and hairline borders, per
 * DESIGN.md ("instruments do not have rounded corners").
 *
 * Stars are INK (`currentColor` inherited from the body colour), never the flame
 * accent: flame is reserved for the scale stepper, batch controls and aisle
 * indices, and a field of flame stars next to an oxblood Delete makes the two
 * reds read as one family. Their four declarations live in `cooking-stars.css`,
 * linked by every surface that prints a rating -- including pages that carry no
 * panel at all.
 */

/* Shared by both regions -- the capture strip above the food and the REVIEWS
   section below the method. */
.cooking-panel {
  border-radius: 0;
}

/* A 120ms state fade so the eye catches that the region changed. No movement, no
   spinner -- see the button's label swap below.

   ON A CLASS THE SWAP ADDS, never on the region itself. Declared on
   `.cooking-panel` this played on every first paint of the recipe page and of
   `/recipes/made/`: the strip and the REVIEWS section faded up from 0.55 to
   announce a change that had not happened. `cooking-panel.js` adds this class
   after an out-of-band swap and only then, which is the discipline
   `.just-changed` already follows -- the mark reaches a node that just moved. */
.cooking-panel-swapped {
  animation: cooking-panel-fade 120ms cubic-bezier(0.2, 0, 0, 1);
}

/* The strip is a LINE on the page, not a card (D-D1). It keeps the hairline box
   the whole panel used to wear, because at one line tall that box reads as a bar
   rather than a container. */
.cooking-capture-strip {
  border: 1px solid var(--bs-border-color);
  padding: 1rem;
}

/* REVIEWS is a page section, not a widget: a rule across the measure under the
   method, the label, then the cards. A second bordered box down here would make
   the reviews read as a control panel bolted to the end of the recipe. */
.cooking-reviews {
  border-top: 1px solid var(--bs-border-color);
  padding-top: 1rem;
  /* Here rather than on the wrapper column, because the section renders empty on
     a recipe this cook has never made (the out-of-band swap needs a target that
     already exists) and a margin out there would leave a gap where nothing is. */
  margin-top: 1.5rem;
}

@keyframes cooking-panel-fade {
  from {
    opacity: 0.55;
  }
  to {
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .cooking-panel-swapped {
    animation: none;
  }
}

.cooking-heading {
  font-size: 1.125rem;
  margin: 0 0 0.5rem;
}

/* The capture strip. It WRAPS below md -- count and note fall to their own
   lines -- and it never becomes a card: the strip is a line on the page, at
   every width. */
.cooking-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
}

/* `.cooking-count` used to share this rule. It is gone with the sentence it
   styled: the count is the make list's `<summary>` now (D-D3), and it is styled
   with the list it opens. */
.cooking-hint {
  color: var(--bs-secondary-color);
  margin: 0;
  font-size: 0.875rem;
}

.cooking-eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 0.75rem;
  color: var(--bs-secondary-color);
  margin: 0 0 0.25rem;
}

.cooking-last-time,
.cooking-review-card {
  border-top: 1px solid var(--bs-border-color);
  margin-top: 0.75rem;
  padding-top: 0.75rem;
}

.cooking-note {
  border-left: 2px solid var(--bs-border-color);
  padding-left: 0.75rem;
  margin: 0;
  font-style: italic;
}

/* A refused Save. Oxblood, and NOT Bootstrap's danger red, because the Delete
   under it is oxblood: one strip showing two reds for one semantic is how a
   reader learns that colour here means nothing. The longhand value and the
   promise to honour the token the day `tokens.css` lands are the same ones
   `.cooking-review-danger` further down carries. */
.cooking-error {
  color: #8a1c11;
  margin: 0.5rem 0;
}

/* The stale label, and -- on your own card only -- the nudge under it. Same voice
   and same size, because they are two sentences of one thought; the nudge loses
   the top margin so the pair reads as one block rather than two loose lines.

   0.75rem, the smallest step already in this file (`.cooking-eyebrow`), rather
   than the 0.875rem it shipped at: this is a note ABOUT a verdict and it was
   reading louder than the verdict. Both sentences drop together, on purpose --
   shrinking the label alone would print one thought at two sizes on your own
   card, which is the drift this shared rule exists to prevent. */
.cooking-stale,
.cooking-stale-nudge {
  color: var(--bs-warning-text-emphasis, var(--bs-body-color));
  font-size: 0.75rem;
  margin: 0.5rem 0 0;
}

.cooking-stale-nudge {
  margin-top: 0;
}

.cooking-offline-banner {
  border: 1px solid var(--bs-border-color);
  padding: 0.5rem 0.75rem;
  margin-bottom: 0.75rem;
}

/* `.cooking-stars` and `.cooking-star` are NOT here -- they are in
   `cooking-stars.css`, which every surface that prints a rating links and this
   sheet's surfaces link alongside it. The rules below are the picker: a control
   for SETTING a rating, which only a page carrying the panel has. */

.cooking-star-input {
  border: 0;
  padding: 0;
  margin: 0 0 1rem;
}

.cooking-legend {
  float: none;
  width: auto;
  font-size: 1rem;
  font-weight: 600;
  margin-bottom: 0.25rem;
}

.cooking-star-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.75rem;
}

.cooking-star-choice {
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* At least 44px in both directions: this is tapped with one hand, in a kitchen,
   often with the other hand full. */
.cooking-star-choice-label,
.cooking-button {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.cooking-star-choice-label {
  min-width: 44px;
  cursor: pointer;
}

.cooking-button {
  border: 1px solid var(--bs-border-color);
  border-radius: 0;
  background: var(--bs-body-bg);
  color: var(--bs-body-color);
  padding: 0 1rem;
}

.cooking-button-primary {
  border-color: var(--bs-body-color);
}

.cooking-button-quiet {
  border-color: transparent;
  text-decoration: underline;
  padding: 0 0.5rem;
}

/* ── Pointer and keyboard feedback, once, for every control here ─────────────
   Every control in this panel overrides border, background and colour, so each
   one silently opts OUT of the hover and focus treatment the browser and
   Bootstrap would otherwise give it -- the summaries and the dismiss button set
   `cursor: pointer` and nothing else. This block is the whole panel's answer,
   written once rather than per control, so a new control joins the list instead
   of inventing a third look.

   A BACKGROUND TINT, and deliberately nothing else. Recolouring the label would
   fight the two colours that already mean something here (oxblood on the
   destructive pair, ink everywhere else), and moving or shadowing anything is
   what DESIGN.md's "no gradient, no shadow" rules out. The tint reads on the
   44px target rather than on six characters of text, which is the shape of
   these controls.

   `:focus-visible` rather than `:focus`, so a tap does not leave a ring behind
   -- and stated explicitly rather than left to the UA, because these controls
   are a `<button>`, a `<summary>` and an `<input>` and the three default rings
   do not match. INK, per DESIGN.md: the palette has no blue, and links and
   primary buttons are ink. */
.cooking-button:hover,
.cooking-remove:hover,
.cooking-dismiss:hover,
.cooking-review-disclose:hover,
.cooking-makes-summary:hover,
.cooking-star-choice-label:hover {
  background-color: var(--bs-tertiary-bg);
}

/* The star picker takes the ring on its RADIO rather than on its label: the
   label is the tap target, but a `<label>` never receives focus, so a rule on it
   would be inert and would read as coverage this list does not have. */
.cooking-button:focus-visible,
.cooking-remove:focus-visible,
.cooking-dismiss:focus-visible,
.cooking-review-disclose:focus-visible,
.cooking-makes-summary:focus-visible,
.cooking-star-radio:focus-visible,
.cooking-input:focus-visible,
.cooking-history-recipe-title:focus-visible {
  outline: 2px solid var(--bs-body-color);
  outline-offset: 2px;
}

.cooking-field {
  margin-bottom: 1rem;
}

.cooking-label {
  display: block;
  font-weight: 600;
}

.cooking-input {
  border: 1px solid var(--bs-border-color);
  border-radius: 0;
  background: var(--bs-body-bg);
  color: var(--bs-body-color);
  padding: 0.5rem;
  min-height: 44px;
  width: 100%;
  max-width: 24rem;
}

textarea.cooking-input {
  max-width: 100%;
}

.cooking-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  border-top: 1px solid var(--bs-border-color);
  padding-top: 0.75rem;
}

/* The in-flight label swap. htmx puts `.htmx-request` on the form
   (`hx-indicator="this"`), so the button reads "Recording..." / "Removing..."
   while it is disabled -- a disabled button with an unchanged label reads as a
   dead one. Both mutating forms share the rule rather than repeating it. */
.cooking-busy {
  display: none;
}

.cooking-capture-form.htmx-request .cooking-idle,
.cooking-undo-form.htmx-request .cooking-idle,
.cooking-verdict-form.htmx-request .cooking-idle,
.cooking-review-delete-form.htmx-request .cooking-idle {
  display: none;
}

.cooking-capture-form.htmx-request .cooking-busy,
.cooking-undo-form.htmx-request .cooking-busy,
.cooking-verdict-form.htmx-request .cooking-busy,
.cooking-review-delete-form.htmx-request .cooking-busy {
  display: inline;
}

/* Undo, and the disclosure under it. The hint is a block below the control
   rather than beside it: it is a sentence that quotes a review, and a sentence
   that long alongside a 44px button reflows into a column at any phone width. */
.cooking-undo {
  margin-bottom: 0.75rem;
}

.cooking-undo .cooking-hint {
  margin-top: 0.25rem;
}

/* The line that reports what a removal exposed carries `.just-changed`, the
   ONE transient highlight on the site (`recipes/static/recipes.css`) -- the same
   class the batch-size widget's in-place commit uses, so "this just changed" is
   one idiom in one colour with one place for a future `--accent` token to land.
   It used to be a second keyframe here, in flame, beside that widget's
   Bootstrap green: two colours for one meaning, both able to fire on one page.
   Nothing about the flash is declared in this file any more. */

@keyframes cooking-notice-fade {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

.cooking-notice {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin: 0.5rem 0;
}

/* Reduce motion: cross-fade in rather than pulse. The line still has to ARRIVE
   visibly -- it is the only thing on the page that explains why the review
   below it changed -- so the preference removes the flash, not the feedback.
   This is the one place the shared highlight is overridden rather than
   suppressed, and it wins on specificity rather than on file order: the shared
   rule is one class in another stylesheet, this is two. */
@media (prefers-reduced-motion: reduce) {
  .cooking-notice.just-changed {
    animation: cooking-notice-fade 250ms cubic-bezier(0.2, 0, 0, 1);
  }
}

.cooking-dismiss {
  border: 1px solid transparent;
  border-radius: 0;
  background: none;
  color: var(--bs-secondary-color);
  min-width: 44px;
  min-height: 44px;
  flex-shrink: 0;
}

/* The review card's meta line: the cook's date and the version the verdict was
   written against, both quiet. Nothing on this line competes with the body above
   it, which is the thing anyone actually reads. */
.cooking-review-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
  margin: 0.5rem 0 0;
  color: var(--bs-secondary-color);
  font-size: 0.875rem;
}

.cooking-review-version {
  border: 1px solid var(--bs-border-color);
  padding: 0 0.25rem;
}

.cooking-review-body > :last-child {
  margin-bottom: 0;
}

/* ── Text nobody controls the length of ──────────────────────────────────────
   Everything named here is typed by a cook: a review body, a note, the excerpt
   quoted back in the make history, a username. One pasted URL has no break
   opportunity in it, and at 375px an unbreakable word does not overflow its own
   box quietly -- it sets the width of the page and every other row goes with it.
   Break inside the word instead. This is the rule that keeps DR2-D5's "rows
   stack" from being undone by a single line of someone else's prose.

   `anywhere` RATHER THAN `break-word`, and the difference is the whole reason
   this rule works. The two wrap identically; they differ only in whether the
   break opportunity counts toward the element's MIN-CONTENT size, and
   `break-word` says it does not. Every element named here is a grid item (or
   inside one) on a track sized `1fr`, whose automatic minimum size is
   min-content -- so under `break-word` the track was still sized by the longest
   unbroken word and grew to 1426px inside a 375px page, exactly the failure the
   paragraph above describes. Shipped that way and was invisible to every Django
   test, because a stylesheet reader can only prove the rule is PRESENT;
   `cooking/tests/e2e/test_cooking_mobile.py` is what measures it. */
.cooking-review-body,
.cooking-review-byline,
.cooking-make-note,
.cooking-make-quote {
  overflow-wrap: anywhere;
}

/* `pre` and `code` are both on the review allowlist
   (`cooking/templatetags/cooking_review.py`) and `pre` does not wrap at all, so
   no amount of `overflow-wrap` reaches it. The block scrolls inside its own box
   rather than handing its width to the page. */
.cooking-review-body pre {
  overflow-x: auto;
}

/* ── The 44px minimum, for both surfaces at once (DR2-D5) ────────────────────
   `Delete` on your review card and `Remove` on a cook are the two highest-
   consequence controls on this page, and both stay INLINE TEXT LINKS. The
   rejected alternative is worth recording because it is the obvious one: a
   full-width oxblood action row per entry is unmissable, and four stacked turn a
   quiet cooking log into a demolition list. Staying a link is not licence to be
   small, so the pair is padded out to a 44x44 target -- the same
   one-handed-in-a-kitchen minimum the star input keeps.

   `min-width` as well as `min-height`, because 44px tall and 40px across is not
   a 44px target and "Delete" is six characters wide.

   ONE RULE FOR BOTH, and that is the point of this block. This shipped as two
   near-identical declarations -- one written with the make list, one with the
   review card -- and two copies of a tap-target minimum is how one of them
   silently loses it. The element-specific parts stay with their elements: the
   summary's missing triangle just below, the button's resets down at
   `.cooking-remove`. */
.cooking-review-disclose,
.cooking-remove {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  min-width: 44px;
  cursor: pointer;
  text-decoration: underline;
}

/* Edit and Delete are native `<details>` summaries styled as the mockup's two
   links, so they work with scripting off. `list-style: none` plus the WebKit
   pseudo-element removes the disclosure triangle -- these read as controls, not
   as an outline. */
.cooking-review-disclose {
  list-style: none;
}

.cooking-review-disclose::-webkit-details-marker {
  display: none;
}

/* Oxblood, and the only colour on the card. DESIGN.md names this `--danger`
   (#8A1C11) and is deliberate that it is NOT the flame accent: flame marks
   something that changed, oxblood marks something that cannot be changed back,
   and a field of flame stars beside a flame Delete would read as one family.
   There is no `tokens.css` in this repo yet, so the value is written longhand
   here and the variable is honoured the day the token file lands -- the same
   pattern `cooking-notice`'s flash already uses for `--accent`.

   THESE ARE THE FIRST DECLARATIONS A DARK MODE HAS TO REVISIT. Everything else
   in this file resolves through a Bootstrap variable and follows a theme switch
   for free; a literal #8a1c11 does not, and oxblood on a dark ground is the one
   colour here that stops carrying its meaning. */
.cooking-review-danger,
.cooking-button-danger,
.cooking-remove {
  color: #8a1c11;
}

.cooking-button-danger {
  border-color: #8a1c11;
}

.cooking-delete-warning {
  margin: 0 0 0.5rem;
}

/* Below md everything in the verdict form stacks, and Save spans the width. A
   horizontal form does not survive 375px. */
@media (max-width: 767.98px) {
  .cooking-actions {
    flex-direction: column;
    align-items: stretch;
  }

  .cooking-save {
    width: 100%;
  }

  .cooking-button-danger {
    width: 100%;
  }
}

/* One other cook's review. The approved mockup (`reviews-final.png`) reads as
   three columns -- who, what, when -- separated by a hairline rule, with the
   stars tucked under the username so the left column is one identity block
   rather than two rows of furniture. Single column first: below md the three
   parts stack in reading order, which is the order they are written in.

   The narrow layout is the BASE rule and the three columns are what a wide
   screen opts into, deliberately that way round (DR2-D5). A stacked fallback
   bolted on under a `max-width` query is the arrangement that rots -- a fourth
   column added later reaches 375px by default and nobody notices. */
.cooking-other-review {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.25rem 1rem;
  border-top: 1px solid var(--bs-border-color);
  margin-top: 0.75rem;
  padding-top: 0.75rem;
}

@media (min-width: 768px) {
  .cooking-other-review {
    grid-template-columns: minmax(7rem, 1fr) 3fr auto;
    align-items: start;
  }

  .cooking-review-when {
    text-align: right;
  }

  /* The stale label is a footnote on the verdict, so it starts where the verdict
     starts: column 2 is the body column (the three parts are auto-placed in DOM
     order), and naming it drops the label onto the next row flush under the words
     it qualifies. It used to span `1 / -1`, on the argument that it is a
     statement about the whole row -- true, and beside the point. Full-bleed from
     the far left, it read as the row's headline and the four-word review indented
     beside it went unnoticed; the owner reported exactly that. An annotation that
     out-shouts the thing it annotates is the wrong hierarchy however defensible
     its logic.

     Inside the md query and nowhere else. Below md the row is one explicit
     column, where `grid-column: 2` does not align the label with anything -- it
     conjures an implicit second track and pulls the label out of the stack. The
     narrow layout wants no placement at all: auto-flow already puts the label
     last, at the same left edge as everything above it. Scoped to this row for a
     second reason too: the same class on YOUR card is not in a grid. */
  .cooking-other-review > .cooking-stale {
    grid-column: 2;
  }
}

.cooking-review-byline {
  margin: 0;
}

/* `inline-block` for a reason worth writing down: the byline's anchor wraps a
   template include, and `djlint --reformat` puts that include on its own line,
   which leaves a newline immediately inside the `<a>` on both sides of the name.
   Inline, that collapses to a rendered space INSIDE the link and the underline
   runs through it. An inline-block strips leading and trailing whitespace inside
   its own box, so the rule underlines the username and nothing else. */
.cooking-review-byline a {
  display: inline-block;
}

/* The date is context, not content: quiet, and never competing with the words
   next to it. Same size and colour as the meta line on your own card. */
.cooking-review-when {
  margin: 0;
  color: var(--bs-secondary-color);
  font-size: 0.875rem;
}

/* The reveal. A native `<details>` styled as the mockup's plain control -- no
   disclosure triangle, because this reads as a link and not as an outline -- and
   it reuses `.cooking-review-disclose` for the 44px one-handed-in-a-kitchen
   target the rest of the panel keeps. Nothing here is scripted: the rows behind
   it are already in the document. */
.cooking-review-more {
  margin-top: 0.75rem;
}

/* The ceiling, said out loud, and quiet for the same reason `.cooking-makes-note`
   is: it is not content, it is the sentence that keeps a capped list from reading
   as the whole one. Only rendered when the cap actually cut something. */
.cooking-review-footnote {
  margin: 0.5rem 0 0;
  color: var(--bs-secondary-color);
  font-size: 0.875rem;
}

/* ── The make history, behind the made-count (D-D3) ──────────────────────────
   The count is a flex item of `.cooking-strip`, so the summary sits on the same
   line as "I made this" and the rows unfold beneath it -- inset by the button's
   width on wide screens, which is deliberate: the log hangs from the control that
   revealed it. Below md the strip wraps and the list takes the full measure,
   which is where it is actually read.

   `align-self: flex-start` keeps the summary level with the top of the button
   instead of letting an opened list drag the closed line down the page. */
.cooking-makes {
  flex: 1 1 12rem;
  align-self: flex-start;
  min-width: 0;
}

/* The whole line is the tap target -- 44px, one-handed, in a kitchen. Only the
   count carries the underline and the caret, because that is the affordance the
   approved mockup puts on it; "last on ..." is context riding along. */
.cooking-makes-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 0.5rem;
  min-height: 44px;
  cursor: pointer;
  color: var(--bs-secondary-color);
  list-style: none;
}

.cooking-makes-summary::-webkit-details-marker {
  display: none;
}

.cooking-makes-count {
  color: var(--bs-body-color);
  text-decoration: underline;
}

/* The caret, in CSS because it is pure affordance -- a screen reader already
   hears the summary's expanded/collapsed state and does not need a second one.
   It rotates rather than swapping glyphs, so the direction reads as a movement.
   The superseded mockup's defect was a made-count with no affordance at all. */
.cooking-makes-count::after {
  content: "";
  display: inline-block;
  width: 0.4em;
  height: 0.4em;
  margin-left: 0.4em;
  vertical-align: 0.15em;
  border-right: 1px solid currentcolor;
  border-bottom: 1px solid currentcolor;
  transform: rotate(45deg);
  transition: transform 120ms cubic-bezier(0.2, 0, 0, 1);
}

.cooking-makes[open] .cooking-makes-count::after {
  transform: rotate(-135deg);
}

@media (prefers-reduced-motion: reduce) {
  .cooking-makes-count::after {
    transition: none;
  }
}

.cooking-make-rows {
  list-style: none;
  margin: 0.5rem 0 0;
  padding: 0;
}

/* One cook: when it was, what you wrote, and the way to take it back off the
   log. Three columns above md -- the approved mockup's proportions -- and a
   single stacked column below it, which is DR2-D5's rule for these rows and not
   a fallback. `auto` on the last column is what keeps Remove an inline link
   rather than a full-width action bar. */
.cooking-make-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.25rem 1rem;
  border-top: 1px solid var(--bs-border-color);
  padding: 0.5rem 0;
}

@media (min-width: 768px) {
  .cooking-make-row {
    grid-template-columns: minmax(7rem, auto) 1fr auto;
    align-items: start;
  }
}

/* The warning is a sentence about the whole row and quotes a review, so it drops
   below all three columns rather than crowding the link it describes. */
.cooking-make-row > .cooking-hint {
  grid-column: 1 / -1;
  margin-top: 0.25rem;
}

.cooking-make-when {
  margin: 0;
}

.cooking-make-note,
.cooking-make-quote {
  margin: 0;
}

.cooking-make-quote {
  font-style: italic;
  color: var(--bs-secondary-color);
}

/* What is left once Remove shares its tap target with Delete (see the 44px block
   above) and its oxblood with the rest of the danger family: the resets that
   make a `<button>` look like the link it is.

   `text-align: left` because a centred label in an `auto` column drifts as the
   label changes length between rows -- and the labels differ per row, since the
   one whose removal walks the standing verdict back says so. */
.cooking-remove {
  border: 0;
  border-radius: 0;
  background: none;
  padding: 0;
  text-align: left;
}

.cooking-make-remove-form.htmx-request .cooking-idle {
  display: none;
}

.cooking-make-remove-form.htmx-request .cooking-busy {
  display: inline;
}

/* The truncation note and the way out, both quiet: neither is content, and the
   link is what makes a five-row cap honest on a recipe you cook every week. */
.cooking-makes-note {
  margin: 0.5rem 0 0;
  color: var(--bs-secondary-color);
  font-size: 0.875rem;
}

.cooking-makes-all {
  margin: 0.5rem 0 0;
  text-align: right;
}

/* `inline-block` for the reason spelled out on `.cooking-review-byline a`:
   `djlint --reformat` puts the link's contents on their own lines, which leaves a
   newline immediately inside the `<a>` on both sides. Inline, that collapses to a
   rendered space INSIDE the link and the underline runs past the words. */
.cooking-makes-all a {
  display: inline-block;
  min-height: 44px;
}

/* ---------------------------------------------------------------------------
   `/recipes/made/` -- the whole log, grouped by dish.

   Almost nothing, and that is the point: the rows on that page are the rows
   above (`.cooking-make-row`, `.cooking-remove`), so everything that governs how
   a cook reads and taps a line is already declared and shared. What is left is
   the spacing between groups and the two quiet lines around them.
   --------------------------------------------------------------------------- */

/* DESIGN.md, Spacing: content caps at 60rem, "wider than that and the method
   column outruns a comfortable measure". A make row is mostly a cook's own
   prose, and the same prose sits inside `col-md-8 offset-md-2` on the recipe
   page -- so without this cap one sentence sets a ~130-character measure here
   and a comfortable one there. `.container` keeps centring it. */
.cooking-history {
  max-width: 60rem;
}

.cooking-history-recipe {
  margin-top: 2rem;
}

/* The heading is a focus target after a removal (T25), reached by fragment
   rather than by script. `tabindex="-1"` makes it focusable and would otherwise
   leave it with no visible ring in some browsers, so the ring is asked for
   explicitly -- a focus move nobody can see is not a focus move. It is asked
   for in the panel's shared `:focus-visible` block above, in ink: this used to
   name Bootstrap's primary variable, which nothing in this repo overrides, so
   it resolved to #0d6efd -- a blue in a palette that has none. */

.cooking-history-count {
  margin: 0;
  color: var(--bs-secondary-color);
}

.cooking-history-empty {
  margin-top: 2rem;
}

.cooking-history-browse a {
  display: inline-block;
  min-height: 44px;
}
