/* ==========================================================================
   recipes.hmpsandbox.com, single stylesheet
   1. Tokens   2. Base & typography   3. Shell   4. Shared components
   5. Index components   6. Recipe components
   7. DESK layout (wide screens)   8. POCKET layout (narrow screens)
   9. Print   10. Motion

   Design intent: a kitchen ledger. Warm grey paper, dark brown ink, a deep
   olive rule, and two voices of type: anything typeset is set in a grotesk,
   and anything TALLIED (numbers, quantities, times, column labels) is set in
   a monospace, uppercase and letterspaced, the way a ruled account book sets
   its columns. Nothing is handwritten and nothing is taped down; that is the
   travel site's language, not this one.

   Two intentional layouts, not one fluid one. The switch is at 900px:
     DESK   (min-width: 901px)  the book open flat on a counter. The index is
                                a ruled list with a sticky preview pane beside
                                it; a recipe is a sticky prep rail beside a
                                numbered method track.
     POCKET (max-width: 900px)  the book stood upright next to the hob. One
                                column, step numbers bleeding into the margin,
                                photos full bleed, and a progress bar fixed to
                                the bottom of the screen while you cook.

   THE ONE RULE THIS SITE IS BUILT AROUND: a step with a photo and a step
   without one are two different layouts (.has-photo / .no-photo). There is
   never an empty image slot, and consecutive photoless steps close up into a
   run so the photographed ones read as landmarks.

   Theming: the four knobs below (--paper, --card, --ink, --accent) can be
   overridden from the recipe_settings table (theme_paper, theme_card,
   theme_ink, theme_accent); the layout template injects them as a :root style
   block. Everything else is derived with color-mix, so a new theme only needs
   those four values plus (optionally) category_palette.

   HOUSE RULES (for future agents): never use em dashes, in copy or in
   comments. No frameworks, no build step, no CDN assets. Do not flatten the
   two layouts into one middle-ground design. See recipes/docs/DESIGN.md.
   ========================================================================== */

/* --- 1. Tokens ------------------------------------------------------------ */

:root {
    /* The four DB-themeable knobs (recipe_settings can override these). */
    --paper:  #eae7de;   /* the page, a warm grey */
    --card:   #f6f4ee;   /* a brighter sheet: panels, plates, the preview pane */
    --ink:    #2f2a24;   /* dark brown text, 11.5:1 on the default paper */
    --accent: #4d5b26;   /* the deep olive rule, 6.0:1 on the default paper */

    /* Derived tones. Percentages are chosen so text stays readable:
       ink-2 is about 6.5:1 and ink-3 about 4.8:1 on the default paper. */
    --paper-2:    color-mix(in srgb, var(--ink) 5%, var(--paper));
    --ink-2:      color-mix(in srgb, var(--ink) 82%, var(--paper));
    --ink-3:      color-mix(in srgb, var(--ink) 66%, var(--paper));
    --rule:       color-mix(in srgb, var(--ink) 20%, var(--paper));
    --rule-strong:color-mix(in srgb, var(--ink) 42%, var(--paper));
    --wash:       color-mix(in srgb, var(--accent) 8%, var(--card));

    /* Shelf color: set per element from PHP (category_color()). The fallback
       keeps components readable if one is ever rendered outside a shelf. */
    --shelf-color: var(--accent);

    /* Two voices. Printed matter is grotesk; anything tallied is monospace. */
    --font-text: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue',
                 Arial, sans-serif;
    --font-tally: ui-monospace, 'SFMono-Regular', 'SF Mono', 'Cascadia Mono',
                  'Segoe UI Mono', Menlo, Consolas, 'Liberation Mono', monospace;

    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.5rem;
    --space-6: 2rem;
    --space-7: 3rem;
    --space-8: 4.5rem;

    --maxw: 1280px;
    --pocket-pad: 1.15rem;
}

/* --- 2. Base & typography --------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    background-color: var(--paper);
    color: var(--ink);
    font-family: var(--font-text);
    font-size: 1rem;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
    font-family: var(--font-text);
    line-height: 1.08;
    margin: 0 0 var(--space-3);
    font-weight: 700;
    letter-spacing: -0.02em;
}

p { margin: 0 0 var(--space-4); }

a { color: inherit; }

img { max-width: 100%; display: block; }

ul, ol { margin: 0; padding: 0; }

button { font: inherit; color: inherit; }

/* Every tallied value: times, quantities, counts, column labels. */
.eyebrow, .row-no, .row-time, .row-steps, .item-qty, .step-no, .step-time,
.spec dt, .spec dd, .preview-stats dt, .preview-stats dd, .preview-shelf,
.shelf-count, .shelf-links a, .method-count, .rail-head, .rail-sub,
.wordmark-sub, .ledger-total dt, .ledger-total dd, .index-legend,
.recipe-nav-label, .cook-bar-text, .step-note::before,
.scaler-value, .scaler-unit, .scaler-reset {
    font-family: var(--font-tally);
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    background: var(--ink);
    color: var(--paper);
    padding: var(--space-3) var(--space-4);
    z-index: 50;
}
.skip-link:focus { left: 0; }

/* --- 3. Shell --------------------------------------------------------------- */

.masthead {
    background: var(--paper);
    border-bottom: 3px double var(--rule-strong);
}

.masthead-bar {
    max-width: var(--maxw);
    margin: 0 auto;
}

.wordmark {
    display: block;
    text-decoration: none;
}

.wordmark-name {
    display: block;
    font-weight: 800;
    letter-spacing: -0.03em;
    line-height: 1;
}

.wordmark-rule {
    display: block;
    height: 2px;
    background: var(--accent);
}

.wordmark-sub {
    display: block;
    color: var(--ink-3);
    font-size: 0.65rem;
}

.shelf-links {
    list-style: none;
    display: flex;
}

.shelf-links a {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    font-size: 0.68rem;
    color: var(--ink-2);
    text-decoration: none;
}

.shelf-links a::before {
    content: '';
    width: 3px;
    height: 0.85em;
    background: var(--shelf-color, var(--ink-3));
}

.shelf-links a:hover { color: var(--ink); }

.shelf-links a[aria-current='page'] {
    color: var(--ink);
    font-weight: 700;
}

.site-main {
    max-width: var(--maxw);
    margin: 0 auto;
}

.site-footer {
    max-width: var(--maxw);
    margin: 0 auto;
    border-top: 3px double var(--rule-strong);
}

.ledger-total {
    display: flex;
    flex-wrap: wrap;
    gap: 0 var(--space-6);
    margin: 0 0 var(--space-3);
}

.ledger-total div { display: flex; align-items: baseline; gap: 0.5rem; }
.ledger-total dt { margin: 0; font-size: 0.63rem; color: var(--ink-3); }
.ledger-total dd { margin: 0; font-size: 0.85rem; font-weight: 700; }

.footer-note {
    margin: 0;
    color: var(--ink-3);
    font-size: 0.88rem;
    max-width: 46rem;
}

/* --- 4. Shared components ---------------------------------------------------- */

.page-intro { max-width: 46rem; }

.eyebrow {
    font-size: 0.66rem;
    color: var(--accent);
    margin: 0 0 var(--space-3);
}

.eyebrow a { color: inherit; }

.lede {
    color: var(--ink-2);
    font-size: 1.06rem;
    margin: 0;
}

.text-link {
    color: inherit;
    text-decoration: underline;
    text-decoration-color: var(--rule-strong);
    text-underline-offset: 3px;
}
.text-link:hover { text-decoration-color: var(--accent); }

.prose p { margin: 0 0 var(--space-4); }
.prose p:last-child { margin-bottom: 0; }
.prose a { color: var(--accent); text-underline-offset: 3px; }

/* --- 5. Index components ----------------------------------------------------- */

.shelf { margin: 0 0 var(--space-7); }

.shelf-head {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: 0 var(--space-3);
    margin: 0 0 var(--space-2);
    font-size: 0.95rem;
    letter-spacing: 0;
}

.shelf-name a { text-decoration: none; }
.shelf-name a:hover { text-decoration: underline; text-underline-offset: 3px; }

.shelf-rule {
    height: 3px;
    border-top: 1px solid var(--shelf-color);
    border-bottom: 1px solid var(--shelf-color);
    opacity: 0.55;
}

.shelf-count { font-size: 0.7rem; color: var(--ink-3); }

.ledger { list-style: none; }

.row-link {
    display: grid;
    align-items: baseline;
    text-decoration: none;
    border-bottom: 1px solid var(--rule);
}

.row-no { color: var(--ink-3); font-size: 0.72rem; }

.row-title { font-weight: 600; }

.row-leader {
    align-self: center;
    border-bottom: 1px dotted var(--rule-strong);
    min-width: 1rem;
}

.row-time, .row-steps { font-size: 0.72rem; text-align: right; }
.row-steps { color: var(--ink-3); }

.row-arrow { color: var(--shelf-color); }

.ledger-row.is-featured .row-no { color: var(--accent); font-weight: 700; }
.ledger-row.is-featured .row-title { font-weight: 700; }

.index-legend {
    font-size: 0.6rem;
    color: var(--ink-3);
    margin: 0;
}

.preview {
    margin: 0;
    background: var(--card);
    border: 1px solid var(--rule);
}

.preview-plate {
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    border-bottom: 1px solid var(--rule);
}

/* No hero photo: a typographic plate rather than a grey box or a placeholder
   icon. Hatching in the shelf color, the title set as a label. */
.preview-plate-blank {
    display: grid;
    place-items: center;
    padding: var(--space-5);
    text-align: center;
    background:
        repeating-linear-gradient(
            45deg,
            transparent 0 7px,
            color-mix(in srgb, var(--shelf-color) 14%, transparent) 7px 8px
        ),
        var(--paper-2);
}

.preview-plate-blank span {
    font-family: var(--font-tally);
    text-transform: uppercase;
    letter-spacing: 0.14em;
    font-size: 0.78rem;
    color: var(--shelf-color);
}

.preview-body { padding: var(--space-4); }

.preview-shelf {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.62rem;
    color: var(--ink-3);
    margin: 0 0 var(--space-2);
}

.preview-shelf::before {
    content: '';
    width: 3px;
    height: 0.85em;
    background: var(--shelf-color);
}

.preview-title {
    font-size: 1.3rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.15;
    margin: 0 0 var(--space-2);
}

.preview-summary {
    color: var(--ink-2);
    font-size: 0.92rem;
    margin: 0 0 var(--space-4);
}

.preview-stats {
    margin: 0;
    border-top: 1px solid var(--rule);
}

.preview-stats div {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: var(--space-3);
    padding: 0.42rem 0;
    border-bottom: 1px dotted var(--rule);
}

.preview-stats dt { margin: 0; font-size: 0.62rem; color: var(--ink-3); }
.preview-stats dd { margin: 0; font-size: 0.72rem; font-weight: 700; }

/* --- 6. Recipe components ---------------------------------------------------- */

.crumb {
    font-size: 0.85rem;
    color: var(--ink-3);
    margin: 0 0 var(--space-4);
}
.crumb span { padding: 0 0.35rem; }

.recipe-hero {
    width: 100%;
    object-fit: cover;
    border: 1px solid var(--rule);
}

.spec {
    display: flex;
    flex-wrap: wrap;
    margin: 0;
    border-top: 1px solid var(--rule-strong);
    border-bottom: 1px solid var(--rule-strong);
}

.spec div {
    padding: var(--space-3) var(--space-4) var(--space-3) 0;
    margin-right: var(--space-4);
    border-right: 1px solid var(--rule);
}
.spec div:last-child { border-right: 0; margin-right: 0; }

.spec dt { margin: 0 0 0.15rem; font-size: 0.6rem; color: var(--ink-3); }
.spec dd { margin: 0; font-size: 0.95rem; font-weight: 700; letter-spacing: 0.02em; }
.spec .spec-total dd { color: var(--accent); }

.headnote {
    color: var(--ink-2);
    border-left: 2px solid var(--shelf-color);
}

.rail-block { margin: 0 0 var(--space-6); }

.rail-head {
    font-size: 0.64rem;
    color: var(--ink-3);
    font-weight: 400;
    letter-spacing: 0.14em;
    margin: 0 0 var(--space-2);
    padding-bottom: var(--space-2);
    border-bottom: 1px solid var(--rule-strong);
}

.rail-sub {
    font-size: 0.6rem;
    color: var(--accent);
    font-weight: 400;
    margin: var(--space-4) 0 var(--space-1);
}

.ledger-items { list-style: none; }

/* One line of the ledger: [tick] item .......... quantity, with any note
   stacked under the item name. Everything is aligned to the FIRST line so a
   wrapping note never drags the tick, the leader or the quantity down with
   it: the offsets below put each on that first line's centre. */
.ledger-item {
    display: grid;
    grid-template-columns: 1.15rem minmax(0, auto) minmax(0.6rem, 1fr) auto;
    align-items: start;
    gap: 0 0.4rem;
    padding: 0.3rem 0;
    border-bottom: 1px dotted var(--rule);
}

.item-tick {
    appearance: none;
    -webkit-appearance: none;
    position: relative;
    width: 0.8rem;
    height: 0.8rem;
    margin: 0.32rem 0 0;
    border: 1px solid var(--rule-strong);
    background: var(--card);
    cursor: pointer;
}

.item-tick::after {
    content: '';
    position: absolute;
    left: 0.13rem;
    top: 0.17rem;
    width: 0.42rem;
    height: 0.2rem;
    border-left: 2px solid var(--card);
    border-bottom: 2px solid var(--card);
    transform: rotate(-45deg) scale(0);
    transform-origin: center;
}

.item-tick:checked { background: var(--accent); border-color: var(--accent); }
.item-tick:checked::after { transform: rotate(-45deg) scale(1); }

.ledger-item label { cursor: pointer; }

.item-name { font-size: 0.92rem; }

/* Stacked, not inline: an inline note pushes the quantity onto a second line
   and breaks the column the ledger is built on. */
.item-note {
    display: block;
    color: var(--ink-3);
    font-size: 0.78rem;
    line-height: 1.35;
}

.item-leader {
    margin-top: 0.72rem;
    border-bottom: 1px dotted var(--rule);
}

.item-qty { font-size: 0.75rem; font-weight: 700; padding-top: 0.16rem; }

.item-tick:checked ~ label .item-name,
.item-tick:checked ~ label .item-note,
.item-tick:checked ~ .item-qty {
    color: var(--ink-3);
    text-decoration: line-through;
    text-decoration-color: var(--rule-strong);
}

/* The servings scaler. Hidden in the markup and revealed by main.js, because
   a stepper that cannot step is worse than no stepper. */
.scaler[hidden] { display: none; }

.scaler-row {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: stretch;
    border: 1px solid var(--rule-strong);
    background: var(--card);
}

.scaler-step {
    background: none;
    border: 0;
    color: var(--ink-2);
    font-size: 1.15rem;
    line-height: 1;
    cursor: pointer;
    padding: 0 0.7rem;
}

.scaler-step:first-of-type { border-right: 1px solid var(--rule); }
.scaler-step:last-of-type  { border-left: 1px solid var(--rule); }
.scaler-step:hover:not(:disabled) { background: var(--wash); color: var(--accent); }
.scaler-step:disabled { color: var(--rule-strong); cursor: default; }

.scaler-readout {
    margin: 0;
    padding: 0.4rem 0.3rem;
    text-align: center;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: center;
    gap: 0 0.35rem;
}

.scaler-value { font-size: 1.05rem; font-weight: 700; }
.scaler-unit { font-size: 0.6rem; color: var(--ink-3); }

.scaler-note {
    font-size: 0.78rem;
    color: var(--ink-3);
    line-height: 1.4;
    margin: var(--space-2) 0 0;
}
.scaler-note b { color: var(--accent); font-weight: 700; }
.scaler-note[hidden] { display: none; }

.scaler-reset {
    margin-top: var(--space-2);
    font-size: 0.6rem;
    color: var(--ink-3);
    background: none;
    border: 1px solid var(--rule-strong);
    padding: 0.3rem 0.5rem;
    cursor: pointer;
}
.scaler-reset:hover { color: var(--accent); border-color: var(--accent); }
.scaler-reset[hidden] { display: none; }

.rail-list { list-style: none; }
.rail-list li {
    font-size: 0.88rem;
    padding: 0.22rem 0;
    border-bottom: 1px dotted var(--rule);
}

.rail-note { color: var(--ink-3); font-size: 0.85rem; margin: 0; }

.method-head {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: 0 var(--space-3);
    font-size: 1.05rem;
    margin: 0 0 var(--space-2);
}

.method-rule {
    height: 3px;
    border-top: 1px solid var(--rule-strong);
    border-bottom: 1px solid var(--rule-strong);
}

.method-count { font-size: 0.65rem; color: var(--ink-3); font-weight: 400; }

.steps { list-style: none; }

.step { position: relative; }

/* The thread running through the method: a hairline down the number gutter,
   spanning the whole step (padding included) so consecutive steps chain into
   one continuous line, with each number sitting on the paper over it. It is
   drawn on the step rather than on the number, so it can never dangle past
   the last one. 1.05rem is the centre of the 2.1rem number in both layouts. */
.step::before {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    left: 1.05rem;
    width: 1px;
    background: var(--rule);
}

.step:last-child::before { display: none; }

.step-mark { position: relative; }

.step-no {
    position: relative;
    z-index: 1;
    display: grid;
    place-items: center;
    width: 2.1rem;
    height: 2.1rem;
    padding: 0;
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--ink-2);
    background: var(--paper);
    border: 1px solid var(--rule-strong);
    cursor: pointer;
}

.step-no:hover { border-color: var(--accent); color: var(--accent); }

.step.is-done .step-no {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--card);
}

.step.is-done .step-text,
.step.is-done .step-figure { opacity: 0.5; }

.step-heading {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0 var(--space-3);
    font-size: 1.02rem;
    margin: 0 0 var(--space-2);
}

.step-time {
    font-size: 0.62rem;
    color: var(--ink-3);
    font-weight: 400;
    letter-spacing: 0.1em;
}

.step-text p { margin: 0 0 var(--space-3); }
.step-text p:last-child { margin-bottom: 0; }

.step-note {
    color: var(--ink-2);
    font-size: 0.88rem;
    background: var(--wash);
    border-left: 2px solid var(--accent);
    padding: var(--space-3) var(--space-4);
}

.step-note::before {
    content: 'Note';
    display: block;
    font-size: 0.58rem;
    color: var(--accent);
    margin-bottom: 0.15rem;
}

.step-figure { margin: 0; }

.step-figure img {
    width: 100%;
    object-fit: cover;
    border: 1px solid var(--rule);
    background: var(--card);
}

.recipe-nav {
    display: grid;
    gap: var(--space-3);
    border-top: 3px double var(--rule-strong);
}

.recipe-nav-link {
    display: block;
    padding: var(--space-4);
    background: var(--card);
    border: 1px solid var(--rule);
    text-decoration: none;
}

.recipe-nav-link:hover { border-color: var(--accent); }
.recipe-nav-link.is-next { text-align: right; }

.recipe-nav-label {
    display: block;
    font-size: 0.6rem;
    color: var(--ink-3);
    margin-bottom: 0.2rem;
}

.recipe-nav-title { font-weight: 700; }

/* The cook bar is revealed by JS (it is useless without the tick buttons)
   and only ever laid out in the pocket layout. */
.cook-bar { display: none; }

/* ==========================================================================
   7. DESK layout: min-width 901px
   The book open flat on a counter. Two zones on the index, a sticky prep
   rail beside a numbered method track on a recipe.
   ========================================================================== */

@media (min-width: 901px) {

    body { font-size: 1.02rem; }

    .masthead-bar {
        display: flex;
        align-items: flex-end;
        justify-content: space-between;
        gap: var(--space-6);
        padding: var(--space-5) var(--space-6) var(--space-4);
    }

    .wordmark-name { font-size: 1.5rem; }
    .wordmark-rule { width: 2.6rem; margin: 0.4rem 0 0.3rem; }

    .shelf-links {
        gap: var(--space-5);
        padding-bottom: 0.35rem;
    }

    .shelf-links a { padding-bottom: 0.3rem; border-bottom: 2px solid transparent; }
    .shelf-links a:hover { border-bottom-color: var(--rule-strong); }
    .shelf-links a[aria-current='page'] { border-bottom-color: var(--shelf-color, var(--accent)); }

    .site-main { padding: var(--space-7) var(--space-6) var(--space-8); }
    .site-footer { padding: var(--space-5) var(--space-6) var(--space-7); }

    .page-intro { margin: 0 0 var(--space-7); }
    .page-intro h1 { font-size: clamp(2.6rem, 4.6vw, 4rem); }

    /* --- index: ruled list + sticky preview pane --- */

    .index-layout {
        display: grid;
        grid-template-columns: minmax(0, 1fr) clamp(19rem, 25vw, 25rem);
        gap: 0 var(--space-8);
        align-items: start;
    }

    .index-preview {
        position: sticky;
        top: var(--space-5);
    }

    .row-link {
        grid-template-columns:
            2.4rem
            minmax(0, auto)
            minmax(1.5rem, 1fr)
            4.6rem
            2.2rem
            1rem;
        gap: 0 var(--space-3);
        padding: 0.5rem var(--space-3) 0.5rem var(--space-2);
        margin-left: calc(var(--space-2) * -1);
    }

    /* The desk row is terse on purpose: the preview pane carries the summary,
       the photo and the counts, so the list itself stays scannable. */
    .row-summary, .row-meta, .row-thumb { display: none; }

    .row-title { font-size: 1.02rem; }

    .row-arrow { opacity: 0; transition: opacity 0.12s ease; }

    .row-link:hover,
    .row-link:focus-visible {
        background: var(--card);
        box-shadow: inset 3px 0 0 var(--shelf-color);
        outline-offset: -2px;
    }

    .row-link:hover .row-arrow,
    .row-link:focus-visible .row-arrow { opacity: 1; }

    .index-legend { margin-top: var(--space-5); }

    /* --- recipe head: title block left, plate right, spec strip under --- */

    .recipe {
        max-width: 1180px;
    }

    .recipe-head {
        display: grid;
        grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
        grid-template-rows: auto auto 1fr;
        gap: 0 var(--space-8);
        margin: 0 0 var(--space-6);
    }

    .recipe-head .crumb { grid-column: 1 / -1; }
    .recipe-title-block { grid-column: 1; grid-row: 2; align-self: end; }
    /* The spec strip sits at the bottom of the left column, so it lines up
       with the foot of the plate beside it. Row 3 takes the slack. */
    .recipe-head .spec { grid-column: 1; grid-row: 3; align-self: end; margin-top: var(--space-5); }

    .recipe-hero {
        grid-column: 2;
        grid-row: 2 / span 2;
        height: 100%;
        max-height: 26rem;
    }

    .recipe-head h1 { font-size: clamp(2.4rem, 4vw, 3.5rem); }

    /* No plate: the title block and the spec strip take the full measure. */
    .recipe-head.no-hero { grid-template-columns: minmax(0, 1fr); }
    .recipe-head.no-hero .recipe-title-block { max-width: 40rem; }

    .headnote {
        max-width: 48rem;
        padding-left: var(--space-5);
        margin: 0 0 var(--space-8);
    }

    /* --- recipe body: sticky prep rail + method track --- */

    .recipe-body {
        display: grid;
        grid-template-columns: 18rem minmax(0, 1fr);
        gap: 0 var(--space-8);
        align-items: start;
    }

    .prep-rail {
        position: sticky;
        top: var(--space-5);
        max-height: calc(100vh - var(--space-7));
        overflow-y: auto;
        overscroll-behavior: contain;
        padding-right: var(--space-3);
    }

    .steps { margin-top: var(--space-5); }

    /* THE DYNAMIC PART. Three lanes when the step has a photo, two when it
       does not, and never an empty lane. */
    .step {
        display: grid;
        gap: 0 var(--space-5);
        padding: var(--space-6) 0;
        border-top: 1px solid var(--rule);
    }

    .step.has-photo {
        grid-template-columns: 2.1rem minmax(0, 1fr) minmax(13rem, 19rem);
    }

    .step.no-photo {
        grid-template-columns: 2.1rem minmax(0, 1fr);
    }

    /* A run of photoless steps closes up and takes a lighter rule, so the
       photographed steps stay the landmarks of the method. */
    .step.in-run {
        padding-top: var(--space-4);
        padding-bottom: var(--space-4);
        border-top-style: dotted;
    }

    .step.in-run .step-no {
        width: 1.7rem;
        height: 1.7rem;
        margin-left: 0.2rem;
        font-size: 0.62rem;
    }

    .step.no-photo .step-text { max-width: 50rem; }
    .step.no-photo .step-note { margin-top: var(--space-4); max-width: 34rem; }

    .step.has-photo .step-note { margin-top: var(--space-4); }

    .step-figure img { aspect-ratio: 4 / 5; }

    .recipe-nav {
        grid-template-columns: 1fr 1fr;
        margin-top: var(--space-8);
        padding-top: var(--space-5);
    }
    .recipe-nav-link.is-next:only-child { grid-column: 2; }

    .ledger-total { gap: 0 var(--space-7); }
}

/* ==========================================================================
   8. POCKET layout: max-width 900px
   The book stood upright next to the hob. One column, full-bleed photos,
   step numbers bleeding into the left margin, and a fixed progress bar.
   The preview pane does not exist here: every row carries its own thumbnail.
   ========================================================================== */

@media (max-width: 900px) {

    body { font-size: 1.02rem; line-height: 1.62; }

    .masthead-bar { padding: var(--space-4) var(--pocket-pad) 0; }

    .wordmark-name { font-size: 1.32rem; }
    .wordmark-rule { width: 2.2rem; margin: 0.35rem 0 0.25rem; }
    .wordmark-sub { margin-bottom: var(--space-4); }

    /* Shelves become a fully visible grid of tabs. No horizontal scroller,
       nothing hidden behind a menu button. */
    .shelf-links {
        display: grid;
        grid-template-columns: 1fr 1fr;
        border-top: 1px solid var(--rule-strong);
        border-left: 1px solid var(--rule-strong);
        margin: 0 calc(var(--pocket-pad) * -1);
    }

    .shelf-links li {
        border-right: 1px solid var(--rule-strong);
        border-bottom: 1px solid var(--rule-strong);
    }

    .shelf-links a {
        width: 100%;
        padding: 0.6rem 0.7rem;
        font-size: 0.66rem;
    }

    .shelf-links a[aria-current='page'] {
        background: var(--card);
        box-shadow: inset 0 -2px 0 var(--shelf-color, var(--accent));
    }

    .site-main { padding: var(--space-6) var(--pocket-pad) var(--space-8); }
    .site-footer { padding: var(--space-5) var(--pocket-pad) var(--space-7); }

    .page-intro { margin: 0 0 var(--space-6); }
    .page-intro h1 { font-size: clamp(2rem, 8.5vw, 2.7rem); }
    .lede { font-size: 1rem; }

    /* --- index: no preview pane, every row is a full entry --- */

    .index-preview { display: none; }

    .shelf-head { margin-bottom: var(--space-1); }

    .row-link {
        grid-template-columns: 2.6rem minmax(0, 1fr) auto;
        grid-template-areas:
            'no   main  thumb'
            'no   meta  thumb';
        align-items: start;
        gap: 0 var(--space-3);
        padding: var(--space-4) 0;
    }

    /* The desk-only columns. The dotted leader and the two number columns are
       a wide-screen device; here the meta line carries the same values. */
    .row-leader, .row-time, .row-steps, .row-arrow { display: none; }

    .row-no {
        grid-area: no;
        font-size: 1.35rem;
        font-weight: 700;
        color: var(--rule-strong);
        line-height: 1;
        padding-top: 0.15rem;
    }

    .ledger-row.is-featured .row-no { color: var(--accent); }

    .row-main { grid-area: main; display: block; min-width: 0; }

    .row-title {
        display: block;
        font-size: 1.15rem;
        line-height: 1.2;
        letter-spacing: -0.015em;
    }

    .row-summary {
        display: block;
        color: var(--ink-2);
        font-size: 0.9rem;
        margin-top: 0.2rem;
    }

    .row-meta {
        display: flex;
        flex-wrap: wrap;
        gap: 0 0.7rem;
        margin-top: 0.45rem;
        font-family: var(--font-tally);
        font-variant-numeric: tabular-nums;
        text-transform: uppercase;
        letter-spacing: 0.07em;
        font-size: 0.6rem;
        color: var(--ink-3);
    }

    .row-meta-time { color: var(--ink); font-weight: 700; }
    .row-meta-photo { color: var(--shelf-color); }

    .row-thumb {
        grid-area: thumb;
        display: block;
        width: 4.6rem;
    }

    .row-thumb img {
        width: 100%;
        aspect-ratio: 1 / 1;
        object-fit: cover;
        border: 1px solid var(--rule);
    }

    .index-legend { display: none; }

    /* --- recipe: one column --- */

    .recipe-head { margin: 0 0 var(--space-5); }
    .recipe-head h1 { font-size: clamp(1.9rem, 8vw, 2.6rem); }

    /* The hero breaks the page margins. It is the one full-bleed object above
       the fold, and it sits between the title and the spec strip. */
    .recipe-hero {
        width: 100vw;
        max-width: 100vw;
        margin: var(--space-5) 0 var(--space-5) calc(var(--pocket-pad) * -1);
        border-left: 0;
        border-right: 0;
        aspect-ratio: 3 / 2;
    }

    .spec {
        display: grid;
        grid-template-columns: 1fr 1fr 1fr;
        gap: 0;
        border-left: 1px solid var(--rule);
    }

    .spec div {
        padding: var(--space-3);
        margin: 0;
        border-right: 1px solid var(--rule);
        border-bottom: 1px solid var(--rule);
    }
    .spec div:last-child { border-right: 1px solid var(--rule); }

    .spec dd { font-size: 0.88rem; }

    .headnote {
        padding-left: var(--space-4);
        margin: 0 0 var(--space-6);
    }

    .prep-rail { margin: 0 0 var(--space-7); }

    /* Touch targets: the stepper is used with one hand and wet fingers. */
    .scaler-step { padding: 0 1.15rem; font-size: 1.3rem; min-height: 2.9rem; }
    .scaler-readout { padding: 0.55rem 0.3rem; }
    .scaler-value { font-size: 1.2rem; }
    .scaler-reset { padding: 0.5rem 0.7rem; }

    .item-name { font-size: 0.96rem; }
    .item-tick { width: 1.05rem; height: 1.05rem; }
    .item-tick::after { left: 0.21rem; top: 0.26rem; width: 0.52rem; height: 0.26rem; }
    .ledger-item { grid-template-columns: 1.5rem minmax(0, auto) minmax(0.6rem, 1fr) auto; padding: 0.45rem 0; }

    /* --- steps: numbers in the margin, photos full bleed --- */

    .steps { margin-top: var(--space-4); }

    .step {
        display: block;
        padding: var(--space-5) 0 var(--space-5) 2.9rem;
        border-top: 1px solid var(--rule);
    }

    .step.in-run { border-top-style: dotted; }

    /* The number leaves the text column entirely and sits in the margin. */
    .step-mark {
        position: absolute;
        left: 0;
        top: var(--space-5);
    }

    .step-heading { font-size: 1.05rem; }

    /* Full-bleed plate under the instruction: the confirmation shot you look
       up at, sized so it never pushes the next step off the screen. */
    .step-figure {
        width: 100vw;
        max-width: 100vw;
        margin: var(--space-4) 0 0 calc((var(--pocket-pad) + 2.9rem) * -1);
    }

    .step-figure img {
        aspect-ratio: 3 / 2;
        border-left: 0;
        border-right: 0;
    }

    .step-note { margin-top: var(--space-4); }

    .recipe-nav {
        grid-template-columns: 1fr;
        margin-top: var(--space-7);
        padding-top: var(--space-5);
    }
    .recipe-nav-link.is-next { text-align: left; }

    /* The cook bar: only in the pocket layout, only once JS has enabled the
       step ticks. Padding at the end of the article keeps it clear of the
       last step. */
    .is-recipe .site-main { padding-bottom: 6rem; }

    .cook-bar {
        display: flex;
        align-items: center;
        gap: var(--space-3);
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 20;
        padding: 0.7rem var(--pocket-pad);
        padding-bottom: calc(0.7rem + env(safe-area-inset-bottom, 0px));
        background: var(--card);
        border-top: 1px solid var(--rule-strong);
    }

    .cook-bar[hidden] { display: none; }

    .cook-bar-text { margin: 0; font-size: 0.62rem; color: var(--ink-2); white-space: nowrap; }
    .cook-bar-text span { font-weight: 700; color: var(--accent); }

    .cook-bar-track {
        flex: 1;
        height: 3px;
        background: var(--rule);
    }

    .cook-bar-track span {
        display: block;
        height: 100%;
        width: 0;
        background: var(--accent);
        transition: width 0.18s ease;
    }

    .cook-bar-reset {
        font-family: var(--font-tally);
        text-transform: uppercase;
        letter-spacing: 0.08em;
        font-size: 0.6rem;
        color: var(--ink-3);
        background: none;
        border: 1px solid var(--rule-strong);
        padding: 0.3rem 0.5rem;
        cursor: pointer;
    }

    .ledger-total { gap: 0 var(--space-5); }
}

/* ==========================================================================
   9. Print: the reason a cookbook is a cookbook. One column, no chrome,
   no ticked state, and no step split across two sheets.
   ========================================================================== */

@media print {
    :root { --paper: #fff; --card: #fff; --ink: #000; }

    body { font-size: 10.5pt; }

    /* The scaler prints as its result, not as its controls: whatever is on
       screen is what lands on the page. */
    .masthead, .site-footer, .cook-bar, .recipe-nav, .scaler-row,
    .scaler-reset, .index-preview, .row-arrow, .skip-link { display: none !important; }

    .site-main { max-width: none; padding: 0; }

    .recipe-head, .recipe-body, .step { display: block; }

    .recipe-hero, .step-figure { max-width: 9cm; margin: 0.4cm 0; }

    .prep-rail { margin-bottom: 0.8cm; }

    .step {
        break-inside: avoid;
        padding: 0.4cm 0;
        border-top: 0.5pt solid #999;
    }

    .step-mark { display: inline-block; }
    .step-mark::before { display: none; }
    .step-no { border-color: #000; background: none; }

    .step-note { background: none; border-left: 1pt solid #000; }

    a { text-decoration: none; }
}

/* --- 10. Motion -------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
    }
}
