/* The 10 September recipe redesign.
 *
 * Everything here decorates markup that `app/recipepage.py` inserts at render
 * time. It is a separate file from `nutrition.css` and `ink.css` because those
 * two are loaded by pages that are not recipes, and none of this applies
 * anywhere else.
 *
 * The doubled-class prefix appears wherever a rule has to outrank the mirrored
 * CookingHub stylesheet, which is scoped to
 * `.ch-embed.ch-embed .ch-recipe.ch-recipe` — four class selectors. A single
 * class here would lose to it silently.
 */

/* --- reserved space for the two Tom's Desk embeds ----------------------- *
 *
 * Item 12a: a script that arrives after first paint and then inserts a box is
 * a layout shift on every recipe page. The slot holds the height open before
 * the answer comes back, so nothing below it moves. `min-height` and not
 * `height`: the embed is allowed to be taller than we guessed, and growing
 * downwards past the fold is not a shift a reader sees.
 *
 * The two numbers are what the embeds actually render to, measured rather
 * than guessed — see audit/recipe-redesign-0910/embed-heights.json.
 */
.ttc-embed-slot { display: block; }
/* The reviews embed opens its iframe at exactly 760px and only ever grows,
   so 760 is not a guess — it is the number the embed itself starts from, and
   reserving it means the frame arriving costs nothing. */
/* The reviews slot is Tom's Desk's own div now (item 3.5) and carries no
   class of ours, so the reserved height is keyed off the id instead. It is
   still reserved: the frame arrives after the page and the layout must not
   jump when it does. */
[id^="tomreviews-"] { display: block; min-height: 760px; }
/* The policy embed measured 1487px at 1440, 1280, 1024 and 900; 1668 at 768;
   3131 at 390. The floors are those numbers rounded up, which is why the
   brackets are where they are rather than on the theme's usual breakpoints. */
.ttc-embed-slot--policy  { min-height: 1500px; }
@media screen and (max-width: 800px) {
  .ttc-embed-slot--policy { min-height: 1700px; }
}
@media screen and (max-width: 560px) {
  .ttc-embed-slot--policy { min-height: 3150px; }
}
/* An embed that fails leaves an empty box. Better an empty box that is the
   right size than a page that jumps, but it must not look like a hole: no
   border, no background, nothing to read as broken. */
.ttc-reviews-embed, .ttc-policy-embed { background: none; }

/* --- item 7: the signs on the ingredient and tool boxes ----------------- */
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-sign,
.ttc-sign {
  display: inline-flex;
  align-items: center;
  gap: .9rem;
  margin: -1.2rem 0 2.4rem;
  padding: .7rem 1.6rem;
  border-radius: 999px;
  font-size: 1.4rem;
  line-height: 1.9rem;
  font-weight: 700;
  letter-spacing: -.01em;
}
/* Brand orange for the ingredients, brand maroon for the tools — the same
   pair the tools box's own red outline and the site's headings already use,
   so the signs read as part of the design rather than as two new colours. */
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-sign--ing,
.ttc-sign--ing  { background: #fff1e3; color: #a8410a; border: 1px solid #f4b184; }
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-sign--tool,
.ttc-sign--tool { background: #fdecec; color: #51000d; border: 1px solid #e79b95; }
.ttc-sign__hand {
  width: 1.6rem; height: 1.6rem; flex: 0 0 auto;
  background: currentColor;
  -webkit-mask: var(--ttc-hand) center/contain no-repeat;
          mask: var(--ttc-hand) center/contain no-repeat;
}
:root {
  --ttc-hand: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9 11V5.5a1.5 1.5 0 0 1 3 0V11m0-1.5a1.5 1.5 0 0 1 3 0V12m0-1a1.5 1.5 0 0 1 3 0v1m0 0v4a6 6 0 0 1-6 6h-1a6 6 0 0 1-5.2-3l-2.3-4a1.5 1.5 0 0 1 2.6-1.5L9 15' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* --- item 10: Ko-fi ----------------------------------------------------- */
.ttc-kofi { text-align: center; }
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-kofi__btn,
.ttc-kofi__btn {
  display: inline-flex;
  align-items: center;
  gap: 1.2rem;
  padding: 1.4rem 3rem;
  border-radius: 999px;
  /* The mockup's button is the brand maroon — #54010b off the JPEG, which is
     #51000d through the compression — not the near-black it was drawn in. */
  background: #51000d;
  color: #fff;
  font-size: 1.8rem;
  line-height: 2.4rem;
  font-weight: 700;
  text-decoration: none;
}
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-kofi__btn:hover,
.ttc-kofi__btn:hover { background: #6b0212; text-decoration: none; }
.ttc-kofi__cup {
  /* D1: Ko-fi's own mark as the mockup draws it -- a white cup with the red
     heart in it, straight on the maroon. The live button had the cup knocked
     out of a salmon-pink disc, which is the one thing item D1 names. */
  width: 2.6rem; height: 2.6rem; flex: 0 0 auto;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3.6 6.2h12.2v7.4a4.6 4.6 0 0 1-4.6 4.6H8.2a4.6 4.6 0 0 1-4.6-4.6V6.2Z' fill='%23fff'/%3E%3Cpath d='M15.8 7.6h1.9a2.6 2.6 0 0 1 0 5.2h-1.9' fill='none' stroke='%23fff' stroke-width='2.1' stroke-linecap='round'/%3E%3Cpath d='M9.7 8.6c.9-.9 2.3-.3 2.3.8 0 1-1.2 1.9-2.3 2.7-1.1-.8-2.3-1.7-2.3-2.7 0-1.1 1.4-1.7 2.3-.8Z' fill='%23ff5f5f'/%3E%3C/svg%3E") center/2.6rem no-repeat;
}

/* --- item 4: the NEW star ------------------------------------------------ *
 *
 * Drawn rather than fetched: it is one shape, it has to sit at two very
 * different sizes (a card corner and a recipe hero), and a background image
 * would be one more request in front of the largest paint on the page.
 * The star is a clip-path on a yellow square, with the word laid over it.
 */
.ttc-new {
  --ttc-new-size: 62px;
  width: var(--ttc-new-size);
  height: var(--ttc-new-size);
  display: inline-grid;
  place-items: center;
  flex: 0 0 auto;
  background: #ffe600;
  clip-path: polygon(50% 0%, 62% 34%, 98% 35%, 69% 57%, 80% 91%,
                     50% 70%, 20% 91%, 31% 57%, 2% 35%, 38% 34%);
}
.ttc-new__word {
  font-size: calc(var(--ttc-new-size) * .19);
  line-height: 1;
  font-weight: 800;
  letter-spacing: .04em;
  color: #1a2428;
  transform: translateY(6%);
}
/* On a card: bottom-left of the bottom band, opposite the share button, which
   is what New Icon.jpg shows. The band is a flex row so the two ends hold. */
.bottom > .ttc-new { --ttc-new-size: 54px; }
article .bottom { position: relative; }

/* --- the hero ----------------------------------------------------------- */
.ch-embed .ttc-hero__servings, .ttc-hero__servings {
  margin: 0 0 1.8rem;
  color: #fff;
  font-size: 1.5rem;
  line-height: 2rem;
  font-weight: 400;
}
.ttc-hero__marks {
  display: flex;
  align-items: center;
  gap: 1.4rem;
  padding: 0 0 1.8rem;
}
.ttc-hero__marks .ttc-flag {
  position: static;
  transform: none;
  width: 4.6rem;
  height: 4.6rem;
}
.ttc-hero__marks .ttc-new { --ttc-new-size: 48px; }

/* The intro clamp. `-webkit-line-clamp` keeps every word in the HTML — the
   text is all there for a search engine and for a reader who expands it —
   and the button is revealed by script only when the text is actually taller
   than the clamp, so a short intro shows no control at all (item 5). */
.ttc-intro__body {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
}
.ttc-intro.is-open .ttc-intro__body {
  -webkit-line-clamp: unset;
  overflow: visible;
}
.ttc-intro__more {
  margin: .4rem 0 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  font-weight: 700;
  text-decoration: underline;
  cursor: pointer;
}
.ttc-intro__more:hover { text-decoration: none; }

/* The diets, over the photograph. Bottom-right, clear of the share icons at
   the top-right, and wrapping upward on a narrow screen rather than off it. */
/* The doubled prefix matters here and not only for tidiness: the card's
   header is INSIDE `.ch-recipe`, so the mirrored CookingHub rules — four class
   selectors — beat a bare `.ttc-pill`, and the pills rendered as dark text on
   the maroon with no white behind them. Measured, not guessed. */
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-hero__diets,
.ttc-hero__diets {
  position: absolute;
  right: 2.4rem;
  bottom: 2.4rem;
  left: 2.4rem;
  z-index: 11;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 1rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-hero__diets > li.ttc-pill,
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-pill,
.ttc-pill {
  padding: .7rem 1.6rem;
  border-radius: 999px;
  background: #fff;
  color: #1a2428;
  font-size: 1.4rem;
  line-height: 1.9rem;
  font-weight: 700;
  white-space: nowrap;
}

/* --- the strip under the hero ------------------------------------------- */
.ttc-herobar { margin: 0 0 3rem; }
.ttc-herobar__in {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2.4rem;
  flex-wrap: wrap;
  padding: 2.4rem 5rem;
  border-radius: 0 0 4rem 4rem;
  background: #f8f8f8;
}
.ttc-herobar__cal { margin: 0; font-size: 1.6rem; line-height: 2.2rem; }
.ttc-herobar__cal a { font-weight: 700; text-decoration: underline; }
.ttc-herobar__cal a:hover { text-decoration: none; }
@media screen and (max-width: 500px) {
  .ttc-herobar__in { padding: 2rem; border-radius: 0 0 2rem 2rem; }
}

/* --- "Before You Start" and the button, on one line --------------------- */
/* Heading and button on one line, the button immediately after the words
   rather than pushed to the far edge: in the mockup the heading block ends at
   x=445 of a container running 45 to 1285 and the button starts at 497, a gap
   of about 52px. `space-between` put it at 1285. */
.ttc-beforebar__in {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 5.2rem;
  flex-wrap: wrap;
}
/* The heading block is a `.gt-block`, and the theme gives those the full
   width of their container. In a flex row that is a first item 957px wide,
   which pushed the button onto a second line — the mockup has the two on one,
   heading left and button right. Letting it shrink is the whole fix. */
.ttc-beforebar__in > .gt-block {
  flex: 0 1 auto;
  width: auto;
  min-width: 0;
  /* The theme centres a `.gt-block` with automatic side margins. Once the
     block had shrunk to its text those margins were 149px each and they put
     the heading in the middle of the row, whatever justify-content said. */
  margin-left: 0;
  margin-right: 0;
}
/* The two blocks inside were centred on their own; in a row they read left. */
.ttc-beforebar__in > .gt-block h2,
.ttc-beforebar__in > .gt-block p { text-align: left !important; }
/* "Before We Start" is maroon in the mockup, not the body's ink. */
.ttc-beforebar__in > .gt-block h2 { color: #51000d; }
.ttc-beforebar__btn { flex: 0 0 auto; }
.ttc-beforebar__btn p { text-align: left !important; margin: 0; }
.ttc-beforebar__btn img { margin: 0 !important; }
/* Stacked below 800, not 760. At 768 the column is 728px and the theme's
   type has stepped up a size, so the heading, its subtitle and a 236px button
   do not fit on one line - they were sharing a row by overflowing it. The
   mockup draws one row at its own width, and above 800 that is what it is. */
@media screen and (max-width: 800px) {
  .ttc-beforebar__in { justify-content: center; }
  .ttc-beforebar__in > .gt-block h2,
  .ttc-beforebar__in > .gt-block p { text-align: center !important; }
  .ttc-beforebar__btn p { text-align: center !important; }
}

/* --- the recipe card's maroon header ------------------------------------ *
 *
 * The mockup repeats the hero's identity line at the top of the card. Same
 * maroon as the hero, same radius, and the diet pills sit at the right on a
 * wide screen and wrap under on a narrow one rather than off the edge.
 */
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__head,
.ttc-card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 2rem 3rem;
  padding: 3rem 5rem;
  margin: 0 0 3rem;
  border-radius: 4rem;
  background: #51000d;
  color: #fff;
}
.ttc-card__headin { display: flex; flex-direction: column; gap: 1.4rem; }
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__title,
.ttc-card__title {
  margin: 0;
  color: #fff;
  font-size: 3.2rem;
  line-height: 3.8rem;
  font-weight: 800;
  letter-spacing: -.02em;
}
.ttc-card__line {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 1.2rem 2.4rem;
  font-size: 1.5rem;
  line-height: 2rem;
}
.ttc-card__marks { display: inline-flex; align-items: center; gap: 1rem; }
.ttc-card__marks .ttc-flag {
  position: static; transform: none; width: 3.4rem; height: 3.4rem;
}
.ttc-card__marks .ttc-new { --ttc-new-size: 36px; }
.ttc-card__date { opacity: .85; }
/* The pill list is absolutely positioned because on the hero it floats over
   the photograph. In the card header and in the nutrition box it is an
   ordinary item in a row, so it is put back to static — and the selector has
   to carry the same `.ch-embed .ch-recipe` weight as the rule it is
   overriding, because the card header is inside `.ch-recipe` and a bare
   `.ttc-card__head .ttc-hero__diets` is two classes against five. Without the
   weight the pill stayed absolute and landed at the bottom-right of the
   Ingredients | Tools panel, half outside it. */
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__head .ttc-hero__diets,
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-nutrition__head .ttc-hero__diets,
.ttc-card__head .ttc-hero__diets,
.ttc-nutrition__head .ttc-hero__diets {
  position: static;
  justify-content: flex-end;
  gap: 1rem;
  left: auto; right: auto; bottom: auto;
  width: auto;
}
@media screen and (max-width: 500px) {
  .ttc-card__head { padding: 2rem; border-radius: 2rem; }
  .ttc-card__title { font-size: 2.6rem; line-height: 3.2rem; }
}

/* --- the green Print button --------------------------------------------- */
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-print,
.ttc-print {
  display: inline-flex;
  align-items: center;
  gap: 1.2rem;
  padding: 1.2rem 3.2rem;
  border: 0;
  border-radius: 999px;
  /* #3bb81e, sampled off the mockup's Print button. It had been #22c55e,
     a bluer green that reads as a different button beside the drawing. */
  background: #3bb81e;
  color: #fff;
  font-size: 1.7rem;
  line-height: 2.2rem;
  font-weight: 700;
  cursor: pointer;
}
.ttc-print:hover { background: #32a01a; }
.ttc-print__icon {
  width: 2rem; height: 2rem; flex: 0 0 auto; background: #fff;
  -webkit-mask: var(--ttc-printer) center/contain no-repeat;
          mask: var(--ttc-printer) center/contain no-repeat;
}
:root {
  --ttc-printer: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7 8V3h10v5M7 18H5a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-2M7 14h10v7H7z' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
/* The strip becomes a row with the button on its right, which is what
   CookingHub's own `.info-buttons` layout does and ours had no button for. */
.ch-embed.ch-embed .ch-recipe.ch-recipe #info .info-buttons {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2.4rem;
  flex-wrap: wrap;
}
/* Nothing on this page prints except the recipe, and a button that prints is
   not part of a printed recipe. */
@media print { .ttc-print, .ttc-kofi, .ttc-sign { display: none !important; } }

/* The embed puts a generated bullet on every `li` inside a recipe, which
   showed as a dot inside each pill — the same trap the diet chips hit on
   9 September, in a different list. */
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-hero__diets > li:before {
  content: none; display: none;
}
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-hero__diets > li {
  padding-left: 0; position: static; background: #fff;
}

/* AAC4 [C5]: the hero card is the brand maroon, on every recipe.
   
   The theme paints it `#603D00` — the brown Tom's note names — through
   `.bgcolor-kitchen-guide`, which is CookingHub's colour for the whole
   kitchen-guide section and arrives with the mirrored bundle. It is not
   edited there: the bundle is regenerated from their theme, so an edit in it
   would be undone by the next mirror. Overridden here instead, on the one
   element that wears it, which is the hero on a recipe and on a recipe
   category — the same card, the same brand, and the maroon the "My Recipes"
   title card in the listing mockup is already painted. */
section.gt-block.intro.bgcolor-kitchen-guide { background: #51000d; }

/* The hero's foot, to the mockup.
 *
 * Four things, all of them visible in a screenshot of the live page beside
 * `New Recipe Page.jpg` at 1440.
 *
 * 1. "Read More" was drawn in the theme's ink — rgb(26, 36, 40) — on the
 *    maroon card, which is all but invisible. The button had `color: inherit`
 *    and the theme's own `button` rule is more specific than that, so the
 *    inheritance never happened. The mockup has it white, bold, underlined.
 * 2. The mockup rules a hairline across the card above the author row. Ours
 *    had nothing there.
 * 3. The mockup's author line is the avatar, the name, and the date — no role
 *    under the name. `<em>Founder</em>` comes from the captured markup and
 *    stays in the HTML; it is not drawn, because it is not in the drawing.
 * 4. "Published:" and the date are on one line in the mockup. The captured
 *    markup breaks them with a `<br>`; the break is collapsed rather than
 *    removed, again so the words in the HTML do not change. */
section.gt-block.intro .ttc-intro__more {
  color: #fff;
  font-weight: 700;
  text-decoration: underline;
}
section.gt-block.intro .content .in.with-info > .info {
  border-top: 1px solid rgba(255, 255, 255, .22);
  padding-top: 2.2rem;
  margin-top: 2.2rem;
}
section.gt-block.intro .chef-label em { display: none; }
section.gt-block.intro .date br { display: none; }
section.gt-block.intro .date { white-space: nowrap; }

/* The "Recipe:" label — item 6 of the allowed set.
 *
 * The mockup has it left-aligned and maroon. The stored markup centres it with
 * an inline `style="text-align: center"`, which is why this needs `!important`
 * to win; the words themselves are Tom's and are not touched, including the
 * line about shopping the ingredients that the mockup does not have and that
 * is written up in QUESTIONS.md §18. */
h2#rec {
  text-align: left !important;
  color: #51000d;
}
h2#rec + p { text-align: left !important; }

/* "Directions:" is maroon in the mockup, like "Recipe:" and "Before We
   Start"; "Ingredients:" and "Tools:" are the body's ink, and stay that way.
   Sampled off the JPEG at the darkest quarter of each heading's pixels:
   #3e0911 for Directions against #212224 for Ingredients. The selector
   carries the `.ch-embed .ch-recipe` weight because the heading is inside the
   recipe block, where the mirrored stylesheet colours it. */
.ch-embed.ch-embed .ch-recipe.ch-recipe h2.directions-title,
h2.directions-title { color: #51000d; }

/* The Print button on a phone.
 *
 * CookingHub hides that container below its phone breakpoint — those were its
 * own "save recipe" controls and it did not want them there. On our pages the
 * container holds one thing, the Print button, which is item 8 of the allowed
 * set and has no reason to disappear on the device most likely to be propped
 * against a mixing bowl. Weighted to beat the mirrored rule, which lives
 * inside `.ch-recipe`. */
.ch-embed.ch-embed .ch-recipe.ch-recipe #info .info-buttons > div.buttons {
  display: block;
}

/* The portrait in the recipe card's identity row, as the mockup draws it:
   the same round avatar the hero shows, at the row's own scale. */
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__author,
.ttc-card__author { display: inline-flex; align-items: center; gap: 1rem; }
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__avatar,
.ttc-card__avatar {
  width: 3.4rem; height: 3.4rem; flex: 0 0 auto;
  border-radius: 50%; object-fit: cover; background: #fff;
}

/* The review box's empty state, when Tom's Desk has none open for this
   recipe. Written by static/site/recipe-redesign.js in place of a frame that
   never reported any content — the alternative was the word "Loading…" on
   the page for ever. */
.ttc-reviews-empty {
  padding: 4rem 3rem;
  text-align: center;
}
.ttc-reviews-empty__lead {
  margin: 0 0 .8rem;
  color: #51000d;
  font-size: 2.2rem;
  font-weight: 800;
}
.ttc-reviews-empty__note {
  margin: 0;
  color: #4a4a4a;
  font-size: 1.6rem;
  line-height: 2.4rem;
}
/* Nothing is reserved once we know the box is empty, so the foot of the page
   does not carry 760px of nothing. */

/* The stats row — item 1 and item 7 of the inventory: the stars, the review
   count, the link, the eye and the view count. */
.ttc-hero__stats, .ttc-card__stats {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: .8rem 1.6rem;
  margin: 1.6rem 0 0;
  color: #fff;
  font-size: 1.5rem;
  line-height: 2rem;
}
.ttc-card__stats { margin: 0; }
.ttc-hero__stats__stars, .ttc-card__stats__stars,
.ttc-hero__stats__views, .ttc-card__stats__views {
  display: inline-flex; align-items: center; gap: .6rem;
}
.ttc-star { width: 1.8rem; height: 1.8rem; fill: #fd7d23; flex: 0 0 auto; }
.ttc-star--off { fill: none; color: rgba(255, 255, 255, .55); }
.ttc-eye { width: 2.2rem; height: 2.2rem; color: #fff; flex: 0 0 auto; }
.ttc-hero__stats__write, .ttc-card__stats__write {
  color: #fff; font-weight: 700; text-decoration: underline;
}
.ttc-hero__stats__write:hover, .ttc-card__stats__write:hover {
  text-decoration: none; color: #fff;
}

/* THE BOLD RULE IN THE DIRECTIONS — addendum J2.
 *
 * A numbered item is bold when it has sub-items beneath it and regular when
 * it is a leaf. That is what makes the numbering readable: bold says "there
 * is more underneath this", so bolding a leaf says it and then does not
 * deliver. Top-level sections are always bold.
 *
 * Derived from the nesting itself with `:has()`, not from a class the
 * renderer writes — the two kinds of recipe on this site arrive by different
 * routes, and a CookingHub one is served from its stored body and never
 * passes through `render_step` at all. A structural selector reads the
 * nesting the document produced either way, on every recipe, with nothing to
 * keep in step.
 *
 * THE SELECTOR IS THE MIRRORED STYLESHEET'S OWN, PLUS THE TEST. CookingHub
 * writes `.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
 * .step h3 { font-weight: 600 }` — seven classes and two elements. A shorter
 * selector of mine lost to it silently and every leaf stayed bold. The
 * `.mark` spans carry their own 700 from the same stylesheet and need the
 * same treatment, or the number stays bold on a regular line.
 *
 * Weight only. Never colour: hierarchy here is boldness, and the ink stays
 * the site's #1a2428 (J1). */
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:not(:has(.step)) > h2,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:not(:has(.step)) > h3,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:not(:has(.step)) > h4,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:not(:has(.step)) > h5,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:not(:has(.step)) > h2 .mark,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:not(:has(.step)) > h3 .mark,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:not(:has(.step)) > h4 .mark,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:not(:has(.step)) > h5 .mark,
.step:not(:has(.step)) > h2, .step:not(:has(.step)) > h3,
.step:not(:has(.step)) > h4, .step:not(:has(.step)) > h5,
.step:not(:has(.step)) > h2 .mark, .step:not(:has(.step)) > h3 .mark,
.step:not(:has(.step)) > h4 .mark, .step:not(:has(.step)) > h5 .mark {
  font-weight: 400;
}
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:has(.step) > h2,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:has(.step) > h3,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:has(.step) > h4,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:has(.step) > h5,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step.step-level-1 > h2,
.step:has(.step) > h2, .step:has(.step) > h3,
.step:has(.step) > h4, .step:has(.step) > h5,
.step.step-level-1 > h2 {
  font-weight: 700;
}

/* =========================================================================
   The 10 September punch-list. Tom put his live screenshots beside
   New Recipe Page.jpg and wrote down every difference; these are the ones
   that are a matter of style rather than of markup.

   Everything here is measured against the mockup at its own width (1315px,
   content column about 1240) and applied in rem, so it holds at all six
   widths rather than only at the one it was drawn at.
   ========================================================================= */

/* --- A3: the rating row ------------------------------------------------- */
/*
 * Two faults, both about contrast on a dark red card. The outline stars were
 * drawn at 55% white, which on maroon is barely a shape; and "(write a
 * review)" was underlined, which the mockup does not do and which on this
 * background reads as the low-contrast link Tom singled out. In the mockup
 * the glyphs are solid white, the empty one is a white outline, and the
 * words carry their weight instead of a rule.
 */
.ttc-star--off { fill: none; color: #fff; }
.ttc-star--off path { stroke-width: 2.2; }
.ttc-hero__stats__write, .ttc-card__stats__write { text-decoration: none; }
.ttc-hero__stats__write:hover,
.ttc-card__stats__write:hover { text-decoration: underline; }

/* A rule above the rating row and another below it, which is how the mockup
 * separates it from the introduction above and the author below. There is no
 * third rule: item A4's "no divider above the author row" is satisfied by
 * these two belonging to the rating row. */
.ttc-hero__stats {
  border-top: 1px solid rgba(255, 255, 255, .38);
  border-bottom: 1px solid rgba(255, 255, 255, .38);
  padding: 1.4rem 0;
  margin: 1.8rem 0 0;
}

/* --- A4: the author row ------------------------------------------------- */
section.gt-block.intro .content .in.with-info > .info {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.6rem;
  border-top: 0;                      /* A4: and no rule of its own */
  padding-top: 1.6rem;
}
section.gt-block.intro .chef-label {
  display: inline-flex;
  align-items: center;
  gap: 1.2rem;
}
section.gt-block.intro .chef-label__img img {
  width: 4.4rem; height: 4.4rem; border-radius: 50%; display: block;
}
section.gt-block.intro .chef-label strong {
  font-weight: 400; font-size: 1.7rem; color: #fff;
}
section.gt-block.intro .date { font-weight: 400; opacity: .92; }

/* --- A5: the card and the photograph are both rounded ------------------- */
/*
 * The mockup's hero is one rounded card with the photograph laid over its
 * right-hand end, itself rounded, so the join is two curves rather than the
 * hard vertical split the live page had.
 */
/*
 * How the mockup actually draws it, which took a magnifying glass: the maroon
 * is the whole card, the photograph is laid ON it at the right, and the
 * photograph's BOTTOM-LEFT corner is rounded so that a curve of maroon shows
 * through underneath it. The top-left stays square, so the two meet in a
 * straight line at the top. That is the "slightly overlapping, with a rounded
 * corner" of item A5 — not a gap between two rectangles, which is what the
 * live page had, and not a photograph rounded on all four sides either.
 */
section.gt-block.intro.bgcolor-kitchen-guide { border-radius: 3rem; }
section.gt-block.intro .img {
  border-radius: 0 3rem 3rem 3rem;
  overflow: hidden;
}

/* --- A6: the Share tab -------------------------------------------------- */
.share-line {
  background: rgba(255, 255, 255, .88) !important;
  border-radius: 0 0 0 3rem !important;
  display: flex !important;
  align-items: center;
  gap: 1.8rem;
}
.share-line__label { font-weight: 700; font-size: 1.5rem; }
.share-line .menu { display: flex; align-items: center; gap: 1.2rem; margin: 0; }
.share-line .menu li { margin: 0; }

/* --- B1/B2: the strip under the hero ------------------------------------ */
.ttc-herobar__in { border-radius: 3rem; }
.ttc-herobar__cal { color: #1a2428; }
.ttc-herobar__cal strong { color: #51000d; font-weight: 700; }
.ttc-herobar__cal a { color: #51000d; font-weight: 700; text-decoration: underline; }

/* --- C2: Jump to Recipe, in markup rather than as a picture ------------- */
.ttc-jump {
  display: inline-flex;
  align-items: center;
  gap: 1.2rem;
  background: #51000d;
  color: #fff;
  font-weight: 700;
  font-size: 1.8rem;
  line-height: 1;
  padding: 1.3rem 2.6rem 1.3rem 1.3rem;
  border-radius: 999px;
  text-decoration: none;
}
.ttc-jump:hover { background: #6b0212; color: #fff; text-decoration: none; }
.ttc-jump__chev { display: inline-flex; }
.ttc-jump__chev svg { width: 2.8rem; height: 2.8rem; display: block; }

/* --- D4: the recipe card's header, two rows ----------------------------- */
/*
 * The doubled prefix is not decoration: this card sits inside `.ch-recipe`,
 * and the block that made `.ttc-card__head` a flex row is written
 * `.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__head` — five classes,
 * which a bare `.ttc-card__head` later in the same file loses to in silence.
 */
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__head,
.ttc-card__head { display: block; }
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__row,
.ttc-card__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.6rem 2.4rem;
  flex-wrap: wrap;
}
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__row--top,
.ttc-card__row--top { margin: 0 0 1.6rem; }
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__ident,
.ttc-card__ident {
  display: flex;
  align-items: center;
  gap: 1.8rem;
  flex-wrap: wrap;
}
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__head .ttc-card__stats,
.ttc-card__head .ttc-card__stats { border: 0; padding: 0; margin: 0; }
/* Everything on the maroon card is white — item D4. */
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__head,
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__head a,
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__head strong,
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__head span,
.ttc-card__head, .ttc-card__head a,
.ttc-card__head strong, .ttc-card__head span { color: #fff; }
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__head .ttc-pill,
.ttc-card__head .ttc-pill { color: #1a2428; }

/* --- F5: the nutrition card's own outline ------------------------------- */
/*
 * Everything else about this box — the cream, the pipe-separated line, the
 * bold note, the pills at the right of the heading — is in
 * static/site/nutrition.css, written against the same mockup and with the
 * same doubled prefix. Only the thin border and the padding were missing.
 */
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-nutrition,
.ttc-nutrition { border: 1px solid #d8c9a6; }
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-nutrition .content > .text,
.ttc-nutrition .content > .text { padding: 2.8rem 3.2rem 3rem; }

/* --- A4 again: the author row has to be IN the flow --------------------- */
/*
 * The theme lays this row out with `position: absolute` — the row, the chef
 * label inside it and the date inside that, all three — pinned to the bottom
 * of the hero card. Absolutely positioned children take no part in their
 * parent's flex layout, which is why the row measured 12px tall with a 34px
 * portrait sitting in it: the rules were applying and had nothing to lay out.
 *
 * Put all three back in the flow, and the row becomes what the mockup draws:
 * portrait, name, and the date at the far right of the same line.
 */
section.gt-block.intro .content .in.with-info > .info,
section.gt-block.intro .content .in.with-info > .info,
section.gt-block.intro .content .in.with-info > .info .date {
  position: static;
}
/* The portrait is pinned by the theme with `position: absolute`, and it was
 * landing at the top-left of the hero -- next to the category pill -- because
 * the nearest positioned ancestor was the whole card. Give the label itself a
 * position and the portrait comes home; the padding is the room it needs. */
section.gt-block.intro .content .in.with-info > .info .chef-label {
  position: relative;
  padding-left: 5.8rem;
  min-height: 4.4rem;
}
section.gt-block.intro .content .in.with-info > .info {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.6rem;
  margin-top: 2rem;
}
section.gt-block.intro .content .in.with-info > .info .date {
  text-align: right;
  white-space: nowrap;
}
/* The review box's empty state, when Tom's Desk has none open for this
   recipe. Written by static/site/recipe-redesign.js in place of a frame that
   never reported any content — the alternative was the word "Loading…" on
   the page for ever. */
.ttc-reviews-empty {
  padding: 4rem 3rem;
  text-align: center;
}
.ttc-reviews-empty__lead {
  margin: 0 0 .8rem;
  color: #51000d;
  font-size: 2.2rem;
  font-weight: 800;
}
.ttc-reviews-empty__note {
  margin: 0;
  color: #4a4a4a;
  font-size: 1.6rem;
  line-height: 2.4rem;
}
/* Nothing is reserved once we know the box is empty, so the foot of the page
   does not carry 760px of nothing. */

/* The stats row — item 1 and item 7 of the inventory: the stars, the review
   count, the link, the eye and the view count. */
.ttc-hero__stats, .ttc-card__stats {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: .8rem 1.6rem;
  margin: 1.6rem 0 0;
  color: #fff;
  font-size: 1.5rem;
  line-height: 2rem;
}
.ttc-card__stats { margin: 0; }
.ttc-hero__stats__stars, .ttc-card__stats__stars,
.ttc-hero__stats__views, .ttc-card__stats__views {
  display: inline-flex; align-items: center; gap: .6rem;
}
.ttc-star { width: 1.8rem; height: 1.8rem; fill: #fd7d23; flex: 0 0 auto; }
.ttc-star--off { fill: none; color: rgba(255, 255, 255, .55); }
.ttc-eye { width: 2.2rem; height: 2.2rem; color: #fff; flex: 0 0 auto; }
.ttc-hero__stats__write, .ttc-card__stats__write {
  color: #fff; font-weight: 700; text-decoration: underline;
}
.ttc-hero__stats__write:hover, .ttc-card__stats__write:hover {
  text-decoration: none; color: #fff;
}

/* THE BOLD RULE IN THE DIRECTIONS — addendum J2.
 *
 * A numbered item is bold when it has sub-items beneath it and regular when
 * it is a leaf. That is what makes the numbering readable: bold says "there
 * is more underneath this", so bolding a leaf says it and then does not
 * deliver. Top-level sections are always bold.
 *
 * Derived from the nesting itself with `:has()`, not from a class the
 * renderer writes — the two kinds of recipe on this site arrive by different
 * routes, and a CookingHub one is served from its stored body and never
 * passes through `render_step` at all. A structural selector reads the
 * nesting the document produced either way, on every recipe, with nothing to
 * keep in step.
 *
 * THE SELECTOR IS THE MIRRORED STYLESHEET'S OWN, PLUS THE TEST. CookingHub
 * writes `.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
 * .step h3 { font-weight: 600 }` — seven classes and two elements. A shorter
 * selector of mine lost to it silently and every leaf stayed bold. The
 * `.mark` spans carry their own 700 from the same stylesheet and need the
 * same treatment, or the number stays bold on a regular line.
 *
 * Weight only. Never colour: hierarchy here is boldness, and the ink stays
 * the site's #1a2428 (J1). */
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:not(:has(.step)) > h2,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:not(:has(.step)) > h3,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:not(:has(.step)) > h4,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:not(:has(.step)) > h5,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:not(:has(.step)) > h2 .mark,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:not(:has(.step)) > h3 .mark,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:not(:has(.step)) > h4 .mark,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:not(:has(.step)) > h5 .mark,
.step:not(:has(.step)) > h2, .step:not(:has(.step)) > h3,
.step:not(:has(.step)) > h4, .step:not(:has(.step)) > h5,
.step:not(:has(.step)) > h2 .mark, .step:not(:has(.step)) > h3 .mark,
.step:not(:has(.step)) > h4 .mark, .step:not(:has(.step)) > h5 .mark {
  font-weight: 400;
}
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:has(.step) > h2,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:has(.step) > h3,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:has(.step) > h4,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step:has(.step) > h5,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content
  .step.step-level-1 > h2,
.step:has(.step) > h2, .step:has(.step) > h3,
.step:has(.step) > h4, .step:has(.step) > h5,
.step.step-level-1 > h2 {
  font-weight: 700;
}

/* =========================================================================
   The 10 September punch-list. Tom put his live screenshots beside
   New Recipe Page.jpg and wrote down every difference; these are the ones
   that are a matter of style rather than of markup.

   Everything here is measured against the mockup at its own width (1315px,
   content column about 1240) and applied in rem, so it holds at all six
   widths rather than only at the one it was drawn at.
   ========================================================================= */

/* --- A3: the rating row ------------------------------------------------- */
/*
 * Two faults, both about contrast on a dark red card. The outline stars were
 * drawn at 55% white, which on maroon is barely a shape; and "(write a
 * review)" was underlined, which the mockup does not do and which on this
 * background reads as the low-contrast link Tom singled out. In the mockup
 * the glyphs are solid white, the empty one is a white outline, and the
 * words carry their weight instead of a rule.
 */
.ttc-star--off { fill: none; color: #fff; }
.ttc-star--off path { stroke-width: 2.2; }
.ttc-hero__stats__write, .ttc-card__stats__write { text-decoration: none; }
.ttc-hero__stats__write:hover,
.ttc-card__stats__write:hover { text-decoration: underline; }

/* A rule above the rating row and another below it, which is how the mockup
 * separates it from the introduction above and the author below. There is no
 * third rule: item A4's "no divider above the author row" is satisfied by
 * these two belonging to the rating row. */
.ttc-hero__stats {
  border-top: 1px solid rgba(255, 255, 255, .38);
  border-bottom: 1px solid rgba(255, 255, 255, .38);
  padding: 1.4rem 0;
  margin: 1.8rem 0 0;
}

/* --- A4: the author row ------------------------------------------------- */
section.gt-block.intro .content .in.with-info > .info {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.6rem;
  border-top: 0;                      /* A4: and no rule of its own */
  padding-top: 1.6rem;
}
section.gt-block.intro .chef-label {
  display: inline-flex;
  align-items: center;
  gap: 1.2rem;
}
section.gt-block.intro .chef-label__img img {
  width: 4.4rem; height: 4.4rem; border-radius: 50%; display: block;
}
section.gt-block.intro .chef-label strong {
  font-weight: 400; font-size: 1.7rem; color: #fff;
}
section.gt-block.intro .date { font-weight: 400; opacity: .92; }

/* --- A5: the card and the photograph are both rounded ------------------- */
/*
 * The mockup's hero is one rounded card with the photograph laid over its
 * right-hand end, itself rounded, so the join is two curves rather than the
 * hard vertical split the live page had.
 */
/*
 * How the mockup actually draws it, which took a magnifying glass: the maroon
 * is the whole card, the photograph is laid ON it at the right, and the
 * photograph's BOTTOM-LEFT corner is rounded so that a curve of maroon shows
 * through underneath it. The top-left stays square, so the two meet in a
 * straight line at the top. That is the "slightly overlapping, with a rounded
 * corner" of item A5 — not a gap between two rectangles, which is what the
 * live page had, and not a photograph rounded on all four sides either.
 */
section.gt-block.intro.bgcolor-kitchen-guide { border-radius: 3rem; }
section.gt-block.intro .img {
  border-radius: 0 3rem 3rem 3rem;
  overflow: hidden;
}

/* --- A6: the Share tab -------------------------------------------------- */
.share-line {
  background: rgba(255, 255, 255, .88) !important;
  border-radius: 0 0 0 3rem !important;
  display: flex !important;
  align-items: center;
  gap: 1.8rem;
}
.share-line__label { font-weight: 700; font-size: 1.5rem; }
.share-line .menu { display: flex; align-items: center; gap: 1.2rem; margin: 0; }
.share-line .menu li { margin: 0; }

/* --- B1/B2: the strip under the hero ------------------------------------ */
.ttc-herobar__in { border-radius: 3rem; }
.ttc-herobar__cal { color: #1a2428; }
.ttc-herobar__cal strong { color: #51000d; font-weight: 700; }
.ttc-herobar__cal a { color: #51000d; font-weight: 700; text-decoration: underline; }

/* --- C2: Jump to Recipe, in markup rather than as a picture ------------- */
.ttc-jump {
  display: inline-flex;
  align-items: center;
  gap: 1.2rem;
  background: #51000d;
  color: #fff;
  font-weight: 700;
  font-size: 1.8rem;
  line-height: 1;
  padding: 1.3rem 2.6rem 1.3rem 1.3rem;
  border-radius: 999px;
  text-decoration: none;
}
.ttc-jump:hover { background: #6b0212; color: #fff; text-decoration: none; }
.ttc-jump__chev { display: inline-flex; }
.ttc-jump__chev svg { width: 2.8rem; height: 2.8rem; display: block; }

/* --- D4: the recipe card's header, two rows ----------------------------- */
/*
 * The doubled prefix is not decoration: this card sits inside `.ch-recipe`,
 * and the block that made `.ttc-card__head` a flex row is written
 * `.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__head` — five classes,
 * which a bare `.ttc-card__head` later in the same file loses to in silence.
 */
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__head,
.ttc-card__head { display: block; }
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__row,
.ttc-card__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.6rem 2.4rem;
  flex-wrap: wrap;
}
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__row--top,
.ttc-card__row--top { margin: 0 0 1.6rem; }
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__ident,
.ttc-card__ident {
  display: flex;
  align-items: center;
  gap: 1.8rem;
  flex-wrap: wrap;
}
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__head .ttc-card__stats,
.ttc-card__head .ttc-card__stats { border: 0; padding: 0; margin: 0; }
/* Everything on the maroon card is white — item D4. */
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__head,
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__head a,
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__head strong,
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__head span,
.ttc-card__head, .ttc-card__head a,
.ttc-card__head strong, .ttc-card__head span { color: #fff; }
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-card__head .ttc-pill,
.ttc-card__head .ttc-pill { color: #1a2428; }

/* --- F5: the nutrition card's own outline ------------------------------- */
/*
 * Everything else about this box — the cream, the pipe-separated line, the
 * bold note, the pills at the right of the heading — is in
 * static/site/nutrition.css, written against the same mockup and with the
 * same doubled prefix. Only the thin border and the padding were missing.
 */
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-nutrition,
.ttc-nutrition { border: 1px solid #d8c9a6; }
.ch-embed.ch-embed .ch-recipe.ch-recipe .ttc-nutrition .content > .text,
.ttc-nutrition .content > .text { padding: 2.8rem 3.2rem 3rem; }

/* --- A4 again: the author row has to be IN the flow --------------------- */
/*
 * The theme lays this row out with `position: absolute` — the row, the chef
 * label inside it and the date inside that, all three — pinned to the bottom
 * of the hero card. Absolutely positioned children take no part in their
 * parent's flex layout, which is why the row measured 12px tall with a 34px
 * portrait sitting in it: the rules were applying and had nothing to lay out.
 *
 * Put all three back in the flow, and the row becomes what the mockup draws:
 * portrait, name, and the date at the far right of the same line.
 */
section.gt-block.intro .content .in.with-info > .info,
section.gt-block.intro .content .in.with-info > .info,
section.gt-block.intro .content .in.with-info > .info .date {
  position: static;
}
/* The portrait is pinned by the theme with `position: absolute`, and it was
 * landing at the top-left of the hero -- next to the category pill -- because
 * the nearest positioned ancestor was the whole card. Give the label itself a
 * position and the portrait comes home; the padding is the room it needs. */
section.gt-block.intro .content .in.with-info > .info .chef-label {
  position: relative;
  padding-left: 5.8rem;
  min-height: 4.4rem;
}
section.gt-block.intro .content .in.with-info > .info {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.6rem;
  margin-top: 2rem;
}
section.gt-block.intro .content .in.with-info > .info .date {
  text-align: right;
  white-space: nowrap;
}


/* --- D1: the Ko-fi button's shape --------------------------------------- */
/* A rounded rectangle in the mockup, not a full pill. */
.ttc-kofi__btn { border-radius: 1.4rem; }

/* --- G1: "Directions:" is the same label as "Recipe:" ------------------- */
/*
 * They are the two labels of the recipe and the mockup writes them the same
 * way -- same maroon, same weight, same size, both left. The live page drew
 * Directions bigger and heavier, which made it read as a level above.
 *
 * The doubled prefix and the element in the selector are there to outrank
 * the mirrored stylesheet, which sets `h2` inside `.ch-recipe` at 2.6rem.
 */
.ch-embed.ch-embed .ch-recipe.ch-recipe h2.directions-title,
h2.directions-title {
  color: #51000d;
  font-size: 2.4rem;
  line-height: 2.9rem;
  font-weight: 700;
  text-align: left;
  margin: 0 0 2rem;
}

/* --- E1: the tools read as the mockup draws them ------------------------ */
/*
 * In the mockup every tool is bold and in the body's ink; the qualifier after
 * one ("(optionally)") is the only part set lighter. Ours were all at 300,
 * which made the whole box read as a caption beside the ingredients.
 */
.ch-embed.ch-embed .ch-recipe.ch-recipe .tools li,
.ch-embed.ch-embed .ch-recipe.ch-recipe .tools p:not(.ttc-sign),
.tools li,
.tools p:not(.ttc-sign) {
  font-weight: 700;
  color: #1a2428;
}

/* --- E2: an ingredient you have already put in the bowl ----------------- */
.ttc-tickable { cursor: pointer; }
.ch-embed.ch-embed .ch-recipe.ch-recipe .ingredients li.is-ticked,
.ingredients li.is-ticked {
  /* The mockup's rule runs past the words, so it is drawn rather than set as
     a text decoration — a decoration stops where the text does. */
  position: relative;
  opacity: .55;
}
.ch-embed.ch-embed .ch-recipe.ch-recipe .ingredients li.is-ticked::after,
.ingredients li.is-ticked::after {
  content: "";
  position: absolute;
  left: 0;
  right: -4rem;
  top: .95em;
  height: 1px;
  background: currentColor;
  pointer-events: none;
}
.ttc-tickable:focus-visible { outline: 2px solid #51000d; outline-offset: 2px; }

/* ROUND 17, JOB 17.2c. THE REVIEWS MOUNT SITS FLUSH WITH ITS NEIGHBOURS.
   Measured on the deployed release: the block below the reviews has its `.text`
   at 79px (1440) and 20px (390) with padding-left 0, while the reviews block's
   own `.text` carried 38.4px and 20px of padding and pushed the mount to 117
   and 40. That difference is the inset Tom has been pointing at. It is ours,
   not the widget's, so it goes here; the widget's own inner inset is zeroed
   from the mount div with data-inset="0". */
.ttc-reviews-embed > .content > .text {
  /* Belt and braces behind the `without-box` class the block now carries: the
     theme's own opt-out does the work, and this catches the case where a
     future template drops that class. It deliberately does NOT use
     !important -- the rule that was winning is eight classes deep, and
     out-shouting it would hide the real mechanism. */
  padding-left: 0;
  padding-right: 0;
}

/* ROUND 38, JOB 39.17. THE STEPS: THE NUMBER AND ITS STEP WERE ON SEPARATE
   LINES ON A PHONE, AND THE LEVELS WERE NOT TOLD APART ANYWHERE.
   ------------------------------------------------------------------------
   MEASURED on /recipes/dutch-schnitzel-holandsky-rizek/ at 1250 and at 390:

                        1250                  390
       step-level-1   x 68   pad 27.6px     x 40   pad 0
       step-level-2   x 96   pad 27.6px     x 40   pad 0
       step-level-3   x 124  pad 35.3px     x 40   pad 42.7px
       .mark          position: absolute at BOTH widths
       h2 / h3 / h4   18.43 / 12.29 / 12.29 px   22.27 / 14.85 / 14.85

   TWO FAULTS.
   1. The mark hangs in the step's left padding. At phone width the theme
      takes that padding off levels 1 and 2 -- and leaves it on level 3 -- so
      the number has no gutter and drops onto its own line above the heading.
      That is Tom's "1." on one line with the title beneath it, and "1.1."
      adrift above its own sentence. With every level at x 40 the cascade is
      gone too, so a level-3 step whose mark restarts at "1." is
      indistinguishable from a level-1 step numbered "1.".
   2. On the desktop levels 2 and 3 render at the SAME 12.29px, and both
      smaller than the body text they introduce. The only thing separating a
      sub-section from a sub-sub-section is 28px of indent.

   WHY THESE SELECTORS. The rules that win here are the theme's
   `.ch-embed.ch-embed .ch-recipe.ch-recipe ...` set -- four classes -- and
   one of them is `... * { margin-top: 0 }`, which beats anything shorter.
   Matching that shape is how the sheet already reaches this markup (see the
   ingredients rule above); out-shouting it with !important would hide the
   mechanism. `section.gt-block.recipe-content` is in the selector for the
   same reason and not for decoration: the theme's own size rule carries it,
   and a first attempt without it lost -- the margins took and the font sizes
   did not move at all. The sizes are in `--ch-rem`, the embed's own unit, so they scale
   with it exactly as the theme's do: the level-1 heading is 2.4 of them.  */
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content .step.step-level-2 > h3 {
  font-size: calc(1.9 * var(--ch-rem)); font-weight: 600;
}
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content .step.step-level-3 > h4 {
  font-size: calc(1.6 * var(--ch-rem)); font-weight: 500;
}
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content .step.step-level-4 > h5 {
  font-size: calc(1.45 * var(--ch-rem)); font-weight: 500;
}

/* SPACING. Every .step measured margin-top: 0 at every level, so nothing
   separates one step from the next but the paragraph's own margin. A step is
   a unit and gets air above it; a new numbered section gets more. */
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content .step.step-level-2,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content .step.step-level-3,
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content .step.step-level-4 {
  margin-top: calc(1.4 * var(--ch-rem));
}
.ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content .step.step-level-1 + .step.step-level-1 {
  margin-top: calc(2.6 * var(--ch-rem));
}

@media (max-width: 767px) {
  /* the gutter the mark hangs in, back at every level, and an even cascade
     on top of it -- smaller than the desktop's 28px because the column is
     310px wide, but present and the same at every step down */
  /* NO margin-left on top of this. A step sits INSIDE its parent, so the
     parent's gutter already indents it: measured 40 / 79 / 125 for levels
     1, 2 and 3 with the padding alone. A margin as well took level 3's text
     to 157px of a 350px column, which is the squashing this job is against. */
  .ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content .step.step-level-1,
  .ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content .step.step-level-2,
  .ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content .step.step-level-3,
  .ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content .step.step-level-4 {
    padding-left: calc(3.2 * var(--ch-rem));
    box-sizing: border-box;
  }
  /* AND THE NUMBER BACK ON THE SAME LINE AS ITS STEP.
     The mark is absolutely positioned at the STEP's top-left. At phone width
     the heading does not start at the step's top -- MEASURED, step y 7874 and
     h2 y 7911, thirty-seven pixels apart -- so the number floated above the
     title with nothing beside it. That is Tom's "1." on one line and "Dutch
     Schnitzel" on the next.
     It is taken out of absolute positioning and hung instead: the step's left
     padding is the gutter and the heading pulls its FIRST line back into it
     with a matching negative indent. A hanging indent cannot drift from its
     own first line, whatever the spacing above it does. */
  .ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content .step > h2 .mark,
  .ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content .step > h3 .mark,
  .ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content .step > h4 .mark,
  .ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content .step > h5 .mark {
    position: static;
    display: inline;
    margin-right: .45em;
  }
  .ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content .step > h2,
  .ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content .step > h3,
  .ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content .step > h4,
  .ch-embed.ch-embed .ch-recipe.ch-recipe section.gt-block.recipe-content .step > h5 {
    text-indent: calc(-3.2 * var(--ch-rem));
  }
}
