/* shop.css — the "zoom into the shop" landing candidate (public/index.html).

   COLOUR: nothing in this file introduces a colour. Every value is one of
   app.css's night tokens (the page is data-theme="dark", like index.html) or a
   color-mix of one of them into transparent. The three brand anchors are
   --accent (#6F8FAF, the night brand blue), --cat-new (#D4DAE1, the chrome/
   silver) and --ink (#E9E6DE, bone as the night theme's text). #000 appears
   only in shadows, as it does in app.css's own night shadows.

   The room itself is WebGL (shop3d.js). It keeps its own small palette, read
   off the approved frame (~/cutsight-assets/landing-src/aisle-ref.png); only the screens'
   blue comes from these tokens.

   MOTION: every animated DOM property below is transform or opacity. */

/* ------------------------------------------------------------------ */
/* Stage                                                              */
/* ------------------------------------------------------------------ */
body.sx { background: var(--bg); }
main.sx-main { display: block; padding: 0; }
.sx-main > * { max-width: none; }
/* The padding keeps a focused element clear of the sticky nav when tabbing;
   the margin is the breathing room an anchor jump lands with. The #how marker
   the scene places at the onboarding stage gets none: it is a scroll position,
   not a heading. */
html { scroll-padding-top: 72px; }
.sx-main, .sx-main [id] { scroll-margin-top: 20px; }
.sx-main #how[aria-hidden="true"] { scroll-margin-top: 0; }

/* NAVY, the fourth brand colour, and scoped to the scene on purpose: the
   product's own dark tokens (--bg, --side, --card…) are hueless greys, and
   repointing them would restyle every screen of the app. The stage behind the
   room is the darkest of these.
   Hue held at --accent's (oklch h ≈ 249, HSL ≈ 210); chroma tapers toward
   black so the darkest steps stay navy instead of drifting purple. */
.sx-scene {
  position: relative;
  --sx-navy-950: #030911;  /* oklch(0.136 0.022 249) ceiling void, canvas clear */
  --sx-navy-900: #06111D;  /* oklch(0.174 0.030 251) walls */
  --sx-navy-850: #091827;  /* oklch(0.204 0.037 250) leather */
  --sx-navy-800: #0D1F31;  /* oklch(0.234 0.042 250) cabinetry, ducts */
  --sx-navy-700: #183046;  /* oklch(0.301 0.050 248) stone tops, trim */
}
.sx-sticky { position: relative; height: 100svh; min-height: 560px; overflow: hidden; }
.sx-stage { position: absolute; inset: 0; overflow: hidden; background: var(--sx-navy-950); }
.sx-still, .sx-still img { position: absolute; inset: 0; width: 100%; height: 100%; }
.sx-still img { object-fit: cover; object-position: 50% 50%; }
.sx-gl { position: absolute; inset: 0; opacity: 0; transition: opacity .6s ease; }
.sx-gl.ready { opacity: 1; }
.sx-css3d, .sx-canvas { position: absolute; inset: 0; }
/* /?still: the room and nothing else, to capture the static images. */
.still-capture .sx-hero, .still-capture .sx-nav, .still-capture .sx-caps,
.still-capture .sx-still, .still-capture .sx-vignette { visibility: hidden; }
.sx-canvas { pointer-events: none; }
.sx-vignette {
  position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(ellipse 80% 70% at 50% 42%, transparent 50%,
              color-mix(in srgb, var(--bg) 88%, transparent) 100%);
}

/* ------------------------------------------------------------------ */
/* Header                                                             */
/* ------------------------------------------------------------------ */
.sx-skip { position: absolute; left: -9999px; }
.sx-skip:focus { left: 16px; top: 12px; z-index: 100; background: var(--ink); color: var(--bg);
                 padding: 10px 14px; border-radius: 8px; text-decoration: none; font-weight: 600; }
.sx-nav {
  position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; gap: 28px;
  padding: 12px clamp(16px, 4vw, 48px);
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  border-bottom: 1px solid var(--line);
}
.sx-brand { display: inline-flex; align-items: baseline; gap: 6px; text-decoration: none; }
.sx-brand .wordmark { font-size: 21px; color: var(--ink); }
.sx-brand .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); display: inline-block; }
/* app.css styles bare `nav` and `nav a` for the product sidebar. Undone here. */
nav.sx-links { flex: 1; display: flex; gap: 24px; padding: 0; overflow: visible; }
nav.sx-links a {
  display: inline-flex; align-items: center; min-height: 44px; padding: 0; margin: 0;
  background: none; box-shadow: none; color: var(--ink-2); font-size: 14px; font-weight: 500;
}
nav.sx-links a:hover { background: none; color: var(--ink); }
@media (max-width: 760px) {
  nav.sx-links { display: none; }
  .sx-nav { justify-content: space-between; }
  .sx-nav .sx-btn-sm { white-space: nowrap; }
}

.sx-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font: 600 15px/1 var(--sans); letter-spacing: -.005em; text-decoration: none; cursor: pointer;
  padding: 15px 24px; min-height: 50px; border-radius: 999px;
  background: var(--ink); color: var(--bg); border: 1px solid var(--ink);
}
.sx-btn:hover { background: var(--cat-new-lit); }
/* A blue ring with a dark gap inside it, so it reads over bone, over black,
   and over the hero still where an LED strip runs behind the button. */
.sx-btn:focus-visible { outline: 3px solid var(--accent-deep); outline-offset: 3px; box-shadow: 0 0 0 3px var(--bg); }
.sx-nav a:focus-visible, .sx-foot a:focus-visible, .sx-brand:focus-visible {
  outline: 2px solid var(--accent-deep); outline-offset: 4px; border-radius: 4px;
}
.sx-btn-sm { padding: 9px 16px; min-height: 40px; font-size: 14px; }
.sx-btn-ghost { background: color-mix(in srgb, var(--bg) 60%, transparent); color: var(--ink); border-color: var(--line-2); }
.sx-btn-ghost:hover { background: var(--card); }

/* ------------------------------------------------------------------ */
/* Hero, captions                                                     */
/* ------------------------------------------------------------------ */
/* The hero is CENTRED in the frame (Logan: "centered in the screen and not
   too low"), optically: the block's centre sits a little above the middle of
   the viewport, the way a centred headline reads as centred. The space the
   fixed nav takes at the top is matched at the bottom, plus the optical lift.
   One rule for every path: the footage, the 3D room and the static page all
   lay this element out the same way. */
.sx-hero {
  position: absolute; inset: 0; z-index: 2;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 72px 20px calc(72px + 6vh); pointer-events: none;
}
.sx-hero::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: radial-gradient(ellipse 46% 36% at 50% 46%, color-mix(in srgb, var(--bg) 72%, transparent), transparent 100%);
}
.sx-hero a, .sx-hero button { pointer-events: auto; }
/* On the static page (reduced motion, no JS) the nav sits in the flow above
   the hero instead of over it, which pushed the same block 68px lower. The
   hero's box is shifted up by the nav's height so it centres in the viewport,
   exactly where the scene paths put it. */
html:not(.scene-on) .sx-hero { top: -68px; bottom: 68px; }
/* Vertical space is tight on a phone: tighter gaps, and the empty status line
   takes no room until it has something to say. */
@media (max-width: 760px) {
  .sx-hero { padding: 68px 20px calc(68px + 8vh); }
  .sx-hero .sx-lede { margin-top: 12px; }
  .sx-hero .sx-cta { margin-top: 20px; }
  .sx-hero .sx-status:empty { min-height: 0; margin: 0; }
  .sx-hero::before { background: radial-gradient(ellipse 80% 34% at 50% 48%, color-mix(in srgb, var(--bg) 78%, transparent), transparent 100%); }
}
.sx-h1 {
  font: 500 clamp(36px, 5vw, 70px)/1.02 var(--sans); letter-spacing: -.035em;
  color: var(--ink); margin: 0; text-wrap: balance;
}
.grad {
  background: linear-gradient(100deg,
    color-mix(in srgb, var(--accent-deep) 74%, var(--ink)) 0%,
    color-mix(in srgb, var(--accent-deep) 50%, var(--ink)) 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.sx-lede { color: var(--ink-2); font-size: clamp(16px, 1.45vw, 19px); line-height: 1.55;
           max-width: 44ch; margin: 18px auto 0; }
.sx-cta { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; margin-top: 30px; }
/* THE ADVISAL under each "Connect your shop" button (public/index.html). Body
   text in the ink colour rather than fine print, naming the button, with the two
   documents as underlined accent links — conspicuous, which is the point. */
/* It lives INSIDE .sx-cta as a full-width flex item, so it is always directly
   below the button it names. Wide: [Connect your shop][See how…] on one row, the
   advisal under both. Narrow, where the buttons stack: Connect your shop, then the
   advisal, then See how… — never a second button between the advisal and its own.
   .sx-cta-qualified so it beats .sx-cap p's grey on the closing frame. */
.sx-cta .sx-agree { flex: 0 0 100%; order: 3; max-width: none; margin: 0; text-wrap: balance; color: var(--ink);
  font-size: 13.5px; line-height: 1.5; text-align: center; text-shadow: 0 1px 3px rgba(0,0,0,.55); }
.sx-cta .sx-agree a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; font-weight: 600; }
.sx-cta .sx-agree[hidden] { display: none; }
@media (max-width: 760px) {
  .sx-cta .sx-agree { order: 2; }
  .sx-cta .sx-btn-ghost { order: 3; }
}
.sx-status { min-height: 1.4em; margin: 14px 0 0; color: var(--ink-2); font-size: 14px; }

.sx-caps { position: absolute; inset: 0; z-index: 3; pointer-events: none; }
/* A dark column behind the desktop captions, so an LED strip seen end-on (a
   bright line through the vanishing point) never runs through the words. */
.sx-scrim {
  position: absolute; left: 0; top: 0; bottom: 0; width: min(620px, 44vw); opacity: 0;
  background: linear-gradient(90deg, color-mix(in srgb, var(--bg) 94%, transparent) 0%,
              color-mix(in srgb, var(--bg) 82%, transparent) 62%, transparent 100%);
}
@media (max-width: 760px) { .sx-scrim { display: none; } }
.sx-caps .sx-cap {
  position: absolute; left: clamp(24px, 3.6vw, 60px); top: 50%; transform: translateY(-50%);
  width: min(400px, 29vw); pointer-events: auto;
}
.sx-caps .sx-cap h2 { font-size: clamp(30px, 3vw, 44px); }
/* THE CLOSE IS COMPOSED EXACTLY AS THE HERO IS (Logan, 1 Oct 2026: "center
   screen like the very first frame of the website"), so the page opens and
   closes on one composition. Same box (the whole viewport), same flex
   centring, the hero's own padding and the hero's own glow, at both widths;
   if the hero's placement changes, change this with it. */
.sx-caps .sx-close {
  left: 0; right: 0; top: 0; bottom: 0; width: auto; transform: none;
  display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center;
  padding: 72px 20px calc(72px + 6vh);
  background: radial-gradient(ellipse 46% 36% at 50% 46%, color-mix(in srgb, var(--bg) 72%, transparent), transparent 100%);
}
.sx-caps .sx-close h2 { font-size: clamp(36px, 5vw, 70px); margin-bottom: 0; }
/* The hero's own spacing, which the caption rules (.sx-cap h2's 14px, .sx-cap
   p's zero margin) would otherwise replace: 18px from heading to lede. */
.sx-caps .sx-close .sx-lede { margin: 18px auto 0; }
/* The hero carries a status line under its buttons ("Opening Square…" when one
   is pressed) that holds its 14px margin and 1.4em of 14px text while empty,
   and so lifts the hero's visible block by half of that. The close holds the
   same space so the two blocks centre on the same line. */
.sx-caps .sx-close .sx-cta { margin-bottom: calc(14px + 1.4 * 14px); }
@media (max-width: 760px) {
  .sx-caps .sx-cap {
    left: 14px; right: 22px; top: auto; bottom: 16px; width: auto; transform: none;
    padding: 16px 18px; border-radius: 14px;
    background: color-mix(in srgb, var(--bg) 92%, transparent); border: 1px solid var(--line);
  }
  .sx-caps .sx-cap h2 { font-size: 26px; margin-bottom: 8px; }
  .sx-caps .sx-cap h2 br { display: none; }
  /* Short captions on a phone: the eyebrow and the title. The sentence is on
     the page twice more below the scene, so nothing is lost. */
  .sx-caps .sx-cap:not(.sx-close) > p:not(.sx-eyebrow) { display: none; }
  .sx-caps .sx-cap h2 { margin-bottom: 0; }
  /* The hero's phone composition: its padding, its glow, its type size (the
     caption rule above would make this heading 26px) and its tighter gaps. */
  /* + 22px top, - 22px bottom: the hero's first frame on a phone sits 22px
     lower than the scene's own geometry, because app.css's phone rule
     "section { margin-top: 22px }" also lands on #scene. The close is always
     seen pinned, so it carries that 22px itself to sit where the hero is seen.
     If that leak is ever fixed, both this and the hero move together: drop it. */
  .sx-caps .sx-close { left: 0; right: 0; top: 0; bottom: 0; border: 0; border-radius: 0;
    padding: calc(68px + 22px) 20px calc(68px + 8vh - 22px);
    background: radial-gradient(ellipse 80% 34% at 50% 48%, color-mix(in srgb, var(--bg) 78%, transparent), transparent 100%); }
  .sx-caps .sx-close h2 { font-size: clamp(36px, 5vw, 70px); }
  .sx-caps .sx-close h2 br { display: inline; }
  .sx-caps .sx-close .sx-lede { margin-top: 12px; }
  .sx-caps .sx-close .sx-cta { margin-top: 20px; margin-bottom: 0; }   /* the hero's empty status takes no room on a phone */
}


/* ------------------------------------------------------------------ */
/* The screens: static sections (the page with no scene)              */
/* ------------------------------------------------------------------ */
.sx-wrap { max-width: 1320px; margin: 0 auto; padding-inline: clamp(16px, 4vw, 48px); }
.sx-part { padding: 72px 0; border-top: 1px solid var(--line); }
.sx-eyebrow { font-size: 11px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
              color: var(--accent-deep); margin: 0 0 12px; }
.sx-cap h2, .sx-h2 {
  font: 500 clamp(30px, 4.2vw, 50px)/1.05 var(--sans); letter-spacing: -.03em;
  color: var(--ink); margin: 0 0 14px; text-wrap: balance;
}
.sx-cap p { color: var(--ink-2); font-size: 16px; line-height: 1.6; max-width: 52ch; margin: 0; }
.sx-cap p b { color: var(--ink); }
/* A hyphenated phrase that should not break at its hyphen ("easy-to-read"). */
.nw { white-space: nowrap; }
.sx-close-part { text-align: center; padding: 110px 0; }
.sx-close-part .sx-lede { margin-inline: auto; }

.sx-frame {
  position: relative; margin-top: 30px; overflow: hidden;
  background: var(--bg); border: 1px solid var(--line-2); border-radius: 14px;
  box-shadow: 0 40px 90px -40px #000;
}
.sx-frame-dash .sx-scr { max-height: 900px; overflow: hidden; }
.sx-frame-mirror { max-width: 560px; }

/* Containment for the product's own shell, which assumes it owns the window. */
.sx-scr { position: relative; }
.sx-scr .shell { min-height: 0; }
.sx-scr aside { position: static; height: auto; z-index: auto; }
.sx-scr .appmain { flex: 1; min-width: 0; padding: 30px 34px 40px; }
.sx-scr .appmain > * { max-width: none; }
.sx-scr .mobbar { position: static; }
.sx-scr nav a, .sx-scr .ghost, .sx-scr .v3-row, .sx-scr .m-row { cursor: default; }
.sx-scr .ctl { display: inline-flex; align-items: center; min-height: 36px; padding: 0 14px; }
.sx-scr .ghost { display: inline-flex; align-items: center; min-height: 34px; padding: 0 12px;
                 border: 1px solid var(--line-2); border-radius: var(--r-md); font-size: 13px; }
.sx-draw, .sx-draw-i { transform-origin: 0 50%; }
.sx-draw { overflow: hidden; }
.sx-dash .m-bar i { transform-origin: 50% 100%; }
@media (max-width: 860px) {
  .sx-scr .appmain { padding: 0 16px 24px; }
}

/* The Clients screen's own rules, scoped here. */
.sx-clients { padding: 26px 26px 30px; }
.sx-clients .fig-even { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.sx-clients .toolbar { display: flex; gap: 10px; align-items: center; margin-bottom: 14px; flex-wrap: wrap; }
.sx-clients .search { flex: 1; min-width: 160px; position: relative; }
.sx-clients .search .input {
  display: block; background: var(--card); border: 1px solid var(--edge); border-radius: 9px;
  color: var(--ink-3); padding: 11px 13px 11px 38px; min-height: 44px; box-sizing: border-box; font-size: 14px;
}
.sx-clients .search svg { position: absolute; left: 13px; top: 50%; transform: translateY(-50%); color: var(--ink-3); }
.sx-clients table.dir { width: 100%; border-collapse: collapse; }
.sx-clients table.dir th, .sx-clients table.dir td { padding-right: 18px; }
.sx-clients table.dir th:last-child, .sx-clients table.dir td:last-child { padding-right: 0; }
.sx-clients table.dir th { white-space: nowrap; }
.sx-clients table.dir td.num { padding-right: 22px; }
.sx-clients table.dir th.on { color: var(--accent-deep); }
.sx-clients .nm { font-size: 13.5px; }
.sx-clients .ph .none { color: var(--ink-3); }
.sx-clients .st { font-size: 10.5px; border-radius: 5px; padding: 2px 8px; border: 1px solid; white-space: nowrap; }
.sx-clients .st.active { color: var(--ink-2); border-color: var(--line-2); background: var(--card-2); }
.sx-clients .st.booked, .sx-clients .st.due { color: var(--accent-deep); border-color: var(--line-2); background: var(--accent-bg); }
.sx-clients .st.atrisk { color: var(--down); border-color: var(--line-2); background: var(--card-2); }
.sx-clients .st.new { color: var(--ink-3); border-color: var(--line-2); background: transparent; }
.sx-clients .count { font-size: 12px; color: var(--ink-3); }
@media (max-width: 720px) { .sx-clients table.dir .hide-sm { display: none; } }
@media (max-width: 760px) { .sx-clients { padding: 18px 14px; } .sx-clients .fig-even { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* The owner's assistant (the how-it-works mirror): public/coachbubble.js's
   panel, persona "assistant", open. These are that module's own rules and
   tokens (it injects them as a <style>; this page does not load it), copied for
   the parts a still panel shows and scoped here. The ramp and the dither are
   read from the module's CSS, not retyped. Motion, the bubble, the scrim and the
   starter chips are left out: the panel is open, and a thread with history
   shows no starters. If the panel's look changes, change it here too. */
.sx-assist {
  --cb-black:#08090B; --cb-ink:#F2F4F7; --cb-ink-2:#CBD3DE;
  --cb-field:#18202A; --cb-field-edge:#7189A0; --cb-me:#2B4A6B; --cb-me-edge:#8CA5C0;
  --cb-ring:#8FA6BD; --cb-hair-onblack:#434D59; --cb-hair-onblue:#6B85A1;
  --cb-sheet-edge:#434D59; --cb-shadow:rgba(0,0,0,.72);
  --cb-ramp:linear-gradient(180deg,
    #08090B 0%, #08090B 55%, #0E151E 60.63%, #121D29 66.25%, #162332 71.88%,
    #1A293A 77.5%, #1C2D40 83.13%, #1F3246 88.75%, #22354B 94.38%, #243950 100%);
  --cb-dither:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)' opacity='.045'/%3E%3C/svg%3E");
  position: relative; height: 640px; overflow: hidden; background: #050607;
}
.sx-assist .as-device { position: absolute; left: 0; top: 0; width: 100%; height: 100%;
  display: flex; flex-direction: column; }
/* The owner's page, behind the open panel and dimmed by its scrim. */
.sx-assist .as-behind { flex: 0 0 auto; height: 52px; display: flex; align-items: center;
  padding: 0 18px; font-size: 19px; color: var(--ink); opacity: .26; }
.sx-assist .cb-sheet { flex: 1 1 auto; min-height: 0; position: relative; display: flex; flex-direction: column;
  border-radius: 26px 26px 0 0; background: var(--cb-black);
  box-shadow: 0 0 0 1px var(--cb-sheet-edge), 0 2px 8px -2px var(--cb-shadow), 0 20px 48px -24px var(--cb-shadow); }
.sx-assist .cb-sheet::before { content: ""; position: absolute; inset: 0; z-index: 0; border-radius: inherit;
  background-image: var(--cb-dither), var(--cb-ramp); background-repeat: repeat, no-repeat;
  background-size: 120px 120px, 100% 100%; pointer-events: none; }
.sx-assist .cb-grip { flex: 0 0 auto; padding: 9px 0 3px; display: grid; place-items: center; position: relative; z-index: 2; }
.sx-assist .cb-grip span { width: 38px; height: 5px; border-radius: 3px; background: var(--cb-ring); display: block; }
.sx-assist .cb-head { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; padding: 2px 14px 9px;
  border-bottom: 1px solid var(--cb-hair-onblack); position: relative; z-index: 2; }
.sx-assist .cb-title { font: 600 15px/1.25 var(--sans); color: var(--cb-ink); flex: 1; }
.sx-assist .cb-sub { font: 400 12.5px/1.3 var(--sans); color: var(--cb-ink-2); margin-top: 1px; }
.sx-assist .cb-x { width: 44px; height: 44px; margin-right: -10px; color: var(--cb-ink-2); display: grid; place-items: center; }
.sx-assist .cb-thread { flex: 1 1 auto; overflow: hidden; padding: 14px 14px 6px; display: flex; flex-direction: column;
  gap: 11px; position: relative; z-index: 2; }
.sx-assist .cb-msg { max-width: 88%; font: 400 15px/1.5 var(--sans); white-space: pre-wrap; overflow-wrap: break-word; }
.sx-assist .cb-msg.cb-me { align-self: flex-end; background: var(--cb-me); color: var(--cb-ink);
  border: 1px solid var(--cb-me-edge); border-radius: 16px 16px 5px 16px; padding: 9px 12px; }
.sx-assist .cb-msg.cb-coach { align-self: flex-start; color: var(--cb-ink); padding: 2px 0; }
.sx-assist .cb-form { flex: 0 0 auto; display: flex; gap: 8px; align-items: flex-end; padding: 9px 12px;
  border-top: 1px solid var(--cb-hair-onblue); position: relative; z-index: 2; }
.sx-assist .cb-input { flex: 1; font: 400 16px/1.35 var(--sans); color: var(--cb-ink-2); background: var(--cb-field);
  border: 1px solid var(--cb-field-edge); border-radius: 14px; padding: 11px 13px; min-height: 44px; }
.sx-assist .cb-send { flex: 0 0 auto; width: 44px; height: 44px; border-radius: 14px; background: var(--cb-ring);
  color: var(--cb-black); display: grid; place-items: center; }
/* In the room the screen takes the glass's own size. On a desktop that is a
   560px-wide document, wider than the real panel (392px), which would leave
   its 15px text small in the mirror; so, like the dashboard (a 360px phone
   document scaled into the glass), the panel is laid out at 400px and scaled
   to fill it. On a phone the glass's document is 360px and needs nothing. */
.scene-on .sx-assist { height: 100%; }
@media (min-width: 761px) {
  .scene-on .sx-assist .as-device { width: calc(100% / 1.4); height: calc(100% / 1.4);
    transform: scale(1.4); transform-origin: 0 0; }
}

/* ------------------------------------------------------------------ */
/* Scene mode (shop.js adds .scene-on to <html>)                      */
/* ------------------------------------------------------------------ */
.scene-on .sx-scene { height: 760vh; }
.scene-on .sx-sticky { position: sticky; top: 0; height: 100svh; }
.scene-on .sx-part[data-stage] { display: none; }
.scene-on .sx-nav {
  position: fixed; left: 0; right: 0; border-bottom-color: transparent;
  background: linear-gradient(180deg, color-mix(in srgb, var(--bg) 90%, transparent), transparent);
}
.scene-on .sx-frame {
  margin: 0; max-width: none; border: 0; border-radius: 0; box-shadow: none; overflow: hidden;
  backface-visibility: hidden;
}
/* Each frame is its own stacking context. Without this, mobile.css's sticky,
   z-indexed .m-top in the dashboard painted through every frame stacked above
   it in the same place. */
.scene-on .sx-frame { z-index: 0; isolation: isolate; }
.sx-scr .m-top { position: static; }
/* In the scene the screen's content can scroll inside its frame (shop.js moves
   .sx-scr up, a transform, to bring a chart or a table into view). */
.scene-on .sx-frame .sx-scr { max-height: none; overflow: visible; }
.scene-on .sx-scr [data-count], .scene-on .sx-clients tbody tr, .scene-on .sx-assist .cb-msg { will-change: transform, opacity; }

/* ------------------------------------------------------------------ */
/* The rest of the page                                               */
/* ------------------------------------------------------------------ */
.sx-band { padding: 88px 0; border-top: 1px solid var(--line); }
.sx-body { color: var(--ink-2); font-size: 16px; line-height: 1.65; max-width: 52ch; margin: 0; }
.sx-body b { color: var(--ink); }
.sx-split { display: grid; grid-template-columns: 1fr 1fr; gap: 56px; align-items: start; }
.sx-steps { list-style: none; margin: 0; padding: 0; }
.sx-steps li { display: grid; grid-template-columns: 44px 1fr; gap: 4px 12px; padding: 18px 0; border-top: 1px solid var(--line); }
.sx-steps .n { color: var(--accent-deep); font-weight: 600; font-size: 13px; grid-row: span 2; }
.sx-steps .t { color: var(--ink); font-weight: 600; font-size: 16px; }
.sx-steps .d { color: var(--ink-2); line-height: 1.6; font-size: 14px; }
.sx-pay { padding: 20px 22px; }
.sx-pay .pay-hd { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 6px; }
.sx-pay .pay-hd .t { font-weight: 600; color: var(--ink); }
.sx-pay .pay-hd .w { color: var(--ink-3); font-size: 13px; }
.sx-pay .pay-row { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; padding: 14px 0; border-top: 1px solid var(--line); }
.sx-pay .nm { font-weight: 600; color: var(--ink); }
.sx-pay .pl { color: var(--ink-3); font-size: 13px; margin-top: 3px; line-height: 1.45; }
.sx-pay .pfig { font-family: "CS Separators", var(--sans); font-weight: 600; color: var(--ink); white-space: nowrap; }
.sx-pay .neg { color: var(--down); }
.sx-pay .short { margin-left: 8px; font-size: 11px; font-weight: 700; letter-spacing: .08em; }
.sx-pay .none { color: var(--ink-3); font-size: 13px; text-align: right; max-width: 22ch; }
.sx-pay .pay-cap { color: var(--ink-3); font-size: 13px; line-height: 1.55; margin: 12px 0 0; }
.sx-log > div { display: grid; grid-template-columns: 110px 1fr; gap: 12px; padding: 12px 0; border-top: 1px solid var(--line); }
.sx-log time { color: var(--ink-3); font-size: 13px; }
.sx-log p { margin: 0; color: var(--ink); line-height: 1.5; }
.sx-log .log-cap { display: block; color: var(--ink-3); font-size: 13px; line-height: 1.55; margin-top: 14px; }
.sx-foot { border-top: 1px solid var(--line); padding: 36px 0 64px; }
.sx-foot .row { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; }
.sx-foot .sp { flex: 1; }
.sx-foot .row > a:not(.sx-brand) { color: var(--ink-2); text-decoration: none; font-size: 14px; min-height: 44px; display: inline-flex; align-items: center; }
.sx-foot .footnote { color: var(--ink-3); font-size: 13px; line-height: 1.6; max-width: 60ch; margin: 18px 0 0; }
@media (max-width: 900px) {
  .sx-split { grid-template-columns: 1fr; gap: 28px; }
}
@media (max-width: 560px) {
  .sx-log > div { grid-template-columns: 1fr; gap: 4px; }
  .sx-part, .sx-band { padding: 56px 0; }
}

/* ------------------------------------------------------------------ */
/* Type craft, for the page's own words (not the product's screens)   */
/* ------------------------------------------------------------------ */
.sx-hero :is(h1, h2), .sx-cap :is(h1, h2), .sx-band :is(h2, h3), .sx-h2 { text-wrap: balance; }
.sx-hero p, .sx-cap p, .sx-band :is(p, li), .sx-foot p { text-wrap: pretty; }
/* Measure: nothing the page itself says runs past about 60 characters. */
.sx-log p, .sx-log .log-cap, .sx-pay .pay-cap, .sx-steps .d { max-width: 60ch; }
/* Space above a heading, little below: an eyebrow mid-column opens a new
   thought; a section heading sits close to what it introduces. */
.sx-band .sx-eyebrow:not(:first-child) { margin-top: 44px; }
.sx-h2 { margin-bottom: 12px; }

/* Figures: tabular, so counting numbers hold still and columns line up. Every
   one is paired with app.css's "CS Separators" face, as app.css requires of
   every tabular element (tools/uirender/v7num.cjs checks the pairing). */
.sx-scr :is(.fig .v, .fig .d, .mrev .v, .mrev .d, .v3-cmp, .tdisc .v, .leg .vl, .crow b,
            .count, td.num, td.muted, .v3-row .sub, .m-row .sub),
.sx-scr svg text, .sx-pay .pfig, .sx-pay .pl {
  font-family: "CS Separators", var(--sans);
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------------ */
/* The static page (reduced motion, no JS, a blocked CDN)             */
/* ------------------------------------------------------------------ */
/* This is the page most people who opt out of motion will read, so it is laid
   out for reading, not as a leftover. On a wide screen the two portrait
   screens sit beside their captions instead of under them with half the row
   empty, and the caption stays in view while its screen scrolls past. */
@media (min-width: 1000px) {
  html:not(.scene-on) .sx-part:is([data-stage="clients"], [data-stage="how"]) .sx-wrap {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 560px); gap: 72px; align-items: start;
  }
  html:not(.scene-on) .sx-part:is([data-stage="clients"], [data-stage="how"]) .sx-cap { position: sticky; top: 120px; }
  html:not(.scene-on) .sx-part:is([data-stage="clients"], [data-stage="how"]) .sx-frame { margin-top: 0; }
}
/* The dashboard is cut at 900px; let it fade out rather than stop at a hard
   edge mid-card. */
html:not(.scene-on) .sx-frame-dash .sx-scr {
  -webkit-mask-image: linear-gradient(180deg, #000 82%, transparent);
  mask-image: linear-gradient(180deg, #000 82%, transparent);
}

/* ------------------------------------------------------------------ */
/* The photoreal stage (shopfootage.js)                               */
/* ------------------------------------------------------------------ */
/* Layers inside #gl, back to front: the aisle clip's poster, the aisle clip,
   the turn clip, and the plate (the turn's last frame) with the screens on
   its glass. Only opacity, visibility and transform change. */
.sf { position: absolute; inset: 0; overflow: hidden; background: #050608; }
.sf-layer { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.sf-novideo .sf-video { visibility: hidden !important; }
/* The plate is laid out at its own pixel size; shopfootage.js moves it like a
   camera would. The glass is a box mapped onto the mirror's corners. */
.sf-stage { position: absolute; left: 0; top: 0; transform-origin: 0 0; opacity: 0; visibility: hidden;
            will-change: transform; }   /* see setZ() in shopfootage.js */
.sf-plate { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.sf-glass { position: absolute; left: 0; top: 0; overflow: hidden; transform-origin: 0 0; background: #07080a; }
.sf-screen { position: absolute; left: 0; top: 0; transform-origin: 0 0; }
.sf-frame { border: 0; display: block; background: transparent; }
.sf-mounted { position: absolute; left: 0; top: 0; }
/* BEHIND GLASS. The room the mirror faces, faint and soft, laid over the
   screen; a cool sheen across the face; and the glass darkening toward its
   edges. All of it above the screen as light, none of it a filter on the
   screen itself, so the text stays sharp at any zoom. */
.sf-reflect { position: absolute; inset: -6%; width: 112%; height: 112%; object-fit: cover; pointer-events: none;
  transform: scaleX(-1); filter: blur(10px) saturate(.6); opacity: .10; mix-blend-mode: screen; }
.sf-glass::after { content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(115deg, rgba(255,255,255,.07) 0%, rgba(255,255,255,0) 34%,
              rgba(255,255,255,0) 66%, rgba(255,255,255,.03) 100%); }
.sf-glass-edge { position: absolute; inset: 0; pointer-events: none;
  box-shadow: inset 0 0 40px 6px rgba(0,0,0,.55), inset 0 0 0 2px rgba(0,0,0,.6); }
/* The onboarding steps are shorter than the glass: centre them in it. */
.sf-mounted[data-frame="how"] { display: flex; flex-direction: column; justify-content: center; }
.sf-smear { visibility: hidden; opacity: 0; pointer-events: none; }
