/*
 * EDITORIAL — the second theme.
 *
 * Drawn by Gabe in the design tool on 2026-09-21 and built from the picture:
 * a white ground, a heavy sans display face, cards with no chrome at all, a
 * numbered index, and the cuisine set small and letterspaced beside the
 * number. His words: "a design that needs to be at least an option, and
 * quite possibly the single design for the site."
 *
 * **Everything here is CSS.** LOCKED.md: a theme changes how a recipe looks,
 * never what it shows. Nothing below hides a field; the numbers come from a
 * CSS counter, which is presentation of position rather than new content.
 *
 * Loaded after recipe.css, so an override can be a line rather than a
 * restatement. Where a rule here is long, that is a measurement: it is the
 * list of what recipe.css has welded together and what a third theme would
 * have to fight. Worth reading as a to-do for factoring, not as a style.
 */

:root[data-design="editorial"] {
  /* The ground goes white, the hairlines go neutral, and the red gets
     brighter: #C92A12 from the handoff against the kitchen theme's #b8462f.
     Both clear AA on white - 5.49:1 and 5.31:1 - so this is a choice about
     the drawing rather than about legibility. It does not clear AA on the
     black filter cells (3.44:1), which is what the tint is for. */
  --flame:       #C92A12;
  --flame-tint:  #F2B8AE;
  --cream:       #ffffff;
  /* 0.62, from 0.86: the pinned header and edit mode's Save bar showed so
     little through them that the glass read as a white bar. Gabe,
     2026-09-25: "lower the opacity of the blurred header background so we
     see more of what's happening". The blur carries the legibility. */
  --cream-glass: rgba(255, 255, 255, 0.62);
  --paper:       #fafafa;
  --charcoal:    #111111;
  --line:        #e4e4e4;
  --muted:       #6b6b6b;
  --soft:        #444444;

  /* **No teal, by construction.** Editorial's touchable is ink, grey or red,
     and it was kept free of the kitchen design's --caribbean one rule at a
     time - so every rule nobody had got to yet was still teal: the open
     filter button, the loading bar, the pager, focus rings, pins, the "add a
     note" link. Gabe, 2026-09-26: "found some teal". The token itself is red
     here now, which is what editorial's hovers, focus and "on" already are,
     and --accent follows it (recipe.css sets --accent from it). Rules that
     want ink rather than red say so below, as Save does. */
  --caribbean:   #C92A12;

  /* One face, three jobs. -apple-system first so it is the platform's own
     grotesque rather than a webfont on the critical path; the drawing is set
     in something very close to it. */
  --sans: 'Archivo', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

/* The page, and everything that inherits from it. The wordmark keeps its own
   face - it is a logo, and it is serif in the drawing too. */
:root[data-design="editorial"] body {
  font-family: var(--sans);
  letter-spacing: -0.008em;
}

/* ------------------------------------------------------------- the cards --

   The polaroid comes off: no stock, no border, no shadow, no radius, no
   padding. The photograph is the card's edge and the text sits under it on
   the page.

   The card is the grid, not .card-body, and `display: contents` is what makes
   that possible. The drawing has four rows - photograph, then a ruled line
   with the cuisine left and the rating right, then the title, then the source
   and the time - and the markup nests those across .card-link, .card-body and
   .card-meta. Flattening those three wrappers lets every field be placed
   directly, without moving one line of PHP: the kitchen theme still sees the
   boxes it was built on. */
[data-design="editorial"] .card {
  display: grid;
  /* Three tracks: the wide one carries the cuisine and the source, the two
     narrow ones carry the rating, then the time and the yield. Three rather
     than two because the time and the yield are separate spans that share a
     line, and two grid items cannot sit in one cell side by side. */
  grid-template-columns: minmax(0, 1fr) auto auto;
  /* The rule line (row 3) is one line tall even when it is empty. A recipe
     with no cuisine, no rating and no yield put nothing on it, the row
     closed to 0 and its title rose 20px above the card beside it - Gabe,
     2026-09-25, a new recipe saved with nothing filled in. `--rule-line` was
     already what every item on the row takes; this makes the row take it
     too. minmax, so a cuisine long enough to wrap still has room. */
  grid-template-rows: auto auto minmax(var(--rule-line), auto);
  /* The three tracks in the bottom row butt against each other without this,
     and "429" ran straight into "30 min". The gap is the air the drawing puts
     either side of its slash. */
  column-gap: 12px;
  align-content: start;
  background: none;
  padding: 0;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  position: static;
}
[data-design="editorial"] .card-link,
[data-design="editorial"] .card-body,
[data-design="editorial"] .card-meta { display: contents; }

[data-design="editorial"] .card-shot {
  grid-column: 1 / -1;
  aspect-ratio: 4 / 3;
  border-radius: 0;
  background: #f0f0f0;
}
/* The grey above is a photograph's loading backdrop. A drawn card keeps the
   recipe's own colour, like the base sheet and this design's own recipe page
   - grey under the white drawing washed both out to nearly nothing. Gabe,
   2026-09-25: "Shouldn't they always have a color?" They should. */
[data-design="editorial"] .card-shot-drawn { background: var(--accent); }

/* The ruled line, drawn by the card itself rather than by whatever happens to
   be sitting on the row.

   It was a border-top shared by the cuisine and the rating, and it broke on
   the cards that have neither: 158 recipes have no cuisine yet, and an
   unrated one of those drew no rule at all - the title just began under the
   photograph. With a cuisine and no rating it ran only as far as the first
   track.

   A pseudo-element is a grid item, so it can take the whole row and be there
   whether or not anything else is. The row is 0px tall and the rule is its
   top edge, which is why the air above and below is margin rather than
   padding. */
[data-design="editorial"] .card::before {
  content: '';
  grid-column: 1 / -1;
  grid-row: 2;
  margin: 12px 0 10px;
  border-top: 2px solid var(--charcoal);
}
/* **One height for the rule line, whatever is on it.**

   The row holds the cuisine at 0.6875rem, the stars, and the yield at
   0.8125rem - three different line boxes, and the row took the tallest. So a
   card with no yield had a 13px row where its neighbour had 20, and its title
   began 7px higher than the card beside it. Gabe, 2026-09-23: "is it my
   imagination or is 'sheet pan' lower than 'aguacate'?!" It was not.

   Each card is its own grid - that is what `display: contents` on the wrappers
   buys - so nothing makes two cards agree about a row unless the row is told
   what it is. `--rule-line` is that number, and every item on the row takes
   it: the text keeps its own size and the box stops depending on which of the
   three happen to be there. */
:root[data-design="editorial"] { --rule-line: 20px; }

[data-design="editorial"] .card-meta .is-cuisine {
  grid-row: 3;
  font-size: 0.6875rem;
  line-height: var(--rule-line);
}
/* An unrated recipe has no stars to print, so the cuisine takes the width and
   the rule still runs the whole way. */
[data-design="editorial"] .card-meta .is-cuisine {
  grid-column: 1 / 3;
  font-family: var(--sans);
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--flame);
}
/* **Your stars, cut into the photograph's top right** on white, the way the
   recipe page does it (.hero-rating). They were on the rule line beside the
   cuisine, and at narrow widths the cuisine ran under them - "SPAN★★★★★" -
   and "MIDDLE EASTERN" broke over two lines to make room. Gabe, 2026-09-30:
   "if you want we can put the stars top right like recipe". The cuisine now
   has its line to itself, bar the yield. This undoes "no overlays on the
   image" for this one mark, as the recipe page already had. */
[data-design="editorial"] .card-shot { grid-row: 1; }
[data-design="editorial"] .card-rating {
  grid-column: 1 / -1;
  grid-row: 1;
  align-self: start;
  justify-self: end;
  z-index: 1;
  position: static;
  padding: 6px 9px 5px;
  background: #fff;
  font-size: 0.75rem;
  line-height: 1;
  letter-spacing: 0.08em;
  color: var(--flame);
  text-shadow: none;
}
/* Not on the Recently row's small cards: no room, and the row is for finding
   your place. Gabe: "prob leave of recent for space?" */
[data-design="editorial"] .row-small .card-rating { display: none; }
[data-design="editorial"] .card-rating .dim { display: none; }
/* The scrim went with the overlay: "no overlays on the image". */
[data-design="editorial"] .card-shot-rated::after { display: none; }

[data-design="editorial"] .card-title {
  grid-column: 1 / -1;
  grid-row: 4;
  /* Tight under the cuisine line - the two read as one label. Gabe,
     2026-09-24: "tighten the leading btwn these two lines". It was 7px. */
  margin: 1px 0 0;
  font-family: var(--sans);
  font-size: 1.5625rem;
  font-weight: 800;
  line-height: 1.04;
  letter-spacing: -0.03em;
  text-wrap: pretty;
  color: var(--charcoal);
}
[data-design="editorial"] .card-link:hover .card-title,
[data-design="editorial"] .card:hover .card-title { text-decoration: none; color: var(--flame); }

/* Source left, time and yield right, on one line under the title.

   min-width: 0 and a hidden overflow, because a grid track of `minmax(0,
   1fr)` still will not shrink a child that refuses to wrap - and
   .card-source-rating is `white-space: nowrap` in recipe.css for a good
   reason of its own. Without this, "carolinescooking.com ★ 4.7 110" ran
   straight over "3 min" in the next track and printed as "4.71 in 3 min".
   Reported with a picture. */
/* Two tracks wide, now that the yield has gone up to the rule line and only
   the time is left out here. At three columns the publisher's name had about
   126px and "NYT Cooking" was printing as "NY…"; taking the middle track back
   gives it half as much again. */
[data-design="editorial"] .card-source {
  grid-column: 1 / 3;
  grid-row: 5;
  min-width: 0;
  overflow: hidden;
  margin-top: 7px;
  padding: 0;
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.01em;
}
[data-design="editorial"] .card:hover .card-source-name { color: var(--flame); }
/* The arrow first, then the name.
   Reordered here rather than in the markup, because the kitchen theme reads
   left to right as name-then-arrow and the two designs share one template. It
   is a flex line already, so this costs one property. */
[data-design="editorial"] .card-source-out { order: -1; }
/* The rating follows the publisher rather than being shoved to the far side
   of the cell. `margin-left: auto` is right in the kitchen theme, where the
   source line owns the card's whole width; here the line is one grid cell of
   three and pushing right closes the gap to the time. */
[data-design="editorial"] .card-source-rating {
  margin-left: 0;
  font-weight: 500;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
/* The community star, red, as drawn. */
[data-design="editorial"] .card-source-rating::before {
  content: '\2605';
  margin-right: 4px;
  color: var(--flame);
}
[data-design="editorial"] .card-meta .is-time,
[data-design="editorial"] .card-meta .is-yield {
  align-self: baseline;
  font-family: var(--sans);
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
/* The time keeps the source's line and takes everything the source does not
   need, so it sets to the right edge whether or not there is a yield beside
   the cuisine above it. */
[data-design="editorial"] .card-meta .is-time {
  grid-column: 3;
  grid-row: 5;
  justify-self: end;
  margin-top: 7px;
}
/* The yield moves up to the rule line, hard right, opposite the cuisine.

   It was next to the time under the title, where it read as a second piece of
   the source line; up here it answers the cuisine - what it is on the left,
   how much of it on the right - and the line under the title is left saying
   only where the recipe came from and how long it takes.

   The margin is air, not alignment: at one column the cuisine can run long
   and 12px of grid gap put "SOUTHEAST ASIAN" within a hair of "20 meatballs".
   The middle dot that used to separate the yield from the time goes with it;
   there is nothing on this row to separate it from. */
[data-design="editorial"] .card-meta .is-yield {
  grid-column: 3;
  grid-row: 3;
  justify-self: end;
  margin-left: 14px;
  line-height: var(--rule-line);
}
[data-design="editorial"] .card-meta-sep { display: none; }

[data-design="editorial"] .card-match {
  grid-column: 1 / -1;
  grid-row: 6;
  font-family: var(--sans);
}

/* ------------------------------------------------------- the card grid --

   **The handoff's grid, and it belongs to this design alone.**

   It specifies `repeat(auto-fill, minmax(280px, 1fr))` with a 32px column gap
   and a 44px row gap. Gabe, 2026-09-21: "the exact same image sizes,
   breakpoints, and aspects through the breaks. Bolder is better in this
   design."

   It lived in `recipe.css` for an hour, which gave the kitchen design the same
   three big cards and the same gaps - and two designs that differ only in
   colour are not two designs. Gabe, 2026-09-22: "not sure which i prefer bc
   they are the same now." So it is scoped here, and the kitchen design keeps
   its four tighter columns.

   **The count cannot literally be auto-fill.** `.row-strip` is a flex strip
   that has to produce the same card width as the grid, and a flex child
   cannot ask how many columns auto-fill chose - so the count is stated and
   both obey it. What is reproduced here is auto-fill's *arithmetic*.

   `n` columns fit when the content box is at least `n * 280 + (n-1) * 32`:
   592px for two, 904px for three. The content box is
   `min(100vw, 1180) - 2 * clamp(20px, 4vw, 48px)`, which puts the switches at
   **644px and 983px** - solved over every integer width rather than estimated,
   because the first attempt was a pixel late at both edges and a pixel is a
   whole column when you are standing on the boundary.

   Three is the ceiling: 1084px of content is short of the 1216 a fourth
   column needs, so the handoff's own numbers stop there.

   Verified against a real auto-fill grid built in the same content box at
   375, 643, 644, 982, 983, 1000, 1280 and 1600 - the tracks match on both
   sides of both switches, the card never goes under 280, and the photograph
   is 1.333 everywhere.

   `--card-gap` is set on `:root[data-design="editorial"]`, which outranks the
   base sheet's `:root` on specificity rather than on order - including the
   base's narrow-screen 14px, which must not reach this design. */
/* ------------------------------------------------- the page has no cap --

   Gabe, 2026-09-22, with a screenshot of the earlier wide version: "i think i
   prefer this earlier version we had with a bit of margin (though i want this
   one to be responsive, no fixed content width, at least this page)."

   So on the browse page the editorial design stops having a content width at
   all. The margin is `--gutter` - clamp(20px, 4vw, 48px) - and nothing else,
   and the three columns keep growing with the window instead of freezing at
   the cap.

   **This replaces the rule settled on 2026-09-21**, which was that past the
   maximum a card should be as large as it is at the two-column snap. That is
   what grew `--wide` from 1180 to 1468 in the first place. The two cannot both
   be true: one says the cards stop growing at a chosen width, the other says
   they never stop. This one is newer and it is the one with a picture.

   **Why a number and not `none`.** `--wide` is not only a `max-width`. Four
   places compute the distance from the viewport edge to the content edge with
   it - the chip band's scroll padding, the filter panel, the design switcher -
   as `max(var(--gutter), calc(50vw - var(--wide) / 2))`. A custom property is
   substituted as text, so `none` would make those `calc()`s invalid and the
   declarations would be dropped. A number far past any monitor keeps every one
   of them arithmetic: the calc goes hugely negative, `max()` picks `--gutter`,
   and every part of the page lines up on the same margin it always did.

   **Scoped to the page with the grid.** `body:has(.card-grid)` is the browse
   page and the search results; the recipe page keeps `--measure`, because two
   columns of prose have a line length to protect and he said "at least this
   page". */
/* **And the themes view, which was left behind.** The row strips have always
   run to the window edge; the masthead and the chip band were still capped at
   1468, so past about 1700px the page had a white header floating in the
   middle of cards that reached both edges - a card visible to the right of
   the masthead, which reads as a broken layout rather than a wide one. Gabe,
   2026-09-24: "display bug at wide window."

   `.rows` is on the results bar as well as the strips, so it covers both
   views and the one selector says the same thing twice rather than the two
   views disagreeing again. */
[data-design="editorial"] body:has(.card-grid),
[data-design="editorial"] body:has(.rows) { --wide: 100000px; }

:root[data-design="editorial"] { --cols: 1; --card-gap: 32px; }
@media (min-width: 644px) { :root[data-design="editorial"] { --cols: 2; } }

/* **740, not 983, and the arithmetic is knowingly broken here.**
   Three columns want 904px of content by the rule above - `3 x 280 + 2 x 32` -
   and a landscape phone has about 680. Gabe, 2026-09-23: "index on horizontal
   phone needs to be three columns or row cuts off." On a themed row the third
   card is the one that says the strip scrolls, and at two columns it is cut in
   half by the edge of a screen that is already short: you see a card and a
   sliver and nothing that reads as a row.
   So the minimum card gives way at this one width. 205px is small and it is
   the whole card - photograph, cuisine, title, source - rather than two and a
   guess. 983 is gone rather than kept as a third step: one column count per
   width, and a second switch inside the phone range would move the grid twice
   while you turn the thing over. */
@media (min-width: 740px) { :root[data-design="editorial"] { --cols: 3; } }

/* 44 down against 32 across, from the handoff. The rows are further apart than
   the columns on purpose: a card is photograph-then-text, so the gap below one
   has to clear the text before the next photograph starts.

   It was 60 here for a day, against the drawing, because these cards carry a
   line the drawing's do not - source, rating, time and yield all under the
   title - and at 44 the foot of one card and the photograph of the next read
   as one block. Gabe asked for the drawing exactly. If the crowding comes
   back, this is the number to move and that is the reason. */
[data-design="editorial"] .card-grid { row-gap: 44px; }

/* One column needs more air than the drawing's 44.

   Measured on a phone: 24px from a photograph to its own kicker, 44px from
   the foot of a card to the next photograph. Not quite twice, which is not
   enough contrast to group - Gabe, reading it on a phone: "very little to tell
   you which image the headline belongs to."

   The drawing's 44 was measured in a three-column grid, where the columns do
   most of the separating and the row gap only has to finish the job. Stacked,
   it is the only thing doing it, so it has to be unambiguous: 72 is three
   times the gap inside a card, which reads as two things rather than one. */
@media (max-width: 643px) {
  [data-design="editorial"] .card-grid { row-gap: 72px; }
}

/* ------------------------------------------------------------- the chrome -- */

/* The masthead's own rule goes: the filter row carries the heavy one, and two
   black lines 20px apart read as a mistake. */
[data-design="editorial"] .topbar { border-bottom: 0; }

/* ------------------------------------------------------ the filter row --

   Cells in a row of equal tracks, not pills in a scrolling bar. 5px of ink
   over them and a hairline under, a 1px divider down the left of each, the
   label left and the count hard right.

   `flex: 1 1 0` rather than the drawing's `repeat(6, 1fr)`, and the
   difference matters. The drawing has six filters; this app has as many as
   twelve, and a chip disappears when its count would be zero - so the number
   of tracks is not a constant and a fixed six would either clip or stretch.
   Equal flex tracks give the same even row at the widths the drawing was
   made at, and still scroll sideways when there are more than fit, which is
   the behaviour the bar already had. */
[data-design="editorial"] .chiprow {
  border-top: 5px solid var(--charcoal);
  border-bottom: 1px solid var(--line);
}
[data-design="editorial"] .chipbar { gap: 0; padding: 0; }

[data-design="editorial"] .chip {
  /* Label left, count right, on one line - and every cell the same width
     whatever is in it. Gabe's lockup, 2026-09-22, sent as a picture.

     It stacked the count under the label for a day, which was read off an
     earlier drawing; the handoff's README said one row all along. Stacking
     also put the count in a different place on every cell, because the count
     slot is right-aligned and the labels are not the same length.

     `flex: 0 0` rather than `1 1 0`: constant means constant. With eleven
     chips the row overflows and scrolls either way, but a grow factor would
     stretch the cells whenever there are few enough to fit - so the row would
     be one shape on the collection and another under a filter that hides
     half of them. 11.5rem is "Southeast Asian" at 13px/700 beside a
     four-character count, with the cell's padding and a gap that does not
     close up. */
  flex-direction: row;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  /* **The first chip ends where the filter panel ends.** The dock sits in the
     margin and the panel is `--rail-w` wide from the window's edge, so a chip
     of `--rail-w` minus the margin puts the divider after the first one exactly
     on the panel's right edge - and every chip after it on the same rhythm.
     Gabe, 2026-09-23: "make chips a width where the first one lines up with the
     panel."

     `--dock-w` is the control plus the air either side of it, which is what
     `.filterdock`'s margins already work out; it is written here so the two
     cannot drift. 11.5rem was "Southeast Asian" at 13px/700 with its count,
     and the new number is wider than that at every width the design uses. */
  flex: 0 0 calc(var(--rail-w) - var(--dock-w));
  padding: 13px 14px 12px;
  border: 0;
  /* On a black cell a grey hairline disappears, so the on state carries its
     own - see below. The divider is the row's rhythm and has to survive
     whatever the cell is doing. Gabe: "hairlines between". */
  border-left: 1px solid #d0d0d0;
  border-radius: 0;
  background: #fff;
  font-family: var(--sans);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: -0.015em;
  text-transform: none;
  transition: background 90ms, color 90ms;
}
[data-design="editorial"] .chip .chip-count {
  font-size: 0.6875rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}
/* **A grey wash, not a red bar.** Gabe, 2026-09-30, agreeing to lose the
   underline "so long as its distinct from the temp chip gray": a red bar
   under a word is this design's mark for *selected* (the Recently tabs, the
   People sort), so on a chip it read as a state that flickered past the
   pointer. White goes pale grey; a selected chip lifts a shade off black,
   nowhere near the temporary chip's #4A4744; a temporary one lifts a shade
   off that. Replaced the red bar that had been here since the row was drawn.
   The slot's hover too, so moving onto the pin, which sits over the chip's
   left edge, does not flick the cell back to white. */
[data-design="editorial"] .chip:hover,
[data-design="editorial"] .chip-slot:hover > .chip {
  border-color: #d0d0d0;
  color: inherit;
  background: #efefef;
  box-shadow: none;
}
[data-design="editorial"] .chip.chip-on:hover,
[data-design="editorial"] .chip-slot:hover > .chip.chip-on { background: #2a2826; color: #fff; }
[data-design="editorial"] .chip.chip-on.chip-temp:hover,
[data-design="editorial"] .chip-slot:hover > .chip.chip-on.chip-temp { background: #5a5653; }
[data-design="editorial"] .chip:active { transform: translateY(1px); }
[data-design="editorial"] .chip.chip-on {
  background: var(--charcoal);
  /* Lighter than the cell, not the same as it: the divider was being painted
     charcoal on charcoal, so a run of selected chips read as one long black
     bar with words in it. */
  border-left-color: rgba(255, 255, 255, 0.28);
  color: #fff;
}
/* The seam between a selected chip and an unselected one belongs to whichever
   is on the right, and only one of them can draw it. When that is the pale
   cell the grey is right; when it is the black one the light rule is. Nothing
   to do beyond saying so - the border is already on the left edge of each
   cell, which is the one place both cases agree on. */
/* White, dimmed - not the flame tint it was. Gabe, 2026-09-30: "no light
   red text". Red on a selected chip read as a second state; the count is
   just smaller and quieter than the label. 10:1 on charcoal. */
[data-design="editorial"] .chip.chip-on .chip-count { color: rgba(255, 255, 255, 0.72); }
[data-design="editorial"] .chip-tick { display: none; }

/* The session mark has to be restated here: this design sets `border: 0` on
   the cell and then puts the divider back on the left, which outranks the base
   sheet's rule by specificity. Inset rather than on the cell's edge, so it
   reads as a mark under the words rather than as another divider. */
/* Solid and very dark rather than dashed. The dashes were the ghost chip's
   idiom borrowed one step too far - on a chip with words and a number in it
   they read as fussy rather than as "temporary". Gabe, 2026-09-23: "still dont
   love, ooh, what about a v. dark gray?" A quiet solid rule says the same
   thing and gets out of the way. */
/* `.chip-loose` was here, and the chip it described is gone. */

/* The picker keeps its circle and its place at the head of the row - Gabe's
   call - and loses the left divider so it reads as the thing the row hangs
   off rather than as the first cell of it.

   No teal. The kitchen theme puts --caribbean on this control's hover and on
   its ring while a filter is on; this palette has two colours and neither is
   that. Ink for the ring, red on hover, which is the hover the filter cells
   use. */
/* No teal anywhere on this control, and **on is just red**. It carried the
   kitchen design's --caribbean, and "on" was a border plus an inset ring of
   the same colour a pixel inside it - a doubled stroke that read as a
   rendering fault at any size. Gabe, 2026-09-22: "Let's lose any teal in the
   filter button. When it's active, make it just red, not this stroke thing
   that's happening now." */
[data-design="editorial"] .filterdock,
[data-design="editorial"] .filterdock:hover,
[data-design="editorial"] .filterdock.is-on,
[data-design="editorial"] .filterdock.is-on:hover { box-shadow: none; }

/* **Red at rest** (until 2026-09-29, see the next note), so it reads as something to press. Gabe, 2026-09-28:
   "let's make the filter settings icon red, i worry people wont get that
   they can customize." A grey icon in a grey ring read as a decoration.
   With red now the resting colour, "a filter is on" is the filled circle,
   white sliders on red - the same fill the Focus mode fill button wears
   while it is on. */
/* **Black at rest, red when a filter is on**, both filled with white sliders.
   Gabe, 2026-09-29: "make the filter setting solid black default and red
   selected." Red outline at rest and red fill when on were the same color
   twice; black and red are two states you can tell apart across the room,
   and a filled black circle still reads as something to press. A filled
   square since 2026-10-04 (punch 198; recipe.css .filterdock). */
[data-design="editorial"] .filterdock,
[data-design="editorial"] .filterdock:hover {
  border-color: var(--charcoal);
  background: var(--charcoal);
  color: #fff;
}
[data-design="editorial"] .filterdock.is-on,
[data-design="editorial"] .filterdock.is-on:hover {
  border-color: var(--flame);
  background: var(--flame);
  color: #fff;
}
/* Inside the square, white: it fills the margin, so an outline outside it
   would be cut off by the window's edge, and flame on a red square is not
   there at all. */
[data-design="editorial"] .filterdock:focus-visible { outline-color: #fff; outline-offset: -5px; }

/* Save is ink. With --caribbean red here, Save would be the same filled red as
   Delete - and Delete is the one filled flame in the app, because it is the
   one act that cannot be taken back. The edit bar reads Delete red, Save ink,
   Cancel outlined. */
[data-design="editorial"] .sb-save,
[data-design="editorial"] .edit-bar button { background: var(--charcoal); border-color: var(--charcoal); color: #fff; }
[data-design="editorial"] .edit-bar button:hover { background: var(--charcoal); border-color: var(--charcoal); }
/* A plan's Delete this plan: filled flame, as the recipe edit bar's Delete is. */
[data-design="editorial"] .edit-bar button.sb-delete, [data-design="editorial"] .edit-bar button.sb-delete:hover { background: var(--flame); border-color: var(--flame); }
/* Open keeps white sliders on its fill (it was red until 2026-09-29). The kitchen design turns the icon teal while the panel is
   open, and that one state was never given editorial's color - Gabe,
   2026-09-26, with a picture of it: "found some teal". */
/* Open: red with a black stroke, so it reads apart from "a filter is on"
   (red alone). Gabe, 2026-09-30: "solid red when filtering, solid red with
   black stroke when open, default unchanged." The stroke is 2px - the 1px
   border and a 1px ring inside it - which is what reads at 30px. It was red
   alone while open for a day ("the filter options icon doesn't go red").
   **No stroke along the top** since the square filled its slot: the heavy
   rule is already there, and the two together were 7px. Gabe, 2026-10-04:
   "lose the top stroke on the button when the panel is open (makes it too
   thick)." So the ring is three sides, and there is no top border at all:
   a red top border met the black sides on a slant at each corner, a little
   bevelled wedge Gabe caught the same day ("still not right on the top").
   The 1px of padding keeps the icon where it was. */
[data-design="editorial"] .filterdock:is([popovertarget]):is(:has(+ [popover]:popover-open)) {
  border-color: var(--charcoal);
  border-top-width: 0;
  padding-top: 1px;
  background: var(--flame);
  color: #fff;
  box-shadow: inset 1px 0 0 var(--charcoal), inset -1px 0 0 var(--charcoal), inset 0 -1px 0 var(--charcoal);
}
[data-design="editorial"] .filterdock.is-on:is([popovertarget]):is(:has(+ [popover]:popover-open)) { color: #fff; }

/* The control gets a slot, and sits in the middle of it.

   It had 7px to the page edge and 4px to the first chip - the arithmetic that
   put the first chip on the gutter, and on the same line as the wordmark above
   it. That alignment cost the control all its air: Gabe, 2026-09-22, with a
   picture of the corner, "give us a bit more padding bot[h] sides and center
   this icon in the gap."

   The space it sits in is the margin itself - from the browser's edge to the
   line the logo and the first photograph stand on. Gabe, 2026-09-22: "align
   left edge of logo with left edge of photo. Put icon in the middle of THAT
   space between edge of photo/logo and edge of browser."

   So both margins are half of what is left of `--gutter` after the 30px
   control, which puts the control's centre on `--gutter / 2` and the first
   chip back on `--gutter` - the same line as the wordmark above it and the
   first card below it. A first attempt gave it a slot of its own, wider than
   the margin; that bought it air and cost the alignment, and the alignment is
   the thing being asked for.

   `max()` because the sum goes negative on a phone: `--gutter` falls to 20
   and the control is 30, so there is no margin to centre in and 4px is all it
   gets. The chip row starts past the gutter at those widths and that is the
   only place it does. */
/* **The control is the slot now: a filled square, edge to first chip, as
   tall as the chips.** Gabe, 2026-10-04, once it was a square: "Make the
   square fill the space" (punch 198). Until then it was 30px, centred in the
   slot with `--dock-air` either side, which is the arithmetic above; the
   icon still sits in the middle of the margin, which is what he asked for on
   09-22.

   `--dock-w` is still the whole slot, so the chip row is told where it starts
   without measuring anything. It is the margin, so the first chip stays on
   the gutter line with the wordmark and the cards - and never narrower than
   45px, the chips' height, so it stays a square where the margin is thin
   (under about 1,120px wide, where the chips start past the gutter, as they
   already did under about 950). At 1,280 it is 48 by 45. */
:root[data-design="editorial"] {
  --dock-w: max(var(--gutter), 45px);
}
[data-design="editorial"] .filterdock {
  width: var(--dock-w);
  height: auto;
  margin: 0;
  align-self: stretch;
}
/* The size of the header's + icon, in a square about the size of the + one. */
[data-design="editorial"] .fd-icon { width: 18px; height: 18px; }
[data-design="editorial"] .chipbar > .chip:first-child,
[data-design="editorial"] .chipbar > .chip-slot:first-child > .chip { border-left: 0; }

/* The row is a run of cells divided by hairlines, and the last one had an open
   end - the divider is on the left of each cell, so the right of the row was
   the only edge without one. */
[data-design="editorial"] .chipbar > .chip:last-child,
[data-design="editorial"] .chipbar > .chip-slot:last-child > .chip { border-right: 1px solid #d0d0d0; }

/* The slot takes the cell's fixed width and the chip fills it, so a chip with
   an x is the same cell as one without. */
[data-design="editorial"] .chip-slot { flex: 0 0 calc(var(--rail-w) - var(--dock-w)); }
[data-design="editorial"] .chip-slot > .chip { flex: 1 1 auto; min-width: 0; }
[data-design="editorial"] .chip-x { right: 6px; border-radius: 0; }
[data-design="editorial"] .chip-x:hover { color: var(--flame); background: none; }
[data-design="editorial"] .chip-on + .chip-x { color: rgba(255, 255, 255, 0.6); }
[data-design="editorial"] .chip-on + .chip-x:hover { color: #fff; background: none; }
[data-design="editorial"] .chip-x:focus-visible { outline-color: var(--flame); }
/* The toast inherits this palette's charcoal and cream from the variables;
   the corners and the face are all it needs told. */
[data-design="editorial"] .chip-toast { border-radius: 0; font-family: var(--sans); }
[data-design="editorial"] .filterpanel {
  border-radius: 0;
  font-family: var(--sans);
}
/* Aggro, on his word - the head is a control now and it dresses like one.
   Gabe, 2026-09-25: "make this aggro bold". */
[data-design="editorial"] .fp-title { font-family: var(--sans); font-weight: 800; letter-spacing: -0.02em; }

/* No teal in this design, here either. The base sheet says a filter that is on
   and a pin that is stuck are both `--caribbean`; every other accent on this
   page is already the flame, and one teal row in a red panel reads as a
   different app's control that wandered in. Same rule as the filter button. */
[data-design="editorial"] button.fp-row:hover,
[data-design="editorial"] .fp-word:hover { background: rgba(214, 60, 32, 0.09); }
[data-design="editorial"] .fp-row.is-pinned .fp-pin,
[data-design="editorial"] .fp-row.is-temp .fp-pin,
[data-design="editorial"] .fp-pin-btn:hover .fp-pin { color: var(--flame); }
[data-design="editorial"] .fp-pin-btn:focus-visible,
[data-design="editorial"] .fp-word:focus-visible { outline-color: var(--flame); }

/* **A temporary chip is a lighter black** - on, and not kept. Gabe,
   2026-09-30: "i'd like to try lighter black temp chips." */
[data-design="editorial"] .chip.chip-on.chip-temp { background: #4A4744; }
/* **The pin is on the left of the label.** Gabe, 2026-09-30: "lets try pin
   in chip on the left of the label" - it reads before the word, the way the
   panel's rows draw it, and the count keeps the right edge to itself. */
[data-design="editorial"] .chip.has-x { padding-left: 34px; padding-right: 14px; }
[data-design="editorial"] .chip-pin { left: 7px; right: auto; border-radius: 0; }
[data-design="editorial"] .chip-pin:hover { color: var(--flame); background: none; }
[data-design="editorial"] .chip-on + .chip-pin { color: rgba(255, 255, 255, 0.75); }
[data-design="editorial"] .chip-on + .chip-pin:hover { color: #fff; background: none; }
[data-design="editorial"] .chip-pin:focus-visible { outline-color: var(--flame); }
[data-design="editorial"] .fp-row:focus-visible { outline-color: var(--flame); }

/* Row and section headings take the display face. */
[data-design="editorial"] .row-head h2,
[data-design="editorial"] .row-title,
[data-design="editorial"] h1,
[data-design="editorial"] h2,
[data-design="editorial"] h3 {
  font-family: var(--sans);
  font-weight: 600;
  letter-spacing: -0.02em;
}

/* The theme headings outrank the card titles under them, which in this
   design are themselves large and heavy - at the shared 1.32rem/600 a row
   was headed by something smaller than its own cards, and Kitchen read
   clearer for it. Gabe, 2026-09-25: "beef up the theme headings" - and then,
   at 1.6rem against titles at 1.5625rem/800: "now they compete with the
   names, we're going to have to go big n bold". 800 is the heaviest Archivo
   the page loads, so the outranking is size. After the shared rule above,
   whose 600 would otherwise win the tie. */
[data-design="editorial"] .row-head h2 {
  font-size: 2.1rem;
  font-weight: 800;
  letter-spacing: -0.03em;
}
/* The two recency tabs are that heading twice, so they keep its size and
   weight; the red bar inside the bottom edge marks the one showing. */
[data-design="editorial"] .row-tab:hover { color: var(--flame); box-shadow: inset 0 -4px 0 transparent; }
[data-design="editorial"] .row-tab.is-on { color: var(--charcoal); box-shadow: inset 0 -4px 0 var(--flame); }
[data-design="editorial"] .row-empty { font-family: var(--sans); font-style: normal; color: var(--muted); }

/* The search field loses its box and keeps a rule under it. */
/* A grey field with no border and no button, which is how it is drawn. The
   button is hidden rather than removed from the markup: Enter still submits,
   the form still produces a real URL, and a theme may not delete a control
   any more than it may delete a field. */
/* The masthead search, exactly as the handoff of 2026-09-24 draws it. The
   structure is in recipe.css and shared; these are this palette's values.

   The field's tint is the ingredient panel's #f0f0f0 rather than the
   handoff's #F5F4F2, because the line that gives the hex also says what it is
   for - "the same tint as the ingredient panel" - and in this app that panel
   is #f0f0f0. Matching the panel is the instruction; the number was written
   from a mock where the panel was a shade lighter. */
[data-design="editorial"] .searchbox {
  border: 0;
  border-radius: 0;
  background: transparent;
  padding: 0;
}
[data-design="editorial"] .searchbox-input {
  background: #f0f0f0;
  font-family: var(--sans);
  font-style: normal;
}
[data-design="editorial"] .searchbox-input::placeholder {
  color: #5c5c5c;
  font-style: normal;
  letter-spacing: 0.02em;
}
[data-design="editorial"] .searchbox-count {
  background: #111111;
  letter-spacing: 0.02em;
}
[data-design="editorial"] .searchbox-go {
  background: var(--flame);
}
[data-design="editorial"] .searchbox-go:hover { background: #111111; }


/* ==========================================================================
   THE RECIPE PAGE
   ==========================================================================

   The browse view was drawn first and built first; this is the same palette
   and the same face applied to the page that was already there. It is not a
   rebuild: the two columns, the sticky mise column, the step grain toggle and
   the focus link are all the app's, and what changes is type, rule and
   colour. Where the drawing asks for something the page does not have - the
   prep/cook/total row, the step numbers as boxes - it is noted rather than
   invented, because that is a template change and lands in both themes.
   -------------------------------------------------------------------------- */

/* The title takes the display face and the drawing's weight. */
/* No rule under the title block, at any width: FOCUS MODE comes next, and a
   rule above a solid red bar was a line drawn above a line. Gabe, 2026-09-24:
   "lose the rule above the focus btn". */
[data-design="editorial"] header.title-block { border-bottom: 0; }

[data-design="editorial"] .title-block h1,
[data-design="editorial"] .title-block h1.is-editing {
  font-family: var(--sans);
  font-weight: 800;
  letter-spacing: -0.035em;
  line-height: 0.97;
}

/* The kicker is the cuisine line, and it reads like the card's. */
[data-design="editorial"] .kicker {
  font-family: var(--sans);
  font-size: 0.6875rem;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--flame);
}

/* The standfirst stays a paragraph rather than becoming italic serif under a
   sans heading, which is what it read as before. */
[data-design="editorial"] .desc {
  font-family: var(--sans);
  font-style: normal;
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--soft);
}

[data-design="editorial"] .source,
[data-design="editorial"] .meta-item,
[data-design="editorial"] .made,
[data-design="editorial"] .from {
  font-family: var(--sans);
  letter-spacing: 0.01em;
}
[data-design="editorial"] .source-rating { color: var(--flame); }

/* FOCUS MODE: the one filled bar on the page, full width, as drawn. Its
   height is named because the title block keeps that much room free under
   itself (the two share a grid cell - see the layout further down). */
:root[data-design="editorial"] { --cook-it-h: 50px; }
[data-design="editorial"] .cook-it {
  display: block;
  width: 100%;
  border-radius: 0;
  border: 0;
  background: var(--flame);
  color: #fff;
  font-family: var(--sans);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  text-align: center;
}
[data-design="editorial"] .cook-it:hover { background: var(--charcoal); }

/* Section rules: heavy over a heading, hairline between rows. */
[data-design="editorial"] .instructions-head,
[data-design="editorial"] .ingredients-head {
  font-family: var(--sans);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
}
[data-design="editorial"] .component-name,
[data-design="editorial"] .component-name-echo {
  font-family: var(--sans);
  font-weight: 800;
  letter-spacing: -0.02em;
}

/* Steps and ingredients: hairlines, no rounded anything. */
[data-design="editorial"] .steps li,
[data-design="editorial"] .ingredients li { border-color: var(--line); }
[data-design="editorial"] .step-title,
[data-design="editorial"] .steps { font-family: var(--sans); }

/* The grain toggle reads as the drawing's DETAIL MODE / AS WRITTEN.

   600 rather than 700 on the pair, so the chosen one has somewhere to go: the
   base sheet says on is weight plus colour now instead of a rule under the
   word, and a design that set both of them bold would have thrown away half
   of that signal. The accent is the flame here, like every other accent on
   this page - `--accent` is the teal in the base tokens. */
[data-design="editorial"] .grain a,
[data-design="editorial"] .grain span {
  font-family: var(--sans);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  border-radius: 0;
}
[data-design="editorial"] .grain a.on { color: var(--flame); font-weight: 800; }

/* The last of the teal. `--accent` is the base sheet's teal and this design
   accents in the flame everywhere else, so "See all (5)" was the one link on a
   page of red that was not. Gabe, 2026-09-23: "Some teal snuck by in Editorial
   - See all (5)." */
[data-design="editorial"] .row-more { color: var(--flame); }
/* And "Any", which was the last of it. */

[data-design="editorial"] .viewseg:hover { color: var(--flame); }

/* Smaller rather than further from the cards. At three columns the bar sits
   directly over the first row of photographs and the toggle was the thing
   touching them: "This is tight but rather than padding, shrink the toggle."
   Padding would have pushed every card down the page to fix one control. */
[data-design="editorial"] .viewseg {
  font-family: var(--sans);
  font-size: 0.6rem;
  letter-spacing: 0.08em;
  padding: 5px 10px;
}
[data-design="editorial"] .viewicon { width: 9px; height: 9px; }

/* Nothing on this page keeps a rounded corner or a shadow. */
[data-design="editorial"] .shot-wrap,
[data-design="editorial"] .shot,
[data-design="editorial"] .scaler-step,
[data-design="editorial"] .scaler-input,
[data-design="editorial"] .scaler-go,
[data-design="editorial"] .note {
  border-radius: 0;
  box-shadow: none;
}
[data-design="editorial"] .scaler-step,
[data-design="editorial"] .scaler-go,
[data-design="editorial"] .scaler-reset {
  font-family: var(--sans);
  font-weight: 700;
}

/* No teal anywhere on this page either. The column headings and the section
   names are set from --caribbean in recipe.css; this palette has ink, grey
   and one red. */
[data-design="editorial"] .instructions-head,
[data-design="editorial"] .ingredients-head,
[data-design="editorial"] .mise-head {
  color: var(--muted);
}

/* Section names read as headings rather than as another caption.
   Gabe: "I think section names aren't showing" - they were, at 11.5px in the
   same grey as the column label above them, which is the same as not. Ink,
   heavier, and a hairline over each so the list divides visibly. */
[data-design="editorial"] .component-head,
[data-design="editorial"] .component-head .component-open {
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--charcoal);
  text-decoration: none;
}
/* **No rule over a section.** There was a 2px one on every section after the
   first, and the steps column drew it over the first as well (see below), so
   a column read heading-rule, rule, section, rule, section. Gabe, 2026-09-24:
   "waaaay to many <hr>". The column heading keeps its rule; a section is
   divided from the one above it by air and the weight of its name. */
[data-design="editorial"] .component-head {
  margin-top: 30px;
  padding-top: 0;
  border-top: 0;
}
/* The first section in a column has the column's own rule above it already. */
/* The first section in a column sits close under the column's own heading.
   "The first", not `:first-child` or `:first-of-type`: the steps column has a
   div before its first section, so both missed there - which is also how the
   steps column came to draw the rule the mise column dropped. */
[data-design="editorial"] .component:not(.component ~ .component) .component-head { margin-top: 12px; }
[data-design="editorial"] .component-head .component-open:hover { color: var(--flame); }

/* The teal was the edit affordance, not the heading.

   Every editable heading on the recipe page is wrapped in an `.edit-open`
   link, and recipe.css colours those --caribbean so the owner can see what
   is clickable. It reads as a heading colour, which is why MISE EN PLACE and
   STEPS came out teal in a palette that has no teal.

   Ink, and red on hover - the affordance survives, in this theme's two
   colours. */
/* The teal is on the heading itself, not on the link inside it - the link
   inherits. Both column headings, both swap panes. */
[data-design="editorial"] [data-swap] > h2,
[data-design="editorial"] .cols-head-mise > h2,
[data-design="editorial"] .instructions-head > h2,
[data-design="editorial"] .instructions-head,
[data-design="editorial"] [data-swap] > h2 > .edit-open {
  color: var(--muted);
}
[data-design="editorial"] .edit-open,
[data-design="editorial"] .note-add,
[data-design="editorial"] .delete-way,
[data-design="editorial"] .edit-way a,
[data-design="editorial"] .section-new {
  color: inherit;
}
[data-design="editorial"] .edit-open:hover,
[data-design="editorial"] .note-add:hover,
[data-design="editorial"] .delete-way:hover,
[data-design="editorial"] .edit-way a:hover,
[data-design="editorial"] .section-new:hover { color: var(--flame); }
[data-design="editorial"] .edit-open-hint { color: var(--muted); }
/* "Clear all check marks" is a quiet control like the ones above: grey at
   rest, no rule under it, red on the way in. It was wearing the kitchen's
   teal on hover over an underline. Gabe, 2026-09-25: "found some teal and
   lose the underline". */
[data-design="editorial"] .gather-clear button { border-bottom: 0; padding-bottom: 0; color: var(--muted); }
[data-design="editorial"] .gather-clear button:hover { color: var(--flame); }

/* ------------------------------------------------------- the two columns --

   The drawing puts the photograph and the mise down the left and the title,
   the standfirst, FOCUS MODE and the steps down the right. The page stacks
   them: photograph full width, then the title, then a two-column body.

   display: contents on the wrappers, so their children become items of one
   grid and can be placed anywhere in it - the same trick the cards use, and
   for the same reason: a stylesheet cannot move an element to a new parent,
   but it can stop a parent from drawing a box. */
@media (min-width: 900px) {
  /* The room the two columns need.

     Gabe, 21 September: "I think editorial needs to go full width or at least
     use narrower margins." The handoff's content column is 1180px, which is
     what `--wide` already is - so the width was never coming from the tokens.
     It was `.wrap`'s own 760px, and that number is the kitchen theme's: a
     serif measure, about 66 characters of Vollkorn, which is the right answer
     for one column of prose and the wrong one for two columns of sans with a
     photograph carrying the left.

     So it is `--measure` that moves, not `.wrap` and not either page - the
     recipe page is the only thing in the app on a plain `.wrap`, everything
     else already asks for `.wrap.wide`.

     Inside the 900px query on purpose. Below it the layout is one column
     again, and one column at 1180 would be a longer line than the kitchen
     theme ever allows - the width is here to be *used* by the second column,
     not to be had for its own sake. */
  /* 1180, not `--wide`. The two were the same number until `--wide` grew to
     1468 to let the cards reach their full size - which is a decision about
     the card grid, and the reading page is not a card grid. This is the width
     the two-column recipe page was drawn at and settled at. */
  :root[data-design="editorial"] { --measure: 1180px; }

  [data-design="editorial"] .wrap:has(.body-grid) {
    display: grid;
    grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
    /* The row gap is what holds STEPS off FOCUS MODE now. It used to be a
       margin on the button, back when the button had a row to itself; with
       the button hung on the bottom of the photograph's row, a margin there
       would only lift it off the photograph's edge - which is the one line
       it is meant to meet. */
    gap: 26px 44px;
    align-items: start;
  }
  /* **`.body-grid` stays a real grid, and that is a fix rather than a
     detail.** It was `display: contents` in the first two-column pass, which
     flattened the mise and the steps into `.wrap`'s grid so each could be
     placed by hand. It also flattened away the box that *bounds the sticky
     mise*: with the mise an item of `.wrap`, its containing block covered the
     note and the source underneath as well, so scrolling to the foot of a
     recipe whose steps are much longer than its ingredients slid the
     ingredient list straight over the note. Measured on Cioppino at 1280:
     the mise ran to 3422 where the steps ended at 3165, and the note starts
     at 3231.

     `.body-grid` already is a grid in recipe.css - two columns from 640px -
     so this only restates the tracks. The mise now stops where the steps
     stop, which is what "the ingredients follow you down the steps" always
     meant.

     The tracks are stated twice, here and on `.wrap`, and they have to stay
     identical: the photograph above sits in `.wrap`'s first column and the
     mise below sits in this one, and the two columns being different widths
     would be visible as a step in the left edge. */
  [data-design="editorial"] .body-grid {
    grid-column: 1 / -1;
    grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
    column-gap: 44px;
    row-gap: 0;
    margin-top: 0;
    align-items: start;
  }

  /* Left: the photograph, then the mise, which keeps its own sticky. */
  [data-design="editorial"] .shot-wrap { grid-column: 1; grid-row: 1; }
  [data-design="editorial"] [data-swap="ingredients"] { grid-column: 1; }

  /* Right: the title at the top, FOCUS MODE at the foot, the steps below.

     Every row is named. .cook-it is a sibling of the two wrappers rather
     than a child of either, so left to auto-placement it took a full-width
     row of its own between the title and everything below it - the button
     ended up under the photograph with the steps pushed past it.

     **The title and FOCUS MODE share row 1 and pull to opposite ends of it.**
     Row 1 is as tall as the photograph, which is much taller than a title,
     and giving the button a row of its own left the space between them empty
     - 166px of it, and 304px once the page was widened to 1180 and the
     photograph grew with the column. A gap that grows when the page does is
     not a gap, it is two things that were never tied to anything.

     Tying them fixes it without a wrapper: the title hangs from the top of
     the row, FOCUS MODE sits on the bottom of it, and the bottom of that row
     is the bottom of the photograph. So the button lines up with the
     photograph's lower edge, and the steps and the mise both start on that
     same line - which is the alignment the drawing has, arrived at from the
     other side.

     Two items in one cell is deliberate. One is `align-self: start` and the
     other `align-self: end`. **They did collide**, which this comment used to
     say they could not: the row is sized by the photograph only while the
     title is the shorter of the two, and a long publisher description made it
     the taller - the button then sat on the Total and Your rating values
     (Gabe's screenshot, 2026-09-26, an NYT salad). So the title keeps the
     button's height, and a gap, free under itself: when the photograph is
     taller that room is inside the row anyway, and when the title is taller
     the row grows by it and the button lands in it. */
  [data-design="editorial"] .title-block { grid-column: 2; grid-row: 1; margin-top: 0; align-self: start; padding-bottom: calc(var(--cook-it-h) + 22px); }
  [data-design="editorial"] .cook-it { grid-column: 2; grid-row: 1; align-self: end; margin: 0; min-height: var(--cook-it-h); box-sizing: border-box; }

  /* In edit mode the Save bar takes row 1, above the photograph and the title,
     and they move down one. The photograph and the title are placed by row
     number, so without this the bar was auto-placed into the first free row -
     under both of them. */
  [data-design="editorial"] .wrap:has(> .edit-mode-bar.is-top) > .edit-mode-bar.is-top { grid-row: 1; }
  [data-design="editorial"] .wrap:has(> .edit-mode-bar.is-top) > .shot-wrap,
  [data-design="editorial"] .wrap:has(> .edit-mode-bar.is-top) > .title-block { grid-row: 2; }

  /* Level with each other, under the photograph. Rows inside `.body-grid`
     now, so they are placed by column alone. */
  [data-design="editorial"] [data-swap="steps"] { grid-column: 2; grid-row: auto; }
  [data-design="editorial"] [data-swap="ingredients"] { grid-column: 1; grid-row: auto; }

  /* Everything after the two columns - the note, the source line, a notice,
     the delete panel - spans the width below them rather than landing in a
     column by accident. */
  [data-design="editorial"] .wrap:has(.body-grid) > *:not(.shot-wrap):not(.title-block):not(.cook-it):not(.body-grid):not(.edit-mode-bar.is-top) {
    grid-column: 1 / -1;
    grid-row: auto;
  }

  /* The note and the source are below the two columns, not beside them. They
     were already, and this is the rule that has to keep being true: the mise
     is sticky, and anything sharing a row with it gets walked over. */
}

/* The last teal on the page: a ticked ingredient and the gather control.
   The drawing strikes a ticked line through and greys it, which is what
   these already do - only the colour was the app's accent rather than this
   palette's. */
[data-design="editorial"] .made,
[data-design="editorial"] .made *,
[data-design="editorial"] .gather,
[data-design="editorial"] .gather * { color: var(--muted); }
/* recipe.css says `.mise li.made`, which outranks `.made` above, so a made
   line kept the accent - teal, then red. Said at its own weight. */
[data-design="editorial"] .mise li.made { color: var(--muted); }
[data-design="editorial"] .mise li.made::before { background: var(--muted); }
[data-design="editorial"] .gather:hover,
[data-design="editorial"] .gather.is-picking { color: var(--flame); }
/* **A number scaling moved stays red inside a checklist line.** The grey
   above reached `.moved` too, so in this design no scaled amount was red -
   not in the mise column, not in a step's Have ready. Gabe, 2026-10-01:
   "ingredients under steps (the in the pan list) should be red when
   scaled". A ticked line goes grey whole, its numbers with it. */
[data-design="editorial"] .gather .moved { color: var(--flame); }
[data-design="editorial"] .gather input[type=checkbox]:checked + span .moved { color: var(--muted); }

/* The box itself, drawn rather than native - Gabe, 2026-09-25: "can we have
   custom square boxes? lets try red." The native box kept the platform's
   rounded corner and filled with the kitchen teal, the one colour and the one
   shape this design has none of. Square, a hairline at rest, solid Flame with
   a white tick when checked. The tick is a background image rather than a
   ::before, which Firefox does not draw on an input. Size and the baseline
   offset are the base sheet's, untouched. */
[data-design="editorial"] .gather input[type=checkbox] {
  -webkit-appearance: none;
  appearance: none;
  border: 1.5px solid var(--muted);
  border-radius: 0;
  background: transparent;
}
[data-design="editorial"] .gather input[type=checkbox]:checked {
  border-color: var(--flame);
  background: var(--flame) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 6.2l2.3 2.3 4.7-5' fill='none' stroke='white' stroke-width='1.8' stroke-linecap='square'/%3E%3C/svg%3E") center / 100% no-repeat;
}
[data-design="editorial"] .gather input[type=checkbox]:focus-visible {
  outline: 2px solid var(--flame);
  outline-offset: 2px;
}

/* A scaled amount is marked in the same red as everything else that is on. */
[data-design="editorial"] .scaler.is-on .scaler-input { color: var(--flame); }

/* ------------------------------------------------ the left column, fixed --

   Three things were wrong in the first two-column pass, all visible in one
   screenshot.

   **The photograph left a hole.** It is 3:2 and short; the title, standfirst
   and times beside it are tall, so the grid row was as deep as the taller of
   the two and the mise began a long way below the picture. The drawing has a
   tall photograph running the depth of the title block, which is also the
   fix: stretch it and let it crop. */
@media (min-width: 900px) {
  /* **Square, not stretched to the column.**

     The drawing has a tall 4:5 photograph running the depth of the title
     block, and stretching to fill the row was the first pass at it. Gabe,
     2026-09-21: "I know Design had the vertical photo but in most cases I
     think it'll make excessive whitespace. Square would be cool as long as it
     stays v. bold." He is right about the whitespace - the right column is a
     title, a standfirst and three times, and a photograph tall enough to run
     past all of it leaves the column empty between the times and FOCUS MODE.

     A square is still the biggest thing on the page - 426px of a 1180px
     measure - and it sets the row height rather than being set by it, so the
     hole closes from both ends. `object-fit: cover` keeps it bold: the
     photograph fills the square and crops, rather than letterboxing into it. */
  [data-design="editorial"] .shot-wrap { align-self: start; min-height: 0; }
  [data-design="editorial"] .shot-wrap .shot,
  [data-design="editorial"] .shot-wrap .shot-drawn {
    aspect-ratio: 1 / 1;
    width: 100%;
    height: auto;
    object-fit: cover;
    margin-top: 0;
  }
}

/* Nothing sits on the photograph, which is what the drawing asks for - "no
   overlays on the image" - and what the cards gave up the same morning. The
   rating is on the times row and is red there, which is where the drawing
   puts YOUR RATING in everything but the exact position. */
[data-design="editorial"] .shot-wrap { position: relative; }
[data-design="editorial"] .shot-wrap::after { display: none; }
[data-design="editorial"] .meta-rating { color: var(--flame); }
/* Stars not given are hollow red, not a paler fill (Gabe, 2026-09-27:
   "make unfilled stars hollow red"). The glyph's outline, stroked; a given
   star fills. The hover preview fills the same way. */
[data-design="editorial"] .meta-rating .dim { color: transparent; -webkit-text-stroke: 1.2px var(--flame); }
[data-design="editorial"] .meta-rating.is-settable button {
  opacity: 1;
  color: transparent;
  -webkit-text-stroke: 1.2px var(--flame);
}
[data-design="editorial"] .meta-rating.is-settable button.on { color: var(--flame); }
@media (hover: hover) {
  [data-design="editorial"] .meta-rating.is-settable:not(.is-just-set):hover button { opacity: 1; color: transparent; }
  [data-design="editorial"] .meta-rating.is-settable:not(.is-just-set) button:hover,
  [data-design="editorial"] .meta-rating.is-settable:not(.is-just-set) button:hover ~ button { color: var(--flame); }
}

/* **"New section" read as a section name.** It is the owner's add control and
   it was set in the same caps, weight and rule as the real headings above the
   lists it adds to - so a recipe with one section appeared to have two, the
   second called NEW SECTION. It is a link, so it reads as one. */
[data-design="editorial"] .section-new {
  margin: 14px 0 0;
  padding: 0;
  border: 0;
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  text-transform: none;
  color: var(--muted);
}
[data-design="editorial"] .section-new a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
[data-design="editorial"] .section-new a:hover { color: var(--flame); }

/* The column headings outrank the section names under them, which they did
   not: MISE EN PLACE was lighter and greyer than PREP beneath it. */
[data-design="editorial"] [data-swap] > h2,
[data-design="editorial"] .cols-head-mise > h2,
[data-design="editorial"] .instructions-head > h2 {
  font-size: 0.8125rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  color: var(--charcoal);
}

/* The air under FOCUS MODE used to be a 26px margin on the button, put there
   when it was butting straight into STEPS. It is the grid's row gap now - the
   button and the steps are in different rows, and a margin on the button
   would lift it off the photograph's bottom edge, which is the one line it is
   meant to meet. See the two-column block above. */

/* ------------------------------------------------------ focus mode --------

   The last view to get the drawing's face, and the reason it was top of the
   list: browse and the recipe page were done, and testers were looking at a
   half-themed app.

   Everything here is type, rule and colour. The bars, the labels inside them,
   the close and the stepper are all in the markup already and all work in the
   kitchen theme - this moves none of them and drops none of them.

   Two places where the drawing is not followed, both on purpose:

   * **Both labels read top to bottom.** The drawing rotates PREVIOUS 180° so
     it reads upward and leaves NEXT reading down. recipe.css has carried a
     note since the bars were built - "two directions would be a puzzle, not a
     symmetry" - and that is a legibility decision the picture did not know it
     was overruling. Kept.
   * **The grain toggle and the size stepper stay.** The drawing's focus view
     has neither, because the drawing does not know this app has them. LOCKED
     says a theme may make a control quieter and never absent, so they are set
     small here rather than removed. */

/* 74px bars, from the handoff, in place of the kitchen theme's 108. The page
   padding has to move with them or the reading column runs underneath. */
@media (min-width: 900px) {
  [data-design="editorial"] .cookview { padding-left: 94px; padding-right: 94px; }
  [data-design="editorial"] .cookview-go { width: 74px; }
  [data-design="editorial"] .cookview-go.prev {
    width: calc(74px + var(--sa-l, env(safe-area-inset-left)));
  }
  [data-design="editorial"] .cookview-go.next {
    width: calc(74px + var(--sa-r, env(safe-area-inset-right)));
  }
}

/* Square, and the hairline is on the inside edge only - the outside edge is
   the screen. The kitchen theme rounds the inner corners because its bars sit
   on cream and read as cards; these are the page. */
[data-design="editorial"] .cookview-go {
  border: 0;
  border-radius: 0;
  background: var(--cream);
  color: var(--charcoal);
}
[data-design="editorial"] .cookview-go.prev { border-right: 1px solid var(--line); }
[data-design="editorial"] .cookview-go.prev:hover { background: #f0f0f0; }

/* NEXT is the red one. It is the thing you press forty times in a cook, and
   in the drawing it is the only flooded colour on the screen. */
[data-design="editorial"] .cookview-go.next {
  background: var(--flame);
  border: 0;
  color: var(--cream);
}
[data-design="editorial"] .cookview-go.next:hover { background: var(--charcoal); }

[data-design="editorial"] .cookview-go span {
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.24em;
}

/* The row above the step: the name at one end, the controls and the way out
   at the other, on one baseline under a hairline. */
[data-design="editorial"] .cookview-top {
  align-items: baseline;
  border-bottom: 1px solid var(--line);
  padding-bottom: 12px;
}
[data-design="editorial"] .cookview-title {
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
}
/* No rule under the name. It had one in the kitchen theme to keep it from
   reading as a caption; here the header's own hairline does that job, and two
   rules 12px apart is the mistake that note was written about. */
[data-design="editorial"] .cookview-name { border-bottom: 0; padding-bottom: 0; }

/* CLOSE, top right, in the drawing's type. */
[data-design="editorial"] .cookview-close {
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  color: var(--muted);
}
[data-design="editorial"] .cookview-close:hover { color: var(--flame); }

/* The grain and the stepper, quieted rather than removed. */
[data-design="editorial"] .cook-views {
  font-family: var(--sans);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
[data-design="editorial"] .cook-views a.on {
  color: var(--charcoal);
  border-bottom: 2px solid var(--flame);
}
[data-design="editorial"] .size-step {
  border-radius: 0;
  border-color: #c9c9c9;
  font-family: var(--sans);
  font-weight: 700;
}
[data-design="editorial"] .size-step:hover:not(:disabled) {
  border-color: var(--charcoal);
  background: #f0f0f0;
  color: var(--charcoal);
}
[data-design="editorial"] .size-fill[aria-pressed="true"],
[data-design="editorial"] .size-fill[aria-pressed="true"]:hover:not(:disabled) {
  border-color: var(--flame);
  background: var(--flame);
  color: #fff;
}

/* Where you are. Tabular figures because the number is the one thing on this
   line that changes, and a step counter that shifts under its own label is
   the sort of movement this whole view exists to avoid. */
[data-design="editorial"] .cookview-where {
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* The step itself. The size is `--cook-size` and stays the cook's - the
   stepper writes it inline and nothing here may outrank that. What the
   drawing sets is the face, the weight and how tight the lines run. */
[data-design="editorial"] .cook-body {
  font-family: var(--sans);
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: -0.025em;
}

/* Have ready, and the preview of what is coming. Both are sections under a
   rule in the drawing, with the heading letterspaced above them. */
[data-design="editorial"] .cookview-ready .mise h2,
[data-design="editorial"] .cookview-next .cookview-where {
  font-family: var(--sans);
  font-size: 0.8125rem;
  font-weight: 800;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
}
[data-design="editorial"] .cookview-ready .mise,
[data-design="editorial"] .cookview-next {
  border-top: 1px solid var(--line);
  padding-top: 12px;
}
/* One rule, not two: the section draws its own line above, and the heading
   arrives from the base sheet carrying another 13px below it. Gabe,
   2026-09-25: "lose the double horizontal line". */
[data-design="editorial"] .cookview-ready .mise h2 { border-top: 0; padding-top: 0; }
/* **Square step numbers, square pieces.** Gabe, 2026-09-24, looking at the
   magnifier in its square button: "I think we should go to square sub/step
   indicators in recipes. I like you using the logo dot for current step but
   this looks more Editorial."

   The circle is the mark's filled dot doing the same job on the page, and it
   stays that in the kitchen theme. This palette has no curves in it anywhere
   else - not the chips, not the count block, not the buttons - and one round
   number thirty times down a recipe is the shape that does not belong. */
[data-design="editorial"] ol.steps > li > .step-no { border-radius: 0; }
[data-design="editorial"] ol.steps > li > .step-no.is-piece { border-radius: 0; }
/* A whole step's number is outlined like a piece's, not filled. A solid
   square on step 4 beside outlined 1.1-1.3 read as a different KIND of
   thing - Gabe, 2026-09-25: "lose the solid square on steps that didn't get
   broken down. Confusing as is." The only filled marks left in the list are
   where you ARE (the logo dot) and where you have BEEN (muted). Editorial
   only: the kitchen's flame circles are its own idiom, and there every
   number is filled so nothing stands out wrongly. */
[data-design="editorial"] ol.steps > li:not(.current):not(.behind) > .step-no {
  background: none;
  color: var(--flame);
  border: 1px solid var(--flame);
  line-height: 28px;
}

/* **The one you are standing on is the logo's dot.** Gabe, 2026-09-24: "lets
   make the current step indicator the circle from the logo." Square numbers
   down the page and a round one where you are - the mark says "here" on the
   masthead and says it again in the list, which is the job the circle was
   doing everywhere before this theme squared the rest of them off.

   999px rather than 50%: a piece carries a dotted label and is a capsule when
   the label is long, so this rounds the ends it has rather than forcing a
   circle onto a box that is not square. */
[data-design="editorial"] ol.steps > li.current > .step-no,
[data-design="editorial"] ol.steps > li.current > .step-no.is-piece {
  border-radius: 999px;
}
/* And the dot is the dot: an unbroken step was printing its number inside
   it, which made it a numbered badge rather than the mark. Gabe,
   2026-09-25: "unbroken steps put their number in the dot. don't want."
   The number is still in the row's own aria-label, and a piece keeps its
   dotted label - "3.1" in a capsule is a place, not a badge. */
[data-design="editorial"] ol.steps > li.current > .step-no:not(.is-piece) { color: transparent; }

/* No teal. `--accent` is the kitchen theme's and this palette has two colours;
   the chevron stands in for the red NEXT rail, so it is the rail's red. */
[data-design="editorial"] .cookview-next-arrow { stroke: var(--flame); }
[data-design="editorial"] .cookview-next:focus-visible { outline-color: var(--flame); }

/* The scale buttons, square and heavier, as the drawing has them - and the
   red only on the way in, which is the hover this theme uses everywhere. */
[data-design="editorial"] .scaler-factor {
  border-radius: 0;
  border-color: #c9c9c9;
  font-family: var(--sans);
  font-weight: 700;
}
[data-design="editorial"] .scaler-factor:hover {
  border-color: var(--charcoal);
  background: #f0f0f0;
  color: var(--charcoal);
  box-shadow: inset 0 -3px 0 var(--flame);
}
[data-design="editorial"] .scaler-factor.is-on,
[data-design="editorial"] .scaler-factor.is-on:hover {
  background: var(--charcoal);
  border-color: var(--charcoal);
  color: var(--cream);
  box-shadow: none;
}

[data-design="editorial"] .colophon { font-family: var(--sans); }

/* ------------------------------------------------- fewer horizontal rules --

   Gabe, 2026-09-21, on the head of the steps column: "too many horizontal
   rules." Three of them inside 170px - a hairline under STEPS, the underline
   on New section, and the 2px rule over the first section name - and the mise
   column did the same under MISE EN PLACE.

   The drawing has one rule there and it is the heavy one. So the column head
   takes the 2px black rule the drawing gives it, and **the first section in
   each column drops its own**, because that rule exists to separate a section
   from the one above it and the first section has nothing above it but the
   head. Every later section keeps its rule, which is the only place it is
   doing work.

   `.section-new` keeps its underline: it is a link, and that is the
   affordance saying so rather than a rule across the column. */
[data-design="editorial"] .instructions-head,
[data-design="editorial"] [data-swap="ingredients"] > h2,
[data-design="editorial"] .cols-head-mise > h2 {
  border-bottom: 2px solid var(--charcoal);
}

[data-design="editorial"] [data-swap] .component:first-of-type > .component-head,
[data-design="editorial"] [data-swap] .component:first-of-type > .component-open {
  border-top: 0;
  padding-top: 0;
}

/* The first-paint fallback for this design's filter row, before nav.js
   measures it. 51px is the one-line cells; the kitchen design's pills are 66.
   Neither number is load-bearing once the script has run. */
:root[data-design="editorial"] { --chiprow-h: 51px; }

/* Hard against the right edge of the cell, in a slot wide enough for the
   widest thing it can hold - "+1,364" - so the digits line up down the row
   however many there are. `space-between` puts it there; the slot is what
   stops it drifting left when the number is short. */
[data-design="editorial"] .chip .chip-count {
  min-width: 3.5ch;
  text-align: right;
}

/* The count reads in this design's own face, beside the layout toggle. */
[data-design="editorial"] .resultcount {
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--muted);
}
/* In the bar it stands beside a 2.1rem heading, so it gets a size that can.
   Gabe, 2026-09-25: "bigger". */
[data-design="editorial"] .row-head-bare .resultcount { font-size: 1rem; }

/* A little bigger, and the wordmark with it - the mark was 52px against a
   filter row of 45 and a wordmark of two short lines, and read as the smaller
   half of its own lockup.

   Then 72 on the drawing - "Logo sized like this", 2026-09-22, with a picture
   of the handoff masthead - and back to 60 an hour later, because **the wrong
   half went up**. Measured off that picture rather than judged by eye:

     the 2x2 ring block   54.5px wide in the drawing    66.2 at a 72px mark
     "The Focus"         130px                         115.2 at 1.55rem

   The drawing's rings are *smaller* than ours and its wordmark is *bigger*.
   Scaling the whole lockup made the rings, which were already too big, worse -
   and left the wordmark short. So the mark goes back where it was and the
   wordmark takes the increase alone: at 60 and 1.75rem the word is 2.36 times
   the ring block, against the drawing's 2.39.

   `--topbar-h` is measured at runtime by nav.js rather than written down, so
   the bar and everything hung off it - the chip row, the filter panel's top
   edge - follow this number without being told. */
:root[data-design="editorial"] { --mark-size: 60px; }
[data-design="editorial"] .topbar-mark { width: var(--mark-size); height: var(--mark-size); }
[data-design="editorial"] .topbar-name { font-size: 1.75rem; }

/* The logo stands on the gutter by its ink, not by its box.

   Gabe, 2026-09-22: "align left edge of logo with left edge of photo." They
   already agreed to the pixel *as elements* - both at 48 - and the rings still
   started 2.9px to the right of the photograph, which is what he could see.

   The gap is the mark's blur padding. `.topbar-mark > svg` is `inset: -50%;
   width: 200%`, so the drawing is twice the box and centred on it, and the
   viewBox is `-50 -50 200 200` with the first ring's left edge at x=4. That
   puts the ink 4% of the mark's width inside the box - 2.88px at 72 - so the
   pull is exactly that, and it stays right if the mark is ever resized.

   On `.topbar-brand` rather than the mark, so the wordmark travels with it and
   the lockup keeps its own spacing. */
[data-design="editorial"] .topbar-brand {
  margin-left: calc(var(--mark-size) * -0.04);
  /* Tighter, on his preference - 15px of air between the rings and the T was
     reading as two marks side by side rather than one lockup. The base gap is
     14px and the rings carry 4% of their own width as blur padding on the
     right as well as the left, so the pull is the gap the eye sees rather than
     the gap the boxes have. */
  gap: 7px;
}

/* The panel's top edge meets the bottom of the chips. It hung 10px below them,
   which read as a gap rather than as the row opening downwards - "scooch the
   filter panel up so the top edge kisses the bottom of the chips". */
:root[data-design="editorial"] {
  --panel-top: var(--band-bottom);
}

/* Red, not teal, and it is the one thing in the head you can press. */
[data-design="editorial"] .fp-clearall { color: var(--flame); }

/* The head sits down against its rule rather than floating above it. */
[data-design="editorial"] .filterpanel { padding-top: 20px; }

/* The review page's name by the lockup: flame on a charcoal rule, as the
   tools page sets "Tools" in this design. */
[data-design="editorial"] .topbar-label { color: var(--flame); border-left-color: var(--charcoal); }

/* ==========================================================================
   THE RECIPE PAGE, REDESIGNED - punch 93, 2026-09-27
   ==========================================================================
   Agreed with Gabe over three rounds in Claude Design ("Recipe View.dc.html",
   round 3), and saved before it as the git tag recipe-page-v1. Top to bottom,
   one column: the photograph as a full-width band with the title on it and
   your rating in its corner; the fact row, the publisher's rating among
   the facts; the standfirst; "Cook from"; then the mise and the steps side by side as
   before. He hates form over function, so every piece here does a job: the
   title on white blocks reads on any photograph with nothing laid over the
   image, the amount column is for reading across a kitchen. A progress track
   and fact cells counting ingredients and steps were built and cut the same
   day on that ground.

   Placed after everything above so it wins on order where it ties; the rules
   above for the old two-column header stay in place for the kitchen-shaped
   parts they still describe. The parts these rules show are hidden in the
   kitchen design by recipe.css. */

:root[data-design="editorial"] {
  /* The no-photograph colour: one colour, not each recipe's own. Gabe: "I
     never subscribed to the whole card color thing. Pick one, it can be a new
     accent color." A deep herb green, beside the red and the ink. */
  --herb: #2E4A3B;
}

/* No-photograph cards on the index take the same one colour. */
[data-design="editorial"] .card-shot-drawn { background: var(--herb); }

/* One column at the top, at every width. */
[data-design="editorial"] .wrap:has(.body-grid) {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0;
  align-items: start;
}
[data-design="editorial"] .wrap:has(.body-grid) > .title-block { display: contents; }
[data-design="editorial"] .wrap:has(.body-grid) > .cook-it { display: none; }

/* The band, and the title on it: both in row 1, the title at its foot.
   **Design 11a** (Gabe, 2026-10-24): the photograph runs the page's full
   width, gutters and all - the 1180px of the top bar, edge to edge on
   anything narrower - 4:3 below desktop and 560px at it, never more than 70%
   of the window, so a landscape phone still sees where the facts begin.
   The FOCUS MODE tab sits on it (--band-r).
   Under 900px the page is 760 wide, and the band followed it: margins from
   760 to 899, then edge to edge again at 900 (Gabe, 2026-10-24: "the
   margins appear and then go full bleed, back and forth"). So under 900 it
   runs past the page's edges too (--bleed): edge to edge until the 1180
   fits, margins after, one way only. */
[data-design="editorial"] .wrap:has(.body-grid) {
  /* The window less its scrollbar, where it shows one: 100vw counts the
     scrollbar, and the band ran 8px under the tab (the script by the band
     sets --scrollbar). */
  --view: calc(100vw - var(--scrollbar, 0px));
  --side: max(0px, (var(--view) - var(--measure)) / 2);
  --bleed: var(--side);
  --band-l: calc(var(--gutter) + var(--bleed));
  --band-r: var(--band-l);
}
@media (min-width: 900px) {
  [data-design="editorial"] .wrap:has(.body-grid) { --bleed: 0px; }
}
[data-design="editorial"] .wrap:has(.body-grid) > .shot-wrap {
  grid-column: 1;
  grid-row: 1;
  margin: 0 calc(-1 * var(--band-r)) 0 calc(-1 * var(--band-l));
  /* A width of its own: left to the grid, the height cap narrowed the 4:3
     box instead of cropping it - 350px of photograph on a landscape phone. */
  width: calc(100% + var(--band-l) + var(--band-r));
  aspect-ratio: 4 / 3;
  max-height: 70vh;
  overflow: hidden;
}
@media (min-width: 1024px) {
  [data-design="editorial"] .wrap:has(.body-grid) > .shot-wrap {
    aspect-ratio: auto;
    height: min(560px, 70vh);
  }
}
/* The photograph sits in a link now, which opens it over the page (Gabe,
   2026-09-28) - the link fills the band so the photograph inside it can. */
[data-design="editorial"] .wrap:has(.body-grid) > .shot-wrap > .shot-open { height: 100%; }
[data-design="editorial"] .wrap:has(.body-grid) > .shot-wrap > .shot,
[data-design="editorial"] .wrap:has(.body-grid) > .shot-wrap > .shot-open > .shot {
  display: block;
  /* An older rule gives the photograph a top margin under 900px; inside the
     band that was a white strip over the image and 24px cut off its foot. */
  margin: 0;
  width: 100%;
  height: 100%;
  max-height: none;
  aspect-ratio: auto;
  object-fit: cover;
  object-position: 50% 45%;
}
[data-design="editorial"] .wrap:has(.body-grid) > .shot-drawn-wrap { background: var(--herb); }
[data-design="editorial"] .wrap:has(.body-grid) > .shot-drawn-wrap > .shot-drawn {
  height: 100%;
  background: transparent;
  aspect-ratio: auto;
}
[data-design="editorial"] .wrap:has(.body-grid) > .title-block > .title-hero {
  grid-column: 1;
  grid-row: 1;
  align-self: end;
  justify-self: start;
  z-index: 1;
  /* From the photograph's left edge, the words on the logo's line; a strip
     of photograph shows under the last slab. */
  max-width: calc(100% - var(--gutter));
  margin: 0 0 var(--gutter) calc(-1 * var(--band-l));
  padding: 0;
  /* The space between the title and the side label is a character of the
     box, and at 80px it would be a 20px gap of photograph. */
  font-size: 0;
  text-wrap: balance;
}
@media (min-width: 1024px) {
  [data-design="editorial"] .wrap:has(.body-grid) > .title-block > .title-hero {
    margin-bottom: 56px;
    text-wrap: wrap;
  }
}
/* In edit mode the title is a field, and a field does not belong on a
   photograph: it drops under the band, before the facts. */
[data-design="editorial"] .wrap:has(.body-grid) > .title-block > .title-hero:has(.is-editing) {
  grid-row: auto;
  align-self: start;
  justify-self: stretch;
  max-width: none;
  margin: 18px 0 0;
  font-size: 1rem;
}
[data-design="editorial"] .wrap:has(> .edit-mode-bar.is-top) > .title-block > .title-hero:not(:has(.is-editing)) { grid-row: 2; }

/* Each line of the title on its own white slab, cut to its words. 80px at
   desktop whatever the length - a long title takes more lines, not smaller
   type - and scaled to the window below it. */
[data-design="editorial"] .title-hero > h1:not(.is-editing) {
  display: inline;
  margin: 0;
  font-size: clamp(32px, min(7.4vw, 14vh), 80px);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.05em;
  color: var(--charcoal);
  background: #fff;
  padding: 2px 26px 10px var(--gutter);
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}
/* The words over every line's white. Each line is painted after the one
   above, and a slab is taller than the line spacing: the white of "Basil"
   covered the foot of the g in "Thighs" (Gabe, 2026-09-27). Positioned, the
   words paint after all the white. */
[data-design="editorial"] .title-hero > h1:not(.is-editing) > * { position: relative; }
[data-design="editorial"] .title-hero > h1 a { color: inherit; text-decoration: none; }
/* Below desktop a long title steps down a size. */
[data-design="editorial"] .title-hero.is-long > h1:not(.is-editing) { font-size: clamp(30px, min(6.2vw, 12vh), 80px); }
[data-design="editorial"] .title-hero.is-longer > h1:not(.is-editing) { font-size: clamp(28px, min(5vw, 10vh), 80px); }
/* A `//` typed in the title breaks the line here, at desktop only; below it
   the title wraps balanced and the break is a space. */
[data-design="editorial"] .title-hero .title-br { display: none; }
@media (min-width: 1024px) {
  [data-design="editorial"] .title-hero > h1:not(.is-editing),
  [data-design="editorial"] .title-hero.is-long > h1:not(.is-editing),
  [data-design="editorial"] .title-hero.is-longer > h1:not(.is-editing) { font-size: 80px; }
  [data-design="editorial"] .title-hero .title-br { display: inline; }
}
[data-design="editorial"] .title-hero > .kicker:not(.is-editing) { display: none; }
/* The cuisine: a red tab on the same white, over the title's first line, the
   kicker's place. Any length fits. It was turned 90° on the end of the last
   word for a day; a long name (Mediterranean) stood taller than the title
   (Gabe, 2026-09-27). 14px since 2026-09-28, up from 11 - "bump up the
   size of the cuisine on the recipe page"; the padding grew with it. */
/* Design 11a: its own slab over the title's, 15px, the tags the title does
   not already say ($heroTags), gone when that leaves none. */
[data-design="editorial"] .title-hero > .kicker-tab {
  display: table;
  position: relative;
  margin: 0;
  padding: 18px 20px 8px var(--gutter);
  background: #fff;
  color: var(--flame);
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 0.16em;
  line-height: 1;
  text-transform: uppercase;
  /* Its white carried on down behind the first line's, so no hairline of
     photograph shows between them at any title size; the title paints over
     it. */
  box-shadow: 0 16px 0 0 #fff;
}

/* Below the band, in this order whatever the markup's: facts, standfirst,
   the two columns, then what follows them. (The byline's order is for edit
   mode, where its fields show.) */
[data-design="editorial"] .wrap:has(.body-grid) > .title-block > .meta-row { order: 1; }
[data-design="editorial"] .wrap:has(.body-grid) > .title-block > .byline { order: 2; }
[data-design="editorial"] .wrap:has(.body-grid) > .title-block > .desc { order: 3; }
/* Edit mode's categories after the description, last before the columns. */
[data-design="editorial"] .wrap:has(.body-grid) > .title-block > .edit-cats { order: 4; }
[data-design="editorial"] .wrap:has(.body-grid) > .body-grid { order: 5; margin-top: 48px; }
[data-design="editorial"] .wrap:has(.body-grid) > .body-grid ~ * { order: 6; }
/* The publisher and their rating are a cell of the fact row, so the byline
   stands down; in edit mode its fields still show here. They were a line of
   their own for an afternoon - Gabe, 2026-09-27: "put the source and rating
   back in the info row". */
[data-design="editorial"] .wrap:has(.body-grid) > .title-block > .byline:not(.is-editing) { display: none; }

/* Your rating, cut into the photograph's top right on the same white as the
   title. The fact row's copy stands down. */
[data-design="editorial"] .wrap:has(.body-grid) > .title-block > .hero-rating {
  grid-column: 1;
  grid-row: 1;
  align-self: start;
  justify-self: end;
  z-index: 1;
  display: block;
  /* A gutter in from the photograph's right edge, wherever that stops. */
  margin: 0 calc(var(--gutter) - var(--band-r)) 0 0;
  padding: 12px 16px;
  background: #fff;
}
/* Design 11a: 20px stars, a tenth of an em apart. */
[data-design="editorial"] .hero-rating .meta-rating {
  font-size: 20px;
  line-height: 1;
  letter-spacing: 0.1em;
}
[data-design="editorial"] .hero-rating .meta-rating.is-settable { gap: 0.1em; letter-spacing: 0; }
[data-design="editorial"] .hero-rating .meta-rating.is-settable button {
  font-size: 20px;
  padding: 0;
}
[data-design="editorial"] .wrap:has(.hero-rating) .meta-row > .meta-item-rating { display: none; }

/* The fact row. */
[data-design="editorial"] .wrap:has(.body-grid) > .title-block > .meta-row {
  display: flex;
  flex-wrap: wrap;
  /* Every cell has its divider and its inset, and the row starts 19px to the
     left with that strip clipped - so whichever cell begins a line, the
     first or one that wrapped (the publisher, beside long times), sits flush
     with no rule before it. */
  margin: 0 0 0 -19px;
  clip-path: inset(0 0 0 19px);
  padding: 0;
  gap: 0;
  /* No rule above: a 5px bar along the photograph's foot ran into the
     title's white and broke round it (Gabe, 2026-09-27: "lose the thick
     line"). The photograph's edge is the line. */
  border-bottom: 1px solid var(--line);
}
/* Add to's list of plans hangs below the row (punch 150), so while it is
   open the clip lets go of the bottom and the right, and keeps the strip.
   The clip-path makes the row a stacking context of its own, so the list's
   z-index 40 only counted inside it - and the pinned heading bar below
   (recipe.css, .cols-head, z-index 6) painted over the list's left half
   (Gabe, 2026-10-03, screenshot). Open, the row rises above the bar. */
[data-design="editorial"] .wrap:has(.body-grid) > .title-block > .meta-row:has(.tray-pick[open]) {
  clip-path: inset(0 -100vmax -100vmax 19px);
  position: relative;
  z-index: 8;
}
[data-design="editorial"] .meta-row > .meta-item,
[data-design="editorial"] .meta-row > .meta-more {
  display: block;
  /* Each as wide as it needs, not a share of the row: two or three facts
     stretched across the page left a gulf between each label and the next. */
  flex: 0 1 auto;
  min-width: 0;
  margin: 0;
  padding: 10px 40px 12px 18px;
  border-left: 1px solid var(--line);
}
[data-design="editorial"] .meta-row > .meta-item-rating { order: 9; }
[data-design="editorial"] .meta-row > .meta-est { order: 10; flex-basis: 100%; margin: 0 0 8px 19px; }
[data-design="editorial"] .meta-row .meta-label {
  font-family: var(--sans);
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  line-height: 1.3;
  text-transform: uppercase;
  color: var(--muted);
}
[data-design="editorial"] .meta-row .meta-label a { color: inherit; text-decoration: none; }
[data-design="editorial"] .meta-row .meta-label a:hover { color: var(--flame); }
[data-design="editorial"] .meta-row .meta-value {
  margin-top: 4px;
  font-family: var(--sans);
  font-size: 1.5rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.15;
  color: var(--charcoal);
}
[data-design="editorial"] .meta-row .meta-small,
[data-design="editorial"] .meta-row .meta-none {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--muted);
}
[data-design="editorial"] .meta-item-source .card-source-rating { font: inherit; color: var(--charcoal); }
/* The open-the-original mark: the card's box-and-arrow, a step away from
   the name and a size up from the caps beside it, so it reads as its own
   control. Its own hover, in the red. */
[data-design="editorial"] .meta-row .meta-label a.meta-out {
  order: 0;
  width: 1.9em;
  height: 1.9em;
  margin: -0.45em -0.45em -0.45em 0.35em;
  color: var(--charcoal);
}
[data-design="editorial"] .meta-row .meta-out svg { width: 1.25em; height: 1.25em; stroke-width: 1.4; }
[data-design="editorial"] .meta-row .meta-label a.meta-out:hover { color: var(--flame); }
/* A long publisher name stays in its cell: the cell takes what the row has
   left, and the name shortens only when that is not enough - not dropping
   the cell to a line of its own ("Hunter Angler Gardener Cook" at 768px),
   and not cut short on a wide page. The rating under it never shortens. */
[data-design="editorial"] .meta-row > .meta-item-source { flex: 1 1 10em; }
[data-design="editorial"] .meta-item-source .meta-label { display: flex; min-width: 0; }
[data-design="editorial"] .meta-item-source .meta-label > a:first-child,
[data-design="editorial"] .meta-item-source .meta-label > :first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
[data-design="editorial"] .meta-item-source .meta-out { flex: none; }

/* The standfirst. */
[data-design="editorial"] .wrap:has(.body-grid) > .title-block > .desc {
  max-width: 62ch;
  margin: 22px 0 0;
  font-size: 1.02rem;
}

/* FOCUS MODE, a tab on the window's right edge, read bottom to top - Gabe's
   pick of three tried on 2026-09-27. Fixed: there from the first view to the
   last, and nothing moves for it. It was a button under the standfirst,
   which a cook reading step 3.4 had long scrolled past. */
[data-design="editorial"] .focus-tab {
  position: fixed;
  z-index: 40;
  right: 0;
  top: calc(50% - 90px);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6em;
  width: 44px;
  height: 180px;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  background: var(--flame);
  color: #fff;
  font-family: var(--sans);
  font-size: 0.6875rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  line-height: 1;
  text-transform: uppercase;
  text-decoration: none;
}
[data-design="editorial"] .focus-tab:hover { background: var(--charcoal); }
/* "Make enough margin that it doesnt obscure": the page keeps a strip clear
   for it - 44px of tab and 20 of air - wherever the margin beside the 1180px
   page is narrower than that. On a wide screen the margin already is. */
[data-design="editorial"] .wrap:has(> .focus-tab) {
  --tab-strip: max(48px, min(64px, calc(64px - (var(--view, 100vw) - 1180px) / 2)));
  padding-right: var(--tab-strip);
  /* With the tab there, the hero's photograph runs the same as without it,
     edge to edge on both sides, and the tab sits on it (Gabe, 2026-10-24:
     "the tab can go over the image"). */
  --band-edge: calc(var(--side) - var(--bleed));
  --band-l: calc(var(--gutter) + var(--side) - var(--band-edge));
  --band-r: calc(var(--tab-strip) + var(--side) - var(--band-edge));
}
/* The rating is a control, so it stays clear of the tab: a gutter in from the
   photograph's edge, or the tab's strip in from the window's, whichever is
   further in. */
[data-design="editorial"] .wrap:has(> .focus-tab) > .title-block > .hero-rating {
  margin-right: max(calc(var(--gutter) - var(--band-r)), calc(-1 * var(--side)));
}

/* The mise as a ledger: the amount and its unit together, in their own
   column, a little heavier than the name; the note under the name. */
[data-design="editorial"] .ingredients .ing {
  position: relative;
  display: grid;
  grid-template-columns: 5.6em minmax(0, 1fr);
  column-gap: 12px;
  align-items: baseline;
}
[data-design="editorial"] .ingredients .ing-amt { grid-column: 1; font-weight: 700; color: var(--charcoal); }
[data-design="editorial"] .ingredients .ing-name { grid-column: 2; }
[data-design="editorial"] .ingredients .ing-comma { display: none; }
[data-design="editorial"] .ingredients .ing-amt-long { display: none; }
[data-design="editorial"] .ingredients .ing-amt-short { display: inline; }
[data-design="editorial"] .ingredients .ing-note { grid-column: 2; font-size: 0.8em; line-height: 1.35; color: var(--muted); }
/* Against the current step: its lines' boxes outlined in red - the boxes to
   tick now - and grey for what the steps before it used. The old highlight
   is this design's no more. A red dot beside the line was the mock's mark,
   and with a box in the row it landed on the box's edge (Gabe, 2026-09-27:
   "weird dot artifacts"). */
[data-design="editorial"] .ingredients { --hl: transparent; }
[data-design="editorial"] .ingredients li.is-used .ing,
[data-design="editorial"] .ingredients li.is-used .ing * { color: #b3b3b3; }
[data-design="editorial"] .ingredients li.is-now .gather input[type=checkbox]:not(:checked) {
  border-color: var(--flame);
  box-shadow: inset 0 0 0 0.5px var(--flame);
}

/* The steps' Have Ready, two ways - the switch beside Small steps,
   have_ready_all(). On the step you are on (the default): the fold's own list,
   opening and closing with the step as it always has. On every step: the
   list that always shows, and nothing opens or closes. Both drawn alike. */
[data-design="editorial"] details.step-open > .produces-inline { display: none; }
[data-design="editorial"] ol.steps.is-ready-all details.step-open > .mise,
[data-design="editorial"] ol.steps:not(.is-ready-all) > li > .step-needs { display: none; }
[data-design="editorial"] details.step-open > .mise { margin: 10px 0 0; }
[data-design="editorial"] details.step-open > .mise > h3 { display: none; }
/* Two even columns, so the boxes line up down the list. They were one row
   that wrapped, every box wherever the line before it ended - Gabe,
   2026-10-01, "is this alignment intended?", then "yes to two columns". */
[data-design="editorial"] details.step-open > .mise > ul {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px 22px;
  font-family: var(--sans);
  font-size: 0.8125rem;
  line-height: 1.35;
  color: var(--soft);
}
[data-design="editorial"] details.step-open > .mise li { font-size: inherit; line-height: inherit; }
[data-design="editorial"] details.step-open > .mise .from { color: var(--flame); }
[data-design="editorial"] details.step-open > .mise .portion { font-weight: 700; color: var(--charcoal); }
/* Steps still to come, a touch quieter than the one you are on. Full
   strength from the redesign until Gabe, 2026-10-01: "let's slightly dim
   subsequent steps in recipe view". Lighter than the classic design's 0.72,
   so they still read at a glance; finished steps stay at 0.38. */
[data-design="editorial"] ol.steps > li.ahead { opacity: 0.8; }
[data-design="editorial"] ol.steps > li > .step-needs {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px 22px;
  margin: 10px 0 0;
  padding: 0;
  list-style: none;
  font-family: var(--sans);
  font-size: 0.8125rem;
  line-height: 1.35;
  color: var(--soft);
}
[data-design="editorial"] ol.steps > li > .step-needs > li { margin: 0; padding: 0; border: 0; }
[data-design="editorial"] .step-needs .from { color: var(--flame); }
[data-design="editorial"] .step-needs .portion { font-weight: 700; color: var(--charcoal); }

/* "Baby steps" and "All ingredients", one above the other, knobs in a
   column (Gabe: "try stacking those two switches"). The pair of grain links
   gives way to the first. */
/* Only on the recipe page: Focus mode's own pair of grain links carries the
   same class and keeps its links - hiding every `.grain > a` took Focus mode's
   step-size setting away for a day. */
[data-design="editorial"] .instructions-head > .grain > a:not(.grain-switch) { display: none; }
/* The lower one sits on the heading's line and the upper one rises into the
   space above, so the Steps rule stays level with the Mise en Place rule
   beside it - stacked in flow, the heading grew by a switch and its rule
   dropped 25px below the other column's. */
[data-design="editorial"] .instructions-head > .grain { position: relative; }
[data-design="editorial"] .instructions-head > .grain > .grain-switch:not(.ready-switch) {
  position: absolute;
  right: 0;
  bottom: calc(100% + 8px);
  white-space: nowrap;
}
/* **Converted** (punch 224), shown as written, rides a row above Baby steps,
   level with Containers over the mise column: both took the same place, one
   word printed over the other (Gabe, 2026-10-08). On, it is the one switch
   and keeps Baby steps' place. */
[data-design="editorial"] .instructions-head > .grain > .conv-switch:not(.is-on) { bottom: calc(100% + 33px); }
[data-design="editorial"] .grain > .grain-switch {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  color: var(--charcoal);
  text-decoration: none;
}
[data-design="editorial"] .grain > .grain-switch > .grain-knob {
  position: relative;
  width: 32px;
  height: 16px;
  border: 2px solid var(--charcoal);
}
[data-design="editorial"] .grain > .grain-switch > .grain-knob::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 8px;
  height: 8px;
  background: var(--muted);
  transition: transform 0.15s ease;
}
[data-design="editorial"] .grain > .grain-switch.is-on > .grain-knob::after { transform: translateX(16px); background: var(--flame); }
/* On, the words go red with the knob. Gabe, 2026-09-30, of Baby steps in
   focus mode: "make the text red when on ... check other switches" - the
   one rule covers every switch: Baby steps on the recipe page and in focus
   mode, and All ingredients. */
[data-design="editorial"] .grain > .grain-switch.is-on { color: var(--flame); }
[data-design="editorial"] .grain-switch:hover { color: var(--flame); }
/* Baby steps still being made (punch 156): the knob goes back and forth
   between off and on until the pieces arrive and the page swaps them in. */
[data-design="editorial"] .grain > .grain-switch.is-busy > .grain-knob::after { background: var(--flame); animation: grain-busy 0.9s ease-in-out infinite alternate; }
@keyframes grain-busy { to { transform: translateX(16px); } }
@media (prefers-reduced-motion: reduce) {
  [data-design="editorial"] .grain > .grain-switch.is-busy > .grain-knob::after { animation: none; transform: translateX(8px); }
}


/* The title's box spans the photograph's band, so its empty parts caught the
   click meant for the photograph (which opens it over the page, Gabe,
   2026-09-28). The box lets clicks through; its words, links and tabs keep
   theirs. */
[data-design="editorial"] .title-hero { pointer-events: none; }
[data-design="editorial"] .title-hero > *,
[data-design="editorial"] .title-hero a { pointer-events: auto; }

/* The heading bar (recipe.css, .cols-head) with room above it for Baby
   steps, which this design lifts 30-odd px above the Steps heading's line -
   at 12px it was cut off by the window's edge. */
@media (min-width: 640px) and (min-height: 520px) {
  [data-design="editorial"] .body-grid.has-cols-head > .cols-head { padding-top: 40px; margin-top: -40px; }
  /* A recipe with a servings control carries the Containers switch above it
     (below), so the block rises 63px over the heading's line, not 38. */
  [data-design="editorial"] .body-grid.has-cols-head > .cols-head:has(.scaler) { padding-top: 64px; margin-top: -64px; }
  /* So does Converted over Baby steps, with or without the control. */
  [data-design="editorial"] .body-grid.has-cols-head > .cols-head:has(.conv-switch:not(.is-on)) { padding-top: 64px; margin-top: -64px; }
}
/* **The servings control rides the heading bar**, above Mise en Place the
   way Baby steps rides above Steps, so the first ingredient and the first
   step start on one line. Gabe, 2026-09-30: "move scale widget up and align
   top of 1st ingredient and step". Its bottom sits where Baby steps' does,
   8px over the heading; it pins with the bar, in the 40px kept above it.
   The column's copy is for the stacked layout; at two columns only its
   sentence stays - an estimated yield - which is not a control and has no
   room up here. ("scaled from 4 - reset" stayed too until it was dropped
   the same day; 1x does the reset.) */
[data-design="editorial"] .cols-head-scale { display: none; }
@media (min-width: 640px) {
  [data-design="editorial"] .cols-head-scale {
    display: block;
    position: absolute;
    left: 0;
    right: 0;
    bottom: calc(100% + 8px);
  }
  [data-design="editorial"] .cols-head-scale .scaler { margin: 0; }
  /* **Containers** rides over the servings control, in the same block so the
     two stay apart when the control wraps. Gabe, 2026-10-03: "put the switch
     over the mise side" - it sat in the Steps column's row, beside Baby
     steps, and the mise column has no room on its own lines (250px at a
     tablet's 768: the heading and the switch are 258px). Left, with the
     control's left edge; the knob follows the word as in the others. */
  [data-design="editorial"] .cols-head-containers { margin: 0 0 8px; justify-content: flex-start; }
  /* A recipe with no yield has no control under it: the switch stands on
     Baby steps' row, level with it (-2px: Baby steps' own line sits 2px
     lower than the block's foot). */
  [data-design="editorial"] .cols-head-containers:last-child { margin-bottom: -2px; }
  /* The control is taller than Baby steps and rises further, so the columns
     start lower by the difference - it sat 16px under the description. With
     the switch over it the block is 25px taller again, so 89. */
  [data-design="editorial"] .body-grid.has-cols-head:has(.cols-head-scale .scaler) { margin-top: 89px; }
  /* Converted over Baby steps rises a row further too, where there is no
     control under Containers to have made the room already. */
  [data-design="editorial"] .body-grid.has-cols-head:has(.conv-switch:not(.is-on)):not(:has(.cols-head-scale .scaler)) { margin-top: 72px; }
  /* And the bar meets its columns at tablet width as it does wide: the
     grid's 40px row gap sat between the rule and both lists there (the wide
     layout already sets it to 0). */
  [data-design="editorial"] .body-grid.has-cols-head { row-gap: 0; }
  [data-design="editorial"] .cols-head-scale .scaler-reset { display: none; }
  [data-design="editorial"] .body-grid.has-cols-head > [data-swap="ingredients"] > .scaler > :not(.scaler-reset) { display: none; }
  [data-design="editorial"] .body-grid.has-cols-head > [data-swap="ingredients"] > .scaler:not(:has(.scaler-reset)) { display: none; }
  [data-design="editorial"] .body-grid.has-cols-head > [data-swap="ingredients"] > .scaler .scaler-reset { margin: 0 0 14px; }
}

/* The bar and the foot keep the same strip on a recipe page, so the search
   lines up with the page's right edge at tablet and phone widths too, not
   only on a wide screen (recipe.css, body[data-slug] .topbar). */
[data-design="editorial"] body:has(.wrap > .focus-tab) .topbar,
[data-design="editorial"] body:has(.wrap > .focus-tab) .sitefoot {
  padding-right: max(48px, min(64px, calc(64px - (100vw - 1180px) / 2)));
}

/* Focus mode shows the Baby steps switch, as the recipe page does, and not
   the pair of grain links (templates/cook.php). */
[data-design="editorial"] .cook-views > a:not(.grain-switch) { display: none; }

/* Dinner plans (116): the editorial face, and no curves. */
[data-design="editorial"] .meal-col-h,
[data-design="editorial"] .meal-serve button { font-family: var(--sans); }
[data-design="editorial"] .meal-clock-time,
[data-design="editorial"] .meal-glance-clock { letter-spacing: -0.03em; }
[data-design="editorial"] .meal-serve input,
[data-design="editorial"] .meal-serve button,
[data-design="editorial"] .meal-hours,
[data-design="editorial"] .meal-shots img,
[data-design="editorial"] .meal-step.is-key,
[data-design="editorial"] .meal-step.is-conditional { border-radius: 0; }
[data-design="editorial"] .meal-step.is-key { background: #fdf1ef; }
/* The menu card's Dinner Plan is Gloock, the logo's lettering, at the
   mock's spacing - not the title's heavy Archivo at -0.035em (punch 160). */
[data-design="editorial"] .title-block.meal-head h1 { font-family: Gloock, Georgia, serif; font-weight: 400; letter-spacing: 0; line-height: 1.02; }
/* Not the recipe page's room for its Cook it button, kept under every
   .title-block at desktop widths. */
[data-design="editorial"] .title-block.meal-head { padding-bottom: 0; }
[data-design="editorial"] .meal-col-h { letter-spacing: 0.14em; }
[data-design="editorial"] .meal-kicker,
[data-design="editorial"] .meal-course-h,
[data-design="editorial"] .meal-glance-cols > span { font-family: var(--sans); }
[data-design="editorial"] .meal-start,
[data-design="editorial"] .meal-live,
[data-design="editorial"] .meal-now { font-family: var(--sans); }
[data-design="editorial"] .meal-start,
[data-design="editorial"] .meal-now { border-radius: 0; }
