/* assets/hearth-customer-frame.css — the frame every customer page shares.
 *
 * Vendor page build, PR C (docs/design/handovers/Hearth_Vendor_Page_Build_Plan.md
 * §6, approved by Ed 28 October 2026). Lifted from the Design System "Hearth
 * Customer Frame" (bundle.css, "Vendor page: Magazine and the page-style frame",
 * 24 October), keeping only what Magazine uses; Poster, Flyer, colour field and
 * film strip stay behind. The vendor page is the first page to use it, and the
 * order page reuses it when the ordering journey is built.
 *
 * ⚠️ NEVER hearth.css (critical rule 9). Customer pages do not load it.
 *
 * ⚠️ WHERE THE HANDOVER AND THE DESIGN SYSTEM DIFFER, THE HANDOVER WINS
 * (handover, "The design"), and three of its decisions show up here:
 *   - the stamp is set FLAT, never rotated (Decided 12, amended 26 October);
 *   - the footer is ink, never Hearthfire and never the faint grey (Decided 27);
 *   - buttons are the tokens' 48px and the live green is --live (plan, open
 *     question 9).
 *
 * ⚠️ THE PAGE IS ONE DOCUMENT AT EVERY WIDTH. The Design System draws a phone
 * board and a computer board side by side (.is-ph / .is-pc); here the phone
 * layout is the default and the computer layout starts at 1000px, the width the
 * prototype switches at.
 *
 * The vendor's colours arrive as custom properties set by the page from the
 * resolver (_shared/theme.ts), never computed here:
 *   --v-panel      their colour as a fill (panel_fill)
 *   --v-panel-end  the far end of its gradient (panel_fill_end)
 *   --v-on-panel   text on that fill (text_on_brand)
 *   --v-ink        their colour as text on this page's paper (brand_on_surface)
 *   --display      their lettering, for their name
 *   --heading      their lettering for headings (falls back to --display)
 */

:root{
  /* The Hearth frame's own tokens (Design System tokens.json). Declared here
     because customer pages link no other sheet that defines them. */
  --paper:#faf8f4;
  --surface:#ffffff;
  --ink:#1f2937;
  --muted:#5f5a54;
  --subtle:#6b6660;
  --line:#e7e1d8;
  --control-line:#8f8a83;
  --live:#2f7a4f;
  --error:#b42318;
  --sand:#efe6d6;
  --sand-ink:#4a3f30;
  --ochre:#8a6212;
  --font-sans:"figtree",-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
  /* The vendor's layer. Neutral defaults, never Hearthfire (learning 85): the
     page overwrites every one from the resolver before it draws. */
  --v-panel:#2a1f17;
  --v-panel-end:#221913;
  --v-on-panel:#ffffff;
  --v-ink:#2a1f17;
  /* Read by .cf unconditionally, so declared; --v-tint deliberately is not. */
  --v-ink-tinted:#2a1f17;
  --display:"cormorant_garamond",Georgia,serif;
  --heading:var(--display);
}

/* ── the page ────────────────────────────────────────────────────────────── */
/* ⚠️ The browser's own 8px body margin, reset. Left in, it drew a paper-white
   edge round a tinted page and made the page 16px taller than its 100vh
   ground, so the editors' preview frame grew by 16px on every measure and
   never settled (tests/session-one-chooser.mjs N). */
body{margin:0}
/* ⚠️ THE GROUND IS var(--v-tint, var(--paper)), AND THAT FALLBACK IS THE
   GUARANTEE: --v-tint is declared only when the vendor confirmed a pale tone
   (vendor.html, applyBrand), so every other vendor gets Hearth's paper. Their
   colour as text re-points at the value guarded against that ground. */
.cf{position:relative;container-type:inline-size;background:var(--v-tint, var(--paper));color:var(--ink);font-family:var(--font-sans);
  min-height:100vh;overflow-x:clip;--v-ink:var(--v-ink-tinted)}
.cf *{box-sizing:border-box}
/* ⚠️ The `hidden` attribute needs this on any page that sets a display
   (learning 125); customer pages do not load hearth.css, which holds the
   global one. */
.cf [hidden]{display:none !important}
.cf img{display:block;max-width:100%}
.cf .field{background:linear-gradient(165deg,var(--v-panel) 0%,var(--v-panel-end) 100%);color:var(--v-on-panel)}
.cf a{color:inherit}
.cf :focus-visible{outline:3px solid var(--ink);outline-offset:3px}
.cf .field :focus-visible{outline-color:var(--v-on-panel)}

.cf .visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* not found, and the error page: ink on paper, nothing of Hearth's accent */
.cf .nf{max-width:640px;margin:0 auto;padding:96px 16px 48px}
.cf .nf h1{font:700 clamp(26px,6cqi,36px)/1.15 var(--font-sans);letter-spacing:-.02em;margin:0 0 14px}
.cf .nf p{font:400 16px/1.55 var(--font-sans);color:var(--muted);margin:0}

/* type */
.cf .kicker{font:800 12px/1.2 var(--font-sans);letter-spacing:.14em;text-transform:uppercase;margin:0}
.cf .body{font:400 16px/1.55 var(--font-sans);margin:0}
.cf .small{font:400 14px/1.5 var(--font-sans);margin:0;color:var(--muted)}
.cf .mname{font-family:var(--heading);font-weight:600;letter-spacing:-.01em;line-height:1.05;margin:0}
.cf h2.sec{font-family:var(--heading);font-weight:600;font-size:clamp(28px,8cqi,40px);line-height:1;letter-spacing:-.02em;margin:0}

/* buttons: one filled per screen, in the vendor's colour */
.cf .btn{font:600 16px/1.2 var(--font-sans);border-radius:10px;min-height:48px;padding:12px 22px;display:inline-flex;align-items:center;
  justify-content:center;text-align:center;text-decoration:none;border:0;cursor:pointer;max-width:100%}
.cf .btn.primary{background:var(--v-panel);color:var(--v-on-panel)}
.cf .btn.line{background:transparent;color:var(--v-ink);border:2px solid var(--v-ink)}
.cf .btn.sm{min-height:44px;font-size:15px;padding:10px 16px}
.cf .btn[disabled]{opacity:.6;cursor:default}
.cf .lnk{font:600 15px/1.4 var(--font-sans);color:var(--v-ink);text-decoration:underline;text-underline-offset:3px;background:none;border:0;padding:0;cursor:pointer}

/* the stamp: always beside a plain fact, set flat (Decided 12) */
.cf .stamp{display:inline-flex;align-items:center;gap:6px;font:800 11.5px/1 var(--font-sans);letter-spacing:.13em;text-transform:uppercase;
  padding:6px 9px 5px;border:2px solid currentColor;border-radius:4px;outline:1px solid currentColor;outline-offset:2px;white-space:nowrap}
.cf .stamp.live{color:var(--live)}
.cf .stamp.soon,.cf .stamp.ink{color:var(--ink)}
.cf .stamp.future{color:var(--ochre);border-style:dashed;outline-style:dashed}
.cf .field .stamp{color:var(--v-on-panel)}
.cf .stamprow{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin:4px 0 2px}
.cf .stamprow .after{font:500 15px/1.4 var(--font-sans)}

/* What's on: date-led rows, one outlined button each */
.cf .prog{border-top:3px solid var(--ink);margin:0;padding:0;list-style:none}
.cf .row{display:grid;grid-template-columns:56px minmax(0,1fr) 68px;gap:12px;padding:16px 0;border-bottom:1px solid var(--line);align-items:start}
.cf .row .d{display:flex;flex-direction:column}
.cf .row .d .w,.cf .row .d .m{font:800 12px/1.2 var(--font-sans);letter-spacing:.12em;text-transform:uppercase}
.cf .row .d .n{font:800 44px/.9 var(--font-sans);letter-spacing:-.04em;color:var(--v-ink);margin:2px 0}
.cf .row .main{display:flex;flex-direction:column;gap:6px;min-width:0}
.cf .row .mname{font-size:23px}
.cf .row .ww{font:400 14px/1.45 var(--font-sans);color:var(--muted);margin:0}
.cf .row .lu{display:none}
.cf .row .act{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-top:6px}
.cf .thumb{width:68px;height:68px;border-radius:12px;overflow:hidden;position:relative;background:var(--sand);color:var(--sand-ink)}
.cf .thumb img{width:100%;height:100%;object-fit:cover}
.cf .thumb .tile{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;text-align:center;
  font:800 12px/1.05 var(--font-sans);text-transform:uppercase;padding:6px;overflow:hidden;overflow-wrap:normal;word-break:normal}
.cf .hours{display:grid;gap:12px;background:var(--sand);color:var(--sand-ink);border-radius:18px;padding:18px;margin-top:16px}
.cf .hours .kicker{color:var(--sand-ink)}
.cf .hours p.h{margin:4px 0 0;font:600 17px/1.4 var(--font-sans);color:var(--ink)}
.cf .hours .btn.line{background:var(--surface);justify-self:start}

/* past moments: a strip that scrolls inside itself, never the page */
.cf .past{display:flex;gap:14px;overflow-x:auto;scroll-snap-type:x mandatory;padding:2px 2px 6px;margin:0 -2px;list-style:none}
.cf .pcard{flex:0 0 250px;border-radius:18px;overflow:hidden;background:var(--surface);box-shadow:0 0 0 1px var(--line);scroll-snap-align:start}
.cf .pcard .pi{aspect-ratio:4/3;background:linear-gradient(165deg,var(--v-panel),var(--v-panel-end));color:var(--v-on-panel);
  display:flex;align-items:flex-end;padding:14px;overflow:hidden}
.cf .pcard .pi img{width:100%;height:100%;object-fit:cover}
.cf .pcard .pi.has{padding:0}
.cf .pcard .pi .mname{font-size:24px}
.cf .pcard .pb{padding:12px 14px 16px;display:flex;flex-direction:column;gap:3px}
.cf .pcard .t{margin:0;font-family:var(--heading);font-weight:600;font-size:19px;line-height:1.2}
.cf .pcard .f{margin:0;font:400 13px/1.45 var(--font-sans);color:var(--muted)}
.cf .pcard .di{margin:6px 0 0;font:400 13.5px/1.45 var(--font-sans);color:var(--ink)}

/* What we make */
.cf .make{display:grid;gap:10px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0;padding:0;list-style:none}
.cf .make li{aspect-ratio:1/1;border-radius:14px;overflow:hidden;background:var(--sand)}
.cf .make.one{grid-template-columns:1fr}
.cf .make.one li{aspect-ratio:16/10}
.cf .make img{width:100%;height:100%;object-fit:cover}

/* blocks */
.cf .blk{border-radius:22px;padding:24px;display:flex;flex-direction:column;gap:14px;position:relative;overflow:hidden;min-width:0}
.cf .blk.paper{background:var(--surface);box-shadow:0 0 0 1px var(--line)}
.cf .blk.sand{background:var(--sand);color:var(--ink)}
.cf .blk.field .lnk{color:var(--v-on-panel)}
/* ⚠️ A link on sand is Hearth's ink, not the vendor's colour. --v-ink is guarded
   against the page's ground (paper or their pale tint); sand is darker than
   either, so a mid-tone brand that passes on paper fails on sand: Healthy
   Habits' teal is 4.9:1 on paper and below 4.5:1 here
   (tests/vendor-page-customer.mjs). Underlined, so it still reads as a link. */
.cf .blk.sand .lnk{color:var(--ink)}
.cf .addr{font:700 21px/1.3 var(--font-sans);letter-spacing:-.01em;margin:0}
.cf .soc{margin:0;padding:0;list-style:none;font:400 14px/1.9 var(--font-sans)}
.cf .soc span{display:inline-block;min-width:84px;color:var(--sand-ink)}
.cf .soc a{font-weight:600;text-decoration:underline;text-underline-offset:3px;overflow-wrap:anywhere}
.cf details.q{border-top:1px solid var(--line);padding:13px 0}
.cf details.q summary{display:flex;justify-content:space-between;gap:12px;font:600 15px/1.4 var(--font-sans);cursor:pointer;list-style:none}
.cf details.q summary::-webkit-details-marker{display:none}
.cf details.q summary::after{content:"+";font-weight:700}
.cf details.q[open] summary::after{content:"\2212"}
.cf details.q p{margin:8px 0 0;font:400 14px/1.55 var(--font-sans);color:var(--muted);white-space:pre-line}
.cf .about{font:400 16px/1.6 var(--font-sans);margin:0;white-space:pre-line}
.cf .gap{border-left:4px solid currentColor;padding:4px 0 4px 16px;margin:6px 0 0}
.cf .gap .who{font:800 11.5px/1.2 var(--font-sans);letter-spacing:.13em;text-transform:uppercase;margin:0 0 6px}
.cf .gap .say{font:500 italic 19px/1.45 var(--font-sans);margin:0;white-space:pre-line}

/* the footer: one quiet line, in ink, always shown (Decided 27) */
.cf .foot{padding:28px 16px 36px;text-align:center;font:400 13px/1.4 var(--font-sans);color:var(--ink);margin:0}
.cf .foot a{color:var(--ink)}

/* the vendor's own preview */
.cf .previewbar{background:#fbf3e2;color:#6b4a0e;font:500 13.5px/1.45 var(--font-sans);padding:10px 16px;border-bottom:1px solid #ecd9b0;margin:0}
.cf .ghost{padding:14px;border:1.5px dashed var(--control-line);border-radius:12px;font:400 14px/1.45 var(--font-sans);color:var(--muted);background:var(--surface);margin:0}

/* follow, in place */
.cf .form{display:flex;flex-direction:column;gap:12px;border-top:2px solid var(--v-ink);padding-top:14px;margin-top:4px}
.cf .form p{margin:0}
.cf .fld{display:flex;flex-direction:column;gap:6px}
.cf .fld label{font:600 14px/1.3 var(--font-sans)}
.cf .fld .hint{font:400 13px/1.4 var(--font-sans);color:var(--muted)}
.cf .inp{font:400 16px/1.3 var(--font-sans);padding:12px;min-height:48px;border:1.5px solid var(--control-line);border-radius:10px;background:var(--surface);color:var(--ink);width:100%}
.cf .inp[aria-invalid="true"]{border-color:var(--error)}
.cf .errmsg{color:var(--error);font:500 13.5px/1.4 var(--font-sans);margin:0}
.cf .formacts{display:flex;gap:16px;align-items:center;flex-wrap:wrap}
.cf .done{display:flex;gap:9px;align-items:baseline;font:600 16px/1.4 var(--font-sans);margin:0}
.cf .done .dot{width:9px;height:9px;border-radius:50%;background:var(--live);flex-shrink:0;transform:translateY(-1px)}
.cf .done small{display:block;font:400 14px/1.45 var(--font-sans);color:var(--muted)}
.cf .inplace{padding:14px 16px 4px}
.cf .inplace:empty{display:none}

/* the phone stack, with a varied rhythm */
.cf .stack{display:flex;flex-direction:column;gap:40px;padding:40px 16px 0}
.cf .stack > .blk.bleed{margin:0 -16px;border-radius:0}

/* ── the vendor's shape (Your look › Corners and Labels) ──────────────────
   Set on <html> by the page from the resolver (theme.corners,
   theme.label_style), the same attributes and the same values order.html
   reacts to, so the vendor judges one look and gets it on both pages
   (tests/brand-preview-shape-parity.mjs). An unknown value selects nothing and
   the page draws as above.

   ⚠️ A CORNER BECOMES 2px, AND A CIRCLE IS NOT A CORNER: the dot beside
   "You're following" keeps its round. Listed, never swept with a wildcard. */
:root[data-corners="square"] .cf .btn,
:root[data-corners="square"] .cf .blk,
:root[data-corners="square"] .cf .thumb,
:root[data-corners="square"] .cf .hours,
:root[data-corners="square"] .cf .pcard,
:root[data-corners="square"] .cf .make li,
:root[data-corners="square"] .cf .inp,
:root[data-corners="square"] .cf .ghost,
:root[data-corners="square"] .cf .stamp{border-radius:2px}
/* Section headings only, never the vendor's name: a name in a coloured bar
   is not a heading style. */
:root[data-label-style="bar"] .cf h2.sec{display:inline-block;background:var(--v-panel);color:var(--v-on-panel);padding:.16em .4em}
:root[data-label-style="underlined"] .cf h2.sec{display:inline-block;border-bottom:3px solid var(--v-ink);padding-bottom:.12em}

/* ── a computer ──────────────────────────────────────────────────────────── */
@media (min-width:1000px){
  .cf .row{grid-template-columns:92px 150px minmax(0,1fr);gap:24px;padding:22px 0;align-items:center}
  .cf .row .d .n{font-size:58px}
  .cf .row .mname{font-size:28px}
  .cf .row .lu{display:block;margin:0;font:500 15px/1.5 var(--font-sans)}
  .cf .row .thumb{grid-column:2;grid-row:1;width:150px;height:104px}
  .cf .row .main{grid-column:3;grid-row:1}
  .cf .thumb .tile{font-size:20px}
  .cf .hours{grid-template-columns:1fr auto;align-items:center;padding:20px 24px}
  .cf .past{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px;overflow:visible}
  .cf .pcard .pi{aspect-ratio:auto;height:220px}
  .cf .make{grid-template-columns:repeat(3,minmax(0,1fr))}
  .cf .make.one{grid-template-columns:1fr}
  /* One photo is a wide band on a computer, not a 16:10 wall. */
  .cf .make.one li{aspect-ratio:21/9}
  .cf .blk{padding:32px}
  .cf .addr{font-size:25px}
  .cf .stack{max-width:1120px;margin:0 auto;padding:56px 0 0;display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:20px}
  .cf .stack > *{grid-column:1 / -1}
  .cf .stack > .blk.bleed{margin:0;border-radius:22px}
  .cf .stack > .span-7{grid-column:span 7}
  .cf .stack > .span-5{grid-column:span 5}
  .cf .inplace{max-width:1120px;margin:0 auto;padding:20px 0 0}
}

/* motion: CSS only, and nothing moves with reduced motion (Must hold 6) */
/* ⚠️ NO SCROLL-REVEAL. The Design System's .rv fades sections in as they
   scroll into view; it left every section below the hero invisible to anything
   that does not scroll (a full-page capture, a print, some readers), so it is
   not used. The form's short entrance is the only motion. */
@media (prefers-reduced-motion:no-preference){
  .cf .form{animation:cf-in .25s ease-out}
}
@keyframes cf-in{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){
  .cf *,.cf *::before,.cf *::after{animation:none !important;transition:none !important;scroll-behavior:auto !important}
}

@media print{
  .cf .inplace,.cf .previewbar{display:none}
}
