/* ============================================================================
   Printable folded MENU sheet - the menu x QR merge. A physical sheet is its own
   surface, so (exactly like qr-card.css) this stylesheet is a self-contained design
   CANVAS: the whole visual language arrives from the chosen SKIN as CSS custom
   properties set inline by partials/print-menu-sheet.php (palette + a display/body
   font pairing + a heading treatment), and this file lays it out. Interior sizing is
   in container units relative to the SHEET, so one sheet scales identically in the
   tiny builder preview and at full page size on paper. It reuses the QR-card page
   shell (.qrc-stage / .qrc-page / .qrc-toolbar) for the print flow.

   Loaded on the fold-builder preview and on the print sheet only.
   RTL: logical properties (border-inline-*, margin-inline-*) so no .rtl build needed.
   ========================================================================== */
:root {
  --pm-bg: #f4f1ec;
  --pm-panel: #fbf8f1;
  --pm-ink: #1a1614;
  --pm-ink-soft: #6b6259;
  --pm-line: rgba(0, 0, 0, .16);
  --pm-accent: #b0883a;
  --pm-display: Georgia, "Times New Roman", serif;
  --pm-body: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

/* ---- The sheet: a size container so every interior cq/em unit scales with it. ---- */
.pm {
  --pm-scale: 1;
  position: relative;
  container-type: size;
  aspect-ratio: 1.4142 / 1;
  width: 100%;
  max-width: 1000px;
  display: grid;
  gap: 0;
  overflow: hidden;
  background: var(--pm-bg);
  color: var(--pm-ink);
  font-family: var(--pm-body);
  /* Base type is a fraction of the sheet's short side, so the whole sheet grows/shrinks as one; every
     interior size is an em of this, and a per-section override just multiplies its own em.
     It is declared as a VARIABLE and applied on the panels (below), never as font-size here: an element is
     never its own query container, so a cqmin used on .pm itself would skip the sheet and resolve against
     the VIEWPORT — the sheet's type would then track the browser window while the sheet box stayed put, and
     a page that pins the sheet (the print/export page, at max-width 1000px) would render type up to 2x too
     large, overflow the panels and get crushed to the auto-fit floor. A custom property is substituted as
     tokens and resolved in the USING element's context, so the panels resolve it against the sheet. */
  --pm-base: calc(1.9cqmin * var(--pm-scale));
  line-height: 1.32;
  /* SQUARE corners: this is a sheet of paper. Rounding it would be a lie on screen and impossible in print
     — and an exported PNG would bleed the page through the four corners. The shadow stays: it is what lifts
     the sheet off the preview backdrop, and it never reaches the printer. */
  box-shadow: 0 10px 34px rgba(0, 0, 0, .18);
}
/* Force every colour/background to print even when the browser's "Background graphics" is off. */
.pm, .pm * { -webkit-print-color-adjust: exact; print-color-adjust: exact; box-sizing: border-box; }

/* ---- Panels + fold guides. Panel inset is a var so a full-bleed photo can break out to the sheet edge. ---- */
/* Padding is a dimension-correct print margin: pad-y in cqh (% of sheet HEIGHT), pad-x in cqw (% of sheet
   WIDTH), so the top heading and the last line always clear the sheet edge by a real margin on tall AND wide
   folds — and, being container-relative, the margin never shrinks with the auto-fit. (em/min-dimension padding
   under-cleared the top/bottom on portrait, so content read as spilling past the frame.) */
/* The panels are the sheet's direct children, so THEY resolve --pm-base against the sheet (see .pm above).
   Every interior size is an em of this, so the whole sheet scales as one at any display size. */
.pm-panel { position: relative; z-index: 1; padding: var(--pm-pad-y, 4.6cqh) var(--pm-pad-x, 3.2cqw); overflow: hidden; display: flex; flex-direction: column; min-width: 0; min-height: 0; font-size: var(--pm-base); }
/* A photo panel fills an otherwise-empty fold panel edge-to-edge with a dish photo (no padding), so a large
   fold on a shorter menu reads as designed rather than blank. */
/* One decorative image behind the WHOLE sheet (spans every column) — fills empty space cohesively on the
   dark boards. Menu panels are transparent so it shows through; a cover's own tint sits on top of it. */
.pm-sheet-bg { position: absolute; inset: 0; z-index: 0; background-size: cover; background-position: center; pointer-events: none; }
/* Between-panel rule: a clean solid hairline by default (a tidy column rule, not a fold-guide look). */
.pm.pm-cols .pm-panel + .pm-panel { border-inline-start: 1px solid var(--pm-line); }
.pm.pm-rows .pm-panel + .pm-panel { border-top: 1px solid var(--pm-line); }
/* Fold-guide aid (toggle): the internal fold lines turn into a BOLD dashed accent rule, every panel gets a
   dashed print-safe-margin frame + a "PANEL n" tag, and a scissors mark sits on each fold — so toggling the
   aid is unmistakable, even on a single-page (fold 1) sheet (which shows the safe-margin frame + PANEL 1). */
.pm[data-guides="1"].pm-cols .pm-panel + .pm-panel { border-inline-start: 2px dashed var(--pm-accent); }
.pm[data-guides="1"].pm-rows .pm-panel + .pm-panel { border-top: 2px dashed var(--pm-accent); }
.pm[data-guides="1"] .pm-panel::after { content: ""; position: absolute; inset: .5em; border: 1px dashed color-mix(in srgb, var(--pm-accent) 45%, transparent); z-index: 3; pointer-events: none; }
.pm[data-guides="1"].pm-cols .pm-panel + .pm-panel::before, .pm[data-guides="1"].pm-rows .pm-panel + .pm-panel::before { content: "\2702"; position: absolute; z-index: 4; font-size: .9em; line-height: 1; color: var(--pm-accent); background: var(--pm-bg); padding: .05em; }
.pm[data-guides="1"].pm-cols .pm-panel + .pm-panel::before { inset-block-start: .3em; inset-inline-start: -.55em; }
.pm[data-guides="1"].pm-rows .pm-panel + .pm-panel::before { inset-inline-start: .3em; inset-block-start: -.55em; }
.pm-panel-label { position: absolute; top: .5em; inset-inline-start: .6em; z-index: 4; font-family: var(--pm-body); font-size: .62em; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--pm-accent); background: color-mix(in srgb, var(--pm-bg) 78%, transparent); border: 1px solid var(--pm-line); border-radius: 999px; padding: .1em .55em; }

/* ---- Cover panel (sits on the skin's panel tint) ---- */
/* Content flows from the top; the QR (when present) sinks to the bottom via margin-top:auto — so a
   brand-only cover no longer stretches its single block across a big dead gap. */
/* The cover content is one vertically-centred block, so a short cover doesn't leave a dead gap between
   the brand at the top and the QR pinned to the bottom. `safe center` makes a DENSE cover (masthead +
   stat + service pills + full contact) fall back to top-alignment instead of overflowing the top edge,
   and font-size:calc(--pm-fit) lets the doc's auto-fit shrink it to the panel — so a cover is never
   clipped at the top (name) or bottom (address). */
.pm-cover { background: var(--pm-panel); justify-content: flex-start; gap: 1.4em; text-align: center; align-items: stretch; container-type: inline-size; font-size: calc(var(--pm-base) * var(--pm-fit, 1)); }
/* The cover reads top-to-bottom as HEADER (brand) / BODY (hero image) / FOOTER (contact + QR inline). The
   body image flex-grows to fill the middle band; the footer's margin-top:auto grounds it (and the QR) at the
   foot even when there's no image. A brand-only cover (no body, no footer) re-centres its single block. */
.pm-cover:not(:has(.pm-cover-body)):not(:has(.pm-cover-footer)) { justify-content: center; }
.pm-cover-header { display: flex; flex-direction: column; align-items: center; gap: 1.1em; width: 100%; }
.pm-cover-brand { display: flex; flex-direction: column; align-items: center; gap: .7em; }
.pm-cover-logo { width: 40%; max-width: 22em; max-height: 12em; height: auto; object-fit: contain; margin-bottom: .6em; }
.pm-cover-name { margin: 0; font-family: var(--pm-display); font-size: 2.6em; font-weight: 800; line-height: 1.08; letter-spacing: .01em; }
/* Identity always: a small wordmark shown when the big name is toggled off (logo-only / QR-only covers),
   so a printed menu is never anonymous. */
.pm-cover-wordmark { margin: 0; font-family: var(--pm-display); font-size: 1.15em; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--pm-ink); }

/* Logo crop shape (data-logoshape): square (default) | rounded | circle. Applies to cover + masthead logos;
   a circle uses a fixed square box + cover-crop so any logo becomes a clean disc. */
.pm[data-logoshape="rounded"] .pm-cover-logo, .pm[data-logoshape="rounded"] .pm-masthead-logo { border-radius: .8em; overflow: hidden; }
/* height:auto + aspect-ratio keeps the logo SQUARE when max-width clamps the width in a narrow panel —
   otherwise the fixed height stays 8em while the width shrinks, and border-radius:50% draws an egg. */
.pm[data-logoshape="circle"] .pm-cover-logo { width: 8em; height: auto; aspect-ratio: 1; max-width: 60%; max-height: none; border-radius: 50%; object-fit: cover; }
.pm[data-logoshape="circle"] .pm-masthead-logo { width: 4.6em; height: 4.6em; max-width: none; max-height: none; border-radius: 50%; object-fit: cover; }
.pm-cover-tagline { margin: 0; font-family: var(--pm-display); font-size: 1.15em; color: var(--pm-accent); font-weight: 600; font-style: italic; }
.pm-cover-blurb { margin: .2em 0 0; font-size: .95em; color: var(--pm-ink-soft); line-height: 1.4; max-width: 92%; }

/* BODY — a hero image bled to the cover's edges: the negative inline margin cancels the panel's side padding
   so the photo spans the full column width, and it flex-grows to fill the band between header and footer.
   object-fit:cover crops cleanly to whatever height is left. */
.pm-cover-body { flex: 1 1 auto; align-self: stretch; min-height: 7em; margin-inline: calc(-1 * var(--pm-pad-x, 3.2cqw)); margin-block: .2em; overflow: hidden; }
.pm-cover-img { width: 100%; height: 100%; display: block; object-fit: cover; }
/* How the hero fills its box, chosen per cover panel: cover crops, contain fits the whole image, fill stretches. */
.pm-cover-img[data-fit="contain"] { object-fit: contain; }
.pm-cover-img[data-fit="fill"] { object-fit: fill; }

/* FOOTER — a 12-col split: restaurant info in 8 cols, the QR in 4, side-by-side along the foot (margin-top:auto
   grounds it). The info type steps down so both fit inline; a very narrow panel collapses to one stacked col. */
.pm-cover-footer { display: grid; grid-template-columns: minmax(0, 1fr) var(--pm-qr-col, 34%); align-items: center; gap: 1.2em; margin-top: auto; width: 100%; }
.pm-cover-footer-info { display: flex; flex-direction: column; align-items: center; gap: .7em; min-width: 0; }
.pm-cover-footer .pm-contact { font-size: .82em; max-width: 100%; }
.pm-cover-footer .pm-qr { margin-top: 0; }
/* QR scale (data-qrsize) as a SHARE of the cover-panel width — so the code stays proportional in a narrow
   gatefold column and a wide single-page cover alike, and the info column always keeps the larger share.
   small/medium/large are the steps the editor exposes; default large. The QR fills its column. */
.pm-cover[data-qrsize="small"]  { --pm-qr-col: 22%; }
.pm-cover[data-qrsize="medium"] { --pm-qr-col: 30%; }
.pm-cover[data-qrsize="large"]  { --pm-qr-col: 38%; }
.pm-cover-footer .pm-qr-media { width: 100%; max-width: none; }
/* Info-only or QR-only footer: one centred column. */
.pm-cover-footer:not(:has(.pm-qr)) { grid-template-columns: minmax(0, 1fr); }
.pm-cover-footer:not(:has(.pm-cover-footer-info)) { grid-template-columns: minmax(0, 1fr); justify-items: center; }

/* Cover alignment (data-align start|center|end) — lets a template push its whole brand + QR block to the
   left or right of its column instead of centre, for a different look. Logical, so it flips under RTL. */
.pm-cover[data-align="start"] { align-items: flex-start; text-align: start; }
.pm-cover[data-align="end"]   { align-items: flex-end;   text-align: end; }
.pm-cover[data-align="start"] .pm-cover-header, .pm-cover[data-align="start"] .pm-cover-brand, .pm-cover[data-align="start"] .pm-cover-footer-info, .pm-cover[data-align="start"] .pm-qr, .pm-cover[data-align="start"] .pm-modes, .pm-cover[data-align="start"] .pm-legend { align-items: flex-start; justify-content: flex-start; }
.pm-cover[data-align="end"] .pm-cover-header, .pm-cover[data-align="end"] .pm-cover-brand, .pm-cover[data-align="end"] .pm-cover-footer-info, .pm-cover[data-align="end"] .pm-qr, .pm-cover[data-align="end"] .pm-modes, .pm-cover[data-align="end"] .pm-legend { align-items: flex-end; justify-content: flex-end; }
.pm-cover[data-align="start"] .pm-contact, .pm-cover[data-align="end"] .pm-contact { max-width: 100%; }

.pm-modes { display: flex; flex-wrap: wrap; justify-content: center; gap: .5em; }
.pm-mode { border: 1px solid var(--pm-accent); color: var(--pm-accent); border-radius: 999px; padding: .25em .8em; font-size: .82em; font-weight: 700; letter-spacing: .02em; }

/* "N+ menu items" cover figure. */
.pm-stat { display: flex; align-items: baseline; justify-content: center; gap: .4em; }
.pm-stat-num { font-family: var(--pm-display); font-size: 2.2em; font-weight: 800; color: var(--pm-accent); line-height: 1; }
.pm-stat-label { font-size: .84em; text-transform: uppercase; letter-spacing: .06em; color: var(--pm-ink-soft); font-weight: 700; }

/* Contact block: label + value pairs on ONE aligned grid — labels align in a column, values in the next,
   each value wrapping at word boundaries. dl/dt/dd with margins reset. */
.pm-contact { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: .4em .8em; width: 100%; max-width: 24em; margin: 0 auto; font-size: .92em; align-items: baseline; text-align: start; }
.pm-contact-label { margin: 0; color: var(--pm-accent); font-weight: 700; text-transform: uppercase; letter-spacing: .04em; font-size: .82em; white-space: nowrap; }
.pm-contact-val { margin: 0; color: var(--pm-ink); overflow-wrap: break-word; }
/* The website already has its scheme stripped; only break it if it genuinely overflows, never mid-token by default. */
.pm-contact-url { overflow-wrap: anywhere; }
/* A boxed "info card" (contactStyle = boxed): groups the service modes + contact into one bordered panel. */
.pm-infocard { container-type: inline-size; display: flex; flex-direction: column; align-items: center; gap: .95em; width: 100%; max-width: 26em; padding: 1.1em 1.2em; border: 1px solid var(--pm-line); border-radius: .5em; background: color-mix(in srgb, var(--pm-panel) 55%, transparent); }
/* The card is narrower than a free contact block (border + padding), so its contact type is a touch smaller
   — a domain like "www.pizzapalace.com" fits on one line even in a slim gatefold column. */
.pm-infocard .pm-contact { max-width: 100%; font-size: .82em; }
/* In a NARROW cover panel (a gatefold's slim column) stack each label above its value, left-aligned, rather
   than squeezing a 2-column grid until the URL/address wraps raggedly. */
@container (max-width: 17em) {
  .pm-contact { grid-template-columns: minmax(0, 1fr); gap: 0; justify-items: start; }
  .pm-contact-label { margin-top: .35em; }
}

.pm-qr { display: flex; flex-direction: column; align-items: center; gap: .5em; margin-top: .2em; }
.pm-qr-media { background: #fff; padding: .7em; border-radius: .6em; width: 42%; max-width: 15em; box-shadow: 0 .1em .5em rgba(0, 0, 0, .18); }
.pm-qr-code { width: 100%; line-height: 0; }
.pm-qr-code img, .pm-qr-code canvas { width: 100% !important; height: auto !important; display: block; }
.pm-qr-caption { color: var(--pm-ink); font-weight: 700; font-size: .82em; text-transform: uppercase; letter-spacing: .04em; }

.pm-legend { display: flex; flex-wrap: wrap; justify-content: center; gap: .4em; }

.pm-powered { display: inline-flex; align-items: center; gap: .5em; margin-top: .2em; color: var(--pm-ink-soft); font-size: .74em; }
.pm-powered img { height: 1.4em; width: auto; object-fit: contain; }

/* ---- Menu panel ---- */
/* --pm-fit (set by the doc's auto-fit script) scales a panel's whole type down so a tall category
   fits its fold instead of being clipped by the panel's overflow:hidden. Default 1 = no change. */
/* Menu content VERTICAL alignment (data-valign top|center|bottom → --pm-valign). Center is the default and
   "safe" so a full page never clips its top; top pins to the header, bottom pins to the footer. */
.pm-menu { gap: var(--pm-menu-gap, 1.5em); font-size: calc(var(--pm-base) * var(--pm-fit, 1)); justify-content: var(--pm-valign, safe center); }
.pm[data-valign="top"]    { --pm-valign: flex-start; }
.pm[data-valign="center"] { --pm-valign: safe center; }
.pm[data-valign="bottom"] { --pm-valign: safe flex-end; }
.pm[data-valign="fill"]   { --pm-valign: space-between; }

/* Spacing / density — the TV board's column-fill lever brought to print. Drives the gaps between sections
   (--pm-sec-gap), between item rows (--pm-item-gap) and the whole column (--pm-menu-gap). "roomy" opens the
   rhythm so a lightly-filled column breathes to the foot instead of leaving a bottom void; "cozy" packs a
   dense column tight; "fill" distributes the sections to the full panel height (space-between). The engine's
   balance + no-clip cap keep every mode printable. */
.pm { --pm-menu-gap: 1.5em; --pm-sec-gap: 1.1em; --pm-item-gap: .55em; }
.pm[data-spacing="cozy"]  { --pm-menu-gap: .85em; --pm-sec-gap: .6em;  --pm-item-gap: .28em; }
.pm[data-spacing="roomy"] { --pm-menu-gap: 2.4em; --pm-sec-gap: 1.9em; --pm-item-gap: .95em; }
/* fill: each section GROWS to its fair share of the column (proportional to its row count, --pm-flex) and its
   item rows spread within (align-content), so the column fills evenly to the foot — no hollow middle, no
   stranded section. Sections never shrink below their content; if a column is over-full the doc's auto-fit
   shrinks the type first. Templates are scoped so a column always holds enough dishes to fill without over-
   stretching. cozy/comfortable/roomy top-align with a fixed gap and no fill. */
.pm[data-spacing="fill"] .pm-menu { justify-content: flex-start; }
/* Per-section density (data-spacing on .pm-section; the partial resolves 'inherit' to the sheet's value, so
   EVERY section carries a concrete value). A section value rescopes the gap vars to that one section; 'fill'
   makes it grow to its fair share (--pm-flex) with its rows spread, so a section can absorb slack on its own
   and no orientation leaves a gap. This replaces the old sheet-wide fill so a per-section override wins. */
.pm-section[data-spacing="cozy"]        { --pm-sec-gap: .6em;  --pm-item-gap: .28em; }
.pm-section[data-spacing="comfortable"] { --pm-sec-gap: 1.1em; --pm-item-gap: .55em; }
.pm-section[data-spacing="roomy"]       { --pm-sec-gap: 1.9em; --pm-item-gap: .95em; }
.pm-section[data-spacing="fill"] { flex: var(--pm-flex, 1) 0 auto; display: flex; flex-direction: column; min-height: min-content; }
.pm-section[data-spacing="fill"] .pm-items { flex: 1 1 auto; align-content: space-between; }
/* Body measure: boxed / custom constrain the menu to a centred column (max-width var); full = no constraint.
   This is the SINGLE source of horizontal width — the centred (fine-dining) treatment no longer forces its
   own max-width, so switching full / boxed / custom actually changes the width. */
.pm[data-body="boxed"] .pm-menu, .pm[data-body="custom"] .pm-menu { max-width: var(--pm-body-max, 42em); margin-inline: auto; width: 100%; }
.pm-section { font-size: calc(1em * var(--pm-sec, 1)); break-inside: avoid; }
/* Breathing room between two categories stacked in the same panel, so they read as distinct sections. */
.pm-section + .pm-section { margin-top: var(--pm-sec-gap, 1.1em); }

/* Brand masthead at the top of a menu panel — carries the logo/name/tagline above the sections so a
   single-page sheet (fold 1) needs no separate cover panel. */
.pm-masthead { display: flex; flex-direction: column; align-items: center; text-align: center; gap: .28em; margin-bottom: 1.1em; padding-bottom: .8em; border-bottom: 2px solid var(--pm-accent); }
.pm-masthead-logo { width: auto; max-width: 55%; max-height: 6em; object-fit: contain; margin-bottom: .2em; }
.pm-masthead-name { margin: 0; font-family: var(--pm-display); font-size: 2.2em; font-weight: 800; line-height: 1.04; letter-spacing: .01em; }
.pm-masthead-tagline { margin: 0; font-family: var(--pm-display); font-size: 1.02em; color: var(--pm-accent); font-weight: 600; font-style: italic; }
.pm-masthead-blurb { margin: .1em 0 0; font-size: .85em; color: var(--pm-ink-soft); line-height: 1.4; max-width: 88%; }
/* Centred-treatment skins (fine dining): the masthead's rule reads better as a hairline than a heavy bar. */
.pm[data-treatment="centered"] .pm-masthead, .pm[data-treatment="rule"] .pm-masthead { border-bottom-width: 1px; }

/* Section head: title + a small item-count pill on one row, an optional note wrapping below it. The
   SKIN treatment (bar | centered | rule | block) restyles this head without touching the markup. */
.pm-sec-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .4em .7em; margin-bottom: .8em; }
/* min-width:min-content keeps a section title WHOLE (it never shrinks below its longest word), so a
   single-word heading like "SALADS" can never shatter into "SALA DS" in a narrow fold column. It grows to
   fill the row and the count pill sits beside it when there's room; when the column is too narrow for both,
   the pill wraps cleanly onto the next line (flex-wrap) rather than crushing the title. */
.pm-sec-title { margin: 0; flex: 1 1 0; min-width: min-content; font-family: var(--pm-display); font-size: 1.72em; font-weight: 800; color: var(--pm-accent); letter-spacing: .01em; line-height: 1.06; text-transform: uppercase; overflow-wrap: normal; word-break: keep-all; }
.pm-sec-count { flex: 0 0 auto; font-size: .66em; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--pm-ink-soft); border: 1px solid var(--pm-line); border-radius: 999px; padding: .15em .6em; }
.pm-sec-note { flex: 1 1 100%; margin: .1em 0 0; font-size: .86em; color: var(--pm-ink-soft); font-style: italic; }
/* Narrower panels (higher fold counts) get a smaller section title, so a single long word like
   "STARTERS" fits the column instead of breaking mid-word. */
.pm[data-fold="4"] .pm-sec-title { font-size: 1.5em; }
.pm[data-fold="5"] .pm-sec-title { font-size: 1.32em; }

/* treatment: bar (default) — an accent rule under the whole head. */
.pm[data-treatment="bar"] .pm-sec-head { border-bottom: 2px solid var(--pm-accent); padding-bottom: .3em; }
/* treatment: centered — head centres, title + count stacked, a short accent underline. */
.pm[data-treatment="centered"] .pm-sec-head { justify-content: center; text-align: center; }
.pm[data-treatment="centered"] .pm-sec-title { flex: 0 0 100%; }
.pm[data-treatment="centered"] .pm-sec-head::after { content: ""; flex: 0 0 100%; height: 2px; width: 3.2em; margin: .35em auto 0; background: var(--pm-accent); }
/* treatment: rule — a thin accent rule above AND below a centred, tracked title. The title must be able
   to shrink + wrap (flex: 1 1 auto, min-width 0) or a long heading like "SIGNATURE PIZZAS" overflows a
   narrow fold panel and gets clipped on both sides; the tracking is modest so single-line titles still fit. */
.pm[data-treatment="rule"] .pm-sec-head { justify-content: center; text-align: center; border-top: 1px solid var(--pm-accent); border-bottom: 1px solid var(--pm-accent); padding: .32em 0; }
.pm[data-treatment="rule"] .pm-sec-title { flex: 1 1 0; min-width: 0; letter-spacing: .08em; font-weight: 700; }
/* treatment: block — the title sits reversed on a solid accent bar. */
.pm[data-treatment="block"] .pm-sec-head { background: var(--pm-accent); padding: .32em .6em; border-radius: .2em; align-items: center; }
/* Reversed title on the accent bar: white + a soft shadow reads on any accent hue (a vendor bgColor
   override near the accent used to collapse contrast when the title was tied to --pm-bg). */
.pm[data-treatment="block"] .pm-sec-title { color: #fff; text-shadow: 0 1px 2px rgba(0, 0, 0, .32); }
.pm[data-treatment="block"] .pm-sec-count { color: #fff; border-color: rgba(255, 255, 255, .55); }

/* The centered treatment is the elegant, no-photo fine-dining column (the "tasting menu" look): the
   item name is centred and letter-spaced, the price sits on its own centred line flanked by a hairline
   accent dot, and the description is centred italic. Used only by the photo-less fine-dining skin, so it
   never competes with a thumbnail. */
/* UNIFIED ITEM STRUCTURE: a treatment (bar | centered | rule | block) restyles only the section HEADING —
   it never changes the item row. Every skin, every fold, front and back, uses the SAME item: name on the
   left, price on a right-aligned rail, description beneath, optional thumbnail — a single left-anchored rail
   that scans cleanly and adapts from a wide 1-column page to a narrow 5-panel strip. The fine-dining skin
   keeps its centred, letter-spaced HEADING for the carte feel, but its dishes read down a proper rail, not a
   centred river. (Heading-only display font on the fine-dining item name for character.) */
.pm[data-treatment="centered"] .pm-item-name { font-family: var(--pm-display); }

/* 1-3 columns of items (per section). */
.pm-items { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(var(--pm-cols, 1), minmax(0, 1fr)); gap: var(--pm-item-gap, .55em) 1.4em; }
.pm-item { display: flex; gap: .7em; break-inside: avoid; }
/* Thumb shrinks as the column count rises (1→3.4em, 2→2.5em, 3→1.6em) so photos don't crowd/clip in a
   narrow multi-column section. */
.pm-item-thumb { flex: 0 0 auto; width: max(1.5em, calc(3.4em - (var(--pm-cols, 1) - 1) * 0.9em)); height: max(1.5em, calc(3.4em - (var(--pm-cols, 1) - 1) * 0.9em)); border-radius: .5em; overflow: hidden; background: var(--pm-line); }
.pm-item-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Image slot with no photo yet — a dashed outline where the picture will go (templates + previews). */
/* TEMPLATE-MODE slots. A starter carries no restaurant data, so the photo / logo / QR slots draw as
   labelled outlines in the SAME dashed language — they show where the vendor's own content will land.
   These never appear on a vendor's sheet; see the template-mode note in print-menu-sheet.php. */
.pm-ph { display: inline-flex; align-items: center; justify-content: center; border: 1.5px dashed var(--pm-line); border-radius: .5em; color: var(--pm-ink-soft); background: transparent; }
.pm-ph svg { width: 46%; height: 46%; max-width: 2.4em; max-height: 2.4em; opacity: .5; }
/* The QR slot's own chrome (white card + padding) is for a REAL code; the outline stands on its own. */
.pm-qr-media:has(.pm-qr-ph) { background: transparent; padding: 0; box-shadow: none; }
/* A full-bleed banner in template mode: the outline fills the banner box instead of a photo. */
.pm-sec-banner-ph { display: flex; align-items: center; justify-content: center; }
.pm-banner-ph { width: 100%; height: 100%; border-radius: 0; }
.pm-logo-ph { width: 8em; height: 8em; max-width: 55%; font-size: 1em; }
.pm-logo-ph i { font-size: 2.2em; }
.pm-logo-ph-sm { width: 4.6em; height: 4.6em; }
.pm-logo-ph-sm i { font-size: 1.5em; }
.pm-qr-ph { width: 100%; aspect-ratio: 1; border-radius: .4em; }
.pm-qr-ph i { font-size: 2.6em; }
/* No logo in the restaurant's settings: their own monogram in the brand accent — never the platform mark. */
.pm-logo-mono { display: inline-flex; align-items: center; justify-content: center; width: 8em; height: 8em; max-width: 55%; aspect-ratio: 1; border-radius: .8em; background: color-mix(in srgb, var(--pm-mono, var(--pm-accent)) 16%, transparent); color: var(--pm-mono, var(--pm-accent)); font-family: var(--pm-display); font-weight: 800; font-size: 1em; line-height: 1; }
.pm-logo-mono { font-size: 2.4em; }
.pm-masthead-logo.pm-logo-mono { width: 2em; height: 2em; font-size: 1.6em; }
.pm-item-thumb-ph { display: flex; align-items: center; justify-content: center; background: transparent; border: 1.5px dashed var(--pm-line); color: var(--pm-ink-soft); }
.pm-item-thumb-ph svg { width: 58%; height: 58%; opacity: .7; }
.pm-item-body { flex: 1 1 auto; min-width: 0; container-type: inline-size; }
/* Name + price on a baseline row, laid out as a GRID (name | gap | price). The NAME is the flexible (1fr)
   track: it takes the free space and word-wraps into it, so a long dish name in a narrow multi-fold column
   breaks at spaces ("San / Pellegrino"), never mid-word. The middle track is a plain gap (empty by default)
   and the price is its own `auto` track — so the price is never clipped and never collides with the name
   (the two column-gaps guarantee ~.7em of separation). Only when the vendor turns dotted leaders ON does the
   middle track become the greedy filler and the name size to its content (the classic name……price look). */
.pm-item-top { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: baseline; column-gap: .35em; }
.pm[data-leaders="1"] .pm-item-top { grid-template-columns: minmax(0, auto) minmax(.7em, 1fr) auto; }
.pm-item-name { min-width: 0; font-weight: 700; font-size: 1em; color: var(--pm-ink); line-height: 1.22; overflow-wrap: break-word; }
.pm-item-num { color: var(--pm-accent); font-weight: 800; }
/* The middle track. Empty by default = a clean gap that flushes the price to the end (the reference-menu
   look). data-leaders="1" fills it with the classic dotted leader; align-self:end keeps the dots on the
   baseline for single-line names. */
.pm-item-lead { align-self: end; margin-bottom: .28em; height: 0; }
.pm[data-leaders="1"] .pm-item-lead { border-bottom: 2px dotted color-mix(in srgb, var(--pm-accent) 45%, var(--pm-line)); }
.pm-item-price { justify-self: end; font-family: var(--pm-display); font-weight: 800; color: var(--pm-accent); font-size: 1.06em; white-space: nowrap; }
/* Genuinely narrow item columns (a four/five-fold landscape panel, a 2–3-up section, a large-photo
   section) can't fit a long dish name AND its price on one baseline — the price would crush the name
   into a mid-word break ("Pelle grino"). Each item body is a container, so ONLY when the column is
   actually narrow does the price tuck directly under the name (left-aligned, tight, still attached to
   its dish) and the name gets the full width to word-wrap. Wide columns keep the clean name…price row —
   consistent for every item in a column, no per-template guessing. */
@container (max-width: 9em) {
    .pm-item-top { grid-template-columns: minmax(0, 1fr); row-gap: .04em; }
    /* The name owns the full column here, so wrap it at word boundaries (never mid-word) — a longer dish
       name breaks as "Rosemary / Fries", not "Rosemar / y Fries". */
    .pm-item-name { overflow-wrap: normal; }
    .pm-item-lead { display: none; }
    .pm-item-price { justify-self: start; }
}
/* A description is capped to 3 lines so one verbose dish can't inflate its row (and force the whole panel's
   auto-fit to over-shrink every other item). Bounded footprint = predictable column heights. */
.pm-item-desc { margin: .15em 0 0; font-size: .84em; color: var(--pm-ink-soft); line-height: 1.32; display: -webkit-box; -webkit-line-clamp: 3; line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.pm-item-meta { display: flex; flex-wrap: wrap; align-items: center; gap: .35em; margin-top: .25em; }
.pm-item-cal { font-size: .74em; color: color-mix(in srgb, var(--pm-ink-soft) 55%, var(--pm-ink)); }

/* Item separators (opt-in per template): a hairline between consecutive dishes — solid | dashed | dotted.
   Spacing stays balanced: a small pad below each item's content, the list's row-gap above the next, so the
   rule breathes and never crowds the text. Skipped on the LAST item of a section and on a hero (which
   carries its own divider). Logical `border-block-end` keeps it RTL-safe. */
/* EVERY item carries the rule, including the last one, so each category CLOSES with a line. Excluding the
   last child (as this once did) broke two ways: a category trailed off with no rule under its final dish,
   and — because .pm-items is a grid filled row-by-row — :last-child is only the bottom-END cell, so a
   multi-column section with an odd item count drew a rule under one bottom cell and not its neighbour. */
.pm[data-divider="solid"]  .pm-item:not(.pm-item-feature) { border-block-end: 1px solid var(--pm-line); padding-block-end: .45em; }
.pm[data-divider="dashed"] .pm-item:not(.pm-item-feature) { border-block-end: 1px dashed var(--pm-line); padding-block-end: .45em; }
.pm[data-divider="dotted"] .pm-item:not(.pm-item-feature) { border-block-end: 1.5px dotted color-mix(in srgb, var(--pm-ink-soft) 50%, var(--pm-line)); padding-block-end: .45em; }

/* Featured / hero item — a section's first dish rendered large: a wide photo on top, then the name +
   price, then the full description. Spans every column of its section. Models the Damascus / Chick-fil-A
   hero dish that anchors a menu. On a photo-less skin it is simply larger, emphasised type. */
.pm-item-feature { grid-column: 1 / -1; flex-direction: column; align-items: stretch; gap: .45em; margin-bottom: 1em; padding-bottom: 1em; border-bottom: 1.5px solid color-mix(in srgb, var(--pm-accent) 45%, var(--pm-line)); }
/* Give the item right after a hero clear breathing room so the highlight reads as separate from the list. */
.pm-item-feature + .pm-item { margin-top: .3em; }
.pm-item-feature .pm-item-thumb { width: 100%; height: auto; max-height: 26cqh; aspect-ratio: 16 / 9; border-radius: .6em; }
.pm-item-feature .pm-item-thumb-ph { aspect-ratio: 16 / 9; }
.pm-item-feature .pm-item-name { font-family: var(--pm-display); font-size: 1.5em; line-height: 1.12; }
.pm-item-feature .pm-item-price { font-size: 1.36em; }
.pm-item-feature .pm-item-desc { font-size: .96em; margin-top: .2em; }
/* Centred-treatment feature (fine dining, no photo): keep it centred with the rest of the column. */
.pm[data-treatment="centered"] .pm-item-feature { align-items: center; }

/* Add-on / combo box under an item — a bordered strip listing its live option names. */
.pm-item-addons { margin-top: .3em; padding: .3em .5em; border: 1px dashed var(--pm-line); border-radius: .35em; font-size: .8em; line-height: 1.35; }
.pm-addons-label { color: var(--pm-accent); font-weight: 700; text-transform: uppercase; letter-spacing: .04em; font-size: .82em; margin-inline-end: .4em; }
.pm-addons-list { color: var(--pm-ink-soft); overflow-wrap: anywhere; }

/* Badge pill — the label carries the meaning; the four flags get a distinct semantic tint so the
   reference-menu read (veg / spicy / popular / chef) is legible on both light and dark skins. */
.pm-badge { display: inline-block; border: 1px solid var(--pm-line); color: var(--pm-ink-soft); border-radius: 999px; padding: .1em .55em; font-size: .68em; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; line-height: 1.5; }
.pm-badge-veg { color: #3f9b52; border-color: color-mix(in srgb, #3f9b52 55%, var(--pm-line)); }
.pm-badge-spicy { color: #e0533b; border-color: color-mix(in srgb, #e0533b 55%, var(--pm-line)); }
.pm-badge-popular { color: #d29a2a; border-color: color-mix(in srgb, #d29a2a 55%, var(--pm-line)); }
.pm-badge-chef { color: var(--pm-accent); border-color: color-mix(in srgb, var(--pm-accent) 55%, var(--pm-line)); }

/* Empty states so a half-built sheet still reads as one. */
.pm-item-empty, .pm-panel-empty { color: var(--pm-ink-soft); font-size: .9em; opacity: .6; grid-column: 1 / -1; }
.pm-panel-empty { margin: auto; }

/* ============================================================================
   Decorative layer — border frames, textures, panel background imagery, image
   treatments and elegant dividers. All opt-in via the config; kept subtle so
   text stays legible. Colours print (print-color-adjust set on .pm above).
   ========================================================================== */

/* ---- Panel decorative background image (fills empty space; blended + low opacity). It sits BEHIND the
   panel content — every real child is lifted above it. ---- */
.pm-panel-bg { position: absolute; inset: 0; background-size: cover; background-position: center; z-index: 0; pointer-events: none; }
.pm-panel > :not(.pm-panel-bg) { position: relative; z-index: 1; }
/* Dark skins: a scrim OVER the blended photo (still under the text, which is z-1) so a bright patch of the
   photo can never wash out the light body copy / prices. Guarantees legibility on charcoal + red + teal. */
.pm[data-dark="1"] .pm-sheet-bg::after, .pm[data-dark="1"] .pm-panel-bg::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(0, 0, 0, .30), rgba(0, 0, 0, .52)); }

/* ---- Border frame (data-border): an inset ruled frame — the fine-dining look. Absolute so the pseudo
   is NOT a grid item; a pure overlay just inside the sheet edge. ---- */
.pm[data-border="thin"]::before, .pm[data-border="double"]::before, .pm[data-border="ornate"]::before {
  content: ""; position: absolute; inset: 2.6%; border: 1px solid var(--pm-accent); z-index: 4; pointer-events: none;
}
/* Ornate = the double rule PLUS a small accent ornament at each of the four corners, so it reads as
   decorated rather than a plain box. */
.pm[data-border="ornate"]::before {
  border-width: 1.5px;
  background:
    radial-gradient(circle, var(--pm-accent) 46%, transparent 52%) top left / 9px 9px no-repeat,
    radial-gradient(circle, var(--pm-accent) 46%, transparent 52%) top right / 9px 9px no-repeat,
    radial-gradient(circle, var(--pm-accent) 46%, transparent 52%) bottom left / 9px 9px no-repeat,
    radial-gradient(circle, var(--pm-accent) 46%, transparent 52%) bottom right / 9px 9px no-repeat;
}
.pm[data-border="double"]::after, .pm[data-border="ornate"]::after {
  content: ""; position: absolute; inset: calc(2.6% + 3px); border: 1px solid var(--pm-accent); opacity: .7; z-index: 4; pointer-events: none;
}
/* A bordered sheet pushes its panel content inward so nothing sits on the frame rule, with a GENEROUS,
   dimension-correct margin: pad-y in cqh (% of height) and pad-x in cqw (% of width), so the masthead
   (header) and the last line (footer) clear the top/bottom frame by a proper print margin on a tall page —
   the min-dimension version under-cleared the top/bottom rule on portrait. cqh/cqw are container-relative,
   so this never shrinks with the auto-fit. */
.pm[data-border="thin"] .pm-panel, .pm[data-border="double"] .pm-panel, .pm[data-border="ornate"] .pm-panel { --pm-pad-y: 6.5cqh; --pm-pad-x: 6.5cqw; }

/* ---- Subtle background texture (data-texture). SVG noise / CSS hatching, very low contrast. ---- */
.pm[data-texture="grain"] { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.11'/%3E%3C/svg%3E"); background-blend-mode: overlay; }
.pm[data-texture="paper"] { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.7' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.07'/%3E%3C/svg%3E"); background-blend-mode: multiply; }
.pm[data-texture="linen"] { background-image: repeating-linear-gradient(45deg, rgba(128,128,128,.08) 0 1px, transparent 1px 6px), repeating-linear-gradient(-45deg, rgba(128,128,128,.08) 0 1px, transparent 1px 6px); }

/* ---- Elegant dividers: the centred / rule treatments use a small centred ornament, never a full-width
   line — and the menu column is contained with margins (not edge-to-edge). ---- */
.pm[data-treatment="centered"] .pm-sec-head::after {
  content: "\25C6"; flex: 0 0 100%; width: auto; height: auto; background: none;
  font-size: .5em; color: var(--pm-accent); letter-spacing: .5em; margin: .35em auto 0; opacity: .85; line-height: 1;
}
.pm[data-treatment="centered"] .pm-masthead, .pm[data-treatment="rule"] .pm-masthead { border-bottom: 0; padding-bottom: .25em; }
.pm[data-treatment="centered"] .pm-masthead::after, .pm[data-treatment="rule"] .pm-masthead::after {
  content: "\25C6"; color: var(--pm-accent); font-size: .8em; margin-top: .35em; opacity: .8; line-height: 1;
}
/* (Width is now owned by data-body — the centred treatment no longer forces its own max-width.) */

/* ---- Image treatments (per section: data-imgstyle) + which side the photo sits on (data-imgalign). ---- */
.pm-section[data-imgalign="end"] .pm-item { flex-direction: row-reverse; }
.pm-section[data-imgstyle="large"] .pm-item-thumb { width: calc(5em - (var(--pm-cols, 1) - 1) * 1em); height: calc(5em - (var(--pm-cols, 1) - 1) * 1em); }
.pm-section[data-imgstyle="framed"] .pm-item-thumb { border: 2px solid var(--pm-accent); padding: 2px; background: transparent; }
.pm-section[data-imgstyle="framed"] .pm-item-thumb img { border-radius: .25em; }
/* full = a category "photo lede": the section LEADS with an edge-to-edge banner (its first item that carries
   a photo) with the HEADING set OVER it on a dark scrim, so the title reads on the image. The banner breaks
   the panel's side padding so it spans the full column width (no L/R gap); its height is driven by --pm-imgh
   (a % of the panel via cqh) so the author can make it taller or shorter. The list below drops per-item
   thumbs — the banner IS the section's photo — so a five-item category reads as one banner + a clean list. */
.pm-section[data-imgstyle="full"] .pm-sec-banner {
  position: relative; overflow: hidden; margin-block-end: .9em;
  margin-inline: calc(-1 * var(--pm-pad-x, 3.2cqw));           /* cancel the panel's side padding → true column width */
  height: calc(var(--pm-imgh, 24) * 1cqh); min-height: 5.5em;
}
.pm-section[data-imgstyle="full"] .pm-sec-banner img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pm-section[data-imgstyle="full"] .pm-sec-banner::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(0, 0, 0, .68) 0%, rgba(0, 0, 0, .18) 46%, transparent 72%);
}
.pm-section[data-imgstyle="full"] .pm-sec-banner .pm-sec-head {
  position: absolute; inset-inline: 0; inset-block-end: 0; margin: 0; z-index: 1;
  padding: 1.1em var(--pm-pad-x, 3.2cqw) .68em;
}
.pm-section[data-imgstyle="full"] .pm-sec-banner .pm-sec-title { color: #fff; text-shadow: 0 1px 3px rgba(0, 0, 0, .45); }
.pm-section[data-imgstyle="full"] .pm-sec-banner .pm-sec-count,
.pm-section[data-imgstyle="full"] .pm-sec-banner .pm-sec-note { color: rgba(255, 255, 255, .92); }
.pm-section[data-imgstyle="full"] .pm-item-thumb { display: none; }
.pm-section[data-imgstyle="full"] .pm-items { row-gap: .5em; }

/* ---- Preview + print sizing (reuses the QR-card .qrc-stage / .qrc-page shell). ---- */
/* One centred sheet by default; a double-sided preview shows BOTH sides side by side (front | back), each
   scaled to fit, so a two-sided design is unmistakable in the editor + the gallery thumbnail. */
.qrc-stage.is-preview { display: flex; flex-wrap: nowrap; gap: 2.5%; justify-content: center; align-items: center; }
/* One sheet: a definite height drives the size (width from aspect-ratio, clamped by max-width). */
.qrc-stage.is-preview .pm { width: auto; height: 92vh; max-width: 96vw; }
/* Two sheets (double-sided): a definite width per sheet so both fit side by side; height from aspect-ratio. */
.qrc-stage.is-preview:has(.qrc-page + .qrc-page) .pm { width: 47vw; height: auto; max-height: 88vh; }
@media print {
  html, body { background: #fff; margin: 0; }
  .qrc-noprint, .qrc-toolbar { display: none !important; }
  .qrc-stage { display: block; }
  /* Each side prints on its OWN physical page (front = page 1, back = page 2) so a duplex print folds into one
     sheet — never two sides crammed on one page, never a blank trailing page. */
  .qrc-page { break-inside: avoid; }
  .qrc-page + .qrc-page { break-before: page; }
  /* The sheet fills the printable page at its exact locked paper proportion, centred — so the printed sheet /
     saved PDF is pixel-identical to the on-screen design (the interior is container-query sized, so filling the
     page reproduces the layout exactly, just at paper scale). */
  .pm { box-shadow: none; border-radius: 0; width: auto; height: 96vh; max-width: 96vw; margin: 0 auto; }
}
