
/* ===========================================================================
   Editorial layer, 2026-09-01.

   Same brand (chocolate, berry, cream, Marcellus + Lato), applied with more
   restraint. What changed and why:

   - The homepage led with a logo, a name and a tagline. That spends the most
     valuable space on the page telling people the name of the site they are
     already on. It now leads with a story.
   - Almost everything was centred. Centred text is fine for a label and bad
     for a paragraph, and page after page of it reads as a template default.
     Long-form is left aligned now.
   - The type scale was timid: an h2 was barely larger than body copy, so
     nothing announced itself. There is a real scale now.
   - Card shadows did the work that alignment should do. Cards are flat, with
     a hairline and a fixed image ratio so the grid actually lines up.

   Loaded after style.css, so it deliberately overrides parts of it.
   =========================================================================== */

:root {
  /* A calmer ground than the old #F5EDE4. Same family, less saturation, so
     photography and the berry accent both have somewhere to sit. */
  --paper: #FBF8F4;
  --surface: #FFFFFF;
  --rule: #E7DDD1;
  /* Warm neutral biased toward the chocolate rather than a flat grey. */
  --ink-soft: #6E5849;
  --measure: 68ch;
}

body { background: var(--paper); }

/* --- shared type -------------------------------------------------------- */

.eyebrow,
.card-meta {
  display: block;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--berry);
}

.textlink {
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--chocolate-dark);
  text-decoration: none;
  border-bottom: 1px solid rgba(59, 35, 24, 0.25);
  padding-bottom: 1px;
  white-space: nowrap;
}
.textlink:hover { border-bottom-color: var(--berry); color: var(--berry); text-decoration: none; }

/* --- the lead story ----------------------------------------------------- */

.lead {
  border-bottom: 1px solid var(--rule);
  padding: 72px 0 76px;
}
.lead-inner {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: 64px;
  align-items: center;
}
.lead-copy h1 {
  font-size: clamp(2.3rem, 4.4vw, 3.6rem);
  line-height: 1.08;
  margin: 14px 0 20px;
  text-wrap: balance;
}
.lead-copy h1 a { color: inherit; text-decoration: none; }
.lead-copy h1 a:hover { color: var(--berry); }
.lead-excerpt {
  font-size: 1.12rem;
  line-height: 1.6;
  color: var(--ink-soft);
  margin: 0 0 26px;
  max-width: 48ch;
}
.lead-art {
  display: block;
  overflow: hidden;
  border-radius: 2px;
}
.lead-art img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  display: block;
  transition: transform 480ms cubic-bezier(.2, .7, .3, 1);
}
.lead-art:hover img { transform: scale(1.02); }

/* --- the promise strip -------------------------------------------------- */

.promise {
  background: var(--surface);
  border-bottom: 1px solid var(--rule);
  padding: 30px 0;
}
/* Was a colored left rail per item -- the single most common "an AI made
   this" card device there is. First replacement (numbered 01/02/03
   markers) was itself the same class of problem twice over: still a
   generic ornament, and worse, FALSE STRUCTURE -- "honest serving sizes /
   macros on every recipe / nothing exotic" is not a sequence, and
   numbering it implies an order that is not there. Settled on pure
   subtraction instead: no device at all, just room. The type is doing
   the work now, which is what the redesign's own stated intent already
   argued for elsewhere in this file ("the typography scale was timid").
   Extra gap (was 34px) gives each statement the air a rail or a numeral
   used to fake. */
.promise ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 44px;
}
.promise li {
  font-size: 0.93rem;
  line-height: 1.55;
  color: var(--ink-soft);
}
.promise strong { display: block; margin-bottom: 4px; color: var(--chocolate-dark); font-weight: 700; }

/* --- sections ----------------------------------------------------------- */

.section { padding: 68px 0; }
.section--tint { background: var(--surface); border-top: 1px solid var(--rule); }
.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 30px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--rule);
}
.section-head h2 {
  margin: 0;
  font-size: clamp(1.5rem, 2.4vw, 2rem);
  line-height: 1.15;
}

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

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(268px, 1fr));
  gap: 40px 30px;
}
.card {
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  overflow: visible;
}
.card-link { display: block; text-decoration: none; color: inherit; }
.card-img-wrap {
  overflow: hidden;
  margin-bottom: 15px;
  background: var(--rule);
  border-radius: 2px;
}
.card-img-wrap img {
  width: 100%;
  /* Fixed ratio is what makes the grid line up. Without it every card is as
     tall as its own photo and the baselines wander. */
  aspect-ratio: 4 / 5;
  object-fit: cover;
  display: block;
  transition: transform 480ms cubic-bezier(.2, .7, .3, 1);
}
.card-link:hover .card-img-wrap img { transform: scale(1.03); }
.card-body { padding: 0; }
.card-body h3 {
  margin: 8px 0 8px;
  font-size: 1.16rem;
  line-height: 1.25;
  text-wrap: balance;
}
.card-link:hover .card-body h3 { color: var(--berry); }
.card-excerpt {
  margin: 0;
  font-size: 0.93rem;
  line-height: 1.6;
  color: var(--ink-soft);
  /* Three lines, so a long description cannot shove one card out of line. */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* --- categories --------------------------------------------------------- */

.cat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(232px, 1fr));
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
}
.cat {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 22px 24px;
  background: var(--surface);
  text-decoration: none;
  color: inherit;
  transition: background 160ms ease;
}
.cat:hover { background: var(--paper); text-decoration: none; }
.cat-name { font-family: "Marcellus", Georgia, serif; font-size: 1.1rem; color: var(--chocolate-dark); }
.cat-count { font-size: 0.8rem; color: var(--ink-soft); font-variant-numeric: tabular-nums; }

/* --- post page ---------------------------------------------------------- */

.post-header { padding: 56px 0 0; text-align: left; }
.post-header .container { max-width: var(--measure); }
.post-header h1 {
  max-width: 26ch;
  margin-left: 0;
  margin-right: 0;
  font-size: clamp(2.1rem, 3.8vw, 3rem);
  line-height: 1.12;
  margin: 14px 0 18px;
  text-wrap: balance;
}
.post-meta {
  display: flex;
  flex-wrap: wrap;
  /* style.css centres this and caps the h1 at 22ch with auto margins, which
     pulls the whole header back to the middle. Both are overridden here. */
  justify-content: flex-start;
  gap: 18px;
  padding: 14px 0 0;
  border-top: 1px solid var(--rule);
  font-size: 0.85rem;
  color: var(--ink-soft);
}
.post-body { max-width: var(--measure); font-size: 1.06rem; line-height: 1.72; }
.post-body h2 {
  margin: 44px 0 14px;
  font-size: 1.6rem;
  line-height: 1.2;
}
.post-body h3 { margin: 32px 0 10px; font-size: 1.2rem; }
.post-body p { margin: 0 0 20px; }
.post-body a { color: var(--berry); text-decoration: underline; text-underline-offset: 2px; }

/* The post hero is a real photograph or it is nothing. A shared brand banner
   stretched across the top of every article is what a template does. */
.post-hero { margin: 0; }
.post-hero img {
  width: 100%;
  max-height: 520px;
  object-fit: cover;
  display: block;
}

/* --- header ------------------------------------------------------------- */

.site-header {
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
  box-shadow: none;
}
.site-nav a {
  font-size: 0.88rem;
  letter-spacing: 0.02em;
}
.nav-cta {
  color: var(--berry);
  font-weight: 700;
}

@media (max-width: 900px) {
  .lead { padding: 40px 0 44px; }
  .lead-inner { grid-template-columns: 1fr; gap: 28px; }
  .lead-art { order: -1; }
  .lead-art img { aspect-ratio: 3 / 2; }
  .promise ul { grid-template-columns: 1fr; gap: 16px; }
  .section { padding: 46px 0; }
  .card-grid { gap: 32px 20px; }
  .post-header { padding: 34px 0 0; }
}

/* --- photo category tiles + card badges ---------------------------------
   From the competitor teardown: The Big Man's World opens on a mosaic of
   photographed category tiles, and Minimalist Baker puts a dietary chip on
   every card. The chip is the one worth copying hardest here, because this
   audience over-indexes on Special Diet (3.52) and browses by constraint.  */

.cat-grid {
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 14px;
  background: transparent;
  border: 0;
}
.cat {
  position: relative;
  display: block;
  padding: 0;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: 3px;
  background: var(--chocolate-dark);
}
.cat img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  opacity: 0.72;
  transition: transform 520ms cubic-bezier(.2,.7,.3,1), opacity 300ms ease;
}
.cat:hover { background: var(--chocolate-dark); }
.cat:hover img { transform: scale(1.05); opacity: 0.6; }
.cat-label {
  position: absolute;
  inset: auto 0 0 0;
  padding: 34px 16px 14px;
  display: flex;
  flex-direction: column;
  gap: 1px;
  /* A scrim, not a flat tint: text stays legible over any photograph. */
  background: linear-gradient(to top, rgba(20,9,4,0.86) 0%, rgba(20,9,4,0.45) 55%, rgba(20,9,4,0) 100%);
}
.cat-name { color: #FFF8F0; font-size: 1.02rem; line-height: 1.15; }
.cat-count { color: rgba(255,248,240,0.72); font-size: 0.76rem; }

.card-img-wrap { position: relative; }
.card-badge {
  position: absolute;
  left: 10px;
  top: 10px;
  padding: 5px 9px;
  border-radius: 2px;
  background: rgba(255, 253, 250, 0.94);
  color: var(--chocolate-dark);
  font-size: 0.63rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  backdrop-filter: blur(2px);
}

@media (max-width: 640px) {
  .cat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .cat-name { font-size: 0.9rem; }
}

/* Categories index: bigger tiles than the homepage strip (this page is only
   about categories, so they get to be the content), plus the descriptions
   underneath so the page has something to read. */
.cat-grid--index { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 18px; }
.cat-grid--index .cat { aspect-ratio: 3 / 2; }
.cat-grid--index .cat-name { font-size: 1.25rem; }

.cat-notes {
  margin-top: 54px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 30px 44px;
}
.cat-note h2 { margin: 0 0 6px; font-size: 1.12rem; }
.cat-note h2 a { color: var(--chocolate-dark); text-decoration: none; }
.cat-note h2 a:hover { color: var(--berry); }
.cat-note p { margin: 0; font-size: 0.94rem; line-height: 1.6; color: var(--ink-soft); }

.page-header { padding: 54px 0 26px; }
.page-header h1 { margin: 0 0 8px; }
.page-header p { margin: 0; color: var(--ink-soft); }


/* --- display face -------------------------------------------------------
   Marcellus is a humanist serif with calligraphic flare in the curves, which
   reads warm rather than expensive. Bodoni Moda is a Didone: near-vertical
   stress, flat unbracketed serifs, very fine hairlines. It is the face the
   fashion houses use, and it is what "thin, straight, luxury" actually means
   typographically.

   Display only. Bodoni's hairlines get fragile below about 18px, so body copy,
   UI and anything small stays on Lato. That split is the whole reason it works.  */
@font-face {
  font-family: "Bodoni Moda";
  src: url("/fonts/BodoniModa.woff2") format("woff2");
  font-weight: 400 500;
  font-style: normal;
  font-display: swap;
}

h1, h2, h3, h4,
.brand-word,
.cat-name,
.cb-price-num,
.cb-facts strong {
  font-family: "Bodoni Moda", "Didot", "Bodoni MT", Georgia, serif;
  font-weight: 400;
  letter-spacing: -0.005em;
}

/* Didones want a little more air between lines than a humanist serif, and the
   thin strokes read better when they are not crammed. */
.lead-copy h1 { line-height: 1.1; letter-spacing: -0.01em; }
.post-header h1 { line-height: 1.14; letter-spacing: -0.01em; }
.post-body h2 { letter-spacing: -0.005em; }

/* The card title is the smallest place the display face appears. Nudge it up so
   the hairlines survive. */
.card-body h3 { font-size: 1.2rem; line-height: 1.28; }

/* --- recipe card, from the visual audit ---------------------------------
   Three things on a recipe post:
   - the card's title and description were centred while the entire page around
     them is left aligned, so the card read as a different design bolted on
   - the card is wider than the body measure, so its left edge did not line up
     with the paragraph directly above it
   - the nutrition rows broke alignment whenever a value carried a
     parenthetical ("20g (natural, from banana)"), because a taller cell
     dragged its neighbours with it  */

.recipe-card {
  max-width: var(--measure);
  margin-left: auto;
  margin-right: auto;
}
.recipe-card-header { text-align: left; }

/* Top-align the cells so a wrapping value grows downward on its own instead of
   shifting the row it sits in. */
.nutrition-grid { align-items: start; }
.nutrition-grid .n-item {
  align-items: baseline;
  gap: 14px;
}
.nutrition-grid .n-item strong {
  text-align: right;
  line-height: 1.35;
}

/* --- mobile nav ---------------------------------------------------------
   The open menu was a third flex item on a non-wrapping, centre-aligned header
   row, so it rendered as a narrow column BESIDE the logo with its first links
   sitting above the brand line. It read as a layout accident, on the viewport
   that carries most of the traffic.

   Made a panel anchored under the header instead of an item inside it, so the
   header row keeps its own layout and the menu cannot interfere with it.  */
@media (max-width: 860px) {
  .site-header { position: relative; }
  .site-header .container { flex-wrap: nowrap; }

  .site-nav {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 40;
    background: var(--paper);
    border-bottom: 1px solid var(--rule);
    box-shadow: 0 14px 28px rgba(35, 16, 9, 0.10);
    padding: 6px 20px 14px;
    gap: 0;
  }
  .site-nav a {
    padding: 14px 2px;
    font-size: 1rem;
    border-bottom: 1px solid var(--rule);
  }
  .site-nav a:last-child { border-bottom: 0; }
  .nav-cta { color: var(--berry); }
}

/* The icon never changed state, so an open menu still showed a hamburger.
   Swap to a close glyph while it is open. */
.nav-toggle[aria-expanded="true"] svg { display: none; }
.nav-toggle[aria-expanded="true"]::after {
  content: "\00d7";
  display: block;
  font-size: 26px;
  line-height: 1;
  color: var(--chocolate-dark);
}

/* --- polish pass, from the independent visual audit --------------------- */

/* Homepage category strip was 4-up, leaving a two-slot hole on the second row
   with six categories. Three columns divides evenly. */
@media (min-width: 861px) {
  .cat-grid:not(.cat-grid--index) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Bodoni below its own floor. The CSS comment says display only, hairlines get
   fragile under about 18px, and four selectors were sitting at 16 to 17px. The
   worst is the tile label, which is thin white type reversed out over a
   photograph. Raised above the floor. */
.cat-name { font-size: 1.18rem; }
.cat-grid--index .cat-name { font-size: 1.3rem; }
.roundup-item h3 { font-size: 1.22rem; }
.cb-card h3, .cb-bonus h3 { font-size: 1.24rem; }

/* Reversed-out Bodoni needs a touch more weight against a photo, or the
   hairlines disappear into the image entirely. */
.cat-label { text-shadow: 0 1px 12px rgba(20, 9, 4, 0.55); }

/* "No serving-size games." was breaking after the hyphen on mobile. */
.optin-form-copy h2 { text-wrap: balance; }
.nowrap { white-space: nowrap; }

/* The 404 section head orphaned "these" onto its own line at 390px because the
   heading and the link shared a row. Stack them on narrow screens. */
@media (max-width: 560px) {
  .section-head { flex-direction: column; align-items: flex-start; gap: 8px; }
  .section-head h2 { text-wrap: balance; }
}

/* The closing CTA is LIGHT now (see .cb-final in style.css), so everything inside
   it that was coloured FOR a dark background has to be re-coloured or it vanishes.
   Doing it here rather than in style.css because this sheet loads second and wins:
   the first attempt set .cb-honest in style.css and the rule below silently beat it,
   shipping an invisible paragraph that only its berry link gave away.
   Every rule is scoped to .cb-final on purpose. The hero at the top of the same page
   is STILL dark and shares these exact classes, so an unscoped fix would make the
   hero's price unreadable while fixing the footer's. */
.cb-final .cb-honest { color: var(--chocolate-light); }
.cb-final .cb-price-num { color: var(--chocolate-dark); }
.cb-final .cb-price-note { color: var(--chocolate-light); }


/* Mobile nutrition: the Sugar value carried a parenthetical that wrapped one
   word per line and made its row four lines tall. Let the value keep its own
   column and wrap normally instead of being squeezed against the label. */
@media (max-width: 560px) {
  .nutrition-grid .n-item { gap: 10px; }
  .nutrition-grid .n-item strong { flex: 1 1 auto; min-width: 0; text-align: right; }
}

/* --- the two download cards on the thank-you page ----------------------- */
.dl-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 20px;
  margin: 28px 0 32px;
}
.dl-card {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 22px 22px 24px;
  background: var(--surface);
}
.dl-tag {
  display: inline-block;
  margin-bottom: 8px;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--berry);
}
.dl-card h2 { margin: 0 0 8px; font-size: 1.24rem; }
.dl-card p { margin: 0 0 16px; font-size: 0.93rem; line-height: 1.6; color: var(--ink-soft); }
/* The honest caveat under the book edition: what it is NOT good at. Sits quieter
   than the description above it (smaller, lighter, no bottom margin fighting the
   button) because it is a footnote, not a selling point. Uses the same tokens as
   the rest of the card so it reads as part of it rather than a warning bolted on. */
.dl-card .dl-note {
  margin: -8px 0 16px;
  font-size: 0.85rem;
  line-height: 1.55;
  color: var(--ink-soft);
  opacity: 0.8;
}
.download-cta--quiet {
  background: transparent;
  color: var(--chocolate-dark);
  border: 1px solid rgba(59, 35, 24, 0.22);
}
.download-cta--quiet:hover { background: var(--paper); }

/* ===========================================================================
   Kitchen features, 2026-09-02: search, index filters, cook mode, ingredient
   checkboxes, the serving scaler, print, and the motion pass. Same tokens,
   same restraint. Anything that needs JS ships [hidden] and is revealed by
   site.js, so a dead control can never render.
   =========================================================================== */

/* --- header search ------------------------------------------------------ */

.header-actions { display: flex; align-items: center; gap: 10px; }

.search-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border-radius: 10px;
  border: 1px solid rgba(59, 35, 24, 0.2);
  background: var(--white);
  cursor: pointer;
}
.search-toggle svg { width: 20px; height: 20px; stroke: var(--chocolate-dark); }

.site-search { position: relative; }
.search-form {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--surface);
}
.search-form:focus-within { border-color: var(--berry); }
.search-glyph { width: 15px; height: 15px; flex: none; stroke: var(--ink-soft); }
.search-input {
  border: 0;
  outline: 0;
  background: transparent;
  font-family: inherit;
  font-size: 0.92rem;
  color: var(--chocolate-dark);
  width: 168px;
}
.search-input::placeholder { color: var(--ink-soft); opacity: 0.8; }
.search-input::-webkit-search-decoration { -webkit-appearance: none; }

.search-results {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  width: min(400px, 92vw);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 3px;
  box-shadow: 0 18px 40px rgba(35, 16, 9, 0.14);
  overflow: hidden;
  z-index: 60;
}
.search-hit {
  display: block;
  padding: 11px 16px;
  text-decoration: none;
  color: inherit;
  border-bottom: 1px solid var(--rule);
}
.search-hit:hover, .search-hit:focus { background: var(--paper); text-decoration: none; }
.search-hit-title {
  display: block;
  font-weight: 700;
  font-size: 0.95rem;
  line-height: 1.35;
  color: var(--chocolate-dark);
}
.search-hit-meta { display: block; margin-top: 2px; font-size: 0.78rem; color: var(--ink-soft); }
.search-all {
  display: block;
  padding: 11px 16px;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--berry);
  text-decoration: none;
}
.search-all:hover { background: var(--paper); text-decoration: none; }
.search-none { margin: 0; padding: 13px 16px; font-size: 0.9rem; color: var(--ink-soft); }

/* Desktop: the input sits in the header row, the way every recipe site she
   already uses does it. The icon button is mobile furniture. */
@media (min-width: 861px) {
  /* The whole actions cluster is mobile furniture: the nav toggle is already
     display:none up here, and hiding the wrapper too keeps the header's
     space-between rhythm at three real items (brand, search, nav). */
  .header-actions { display: none; }
}

/* Mobile: a panel under the header, same treatment as the nav panel, opened
   from an icon that only exists once JS is running. */
@media (max-width: 860px) {
  .site-search {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 41;
    background: var(--paper);
    border-bottom: 1px solid var(--rule);
    box-shadow: 0 14px 28px rgba(35, 16, 9, 0.10);
    padding: 12px 20px 14px;
  }
  .site-search.is-open { display: block; }
  .search-results {
    position: static;
    width: auto;
    margin-top: 10px;
    box-shadow: none;
  }
  .search-input { width: 100%; flex: 1 1 auto; font-size: 1rem; }
}

/* --- recipes index: filter bar ------------------------------------------ */

.filter-bar { margin: -6px 0 34px; }
.filter-chips { display: flex; flex-wrap: wrap; gap: 10px; }
.filter-chip {
  font-family: inherit;
  cursor: pointer;
  line-height: 1.2;
  /* chip base (style.css) is a fully-rounded 999px pill. Match the
     card grid established near-square language instead. */
  border-radius: 2px;
}
.filter-chip.is-active {
  background: var(--chocolate-dark);
  border-color: var(--chocolate-dark);
  color: var(--white);
}
.filter-chip.is-active:hover { background: var(--chocolate); border-color: var(--chocolate); }
.chip-count { font-weight: 400; font-size: 0.82em; opacity: 0.65; }
.filter-status { margin: 14px 0 0; font-size: 0.88rem; color: var(--ink-soft); }
.filter-clear {
  background: none;
  border: 0;
  padding: 0 0 1px;
  cursor: pointer;
  font-family: inherit;
  font-size: 0.88rem;
}
.filter-empty { padding: 26px 0 8px; color: var(--ink-soft); }
.filter-empty p { margin: 0; }
.card[hidden] { display: none; }

/* --- cook mode ----------------------------------------------------------- */

.cook-mode {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 14px;
  margin: 20px 0 2px;
}
.cook-mode-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 16px;
  border-radius: 999px;
  border: 1px solid rgba(59, 35, 24, 0.22);
  background: var(--surface);
  color: var(--chocolate-dark);
  font-family: inherit;
  font-weight: 700;
  font-size: 0.88rem;
  cursor: pointer;
}
.cook-mode-btn svg { width: 15px; height: 15px; }
.cook-mode-btn[aria-pressed="true"] {
  background: var(--berry);
  border-color: var(--berry);
  color: var(--white);
}
.cook-mode-hint { font-size: 0.82rem; color: var(--ink-soft); }

/* --- ingredient checkboxes -----------------------------------------------
   Real checkboxes, styled to sit exactly where the old decorative gold square
   sat, so the list looks the same until you touch it. Works with JS off. */

.ingredients-list li.ing-item { padding: 0; }
.ingredients-list li.ing-item::before { display: none; }
.ing-label {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 9px 0;
  cursor: pointer;
}
.ing-check {
  appearance: none;
  -webkit-appearance: none;
  flex: none;
  width: 16px;
  height: 16px;
  margin: 4px 0 0;
  border-radius: 3px;
  background: var(--gold);
  border: 1px solid var(--berry);
  cursor: pointer;
  display: inline-grid;
  place-content: center;
}
.ing-check::before {
  content: "";
  width: 9px;
  height: 9px;
  transform: scale(0);
  background: var(--white);
  clip-path: polygon(14% 44%, 0 65%, 40% 100%, 100% 16%, 82% 2%, 38% 60%);
}
.ing-check:checked { background: var(--berry); }
.ing-check:checked::before { transform: scale(1); }
.ing-check:focus-visible { outline: 3px solid var(--berry); outline-offset: 2px; }
.ing-check:checked + .ing-text {
  color: var(--ink-soft);
  text-decoration: line-through;
  text-decoration-color: rgba(110, 88, 73, 0.55);
}
.ingredients-list li.ing-heading {
  padding: 16px 0 6px;
  font-weight: 700;
  color: var(--chocolate-dark);
  border-bottom: 0;
}
.ingredients-list li.ing-heading::before { display: none; }

/* --- serving scaler ------------------------------------------------------ */

.scale-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 14px;
  margin: 2px 0 14px;
}
.scale-label {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 900;
  color: var(--berry);
}
.scale-btns {
  display: inline-flex;
  border: 1px solid rgba(59, 35, 24, 0.22);
  border-radius: 999px;
  overflow: hidden;
  background: var(--surface);
}
.scale-btn {
  border: 0;
  background: transparent;
  font-family: inherit;
  font-weight: 700;
  font-size: 0.88rem;
  padding: 8px 14px;
  min-width: 44px;
  cursor: pointer;
  color: var(--chocolate-dark);
}
.scale-btn + .scale-btn { border-left: 1px solid rgba(59, 35, 24, 0.14); }
.scale-btn.is-active { background: var(--chocolate-dark); color: var(--white); }
.scale-note {
  flex-basis: 100%;
  margin: 0;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--ink-soft);
}
/* Scaled numbers get a quiet tint so it is always visible that the page is
   no longer showing the original quantities. */
.is-scaled .qty {
  background: rgba(231, 201, 160, 0.45);
  border-radius: 2px;
  padding: 0 1px;
  font-variant-numeric: tabular-nums;
}

/* --- print ---------------------------------------------------------------
   style.css already drops the header, footer, hero and opt-in. This finishes
   the job: a recipe page prints as the recipe card plus the tips, nothing
   else, sized to land on one sheet. */

@media print {
  .site-search, .header-actions, .search-results, .cook-mode, .scale-row,
  .cb-nudge, .ad-slot, .grid-section, .filter-bar, .filter-empty { display: none !important; }

  body.is-recipe .post-header,
  body.is-recipe .post-body:not(.post-notes) { display: none !important; }

  body { font-size: 12px; }
  body.is-recipe .recipe-card {
    max-width: 100%;
    margin: 0;
    padding: 0;
    border: 0;
    box-shadow: none;
  }
  .recipe-card-header { padding-bottom: 10px; margin-bottom: 10px; }
  .recipe-card h2 { font-size: 21px; }
  .recipe-card h3, .nutrition-box h3 { font-size: 14px; margin-top: 12px; break-after: avoid; }
  .recipe-meta-row { margin: 8px 0 12px; padding: 8px 10px; gap: 4px 10px; }
  .ing-label { padding: 3px 0; gap: 10px; }
  .ing-check { print-color-adjust: exact; -webkit-print-color-adjust: exact; }
  .ingredients-list li.ing-heading { padding: 8px 0 2px; }
  .instructions-list li { padding: 4px 0 4px 32px; }
  .instructions-list li::before {
    width: 20px; height: 20px; font-size: 11px; top: 3px;
    print-color-adjust: exact; -webkit-print-color-adjust: exact;
  }
  .ing-item, .instructions-list li, .nutrition-box { break-inside: avoid; }
  .nutrition-box { margin-top: 10px; padding: 8px 12px; }
  .nutrition-note { font-size: 9px; margin-top: 6px; }
  .post-notes { max-width: 100%; font-size: 12px; }
  .post-notes h2 { font-size: 15px; margin: 12px 0 6px; }
  .post-notes .ingredients-list li { padding: 3px 0 3px 22px; }
  .post-notes .ingredients-list li::before { top: 8px; width: 8px; height: 8px; }
  /* A scaled recipe prints its scaled numbers; only the highlight goes. */
  .is-scaled .qty { background: transparent; padding: 0; }
  .recipe-card::after {
    content: "thehealthycravings.com";
    display: block;
    margin-top: 14px;
    font-size: 10px;
    letter-spacing: 0.06em;
    color: #6E5849;
  }
}

/* --- motion --------------------------------------------------------------
   One idea per surface: pages settle in, below-the-fold cards rise as they
   arrive, and the things you touch acknowledge it. All of it sits inside a
   reduced-motion guard; with that preference set the site simply does not
   move. The scroll-reveal hidden state is applied by JS, never here, so a
   page without JS shows everything. */

@media (prefers-reduced-motion: no-preference) {
  @keyframes hc-rise {
    from { opacity: 0; transform: translateY(10px); }
    to { opacity: 1; transform: none; }
  }

  .post-header .container,
  .page-header .container { animation: hc-rise 0.5s cubic-bezier(0.2, 0.7, 0.3, 1) both; }
  .lead-copy { animation: hc-rise 0.55s cubic-bezier(0.2, 0.7, 0.3, 1) both; }
  .lead-art { animation: hc-rise 0.55s cubic-bezier(0.2, 0.7, 0.3, 1) 90ms both; }

  .reveal-pending {
    opacity: 0;
    transform: translateY(14px);
    transition:
      opacity 520ms cubic-bezier(0.2, 0.7, 0.3, 1),
      transform 520ms cubic-bezier(0.2, 0.7, 0.3, 1);
  }
  .reveal-pending.is-in { opacity: 1; transform: none; }

  .chip, .scale-btn, .cook-mode-btn, .print-btn, .textlink, .filter-clear,
  .search-form, .search-toggle, .nav-toggle, .site-nav a, .cat, .download-cta {
    transition:
      background-color 160ms ease, color 160ms ease,
      border-color 160ms ease, box-shadow 160ms ease, transform 120ms ease;
  }
  .chip:active, .scale-btn:active, .cook-mode-btn:active, .print-btn:active,
  .search-toggle:active, .nav-toggle:active, .download-cta:active {
    transform: translateY(1px);
  }
  .ing-check::before { transition: transform 140ms ease; }
}

/* A [hidden] control stays hidden even where a rule above sets display:flex.
   Author display beats the UA's [hidden] rule, and these are exactly the
   controls that must never render before JS takes them over. */
.scale-row[hidden], .cook-mode[hidden], .scale-note[hidden],
.search-results[hidden], .filter-bar[hidden], .filter-empty[hidden],
.search-toggle[hidden] { display: none !important; }


/* ===========================================================================
   Site design pass, 2026-09-03: removing the remaining generic-AI-page
   devices (a rail, a circle badge, a pill badge, centred index headers) and
   finishing the one deliberate device this brand actually earns: honest
   numbers get their own consistent look everywhere they appear.

   Two tiers, on purpose, not one: Bodoni Moda's hairlines are documented
   above (~line 383) as fragile below about 18px, so only numbers that are
   already large enough (the promise numerals, the roundup numbering, the
   new card calorie mark) switch to Bodoni. Small inline numbers (a
   nutrition-grid value, a roundup's "~90 cal") stay on Lato at their
   existing size, but pick up the same tabular figures and the same berry
   accent colour, so they still read as part of one system without asking
   Bodoni to render body-copy-sized text.
   =========================================================================== */

/* The nutrition heading on every single recipe page carried the exact same
   left rail as the homepage promise block (style.css, .nutrition-box h3).
   Same fix, same reasoning: a rule below the heading instead of a bar beside
   it, matching how .section-head already divides a heading from its content
   elsewhere on the site. */
.nutrition-box h3 {
  border-left: 0;
  padding-left: 0;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--rule);
}

/* Small inline figures: no font swap, just the shared colour + tabular
   alignment. */
.nutrition-grid .n-item strong {
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--berry);
}
.roundup-item .cal-badge {
  background: none;
  border-radius: 0;
  padding: 0;
  margin-left: 8px;
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--berry);
}

/* The roundup list's numbering was a filled gold circle, the generic
   "numbered avatar" list device. A bare Bodoni numeral reads as deliberate
   in a way a circle badge does not, and it is large enough (1.5rem) to keep
   Bodoni's hairlines intact. */
.roundup-item .num {
  width: auto;
  height: auto;
  border-radius: 0;
  background: none;
  font-family: "Bodoni Moda", "Didot", "Bodoni MT", Georgia, serif;
  font-variant-numeric: tabular-nums lining-nums;
  font-size: 1.5rem;
  line-height: 1.15;
  color: var(--gold);
  padding-top: 1px;
}

/* New: a calorie figure on recipe cards themselves (home "Latest", the
   recipes index, and category pages), so the brand's actual differentiator
   -- honest numbers -- shows up at the exact moment someone is deciding
   whether to click, not only after they land on the recipe. Large enough
   for Bodoni; the unit stays small Lato so it reads as a label, not a
   second number. */
.card-figure {
  margin: 2px 0 6px;
  display: flex;
  align-items: baseline;
  gap: 5px;
}
.card-figure-num {
  font-family: "Bodoni Moda", "Didot", "Bodoni MT", Georgia, serif;
  font-variant-numeric: tabular-nums lining-nums;
  font-size: 1.2rem;
  line-height: 1;
  color: var(--berry);
}
.card-figure-unit {
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* Left-aligned modifier for the three browse-surface page headers (all
   recipes, categories, one category). style.css's base .page-header is
   still centred for about.html (a single narrative bio block) and
   thank-you.html (a transactional confirmation) -- neither is a browse
   surface, and a centred single message is not the tell. */
.page-header--left,
.page-header--left p {
  text-align: left;
  margin-left: 0;
  margin-right: 0;
}

/* The homepage's new essay rail: a plain text list, deliberately not a
   card grid, so it reads as a different kind of content instead of more
   uniform photo cards. */
.guide-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 22px;
  max-width: var(--measure);
}
.guide-item {
  padding-bottom: 22px;
  border-bottom: 1px solid var(--rule);
}
.guide-item:last-child { border-bottom: 0; padding-bottom: 0; }
.guide-link {
  font-family: "Bodoni Moda", "Didot", "Bodoni MT", Georgia, serif;
  font-size: 1.15rem;
  color: var(--chocolate-dark);
  text-decoration: none;
}
.guide-link:hover { color: var(--berry); }
.guide-item p { margin: 6px 0 0; color: var(--ink-soft); font-size: 0.92rem; }


/* Two more of the same left-rail device (style.css), found by grepping for
   every remaining "border-left: Npx solid var(--berry|gold)" after the
   coordinator flagged that a fix applied where a symptom appeared had
   already missed a sibling three times in one day.

   .recipe-card h3 styles "Ingredients" and "Instructions" on every single
   recipe page (Nutrition already fixed above). Unlike the homepage promise
   block, these three headings genuinely ARE an ordered sequence within one
   recipe, so a plain divider (not a number, not a rail) fits without
   claiming false structure. */
.recipe-card h3 {
  border-left: 0;
  padding-left: 0;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--rule);
}

/* .cb-bonus: four bonus cards on the cookbook sales page, each with a berry
   left rail -- the same card-rail device, just on a page the earlier pass
   never opened. Each already carries its own "Up front" / "Bonus" label, so
   subtraction reads as complete rather than empty. */
.cb-bonus {
  border-left: 0;
  padding: 4px 0;
}

/* --- mobile pass: touch targets and one centred paragraph ----------------
   73.8% of this audience is on an iPhone, so 390px is the design width and a
   thumb is the pointer. Every rule in THIS block is scoped to phones and touch
   and leaves the 1440px rendering untouched, deliberately, because none of it
   is a visual complaint on a desktop where the pointer is a mouse. (Two later
   rules in this file are not scoped that way and say so where they sit.)
   These rules live at the END of editorial.css because this sheet loads after
   style.css, so nothing later can silently beat them. That is not paranoia:
   the first pass at the cookbook CTA set a colour in style.css, editorial.css
   overrode it, and the paragraph shipped invisible. */
@media (max-width: 860px), (hover: none) {

  /* Every control below measured under the 44px iOS minimum at 390px. The
     sizes are from a sweep of all 91 built pages, and each is corrected by
     padding rather than by switching display, so no inline layout moves:
     .filter-chip carries a count span beside its label, and turning it into a
     flex container is exactly how that spacing gets eaten. */

  /* Filter chips, 38px. The primary control on /recipes/, six of them. */
  .filter-chip { padding-top: 13px; padding-bottom: 13px; }

  /* Scale buttons, 33px, the worst on the site and the one tapped with batter
     on your hands. min-width was already set to 44px here, so the 44 rule was
     understood and the height was simply missed. */
  .scale-btn { padding-top: 14px; padding-bottom: 14px; }

  /* Cook mode 37px and print 40px. .btn was 42px and covers every primary
     button on the site: the opt-in submit, the 404 CTA and both cookbook
     buttons, all of which want the extra two pixels. */
  .cook-mode-btn { padding-top: 13px; padding-bottom: 13px; }
  .print-btn { padding-top: 13px; padding-bottom: 13px; }
  .btn { padding-top: 14px; padding-bottom: 14px; }

  /* Header icon buttons, 42px, two short. */
  .nav-toggle,
  .search-toggle { width: 44px; height: 44px; }

  /* Footer nav links were 28px tall in a wrapped row. Padding takes each to
     44 and the row-gap drops to zero to pay most of it back: a row was 28 plus
     16 of gap and is now 44 plus none, so the rows sit where they did and only
     the last one adds height. Measured: the nav block goes 72 to 88 on a phone,
     16px in a footer, and the link spacing looks unchanged. */
  .footer-nav { gap: 0 16px; }
  .footer-nav a { display: inline-block; padding: 8px 0; }

  /* "Jump to recipe" is 31px and exists purely to help a phone reader skip the
     intro, so it is the last link that should be hard to hit. Its underline is
     a border-bottom, so padding would detach the rule from the text. An
     invisible box extends the hit area instead and the link looks unchanged. */
  .jump-link { position: relative; }
  .jump-link::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: 44px;
    transform: translateY(-50%);
  }

  /* Roundup titles are links and were 31px tall. Laying the heading out as a
     flex row (see below) makes the link a block-level flex item sized to its
     own line box rather than an inline box carrying the heading's leading, so
     it measures 24px. Same invisible-box treatment, which repays the 7px and
     takes it past 44 at the same time. */
  .roundup-item h3 a { position: relative; }
  .roundup-item h3 a::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: 44px;
    transform: translateY(-50%);
  }
}

/* The opt-in supporting line is centred, which is right at 390px where it sets
   as two balanced lines. At 375px and below, which is the iPhone SE, the 13
   mini and the 12 mini, it becomes three lines and centring them individually
   leaves both edges ragged. Same defect as the cookbook honesty paragraph.
   Flush left inside the still-centred card below 390 only, so the design width
   is untouched. */
@media (max-width: 389px) {
  .optin-form-copy p { text-align: left; }
}

/* The roundup title and its calorie figure sit on one line, spaced by an 8px
   margin-left on the badge and nothing else (there is no whitespace between the
   two in the markup). When a title very nearly fills the line, the badge wraps
   onto a line of its own and carries that margin with it, so it lands 8px in
   from the title's left edge and lines up with nothing at all. Three items on
   the 27-desserts roundup do this at 390px.
   Laying the heading out as a wrapping flex row fixes the cause rather than the
   symptom: column-gap gives the same 8px between them on one line and simply
   does not exist at the start of a new one. */
.roundup-item h3 {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: 8px;
  row-gap: 2px;
}
.roundup-item .cal-badge { margin-left: 0; }

/* The cookbook nudge keeps a 84px art column beside the copy all the way down
   to 390px, which leaves the text 208px wide, about 26 characters, so the
   paragraph sets as ten stub lines and the heading breaks after "if". The
   cover is also centred against that tall column, so it floats with roughly
   170px of empty card above and below it. Stack them on a phone: the copy gets
   the full 310px and the cover sits above it at a sensible size. */
@media (max-width: 640px) {
  .cb-nudge {
    grid-template-columns: minmax(0, 1fr);
    gap: 16px;
    align-items: start;
  }
  .cb-nudge-art { width: 96px; }
}

/* .cb-final is the last block in <main> and .site-footer carries a 30px top
   margin, so 30px of the body's own paler cream shows between them. That was
   invisible while this block was dark chocolate. Now that it is cream, two
   near-identical creams meet at a hard edge and the strip reads as a mistake.
   Only the cookbook page ends on a full-bleed light band, so the gap is closed
   only there, and a browser without :has() simply keeps today's behaviour. */
body:has(.cb-final) .site-footer { margin-top: 0; }
