/* ──────────────────────────────────────────────────────────
   CNL · marketing pages (site.css)
   Loaded AFTER legal.css — reuses its tokens, nav.top, .brand,
   footer, and .btn-primary. Adds the editorial marketing
   components: full nav links, page heroes, § sections, steps,
   feature rows + mini mocks, pricing card, trades, FAQ, the
   card-reader layout, and CTA bands.
   ────────────────────────────────────────────────────────── */

/* ── Nav (full links) ────────────────────────────────── */
.nav-links {
  display: flex; align-items: center; gap: 22px;
  font-size: 14px;
}
.nav-links a { color: var(--muted); transition: color 120ms; }
.nav-links a:hover,
.nav-links a.current { color: var(--ink); }
.nav-pill {
  background: var(--bg-card); border: 1px solid var(--rule-strong);
  padding: 6px 12px; font-size: 13px; border-radius: 6px;
  color: var(--muted);
}
.nav-pill:hover { color: var(--ink); border-color: var(--hover-border); }
/* .nav-cta's base rule moved to legal.css so the legal shell can carry the
   pill too (/contact). Written as .nav-links a.nav-cta so this beats
   `.nav-links a` and its :hover on specificity — in the light theme the
   button is dark, and the generic muted link color would vanish into it. */
.nav-links a.nav-cta, .nav-links a.nav-cta:hover { color: var(--accent-ink); }

/* ── Features dropdown ───────────────────────────────── */
.nav-item { display: inline-flex; align-items: center; }
.nav-item.has-sub { position: relative; }
.nav-item.has-sub > a { display: inline-flex; align-items: center; gap: 5px; }
.nav-item.has-sub > a .caret {
  font-size: 9px; line-height: 1; color: var(--muted-2);
  transition: transform 140ms ease, color 120ms;
}
.nav-item.has-sub:hover > a .caret,
.nav-item.has-sub:focus-within > a .caret { color: var(--ink); transform: rotate(180deg); }
/* Transparent bridge so the cursor keeps hover between link and panel. */
.nav-item.has-sub::after {
  content: ''; position: absolute; left: 0; right: 0; top: 100%; height: 10px;
}
.nav-sub {
  position: absolute; top: calc(100% + 8px); left: 50%;
  transform: translateX(-50%) translateY(-4px);
  min-width: 184px;
  display: flex; flex-direction: column; padding: 6px;
  background: var(--bg-card);
  border: 1px solid var(--rule-strong); border-radius: 8px;
  box-shadow: var(--shadow-sm);
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity 140ms ease, transform 140ms ease, visibility 140ms;
  z-index: 60;
}
.nav-item.has-sub:hover .nav-sub,
.nav-item.has-sub:focus-within .nav-sub {
  opacity: 1; visibility: visible; pointer-events: auto;
  transform: translateX(-50%) translateY(0);
}
.nav-sub a {
  display: block; padding: 8px 12px; font-size: 13.5px;
  color: var(--muted); border-radius: 5px; white-space: nowrap;
  transition: color 120ms, background 120ms;
}
.nav-sub a:hover, .nav-sub a:focus { color: var(--ink); background: var(--bg); }

/* Hamburger toggle — hidden on desktop, revealed at the mobile breakpoint. */
.nav-toggle {
  display: none;
  flex-direction: column; justify-content: center; gap: 5px;
  width: 40px; height: 40px; padding: 0;
  margin: -8px -8px -8px 0;           /* bigger tap target, no layout shift */
  background: transparent; border: 0; cursor: pointer;
}
.nav-toggle span {
  display: block; width: 22px; height: 1.5px; margin: 0 auto;
  background: var(--ink); border-radius: 2px;
  transition: transform 180ms ease, opacity 140ms ease;
}
.nav-toggle.open span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.nav-toggle.open span:nth-child(2) { opacity: 0; }
.nav-toggle.open span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

@media (max-width: 820px) {
  .nav-toggle { display: flex; }
  /* Collapse the link row into a full-width dropdown sheet under the nav.
     Solid opaque background so page content never shows through it. */
  .nav-links {
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    padding: 6px 24px 18px;
    background: var(--bg);
    border-bottom: 1px solid var(--rule);
    box-shadow: var(--shadow-sm);
    max-height: calc(100vh - 64px); overflow-y: auto;
    display: none;
  }
  .nav-links.open { display: flex; }
  .nav-links a {
    text-align: left;
    font-size: 16px; padding: 14px 2px;
    border-bottom: 1px solid var(--rule);
  }
  /* Manage + Start become full-width buttons at the foot of the sheet. */
  .nav-pill, .nav-cta {
    text-align: center; padding: 12px; font-size: 15px; border-bottom: 0;
  }
  .nav-pill { margin-top: 12px; }
  .nav-cta { margin-top: 8px; }

  /* Features submenu: shown inline & indented under Features (no hover on touch). */
  .nav-item, .nav-item.has-sub { display: block; position: static; }
  .nav-item.has-sub::after { display: none; }
  .nav-item.has-sub > a { display: flex; justify-content: space-between; }
  .nav-sub {
    position: static; transform: none;
    opacity: 1; visibility: visible; pointer-events: auto;
    display: flex; flex-direction: column;
    min-width: 0; padding: 0; margin: 0;
    background: transparent; border: 0; border-radius: 0; box-shadow: none;
  }
  .nav-sub a {
    padding: 12px 2px 12px 18px; font-size: 15px;
    color: var(--muted); border-bottom: 1px solid var(--rule);
    white-space: normal;
  }
}

/* ── Buttons ─────────────────────────────────────────── */
.btn-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.btn-ghost {
  display: inline-flex; align-items: center; gap: 8px;
  background: transparent; color: var(--ink);
  padding: 11px 18px; font-size: 14px; font-weight: 500;
  border: 1px solid var(--rule-strong); border-radius: 8px;
  transition: border-color 120ms, background 120ms;
  cursor: pointer; font-family: var(--sans);
}
.btn-ghost:hover { border-color: var(--hover-border); background: var(--hover-bg); }
.btn-primary.lg, .btn-ghost.lg { padding: 13px 22px; font-size: 14.5px; }

/* ── Page hero (marketing) ───────────────────────────── */
.mhero {
  position: relative; overflow: hidden;
  border-bottom: 1px solid var(--rule);
  padding: 88px 0 72px;
}
.mhero::before {
  content: ''; position: absolute; inset: 0;
  background-image:
    linear-gradient(to right, var(--grid-line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px);
  background-size: 56px 56px;
  -webkit-mask-image: radial-gradient(ellipse 75% 70% at 40% 35%, #000 25%, transparent 75%);
          mask-image: radial-gradient(ellipse 75% 70% at 40% 35%, #000 25%, transparent 75%);
  pointer-events: none;
}
.mhero .inner { position: relative; max-width: 920px; }
.mk-num {
  font-family: var(--mono); font-size: 11px;
  color: var(--muted-2); letter-spacing: 0; margin: 0 0 26px;
}
.mk-eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--mono); font-size: 11.5px; color: var(--muted);
  border: 1px solid var(--rule-strong); background: var(--bg-card);
  padding: 5px 12px; border-radius: 999px; margin-bottom: 24px;
  letter-spacing: 0;
}
.mk-eyebrow .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--ok); }
.mhero h1 {
  font-family: var(--sans); font-weight: 500;
  font-size: clamp(32px, 4.4vw, 50px); line-height: 1.04;
  letter-spacing: -0.03em; margin: 0; color: var(--ink);
  max-width: 18ch; text-wrap: balance;
}
.mhero h1 .serif {
  color: var(--muted);
}
.mhero .lede {
  font-size: 16.5px; line-height: 1.58; color: var(--muted);
  max-width: 54ch; margin: 22px 0 0;
}
.mhero .btn-row { margin-top: 36px; }

/* ── Section (§) ─────────────────────────────────────── */
.msec {
  position: relative;
  border-bottom: 1px solid var(--rule);
  padding: 88px 0;
}
.msec.tight { padding: 64px 0; }
.msec-num {
  position: absolute; top: 26px; left: 24px;
  font-family: var(--mono); font-size: 11px; color: var(--muted-2);
  letter-spacing: 0; pointer-events: none;
}
.msec-head { max-width: 760px; margin: 0 0 48px; }
.msec-kicker {
  font-family: var(--mono); font-size: 11px; color: var(--muted-2);
  letter-spacing: 0; margin: 0 0 16px;
}
/* On mobile the absolute left-margin marker collides with the kicker where both
   exist — hide the marker only on those sections (keep it where it's the sole one). */
@media (max-width: 820px) {
  .msec:has(.msec-kicker) .msec-num { display: none; }
}
.msec h2 {
  font-family: var(--sans); font-weight: 500;
  font-size: clamp(24px, 2.8vw, 34px); line-height: 1.1;
  letter-spacing: -0.025em; margin: 0; color: var(--ink);
  max-width: 20ch; text-wrap: balance;
}
.msec h2 .dim { color: var(--muted); }
.msec h2 .serif { color: var(--muted); }
.msec-head .lede {
  font-size: 16px; line-height: 1.6; color: var(--muted);
  max-width: 56ch; margin: 18px 0 0;
}

/* ── Steps ───────────────────────────────────────────── */
.steps {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px;
  background: var(--rule); border: 1px solid var(--rule);
  border-radius: 12px; overflow: hidden;
}
.step {
  background: var(--bg); padding: 32px 28px 36px;
  display: flex; flex-direction: column; gap: 14px;
}
.step .n {
  font-family: var(--mono); font-size: 12px;
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--ink); color: var(--bg);
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 500;
}
.step h3 {
  font-family: var(--sans); font-weight: 500; font-size: 18px;
  letter-spacing: -0.015em; margin: 0; color: var(--ink);
}
.step p { font-size: 14px; line-height: 1.6; color: var(--muted); margin: 0; }
.step .tag {
  font-family: var(--mono); font-size: 11px; color: var(--ok);
  margin-top: auto; padding-top: 8px;
}
@media (max-width: 760px) {
  .steps { grid-template-columns: 1fr; }
}

/* ── Feature rows (detail) ───────────────────────────── */
.frow {
  display: grid; grid-template-columns: 1fr 1fr; gap: 56px;
  align-items: center;
  padding: 56px 0;
  border-top: 1px solid var(--rule);
}
.frow:first-of-type { border-top: 0; }
.frow.reverse .frow-copy { order: 2; }
.frow.headline {
  grid-template-columns: 1fr; gap: 36px;
  padding: 8px 0 64px;
  border-top: 0;
}
.frow-kicker {
  font-family: var(--mono); font-size: 11px; color: var(--muted-2);
  letter-spacing: 0; margin: 0 0 16px;
  display: flex; align-items: center; gap: 10px;
}
.frow-kicker .badge {
  font-family: var(--mono); font-size: 10px; color: var(--ok);
  background: var(--ok-bg); border: 1px solid var(--ok-border);
  padding: 2px 8px; border-radius: 999px; letter-spacing: 0.04em;
  text-transform: uppercase;
}
/* .frow.headline's heading is an h2 on /features (first heading after the
   h1 — an h3 there broke the document outline); the spokes' later rows stay
   h3. Same look either way. */
.frow h3, .frow.headline h2 {
  font-family: var(--sans); font-weight: 500;
  font-size: clamp(20px, 2vw, 25px); line-height: 1.14;
  letter-spacing: -0.02em; margin: 0 0 14px; color: var(--ink);
  max-width: 18ch;
}
.frow.headline h3, .frow.headline h2 { font-size: clamp(23px, 2.6vw, 31px); max-width: 16ch; }
.frow p {
  font-size: 15.5px; line-height: 1.62; color: var(--muted);
  margin: 0; max-width: 46ch;
}
.frow .frow-link {
  display: inline-flex; align-items: center; gap: 8px;
  margin-top: 20px; font-family: var(--mono); font-size: 12.5px;
  color: var(--ink); border-bottom: 1px solid var(--rule-strong);
  padding-bottom: 3px;
}
.frow .frow-link:hover { border-color: var(--ink); }
.frow .frow-link .arrow { transition: transform 160ms; }
.frow .frow-link:hover .arrow { transform: translateX(3px); }

/* mock panel shell */
.mock {
  border: 1px solid var(--rule-strong); background: var(--bg-card);
  border-radius: 12px; padding: 24px; position: relative; overflow: hidden;
  min-height: 220px;
}
.frow.headline .mock { min-height: 280px; padding: 0; }

/* mock: mini browser (website/domain). Flex column so .mb-body grows to fill
   .mock's min-height — otherwise the dark #0a0a0a shell shows through as a
   stray band under the cream body when the content comes up short. */
/* The shell is dark hardware in both themes (see --shell-* in legal.css),
   so the chrome's borders and URL pill are pinned to the device's own
   values — the same fixed treatment as the landing hero's .hv-urlpill.
   Page tokens here would paint a cream pill on a black bezel in light. */
.mock-browser { padding: 0; background: var(--shell-bg); border-color: #262626; display: flex; flex-direction: column; }
.mb-chrome {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 14px; border-bottom: 1px solid #1c1c1c;
  background: var(--shell-chrome);
  flex-shrink: 0; /* keep the chrome bar at natural height inside .mock-browser */
}
.mb-dots { display: flex; gap: 6px; }
.mb-dots span { width: 9px; height: 9px; border-radius: 50%; background: var(--shell-dot); }
.mb-url {
  flex: 1; text-align: center;
  font-family: var(--mono); font-size: 11.5px; color: #8f8a84;
  background: #050505; border: 1px solid #262626;
  border-radius: 6px; padding: 4px 12px;
}
.mb-url b { color: #ededed; font-weight: 500; }
.mb-body {
  background: #f3e9d8; color: #2a1f15; padding: 30px 32px 34px;
  font-family: var(--serif);
  /* Grow into leftover space so the cream body fills the card to the bottom.
     Deliberately flex-grow (basis stays auto), not `flex: 1`: with basis auto
     the body's base size is its real content height, so when content is taller
     than the card's min-height the card grows instead of clipping the Book CTA
     under .mock's overflow:hidden. */
  flex-grow: 1;
}
.mb-eyebrow {
  font-family: var(--sans); font-size: 9px; letter-spacing: 0.28em;
  text-transform: uppercase; color: #7a1d2e; margin-bottom: 12px;
}
.mb-title { font-size: 30px; line-height: 1.05; font-weight: 400; font-style: italic; color: #2a1f15; margin: 0 0 10px; }
.mb-sub { font-size: 13px; color: #6a4a3a; font-style: italic; margin: 0 0 18px; }
.mb-cta {
  font-family: var(--sans); font-size: 9.5px; letter-spacing: 0.2em;
  text-transform: uppercase; color: #7a1d2e;
  border: 1px solid #7a1d2e; padding: 7px 14px; display: inline-block;
}

/* Landing feature 01 — an authentic scaled preview of the REAL demo site
   (/uploads/home.html, "Salon Felicità"), framed like a browser screenshot. Fills
   below the ~40px chrome. The iframe renders at desktop width (250% of the frame) and
   is scaled to fit the frame width exactly; the generous height top-crops it like a
   screenshot. Non-interactive. */
.mb-preview {
  position: absolute; left: 0; right: 0; top: 40px; bottom: 0;
  overflow: hidden; background: #fff;
}
.mb-preview iframe {
  width: 250%; height: 1500px; border: 0;
  transform: scale(0.4); transform-origin: top left;
  pointer-events: none;
}

/* mock: calendar heatmap */
.mock-cal { display: grid; grid-template-columns: repeat(7, 1fr); gap: 5px; align-content: center; }
.mock-cal i { aspect-ratio: 1; border-radius: 3px; background: var(--cal-0); display: block; }
.mock-cal i.l1 { background: var(--cal-1); } .mock-cal i.l2 { background: var(--cal-2); }
.mock-cal i.l3 { background: var(--cal-3); } .mock-cal i.l4 { background: var(--cal-4); }

/* mock: charge list */
.mock-charge { display: flex; flex-direction: column; gap: 8px; justify-content: center; }
.mc-row {
  display: flex; justify-content: space-between; align-items: center;
  border: 1px solid var(--rule); border-radius: 6px; padding: 10px 12px;
  font-family: var(--mono); font-size: 11px;
}
.mc-row .who { color: var(--ink); }
.mc-row .who small { display: block; color: var(--muted); font-size: 9.5px; margin-top: 2px; }
.mc-btn { background: var(--accent); color: var(--accent-ink); padding: 5px 10px; border-radius: 4px; font-size: 10px; font-weight: 500; }
.mc-btn.paid { background: var(--hover-bg); color: var(--muted); }

/* mock: SMS bubbles */
.mock-sms { display: flex; flex-direction: column; gap: 10px; justify-content: center; }
.sms {
  max-width: 80%; font-size: 12.5px; line-height: 1.45;
  padding: 10px 14px; border-radius: 14px;
}
.sms.them { align-self: flex-start; background: var(--hover-bg); color: var(--ink); border-bottom-left-radius: 4px; }
.sms.you  { align-self: flex-end; background: var(--accent); color: var(--accent-ink); border-bottom-right-radius: 4px; }
.sms small { display: block; font-family: var(--mono); font-size: 9.5px; opacity: 0.6; margin-top: 4px; }

/* mock: bars — needs a definite height (not just .mock's min-height) so the
   percentage heights on the <i> bars have something to resolve against. 220px
   border-box matches .mock's min-height exactly, so the card renders the same
   size as every other .mock. */
.mock-bars { display: flex; align-items: flex-end; gap: 6px; height: 220px; }
.mock-bars i { flex: 1; background: var(--bar); border-radius: 2px 2px 0 0; display: block; }
.mock-bars i.d { background: var(--bar-hi); }

@media (max-width: 760px) {
  .frow, .frow.reverse { grid-template-columns: 1fr; gap: 28px; }
  .frow.reverse .frow-copy { order: 0; }
}

/* ── Pricing card ────────────────────────────────────── */
.price-wrap { display: flex; flex-direction: column; align-items: center; }
.price-card-mk {
  width: 100%; max-width: 440px;
  border: 1px solid var(--rule-strong);
  background: linear-gradient(180deg, var(--bg-card), var(--bg-elev));
  border-radius: 16px; padding: 32px 32px 28px;
}
.price-card-mk .pc-name {
  font-family: var(--mono); font-size: 12px; color: var(--muted);
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 20px;
}
.price-card-mk .pc-tag {
  font-family: var(--mono); font-size: 10.5px; color: var(--ok);
  background: var(--ok-bg); border: 1px solid var(--ok-border);
  padding: 3px 9px; border-radius: 999px;
}
.price-card-mk .pc-amount {
  font-size: 40px; font-weight: 500; letter-spacing: -0.03em;
  color: var(--ink); line-height: 1; margin-bottom: 6px;
  font-variant-numeric: tabular-nums;
}
.price-card-mk .pc-amount .per { font-size: 15px; color: var(--muted); font-weight: 400; letter-spacing: 0; margin-left: 6px; }
.price-card-mk .pc-meta { font-size: 14px; color: var(--muted); margin: 0 0 26px; line-height: 1.5; }
.price-card-mk .pc-list { list-style: none; padding: 0; margin: 0 0 28px; }
.price-card-mk .pc-list li {
  font-size: 14px; padding: 10px 0; color: var(--ink);
  border-top: 1px solid var(--rule);
  display: flex; gap: 10px; align-items: flex-start;
}
.price-card-mk .pc-list li::before { content: '✓'; color: var(--ok); font-size: 12px; line-height: 1.5; }
.price-card-mk .price-cta { width: 100%; justify-content: center; }
.price-note {
  margin: 22px auto 0; max-width: 440px; text-align: center;
  font-size: 12.5px; color: var(--muted-2); line-height: 1.6;
}

/* honest-math breakdown */
.math {
  max-width: 620px; margin: 40px auto 0;
  border: 1px solid var(--rule); border-radius: 12px; overflow: hidden;
}
.math-row {
  display: grid; grid-template-columns: 1fr auto; gap: 16px;
  padding: 16px 22px; border-top: 1px solid var(--rule);
  align-items: baseline;
}
.math-row:first-child { border-top: 0; }
.math-row .ml { font-size: 14px; color: var(--ink); }
.math-row .ml small { display: block; color: var(--muted); font-size: 12px; margin-top: 3px; }
.math-row .mr { font-family: var(--mono); font-size: 14px; color: var(--ink); text-align: right; white-space: nowrap; }
.math-row .mr.zero { color: var(--ok); }

/* ── Trades / who it's for ───────────────────────────── */
.trades {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px;
}
.trade {
  border: 1px solid var(--rule-strong); background: var(--bg-card);
  border-radius: 12px; padding: 28px 26px;
  display: flex; flex-direction: column; gap: 10px;
  min-height: 160px;
}
.trade .tn { font-family: var(--mono); font-size: 11px; color: var(--muted-2); }
.trade h3 {
  font-family: var(--sans); font-weight: 500; font-size: 22px;
  letter-spacing: -0.02em; margin: 0; color: var(--ink);
}
.trade p { font-size: 13.5px; line-height: 1.55; color: var(--muted); margin: 0; }
.trades-also {
  margin: 24px 0 0; font-size: 15px; color: var(--muted); line-height: 1.6;
}
.trades-also strong { color: var(--ink); font-weight: 500; }
@media (max-width: 760px) { .trades { grid-template-columns: 1fr; } }

/* ── Wedge grid ──────────────────────────────────────── */
.wedge {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px;
  background: var(--rule); border: 1px solid var(--rule);
  border-radius: 12px; overflow: hidden;
}
.wedge .w {
  background: var(--bg); padding: 26px 22px;
  display: flex; flex-direction: column; gap: 10px;
}
.wedge .w .wn { font-family: var(--mono); font-size: 11px; color: var(--muted-2); }
.wedge .w h4 { font-family: var(--sans); font-weight: 500; font-size: 15.5px; letter-spacing: -0.01em; margin: 0; color: var(--ink); }
.wedge .w p { font-size: 13px; line-height: 1.55; color: var(--muted); margin: 0; }
@media (max-width: 820px) { .wedge { grid-template-columns: 1fr 1fr; } }
@media (max-width: 480px) { .wedge { grid-template-columns: 1fr; } }

/* ── Card reader page ────────────────────────────────── */
.reader {
  display: grid; grid-template-columns: 1fr 1fr; gap: 56px; align-items: center;
}
.reader-visual {
  border: 1px solid var(--rule-strong);
  background: radial-gradient(ellipse 80% 70% at 50% 30%, var(--bg-card), var(--bg-elev));
  border-radius: 16px; padding: 24px; height: 430px;
  width: 100%; max-width: 330px; margin: 0 auto;
  display: flex; align-items: center; justify-content: center;
}

/* ── Reader product photo — the plate's content (templates/_reader_visual.html
   + static/img/README-reader-asset.md; the CSS-drawn fallback reader that
   used to fill the plate is deleted — the shipped assets are committed, so
   the photo is the permanent state).
   The photo is a CUTOUT (transparent background), so the .reader-visual plate
   is the background in both themes: its gradient is built from theme tokens
   keyed off html[data-theme], which the pre-paint boot script always resolves
   (OS preference on first visit, the L|D toggle thereafter) — so one asset
   follows the toggle live with no prefers-color-scheme query and no second
   image. The plate has a FIXED height (430px), and the img carries
   width/height attributes, so neither the photo appearing nor its load can
   shift layout. */
.reader-photo {
  margin: 0; position: relative;
  align-self: stretch; flex: 1 1 auto; min-width: 0;
  display: flex; align-items: center; justify-content: center;
}
.reader-photo picture { display: contents; }
.reader-photo img {
  max-width: 100%; max-height: 100%; width: auto; height: auto;
  /* grounds the cutout on the plate; overridden per theme below */
  filter: drop-shadow(0 18px 32px rgba(28,24,20,0.30));
}
/* Dark: a black device on a near-black plate needs separation — a deeper
   shadow plus a faintly lifted plate so the silhouette reads. [data-theme] is
   the single theme authority here (see note above), so this follows the L|D
   toggle instantly, not just the OS setting. */
:root[data-theme="dark"] .reader-photo img {
  filter: drop-shadow(0 18px 36px rgba(0,0,0,0.75)) drop-shadow(0 0 24px rgba(255,255,255,0.05));
}
:root[data-theme="dark"] .reader-visual.has-photo {
  background: radial-gradient(ellipse 80% 70% at 50% 30%, #171717, var(--bg-elev));
}

/* Tip-prompt overlay ($48.00 / Add a tip? / 18% 20% 25%) — OFF by default
   (READER_PHOTO_TIP_OVERLAY, config.py): the shipped photo (Stripe's own
   render of the WisePOS E) has a blank screen, but a synthetic prompt drawn
   onto it read worse than the clean device; this panel waits for a live shot
   that would carry it honestly. Styled as the device's own lit white screen
   (literal colors — a device screen is not theme-tinted), so it reads
   correctly on both page themes.

   GEOMETRY. The render shows the device at a three-quarter angle, so its
   screen is a perspective quadrilateral, not an upright rectangle — a flat
   translated panel would visibly float over the device. The panel is laid out
   flat at a comfortable design size (the local box below) and then mapped
   onto the lit display area with a
   matrix3d homography computed from the display's four measured corners:
   TL(74.0,128.7) TR(160.1,115.7) BL(142.0,294.3) BR(250.0,270.3) in the
   280×373.3 CSS px the rendered image occupies (the display, not the outer
   glass panel — the glass keeps its dark margin around the lit screen, which
   is exactly how the real device draws this prompt). The matrix bakes in the
   panel's position (its translation column), scale (~0.65) and the differing
   edge angles the perspective produces.

   Tuning after an asset re-crop: --tip-dx/--tip-dy nudge the panel along the
   SCREEN PLANE (local px before the mapping — +x slides toward the device's
   right edge, +y toward its chin); --tip-scale grows/shrinks it about its
   center. Recompute the matrix itself only if the device is re-photographed
   at a different angle. */
.reader-photo-tip {
  --tip-dx: 0px;    /* nudge along the screen's own x-axis */
  --tip-dy: 0px;    /* nudge along the screen's own y-axis */
  --tip-scale: 1;   /* grow/shrink about the panel center */
  position: absolute; left: 0; top: 0;
  width: 132px; height: 272px;   /* local design box, pre-transform */
  transform-origin: 0 0;
  transform:
    matrix3d(0.695032, -0.066881, 0, 0.000269,
             0.128557, 0.357345, 0, -0.000855,
             0, 0, 1, 0,
             74.0, 128.6666, 0, 1)
    translate(calc(var(--tip-dx) + 66px), calc(var(--tip-dy) + 136px))
    scale(var(--tip-scale))
    translate(-66px, -136px);   /* ± half the local box: scale acts about center */
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px; padding: 16px 10px;
  /* A whisper of translucency + a diagonal sheen: the render's own screen
     lighting shows through, so the panel reads as the glass lighting up
     rather than a sticker over it. */
  background:
    linear-gradient(160deg, rgba(255,255,255,0.35), rgba(255,255,255,0) 45%),
    rgba(251,251,252,0.92);
  border-radius: 5px; color: #1a1a1a;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,0.28);
  pointer-events: none;
}
.reader-photo-tip .amt { font-family: var(--sans); font-weight: 600; font-size: 26px; letter-spacing: -0.02em; }
.reader-photo-tip .tip { font-family: var(--mono); font-size: 10px; letter-spacing: 0.1em; color: #777; text-transform: uppercase; }
.reader-photo-tip .tip-row { display: flex; gap: 5px; margin-top: 2px; }
.reader-photo-tip .tip-row span { font-family: var(--mono); font-size: 9.5px; border: 1px solid #635bff; color: #635bff; padding: 3px 5px; border-radius: 4px; }

.reader-specs { list-style: none; padding: 0; margin: 24px 0 0; }
.reader-specs li {
  padding: 18px 0; border-top: 1px solid var(--rule);
  display: grid; grid-template-columns: 28px 1fr; gap: 16px; align-items: start;
}
.reader-specs li:first-child { border-top: 0; }
.reader-specs .ic {
  width: 28px; height: 28px; border-radius: 7px;
  border: 1px solid var(--rule-strong); background: var(--bg-card);
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; color: var(--ink);
}
.reader-specs h3 { font-family: var(--sans); font-weight: 500; font-size: 15.5px; letter-spacing: -0.01em; margin: 0 0 4px; color: var(--ink); }
.reader-specs p { font-size: 13.5px; line-height: 1.55; color: var(--muted); margin: 0; }
.reader-cta-row { margin-top: 28px; }
.reader-optional { margin-top: 16px; font-size: 13px; color: var(--muted-2); font-style: italic; }

/* buy confirmation */
.buy-confirm {
  display: none; margin-top: 28px;
  border: 1px solid var(--ok-border); background: var(--ok-bg); border-radius: 12px;
  padding: 22px 24px;
}
.buy-confirm.show { display: block; }
.buy-confirm .ok { font-family: var(--mono); font-size: 11px; color: var(--ok); margin: 0 0 8px; }
.buy-confirm h3 { font-family: var(--sans); font-weight: 500; font-size: 17px; margin: 0 0 6px; color: var(--ink); letter-spacing: -0.015em; }
.buy-confirm p { font-size: 13.5px; color: var(--muted); line-height: 1.6; margin: 0; }
@media (max-width: 820px) { .reader { grid-template-columns: 1fr; gap: 36px; } }

/* ── Tip calculator (§ 03, /card-readers) ────────────────
   Stateless by design: no cookie, no storage, nothing leaves
   the page. Ships with the HTML `hidden` attribute and is
   revealed by its script, so with JS off the section is pure
   prose and no dead form renders — which is why there are no
   no-JS fallback styles here. Inputs reuse .field/.field
   input[type="text"] from legal.css. */
.tipcalc {
  margin-top: 40px; max-width: 760px;
  border: 1px solid var(--rule-strong); border-radius: 12px;
  background: var(--bg-elev);
  padding: 26px 26px 22px;
}
.tipcalc-head h3 {
  font-family: var(--sans); font-weight: 500; font-size: 17px;
  letter-spacing: -0.015em; margin: 0 0 4px; color: var(--ink);
}
.tipcalc-head p { font-size: 13.5px; color: var(--muted); margin: 0 0 22px; line-height: 1.6; }
.tipcalc-body { display: grid; grid-template-columns: 1fr; gap: 24px; }
.tipcalc-fields { display: flex; flex-direction: column; gap: 16px; }
/* Reserved height: the two output lines rewrite on every keystroke,
   including a shorter neutral state, and the caveat below must not move. */
.tipcalc-result { min-height: 118px; }
.tipcalc-result-k { font-family: var(--mono); font-size: 11px; color: var(--muted-2); margin: 0 0 10px; }
.tipcalc-amt {
  font-family: var(--sans); font-weight: 500; font-size: 30px;
  letter-spacing: -0.02em; line-height: 1.15; color: var(--ink);
  margin: 0 0 8px;
}
.tipcalc-amt .unit { font-size: 15px; font-weight: 400; letter-spacing: -0.005em; color: var(--muted); }
.tipcalc-payback { font-size: 13.5px; line-height: 1.6; color: var(--muted); margin: 0; max-width: 44ch; }
.tipcalc-caveat {
  margin: 22px 0 0; padding-top: 16px; border-top: 1px solid var(--rule);
  font-size: 12.5px; line-height: 1.6; color: var(--muted-2);
}
@media (min-width: 700px) {
  .tipcalc-body { grid-template-columns: 1fr 1.1fr; gap: 32px; }
  .tipcalc-result { border-left: 1px solid var(--rule); padding-left: 32px; min-height: 96px; }
}

/* ── FAQ accordion ───────────────────────────────────── */
.faq { max-width: 760px; }
.faq details {
  border-top: 1px solid var(--rule);
}
.faq details:last-child { border-bottom: 1px solid var(--rule); }
.faq summary {
  list-style: none; cursor: pointer;
  padding: 24px 40px 24px 0; position: relative;
  font-family: var(--sans); font-weight: 500; font-size: 17px;
  letter-spacing: -0.015em; color: var(--ink);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: '+'; position: absolute; right: 6px; top: 22px;
  font-size: 20px; color: var(--muted); font-weight: 400;
  transition: transform 200ms;
}
.faq details[open] summary::after { content: '–'; }
.faq summary:hover { color: var(--ink); }
.faq .faq-a {
  padding: 0 40px 26px 0;
  font-size: 15px; line-height: 1.65; color: var(--muted);
  max-width: 60ch;
  margin-top: -4px;
}
.faq .faq-a a { color: var(--ink); border-bottom: 1px solid var(--rule-strong); }

/* ── CTA band ────────────────────────────────────────── */
.cta-band {
  border-bottom: 1px solid var(--rule);
  padding: 80px 0; text-align: center; position: relative; overflow: hidden;
}
.cta-band::before {
  content: ''; position: absolute; inset: 0;
  background-image:
    linear-gradient(to right, var(--grid-line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px);
  background-size: 56px 56px;
  -webkit-mask-image: radial-gradient(ellipse 50% 80% at 50% 50%, #000 10%, transparent 70%);
          mask-image: radial-gradient(ellipse 50% 80% at 50% 50%, #000 10%, transparent 70%);
  pointer-events: none;
}
.cta-band .inner { position: relative; }
.cta-band h2 {
  font-family: var(--sans); font-weight: 500;
  font-size: clamp(25px, 3vw, 36px); letter-spacing: -0.025em;
  line-height: 1.05; margin: 0 auto 16px; max-width: 18ch; color: var(--ink);
  text-wrap: balance;
}
.cta-band p { font-size: 16px; color: var(--muted); margin: 0 auto 32px; max-width: 48ch; line-height: 1.6; }
.cta-band .btn-row { justify-content: center; }

/* small print line */
.fineprint { font-family: var(--mono); font-size: 11px; color: var(--muted-2); margin-top: 18px; }

/* ── Feature hub: grouped capability grid ─────────────────────────────
   /features lists every area; the four spokes go deep. Groups keep ~20
   cards legible — an ungrouped wall of them reads as a spec sheet. */
.fgroup { padding: 48px 0; border-top: 1px solid var(--rule); }
.fgroup:first-of-type { border-top: 0; padding-top: 8px; }
.fgroup-head {
  display: flex; align-items: baseline; gap: 16px;
  margin: 0 0 28px; flex-wrap: wrap;
}
.fgroup-num {
  font-family: var(--mono); font-size: 11px; color: var(--muted-2);
}
.fgroup-head h3 {
  font-size: 24px; font-weight: 400; margin: 0; letter-spacing: -0.01em;
}
.fgroup-link {
  margin-left: auto;
  font-family: var(--mono); font-size: 12px; color: var(--muted);
  display: inline-flex; align-items: center; gap: 7px;
  border-bottom: 1px solid transparent;
  transition: color 160ms ease, border-color 160ms ease;
}
.fgroup-link:hover { color: var(--ink); border-bottom-color: var(--rule-strong); }

.fgrid {
  display: flex; flex-wrap: wrap; gap: 1px;
  background: var(--rule);           /* the gap IS the hairline grid */
  border: 1px solid var(--rule);
  border-radius: 10px; overflow: hidden;
}
.fcard {
  /* Flex-wrap rather than auto-fit grid: cards in a short last row grow to
     fill it, so no unpainted cell ever exposes the container's --rule
     background as a grey void (grid did, whenever the count didn't divide
     by the column count — 6 cards over 4 columns, or 4 over 3). */
  flex: 1 1 248px;
  background: var(--bg); padding: 22px 20px 24px;
  transition: background 180ms ease;
}
.fcard:hover { background: var(--bg-card); }
.fcard h4 {
  font-size: 14.5px; font-weight: 500; margin: 0 0 8px; letter-spacing: -0.005em;
}
.fcard p {
  font-size: 13.5px; line-height: 1.65; color: var(--muted); margin: 0;
}

/* the honest-limits block */
.fnot { max-width: 720px; }
.fnot p {
  font-size: 15px; line-height: 1.75; color: var(--muted); margin: 0 0 18px;
}
.fnot p:last-child { margin-bottom: 0; }

@media (max-width: 700px) {
  .fcard { flex-basis: 100%; } /* single column, as the grid version forced */
  .fgroup-link { margin-left: 0; width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .fcard, .fgroup-link { transition: none; }
}

/* ── Feature spokes ───────────────────────────────────────────────── */

/* /features/website — the live-edit mock (the pitch, shown not told) */
.mock-edit { padding: 0; overflow: hidden; }
.me-bar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 11px 16px; border-bottom: 1px solid var(--rule);
  background: var(--bg-elev);
  font-family: var(--mono); font-size: 11px; color: var(--muted-2);
}
.me-keys { margin-left: auto; }
.me-bar kbd {
  font-family: var(--mono); font-size: 10px;
  border: 1px solid var(--rule-strong); border-radius: 3px;
  padding: 1px 5px; color: var(--muted); background: var(--bg);
}
.me-page { padding: 40px 32px 44px; background: #f0f1ec; }
.me-eyebrow {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.16em;
  color: #5a7a5e; margin-bottom: 18px; display: inline-block;
  padding: 3px 2px; border-radius: 2px;
}
.me-eyebrow.editing { outline: 2px solid rgba(90,122,94,.9); outline-offset: 3px; }
.me-caret {
  display: none; width: 1.5px; height: 11px; margin-left: 1px;
  background: #5a7a5e; vertical-align: -1px;
  animation: me-blink 1s step-end infinite;
}
.me-eyebrow.editing .me-caret { display: inline-block; }
@keyframes me-blink { 50% { opacity: 0; } }
.me-head {
  font-family: var(--serif); font-size: 40px; line-height: 1.08;
  color: #2b1f22; margin: 0 0 16px; font-weight: 300;
}
.me-head em { color: #5a7a5e; }
.me-sub {
  font-family: var(--serif); font-style: italic; font-size: 15px;
  color: #6b5a5e; margin: 0; max-width: 44ch; line-height: 1.6;
}
.me-save {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 16px; border-top: 1px solid var(--rule); background: var(--bg-elev);
}
.me-status { font-family: var(--mono); font-size: 11px; color: var(--muted); }
.me-btn {
  margin-left: auto; font-family: var(--mono); font-size: 11px;
  background: var(--accent); color: var(--accent-ink);
  padding: 6px 12px; border-radius: 4px;
}

/* palettes + type pairing */
.mock-swatch { display: flex; flex-direction: column; justify-content: center; gap: 18px; }
.sw-row { display: flex; gap: 8px; }
.sw { width: 100%; height: 44px; border-radius: 4px; border: 1px solid var(--rule-strong); }
.sw-label { font-family: var(--mono); font-size: 11px; color: var(--muted-2); margin: 0; }
.sw-type {
  display: flex; align-items: baseline; gap: 12px;
  border-top: 1px solid var(--rule); padding-top: 18px;
}
.sw-serif { font-family: var(--serif); font-size: 26px; color: var(--ink); }
.sw-plus { font-family: var(--mono); font-size: 12px; color: var(--muted-2); }
.sw-sans { font-family: var(--sans); font-size: 17px; color: var(--muted); }

/* page show/hide */
.mock-pages { display: flex; flex-direction: column; gap: 1px; padding: 0; background: var(--rule); }
.pg-row {
  display: flex; align-items: center; justify-content: space-between;
  background: var(--bg-card); padding: 15px 20px; font-size: 13.5px;
}
.pg-row:first-child { padding-top: 22px; }
.pg-row:last-child { padding-bottom: 22px; }
.pg-slug { font-family: var(--mono); font-size: 11px; color: var(--muted-2); }
.pg-row.off { opacity: 0.42; }
.pg-row.off span:first-child { text-decoration: line-through; }

@media (max-width: 700px) {
  .me-head { font-size: 30px; }
  .me-keys { margin-left: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .me-caret { animation: none; }
}

/* /features/booking — hours table */
.mock-hours { display: flex; flex-direction: column; gap: 1px; padding: 0; background: var(--rule); }
.hr-row {
  display: flex; align-items: center; justify-content: space-between;
  background: var(--bg-card); padding: 15px 20px; font-size: 13.5px;
}
.hr-row:first-child { padding-top: 22px; }
.hr-row:last-child { padding-bottom: 22px; }
.hr-t { font-family: var(--mono); font-size: 12px; color: var(--muted); }
.hr-row.off { opacity: 0.45; }
.hr-row.lunch { border-top: 1px solid var(--rule); }
.hr-row.lunch .hr-t { color: var(--muted-2); }

/* /features/payments — the reader screen */
.mock-reader {
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-elev);
}
.rd-screen {
  width: 100%; max-width: 300px; text-align: center;
  background: var(--bg); border: 1px solid var(--rule-strong);
  border-radius: 14px; padding: 28px 22px;
}
.rd-amt { font-size: 34px; font-weight: 300; margin: 0 0 4px; letter-spacing: -0.02em; }
.rd-svc { font-family: var(--mono); font-size: 10.5px; color: var(--muted-2); margin: 0 0 22px; }
.rd-tips { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; margin-bottom: 16px; }
.rd-tips span {
  font-family: var(--mono); font-size: 11px; color: var(--muted);
  border: 1px solid var(--rule-strong); border-radius: 4px; padding: 9px 0;
}
.rd-tips .on { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.rd-hint { font-family: var(--mono); font-size: 10px; color: var(--muted-2); margin: 0; }

/* /features/payments — the money stack */
.mock-money { display: flex; flex-direction: column; gap: 1px; padding: 0; background: var(--rule); }
.mn-row {
  display: flex; align-items: baseline; justify-content: space-between;
  background: var(--bg-card); padding: 14px 20px; font-size: 13.5px;
}
.mn-row:first-child { padding-top: 22px; }
.mn-row b { font-family: var(--mono); font-size: 14px; font-weight: 500; }
.mn-row.dim, .mn-row.dim b { color: var(--muted-2); }
.mn-row.net { background: var(--bg-elev); padding: 20px; border-top: 1px solid var(--rule-strong); }
.mn-row.net b { font-size: 20px; }

/* /features/clients — note card */
.mock-note { display: flex; flex-direction: column; justify-content: center; }
.nt-who { font-size: 15px; margin: 0 0 14px; display: flex; align-items: center; gap: 10px; }
.nt-tag {
  font-family: var(--mono); font-size: 10px; color: var(--rose);
  background: var(--rose-bg); border-radius: 999px; padding: 3px 9px;
}
.nt-body { font-size: 13.5px; line-height: 1.7; color: var(--muted); margin: 0 0 16px; }
.nt-meta {
  font-family: var(--mono); font-size: 11px; color: var(--muted-2); margin: 0;
  border-top: 1px solid var(--rule); padding-top: 14px;
}

/* /features/clients — visit-rhythm strip (the gap is the point) */
.mock-heat {
  /* One column per week (7 rows = days), so a steady client sits on one row and
     the gap where they stopped is a block of silence you can see across the
     room. Row-wise layout makes the same data look like random noise. */
  display: grid; grid-template-rows: repeat(7, 1fr);
  grid-auto-flow: column; grid-auto-columns: 1fr;
  gap: 3px; align-content: center;
}
.mock-heat i { aspect-ratio: 1 / 1; border-radius: 2px; background: var(--rule); }
.mock-heat i.v { background: var(--accent); }

/* /features/clients — segments */
.mock-seg { display: flex; flex-direction: column; gap: 1px; padding: 0; background: var(--rule); }
.sg-row {
  display: flex; align-items: center; gap: 16px;
  background: var(--bg-card); padding: 16px 20px;
}
.sg-row:first-child { padding-top: 22px; }
.sg-row:last-child { padding-bottom: 22px; }
.sg-n {
  font-family: var(--mono); font-size: 15px; color: var(--ink);
  min-width: 34px; text-align: right;
}
.sg-l { font-size: 13.5px; color: var(--muted); }
.sg-row.hot .sg-n, .sg-row.hot .sg-l { color: var(--rose); }

@media (max-width: 700px) {
  .rd-amt { font-size: 28px; }
}
