/* ══════════════════════════════════════════════════════════════════════
   app.kevinchia.sg — the marketing design system.  Function first.
   ──────────────────────────────────────────────────────────────────────
   ONE ACCENT PER PAGE.  Each product page sets --accent + --accent-wash
   in its own <style>; every colour on the page reads from those two.
   Across the site the products are told apart by colour; on any single
   page you still only ever see one.  The footer is where they all appear
   together, which is what makes the colour carry information rather than
   decoration.

   ⚠ NO DARK MODE.  There is no data-theme attribute, no toggle and no
   prefers-color-scheme block anywhere.  One theme, deliberately (Kevin,
   2026-09-04) — a second palette doubles every colour decision for a
   feature nobody asked for.

   ⚠ EVERY ACCENT MUST CLEAR 4.5:1 ON --bg AND ON WHITE.  The accent is
   used as text (links, eyebrows, figures) and as a button background
   with white type, so it has to pass both ways.  The ten in use:
     Pro 365    #4038B8  8.26      HRMS        #A21B62  7.13
     P&L        #15653F  6.90      Payroll     #8A4B14  6.60
     Bookings   #0E6C7E  5.90      CRM         #0D6E9E  5.47
     Online Shop   #C2410C  5.04      Compliance  #6B21A8  8.49
     Chatbot    #B0203A  6.57      Invoicing   #7A5A00  6.22
     (Invoicing added 2026-09-11 with /invoice.html; 6.38:1 on white.)
     POS   #1E4FC8  6.80      Snap Inv.   #4A6508  6.48
     (Both added 2026-09-14 with /pos.html and /inventory.html.  On white
     6.98 and 6.65; on #F5F5F7 6.41 and 6.11; #6E6E73 on their washes
     #F5F8FE and #F8FAF2 is 4.77 and 4.82.)
     PayNow Auto-Confirm   #047857  5.29
     (Added 2026-09-16 with /paynow.html.  5.48 on white, 5.04 on #F5F5F7;
     #6E6E73 on its wash #F5FBF8 is 4.84.)
     Your AI    #A3431F  6.05
     (Added 2026-09-17 with /ai.html.  6.21 on white, 5.71 on #F5F5F7;
     #6E6E73 on its wash #FBF6F3 is 4.73.)
     Balance sh #3A5470  7.63      Auto acct.  #2F5D50  7.30
     (Balance sheet split off /auto-accounting.html 2026-09-14.  7.83 on white,
     7.19 on #F5F5F7; #6E6E73 on its wash #F3F6F9 is 4.68.)
   ══════════════════════════════════════════════════════════════════════ */
:root{
  --bg:#FCFCFB;
  --surface:#FFFFFF;
  --ink:#16181C;          /* 17.3:1 on --bg */
  --ink-2:#5C6067;        /*  6.2:1 on --bg */
  --hair:#E6E5E1;
  --hair-2:#F1F0EC;
  --font:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  --mono:'DM Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
  --nav-h:60px;
  /* fallbacks — every page overrides these two */
  --accent:#4038B8;
  --accent-wash:#F0EFFA;
}
*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth;scroll-padding-top:76px;-webkit-text-size-adjust:100%}
body{background:var(--bg);color:var(--ink);font-family:var(--font);font-size:17px;line-height:1.62;
  -webkit-font-smoothing:antialiased;overflow-x:hidden}
img{max-width:100%;display:block}
a{color:inherit}

.wrap{max-width:1080px;margin:0 auto;padding:0 24px}
.sec{padding:84px 0;border-top:1px solid var(--hair)}
.sec.flush{border-top:0}
.narrow{max-width:64ch}

/* ── type ─────────────────────────────────────────── */
h1{font-size:clamp(36px,5.6vw,58px);line-height:1.06;letter-spacing:-.028em;font-weight:700}
h2{font-size:clamp(27px,3.4vw,38px);line-height:1.14;letter-spacing:-.022em;font-weight:700}
h3{font-size:19px;line-height:1.32;letter-spacing:-.012em;font-weight:600}
.eyebrow{font-size:12px;font-weight:600;letter-spacing:.11em;text-transform:uppercase;color:var(--accent)}
.lede{font-size:clamp(18px,2.1vw,21px);line-height:1.55;color:var(--ink-2)}
.body{font-size:16.5px;line-height:1.68;color:var(--ink-2)}
.body b,.body strong{color:var(--ink);font-weight:600}
.num{font-family:var(--mono);font-variant-numeric:tabular-nums}
.link{color:var(--accent);text-decoration:underline;text-underline-offset:3px;
  text-decoration-thickness:1px;font-weight:500}
.link:hover{text-decoration-thickness:2px}
.h2sub{margin:14px 0 0}
.mt16{margin-top:16px}.mt26{margin-top:26px}.mt34{margin-top:34px}

/* ── buttons ──────────────────────────────────────── */
.btn{display:inline-flex;align-items:center;gap:8px;padding:12px 22px;border-radius:6px;
  background:var(--accent);color:#fff;font-size:15.5px;font-weight:600;text-decoration:none;
  border:1px solid var(--accent);transition:opacity .15s}
.btn:hover{opacity:.88}
.btn-ghost{background:transparent;color:var(--ink);border-color:var(--hair)}
.btn-ghost:hover{border-color:var(--ink-2);opacity:1}
.btn-lg{padding:15px 30px;font-size:16.5px}
.btns{display:flex;gap:12px;flex-wrap:wrap}

/* ── nav (injected by shell.js) ───────────────────── */
#nav{position:sticky;top:0;z-index:80;background:rgba(252,252,251,.94);
  backdrop-filter:saturate(180%) blur(12px);border-bottom:1px solid var(--hair)}
/* ⚠ WIDER THAN THE 1024px PAGE WRAP ON PURPOSE.  The three groups are
   equal-flex, so the centre one sits dead on the page centre line only
   while the RIGHT group fits inside its third — `.nav-r` is nowrap and will
   not shrink, so anything it outgrows pushes the middle left.  Since
   2026-09-05 that group is only "Sign in" + "Start free" (the products
   dropdown moved to the footer), which is what gives the centre group its
   headroom back.  Re-measure if a nav label is added or reworded. */
.nav-in{max-width:1160px;margin:0 auto;padding:0 24px;height:var(--nav-h);
  display:flex;align-items:center;gap:16px}
/* ⚠ NO `gap` ON THIS FLEX ROW, AND THAT IS THE POINT (Kevin, 2026-09-05:
   "the top left snapbook .ai just bring them together app.kevinchia.sg").  The
   text node "snapbook" and the <small>.ai</small> are two separate flex
   items, so ANY gap here opens a space in the middle of the company's own
   name — it read as "snapbook .ai", two words.  The dot and the caret carry
   their own margins instead, so spacing them never touches the wordmark.
   ⚠ This is the nav AND the footer wordmark; both were wrong the same way. */
.brand{display:flex;align-items:center;text-decoration:none;font-weight:700;
  font-size:16px;letter-spacing:-.02em;flex-shrink:0;color:var(--ink)}
.brand-dot{width:9px;height:9px;border-radius:2px;background:var(--accent);
  flex-shrink:0;margin-right:9px}
.brand small{font-weight:500;color:var(--ink-2);font-size:16px}

/* ⚠ THE PAGE NAV SITS IN THE MIDDLE OF THE BAR (Kevin, 2026-09-04).  The
   left group and the right-hand controls each take `flex:1`, so they claim
   equal width whatever they contain and the centre group lands exactly on
   the centre line.  Do NOT centre it with absolute positioning: the right
   group grows when a page's button label changes and the two would overlap. */
.nav-l{flex:1 1 0;display:flex;align-items:center;gap:10px;min-width:0}

/* ⚠ "app.kevinchia.sg" AND "/pl" MUST READ AS TWO THINGS, NOT ONE NAME.  The
   divider and the lighter weight are doing that job — welded together they
   read as a strange company name, which is why the same arrangement was
   reversed on 2026-09-04.  See the note in shell.js. */
.nav-sep{width:1px;height:17px;background:var(--hair);flex-shrink:0}
.brand-top{display:flex;align-items:center;padding:6px 8px;border-radius:5px;
  font-size:14.5px;font-weight:600;color:var(--ink-2);text-decoration:none;
  white-space:nowrap;flex-shrink:0}
.brand-top:hover{color:var(--ink);background:var(--hair-2)}

.anchors{display:flex;gap:1px;min-width:0;overflow:hidden;justify-content:center}
.anchors a{padding:6px 7px;border-radius:5px;font-size:14.5px;font-weight:500;
  color:var(--ink-2);text-decoration:none;white-space:nowrap}
.anchors a:hover{color:var(--ink);background:var(--hair-2)}
.anchors a.on{color:var(--accent);background:var(--accent-wash)}
.nav-r{flex:1 1 0;display:flex;align-items:center;justify-content:flex-end;gap:10px;white-space:nowrap}
.nav-r a.sign{font-size:14.5px;font-weight:500;color:var(--ink-2);text-decoration:none;padding:6px 4px}
.nav-r a.sign:hover{color:var(--ink)}
.nav-r .btn{padding:8px 16px;font-size:14.5px}
/* ── the site menu behind the wordmark (shell.js, data-menu) ──────────
   ⚠ IT ADDS NO WIDTH TO THE BAR.  The trigger is the wordmark that was
   already there, which is the only reason a site menu is allowed back into
   this bar at all — the old "All products" dropdown was removed on
   2026-09-05 because its ~120px pushed the centre links off the page
   centre line between 1040 and 1200px.  The measured centring is unchanged;
   re-measure that band anyway if anything is ever added BESIDE the caret. */
.brand-btn{background:none;border:0;padding:0;font:inherit;cursor:pointer;
  color:var(--ink)}
.brand-caret{width:10px;height:6px;color:var(--ink-2);flex-shrink:0;margin-left:8px;
  transition:transform .2s}
.brand-btn:hover .brand-caret{color:var(--ink)}
.mm-open .brand-caret{transform:rotate(180deg)}

/* ⚠ 70, AGAINST THE NAV'S 80.  The bar stays above the panel and stays
   pressable, so the wordmark you opened it with is still there with its
   caret turned over.  A menu that covers its own trigger leaves nothing
   obvious to press to get out again. */
.mm{position:fixed;inset:var(--nav-h) 0 0 0;z-index:70;display:flex;flex-direction:column}
.mm[hidden]{display:none}
.mm-scrim{position:absolute;inset:0;background:rgba(22,24,28,.34);opacity:0;
  transition:opacity .2s}
.mm-panel{position:relative;background:var(--bg);border-bottom:1px solid var(--hair);
  box-shadow:0 18px 40px -24px rgba(22,24,28,.3);max-height:100%;overflow-y:auto;
  padding:36px 0 30px;opacity:0;transform:translateY(-10px);
  transition:opacity .2s,transform .2s}
.mm.on .mm-scrim{opacity:1}
.mm.on .mm-panel{opacity:1;transform:none}
/* the panel scrolls inside itself; the page behind it must not scroll with it */
body.mm-open{overflow:hidden}
/* the menu's legal line IS .f-bar (see shell.js); it only sits tighter */
.mm .f-bar{margin-top:34px}

/* ⚠ PHONES ONLY, AND IT IS NOT A DUPLICATE OF THE WORDMARK.  Below 1040px
   the centre section links are display:none, so a phone has no navigation
   on the page at all; this is a thumb-sized target at the bottom of the
   screen instead of 16px of type at the top.  z-index 90 puts it above the
   nav as well as the panel, so the same button closes what it opened. */
.mm-fab{display:none;position:fixed;right:16px;bottom:16px;z-index:90;
  width:50px;height:50px;border-radius:50%;border:1px solid var(--hair);
  background:var(--surface);color:var(--ink);cursor:pointer;
  align-items:center;justify-content:center;
  box-shadow:0 6px 20px -6px rgba(22,24,28,.28)}
.mm-fab svg{width:22px;height:22px}
.mm-fab .mm-i-close{display:none}
.mm-open .mm-fab{background:var(--ink);color:var(--surface);border-color:var(--ink)}
.mm-open .mm-fab .mm-i-open{display:none}
.mm-open .mm-fab .mm-i-close{display:block}
@media(max-width:700px){
  .mm-fab{display:flex}
  /* ⚠ THE BOTTOM PADDING CLEARS THE FLOATING BUTTON.  The panel scrolls
     inside itself and the button is fixed over its bottom-right corner, so
     at 26px the last row of the longest column sits underneath it and is
     unreachable — 50px of button, 16px of inset and a little air. */
  .mm-panel{padding:28px 0 86px}
}
@media(prefers-reduced-motion:reduce){
  .mm-scrim,.mm-panel,.brand-caret{transition:none}
}

/* ── hero ─────────────────────────────────────────── */
.hero{padding:74px 0 66px}
.hero h1{margin:16px 0 22px;max-width:17ch}
.hero .lede{max-width:56ch}
.hero .btns{margin-top:32px}
.hero-note{margin-top:20px;font-size:14.5px;color:var(--ink-2)}
.hero-note b{color:var(--ink);font-weight:600}
.who{margin-top:38px;display:flex;flex-wrap:wrap;gap:8px}
.who span{font-size:13.5px;font-weight:500;color:var(--ink-2);background:var(--surface);
  border:1px solid var(--hair);border-radius:99px;padding:5px 13px}

/* ── proof strip ──────────────────────────────────── */
.proof{background:var(--surface);border-top:1px solid var(--hair);border-bottom:1px solid var(--hair)}
.proof-in{max-width:1080px;margin:0 auto;padding:22px 24px;display:flex;flex-wrap:wrap;gap:10px 28px}
.proof-in div{font-size:14.5px;font-weight:500;color:var(--ink-2);display:flex;align-items:center;gap:8px}
.proof-in b{color:var(--ink);font-weight:600}
.tick{width:15px;height:15px;flex-shrink:0;color:var(--accent)}

/* ── card grids ───────────────────────────────────── */
.g{display:grid;gap:1px;background:var(--hair);border:1px solid var(--hair);border-radius:8px;
  overflow:hidden;margin-top:34px}
.g2{grid-template-columns:repeat(2,1fr)}
.g3{grid-template-columns:repeat(3,1fr)}
.g4{grid-template-columns:repeat(4,1fr)}
.g > div{background:var(--surface);padding:26px 24px}
.g h3{margin-bottom:9px}
.g p{font-size:15.5px;line-height:1.6;color:var(--ink-2)}
.g p b{color:var(--ink);font-weight:600}

/* ── numbered steps ───────────────────────────────── */
.steps{counter-reset:s;margin-top:34px;display:grid;grid-template-columns:repeat(4,1fr);gap:1px;
  background:var(--hair);border:1px solid var(--hair);border-radius:8px;overflow:hidden}
.steps.s3{grid-template-columns:repeat(3,1fr)}
.steps > div{background:var(--surface);padding:26px 24px}
.steps .n{counter-increment:s;display:flex;align-items:center;justify-content:center;
  width:26px;height:26px;border-radius:5px;background:var(--accent);color:#fff;
  font-family:var(--mono);font-size:13px;font-weight:500;margin-bottom:14px}
.steps .n::before{content:counter(s)}
.steps h3{margin-bottom:8px;font-size:17px}
.steps p{font-size:15px;line-height:1.58;color:var(--ink-2)}

/* ── the worked example (two columns: mock + notes) ── */
.demo{margin-top:36px;display:grid;grid-template-columns:1fr 1fr;gap:26px;align-items:start}
.phone{background:var(--surface);border:1px solid var(--hair);border-radius:10px;padding:22px 20px}
.ph-top{display:flex;align-items:center;gap:8px;padding-bottom:14px;border-bottom:1px solid var(--hair);margin-bottom:16px}
.ph-top .d{width:8px;height:8px;border-radius:2px;background:var(--accent)}
.ph-top b{font-size:14px;font-weight:600}
.ph-q{font-size:15px;font-weight:600;margin-bottom:12px}
.ph-opts{display:grid;gap:8px}
.ph-opt{display:flex;justify-content:space-between;align-items:center;gap:12px;
  border:1px solid var(--hair);border-radius:6px;padding:11px 13px;font-size:14.5px}
.ph-opt.pick{border-color:var(--accent);background:var(--accent-wash);font-weight:600}
.ph-opt .p{font-family:var(--mono);font-size:13.5px;color:var(--ink-2)}
.ph-opt.pick .p{color:var(--accent)}
.ph-rule{margin-top:20px;padding-top:16px;border-top:1px solid var(--hair)}
.ph-done{display:flex;justify-content:space-between;gap:14px;font-size:14px;color:var(--ink-2);
  padding:7px 0;border-bottom:1px solid var(--hair-2)}
.ph-done:last-child{border:0}
.ph-done b{color:var(--ink);font-family:var(--mono);font-weight:500;white-space:nowrap}
.ph-tot{display:flex;justify-content:space-between;font-size:16px;font-weight:700;
  margin-top:12px;padding-top:12px;border-top:1px solid var(--hair)}
.ph-tot span:last-child{font-family:var(--mono);color:var(--accent)}
.demo-note{font-size:15.5px;line-height:1.68;color:var(--ink-2)}
.demo-note b{color:var(--ink);font-weight:600}
.demo-note p+p{margin-top:14px}

/* ── objections ───────────────────────────────────── */
.obj{margin-top:32px;display:grid;gap:14px}
.obj > div{background:var(--surface);border:1px solid var(--hair);border-left:3px solid var(--accent);
  border-radius:6px;padding:20px 22px}
.obj q{display:block;font-size:16.5px;font-weight:600;font-style:italic;margin-bottom:8px}
.obj q::before{content:'\201C'}.obj q::after{content:'\201D'}
.obj p{font-size:15.5px;line-height:1.62;color:var(--ink-2)}

/* ── features (three columns, three bullets each) ─── */
.feat{margin-top:34px;display:grid;grid-template-columns:repeat(3,1fr);gap:1px;
  background:var(--hair);border:1px solid var(--hair);border-radius:8px;overflow:hidden}
.feat > div{background:var(--surface);padding:26px 24px}
.feat h3{margin-bottom:12px;display:flex;align-items:center;gap:9px}
.feat h3 .d{width:7px;height:7px;border-radius:2px;background:var(--accent);flex-shrink:0}
.feat ul{list-style:none}
.feat li{font-size:15px;line-height:1.55;color:var(--ink-2);padding-left:16px;position:relative;margin-bottom:9px}
.feat li:last-child{margin-bottom:0}
.feat li::before{content:'';position:absolute;left:0;top:9px;width:5px;height:5px;
  border-radius:1px;background:var(--hair);border:1px solid #C9C7C0}
.feat li b{color:var(--ink);font-weight:600}

/* ── testimonial ──────────────────────────────────── */
.tm{background:var(--surface);border:1px solid var(--hair);border-radius:8px;padding:34px 32px;margin-top:6px}
.tm .pull{font-size:clamp(20px,2.5vw,26px);line-height:1.32;letter-spacing:-.018em;font-weight:600;margin-bottom:18px}
.tm .q{font-size:16px;line-height:1.68;color:var(--ink-2)}
.tm .by{margin-top:18px;font-size:14.5px;color:var(--ink-2)}
.tm .by b{color:var(--ink);font-weight:600}
.tm-mini{margin-top:26px;padding:20px 22px;background:var(--accent-wash);border-radius:8px;
  font-size:16px;line-height:1.6;font-weight:500}
.tm-mini span{display:block;margin-top:8px;font-size:14px;font-weight:400;color:var(--ink-2)}

/* ── built by ─────────────────────────────────────── */
.team-shot{border:1px solid var(--hair);border-bottom:0;border-radius:8px 8px 0 0;overflow:hidden;margin:34px 0 0}
/* ⚠ height:auto is REQUIRED — the width/height attributes are a presentational
   hint that beats aspect-ratio, so without it the photo renders full height and
   no crop happens.  object-position 15% lands the band just below both logos. */
.team-shot img{width:100%;height:auto;aspect-ratio:2/1;object-fit:cover;object-position:center 15%}
.people{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:var(--hair);
  border:1px solid var(--hair);border-radius:0 0 8px 8px;overflow:hidden}
.people > div{background:var(--surface);padding:24px}
.people h3{margin-bottom:3px}
.people .role{font-size:13px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--accent);margin-bottom:11px}
.people p{font-size:15px;line-height:1.6;color:var(--ink-2)}

/* ── pricing ──────────────────────────────────────── */
.plans{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-top:34px}
.plans.p3{grid-template-columns:repeat(3,1fr)}
.plan{background:var(--surface);border:1px solid var(--hair);border-radius:8px;padding:28px 26px;
  display:flex;flex-direction:column}
.plan.hi{border:2px solid var(--accent)}
.plan .tag{font-size:12px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--accent)}
.plan .price{font-family:var(--mono);font-size:38px;font-weight:500;letter-spacing:-.02em;margin:12px 0 4px}
.plan .price small{font-size:17px;color:var(--ink-2);letter-spacing:0}
.plan .per{font-size:15px;color:var(--ink-2)}
.plan ul{list-style:none;margin:20px 0 24px}
.plan li{font-size:15px;line-height:1.5;color:var(--ink-2);padding-left:22px;position:relative;margin-bottom:10px}
.plan li svg{position:absolute;left:0;top:4px;width:14px;height:14px;color:var(--accent)}
.plan li b{color:var(--ink);font-weight:600}
.plan .btn,.plan .btn-ghost{margin-top:auto;align-self:flex-start}

/* ── what it does not do ──────────────────────────── */
.no{margin-top:32px;display:grid;grid-template-columns:1fr 1fr;gap:1px;
  background:var(--hair);border:1px solid var(--hair);border-radius:8px;overflow:hidden}
.no > div{background:var(--surface);padding:20px 22px;font-size:15px;line-height:1.58;color:var(--ink-2)}
.no b{color:var(--ink);font-weight:600;display:block;margin-bottom:3px}

/* ── comparison table ─────────────────────────────────
   One shape on all seven module pages, so somebody reading two of them
   sees one house style.

   ⚠ EVERY TABLE KEEPS AT LEAST ONE ROW THE OTHER SIDE WINS (Kevin,
   2026-09-04).  A table we win on every line reads as marketing and is
   not believed; one that concedes something is read as true.  The
   conceded row is also simply the honest one — Xero really does file the
   GST F5 straight to IRAS and we do not, Calendly really does sync to
   Google Calendar.  Do not "tidy" those rows out.

   ⚠ NO COMPETITOR PRICE IS EVER STATED, DELIBERATELY.  Their price is
   theirs to change and we would not notice; a wrong figure on our own
   site is worse than no figure.  The cost row states OUR price in full
   (it cannot go stale on us) and links to their published page for
   theirs.  What we DO compare is the pricing MODEL — "per employee every
   month" against "one flat price" — which is a real difference and needs
   no number.

   ⚠ NEVER CLAIM A COMPETITOR LACKS SOMETHING WITHOUT CHECKING.  Two rows
   were dropped from the first draft for exactly this: Talenox does have
   time and attendance, and Take App does support PayNow.  "I could not
   find it" is not "they do not have it". */
.cmp{margin-top:34px;display:grid;grid-template-columns:1.6fr 1fr 1fr;gap:1px;
  background:var(--hair);border:1px solid var(--hair);border-radius:8px;overflow:hidden}
.cmp > div{background:var(--surface);padding:14px 16px;font-size:14.5px;line-height:1.5;color:var(--ink-2)}
.cmp .h{background:var(--hair-2);font-size:12px;font-weight:600;letter-spacing:.09em;
  text-transform:uppercase;color:var(--ink-2)}
.cmp .h.us{color:var(--accent)}
.cmp .k{color:var(--ink);font-weight:500}
.cmp b{color:var(--ink);font-weight:600}
.cmp .y::before{content:'\2713';color:var(--accent);font-weight:700;margin-right:7px}
.cmp .n::before{content:'\2715';color:var(--ink-2);opacity:.65;margin-right:7px}
.cmp a{color:var(--accent);text-decoration:underline;text-underline-offset:3px}
.cmp-note{margin-top:18px;font-size:15px;line-height:1.65;color:var(--ink-2);max-width:72ch}
.cmp-note b{color:var(--ink);font-weight:600}

/* ── the dark platform band ───────────────────────────
   ⚠ This block is dark in the ONE theme, so its children must never use
   --ink*.  Everything inside is explicitly white or rgba white.       */
.band{background:#111315;border-radius:10px;padding:44px 40px;margin-top:34px;color:#fff}
.band .eyebrow{color:#A9B4FF}
.band h2{margin:14px 0 16px;max-width:21ch}
.band p{font-size:17px;line-height:1.62;color:rgba(255,255,255,.78);max-width:60ch}
.band p+p{margin-top:14px}
.band b{color:#fff;font-weight:600}
.band .flow{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin:26px 0 28px}
.band .flow span{font-size:14px;font-weight:500;color:rgba(255,255,255,.9);
  border:1px solid rgba(255,255,255,.22);border-radius:99px;padding:6px 14px}
.band .flow span.arw{border:0;padding:0;color:rgba(255,255,255,.5)}
.band .btn{background:#fff;color:#111315;border-color:#fff}
.band .btn-ghost{background:transparent;color:#fff;border-color:rgba(255,255,255,.32)}
.band-p{margin-top:20px;font-size:14.5px;color:rgba(255,255,255,.68)}

/* ── faq ──────────────────────────────────────────── */
.faq{margin-top:32px;border-top:1px solid var(--hair)}
.faq details{border-bottom:1px solid var(--hair)}
.faq summary{padding:18px 0;font-size:17px;font-weight:600;cursor:pointer;list-style:none;
  display:flex;justify-content:space-between;gap:18px;align-items:baseline}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:'+';font-family:var(--mono);color:var(--accent);font-size:20px;flex-shrink:0}
.faq details[open] summary::after{content:'\2212'}
.faq p{font-size:16px;line-height:1.68;color:var(--ink-2);padding-bottom:20px;max-width:72ch}
.faq p+p{margin-top:-6px;padding-top:0}

/* ── final cta ────────────────────────────────────── */
.end{padding:84px 0 92px;border-top:1px solid var(--hair)}
.end h2{max-width:19ch}

/* ── footer (injected by shell.js) ────────────────── */
footer{background:var(--surface);border-top:1px solid var(--hair);padding:56px 0 34px}
/* ⚠ auto-fit, NOT a fixed column count.  The footer carries FIVE columns
   today (Company, three product groups, Full systems) and the count is
   decided in shell.js, not here — a hardcoded `repeat(5,1fr)` would silently
   squash a sixth.
   ⚠ THE 138px AND THE 22px GAP ARE MEASURED, NOT PICKED.  The wrap is
   1080px less 48px of padding = 1032px, so auto-fit fits
   floor((1032 + gap) / (min + gap)) columns: at the old 152/26 that is
   FIVE, and a sixth dropped onto a row of its own the day the verticals
   column appeared.  138/22 fits SIX with room to spare, and each column
   still stretches to ~154px.  Re-do that arithmetic before adding a
   seventh — a stranded column reads as a broken footer.
   ⚠ THE 138px IS DELIBERATELY LEFT WHERE IT IS NOW THERE ARE ONLY FIVE
   (the Get started column went on 2026-09-06 — see shell.js).  It buys
   nothing today: with five items and 1fr each, five is all auto-fit can
   place above 1000px whatever the minimum, so raising it back to 152 would
   change not a pixel.  It is headroom for the sixth column, and the 999.98
   breakpoint below was derived against six.  Leave both alone. */
.f-cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(138px,1fr));gap:34px 22px}
.f-top{display:flex;align-items:flex-end;justify-content:space-between;gap:24px;
  padding-bottom:26px;margin-bottom:34px;border-bottom:1px solid var(--hair)}
.f-top p{font-size:14.5px;line-height:1.6;color:var(--ink-2);margin-top:11px;max-width:46ch}
.f-h{font-size:12px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink-2);margin-bottom:14px}
/* ⚠ THESE FOUR SERVE THE FOOTER **AND** THE SITE MENU, which is the same
   markup from the same string (see shell.js).  Extend the selector; do not
   write a `.mm` copy, or the menu and the footer drift apart on screen the
   week somebody restyles one of them. */
footer ul,.mm ul{list-style:none}
footer li,.mm li{margin-bottom:9px}
footer a,.mm a{font-size:14.5px;color:var(--ink-2);text-decoration:none;display:flex;align-items:center;gap:9px}
footer a:hover,.mm a:hover{color:var(--ink)}
footer a .d,.mm a .d{width:8px;height:8px;border-radius:2px;flex-shrink:0}

/* ⚠ THE FOOTER WORDMARK IS A `footer a`, SO IT INHERITS THE RULE ABOVE —
   9px of gap and 14.5px of type.  `.brand` is (0,1,0) and `footer a` is
   (0,1,1), so `.brand` loses whatever the load order: the gap opened a space
   in the middle of the company's own name ("snapbook .ai"), and "snapbook"
   rendered a size smaller than the ".ai" beside it, which `.brand small`
   still held at 16px.  This restates the wordmark at equal specificity so the
   footer matches the nav exactly.  Same rule and same reason as up there:
   NEVER space these two children with `gap` — the dot carries its own
   margin. */
footer .brand{gap:0;font:inherit;letter-spacing:-.02em;color:var(--ink)}

/* ⚠ `font:inherit` IS THE NAV'S OWN RULE, COPIED ON PURPOSE (Kevin,
   2026-09-05: "make the same as screen" — the footer wordmark should read
   exactly as the top one does).  `.brand-btn` carries `font:inherit` and
   sits after `.brand`, so the nav wordmark actually renders at the body's
   17px / weight 400, NOT at the 16px / 700 `.brand` declares.  Anything
   fixed here would match the top at one breakpoint and miss it at the next,
   because the body drops to 16px below 700px; inheriting tracks it.
   ⚠ THE ".ai" IS STILL `.brand small` IN BOTH PLACES — 16px, weight 500,
   --ink-2 — so the two halves stay related the same way top and bottom. */

/* The Instagram mark sits on the wordmark's own line (see shell.js). */
.f-id{display:flex;align-items:center;gap:13px}
.f-ig{color:var(--ink-2)}
.f-ig:hover{color:var(--ink)}
.f-ig svg{width:17px;height:17px}
/* ⚠ A VERTICAL WITH NO PAGE YET IS A LABEL, NOT A DEAD LINK.  Three plain
   grey lines in a footer read as something broken; the tag is what makes
   them read as a decision.  Same 14.5px and --ink-2 as every link beside
   them, so the column looks like one list rather than two.  --ink-2 is
   6.2:1 on --bg and better again on the footer's white. */
/* ⚠ NOT display:flex, unlike every real link beside it.  A flex row makes
   the tag its own item, so `flex-wrap` drops it onto a line of its own and
   "Custom system · EDG grant" became a three-line entry in a 154px column.
   Inline, the tag flows with the last word like any other. */
.f-soon{font-size:14.5px;color:var(--ink-2);display:block}
.f-soon em{font-style:normal;font-size:10px;font-weight:600;letter-spacing:.07em;
  text-transform:uppercase;border:1px solid var(--hair);border-radius:100px;
  padding:1px 5px;margin-left:7px;white-space:nowrap}
.f-bar{margin-top:46px;padding-top:22px;border-top:1px solid var(--hair);
  display:flex;flex-wrap:wrap;gap:10px 22px;align-items:center;font-size:13.5px;color:var(--ink-2)}
.f-bar a{font-size:13.5px;display:inline}
.f-bar .sp{margin-left:auto}

/* ── responsive ───────────────────────────────────── */
@media(max-width:1040px){ .anchors{display:none} }
/* ⚠ 999px, AND IT IS ITS OWN QUERY RATHER THAN PART OF THE 940px BLOCK BELOW.
   auto-fit only fits all six columns from 1000px up; below that it lands on
   FIVE and strands the sixth on a row of its own, which reads as a broken
   footer.  Three columns hold that gap and give a clean 3+3.
   ⚠ AT FIVE COLUMNS THIS IS NOW CONSERVATIVE RATHER THAN LOAD-BEARING, AND
   THAT IS FINE.  Five would in fact survive on one row down to about 810px
   before stranding one, so between 810 and 1000 this shows three where five
   would fit.  That is a readability call, not a bug: five columns at their
   138px minimum are very narrow, and "Face your customers" is a long heading.
   Five lands 3+2 here and 2+2+1 at the phone breakpoint, where the one on its
   own is Full systems — eight rows, the longest column, so it fills the row
   rather than looking stranded.  Measured, not assumed.
   ⚠ THIS NUMBER WAS 989 AND THAT LEFT A LIVE 990-999px BAND WHERE THE SIXTH
   COLUMN STRANDED, ON EVERY PAGE INCLUDING THE HOMEPAGE (found 2026-09-05,
   measured in a real browser rather than derived).  The arithmetic below is
   right; what it missed is THE SCROLLBAR.  A page tall enough to scroll — all
   of them — loses about 14px to it, so the viewport width that clears the
   threshold is ~1004px, not 990.  Re-derive this whenever the 138px minimum
   or the 22px gap moves, and subtract a scrollbar before you trust it:
   six fit when (wrap + gap) / (min + gap) >= 6, where wrap is the viewport,
   LESS the scrollbar, less the 48px of .wrap padding.  Then go and measure it.
   ⚠ THE .98 IS NOT A TYPO.  A viewport can be a fractional width (a scaled
   display, browser zoom, a fractional device pixel ratio), and a whole-number
   `max-width:999px` then fails at a reported 999.33 while auto-fit still only
   fits five — which strands the column at exactly one width.  Measured: 999px
   stranded with the whole number and does not with this one. */
@media(max-width:999.98px){ .f-cols{grid-template-columns:repeat(3,1fr)} }
@media(max-width:940px){
  .g3,.g4,.feat,.steps,.steps.s3,.plans.p3{grid-template-columns:repeat(2,1fr)}
  .demo{grid-template-columns:1fr}
}
/* ⚠ THE NAV OVERFLOWS BELOW ~400px WITHOUT THIS, and a horizontally
   scrolling page is the most obvious kind of broken there is.  The brand
   suffix ("/snapslot") is the widest optional thing in the bar and the page
   title already says where you are, so it is the first thing to go. */
@media(max-width:700px){
  body{font-size:16px}
  .nav-in{gap:10px;padding:0 16px}
  .brand small{display:none}
  /* ⚠ ...THE NAV'S ONLY.  `.brand small` also matches the FOOTER wordmark,
     which had been dropping the ".ai" off the company's own name on every
     phone since the rebuild — for a width problem the footer does not have
     (it sits on its own row with the whole page to itself). */
  footer .brand small{display:inline}
  .nav-r{gap:8px}
  .nav-r .btn{padding:8px 13px}
  .wrap{padding:0 20px}
  .proof-in{padding:20px}
  .sec{padding:60px 0}
  .hero{padding:52px 0 46px}
  .end{padding:60px 0 68px}
  .g,.g2,.g3,.g4,.feat,.steps,.steps.s3,.plans,.plans.p3,.no,.people{grid-template-columns:1fr}
  .band{padding:32px 24px}
  .cmp{grid-template-columns:1fr 1fr}
  .cmp .h.blank{display:none}
  .cmp .k{grid-column:1/-1;background:var(--hair-2)}
  .team-shot img{aspect-ratio:4/3}
  .f-cols{grid-template-columns:1fr 1fr;gap:28px 20px}
  .f-top{flex-direction:column;align-items:flex-start;gap:16px}
  .f-bar .sp{margin-left:0;width:100%}
  .nav-r a.sign{display:none}
}

/* ⚠ THE PAGE NAME IS THE FIRST THING TO GO ON A PHONE.  It is the widest
   optional item in the bar ("/compliance" is 11 characters) and the hero
   headline underneath already says which page you are on, so losing it
   costs nothing and a horizontally scrolling page is the most obvious kind
   of broken there is.  Measured: without this rule the bar overflows below
   about 420px on the longest page names. */
@media(max-width:600px){ .brand-top,.nav-sep{display:none} }

/* ── legal pages (privacy, terms) ─────────────────────
   These two keep their original markup and their original words; only the
   chrome around them changed.  Legal text is the one thing on the site that
   must not be quietly reworded, so the rebuild rehoused it rather than
   rewriting it. */
.legal-wrap{max-width:820px;margin:0 auto;padding:64px 24px 88px}
.legal-eyebrow{font-size:12px;font-weight:600;letter-spacing:.11em;text-transform:uppercase;color:var(--accent)}
.legal-title{font-size:clamp(32px,4.6vw,46px);line-height:1.08;letter-spacing:-.026em;
  font-weight:700;margin:14px 0 10px}
.legal-meta{font-size:14.5px;color:var(--ink-2);margin-bottom:38px;padding-bottom:26px;
  border-bottom:1px solid var(--hair)}
.legal-section{margin-bottom:38px}
.legal-section h2{font-size:21px;line-height:1.3;letter-spacing:-.012em;font-weight:600;margin-bottom:12px}
.legal-section h3{font-size:17px;margin:20px 0 8px}
.legal-section p{font-size:16px;line-height:1.7;color:var(--ink-2);margin-bottom:12px}
.legal-section ul,.legal-section ol{margin:0 0 14px 20px}
.legal-section li{font-size:16px;line-height:1.7;color:var(--ink-2);margin-bottom:7px}
.legal-section a{color:var(--accent);text-decoration:underline;text-underline-offset:3px}
.legal-section strong,.legal-section b{color:var(--ink);font-weight:600}
.legal-section table{width:100%;border-collapse:collapse;margin:14px 0;font-size:15px}
.legal-section th,.legal-section td{text-align:left;padding:10px 12px;border:1px solid var(--hair);
  color:var(--ink-2);vertical-align:top}
.legal-section th{background:var(--surface);color:var(--ink);font-weight:600}
.legal-highlight{background:var(--accent-wash);border-radius:8px;padding:20px 22px;margin:20px 0}
.legal-highlight p{margin-bottom:0}
.legal-contact{background:var(--surface);border:1px solid var(--hair);border-radius:8px;
  padding:22px 24px;margin-top:34px}
.legal-contact p{margin-bottom:6px}
@media(max-width:700px){ .legal-wrap{padding:44px 20px 64px} }
