/* ==========================================================================
   Quickmunch — premium presentation build (light).
   Near-white canvas, deep ink type, product UI as the hero. Film runs at full
   strength rather than washed into a background — on a light page a video at
   30% opacity reads as a mistake, not as atmosphere.
   Assets come from the parent build (../assets/…). 100% local, no CDN.
   ========================================================================== */

:root {
  --brand: #ff003d;
  --brand-2: #ff4d6d;
  --brand-deep: #c8002f;

  --bg: #ffffff;
  --bg-2: #faf8f9;
  --ink: #0f0a12;
  --ink-2: #574c55;
  --ink-3: #8b8189;
  --line: rgba(15,10,18,.10);
  --line-2: rgba(15,10,18,.06);
  --glass: rgba(255,255,255,.72);

  --sh-s: 0 2px 6px rgba(20,10,25,.05);
  --sh-m: 0 18px 40px -16px rgba(20,10,25,.22), 0 2px 6px rgba(20,10,25,.05);
  --sh-l: 0 44px 90px -28px rgba(20,10,25,.30), 0 4px 12px rgba(20,10,25,.06);

  --r-l: 28px;
  --r-m: 16px;
  --maxw: 1360px;
  --pad: clamp(20px, 4vw, 64px);

  /* Vertical rhythm. Four values, and nothing on the page is allowed a fifth —
     every ad-hoc margin that used to live in a style="" attribute now resolves
     to one of these, so the beat between sections is identical all the way down.
       --sec-pt/pb  air above and below a section
       --gap-head   head block -> the content it introduces
       --gap-block  block -> block inside one column
       --gap-tight  media -> media, where they should read as one object */
  --sec-pt: clamp(56px, 5vw, 74px);
  --sec-pb: clamp(84px, 10vw, 150px);
  --gap-head: clamp(34px, 3.4vw, 48px);
  --gap-block: clamp(28px, 2.8vw, 40px);
  --gap-tight: clamp(14px, 1.4vw, 20px);
}

* { box-sizing: border-box; }
/* clip on BOTH, not hidden: `hidden` would make this a scroll container and kill
   position:sticky, and relying on body-to-viewport overflow propagation alone
   still left the page scrollable by a scrollbar's width. */
html { -webkit-text-size-adjust: 100%; overflow-x: clip; }
body {
  margin: 0; background: var(--bg); color: var(--ink-2);
  font-family: 'Poppins', system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
  -webkit-font-smoothing: antialiased; line-height: 1.5;
  overflow-x: clip;
}
img, video { display: block; max-width: 100%; }
::selection { background: var(--brand); color: #fff; }

.wrap { width: 100%; max-width: var(--maxw); margin: 0 auto; padding-inline: var(--pad); }

/* ==========================================================================
   Nav. Transparent over the hero, then a hairline and glass once you move.
   ========================================================================== */
.nav { position: sticky; top: 0; z-index: 9999; transition: background .3s ease, border-color .3s ease, backdrop-filter .3s ease; border-bottom: 1px solid transparent; }
.nav.stuck { background: rgba(255,255,255,.82); backdrop-filter: saturate(180%) blur(16px); border-bottom-color: var(--line); }
/* Fluid: the bar runs the full width of the window rather than stopping at the
   1360px measure, which is what gives eight tabs room to sit on one line. */
.nav-in { display: flex; align-items: center; gap: 26px; height: 70px; padding-inline: var(--pad); }
/* The link generates no box (display:contents), so the logo keeps its flex/absolute
   behaviour at every breakpoint; #top is the spec'd scroll-to-start fragment. */
.nav-home { display: contents; }
.nav-logo { height: 26px; width: auto; cursor: pointer; }
/* Eight tabs, so the row is tighter than the bar's 26px gap and gives up the
   old 10px lead-in. html is overflow-x:clip, so a bar that does not fit is
   silently cut rather than scrolled - it has to actually fit. */
.nav-links { display: none; gap: 22px; }
@media (min-width: 1460px) { .nav-links { display: flex; } }
.nav-links a { color: var(--ink-2); text-decoration: none; font-size: .87rem; font-weight: 500; white-space: nowrap; transition: color .2s; }
.nav-end .btn { white-space: nowrap; }
.nav-links a:hover { color: var(--ink); }
.nav-end { margin-left: auto; display: flex; align-items: center; gap: 10px; }
/* Logo + burger + two buttons needs 431px of a 390px bar, and overflow:clip was
   quietly amputating the primary CTA. Below 620px only the primary survives. */
@media (max-width: 619px) {
  .nav-end .btn-quiet { display: none; }
  /* (The white-label pill hides <=859px from the inline conversion layer -
     it must outrank the pill's own rules there, which load after this sheet.) */
  /* The CTA is wider than the centre allows: the logo returns to the flow. */
  .nav-in .nav-logo { position: static; transform: none; }
}
@media (max-width: 419px) { .nav-in .nav-logo { height: 24px; } .nav-end .btn { padding-inline: 14px; } }

.btn { display: inline-flex; align-items: center; gap: 8px; border-radius: 999px; font: inherit; font-size: .85rem; font-weight: 600; padding: 10px 20px; text-decoration: none; cursor: pointer; border: 1px solid transparent; transition: transform .2s, box-shadow .2s, background .2s, color .2s, border-color .2s; }
/* Buttons speak the product's language: the primary is the app's own red
   gradient (--qm-grad in app.css), the quiet one its outline variant. Values
   mirror .qm-btn / .qm-btn-outline so a visitor meets the same button here and
   inside the product. */
.btn-dark {
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--brand) 83%, #000) 0%,
    color-mix(in srgb, color-mix(in srgb, var(--brand) 80%, #fff) 85%, #000) 100%);
  color: #fff;
  box-shadow: 0 12px 22px color-mix(in srgb, var(--brand) 22%, transparent);
}
.btn-dark:hover {
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--brand) 60%, #584e42) 0%,
    color-mix(in srgb, var(--brand) 83%, #000) 100%);
  color: #fff; transform: translateY(-2px);
  box-shadow: 0 14px 26px color-mix(in srgb, var(--brand) 34%, transparent);
}
.btn-dark:active { transform: translateY(0); }
.btn-quiet { background: #fff; color: var(--brand);
  border-color: color-mix(in srgb, var(--brand) 14%, #fff); box-shadow: none; }
.btn-quiet:hover { background: #fff; border-color: var(--brand); color: var(--brand); }
.btn-lg { padding: 14px 26px; font-size: .92rem; }
.btn-light { background: #fff; color: var(--ink); }
.btn-ghost-light { background: rgba(255,255,255,.12); color: #fff; border-color: rgba(255,255,255,.34); }
.btn-ghost-light:hover { background: rgba(255,255,255,.2); border-color: #fff; }
/* The closing band centres its text; its buttons (the hero's own .hero-cta) centre with it. */
.cinema .hero-cta { justify-content: center; }

.nav-burger { width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--line); border-radius: 11px; background: #fff; cursor: pointer; }
@media (min-width: 1460px) { .nav-burger { display: none; } }
.nav-burger span { display: block; width: 16px; height: 1.5px; background: var(--ink); position: relative; }
.nav-burger span::before, .nav-burger span::after { content: ""; position: absolute; left: 0; width: 16px; height: 1.5px; background: var(--ink); }
.nav-burger span::before { top: -5px; } .nav-burger span::after { top: 5px; }
.nav-drawer { display: none; padding: 8px var(--pad) 20px; border-top: 1px solid var(--line-2); background: rgba(255,255,255,.96); backdrop-filter: blur(14px); }
.nav-drawer.open { display: block; }
.nav-drawer a { display: block; padding: 12px 0; color: var(--ink-2); text-decoration: none; font-size: .95rem; font-weight: 500; border-bottom: 1px solid var(--line-2); }
.nav-drawer-group { margin: 14px 0 2px; font-size: .74rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--brand); }
.nav-drawer a.nav-drawer-sub { padding-left: 14px; font-weight: 400; }
/* The two grouped chapters fold: native details, styled as drawer rows. */
.nav-acc { border-bottom: 1px solid var(--line-2); }
.nav-acc summary { list-style: none; display: flex; align-items: center; justify-content: space-between;
  padding: 12px 0; font-size: .95rem; font-weight: 600; color: var(--ink); cursor: pointer; }
.nav-acc summary::-webkit-details-marker { display: none; }
.nav-acc summary .nav-chev { width: 7px; height: 7px; margin-right: 4px; transition: transform .2s; }
.nav-acc[open] summary .nav-chev { transform: translateY(1px) rotate(225deg); }
.nav-acc .nav-acc-body { padding-bottom: 6px; }
.nav-acc .nav-acc-body a { border-bottom: 0; padding-block: 9px; }

/* "QM is for" - a highlighted tab on the links' own line, with the drop-down under the bar. The
   panel wears the product's primary gradient; the four tiles are white with ink type and a hint of
   the red rising behind each screenshot; 24px of air around, 16px between; one type scale. The strip
   under them carries the live outline (whites and pinks on the red) and the White-label pill. */
.nav-item { position: relative; display: flex; align-items: center; }
.nav-for-btn { display: inline-flex; align-items: center; gap: 7px; font: inherit; font-size: .87rem; font-weight: 600; color: var(--brand); background: none; border: 0; padding: 0; cursor: pointer; white-space: nowrap; line-height: inherit; }
.nav-for-btn::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--brand); animation: qmPulse 1.6s ease-out infinite; }
.nav-for-btn:hover, .nav-for-btn[aria-expanded="true"] { color: color-mix(in srgb, var(--brand) 82%, #000); }
.nav-chev { width: 6px; height: 6px; border-right: 1.6px solid currentColor; border-bottom: 1.6px solid currentColor; transform: translateY(-2px) rotate(45deg); transition: transform .2s; }
.nav-for-btn[aria-expanded="true"] .nav-chev { transform: translateY(1px) rotate(225deg); }
.nav-for { --for-w: min(1470px, calc(100vw - 2 * var(--pad))); position: absolute; left: min(calc(var(--pad) + 290px), calc(100vw - var(--pad) - var(--for-w))); top: 100%; z-index: 61; width: var(--for-w); padding: 6px 0 18px; }
.nav-for[hidden] { display: none; }
.nav-for .wrap { max-width: none; padding: 0; }
/* The panel: the product's own gradient (.qm-btn's), one radius, one shadow. */
.nav-for-box { position: relative; padding: 24px; border-radius: 22px; color: #fff;
  background: linear-gradient(135deg, color-mix(in srgb, var(--brand) 90%, #000) 0%, var(--brand) 55%, color-mix(in srgb, var(--brand) 80%, #fff) 100%);
  box-shadow: 0 30px 70px -20px color-mix(in srgb, var(--brand) 55%, transparent), 0 8px 24px rgba(31, 11, 18, .18);
  animation: qmForIn .22s ease both; }
.nav-for-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
/* The tiles: dark on the red, white type, the red rising only at the foot behind the screenshot. */
.nav-for-card { position: relative; display: flex; flex-direction: column; padding: 24px 0 0; border-radius: 14px; color: #fff; text-decoration: none; overflow: hidden; background: linear-gradient(180deg, #150508 46%, #4a0a1e 82%, var(--brand) 100%); box-shadow: 0 14px 34px -14px rgba(40, 0, 14, .55); transition: transform .2s, box-shadow .2s; animation: qmCardIn .4s ease both; }
.nav-for-card:nth-child(2) { animation-delay: .04s; } .nav-for-card:nth-child(3) { animation-delay: .08s; } .nav-for-card:nth-child(4) { animation-delay: .12s; }
.nav-for-card:hover { transform: translateY(-2px); box-shadow: 0 20px 40px -14px rgba(40, 0, 14, .65); }
.nav-for-card b { display: block; padding: 0 24px; margin: 0 0 14px; font-size: 1.2rem; line-height: 1.3; font-weight: 700; letter-spacing: -.01em; color: #fff; white-space: nowrap; }
.nav-for-card p { margin: 0 0 24px; padding: 0 24px; font-size: .9rem; line-height: 1.55; color: rgba(255,255,255,.75); font-weight: 300; min-height: 4.6em; }
.nav-for-shot { position: relative; top: 10px; display: block; width: calc(100% - 60px); margin: auto 0 0 auto; border-radius: 8px 0 0 0; overflow: hidden; aspect-ratio: 16 / 9; max-height: 180px; background: #fff; transition: top .3s ease; }
.nav-for-card:hover .nav-for-shot { top: 0; }
.nav-for-shot img { width: 100%; height: 100%; object-fit: cover; object-position: top left; display: block; }
/* The strip: glass over the red, the animated outline in whites and pinks, the White-label pill
   white with the brand inside it, pulsing. */
.nav-for-stripwrap { position: relative; margin-top: 20px; }
.nav-for-stripwrap::before { content: ""; position: absolute; inset: 4px; border-radius: 12px; background: linear-gradient(90deg, #ff6a3d, #ffc83d, #36d1ff, #8a5bff, #ff4fd8, #ff6a3d); background-size: 300% 100%; filter: blur(18px); opacity: .5; animation: qmGlow 8s linear infinite; }
.nav-for-strip { position: relative; z-index: 1; display: flex; align-items: center; gap: 18px; padding: 16px 20px; border: 3px solid transparent; border-radius: 14px; color: rgba(255,255,255,.92); font-size: .95rem; line-height: 1.5; font-weight: 300; text-decoration: none;
  background: linear-gradient(rgba(255,255,255,.14), rgba(255,255,255,.14)) padding-box, linear-gradient(var(--brand), var(--brand)) padding-box, linear-gradient(90deg, #ff6a3d, #ffc83d, #36d1ff, #8a5bff, #ff4fd8, #ff6a3d) border-box;
  background-size: auto, auto, 300% 100%; animation: qmOutline 8s linear infinite; }
.nav-for-strip b { display: inline-flex; align-items: center; gap: 9px; padding: 9px 16px; border-radius: 9px; background: #fff; color: var(--brand); font-weight: 700; font-size: 1rem; line-height: 1.2; white-space: nowrap; animation: qmPulseW 1.5s ease-out infinite; }
.nav-for-strip b i { width: 8px; height: 8px; border-radius: 50%; background: var(--brand); }
.nav-for-strip span { color: rgba(255,255,255,.92); }
.nav-for-strip:hover span { color: #fff; }
/* Specifications: the lettered chapters in a quiet card off the nav's end. */
.nav-item { position: relative; }
.nav-spec-btn { display: inline-flex; align-items: center; gap: 7px; background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; font-size: .87rem; font-weight: 500; color: var(--ink-2); white-space: nowrap; transition: color .2s; }
.nav-spec-btn:hover, .nav-spec-btn[aria-expanded="true"] { color: var(--ink); }
.nav-spec-btn[aria-expanded="true"] .nav-chev { transform: translateY(1px) rotate(225deg); }
.nav-spec { position: absolute; top: calc(100% + 24px); left: -10px; z-index: 61; width: 280px; padding: 8px;
  background: #fff; border: 1px solid var(--line); border-radius: 16px; box-shadow: var(--sh-l); animation: qmForIn .18s ease both; }
.nav-spec[hidden] { display: none; }
.nav-spec a { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: 10px; text-decoration: none;
  color: var(--ink-2); font-size: .9rem; font-weight: 500; transition: background .15s, color .15s; }
.nav-spec a:hover { background: color-mix(in srgb, var(--brand) 7%, #fff); color: var(--ink); }


@keyframes qmForIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes qmCardIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes qmGlow { 0% { background-position: 0 0; } 50% { background-position: 300% 0; } 100% { background-position: 0 0; } }
@keyframes qmOutline { 0% { background-position: 0 0, 0 0, 0 0; } 50% { background-position: 0 0, 0 0, 300% 0; } 100% { background-position: 0 0, 0 0, 0 0; } }
@keyframes qmPulse { 0% { box-shadow: 0 0 0 0 rgba(255,0,61,.7); } 70% { box-shadow: 0 0 0 7px rgba(255,0,61,0); } 100% { box-shadow: 0 0 0 0 rgba(255,0,61,0); } }
@keyframes qmPulseW { 0% { box-shadow: 0 0 0 0 rgba(255,255,255,.75); } 70% { box-shadow: 0 0 0 8px rgba(255,255,255,0); } 100% { box-shadow: 0 0 0 0 rgba(255,255,255,0); } }
@media (prefers-reduced-motion: reduce) { .nav-for-box, .nav-for-card, .nav-for-stripwrap::before, .nav-for-strip, .nav-for-strip b, .nav-for-btn::before { animation: none; } }
@media (max-width: 1459px) { .nav-for { display: none !important; } }

/* ==========================================================================
   Hero. One claim, then the product itself — three real screens layered.
   ========================================================================== */
.hero { position: relative; padding-block: clamp(56px, 9vw, 110px) 0; overflow: clip; }
.hero-mark { display: inline-flex; align-items: center; gap: 10px; font-size: .8rem; color: var(--ink-3); font-weight: 500; margin-bottom: 26px; }
.hero-mark s { text-decoration: none; width: 6px; height: 6px; border-radius: 50%; background: var(--brand); box-shadow: 0 0 0 4px rgba(255,0,61,.14); }
.hero h1 {
  font-size: clamp(2.7rem, 7.4vw, 6.2rem); line-height: .95; letter-spacing: -.045em;
  font-weight: 700; color: var(--ink); margin: 0; max-width: 15ch;
}
.hero h1 .accent { background: linear-gradient(100deg, var(--brand) 8%, var(--brand-2) 92%); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
.hero-sub { font-size: clamp(1.02rem, 1.5vw, 1.24rem); color: var(--ink-2); font-weight: 300; max-width: 52ch; margin: 26px 0 0; }
.hero-cta { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 34px; }
.hero-note { display: flex; flex-wrap: wrap; gap: 8px 24px; margin-top: 30px; font-size: .8rem; color: var(--ink-3); }
.hero-note span { display: inline-flex; align-items: center; gap: 7px; }
.hero-note i { width: 5px; height: 5px; border-radius: 50%; background: var(--brand); }

/* The stage: the storefront behind, the till and the board in front of it. */
.stage { position: relative; margin-top: clamp(48px, 7vw, 96px); }
.stage-glow { position: absolute; left: 8%; right: 8%; top: 12%; bottom: -6%; background: radial-gradient(52% 50% at 50% 50%, rgba(255,0,61,.20), transparent 72%); filter: blur(60px); z-index: 0; }
.stage-main { position: relative; z-index: 1; border-radius: var(--r-l); overflow: hidden; border: 1px solid var(--line); background: #fff; box-shadow: var(--sh-l); max-width: 1080px; margin-inline: auto; aspect-ratio: 16/9.2; }
.stage-main .screen-view { inset: 48px 0 0 0; }
.stage-card { position: absolute; z-index: 2; border-radius: var(--r-m); overflow: hidden; border: 1px solid var(--line); background: #fff; box-shadow: var(--sh-l); }
.stage-card img { width: 100%; height: auto; display: block; }
.stage-till { left: 0; bottom: -6%; width: 40%; max-width: 430px; }
.stage-kds { right: 0; bottom: 12%; width: 30%; max-width: 330px; }
@media (max-width: 860px) {
  .stage-till, .stage-kds { position: static; width: auto; max-width: none; margin-top: 16px; }
  .stage-main { aspect-ratio: 4/3; }
}
/* Hero foot: the page continues, so give the eye somewhere to go. */
/* The hero has no bottom padding of its own — this stands in for it. It has to
   clear the till card, which hangs 6% of the stage below the stage's own box,
   and then leave the page's standard --sec-pb underneath. */
.hero-tail { height: clamp(96px, 12.6vw, 182px); }

/* ==========================================================================
   Footer.
   ========================================================================== */
.foot { border-top: 1px solid var(--line); padding-block: clamp(56px, 7vw, 90px) 40px; background: var(--bg-2); }
.foot-grid { display: grid; gap: 34px; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 820px) { .foot-grid { grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr)); gap: 44px; } }
.foot-logo { height: 26px; width: auto; }
.foot-tag { font-size: .86rem; color: var(--ink-3); font-weight: 300; margin: 16px 0 0; max-width: 34ch; }
.foot h4 { margin: 0 0 14px; font-size: .76rem; font-weight: 600; color: var(--ink); letter-spacing: .02em; }
.foot ul { list-style: none; margin: 0; padding: 0; }
.foot li { margin-bottom: 9px; }
.foot a { color: var(--ink-3); text-decoration: none; font-size: .84rem; font-weight: 300; transition: color .2s; }
.foot a:hover { color: var(--ink); }
.foot-base { display: flex; flex-wrap: wrap; gap: 10px 26px; align-items: center; justify-content: space-between; margin-top: clamp(40px, 5vw, 64px); padding-top: 24px; border-top: 1px solid var(--line-2); font-size: .78rem; color: var(--ink-3); }
.foot-base b { color: var(--ink-2); font-weight: 500; }

/* ---- Type ---------------------------------------------------------------- */
.display {
  font-size: clamp(2.4rem, 6vw, 5rem);
  line-height: .98; letter-spacing: -.04em; font-weight: 700;
  margin: 0; color: var(--ink);
}
.display .dim { color: #c4bcc2; }
.display .accent {
  background: linear-gradient(100deg, var(--brand) 8%, var(--brand-2) 92%);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}
.sub { font-size: clamp(1rem, 1.35vw, 1.16rem); color: var(--ink-2); max-width: 46ch; margin: 24px 0 0; font-weight: 300; }

/* Structural index rather than a letterspaced brand kicker. */
.idx { display: flex; align-items: center; gap: 14px; font-size: .78rem; color: var(--ink-3); font-weight: 500; margin-bottom: 26px; font-variant-numeric: tabular-nums; }
.idx::after { content: ""; flex: 1; height: 1px; background: var(--line); max-width: 120px; }
.idx b { color: var(--brand); font-weight: 700; }

/* Rhythm. Two neighbours each contributing a full 190px stacked into roughly
   400px of dead white between the money and reporting sections. The gap between
   blocks is now one unit rather than two: a generous bottom pad, and a much
   smaller top pad on anything that follows another block. */
/* One rhythm, no exceptions. This used to be a base value plus an adjacency
   override (.sec + .sec …), which silently missed any section whose predecessor
   was not itself a .sec — four of them ran 14px taller than the rest. Invisible
   one at a time, and the reason the page had no steady beat. */
.sec { position: relative; padding-block: var(--sec-pt) var(--sec-pb); }

/* The head block: one measure, one gap to whatever it introduces. Adjacent
   margins collapse, so a child with its own top margin can only ever widen
   this gap, never narrow it. */
.sec-head { max-width: 760px; margin-bottom: var(--gap-head); }
.sec-head:last-child { margin-bottom: 0; }
:where(* + .sec-head) { margin-top: var(--gap-head); }
.tint { background: linear-gradient(180deg, #fff 0%, var(--bg-2) 100%); }

/* ==========================================================================
   01 — Scope. A pinned column of applications; the screen changes as you scroll.
   ========================================================================== */
/* Was 0/0 on the section with the whole lead-in loaded onto .scope-head, so
   the first three gaps on the page ran 222 / 72 / 216 instead of one value.
   The section keeps the page rhythm; the head only spaces itself off the pinned
   stage below it. */
.scope { padding-block: var(--sec-pt) var(--sec-pb); }
.scope-head { padding-block: 0 var(--gap-head); }
.scope-stage { display: grid; gap: 40px; align-items: center; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 1000px) { .scope-stage { grid-template-columns: minmax(0, 350px) minmax(0, 1fr); gap: clamp(40px, 6vw, 96px); } }

.scope-list { list-style: none; margin: 0; padding: 0; }
.scope-item { position: relative; padding: 22px 0 22px 30px; border-top: 1px solid var(--line-2); cursor: pointer; }
.scope-item:last-child { border-bottom: 1px solid var(--line-2); }
.scope-item::before {
  content: ""; position: absolute; left: 0; top: 22px; bottom: 22px; width: 2px;
  background: var(--brand); transform: scaleY(0); transform-origin: top;
  transition: transform .45s cubic-bezier(.4,0,.2,1);
}
.scope-item.on::before { transform: scaleY(1); }
.scope-n { font-size: .72rem; color: var(--ink-3); font-variant-numeric: tabular-nums; letter-spacing: .04em; }
.scope-t { font-size: clamp(1.15rem, 1.8vw, 1.5rem); font-weight: 600; letter-spacing: -.025em; color: #b6adb4; margin: 4px 0 0; transition: color .4s ease; }
.scope-item.on .scope-t { color: var(--ink); }
.scope-d {
  font-size: .89rem; color: var(--ink-2); font-weight: 300; margin: 0;
  max-height: 0; opacity: 0; overflow: hidden;
  transition: max-height .5s cubic-bezier(.4,0,.2,1), opacity .35s ease, margin .5s ease;
}
.scope-item.on .scope-d { max-height: 90px; opacity: 1; margin-top: 8px; }

/* The screen. One frame, contents cross-fade. */
.screen {
  position: relative; border-radius: var(--r-l); overflow: hidden;
  background: #fff; border: 1px solid var(--line);
  box-shadow: var(--sh-l);
  aspect-ratio: 16 / 11;
}
.screen-bar { display: flex; align-items: center; gap: 7px; padding: 15px 18px; border-bottom: 1px solid var(--line-2); background: #fcfbfc; }
.screen-bar i { width: 9px; height: 9px; border-radius: 50%; background: rgba(15,10,18,.13); }
.screen-url { margin-left: 10px; font-size: .68rem; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.screen-view { position: absolute; inset: 48px 0 0 0; overflow: hidden; background: #fff; }
.screen-slide { position: absolute; inset: 0; opacity: 0; }
.screen-slide.on { opacity: 1; }
/* height:auto is load-bearing, and the hero's image sits directly in
   .screen-view with no .screen-slide wrapper — so it was falling through to the
   reset and keeping the height attribute as a presentational hint. 1440x960
   rendered as 1078x960: a third too tall. */
.screen-slide img,
.screen-view > img { width: 100%; height: auto; }

/* ==========================================================================
   02 — In venue. A cinematic film band, then the systems run past horizontally.
   ========================================================================== */
.venue { background: linear-gradient(180deg, #fff 0%, var(--bg-2) 62%, #fff 100%); overflow: clip; }
.venue-head { max-width: 780px; }

/* Full-strength film in a rounded band — not a washed-out backdrop.
   The wrapper carries the width so JS can widen it toward full-bleed on scroll
   and let it settle back, without touching the film's own radius or shadow. */
.venue-filmwrap { width: 100%; max-width: var(--maxw); margin: clamp(44px, 6vw, 76px) auto 0; padding-inline: var(--pad); will-change: max-width, padding; }
/* This wrap's width is scrubbed on scroll. With aspect-ratio the height grew
   with it, so the document's total height changed on every frame — and every
   ScrollTrigger position below, including the pinned rail in this same section,
   was recomputed mid-scroll. That was the stutter: 4 dropped frames per pass,
   measured. A fixed height keeps the reflow inside this one element. */
@media (min-width: 701px) {
  /* The height is the 21:9 height this film would have at the container's rest
     width — the same figure the static second film resolves to — so the two
     match. A clamp only approximated it and left the first ~70px taller. */
  #venueFilmWrap .venue-film {
    aspect-ratio: auto;
    height: calc((min(var(--maxw), 100vw) - 2 * var(--pad)) * 9 / 21);
  }
}
.venue-film {
  position: relative;
  border-radius: var(--r-l); overflow: hidden;
  aspect-ratio: 21 / 9; background: #0d0810; box-shadow: var(--sh-l);
}
.venue-film video, .venue-film img { position: absolute; left: 0; top: -6%; width: 100%; height: 112%; object-fit: cover; }
.venue-film::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, rgba(10,5,12,.72) 0%, rgba(10,5,12,.25) 46%, transparent 72%);
}
.venue-quote {
  position: absolute; left: clamp(22px, 4vw, 54px); bottom: clamp(22px, 4vw, 48px); right: 20%;
  z-index: 2; color: #fff; font-size: clamp(1.05rem, 2.1vw, 1.75rem);
  font-weight: 500; letter-spacing: -.025em; line-height: 1.25; margin: 0;
}
/* The FIRST film reads top-down: its quote sits at the top, and the two
   overlapping boards own the bottom edge. The second film keeps its base. */
#venueFilmWrap .venue-quote { top: clamp(22px, 4vw, 48px); bottom: auto; }
@media (max-width: 700px) { .venue-quote { right: 22px; } .venue-film { aspect-ratio: 4/3; } }

.venue-stat { display: flex; gap: clamp(28px, 5vw, 76px); margin-top: var(--gap-block); flex-wrap: wrap; }
.venue-stat b { display: block; font-size: clamp(2rem, 4vw, 3.1rem); font-weight: 700; letter-spacing: -.045em; line-height: 1; color: var(--ink); font-variant-numeric: tabular-nums; }
.venue-stat span { display: block; font-size: .8rem; color: var(--ink-3); margin-top: 8px; }

/* Pinned horizontal track */
.rail { margin-top: clamp(50px, 7vw, 96px); }
/* Below the pin breakpoint this is a plain swipeable rail. Declared in CSS, not
   left to JS: with reduced motion the script never runs and the cards would
   otherwise sit outside the viewport. */
@media (max-width: 1039px) {
  .rail { overflow-x: auto; overscroll-behavior-x: contain; -webkit-overflow-scrolling: touch; scroll-snap-type: x proximity; }
  .rail .sys { scroll-snap-align: start; }
}
.rail-track { display: flex; gap: 22px; padding-inline: var(--pad); will-change: transform; }
.sys {
  flex: 0 0 clamp(266px, 26vw, 372px);
  border: 1px solid var(--line);
  /* Square along the top: the screenshot runs to the card edge rather than
     sitting inside a rounded frame that fights the UI's own corners. */
  border-radius: 0 0 var(--r-l) var(--r-l);
  background: #fff; box-shadow: var(--sh-m); overflow: hidden;
  display: flex; flex-direction: column;
}
.sys-shot { aspect-ratio: 4 / 3; overflow: hidden; background: var(--bg-2); border-bottom: 1px solid var(--line-2); }
.sys-shot img { width: 100%; height: 100%; object-fit: cover; object-position: top center; }
.sys-body { padding: 20px 22px 26px; }
.sys-n { font-size: .7rem; color: var(--brand); font-variant-numeric: tabular-nums; font-weight: 700; }
.sys-t { font-size: 1.1rem; font-weight: 600; letter-spacing: -.025em; margin: 8px 0 6px; color: var(--ink); }
.sys-d { font-size: .84rem; color: var(--ink-2); font-weight: 300; margin: 0; }

/* ==========================================================================
   03 — POS. Film bleeding one edge, the real till beside it.
   ========================================================================== */
/* The POS sections bleed their film to the viewport edge, so they carry their
   own container rather than .wrap — but the vertical rhythm is the page's, not
   theirs. This used to restate the old .sec values and so ran 14px tall. */
.pos { position: relative; overflow: clip; padding-block: var(--sec-pt) var(--sec-pb); }
.pos-grid { display: grid; gap: 44px; align-items: center; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 1040px) {
  .pos-grid {
    grid-template-columns: minmax(0, 1.08fr) minmax(0, .92fr);
    /* Tuned to land on the same 52/64/72/80 gutter the .duo sections resolve to
       at 1040/1280/1440/1600 — those get there via .sub's 46ch cap, which the
       POS copy column does not have. */
    column-gap: clamp(48px, 5vw, 88px);
    max-width: none; padding-left: 0;
    padding-right: max(var(--pad), calc((100% - var(--maxw)) / 2 + var(--pad)));
  }
}
/* The card is positioned against THIS, not against .pos-film — the film needs
   overflow:hidden to clip the video to its radius, and that was cropping the
   product card straight through. */
.pos-media { position: relative; }
.pos-film { position: relative; border-radius: 0 var(--r-l) var(--r-l) 0; overflow: hidden; aspect-ratio: 5 / 4; background: #0b0810; box-shadow: var(--sh-l); }
@media (max-width: 1039px) { .pos-film { border-radius: var(--r-l); aspect-ratio: 16/10; margin-inline: var(--pad); } }
/* Oversized so the drift never exposes the container edge — that gap was the
   dark strip along the bottom in the earlier build. */
.pos-film video { position: absolute; left: 0; top: -7%; width: 100%; height: 114%; object-fit: cover; object-position: 24% center; }
/* A still needs no oversize: the parallax drift only runs on the video, so
   giving the photo the same 114% would just crop it for nothing. */
.pos-film img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 42% center; }

/* The till, straddling the film's inner edge. Shown whole, never cropped —
   this screen is the product being sold. */
.pos-till {
  position: relative; z-index: 3; margin: -64px var(--pad) 0;
  border-radius: var(--r-m); overflow: hidden;
  border: 1px solid var(--line); background: #fff;
  box-shadow: var(--sh-l);
}
/* Overhang trimmed from -17%/64%: once the card stopped being clipped by the
   film it turned out to have been sitting on top of the capability list. */
@media (min-width: 1040px) { .pos-till { position: absolute; right: -7%; bottom: 7%; width: 56%; margin: 0; } }
/* Only a section carrying a till needs the wider gap: the card straddles the
   film's inner edge by 7% of the media column, so the standard 58px gutter
   left the copy 9px from a screenshot. A section without one keeps the page
   norm — measured, not guessed. */
@media (min-width: 1040px) {
  .pos--till .pos-grid { column-gap: clamp(64px, 8.6vw, 132px); }
  /* Below 1280 the gap is proportionally smaller, so the straddle pulls in to
     hold the same clearance. */
}
@media (min-width: 1040px) and (max-width: 1279px) { .pos-till { right: -4%; } }
.pos-till img { width: 100%; height: auto; }
/* A clip can ride the card instead of a still — section 11 does exactly that. */
.pos-till video { display: block; width: 100%; height: auto; }

/* Shape variant: the two layers of .pos--till, swapped.
   Section 11 used to be a .duo, whose 4/3 film in an even column came out 586x440 against the
   658x526 and 686x549 of 09 and 10 — the odd one out in a run of three. It is now the same
   scaffolding as 09: the brand shape takes the film's slot, so it inherits that size, radius,
   bleed and shadow with no geometry restated, and the clip sits on it where 09 puts its
   screenshot. Only what FILLS each slot differs. */
.pos--shape .pos-film { background: linear-gradient(100deg, var(--brand) 8%, var(--brand-2) 92%); }
/* The media keeps the size it had as a .duo — 89% of this column, which is the 586px it was
   at 1440. Only its surroundings changed: it now sits on the shape and straddles the inner
   edge the way 09's card does, instead of being the whole media. Wider than 09's 56% card, so
   the straddle leans on the wider gutter .pos--till already sets. */
@media (min-width: 1040px) {
  /* Centred on the shape vertically, not pinned to its foot. .pos-till's bottom:7% is right
     for 09, whose card is a short 56% strip against a tall film. Here the card is 89% wide and
     its height follows its own content, so a still at 16/9 sat 159px from the top and 37px
     from the bottom — the lopsidedness that read as broken. The horizontal straddle is
     untouched; only the vertical gaps are evened up. */
  .pos--shape .pos-till { width: 89%; top: 50%; bottom: auto; transform: translateY(-50%); }
}
/* A clip has no intrinsic box the way an image does, so the card carries the 4/3 the video was
   cropped to as a .duo-film. A card holding a still keeps the still's own ratio, exactly as
   09's does — nothing is cropped that was not cropped before. */
/* A card holding a CLIP drops the card. .pos-till is a white surface with a hairline border,
   which is right behind a screenshot — 04 and 09 both keep it — but around dark footage it
   reads as a white outline drawn on the video. The radius and the shadow stay; only the
   border and the white fill go, and overflow:hidden still clips the clip to the corner. */
.pos--shape .pos-till:has(video) { aspect-ratio: 4 / 3; border: 0; background: transparent; }
.pos--shape .pos-till video { width: 100%; height: 100%; object-fit: cover; }

/* ---- A payment card on the film, section 10 ----------------------------------
   Drawn rather than photographed: it stays sharp at any size, costs no request, and follows
   the brand tokens if they change. .pos-till supplies the position and the straddle; the card
   brings its own surface, so the white card chrome under it goes.
   1.586 is ID-1, the real credit-card ratio — a card at any other proportion reads as wrong
   even when nobody can say why. */
.pos-till--card { border: 0; background: transparent; box-shadow: none; overflow: visible; }
.ccard {
  position: relative; aspect-ratio: 1.586; border-radius: 18px; overflow: hidden;
  padding: clamp(14px, 2.2cqw, 22px);
  display: flex; flex-direction: column; justify-content: space-between;
  background: linear-gradient(122deg, #2a0512 0%, var(--brand) 52%, var(--brand-2) 100%);
  box-shadow: 0 30px 60px -18px rgba(40, 4, 18, .55), 0 2px 6px rgba(40, 4, 18, .2);
  color: #fff; container-type: inline-size;
}
/* The sheen every plastic card has, so it reads as an object and not a rectangle. */
.ccard::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(148deg, rgba(255,255,255,.22) 0 22%, transparent 46%);
  pointer-events: none;
}
.ccard-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.ccard-brand { font-size: clamp(11px, 4.4cqw, 19px); font-weight: 800; letter-spacing: -.02em; line-height: 1; }
.ccard-brand b { font-weight: 800; opacity: .72; }
.ccard-wave { width: clamp(14px, 5cqw, 22px); height: auto; opacity: .85; }
.ccard-chip {
  width: clamp(28px, 11cqw, 46px); aspect-ratio: 4 / 3; border-radius: 5px;
  background: linear-gradient(150deg, #f6dfa2, #c9a24d 52%, #f0d79a);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.35);
  position: relative;
}
/* The contact pads, as two hairlines rather than a drawn grid — at this size that is all
   that reads, and more detail just turns to noise. */
.ccard-chip::before, .ccard-chip::after {
  content: ""; position: absolute; left: 12%; right: 12%; height: 1px; background: rgba(90,60,10,.45);
}
.ccard-chip::before { top: 36%; }
.ccard-chip::after { top: 64%; }
.ccard-num {
  margin: 0; font-size: clamp(12px, 5.2cqw, 22px); font-weight: 600;
  letter-spacing: .06em; font-variant-numeric: tabular-nums; text-shadow: 0 1px 2px rgba(0,0,0,.25);
}
.ccard-foot { display: flex; gap: clamp(12px, 5cqw, 30px); font-size: clamp(7px, 2.6cqw, 11px); }
.ccard-foot span { display: flex; flex-direction: column; gap: 2px; }
.ccard-foot s { text-decoration: none; opacity: .62; font-size: .8em; letter-spacing: .12em; text-transform: uppercase; }
@media (max-width: 1039px) { .pos-till--card { max-width: 300px; } }

/* Mirrored variant: film bleeds off the RIGHT, copy sits left on the page
   margin, and the product card overhangs the film's left edge. */
.pos--mirror .pos-film { border-radius: var(--r-l) 0 0 var(--r-l); }
@media (min-width: 1040px) {
  .pos--mirror .pos-grid {
    grid-template-columns: minmax(0, .92fr) minmax(0, 1.08fr);
    padding-right: 0;
    padding-left: max(var(--pad), calc((100% - var(--maxw)) / 2 + var(--pad)));
  }
  .pos--mirror .pos-till { right: auto; left: -7%; }
}
@media (max-width: 1039px) { .pos--mirror .pos-film { border-radius: var(--r-l); } }

.pos-copy { min-width: 0; position: relative; }
/* The tablet (04) and the till station (06), hanging off the page beside the copy —
   .pos is overflow:clip, so each one bleeds off the right edge of the section. */
.pos-over { position: absolute; left: calc(100% + 28px); top: 50%; transform: translateY(-50%); height: auto; filter: drop-shadow(0 18px 34px rgba(31,11,18,.26)); pointer-events: none; }
.pos-over--tab { width: clamp(320px, 27vw, 560px); }
.pos-over--till { width: clamp(360px, 31vw, 640px); }
/* Below ~1600 the copy column reaches the window and only a meaningless sliver would
   show, so the object stands down rather than reading as a stray dark edge. */
@media (max-width: 1599px) { .pos-over { display: none; } }
/* Capabilities as a quiet spec column. No glyphs — the till is the visual. */
.caps { list-style: none; margin: var(--gap-block) 0 0; padding: 0; column-gap: 34px; }
@media (min-width: 620px) { .caps { columns: 2; } }
.caps li { break-inside: avoid; padding: 10px 0; border-top: 1px solid var(--line-2); font-size: .86rem; color: var(--ink-2); font-weight: 300; }
.caps li b { color: var(--ink); font-weight: 600; }
/* A model name is an identifier the buyer will paste, so it is set as one. */
.caps li code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .82em; color: var(--ink-3); }
.caps--wide li { padding: 12px 0; }
/* 14 names four AI providers, so each row carries its mark. The row becomes a
   flex pair - mark, then the text - and the fifth row (not a provider) takes a
   blank of the same width, so every line starts on one left edge. flex-start
   plus the nudge keeps the mark on the FIRST line when a row wraps. */
.caps--mark li { display: flex; align-items: flex-start; gap: 10px; }
.caps-mark { width: 18px; height: 18px; flex: 0 0 18px; object-fit: contain; margin-top: 2px; }
.caps-mark--blank { display: block; }
.caps--mark li > span { min-width: 0; }

/* Device profiles — order mode is a setting on a paired device, not something
   a visitor toggles, so it is presented as three devices. */
.modes { display: grid; gap: 12px; margin-top: var(--gap-block); grid-template-columns: minmax(0, 1fr); }
@media (min-width: 700px) { .modes { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.mode { border: 1px solid var(--line); border-radius: var(--r-m); padding: 18px 18px 20px; background: #fff; box-shadow: var(--sh-s); }
.mode-h { display: flex; align-items: center; gap: 9px; font-size: .82rem; font-weight: 600; color: var(--ink); margin: 0; }
.mode-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--brand); flex: 0 0 auto; }
.mode p { margin: 8px 0 0; font-size: .8rem; color: var(--ink-3); font-weight: 300; line-height: 1.5; }
.mode code { font-size: .71rem; color: var(--ink-2); background: var(--bg-2); border: 1px solid var(--line-2); padding: 2px 7px; border-radius: 5px; margin-top: 12px; display: inline-block; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }

/* ==========================================================================
   04 — Storefront. Sticky copy; the six homepage layouts scrub past beside it.
   ========================================================================== */
/* clip, not hidden: the dashboard behind the frame overhangs to the right and
   must not add page-wide scroll, but .store-sticky has to keep sticking. */
.store { background: linear-gradient(180deg, #fff, var(--bg-2)); overflow: clip; }
.store-grid { display: grid; gap: 40px; grid-template-columns: minmax(0, 1fr); align-items: start; }
@media (min-width: 1000px) { .store-grid { grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr); gap: clamp(40px, 5vw, 90px); } }
.store-sticky { position: sticky; top: clamp(60px, 14vh, 140px); }
/* A numbered index, not a row of pills. Pill tabs are the default reach and they
   look like every SaaS template; this matches the numbered lists used elsewhere
   on the page and lets the layout names breathe. */
.layout-tabs { display: grid; margin-top: 30px; }
.layout-tabs button {
  position: relative; display: flex; align-items: baseline; gap: 14px;
  border: 0; border-top: 1px solid var(--line-2); background: none;
  padding: 13px 0 13px 22px; font: inherit; font-size: .95rem; font-weight: 500;
  color: var(--ink-3); cursor: pointer; text-align: left; width: 100%;
  transition: color .3s ease;
}
.layout-tabs button:last-child { border-bottom: 1px solid var(--line-2); }
.layout-tabs button::before {
  content: ""; position: absolute; left: 0; top: 13px; bottom: 13px; width: 2px;
  background: var(--brand); transform: scaleY(0); transform-origin: top;
  transition: transform .4s cubic-bezier(.4,0,.2,1);
}
.layout-tabs button.on::before { transform: scaleY(1); }
.layout-tabs button.on { color: var(--ink); font-weight: 600; }
.layout-tabs button:hover { color: var(--ink-2); }
.layout-tabs i { font-style: normal; font-size: .72rem; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.store-media { position: relative; }
.store-frame { position: relative; z-index: 1; border-radius: var(--r-l); overflow: hidden; border: 1px solid var(--line); background: #fff; box-shadow: var(--sh-l); aspect-ratio: 4 / 3.2; }

/* The vendor dashboard, sitting behind the storefront and offset up and right —
   the other side of the same install. Only its top and right edges show. */
.store-behind {
  position: absolute; z-index: 0; margin: 0; overflow: hidden;
  /* -8% put its top edge level with the section's, where the sticky nav band
     crosses it. It reveals along the right instead. */
  left: 24%; right: -14%; top: -3%; height: 76%;
  border-radius: var(--r-l); border: 1px solid var(--line);
  background: #fff; box-shadow: var(--sh-m);
}
.store-behind img { width: 100%; height: 100%; object-fit: cover; object-position: top right; }
@media (max-width: 999px) { .store-behind { display: none; } }

@media (min-width: 1000px) {
  /* The copy column runs taller than a 4:3.2 frame, which left dead space under
     the image. The frame now takes the row's height instead of a fixed ratio,
     so the two columns end together at every width. */
  .store-media { align-self: stretch; min-height: clamp(420px, 38vw, 760px); }
  .store-frame { aspect-ratio: auto; height: 100%; }
}
.store-inset { margin-top: 20px; border-radius: var(--r-m); overflow: hidden; box-shadow: var(--sh-m); aspect-ratio: 16/9; position: relative; background: #0b0810; }
.store-inset video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* ==========================================================================
   Cinema — a full-bleed statement over film. The page punctuation.
   ========================================================================== */
.cinema { position: relative; overflow: clip; min-height: clamp(460px, 66vh, 760px); display: grid; place-items: center; }
.cinema-film { position: absolute; inset: 0; z-index: 0; background: #0b0810; }
.cinema-film video, .cinema-film img { position: absolute; left: 0; top: -6%; width: 100%; height: 112%; object-fit: cover; }
.cinema::after { content: ""; position: absolute; inset: 0; z-index: 1; background: linear-gradient(180deg, rgba(9,5,11,.62), rgba(9,5,11,.78)); }
.cinema .wrap { position: relative; z-index: 2; text-align: center; }
.cinema .display { color: #fff; }
.cinema .display .dim { color: rgba(255,255,255,.42); }
.cinema .sub { color: rgba(255,255,255,.78); margin-inline: auto; }
.cinema .idx { justify-content: center; color: rgba(255,255,255,.55); }
.cinema .idx::after { background: rgba(255,255,255,.22); }

/* ==========================================================================
   Duo — film one side, a live panel the other. Sides alternate down the page.
   ========================================================================== */
.duo { position: relative; overflow: clip; }
.duo-grid { display: grid; gap: 40px; align-items: center; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 1000px) { .duo-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(40px, 5vw, 84px); } .duo--flip .duo-media { order: 2; } }
.duo-film { position: relative; border-radius: var(--r-l); overflow: hidden; aspect-ratio: 4 / 3; background: #0b0810; box-shadow: var(--sh-l); }
.duo-film video, .duo-film img { position: absolute; left: 0; top: -6%; width: 100%; height: 112%; object-fit: cover; }
.duo-shot { border-radius: var(--r-m); overflow: hidden; border: 1px solid var(--line); box-shadow: var(--sh-m); background: #fff; }
/* A shot holding switchable slides needs a box of its own: .screen-slide is absolute, so
   without one the card collapses to nothing. The ratio is the desktop captures' own, so the
   frame is exactly the image and never letterboxes it. */
.duo-shot--slides { position: relative; aspect-ratio: 1000 / 625; }
.duo-shot--slides img { width: 100%; height: 100%; object-fit: cover; }
.duo-shot img { width: 100%; height: auto; }
.duo-stack { display: grid; gap: 16px; }
.duo-film + .duo-stack { margin-top: var(--gap-tight); }

/* ==========================================================================
   SYNC — one menu, three surfaces at once.
   A full-width band: two screens stacked on the left, the copy in the middle,
   the till tall on the right. The clips run to the viewport edge — the whole
   point is that the change reaches everything, so the composition should not
   stop at a container.
   ========================================================================== */
.sync { display: grid; gap: var(--gap-tight); grid-template-columns: minmax(0, 1fr); }
.sync-col { display: grid; gap: var(--gap-tight); min-width: 0; }
.sync-copy { min-width: 0; padding-inline: var(--pad); }
@media (min-width: 1100px) {
  .sync--band {
    /* Asymmetric on purpose: the copy sits between two clips and was the
       narrowest column of the three. The till on the right gives up the width
       rather than the two screens on the left, which carry the argument. */
    grid-template-columns: minmax(0, 1fr) minmax(0, 660px) minmax(0, .72fr);
    grid-template-rows: minmax(clamp(440px, 38vw, 620px), auto);
    align-items: stretch;
  }
  /* The copy column sets the band's height and both media columns stretch to
     it, so all three surfaces line up top and bottom. Sizing the media from a
     ratio instead left the shorter side floating in ~150px of dead space. */
  .sync--band .sync-cell { aspect-ratio: auto; }
  .sync--band .sync-col { grid-template-rows: 1fr 1fr; }
  /* Flush to the viewport edge, so only the inner corners are rounded — the
     same treatment the POS band already uses. One language, not two. */
  .sync--band .sync-col .sync-cell { border-radius: 0 var(--r-l) var(--r-l) 0; }
  .sync--band > .sync-cell--tall { border-radius: var(--r-l) 0 0 var(--r-l); }
  /* Padding plus the grid gap has to reach the page's 72px media-to-copy
     gutter — the same clearance every other split section gives. */
  .sync-copy { padding-inline: clamp(26px, 3.6vw, 56px); padding-block: clamp(16px, 2vw, 36px); }
}
@media (min-width: 760px) and (max-width: 1099px) {
  /* Copy above, then the same left-stack / tall-right pairing. Placement is
     explicit: auto-flow put the full-width copy on its own row *after* the
     left column, which stranded the tall cell in a third row of its own — and
     a height:100% cell in an auto row with no siblings resolves to zero. */
  .sync--band { grid-template-columns: minmax(0, 1fr) minmax(0, 1.06fr); padding-inline: var(--pad); }
  .sync--band .sync-copy { grid-column: 1 / -1; grid-row: 1; padding-inline: 0; }
  .sync--band .sync-col { grid-column: 1; grid-row: 2; }
  .sync--band .sync-col .sync-cell { aspect-ratio: 16 / 9; }
  .sync--band > .sync-cell--tall { grid-column: 2; grid-row: 2; aspect-ratio: auto; height: 100%; }
}
@media (max-width: 759px) {
  .sync--band { padding-inline: var(--pad); }
  .sync--band .sync-copy { padding-inline: 0; }
}
.sync-cell {
  position: relative; margin: 0; min-width: 0; overflow: hidden;
  border-radius: var(--r-l); background: #0b0810; box-shadow: var(--sh-l);
  aspect-ratio: 16 / 10;
}
.sync-cell video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
/* Scrim, so the caption survives whatever frame the clip happens to be on. */
.sync-cell::after {
  content: ""; position: absolute; inset: auto 0 0 0; height: 46%; z-index: 1;
  background: linear-gradient(180deg, transparent, rgba(8,4,10,.68));
}
.sync-cell figcaption {
  position: absolute; z-index: 2; left: clamp(14px, 1.6vw, 22px); bottom: clamp(12px, 1.4vw, 18px);
  color: #fff; font-size: clamp(.78rem, 1vw, .9rem); font-weight: 500; letter-spacing: -.01em;
}
.sync-cell figcaption b { display: block; font-weight: 600; }
.sync-cell figcaption s { display: block; text-decoration: none; font-weight: 300; font-size: .78em; color: rgba(255,255,255,.72); margin-top: 2px; }

/* The screens strip drifts rather than waiting to be swiped — same behaviour as
   the long-tail rows, so the page has one idiom for "many things at once". */
.drift-mask--inline { margin-top: var(--gap-tight); }
.drift-mask--inline::before, .drift-mask--inline::after { width: clamp(24px, 4vw, 70px); }
.drift-row--sm figure { flex: 0 0 clamp(156px, 18vw, 212px); margin: 0; }
.drift-row--sm img,
.drift-row--sm video { width: 100%; height: auto; aspect-ratio: 4/3; object-fit: cover; object-position: top center; border-radius: 12px; border: 1px solid var(--line); background: #fff; display: block; }
.drift-row--sm video { background: #0b0810; }
.drift-row--sm figcaption { font-size: .74rem; color: var(--ink-3); margin-top: 8px; font-weight: 500; }
/* A floor stand is a narrow object. Giving it the same track as a wall of
   landscape boards cropped it into something it is not — so portrait creatives
   get their own, narrower track and keep their real shape. */
.drift-row--sm figure.is-portrait { flex-basis: clamp(108px, 12.4vw, 148px); }
.drift-row--sm figure.is-portrait img { aspect-ratio: 3/4; object-position: center; }

/* The screens strip mixes 4:3 and 3:4 in one row, so the two widths are tied:
   at 4:3 and 3:4 the heights match only when landscape = portrait x 16/9. The
   clamps below hold that ratio at every stop (13.4 x 16/9 = 23.8vw), which is
   why they are not round numbers. */
.drift-row--lg figure { flex-basis: clamp(214px, 23.8vw, 299px); }
.drift-row--lg figure.is-portrait { flex-basis: clamp(120px, 13.4vw, 168px); }
/* One overlap width for every floating shot. It was 72% / 74% / 78% in three
   style attributes, which is three near-misses rather than a deliberate three. */
/* One overlap width for every floating shot. It was 72% / 74% / 78% in three
   style attributes, which is three near-misses rather than a deliberate three. */
.duo-float { max-width: 76%; margin-top: -16%; margin-left: 14%; position: relative; z-index: 2; }

/* ==========================================================================
   SCROLLSHOT — a tall screenshot held at a readable height, which scrolls
   itself on hover. Shows the top of a report at rest and the whole of it on
   demand, instead of shrinking a 1700px page to a thumbnail.
   ========================================================================== */
.scrollshot { --h: clamp(230px, 26vw, 360px); height: var(--h); overflow: hidden; position: relative; }
/* When the frame is the section's whole media column rather than a float over
   one, it can afford the height of a real browser window. */
.scrollshot--tall { --h: clamp(320px, 38vw, 540px); }
.scrollshot img {
  width: 100%; height: auto; display: block;
  transition: transform 7s cubic-bezier(.33,0,.25,1);
  will-change: transform;
}
/* translateY(%) resolves against the IMAGE's own height, so this lands its
   bottom edge exactly on the frame's — no JS measurement needed. */
.scrollshot:hover img,
.scrollshot:focus-within img { transform: translateY(calc(var(--h) - 100%)); }
/* The fade is the affordance: it says there is more below, and it clears out
   of the way once you are reading. */
.scrollshot::after {
  content: ""; position: absolute; inset: auto 0 0 0; height: 42%; pointer-events: none;
  background: linear-gradient(180deg, transparent, #fff 88%);
  transition: opacity .5s; z-index: 2;
}
.scrollshot:hover::after, .scrollshot:focus-within::after { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .scrollshot img { transition: none; }
  .scrollshot:hover img, .scrollshot:focus-within img { transform: none; }
}

/* ==========================================================================
   SHOTWALL — the rest of the dashboard, behind the section rather than
   listed in it. Real pages, faded to a texture.
   ========================================================================== */
.shotwall {
  position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none;
  display: grid; gap: 16px; padding: clamp(20px, 3vw, 46px);
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  /* 1fr rows, not a fixed height: with a fixed row height the twelve tiles
     covered only the top third of the section and the rest was plain white. */
  grid-auto-rows: minmax(0, 1fr);
  /* Dashboard pages are near-white, so opacity alone can never make them
     visible on a white section — 0.085 measured 254/255, and 0.5 still measured
     253. The section is tinted instead and the tiles left nearly opaque, so a
     white page reads as a white card against a warm grey field. */
  opacity: .92;
  /* Clear where the words are, full strength everywhere else. The hole is sized
     to fully contain the copy block — its corners have to fall inside the
     transparent stop, not part-way down the fade, or text sits on screenshots. */
  -webkit-mask-image: radial-gradient(78% 46% at 50% 52%, transparent 0%, transparent 64%, #000 100%);
          mask-image: radial-gradient(78% 46% at 50% 52%, transparent 0%, transparent 64%, #000 100%);
}
@media (min-width: 900px) {
  /* Split layout: the copy column sits right of centre, so the hole moves with it. */
  .shotwall {
    -webkit-mask-image: radial-gradient(53% 72% at 73% 47%, transparent 0%, transparent 62%, #000 100%);
            mask-image: radial-gradient(53% 72% at 73% 47%, transparent 0%, transparent 62%, #000 100%);
  }
}
.shotwall img {
  width: 100%; height: 100%; object-fit: cover; object-position: top center;
  border-radius: 10px; border: 1px solid var(--line); box-shadow: var(--sh-s);
}
/* The field the white cards are read against. Without it there is nothing for
   a screenshot of a white page to contrast with. */
.has-wall { background: linear-gradient(180deg, #fff 0%, #f4f0f2 26%, #f4f0f2 74%, #fff 100%); }
.has-wall > .wrap { position: relative; z-index: 1; }

/* --- Hero variant: the stage sits over the system it is one view of. -------
   Bled past the container to the viewport edge, cleared through the middle
   where the mockup and its two cards sit, and much lighter than the reporting
   wall — this one is atmosphere, not evidence. It carries its own tint band
   because the hero above it must stay pure white behind the headline. */
.shotwall--hero {
  inset: -6% calc(50% - 50vw) -14%;
  z-index: 0; opacity: .24; gap: 14px;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  /* Rows follow the tiles' own shape instead of splitting the height evenly.
     With 1fr rows the cell ended up an arbitrary aspect and object-fit:cover
     sliced each 7:5 thumbnail into a fragment of a page — legible as texture,
     not as a screen. */
  grid-auto-rows: auto;
  /* Two layers intersected: a hole through the middle where the stage sits, and
     a fade at top and bottom. One radial alone left the wall at full strength
     along its own top edge, which read as a hard band ruled across the hero. */
  -webkit-mask-image:
    radial-gradient(56% 62% at 50% 44%, transparent 26%, #000 88%),
    linear-gradient(180deg, transparent 0%, #000 16%, #000 74%, transparent 99%);
  -webkit-mask-composite: source-in;
  mask-image:
    radial-gradient(56% 62% at 50% 44%, transparent 26%, #000 88%),
    linear-gradient(180deg, transparent 0%, #000 16%, #000 74%, transparent 99%);
  mask-composite: intersect;
}
/* 7:5 is exactly the tile derivation's own ratio, so cover crops nothing and
   each cell shows a whole page thumbnail. */
.shotwall--hero img { height: auto; aspect-ratio: 7 / 5; border-radius: 8px; }
/* No z-index or positioning fixes belong here: .stage-main is already
   position:relative/z-1 and the two cards are position:absolute/z-2, so the
   wall at z-0 sits under all of them on DOM order alone. Restating position
   here once turned both absolutely-placed cards into flow elements and dropped
   them out of the composition. */

/* Device mockups, drawn rather than photographed. */
.mock { position: relative; margin: 0 auto; background: #14101a; border-radius: 34px; padding: 9px; box-shadow: var(--sh-l); }
.mock-screen { border-radius: 26px; overflow: hidden; background: #000; position: relative; }
.mock-screen img, .mock-screen video { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Sized up substantially: at 250/296px the footage inside was too small to read
   as a kiosk or a table code — the device won, the content lost. */
.mock--phone { max-width: clamp(230px, 26vw, 330px); }
/* One device wears the brand: the kiosk keeps its black bezel, the phone's
   frame takes the primary red - the pair reads as product, not stock mockups. */
#selfserve .mock--phone { background: linear-gradient(160deg, var(--brand) 0%, var(--brand-2) 100%); }
.mock--phone .mock-screen { aspect-ratio: 9 / 17; }
.mock--kiosk { max-width: clamp(280px, 34vw, 430px); border-radius: 24px; padding: 9px; }
.mock--kiosk .mock-screen { aspect-ratio: 9 / 15; border-radius: 16px; }
/* Overlapped rather than sat side by side: two separate devices with a gap
   between them read as a spec sheet. The phone tucks in front of the kiosk's
   lower corner so the pair reads as one object. */
.mock-trio { position: relative; display: flex; align-items: flex-end; justify-content: center; }
.mock-trio .mock--kiosk { position: relative; z-index: 1; }
.mock-trio .mock--phone { position: relative; z-index: 2; margin-left: -14%; margin-bottom: -8%; }
@media (min-width: 1000px) {
  /* The kiosk is the product in this section, but it was sharing a 586px grid
     track with the phone and both were flex-shrinking to fit — 339px against
     the POS film's 686 two sections earlier. The media column now bleeds to the
     viewport edge on its own side, exactly as the POS band does, and the two
     devices take fixed shares of it instead of shrinking against each other.
     Nothing moves: same side, same overlap, same order. */
  #selfserve .duo-media { margin-left: calc(-1 * max(var(--pad), (100vw - var(--maxw)) / 2 + var(--pad))); }
  .mock-trio .mock--kiosk { flex: 0 0 64%; max-width: none; }
  .mock-trio .mock--phone { flex: 0 0 44%; max-width: none; margin-left: -8%; }
  /* It runs off the edge, so it is not rounded there — and the 9px of bezel at
     x=0 read as a sliver rather than a device frame, so that goes too. */
  #selfserve .mock--kiosk { border-radius: 0 24px 24px 0; padding-left: 0; }
  #selfserve .mock--kiosk .mock-screen {
    border-radius: 0 16px 16px 0;
    /* 9/15 at this width came out 718 tall — half again the POS film it is
       meant to sit alongside. */
    aspect-ratio: 9 / 12;
  }
}
@media (max-width: 560px) {
  .mock-trio { flex-direction: column; align-items: center; }
  .mock-trio .mock--phone { margin-left: 0; margin-top: -22%; margin-bottom: 0; }
}

/* ==========================================================================
   Live map — the product tracker, rebuilt for the light canvas.
   ========================================================================== */
/* Real tiles. The video sits INSIDE the map as an inset rather than stacked
   above it — film, then map, then a screenshot was three tall blocks in one
   column and pushed the section far past a screen. */
.livemap-wrap { position: relative; }
.livemap { position: relative; border-radius: var(--r-l); overflow: hidden; background: #eceaf0; border: 1px solid var(--line); aspect-ratio: 16 / 12.5; box-shadow: var(--sh-m); z-index: 0; }
.livemap .leaflet-container { background: #eceaf0; font-family: inherit; }
.livemap .leaflet-control-attribution { font-size: .62rem; background: rgba(255,255,255,.8); }
.livemap-inset {
  position: absolute; right: 14px; bottom: 14px; z-index: 500;
  width: clamp(120px, 26%, 210px); aspect-ratio: 16/10;
  border-radius: 12px; overflow: hidden; border: 2px solid #fff;
  box-shadow: var(--sh-m); background: #0b0810;
}
.livemap-inset video { width: 100%; height: 100%; object-fit: cover; display: block; }

/* The rider marker: the courier from the film, as an avatar. */
.rider-pin { position: relative; }
.rider-pin img { width: 40px; height: 40px; border-radius: 50%; border: 3px solid #fff; box-shadow: 0 6px 16px rgba(20,10,25,.4); display: block; }
.rider-pin::after {
  content: ""; position: absolute; left: 50%; bottom: -6px; transform: translateX(-50%) rotate(45deg);
  width: 12px; height: 12px; background: #fff; border-radius: 2px;
}
.venue-pin { width: 16px; height: 16px; border-radius: 50%; background: var(--brand); border: 3px solid #fff; box-shadow: 0 4px 12px rgba(255,0,61,.5); }

/* The example zone's size, said out loud — the map holds one fixed radius while
   the control expresses the rest, so the number has to be on the map. */
.livemap-tag {
  position: absolute; z-index: 500; left: 14px; top: 14px;
  font-size: .72rem; font-weight: 600; letter-spacing: .01em; color: var(--ink);
  background: rgba(255,255,255,.92); border: 1px solid var(--line);
  border-radius: 999px; padding: 6px 12px; box-shadow: var(--sh-s);
}

/* ==========================================================================
   ZONE CONTROL — a radius is a big number, so it gets a big control.
   The native range is still underneath and still does the work; everything
   here is the track, the fill and the knob it draws.
   ========================================================================== */
.zone-ctl { --p: 10%; display: grid; gap: 10px; margin-top: var(--gap-block); }
.zone-ctl-head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; }
.zone-ctl-head label { font-size: .78rem; color: var(--ink-3); font-weight: 500; }
.zone-val {
  font-size: clamp(1.6rem, 2.6vw, 2.3rem); font-weight: 700; letter-spacing: -.045em;
  color: var(--ink); line-height: 1; font-variant-numeric: tabular-nums;
}
.zone-track { position: relative; height: 40px; display: flex; align-items: center; }
.zone-input {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 40px; margin: 0; background: transparent; cursor: grab;
}
.zone-input:active { cursor: grabbing; }
.zone-input:focus-visible { outline: 2px solid var(--brand); outline-offset: 6px; border-radius: 999px; }

/* The two engines need the track and thumb declared separately — a shared rule
   is dropped wholesale by both if either selector is unknown. */
.zone-input::-webkit-slider-runnable-track {
  height: 12px; border-radius: 999px;
  background: linear-gradient(90deg, var(--brand) 0 var(--p), var(--line) var(--p) 100%);
}
.zone-input::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 30px; height: 30px; margin-top: -9px; border-radius: 50%;
  background: #fff; border: 3px solid var(--brand);
  box-shadow: 0 6px 16px -4px rgba(255,0,61,.55), var(--sh-s);
  transition: transform .18s ease;
}
.zone-input:hover::-webkit-slider-thumb, .zone-input:active::-webkit-slider-thumb { transform: scale(1.12); }
.zone-input::-moz-range-track { height: 12px; border-radius: 999px; background: var(--line); }
.zone-input::-moz-range-progress { height: 12px; border-radius: 999px; background: var(--brand); }
.zone-input::-moz-range-thumb {
  width: 24px; height: 24px; border-radius: 50%;
  background: #fff; border: 3px solid var(--brand);
  box-shadow: 0 6px 16px -4px rgba(255,0,61,.55);
}
.zone-scale { display: flex; justify-content: space-between; font-size: .7rem; color: var(--ink-3); font-variant-numeric: tabular-nums; }

/* ==========================================================================
   ZONE RINGS — the radius as three rings expanding off the section's left
   edge. Deliberately not centred: anchored past the edge so they read as a
   fragment of something larger rather than a diagram.
   ========================================================================== */
.zone-rings {
  --zr: 220px;
  /* inset:0, not a 0x0 anchor point: a mask is computed against the element's
     own box, so on a zero-sized element it masks everything away. */
  position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: hidden;
  /* Faded out before they reach the copy column — left-anchored is the point,
     and an arc sweeping under the text would just be noise. */
  -webkit-mask-image: linear-gradient(90deg, #000 0%, #000 30%, transparent 58%);
          mask-image: linear-gradient(90deg, #000 0%, #000 30%, transparent 58%);
}
.zone-rings span {
  position: absolute; left: 0; top: 50%; translate: -50% -50%;
  border-radius: 50%; border: 1.5px solid var(--brand);
  background: radial-gradient(circle, rgba(255,0,61,.09), rgba(255,0,61,.03) 70%, transparent 72%);
  transition: width .55s cubic-bezier(.22,1,.36,1), height .55s cubic-bezier(.22,1,.36,1);
}
.zone-rings span:nth-child(1) { width: var(--zr); height: var(--zr); opacity: .55; }
.zone-rings span:nth-child(2) { width: calc(var(--zr) * 1.75); height: calc(var(--zr) * 1.75); opacity: .34; }
.zone-rings span:nth-child(3) { width: calc(var(--zr) * 2.7);  height: calc(var(--zr) * 2.7);  opacity: .20; }
@media (prefers-reduced-motion: reduce) { .zone-rings span { transition: none; } }

/* The rings need room, and the section is the shortest on the page without it. */
#delivery { position: relative; overflow: clip; }
@media (min-width: 1000px) { #delivery .duo-grid { min-height: clamp(520px, 44vw, 700px); } }

.map-note { margin: 14px 0 0; font-size: .84rem; color: var(--ink-2); font-weight: 300; }
.map-note b { color: var(--ink); font-weight: 600; }

/* ==========================================================================
   Mosaic — many screens at once, for the long tail.
   ========================================================================== */
/* ==========================================================================
   The long tail, as two screens drifting past rather than a wall of thumbnails.
   A static grid of twelve equal tiles reads as documentation however it is
   arranged; motion turns the same assets into a sense of volume. Rows travel in
   opposite directions and pause on hover.
   ========================================================================== */
.drift { overflow: clip; }
.drift-row { display: flex; align-items: flex-start; gap: 16px; width: max-content; will-change: transform; }
.drift-row + .drift-row { margin-top: 16px; }
.drift-row:hover { animation-play-state: paused; }
.drift-card {
  flex: 0 0 clamp(212px, 21vw, 292px);
  border: 1px solid var(--line); border-radius: var(--r-m); overflow: hidden;
  background: #fff; box-shadow: var(--sh-s); position: relative;
}
.drift-card img { width: 100%; height: auto; aspect-ratio: 16/11; object-fit: cover; object-position: top center; display: block; }
.drift-card span {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 26px 13px 11px;
  font-size: .76rem; font-weight: 600; color: #fff; letter-spacing: -.01em;
  background: linear-gradient(180deg, transparent, rgba(12,7,15,.22) 40%, rgba(12,7,15,.8) 100%);
}
/* Edges fade so the rows read as continuing past the viewport. */
.drift-mask { position: relative; }
.drift-mask::before, .drift-mask::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: clamp(40px, 8vw, 140px); z-index: 2; pointer-events: none;
}
.drift-mask::before { left: 0;  background: linear-gradient(90deg, var(--bg-2), transparent); }
.drift-mask::after  { right: 0; background: linear-gradient(270deg, var(--bg-2), transparent); }
@media (prefers-reduced-motion: reduce) {
  .drift-mask { overflow-x: auto; }
  .drift-row { width: auto; }
}

/* Twelve tiles on a four-column grid — three full rows, nothing ragged.
   Mixed spans were tried and abandoned: with tiles of differing row heights the
   grid could not tessellate and left holes across the wall. Fewer, larger tiles
   beat more, smaller ones here; at five across the screenshots were unreadable. */
.mosaic { display: grid; gap: 16px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 720px)  { .mosaic { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1080px) { .mosaic { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.tile {
  position: relative; border: 1px solid var(--line); border-radius: var(--r-m);
  overflow: hidden; background: #fff; box-shadow: var(--sh-s);
  transition: transform .4s cubic-bezier(.4,0,.2,1), box-shadow .4s;
}
.tile:hover { transform: translateY(-5px); box-shadow: var(--sh-m); }
/* height:auto is load-bearing. The markup carries width/height attributes, which
   map to presentational hints and set a DEFINITE height — with both dimensions
   definite, aspect-ratio is ignored and every tile rendered as a tall narrow
   sliver of the screenshot. */
.tile img { width: 100%; height: auto; aspect-ratio: 16/11; object-fit: cover; object-position: top center; }
/* The label rides the image, but on a scrim shallow enough to leave the screen
   readable — the earlier gradient covered nearly half the tile. */
.tile span {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 30px 14px 12px;
  font-size: .8rem; font-weight: 600; color: #fff; letter-spacing: -.01em;
  background: linear-gradient(180deg, transparent, rgba(12,7,15,.24) 42%, rgba(12,7,15,.82) 100%);
}

/* ==========================================================================
   Steps — the installer, as a numbered run.
   ========================================================================== */
.steps { display: grid; gap: 18px; grid-template-columns: minmax(0, 1fr); counter-reset: s; }
@media (min-width: 700px)  { .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1100px) { .steps { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
.step { border: 1px solid var(--line); border-radius: var(--r-m); overflow: hidden; background: #fff; box-shadow: var(--sh-s); }
.step img { width: 100%; height: auto; aspect-ratio: 16/10; object-fit: cover; object-position: top center; border-bottom: 1px solid var(--line-2); }
.step-b { padding: 16px 18px 20px; }
.step-b h3 { margin: 0 0 5px; font-size: .95rem; font-weight: 600; color: var(--ink); letter-spacing: -.02em; display: flex; gap: 9px; align-items: baseline; }
.step-b h3::before { counter-increment: s; content: counter(s, decimal-leading-zero); color: var(--brand); font-size: .72rem; font-variant-numeric: tabular-nums; }
.step-b p { margin: 0; font-size: .8rem; color: var(--ink-3); font-weight: 300; }

/* ==========================================================================
   Money — the three business models, as a live split.
   ========================================================================== */
/* Asymmetric, like every other section on this page — the centred stack of three
   equal cards with two sliders under it was the generic version of this idea. */
.money-grid { display: grid; gap: clamp(34px, 4vw, 70px); align-items: center; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 1000px) { .money-grid { grid-template-columns: minmax(0, .82fr) minmax(0, 1.18fr); } }

/* The models read as a chosen list, not a pill switcher. */
.model-list { list-style: none; margin: 34px 0 0; padding: 0; }
.model { position: relative; padding: 18px 0 18px 26px; border-top: 1px solid var(--line-2); cursor: pointer; }
.model:last-child { border-bottom: 1px solid var(--line-2); }
.model::before { content: ""; position: absolute; left: 0; top: 18px; bottom: 18px; width: 2px; background: var(--brand); transform: scaleY(0); transform-origin: top; transition: transform .4s cubic-bezier(.4,0,.2,1); }
.model.on::before { transform: scaleY(1); }
.model b { display: block; font-size: 1.06rem; font-weight: 600; letter-spacing: -.02em; color: #b6adb4; transition: color .35s; }
.model.on b { color: var(--ink); }
.model p { margin: 0; font-size: .85rem; color: var(--ink-2); font-weight: 300; max-height: 0; opacity: 0; overflow: hidden; transition: max-height .45s cubic-bezier(.4,0,.2,1), opacity .3s, margin .45s; }
.model.on p { max-height: 80px; opacity: 1; margin-top: 7px; }

/* The split itself: a single bar the money divides, rather than three cards. */
.split-card { border: 1px solid var(--line); border-radius: var(--r-l); background: #fff; box-shadow: var(--sh-m); padding: clamp(24px, 3vw, 38px); }
.split-total { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; }
.split-total em { font-style: normal; font-size: .74rem; color: var(--ink-3); text-transform: uppercase; letter-spacing: .07em; }
.split-total b { font-size: clamp(2rem, 3.6vw, 2.9rem); font-weight: 700; letter-spacing: -.045em; color: var(--ink); font-variant-numeric: tabular-nums; }
.split-bar { display: flex; height: 14px; border-radius: 99px; overflow: hidden; margin: 26px 0 18px; background: var(--bg-2); }
.split-seg { transition: flex-basis .5s cubic-bezier(.4,0,.2,1), opacity .35s; flex-grow: 0; flex-shrink: 0; }
.split-seg--keep { background: linear-gradient(90deg, var(--brand), var(--brand-2)); }
.split-seg--pass { background: var(--ink); }
.split-seg.off { opacity: 0; }
.split-key { display: grid; gap: 14px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.split-key div { min-width: 0; }
.split-key span { display: flex; align-items: center; gap: 8px; font-size: .76rem; color: var(--ink-3); }
.split-key i { width: 9px; height: 9px; border-radius: 3px; flex: 0 0 auto; }
.split-key i.keep { background: var(--brand); }
.split-key i.pass { background: var(--ink); }
.split-key b { display: block; font-size: 1.24rem; font-weight: 700; letter-spacing: -.03em; color: var(--ink); margin-top: 6px; font-variant-numeric: tabular-nums; }
.split-key div.off { opacity: .3; }
.money-ctl { display: flex; align-items: center; gap: 16px; margin-top: 26px; }
.money-ctl label { font-size: .78rem; color: var(--ink-3); min-width: 88px; }
.money-ctl input { flex: 1; min-width: 0; accent-color: var(--brand); }
.money-ctl b { font-variant-numeric: tabular-nums; color: var(--ink); font-size: .88rem; min-width: 56px; text-align: right; }
.money-out { margin: 24px 0 0; font-size: .88rem; color: var(--ink-2); font-weight: 300; line-height: 1.6; }
.money-out b { color: var(--ink); font-weight: 600; }

/* ==========================================================================
   Roles — what a person cannot open is the point.
   ========================================================================== */
.roles-board { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-top: 34px; }
@media (min-width: 720px) { .roles-board { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
.panel { border: 1px solid var(--line); border-radius: var(--r-m); background: #fff; padding: 15px 14px 17px; box-shadow: var(--sh-s); transition: opacity .35s, transform .35s, box-shadow .35s; }
.panel b { display: block; font-size: .82rem; font-weight: 600; color: var(--ink); }
.panel span { display: block; font-size: .7rem; color: var(--ink-3); margin-top: 3px; }
.panel.hide { opacity: .22; transform: scale(.96); box-shadow: none; border-style: dashed; }


/* ==========================================================================
   Bento. Mixed cell sizes carrying mixed content — a screenshot, a logo strip,
   a diagram, a figure. Deliberately not a card grid: everything the same size
   reads as a list however it is styled.
   ========================================================================== */
.bento { display: grid; gap: 14px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 820px)  { .bento { grid-template-columns: repeat(4, minmax(0, 1fr)); grid-auto-rows: clamp(132px, 13vw, 172px); gap: 16px; } }
.bo {
  position: relative; overflow: hidden; border-radius: var(--r-l);
  border: 1px solid var(--line); background: #fff; box-shadow: var(--sh-s);
  padding: 22px; display: flex; flex-direction: column; justify-content: flex-end;
  transition: transform .4s cubic-bezier(.4,0,.2,1), box-shadow .4s;
}
.bo:hover { transform: translateY(-4px); box-shadow: var(--sh-m); }
@media (min-width: 820px) {
  .bo { grid-column: span 1; grid-row: span 1; }
  .bo--w2 { grid-column: span 2; }
  .bo--h2 { grid-row: span 2; }
  .bo--w2h2 { grid-column: span 2; grid-row: span 2; }
}
.bo h3 { margin: 0; font-size: .98rem; font-weight: 600; letter-spacing: -.02em; color: var(--ink); }
.bo p { margin: 6px 0 0; font-size: .8rem; color: var(--ink-3); font-weight: 300; line-height: 1.5; }
.bo-top { margin-bottom: auto; }
.bo-fig { font-size: clamp(1.9rem, 3.4vw, 2.8rem); font-weight: 700; letter-spacing: -.04em; color: var(--ink); line-height: 1; font-variant-numeric: tabular-nums; }
.bo-shot { position: absolute; inset: 0 0 auto 0; height: 62%; overflow: hidden; }
.bo-shot img { width: 100%; height: 100%; object-fit: cover; object-position: top center; }
.bo-shot::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, transparent 40%, #fff 96%); }
/* Below 820px the bento has no fixed row height, so a shot cell needs a floor
   of its own. Above it the grid's rows govern, and this floor would fight them
   — a 1x1 cell would silently grow its whole row and the mosaic stops
   tessellating. Every shot cell is therefore h2 on desktop. */
.bo--shot { justify-content: flex-end; min-height: 250px; }
@media (min-width: 820px) { .bo--shot { min-height: 0; } }
.bo--tint { background: linear-gradient(160deg, #fff, var(--bg-2)); }

/* Payment marks. */
.paylogos { display: flex; align-items: center; gap: clamp(16px, 3vw, 32px); flex-wrap: wrap; margin-bottom: auto; }
.paylogos img { height: 26px; width: auto; opacity: .85; }
.paymark { font-size: 1.32rem; font-weight: 700; letter-spacing: -.04em; color: var(--ink); }
.paychip { display: inline-flex; align-items: center; font-size: .74rem; font-weight: 500; color: var(--ink-2); border: 1px solid var(--line); border-radius: 999px; padding: 5px 12px; }

/* The seven sponsored slots, drawn on a page skeleton. */
.slots { position: absolute; inset: 18px 18px auto 18px; height: 58%; display: grid; gap: 5px; grid-template-columns: repeat(4, 1fr); grid-auto-rows: 1fr; }
.slot { border-radius: 5px; background: var(--bg-2); border: 1px solid var(--line-2); }
.slot--ad { background: color-mix(in srgb, var(--brand) 14%, #fff); border-color: color-mix(in srgb, var(--brand) 40%, #fff); }
.slot--hero { grid-column: span 4; }
.slot--tall { grid-row: span 2; }
.slot--wide { grid-column: span 3; }

/* Newsletter routing, as a small flow. */
.route { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: auto; font-size: .74rem; color: var(--ink-3); }
.route b { color: var(--ink); font-weight: 600; }
.route span { border: 1px solid var(--line); border-radius: 8px; padding: 6px 10px; background: var(--bg-2); }
.route em { font-style: normal; color: var(--ink-3); }

/* Shared quiet segmented control. */
.seg2 { display: flex; flex-wrap: wrap; gap: 0 26px; border-bottom: 1px solid var(--line); margin-top: var(--gap-block); }
.seg2 button { position: relative; display: inline-flex; align-items: center; gap: 8px; background: none; border: 0; padding: 0 0 12px; font: inherit; font-size: .88rem; font-weight: 500; color: var(--ink-3); cursor: pointer; transition: color .2s; }
/* A flag beside the language name. The three files sit at different native ratios, so a fixed
   box with object-fit keeps the row even. Muted until its tab is the live one, so the strip
   reads as one control rather than three competing colours. */
.seg2 button img { width: 20px; height: 14px; object-fit: cover; border-radius: 2px; box-shadow: 0 0 0 1px var(--line); filter: saturate(.35) opacity(.7); transition: filter .2s; }
.seg2 button.on img, .seg2 button:hover img { filter: none; }
.seg2 button.on { color: var(--ink); font-weight: 600; }
.seg2 button::after { content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; background: var(--brand); transform: scaleX(0); transform-origin: left; transition: transform .3s cubic-bezier(.4,0,.2,1); }
.seg2 button.on::after { transform: scaleX(1); }

/* Language flags — the product's own set. */
.flags { display: inline-flex; gap: 10px; align-items: center; margin-top: 20px; }
.flags img { width: 30px; height: 21px; object-fit: cover; border-radius: 3px; box-shadow: var(--sh-s); }

/* ==========================================================================
   LANG DEMO — the direction flip, performed rather than described. Arabic
   cannot be screenshotted from the demo build (enabled_languages = 'en'), so
   the page does it live with the product's own strings.
   ========================================================================== */
.lang-demo { display: flex; overflow: hidden; background: #fff; }
.ld-rail { flex: 0 0 46px; background: var(--bg-2); border-inline-end: 1px solid var(--line-2); padding: 14px 0; display: grid; gap: 12px; justify-items: center; align-content: start; }
.ld-rail i { width: 18px; height: 18px; border-radius: 6px; background: var(--line); display: block; }
.ld-rail i:first-child { background: var(--brand); }
.ld-body { flex: 1; min-width: 0; padding: clamp(14px, 1.6vw, 20px); }
.ld-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.ld-head b { font-size: clamp(.92rem, 1.2vw, 1.06rem); font-weight: 600; color: var(--ink); letter-spacing: -.02em; }
.ld-head span { font-size: .72rem; color: var(--ink-3); }
.ld-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 9px 0; border-top: 1px solid var(--line-2); font-size: .82rem; }
.ld-row span { color: var(--ink-2); font-weight: 300; }
.ld-row b { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
.ld-foot { display: flex; gap: 8px; margin-top: 16px; }
.ld-foot button {
  font: inherit; font-size: .74rem; font-weight: 500; cursor: default;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
  border-radius: 999px; padding: 7px 15px;
}
.ld-foot .ld-primary { background: var(--brand); border-color: var(--brand); color: #fff; font-weight: 600; }
/* Arabic needs its own face — the Latin stack renders it as fallback boxes on
   some systems and mismatched weights on the rest. */
.lang-demo[dir="rtl"] { font-family: 'Segoe UI', Tahoma, 'Noto Naskh Arabic', 'Arial', sans-serif; }

/* ==========================================================================
   SWITCHES — one row per surface a buyer can turn off.
   ========================================================================== */
.switches { display: grid; gap: 10px; grid-template-columns: minmax(0, 1fr); margin-top: var(--gap-block); }
@media (min-width: 560px) and (max-width: 859px) { .switches { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.sw {
  display: flex; align-items: center; gap: 12px; width: 100%;
  font: inherit; text-align: start; cursor: pointer;
  border: 1px solid var(--line); background: #fff; border-radius: var(--r-m);
  padding: 12px 14px; transition: border-color .25s, background .25s, opacity .25s;
}
.sw-dot {
  flex: 0 0 34px; height: 20px; border-radius: 999px; background: var(--line);
  position: relative; transition: background .25s;
}
.sw-dot::after {
  content: ""; position: absolute; top: 3px; inset-inline-start: 3px;
  width: 14px; height: 14px; border-radius: 50%; background: #fff;
  box-shadow: var(--sh-s); transition: translate .25s cubic-bezier(.4,0,.2,1);
}
.sw[aria-pressed="true"] .sw-dot { background: var(--brand); }
.sw[aria-pressed="true"] .sw-dot::after { translate: 14px 0; }
.sw[aria-pressed="false"] { opacity: .5; background: var(--bg-2); }
.sw-label { font-size: .84rem; font-weight: 500; color: var(--ink); min-width: 0; }
.sw-out { margin: var(--gap-block) 0 0; font-size: .84rem; color: var(--ink-2); font-weight: 300; line-height: 1.6; }
.sw-out b { color: var(--ink); font-weight: 600; }
.sw--solo { max-width: 320px; margin-bottom: var(--gap-tight); }
/* The storefront master sits above the eight it governs, not among them. */
.sw--master {
  margin-bottom: var(--gap-tight); align-items: center; padding: 14px;
  background: linear-gradient(160deg, #fff, var(--bg-2));
  border-color: color-mix(in srgb, var(--brand) 26%, var(--line));
}
.sw--master .sw-dot { margin-top: 0; }
.sw-label s { display: block; text-decoration: none; margin-top: 2px; font-size: .74rem; font-weight: 300; color: var(--ink-3); }

/* A live indicator beside each service name in C: green and breathing while the
   surface is on, red once it is switched off. It reports state only - the knob on
   the right is still the control - so it is aria-hidden and driven entirely by
   aria-pressed, with no JS of its own. */
#services .sw-live {
  flex: 0 0 8px; width: 8px; height: 8px; border-radius: 50%;
  position: relative; background: #16a34a; transition: background .25s;
}
/* The row is space-between, so the label has to claim the slack or it would
   drift to the middle and leave the dot stranded at the edge. */
#services .sw-live ~ .sw-label { margin-inline-end: auto; }
#services .sw[aria-pressed="false"] .sw-live { background: #e11d48; }
/* The halo: a second circle growing out of the dot. background: inherit means it
   follows the state colour without a second pair of rules. */
#services .sw-live::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  background: inherit; animation: sw-live-pulse 2s ease-out infinite;
}
@keyframes sw-live-pulse {
  0%        { opacity: .5; transform: scale(1); }
  70%, 100% { opacity: 0;  transform: scale(3); }
}
@media (prefers-reduced-motion: reduce) { #services .sw-live::after { animation: none; } }
/* The off state dimmed the WHOLE row, which took the red indicator down with it -
   opacity on a parent cannot be undone by a child. So in C the two parts that
   should recede are dimmed directly, and the row itself stays at full strength.
   The lone switch in 10 has no indicator and keeps the original row-level dim. */
#services .sw[aria-pressed="false"] { opacity: 1; box-shadow: var(--sh-s); }
#services .sw[aria-pressed="false"] .sw-dot,
#services .sw[aria-pressed="false"] .sw-label { opacity: .5; }

/* ==========================================================================
   BOOKDEMO — the public booking page, and what switching it off does to it.
   ========================================================================== */
.bookdemo { position: relative; }
.bookdemo-shot {
  position: relative; border-radius: var(--r-l); overflow: hidden;
  border: 1px solid var(--line); background: #fff; box-shadow: var(--sh-l);
}
.bookdemo-shot img { width: 100%; height: auto; display: block; transition: filter .45s ease, opacity .45s ease; }
.bookdemo[data-on="false"] .bookdemo-shot img { filter: grayscale(1) blur(3px); opacity: .3; }
.bookdemo-404 {
  position: absolute; inset: 0; z-index: 2; display: grid; place-items: center;
  text-align: center; opacity: 0; pointer-events: none; transition: opacity .45s ease;
}
.bookdemo[data-on="false"] .bookdemo-404 { opacity: 1; }
.bookdemo-404 b { display: block; font-size: clamp(1.9rem, 3.6vw, 3rem); font-weight: 700; letter-spacing: -.045em; color: var(--ink); line-height: 1; }
.bookdemo-404 code { display: block; margin-top: 10px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .76rem; color: var(--ink-3); }
@media (prefers-reduced-motion: reduce) {
  .bookdemo-shot img, .bookdemo-404 { transition: none; }
}

/* ---- Motion defaults ----------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; scroll-behavior: auto !important; }
  .scope-d { max-height: 90px; opacity: 1; margin-top: 8px; }
}

/* ==========================================================================
   H — Integrations. Every mark carries its OWN brand colour - the logos are real,
   not repainted. Consistency comes from the frame instead: one cell, one 34px box
   every mark is fitted into, one label style. No rule here touches logo colour, and
   hover moves the card, never the ink.
   ========================================================================== */
.intg-grid { list-style: none; margin: var(--gap-block) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
@media (min-width: 620px)  { .intg-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 900px)  { .intg-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 1200px) { .intg-grid { grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 14px; } }

.intg-cell { display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; padding: 26px 14px; text-align: center;
  border: 1px solid var(--line); border-radius: var(--r-l); background: #fff;
  transition: border-color .25s ease, transform .25s ease, box-shadow .25s ease; }
.intg-cell:hover { border-color: color-mix(in srgb, var(--brand) 34%, var(--line));
  transform: translateY(-3px); box-shadow: var(--sh-m); }

/* One box for every mark. object-fit keeps the tall ones (Bing, Maps) and the wide
   ones from stretching - they letterbox inside the same 34px square instead. */
.intg-mark { width: 34px; height: 34px; display: block; flex: 0 0 auto; object-fit: contain; }
.intg-cell span { font-size: .82rem; font-weight: 500; color: var(--ink-3); letter-spacing: -.01em; }
.intg-cell:hover span { color: var(--ink); }

/* =====================================================================
   MOBILE POLISH LAYER — phones only (≤859px). Desktop composition lives
   at ≥860/1000/1040 and is untouched by everything below.
   ===================================================================== */
/* The switch column stands on the same pink ground the section-9 shape wears:
   the backdrop says "this is the product", and the eight tiles stepping right
   under their master draw the all-of-it / some-of-it hierarchy. Painted as a
   ::before so nothing is added to or moved in the DOM. */
#services .duo-media { position: relative; }
#services .duo-media::before { content: ""; position: absolute;
  /* right: 50% - 50vw = the viewport's own right edge - the panel bleeds off
     the page exactly as section 9's shape does, rounded only on its open side. */
  inset: -20px calc(50% - 50vw) -20px 54%; z-index: 0;
  border-radius: var(--r-l) 0 0 var(--r-l);
  background: linear-gradient(100deg, var(--brand) 8%, var(--brand-2) 92%);
  box-shadow: var(--sh-l); }
#services .duo-media > * { position: relative; z-index: 1; }
/* The closing line stays on the white page, clear of the panel. */
@media (min-width: 860px) { #services .sw-out { max-width: 52%; min-height: 4.8em; } }

/* What was missing: ELEVATION. Everything that rides the pink floats in this
   design language (see section 9's overlay). Bordered flat tiles read as paper
   cutouts against the panel; shadowed borderless cards sit ON it. */
#services .sw { border-color: transparent; box-shadow: var(--sh-m); }
#services .sw--master { box-shadow: var(--sh-l); }

/* Alternate tiles step right - one yes, one no - drawing "some of it". */
@media (min-width: 860px) { #services .switches .sw:nth-child(odd) { margin-left: 26px; } }

.sell-eyebrow { margin: 0 0 4px; font-size: .72rem; font-weight: 800;
  letter-spacing: .12em; text-transform: uppercase; color: var(--brand); }

/* Section 10: the shot under the three-tab switcher sat flush against the
   description at every width. */
#selfserve .duo-stack { margin-top: 18px; }

/* The white-label line, planted on the switch stack: the pitch lands at the
   moment the reader sees the switches it describes. */
.sell-kicker { margin: 0 0 12px; font-size: 1.05rem; font-weight: 700;
  letter-spacing: -.02em; color: var(--ink); }
.sell-kicker em { font-style: normal; color: var(--brand); }
/* The cycling verb keeps its seat (no reflow as letters come and go) and
   carries a typing caret. */
.sell-verb { display: inline-block; min-width: 2.2ch; border-right: 2px solid var(--brand);
  padding-right: 2px; animation: qm-caret 1s step-end infinite; }
@keyframes qm-caret { 50% { border-color: transparent; } }
@media (prefers-reduced-motion: reduce) { .sell-verb { border-right: 0; animation: none; } }
/* At display scale the caret keeps proportion. */
.display .sell-verb { border-right-width: 5px; padding-right: 8px; min-width: 2.4ch; }

/* The hero's inventory line: the promise stays black, the list types itself out
   in brand red beneath it. min-height holds the line's box so the h1 never
   reflows as words of different length come and go. */
/* The hero's inventory line. Three jobs kept apart, because combining them is
   what caused both faults: a reserved-width box (so the headline never re-lays
   out as letters come and go - that was the page-wide stutter), the gradient
   text itself, and a caret that HUGS the text rather than sitting at the right
   edge of the reserved box - that stray dash. `contain` keeps each keystroke's
   recalculation inside this box instead of the whole page. */
.hero-cycle-wrap { display: inline-block; text-align: left;
  white-space: nowrap; contain: layout style; vertical-align: baseline;
  /* Headline size - the typed item is part of the headline, so it is set like
     one. The box is reserved at the longest item's width so no item can
     re-lay-out the page as it types. */
  font-size: 1em; min-width: 13.5ch; }
.hero-cycle { background: linear-gradient(100deg, var(--brand) 8%, var(--brand-2) 92%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; }
.hero-caret { display: inline-block; width: .06em; height: .78em; margin-left: .05em;
  background: var(--brand-2); vertical-align: baseline;
  animation: qm-caret 1s step-end infinite; }
@media (prefers-reduced-motion: reduce) { .hero-caret { display: none; } }

/* Switch tiles at every width: the words lead, the toggle closes the row.
   The dot keeps its base flex-basis - it has no width of its own, the 34px
   basis IS its width, which is why overriding it erased every knob. */
.sw { justify-content: space-between; }
.sw .sw-dot { order: 2; }

@media (max-width: 859px) {

  /* One rhythm for every chapter, and headings sized for a 393px measure. */
  .sec, .scope, .pos { padding-block: 60px; }
  .display { font-size: clamp(2.1rem, 9.4vw, 2.9rem); letter-spacing: -.035em; }
  .wrap { padding-inline: 20px; }

  /* Accordions: the stage leads; items are cards, accent + chevron on the right. */
  .scope-stage { align-items: start; }
  .scope-stage > div:not(.screen):not(.scope-list) { order: -2; }
  .scope-stage .screen { order: -1; }
  .scope-list { margin-top: 26px; }
  .scope-item { padding: 16px 46px 16px 18px; border: 1px solid var(--line-2);
    border-radius: 16px; margin-bottom: 12px; background: #fff; }
  .scope-item:last-child { border-bottom: 1px solid var(--line-2); }
  .scope-item::before { left: auto; right: 0; border-radius: 3px 0 0 3px; }
  .scope-item::after { content: ''; position: absolute; right: 18px; top: 26px;
    width: 9px; height: 9px; border-right: 2px solid var(--ink-3);
    border-bottom: 2px solid var(--ink-3); transform: rotate(45deg);
    transition: transform .3s ease; }
  .scope-item.on::after { transform: rotate(225deg); }
  .scope-n { font-size: .72rem; }

  /* Films and feature media: near-full width with 12px gutters, and the SAME
     rounded frame they wear on desktop — the radius is the design's character. */
  /* venue-filmwrap is a direct child of its section - already viewport-wide.
     Its inset comes from its own padding, so that is what goes to zero; the
     negative margin treatment belongs only to children of the padded wrap. */
  .venue-filmwrap { margin-inline: 0; padding-inline: 0; max-width: none; }
  .pos-media { margin-inline: -20px; max-width: none; }
  /* The backdrops those overlays ride (the pink shapes, the payment photo)
     widen to the film standard - 366 with the 22px frame - so a 350 overlay
     always rides a visibly larger ground, never one narrower than itself. */
  .pos-media .pos-film { margin-inline: 12px; border-radius: 22px; }
  .venue-film, .pos-film, .duo-film { border-radius: 22px; overflow: hidden; }

  /* The chapter films grow as they approach the viewport's centre and give it
     back on the way out — a scale, so no frame is ever cropped away. */
  /* The film keeps its base ratio and overscan; a fixed 20px gutter and the
     22px frame at rest - no scroll-linked animation. */
  /* Pinned hard: no script or animation may resize these films on a phone. */
  .venue-filmwrap, #venueFilmWrap { max-width: none !important; padding-inline: 0 !important; }
  .venue-film { width: calc(100% - 40px) !important; margin-inline: auto;
    border-radius: 22px; margin-block: 6px; transform: none !important; }

  /* THE overlay standard: every element that rides over a film, photo or pink
     panel - till stills, the credit card, report shots, the calendar pair, the
     language panel - wears ONE width (full measure minus 16px) and ONE seat
     (centred, riding 12% up over its backdrop). The map card set the size. */
  /* pos-media bleeds to the viewport edge, so its overlays subtract the full
     40px to land on the same 350px every duo overlay lands on. */
  .pos-till, .pos-till--card { position: relative; right: auto; left: auto; bottom: auto;
    width: calc(100% - 40px); max-width: none; margin: -12% auto 0; float: none; z-index: 2; }
  .duo-float { width: calc(100% - 16px); max-width: none; margin: -12% auto 0; }

  /* The in-venue counters. */
  .venue-stat { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 26px 18px; text-align: center; justify-items: center; }

  /* The eight-system rail: swipe with air around it, not glued to its chapter. */
  .rail { margin-block: 34px 10px; }
  .rail { scrollbar-width: none; }
  .rail::-webkit-scrollbar { display: none; }
  .rail-track { scroll-snap-type: x mandatory;
    padding: 6px 20px 20px; scroll-padding-inline: 20px; }
  .rail-track .sys { scroll-snap-align: center; }

  /* One thought per row. */
  /* Bento cards (Growth 21, Operations 22): one per row with room to read -
     a consistent gap, fuller padding, and body copy at a phone-legible size. */
  .bento { grid-template-columns: 1fr !important; grid-auto-rows: auto; gap: 16px; }
  .bo { padding: 24px 20px; }
  .bo p { font-size: .875rem; line-height: 1.6; margin-top: 8px; }
  /* Screenshot cards: the absolute shot band gets a FIXED height and the card
     reserves that band plus clearance with padding - the title starts below the
     image by construction, never under its fade. Same cure as the slots card. */
  .bo--shot { padding-top: 212px; min-height: 0; justify-content: flex-start; }
  .bo-shot { height: 186px; }
  /* The gateway-logo block and the newsletter-route block ended flush against
     their titles (0px), and their chips wrapped with no row air. */
  .bo .paylogos, .bo .route { margin-bottom: 16px; row-gap: 10px; flex-wrap: wrap; }
  .switches { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* Tall report screenshots: the hover-scroll is a mouse interaction, so on a
     phone the shot pans by itself — the whole report passes through the frame. */
  .scrollshot { --h: min(58vh, 460px); }
  .scrollshot img { animation: qm-shot-pan 18s ease-in-out infinite alternate; }
  .duo-float { margin-top: -10%; }

  /* Words first on a phone; the picture follows. Same reading order as the
     desktop's text column. Applies to Reporting (17), AI (18), Branches (19). */
  /* align-items:stretch overrides the base grid's centring: a flex column with
     centred items shrinks every child to content width (the 210px film bug). */
  #analytics .duo-grid, #ai .duo-grid, #rtl .duo-grid, #kitchen .duo-grid { display: flex; flex-direction: column; align-items: stretch; }
  #analytics .duo-media, #ai .duo-media, #rtl .duo-media, #kitchen .duo-media { order: 2; }
  /* Every chapter now ends on its media, so the 60px+60px boundary reads the
     same between every pair - no text-tail chapters with double the visual air. */
  #analytics .duo-media, #ai .duo-media, #rtl .duo-media, #kitchen .duo-media { margin-bottom: 0; }
  /* Branches is a pos-chapter, not a duo: same words-first order via its grid. */
  #branches .pos-grid { display: flex; flex-direction: column; }
  #branches .pos-media { order: 2; }

  .duo-media { margin-inline: -8px; max-width: none; }

  /* Growth: the slot mock owns a fixed band at the top of the card and the
     words start below it with real clearance - overlap is impossible. */
  .bo:has(.slots) { padding-top: 250px; }
  .bo .slots { height: 205px; margin-bottom: 18px; }

  /* The delivery chapter rides up over the interstitial film: the map card
     lands centred on the film's lower band, the words above it move up to the
     film's upper half, and the film keeps every pixel it had - the overlap is
     the composition, nothing is cropped or hidden. */
  #break0 .wrap { transform: translateY(-12%); }
  #break0 .sub { margin-top: 8px; }
  #delivery { margin-top: -120px; padding-top: 0; }
  #delivery .duo-media { position: relative; z-index: 3; }
  /* A taller frame for the map on a phone: 16:11 reads letterboxy at this width. */
  #delivery .livemap { aspect-ratio: 4 / 3.4; }

  /* The bar, in flow: burger, logo, then the call to action on the right.
     No absolute positioning - nothing can overlap. */
  /* The id outranks the scrolled-state's translucent white: solid at all times. */
  /* The scroll handler writes a translucent white INLINE; only !important outranks
     an inline style, which is exactly the job here: the bar stays solid. */
  #nav { background: #fff !important; border-bottom-color: var(--line); backdrop-filter: none !important; }
  .nav-in { padding-inline: 12px; gap: 10px; position: relative; }
  /* Logo dead centre (safe now the burger carries no auto-margin); burger bars
     in the brand red of the logotype. */
  .nav-logo { position: absolute; left: 50%; transform: translateX(-50%); }
  .nav-burger span, .nav-burger span::before, .nav-burger span::after { background: var(--brand); }

  /* Reservations pair: the public-booking chapter continues the reservations
     story, so its boundary is a beat, not a full chapter break. And the
     calendar/booking shots grow from their 76% desktop float to the full measure. */
  #resvpublic { padding-top: 14px; }

  /* Section 20: film and panel STACK at full width - the reorder must never
     put them side by side. The panel keeps its ride over the film's edge. */
  #rtl .duo-media { display: block; }
  #rtl .duo-film { width: 100%; }
  /* lang panel: covered by the .duo-float standard above */

  /* Section 17's decorative screenshot wall scatters into broken-looking pills
     at phone width; it hides here (aria-hidden decoration - the film and the
     panning report carry the section's visuals). Desktop keeps the wall. */
  #analytics .shotwall { display: none; }
  .nav-burger { width: 44px; height: 44px; display: grid; place-items: center; flex: 0 0 auto; }

  /* The typed item rides on its own line at headline size, one line, never
     wrapping - the word list is kept short enough that it fits. */
  .hero-cycle-wrap { min-width: 0; }
  /* "runs on." is one phrase - it never splits across two lines, and the h1's
     15ch cap was forcing the break. */
  .hero h1 { line-height: 1.02; max-width: none; }
  .hero h1 .accent { white-space: nowrap; }

  .nav-logo { height: 28px; width: auto; }

  /* Section 03 (What you offer): the words lead, the switch tiles follow -
     the same order the desktop reads, left before right. */
  #services .duo-grid { display: flex; flex-direction: column; }
  #services .duo-media { order: 2; }

  .sw--master { width: 100%; }
  #services .duo-media::before { display: none; }
  /* The reservations on/off switch spans the full measure on a phone. */
  .sw--solo { width: 100%; max-width: none; margin-inline: 0; }
}
@keyframes qm-shot-pan {
  0%, 8%   { transform: translateY(0); }
  92%, 100% { transform: translateY(calc(-100% + var(--h, 420px))); }
}
@media (max-width: 859px) and (prefers-reduced-motion: reduce) {
  .scrollshot img { animation: none; }
  .venue-film { transform: none; }
}
@media (max-width: 859px) {
  .intg-cell { padding: 20px 10px; gap: 9px; }
  .intg-mark { width: 28px; height: 28px; }
}


/* ==========================================================================
   HERO — rebuilt on the approved preview-image composition (2026-08). The
   copy column keeps the landing's voice; the staging is the preview's: the
   tinted field, the screenshot wall, the rings, the kiosk on its panel, two
   storefront cards and the garnishes. No logo, caps line or market tabs.
   ========================================================================== */
.hero { background: #fff; }
/* The preview field, capped at the fold: tint and wall end before the stage. */
.hero::before { content: ""; position: absolute; inset: 0 0 auto; height: min(104vh, 920px); z-index: 0;
  background: linear-gradient(180deg, #fff 0%, #f7f4f5 30%, #f7f4f5 74%, #fff 100%); }
.hero-wall { position: absolute; inset: -14px -14px auto; height: min(104vh, 920px); z-index: 0; display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; padding: 10px; opacity: .38; pointer-events: none; overflow: hidden;
  -webkit-mask-image:
    radial-gradient(56% 82% at 24% 46%, transparent 0%, transparent 42%, #000 90%),
    linear-gradient(180deg, transparent 0%, #000 14%, #000 80%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-image:
    radial-gradient(56% 82% at 24% 46%, transparent 0%, transparent 42%, #000 90%),
    linear-gradient(180deg, transparent 0%, #000 14%, #000 80%, transparent 100%);
  mask-composite: intersect; }
.hero-wall img { width: 100%; height: auto; aspect-ratio: 7 / 5; object-fit: cover; object-position: top center; border-radius: 8px; border: 1px solid #eae4e6; box-shadow: 0 2px 8px rgba(31,11,18,.05); }
.hero-rings { position: absolute; left: clamp(-190px, -13vw, -130px); top: clamp(-210px, -14vw, -150px); width: clamp(300px, 26vw, 400px); aspect-ratio: 1; z-index: 0; pointer-events: none; }
.hero-rings i { position: absolute; inset: 0; border: 2px solid rgba(255,0,61,.30); border-radius: 50%; }
.hero-rings i:nth-child(2) { inset: 15%; border-color: rgba(255,0,61,.40); }
.hero-rings i:nth-child(3) { inset: 30%; border-color: rgba(255,0,61,.50); }
.hero-grid { position: relative; z-index: 1; display: grid; grid-template-columns: minmax(0, 1.02fr) minmax(0, .98fr); gap: clamp(28px, 4vw, 64px); align-items: center; max-width: min(96vw, 1560px); }
.hero-grid h1 { font-size: clamp(2.4rem, 4.5vw, 4.3rem); max-width: none; }
.hero-feats { list-style: none; display: grid; grid-template-columns: repeat(2, minmax(0, max-content)); gap: 11px 30px; margin: 26px 0 0; padding: 0; }
.hero-feats li { display: flex; align-items: center; gap: 9px; font-size: .92rem; font-weight: 600; color: var(--ink); white-space: nowrap; }
.hero-feats i { flex: 0 0 auto; width: 6px; height: 6px; border-radius: 50%; background: var(--brand); }
.hero-vis { position: relative; z-index: 1; min-height: clamp(430px, 40vw, 620px); }
.hv-panel { position: absolute; right: 0; top: 0; height: 100%; width: clamp(190px, 40%, 300px); border-radius: 30px; background: linear-gradient(180deg, #ff003d, #ff3364); box-shadow: 0 24px 54px rgba(255,0,61,.32); }
.hv-card { position: absolute; border-radius: 12px; overflow: hidden; border: 1px solid #eee; background: #fff; }
.hv-card img { display: block; width: 100%; height: auto; }
.hv-carda { left: 0; top: 5%; width: 50%; box-shadow: 0 16px 34px rgba(31,11,18,.20), 0 3px 10px rgba(31,11,18,.08); }
.hv-cardb { left: 4%; top: 36%; width: 39%; box-shadow: 0 20px 40px rgba(31,11,18,.26), 0 4px 12px rgba(31,11,18,.10); }
/* The printed A5 menu, fanned between the storefront cards and the kiosk. */
.hv-cardm { right: 27%; top: -2%; width: 26%; box-shadow: 0 30px 56px rgba(31,11,18,.38), 0 8px 18px rgba(31,11,18,.16); }
/* The till station and the tablet, on the kiosk's level: one left of it, one right. */
.hv-pos, .hv-tab { position: absolute; height: auto; }
.hv-pos { left: -3%; bottom: 2%; width: 47%; filter: drop-shadow(0 16px 30px rgba(31,11,18,.28)); }
.hv-tab { right: 3.5%; bottom: -12%; width: 29%; filter: drop-shadow(0 14px 26px rgba(31,11,18,.30)); }
.hv-kiosk { position: absolute; right: 0; bottom: -5%; width: clamp(260px, 57%, 410px); height: auto; filter: drop-shadow(0 18px 32px rgba(31,11,18,.30)); }
/* The holographic sticker, stuck on the panel's top-left corner beside the printed menu. */
.hv-sticker { position: absolute; right: 2%; top: -4%; width: 28%; height: auto; transform: rotate(-7deg); transform-origin: 50% 100%; filter: drop-shadow(0 12px 24px rgba(31,11,18,.34)); }
/* The wall board (section 03's first screen), bleeding in from the left edge beside the copy. */
.hero-tv { position: absolute; z-index: 0; top: 50%; right: calc(100% + 14px); width: clamp(420px, 36vw, 660px); transform: translateY(-50%); pointer-events: none; }
.hero-tv .tvband-frame { box-shadow: 0 30px 60px -18px rgba(31,11,18,.45); }
.hero-tv--right { right: auto; left: calc(100% + 14px); }
@media (max-width: 1740px) { .hero-tv { display: none; } }
@media (max-width: 1020px) {
  .hero-grid { grid-template-columns: minmax(0, 1fr); }
  .hero-vis { width: 100%; max-width: 560px; margin: 18px auto 0; min-height: min(104vw, 540px); }
  .hero-wall { opacity: .3;
    -webkit-mask-image: linear-gradient(180deg, transparent 0%, rgba(0,0,0,.85) 34%, #000 72%, transparent 100%);
            mask-image: linear-gradient(180deg, transparent 0%, rgba(0,0,0,.85) 34%, #000 72%, transparent 100%); }
}

/* ==========================================================================
   PRINT - the menu generator, staged as a print table (section 13).
   Sheets are near-sharp paper with press shadows; the head mirrors the
   band-head pattern (copy left, caps right).
   ========================================================================== */
/* Sits close on the heels of Delivery - the default section gap read as a hole. */
.printshop { padding-top: clamp(24px, 2.5vw, 40px); overflow: clip; }
.printshop-head { display: grid; grid-template-columns: minmax(0, .88fr) minmax(0, 1.12fr); gap: clamp(24px, 3vw, 56px); align-items: center; }
/* The same brand-gradient panel section 06 puts behind its film - here it is
   the mat the press proofs lie on, bleeding off to the right with the table. */
.print-table::before { content: ""; position: absolute; inset: -7% -6% -3% 16%; border-radius: var(--r-l);
  background: linear-gradient(100deg, var(--brand) 8%, var(--brand-2) 92%);
  box-shadow: 0 30px 60px rgba(255,0,61,.26); }
.print-table { position: relative; margin: 0; aspect-ratio: 2.1 / 1;
  width: calc(100% + var(--pad) + max((100vw - var(--maxw)) / 2, 0px) + 5vw); }
.pt-sheet { position: absolute; height: auto; border-radius: 4px; background: #fff; }
.pt-back  { width: 40%; left: 23%; bottom: 56%; transform: rotate(-1.5deg); box-shadow: 0 22px 46px rgba(31,11,18,.28), 0 4px 10px rgba(31,11,18,.12); }
.pt-left  { width: 37%; left: -1%; bottom: 14%; transform: rotate(-4.5deg); box-shadow: 0 18px 40px rgba(31,11,18,.22), 0 3px 10px rgba(31,11,18,.10); }
.pt-right { width: 37%; right: 0; bottom: 16%; transform: rotate(3.5deg); box-shadow: 0 18px 40px rgba(31,11,18,.22), 0 3px 10px rgba(31,11,18,.10); }
.pt-main  { width: 56%; left: 17%; bottom: 0; z-index: 2; box-shadow: 0 34px 64px rgba(31,11,18,.30), 0 6px 16px rgba(31,11,18,.12); }
.pt-tall  { width: 20%; right: 7%; bottom: -5%; z-index: 3; transform: rotate(2deg); box-shadow: 0 26px 52px rgba(31,11,18,.34), 0 5px 14px rgba(31,11,18,.14); }
@media (max-width: 960px) { .printshop-head { grid-template-columns: minmax(0, 1fr); align-items: start; } .print-table { width: 100%; margin-top: var(--gap-block); } }
@media (max-width: 700px) {
  /* All five proofs in a snap filmstrip ON the mat: the gradient becomes the
     scroller's own background, so the sheets slide inside it. Native pan-x
     keeps vertical page scrolling untouched, exactly like the in-venue rail. */
  .print-table { aspect-ratio: auto; position: relative; display: flex; gap: 14px; align-items: center;
    overflow-x: auto; overscroll-behavior-x: contain; -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity; padding: 20px 16px; border-radius: var(--r-l);
    background: linear-gradient(100deg, var(--brand) 8%, var(--brand-2) 92%);
    box-shadow: 0 24px 48px rgba(255,0,61,.22); scrollbar-width: none; }
  .print-table::-webkit-scrollbar { display: none; }
  .print-table::before { display: none; }
  .pt-sheet { display: block; position: static; flex: 0 0 auto; width: auto;
    height: clamp(230px, 64vw, 320px); transform: none; scroll-snap-align: center; }
}