/* coffee.styles.css: the coffee "Steamed Milk" stylesheet for coffee.tabl.page (index, download, 404; the calculator adds calculator.css).
   Built 2026-09-28 by concatenating the approved mockups design/coffee-refresh/mockups/css/base.css + coffee.css + pages.css, in that order.
   Edit this file directly from now on; the mockup files are the approval record, not the source. */

/* ==================== base.css ==================== */
/* TABL coffee "Steamed Milk" base: a fork of portal-landing-page/public/daylight.styles.css (525a7a0).
   Same selectors, breakpoints and hooks as production Daylight; only the palette and fonts change here.
   The coffee signature (pill buttons, menu-board eyebrows, saucer rings, espresso callouts, caramel
   closing band, cup labels ...) lives in coffee.css, loaded after this file.
   Token source: design/coffee-refresh/research/verdict.md §3 (57 pairs verified by verdict-contrast.cjs).
   Rule: no blue anywhere except the logo SVG/favicons (brand art).
   Font URLs are root-relative (/fonts/), served from public/fonts/. */

/* Display: Bricolage Grotesque variable (opsz 24-96, wght 500-700), SIL OFL 1.1, fonts/OFL-bricolage-grotesque.txt.
   Body: Atkinson Hyperlegible 400/700, SIL OFL 1.1, fonts/OFL-LICENSES.txt. */
@font-face {
  font-family: "Bricolage Grotesque";
  src: url("/fonts/bricolage-grotesque-var-latin.woff2") format("woff2");
  font-weight: 500 700;
  font-display: swap;
}
@font-face {
  font-family: "Atkinson Hyperlegible";
  src: url("/fonts/atkinson-hyperlegible-400-v1.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Atkinson Hyperlegible";
  src: url("/fonts/atkinson-hyperlegible-700-v1.woff2") format("woff2");
  font-weight: 700;
  font-display: swap;
}
/* Size-adjusted fallbacks so the swap does not reflow the hero. Ratios from the font files (fontTools):
   Bricolage avg advance .4675em vs Arial Bold .5073em; Atkinson .4735em vs Arial .4781em. */
@font-face {
  font-family: "Bricolage Fallback";
  src: local("Arial Bold"), local("Arial-BoldMT"), local("Helvetica Neue Bold"), local("Arial");
  size-adjust: 92.2%;
  ascent-override: 100.9%;
  descent-override: 29.3%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Atkinson Fallback";
  src: local("Arial"), local("ArialMT"), local("Helvetica Neue");
  size-adjust: 99%;
  ascent-override: 96%;
  descent-override: 29.3%;
  line-gap-override: 0%;
}

:root {
  /* Surfaces: steamed-milk page, foam cards, latte bands. Never brighter (the food-truck site read "too white"). */
  --paper: #E6DDCF;          /* page, header bar, nav sheet, theme-color */
  --surface: #F1EADF;        /* foam: cards, inputs, modal, receipt */
  --sunk: #DDD0BD;           /* latte: alternate bands, bar track, saucer disc */
  --crema: #EFD9B2;          /* TABL's side: compare column, You-pay, TABL row, primary tag, icon tiles */
  --crema-line: #D2AD73;     /* 1px edges on crema */
  --kraft: #CFB48C;          /* testimonial cup-sleeve foot (7% ink ribs max) */
  /* Espresso ink */
  --ink: #2A1810;            /* headings, names, big numbers; 12.62 on paper */
  --ink-2: #4A362B;          /* body; 8.42 on paper */
  --ink-3: #6A5243;          /* meta, mono labels; 4.77 on sunk (tightest text pair) */
  --line: #D3C5B1;
  --line-strong: #BFAE95;    /* dotted leaders, dashed borders, empty punch holes */
  --field-border: #7F6857;   /* inputs, ghost pills, rail buttons, toggles: 3.44 latte / 3.88 paper / 4.37 foam */
  /* One action colour: rust (coffee's own). Rust never sits on espresso. */
  --accent: #93421F;         /* primary, links, focus on light; white on it 6.91 */
  --accent-hover: #6F2F16;   /* hover/press; rust text on crema 7.28 */
  --on-accent: #FFFFFF;      /* label/tick on rust, go and danger fills */
  --caramel: #D89A52;        /* on espresso only (keys, dots, focus on dark) + closing band fill. Never text on light. */
  --glyph-tile: #C0782F;     /* bright tile of the four-square marker (decorative) */
  --star: #A5621C;           /* stars, graphic 3.58 on paper */
  --sage: #738E75;           /* decoration only on light (live dot) */
  --go: #4F7355;             /* check badges with a white tick */
  --go-ink: #3F5F45;         /* "Not your cost" stamp, customer tag, shield */
  --danger: #A1283A;         /* X badge, form errors (coffee cherry) */
  --typ-tint: #EDD9D3;       /* typical-POS column (+6% danger hatch) */
  --typ-ink: #8A2233;        /* typical verdict lead-ins, "$x more than TABL" */
  --bar: #7B6452;            /* competitor bars, 3.65 on latte */
  /* Espresso bookends */
  --bezel: #1C110C;          /* tablet, phone, screen-stage frames */
  --night: #160D0A;          /* spec strip, Screens band, footer, callout chips */
  --night-raised: #2B1812;   /* hover on espresso */
  --on-dark: #FFF3DE;        /* crema text on espresso, footer logo plate */
  --on-dark-2: #D8C1A5;      /* latte muted text on espresso */
  --night-line: color-mix(in srgb, var(--on-dark) 12%, transparent);
  --scrim: color-mix(in srgb, var(--night) 48%, transparent);
  /* Sampled from the top row of the J's Coffee demo poster (r=297, img/digital-menu-poster-coffee.jpg) at 10% and
     75% across, so the phone status bar sits on the demo page's own background. The demo's cool grey is its
     content (like the Portal screenshots), not part of the page palette. */
  --demo-top: #D6DFE6;
  --demo-top-end: #E2E5EA;

  --font-display: "Bricolage Grotesque", "Bricolage Fallback", "Avenir Next", "Segoe UI", sans-serif;
  --font-body: "Atkinson Hyperlegible", "Atkinson Fallback", Verdana, sans-serif;
  --font-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Roboto Mono", monospace;

  --r-xs: 6px;     /* tags */
  --r-sm: 10px;    /* inputs, chips, callouts */
  --r-md: 18px;    /* cards */
  --r-lg: 24px;    /* tablet bezel, modal */
  --r-xl: 44px;    /* phone */
  --r-pill: 999px; /* buttons, rail buttons, toggles */

  --e1: 0 1px 2px color-mix(in srgb, var(--ink) 7%, transparent);
  --e2: 0 1px 2px color-mix(in srgb, var(--ink) 7%, transparent), 0 10px 26px -10px color-mix(in srgb, var(--ink) 20%, transparent);
  --e3: 0 2px 4px color-mix(in srgb, var(--ink) 9%, transparent), 0 30px 60px -22px color-mix(in srgb, var(--ink) 40%, transparent);

  --container: 1180px;
  --container-wide: 1280px;
  --gutter: 32px;
  --section-pad: clamp(72px, 9vw, 128px);
  --ease: cubic-bezier(0.2, 0.8, 0.2, 1);

  /* TABL four-square mark: three espresso tiles (#2A1810 = --ink) and one caramel tile (#C0782F = --glyph-tile).
     Hex is baked into the URI (custom properties do not reach inside data URIs). */
  --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Crect width='5' height='5' rx='1.2' fill='%232A1810'/%3E%3Crect x='7' width='5' height='5' rx='1.2' fill='%23C0782F'/%3E%3Crect y='7' width='5' height='5' rx='1.2' fill='%232A1810'/%3E%3Crect x='7' y='7' width='5' height='5' rx='1.2' fill='%232A1810'/%3E%3C/svg%3E");
  /* On espresso: latte tiles (#D8C1A5 = --on-dark-2) and a caramel tile (#D89A52 = --caramel). */
  --glyph-night: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Crect width='5' height='5' rx='1.2' fill='%23D8C1A5'/%3E%3Crect x='7' width='5' height='5' rx='1.2' fill='%23D89A52'/%3E%3Crect y='7' width='5' height='5' rx='1.2' fill='%23D8C1A5'/%3E%3Crect x='7' y='7' width='5' height='5' rx='1.2' fill='%23D8C1A5'/%3E%3C/svg%3E");
  /* Select chevrons stay background images (a <select> has no pseudo-elements to mask): ink-2 down, rust up. */
  --i-chevron-down: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%234A362B' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  --i-chevron-up: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2393421F' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m18 15-6-6-6 6'/%3E%3C/svg%3E");
  /* Masks (drawn with background: currentColor), colour-safe. */
  --i-alert: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 8v4M12 16h.01'/%3E%3C/svg%3E");
  --i-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
}

/* Big monitors: a wider column so the page doesn't float as a narrow block in the middle. */
@media (min-width: 1600px) { :root { --container: 1320px; } }
@media (max-width: 1100px) { :root { --gutter: 24px; } }
@media (max-width: 400px) { :root { --gutter: 16px; } }

/* ---------- Base ---------- */

*, *::before, *::after { box-sizing: border-box; }
/* Scroll padding keeps focused elements (and native #hash jumps) clear of the sticky header. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: 80px; }
@media (max-width: 1100px) { html { scroll-padding-top: 72px; } }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink-2);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.6;
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
body.modal-open { overflow: hidden; }
img { max-width: 100%; height: auto; display: block; -webkit-user-drag: none; }
svg { flex: none; }
a { color: var(--accent); text-underline-offset: 0.18em; text-decoration-thickness: 1px; }
a:hover { color: var(--accent-hover); }
h1, h2, h3 { margin: 0; font-family: var(--font-display); color: var(--ink); font-weight: 650; text-wrap: balance; }
p { margin: 0; }
ul, ol { margin: 0; padding: 0; }
button, input, select, textarea { font: inherit; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
p, li, dd, summary { text-wrap: pretty; }
[hidden] { display: none !important; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip-link { position: absolute; left: 12px; top: -48px; z-index: 100; padding: 10px 14px; background: var(--night); color: var(--on-dark); border-radius: var(--r-sm); }
.skip-link:focus { top: 12px; color: var(--on-dark); }

.container { width: min(100% - 2 * var(--gutter), var(--container)); margin-inline: auto; }
.container--wide { width: min(100% - 2 * var(--gutter), var(--container-wide)); margin-inline: auto; }
.section, .testimonials, .compare, .screens, .features, .digital-menu, .partners, .faq { padding-block: var(--section-pad); }
.band--sunk { background: var(--sunk); }
.band--night { background: var(--night); color: var(--on-dark-2); }

/* ---------- Primitives ---------- */

.icon { width: 20px; height: 20px; flex: none; stroke-width: 1.75; }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 44px; padding: 0 18px;
  border-radius: var(--r-sm); border: 1.5px solid transparent;
  font: 600 0.9375rem/1 var(--font-display); letter-spacing: -0.005em;
  text-decoration: none; cursor: pointer; white-space: nowrap;
  transition: background-color 120ms var(--ease), border-color 120ms var(--ease), color 120ms var(--ease), transform 120ms var(--ease);
}
.btn:active { transform: translateY(1px); }
.btn .icon { width: 18px; height: 18px; stroke-width: 2; }
.btn-primary { background: var(--accent); color: var(--on-accent); }
.btn-primary:hover { background: var(--accent-hover); color: var(--on-accent); }
.btn-primary:disabled, .btn-primary[aria-disabled="true"] { background: var(--sunk); border-color: var(--line-strong); color: var(--ink-3); cursor: not-allowed; transform: none; }
.btn-secondary { background: var(--surface); color: var(--ink); border-color: var(--field-border); }
.btn-secondary:hover { border-color: var(--ink); color: var(--ink); }
.btn-secondary:disabled { color: var(--ink-3); border-color: var(--line-strong); cursor: not-allowed; transform: none; }
.btn-night { background: transparent; color: var(--on-dark); border-color: color-mix(in srgb, var(--on-dark) 40%, transparent); }
.btn-night:hover { border-color: var(--on-dark); color: var(--on-dark); }
.btn-ink { background: var(--night); color: var(--on-dark); border-color: var(--night); }
.btn-ink:hover { background: var(--night-raised); border-color: var(--night-raised); color: var(--on-dark); }
.btn-lg { min-height: 52px; padding: 0 24px; font-size: 1.0625rem; }

/* .chip / .chip-primary are the older names on pages not yet moved to .tag. */
.tag, .chip {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 30px; padding: 0 10px;
  border-radius: var(--r-xs); border: 1px solid var(--line-strong);
  background: var(--surface); color: var(--ink-2);
  font: 500 0.8125rem/1.2 var(--font-mono); letter-spacing: 0.01em;
}
.tag--primary, .chip-primary { background: var(--crema); border-color: var(--crema-line); color: var(--accent-hover); }
.tag--primary::before, .chip-primary::before { content: ""; width: 12px; height: 12px; background: var(--glyph) center / contain no-repeat; flex: none; }

.eyebrow {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 18px;
  font: 500 0.8125rem/1 var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink-3);
}
/* Section numbers are set per section, not with CSS counters: content-visibility (style containment)
   scopes counters to each section, so a counter would restart at 01 in every one. */
.page-landing #testimonials { --sec: "01"; }
.page-landing #compare { --sec: "02"; }
.page-landing #screens { --sec: "03"; }
.page-landing #features { --sec: "04"; }
.page-landing #digital-menu { --sec: "05"; }
.page-landing #partners { --sec: "06"; }
.page-landing #faq { --sec: "07"; }
.page-landing main > section .section-header .eyebrow::before {
  content: var(--sec) "  /";
  white-space: pre;
  padding-left: 22px;
  background: var(--glyph) left center / 12px 12px no-repeat;
  color: var(--ink);
}
.band--night .eyebrow { color: var(--on-dark-2); }
.page-landing .band--night .section-header .eyebrow::before { background-image: var(--glyph-night); color: var(--on-dark); }

.section-header { max-width: 760px; margin-bottom: 48px; }
.section-header h2 {
  font-size: clamp(1.875rem, 1.35rem + 2.1vw, 3rem);
  line-height: 1.06; letter-spacing: -0.028em; font-stretch: 92%;
}
.section-header h2 + p {
  margin-top: 18px; max-width: 60ch;
  font-size: clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem); line-height: 1.55; color: var(--ink-2);
}
.band--night .section-header h2 { color: var(--on-dark); }
.band--night .section-header h2 + p { color: var(--on-dark-2); }
.section-header--split {
  max-width: none; display: flex; align-items: flex-end; justify-content: space-between; gap: 32px;
}
.section-header--split > div { max-width: 700px; }

/* ---------- Header / nav ---------- */

.site-header {
  position: sticky; top: 0; z-index: 50;
  background: var(--paper);
  border-bottom: 1px solid var(--line);
}
.nav { display: flex; align-items: center; gap: 24px; height: 64px; }
.brand { display: flex; align-items: center; flex: none; min-height: 44px; }
.brand img { height: 30px; width: auto; }
.site-header .brand { padding: 4px 8px; border: 1px solid rgba(9, 38, 102, 0.1); border-radius: 14px; background: #fff; box-shadow: 0 2px 6px rgba(9, 38, 102, 0.06); }
.site-header .brand img { display: block; height: 34px; }
.nav-links { display: flex; align-items: center; gap: 14px; margin-left: auto; }
.nav-links > a:not(.btn) {
  font: 500 0.9375rem/1 var(--font-display); color: var(--ink-2); text-decoration: none;
  padding: 10px 0; border-bottom: 2px solid transparent;
}
.nav-links > a:not(.btn):hover { color: var(--ink); border-bottom-color: var(--accent); }
.nav-actions { display: flex; align-items: center; gap: 10px; margin-left: 6px; }
.nav-links .nav-calculator-cta[aria-current="page"] { background: var(--crema); border-color: var(--crema-line); color: var(--accent-hover); }
.nav-mobile-cta { gap: 6px; padding-inline: 12px; border-color: var(--field-border); background: var(--crema); white-space: nowrap; }
.nav-mobile-cta .icon { width: 16px; height: 16px; }
.nav-toggle {
  display: none; margin-left: auto;
  width: 44px; height: 44px; padding: 0; border-radius: var(--r-sm);
  border: 1.5px solid var(--line-strong); background: var(--surface); color: var(--ink);
  align-items: center; justify-content: center; flex-direction: column; gap: 4px; cursor: pointer;
}
.nav-toggle-bar { display: block; width: 18px; height: 2px; border-radius: 2px; background: currentColor; transition: transform 200ms var(--ease), opacity 200ms var(--ease); }

@media (min-width: 1101px) and (max-width: 1240px) {
  .nav { gap: 16px; }
  .nav-links { gap: 8px; }
}

@media (max-width: 1100px) {
  .nav { height: 56px; }
  .brand img { height: 26px; }
  .site-header .brand img { height: 30px; }
  .nav-toggle { display: inline-flex; }
  .nav-links { display: none; }
  .nav-open .nav-links {
    display: flex; position: fixed; inset: 56px 0 auto 0; z-index: 49;
    flex-direction: column; align-items: stretch; gap: 0;
    max-height: calc(100dvh - 56px); overflow-y: auto; overscroll-behavior: contain;
    padding: 8px var(--gutter) 24px; margin: 0;
    background: var(--paper); border-bottom: 1px solid var(--line); box-shadow: var(--e3);
  }
  .nav-open .nav-links > a:not(.btn) {
    min-height: 56px; display: flex; align-items: center; flex: none;
    font-size: 1.125rem; color: var(--ink); border-bottom: 1px solid var(--line);
  }
  .nav-open .nav-actions { flex-direction: column; align-items: stretch; margin: 20px 0 0; gap: 10px; }
  .nav-open .nav-links > .btn { margin-top: 10px; }
  .nav-open .nav-links .btn { min-height: 52px; font-size: 1.0625rem; flex: none; }
  /* The first child is the sr-only label, so the three bars are children 2-4. */
  .nav-open .nav-toggle-bar:nth-child(2) { transform: translateY(6px) rotate(45deg); }
  .nav-open .nav-toggle-bar:nth-child(3) { opacity: 0; }
  .nav-open .nav-toggle-bar:nth-child(4) { transform: translateY(-6px) rotate(-45deg); }
  .nav-open::before { content: ""; position: fixed; inset: 56px 0 0; z-index: 48; background: color-mix(in srgb, var(--night) 32%, transparent); }
}
@media (min-width: 721px) and (max-width: 1100px) {
  /* Tablet sheet: the two actions sit side by side instead of stretching like phone controls. */
  .nav-open .nav-actions { flex-direction: row; max-width: 560px; }
  .nav-open .nav-actions .btn { flex: 1 1 0; }
}

/* ---------- Hero ---------- */

.hero { position: relative; padding-top: clamp(40px, 6vw, 80px); }
.hero::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 100%; pointer-events: none;
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--ink) 6%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--ink) 6%, transparent) 1px, transparent 1px);
  background-size: 24px 24px;
  -webkit-mask-image: radial-gradient(ellipse 60% 70% at 74% 42%, #000 10%, transparent 70%);
  mask-image: radial-gradient(ellipse 60% 70% at 74% 42%, #000 10%, transparent 70%);
}
.hero-grid {
  position: relative;
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(32px, 4vw, 64px); align-items: center;
}
.chip-row { display: flex; flex-wrap: wrap; gap: 8px; }
.hero h1 {
  margin: 24px 0 22px;
  font-size: clamp(2.5rem, 1.5rem + 4.2vw, 4.75rem);
  line-height: 0.98; letter-spacing: -0.032em; font-stretch: 88%; font-weight: 650;
}
.lead { max-width: 36ch; font-size: clamp(1.125rem, 1rem + 0.45vw, 1.3125rem); line-height: 1.5; color: var(--ink-2); }
.cta-row { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 32px; }

.proof {
  display: inline-flex; align-items: center; gap: 14px; margin-top: 28px; min-height: 44px;
  color: var(--ink-2); text-decoration: none;
}
.proof:hover { color: var(--ink); }
.proof-avatars { display: flex; }
.proof-avatars > span {
  width: 38px; height: 38px; border-radius: 50%; overflow: hidden; flex: none;
  margin-left: -10px; border: 2px solid var(--paper); background: var(--surface);
  box-shadow: 0 0 0 1px var(--line);
}
.proof-avatars > span:first-child { margin-left: 0; }
.proof-avatars img { width: 100%; height: 100%; object-fit: cover; }
.proof-text { display: flex; flex-direction: column; gap: 2px; font-size: 0.9375rem; line-height: 1.3; }
.proof-text strong { font-family: var(--font-display); font-weight: 600; color: var(--ink); }
.stars { color: var(--star); letter-spacing: 0.08em; }

/* --hero-media-top is the tablet's top edge; the ambient steam (end of file) rises from it, so both move together. */
.hero-media { position: relative; --hero-media-top: 64px; padding: var(--hero-media-top) 0 72px; }
.device-frame--tablet {
  position: relative;
  background: var(--bezel); border-radius: var(--r-lg); padding: 12px;
  box-shadow: var(--e3), inset 0 0 0 1px color-mix(in srgb, var(--on-dark) 8%, transparent);
}
.device-frame--tablet::before {
  content: ""; position: absolute; top: 50%; left: 5px; width: 3px; height: 3px; margin-top: -1.5px;
  border-radius: 50%; background: var(--night-raised);
}
.device-screen { position: relative; }
.device-screen img { width: 100%; border-radius: 8px; }

/* Callouts: positioned in % of the 16:10 screenshot, so they hold at every width. */
.callout { position: absolute; left: var(--x); width: 0; }
.callout--up { top: calc(-1 * var(--reach)); height: calc(var(--y) + var(--reach)); }
.callout--down { top: var(--y); height: calc(100% - var(--y) + var(--reach)); }
.callout::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; border-left: 1px solid var(--ink); }
.callout-dot {
  position: absolute; left: 0; width: 12px; height: 12px; border-radius: 50%;
  background: var(--caramel); transform: translate(-50%, -50%);
  box-shadow: 0 0 0 2px var(--night);
}
.callout--up .callout-dot { top: 100%; }
.callout--down .callout-dot { top: 0; }
.callout-label {
  position: absolute; left: 0; white-space: nowrap;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 10px; border-radius: var(--r-xs);
  background: var(--surface); border: 1px solid var(--line-strong); box-shadow: var(--e1);
  font: 500 0.8125rem/1 var(--font-mono); color: var(--ink);
}
.callout-label b { font-weight: 600; color: var(--accent-hover); }
/* The one feature the owner wants called out in the hero. */
.callout-label em, .callout-legend em { font-style: normal; font-weight: 600; color: var(--accent-hover); }
.callout--up .callout-label { top: 0; transform: translate(-12px, -100%); }
.callout--down .callout-label { bottom: 0; transform: translate(-12px, 100%); }
.callout--flip .callout-label { transform: translate(calc(-100% + 12px), -100%); }
/* Read by screen readers everywhere; shown as a numbered key on phones, where the labels are hidden. */
.callout-legend {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  list-style: none;
}

.hero-specs-band { position: relative; margin-top: 24px; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); background: var(--paper); }
.hero-bullets { list-style: none; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.hero-bullets li {
  padding: 22px 24px 24px; border-left: 1px solid var(--line);
  font-size: 0.9375rem; line-height: 1.45; color: var(--ink-2);
}
.hero-bullets li:first-child { border-left: 0; padding-left: 0; }
.spec-key {
  display: block; margin-bottom: 10px;
  font: 600 0.8125rem/1 var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink);
}

/* ---------- Testimonials: ticket rail ---------- */

.rail-controls { display: flex; align-items: center; gap: 8px; flex: none; }
.rail-btn {
  width: 44px; height: 44px; display: grid; place-items: center; padding: 0;
  border-radius: var(--r-sm); border: 1.5px solid var(--field-border); background: var(--surface); color: var(--ink);
  cursor: pointer; transition: border-color 120ms var(--ease), opacity 120ms var(--ease);
}
.rail-btn:hover { border-color: var(--ink); }
.rail-btn:disabled { opacity: 0.4; cursor: default; border-color: var(--field-border); }
.rail-btn .icon { width: 18px; height: 18px; stroke-width: 2; }
.rail-count { min-width: 68px; text-align: center; font: 500 0.875rem/1 var(--font-mono); color: var(--ink-3); font-variant-numeric: tabular-nums; }
.rail-count b { color: var(--ink); font-weight: 600; }

/* The rail is the scroller itself: native swipe + scroll snap, edge-aligned with the container. */
.testimonial-set {
  display: flex; align-items: stretch; gap: 20px;
  overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; overscroll-behavior-x: contain;
  padding: 4px max(var(--gutter), calc((100% - var(--container)) / 2)) 8px;
  scroll-padding-inline: max(var(--gutter), calc((100% - var(--container)) / 2));
}
.testimonial-set::-webkit-scrollbar { display: none; }
.testimonial-set:focus-visible { outline-offset: -2px; }
.testimonial-card {
  flex: 0 0 clamp(280px, 29vw, 372px); scroll-snap-align: start; display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); box-shadow: var(--e1);
}
.ticket-stub {
  position: relative;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 20px; border-bottom: 1.5px dashed var(--line-strong);
  font: 500 0.8125rem/1 var(--font-mono); letter-spacing: 0.08em; color: var(--ink-3);
}
.ticket-stub::before, .ticket-stub::after {
  content: ""; position: absolute; bottom: -9px; width: 16px; height: 16px; border-radius: 50%;
  background: var(--sunk); border: 1px solid var(--line);
}
.ticket-stub::before { left: -9px; clip-path: inset(0 0 0 50%); }
.ticket-stub::after { right: -9px; clip-path: inset(0 50% 0 0); }
.ticket-stub .stars { font-family: var(--font-body); font-size: 0.9375rem; letter-spacing: 0.1em; }
.testimonial-copy { padding: 20px 20px 0; font-size: 1rem; line-height: 1.6; color: var(--ink-2); }
.testimonial-copy::before { content: "\201C"; }
.testimonial-copy::after { content: "\201D"; }
.testimonial-copy.is-clamped { display: -webkit-box; -webkit-line-clamp: 9; line-clamp: 9; -webkit-box-orient: vertical; overflow: hidden; }
.ticket-more {
  align-self: center; margin: 4px 20px 0; padding: 0 4px; min-height: 44px; border: 0; background: none; cursor: pointer;
  font: 600 0.875rem/1 var(--font-display); color: var(--accent); text-decoration: underline; text-underline-offset: 0.2em;
}
.ticket-more:hover { color: var(--accent-hover); }
.ticket-foot { display: flex; align-items: center; gap: 12px; padding: 18px 20px 16px; margin-top: auto; }
.testimonial-logo { width: 44px; height: 44px; border-radius: 50%; overflow: hidden; flex: none; background: var(--surface); box-shadow: 0 0 0 1px var(--line); }
.testimonial-logo.ticket-logo--dark { background: var(--night); }
.testimonial-logo picture, .proof-avatars picture { display: block; width: 100%; height: 100%; }
.testimonial-logo img { width: 100%; height: 100%; object-fit: cover; }
.ticket-who { min-width: 0; }
.testimonial-business { font: 600 1rem/1.25 var(--font-display); color: var(--ink); }
.testimonial-owner { margin-top: 3px; font: 0.8125rem/1.3 var(--font-mono); color: var(--ink-3); }
.ticket-source {
  margin-left: auto; flex: none; min-height: 44px; display: inline-flex; align-items: center; gap: 4px;
  font: 600 0.875rem/1 var(--font-display); color: var(--accent); text-decoration: none;
}
.ticket-source:hover { text-decoration: underline; text-underline-offset: 0.2em; }
.ticket-source .icon { width: 16px; height: 16px; stroke-width: 2; }

/* ---------- Compare: receipt ledger ---------- */

/* TABL is a raised ink column that overhangs the table, with solid green check badges;
   the typical POS column reads as clearly worse (warm hatch, solid red X badges, bold red verdicts). */
.compare-board { position: relative; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); box-shadow: var(--e1); }
.compare-board-top, .compare-row { display: grid; grid-template-columns: minmax(200px, 0.78fr) minmax(0, 1.15fr) minmax(0, 1.05fr); }
.compare-board-top span {
  display: flex; align-items: center; gap: 10px; padding: 16px 24px; border-bottom: 1px solid var(--line);
  font: 500 0.8125rem/1.2 var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-3);
}
.compare-board-top span:nth-child(2) {
  position: relative; margin-top: -16px; padding-top: 32px; border-radius: 16px 16px 0 0;
  background: var(--night); color: var(--on-dark); border-bottom-color: color-mix(in srgb, var(--on-dark) 14%, transparent); font-weight: 600;
}
.compare-board-top span:nth-child(2)::before { content: ""; width: 14px; height: 14px; flex: none; background: var(--glyph-night) center / contain no-repeat; }
.compare-row + .compare-row { border-top: 1px solid var(--line); }
.compare-topic { display: flex; align-items: baseline; gap: 14px; padding: 26px 24px; }
.ledger-num { font: 500 0.8125rem/1 var(--font-mono); color: var(--ink-3); font-variant-numeric: tabular-nums; }
.compare-topic h3 { font-size: 1.25rem; font-weight: 650; letter-spacing: -0.014em; }
.compare-cell { display: flex; gap: 14px; padding: 26px 24px; font-size: 1rem; line-height: 1.5; }
.compare-cell .icon { flex: none; box-sizing: border-box; width: 26px; height: 26px; padding: 5px; margin-top: -1px; border-radius: 50%; }
.compare-cell-portal { position: relative; background: var(--night); color: var(--on-dark); font-weight: 500; box-shadow: 14px 0 28px -18px color-mix(in srgb, var(--ink) 55%, transparent), -14px 0 28px -18px color-mix(in srgb, var(--ink) 55%, transparent); }
.compare-row + .compare-row .compare-cell-portal { border-top: 1px solid var(--night-line); margin-top: -1px; }
.compare-row:last-child .compare-cell-portal { margin-bottom: -16px; padding-bottom: 42px; border-radius: 0 0 16px 16px; }
.compare-cell-portal .icon { background: var(--go); color: var(--on-accent); stroke-width: 3.2; }
/* Typical POS: readable, but clearly the weaker option (warm warning tint, solid red X badge mirroring
   the TABL check, and a bold red verdict before each sentence). */
.compare-cell-typical {
  color: var(--ink-2);
  background-color: var(--typ-tint);
  background-image: repeating-linear-gradient(135deg, color-mix(in srgb, var(--danger) 6%, transparent) 0 1px, transparent 1px 9px);
}
.compare-cell-typical .icon { color: var(--on-accent); background: var(--danger); box-shadow: none; stroke-width: 3.2; }
.compare-cell-typical b { color: var(--typ-ink); font-weight: 700; }
.compare-board-top span:nth-child(3) { color: var(--typ-ink); }
.compare-row:last-child .compare-cell-typical { border-bottom-right-radius: var(--r-md); }
.ledger-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ---------- Screens: night band ---------- */

.screen-stage {
  background: var(--bezel); border-radius: var(--r-lg); padding: 14px;
  box-shadow: 0 0 0 1px var(--night-line), 0 40px 80px -30px color-mix(in srgb, var(--bezel) 90%, transparent);
}
.screen-stage img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; object-position: top left; border-radius: 8px; }
.screens-caption {
  display: flex; justify-content: space-between; gap: 16px; margin: 18px 2px 0;
  font: 500 0.8125rem/1 var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--on-dark-2);
}
.screens-caption b { color: var(--on-dark); font-weight: 600; }
.screen-thumbs { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 16px; margin-top: 28px; }
.thumb {
  display: flex; flex-direction: column; gap: 10px; padding: 0; border: 0; background: none; text-align: left; cursor: pointer;
  font: 500 0.875rem/1.2 var(--font-display); color: var(--on-dark-2);
}
.thumb picture { display: block; }
.thumb img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; object-position: top left; border-radius: 6px; box-shadow: 0 0 0 1px var(--night-line); opacity: 0.72; transition: opacity 120ms var(--ease); }
.thumb:hover img { opacity: 0.9; }
.thumb > span { display: grid; gap: 3px; padding-top: 8px; border-top: 2px solid var(--night-line); }
.thumb-name { display: flex; align-items: center; gap: 8px; }
/* One short line under each screen name so owners know what they are looking at. */
.thumb-note { font: 400 0.8125rem/1.3 var(--font-body); color: var(--on-dark-2); }
.thumb.is-active { color: var(--on-dark); }
.thumb.is-active img { opacity: 1; box-shadow: 0 0 0 2px var(--caramel); }
.thumb.is-active > span { border-top-color: var(--caramel); }
.thumb.is-active .thumb-name::before { content: ""; width: 12px; height: 12px; flex: none; background: var(--glyph-night) center / contain no-repeat; }
.thumb.is-active .thumb-note { color: var(--on-dark); }
.band--night :focus-visible { outline-color: var(--caramel); }

@media (min-width: 1101px) {
  /* App switcher: stage on the left, a 312px column of 152px thumbnails on the right. */
  /* Approved mockup proportions: 96px thumbs (200w files keep the picked image under 2.2x). */
  .screens-layout { display: grid; grid-template-columns: minmax(0, 1fr) 264px; grid-template-rows: auto 1fr; column-gap: 32px; align-items: start; }
  .screen-preview, .screens-caption { grid-column: 1; }
  .screen-thumbs { grid-column: 2; grid-row: 1 / span 2; grid-template-columns: minmax(0, 1fr); gap: 8px; margin-top: 0; }
  .thumb { display: grid; grid-template-columns: 96px minmax(0, 1fr); align-items: center; gap: 14px; padding: 6px; border-radius: 10px; }
  .thumb:hover, .thumb.is-active { background: var(--night-raised); }
  .thumb > span { border-top: 0; padding: 0; }
}

/* ---------- Features ---------- */

/* Four groups, each a header (number, title, one-line point) over four white cards.
   Icons sit in tinted tiles; Customer Loyalty is the one highlighted card. */
.feature-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
.feature-group-label {
  grid-column: 1 / -1; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: baseline; column-gap: 16px;
  margin-top: 40px; padding-bottom: 16px; border-bottom: 1px solid var(--ink);
}
.feature-group-label:first-child { margin-top: 0; }
.feature-group-num {
  align-self: center; display: grid; place-items: center; width: 34px; height: 34px; border-radius: var(--r-sm);
  background: var(--night); color: var(--on-dark); font: 600 0.875rem/1 var(--font-mono); font-variant-numeric: tabular-nums;
}
.feature-group-title { font: 650 clamp(1.25rem, 1.1rem + 0.5vw, 1.5rem)/1.2 var(--font-display); letter-spacing: -0.018em; color: var(--ink); }
.feature-group-note { font-size: 0.9375rem; line-height: 1.4; color: var(--ink-2); text-align: right; }
.feature-card {
  display: flex; flex-direction: column; padding: 22px 22px 24px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); box-shadow: var(--e1);
}
.feature-icon {
  display: grid; place-items: center; width: 44px; height: 44px; margin-bottom: 18px;
  border-radius: 10px; background: var(--crema); box-shadow: inset 0 0 0 1px var(--crema-line); color: var(--accent-hover);
}
.feature-card .icon { display: block; width: 22px; height: 22px; stroke-width: 1.9; }
.feature-card h3 { font-size: 1.125rem; font-weight: 650; letter-spacing: -0.012em; line-height: 1.3; }
.feature-card p { margin-top: 8px; font-size: 0.9375rem; line-height: 1.55; color: var(--ink-2); }
.feature-card--highlight { background: var(--night); border-color: var(--night); box-shadow: var(--e2); }
.feature-card--highlight h3 { color: var(--on-dark); }
.feature-card--highlight p { color: var(--on-dark-2); }
.feature-card--highlight .feature-icon { background: var(--caramel); box-shadow: none; color: var(--night); }

/* ---------- Digital menu ---------- */

/* The order story from scan to ticket: lead, three steps and a "Try it" card on the left; the phone on a
   stage with two labels from real Portal screens on the right. The copy column stretches to the stage,
   so both columns end on one line. */
.digital-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.08fr); gap: clamp(40px, 4vw, 64px); align-items: stretch; }
.digital-copy { display: flex; flex-direction: column; }
.digital-copy .section-header { margin-bottom: 0; }
.digital-body { flex: 1; display: flex; flex-direction: column; margin-top: 20px; }
.dm-lead { font-size: clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem); line-height: 1.55; color: var(--ink-2); }
.dm-lead strong { font-weight: 700; color: var(--ink); }
/* Phrase-intact H2: "Showcase your items with / digital and QR menus / tied to your POS". Where the column is
   too narrow for "Showcase your items with" (961-1100) it wraps naturally. Phones (720 and under) wrap too, with
   text-wrap: balance: a no-wrap phrase ran 14px off a 390 screen under WCAG 1.4.12 text spacing. */
@media (min-width: 1101px), (min-width: 721px) and (max-width: 960px) { .dm-nowrap { white-space: nowrap; } }

/* Steps: numbered ledger, ink rule on top, hairlines between. Rows share any spare height, so the column
   always ends level with the stage. */
.dm-steps { flex: 1; display: flex; flex-direction: column; list-style: none; margin: 28px 0; border-top: 1px solid var(--ink); }
.dm-step {
  flex: 1 0 auto; display: grid; grid-template-columns: 34px minmax(0, 1fr); column-gap: 18px; align-content: center; align-items: start;
  padding: 14px 0; border-bottom: 1px solid var(--line-strong);
}
/* Outlined, not filled: the Features section above ends on a filled ink "04" tile. */
.dm-step-num {
  display: grid; place-items: center; width: 34px; height: 34px; border-radius: var(--r-sm);
  color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--ink);
  font: 600 0.875rem/1 var(--font-mono); font-variant-numeric: tabular-nums;
}
.dm-step h3 { font-size: 1.1875rem; font-weight: 650; letter-spacing: -0.014em; line-height: 1.25; padding-top: 4px; }
.dm-step p { margin-top: 6px; font-size: 1rem; line-height: 1.5; color: var(--ink-2); }

/* Try it: ink card, a real QR code for the same demo URL, and the section's one demo link as a primary button. */
.dm-try {
  margin-top: auto;
  display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 24px; align-items: center;
  padding: 20px 24px 20px 20px; border-radius: var(--r-md);
  background: var(--night); color: var(--on-dark-2); box-shadow: var(--e2);
}
.dm-qr { padding: 12px; border-radius: var(--r-sm); background: var(--surface); color: var(--ink); line-height: 0; }
.dm-qr svg { display: block; width: 87px; height: 87px; } /* 29 modules at 3px; 4px from 1600 */
.dm-try-key {
  display: flex; align-items: center; gap: 8px;
  font: 500 0.75rem/1 var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--on-dark-2);
}
.dm-try-key::before { content: ""; width: 12px; height: 12px; flex: none; background: var(--glyph-night) center / contain no-repeat; }
.dm-try-title { margin-top: 10px; font: 650 1.125rem/1.3 var(--font-display); letter-spacing: -0.014em; color: var(--on-dark); }
.dm-try .demo-link { margin-top: 14px; }
.dm-try .demo-link:focus-visible { outline-color: var(--caramel); }
.mobile-inline-copy { display: none; }

/* Stage: surface panel, hero grid texture, one caption line. */
.dm-stage {
  position: relative; height: 100%; display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--e1);
}
.dm-stage::before {
  content: ""; position: absolute; inset: 53px 0 44px; pointer-events: none;
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--ink) 7%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--ink) 7%, transparent) 1px, transparent 1px);
  background-size: 24px 24px; background-position: -1px -1px;
  -webkit-mask-image: radial-gradient(ellipse 62% 58% at 44% 52%, #000 15%, transparent 78%);
  mask-image: radial-gradient(ellipse 62% 58% at 44% 52%, #000 15%, transparent 78%);
}
.dm-stage-bar {
  position: relative; display: flex; align-items: center; justify-content: space-between; gap: 16px;
  min-height: 53px; padding: 0 20px; border-bottom: 1px solid var(--line);
}
.live-tag {
  display: inline-flex; align-items: center; gap: 8px; min-height: 30px; padding: 0 12px;
  border-radius: var(--r-xs); background: var(--surface); border: 1px solid var(--line-strong);
  font: 500 0.8125rem/1 var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink);
}
.live-tag::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--sage); box-shadow: 0 0 0 3px color-mix(in srgb, var(--sage) 22%, transparent); }
.dm-stage-bar .live-tag { min-height: 0; padding: 0; border: 0; background: none; }
.dm-device { position: relative; flex: 1; display: flex; align-items: center; justify-content: center; padding: 36px 24px; }
.dm-stage-foot {
  position: relative; padding: 13px 20px; border-top: 1px solid var(--line);
  font-size: 0.875rem; line-height: 1.4; color: var(--ink-3); text-align: center; text-wrap: balance;
}

/* Phone. The screen is the demo page's canvas: its background is the page's own top colour (sampled, see
   --demo-top), so the status bar sits on the page like a real iPhone, with no white band or seam. The page
   (poster, then the live iframe on desktop) is pinned to the bottom; the 375:810 screen leaves exactly the
   status-bar gap above a 390:792 page. Sizes are in cqw so the island and status row scale with the phone.
   ponytail: cqw needs Chrome 105 / Safari 16 / Firefox 110; older browsers get an unsized status row. */
.phone-frame {
  width: min(100%, 292px); padding: 11px; border-radius: var(--r-xl);
  background: var(--bezel); box-shadow: var(--e3), inset 0 0 0 1px color-mix(in srgb, var(--on-dark) 8%, transparent);
}
.phone-screen {
  position: relative; aspect-ratio: 375 / 810; border-radius: 34px; overflow: hidden; container-type: inline-size;
  background: linear-gradient(90deg, var(--demo-top) 10%, var(--demo-top-end) 75%) var(--demo-top);
}
.phone-screen::before {
  content: ""; position: absolute; top: 3.08cqw; left: 50%; z-index: 2; width: 28.77cqw; height: 8.22cqw; margin-left: -14.38cqw;
  border-radius: 20px; background: var(--bezel);
}
/* Time centred in the left ear, signal / wifi / battery in the right one, on the island's centre line. */
.phone-status {
  position: absolute; inset: 3.08cqw 0 auto; z-index: 2; height: 8.22cqw; pointer-events: none;
  display: grid; grid-template-columns: 1fr 28.77cqw 1fr; align-items: center; justify-items: center;
  color: var(--ink); font: 600 4.45cqw/1 -apple-system, "SF Pro Text", "Helvetica Neue", Arial, sans-serif;
}
.phone-status svg { grid-column: 3; display: block; height: 3.77cqw; width: auto; }
.phone-screen-poster { position: absolute; left: 0; bottom: 0; width: 100%; }
.dm-device .phone-frame { flex: none; } /* keeps the 314px frame (and the iframe scale) from shrinking at 1101-1119 */
.phone-screen-demo { display: none; }

/* Chips: labels lifted from real Portal screens; decorative, so click-through. Anchored to the phone (which is
   centred vertically): each overlaps the right bezel by 28px. The Menu chip starts 137px below the phone top,
   clear of the live demo's share button. */
.dm-chip { position: absolute; left: calc(50% + 63px); z-index: 3; width: 204px; pointer-events: none; cursor: default; user-select: none; }
.dm-link { top: calc(50% - 200px); }
.dm-ticket { top: calc(50% + 118px); }
.dm-tab {
  display: inline-flex; align-items: center; gap: 7px; padding: 7px 10px 6px; border-radius: 7px 7px 0 0;
  background: var(--night); color: var(--on-dark); font: 500 0.6875rem/1 var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase;
}
.dm-tab::before { content: ""; width: 10px; height: 10px; flex: none; background: var(--glyph-night) center / contain no-repeat; }
/* A quiet list, not buttons: ink text, no borders, no hover. */
.dm-link-list {
  list-style: none; overflow: hidden; border-radius: 0 var(--r-md) var(--r-md) var(--r-md);
  background: var(--surface); box-shadow: var(--e3), 0 0 0 1px var(--line-strong);
}
.dm-link-list li { display: flex; align-items: center; gap: 10px; padding: 11px 12px; font: 600 0.875rem/1.15 var(--font-display); color: var(--ink); }
.dm-link-list li + li { border-top: 1px solid var(--line); }
.dm-link-list .icon { width: 16px; height: 16px; stroke-width: 2; color: var(--accent); }
.dm-ticket-card { overflow: hidden; border-radius: 0 var(--r-md) var(--r-md) var(--r-md); background: var(--surface); box-shadow: var(--e3), 0 0 0 1px var(--line-strong); }
.dm-ticket-top {
  display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px 10px;
  background: var(--night); color: var(--on-dark); font: 600 0.9375rem/1 var(--font-display);
  border-top: 1px solid var(--night-line);
}
.dm-ticket-top b { font-weight: 600; }
.dm-pill { padding: 4px 6px 3px; border-radius: var(--r-xs); background: var(--surface); color: var(--ink); font: 700 0.6875rem/1 var(--font-mono); letter-spacing: 0.06em; text-transform: uppercase; }
/* 5.2:1 at 11px (plain --go on its wash was 3.1:1). */
.dm-pill--go { background: color-mix(in srgb, var(--go) 16%, var(--surface)); color: color-mix(in srgb, var(--go) 70%, var(--ink)); }
.dm-ticket-main { padding: 10px 12px 12px; }
.dm-ticket-status {
  padding: 6px; border-radius: 6px; text-align: center;
  background: var(--crema); box-shadow: inset 0 0 0 1px var(--crema-line); color: var(--accent-hover);
  font: 600 0.8125rem/1 var(--font-display);
}
.dm-ticket-name { margin-top: 10px; font: 650 1rem/1.2 var(--font-display); letter-spacing: -0.01em; color: var(--ink); }
.dm-ticket-total {
  display: flex; justify-content: space-between; margin-top: 10px; padding-top: 10px; border-top: 1.5px dashed var(--line-strong);
  font: 600 0.875rem/1 var(--font-display); color: var(--ink); font-variant-numeric: tabular-nums;
}
.dm-ticket-item { margin-top: 8px; font-size: 0.8125rem; line-height: 1.35; color: var(--ink-2); }
.dm-ticket-item small { display: block; padding-left: 12px; font-size: 0.75rem; color: var(--ink-3); }
.dm-ticket-item small::before { content: "\2022\00a0"; }

/* Wide desktop: a bigger code (4px per module) scans more reliably off a monitor, and there is room for it. */
@media (min-width: 1600px) {
  .dm-qr { padding: 16px; } /* 4-module quiet zone */
  .dm-qr svg { width: 116px; height: 116px; }
}
/* 961-1100: the copy column is at its narrowest beside the code, so the button (which never wraps) gets back
   the 28px it needs to stay inside the card. */
@media (min-width: 961px) and (max-width: 1100px) {
  .dm-try { column-gap: 16px; padding-right: 20px; }
  .dm-try .demo-link { padding-inline: 16px; }
}
/* Desktop: the live demo loads at a real 390px phone width and is scaled into the fixed 292px screen
   (292 / 390 = 0.748718), pinned to the bottom like the poster it covers once settled.
   ponytail: fixed scale because the desktop frame never flexes; use container units if it ever does. */
@media (min-width: 1101px) {
  .dm-device .phone-frame { width: 314px; margin-right: 132px; } /* phone sits 66px left of centre; the chips balance the right */
  .phone-screen-demo {
    position: absolute; left: 0; bottom: 0; display: block;
    width: 390px; height: 792px; border: 0; background: transparent;
    transform: scale(0.748718); transform-origin: 0 100%;
    opacity: 0; transition: opacity 200ms var(--ease);
  }
  .phone-screen-demo.is-ready { opacity: 1; } /* set by script.js once the demo has settled */
}
/* Narrow desktop (1101-1240): the stage is ~516px, so the phone moves further left to keep the chips inside it. */
@media (min-width: 1101px) and (max-width: 1240px) {
  .dm-device { padding-inline: 16px; }
  .dm-device .phone-frame { margin-right: 160px; }
  .dm-chip { left: calc(50% + 49px); }
}
/* 1101-1180: narrower chips so both labels stay on one line with a ~20px inset each side; keeps the 28px bezel overlap. */
@media (min-width: 1101px) and (max-width: 1180px) {
  .dm-chip { width: 190px; left: calc(50% + 45px); }
  .dm-device .phone-frame { margin-right: 168px; }
  .dm-link-list li { padding-inline: 10px; gap: 8px; white-space: nowrap; font-size: 0.84375rem; }
}
/* Tablet and phone: the static poster instead of the live demo, so the "Interactive Demo" bar goes and the
   note becomes a caption. */
@media (max-width: 1100px) {
  .desktop-inline-copy, .phone-demo-label, .dm-stage-bar, .dm-link { display: none; }
  .mobile-inline-copy { display: inline; }
  .dm-stage::before { inset: 0; border-radius: var(--r-lg); }
  .dm-device { flex-direction: column; padding: 32px 20px 0; }
  /* The ticket hangs under the phone with its tab tucked over the bottom bezel: nothing on the screen is covered. */
  .dm-ticket { position: relative; left: auto; top: auto; margin-top: -20px; }
  .dm-stage-foot { padding: 20px 20px 24px; border-top: 0; }
}
@media (max-width: 960px) {
  .digital-grid { grid-template-columns: minmax(0, 1fr); gap: 40px; }
  .dm-steps { flex: none; }
}
@media (max-width: 720px) {
  .dm-steps { margin: 24px 0; }
  .dm-step { column-gap: 14px; }
  .dm-step-num { width: 30px; height: 30px; }
  .dm-step h3 { font-size: 1.0625rem; }
  .dm-step p { margin-top: 4px; font-size: 0.9375rem; }
  /* A phone cannot scan its own screen: drop the code, keep one full-width button. */
  .dm-try { grid-template-columns: minmax(0, 1fr); padding: 20px; }
  .dm-qr { display: none; }
  .dm-try .demo-link { display: flex; width: 100%; }
  .dm-device { padding: 20px 16px 0; }
}
/* Phones: a smaller phone and a lighter caption, so the stage fits one screen. */
@media (max-width: 599px) {
  .dm-device .phone-frame { width: min(100%, 248px); }
  .dm-stage-foot { font-size: 0.8125rem; padding: 14px 16px 18px; }
}
/* Tablets (600-960): the stage is full-column wide, so the chips go back beside the phone as on desktop. */
@media (min-width: 600px) and (max-width: 960px) {
  .dm-device { flex-direction: row; padding: 40px 24px; }
  .dm-device .phone-frame { margin-right: 132px; }
  .dm-link { display: block; top: calc(50% - 190px); }
  .dm-chip { position: absolute; left: calc(50% + 52px); margin: 0; }
  .dm-ticket { top: calc(50% + 100px); }
}

/* ---------- Partners ---------- */

/* Two groups that say what each partner is: built-in integrations (wide) and the community. */
.partner-grid { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 20px; }
.partner-group-label {
  grid-column: 1 / -1; margin-top: 20px; padding-bottom: 14px; border-bottom: 1px solid var(--ink);
  font: 500 0.8125rem/1 var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink);
}
.partner-group-label:first-child { margin-top: 0; }
.partner-card { grid-column: span 2; min-width: 0; }
.partner-card--integration { grid-column: span 3; }
.partner-card__link {
  position: relative; display: flex; flex-direction: column; gap: 20px; height: 100%; padding: 16px 16px 24px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 16px; box-shadow: var(--e1);
  color: inherit; text-decoration: none;
  transition: transform 160ms var(--ease), box-shadow 160ms var(--ease), border-color 160ms var(--ease);
}
.partner-card__link:hover { color: inherit; transform: translateY(-2px); border-color: var(--line-strong); box-shadow: var(--e2); }
.partner-card__link:focus-visible { outline-offset: 3px; border-radius: 16px; }
.partner-card--integration .partner-card__link { flex-direction: row; align-items: center; gap: 28px; padding: 16px 28px 16px 16px; }
.partner-card__logo {
  height: 128px; display: grid; place-items: center; padding: 18px;
  border-radius: var(--r-md); border: 1px solid var(--line);
  background: var(--surface);
}
.partner-card--integration .partner-card__logo { flex: 0 0 46%; }
.partner-card__logo--dark { background: var(--night); border-color: var(--night); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--on-dark) 6%, transparent); }
.partner-card__logo picture { display: block; }
.partner-card__logo img { max-height: 82px; max-width: 100%; width: auto; }
/* Some logo files have a baked-in white box; multiply drops it into the plate. */
.partner-card__logo:not(.partner-card__logo--dark) img { mix-blend-mode: multiply; }
.partner-card__logo--wordmark img { max-height: 40px; }
.partner-card__body { display: grid; gap: 10px; min-width: 0; padding: 0 8px; }
.partner-card--integration .partner-card__body { padding: 0 28px 0 0; } /* clears the outbound chip */
.partner-card__kind {
  display: inline-flex; align-items: center; gap: 8px; justify-self: start;
  font: 500 0.8125rem/1 var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3);
}
.partner-card--integration .partner-card__kind { color: var(--accent-hover); }
.partner-card--integration .partner-card__kind::before { content: ""; width: 12px; height: 12px; flex: none; background: var(--glyph) center / contain no-repeat; }
.partner-card__description { font-size: 0.9375rem; line-height: 1.55; color: var(--ink-2); }
/* Outbound cue: a small chip in the corner of the logo plate. */
.partner-card__go {
  position: absolute; top: 26px; right: 26px; width: 28px; height: 28px; padding: 6px;
  border-radius: 50%; background: color-mix(in srgb, var(--surface) 92%, transparent); border: 1px solid var(--line); color: var(--ink-2);
  transition: transform 160ms var(--ease), color 160ms var(--ease), border-color 160ms var(--ease);
}
.partner-card--integration .partner-card__go { top: 16px; right: 16px; }
.partner-card__link:hover .partner-card__go { color: var(--accent); border-color: var(--crema-line); transform: translate(2px, -2px); }
.partners-cta a { display: inline-flex; align-items: center; min-height: 44px; font-weight: 700; }

/* ---------- FAQ ---------- */

.faq-layout { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: clamp(40px, 6vw, 96px); align-items: start; }
.faq-intro { position: sticky; top: 104px; }
.faq-intro .section-header { margin-bottom: 0; }
.still-deciding { margin-top: 28px; padding-top: 20px; border-top: 1px solid var(--line-strong); font-size: 0.9375rem; color: var(--ink-2); }
.still-deciding strong { display: block; font: 600 1rem/1.3 var(--font-display); color: var(--ink); margin-bottom: 4px; }
.faq-group + .faq-group { margin-top: 44px; }
.faq-group h3 {
  padding-bottom: 12px; border-bottom: 1px solid var(--ink);
  font: 500 0.8125rem/1 var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink);
}
.faq-item { border-bottom: 1px solid var(--line-strong); }
.faq-item summary {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  min-height: 60px; padding: 16px 0; cursor: pointer; list-style: none;
  font: 600 1.0625rem/1.4 var(--font-display); color: var(--ink); letter-spacing: -0.005em;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: "+"; flex: none; width: 28px; height: 28px; display: grid; place-items: center;
  border-radius: var(--r-xs); border: 1px solid var(--line-strong);
  font: 400 1.125rem/1 var(--font-mono); color: var(--ink-2);
}
.faq-item summary:hover::after { border-color: var(--ink); }
.faq-item[open] summary::after { content: "\2212"; background: var(--night); border-color: var(--night); color: var(--on-dark); }
.faq-item p { max-width: 64ch; padding: 0 48px 22px 0; color: var(--ink-2); font-size: 1rem; }

/* ---------- Closing band + footer ---------- */

.closing { background: var(--night); color: var(--on-dark-2); padding-block: clamp(80px, 10vw, 136px) clamp(56px, 7vw, 88px); }
.closing-inner { display: flex; align-items: flex-end; justify-content: space-between; gap: 40px; }
.closing h2 {
  font-size: clamp(2.5rem, 1.6rem + 4vw, 4.75rem); line-height: 0.98;
  letter-spacing: -0.032em; font-stretch: 88%; color: var(--on-dark);
}
.closing p { margin-top: 18px; font-size: 1.1875rem; color: var(--on-dark-2); }
.closing .cta-row { margin-top: 0; flex: none; }

.site-footer { background: var(--night); color: var(--on-dark-2); }
.footer-grid {
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 4fr); column-gap: 48px;
  padding-top: 48px; border-top: 1px solid var(--night-line);
}
.footer-logo { width: 132px; height: auto; border-radius: 8px; }
.footer-brand { margin-top: 28px; font: 600 1.0625rem/1.2 var(--font-display); color: var(--on-dark); }
.footer-copy { margin-top: 8px; max-width: 46ch; font-size: 0.9375rem; }
.footer-label { margin-bottom: 14px; font: 500 0.8125rem/1 var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--on-dark-2); }
.footer-link-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px 32px; }
.footer-link-grid a, .footer-link-grid button {
  min-height: 44px; display: flex; align-items: center; padding: 0; border: 0; background: none; cursor: pointer;
  font: 500 1rem/1.2 var(--font-display); color: var(--on-dark); text-decoration: none; text-align: left;
}
.footer-link-grid a:hover, .footer-link-grid button:hover { color: var(--on-dark); text-decoration: underline; text-underline-offset: 0.2em; }
.footer-legal {
  grid-column: 1 / -1; margin-top: 48px;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px;
  padding-block: 20px 28px; border-top: 1px solid var(--night-line);
}
.footer-legal > p { font: 0.8125rem/1.4 var(--font-mono); color: var(--on-dark-2); }
.footer-socials {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 24px;
  font: 500 0.8125rem/1 var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase;
}
/* Each label stays on one line with its icons. */
.footer-social-group { display: inline-flex; align-items: center; gap: 10px; white-space: nowrap; }
.footer-social {
  width: 44px; height: 44px; display: grid; place-items: center; border-radius: 50%;
  color: var(--on-dark); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--on-dark) 20%, transparent);
}
.footer-social:hover { color: var(--on-dark); box-shadow: inset 0 0 0 1px var(--on-dark); }
.footer-social svg { width: 18px; height: 18px; }
.site-footer :focus-visible, .closing :focus-visible { outline-color: var(--caramel); }

/* ---------- Demo modal ---------- */

/* The opacity transition is load-bearing: script.js hides the modal on its transitionend. */
.demo-modal {
  position: fixed; inset: 0; z-index: 100; display: grid; place-items: center; padding: 32px 24px;
  opacity: 0; transition: opacity 160ms var(--ease);
}
.demo-modal.is-open { opacity: 1; }
.demo-backdrop { position: absolute; inset: 0; background: var(--scrim); }
.demo-dialog {
  position: relative; display: flex; flex-direction: column;
  width: min(100%, 640px); max-height: calc(100dvh - 64px);
  background: var(--surface); border-radius: var(--r-lg); box-shadow: var(--e3); overflow: hidden;
}
.demo-dialog:focus { outline: none; }
.demo-close {
  /* Above the phone header's eyebrow + title (z-index 2), which would otherwise swallow the tap. */
  position: absolute; top: 16px; right: 16px; z-index: 3;
  width: 44px; height: 44px; display: grid; place-items: center; padding: 0;
  border-radius: var(--r-sm); border: 1.5px solid var(--line-strong); background: var(--surface); color: var(--ink);
  cursor: pointer; transition: border-color 120ms var(--ease);
}
.demo-close:hover { border-color: var(--ink); }
.demo-close svg { width: 20px; height: 20px; }
.demo-modal.is-success .demo-close { display: none; }

.demo-content { overflow-y: auto; overscroll-behavior: contain; padding: 0 40px; scroll-padding-block: 44px 128px; }
/* Sticky top fade doubles as top padding; scrolled fields fade out under the sheet edge and close button. */
.demo-content::before {
  content: ""; position: sticky; top: 0; z-index: 1; display: block; height: 36px; margin-inline: -40px;
  background: linear-gradient(var(--surface) 45%, color-mix(in srgb, var(--surface) 0%, transparent));
}
.demo-header { margin-bottom: 28px; }
.demo-header .eyebrow, .demo-header h2 { padding-right: 56px; }
.demo-header .eyebrow { margin-bottom: 14px; }
.demo-header .eyebrow::before { content: ""; width: 12px; height: 12px; flex: none; background: var(--glyph) center / contain no-repeat; }
.demo-header h2 { font-size: 1.75rem; line-height: 1.15; letter-spacing: -0.02em; font-stretch: 92%; }
.demo-header h2 + p { margin-top: 8px; font-size: 1rem; line-height: 1.55; color: var(--ink-2); }

/* Subgrid keeps each row's inputs level even when one label wraps to two lines. */
.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 20px; }
.field { display: grid; grid-row: span 3; grid-template-rows: subgrid; row-gap: 8px; min-width: 0; }
.field-label { align-self: end; font: 600 0.9375rem/1.35 var(--font-display); color: var(--ink); }
.field > input, .field > select, .multiselect { align-self: start; }

.field input, .field select, .multiselect-toggle {
  width: 100%; height: 48px; margin: 0; padding: 0 14px;
  border: 1px solid var(--field-border); border-radius: var(--r-sm);
  background-color: var(--surface); color: var(--ink);
  font: 400 1rem/1.25 var(--font-body);
  transition: border-color 120ms var(--ease), box-shadow 120ms var(--ease);
}
.field input::placeholder { color: var(--ink-3); opacity: 1; }
.field select, .multiselect-toggle {
  -webkit-appearance: none; appearance: none; padding-right: 44px; cursor: pointer;
  background: var(--surface) var(--i-chevron-down) right 14px center / 18px no-repeat;
}
.field select:invalid { color: var(--ink-3); }
.field select option { color: var(--ink); }
.field input:hover, .field select:hover, .multiselect-toggle:hover { border-color: var(--ink-3); }
.field input:focus-visible, .field select:focus-visible, .multiselect-toggle:focus-visible,
.multiselect.is-open .multiselect-toggle {
  outline: none; border-color: var(--accent); border-radius: var(--r-sm);
  box-shadow: 0 0 0 2px var(--accent), 0 0 0 6px color-mix(in srgb, var(--accent) 22%, transparent); /* 1px border + 2px = 3px rust ring */
}
.field.is-invalid input, .field.is-invalid select, .field.is-invalid .multiselect-toggle {
  border-color: var(--danger); box-shadow: 0 0 0 1px var(--danger);
}
.field-error { display: flex; gap: 6px; min-height: 20px; margin-bottom: 12px; font: 0.875rem/1.4 var(--font-body); color: var(--danger); }
/* Icon drawn in CSS so script.js can keep setting textContent. */
.field-error:not(:empty)::before { content: ""; flex: none; width: 16px; height: 16px; margin-top: 2px; background: currentColor; -webkit-mask: var(--i-alert) center / contain no-repeat; mask: var(--i-alert) center / contain no-repeat; }

/* Business types: a disclosure that opens inline, so it never needs clipping or drop-up math. */
.multiselect-toggle { display: flex; align-items: center; text-align: left; }
.multiselect-value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.multiselect-value.is-placeholder { color: var(--ink-3); }
.multiselect.is-open .multiselect-toggle { background-image: var(--i-chevron-up); }
/* Four rows, then the list scrolls inside its own border; the edge shadow means "more below". */
.multiselect-panel {
  max-height: 200px; overflow-y: auto; overscroll-behavior: contain;
  margin-top: 8px; padding: 4px; border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  background:
    linear-gradient(var(--surface), var(--surface)) center bottom / 100% 16px no-repeat local,
    linear-gradient(color-mix(in srgb, var(--ink) 0%, transparent), color-mix(in srgb, var(--ink) 12%, transparent)) center bottom / 100% 16px no-repeat scroll,
    var(--surface);
}
.multiselect-option {
  position: relative; display: flex; align-items: center; gap: 12px;
  min-height: 44px; padding: 0 10px; border-radius: 6px; cursor: pointer;
  font-size: 1rem; color: var(--ink);
}
.multiselect-option + .multiselect-option { margin-top: 2px; }
.multiselect-option:hover { background: var(--sunk); }
.multiselect-option:has(input:checked) { background: var(--crema); }
.field .multiselect-option input { position: absolute; opacity: 0; width: 1px; height: 1px; padding: 0; border: 0; pointer-events: none; }
.multiselect-box {
  flex: none; width: 20px; height: 20px; display: grid; place-items: center;
  border-radius: var(--r-xs); border: 1.5px solid var(--field-border); background: var(--surface);
}
.multiselect-option input:checked + .multiselect-box { background: var(--accent); border-color: var(--accent); }
.multiselect-option input:checked + .multiselect-box::after { content: ""; width: 13px; height: 13px; background: var(--on-accent); -webkit-mask: var(--i-check) center / contain no-repeat; mask: var(--i-check) center / contain no-repeat; }
.multiselect-option input:focus-visible + .multiselect-box { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Business-referral status (business-referral.js inserts <small> + a Retry button right after the select for ?ref=biz_ links). */
.field--referral:has(> [data-business-referral-status]) { grid-row: span 4; }
.field--referral:has(> [data-business-referral-status] + .btn:not([hidden])) { grid-row: span 5; }
.field select:disabled { cursor: not-allowed; opacity: 1; color: var(--ink-2); background-image: none; background-color: var(--sunk); border-color: var(--line-strong); }
[data-business-referral-status] { display: flex; gap: 10px; font-size: 0.875rem; line-height: 1.45; color: var(--ink-2); }
[data-business-referral-status]:empty { display: none; }
[data-business-referral-status]::before { content: ""; flex: none; width: 8px; height: 8px; margin-top: 6px; border-radius: 50%; background: var(--danger); box-shadow: 0 0 0 3px color-mix(in srgb, var(--danger) 14%, transparent); }
.field--referral > .btn { justify-self: start; min-height: 44px; font-size: 0.9375rem; }

.form-note { margin: 4px 0 24px; text-wrap: pretty; font-size: 0.875rem; line-height: 1.5; color: var(--ink-3); }
.form-actions {
  position: sticky; bottom: 0; z-index: 1;
  display: flex; align-items: center; gap: 12px; margin: 0 -40px; padding: 16px 40px 20px;
  background: var(--surface); border-top: 1px solid var(--line);
  box-shadow: 0 -10px 20px -16px color-mix(in srgb, var(--ink) 28%, transparent);
}
.form-actions .btn { min-height: 48px; padding: 0 22px; font-size: 1rem; }
/* The hint is first in the DOM so it reads before the button; shown beside it on wide screens. */
.form-actions .form-note { order: 1; flex: 1; margin: 0 0 0 4px; text-wrap: balance; line-height: 1.4; }
.form-status { margin: 0 0 16px; font-size: 0.9375rem; line-height: 1.5; color: var(--ink-2); }
.form-status[data-status="error"] { color: var(--danger); }
.form-status:empty { display: none; }

/* ---------- Demo success ---------- */

.demo-modal.is-success .demo-dialog { width: min(100%, 520px); }
.demo-success { overflow-y: auto; padding: 48px 40px 40px; }
.demo-success-card { display: grid; justify-items: center; text-align: center; }
.demo-success-icon { width: 56px; height: 56px; margin-bottom: 24px; }
.demo-success-icon svg { width: 100%; height: 100%; display: block; }
.demo-success-card .eyebrow { margin-bottom: 12px; color: var(--ink-3); }
.demo-success-card h2 { font-size: 2rem; line-height: 1.1; letter-spacing: -0.024em; font-stretch: 92%; }
.demo-success-lede { max-width: 36ch; margin-top: 14px; font-size: 1.0625rem; line-height: 1.55; color: var(--ink-2); }
.demo-success-lede strong { color: var(--ink); white-space: nowrap; }
.demo-success-note {
  justify-self: stretch; margin-top: 28px; text-wrap: balance; padding-top: 20px; border-top: 1.5px dashed var(--line-strong);
  font: 0.875rem/1.45 var(--font-body); color: var(--ink-3);
}
.demo-success-note svg { display: inline-block; width: 18px; height: 18px; margin: -3px 8px 0 0; vertical-align: middle; color: var(--ink-3); }
.demo-success-card .btn { margin-top: 24px; min-width: 200px; }

/* ---------- 404 basics (refined in the pages section at the end of this file) ---------- */

.error-page { position: relative; padding-block: clamp(48px, 8vw, 120px); }
.error-panel {
  max-width: 760px; margin-inline: auto; padding: clamp(28px, 5vw, 48px);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--e2);
}
.error-code { margin-top: 24px; font: 600 clamp(4rem, 2.5rem + 6vw, 6.5rem)/0.9 var(--font-mono); letter-spacing: -0.06em; color: var(--ink-3); }
.error-panel h1 { margin: 20px 0 14px; font-size: clamp(2.25rem, 1.6rem + 2.4vw, 3.5rem); line-height: 1; letter-spacing: -0.03em; font-stretch: 88%; }
.error-copy { margin-top: 14px; max-width: 46ch; color: var(--ink-3); }
.error-actions { margin-top: 28px; }

/* ---------- Reveal ---------- */

/* Below-the-fold blocks fade up as they scroll in. The hero is never hidden (LCP), and nothing hides
   without script or under reduced motion. */
@media (prefers-reduced-motion: no-preference) and (scripting: enabled) {
  [data-animate] { transition: opacity 600ms var(--ease), transform 600ms var(--ease); }
  [data-animate]:not(.is-visible) { opacity: 0; transform: translateY(16px); }
  .hero [data-animate]:not(.is-visible) { opacity: 1; transform: none; }
}

/* Offscreen sections skip rendering until near the viewport; the anchor scroller in script.js
   re-aims while their real heights come in. */
/* Placeholder heights ~ real heights (coffee mockup measured at 1440 here, 390 in the phone block, 810 for the
   stacked digital menu), so the page length barely moves as they render. */
.testimonials, .compare, .digital-menu, .faq { content-visibility: auto; }
.testimonials { contain-intrinsic-size: auto 988px; }
.compare { contain-intrinsic-size: auto 1415px; }
.digital-menu { contain-intrinsic-size: auto 1142px; }
.faq { contain-intrinsic-size: auto 2082px; }

/* ---------- Responsive ---------- */

@media (max-width: 1100px) {
  .screen-thumbs { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 960px) {
  .hero-grid { grid-template-columns: minmax(0, 1fr); }
  .hero-copy { max-width: 640px; }
  .lead { max-width: 46ch; }
  .hero-media { padding-top: 56px; }
  .hero-bullets { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hero-bullets li:nth-child(3) { border-left: 0; padding-left: 0; }
  .hero-bullets li:nth-child(n + 3) { border-top: 1px solid var(--line); }
  .feature-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .feature-group-label { grid-template-columns: auto minmax(0, 1fr); row-gap: 6px; }
  .feature-group-note { grid-column: 2; text-align: left; }
  .partner-card--integration { grid-column: 1 / -1; }
  .faq-layout { grid-template-columns: minmax(0, 1fr); }
  .faq-intro { position: static; }
  .closing-inner { flex-direction: column; align-items: flex-start; }
  .footer-grid { grid-template-columns: minmax(0, 1fr); row-gap: 48px; }
  .footer-legal { margin-top: 0; }
}

@media (min-width: 721px) and (max-width: 960px) {
  .hero-media { --hero-media-top: 136px; padding-top: var(--hero-media-top); } /* the steam follows (end of file) */
  .digital-menu { contain-intrinsic-size: auto 1628px; } /* 810 measured; 1626-1628 across the band */
}

@media (max-width: 720px) {
  .section-header { margin-bottom: 32px; }
  .section-header--split { flex-direction: column; align-items: flex-start; gap: 20px; }
  .cta-row .btn { flex: 1 1 100%; }
  .proof { margin-top: 24px; }

  .hero-media { padding: 28px 0 0; }
  .device-frame--tablet { padding: 6px; border-radius: 14px; }
  .device-screen img { border-radius: 6px; }
  .callout { height: 0 !important; top: var(--y) !important; }
  .callout::before, .callout-label { display: none; }
  .callout-dot {
    top: 0 !important; width: 20px; height: 20px; display: grid; place-items: center;
    box-shadow: 0 0 0 2px var(--night), 0 2px 6px color-mix(in srgb, var(--ink) 30%, transparent);
    font: 700 0.8125rem/1 var(--font-mono); color: var(--night);
  }
  .callout--up .callout-dot { transform: translate(-50%, -100%); }
  .callout--down .callout-dot { transform: translate(-50%, 0); }
  .callout-dot::after { content: attr(data-n); }
  .callout-legend {
    position: static; width: auto; height: auto; margin: 16px 0 0; overflow: visible; clip: auto; white-space: normal;
    display: grid; gap: 8px;
    font: 500 0.8125rem/1.35 var(--font-mono); color: var(--ink-2);
  }
  .callout-legend li { display: flex; align-items: center; gap: 10px; }
  .callout-legend b {
    width: 24px; height: 24px; flex: none; display: grid; place-items: center; border-radius: 50%;
    background: var(--night); color: var(--caramel); font-size: 0.8125rem;
  }

  .hero-specs-band { margin-top: 32px; }
  .hero-bullets { grid-template-columns: minmax(0, 1fr); }
  .hero-bullets li, .hero-bullets li:nth-child(n) {
    display: grid; grid-template-columns: 92px minmax(0, 1fr); gap: 12px; align-items: baseline;
    padding: 16px 0; border-left: 0; border-top: 1px solid var(--line);
  }
  .hero-bullets li:first-child { border-top: 0; }
  .spec-key { margin: 0; }

  /* One ticket in view: let each hang at its own length. */
  .testimonial-set { gap: 12px; align-items: flex-start; }
  .testimonial-card { flex-basis: min(86vw, 372px); }
  .testimonial-copy.is-clamped { -webkit-line-clamp: 7; line-clamp: 7; }

  .compare-board-top { display: none; }
  .compare-row { grid-template-columns: minmax(0, 1fr); padding: 20px; gap: 10px; }
  .compare-topic { padding: 0 0 4px; }
  .compare-cell { display: grid; grid-template-columns: 26px minmax(0, 1fr); column-gap: 12px; row-gap: 8px; padding: 16px; border-radius: var(--r-sm); }
  .compare-cell-portal, .compare-row + .compare-row .compare-cell-portal, .compare-row:last-child .compare-cell-portal { margin: 0; padding: 16px; border: 0; border-radius: var(--r-sm); box-shadow: var(--e2); }
  .compare-cell-typical { border: 1px solid var(--line); }
  .compare-row:last-child .compare-cell-typical { border-radius: var(--r-sm); }
  .compare-cell p { display: contents; }
  .ledger-label {
    position: static; width: auto; height: auto; overflow: visible; clip: auto; white-space: normal;
    grid-column: 1 / -1; grid-row: 1; margin-bottom: 2px;
    font: 500 0.8125rem/1 var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase;
  }
  .compare-cell-portal .ledger-label { color: var(--caramel); }
  .compare-cell-typical .ledger-label { color: var(--typ-ink); }
  .compare-cell-typical { border-color: color-mix(in srgb, var(--typ-ink) 16%, var(--typ-tint)); }
  .compare-cell .icon { grid-row: 2; }

  .screen-stage { padding: 6px; border-radius: 14px; }
  .screen-stage img { border-radius: 6px; }
  .screens-caption { white-space: nowrap; }
  .screens-caption > span + span { display: none; }
  .screen-thumbs { gap: 12px; }
  .thumb { font-size: 0.8125rem; }

  .feature-grid { grid-template-columns: minmax(0, 1fr); gap: 10px; }
  .feature-group-label { margin-top: 32px; padding-bottom: 12px; margin-bottom: 4px; }
  .feature-group-num { width: 30px; height: 30px; }
  /* Phones: compact rows, icon tile on the left. */
  .feature-card { display: grid; grid-template-columns: 40px minmax(0, 1fr); column-gap: 14px; padding: 16px; }
  .feature-icon { grid-row: span 2; width: 40px; height: 40px; margin: 0; }
  .feature-card .icon { width: 20px; height: 20px; }
  .feature-card p { margin-top: 4px; }

  .partner-grid { gap: 12px; }
  .partner-card, .partner-card--integration { grid-column: 1 / -1; }
  /* Phones: logo + category on one line, description full width underneath. */
  .partner-card__link, .partner-card--integration .partner-card__link {
    display: grid; grid-template-columns: 104px minmax(0, 1fr); grid-template-areas: "logo kind" "desc desc";
    align-items: center; column-gap: 16px; row-gap: 14px; padding: 12px 12px 18px;
  }
  .partner-card__logo, .partner-card--integration .partner-card__logo { grid-area: logo; height: 72px; padding: 10px; }
  .partner-card__logo img { max-height: 48px; }
  .partner-card__logo--wordmark img { max-height: 24px; }
  .partner-card__body, .partner-card--integration .partner-card__body { display: contents; }
  .partner-card__kind { grid-area: kind; padding-right: 32px; }
  .partner-card__description { grid-area: desc; padding: 0 4px; }
  .partner-card__go, .partner-card--integration .partner-card__go { top: 12px; right: 12px; width: 24px; height: 24px; padding: 5px; }
  .partners-cta { padding: 8px 16px; }

  .faq-item p { padding-right: 0; }
  .closing .cta-row { width: 100%; }
  .footer-legal { flex-direction: column-reverse; align-items: stretch; }

  .testimonials { contain-intrinsic-size: auto 934px; }
  .compare { contain-intrinsic-size: auto 3266px; }
  .digital-menu { contain-intrinsic-size: auto 1788px; }
  .faq { contain-intrinsic-size: auto 2497px; }

  /* Demo modal: bottom sheet that starts 48px down, so a tap at the top of the screen still closes it. */

  .demo-modal { display: block; padding: 0; }
  .demo-dialog { position: absolute; inset: 48px 0 0; width: auto; max-height: none; border-radius: var(--r-lg) var(--r-lg) 0 0; }
  .demo-close { top: 12px; right: 12px; }
  .demo-content { padding: 0 20px; scroll-padding-block: 96px 160px; }
  /* A 64px sticky band behind the close button: fields scroll under the band, never under the button.
     It takes 28px of flow (as before) and the eyebrow + title sit above it, so the resting sheet is unchanged. */
  .demo-content::before { height: 64px; margin: 0 -20px -36px; background: linear-gradient(var(--surface) 58px, color-mix(in srgb, var(--surface) 0%, transparent)); }
  .demo-header .eyebrow, .demo-header h2 { position: relative; z-index: 2; }
  .demo-header { margin-bottom: 24px; }
  .demo-header .eyebrow, .demo-header h2 { padding-right: 48px; }
  .demo-header h2 { font-size: 1.625rem; }
  /* One column needs no row alignment, so empty error rows collapse. */
  .form-grid { grid-template-columns: minmax(0, 1fr); }
  .field-error { margin-bottom: 16px; }
  .field-error:empty { min-height: 0; }
  .form-actions { flex-wrap: wrap; row-gap: 10px; margin: 0 -20px; padding: 12px 20px calc(12px + env(safe-area-inset-bottom)); }
  .form-actions .form-note { order: 0; flex: 1 0 100%; margin: 0; }
  .form-actions .btn-primary { flex: 2 1 0; }
  .form-actions .btn-secondary { flex: 1 1 0; }
  .form-actions .btn { padding: 0 12px; }
  .demo-modal.is-success .demo-dialog { inset: auto 0 0; max-height: calc(100dvh - 48px); }
  .demo-success { padding: 40px 20px calc(24px + env(safe-area-inset-bottom)); }
  .demo-success-card h2 { font-size: 1.75rem; }
  .demo-success-card .btn { justify-self: stretch; }
}

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

/* ================================================================
   Pages (calculator / download / 404): owned by the PAGES pass.
   Add page-specific rules below this line.
   ================================================================ */

/* ---------- Secondary pages: download + 404 ---------- */
/* Port of the download/404 parts of design/daylight-mockups/pages.css. The calculator lives in calculator.css. */

/* Download */
.dl-hero { position: relative; padding-block: clamp(40px, 6vw, 88px) var(--section-pad); }
.dl-hero::before, .error-page::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--ink) 6%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--ink) 6%, transparent) 1px, transparent 1px);
  background-size: 24px 24px;
  -webkit-mask-image: radial-gradient(ellipse 38% 60% at 72% 46%, #000 10%, transparent 70%);
  mask-image: radial-gradient(ellipse 38% 60% at 72% 46%, #000 10%, transparent 70%);
}
.dl-grid {
  position: relative;
  display: grid; grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
  gap: clamp(40px, 6vw, 96px); align-items: center;
}
.dl-eyebrow { margin: 0; }
.dl-eyebrow::before { content: ""; width: 12px; height: 12px; flex: none; background: var(--glyph) center / contain no-repeat; }
.dl-copy h1 {
  margin: 18px 0 20px;
  font-size: clamp(2.5rem, 1.6rem + 3.4vw, 4.25rem);
  line-height: 0.98; letter-spacing: -0.032em; font-stretch: 88%;
}
.dl-tags { margin-top: 24px; }
.dl-note {
  display: flex; gap: 12px; align-items: flex-start; max-width: 50ch;
  margin-top: 16px; padding: 14px 16px;
  border: 1px dashed var(--line-strong); border-radius: var(--r-sm); background: var(--surface);
  font-size: 0.9375rem; line-height: 1.5; color: var(--ink-2);
}
.dl-note .icon { width: 18px; height: 18px; margin-top: 2px; color: var(--accent); }
.dl-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-top: 28px; max-width: 520px; }
.dl-actions .btn { justify-content: space-between; }
.dl-actions .btn .icon { opacity: 0.8; }
.dl-actions .dl-back { grid-column: 1 / -1; justify-content: center; }

.dl-proof { margin: 36px 0 0; max-width: 520px; border-top: 1px solid var(--ink); }
.dl-proof > div {
  display: grid; grid-template-columns: 120px minmax(0, 1fr); gap: 16px; align-items: baseline;
  padding: 16px 0; border-bottom: 1px solid var(--line-strong);
}
.dl-proof dt { font: 600 0.8125rem/1 var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-3); }
.dl-proof dd { margin: 0; font: 600 1.0625rem/1.35 var(--font-display); color: var(--ink); }

.dl-media { position: relative; display: flex; flex-direction: column; align-items: center; padding: 8px 0 40px; }
.dl-status { margin-bottom: 20px; }
.dl-phone { width: min(100%, 300px); }
/* The screenshot carries its own status bar, so no 44px gutter here (unlike the digital-menu phone). */
.dl-phone .phone-screen { aspect-ratio: 368 / 800; padding-top: 0; background: var(--surface); }
.dl-phone .phone-screen::before { top: 8px; width: 76px; height: 22px; margin-left: -38px; }
.dl-phone .phone-screen img { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.dl-overlay {
  position: absolute; left: 50%; bottom: 0; z-index: 2;
  width: min(100%, 280px); transform: translateX(-78%);
  display: grid; gap: 8px; padding: 16px 18px 18px;
  background: var(--night); border-radius: var(--r-md); box-shadow: var(--e3);
}
.dl-overlay span {
  display: flex; align-items: center; gap: 8px;
  font: 500 0.8125rem/1 var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--on-dark-2);
}
.dl-overlay span::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--sage); box-shadow: 0 0 0 3px color-mix(in srgb, var(--sage) 22%, transparent); }
.dl-overlay strong { font: 600 1.125rem/1.3 var(--font-display); color: var(--on-dark); letter-spacing: -0.01em; }

/* 404: a ticket with a torn-off stub. .error-panel / .error-actions are the test hooks. */
.error-page::before {
  -webkit-mask-image: radial-gradient(ellipse 50% 70% at 50% 50%, #000 15%, transparent 72%);
  mask-image: radial-gradient(ellipse 50% 70% at 50% 50%, #000 15%, transparent 72%);
}
.nf-ticket {
  position: relative; max-width: 940px; padding: 0;
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
}
.nf-stub {
  position: relative; display: flex; flex-direction: column; justify-content: space-between; gap: 40px;
  padding: 40px; border-right: 1.5px dashed var(--line-strong);
  border-radius: var(--r-lg) 0 0 var(--r-lg);
  background-color: var(--surface);
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--ink) 5.5%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--ink) 5.5%, transparent) 1px, transparent 1px);
  background-size: 24px 24px; background-position: 40px 40px;
}
/* Notches where the perforation meets the edges. */
.nf-stub::before, .nf-stub::after {
  content: ""; position: absolute; right: -12px; width: 22px; height: 22px; border-radius: 50%;
  background: var(--paper); border: 1px solid var(--line);
}
.nf-stub::before { top: -12px; clip-path: inset(50% 0 0 0); }
.nf-stub::after { bottom: -12px; clip-path: inset(0 0 50% 0); }
.mark-missing { width: 96px; height: 96px; }
.nf-code {
  font: 600 clamp(5.5rem, 3rem + 7vw, 7.5rem)/0.85 var(--font-mono); letter-spacing: -0.06em; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.nf-body { padding: 44px 48px 48px; }
.nf-body h1 { margin: 28px 0 16px; }
.nf-body .lead { max-width: 40ch; font-size: clamp(1.0625rem, 1rem + 0.3vw, 1.25rem); }
.nf-body .error-copy { font-size: 1rem; }

@media (max-width: 960px) {
  .dl-grid { grid-template-columns: minmax(0, 1fr); max-width: 640px; }
  .nf-ticket { grid-template-columns: minmax(0, 1fr); }
  .nf-stub { flex-direction: row; align-items: flex-end; padding: 32px; border-right: 0; border-bottom: 1.5px dashed var(--line-strong); border-radius: var(--r-lg) var(--r-lg) 0 0; }
  .nf-stub::before, .nf-stub::after { top: auto; bottom: -12px; right: auto; clip-path: inset(0 0 0 50%); }
  .nf-stub::before { left: -12px; }
  .nf-stub::after { left: auto; right: -12px; clip-path: inset(0 50% 0 0); }
}

@media (max-width: 720px) {
  .dl-actions { grid-template-columns: minmax(0, 1fr); }
  .dl-proof > div { grid-template-columns: 96px minmax(0, 1fr); }
  .dl-media { padding-bottom: 0; }
  .dl-phone { width: min(78%, 260px); }
  /* Caption under the phone instead of over the bezel. */
  .dl-overlay { position: relative; left: auto; bottom: auto; transform: none; margin-top: 16px; width: min(100%, 320px); }

  .nf-stub { padding: 24px; gap: 24px; }
  .mark-missing { width: 72px; height: 72px; }
  .nf-body { padding: 28px 24px; }
  .nf-body h1 { margin-top: 22px; }
}

/* ==================== coffee.css ==================== */
/* TABL coffee "Steamed Milk": the coffee signature layer. Loads after base.css (the recoloured Daylight fork),
   overrides production selectors only, so an approved mockup ports as base.css + coffee.css.
   Spec: design/coffee-refresh/research/verdict.md §4-§6 (build-overrides.md wins on conflicts).

   Contents (page order):
     1. Type          2. Primitives (pill buttons, tags, focus)     3. Menu-board eyebrows (--sec)
     4. Header / nav  5. Hero (saucer, tablet, callouts, proof punch card)   6. Spec strip (menu board)
     6a. Testimonials  6b. Compare  6c. Screens  6d. Features  6e. Digital menu  6f. Partners  6g. FAQ
     7. Closing band (caramel)   8. Footer (espresso)   9. Demo modal skin   10. Responsive for 1-9
     11. Responsive for the sections (6a-6g)
   Rules that bind every section: rust never sits on espresso (use --caramel there); caramel is never text on light;
   the page stays latte/foam, never white. */

/* ---------- 1. Type ---------- */

h1, h2, h3 { font-optical-sizing: auto; font-stretch: normal; }
.section-header h2 { font-size: clamp(1.875rem, 3.4vw, 3rem); line-height: 1.04; letter-spacing: -0.03em; font-weight: 650; }
.hero h1 {
  font-size: clamp(2.75rem, 5vw, 4.5rem); /* 44-72px: "The Best Coffee / Shop POS" on two lines at 1440 and 390 */
  line-height: 0.96; letter-spacing: -0.04em; font-weight: 680;
}
/* Two-column hero only: the H1 may overhang into the grid gap ("The Best Coffee" is 474px at 72px, the column 463-469px). */
@media (min-width: 961px) { .hero h1 { margin-right: -32px; } }

/* ---------- 2. Primitives ---------- */

:focus-visible { outline-width: 3px; }
.btn { border-radius: var(--r-pill); padding: 0 20px; }
.btn-lg { padding: 0 26px; }
.btn-secondary:hover { background: var(--paper); }

/* ---------- 3. Menu-board eyebrows ----------
   "TESTIMONIALS ········ 01": label, dotted leader, the section number in the price slot (rust; caramel on espresso).
   The number comes from --sec (set per section id in base.css), so the eyebrow textContent is untouched. */

.page-landing main > section .section-header .eyebrow { align-items: baseline; max-width: 360px; font-weight: 600; }
.page-landing main > section .section-header .eyebrow::before,
.page-landing .band--night .section-header .eyebrow::before {
  content: ""; order: 1; flex: 1; min-width: 24px; padding: 0; background: none;
  border-bottom: 2px dotted var(--line-strong); transform: translateY(-3px);
}
.page-landing main > section .section-header .eyebrow::after { content: var(--sec); order: 2; color: var(--accent); font-variant-numeric: tabular-nums; }
.page-landing .band--night .section-header .eyebrow::before { border-bottom-color: color-mix(in srgb, var(--on-dark-2) 45%, transparent); }
.page-landing .band--night .section-header .eyebrow::after { color: var(--caramel); }

/* ---------- 4. Header / nav ---------- */

/* The bar is --paper itself (base.css), so it never reads brighter than the page. */
.nav-toggle { border-radius: var(--r-pill); border-color: var(--field-border); }

/* ---------- 5. Hero ---------- */

.hero { overflow: clip; padding-top: clamp(36px, 5vw, 72px); }
.hero::before { content: none; } /* the saucer is the only texture: no grid or gradient (the one glow is the ambient morning light, end of file) */
.hero .lead { max-width: 37ch; }

/* Proof row as a loyalty punch card: one ringed stamp per published testimonial. */
.proof { flex-wrap: wrap; gap: 12px 16px; }
.proof-avatars {
  gap: 8px; padding: 7px; border-radius: 14px;
  background: var(--surface); border: 1.5px dashed var(--line-strong);
}
.proof-avatars > span, .proof-avatars > span:first-child {
  width: 40px; height: 40px; margin: 0; border: 0;
  background: var(--surface); box-shadow: 0 0 0 2px var(--caramel);
}

/* Saucer: top view of a cup on a saucer. A flat latte disc and two hairline rings behind the device.
   Reusable: add .saucer to any positioned block (phone, download, 404). Knobs: --saucer (disc width),
   --saucer-x (shift right; the hero uses it to keep the rings off the lead), --saucer-y (centre). */
.hero-media, .saucer { position: relative; isolation: isolate; }
.hero-media::before, .hero-media::after, .saucer::before, .saucer::after {
  content: ""; position: absolute; left: calc(50% + var(--saucer-x, 0px)); top: var(--saucer-y, 50%); z-index: -1; aspect-ratio: 1; border-radius: 50%;
  transform: translate(-50%, -50%); pointer-events: none;
}
.hero-media::before, .saucer::before { width: var(--saucer, 100%); background: var(--sunk); box-shadow: inset 0 0 0 1px var(--line); }
.hero-media::after, .saucer::after {
  width: calc(var(--saucer, 100%) + 12%);
  border: 1px solid var(--line-strong); outline: 1px solid var(--line-strong); outline-offset: 28px;
}
.hero-media { padding-bottom: 128px; --saucer-x: 24px; } /* bottom room for the three-line callout 03; top stays base.css */

.device-frame--tablet { padding: 12px; } /* radius 24 (--r-lg), 1px on-dark rim + --e3 come from base.css */
.device-screen img { border-radius: 12px; }

/* Callouts: espresso menu-board chips on 1px ink leaders; caramel dots with an espresso ring (base.css).
   Positions are % of coffee's own 1080x675 J's Coffee order-queue shot (Portal 2.6.1). */
.callout-label {
  gap: 9px; padding: 8px 12px; border: 0; border-radius: var(--r-sm);
  background: var(--night); color: var(--on-dark); box-shadow: var(--e2);
}
.callout-label b, .callout-label em { font-weight: 700; color: var(--caramel); }
.callout-label:has(small) { align-items: flex-start; }
.callout-label small, .callout-legend small { display: block; margin-top: 6px; font: 500 0.8125rem/1.3 var(--font-mono); }
/* The ticket line wraps to two balanced lines on the chip too (under 22rem), so the flipped chip stays clear of the
   proof row; the chip's first line keeps base.css's nowrap. */
.callout-label small { max-width: 22rem; white-space: normal; color: var(--on-dark-2); }
.callout-label small, .callout-legend small { text-wrap: balance; }
.callout--down.callout--flip .callout-label { transform: translate(calc(-100% + 12px), 100%); }
@media (prefers-reduced-motion: no-preference) {
  /* Leaders draw once; nothing loops. */
  .callout::before { transform-origin: 0 100%; animation: coffee-leader 700ms var(--ease) 250ms both; }
  .callout--down::before { transform-origin: 0 0; }
  @keyframes coffee-leader { from { transform: scaleY(0); } }
}

/* ---------- 6. Spec strip: the menu board ----------
   Full-bleed espresso band; caramel mono keys (aria-hidden) with dotted caramel leaders; bullet text verbatim. */

.hero-specs-band { margin-top: 8px; background: var(--night); border: 0; color: var(--on-dark); }
.hero-bullets { gap: 28px 40px; padding-block: 30px 32px; }
.hero-bullets li, .hero-bullets li:nth-child(n) {
  display: block; padding: 0; border: 0;
  font-size: 0.9375rem; line-height: 1.5; color: var(--on-dark);
}
.spec-key {
  display: flex; align-items: baseline; gap: 10px; margin-bottom: 10px;
  font: 700 0.8125rem/1 var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--caramel);
}
.spec-key::after { content: ""; flex: 1; min-width: 16px; border-bottom: 2px dotted color-mix(in srgb, var(--caramel) 55%, transparent); transform: translateY(-3px); }

/* ---------- 6a. Testimonials (01): cup labels on the latte band ----------
   Foam cup with a rust grease-pencil circle round the number, a kraft sleeve foot (7% ink ribs, arced top) holding
   the logo, name and an ink source link (7.54 on the sleeve). The counter is a punch card: one hole per card, the card in
   view punched rust (index.html shim sets .is-on). */

.rail-controls { gap: 10px; }
.section-header--split > .rail-controls { max-width: 100%; } /* column width, not the 700px text cap: at 320 this is what makes the holes shrink */
.rail-btn { flex: none; border-radius: 50%; }
/* One hole per card on one line: holes are 10px (8px on phones) and shrink to share whatever the arrows and
   "01 / 13" leave, so the row never overflows whatever the card count or the device's monospace font
   (13 holes come out about 6px at 320). */
.punches { display: inline-flex; align-items: center; gap: 5px; margin-left: 6px; min-width: 0; }
.punches i { width: 10px; min-width: 0; aspect-ratio: 1; border-radius: 50%; border: 1.5px solid var(--field-border); }
.punches i.is-on { background: var(--accent); border-color: var(--accent); }
.rail-count { flex: none; min-width: 0; text-align: left; white-space: nowrap; }
@media (max-width: 440px) {
  .punches { gap: 4px; margin-left: 2px; }
  .punches i { width: 8px; }
}
@media (max-width: 359px) {
  .rail-controls { gap: 8px; }
  .punches { gap: 3px; }
}

.testimonial-set { gap: 20px; padding-bottom: 28px; } /* room for the --e2 shadow inside the scroller */
.testimonial-card {
  flex-basis: clamp(344px, 29vw, 360px); overflow: hidden; /* 344 min: the sleeve row (logo, name, source) keeps names to two lines */
  border-radius: var(--r-md) var(--r-md) 22px 22px; box-shadow: var(--e2);
}
.ticket-stub { padding: 20px 22px 0; border-bottom: 0; }
.ticket-stub::before, .ticket-stub::after { content: none; }
.ticket-stub > span:first-child {
  display: inline-grid; place-items: center; min-width: 40px; height: 40px; padding: 0 8px;
  border: 2px solid var(--accent); border-radius: 48% 52% 50% 46% / 54% 46% 54% 46%; /* a hand-drawn ring, not a perfect circle */
  font: 700 0.875rem/1 var(--font-mono); letter-spacing: 0.02em; color: var(--accent); transform: rotate(-6deg);
}
.ticket-stub .stars { color: var(--star); font-size: 1rem; letter-spacing: 0.08em; }
.testimonial-copy { padding: 16px 22px 0; margin-bottom: 22px; font-size: 1.0625rem; } /* no bottom padding: the clamp would show line 10 in it */
.ticket-more { align-self: flex-start; margin: -12px 18px 14px; }
.ticket-foot {
  margin-top: auto; min-height: 108px; padding: 26px 22px 18px; /* = a two-line name, so every sleeve in the rail starts level */
  background: var(--kraft) repeating-linear-gradient(90deg, color-mix(in srgb, var(--ink) 7%, transparent) 0 1px, transparent 1px 7px);
  border-radius: 50% 50% 0 0 / 16px 16px 0 0; /* the sleeve's printed arc */
}
.testimonial-logo { width: 48px; height: 48px; box-shadow: 0 0 0 2px var(--surface); }
.testimonial-business { font-weight: 650; }
.testimonial-owner { color: var(--ink-2); white-space: nowrap; }
.ticket-source { color: var(--ink); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.2em; }
.ticket-source:hover { color: var(--ink); text-decoration-thickness: 2px; }

/* ---------- 6b. Compare (02): crema is TABL's side ----------
   The raised, overhanging column keeps Daylight's geometry; ink becomes crema with a 4px rust cap and
   crema-line edges. Typical stays the cherry-hatched column from base.css. */

.compare-board-top span:nth-child(2) {
  background: var(--crema); color: var(--accent-hover); border-bottom-color: var(--crema-line);
  box-shadow: inset 0 4px 0 var(--accent), inset 1px 0 0 var(--crema-line), inset -1px 0 0 var(--crema-line);
}
.compare-board-top span:nth-child(2)::before { background-image: var(--glyph); }
.compare-cell-portal {
  background: var(--crema); color: var(--ink);
  box-shadow: inset 1px 0 0 var(--crema-line), inset -1px 0 0 var(--crema-line),
    12px 0 24px -18px color-mix(in srgb, var(--ink) 34%, transparent), -12px 0 24px -18px color-mix(in srgb, var(--ink) 34%, transparent);
}
.compare-row + .compare-row .compare-cell-portal { border-top-color: var(--crema-line); }
.compare-row:last-child .compare-cell-portal {
  box-shadow: inset 1px 0 0 var(--crema-line), inset -1px 0 0 var(--crema-line), inset 0 -1px 0 var(--crema-line), var(--e2);
}
.ledger-num { color: var(--accent); font-weight: 600; }

/* ---------- 6c. Screens (03): the espresso band ----------
   base.css already draws it in coffee tokens (night band, bezel stage, caramel active ring + glyph, caramel focus). */

.screen-stage { border-radius: var(--r-lg); }
.thumb img { border-radius: var(--r-xs); }

/* ---------- 6d. Features (04): crema number tiles, foam cards, a loyalty punch card ---------- */

.feature-group-label { border-bottom: 2px solid var(--ink); }
.feature-group-num {
  width: 28px; height: 28px; border-radius: var(--r-xs);
  background: var(--crema); box-shadow: inset 0 0 0 1px var(--crema-line); color: var(--accent);
  font: 700 0.8125rem/1 var(--font-mono);
}
.feature-card { box-shadow: none; }
.feature-icon { width: 36px; height: 36px; margin-bottom: 16px; border-radius: var(--r-sm); }
.feature-card .icon { width: 20px; height: 20px; }
/* Customer Loyalty: a crema punch card, dashed inner border 6px in, five of six punched (decorative). */
.feature-card--highlight { position: relative; background: var(--crema); border-color: var(--crema-line); box-shadow: var(--e2); }
.feature-card--highlight::before {
  content: ""; position: absolute; inset: 6px; border: 1.5px dashed var(--crema-line); border-radius: 13px; pointer-events: none;
}
.feature-card--highlight h3 { color: var(--ink); }
.feature-card--highlight p { color: var(--ink-2); }
.feature-card--highlight .feature-icon { background: var(--surface); box-shadow: inset 0 0 0 1px var(--crema-line); color: var(--accent-hover); }
.punch-row { display: flex; gap: 8px; margin-top: auto; padding-top: 18px; }
.punch-row i { width: 14px; height: 14px; border-radius: 50%; background: var(--accent); }
.punch-row i:last-child { background: none; border: 1.5px solid var(--accent); }

/* ---------- 6e. Digital menu (05): scan to ticket on a saucer ----------
   Rust outline step circles; the Try-it card is espresso, so its button flips to a caramel pill with an espresso
   label (rust never sits on espresso) and the QR is espresso modules on a crema plate (never inverted). The saucer
   replaces Daylight's grid, centred on the phone (which sits 66px left of the stage centre where the chips show). */

.dm-step-num { border-radius: 50%; color: var(--accent); box-shadow: inset 0 0 0 1.5px var(--accent); }
.dm-try-key { color: var(--caramel); }
.dm-try-note { margin-top: 6px; font-size: 0.9375rem; line-height: 1.45; color: var(--on-dark-2); }
.dm-try .demo-link { margin-top: 16px; }
.dm-try .btn-primary { background: var(--caramel); border-color: var(--caramel); color: var(--night); }
.dm-try .btn-primary:hover { background: color-mix(in srgb, var(--caramel) 80%, var(--on-dark)); border-color: transparent; color: var(--night); }
.dm-qr { background: var(--on-dark); color: var(--night); }
.dm-stage::before { content: none; }
/* Two-column desktop: Bricolage is wider than Daylight's condensed face, so the H2 steps down a size to keep
   "Showcase your items with / digital and QR menus / tied to your POS" on three lines. */
@media (min-width: 1101px) { .digital-copy .section-header h2 { font-size: clamp(1.875rem, 2.9vw, 2.625rem); } }
.dm-device.saucer { --saucer: 400px; --saucer-x: -66px; }
.dm-device.saucer::after { width: calc(var(--saucer) + 56px); outline-offset: 24px; }
@media (min-width: 1101px) {
  /* One ring, wholly inside the stage: the second ring was clipped at the stage edge and ran behind both chips. */
  .dm-device.saucer { overflow: clip; }
  .dm-device.saucer::after { width: calc(var(--saucer) + 28px); outline: 0; }
  /* The live demo iframe is a Tab stop with no ring of its own: ring the bezel (rust on latte, 4.55). The class is
     set by script.js (a cross-origin iframe never matches :focus-within). */
  .dm-device .phone-frame.is-demo-focused { outline: 3px solid var(--accent); outline-offset: 4px; }
}
.dm-link-list, .dm-ticket-card { border-radius: 0 var(--r-sm) var(--r-sm) var(--r-sm); }
.dm-tab { border-radius: var(--r-xs) var(--r-xs) 0 0; }

/* ---------- 6f. Partners (06): foam plates on the espresso band, an open seat for the next partner ----------
   The band breaks the paper/latte run between Features and the closing band. Rust stays inside the foam cards. */

.partners.band--night .partner-group-label { color: var(--on-dark-2); border-bottom-color: color-mix(in srgb, var(--on-dark) 28%, transparent); }
.partners.band--night .partner-grid > .partners-cta { color: var(--on-dark); background: var(--night-raised); border-color: var(--caramel); }
.partners.band--night .partners-cta a { color: var(--caramel); }
.partners.band--night .partner-card__link:focus-visible, .partners.band--night .partners-cta a:focus-visible { outline-color: var(--caramel); }

.partner-card__link:focus-visible { outline: 3px solid var(--accent); }
.partners-cta a:focus-visible { outline: 3px solid var(--accent); }
/* Community cards retain their horizontal layout. */
.partner-card--wide { grid-column: span 3; }
.partner-card--recipe { grid-column: 1 / -1; }
.partner-card--recipe .partner-card__logo { background: var(--on-accent); }
.partner-card--recipe .partner-card__logo img { mix-blend-mode: normal; height: auto; object-fit: contain; }
.partner-card__name { font: 700 1.5rem/1.2 var(--font-display); color: var(--ink); }
@media (min-width: 721px) { /* phones use base.css's logo + kind row for every card */
  .partner-card--wide .partner-card__link { flex-direction: row; align-items: center; gap: 28px; padding: 16px 28px 16px 16px; }
  .partner-card--wide .partner-card__logo { flex: 0 0 46%; }
  .partner-card--recipe .partner-card__logo { flex-basis: 30%; height: 150px; }
  .partner-card--recipe .partner-card__logo img { max-height: 112px; }
  .partner-card--wide .partner-card__body { padding: 0 28px 0 0; }
  .partner-card--wide .partner-card__go { top: 16px; right: 16px; }
  /* Top-aligned text, so every kind line sits 30px below its card top (a ledger, not three centred blocks). */
  .partner-card--integration .partner-card__body, .partner-card--wide .partner-card__body { align-self: flex-start; padding-top: 8px; }
}
.partner-grid > .partners-cta {
  grid-column: 1 / -1; display: grid; align-content: center; justify-items: start; gap: 14px;
  padding: 28px; background: var(--crema); border: 1px solid var(--crema-line); border-left: 4px solid var(--accent); border-radius: 16px;
  color: var(--ink);
}
.partners-cta h3 { max-width: 22ch; font: 700 clamp(1.375rem, 2.1vw, 1.875rem)/1.2 var(--font-display); color: inherit; }
.partners-cta p { max-width: 44ch; font: 400 1rem/1.5 var(--font-body); }
.partner-grid > .partners-cta a { min-height: 44px; gap: 10px; font: 700 1rem/1.3 var(--font-body); }
.partners-cta__email { font: 400 0.875rem/1.4 var(--font-body); }
.partner-card__link:active { transform: translateY(0); }
.partners-cta a:active { opacity: 0.8; }

/* ---------- 6g. FAQ (07): latte band, dotted group leaders, round toggles ---------- */

.still-deciding {
  padding: 18px 20px; border: 1px solid var(--crema-line); border-radius: var(--r-md);
  background: var(--crema); color: var(--ink-2);
}
.faq-group h3 {
  display: flex; align-items: baseline; gap: 12px; padding-bottom: 12px; border-bottom: 0;
  font-weight: 600; color: var(--ink-3);
}
.faq-group h3::after { content: ""; flex: 1; min-width: 24px; border-bottom: 2px dotted var(--line-strong); transform: translateY(-3px); }
.faq-item summary::after {
  border-radius: 50%; border: 1.5px solid var(--field-border); color: var(--accent); font-weight: 600;
}
.faq-item summary:hover::after { border-color: var(--accent); }
.faq-item[open] summary::after { background: var(--crema); border-color: var(--field-border); color: var(--accent-hover); }

/* ---------- 7. Closing band: the page's one saturated coffee moment ----------
   Solid caramel; espresso type (ink 7.01, night 7.90). Rust would fail here, so the primary is an espresso pill. */

.closing { background: var(--caramel); color: var(--night); padding-block: clamp(64px, 8vw, 112px); }
.closing h2 { font-size: clamp(2.125rem, 4.4vw, 3.5rem); line-height: 1; letter-spacing: -0.035em; font-weight: 680; color: var(--ink); }
.closing p { margin-top: 16px; font: 500 1rem/1.4 var(--font-mono); color: var(--night); }
.closing .btn-primary { background: var(--night); border-color: var(--night); color: var(--on-dark); }
.closing .btn-primary:hover { background: var(--night-raised); border-color: var(--night-raised); color: var(--on-dark); }
.closing .btn-night { color: var(--night); border-color: var(--night); }
.closing .btn-night:hover { color: var(--night); border-color: var(--night); background: color-mix(in srgb, var(--night) 8%, transparent); }
.closing :focus-visible { outline: 3px solid var(--night); outline-offset: 3px; }

/* ---------- 8. Footer: espresso ---------- */

.footer-grid { padding-top: clamp(48px, 6vw, 72px); border-top: 0; }
/* The navy logo art stays untouched on a crema plate drawn in CSS (12.92:1). */
.footer-logo { width: auto; height: 46px; padding: 8px 12px; border-radius: 10px; background: var(--on-dark); box-sizing: border-box; }
.footer-link-grid a, .footer-link-grid button { color: var(--on-dark-2); }
.footer-link-grid a:hover, .footer-link-grid button:hover { color: var(--on-dark); text-decoration-color: var(--caramel); text-decoration-thickness: 2px; }
.footer-social { color: var(--on-dark-2); }

/* ---------- 9. Demo modal skin ----------
   Foam sheet (radius 24 from --r-lg), espresso 48% scrim, 48px inputs with a 3px rust focus ring (base.css). */

.demo-close { border-radius: var(--r-pill); border-color: var(--field-border); }
.demo-header h2, .demo-success-card h2 { letter-spacing: -0.025em; }
.multiselect-box { border-radius: 50%; }

/* ---------- 10. Responsive (chrome + hero) ---------- */

@media (min-width: 961px) and (max-width: 1100px) {
  /* Two columns but a narrow tablet: callout 03 wraps so the flipped chip stays clear of the proof row. */
  .callout--down.callout--flip .callout-label { width: 17.5rem; white-space: normal; line-height: 1.3; }
  .hero-media { padding-bottom: 164px; } /* the wrapped chip is five lines here */
}
@media (max-width: 960px) {
  /* Stacked: a smaller saucer (disc 84%, one ring) centred on the tablet, so no ring crosses the copy or legend. */
  .hero-media { --saucer: 84%; --saucer-x: 0px; }
  .hero-media::after { width: calc(var(--saucer) + 6%); outline: 0; }
}
@media (min-width: 721px) and (max-width: 960px) {
  .hero-media { padding-bottom: 136px; } /* = base.css top padding, so 50% is the tablet's centre */
}
@media (max-width: 720px) {
  .device-frame--tablet { padding: 8px; border-radius: 16px; }
  .device-screen img { border-radius: 8px; }
  /* The legend sits inside .hero-media here, so centre the saucer on the tablet, not the block:
     40px top padding + half the 16:10 tablet (8px bezel each side). */
  .hero-media { padding: 40px 0 0; --saucer-y: calc(40px + (100vw - 2 * var(--gutter) - 16px) * 0.3125 + 8px); }
  .callout-legend { gap: 10px; margin-top: 48px; }
  .callout-legend li { align-items: flex-start; }
  .callout-legend small { color: var(--ink-3); }
  .hero-specs-band { margin-top: 36px; }
  .hero-bullets { gap: 22px; padding-block: 28px; }
}
@media (max-width: 400px) {
  .proof-avatars { gap: 6px; padding: 6px; }
  .proof-avatars > span, .proof-avatars > span:first-child { width: 34px; height: 34px; }
}

/* ---------- 11. Responsive (sections 6a-6g) ---------- */

@media (max-width: 1100px) {
  .dm-device.saucer { --saucer: 340px; --saucer-x: 0px; --saucer-y: calc(32px + 50% - 60px); } /* phone centred; the ticket hangs below it */
}
@media (max-width: 960px) {
  .partner-card--wide, .partner-grid > .partners-cta { grid-column: 1 / -1; }
}
@media (min-width: 600px) and (max-width: 960px) {
  .dm-device.saucer { --saucer-x: -66px; --saucer-y: 50%; } /* chips beside the phone again */
}
@media (max-width: 720px) {
  /* Every sleeve sits at the card foot, as at 1440 (base.css lets phone cards hang at their own length). */
  .testimonial-set { align-items: stretch; }
  .testimonial-card { flex-basis: min(86vw, 360px); }
  .ticket-foot { padding: 24px 18px 16px; }
  .testimonial-copy { padding-inline: 20px; }
  .ticket-stub { padding-inline: 20px; }

  /* Compare: each row a stacked ticket; TABL's cell is a crema card with the rust cap. */
  .compare-cell-portal, .compare-row + .compare-row .compare-cell-portal, .compare-row:last-child .compare-cell-portal {
    box-shadow: inset 0 3px 0 var(--accent), inset 0 0 0 1px var(--crema-line), var(--e1);
  }
  .compare-cell-portal .ledger-label { color: var(--accent-hover); }

  .feature-card .punch-row { grid-column: 2; padding-top: 12px; }
  .feature-card--highlight::before { inset: 5px; border-radius: 12px; }

  .partner-grid > .partners-cta { padding: 24px 20px; }
  .partner-card__name { display: none; }
}
@media (max-width: 599px) {
  .dm-device.saucer { --saucer: 280px; --saucer-y: calc(20px + 50% - 60px); }
  .dm-device.saucer::after { width: calc(var(--saucer) + 28px); outline: 0; }
}

/* ==================== pages.css ==================== */
/* TABL coffee "Steamed Milk": download + 404. Loads after base.css + coffee.css.
   Spec: design/coffee-refresh/research/verdict.md §6 "Download and 404 (light pass)".
   base.css already carries Daylight's dl-* / 404 layout (recoloured); this file only re-skins it:
   saucer rings instead of the graph grid, Bricolage display sizes, a cup-label 404 mark instead of the torn ticket.
   The saucer itself (.saucer, --saucer / --saucer-x / --saucer-y) lives in coffee.css §5. */

/* The saucer is the only texture: drop Daylight's graph grid on both pages. */
.dl-hero::before, .error-page::before { content: none; }
.dl-hero, .error-page { overflow: clip; } /* the outer ring may run past the viewport on phones */

/* Display type matches the hero H1 (verdict §4). */
.dl-copy h1, .nf-body h1 {
  font-size: clamp(2.75rem, 5vw, 4.5rem); line-height: 0.96; letter-spacing: -0.04em; font-weight: 680; font-stretch: normal;
}

/* ---------- Download ---------- */

.dl-copy h1 { margin: 18px 0 22px; }
.dl-proof dt { display: flex; align-items: center; gap: 8px; }
.dl-proof dt::before { /* the sage live dot: all three are available now */
  content: ""; width: 8px; height: 8px; flex: none; border-radius: 50%;
  background: var(--sage); box-shadow: 0 0 0 3px color-mix(in srgb, var(--sage) 22%, transparent);
}

/* No phone: Daylight's shot is J's Food Truck. The media column is a saucer with an espresso app tile at its centre
   (the four-square mark, not a claimed App Store icon), the store status above and the availability card below. */
.dl-media { --saucer: min(78%, 390px); justify-content: center; gap: 28px; min-height: 520px; padding: 24px 0; }
.dl-status { margin: 0; }
.dl-app {
  display: grid; place-items: center; width: 136px; aspect-ratio: 1; border-radius: 32px;
  background: var(--night) var(--glyph-night) center / 58px 58px no-repeat;
  box-shadow: var(--e3), inset 0 0 0 1px color-mix(in srgb, var(--on-dark) 8%, transparent);
}
.dl-overlay { position: relative; left: auto; bottom: auto; transform: none; width: min(100%, 300px); }

/* ---------- 404: a cup label with no name on it ---------- */

/* Same grid as .dl-grid: copy starts at the container edge, the mark sits on the right like the hero and download. */
.nf-ticket.error-panel {
  max-width: none; padding: 0; background: none; border: 0; box-shadow: none;
  grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); align-items: center; gap: clamp(40px, 6vw, 96px);
}
.nf-mark { --saucer: min(78%, 390px); display: grid; place-items: center; min-height: 480px; }
@media (min-width: 961px) { .nf-mark { order: 2; } } /* stacked (<=960) keeps the mark first */

/* The testimonial cup label (coffee-a.css): foam card, kraft sleeve foot with ribs and a printed arc. */
.nf-label {
  width: min(100%, 280px); overflow: hidden; transform: rotate(-3deg);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md) var(--r-md) 22px 22px; box-shadow: var(--e2);
}
.nf-label .nf-code {
  display: grid; place-items: center; width: 196px; height: 124px; margin: 30px auto 34px;
  font: 600 4.5rem/1 var(--font-mono); letter-spacing: -0.04em; color: var(--ink);
  border: 3px solid var(--accent); border-radius: 52% 48% 55% 45% / 50% 56% 44% 50%; /* grease pencil, not a compass */
  transform: rotate(-6deg);
}
.nf-sleeve {
  display: flex; align-items: center; gap: 12px; padding: 22px 22px 20px;
  background: var(--kraft) repeating-linear-gradient(90deg, color-mix(in srgb, var(--ink) 7%, transparent) 0 1px, transparent 1px 7px);
  border-radius: 50% 50% 0 0 / 16px 16px 0 0;
}
.nf-sleeve-mark { display: grid; place-items: center; width: 48px; height: 48px; flex: none; border-radius: 50%; background: var(--surface); }
.mark-missing { width: 26px; height: 26px; }
.mark-missing rect { fill: var(--ink); }
.mark-missing .mark-tile { fill: var(--glyph-tile); }
.mark-missing .mark-gap { fill: none; stroke: var(--ink-3); }
/* The name lines nobody wrote on. */
.nf-sleeve-lines { display: grid; gap: 9px; flex: 1; }
.nf-sleeve-lines i { display: block; height: 6px; border-radius: 3px; background: color-mix(in srgb, var(--ink) 22%, transparent); }
.nf-sleeve-lines i:first-child { width: 78%; }
.nf-sleeve-lines i:last-child { width: 46%; }

.nf-body { padding: 0; }
.nf-body h1 { margin: 26px 0 18px; }
.nf-body .lead { max-width: 36ch; }
.nf-body .error-copy { max-width: 48ch; font-size: 1rem; }

@media (max-width: 960px) {
  .dl-media { min-height: 480px; --saucer: min(72%, 340px); }
  .nf-ticket.error-panel { grid-template-columns: minmax(0, 1fr); max-width: 640px; gap: 8px; }
  .nf-mark { min-height: 480px; --saucer: min(90%, 340px); } /* the outer ring is disc + 12% + 56px */
}
@media (max-width: 720px) {
  .dl-media { --saucer: min(80%, 280px); min-height: 400px; gap: 22px; padding: 16px 0 8px; }
  .dl-app { width: 112px; border-radius: 26px; background-size: 48px 48px; }
  .dl-overlay { margin-top: 0; }
  .nf-mark { min-height: 400px; --saucer: min(80%, 280px); }
  .nf-label { width: 236px; }
  .nf-label .nf-code { width: 164px; height: 104px; margin: 24px auto 28px; font-size: 3.75rem; }
  .nf-sleeve { padding: 18px 18px 16px; }
}

/* ==================== Ambient motion ==================== */
/* Owner-approved 2026-09-28 ("Keep it all!"): the eight layers previewed in design/coffee-refresh/motion/variants
   (steam, living-bands, crema-light, ripples, pulse-dots, compare-motion, screens-motion, features-motion), built in
   with the same colours, sizes, timings and phone rules. The rhythmic parts share one 2.5s beat: hero dots 7.5s
   (3 beats), spec leaders and Features 10s (4), Compare 7.5s, a ripple every 10s, Screens on the 10s gallery autoplay.
   Rules for every layer:
   - Decorative only: injected layers are aria-hidden with pointer-events: none, and every layer sits under the text.
   - Only transform and opacity animate; no text or button moves (the digital-menu chips are decorative art, held still
     under pointer or focus).
   - Every loop is declared paused (the two one-shot entrance fades, steam-in and cl-in, are not: a remembered Pause
     then shows the frozen wisps and light, as a mid-visit press does). script.js ("Ambient motion") adds .ambient-on to a section only while it is on screen
     below the sticky header, the tab is visible, reduced motion is off and the footer "Pause motion" toggle is off.
   - Everything sits inside prefers-reduced-motion: no-preference: under reduce none of it exists (today's static page).
   Scope: the landing page has all eight. The download and 404 pages have only the closing-band drizzle and a ripple on
   their .saucer; the calculator has the drizzle and the morning light (its .calc-hero is a .hero, as previewed). */

/* Layers script.js injects; shown only inside the no-preference blocks below. */
.steam, .cl-layer, .ripples-drop, .sm-halo { display: none; }

/* ---------- Steam (hero): soft ribbons rise from behind the tablet, like a fresh cup on the saucer ----------
   Under the tablet and callout chips (above the saucer rings); no text sits on it. The ribbon shape is a static SVG
   alpha mask (design/coffee-refresh/motion/work/steam/gen.cjs), tinted white so it reads as steam, never smoke.
   721px and up only (40px of room above the tablet on phones). */
@media (prefers-reduced-motion: no-preference) and (min-width: 721px) {
  .steam {
    --steam-a: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 300'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='1' x2='0' y2='0'%3E%3Cstop offset='0' stop-opacity='0'/%3E%3Cstop offset='.14' stop-opacity='1'/%3E%3Cstop offset='.38' stop-opacity='.75'/%3E%3Cstop offset='.66' stop-opacity='0'/%3E%3C/linearGradient%3E%3Cfilter id='f' x='-50%' y='-10%' width='200%' height='120%'%3E%3CfeGaussianBlur stdDeviation='2.4'/%3E%3C/filter%3E%3C/defs%3E%3Cg filter='url(%23f)' fill='url(%23g)'%3E%3Cpolygon points='48.2 300.0 48.5 291.7 49.2 283.3 50.1 275.0 51.2 266.7 52.3 258.3 53.1 250.0 53.7 241.7 53.7 233.3 53.2 225.0 52.0 216.7 50.1 208.3 47.6 200.0 44.5 191.7 40.9 183.3 37.2 175.0 33.4 166.7 29.8 158.3 26.7 150.0 24.4 141.7 22.9 133.3 22.5 125.0 23.3 116.7 25.2 108.3 28.3 100.0 32.4 91.7 37.3 83.3 42.7 75.0 48.3 66.7 53.7 58.3 58.6 50.0 62.6 41.7 65.4 33.3 66.7 25.0 66.3 16.7 64.2 8.3 60.4 0.0 88.0 0.0 91.2 8.3 92.6 16.7 92.3 25.0 90.3 33.3 86.9 41.7 82.2 50.0 76.6 58.3 70.5 66.7 64.3 75.0 58.2 83.3 52.7 91.7 47.9 100.0 44.1 108.3 41.5 116.7 40.1 125.0 39.8 133.3 40.6 141.7 42.3 150.0 44.8 158.3 47.7 166.7 50.8 175.0 53.9 183.3 56.7 191.7 59.2 200.0 61.1 208.3 62.3 216.7 62.8 225.0 62.7 233.3 61.9 241.7 60.7 250.0 59.2 258.3 57.5 266.7 55.7 275.0 54.1 283.3 52.8 291.7 51.8 300.0'/%3E%3Cg opacity='.8'%3E%3Cpolygon points='48.9 300.0 48.5 291.7 47.9 283.3 47.1 275.0 46.1 266.7 44.9 258.3 43.5 250.0 42.0 241.7 40.5 233.3 38.9 225.0 37.3 216.7 35.8 208.3 34.4 200.0 33.2 191.7 32.2 183.3 31.5 175.0 31.2 166.7 31.1 158.3 31.4 150.0 32.1 141.7 33.2 133.3 34.7 125.0 36.5 116.7 38.6 108.3 41.1 100.0 43.7 91.7 46.6 83.3 49.5 75.0 52.5 66.7 55.5 58.3 58.3 50.0 60.9 41.7 63.2 33.3 65.2 25.0 66.7 16.7 67.7 8.3 68.1 0.0 89.7 0.0 88.8 8.3 87.3 16.7 85.3 25.0 82.8 33.3 80.0 41.7 76.9 50.0 73.6 58.3 70.1 66.7 66.6 75.0 63.2 83.3 59.8 91.7 56.7 100.0 53.7 108.3 51.1 116.7 48.8 125.0 46.8 133.3 45.2 141.7 44.0 150.0 43.2 158.3 42.8 166.7 42.6 175.0 42.8 183.3 43.3 191.7 44.0 200.0 44.9 208.3 45.9 216.7 47.0 225.0 48.1 233.3 49.1 241.7 50.1 250.0 51.0 258.3 51.7 266.7 52.2 275.0 52.5 283.3 52.6 291.7 52.5 300.0'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
    --steam-b: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 300'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='1' x2='0' y2='0'%3E%3Cstop offset='0' stop-opacity='0'/%3E%3Cstop offset='.14' stop-opacity='1'/%3E%3Cstop offset='.38' stop-opacity='.75'/%3E%3Cstop offset='.66' stop-opacity='0'/%3E%3C/linearGradient%3E%3Cfilter id='f' x='-50%' y='-10%' width='200%' height='120%'%3E%3CfeGaussianBlur stdDeviation='2.4'/%3E%3C/filter%3E%3C/defs%3E%3Cg filter='url(%23f)' fill='url(%23g)'%3E%3Cpolygon points='49.8 300.0 49.9 291.7 49.5 283.3 48.8 275.0 47.7 266.7 46.2 258.3 44.3 250.0 42.1 241.7 39.8 233.3 37.4 225.0 35.0 216.7 32.8 208.3 31.0 200.0 29.6 191.7 28.8 183.3 28.7 175.0 29.4 166.7 30.7 158.3 32.9 150.0 35.7 141.7 39.1 133.3 43.0 125.0 47.2 116.7 51.5 108.3 55.6 100.0 59.5 91.7 62.9 83.3 65.5 75.0 67.2 66.7 67.8 58.3 67.2 50.0 65.4 41.7 62.3 33.3 58.0 25.0 52.7 16.7 46.3 8.3 39.2 0.0 66.8 0.0 73.3 8.3 78.9 16.7 83.6 25.0 87.3 33.3 89.7 41.7 90.8 50.0 90.7 58.3 89.4 66.7 87.1 75.0 83.8 83.3 79.8 91.7 75.2 100.0 70.4 108.3 65.4 116.7 60.6 125.0 56.0 133.3 52.0 141.7 48.5 150.0 45.7 158.3 43.6 166.7 42.3 175.0 41.8 183.3 41.9 191.7 42.6 200.0 43.7 208.3 45.3 216.7 47.0 225.0 48.7 233.3 50.4 241.7 51.9 250.0 53.1 258.3 54.0 266.7 54.4 275.0 54.5 283.3 54.1 291.7 53.4 300.0'/%3E%3Cg opacity='.8'%3E%3Cpolygon points='46.3 300.0 45.3 291.7 44.5 283.3 43.8 275.0 43.3 266.7 43.0 258.3 42.9 250.0 43.0 241.7 43.3 233.3 43.9 225.0 44.7 216.7 45.7 208.3 47.0 200.0 48.4 191.7 49.9 183.3 51.5 175.0 53.3 166.7 55.0 158.3 56.8 150.0 58.5 141.7 60.1 133.3 61.6 125.0 62.8 116.7 63.9 108.3 64.6 100.0 65.0 91.7 65.1 83.3 64.8 75.0 64.1 66.7 63.0 58.3 61.4 50.0 59.5 41.7 57.1 33.3 54.3 25.0 51.1 16.7 47.6 8.3 43.8 0.0 65.4 0.0 68.7 8.3 71.7 16.7 74.4 25.0 76.7 33.3 78.6 41.7 80.0 50.0 81.1 58.3 81.7 66.7 81.9 75.0 81.7 83.3 81.1 91.7 80.2 100.0 79.0 108.3 77.4 116.7 75.7 125.0 73.7 133.3 71.6 141.7 69.4 150.0 67.1 158.3 64.9 166.7 62.6 175.0 60.5 183.3 58.5 191.7 56.6 200.0 54.8 208.3 53.3 216.7 52.0 225.0 50.9 233.3 50.1 241.7 49.5 250.0 49.1 258.3 48.9 266.7 48.9 275.0 49.1 283.3 49.4 291.7 49.9 300.0'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
    --steam-c: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 300'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='1' x2='0' y2='0'%3E%3Cstop offset='0' stop-opacity='0'/%3E%3Cstop offset='.14' stop-opacity='1'/%3E%3Cstop offset='.38' stop-opacity='.75'/%3E%3Cstop offset='.66' stop-opacity='0'/%3E%3C/linearGradient%3E%3Cfilter id='f' x='-50%' y='-10%' width='200%' height='120%'%3E%3CfeGaussianBlur stdDeviation='2.4'/%3E%3C/filter%3E%3C/defs%3E%3Cg filter='url(%23f)' fill='url(%23g)'%3E%3Cpolygon points='47.3 300.0 46.1 291.7 44.7 283.3 43.3 275.0 41.9 266.7 40.6 258.3 39.7 250.0 39.2 241.7 39.2 233.3 39.7 225.0 40.7 216.7 42.3 208.3 44.4 200.0 46.7 191.7 49.3 183.3 51.9 175.0 54.3 166.7 56.4 158.3 57.9 150.0 58.6 141.7 58.6 133.3 57.6 125.0 55.6 116.7 52.6 108.3 48.8 100.0 44.2 91.7 39.1 83.3 33.6 75.0 28.1 66.7 22.8 58.3 18.1 50.0 14.1 41.7 11.2 33.3 9.5 25.0 9.3 16.7 10.5 8.3 13.2 0.0 40.8 0.0 37.4 8.3 35.6 16.7 35.1 25.0 36.1 33.3 38.4 41.7 41.7 50.0 45.8 58.3 50.4 66.7 55.2 75.0 60.0 83.3 64.5 91.7 68.4 100.0 71.6 108.3 73.9 116.7 75.2 125.0 75.5 133.3 74.9 141.7 73.5 150.0 71.3 158.3 68.6 166.7 65.5 175.0 62.2 183.3 59.0 191.7 56.0 200.0 53.3 208.3 51.0 216.7 49.3 225.0 48.1 233.3 47.5 241.7 47.3 250.0 47.6 258.3 48.1 266.7 48.9 275.0 49.7 283.3 50.4 291.7 50.9 300.0'/%3E%3Cg opacity='.8'%3E%3Cpolygon points='48.4 300.0 48.6 291.7 49.0 283.3 49.5 275.0 50.1 266.7 50.9 258.3 51.7 250.0 52.5 241.7 53.3 233.3 54.0 225.0 54.7 216.7 55.1 208.3 55.5 200.0 55.6 191.7 55.4 183.3 55.0 175.0 54.3 166.7 53.2 158.3 51.9 150.0 50.3 141.7 48.3 133.3 46.1 125.0 43.7 116.7 41.1 108.3 38.2 100.0 35.3 91.7 32.3 83.3 29.4 75.0 26.5 66.7 23.7 58.3 21.1 50.0 18.8 41.7 16.7 33.3 15.1 25.0 13.9 16.7 13.2 8.3 12.9 0.0 34.5 0.0 34.3 8.3 34.5 16.7 35.2 25.0 36.3 33.3 37.9 41.7 39.7 50.0 41.8 58.3 44.1 66.7 46.5 75.0 48.9 83.3 51.4 91.7 53.8 100.0 56.2 108.3 58.3 116.7 60.2 125.0 61.9 133.3 63.4 141.7 64.5 150.0 65.3 158.3 65.9 166.7 66.1 175.0 66.0 183.3 65.7 191.7 65.1 200.0 64.2 208.3 63.3 216.7 62.1 225.0 60.9 233.3 59.6 241.7 58.3 250.0 57.0 258.3 55.7 266.7 54.6 275.0 53.6 283.3 52.7 291.7 52.0 300.0'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
    display: block; position: absolute; z-index: 0; left: 0; right: 0;
    /* The tablet's top edge is .hero-media's padding-top (--hero-media-top, set beside that padding in the Hero
       section); 48px tucked behind the bezel, and .hero clips the top. */
    bottom: calc(100% - var(--hero-media-top) - 48px); height: 400px;
    overflow: hidden; pointer-events: none;
    animation: steam-in 2.4s ease-out 0.4s both; /* a one-shot fade, not a loop: never held */
  }
  .steam i {
    position: absolute; bottom: 0; left: var(--x); width: 150px; height: 300px; margin-left: -75px;
    transform-origin: 50% 100%; opacity: 0;
    animation: steam-rise var(--d) linear var(--t) infinite paused;
  }
  .steam b {
    position: absolute; inset: 0; opacity: var(--o);
    background: var(--on-accent); /* pure white on latte: steam, not smoke (owner, 2026-09-28: make it more prominent) */
    -webkit-mask: var(--m) center / 100% 100% no-repeat; mask: var(--m) center / 100% 100% no-repeat;
    transform-origin: 50% 100%;
    animation: steam-sway var(--s) ease-in-out var(--t) infinite alternate paused;
  }
  /* Staggered, never in step: three rise periods against three sway periods. Placed in the gaps between the chips. */
  .steam i:nth-child(1) { --x: 7%;  --d: 13s;   --t: -3s;   --s: 9s;  --o: 1; --m: var(--steam-a); }
  .steam i:nth-child(2) { --x: 31%; --d: 16s;   --t: -10s;  --s: 11s; --o: 1; --m: var(--steam-b); }
  .steam i:nth-child(3) { --x: 92%; --d: 14.5s; --t: -6.5s; --s: 10s; --o: 1; --m: var(--steam-c); }
  .hero-media.ambient-on > .steam, .hero-media.ambient-on > .steam * { animation-play-state: running; }

  @keyframes steam-in { from { opacity: 0; } }
  @keyframes steam-rise {
    0%   { transform: translateY(0) scale(0.75, 0.85); opacity: 0; }
    25%  { opacity: 1; }
    60%  { opacity: 0.9; }
    100% { transform: translateY(-84px) scale(1.3, 1.3); opacity: 0; }
  }
  @keyframes steam-sway {
    from { transform: translateX(-4px) skewX(-7deg); }
    to   { transform: translateX(4px) skewX(7deg); }
  }
}
@media (prefers-reduced-motion: no-preference) and (min-width: 721px) and (max-width: 960px) {
  /* Stacked: the tablet sits --hero-media-top (136px) down under the copy, so the layer stays inside .hero-media. */
  .steam { height: calc(var(--hero-media-top) + 48px); }
}

@media (prefers-reduced-motion: no-preference) {
  /* ---------- Living bands: caramel closing-band drizzle + spec-strip leaders ----------
     Closing band: soft cream (--on-dark) ribbons through a blurred, seamless 960px wave mask; the second copy sits 160px
     along the wave and crossfading the two sways the ribbons without moving anything. The drizzle is a visible texture
     even at rest (opacity 0.05-0.22). Cream only lifts the caramel, so the dark text gains contrast (ink 7.01 -> ~7.8).
     Spec strip: the dotted menu-board leaders keep their 55% caramel at rest (colour moved to opacity) and brighten in
     turn, one per 2.5s beat (10s for the four). Phones: only the drizzle runs. */
  .closing { position: relative; isolation: isolate; overflow: clip; }
  .closing::before, .closing::after {
    content: ""; position: absolute; z-index: -1; inset: 0; pointer-events: none; background: var(--on-dark);
    --lb-wave: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 960 400' preserveAspectRatio='none'%3E%3Cfilter id='b' x='-10%25' y='-50%25' width='120%25' height='200%25'%3E%3CfeGaussianBlur stdDeviation='9'/%3E%3C/filter%3E%3Cg fill='none' stroke='%23000' stroke-linecap='round' filter='url(%23b)'%3E%3Cpath stroke-width='26' stroke-opacity='0.55' d='M-960 110C-800 48.7 -640 48.7 -480 110C-320 171.3 -160 171.3 0 110C160 48.7 320 48.7 480 110C640 171.3 800 171.3 960 110C1120 48.7 1280 48.7 1440 110C1600 171.3 1760 171.3 1920 110'/%3E%3Cpath stroke-width='12' stroke-opacity='0.8' d='M-1080 245C-1000 199.7 -920 199.7 -840 245C-760 290.3 -680 290.3 -600 245C-520 199.7 -440 199.7 -360 245C-280 290.3 -200 290.3 -120 245C-40 199.7 40 199.7 120 245C200 290.3 280 290.3 360 245C440 199.7 520 199.7 600 245C680 290.3 760 290.3 840 245C920 199.7 1000 199.7 1080 245C1160 290.3 1240 290.3 1320 245C1400 199.7 1480 199.7 1560 245C1640 290.3 1720 290.3 1800 245C1880 199.7 1960 199.7 2040 245'/%3E%3Cpath stroke-width='40' stroke-opacity='0.35' d='M-1360 320C-1200 290.7 -1040 290.7 -880 320C-720 349.3 -560 349.3 -400 320C-240 290.7 -80 290.7 80 320C240 349.3 400 349.3 560 320C720 290.7 880 290.7 1040 320C1200 349.3 1360 349.3 1520 320C1680 290.7 1840 290.7 2000 320'/%3E%3C/g%3E%3C/svg%3E");
    -webkit-mask: var(--lb-wave) 0 0 / 960px 100% repeat-x;
    mask: var(--lb-wave) 0 0 / 960px 100% repeat-x;
    opacity: 0.05; animation: lb-sway 11s ease-in-out infinite alternate paused;
  }
  .closing::after { -webkit-mask-position: 160px 0; mask-position: 160px 0; animation-direction: alternate-reverse; }

  .spec-key::after { border-bottom-color: var(--caramel); opacity: 0.55; animation: lb-leader 10s ease-in-out infinite paused; }
  .hero-bullets li:nth-child(2) .spec-key::after { animation-delay: 2.5s; }
  .hero-bullets li:nth-child(3) .spec-key::after { animation-delay: 5s; }
  .hero-bullets li:nth-child(4) .spec-key::after { animation-delay: 7.5s; }

  .closing.ambient-on::before, .closing.ambient-on::after, .hero-specs-band.ambient-on .spec-key::after { animation-play-state: running; }
  @media (max-width: 720px) { .spec-key::after { animation: none; } }

  @keyframes lb-sway { to { opacity: 0.22; } }
  @keyframes lb-leader { 0%, 50%, 100% { opacity: 0.55; } 25% { opacity: 1; } }

  /* ---------- Morning light (hero): one soft patch of warm sun drifts across the hero paper ----------
     A very large, very soft glow, 18s each way and back, like sun moving along a café wall. Warm cream (luminance 0.81
     vs paper 0.73), so it only ever lightens and the text only gains contrast. It passes behind the headline (owner
     sign-off 2026-09-28, overriding the flat-hero note in §5). z-index -1 inside the isolated hero: behind every word,
     card and image. Phones keep it: one compositor layer that pauses once the hero scrolls away. */
  .hero { isolation: isolate; }
  .cl-layer {
    display: block; position: absolute; inset: 0; z-index: -1; overflow: hidden; pointer-events: none; contain: strict;
    --cl-sun: color-mix(in srgb, var(--on-dark) 78%, var(--caramel));
    --cl-c: color-mix(in srgb, var(--cl-sun) 100%, transparent);
    animation: cl-in 2.4s ease-out backwards; /* fades in once instead of popping in after first paint; not a loop, never held */
  }
  .cl-glow {
    --cl-h: clamp(460px, 140%, 1100px);
    position: absolute; left: 0; top: calc(50% - var(--cl-h) / 2);
    width: clamp(560px, 70%, 1100px); height: var(--cl-h); border-radius: 50%;
    background: radial-gradient(closest-side,
      var(--cl-c),
      color-mix(in srgb, var(--cl-c) 72%, transparent) 40%,
      color-mix(in srgb, var(--cl-c) 28%, transparent) 70%,
      transparent);
    will-change: transform, opacity;
    animation: cl-drift 18s ease-in-out -4s infinite alternate paused;
  }
  .hero.ambient-on > .cl-layer, .hero.ambient-on > .cl-layer > .cl-glow { animation-play-state: running; }

  @keyframes cl-in { from { opacity: 0; } }
  @keyframes cl-drift {
    0% { transform: translate3d(-38%, -7%, 0) scale(0.94); opacity: 0.55; }
    45% { opacity: 1; }
    100% { transform: translate3d(100%, 7%, 0) scale(1.06); opacity: 0.8; }
  }

  /* ---------- Saucer ripples: a drop lands in the cup every 10s (4 beats) ----------
     A faint caramel (--glyph-tile) ripple, leading ring + fainter trailing ring, rises from behind the device and
     dissolves into the saucer rim over 7s (peak 0.6). Between drops nothing runs (script.js adds .is-dropping on a
     timer, only to saucers with .ambient-on). Tied to the saucer knobs (--saucer, --saucer-x, --saucer-y), so it follows
     every host and breakpoint: .hero-media, .dm-device.saucer, .dl-media.saucer, .nf-mark.saucer. */
  .ripples-drop {
    display: block; position: absolute; z-index: -1; pointer-events: none;
    left: calc(50% + var(--saucer-x, 0px)); top: var(--saucer-y, 50%);
    /* Full size = 1.16x the disc, i.e. just past the first rim ring; drawn at full size so the line stays crisp. */
    width: calc(var(--saucer, 100%) * 1.16); aspect-ratio: 1; border-radius: 50%;
    /* The crest: a crisp caramel edge with a soft foam highlight just inside it, like light catching a ripple on milk. */
    border: 1.5px solid var(--glyph-tile);
    background: radial-gradient(closest-side, transparent 86%, color-mix(in srgb, var(--surface) 75%, transparent) 97%, transparent);
    opacity: 0; transform: translate(-50%, -50%) scale(0.62);
  }
  /* Stacked hero: the legend sits just outside the single rim ring, so the ripple ends exactly on that ring. */
  @media (max-width: 960px) { .hero-media > .ripples-drop { width: calc(var(--saucer) + 6%); } }
  /* The trailing ring: a drop never makes just one. */
  .ripples-drop::before {
    content: ""; position: absolute; inset: 16px; border-radius: 50%;
    border: 1px solid var(--glyph-tile); opacity: 0.45;
  }
  .is-dropping > .ripples-drop { animation: ripples-drop 7s cubic-bezier(0.25, 0.6, 0.35, 1) both paused; }
  .ambient-on.is-dropping > .ripples-drop { animation-play-state: running; }
  @keyframes ripples-drop {
    0% { opacity: 0; transform: translate(-50%, -50%) scale(0.62); }
    35% { opacity: 0.6; }
    100% { opacity: 0; transform: translate(-50%, -50%) scale(1); }
  }

  /* ---------- Pulse dots (hero + digital menu): the food-truck site's pings in coffee colours ----------
     The three callout dots ping in turn, 01 -> 02 -> 03 every 2.5s (7.5s cycle), and a caramel pulse runs down each
     leader as its dot lights. The digital menu's live dot breathes and its Portal / Order Queue chips bob out of step
     (held still under pointer or focus). */
  .page-landing .callout-dot { z-index: 1; } /* keeps the signal line under the dot */
  .page-landing .callout-dot::before {
    content: ""; position: absolute; inset: -7px; border-radius: 50%; pointer-events: none;
    border: 2.5px solid var(--caramel); background: color-mix(in srgb, var(--caramel) 22%, transparent); opacity: 0;
    animation: pd-ping 7.5s cubic-bezier(0, 0, 0.2, 1) infinite paused;
  }
  .page-landing .callout::after {
    content: ""; position: absolute; left: 0; top: 0; bottom: 0; border-left: 1.5px solid var(--caramel); pointer-events: none;
    transform: scaleY(0); transform-origin: top; opacity: 0;
    animation: pd-signal 7.5s cubic-bezier(0.2, 0.8, 0.2, 1) infinite paused;
  }
  .page-landing .callout--down::after { transform-origin: bottom; }
  .page-landing .callout:nth-of-type(2)::after, .page-landing .callout:nth-of-type(2) .callout-dot::before { animation-delay: 2.5s; }
  .page-landing .callout:nth-of-type(3)::after, .page-landing .callout:nth-of-type(3) .callout-dot::before { animation-delay: 5s; }
  .page-landing .live-tag::before { animation: pd-breathe 2.5s ease-in-out infinite alternate paused; }
  .page-landing .dm-chip { animation: pd-chip 7.5s ease-in-out infinite paused; }
  .page-landing .dm-link { animation-delay: 3.75s; }
  .hero.ambient-on .callout-dot::before, .hero.ambient-on .callout::after,
  .digital-menu.ambient-on .live-tag::before, .digital-menu.ambient-on .dm-chip { animation-play-state: running; }
  .dm-device:hover .dm-chip, .dm-device:focus-within .dm-chip { animation-play-state: paused; } /* after the rule above */
  @media (max-width: 1100px) {
    .page-landing .dm-ticket { animation-name: pd-sink; } /* in flow under the phone: bob down, never over the screen */
  }
  @media (max-width: 720px) {
    .page-landing .callout-dot::before { inset: -2px; }
  }
  @keyframes pd-ping { 0%, 6% { transform: scale(1); opacity: 0; } 8% { opacity: 0.9; } 32%, 100% { transform: scale(2.4); opacity: 0; } }
  @keyframes pd-signal { 0% { transform: scaleY(0); opacity: 1; } 8% { transform: scaleY(1); opacity: 1; } 22%, 100% { transform: scaleY(1); opacity: 0; } }
  @keyframes pd-breathe { from { opacity: 1; } to { opacity: 0.35; } }
  @keyframes pd-chip { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }
  @keyframes pd-sink { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(6px); } }

  /* ---------- Compare (02): crema settling down TABL's column; Typical stays still ----------
     A warm light (--on-dark wash over crema) settles down the column row by row, and as it reaches a row the green check
     ticks: a small pop and one soft ring. Rows are 0.625s apart (a quarter beat): the wave runs 5s and rests 2.5s on
     the 7.5s cycle. The TABL cell's own pseudo-elements at z-index -1 inside the isolated cell: under the text, never
     hit. The ring stays in the badge's own column (radius <= 25px; the text starts 27px from the badge centre).
     Hovering or focusing the calculator link holds the whole column still. */
  .compare-row { --cm-d: 0s; }
  .compare-row:nth-child(3) { --cm-d: 0.625s; } /* child 1 is .compare-board-top */
  .compare-row:nth-child(4) { --cm-d: 1.25s; }
  .compare-row:nth-child(5) { --cm-d: 1.875s; }
  .compare-row:nth-child(6) { --cm-d: 2.5s; }
  .compare-row:nth-child(7) { --cm-d: 3.125s; }
  .compare-row:nth-child(8) { --cm-d: 3.75s; }
  .compare-row:nth-child(9) { --cm-d: 4.375s; }

  .compare-cell-portal { isolation: isolate; }
  .compare-cell-portal::before, .compare-cell-portal::after { content: ""; position: absolute; z-index: -1; pointer-events: none; opacity: 0; }
  /* 1px in from the sides so the crema-line edges stay drawn. */
  .compare-cell-portal::before {
    inset: 0 1px; border-radius: inherit;
    background: linear-gradient(90deg, var(--on-dark) 10%, color-mix(in srgb, var(--on-dark) 35%, transparent));
    animation: cm-glow 7.5s ease-in-out var(--cm-d) infinite paused;
  }
  .compare-row:last-child .compare-cell-portal::before { bottom: 1px; }
  .compare-cell-portal::after {
    left: 24px; top: 25px; width: 26px; height: 26px; box-sizing: border-box; border-radius: 50%;
    border: 2px solid var(--go);
    animation: cm-ring 7.5s cubic-bezier(0, 0, 0.2, 1) var(--cm-d) infinite paused;
  }
  .compare-cell-portal .icon { animation: cm-tick 7.5s ease-out var(--cm-d) infinite paused; }

  .compare.ambient-on .compare-cell-portal::before, .compare.ambient-on .compare-cell-portal::after,
  .compare.ambient-on .compare-cell-portal .icon { animation-play-state: running; }
  .compare:has(.inline-link:hover, .inline-link:focus-visible) .compare-cell-portal::before,
  .compare:has(.inline-link:hover, .inline-link:focus-visible) .compare-cell-portal::after,
  .compare:has(.inline-link:hover, .inline-link:focus-visible) .compare-cell-portal .icon { animation-play-state: paused; }

  /* Phones: stacked tickets with a 3px rust cap; the badge sits under the ledger label. */
  @media (max-width: 720px) {
    .compare-cell-portal::before, .compare-row:last-child .compare-cell-portal::before { inset: 3px 1px 1px; }
    .compare-cell-portal::after { left: 16px; top: 38px; animation-name: cm-ring-sm; }
  }
  @keyframes cm-glow { 0% { opacity: 0; } 10% { opacity: 1; } 40%, 100% { opacity: 0; } }
  /* Fixed scales (a var() in the keyframes would keep the ring off the compositor): ring radius 24.7px, phones 20.8px. */
  @keyframes cm-ring { 0%, 6% { transform: scale(1); opacity: 0; } 8% { opacity: 0.9; } 30%, 100% { transform: scale(1.9); opacity: 0; } }
  @keyframes cm-ring-sm { 0%, 6% { transform: scale(1); opacity: 0; } 8% { opacity: 0.9; } 30%, 100% { transform: scale(1.6); opacity: 0; } }
  @keyframes cm-tick { 0%, 6% { transform: scale(1); } 9% { transform: scale(1.14); } 18%, 100% { transform: scale(1); } }

  /* ---------- Screens (03): now-playing line + screen glow, on the gallery's own 10s autoplay ----------
     1. Now-playing line: a caramel line fills under the active screen's name over each 10s interval, so the next screen
        arrives as it completes. It holds while the rail is hovered or focused (autoplay pauses there), restarts with
        autoplay, and is gone for good after the first tap or arrow key, when autoplay ends.
     2. Screen glow: as each autoplay screen arrives, a warm caramel light blooms behind the bezel (1.5s), holds softly
        and fades out by the end of the 10s. It lives only in the gaps between the bezel and the nearest text (header
        48px above, rail 32px right, page gutter at the sides) and fades out down the bezel sides. After the first tap
        it just finishes fading: the band then rests exactly as before.
     script.js (screen gallery) sets on #screens: .sm-auto (autoplay not ended), .sm-run (interval running), .sm-b
     (flipped to restart the fill) and .sm-glow / .sm-hb (flipped to restart the glow). */
  /* The glow window (.sm-halo) stops 8px short of the header text and 4px inside the page gutter, and its mask fades to
     nothing at every edge; inside it, the bezel's own shape casts a soft caramel shadow upward. */
  .screen-preview { position: relative; isolation: isolate; }
  .sm-halo {
    --sm-side: min(28px, var(--gutter) - 4px); --sm-top: 40px;
    display: block; position: absolute; z-index: -1; pointer-events: none; overflow: hidden;
    inset: calc(-1 * var(--sm-top)) calc(-1 * var(--sm-side)) 35%;
    --sm-mask: linear-gradient(transparent, #000 12px, #000 40%, transparent), linear-gradient(90deg, transparent, #000 8px, #000 calc(100% - 8px), transparent);
    -webkit-mask: var(--sm-mask); -webkit-mask-composite: source-in; mask: var(--sm-mask); mask-composite: intersect;
    opacity: 0;
  }
  .sm-halo::before {
    content: ""; position: absolute; inset: var(--sm-top) var(--sm-side) -100vh; border-radius: var(--r-lg);
    box-shadow: 0 -10px calc(var(--sm-side) + 8px) -6px color-mix(in srgb, var(--caramel) 85%, transparent);
  }
  .sm-glow .sm-halo { animation: sm-bloom-a 10s linear forwards paused; }
  .sm-glow.sm-hb .sm-halo { animation-name: sm-bloom-b; }
  .screens.ambient-on .sm-halo { animation-play-state: running; }

  /* Rail rows (1101px and up): track + fill under the screen name, 8px below the note. */
  @media (min-width: 1101px) {
    .sm-auto .thumb.is-active { position: relative; }
    .sm-auto .thumb.is-active::before, .sm-auto .thumb.is-active::after {
      content: ""; position: absolute; left: 116px; right: 16px; bottom: 8px; height: 2px; border-radius: 2px; pointer-events: none;
    }
    .sm-auto .thumb.is-active::before { background: var(--night-line); }
    .sm-auto .thumb.is-active::after {
      background: var(--caramel); transform: scaleX(0); transform-origin: left;
      animation: sm-fill-a 10s linear forwards paused;
    }
  }
  /* 1100px and below: the active thumb's caramel rule becomes the track and the fill runs along it. */
  @media (max-width: 1100px) {
    .sm-auto .thumb.is-active > span { position: relative; border-top-color: color-mix(in srgb, var(--caramel) 30%, transparent); }
    .sm-auto .thumb.is-active > span::before {
      content: ""; position: absolute; left: 0; right: 0; top: -2px; height: 2px; pointer-events: none;
      background: var(--caramel); transform: scaleX(0); transform-origin: left;
      animation: sm-fill-a 10s linear forwards paused;
    }
  }
  /* Flipping the keyframe name restarts the fill from 0 each time autoplay (re)starts. */
  .sm-b .thumb.is-active::after, .sm-b .thumb.is-active > span::before { animation-name: sm-fill-b; }
  .sm-run .thumb.is-active::after, .sm-run .thumb.is-active > span::before { animation-play-state: running; }

  /* Hover or keyboard focus on the rail holds the glow still too (the line is held by autoplay pausing). A mouse tap's
     leftover focus does not, so the last glow can fade out once the pointer leaves. */
  .screens:has(.screen-thumbs:hover, .screen-thumbs :focus-visible) .sm-halo { animation-play-state: paused; }

  @media (max-width: 720px) { .sm-halo { --sm-top: 24px; } }

  @keyframes sm-bloom-a { 0% { opacity: 0; animation-timing-function: cubic-bezier(0.2, 0.8, 0.2, 1); } 15% { opacity: 1; animation-timing-function: ease-in-out; } 55% { opacity: 0.75; animation-timing-function: ease-in; } 100% { opacity: 0; } }
  @keyframes sm-bloom-b { 0% { opacity: 0; animation-timing-function: cubic-bezier(0.2, 0.8, 0.2, 1); } 15% { opacity: 1; animation-timing-function: ease-in-out; } 55% { opacity: 0.75; animation-timing-function: ease-in; } 100% { opacity: 0; } }
  @keyframes sm-fill-a { to { transform: scaleX(1); } }
  @keyframes sm-fill-b { to { transform: scaleX(1); } }

  /* ---------- Features (04): the hero pulse carried down the page on the same 2.5s beat ----------
     One 10s cycle, four 2.5s steps, one group per step (01 -> 02 -> 03 -> 04): the group's number tile pings a caramel
     ring, a caramel pulse runs along the group's ink rule, and each icon tile under it warms to caramel and its icon
     nods as the pulse passes, card by card. On group 03's step the Customer Loyalty punch card stamps its sixth hole
     (rust, with a caramel ring), holds it about three seconds, then fades back to five of six.
     Text never moves or loses contrast: the number ring is border-only under the digits (isolated tile, z-index -1);
     the warm-up sits under the icon inside its tile; every ring stops short of the nearest text. */
  /* Step timing. The grid is flat (label, 4 cards, label, 4 cards...), so group g is children 5g+1..5g+5:
     --fm-g = 2.5s x g, and card c wakes --fm-c after its step starts, as the rule pulse (0.2s + 1.2s) passes above it. */
  #features .feature-grid > * { --fm-g: 0s; --fm-c: 0.35s; }
  #features .feature-grid > :nth-child(n+6) { --fm-g: 2.5s; }
  #features .feature-grid > :nth-child(n+11) { --fm-g: 5s; }
  #features .feature-grid > :nth-child(n+16) { --fm-g: 7.5s; }
  #features .feature-grid > :nth-child(5n+3) { --fm-c: 0.65s; }
  #features .feature-grid > :nth-child(5n+4) { --fm-c: 0.95s; }
  #features .feature-grid > :nth-child(5n+5) { --fm-c: 1.25s; }

  #features .feature-group-label, #features .punch-row i:last-child { position: relative; }
  #features .feature-group-num, #features .feature-icon { position: relative; isolation: isolate; }

  /* 01-04 ping: border-only, under the digits, fades out inside the 16px gap before the title. */
  #features .feature-group-num::before {
    content: ""; position: absolute; z-index: -1; inset: -1px; border-radius: inherit; pointer-events: none;
    border: 2.5px solid var(--caramel); opacity: 0;
    animation: fm-ping 10s cubic-bezier(0, 0, 0.2, 1) var(--fm-g) infinite paused;
  }
  /* The pulse along the 2px ink rule under the group title. */
  #features .feature-group-label::after {
    content: ""; position: absolute; left: 0; right: 0; bottom: -2px; height: 2px; pointer-events: none;
    background: var(--caramel); transform: scaleX(0); transform-origin: left; opacity: 0;
    animation: fm-line 10s linear calc(var(--fm-g) + 0.2s) infinite paused;
  }
  /* Icon tile warms to caramel under the icon, a ring leaves its edge, the icon nods. */
  #features .feature-icon::before, #features .feature-icon::after {
    content: ""; position: absolute; z-index: -1; border-radius: inherit; pointer-events: none; opacity: 0;
  }
  #features .feature-icon::before {
    inset: 0; background: color-mix(in srgb, var(--caramel) 75%, var(--crema));
    animation: fm-glow 10s ease-in-out calc(var(--fm-g) + var(--fm-c)) infinite paused;
  }
  #features .feature-icon::after {
    inset: -1px; border: 2px solid var(--caramel);
    animation: fm-halo 10s cubic-bezier(0, 0, 0.2, 1) calc(var(--fm-g) + var(--fm-c)) infinite paused;
  }
  #features .feature-icon .icon { animation: fm-nod 10s ease-in-out calc(var(--fm-g) + var(--fm-c)) infinite paused; }

  /* Loyalty (group 03, 5s step): the sixth punch lands at 6.5s, rings at 6.75s, holds, fades back by 10.1s. */
  #features .punch-row i:last-child::before, #features .punch-row i:last-child::after {
    content: ""; position: absolute; inset: -1.5px; border-radius: 50%; pointer-events: none; opacity: 0;
  }
  #features .punch-row i:last-child::before { background: var(--accent); animation: fm-stamp 10s linear 6.5s infinite paused; }
  #features .punch-row i:last-child::after { border: 2px solid var(--caramel); animation: fm-burst 10s cubic-bezier(0, 0, 0.2, 1) 6.75s infinite paused; }

  #features.ambient-on :is(.feature-group-num, .feature-group-label, .feature-icon, .punch-row i)::before,
  #features.ambient-on :is(.feature-group-label, .feature-icon, .punch-row i)::after,
  #features.ambient-on .feature-icon .icon { animation-play-state: running; }

  @keyframes fm-ping { 0% { transform: scale(1); opacity: 0; } 2% { opacity: 0.95; } 16%, 100% { transform: scale(1.75); opacity: 0; } }
  @keyframes fm-line { 0% { transform: scaleX(0); opacity: 1; } 12% { transform: scaleX(1); opacity: 1; } 20%, 100% { transform: scaleX(1); opacity: 0; } }
  @keyframes fm-glow { 0% { opacity: 0; } 4%, 6% { opacity: 1; } 15%, 100% { opacity: 0; } }
  @keyframes fm-halo { 0% { transform: scale(1); opacity: 0; } 2% { opacity: 0.9; } 14%, 100% { transform: scale(1.45); opacity: 0; } }
  @keyframes fm-nod {
    0%, 13%, 100% { transform: none; }
    4% { transform: translateY(-3px) rotate(-9deg) scale(1.12); }
    8% { transform: translateY(0) rotate(3deg) scale(1.02); }
  }
  @keyframes fm-stamp {
    0% { transform: scale(1.9); opacity: 0; animation-timing-function: cubic-bezier(0.5, 0, 0.9, 0.5); }
    2.5% { transform: scale(0.84); opacity: 1; animation-timing-function: cubic-bezier(0.2, 0.8, 0.2, 1); }
    5%, 30% { transform: scale(1); opacity: 1; animation-timing-function: ease-in-out; }
    36%, 100% { transform: scale(1); opacity: 0; }
  }
  @keyframes fm-burst { 0% { transform: scale(1); opacity: 0.9; } 12%, 100% { transform: scale(2.3); opacity: 0; } }
}

/* ---------- Footer "Pause motion" toggle (WCAG 2.2.2) ----------
   Footer chrome: the social pill's ring and mono label. script.js unhides it (no script, no motion) and swaps the
   label (Pause motion / Play motion, no aria-pressed); pressed pauses every ambient loop (html.motion-paused, which
   also swaps the icon), remembered per browser. There is
   nothing to pause under reduced motion, so it is not shown there. */
.footer-motion {
  display: inline-flex; align-items: center; gap: 10px; min-height: 44px; margin-right: auto; padding: 0 18px 0 14px;
  border: 0; border-radius: var(--r-pill); background: none; cursor: pointer;
  color: var(--on-dark-2); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--on-dark) 20%, transparent);
  font: 500 0.8125rem/1 var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase; white-space: nowrap;
}
.footer-motion:hover { color: var(--on-dark); box-shadow: inset 0 0 0 1px var(--on-dark); }
.footer-motion .icon { width: 16px; height: 16px; }
.motion-paused .footer-motion .motion-pause, html:not(.motion-paused) .footer-motion .motion-play { display: none; }
/* order: 1 puts it above the socials in the column-reverse footer, so the screen order matches the Tab order. */
@media (max-width: 720px) { .footer-motion { align-self: flex-start; margin-right: 0; order: 1; } }
@media (prefers-reduced-motion: reduce) { .footer-motion { display: none; } }
