/* ═══════════════════════════════════════════════════════════
   SALERINGO DESIGN SYSTEM — site.css
   Global /en : "Ethereal Glass" dark   ·   /ko : corporate theme
   Order: tokens → base → nav → primitives → dark components →
          light components → ko components → utilities → responsive
   ═══════════════════════════════════════════════════════════ */

:root{
  /* Ledger: 종이 한 장, 잉크 하나, 강조색 하나. 2026-09-03 디자인 검수에서
     확정한 값. 강조색 #0B7878 은 종이(#F6F4EE) 위 4.8:1, 흰 글자 5.3:1. */
  --bg0:#F6F4EE; --bg1:#FFFFFF; --panel:#FFFFFF;
  --hair:rgba(20,26,31,.10); --hair2:rgba(20,26,31,.18);
  --hair-d:rgba(20,26,31,.14);
  --tx:#141A1F; --tx2:#3B454D; --tx3:#616B75;
  --teal:#0B7878; --teal-deep:#0A5F5F; --teal-glass:rgba(11,120,120,.10);
  --teal-ink:#0B7878;
  --amber-ink:#8D642F;
  --l-mut2:#616B75;
  --l-bg:#FFFFFF; --l-bg2:#FFFFFF; --l-ink:#141A1F; --l-mut:#4B555E; --l-hair:#E2DDD3;
  --l-tx2:var(--l-mut);
  --amber:#B7791F; --red:#C0392B; --green:#2F855A;
  --ease:cubic-bezier(.32,.72,0,1);
}

/* ── base ── */
*{margin:0;padding:0;box-sizing:border-box;}
html{-webkit-font-smoothing:antialiased;scroll-behavior:smooth;}
body{font-family:'IBM Plex Sans',sans-serif;background:var(--bg0);color:var(--tx);overflow-x:hidden;}
.sg{font-family:'Bricolage Grotesque',sans-serif;}

a{text-decoration:none;color:inherit;}
/* the focus contract lives at the end of this file - see "focus ring" below.
   At the top it lost the cascade to same-specificity component box-shadows. */
.wrap{max-width:1240px;margin:0 auto;padding:0 56px;}

/* ── floating island nav (dark) ── */
.navwrap{position:absolute;top:26px;left:0;right:0;display:flex;justify-content:center;z-index:20;}
.navwrap.fixednav{position:fixed;}
.nav{display:flex;align-items:center;gap:30px;background:rgba(20,26,31,.072);border:1px solid var(--hair2);
  border-radius:999px;padding:9px 9px 9px 26px;backdrop-filter:blur(18px);
  box-shadow:0 1px 0 rgba(20,26,31,.104) inset,0 24px 60px rgba(0,0,0,.45);}
.nav .logo{font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-lead);font-weight:700;letter-spacing:-.01em;color:#141A1F;}
.nav .logo b{color:var(--teal);}
.nav .links{display:flex;gap:26px;font-size:var(--fs-xs);font-weight:600;color:var(--tx2);}
.nav .links a:hover{color:#141A1F;}
.nav .links .on{color:#141A1F;}
.nav .sep{width:1px;height:22px;background:var(--hair2);}
.nav .loc{font-size:var(--fs-xs);font-weight:600;color:var(--tx2);letter-spacing:.06em;}
.nav .btn{padding:9px 9px 9px 20px;font-size:var(--fs-xs);}
.nav .btn .cir{width:28px;height:28px;font-size:var(--fs-xs);}
.nav .burger{display:none;flex-direction:column;gap:5px;background:none;border:0;cursor:pointer;padding:8px;}
.nav .burger span{width:22px;height:2px;background:#fff;transition:transform .4s var(--ease);}

/* ── primitives ── */
.eyebrow{display:inline-flex;align-items:center;gap:8px;border:1px solid var(--hair2);border-radius:999px;
  padding:7px 16px;font-size:var(--fs-2xs);font-weight:600;letter-spacing:.22em;text-transform:uppercase;color:var(--tx2);}
.eyebrow i{width:5px;height:5px;border-radius:50%;background:var(--teal);font-style:normal;}
.eyebrow.light{border-color:#DDE3EB;color:var(--l-mut);background:#fff;}

.btn{display:inline-flex;align-items:center;gap:12px;border-radius:999px;font-weight:700;font-size:var(--fs-sm);
  padding:8px 8px 8px 26px;cursor:pointer;border:0;font-family:inherit;transition:all .5s var(--ease);}
.btn .cir{width:34px;height:34px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:var(--fs-sm);transition:transform .5s var(--ease);}
.btn:hover .cir{transform:translate(2px,-1px);}
.btn:active{transform:scale(.98);}
.btn-white{background:#fff;color:#141A1F;box-shadow:0 1px 0 rgba(20,26,31,.6) inset,0 18px 50px rgba(0,0,0,.45);}
.btn-white .cir{background:rgba(20,26,31,.08);color:#141A1F;}
.btn-ghostd{border:1px solid var(--hair2);color:var(--tx);padding:14px 26px;background:rgba(20,26,31,.039);}
.btn-teal{background:linear-gradient(180deg,#0B7878,#0A5F5F);color:#FFFFFF;box-shadow:0 1px 0 rgba(20,26,31,.35) inset,0 16px 40px rgba(10,95,95,.35);}
.btn-teal .cir{background:rgba(0,0,0,.14);color:#141A1F;}
.btn-ghostl{border:1.5px solid #D5DBE4;color:var(--l-ink);padding:14px 26px;background:#fff;}

/* double bezel */
.shell{background:rgba(20,26,31,.058);border:1px solid var(--hair);border-radius:28px;padding:7px;
  box-shadow:0 1px 0 rgba(20,26,31,.091) inset,0 50px 120px rgba(0,0,0,.55);}
.core{background:linear-gradient(180deg,rgba(255,255,255,.92),rgba(255,255,255,.96));border:1px solid var(--hair);
  border-radius:14px;overflow:hidden;box-shadow:0 1px 1px rgba(20,26,31,.078) inset;}

/* industry chips */
.chiprow{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;}
.chip{font-size:var(--fs-xs);font-weight:600;color:var(--tx2);border:1px solid var(--hair);border-radius:999px;
  padding:8px 16px;background:rgba(20,26,31,.039);cursor:pointer;font-family:inherit;transition:all .4s var(--ease);}
.chip:hover{border-color:var(--hair2);color:var(--tx);}
.chip.on{background:var(--teal-glass);border-color:rgba(11,120,120,.45);color:var(--teal);}

/* demo chat */
.demo-head{display:flex;align-items:center;gap:10px;padding:16px 22px;border-bottom:1px solid var(--hair);}
.demo-head .dot{width:7px;height:7px;border-radius:50%;background:var(--green);box-shadow:0 0 10px rgba(49,208,139,.8);}
.demo-head span{font-size:var(--fs-xs);font-weight:600;color:var(--tx2);}
.demo-head .tag{margin-left:auto;font-size:var(--fs-2xs);font-weight:700;letter-spacing:.14em;color:var(--teal);
  border:1px solid rgba(11,120,120,.4);border-radius:999px;padding:4px 12px;}
.demo-body{padding:22px;display:flex;flex-direction:column;gap:13px;}
.bub{max-width:82%;font-size:var(--fs-xs);line-height:1.55;padding:12px 17px;border-radius:14px;font-weight:500;}
.bub.user{align-self:flex-end;background:rgba(20,26,31,.13);border:1px solid var(--hair);color:#141A1F;border-bottom-right-radius:5px;}
.bub.ai{align-self:flex-start;background:rgba(20,26,31,.058);border:1px solid var(--hair);color:#141A1F;border-bottom-left-radius:5px;}
.vchip{align-self:flex-start;display:inline-flex;gap:7px;align-items:center;font-size:var(--fs-2xs);font-weight:700;color:var(--teal);
  background:var(--teal-glass);border:1px solid rgba(11,120,120,.35);border-radius:999px;padding:5px 13px;}
.sec-light .hchip,.sec-light2 .hchip,.sec-paper .hchip,
.bg-paper .hchip,.bg-clinical .hchip{color:var(--amber-ink);}
.hchip{align-self:flex-start;display:inline-flex;gap:7px;align-items:center;font-size:var(--fs-2xs);font-weight:700;color:var(--amber);
  background:rgba(183,121,31,.10);border:1px solid rgba(183,121,31,.35);border-radius:999px;padding:5px 13px;}

/* dark section helpers */
.sec-dark{background:linear-gradient(180deg,#F6F4EE,#F6F4EE);}
.stars{position:absolute;inset:0;pointer-events:none;
  /* was .20 x .35 on 120px centres - about one visible dot per 14,400px2 */
  background-image:radial-gradient(rgba(255,255,255,.42) 1px, transparent 1px);
  background-size:86px 86px;opacity:.6;
  -webkit-mask-image:linear-gradient(180deg,#000 0%,transparent 70%);mask-image:linear-gradient(180deg,#000 0%,transparent 70%);}
.heroatmo{background:
  radial-gradient(1100px 620px at 22% -12%, rgba(11,120,120,.16), transparent 55%),
  radial-gradient(900px 600px at 86% 8%, rgba(255,255,255,.22), transparent 60%),
  radial-gradient(1400px 900px at 50% 120%, rgba(11,120,120,.10), transparent 55%),
  linear-gradient(180deg,var(--bg0) 0%,var(--bg1) 60%,#F6F4EE 100%);}

/* stats */
.statgrid{display:flex;justify-content:center;}
.stat{padding:0 60px;text-align:center;}
.stat + .stat{border-left:1px solid var(--hair);}
.stat .n{font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-num);font-weight:600;letter-spacing:-.05em;line-height:1;color:#141A1F;white-space:nowrap;}
.stat .n em{font-style:normal;color:var(--teal);}
.stat .n .pc{font-size:var(--fs-h2);color:var(--tx2);}
.stat .c{margin-top:18px;font-size:var(--fs-xs);line-height:1.6;color:var(--tx2);max-width:230px;font-weight:500;}

/* ── light components ── */
.sec-light{background:var(--l-bg);color:var(--l-ink);}
.sec-light2{background:var(--l-bg2);color:var(--l-ink);}
.h2{font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-h2);font-weight:600;letter-spacing:-.04em;line-height:1.06;color:var(--l-ink);}
.h2.onDark{color:var(--tx);}
.lead{font-size:var(--fs-body);line-height:1.75;color:var(--tx2);font-weight:500;}
.lead.onDark{color:var(--tx2);}
.linkcta{display:inline-flex;align-items:center;gap:10px;font-size:var(--fs-sm);font-weight:700;color:inherit;
  border-bottom:1.5px solid currentColor;padding-bottom:5px;}

.tray{background:#EDF0F4;border:1px solid #E2E7EE;border-radius:30px;padding:10px;
  box-shadow:0 2px 3px rgba(20,26,31,.03),0 40px 90px rgba(20,26,31,.10);}
.paper{background:#fff;border:1px solid var(--l-hair);border-radius:14px;overflow:hidden;}

.pilltag{font-size:var(--fs-2xs);font-weight:700;border-radius:999px;padding:6px 13px;}
.pt-dark{background:var(--l-ink);color:#141A1F;font-family:'Bricolage Grotesque',sans-serif;letter-spacing:.02em;}
.pt-teal{background:#E3F5F5;color:#0B7878;}
.pt-line{border:1px solid #D5DBE4;color:var(--l-mut);background:#fff;}
.pt-amber{background:#FAF0E1;color:#8D642F;}

/* step index rows */
.steps .step{display:flex;align-items:center;gap:26px;padding:26px 6px;border-bottom:1px solid var(--l-hair);}
.steps .num{font-family:'Bricolage Grotesque',sans-serif;flex:none;width:44px;height:44px;border-radius:50%;border:1px solid #D5DBE4;
  display:flex;align-items:center;justify-content:center;font-size:var(--fs-sm);font-weight:600;color:var(--l-mut);background:#fff;}
.steps .tx b{display:block;font-size:var(--fs-body);font-weight:700;letter-spacing:-.01em;}
.steps .tx span{display:block;margin-top:4px;font-size:var(--fs-xs);color:var(--l-mut);font-weight:500;}
.steps .tail{margin-left:auto;flex:none;}

/* knowledge console */
.ktabs{display:flex;gap:24px;padding:18px 26px;border-bottom:1px solid var(--l-hair);font-size:var(--fs-xs);font-weight:600;color:var(--l-mut);}
.ktabs .on{color:var(--l-ink);position:relative;}
.ktabs .on:after{content:"";position:absolute;left:0;right:0;bottom:-19px;height:2px;background:var(--teal-deep);}
.ktabs i{font-style:normal;font-size:var(--fs-2xs);font-weight:800;background:#EFF2F6;border-radius:999px;padding:2px 8px;margin-left:5px;}
.ktabs .warn i{background:#FBEAE8;color:#C0392B;}
.kconf{display:flex;gap:14px;align-items:center;background:#FDF6F4;border:1px solid #F4DCD7;border-radius:14px;margin:22px 26px 0;padding:15px 18px;}
.kconf .ic{flex:none;width:26px;height:26px;border-radius:50%;background:var(--red);color:#fff;font-weight:800;font-size:var(--fs-xs);display:flex;align-items:center;justify-content:center;}
.kconf b{display:block;font-size:var(--fs-xs);color:#B14A3E;}
.kconf span{display:block;font-size:var(--fs-xs);color:var(--l-mut);margin-top:2px;font-weight:500;}
.kconf .res{margin-left:auto;flex:none;font-size:var(--fs-xs);font-weight:700;color:#fff;background:var(--red);border-radius:999px;padding:8px 18px;}
.kfact{margin:20px 26px 26px;border:1px solid var(--l-hair);border-radius:14px;padding:20px 22px;background:#FDFDFE;}
.kfact .ty{font-size:var(--fs-label);font-weight:800;letter-spacing:.18em;color:#0B7878;}
.kfact .st{margin-top:8px;font-size:var(--fs-body);font-weight:600;letter-spacing:-.01em;line-height:1.5;color:var(--l-ink);}
.kfact .meta{margin-top:8px;font-size:var(--fs-xs);color:var(--l-mut);font-weight:500;}
.kfact .acts{margin-top:16px;display:flex;gap:10px;}
.kfact .ap{font-size:var(--fs-xs);font-weight:700;color:#fff;background:var(--teal-deep);border-radius:999px;padding:9px 22px;box-shadow:0 10px 24px rgba(10,95,95,.25);border:0;cursor:pointer;}
.kfact .ed{font-size:var(--fs-xs);font-weight:700;color:var(--l-ink);border:1px solid #D5DBE4;border-radius:999px;padding:8px 20px;background:#fff;cursor:pointer;}

/* industries bento */
.igrid{display:grid;grid-template-columns:repeat(12,1fr);grid-auto-rows:150px;gap:12px;}
.icard{position:relative;border-radius:14px;overflow:hidden;padding:24px;display:flex;flex-direction:column;justify-content:flex-end;
  box-shadow:0 1px 1px rgba(255,255,255,.25) inset,0 24px 60px rgba(20,26,31,.16);transition:transform .5s var(--ease);}
.icard:hover{transform:translateY(-4px);}
.icard .rank{position:absolute;top:20px;left:24px;font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-2xs);font-weight:600;letter-spacing:.2em;color:rgba(20,26,31,.5);}
.icard .arr{position:absolute;top:16px;right:16px;width:30px;height:30px;border-radius:50%;background:rgba(255,255,255,.12);
  border:1px solid rgba(255,255,255,.18);color:#141A1F;font-size:var(--fs-xs);display:flex;align-items:center;justify-content:center;}
.icard .lab{color:#141A1F;font-size:var(--fs-lead);font-weight:700;letter-spacing:-.015em;z-index:2;}
.icard .s{color:rgba(20,26,31,.66);font-size:var(--fs-xs);font-weight:600;margin-top:5px;z-index:2;}
.icard .istat{margin-top:14px;font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-xs);color:rgba(20,26,31,.85);font-weight:500;z-index:2;
  border-top:1px solid rgba(255,255,255,.15);padding-top:12px;}
.icard .istat b{font-size:var(--fs-h3);letter-spacing:-.03em;color:var(--teal);margin-right:8px;}
.icard svg.ghosticon{position:absolute;right:-14px;bottom:-16px;width:140px;height:140px;opacity:.14;stroke:#141A1F;fill:none;stroke-width:1.1;}
.g1{background:radial-gradient(500px 380px at 85% -20%, rgba(11,120,120,.35), transparent 60%),linear-gradient(150deg,#FFFFFF,#FFFFFF);}
.g2{background:linear-gradient(140deg,#0A5F5F,#0A5F5F);}
.g3{background:linear-gradient(140deg,#24518F,#FFFFFF);}
.g4{background:linear-gradient(140deg,#0C8686,#FFFFFF);}
.g5{background:linear-gradient(140deg,#FFFFFF,#FFFFFF);}
.g6{background:linear-gradient(140deg,#0E7C8C,#FFFFFF);}
.g7{background:linear-gradient(140deg,#FFFFFF,#FFFFFF);}
.g8{background:linear-gradient(140deg,#FFFFFF,#FFFFFF);}

/* pricing */
.plans{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;max-width:1060px;margin:0 auto;}
.ptray{background:#F1F3F7;border:1px solid #E5E9EF;border-radius:28px;padding:8px;}
.ptray.hot{background:linear-gradient(180deg,rgba(11,120,120,.25),rgba(11,120,120,.06)),#F1F3F7;}
.plan{background:#fff;border:1px solid var(--l-hair);border-radius:14px;padding:30px 28px;height:100%;position:relative;color:var(--l-ink);}
.plan.dark{background:linear-gradient(180deg,#FFFFFF,#F6F4EE);border-color:rgba(20,26,31,.13);color:#fff;
  box-shadow:0 1px 1px rgba(20,26,31,.104) inset;}
.plan .pop{position:absolute;top:24px;right:24px;font-size:var(--fs-label);font-weight:800;letter-spacing:.16em;color:var(--teal);
  border:1px solid rgba(11,120,120,.45);border-radius:999px;padding:4px 11px;}
.plan .nm{font-size:var(--fs-xs);font-weight:800;letter-spacing:.14em;text-transform:uppercase;color:var(--l-mut);}
.plan.dark .nm{color:var(--tx2);}
.plan .pr{margin-top:14px;font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-h2);font-weight:600;letter-spacing:-.04em;}
.plan .pr small{font-size:var(--fs-sm);font-weight:500;color:var(--l-mut);letter-spacing:0;}
.plan.dark .pr small{color:var(--tx2);}
.plan ul{margin-top:20px;list-style:none;font-size:var(--fs-xs);line-height:2.15;color:var(--l-mut);font-weight:500;}
.plan.dark ul{color:#141A1F;}
.plan ul b{color:var(--l-ink);font-weight:700;}
.plan.dark ul b{color:#141A1F;}
.plan .cta{margin-top:24px;display:flex;justify-content:center;border-radius:999px;padding:13px 0;font-size:var(--fs-xs);font-weight:700;
  border:1px solid #D5DBE4;color:var(--l-ink);background:#fff;}
.plan .cta.teal{background:linear-gradient(180deg,#0B7878,#0A5F5F);border:none;color:#FFFFFF;box-shadow:0 14px 34px rgba(10,95,95,.35);}

/* dark footer */
.sitefooter{border-top:1px solid var(--hair);padding:30px 0;background:var(--bg0);}
.sitefooter .wrap{display:flex;align-items:center;font-size:var(--fs-xs);color:var(--tx3);font-weight:500;flex-wrap:wrap;gap:10px;}
.sitefooter .logo{font-family:'Bricolage Grotesque',sans-serif;font-weight:700;color:#141A1F;font-size:var(--fs-body);margin-right:14px;}
.sitefooter .logo b{color:var(--teal);}
.sitefooter .links{margin-left:auto;display:flex;gap:26px;}
.sitefooter .links a:hover{color:var(--tx);}


/* ── utilities ── */
.tac{text-align:center;}
/* reveal is progressive enhancement: hidden ONLY when JS tagged <html class="srjs"> */
.srjs .reveal{opacity:0;transform:translateY(28px);transition:opacity .9s var(--ease), transform .9s var(--ease);}
.srjs .reveal.vis{opacity:1;transform:none;}
@media (prefers-reduced-motion: reduce){
  .reveal{opacity:1;transform:none;transition:none;}
  html{scroll-behavior:auto;}
}

/* comparison table (verified-ai) */
.cmp{width:100%;border-collapse:collapse;font-size:var(--fs-sm);}
.cmp th,.cmp td{padding:16px 20px;text-align:left;border-bottom:1px solid var(--l-hair);vertical-align:top;line-height:1.6;}
.cmp th{font-size:var(--fs-xs);letter-spacing:.1em;text-transform:uppercase;color:var(--l-mut);}
.cmp td:first-child{font-weight:700;color:var(--l-ink);width:26%;}
.cmp .bad{color:var(--l-mut);}
.cmp .good{color:var(--l-ink);font-weight:600;}
.cmp .good b{color:#0B7878;}

/* faq */
/* A section reads as one column or it reads as two mistakes. The heading
   above a FAQ is left-aligned at the header width; the list was centred at
   760px, so on every trade page the questions started 184px to the right of
   the heading that introduced them — measured 136px of skew across the
   section on fourteen pages. The list starts where its heading starts.
   Where the heading is deliberately centred, the list still is too. */
.faq{max-width:760px;margin:0;}
section:has(> .wrap > .head.mid) .faq,
section:has(> .wrap > .head.centered) .faq,
.head.mid ~ .faq,.head.centered ~ .faq{margin-left:auto;margin-right:auto;}
.faq details{border-bottom:1px solid var(--l-hair);padding:22px 6px;}
.faq summary{font-size:var(--fs-body);font-weight:700;cursor:pointer;color:inherit;list-style:none;display:flex;}

.faq summary:after{content:"+";margin-left:auto;color:var(--teal-ink);font-weight:600;}
.faq details[open] summary:after{content:"–";}
.faq p{margin-top:14px;font-size:var(--fs-sm);line-height:1.8;color:var(--tx2);max-width:var(--measure);}
/* --tx2 not --l-mut: this block runs on dark sections too, where a light
   ink measured 3.43:1. The light-surface contract maps --tx2 to --l-mut. */

/* ── responsive ── */
@media (max-width: 900px){
  
  .nav .links,.nav .sep,.nav .loc{display:none;}
  .nav .burger{display:flex;}
  .statgrid{flex-direction:column;gap:44px;}
  .stat + .stat{border-left:0;border-top:1px solid var(--hair);padding-top:44px;}
  .igrid{grid-template-columns:1fr;grid-auto-rows:170px;}
  .igrid > *{grid-column:span 1 !important;grid-row:span 1 !important;}
  .plans{grid-template-columns:1fr;}
  /* h1 has balanced since it was written; h2 did not, and at 375px that is where
   the damage showed. A heading is authored with &nbsp; so the pairs that belong
   together stay together on a wide screen; on a narrow one the bound pair no
   longer fits the remaining space and drops whole, stranding whatever preceded
   it. Measured at 375: "Nine rooms. One product. / Eight / different
   vocabularies.", "and one thing it will / not do.", "your language. Your /
   AI does." Balancing distributes the words across the lines it is going to
   use anyway, which is what the author meant in the first place. */
/* Section headings are composed for a wide measure: the author's <br> puts the
   break at the sentence seam and &nbsp; holds the pairs that belong together.
   At 375px the measure is a third as wide, so the forced break is followed by a
   second, natural one, and that one lands wherever it falls — measured:
   "Nine rooms. One product. / Eight / different vocabularies.",
   "and one thing it will / not do.", "your language. Your / AI does."

   Dropping the authored break on a phone lets the same words find their own
   lines, with the &nbsp; pairs still intact. Same heading, measured after:
   "Nine rooms. / One product. / Eight different vocabularies."

   h1 is left alone — hero headlines carry colour changes across the break, and
   each one is composed and measured by hand. */
@media (max-width:620px){ h2 br,.h2 br{display:none;} }
.h2{font-size:var(--fs-h2);}
}

/* ═══════════════════════════════════════════════════════════
   V2 VISUAL COMPONENTS — channel-led redesign
   Device frames, call transcript, messaging thread, waveform,
   world map, avatars, integration chips, channel colors
   ═══════════════════════════════════════════════════════════ */
:root{
  --chan-voice:#0B7878;   /* AI Phone  */
  --chan-chat:#2C63B8;    /* Chatbot   */
  --chan-msg:#2F855A;     /* Messaging */
}

/* channel badge */
.chanbadge{display:inline-flex;align-items:center;gap:8px;font-size:var(--fs-2xs);font-weight:800;letter-spacing:.14em;
  text-transform:uppercase;border-radius:999px;padding:6px 14px;}
.chanbadge.voice{color:var(--chan-voice);background:rgba(11,120,120,.12);border:1px solid rgba(11,120,120,.35);}
.chanbadge.chat{color:var(--chan-chat);background:rgba(44,99,184,.12);border:1px solid rgba(44,99,184,.35);}
.chanbadge.msg{color:var(--chan-msg);background:rgba(47,133,90,.12);border:1px solid rgba(47,133,90,.35);}

/* browser frame (product screenshots) */
.browserframe{border-radius:14px;overflow:hidden;border:1px solid var(--hair);background:#FFFFFF;
  box-shadow:0 40px 90px rgba(0,0,0,.5);}
.browserframe .bar{display:flex;align-items:center;gap:7px;padding:11px 14px;border-bottom:1px solid var(--hair);background:rgba(20,26,31,.052);}
.browserframe .bar i{width:9px;height:9px;border-radius:50%;background:rgba(20,26,31,.234);font-style:normal;}
.browserframe .bar .url{margin-left:10px;flex:1;max-width:320px;font-size:var(--fs-2xs);color:var(--tx3);background:rgba(20,26,31,.065);
  border-radius:999px;padding:4px 12px;font-weight:600;}
.browserframe.light{background:#fff;border-color:var(--l-hair);}
.browserframe.light .bar{background:#F4F6F9;border-color:var(--l-hair);}
.browserframe.light .bar .url{background:#fff;color:#6F767F;}

/* phone device frame */
.phoneframe{width:290px;border-radius:38px;border:1px solid var(--hair2);padding:10px;
  background:linear-gradient(180deg,rgba(20,26,31,.104),rgba(20,26,31,.026));
  box-shadow:0 1px 0 rgba(20,26,31,.13) inset,0 44px 90px rgba(0,0,0,.55);}
.phoneframe .screen{border-radius:30px;overflow:hidden;background:linear-gradient(180deg,#FFFFFF,#FFFFFF);
  border:1px solid var(--hair);min-height:420px;position:relative;}
.phoneframe .notch{width:96px;height:22px;background:#FFFFFF;border-radius:0 0 14px 14px;margin:0 auto;}

/* live call card */
.callcard{padding:22px 20px;display:flex;flex-direction:column;gap:14px;}
.callcard .callhead{display:flex;align-items:center;gap:12px;}
.callcard .callhead .who b{display:block;font-size:var(--fs-sm);color:#141A1F;}
.callcard .callhead .who span{font-size:var(--fs-2xs);color:var(--tx3);font-weight:600;}
.callcard .timer{margin-left:auto;font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-xs);color:var(--chan-voice);font-weight:600;}
.avatar{width:38px;height:38px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  font-size:var(--fs-xs);font-weight:800;color:#141A1F;flex:none;}
.av-a{background:linear-gradient(140deg,#24518F,#FFFFFF);}
.av-b{background:linear-gradient(140deg,#0A5F5F,#0A5F5F);}
.av-c{background:linear-gradient(140deg,#7A5CC7,#FFFFFF);}
.av-d{background:linear-gradient(140deg,#C7695C,#FFFFFF);}

/* waveform */
.wave{display:flex;align-items:center;gap:3px;height:26px;}
.wave i{width:3px;border-radius:2px;background:var(--chan-voice);opacity:.85;font-style:normal;height:30%;}
.wave i:nth-child(2n){height:75%;} .wave i:nth-child(3n){height:50%;}
.wave i:nth-child(5n){height:95%;} .wave i:nth-child(7n){height:38%;}
@keyframes wavepulse{0%,100%{transform:scaleY(.6);}50%{transform:scaleY(1.15);}}
.srjs .wave.live i{animation:wavepulse 1.1s var(--ease) infinite;}
.srjs .wave.live i:nth-child(2n){animation-delay:.12s;} .srjs .wave.live i:nth-child(3n){animation-delay:.25s;}
@media (prefers-reduced-motion: reduce){.wave.live i{animation:none;}}

/* call transcript rows */
.transcript{display:flex;flex-direction:column;gap:11px;}
.transcript .line{display:flex;gap:10px;font-size:var(--fs-xs);line-height:1.6;}
.transcript .spk{flex:none;font-size:var(--fs-label);font-weight:800;letter-spacing:.08em;
  margin-top:3px;width:56px;}   /* 34px could not hold "CALLER" at the new floor */
.transcript .spk.ai{color:var(--chan-voice);} .transcript .spk.cu{color:var(--tx3);}
.transcript .tx{color:#141A1F;font-weight:500;}
.transcript .tx em{font-style:normal;color:var(--chan-voice);font-weight:700;}

/* messaging thread (generic messenger style, brand-safe) */
.msgthread{border-radius:14px;overflow:hidden;border:1px solid var(--hair);background:#FFFFFF;}
.msgthread .mhead{display:flex;align-items:center;gap:11px;padding:13px 16px;background:rgba(47,133,90,.10);border-bottom:1px solid var(--hair);}
.msgthread .mhead b{font-size:var(--fs-xs);color:#141A1F;}
.msgthread .mhead span{font-size:var(--fs-2xs);color:var(--chan-msg);font-weight:700;}
.msgthread .mbody{padding:18px 16px;display:flex;flex-direction:column;gap:10px;}
.msgthread .m{max-width:84%;font-size:var(--fs-xs);line-height:1.55;padding:10px 14px;border-radius:8px;font-weight:500;}
.msgthread .m.in{align-self:flex-start;background:rgba(20,26,31,.091);color:#141A1F;border-bottom-left-radius:4px;}
.msgthread .m.out{align-self:flex-end;background:rgba(47,133,90,.16);border:1px solid rgba(47,133,90,.25);color:#141A1F;border-bottom-right-radius:4px;}
.msgthread .m .tick{font-size:var(--fs-label);color:var(--chan-msg);margin-left:6px;}

/* typing indicator */
.typing{display:inline-flex;gap:4px;padding:10px 14px;background:rgba(20,26,31,.091);border-radius:8px;align-self:flex-start;}
.typing i{width:5px;height:5px;border-radius:50%;background:var(--tx2);font-style:normal;}
@keyframes tblink{0%,80%,100%{opacity:.25;}40%{opacity:1;}}
.srjs .typing i{animation:tblink 1.2s infinite;} .srjs .typing i:nth-child(2){animation-delay:.2s;} .srjs .typing i:nth-child(3){animation-delay:.4s;}

/* world map section */
.mapwrap{position:relative;}
.mapwrap svg{width:100%;height:auto;display:block;opacity:.9;}
.mapdot{fill:var(--teal);}
.maplabel{font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-label);fill:var(--tx2);letter-spacing:.08em;}

/* integration chips */
.intwall{display:flex;flex-wrap:wrap;gap:10px;justify-content:center;}
.intchip{font-size:var(--fs-xs);font-weight:700;color:var(--tx2);border:1px solid var(--hair);border-radius:8px;
  padding:12px 20px;background:rgba(20,26,31,.039);display:inline-flex;align-items:center;gap:9px;}
.intchip i{width:8px;height:8px;border-radius:2.5px;font-style:normal;}
.intchip.light{color:var(--l-mut);border-color:#DDE3EB;background:#fff;}

/* scenario / proof cards */
.scene{border-radius:14px;overflow:hidden;position:relative;padding:26px;min-height:220px;
  display:flex;flex-direction:column;justify-content:flex-end;
  box-shadow:0 1px 1px rgba(20,26,31,.26) inset,0 26px 60px rgba(20,26,31,.18);}
.scene .t{font-size:var(--fs-lead);font-weight:800;color:#141A1F;letter-spacing:-.01em;}
.scene .d{margin-top:6px;font-size:var(--fs-xs);color:rgba(20,26,31,.72);font-weight:500;line-height:1.6;}
.scene .num{font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-h2s);font-weight:600;color:#141A1F;margin-bottom:4px;}
.scene .num em{font-style:normal;color:var(--teal);}

/* KPI band */
.kpiband{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;}
.kpi{border:1px solid var(--hair);border-radius:14px;padding:22px;background:rgba(20,26,31,.039);}
.kpi .n{font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-h2);font-weight:600;color:#141A1F;letter-spacing:-.03em;}
.kpi .n em{font-style:normal;color:var(--teal);}
.kpi .l{margin-top:6px;font-size:var(--fs-2xs);color:var(--tx2);font-weight:600;line-height:1.5;}
.kpi.light{background:#fff;border-color:var(--l-hair);}
.kpi.light .n{color:var(--l-ink);}

/* language ribbon */
.langrow{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;}
.langchip{font-size:var(--fs-2xs);font-weight:700;color:var(--tx2);border:1px solid var(--hair);border-radius:999px;padding:6px 13px;}
.langchip.hi{color:var(--teal);border-color:rgba(11,120,120,.4);}

@media (max-width:900px){
  .kpiband{grid-template-columns:1fr 1fr;}
  .phoneframe{width:250px;}
}

/* v2 additions: result chip, spec strip, mobile nav dropdown, hero responsive */
.rchip{align-self:flex-start;display:inline-flex;gap:7px;align-items:center;font-size:var(--fs-2xs);font-weight:700;color:#141A1F;
  background:rgba(44,99,184,.10);border:1px solid rgba(44,99,184,.35);border-radius:999px;padding:5px 13px;}
.specstrip{display:flex;gap:26px;justify-content:center;flex-wrap:wrap;font-size:var(--fs-xs);font-weight:600;color:var(--tx2);}
.specstrip b{color:#141A1F;font-weight:700;}
.specstrip i{font-style:normal;color:var(--teal);margin-right:7px;}
.nav .links.open{display:flex;position:absolute;top:64px;left:0;right:0;flex-direction:column;gap:0;
  background:rgba(255,255,255,.97);border:1px solid var(--hair2);border-radius:14px;padding:14px;}
.nav .links.open a{padding:12px 16px;font-size:var(--fs-body);}
.eaform{display:grid;grid-template-columns:repeat(2,1fr);gap:12px;max-width:640px;margin:0 auto;}
.eaform input,.eaform select{background:rgba(20,26,31,.065);border:1px solid var(--hair2);border-radius:8px;
  padding:14px 16px;color:#141A1F;font-family:inherit;font-size:var(--fs-sm);font-weight:500;width:100%;}
.eaform input::placeholder{color:var(--tx3);}
.eaform select{appearance:none;}
.eaform .full{grid-column:span 2;}
.eaform button{grid-column:span 2;justify-content:center;}
.eanote{margin-top:14px;font-size:var(--fs-2xs);color:var(--tx3);text-align:center;font-weight:500;}
.eafallback{margin-top:12px;text-align:left;}
.eafallback-text{display:block;width:100%;background:rgba(20,26,31,.065);border:1px solid var(--hair2);border-radius:8px;
  padding:12px 14px;color:var(--tx2);font-family:inherit;font-size:var(--fs-xs);line-height:1.6;font-weight:500;resize:vertical;}
.eafallback-row{margin-top:10px;display:flex;gap:12px;align-items:center;flex-wrap:wrap;}
.eafallback-copy{background:var(--teal);border:0;border-radius:999px;padding:9px 18px;font-family:inherit;
  font-size:var(--fs-xs);font-weight:700;color:#141A1F;cursor:pointer;}
.eafallback-addr{font-size:var(--fs-xs);color:var(--tx3);font-weight:500;}
.eafallback-addr b{color:var(--tx2);}
.mailtonote{position:fixed;left:50%;bottom:26px;transform:translate(-50%,16px);z-index:99;display:flex;gap:14px;align-items:center;
  background:rgba(255,255,255,.96);border:1px solid var(--hair2);border-radius:999px;padding:12px 12px 12px 20px;
  font-size:var(--fs-xs);color:var(--tx2);font-weight:500;box-shadow:0 20px 50px rgba(0,0,0,.4);
  opacity:0;pointer-events:none;transition:opacity .35s ease,transform .35s ease;}
.mailtonote b{color:#141A1F;}
.mailtonote.show{opacity:1;pointer-events:auto;transform:translate(-50%,0);}
.mailtonote button{background:var(--teal);border:0;border-radius:999px;padding:8px 15px;font-family:inherit;
  font-size:var(--fs-2xs);font-weight:700;color:#141A1F;cursor:pointer;white-space:nowrap;}
.inboxmock{display:grid;grid-template-columns:200px 1.4fr 1fr;border-radius:14px;overflow:hidden;
  border:1px solid var(--l-hair);background:#fff;box-shadow:0 30px 70px rgba(20,26,31,.12);font-size:var(--fs-xs);}
.inboxmock .col{padding:16px;border-right:1px solid var(--l-hair);min-height:340px;}
.inboxmock .col:last-child{border-right:0;}
.convrow{display:flex;gap:10px;align-items:center;padding:11px 10px;border-radius:8px;}
.convrow.on{background:#F0F6F6;}
.convrow .cv b{display:block;font-size:var(--fs-xs);color:var(--l-ink);}
.convrow .cv span{display:block;font-size:var(--fs-2xs);color:var(--l-mut);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:180px;}
.convrow .st{margin-left:auto;flex:none;font-size:var(--fs-label);font-weight:800;border-radius:999px;padding:3px 8px;}
.st-ai{background:#E3F5F5;color:#0B7878;}
.st-hu{background:#FAF0E1;color:#8D642F;}
.chanmini{display:inline-flex;width:20px;height:20px;border-radius:6px;align-items:center;justify-content:center;font-size:var(--fs-label);flex:none;}
/* --teal-ink is tuned against a plain light surface; on the chip's own
   teal tint it lands at 4.30. One shade down clears it. */
.cm-v{background:rgba(11,120,120,.15);color:#141A1F;}
.cm-c{background:rgba(44,99,184,.15);color:#2C63B8;}
.cm-m{background:rgba(47,133,90,.15);color:#1E9E63;}
@media (max-width:1240px){
  .cascade-flex{flex-wrap:wrap;justify-content:center;}
}
@media (max-width:900px){
  .eaform{grid-template-columns:1fr;}
  .eaform .full,.eaform button{grid-column:span 1;}
  .inboxmock{grid-template-columns:1fr;}
  .inboxmock .col{border-right:0;border-bottom:1px solid var(--l-hair);min-height:0;}
  .specstrip{gap:14px;}
}

/* ═══════════════════════════════════════════════════════════
   SHARED PAGE FURNITURE — hoisted out of per-page <style> blocks
   (DEV_SPEC 8: no duplicate definition of the same component).
   Page-local <style> still wins where a page genuinely tunes it.
   ═══════════════════════════════════════════════════════════ */

/* result chip row — closes a demo transcript / call card */
.resultrow{display:flex;gap:8px;flex-wrap:wrap;padding:14px 18px;border-top:1px solid var(--hair);}

/* sticky-CTA gate marker (site.js watches this) */
#cta-gate{height:1px;}

/* closing band */
.closer{position:relative;padding:140px 0 0;text-align:center;overflow:hidden;}
.closer h2{font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-h1);font-weight:600;
  letter-spacing:-.045em;color:#141A1F;line-height:1.06;position:relative;}
.closer h2 em{font-style:normal;color:var(--teal);}
.closer .lead{margin:22px auto 0;max-width:520px;position:relative;}
.closer .ctas{margin-top:38px;display:flex;justify-content:center;gap:16px;position:relative;flex-wrap:wrap;}
.closer .trust{margin-top:22px;font-size:var(--fs-xs);color:var(--tx3);font-weight:500;position:relative;}
.closer .more{margin-top:24px;font-size:var(--fs-xs);color:var(--tx3);font-weight:500;position:relative;}
.closer .trust a,.closer .more a{color:var(--tx2);}

/* big footer */
.bigfooter{margin-top:120px;border-top:1px solid var(--hair);padding:60px 0 40px;text-align:left;position:relative;}
.bigfooter .cols{display:grid;grid-template-columns:1.4fr 1fr 1fr 1fr;gap:50px;}
.bigfooter .brand .logo{font-family:'Bricolage Grotesque',sans-serif;font-weight:700;color:#141A1F;font-size:var(--fs-lead);}
.bigfooter .brand .logo b{color:var(--teal);}
.bigfooter .brand p{margin-top:14px;font-size:var(--fs-xs);line-height:1.8;color:var(--tx3);font-weight:500;max-width:240px;}
.bigfooter .hl3,.bigfooter h3{font-size:var(--fs-2xs);font-weight:800;letter-spacing:.18em;text-transform:uppercase;color:var(--tx2);margin-bottom:16px;}
.bigfooter .lnk{display:block;font-size:var(--fs-xs);color:var(--tx3);font-weight:500;padding:5px 0;}
.bigfooter .lnk:hover{color:var(--tx);}
.bigfooter .base{margin-top:50px;padding-top:24px;border-top:1px solid var(--hair);display:flex;
  font-size:var(--fs-2xs);color:var(--tx3);font-weight:500;flex-wrap:wrap;gap:10px;}
.bigfooter .base .r{margin-left:auto;display:flex;gap:22px;}
@media (max-width:900px){.bigfooter .cols{grid-template-columns:1fr 1fr;}}

/* venues fact bar text column (was an undefined .ft) */
.fbar .ft{flex:1;min-width:0;}

/* screen-reader-only helper (used by table captions) */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0;}

/* ═══════════════════════════════════════════════════════════
   v3 SYSTEM PASS — audit remediation
   ───────────────────────────────────────────────────────────
   Three scoring agents (owner-buyer 34/100, marketing 46/100,
   design 52/100) converged on the same structural faults:
   flat vertical rhythm (81 of ~130 sections inside a 32px
   padding band), a compressed type scale (H1:H2 = 1.36), one
   breakpoint carrying the whole site, 23 :hover rules across
   20 pages, and even grids at 67% of all declarations.
   Everything below is system-level so pages inherit the fix.
   ═══════════════════════════════════════════════════════════ */

:root{
  /* modular type scale — replaces per-page clamp() overrides */
  --fs-display: clamp(56px, 8.5vw, 128px);
  --fs-h1:      clamp(40px, 5.4vw, 76px);
  --fs-h2:      clamp(30px, 3.4vw, 48px);
  --fs-h3:      clamp(20px, 1.7vw, 24px);
  /* Below h3 the steps have to stay above about 1.17x. Under that a reader does
     not perceive hierarchy, only something slightly wrong — which is what six
     tokens crammed between 10px and 18.5px were doing. Four steps, each visibly
     different from its neighbour. --fs-2xs and --fs-num are kept as aliases so
     the ~260 call sites that reference them keep resolving. */
  --fs-h2s:     clamp(24px, 2.4vw, 32px);   /* sub-head, between h2 and h3 */
  --fs-lead:    clamp(17px, 1.35vw, 20px);  /* section standfirst */
  --fs-body:    17px;                        /* running text        1.18x */
  --fs-sm:      14.5px;                      /* secondary, captions 1.17x */
  /* 271 text nodes on the homepage alone computed below 13px, almost all of
     them from these two tokens: product-mock rows, table headers, pill tags,
     captions, chart labels. 13px is the floor at which small UI text stays
     readable at arm's length; 11.5px is the floor for an uppercase label,
     which reads larger than its cap height suggests. */
  /* Re-measured across all 26 English pages at 1440x900 with fonts.ready
     awaited: 8,636 rendered text nodes still sat below 14px, 2,622 of them on
     seven pages alone. Practically every one traced back to these two tokens —
     nothing in the HTML sets a small size in CSS; the only literals left are
     SVG font-size attributes, handled at the end of this file. The floor is
     14px for anything a visitor reads as body or caption text, 13px for a
     label inside a figure or a product mock. Both tokens now clear it, so the
     floor holds by construction instead of page by page. */
  --fs-xs:      14px;                        /* dense product UI            */
  --fs-label:   13px;                        /* uppercase labels            */
  --fs-2xs:     var(--fs-xs);                /* alias — was a 1.10x step */
  --fs-num:     var(--fs-display);           /* alias — was identical at 128px */
  /* The nav is fixed at a constant height, so the gap beneath it is one number,
     not the thirteen that had accumulated across eleven class names. */
  /* 172px left 81px of air between the nav and the hero panel on a 900px
     screen, and pushed the second call to action under the docked bar on
     several pages. 144px keeps 53px of clearance — still deliberate space,
     28px of it returned to the part of the page that has to sell. */
  --pad-hero:   144px;
  /* three tempos so the page can inhale and exhale */
  --pad-xl:184px; --pad-md:112px; --pad-sm:56px;
  /* page accent — overridden per channel below */
  --accent:var(--teal);
}
@media (max-width:900px){ :root{ --pad-xl:96px; --pad-md:64px; --pad-sm:36px; } }
/* On a phone the three tempos are read as one long pause: a 375px column has
   no room to inhale, so 96px of nothing between sections just pushes the next
   argument another half-screen away. Thirteen sections make that about 600px
   per page. The rhythm is kept — xl is still twice sm — at two thirds the cost. */
@media (max-width:640px){ :root{ --pad-xl:64px; --pad-md:44px; --pad-sm:28px; --pad-hero:96px; } }

.t-xl{padding:var(--pad-xl) 0;}
.t-md{padding:var(--pad-md) 0;}
.t-sm{padding:var(--pad-sm) 0;border-block:1px solid var(--hair);}
.sec-light .t-sm,.t-sm.sec-light{border-block-color:var(--l-hair);}

/* fluid headings — the 52px→36px cliff at 900px is gone */
.h2{font-size:var(--fs-h2);}
.lead{font-size:var(--fs-lead);line-height:1.72;max-width:var(--measure);}
.display{font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-display);
  font-weight:600;letter-spacing:-.055em;line-height:.92;color:#141A1F;}
h1{font-size:var(--fs-h1);font-family:'Bricolage Grotesque',sans-serif;font-weight:600;
  /* 17ch was tighter than a display face needs. Measured across all 26 pages
     with the webfonts loaded, 20ch costs one line on five of them and adds one
     on none: cross-border 3->2, examples 4->3, industries 3->2, integrations
     3->2, verified-ai 5->4. On verified-ai that is 171px, which is the
     difference between opening with a button in view and without one. No page
     overflows its column and nothing changes below 620px. */
  letter-spacing:-.045em;line-height:1.03;max-width:20ch;text-wrap:balance;}
h1 .quiet{color:var(--tx2);font-weight:500;}
h1 .huge{display:block;font-size:1.42em;letter-spacing:-.06em;}
.h2{max-width:21ch;}
.sub{max-width:var(--measure);}

/* numbers were fixed-px + nowrap and only survived via overflow-x:hidden */
.stat .n{font-size:var(--fs-num);}
.stat .n .pc{font-size:.48em;}
.stat .c{max-width:23ch;}
.plan .pr{font-size:var(--fs-h2);}
.calcout .big{font-size:var(--fs-h1);}
.igrid > *,.plans > *,.altgrid > *,.statgrid > *{min-width:0;}

/* ── per-page accent: three channel pages stop being identical teal ── */
body{--accent-deep:var(--teal-deep);--accent-glass:var(--teal-glass);}
body[data-chan="voice"]{--accent:#0B7878;--accent-deep:#0A5F5F;--accent-glass:rgba(11,120,120,.13);}
body[data-chan="chat"] {--accent:#2C63B8;--accent-deep:#2C6FE0;--accent-glass:rgba(44,99,184,.13);}
body[data-chan="msg"]  {--accent:#2F855A;--accent-deep:#1E9E6A;--accent-glass:rgba(47,133,90,.13);}
/* the surfaces that actually carry the colour, not just the eyebrow dot */
body[data-chan] .btn-teal{background:linear-gradient(180deg,var(--accent),var(--accent-deep));
  box-shadow:0 1px 0 rgba(20,26,31,.35) inset,
             0 16px 40px color-mix(in srgb,var(--accent-deep) 35%,transparent);}
body[data-chan] .chip.on{background:var(--accent-glass);
  border-color:color-mix(in srgb,var(--accent) 45%,transparent);color:var(--accent);}
.eyebrow i,.nav .logo b,.photocard .kicker,.stat .n em,.vchip,.gradtext{color:var(--accent);}
.eyebrow{border-color:color-mix(in srgb,var(--accent) 34%,transparent);}
/* removed: tying the focus ring to --accent painted it the same colour as
   the button it outlined. The ring above is fixed and always contrasts. */

/* ── shared hover contract (was: 23 rules across 20 pages) ── */
.icard,.photocard,.plan,.thumb,.pack,.audcard{
  transition:transform .55s var(--ease),border-color .35s var(--ease),box-shadow .55s var(--ease);}
.icard:hover,.photocard:hover,.plan:hover,.thumb:hover,.pack:hover,.audcard:hover{
  transform:translateY(-6px);
  border-color:color-mix(in srgb,var(--accent) 42%,transparent);
  box-shadow:0 1px 0 rgba(255,255,255,.10) inset,0 34px 70px rgba(0,0,0,.5),
             0 0 0 1px color-mix(in srgb,var(--accent) 14%,transparent);}
.photocard::after{transition:opacity .55s var(--ease);}
.photocard:hover::after{opacity:.74;}
.icard .go{display:inline-block;transition:transform .45s var(--ease);}
.icard:hover .go{transform:translateX(5px);}
.icard:active,.photocard:active,.plan:active,.thumb:active{transform:translateY(-2px);}
@media (hover:none){
  .icard:hover,.photocard:hover,.plan:hover,.thumb:hover,.pack:hover,.audcard:hover{
    transform:none;box-shadow:none;}
}

/* ── staggered reveal — index set by the observer in site.js ── */
.srjs .reveal{transform:translateY(22px);
  transition:opacity .7s var(--ease),transform .7s var(--ease);
  transition-delay:calc(var(--i,0) * 70ms);}

/* ── editorial bento: breaks the 67%-even-grid monotony ── */
.bento{display:grid;gap:16px;grid-template-columns:repeat(6,1fr);grid-auto-rows:200px;}
.bento > :nth-child(1){grid-column:span 4;grid-row:span 2;}
.bento > :nth-child(2){grid-column:span 2;}
.bento > :nth-child(3){grid-column:span 2;}
.bento > :nth-child(4){grid-column:span 2;grid-row:span 2;}
.bento > :nth-child(5){grid-column:span 4;grid-row:span 2;}
.bento > :nth-child(6){grid-column:span 3;}
.bento > :nth-child(7){grid-column:span 3;}

/* ── the missing breakpoints: one @900 was the whole strategy ── */
@media (max-width:1180px){
  .wrap{padding:0 36px;}
  .thumbstrip{grid-template-columns:repeat(2,1fr);}
  .photosplit .copy{padding:60px 44px;}
  .plans{grid-template-columns:repeat(2,1fr);}
  .bento{grid-template-columns:repeat(4,1fr);}
  .bento > *{grid-column:span 2;}
  .bento > :nth-child(1){grid-column:span 4;}
}
@media (max-width:620px){
  .wrap{padding:0 18px;}
  .hero-panel{padding:24px 18px;border-radius:14px;}
  .photohero{min-height:auto;padding:120px 0 44px;}
  .thumbstrip{grid-template-columns:1fr;}
  .eyebrow{font-size:var(--fs-label);letter-spacing:.16em;padding:6px 12px;}
  .btn{font-size:var(--fs-xs);padding:7px 7px 7px 20px;
    min-height:48px;}  /* was 31px tall here: under the 44px touch minimum */
  .ctas{flex-direction:column;align-items:stretch;}
  .ctas .btn{justify-content:space-between;}
  .bento{grid-template-columns:1fr;grid-auto-rows:190px;}
  .bento > *{grid-column:span 1 !important;grid-row:span 1 !important;}
}

/* ── contact rail: the site sold phone answering and had no phone number ── */
.contactbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  font-size:var(--fs-xs);font-weight:600;color:var(--tx2);}
.contactbar a{display:inline-flex;align-items:center;gap:7px;color:#141A1F;font-weight:700;}
.contactbar a:hover{color:var(--accent);}
.contactbar .sepdot{width:3px;height:3px;border-radius:50%;background:var(--tx3);}
.nav .telcta{display:inline-flex;align-items:center;gap:7px;font-size:var(--fs-xs);font-weight:700;
  color:var(--tx2);white-space:nowrap;}
.nav .telcta b{color:#141A1F;}
.nav .telcta:hover b{color:var(--accent);}
@media (max-width:1100px){.nav .telcta{display:none;}}
/* 로그인 — 요금을 내고 쓰시는 분이 돌아오는 문. 팔러 나가는 단추(견적 받기)
   옆에 두되, 그 단추와 경쟁하지 않게 글자 링크로 둔다. 좁은 화면에서도
   남긴다: 버거 메뉴 안에 넣으면 이미 고객인 분이 메뉴를 열어 찾아야 한다. */
.nav .navlogin{font-size:var(--fs-xs);font-weight:700;color:var(--tx2);white-space:nowrap;}
.nav .navlogin:hover{color:#141A1F;}
.navwrap.onlight .nav .navlogin{color:var(--l-mut);}
.navwrap.onlight .nav .navlogin:hover{color:var(--l-ink);}

/* ── proof block that replaces an empty rectangle ── */
.proofgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-top:30px;}
@media (max-width:900px){.proofgrid{grid-template-columns:1fr;}}
.proofcard{border:1px solid var(--l-hair);border-radius:14px;padding:24px;background:#fff;}
.proofcard .num{font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-xs);font-weight:700;
  color:var(--teal-ink);letter-spacing:.02em;}.proofcard h4,.proofcard .hl4{margin-top:10px;font-size:var(--fs-body);color:var(--l-ink);letter-spacing:-.02em;}
.proofcard p{margin-top:9px;font-size:var(--fs-xs);line-height:1.7;color:var(--l-mut);font-weight:500;}
.proofcard .lnkrow{margin-top:14px;display:flex;gap:14px;flex-wrap:wrap;}
.proofcard .lnkrow a{font-size:var(--fs-xs);font-weight:700;color:var(--l-ink);
  border-bottom:1.5px solid var(--l-ink);padding-bottom:2px;}

/* lead-capture success state (replaces the form on a confirmed POST) */
.easent{padding:26px 24px;border:1px solid rgba(58,201,138,.32);border-radius:14px;
  background:rgba(58,201,138,.08);}
.easent b{display:block;font-size:var(--fs-body);color:#141A1F;letter-spacing:-.015em;}
.easent span{display:block;margin-top:9px;font-size:var(--fs-xs);line-height:1.7;color:var(--tx2);font-weight:500;}

/* the reference a visitor can quote back at us */
.easent .earef{display:inline-block;margin-top:12px;padding:8px 14px;border-radius:8px;
  font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-body);font-weight:600;
  letter-spacing:.06em;color:#141A1F;background:rgba(58,201,138,.12);
  border:1px solid rgba(58,201,138,.3);user-select:all;}
.easent b + .earef{margin-top:14px;}
.sec-light .easent .earef,.sec-light2 .easent .earef{color:#0B6B4A;background:#E9F7F1;border-color:#B9E3D2;}

/* ── composer fallback: three routes, not one ──
   A buyer audit found three qualified buyers reaching the end of the funnel and
   being handed an unsent mailto: draft. mailto: only fires for people with a
   desktop mail client configured — on mobile, and for webmail users, it silently
   does nothing. These give the visitor their own route instead of ours. */
.eafallback-lead{font-size:var(--fs-xs);line-height:1.7;color:var(--tx2);font-weight:600;margin-bottom:14px;}
.eafallback-routes{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:16px;}
.eafallback-routes .btn{font-size:var(--fs-xs);}
@media(max-width:520px){
  .eafallback-routes{flex-direction:column;align-items:stretch;}
  .eafallback-routes .btn{justify-content:space-between;}
}

/* ── overflow guards, measured rather than masked ──
   body{overflow-x:hidden} was hiding real layout breaks along with decorative
   bleed. These were found by removing the mask and testing all 21 pages at
   390px: a 920px glow with no clipping ancestor, and a KPI band that folded
   4->2 and stopped. Fixed at the source so the mask is a belt, not the braces. */
@media (max-width:620px){
  .kpiband{grid-template-columns:1fr;}
  .kpi{padding:18px;}
  .kpi .n{font-size:var(--fs-h2);}
}
/* any decorative aura/glow is clipped by its own section */
.aur,.glow,.hglow,.ghost,.cas-glow{pointer-events:none;max-width:100vw;}
section,header{overflow-x:clip;}

/* ═══════════════════════════════════════════════════════════
   MOTION LAYER
   ───────────────────────────────────────────────────────────
   A design audit measured two @keyframes across 26 pages and
   called it the one dimension where the gap to the best B2B
   sites is categorical rather than incremental: the whole
   scroll experience was a single opacity+translateY fade.

   This is scroll-driven, CSS-only, and additive — it upgrades
   the existing .reveal contract where the browser supports
   animation-timeline and leaves the IntersectionObserver
   fallback untouched everywhere else. No JS, no library, no
   layout change, and it never runs under reduced-motion.
   ═══════════════════════════════════════════════════════════ */

@keyframes sr-rise{
  from{opacity:0;transform:translate3d(0,34px,0) scale(.986);}
  to  {opacity:1;transform:none;}
}
@keyframes sr-riseleft{
  from{opacity:0;transform:translate3d(-28px,12px,0);}
  to  {opacity:1;transform:none;}
}
@keyframes sr-count{
  from{opacity:0;transform:translateY(.34em);}
  to  {opacity:1;transform:none;}
}
@keyframes sr-park{
  from{transform:scale(1.07) translateY(0);}
  to  {transform:scale(1) translateY(-3.5%);}
}
@keyframes sr-wipe{
  from{clip-path:inset(0 0 100% 0);}
  to  {clip-path:inset(0 0 0 0);}
}

@supports (animation-timeline: view()){
  @media (prefers-reduced-motion: no-preference){
    /* the reveal stops being a timed fade and becomes a function of scroll */
    .srjs .reveal{
      animation:sr-rise .01s linear both;
      animation-timeline:view();
      animation-range:cover 0% cover 20%;
      opacity:1;transform:none;transition:none;
    }
    /* section headings wipe rather than fade — one different gesture, used sparingly */
    .srjs .t-xl .h2.reveal,.srjs .t-xl h2.reveal{
      animation:sr-wipe .01s linear both;
      animation-timeline:view();
      animation-range:cover 0% cover 22%;
    }
    /* editorial copy blocks arrive from the side they sit on */
    .srjs .photosplit .copy.reveal,.srjs .duo > .reveal:first-child{
      animation:sr-riseleft .01s linear both;
      animation-timeline:view();
      animation-range:cover 0% cover 22%;
    }
    /* big numbers count in — the figures are the argument on this site */
    .srjs .kpi .n,.srjs .stat .n,.srjs .kpitile .vl,.srjs .fstep b,.srjs .mathrow.total .val{
      animation:sr-count .01s linear both;
      animation-timeline:view();
      animation-range:cover 2% cover 24%;
    }
    /* hero photography settles instead of sitting still */
    .photohero .bgimg img{
      animation:sr-park .01s linear both;
      animation-timeline:view();
      animation-range:entry 0% cover 62%;
      will-change:transform;
    }
  }
}

/* press states — there were two on the whole site */
.chip:active,.exfilter button:active,.linkcta:active,.faq summary:active,
.slotchip input:active + span,.thumb:active{transform:scale(.975);}
.chip,.exfilter button,.linkcta,.faq summary{transition:transform .18s var(--ease);}

/* ── mobile hero: the padding was stacking ──
   `.photohero` already drops to `padding:120px 0 44px` under 620px, and the
   page-level `.hero-inner` kept its desktop `padding-top:150px` on top of it.
   Measured at 375px: 179px of dead black between the nav and the first word.
   The nav is 91px tall; 24px of clearance under it is enough. */
@media (max-width:620px){
  .hero-inner,.phero .hcap,.gshero > .wrap,.inthero > .wrap,.exhero > .wrap,.dochero > .wrap{
    padding-top:24px !important;
  }
  .photohero,.phero,.gshero,.inthero,.exhero,.dochero{padding-top:104px !important;}
  /* This was tuned for the home page, but every hero header carries both
     classes, so it applied to eight pages at once and put the first line
     of six of them at y=92 with the fixed nav ending at 93. 96px plus the
     inner 24px starts content at 120 — clear of the nav, still tight. */
  .hero.photohero{padding-top:96px !important;}
  .hero .sub{margin-top:14px;} .hero .ctas{margin-top:20px;} .heroprice{margin-top:12px;}
  .hero-panel{padding:22px 18px;}
}

/* ── build version beside the wordmark ──
   Small, quiet, and never competing with the logo: a reader should be able to
   quote it in a bug report without it drawing the eye on the way past. */
.ver{display:inline-block;margin-left:7px;font-family:'Bricolage Grotesque',sans-serif;
  font-size:var(--fs-label);font-weight:700;letter-spacing:.06em;color:var(--tx3);
  border:1px solid var(--hair2);border-radius:5px;padding:2px 5px;
  vertical-align:middle;transform:translateY(-1px);white-space:nowrap;}
.nav .logo + .ver{opacity:.75;}
.nav:hover .ver{opacity:1;color:var(--tx2);}
.ver-f{margin-left:8px;opacity:.6;}
.sec-light .ver,.bigfooter .ver{border-color:rgba(20,26,31,.208);}
@media (max-width:620px){.nav .ver{display:none;}}


/* ═══ BACK TO TOP ═══════════════════════════════════════════════
   Sits above the sticky offer bar and steps up out of its way when
   that bar is showing, so the two never overlap in the corner. */
.totop-mark{position:absolute;top:200vh;left:0;width:1px;height:1px;pointer-events:none;}

.totop{
  position:fixed;right:22px;bottom:22px;z-index:41;
  width:46px;height:46px;border-radius:50%;
  display:grid;place-items:center;cursor:pointer;
  border:1px solid rgba(11,120,120,.42);
  background:rgba(20,26,31,.72);
  -webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);
  color:var(--teal);
  box-shadow:0 10px 30px rgba(2,8,14,.5);
  opacity:0;visibility:hidden;transform:translateY(10px) scale(.94);
  transition:opacity .32s cubic-bezier(.32,.72,0,1),
             transform .32s cubic-bezier(.32,.72,0,1),
             visibility .32s,
             bottom .32s cubic-bezier(.32,.72,0,1),
             background .18s,border-color .18s;
}
.totop.show{opacity:1;visibility:visible;transform:none;}
.totop:hover{background:rgba(11,120,120,.16);border-color:rgba(11,120,120,.78);}
.totop:active{transform:scale(.93);}
.totop:focus-visible{outline:3px solid #FFFFFF;outline-offset:2px;
  box-shadow:0 0 0 6px rgba(4,8,15,.85);}  /* same contract as every other control */
.totop svg{width:20px;height:20px;display:block;}

/* the offer bar owns the bottom edge whenever it is up */
body:has(.stickycta.show) .totop{bottom:calc(22px + var(--stickycta-h,124px));}

@media(max-width:620px){
  .totop{right:14px;bottom:14px;width:42px;height:42px;}
  .totop svg{width:18px;height:18px;}
  body:has(.stickycta.show) .totop{bottom:calc(14px + var(--stickycta-h,124px));}
}
@media(prefers-reduced-motion:reduce){
  .totop{transition:opacity .01ms,visibility .01ms;}
}


/* ═══ PILOT PROOF ═══════════════════════════════════════════════
   The stat card carries its denominator under the number. A bare
   "61%" invites the question "out of what?"; printing "14 of 23"
   answers it before it is asked, and a small honest sample reads
   as more trustworthy than a large unsourced one. */
.statrow{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:34px;}
@media(max-width:900px){.statrow{grid-template-columns:repeat(2,1fr);}}
@media(max-width:560px){.statrow{grid-template-columns:1fr;}}

.statcard{border:1px solid var(--hair);border-radius:14px;padding:20px 20px 18px;
  background:rgba(20,26,31,.036);position:relative;overflow:hidden;}
.statcard::before{content:'';position:absolute;left:0;top:0;bottom:0;width:2px;
  background:rgba(11,120,120,.5);}
.statcard.hi{border-color:rgba(11,120,120,.34);background:rgba(11,120,120,.05);}
.statcard.hi::before{background:var(--teal);}
.statcard .sl{display:block;font-size:var(--fs-label);font-weight:800;letter-spacing:.13em;
  text-transform:uppercase;color:var(--tx3);}
.statcard .sv{display:block;margin-top:10px;font-family:'Bricolage Grotesque',sans-serif;
  font-size:var(--fs-h2);font-weight:600;letter-spacing:-.04em;line-height:1;color:#141A1F;}
.statcard.hi .sv{color:var(--teal);}
.statcard .sd{display:block;margin-top:8px;font-size:var(--fs-xs);font-weight:700;color:var(--teal);
  font-variant-numeric:tabular-nums;}
.statcard .sn{margin:12px 0 0;font-size:var(--fs-xs);line-height:1.65;color:var(--tx2);font-weight:500;}

.caselog{margin-top:40px;}
.caselog .ch{font-size:var(--fs-h3);font-weight:700;color:#141A1F;margin:0 0 18px;
  font-family:'Bricolage Grotesque',sans-serif;letter-spacing:-.02em;}
.cases{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;}
@media(max-width:1000px){.cases{grid-template-columns:repeat(2,1fr);}}
@media(max-width:560px){.cases{grid-template-columns:1fr;}}
.case{border:1px solid var(--hair);border-radius:14px;padding:16px 16px 15px;
  background:rgba(0,0,0,.2);}
.case .ct{display:inline-block;font-size:var(--fs-label);font-weight:800;letter-spacing:.12em;
  text-transform:uppercase;color:var(--teal);background:rgba(11,120,120,.1);
  border-radius:999px;padding:4px 9px;margin-bottom:10px;}
.case b{display:block;font-size:var(--fs-sm);line-height:1.5;color:#141A1F;font-weight:700;}
.case p{margin:8px 0 0;font-size:var(--fs-xs);line-height:1.65;color:var(--tx3);font-weight:500;}

/* The disclaimer is set as a peer of the numbers, not as fine print under
   them — a limitation printed small reads as a limitation being hidden. */
.proofnote{margin-top:34px;border:1px solid var(--hair);border-left:2px solid rgba(11,120,120,.55);
  border-radius:14px;padding:20px 22px;background:rgba(20,26,31,.029);
  display:grid;gap:12px;max-width:var(--measure);}
.proofnote p{margin:0;font-size:var(--fs-sm);line-height:1.72;color:var(--tx2);font-weight:500;}
.proofnote b{color:#141A1F;font-weight:700;}


/* ═══ ONE HERO GAP ══════════════════════════════════════════════
   Eleven class names did the same job at thirteen different heights
   (124px–196px). They all clear the same fixed nav. */
.hero-inner,.hero-split,.gshero,.inthero,.exhero,.dhero-inner,.dochero,
.heroinner,.herogrid,.herostage{padding-top:var(--pad-hero) !important;}
@media(max-width:900px){
  .hero-inner,.hero-split,.gshero,.inthero,.exhero,.dhero-inner,.dochero,
  .heroinner,.herogrid,.herostage{padding-top:126px !important;}
}
/* Per-page <style> blocks are parsed after this file, so at equal specificity
   they win. !important is the cheap way to hold one number across 26 pages
   without hunting every override — the mobile block below still overrides it. */

/* ═══ ONE CLOSER GAP ════════════════════════════════════════════
   about / cross-border / security already used the token and render
   correctly; the other eighteen pages each picked their own number. */
.closer{padding-top:var(--pad-xl) !important;}/* ═══ NO ORPHANS,NO WIDOWS ═════════════════════════════════════
   A heading that drops one word onto its own line ("…your own price
   / list.") reads as amateur however good the type is. `balance`
   evens the line lengths of short blocks; `pretty` stops body copy
   ending on a single word. Both are ignored by older engines,so
   there is no fallback to write. */
h1,h2,h3,h4,h5,.h1,.h2,.h3,.display,.hero h1,.head h2,.khead h2,.secintro h2,.hl4,.hl5{
  text-wrap:balance;
}
p,.lead,.sub,li,figcaption,.labwhy,.sn,.statnote,.proofnote p,.pipecap,
.exturn,.qa,.v,.mt,.m,.ds,.tx,.rv,.stat,.bub,.code,.cap,.txt,
.altnote,.channote,.whotxt,.st,.nm,.d{
  text-wrap:pretty;
}


/* ═══ EQUAL-HEIGHT SIBLINGS, SITE-WIDE ═════════════════════════
   A stretched grid track does nothing unless the card inside it is
   also told to fill. These are the card wrappers that sit directly
   in a multi-column grid; the mock or list inside each one takes the
   slack so the two columns finish on the same line. */
.crmduo > *,.crmtrio > *,.esccols > *,.faqcols > *,.thinkcols > *,
.duo > *,.pairgrid > *,.crmgrid > *,.introw > *,.reqwrap > *,
.cols > *,.grid > *,.wagrid > *,.qrow > *{min-width:0;}

.crmduo > .cwrap,.crmduo > div,.crmtrio > div,.duo > div,.pairgrid > div{
  display:flex;flex-direction:column;
}
.crmduo > div > .appwin,.crmduo > div > .quotedoc,.crmduo > div > .custcard,
.crmtrio > div > .appwin,.duo > div > .appwin,.pairgrid > div > .appwin{
  /* grow into the slack, but never shrink below the content: `flex:1` is
     basis 0, which sized these windows from the grid rather than from what
     is in them, and .appwin clips its overflow - the WhatsApp pipeline mock
     lost 107px, cutting "Inquiry / Booked / Quoted" through the middle. */
  flex:1 0 auto;
}

/* a pack that is on the roadmap says so wherever it is linked, not only on its own page */
.rmtag{font-style:normal;font-size:var(--fs-label);font-weight:800;letter-spacing:.1em;
  text-transform:uppercase;color:#141A1F;background:rgba(183,121,31,.13);
  border:1px solid rgba(183,121,31,.3);border-radius:999px;padding:2px 7px;margin-left:6px;
  vertical-align:middle;white-space:nowrap;}


/* ═══ OPTICAL ALIGNMENT + PINNED CARD FOOTERS ══════════════════
   1 · The eyebrow is a pill, so its *box* lines up with the heading
   while its *text* sits 17px inside — 129 places on the site where
   the first two lines of a section disagree about where the left
   margin is. Pulling the pill back by its own inset puts the text
   on the grid. Centered sections are excluded: there the box, not
   the text, is what should be centered. */
.head:not(.mid):not(.centered) > .eyebrow,
.secrule > .eyebrow{margin-left:-17px;}
@media(max-width:620px){
  .head:not(.mid):not(.centered) > .eyebrow,
  .secrule > .eyebrow{margin-left:0;}
}

/* 2 · A card whose footer floats leaves a different amount of dead
   space under every sibling. Pin the last element and the row reads
   as one object instead of four near-misses. */
.plan,.statcol,.kpi,.riskitem,.statcard,.case,.kpitile,.weekday,
.whocard,.wcard,.pl,.warncard,.regcard,.hcard,.rate,.fstep,.mlcard{
  display:flex;flex-direction:column;
}
.plan > .cta,
.statcol > ul,
.kpi > .l,
.kpitile > .dl,
.weekday > ul,
.statcard > .sn,
.case > p,
.riskitem > span:last-child{
  margin-top:auto;
}
.statcol > ul{padding-top:14px;}
.kpi > .l{padding-top:6px;}


/* ═══ SPECIFICITY REPAIRS ═══════════════════════════════════════
   `.cta` is not always a direct child of `.plan`, and `.gsform`
   carries `.eaform` too — both fixes above were losing to a rule
   with equal or greater weight. These are scoped to win. */
.plans .plan,.ptray .plan{display:flex;flex-direction:column;}
.plans .plan .cta,.ptray .plan .cta{margin-top:auto;}
form.gsform.eaform{grid-template-columns:1fr;}
form.gsform.eaform .two{display:grid;grid-template-columns:repeat(2,1fr);gap:12px;}
@media(max-width:620px){form.gsform.eaform .two{grid-template-columns:1fr;}}


/* A `grid-column:span 2` child conjures an implicit second track even when
   only one is declared — which is why the single-column form kept rendering
   two. Inside the one-column variant, nothing spans. */
form.gsform.eaform > *,
form.gsform.eaform .full,
form.gsform.eaform button{grid-column:auto;}


/* ═══ SUB-PROCESSOR TABLE + RETENTION GRID (light sections) ═════ */
.sptable{margin-top:30px;border:1px solid var(--l-hair);border-radius:14px;overflow:hidden;background:#fff;}
.sprow{display:grid;grid-template-columns:1.1fr 2fr .8fr;gap:16px;padding:13px 20px;
  border-bottom:1px solid var(--l-hair);font-size:var(--fs-sm);color:var(--l-tx2);align-items:center;}
.sprow:last-child{border-bottom:0;}
.sprow.sph{background:var(--l-bg2,#F4F6F9);font-size:var(--fs-label);font-weight:800;
  letter-spacing:.12em;text-transform:uppercase;color:var(--l-tx3);}
.sprow .spn{font-weight:700;color:var(--l-ink);}
.sprow .spl{font-weight:700;color:var(--l-tx3);font-size:var(--fs-xs);}
@media(max-width:760px){
  .sprow{grid-template-columns:1fr;gap:4px;padding:14px 16px;}
  .sprow.sph{display:none;}
  .sprow .spl{opacity:.8;}
}
.spnote{margin-top:16px;font-size:var(--fs-sm);line-height:1.72;color:var(--l-tx2);
  font-weight:500;max-width:var(--measure);}

.retgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-top:28px;align-items:stretch;}
@media(max-width:900px){.retgrid{grid-template-columns:repeat(2,1fr);}}
@media(max-width:560px){.retgrid{grid-template-columns:1fr;}}
.retcard{border:1px solid var(--l-hair);border-radius:14px;padding:18px;background:#fff;
  display:flex;flex-direction:column;}
.retcard.hi{border-color:rgba(20,26,31,.34);background:rgba(255,255,255,.045);}
.retcard b{font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-h3);font-weight:600;
  letter-spacing:-.03em;color:var(--l-ink);}
.retcard.hi b{color:var(--teal-deep,#0A5F5F);font-size:var(--fs-lead);}
.retcard > span{display:block;margin-top:6px;font-size:var(--fs-xs);font-weight:700;color:var(--l-tx2);}
.retcard p{margin:9px 0 0;font-size:var(--fs-xs);line-height:1.65;color:var(--l-tx3);font-weight:500;
  margin-top:auto;padding-top:9px;}


/* ═══ LIVE CUSTOMER LINES ═══════════════════════════════════════
   The strongest object on the site: six numbers a stranger can dial
   without asking us first. Two are ours and are marked as such —
   the admission is what makes the other four credible. */
.livegrid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-top:32px;align-items:stretch;}
@media(max-width:980px){.livegrid{grid-template-columns:repeat(2,1fr);}}
@media(max-width:600px){.livegrid{grid-template-columns:1fr;}}

.livecard{border:1px solid rgba(11,120,120,.28);border-radius:14px;padding:19px;
  background:rgba(11,120,120,.045);display:flex;flex-direction:column;
  transition:border-color .2s,background .2s;}
.livecard:hover{border-color:rgba(11,120,120,.55);background:rgba(11,120,120,.075);}
.livecard.ours{border-color:var(--hair);background:rgba(20,26,31,.034);}
.livecard.ours:hover{border-color:var(--hair2);}
.livecard .lt{display:block;font-size:var(--fs-label);font-weight:800;letter-spacing:.13em;
  text-transform:uppercase;color:var(--teal);}
.livecard.ours .lt{color:var(--tx3);}
.livecard b{display:block;margin-top:8px;font-family:'Bricolage Grotesque',sans-serif;
  font-size:var(--fs-h3);font-weight:600;letter-spacing:-.02em;color:#141A1F;line-height:1.2;}
.livecard .lnum{display:inline-block;align-self:flex-start;margin-top:11px;
  font-family:ui-monospace,'SF Mono',Menlo,Consolas,monospace;font-size:var(--fs-sm);
  font-weight:700;color:var(--teal);letter-spacing:.01em;
  border-bottom:1px solid rgba(11,120,120,.4);padding-bottom:2px;}
.livecard .lnum:hover{border-bottom-color:var(--teal);}
.livecard.ours .lnum{color:#AFC3DC;border-bottom-color:rgba(120,150,190,.35);}
.livecard p{margin:12px 0 0;font-size:var(--fs-xs);line-height:1.68;color:var(--tx2);
  font-weight:500;margin-top:auto;padding-top:12px;}

.livenote{margin-top:30px;border:1px solid var(--hair);border-left:2px solid rgba(11,120,120,.55);
  border-radius:14px;padding:20px 22px;background:rgba(20,26,31,.029);display:grid;gap:12px;
  max-width:var(--measure);}
.livenote p{margin:0;font-size:var(--fs-sm);line-height:1.72;color:var(--tx2);font-weight:500;}
.livenote b{color:#141A1F;font-weight:700;}

/* ═══ CONCLUSION BAND ═══════════════════════════════════════════
   The complaint was that a reader could follow a path and not know
   what it added up to. Every page now ends by naming what it just
   showed and handing off to exactly one next page. */
.concsec{border-top:1px solid var(--hair);}
.concwrap{display:grid;grid-template-columns:1fr auto;gap:26px;align-items:center;}
@media(max-width:820px){.concwrap{grid-template-columns:1fr;gap:18px;}}
.cnl{display:block;font-size:var(--fs-label);font-weight:800;letter-spacing:.13em;
  text-transform:uppercase;color:var(--teal);}
.cnp{margin:10px 0 0;font-size:var(--fs-sm);line-height:1.72;color:var(--tx2);
  font-weight:500;max-width:var(--measure);}
.concbtn{white-space:nowrap;}
@media(max-width:820px){.concbtn{justify-self:start;}}

/* ═══ THE REAL BRAND MARK ═══════════════════════════════════════
   The company's actual logo is a green headset-and-speech-bubble
   mark beside a navy wordmark. Navy is unreadable on this ground,
   so the mark travels and the wordmark stays in the site's own
   white — same identity, legible on dark. */
.logo{display:inline-flex;align-items:center;gap:9px;}
.lmark{width:26px;height:26px;flex:none;display:block;}
@media(max-width:620px){.lmark{width:22px;height:22px;}}

/* ═══ SEGMENT BOUNDARY ══════════════════════════════════════════
   Two English sites, same company, prices an order of magnitude
   apart. Unexplained that reads as one being false; named, it reads
   as two products. Cheaper to say it than to be caught by it. */
.segwrap{display:grid;grid-template-columns:1fr 1fr;gap:16px;align-items:stretch;}
@media(max-width:820px){.segwrap{grid-template-columns:1fr;}}
.segcol{border:1px solid var(--hair);border-radius:14px;padding:20px;
  background:rgba(20,26,31,.034);display:flex;flex-direction:column;}
.segcol.on{border-color:rgba(11,120,120,.42);background:rgba(11,120,120,.055);}
.sgl{display:block;font-size:var(--fs-label);font-weight:800;letter-spacing:.13em;
  text-transform:uppercase;color:var(--tx3);}
.segcol.on .sgl{color:var(--teal);}
.segcol b{display:block;margin-top:8px;font-size:var(--fs-sm);line-height:1.4;color:#141A1F;font-weight:700;}
.segcol p{margin:10px 0 0;font-size:var(--fs-xs);line-height:1.68;color:var(--tx2);font-weight:500;}
.segcol > p{flex:1;}
.sgp{display:block;margin-top:auto;padding-top:14px;font-family:'Bricolage Grotesque',sans-serif;
  font-size:var(--fs-sm);font-weight:700;color:#141A1F;letter-spacing:-.01em;}
.sga{display:inline-block;margin-top:10px;font-size:var(--fs-xs);font-weight:700;color:var(--teal);
  border-bottom:1px solid rgba(11,120,120,.4);padding-bottom:2px;align-self:flex-start;}
.segnote{margin:16px 0 0;font-size:var(--fs-sm);line-height:1.72;color:var(--tx3);
  font-weight:500;max-width:var(--measure);}

/* A disclaimer occupying the position of a conclusion reads as the point of
   the section. .capnote demotes it to what it is - a footnote - so the
   sentence after it is the last thing read. */
.capnote{display:block;margin-bottom:10px;font-size:var(--fs-xs);line-height:1.6;
  opacity:.62;font-weight:500;letter-spacing:.005em;}

/* ── the light-surface contract ────────────────────────────────────────────
   Every failure left after the token pass had the same shape: a class painted
   a light background and said nothing about ink, so its children kept the dark
   theme's --tx / --tx2 / --tx3 / --teal-deep and landed between 1.0 and 3.2:1.
   Chasing each selector does not converge - a new light surface reintroduces
   the bug. Custom properties inherit, so remapping the four inks at the light
   surface fixes every descendant that reaches for them, including ones written
   later. Dark cards nested inside a light section reset them again below. */
.sec-light,.sec-light2,.sec-paper,.bg-paper,.bg-clinical,
.roomband,.chairband,.openband,.vetband,.hallband,
.faqsec,.start,.paper,.tray,.langnote,.convrow.on,.custsec,
/* found by sweeping every page for an element that paints a light ground
   and still resolves --tx2 to the dark theme's value */
.quotedoc,.browserframe.light,.browserframe.light .bar,.inboxmock,
.qmini,.kconf,.kfact,.handles{
  color:var(--l-ink);
  --tx:var(--l-ink); --tx2:var(--l-mut); --tx3:var(--l-mut2);
  --teal-deep:var(--teal-ink); --amber:var(--amber-ink);
}
/* dark surfaces that legitimately sit inside a light section put the dark
   theme back, or the remap above would turn their text dark-on-dark */
.sec-light .appwin,.sec-light2 .appwin,.bg-paper .appwin,.bg-clinical .appwin,
.sec-light .altcol.win,.sec-light2 .altcol.win,.bg-paper .altcol.win,
.sec-light .endcta,.sec-light2 .endcta,.bg-paper .endcta,
.navwrap:not(.onlight) .nav,.stickycta,
.scene-overlay,.appwin,.altcol.win,.endcta,.browserframe:not(.light),
.sec-light .sec-dark,.sec-light2 .sec-dark,.closer,.sec-dark{
  color:var(--tx);
  --tx:#141A1F; --tx2:#3B454D; --tx3:#616B75;
  --teal-deep:#0A5F5F; --amber:#B7791F;
}

/* ── light-surface leftovers the contract above cannot reach ───────────────
   These name a literal colour rather than an ink token, so nothing inherits
   its way out of them. Each was measured on the ground it actually sits on. */
.navwrap.onlight .nav{color:var(--l-ink);--tx:var(--l-ink);--tx2:var(--l-mut);--tx3:var(--l-mut2);}
.navwrap.onlight .telcta b,.navwrap.onlight .telcta span,
.navwrap.onlight .nav .links a{color:var(--l-ink);}
.sec-light .ptlist li b,.sec-light2 .ptlist li b{color:var(--l-ink);}
.sec-light .ptlist li,.sec-light2 .ptlist li{border-bottom-color:var(--l-hair);}
.scene-frame.light .caption{color:var(--l-mut);text-shadow:none;}
.by .avatar,.av-c{color:#141A1F;}
.pt-teal{color:#0B7878;}                      /* was #0B7878 - 4.28:1 on #E3F5F5 */
.pt-amber{color:var(--amber-ink);}            /* was #8D642F - 3.19:1 on #FAF0E1 */
.sec-light .chanbadge.voice,.sec-light2 .chanbadge.voice,
.bg-paper .chanbadge.voice,.bg-clinical .chanbadge.voice{color:#0B7878;}
.sec-light .chanbadge.chat,.sec-light2 .chanbadge.chat,
.bg-paper .chanbadge.chat,.bg-clinical .chanbadge.chat{color:#2C63B8;}
.sec-light .cmp .lim,.sec-light2 .cmp .lim,table.cmp .lim{color:var(--amber-ink);}
/* tick / cross markers sitting on their own tinted pill */
.sec-light .yes i,.sec-light2 .yes i,.bg-paper .yes i,.bg-clinical .yes i,
.sec-light .ok i,.sec-light2 .ok i{color:#0B7878;}
.sec-light .no i,.sec-light2 .no i,.bg-paper .no i,.bg-clinical .no i{color:#A8453A;}

/* ── equal-height cards: pin the trailing element ──────────────────────────
   Measured bottom gaps in each row before this rule:
     .statcol   25 / 307 / 227  (veterinary)   jag 282px
     .statcol   25 / 105 / 185  (home-services) jag 160px
     .wcard     80 / 80 / 31                    jag  49px
     .regcard   27 / 27 / 47 / 27 / 62          jag  35px
     .paper     33 / 33 / 59                    jag  26px
     .whocard   42 / 19 / 21 / 21               jag  23px
     .scard, .rate, .hcard, .herostat > *       jag  19-20px
   The grid already stretches the cards; what jags is the LAST line inside each
   one, because the paragraphs above it wrap to different depths. Same fix the
   site already uses on .plan .cta and .tlstep .who. */
.statcol,.wcard,.whocard,.paper,.hcard,.regcard,.rate,.scard,.herostat > *{
  display:flex;flex-direction:column;height:100%;}
.statcol > *:last-child,.wcard > *:last-child,.whocard > *:last-child,
.paper > *:last-child,.hcard > *:last-child,.regcard > *:last-child,
.rate > *:last-child,.scard > *:last-child,.herostat > * > *:last-child{
  margin-top:auto;}
/* a pinned element that is itself a flex row must not stretch to fill */
.hcard > .hchip:last-child,.regcard > .tag:last-child{align-self:flex-start;}

/* ── UI boundaries ─────────────────────────────────────────────────────────
   Every card border on the site measured 1.08-1.50:1 against its own fill, so
   nothing read as a discrete object. WCAG 1.4.11 asks 3:1 for a UI boundary.
   These are the smallest values that make an edge visible without turning the
   dark surfaces into a wireframe. */
.statcard,.pkcard,.pipecolx,.regcard,.appwin,.pipecol,.custcard,.tdcard,.kpitile{
  border-color:rgba(20,26,31,.221);}
.appwin{border-color:rgba(20,26,31,.312);}
.plan,.pack,.proofcard,.hcard,.excard,.sptable,.quotedoc,
.sptable td,.sptable th,table.cmp td,table.cmp th{border-color:#D6DDE7;}
/* .quotedoc had border-width:0 - a box on a light section with no edge at all */
.quotedoc{border:1px solid #D6DDE7;}

/* section-closing sentences added where a section previously ended on a
   disclaimer, a caption, a promo chip or a nav link */
.stackfoot,.exfoot,.custfoot,.whyfoot{margin-top:26px;max-width:var(--measure);
  font-size:var(--fs-sm);line-height:1.75;font-weight:500;color:inherit;opacity:.92;
  text-wrap:pretty;}
.custfoot,.exfoot{margin-left:auto;margin-right:auto;text-align:center;}
.storyfoot{margin:22px 0 20px;max-width:var(--measure);font-size:var(--fs-sm);line-height:1.7;
  font-weight:600;color:inherit;text-wrap:pretty;}

/* markers that sit on their own tinted pill rather than on the section ground */
.sec-light .fbar i,.bg-paper .fbar i,.bg-clinical .fbar i,
.sec-light li > i,.sec-light2 li > i,.bg-paper li > i,.bg-clinical li > i,
.sec-light .steprow i,.sec-light2 .steprow i{color:#0B7878;}
.sec-light .no > i,.sec-light2 .no > i,.sec-light .x > i{color:#A8453A;}/* before/after columns appear on both grounds; the markers were only ever
   tuned for the dark one */
.sec-light .baCol.after li i,.sec-light2 .baCol.after li i,.bg-paper .baCol.after li i,.bg-clinical .baCol.after li i,.sec-light .baCol.after h4,.sec-light2 .baCol.after h4,.bg-paper .baCol.after h4,.bg-clinical .baCol.after h4,.sec-light .baCol.after .hl4,.sec-light2 .baCol.after .hl4,.bg-paper .baCol.after .hl4,.bg-clinical .baCol.after .hl4{color:#0B7878;}.sec-light .baCol.before li i,.sec-light2 .baCol.before li i,.bg-paper .baCol.before li i,.bg-clinical .baCol.before li i,.sec-light .baCol.before h4,.sec-light2 .baCol.before h4,.bg-paper .baCol.before h4,.bg-clinical .baCol.before h4,.sec-light .baCol.before .hl4,.sec-light2 .baCol.before .hl4,.bg-paper .baCol.before .hl4,.bg-clinical .baCol.before .hl4{color:#A8453A;}
.sec-light .baArrow,.sec-light2 .baArrow,.bg-paper .baArrow,.bg-clinical .baArrow{color:#616B75;}
/* the roadmap arrow on integrations sits on the section ground, not a pill */
.sec-light .ptlist li > i,.sec-light2 .ptlist li > i{color:#0B7878;}

/* ── status pills: the ink and its own tint were picked together and both drifted
   light, so each pair sat at 3.0-3.2:1. Only the ink moves; the tints are what
   make the states scannable. */
.st-hu{color:#8A5A11;}                 /* was #8D642F on #FAF0E1 - 3.19:1 */
.pt-amber{background:#FAF0E1;color:#8A5A11;}
.cm-m{background:rgba(47,133,90,.15);color:#15784B;}   /* was #1E9E63 - 3.08:1 */
.cm-c{color:#141A1F;}                  /* was #3D7DE0 on #E6F0FF - 3.52:1 */
.sec-light .x,.sec-light2 .x,.bg-paper .x,.bg-clinical .x,
.sec-light span.x,.sec-light2 span.x{color:#A8453A;}    /* was --red - 3.19:1 */
/* white on the flat teal button was 3.09:1; the deeper teal carries it to 4.6 */
.kfact .ap{background:#0B7878;}
.secfoot{margin-top:26px;max-width:var(--measure);font-size:var(--fs-sm);line-height:1.75;
  font-weight:500;color:inherit;opacity:.92;text-wrap:pretty;}

/* the last of the tinted status pills, all measured 3.19-3.40:1 */
.y,.yes > span.y{color:#15784B;}       /* was #1E9E6A on #F5FBFB */
span.x,.no > span.x{color:#A8453A;}    /* was #D96A5E on #FDF6F4 */
.ftag{color:var(--tx2);}               /* follows its surface; was #8793A5 at 3.34:1 */
.sec-light .ftag,.sec-light2 .ftag,.bg-paper .ftag,.bg-clinical .ftag{color:#5F6B7E;}
.kconf .ic,.kconf .res{background:#B8483B;}   /* white on --red was 3.40:1 */
.seccap{margin-top:28px;max-width:var(--measure);font-size:var(--fs-sm);line-height:1.75;
  font-weight:500;color:inherit;opacity:.94;text-wrap:pretty;}
.guidelink{margin-top:18px;font-size:var(--fs-sm);font-weight:700;}
.guidelink a{color:inherit;text-decoration:underline;text-underline-offset:4px;
  text-decoration-thickness:1px;text-decoration-color:currentColor;opacity:.9;}
.guidelink a:hover{opacity:1;}

/* ── .startpath — the visitor's first decision ─────────────────────────────
   Measured before this existed: index.html put 96 distinct labels across 35
   destinations in front of a first-time reader, and the first thing they could
   touch was five screens down. Nothing ranked any of it. This is the one
   element on the page whose job is to say what to do first, what it costs in
   seconds, and what comes back. It sits under the hero CTAs, where the reader
   is already deciding. */
.startpath{margin-top:34px;max-width:760px;border-radius:14px;padding:26px 26px 22px;
  background:rgba(20,26,31,.058);border:1px solid rgba(20,26,31,.208);
  backdrop-filter:blur(14px);box-shadow:0 1px 0 rgba(20,26,31,.091) inset,0 30px 70px rgba(0,0,0,.4);}
.startpath .sp-lead{font-size:var(--fs-sm);line-height:1.7;color:var(--tx2);font-weight:500;
  max-width:var(--measure);text-wrap:pretty;}
.startpath .sp-lead b{color:var(--tx);font-weight:700;}
.sp-steps{list-style:none;margin:18px 0 0;padding:0;display:grid;gap:8px;counter-reset:sp;}
.sp-steps > li{border-radius:14px;border:1px solid transparent;transition:
  background .4s var(--ease),border-color .4s var(--ease),transform .4s var(--ease);}
.sp-steps > li > a{display:flex;gap:16px;align-items:flex-start;padding:14px 16px;
  text-decoration:none;color:inherit;border-radius:14px;}
.sp-n{flex:none;width:30px;height:30px;border-radius:50%;display:flex;align-items:center;
  justify-content:center;font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-xs);
  font-weight:700;color:var(--teal);background:rgba(11,120,120,.14);
  border:1px solid rgba(11,120,120,.42);transition:all .4s var(--ease);}
.sp-b{display:flex;flex-direction:column;gap:4px;min-width:0;}
.sp-b > b{font-size:var(--fs-body);font-weight:700;letter-spacing:-.02em;color:var(--tx);}
.sp-d{font-size:var(--fs-sm);line-height:1.6;color:var(--tx2);font-weight:500;text-wrap:pretty;}
.sp-t{font-size:var(--fs-label);font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--tx3);margin-top:2px;}
.sp-steps > li:hover{background:rgba(20,26,31,.065);border-color:rgba(20,26,31,.182);}
.sp-steps > li:hover .sp-n{transform:scale(1.06);background:rgba(11,120,120,.22);}
/* where the reader is now, and what they have already been through */
.sp-steps > li.is-now{background:rgba(11,120,120,.10);border-color:rgba(11,120,120,.40);}
.sp-steps > li.is-now .sp-n{background:var(--teal);color:#FFFFFF;border-color:var(--teal);}
.sp-steps > li.is-done .sp-n{background:rgba(11,120,120,.10);color:var(--teal);}
.sp-steps > li.is-done .sp-n::after{content:"✓";}
.sp-steps > li.is-done .sp-n{font-size:0;}
.sp-steps > li.is-done .sp-n::after{font-size:13px;}
.sp-end{margin-top:16px;padding-top:16px;border-top:1px solid rgba(20,26,31,.156);
  font-size:var(--fs-sm);color:var(--tx2);font-weight:500;}
.sp-end a{color:var(--teal);font-weight:700;text-decoration:none;}
.sp-end a:hover{text-decoration:underline;text-underline-offset:4px;}
@media (max-width:760px){
  .startpath{margin-top:26px;padding:20px 18px 18px;border-radius:14px;}
  .sp-steps > li > a{padding:12px 12px;gap:13px;}
}
/* the sticky bar becomes the step counter while a step is still ahead */
.stickycta .stepnum{display:inline-block;margin-right:10px;padding:3px 9px;border-radius:999px;
  font-size:var(--fs-label);font-weight:800;letter-spacing:.1em;color:var(--teal);
  background:rgba(11,120,120,.14);border:1px solid rgba(11,120,120,.34);}
@media (prefers-reduced-motion:reduce){
  .sp-steps > li,.sp-n{transition:none;}
}

/* the path is its own band now, so it can be a row rather than a list */
.pathsec{padding-top:var(--pad-sm);padding-bottom:var(--pad-sm);}
.pathsec .startpath{margin:0 auto;max-width:1180px;padding:30px 30px 26px;}
.pathsec .sp-steps{grid-template-columns:repeat(3,1fr);gap:12px;}
.pathsec .sp-steps > li{border:1px solid rgba(20,26,31,.13);
  background:rgba(20,26,31,.039);display:flex;}
.pathsec .sp-steps > li > a{flex-direction:column;gap:12px;height:100%;padding:18px 18px 16px;}
.pathsec .sp-lead{max-width:var(--measure);}
/* 절 하나를 딴 쪽으로 옮기고 남긴 한 줄짜리 문. .sp-lead 의 옷을 같은
   조리법으로 — 저 규칙이 .startpath 밑에만 있어 여기선 맨몸이었습니다. */
.sr-door{margin:0 auto;max-width:var(--measure);font-size:var(--fs-sm);line-height:1.7;color:var(--tx2);}
.sr-door b{color:var(--tx);}

.pathsec .sp-t{margin-top:auto;padding-top:10px;}
.pathsec .sp-b{flex:1;}
@media (max-width:900px){
  .pathsec .sp-steps{grid-template-columns:1fr;}
  .pathsec .sp-steps > li > a{flex-direction:row;gap:14px;}
  .pathsec .sp-t{margin-top:2px;padding-top:0;}
  .pathsec .startpath{padding:22px 18px 18px;}
}
/* the hero's own pointer down to it */
.heroscroll{margin-top:22px;}
.heroscroll a{display:inline-flex;align-items:center;gap:8px;font-size:var(--fs-sm);
  font-weight:700;color:var(--teal);text-decoration:none;padding:9px 16px;border-radius:999px;
  background:rgba(11,120,120,.10);border:1px solid rgba(11,120,120,.34);
  transition:background .4s var(--ease),transform .4s var(--ease);}
.heroscroll a:hover{background:rgba(11,120,120,.18);transform:translateY(2px);}
@media (prefers-reduced-motion:reduce){.heroscroll a{transition:none;}}

/* ── .tryme — "this one responds to you" ───────────────────────────────────
   The interactive blocks were indistinguishable from the illustrated ones, so
   readers scrolled past a playable demo without knowing it was playable. Same
   badge, same words, on everything that answers a click. */
.tryme{display:inline-flex;align-items:center;gap:8px;margin-left:12px;vertical-align:middle;
  padding:5px 13px 5px 10px;border-radius:999px;font-size:var(--fs-label);font-weight:800;
  letter-spacing:.1em;text-transform:uppercase;white-space:nowrap;
  color:var(--teal);background:rgba(11,120,120,.12);border:1px solid rgba(11,120,120,.40);}
.tryme > i{font-style:normal;font-size:7px;line-height:1;animation:trypulse 2.6s var(--ease) infinite;}
@keyframes trypulse{0%,100%{opacity:.35;}50%{opacity:1;}}
.sec-light .tryme,.sec-light2 .tryme,.bg-paper .tryme,.bg-clinical .tryme{
  color:#0B7878;background:rgba(10,114,114,.09);border-color:rgba(10,114,114,.34);}
@media (max-width:640px){
  .tryme{margin-left:0;margin-top:10px;display:flex;width:fit-content;}
}
@media (prefers-reduced-motion:reduce){.tryme > i{animation:none;opacity:.8;}}

/* the path's fine print — what you actually submit, said before you scroll to it */
.sp-fine{display:block;margin-top:8px;font-size:var(--fs-xs);line-height:1.65;
  color:var(--tx3);font-weight:500;max-width:var(--measure);}

/* ── .asksec — what to discuss ─────────────────────────────────────────────
   A first-time buyer's hardest problem is not comparing features, it is not
   knowing which questions separate the products. Each item links to the place
   on this site that answers it, including the two answers that are not
   flattering. */
.asklist{list-style:none;margin:38px 0 0;padding:0;counter-reset:ask;
  display:grid;gap:14px;}
.asklist > li{counter-increment:ask;position:relative;display:grid;gap:6px;
  padding:22px 24px 20px 74px;background:#fff;border:1px solid #D6DDE7;border-radius:14px;
  box-shadow:0 14px 34px rgba(20,26,31,.05);}
.asklist > li::before{content:counter(ask);position:absolute;left:24px;top:22px;
  width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-xs);font-weight:700;
  color:#0B7878;background:rgba(10,114,114,.10);border:1px solid rgba(10,114,114,.30);}
.asklist > li > b{font-size:var(--fs-lead);font-weight:700;letter-spacing:-.02em;
  color:var(--l-ink);text-wrap:balance;}
.asklist > li > span{font-size:var(--fs-sm);line-height:1.7;color:var(--l-mut);
  font-weight:500;text-wrap:pretty;}
.asklist > li > a{justify-self:start;margin-top:6px;font-size:var(--fs-sm);font-weight:700;
  color:#0B7878;text-decoration:none;border-bottom:1px solid rgba(10,114,114,.35);
  padding-bottom:2px;transition:border-color .35s var(--ease);}
.asklist > li > a:hover{border-bottom-color:#0B7878;}
@media (min-width:900px){.asklist{grid-template-columns:1fr 1fr;}
  .asklist > li:first-child{grid-column:1 / -1;}}
@media (max-width:520px){.asklist > li{padding:20px 18px 18px 18px;}
  .asklist > li::before{position:static;margin-bottom:6px;}}
@media (prefers-reduced-motion:reduce){.asklist > li > a{transition:none;}}

/* the tour link uses --teal on a teal-tinted pill, which reads on the dark
   theme and measured 2.0:1 on the light heroes it also landed on */
.sec-light .heroscroll a,.sec-light2 .heroscroll a,.bg-paper .heroscroll a,
.bg-clinical .heroscroll a,.photohero.light .heroscroll a,
.roomband .heroscroll a,.chairband .heroscroll a,.openband .heroscroll a,
.vetband .heroscroll a,.hallband .heroscroll a{
  color:#0B7878;background:rgba(10,114,114,.09);border-color:rgba(10,114,114,.34);}

/* ── .guiderail — the tour, docked in the bar ──────────────────────────────
   Two earlier attempts failed for reasons worth recording. Collapsed dots at
   the screen edge were unreadable as controls ("있는줄도 몰랐다"). Expanding
   them into a floating left panel then covered the H1 and 274 other text nodes
   at 1440px — measured. So the tour goes into the one element that already owns
   a reserved strip of the viewport: the sticky bar. Always visible, labelled,
   and on top of nothing. */
.stickycta.hasguide{transform:none;}          /* the guide is not gated on scroll */
.stickycta.hasguide .wrap{gap:14px;}
.stickycta.hasguide .msg{display:none;}       /* the steps say it better */

.guiderail{display:flex;align-items:center;gap:14px;min-width:0;flex:1;}
.gr-head{margin:0;flex:none;font-size:var(--fs-label);font-weight:800;
  letter-spacing:.14em;text-transform:uppercase;color:var(--tx3);white-space:nowrap;}
.guiderail ol{list-style:none;margin:0;padding:0;display:flex;align-items:center;gap:6px;
  min-width:0;overflow-x:auto;scrollbar-width:none;}
.guiderail ol::-webkit-scrollbar{display:none;}
.guiderail a{display:flex;align-items:center;gap:9px;padding:7px 14px 7px 7px;
  border-radius:999px;text-decoration:none;color:inherit;white-space:nowrap;
  border:1px solid transparent;transition:background .35s var(--ease),border-color .35s var(--ease);}
.guiderail a:hover{background:rgba(20,26,31,.091);border-color:rgba(20,26,31,.182);}
.gr-dot{flex:none;width:24px;height:24px;border-radius:50%;display:flex;align-items:center;
  justify-content:center;font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-label);
  font-weight:800;color:var(--tx2);background:rgba(20,26,31,.104);
  border:1px solid rgba(20,26,31,.286);transition:all .35s var(--ease);}
.gr-lab{font-size:var(--fs-xs);font-weight:700;color:var(--tx);}
.guiderail li.is-now a{background:rgba(11,120,120,.14);border-color:rgba(11,120,120,.42);}
.guiderail li.is-now .gr-dot{background:var(--teal);color:#FFFFFF;border-color:var(--teal);}
.guiderail li.is-done .gr-dot{color:var(--teal);background:rgba(11,120,120,.14);
  border-color:rgba(11,120,120,.45);font-size:0;}
.guiderail li.is-done .gr-dot::after{content:"✓";font-size:12px;}
.guiderail li.is-done .gr-lab{color:var(--tx2);}
.guiderail li.gr-end{margin-left:4px;padding-left:10px;border-left:1px solid rgba(20,26,31,.182);}
.guiderail li.gr-end.is-now .gr-dot{background:var(--teal);color:#FFFFFF;border-color:var(--teal);}
/* the step the reader has not started yet */
.guiderail li.is-next .gr-dot{color:var(--teal);border-color:rgba(11,120,120,.6);
  background:rgba(11,120,120,.16);animation:grnext 2.4s var(--ease) infinite;}
@keyframes grnext{0%,100%{box-shadow:0 0 0 0 rgba(11,120,120,.4);}
  60%{box-shadow:0 0 0 8px rgba(11,120,120,0);}}
@media (max-width:1080px){
  .gr-head{display:none;}
  .guiderail li.gr-end{display:none;}
}
@media (max-width:720px){
  .gr-lab{display:none;}
  .guiderail a{padding:6px;}
  .stickycta.hasguide .msg{display:block;font-size:var(--fs-label);}
}
@media (prefers-reduced-motion:reduce){
  .guiderail a,.gr-dot{transition:none;}
  .guiderail li.is-next .gr-dot{animation:none;}
}

/* ── .focusring — points at the control, not the section ───────────────────
   Landing on the right section still left the reader hunting for the thing
   that responds. This rings the actual control and names it, then gets out of
   the way the moment they touch it. */
.focusring{position:absolute;left:0;top:0;z-index:34;pointer-events:none;
  border-radius:14px;border:2px solid var(--teal);
  box-shadow:0 0 0 6px rgba(11,120,120,.16),0 0 40px rgba(11,120,120,.35);
  opacity:0;transition:opacity .35s var(--ease);}
.focusring.on{opacity:1;animation:frpulse 1.5s var(--ease) infinite;}
@keyframes frpulse{
  0%,100%{box-shadow:0 0 0 6px rgba(11,120,120,.16),0 0 40px rgba(11,120,120,.30);}
  50%    {box-shadow:0 0 0 11px rgba(11,120,120,.06),0 0 56px rgba(11,120,120,.44);}
}
.fr-cue{position:absolute;left:50%;top:-14px;transform:translate(-50%,-100%);
  padding:7px 14px;border-radius:999px;white-space:nowrap;
  font-size:var(--fs-xs);font-weight:800;letter-spacing:.06em;text-transform:uppercase;
  color:#FFFFFF;background:var(--teal);box-shadow:0 10px 26px rgba(11,120,120,.4);}
.fr-cue::after{content:"";position:absolute;left:50%;bottom:-6px;transform:translateX(-50%);
  border:6px solid transparent;border-top-color:var(--teal);border-bottom:0;}
@media (prefers-reduced-motion:reduce){
  .focusring.on{animation:none;}
  .focusring{transition:none;}
}

/* The step cards were prose inside an <a>. A reader read them instead of
   pressing them, so each now carries a button face and lifts on hover. */
.sp-go{align-self:flex-start;margin-top:12px;padding:9px 18px;border-radius:999px;
  font-size:var(--fs-sm);font-weight:800;white-space:nowrap;
  color:#FFFFFF;background:var(--teal);
  box-shadow:0 8px 22px rgba(11,120,120,.32);
  transition:transform .35s var(--ease),box-shadow .35s var(--ease);}
.pathsec .sp-steps > li{cursor:pointer;}
.pathsec .sp-steps > li:hover{transform:translateY(-3px);
  border-color:rgba(11,120,120,.45);background:rgba(11,120,120,.07);}
.pathsec .sp-steps > li:hover .sp-go{transform:translateX(3px);
  box-shadow:0 12px 30px rgba(11,120,120,.46);}
.pathsec .sp-steps > li:active{transform:translateY(-1px);}
@media (prefers-reduced-motion:reduce){
  .sp-go,.pathsec .sp-steps > li{transition:none;}
  .pathsec .sp-steps > li:hover{transform:none;}
}

/* ── spotlight ─────────────────────────────────────────────────────────────
   A ring around the control was still competing with a full page of equally
   bright content — the reader said they still could not tell where to look.
   The ring now also casts a page-sized shadow, so everything except the target
   dims and the eye has one place to go. The target itself stays clickable:
   this is a box-shadow on a pointer-events:none element, not an overlay. */
.focusring.on{box-shadow:0 0 0 6px rgba(11,120,120,.22),
  0 0 0 100vmax rgba(20,26,31,.74), 0 0 60px rgba(11,120,120,.5);}
@keyframes frpulse{
  0%,100%{box-shadow:0 0 0 6px rgba(11,120,120,.22),
    0 0 0 100vmax rgba(20,26,31,.74), 0 0 60px rgba(11,120,120,.42);}
  50%    {box-shadow:0 0 0 12px rgba(11,120,120,.10),
    0 0 0 100vmax rgba(20,26,31,.74), 0 0 78px rgba(11,120,120,.60);}
}
/* the instruction has to be readable against the dimmed page, so it grows */
.fr-cue{top:-16px;padding:10px 20px;font-size:var(--fs-sm);letter-spacing:.04em;
  box-shadow:0 14px 34px rgba(0,0,0,.5),0 0 0 1px rgba(20,26,31,.182);}
.fr-cue::after{border-width:8px;}
/* a second line under the ring telling them what happens when they do it */
.fr-sub{position:absolute;left:50%;bottom:-14px;transform:translate(-50%,100%);
  /* the ring is only as wide as the control, so the caption has to size to its
     own text rather than inherit that width */
  width:max-content;max-width:min(78vw,420px);
  padding:11px 18px;border-radius:14px;text-align:center;
  font-size:var(--fs-xs);line-height:1.55;font-weight:600;color:var(--tx);
  background:rgba(20,26,31,.94);border:1px solid rgba(20,26,31,.208);
  box-shadow:0 16px 40px rgba(0,0,0,.5);}

/* a page can declare its tour without printing the three-card band — the band
   is index.html's own front-page treatment, every other page just feeds the
   docked bar and the spotlight */
[data-startpath][data-compact]{display:none;}

/* The bar is translucent, so on the light-bodied pages (webchat,
   ai-answering-service) the page behind lifted its ground and the rail title
   landed at 4.46-4.49:1 — just under. An opaque ground makes the guide read the
   same on every page instead of drifting with whatever is behind it. */
.stickycta.hasguide{background:#FFFFFF;}
.stickycta.hasguide .gr-head{color:var(--tx2);}

/* Second pass on card-footer alignment. The detector flagged 23 rows; most were
   false positives worth naming: .altcol is a comparison column whose list length
   legitimately differs (the CARDS are already equal height, and pinning the <ul>
   would open a hole mid-card), and .appwin / .pack are product mocks and a
   deliberate bento. These four are the real ones — equal-height cards whose
   trailing line floated at different depths. Measured jags: .pkcard 66-110px,
   .proofcard 44px, .mlcard 22px, .warncard 21px. */
.proofcard,.pkcard,.mlcard,.warncard{display:flex;flex-direction:column;height:100%;}
.proofcard > *:last-child,.pkcard > *:last-child,
.mlcard > *:last-child,.warncard > *:last-child{margin-top:auto;}

/* Two closing sentences were injected inside a grid rather than after it,
   so they rendered as an 83px column clipped mid-sentence. A caption is
   never a grid cell — if it lands in one, it spans the row. */
.seccap,.storyfoot,.secfoot,.custfoot,.whyfoot,.exfoot,.stackfoot{grid-column:1 / -1;}

/* was an inline grid-template-columns:repeat(3,1fr), which no media query
   could override — at 375px the three cards were 102px wide and their
   captions ran one word per line and clipped past the viewport */
.whophotos{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;}
@media (max-width:900px){.whophotos{grid-template-columns:1fr;gap:18px;}}

/* ── where the hint goes ──────────────────────────────────────────────────
   Three placements, not two. The hero has a paragraph above the buttons and
   the price line below them, so "flip it to the other side" had nowhere to
   land: measured at 1440x900 the cue sat on top of the sub-headline. The copy
   column is narrow relative to the band, so there is always room beside it.

   The horizontal clamp is a variable rather than an inline `transform`.
   It used to be written straight onto style.transform, which is an inline
   declaration and therefore beat .cue-above's transform — the flip set the
   right `top` and then had its translate overwritten, so the class silently
   did nothing. */
.fr-cue,.fr-sub{--fr-dx:0px;}
.fr-cue{transform:translate(calc(-50% + var(--fr-dx)),-100%);}
.fr-sub{transform:translate(calc(-50% + var(--fr-dx)),100%);}

.focusring.cue-above .fr-sub{bottom:auto;top:-16px;
  transform:translate(calc(-50% + var(--fr-dx)),-100%);}
.focusring.cue-above .fr-cue{top:auto;bottom:-14px;
  transform:translate(calc(-50% + var(--fr-dx)),100%);}
.focusring.cue-above .fr-cue::after{top:-6px;bottom:auto;
  border-top-color:transparent;border-bottom-color:var(--teal);border-top:0;border-bottom-width:6px;}

/* beside the control: the pointer turns to face it */
.focusring.cue-side .fr-cue{left:auto;right:calc(-16px - var(--fr-side,0px));
  top:50%;bottom:auto;transform:translate(calc(100% + var(--fr-dx)),-50%);}
.focusring.cue-side .fr-cue::after{left:-6px;right:auto;bottom:auto;top:50%;
  transform:translateY(-50%);
  border:6px solid transparent;border-right-color:var(--teal);border-left:0;}
.focusring.cue-side .fr-sub{left:auto;right:calc(-16px - var(--fr-side,0px));
  top:calc(50% + 22px);bottom:auto;
  transform:translate(calc(100% + var(--fr-dx)),0);text-align:left;max-width:min(46vw,360px);}
/* mirrored when the control sits in the right half of the screen */
.focusring.cue-side.side-left .fr-cue{right:auto;left:calc(-16px - var(--fr-side,0px));
  transform:translate(calc(-100% + var(--fr-dx)),-50%);}
.focusring.cue-side.side-left .fr-cue::after{left:auto;right:-6px;
  border:6px solid transparent;border-left-color:var(--teal);border-right:0;}
.focusring.cue-side.side-left .fr-sub{right:auto;left:calc(-16px - var(--fr-side,0px));
  transform:translate(calc(-100% + var(--fr-dx)),0);text-align:right;}
/* a hint you cannot switch off is an obstruction, not a guide */
.fr-x{position:absolute;right:-13px;top:-13px;width:26px;height:26px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;pointer-events:auto;cursor:pointer;
  font-size:16px;line-height:1;font-weight:700;color:var(--tx);
  background:rgba(20,26,31,.96);border:1px solid rgba(20,26,31,.364);
  box-shadow:0 6px 18px rgba(0,0,0,.5);transition:background .3s var(--ease);}
.fr-x:hover{background:rgba(255,255,255,.98);}
@media (prefers-reduced-motion:reduce){.fr-x{transition:none;}}

/* ── running text: measure and leading ─────────────────────────────────────
   Audit of 11,264 rendered text elements found `line-height:normal` carrying
   121,547 characters — 27% of all text on the site — resolving to 1.23 on Plus
   Jakarta at 13px, while every explicitly-styled block uses 1.55–1.80. And 99
   blocks exceeded 80 characters per line (worst: 130). Neither is a per-page
   problem; both are one missing rule. */
p, li, dd { line-height: 1.65; }
p { max-width:var(--measure); }
/* product mocks, tables and chat bubbles are UI, not prose — they set their
   own measure and must not inherit a prose cap */
.appwin p, .bub, .exturn, td p, th p, .labcard p, .quotedoc p,
.crow p, .pcard p, figure p, .fr-sub, .sp-d, .gr-lab { max-width: none; }
/* A caption is prose even when it is printed inside the mock it describes.
   .crmcap sits in .appwin > .body and was therefore exempted along with the
   UI around it: measured at 1440, 94 characters on one line. Captions take
   the measure back. */
html .appwin .crmcap,html .appwin .mockcap,html .appwin .seccap,
html .appwin .exlabel,html .appwin .statnote{max-width:var(--measure);}

/* the "how it sends" clause prepended to lead-form fine print when no
   endpoint is configured - the one fact a visitor needs before clicking */
.eanote-how{color:var(--tx);font-weight:700;}
.sec-light .eanote-how,.sec-light2 .eanote-how,.onlight .eanote-how{color:var(--l-ink);}


/* ── focus ring ────────────────────────────────────────────────────────────
   One ring cannot serve both the dark sections and the light ones, so it is
   two-tone: a ring plus a collar in the opposite value. Whichever surface a
   control sits on, one of the two contrasts. Measured across 1,505 focusable
   elements on 26 pages. Declared last, and specificity-bumped with a leading html,
   because site.css loads before scenes.css and crm.css, whose .btn and .chip
   rules set box-shadow and were
   erasing the collar. */
html :focus-visible{
  outline:3px solid #FFFFFF;
  outline-offset:2px;
  border-radius:6px;
  box-shadow:0 0 0 6px rgba(4,8,15,.85);
}
html .sec-light :focus-visible,
html .sec-light2 :focus-visible,
html .bg-paper :focus-visible,
html .bg-clinical :focus-visible,
html .onlight :focus-visible,
html .hero-panel.lt :focus-visible{
  outline-color:#141A1F;
  box-shadow:0 0 0 6px rgba(20,26,31,.92);
}

/* ── narrow-width corrections, last on purpose ─────────────────────────────
   Media queries carry no specificity, so between two rules that both match,
   the one written later wins. Several narrow-width rules in this file sit
   ABOVE the wider ones they were meant to override, and lost:

     .plans      max-900 "1fr"        lost to max-1180 "repeat(2,1fr)"
                 -> three pricing cards rendered 154px wide side by side on a
                    375px screen instead of stacking.
     hero gap    max-620 "24px"       lost to max-900 "126px"
                 -> the comment above that block says "the mobile block below
                    still overrides it", but that block is above, not below.
                    Measured on a 375x812 phone: the h1 sat 275-306px down,
                    a third of the fold empty before the first word.

   Restated here rather than moved, so the original blocks stay readable next
   to the reasoning that produced them. */
@media (max-width:900px){
  .plans{grid-template-columns:1fr;}
}
@media (max-width:620px){
  .hero-inner,.hero-split,.gshero,.inthero,.exhero,.dhero-inner,.dochero,
  .heroinner,.herogrid,.herostage,
  .phero .hcap,.gshero > .wrap,.inthero > .wrap,.exhero > .wrap,.dochero > .wrap{
    padding-top:24px !important;
  }
  .photohero,.phero,.gshero,.inthero,.exhero,.dochero{padding-top:104px !important;}
  /* This was tuned for the home page, but every hero header carries both
     classes, so it applied to eight pages at once and put the first line
     of six of them at y=92 with the fixed nav ending at 93. 96px plus the
     inner 24px starts content at 120 — clear of the nav, still tight. */
  .hero.photohero{padding-top:96px !important;}
}


/* ── clearance for the fixed sticky bar ───────────────────────────────────
   site.js measures the bar and sets --stickycta-h. Without this the footer's
   last two lines sat under the bar at every scroll position and could not be
   read, and on a phone the bar covered the hero's buttons at first paint. */
/* Reserve the height only while the bar is actually up. It steps aside at the
   closer, and padding held open for a bar that is not there reads as a dead
   band above the footer. */
body:has(.stickycta.show){padding-bottom:var(--stickycta-h,0px);}

/* Gating .hasguide on .show was tried and reverted: the observer that sets
   .show never fired on these pages, so the guide disappeared entirely on
   phones. The bar stays up; the heroes that put their buttons underneath it
   are shortened instead. */

/* ── measured corrections from a full-site visual pass ─────────────────────
   Every number below was measured at 375x812 and 1440x900 before it was
   changed; each one is a control a reader has to hit or a word they have to
   read, so none of them is cosmetic. */

/* The header call-to-action wrapped to two lines on every page at 375px:
   "Get my / plan" plus the arrow chip inside a 134x50 box. */
.nav .btn{white-space:nowrap;}

/* The burger is the only way into the menu on a phone and measured 38x32 —
   twelve pixels under the 44px minimum, in both dimensions. */
.nav .burger{min-width:44px;min-height:44px;align-items:center;justify-content:center;}

/* Full-width plan buttons measured 41.4px tall: wide, but still short of a
   comfortable target. */
.plan .cta{min-height:44px;align-items:center;}

/* Eyebrow pills wrapped leaving one word alone and centred on a second line —
   "…dealing / with", "…selling / happens", "…no / vaporware". Headings on this
   site already balance; these did not. */
.eyebrow{text-wrap:balance;}

/* Below 900px the before/after arrow is rotated a quarter turn while it is
   still a full-width grid item: a 339x29 box paints as 29x339 and bled about
   155px into the card above and the card below, dropping the glyph on top of
   the sentence inside them. Rotating a square instead keeps the paint inside
   the layout. */
@media (max-width:900px){
  .baArrow{width:44px;height:44px;margin-inline:auto;display:flex;
    align-items:center;justify-content:center;}
}

/* Legal pages ran 113-119 characters per line at 1440. The paragraphs were
   capped and the list items were not, so the two disagreed inside the same
   section. */
.dsec p,.dsec li,.dsec dd{max-width:var(--measure);}

/* The knowledge-base tab strip needs 370px and its frame is 338px wide on a
   phone, with overflow hidden: the fifth tab was rendered completely off the
   edge. It scrolls now rather than disappearing. */
@media (max-width:900px){
  .ktabs{overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;}
  .ktabs::-webkit-scrollbar{display:none;}
  .ktabs > span{flex:none;}
}

/* ── content that was being cut off ────────────────────────────────────────
   Each of these was measured: scrollHeight against clientHeight, or a painted
   rect against the box that was supposed to contain it. */

/* .bento fixes its row height, so any card whose content is taller either
   spills past its own rounded border onto the section behind it, or — where
   the card clips — simply loses the rest. Measured on platform: cards of
   190px holding 198, 219, 270 and 368px of content; the "Boutique stays" card
   lost 155px, every field chip and the whole "Automates:" line, leaving a
   photo and an orphan title. Rows size to content once the grid is a single
   column, where a fixed height buys nothing anyway. */
@media (max-width:900px){
  .bento{grid-auto-rows:auto;}
  .bento > *{min-height:190px;}
}
/* the same overflow at full width, where the row height is 200px */
.bento > *{overflow:visible;}
.bento > * > *{min-width:0;}

/* The "try it" badge sits after a section eyebrow in a nowrap row and was
   pushed off the right edge — 197px of it gone on demo, nearly half the
   badge. It wraps to its own line on narrow screens instead. */
@media (max-width:768px){
  .secrule{flex-wrap:wrap;}
}

/* The eyebrow's dot is 5px and was allowed to shrink; inside a squeezed pill
   it rendered 1.6px wide and read as a stray apostrophe. */
.eyebrow i{flex:none;}

/* Range inputs painted 4px tall — the whole control, not the track. The thumb
   is what you grab, so the input itself needs a real target height. */
input[type=range]{min-height:44px;}

/* The nav is a fixed-width island: logo 107 + button 144 + burger 44 + two
   30px gaps + 35px of padding needs 390px, and the phone it has to fit on is
   375. It used to squeeze by letting the button wrap to two lines and the
   burger sit at 38px, both of which were the defects fixed above. The room
   comes out of the gaps and the padding instead. */
@media (max-width:620px){
  .navwrap .nav{gap:12px;padding-left:14px;padding-right:8px;}
  .nav .btn{padding-left:15px;}
}

/* The lead-form submit measured 37px at desktop on nine pages: the mobile
   block gave .btn a minimum height and the base rule never did. */
.btn{min-height:44px;}

/* .bento fixes its row height at 200px on the desktop grid too, and a card
   whose content is 20px taller printed that last line below its own rounded
   border, on the section behind it. minmax keeps the bento rhythm and lets a
   card grow rather than spill. */
.bento{grid-auto-rows:minmax(200px,auto);}

/* The back-to-top button stepped aside for the sticky bar only when the bar
   carried .show, and a bar holding the guide never gets it — so on a phone the
   42px button sat on the bar's own call to action with a 37x31 overlap and
   took the tap. */
body:has(.stickycta.hasguide) .totop{bottom:calc(22px + var(--stickycta-h,124px));}
@media (max-width:620px){
  body:has(.stickycta.hasguide) .totop{bottom:calc(14px + var(--stickycta-h,124px));}
}

/* Controls that were still under the touch minimum: the header phone link
   (17-19px), FAQ disclosure rows (21px) and inline arrow links (25-27px). */
/* Reach the target height with padding, not by setting display: these
   elements are hidden with display:none at some widths and forcing a display
   value brought the header phone link back on a phone, which pushed the nav
   8px past the screen. */
.nav .telcta{padding-block:calc((44px - 1.2em) / 2);}
/* the disclosure rows are .faq summary, not .faq details summary. They are
   already display:flex, so a minimum height is enough and cannot resurrect
   anything a display:none was hiding. */
.faq summary,details.voicefold > summary{min-height:44px;align-items:center;}
.linkcta{padding-block:calc((44px - 1.3em) / 2);}

/* The submit sat 11px shorter than the inputs beside it in the same form. */
.eaform .btn{min-height:48px;}

/* A caption chip is a label, not a panel: unconstrained it grew to 84-98% of
   the illustration it labels and buried the artwork's own text. */
.scene-overlay{max-width:min(62%,340px);}
@media (max-width:620px){.scene-overlay{max-width:100%;}}

/* Any page with a sticky bar, guide or not: the back-to-top button clears it. */
body:has(.stickycta) .totop{bottom:calc(22px + var(--stickycta-h,0px));}
@media (max-width:620px){
  body:has(.stickycta) .totop{bottom:calc(14px + var(--stickycta-h,0px));}
}

/* A hint that cannot be placed without sitting on the reader's own words is an
   obstruction, not a hint. When all three placements collide — which happens on
   a phone, where the copy fills the column — the ring still points at the
   control and the docked guide bar still names the step. */
/* cue-hide fires when the pointer cannot be placed without covering a
   control. It used to hide only the label and the sub, which left the
   44px close button floating over the primary CTA on the home page at
   375px — a close button with nothing left to close. Nothing to say
   means nothing to show. */
.focusring.cue-hide{display:none;}


/* ═══ layout balance pass — measured on 26 pages at 1440, 1024 and 375 ═══
   The complaint was not six bugs, it was six classes of bug. Each block below
   is one class, stated as a rule and applied everywhere the class occurs, not
   at the single instance it was spotted at. Every number was measured in the
   browser with document.fonts.ready awaited, before and after.

   These rules carry a leading `html` because site.css loads before scenes.css
   and crm.css and several of the properties are already set there at equal
   specificity, and because a handful of the measures are set in per-page
   <style> blocks, which are parsed after every stylesheet. One extra element
   in the selector wins both without reaching for !important. */

/* ── 1. explanatory prose is never a peer in a card grid ──────────────────
   Measured cause of most "orphan last row" reports: a footnote paragraph is a
   direct child of the grid or the chip row it explains, so it wraps onto a
   line of its own and is counted — and centred — as if it were a ninth chip.
   index .igrid read 3,2,3,1 and .langrow read 9,3,1 for exactly this reason;
   pricing .altgrid read 4,1. It also produced most of class 4: 76 centred
   multi-line prose blocks at 1440, rising to 153 at 375.

   THE RULE, applied site-wide: a section header block — its eyebrow, its
   heading and the standfirst directly under it — and a one-sentence closer
   may centre. Explanatory prose may not. It spans its row, aligns left,
   caps at 70ch and sits flush with the content column it belongs to. */
html .seccap,html .storyfoot,html .secfoot,html .custfoot,html .whyfoot,
html .exfoot,html .stackfoot,html .guidelink,html .tnote,html .altnote,
html .livenote,html .proofnote,html .metnote,html .plainfoot,html .costfoot,
html .vpfoot,html .stagefoot,html .fn,html .disclaim,html .note,html .prob,
html .eanote,html .mockcap,html .photocap,html .capL,html .alt,html .whotxt,
html .heroscroll{
  grid-column:1 / -1;   /* it is a band under the grid, not a cell in it */
  flex-basis:100%;      /* the flex rows need the same statement */
  width:100%;
  max-width:var(--measure);
  text-align:left;
  margin-inline:0;
}

/* The other half of the same rule. Standfirsts are allowed to centre, but the
   measure has to be one number or the centring has no rule behind it. Measured
   across the 26 pages: .lead and .sub were capped at 400, 410, 420, 440, 460,
   520, 530, 540, 560, 600, 610, 620, 640, 660 and 680px, plus two in ch — set
   in per-page <style> blocks, twenty different answers to one question. */
html .lead,html .sub,html .lsub{max-width:var(--measure);}

/* ── 2. a column of cards ends where the panel beside it ends ─────────────
   .todayside is three cards in the right half of a two-column dashboard and
   carried align-content:start, so the stack finished 110px above the bottom of
   the painted panel on its left. .calcout is the right half of the calculator
   shell and finished 166px short of the left half. Both now resolve their own
   slack instead of leaving it at the bottom edge. */
html .todayside{align-content:stretch;}
html .calcout{display:flex;flex-direction:column;justify-content:center;}

/* ── 3. wrapping token rows wrap evenly ───────────────────────────────────
   Free wrapping put 8 items on one line and 1 alone underneath. The counts
   measured: .intwall 8+1 at 1440 and 5+1 at 1024, .langrow 9+3 at 1440 and
   6,5,6,2 on industries, .kwrow 5,3,1, .chiprow 7+1, .exfilter 7+2.
   Even tracks make the row count deliberate at every width — the minimum
   track on each is set from the widest item that row actually holds, so the
   column count falls where the balance is even rather than where the text
   happens to run out. */
html .langrow,html .intwall,html .kwrow,html .chiprow,html .exfilter{
  display:grid;align-items:stretch;justify-items:stretch;
}
html .langrow > *,html .intwall > *,html .kwrow > *,
html .chiprow > *,html .exfilter > *{
  text-align:center;justify-content:center;width:100%;
}
/* the column counts moved to the balanced block at the end of this file */
/* Below the phone breakpoint two columns of these leave a 1-item last row on
   every odd count, and a single column reads as a list, which is what a
   wrapped row of nine becomes on a 375px screen anyway. */
@media (max-width:620px){
  html .intwall,html .chiprow,html .exfilter{grid-template-columns:1fr;}
}

/* ── 4. the legible floor inside figures ──────────────────────────────────
   The only text on the site still set in px rather than a token is the label
   inside a hand-drawn SVG — 150 elements at 12.5, 60 at 12, and a handful at
   11.5, 11 and 10.5, including every label on the capture fan on the home
   page. They are presentation attributes, which any CSS declaration outranks,
   so the floor can be applied to exactly the sizes that break it and nothing
   above it is touched. Written against the attribute rather than the element
   because several of them are inherited from a <g>. */
svg [font-size="10.5"],svg [font-size="11"],svg [font-size="11.5"],
svg [font-size="12"],svg [font-size="12.5"]{font-size:13px;}

/* ── 5. the same two rules again, one step heavier ────────────────────────
   Nine of the blocks above are centred by a per-page <style> rule written as
   a descendant pair — `.altsec .note`, `.vocabsec .note`, `.proofslot
   .proofnote` — which outranks a single class plus `html`. An attribute
   selector on the ancestor carries one more unit of weight and settles it
   without !important, which would take the decision away from the pages for
   good. Measured after: pricing's 11-line centred footnote and index's
   5-line one both read left, capped, flush with their column. */
html [class] .seccap,html [class] .storyfoot,html [class] .secfoot,
html [class] .custfoot,html [class] .whyfoot,html [class] .exfoot,
html [class] .stackfoot,html [class] .guidelink,html [class] .tnote,
html [class] .altnote,html [class] .livenote,html [class] .proofnote,
html [class] .metnote,html [class] .plainfoot,html [class] .costfoot,
html [class] .vpfoot,html [class] .stagefoot,html [class] .fn,
html [class] .disclaim,html [class] .note,html [class] .prob,
html [class] .eanote,html [class] .mockcap,html [class] .photocap,
html [class] .capL,html [class] .whotxt{
  text-align:left;max-width:var(--measure);margin-inline:0;
}
/* .fn is also the step number inside a flow card, where it is a label and not
   a footnote — one class doing two jobs. Put that one back. */
html [class] .fstep .fn{text-align:inherit;max-width:none;}

/* Card body copy is prose too: four paragraphs inside webchat's flow cards
   were centred at 4 lines each because the card centres its label. */
html .fstep p,html .fstep b{text-align:left;}

/* ── 6. the last text below the floor ─────────────────────────────────────
   After the token change, 26 pages held 10 rendered nodes still under the
   floor. Six were SVG labels at 8.5 and 9.5, outside the range the block
   above covers. Four were the hero shelf's two micro-labels on the home page,
   set to 9px in that page's own <style> — small enough that the eye reads
   them as texture rather than words. */
svg [font-size="8"],svg [font-size="8.5"],svg [font-size="9"],
svg [font-size="9.5"],svg [font-size="10"]{font-size:13px;}
/* The other four are the home page hero shelf's two micro-labels, set to 9px
   in index.html's own <style>. Raising them to the 13px floor was tried and
   measured: the label overflows its card by 25 and 27px, because the card is
   sized for 9px text. That one needs the card to change, not the type, so it
   is left alone and written up rather than half-fixed here.
   index.html <style>: .heroshelf .nl .t i / .heroshelf .nl .t em. */

/* ── 7. the floor is per role, and a product mock is a figure ─────────────
   Raising --fs-xs and --fs-label by one and two pixels is right for text a
   visitor reads, and wrong inside the software mock-ups: those boxes are
   drawn to a fixed width and the extra pixel pushed 96 elements past their
   own edge at 375 and 19 at 1440 — transcript speaker labels, KPI tiles, the
   funnel row, the calendar grid, the footer brand block. Measured, not
   assumed: the same diff with the tokens rolled back showed none of them.

   A mock is a picture of an interface, so its labels take the figure floor of
   13px rather than the body floor of 14px — the same floor the SVG labels
   above take, for the same reason. Scoping the two tokens to the mock chrome
   is one declaration and reaches every mock on every page. */
html .appwin,html .calmock,html .pipeboard,html .quotedoc,html .custcard,
html .kpitiles,html .repcard,html .ledger,html .transcript,html .funnelrow,
html .browserframe,html .msgthread,html .callcard,html .demo-body,
html .bigfooter .brand{
  --fs-xs:13px;
  --fs-label:13px;
}

/* ── the same slack rule, on the column grids that were left out ──────────
   The pattern above already exists for .crmduo / .crmtrio / .duo / .pairgrid:
   a stretched grid track does nothing unless the card inside it is told to
   fill, so the mock takes the slack and both columns finish on one line.
   Six more grids of the same shape were only ever given `min-width:0`.

   Measured at 1440 before this: the last mark inside one column landed ahead
   of the other by 247px on webchat .thinkcols, 343px on clinics .cols, 268px
   on stays .cols, 250px on academies .cols, 248px on franchise .split and
   213px on voice .faqcols.

   `flex:1 0 auto` and not `flex:1`, for the reason recorded above: basis 0
   sizes the window from the grid instead of from its contents, and .appwin
   clips, which cost the WhatsApp mock 107px of its own pipeline. */
.thinkcols > div,.faqcols > div,.cols > div,.split > div,
.grid > div,.reqwrap > div,.reqwrap > aside{
  display:flex;flex-direction:column;
}
.thinkcols > div > .appwin,.thinkcols > div > .gradborder,
.faqcols > div > .appwin,.cols > div > .appwin,.split > div > .appwin,
.grid > div > .appwin,.reqwrap > div > .appwin,
.thinkcols > div > .tsteps,.faqcols > div > .faq{
  flex:1 0 auto;
}

/* ═══════════════════════════════════════════════════════════════════════════
   HEADER MENUS — the 21 destinations that only the footer knew about
   ───────────────────────────────────────────────────────────────────────────
   Measured problem: the header carried 5 links, the footer 26. Twenty-one
   destinations existed only below a page that is thirteen screens tall, so in
   practice they did not exist. Each top-level item is now a disclosure button
   that opens a panel of the pages underneath it, grouped by what a buyer is
   trying to do rather than by filename.

   Constraints this is built against:
     • the header already overflows its budget at 375 — so nothing new is added
       to the nav ROW. The panels are overlays that cost the row zero pixels,
       and below 900px the whole .links group is already display:none and folds
       into the existing burger.
     • 44px minimum on every target, panel links included.
     • click to open, never hover — a hover menu is unusable by keyboard and
       hostile on touch.
   ═══════════════════════════════════════════════════════════════════════════ */

.navitem{position:static;display:inline-flex;}

/* The top-level control is a real <button>, so Enter and Space work without a
   single line of script, and assistive tech is told it is a disclosure. */
.nav .navtop{
  display:inline-flex;align-items:center;gap:6px;
  min-height:44px;padding:0 2px;
  background:none;border:0;cursor:pointer;
  font:inherit;font-size:var(--fs-xs);font-weight:600;
  color:var(--tx2);letter-spacing:inherit;white-space:nowrap;
}
.nav .navtop:hover,.nav .navtop[aria-expanded="true"]{color:#141A1F;}
.nav .navtop.on{color:#141A1F;}
.navwrap.onlight .nav .navtop{color:var(--l-mut);}
.navwrap.onlight .nav .navtop:hover,
.navwrap.onlight .nav .navtop.on,
.navwrap.onlight .nav .navtop[aria-expanded="true"]{color:var(--l-ink);}

/* the chevron is drawn, not typed — a glyph would inherit the 13px floor and
   render as text to a screen reader that ignores aria-hidden on ::before */
.nav .navtop .cv{
  width:7px;height:7px;border-right:2px solid currentColor;border-bottom:2px solid currentColor;
  transform:translateY(-2px) rotate(45deg);opacity:.55;transition:transform .25s var(--ease),opacity .25s;
}
.nav .navtop[aria-expanded="true"] .cv{transform:translateY(1px) rotate(-135deg);opacity:1;}

/* ── the panel ──────────────────────────────────────────────────────────────
   .navwrap is the containing block (left:0;right:0), so centring inside it can
   never exceed the viewport: the width is clamped to 100vw minus the gutters
   before the translate is applied. This is what keeps document overflow at 0. */
.navpanel{
  position:absolute;top:calc(100% + 12px);left:50%;transform:translateX(-50%);
  width:min(1060px,calc(100vw - 32px));
  background:rgba(20,26,31,.975);border:1px solid var(--hair2);border-radius:14px;
  padding:26px 28px 20px;backdrop-filter:blur(20px);
  box-shadow:0 30px 80px rgba(0,0,0,.55);
  z-index:30;
  color:#141A1F;--tx:#141A1F;--tx2:#3B454D;--tx3:#616B75;
}
.navpanel[hidden]{display:none;}
.np-in{display:grid;grid-template-columns:repeat(auto-fit,minmax(178px,1fr));gap:8px 26px;}
.np-col{min-width:0;}
.np-h{
  margin:0 0 6px;font-size:var(--fs-label);font-weight:800;letter-spacing:.14em;
  text-transform:uppercase;color:var(--tx3);
}
.np-col ul{list-style:none;margin:0;padding:0;}
.np-col a{
  display:flex;align-items:center;min-height:44px;padding:4px 10px;
  margin-left:-10px;border-radius:8px;
  font-size:var(--fs-xs);font-weight:600;color:var(--tx2);line-height:1.35;
}
.np-col a:hover,.np-col a:focus-visible{background:rgba(20,26,31,.091);color:#141A1F;}
.np-col a.np-here{color:#141A1F;box-shadow:inset 2px 0 0 var(--teal);}

/* the tour handoff — every panel offers the subject tour that covers it */
.np-foot{
  grid-column:1/-1;display:flex;flex-wrap:wrap;align-items:center;gap:8px 22px;
  margin:14px 0 0;padding-top:14px;border-top:1px solid var(--hair2);
}
.np-foot a{display:inline-flex;align-items:center;min-height:44px;font-size:var(--fs-xs);font-weight:700;}
.np-tour{color:var(--teal);}
.np-tour:hover{color:#141A1F;}
.np-all{color:var(--tx3);margin-left:auto;font-weight:600;}
.np-all:hover{color:#141A1F;}
@media (prefers-reduced-motion:reduce){.nav .navtop .cv{transition:none;}}

/* ── mobile: fold into the burger that already exists ───────────────────────
   Below 900px .nav .links is display:none until site.js adds .open. The panels
   become inline accordions inside that same sheet — one pattern, not two. */
@media (max-width:900px){
  .nav .links.open{max-height:calc(100vh - 96px);overflow-y:auto;-webkit-overflow-scrolling:touch;}
  .nav .links.open .navitem{display:block;width:100%;}
  .nav .links.open .navtop{
    width:100%;justify-content:space-between;padding:0 16px;min-height:52px;
    font-size:var(--fs-body);color:#141A1F;border-bottom:1px solid var(--hair2);
  }
  .nav .links.open .navitem:last-child .navtop{border-bottom:0;}
  .navpanel{
    position:static;transform:none;width:auto;
    background:rgba(20,26,31,.039);border:0;border-radius:0;
    padding:8px 16px 14px;box-shadow:none;backdrop-filter:none;
  }
  .np-in{grid-template-columns:1fr;gap:2px;}
  .np-h{margin-top:12px;}
  .np-foot{margin-top:10px;padding-top:10px;}
  .np-all{margin-left:0;}
}

/* ═══════════════════════════════════════════════════════════════════════════
   FOOTER — one canonical footer, fourteen trades, grouped
   The industries column used to differ on 10 of 26 pages (three of them had no
   Clinics link at all) because each page carried its own copy. It is now
   generated from one table, and the trades are grouped with the same four
   headings the header uses, so the structure is learned once.
   ═══════════════════════════════════════════════════════════════════════════ */
.bigfooter .cols{grid-template-columns:1.35fr 1fr 2.05fr 1fr 1fr;gap:44px;}
.bigfooter .fcol{min-width:0;}
.bigfooter .ftgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:4px 22px;}
.bigfooter .fgrp{min-width:0;}.bigfooter h5,.bigfooter .hl5{
  margin:0 0 2px;font-size:var(--fs-label);font-weight:800;letter-spacing:.1em;
  text-transform:uppercase;color:var(--tx3);
}.bigfooter .fgrp + .fgrp h5,.bigfooter .fgrp + .fgrp .hl5{margin-top:12px;}
/* Footer links measured 31px tall against the site's own 44px rule. */
.bigfooter .lnk{display:flex;align-items:center;min-height:44px;padding:2px 0;}
.bigfooter .lnk[aria-current="page"]{color:var(--tx);}
.bigfooter .fmail{margin-top:10px;}
.bigfooter .fmap{
  margin-top:8px;font-weight:700;color:var(--teal);
}
.bigfooter .fmap:hover{color:#141A1F;}
.bigfooter .base .r{align-items:center;gap:20px;flex-wrap:wrap;}
.bigfooter .base .r .lnk{min-height:44px;}
@media (max-width:1180px){
  .bigfooter .cols{grid-template-columns:1fr 1fr 1fr;gap:34px;}
  .bigfooter .ftrades{grid-column:1/-1;}
}
@media (max-width:900px){
  .bigfooter .cols{grid-template-columns:1fr 1fr;gap:30px;}
  .bigfooter .ftrades{grid-column:1/-1;}
  .bigfooter .brand{grid-column:1/-1;}
}

/* ── the subject tour, in the rail that already exists ──────────────────────
   A cross-page tour renders as .guiderail.tourrail — same dots, same done /
   here / ahead states, same dock. The only additions are a way out and the
   next-stop button, which is the bar's own .btn retargeted. */
.gr-stop{
  flex:none;display:inline-flex;align-items:center;min-height:44px;padding:0 12px;
  font-size:var(--fs-label);font-weight:700;color:var(--tx3);
  border:1px solid var(--hair2);border-radius:999px;white-space:nowrap;
}
.gr-stop:hover{color:#141A1F;border-color:rgba(20,26,31,.3);}
.stickycta.hastour .btn{white-space:nowrap;}
@media (max-width:900px){
  .gr-stop{padding:0 10px;font-size:var(--fs-label);}
}

/* ── sitemap.html ───────────────────────────────────────────────────────────
   The human sitemap: every page, grouped, with a line of orientation and the
   anchors worth landing on. */
.smhero{padding:150px 0 40px;}
.smgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:26px;align-items:start;}
.smcard{
  border:1px solid var(--hair);border-radius:14px;padding:22px 24px 18px;
  background:rgba(20,26,31,.026);min-width:0;
}
.smcard > h3{font-size:var(--fs-lead);margin:0 0 4px;}
.smcard > p.smlede{margin:0 0 14px;font-size:var(--fs-sm);color:var(--tx3);line-height:1.6;}
.smpage{padding-top:14px;border-top:1px solid var(--hair);}
.smcard > .smpage:first-of-type{border-top:0;padding-top:0;}
.smpage + .smpage{margin-top:12px;}
.smpage > a.smt{
  display:flex;align-items:center;min-height:44px;
  font-size:var(--fs-body);font-weight:700;color:var(--tx);
}
.smpage > a.smt:hover{color:var(--teal);}
.smpage > p{margin:0 0 6px;font-size:var(--fs-sm);color:var(--tx3);line-height:1.6;}
.smanch{display:flex;flex-wrap:wrap;gap:6px;list-style:none;margin:0;padding:0;}
.smanch a{
  display:inline-flex;align-items:center;min-height:44px;padding:0 12px;
  border:1px solid var(--hair);border-radius:999px;
  font-size:var(--fs-label);font-weight:600;color:var(--tx3);
}
.smanch a:hover{color:#141A1F;border-color:var(--hair2);background:rgba(20,26,31,.065);}
.tourcards{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(340px,100%),1fr));gap:18px;}
.tourcard{
  display:flex;flex-direction:column;gap:8px;
  border:1px solid var(--hair2);border-radius:14px;padding:22px 24px;
  background:rgba(11,120,120,.05);min-width:0;
}
.tourcard h3{margin:0;font-size:var(--fs-lead);}
.tourcard p{margin:0;font-size:var(--fs-sm);color:var(--tx3);line-height:1.65;}
.tourcard .stops{margin:0;font-size:var(--fs-label);color:var(--tx3);font-weight:700;letter-spacing:.06em;text-transform:uppercase;}
.tourcard .linkcta{margin-top:auto;align-self:flex-start;}
.tradetour{display:flex;flex-wrap:wrap;gap:8px;margin-top:6px;}
.tradetour a{
  display:inline-flex;align-items:center;min-height:44px;padding:0 14px;
  border:1px solid var(--hair2);border-radius:999px;
  font-size:var(--fs-xs);font-weight:600;color:var(--tx2);
}
.tradetour a:hover{color:#141A1F;background:rgba(11,120,120,.12);border-color:rgba(11,120,120,.42);}

/* A subject tour has six or seven stops where the in-page tour has three, and
   at seven the rail scrolled: stops 5-7 existed but were off the end of the
   bar. Only the stop you are on and the one you are going to need their words
   — the rest are dots, which is all a progress rail ever needed to be. */
.tourrail li:not(.is-now):not(.is-next) .gr-lab{display:none;}
.tourrail li:not(.is-now):not(.is-next) > a{padding-right:7px;}

/* The wordmark is a link home and measured 22px — half the site's own touch
   minimum, and the one control on every page that a lost reader reaches for.
   It is given the height without changing the nav row, which already sits at
   46px because of the button beside it. */
.nav .logo{display:inline-flex;align-items:center;min-height:44px;}
/* Fourteen trade chips in a one-quarter column stacked fourteen rows deep and
   made the card three times the height of the four beside it. Given the full
   width they lay out as one band. */
.tourcard-wide{grid-column:1/-1;}

/* ── a floor under the narrowest phones ───────────────────────────────────
   375px is this site's tested floor and headings sit inside their boxes there.
   At 320 — an iPhone SE, below the floor but a real device — a heading whose
   &nbsp; chain has no break opportunity left hangs out of its own column;
   measured worst case, 263px past a 306px box, which clips.

   `overflow-wrap:anywhere` is a safety net rather than a style: it only breaks
   inside a word when there is no other opportunity at all. It is scoped to
   360px and below so it can never touch a width anyone composes for. */
@media (max-width:360px){h1,h2,h3,h4,.h1,.h2,.hl4{overflow-wrap:anywhere;}
}

/* ── the last controls under the touch floor ──────────────────────────────
   The site holds every control to 44px. An audit across all 33 pages found two
   classes still under it, and both are things a reader is meant to press:

     .chip      33-35px, 48 of them — the trade and channel pickers on the
                home page, the demo, and the price lab
     .fr-x      26px    — the control that dismisses the guided-tour spotlight,
                which is the one control a reader reaches for when the overlay
                is in their way

   Padding is left alone so the pills keep their shape; the height comes from a
   floor and centred content instead. */
.chip{min-height:44px;display:inline-flex;align-items:center;}
.askrow .chip,.labsamples .chip{min-height:44px;}
.fr-x{width:26px;height:26px;right:-9px;top:-40px;font-size:16px;}
/* The 44px lives here instead: an invisible, centred hit area. The circle
   stays small so it cannot land on the control beside the one being
   pointed at, and it sits above the ring where there is nothing to hit. */
.fr-x::before{content:"";position:absolute;left:50%;top:50%;width:44px;height:44px;
  transform:translate(-50%,-50%);border-radius:50%;}

/* Named controls still under the floor after the .chip pass. Unclassed anchors
   are left alone deliberately: they are links inside sentences, which WCAG 2.5.8
   exempts, and forcing 44px on them would put holes in the prose. */
.chtab,.lnum,.num{min-height:44px;display:inline-flex;align-items:center;justify-content:center;}

/* ── the last measured contrast misses ────────────────────────────────────
   After the hard-coded inks were replaced with the tuned ones, fifteen items
   were still under AA. They are all small text sitting on a tinted panel rather
   than on one of the eleven dark surfaces the tokens were tuned against, so the
   token is right and the ground is the thing that moved.

     .fstep span      --tx3 on a 14% green tint  -> 4.29:1
     .ver             the build badge, four grounds -> 4.14:1
     .altsec .photocap a warm grey on near-white -> 3.64:1

   Measured after: 4.99, 4.7 and 4.6 respectively. */
html .funnelrow .fstep span,html .funnelrow .fstep .fn,html .fstep span{color:#939FB0;}
.ver{color:#9AA6B8;}
.navwrap.onlight .ver,.sec-light .ver{color:#4B555E;}
html .altsec .photocap{color:#616B75;}

/* ── one scale of widths, not six ─────────────────────────────────────────
   Measured at 1440 across 33 pages: 231 sections stacked blocks at three or
   more different content widths — a grid at 1128, a standfirst at 651-816, a
   caption at 702-742. Nothing was wrong with any single number; having six of
   them in one section is what reads as prose skewed to one side.

   --measure is the reading column. It is the only width prose may take. */
:root{
  /* Three widths, and only three. Measured before this: a single section would
     put its grid at 1128, its header block at 600-620 and its caption at
     702-742 — six different content columns stacked up the page, which is what
     reads as prose skewed to one side under a full-width grid.
       --w-full   the grid and figure column (the .wrap's own width)
       --w-head   a section header: related to the grid, not floating in it
       --measure  running prose, the only width a paragraph may take */
  --w-head:62rem;
  /* a multiplier on the element's own em: ~76 characters at any size.
     72ch was 140 characters, because ch is the width of "0". */
  --measure-em:36;
  --measure:calc(var(--measure-em) * 1em);
}

html .lead,html .sub,html .lsub,html .secintro,html .standfirst{
  max-width:var(--measure);
}

/* ── a caption is one column ───────────────────────────────────────────────
   These used to flow into CSS multi-columns so a caption would reach the
   full width of its figure. That solved a width problem and created a
   reading one: the median caption here is 163 characters — two or three
   lines — so each column held a line and a half and the sentence broke
   across the gutter. A reader hit "arrives as a message with two", jumped
   back up and to the right, and carried on at "delivery ticks against an
   account". Nothing in multicol prevents that; orphans and widows govern
   where a column breaks, not whether the break makes sense.

   92ch rather than the 72ch prose takes: a caption is set several steps
   smaller, so 92 characters of it is a physically shorter line than 72
   characters of a standfirst — and it puts the short fifth of them on one
   line instead of stranding three words on a second. */
html [class] figcaption.scenecap,html [class] .scenecap,html [class] .photocap,
html [class] .mockcap,html [class] .exlabel,html [class] .pkcap,
html [class] .statnote,html [class] .seccap,html [class] .funfoot,
html [class] .labfoot,html [class] .altnote,html [class] .proofnote,
html [class] .metnote,html [class] .storyfoot,html [class] .secfoot,
html [class] .custfoot,html [class] .whyfoot,html [class] .exfoot,
html [class] .stackfoot,html [class] .tnote,html [class] .livenote,
html [class] .plainfoot,html [class] .costfoot,html [class] .vpfoot,
html [class] .stagefoot,html [class] .disclaim,html [class] .note{
  max-width:min(100%,calc(var(--measure-em) * 1em));
  columns:auto;
  column-count:1;
  column-width:auto;
  text-wrap:pretty;
}

/* Section header blocks were capped per page at 600, 620, 640, 660, 680, 700,
   720, 740 and 800px above a 1128px grid. One value, related to the grid. */
html [class] .head,html [class] .blockhead,html [class] .sechead,
html [class] .khead,html [class] .thead,html [class] .chead{
  max-width:var(--w-head);
}

/* ── a section header fills its section ───────────────────────────────────
   Seventy-five header blocks carried an inline max-width at eight different
   values above a grid that is always 1128px, so the page stepped 660 -> 700 ->
   1128 down its own left edge. They take one width now.

   Filling that width is not the same as widening the prose. Past about 75
   characters a line stops being readable, so instead of one long measure the
   header takes two columns on a wide screen — the heading left, the standfirst
   right — which is the arrangement this site already uses on the channel band.
   Both keep a reading measure; together they span the grid.

   Only headers that actually have a standfirst to put in the second column, and
   only where the section is wide enough to carry two. Centred headers are left
   centred: there the balance is the point. */
@media (min-width:1100px){
  html [class] .head:not(.mid):not(.centered):has(> .lead),
  html [class] .blockhead:not(.mid):has(> .lead),
  html [class] .sechead:not(.mid):has(> .lead){
    max-width:none;
    display:grid;
    grid-template-columns:1.02fr .98fr;
    column-gap:64px;
    align-items:end;
  }
  html [class] .head:not(.mid):not(.centered):has(> .lead) > .eyebrow,
  html [class] .blockhead:not(.mid):has(> .lead) > .eyebrow,
  html [class] .sechead:not(.mid):has(> .lead) > .eyebrow{
    grid-column:1;grid-row:1;justify-self:start;
  }
  html [class] .head:not(.mid):not(.centered):has(> .lead) > h2,
  html [class] .head:not(.mid):not(.centered):has(> .lead) > .h2,
  html [class] .blockhead:not(.mid):has(> .lead) > h2,
  html [class] .sechead:not(.mid):has(> .lead) > h2{
    grid-column:1;grid-row:2;max-width:none;
  }
  html [class] .head:not(.mid):not(.centered):has(> .lead) > .lead,
  html [class] .blockhead:not(.mid):has(> .lead) > .lead,
  html [class] .sechead:not(.mid):has(> .lead) > .lead{
    grid-column:2;grid-row:2;margin-top:0;max-width:var(--measure);
  }
  /* anything else in the block sits under both columns rather than beside one */
  html [class] .head:not(.mid):not(.centered):has(> .lead) > *:not(.eyebrow):not(h2):not(.h2):not(.lead),
  html [class] .blockhead:not(.mid):has(> .lead) > *:not(.eyebrow):not(h2):not(.h2):not(.lead),
  html [class] .sechead:not(.mid):has(> .lead) > *:not(.eyebrow):not(h2):not(.h2):not(.lead){
    grid-column:1 / -1;
  }
  /* a pill is not a row: badges and chips keep their own width */
  html [class] .head:has(> .lead) > .eyebrow,
  html [class] .head:has(> .lead) > .tryme,
  html [class] .head:has(> .lead) > .rmtag,
  html [class] .head:has(> .lead) > .pill,
  html [class] .blockhead:has(> .lead) > .eyebrow,
  html [class] .sechead:has(> .lead) > .eyebrow{
    justify-self:start;width:max-content;max-width:100%;
  }
  html [class] .head:has(> .lead) > .tryme{grid-column:1;grid-row:3;margin-top:14px;}
}

/* ── the chip walls read a computed column count ───────────────────────────
   The count comes from assets/js/balance.js, which asks how many columns
   divide the items evenly rather than only how many fit. `auto-fit` is the
   fallback when the script has not run: it fills the row, which is what
   these did before, stub last row and all. Every wall declares the minimum
   chip width it wants as a token so the script and the fallback read the
   same number from one place. */
html .langrow,html .intwall,html .kwrow,html .chiprow,html .exfilter,
html .langbig,html .tradewords,html .tradetour,html .smanch,
html .np-in,html .bigfooter .ftgrid,
html .tline,html .cases,html .whogrid,html .stackrow,html .tourcards,
html .funflow,html .gatesteps,html .specstrip,html .chanlinks,
html .approvedby{
  display:grid;align-items:stretch;justify-items:stretch;
  grid-template-columns:repeat(var(--cols,auto-fit),minmax(var(--chip-min),1fr));
}
html .langbig > *,html .tradewords > *,html .tradetour > *,html .smanch > *{
  text-align:center;justify-content:center;width:100%;
}
html .langrow  {--chip-min:156px;}
html .intwall  {--chip-min:160px;}
html .kwrow    {--chip-min:150px;}
html .chiprow  {--chip-min:210px;}
html .exfilter {--chip-min:180px;}
html .langbig  {--chip-min:150px;}
html .tradewords{--chip-min:170px;}
html .tradetour{--chip-min:150px;}
html .smanch  {--chip-min:130px;}
html .np-in   {--chip-min:150px;}
html .bigfooter .ftgrid{--chip-min:150px;}
/* A card holding sentences needs room for about 45 characters a line;
   at 1128px a 340px floor gives three columns, and the balancer steps
   down to two when three would leave a stub row. */
html .tline,html .cases,html .whogrid,html .stackrow,html .tourcards,
html .funflow,html .gatesteps,html .specstrip,html .chanlinks,
html .approvedby{--chip-min:340px;}
/* Both are menus rather than chip walls: only the column count is shared,
   the links keep their own left alignment. */

/* ── the sitemap's cards align, and the long one is a band ────────────────
   Seven index cards running 434px to 3144px tall. In a three-track grid the
   long one took a column and the row beside it stood open. Multicol was
   worse: it cannot split a card marked break-inside:avoid, so three cards
   balanced into two of the three columns and the section grew from 3695px
   to 6160.

   So the long card stops being a column. It is the first band, full width,
   with its own list flowing inside it; the remaining six form an even three
   by two whose cards stretch to their row, which is what makes their
   bottoms line up. */
html .smgrid{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:26px;align-items:stretch;
}
html .smgrid > .wide{grid-column:1 / -1;}
html .smgrid > .wide .smanch{--chip-min:150px;}
@media (max-width:1000px){ html .smgrid{grid-template-columns:repeat(2,minmax(0,1fr));} }
@media (max-width:700px){  html .smgrid{grid-template-columns:1fr;} }

/* On a phone two columns of chips leave a one-item last row on every odd
   count and a single column reads as the list it already is at 375px. This
   sits after the balanced block so it still outranks the computed count. */
@media (max-width:620px){
  html .intwall,html .chiprow,html .exfilter,html .tradewords{
    grid-template-columns:1fr;
  }
}

/* ── a bento closes its last row ───────────────────────────────────────────
   The pattern is written for seven cards, where six and seven take three
   columns each and close the row together. Platform has six, so the sixth
   took three of six columns and left a 548px hole beside it — measured at
   1440. A last card with no partner spans the row instead of half of it,
   which is also the right shape for the card that lands there: the "and
   yours" catch-all at the end of a list of trades. */
html .bento > :nth-child(6):last-child{grid-column:span 6;}
html .bento > :nth-child(3):last-child{grid-column:span 2;}

/* ── an inline grid a media query can still reach ──────────────────────────
   Six grids declared their columns in a style attribute, which outranks
   every rule in every sheet — so no breakpoint could collapse them and they
   held two or three columns down to 375px. Measured there: a report card at
   187px with a 45px tile inside it, where the word "Conversations" needs
   133. The column list moved to a custom property, which a rule reads and a
   media query can override. */
html .autocols{ grid-template-columns:var(--gc,1fr); }
@media (max-width:700px){ html .autocols{ grid-template-columns:1fr; } }

/* The footer's trade block ends with the way out of it: every trade on one
   page. It sits under the groups rather than inside them. */
html .bigfooter .ftall{
  display:inline-block;margin-top:14px;font-weight:700;color:var(--teal);
}
html .bigfooter .ftall:hover{color:#141A1F;}

/* 120px of air above the footer plus 60px inside it is a screen and a quarter
   of nothing between the last argument and the site map, on a phone. */
@media (max-width:640px){
  html .bigfooter{margin-top:56px;padding:36px 0 28px;}
}

/* On a phone the trade directory is twenty-five links at the site's own 44px
   touch height — about 830px of footer, on all seventy-one pages, below the
   thing the reader came for. The links stay in the document; only the grid is
   folded away, and .ftall ("all twenty-five trades") is the way in. */
@media (max-width:700px){
  html .bigfooter .ftgrid{display:none;}
  html .bigfooter .ftall{margin-top:6px;}
}



/* The link row under a nav panel spans the columns. It was a grid child like
   any other, so the balancer counted six items in a five-group panel and
   settled on four columns to divide them. */
html .np-in > .np-foot{grid-column:1 / -1;}

/* ── a standalone link is a target, not a word in a sentence ───────────────
   Measured at 375 across 44 pages: the named links that stand on their own —
   "The dental pack →", "Pricing ↗", the section chips on the site map — are
   47 to 161px wide and 18 to 23px tall. Width is fine; height misses the
   24px floor by a few pixels.

   The fix is a hit area rather than a size change: growing the links
   themselves would reflow lists that are already tuned. Six pixels of reach
   above and below takes the smallest of them past the floor and stays well
   inside the gap between neighbours, so the next link down cannot steal the
   tap. Links inside a sentence are left alone — WCAG exempts them, and
   padding them out would break the line they sit in. */
@media (pointer:coarse){
  html a.go, html .fcol a.lnk, html .smanch a, html .smt, html .np-col a{
    position:relative;
  }
  html a.go::after, html .fcol a.lnk::after, html .smanch a::after,
  html .smt::after, html .np-col a::after{
    content:"";position:absolute;left:0;right:0;top:-6px;bottom:-6px;
  }
}

/* ── running text takes the measure, wherever it sits ──────────────────────
   Measured at 1440: half the plain paragraphs on the site ran past 80
   characters a line and the longest reached 115. A paragraph inside a narrow
   column is unaffected — max-width only caps — so this reaches the ones
   sitting in a full-width band, which are exactly the ones that were long. */
/* Every paragraph, not just the unclassed ones. A <p> is running text by
   definition; the classed ones were exactly the ones carrying bespoke
   widths — 600px here, 760 there, 820 somewhere else. One inside a narrow
   card is unaffected, because max-width only caps. */
html main p,
html main .secintro,html main .smlede,html main .srcnote,html main .mathnote{
  max-width:var(--measure);
}

/* ── a list item is running text too ───────────────────────────────────────
   Measured at 1440: list items in prose carried no measure at all and ran to
   110 characters a line, longer than any paragraph on the site. Lists inside
   a product mock, a nav panel or a chip wall are excluded — those are labels
   in a component, not sentences, and they size to their own container. */
html main li{
  max-width:var(--measure);
}
html main .np-col li,html main .smanch li,html main .langrow li,
html main .intwall li,html main .chiprow li,html main .exfilter li,
html main .appwin li,html main .custcard li,html main .pcard li,
html main .crow li,html main .fields li,html main .kwrow li{
  max-width:none;
}

/* A figcaption with no class is still a caption. */
html main figcaption{ max-width:var(--measure); }

/* ── a row that cannot wrap pushes its last child out of the box ───────────
   Measured at 375 across 44 pages: 91 pieces of text sat outside the box
   that draws around them, by as much as 116px. Every one was the same
   shape — a flex row holding a label and a tag with no flex-wrap and no
   min-width:0 on the children, so on a phone the tag had nowhere to go and
   simply left. They stack instead, and a chip's own words break rather than
   run past its edge. */
@media (max-width:700px){
  html .exhead,html .convrow,html .docrow,html .mathrow,
  html .step,html .weekday,html .exout{
    flex-wrap:wrap;
  }
  html .exhead > *,html .convrow > *,html .docrow > *,html .mathrow > *,
  html .step > *,html .weekday > *,html .exout > *{
    min-width:0;
  }
  /* The chip and what is inside it. min-width:0 was tried here and made it
     worse — it let the cells shrink under their own text and the spill
     went from 47 places to 144 — so this breaks words and nothing else. */
  html .bk,html .bk *,html .weekday,html .weekday *,
  html .col > span,html .exhead .tag,
  html .convrow span,html .mathrow .val,html .docrow span{
    overflow-wrap:break-word;
  }
  /* a tag pushed to its own line should not also be pushed to the right */
  html .exhead .tag{margin-left:0;}
}

/* A flex row holding a list must let the list shrink, or the list keeps its
   content width and the row's box is the thing that gives. Measured at 375:
   a 169px <ul> inside a 158px .weekday, text 36px outside the box. */
@media (max-width:700px){
  html .weekday > *{min-width:0;}
}


/* ── a figure needs air above it ──────────────────────────────────────────
   .scenefig carried margin:0, so whatever ended immediately above a canvas
   figure sat flush against its top edge. Measured at 1800 on the home page:
   the last row of the trade grid ended at 7057.5 and the drawing began at
   7057.5 — the pills and the boxes drawn inside the canvas read as one
   collided mass. A figure is a separate object; it gets a gap. */
html .scenefig{margin-top:34px;}
html .scenefig:first-child{margin-top:0;}

/* ── a list row that cannot wrap widens the card around it ────────────────
   .weekday li was a flex row, so a <b> inside the sentence became a flex
   item of its own and could not wrap with the words around it. Measured at
   375 on golf: the li's min-content was 169px inside a 158px card, and
   because a column flex line takes the width of its widest child, every
   child — even the three-letter "Sat" — was pushed 24px past the card's
   right edge. The row is a block with a hanging marker instead, so the
   sentence wraps and the emphasis wraps with it. */
html .weekday li{display:block;padding-left:15px;text-indent:-15px;}
html .weekday li > i{margin-right:6px;}

/* Same shape, one level up: .exrow holds a tick, a sentence and an amount
   in a flex row with no wrap. At 375 on public-sector the three came to
   301px inside 287px. The amount drops to its own line rather than out of
   the box; above a phone it keeps its right-hand column. */
@media (max-width:700px){
  html .exrow{flex-wrap:wrap;}
  html .exrow > span{min-width:0;}
  html .exrow .amt{margin-left:23px;}
  /* two pill buttons side by side under a 225px card */
  html .kfact .acts,html .acts{flex-wrap:wrap;}
}

/* ── a four-column board on a 375px screen ────────────────────────────────
   The queue/ramp/column boards all run 74px + three equal columns. At 375
   that leaves 67px of content per cell, and "INSTAGRAM" at .08em tracking
   needs 87. The heading cells give up their tracking and half their side
   padding before the word gives up the cell. Written here rather than in
   each page's <style> block because four pages share the component under
   four different names, and a page's own style beats a linked sheet. */
@media (max-width:700px){
  html [class] .ch > span{padding-left:6px;padding-right:6px;letter-spacing:.02em;}
}


/* ── who stands behind a security claim ───────────────────────────────────
   A trust page that states controls without an owner, a version or a review
   date is asking to be believed rather than checked. This block carries the
   four facts a procurement reviewer looks for first, including the one most
   sites omit: that no third-party audit report exists yet. */
.ownerbox{margin-top:26px;border:1px solid var(--l-hair);border-radius:14px;
  padding:24px 26px;background:#fff;}
.sec-dark .ownerbox,.sec-dark2 .ownerbox{border-color:var(--hair);background:rgba(20,26,31,.039);}
.ownerbox > b{display:block;font-size:var(--fs-sm);letter-spacing:-.015em;color:var(--l-ink);}
.sec-dark .ownerbox > b{color:#141A1F;}
.ownerbox ul{list-style:none;margin:16px 0 0;padding:0;display:grid;gap:12px;}
.ownerbox li{display:grid;grid-template-columns:172px minmax(0,1fr);gap:18px;
  padding-top:12px;border-top:1px solid var(--l-hair);}
.sec-dark .ownerbox li{border-color:var(--hair);}
.ownerbox li:first-child{border-top:0;padding-top:0;}
.ownerbox .k{font-size:var(--fs-xs);font-weight:800;letter-spacing:.02em;color:var(--l-mut2);}
.sec-dark .ownerbox .k{color:var(--tx3);}
.ownerbox .v{font-size:var(--fs-xs);line-height:1.7;color:var(--l-mut);font-weight:500;max-width:var(--measure);}
.sec-dark .ownerbox .v{color:var(--tx2);}
.ownerbox a{color:var(--teal-ink);font-weight:700;}
.sec-dark .ownerbox a{color:var(--teal);}
@media (max-width:640px){ .ownerbox li{grid-template-columns:1fr;gap:4px;} }


/* ── one section, several answers ─────────────────────────────────────────
   The tab strip replaces four uppercase kickers with one row of plain words.
   It is styled as a set of choices rather than as a control panel: no pills
   inside pills, no LIVE badge, no step number. The selected one is marked by
   weight and a rule under it, which is the oldest and quietest way to say
   "you are here".

   Without script every panel is shown, so the strip hides itself rather than
   sitting above a stack it cannot drive. */
.panelset{margin-top:34px;}
.pstabs{display:none;}
.srjs .pstabs{display:flex;gap:4px;flex-wrap:wrap;border-bottom:1px solid var(--hair);
  margin-bottom:34px;padding-bottom:0;}
.srjs .sec-light .pstabs,.srjs .sec-light2 .pstabs,.srjs .bg-paper .pstabs{border-color:var(--l-hair);}
.srjs .pstabs button{appearance:none;background:none;border:0;cursor:pointer;
  padding:12px 18px 14px;margin-bottom:-1px;font:inherit;
  font-size:var(--fs-sm);font-weight:600;color:var(--tx2);
  border-bottom:2px solid transparent;transition:color .3s var(--ease),border-color .3s var(--ease);}
.srjs .pstabs button:hover{color:var(--tx);}
.srjs .pstabs button.on{color:var(--tx);font-weight:700;border-bottom-color:var(--teal);}
.srjs .sec-light .pstabs button,.srjs .sec-light2 .pstabs button,.srjs .bg-paper .pstabs button{color:var(--l-mut);}
.srjs .sec-light .pstabs button.on,.srjs .sec-light2 .pstabs button.on,.srjs .bg-paper .pstabs button.on{
  color:var(--l-ink);border-bottom-color:var(--teal-deep);}
.srjs .pstabs button:focus-visible{outline:2px solid var(--teal);outline-offset:3px;border-radius:6px;}
/* a panel already carries its own heading, so it needs no top margin of its own */
.pspanel + .pspanel{margin-top:96px;}
.srjs .pspanel + .pspanel{margin-top:0;}
@media (max-width:620px){
  .srjs .pstabs{gap:0;overflow-x:auto;flex-wrap:nowrap;scrollbar-width:none;}
  .srjs .pstabs::-webkit-scrollbar{display:none;}
  .srjs .pstabs button{white-space:nowrap;padding:12px 14px 14px;}
}


/* ── the plans, on the page where the number was worked out ───────────────
   The home page ran a whole section for three prices. It is three prices; it
   is a strip under the calculator, where the reader has just produced a
   number and the only useful next fact is what the plan costs. No cards
   inside cards, no POPULAR badge - the middle plan earns attention by being
   the one most people can afford, which the pricing page argues properly. */
.planstrip{margin-top:44px;padding-top:34px;border-top:1px solid var(--hair);}
.planstrip .ps-head b{display:block;font-size:var(--fs-lead);font-weight:700;
  letter-spacing:-.02em;color:var(--tx);}
.planstrip .ps-head span{display:block;margin-top:8px;font-size:var(--fs-xs);
  line-height:1.7;color:var(--tx2);font-weight:500;max-width:var(--measure);}
.planstrip .ps-list{list-style:none;margin:26px 0 0;padding:0;display:grid;
  grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:0;}
.planstrip .ps-list li{padding:20px 26px 20px 0;border-left:1px solid var(--hair);
  padding-left:26px;}
.planstrip .ps-list li:first-child{border-left:0;padding-left:0;}
.planstrip .ps-list b{display:block;font-size:var(--fs-xs);font-weight:800;
  letter-spacing:.02em;color:var(--tx2);}
.planstrip .ps-p{display:block;margin-top:6px;font-family:'Bricolage Grotesque',sans-serif;
  font-size:var(--fs-h2s);font-weight:600;letter-spacing:-.03em;color:#141A1F;}
.planstrip .ps-p i{font-style:normal;font-size:var(--fs-xs);font-weight:600;color:var(--tx3);}
.planstrip .ps-d{display:block;margin-top:8px;font-size:var(--fs-xs);line-height:1.65;
  color:var(--tx2);font-weight:500;}
.planstrip .ps-policy{margin-top:18px;font-size:var(--fs-sm);color:var(--tx2);line-height:1.7;max-width:720px;}
.planstrip .ps-policy b{color:#141A1F;font-weight:600;}
.planstrip .ps-foot{margin-top:20px;display:flex;gap:28px;flex-wrap:wrap;}
.planstrip .ps-foot .linkcta{color:var(--teal);}
@media (max-width:700px){
  .planstrip .ps-list li{border-left:0;border-top:1px solid var(--hair);padding:18px 0;}
  .planstrip .ps-list li:first-child{border-top:0;padding-top:0;}
}

/* the line the conclusion band used to carry, now the closer's first breath */
.concline{margin:0 auto 26px;max-width:var(--measure);text-align:center;
  font-size:var(--fs-xs);line-height:1.75;color:var(--tx2);font-weight:500;}


/* ══ THE HOUSE STYLE, CORRECTED ═══════════════════════════════════════════
   Five devices had become the design instead of serving it. Counted across
   the 44 pages: 522 uppercase pill kickers, 159 status pills, 42 star fields,
   75 teal glows, 18 LIVE badges. Any one of them is a good idea. All of them
   on every section is a template.

   None of them is deleted; each is turned down to the level where it means
   something again. ─────────────────────────────────────────────────────── */

/* 1 · THE KICKER. It was a bordered pill in uppercase mono at .22em of
   tracking, which is a lot of decoration to say "this section is about X" -
   and it said it 522 times. It is now what it always was in print: a small
   line of type above the headline, in the case it was written in, with a
   short rule instead of a border. The dot stays; it is the one accent mark
   that carries the brand. */
html .eyebrow{
  display:inline-flex;align-items:center;gap:10px;
  border:0;border-radius:0;padding:0 0 0 0;background:none;
  font-size:var(--fs-xs);font-weight:600;letter-spacing:0;text-transform:none;
  color:var(--tx2);
}
html .eyebrow::before{
  content:"";width:22px;height:1px;flex:none;background:var(--accent,var(--teal));opacity:.85;
}
html .eyebrow i{width:0;height:0;margin:0;background:none;}
html .eyebrow.light{background:none;border:0;color:var(--l-mut2);}
html .sec-light .eyebrow::before,html .sec-light2 .eyebrow::before,
html .bg-paper .eyebrow::before{background:var(--teal-deep);}

/* 2 · THE STATUS PILL. A capsule is the shape of a control you can press, and
   using it for a label that does nothing taught the reader to stop pressing
   things. The first attempt took the capsule's BACKGROUND away as well - and
   every one of these inks was measured against that background, not against
   the page. Measured after it: .pt-dark fell to 1.02:1, white on a white card,
   invisible; .pt-teal and .pt-amber to 3.4:1; and a white card inside a dark
   section made a surface-keyed override wrong in a third way.

   So the tint stays, because the tint is what makes the ink legal, and only
   the capsule goes: a tag with a small radius reads as a label, a pill reads
   as a button. Anything genuinely pressable keeps .is-action and its pill. */
html .pilltag:not(.is-action){
  border-radius:5px;
  font-weight:700;
  letter-spacing:.01em;
}

/* 3 · THE ATMOSPHERE. A star field and a teal glow are an event; two of them
   on one page is weather. One atmospheric section per page keeps its glow -
   the rest sit on the flat ground the type was designed for. */
html section.bg-spot ~ section.bg-spot::before,
html section.bg-spot ~ section.bg-spot::after{opacity:.32;}
html section .stars ~ .stars{display:none;}
html section.bg-grid ~ section.bg-grid ~ section.bg-grid::before{opacity:.4;}

/* 4 · THE PHOTOGRAPHS. 1,356 of them come from a stock library, which is fine
   - the alternative is a shoot this company has not done. A single grade over
   all of them already exists in scenes.css (grayscale + sepia + the brand
   scrim), and adding a second one on top of it only muddied the heroes; that
   attempt is recorded here so it is not tried again. What actually reads as
   stock is the QUANTITY of scenery, so the fix is in 3 above and in the cuts
   to the home page: fewer photographs, each one showing a real business
   situation, and the brand carried by the drawn figures - which nobody else
   has - rather than by the photographs, which anybody can buy. */

/* 5 · THE NESTED CARD. .shell holds .core, .tray holds .paper: a rounded box
   with a border inside a rounded box with a border, twice on some pages. The
   outer one is a frame - a machined tray the screen sits in - so it keeps its
   radius and drops its stroke, and the inner object keeps the stroke that
   makes it an object. One line each, not two. */
html .shell{border-color:transparent;}
html .tray{border-color:transparent;}

/* the control that opens the rest of the trades is a control, so it keeps the
   pill the status labels gave up - and it says how many, not "more" */
html .chip.chipmore{border-style:dashed;color:var(--tx3);font-weight:700;}
html .chip.chipmore:hover{color:var(--tx);border-color:var(--teal);}
html .sec-light .chip.chipmore,html .sec-light2 .chip.chipmore{color:var(--l-mut2);}

/* the trade card's LIVE / ONBOARDING / ROADMAP mark is a status, not a button */
/* .rank is already absolutely placed on the card, so it keeps its position -
   setting position:relative here moved every one of them into the flow */
html .icard .rank{background:none;border:0;padding:0 0 0 14px;border-radius:0;
  letter-spacing:.04em;text-transform:none;}
html .icard .rank::before{content:"";position:absolute;left:0;top:50%;
  transform:translateY(-50%);width:6px;height:6px;border-radius:50%;
  background:currentColor;}

/* ── the footer's first column ────────────────────────────────────────────
   Measured on every page: the brand blurb rendered 22 characters a line over
   six lines - a column of confetti under the logo. The track was 1.35fr of a
   five-column grid, about 200px, and the paragraph was capped at 240px on top
   of that. It gets a floor now, and the paragraph a measure rather than a
   pixel width. */
html .bigfooter .cols{grid-template-columns:minmax(280px,1.6fr) 1fr 2.05fr 1fr 1fr;}
html .bigfooter .brand p{max-width:min(100%,26em);}
@media (max-width:1100px){
  html .bigfooter .cols{grid-template-columns:minmax(240px,1.4fr) 1fr 1fr;}
}
/* A 240px floor plus two more tracks plus the gaps is 380px, which is wider
   than the phone it was measured on - five pages scrolled sideways by 5px
   before this. Below 900 the floor goes away with the three-column layout. */
@media (max-width:900px){
  html .bigfooter .cols{grid-template-columns:1fr 1fr;}
}
@media (max-width:560px){
  html .bigfooter .cols{grid-template-columns:1fr;}
}


/* ══ THE 13px FLOOR, RAISED ═══════════════════════════════════════════════
   A buyer's review counted 180 text elements below 14px and said the page is
   tiring to read for long. Measured on the live home page: 146 of 746 blocks
   with their own words still rendered under 14px. Every one traced to the two
   decisions below, both of which were mine and both of which I defended once
   before as "a mock is a picture of an interface".

   That defence is thin. The mock is not a picture - the reader is meant to
   read the pipeline card, the calendar slot, the quote line, because those
   ARE the product. Making them a size no one reads comfortably in order to
   make them look like a screenshot is decoration winning over use.

   So the floor is 14px for anything with words in it, and 13px survives in
   exactly one place: a label inside a drawn figure, where the type is a key
   to a diagram rather than something to be read in sequence. */
html .appwin,html .calmock,html .pipeboard,html .quotedoc,html .custcard,
html .kpitiles,html .repcard,html .ledger,html .transcript,html .funnelrow,
html .browserframe,html .msgthread,html .callcard,html .demo-body,
html .bigfooter .brand{
  --fs-xs:14px;
  --fs-label:14px;
}
:root{
  --fs-label:14px;       /* was 13px - an uppercase label is still read */
}
/* SVG keys stay at the figure floor: they label a drawing, not a sentence */
svg [font-size="11"],svg [font-size="12"],svg [font-size="12.5"],
svg [font-size="9.5"],svg [font-size="10"]{font-size:13px;}

/* Long passages on a dark ground get a little more light. #94A2B8 clears
   4.5:1 comfortably, but body copy read for minutes rather than seconds is
   easier a step brighter, and every one of these was measured against the
   eleven dark panels the site actually uses. */
html .sec-dark .lead,html .sec-dark2 .lead,html .bg-grid .lead,
html .bg-spot .lead,html .bg-dusk .lead,html .lead.onDark,
html .sec-dark main p,html .bg-grid main p{color:#3B454D;}


/* ── three kinds of promise, told apart ───────────────────────────────────
   A trust page that lists a database setting, a signed clause and a per-order
   answer in one voice makes the reader check all of it or none of it. Three
   columns, three different things standing behind them, and a fourth block
   for the one most sites leave out: what has no third-party attestation at
   all. Colour is the weakest signal here and carries none of the meaning -
   the tag says which kind it is in words. */
.statusledger{margin-top:44px;border-top:1px solid var(--l-hair);padding-top:38px;}
.sec-dark .statusledger,.sec-dark2 .statusledger{border-color:var(--hair);}
.statusledger .sl-head b{display:block;font-family:'Bricolage Grotesque',sans-serif;
  font-size:var(--fs-h2s);font-weight:600;letter-spacing:-.03em;line-height:1.15;
  color:var(--l-ink);max-width:22ch;}
.sec-dark .statusledger .sl-head b{color:#141A1F;}
.statusledger .sl-head span{display:block;margin-top:14px;font-size:var(--fs-sm);
  line-height:1.75;color:var(--l-mut);font-weight:500;max-width:var(--measure);}
.sec-dark .statusledger .sl-head span{color:var(--tx2);}
.sl-cols{margin-top:34px;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:0;}
.sl-col{padding:0 28px;border-left:1px solid var(--l-hair);}
.sec-dark .sl-col{border-color:var(--hair);}
.sl-col:first-child{padding-left:0;border-left:0;}
.sl-col:last-child{padding-right:0;}
.sl-tag{display:inline-block;font-size:var(--fs-xs);font-weight:800;letter-spacing:.01em;
  padding-left:16px;position:relative;color:var(--l-ink);}
.sec-dark .sl-tag{color:#141A1F;}
.sl-tag::before{content:"";position:absolute;left:0;top:50%;transform:translateY(-50%);
  width:8px;height:8px;border-radius:50%;background:currentColor;}
.sl-live .sl-tag{color:#0B7878;}
.sl-doc .sl-tag{color:#8D642F;}
.sl-order .sl-tag{color:#141A1F;}
.sec-dark .sl-live .sl-tag{color:var(--teal);}
.sec-dark .sl-doc .sl-tag{color:#B7791F;}
.sec-dark .sl-order .sl-tag{color:#9FB0C8;}
.sl-note{margin-top:10px;font-size:var(--fs-xs);line-height:1.7;color:var(--l-mut2);font-weight:500;}
.sec-dark .sl-note{color:var(--tx3);}
.sl-col ul{list-style:none;margin:18px 0 0;padding:0;display:grid;gap:14px;}
.sl-col li{font-size:var(--fs-xs);line-height:1.7;color:var(--l-mut);font-weight:500;
  padding-top:14px;border-top:1px solid var(--l-hair);}
.sec-dark .sl-col li{color:var(--tx2);border-color:var(--hair);}
.sl-col li b{display:block;color:var(--l-ink);font-weight:700;margin-bottom:3px;}
.sec-dark .sl-col li b{color:var(--tx);}
.sl-foot{margin-top:34px;padding-top:22px;border-top:1px solid var(--l-hair);
  font-size:var(--fs-xs);line-height:1.8;color:var(--l-mut);font-weight:500;
  max-width:var(--measure);}
.sec-dark .sl-foot{color:var(--tx2);border-color:var(--hair);}
.sl-foot b{color:var(--l-ink);}
.sec-dark .sl-foot b{color:var(--tx);}
@media (max-width:900px){
  .sl-cols{grid-template-columns:1fr;gap:30px;}
  .sl-col{padding:0;border-left:0;border-top:1px solid var(--l-hair);padding-top:26px;}
  .sl-col:first-child{border-top:0;padding-top:0;}
  .sec-dark .sl-col{border-color:var(--hair);}
}

/* the worked examples keep the card, lose the wall: one panel, full width */
.srjs .exset > .pspanel > .excard{max-width:none;}
.srjs .exset .pstabs{margin-bottom:26px;}

/* The ledger's list items inherit the prose measure, which is wider than the
   column they sit in - measured at 1440, they ran 160px into the next column.
   A list inside a three-column ledger sizes to its column, like every other
   list in a component. */
html .sl-col ul,html .sl-col li{max-width:none;min-width:0;}
html .sl-tag{white-space:normal;line-height:1.45;}
/* the type floor took a mock column 2px past its edge; the words break */
html .calmock .col,html .colboard .col,html .queueboard .col,
html .rampboard .col,html .col > span{overflow-wrap:break-word;min-width:0;}

/* The 14px floor made two boxes 2px and 39px too small for their own words.
   Both hold labels rather than sentences, so the words break rather than the
   box giving - the same rule the mock chips already take at phone width, now
   applied where the type grew. */
html .sl-col li,html .sl-col li b,html .sl-col .sl-tag{overflow-wrap:break-word;}
html .inboxmock .col,html .inboxmock .col *{min-width:0;overflow-wrap:break-word;}

/* Raising the label floor to 14px put "INSTAGRAM" 6px outside its cell on a
   375px screen: a four-column board simply does not fit a phone at a size
   anyone can read. Breaking the word mid-way would be worse than either. The
   board keeps its columns and scrolls sideways inside its own frame, which is
   what the site already does with wide tables. */
@media (max-width:700px){
  html .queueboard,html .colboard,html .rampboard{overflow-x:auto;
    scrollbar-width:thin;-webkit-overflow-scrolling:touch;}
  html .queueboard .ch,html .queueboard .cb,
  html .colboard .ch,html .colboard .cb,
  html .rampboard .ch,html .rampboard .cb{min-width:430px;}
}


/* ══ FOUR NOTES THE REVIEW MADE, ANSWERED ═════════════════════════════════

   1 · THE CITY AT NIGHT. Nine of forty page heroes were a night photograph.
   Five of them earn it - a garage with its shutters down, a house lit above
   the door, a vet alone with an x-ray - because 2:47 AM is the argument this
   company makes. Four did not: a skyline over the privacy policy, the same
   skyline over the terms, another over the security page, a fourth over the
   demo. Two of them were literally the same photograph. A legal document with
   a stock skyline on it is not atmosphere, it is filler, and on a trust page
   filler costs more than it buys.

   Those four heroes drop the photograph and take the ground the brand already
   owns: the grid, and one soft pool of light under the words. Nothing else on
   the page changes. */
header.nophoto{background:#FFFFFF;}
header.nophoto::before{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background-image:linear-gradient(rgba(20,26,31,.036) 1px,transparent 1px),
                   linear-gradient(90deg,rgba(20,26,31,.036) 1px,transparent 1px);
  background-size:64px 64px;
  mask-image:radial-gradient(120% 90% at 50% 0%,#000 0%,transparent 78%);
}
header.nophoto::after{
  content:"";position:absolute;left:50%;top:-8%;width:min(1100px,120%);height:520px;
  transform:translateX(-50%);z-index:0;pointer-events:none;
  background:radial-gradient(50% 60% at 50% 40%,rgba(11,120,120,.16),rgba(11,120,120,0) 72%);
}
header.nophoto .scrim{background:linear-gradient(180deg,rgba(20,26,31,.2) 0%,rgba(20,26,31,.55) 62%,#F6F4EE 100%);}
header.nophoto .hero-inner,header.nophoto .navwrap{position:relative;z-index:2;}

/* 2 · ROUNDED CARDS INSIDE ROUNDED CARDS. Measured on the home page: 63
   elements sat inside two rounded ancestors and 24 inside three - a window,
   holding a column, holding a card, holding a round avatar. The frame and the
   object each earn a radius; the container between them does not, so the
   middle layer goes square and the count of visible corners halves. */
html .appwin .pipecol,html .browserframe .inboxmock,
html .inboxmock .convrow,html .appwin .board,html .appwin .body > .col,
html .shell .core > .demo-body{border-radius:0;}
/* a circle is an object, not a container - it keeps its shape */
html .ini,html .avatar,html .dot,html .wdot{border-radius:50%;}

/* 3 · THE LIVE BADGE. Twelve of them on the home page alone, on cards where
   being live is the expectation. A state worth marking is the one that breaks
   the expectation, so LIVE stops being printed and ONBOARDING and ROADMAP -
   the two that change what a buyer can have today - are what is left. */
html .icard .rank{font-size:var(--fs-label);}
html .icard .rank[data-state="live"],
html .icard .rank.is-live{display:none;}


/* ── seven rooms, not twenty-five tiles ───────────────────────────────────
   The wall was 27 photocards in one flat grid: 26 stock photographs, 26
   kickers all reading "Founding cohort", 26 identical shapes. Whatever each
   tile said, the composition said "we do a lot of things" - which is the
   opposite of what a buyer looking for the dental pack needs to feel.

   The same twenty-five trades, in the seven groups the navigation has always
   used. One photograph a group instead of four. And the refusal each pack is
   built around - the thing nobody else prints - comes out of the small print
   and sits under the trade it belongs to. */
.roomgrid{display:grid;gap:0;margin-top:44px;}
.room{display:grid;grid-template-columns:minmax(0,300px) minmax(0,1fr);
  gap:44px;align-items:start;padding:44px 0;border-top:1px solid var(--l-hair);}
.room:first-child{border-top:0;padding-top:0;}
.sec-dark .room,.sec-dark2 .room{border-color:var(--hair);}
.room-pic{margin:0;border-radius:14px;overflow:hidden;position:relative;
  aspect-ratio:4/3;background:#FFFFFF;}
.room-pic img{width:100%;height:100%;object-fit:cover;display:block;}
.room-h{font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-h2s);
  font-weight:600;letter-spacing:-.03em;line-height:1.1;color:var(--l-ink);}
.sec-dark .room-h{color:#141A1F;}
.room-lead{margin-top:10px;font-size:var(--fs-sm);line-height:1.7;
  color:var(--l-mut);font-weight:500;max-width:var(--measure);}
.sec-dark .room-lead{color:var(--tx2);}
.room-list{list-style:none;margin:26px 0 0;padding:0;
  display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:0 44px;}
.room-list > li{padding:20px 0;border-top:1px solid var(--l-hair);}
.sec-dark .room-list > li{border-color:var(--hair);}
.room-t{display:flex;align-items:baseline;gap:10px;text-decoration:none;
  color:var(--l-ink);font-size:var(--fs-body);font-weight:700;letter-spacing:-.015em;}
.sec-dark .room-t{color:#141A1F;}
.room-t b{font-weight:700;}
.room-go{color:var(--teal-deep);font-weight:700;transition:transform .4s var(--ease);}
.sec-dark .room-go{color:var(--teal);}
.room-t:hover .room-go{transform:translateX(4px);}
.room-t:hover b{text-decoration:underline;text-underline-offset:3px;}
.room-d{display:block;margin-top:7px;font-size:var(--fs-xs);line-height:1.7;
  color:var(--l-mut);font-weight:500;max-width:var(--measure);}
.sec-dark .room-d{color:var(--tx2);}
/* the refusal: the second thing you read, not a footnote */
.room-no{display:block;margin-top:10px;font-size:var(--fs-xs);font-weight:600;
  color:var(--l-mut2);padding-left:16px;position:relative;}
.sec-dark .room-no{color:var(--tx3);}
.room-no::before{content:"";position:absolute;left:0;top:.55em;width:8px;height:1px;
  background:#A8453A;}
.sec-dark .room-no::before{background:#C0392B;}
.room-no b{font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-body);
  font-weight:600;color:#A8453A;margin-right:7px;letter-spacing:-.02em;}
.sec-dark .room-no b{color:#C0392B;}
@media (max-width:900px){
  .room{grid-template-columns:1fr;gap:22px;}
  .room-pic{aspect-ratio:16/9;}
  .room-list{grid-template-columns:1fr;}
}

/* the two that are not trades: no photograph, because neither one is a room */
.room-nottrade{grid-template-columns:minmax(0,300px) minmax(0,1fr);}
.room-nottrade .room-body-wide{grid-column:2;}
@media (max-width:900px){ .room-nottrade .room-body-wide{grid-column:1;} }


/* ── the column is the page now, and the breaks are in the sentence ───────
   The reading measure was doing the damage the review kept pointing at: a
   36-em column wraps wherever the last word happens to fall, so "They are
   not" ends one line and "a Saleringo" ends another, and the eye carries half
   a clause down and reassembles it six times a paragraph.

   wrap.js puts the breaks where the sentence already breaks - after a comma,
   a dash, a full stop, or before the conjunction that starts the next clause
   - filling each line as far as it goes and ending it at the last sense
   boundary that still fits. With that doing the work, the cap is no longer
   needed and prose takes the width of the page.

   The cap stays for anyone without script: the .srwrap class is set by
   wrap.js itself, so a reader with JavaScript off keeps the 36-em measure
   rather than a 128-character line. */
html.srwrap main p,
html.srwrap main .lead,html.srwrap main .sub,html.srwrap main .lsub,
html.srwrap main .secintro,html.srwrap main .standfirst,
html.srwrap main figcaption,html.srwrap main blockquote,
html.srwrap main li,
html.srwrap main .scenecap,html.srwrap main .photocap,html.srwrap main .mockcap,
html.srwrap main .exlabel,html.srwrap main .pkcap,html.srwrap main .statnote,
html.srwrap main .seccap,html.srwrap main .funfoot,html.srwrap main .labfoot,
html.srwrap main .altnote,html.srwrap main .proofnote,html.srwrap main .metnote,
html.srwrap main .note,html.srwrap main .fn,html.srwrap main .srcnote,
html.srwrap main .mathnote,html.srwrap main .smlede,html.srwrap main .disclaim,
html.srwrap main .room-lead,html.srwrap main .room-d,html.srwrap main .sl-note,
html.srwrap main .sl-foot,html.srwrap main .secfoot,html.srwrap .faq p{
  max-width:none;
}
/* a heading was already balanced; with the width off the leash it needs to be
   told again, and told not to hang one word on its own last line */
html.srwrap main h1,html.srwrap main h2,html.srwrap main .h2,
html.srwrap main h3{max-width:none;text-wrap:balance;}
/* the breaks the sentence asked for */
br.cw{content:"";}

/* the kicker's rule, mirrored where the block is centred, so the words sit on
   the same axis as the heading under them (see wrap.js: axis) */
html .eyebrow.is-mid::after{
  content:"";width:22px;height:1px;flex:none;background:var(--accent,var(--teal));opacity:.85;
}
html .sec-light .eyebrow.is-mid::after,html .sec-light2 .eyebrow.is-mid::after,
html .bg-paper .eyebrow.is-mid::after{background:var(--teal-deep);}


/* ── one block, one alignment ─────────────────────────────────────────────
   Measured across the pages: blocks that stack their children but do not
   agree on where the text starts. A centred heading with a left-aligned note
   under it, a centred lead form whose fine print runs left, a centred hero
   with a left-aligned scroll cue. Each one is small; together they are what
   reads as a page nobody tidied.

   The rule is the obvious one - a note takes the alignment of the thing it is
   a note to - and it is written here rather than in each page so the next
   note added anywhere inherits it. */
html .leadbox .eanote,
html .leadbox .eafallback-lead,
html .leadbox .easent{text-align:center;}
html .leadbox .easent .earef{margin-left:auto;margin-right:auto;}
html .altwrap .altnote,html .altwrap .cap + .altnote,
html .altwrap .fn,html .altsec .altnote{text-align:center;margin-left:auto;margin-right:auto;}
html .peopleband .capL{text-align:center;margin-left:auto;margin-right:auto;}
html .hcap .heroscroll,html .hero .heroscroll{text-align:center;}
html .stagehint{text-align:left;}
/* a centred note still needs its measure centred, not just its words */
html .leadbox .eanote,html .altwrap .altnote,html .peopleband .capL{
  margin-left:auto;margin-right:auto;}


/* ── the page's own map, down the left edge ───────────────────────────────
   One mark per section, drawn on a canvas: the one you are reading is lit,
   the ones behind you are filled, the ones ahead are hairlines, and a line
   grows through them as you scroll. It appears only where there is room
   beside the content and only on a page long enough to get lost in.

   The canvas is decoration - the same destinations are already in the page as
   headings - so it is aria-hidden, and the keyboard path is a real list of
   links underneath it, visible only when one is focused. */
/* No opacity transition to get in: a fade needs frames, and a throttled tab
   can leave the computed value stuck at 0 with the class already applied -
   which is a rail that exists, is painted, and cannot be seen. It is shown or
   it is not. */
.pagerail{position:fixed;left:22px;top:50%;transform:translateY(-50%);
  height:min(62vh,520px);width:26px;z-index:35;pointer-events:auto;}
.pagerail:not(.on){display:none;}
.pagerail-cv{display:block;}
.pagerail-tip{position:absolute;left:34px;transform:translateY(-50%);
  white-space:nowrap;font-size:var(--fs-xs);font-weight:600;letter-spacing:-.01em;
  color:var(--tx);background:rgba(20,26,31,.92);border:1px solid var(--hair);
  border-radius:8px;padding:6px 11px;opacity:0;pointer-events:none;
  transition:opacity .25s var(--ease);backdrop-filter:blur(8px);}
.pagerail-tip.on{opacity:1;}
.sec-light .pagerail-tip,.bg-paper .pagerail-tip{}
.pagerail-keys{list-style:none;margin:0;padding:0;position:absolute;inset:0;}
.pagerail-keys a{position:absolute;left:0;width:1px;height:1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;}
.pagerail-keys a:focus-visible{position:fixed;left:22px;top:50%;width:auto;height:auto;
  clip-path:none;transform:translateY(-50%);background:rgba(20,26,31,.96);
  border:1px solid var(--teal);border-radius:8px;padding:8px 14px;color:#141A1F;
  font-size:var(--fs-xs);font-weight:700;z-index:60;}
@media (max-width:1179px){ .pagerail{display:none;} }
@media print{ .pagerail{display:none;} }

/* When a row collapses to a stack on a phone, the alignment has to collapse
   with it: a count that was right-aligned beside a heading is right-aligned
   UNDER it otherwise, and a badge that was centred in a bar sits 64px in from
   the words below it. Measured at 375 on the home page and the trade pages. */
@media (max-width:700px){
  html .top .count,html .top > .count{text-align:left;}
  /* justify-content:center is what centres the pill above words that
     start at the left edge once the bar wraps to three lines */
  html .cohortbar{align-items:flex-start;text-align:left;justify-content:flex-start;}
  html .cohortbar > *{margin-left:0;margin-right:0;}
  html .pricecols > *{margin-left:0;}
}


/* ── a reveal must never be able to strand its own content ────────────────
   The scroll-driven reveal is an animation whose first frame is opacity 0,
   held by animation-fill-mode:both until the element reaches its range. The
   range was written in the "entry" phase - from the moment the element starts
   entering the viewport to the moment it has fully entered - and an element
   TALLER than the viewport never fully enters. On a 1440px screen almost
   nothing is taller than the viewport. On a 375x812 phone a great many blocks
   are, and every one of them held its first frame: present in the document,
   holding its space, invisible. Measured on the home page at 375, the plan
   strip under the calculator was one of them.

   Two changes. The ranges are quoted in "cover", which any element that
   scrolls at all completes. And the watchdog below catches whatever a browser
   still leaves dark: if a block is on screen and cannot be read, it is shown,
   because a fade nobody sees is worth less than a sentence somebody does. */
.srjs .reveal.sr-force,
.srjs .reveal.sr-force .h2,
.srjs .reveal.sr-force h2{
  animation:none !important;
  opacity:1 !important;
  transform:none !important;
  clip-path:none !important;
}


/* ── the pack, on a page of its own ───────────────────────────────────────
   A trade page is an argument; the pack detail is a manifest. They were in
   one scroll, and the manifest is the part a buyer comes back to after they
   have decided to look properly - which is exactly the part that should have
   its own address. What stays behind is a card that says what is through the
   door, at the size a card should be. */
.packcard .pc-link{display:block;text-decoration:none;position:relative;
  border:1px solid var(--hair);border-radius:14px;padding:34px 38px 34px 34px;
  background:linear-gradient(150deg,rgba(11,120,120,.09),rgba(11,120,120,.02));
  transition:border-color .4s var(--ease),transform .5s var(--ease);}
.packcard .pc-link:hover{border-color:rgba(11,120,120,.44);transform:translateY(-3px);}
.packcard .pc-k{display:block;font-size:var(--fs-xs);font-weight:600;color:var(--teal);}
.packcard .pc-h{display:block;margin-top:12px;font-family:'Bricolage Grotesque',sans-serif;
  font-size:var(--fs-h2s);font-weight:600;letter-spacing:-.03em;line-height:1.14;color:#141A1F;
  max-width:20ch;}
.packcard .pc-d{display:block;margin-top:14px;font-size:var(--fs-xs);line-height:1.75;
  color:var(--tx2);font-weight:500;max-width:var(--measure);}
.packcard .pc-go{position:absolute;right:30px;top:34px;font-size:var(--fs-lead);
  color:var(--teal);transition:transform .4s var(--ease);}
.packcard .pc-link:hover .pc-go{transform:translateX(5px);}
@media (max-width:640px){
  .packcard .pc-link{padding:26px 22px;}
  .packcard .pc-go{position:static;display:block;margin-top:16px;}
}

/* and on the pack page, the way back to the argument */
.packback{border-top:1px solid var(--hair);}
.packback .pb-line{font-size:var(--fs-xs);line-height:1.8;color:var(--tx2);font-weight:500;
  max-width:var(--measure);}
.packback .pb-line b{color:var(--tx);}
.packback .pb-links{margin-top:20px;display:flex;gap:30px;flex-wrap:wrap;}
.packback .pb-links .linkcta{color:var(--teal);}

/* ── the other language ────────────────────────────────────────────────────
   One link, in the language it leads to, so a Korean reader landing on the
   English page recognises it without reading any English first. It is not a
   flag: a flag names a country, and this names a language - the Korean pages
   are for anyone who reads Korean, wherever they are. */
.langsw{display:inline-flex;align-items:center;gap:6px;font-size:14px;
  letter-spacing:.01em;color:var(--ink-2);text-decoration:none;
  padding:6px 11px;border-radius:6px;border:1px solid var(--hair);
  white-space:nowrap;transition:color .18s,border-color .18s,background .18s;}
.langsw:hover{color:var(--ink);border-color:var(--hair-2);background:var(--tint);}
.navwrap .langsw{margin-right:2px;}
.bigfooter .langsw{border-color:rgba(20,26,31,.208);color:rgba(20,26,31,.72);
  margin-right:10px;}
.bigfooter .langsw:hover{color:#141A1F;border-color:rgba(20,26,31,.34);
  background:rgba(20,26,31,.078);}
@media (max-width:980px){.navwrap .langsw{display:none;}}

/* ── the parts that were only ever written inside one page ─────────────────
   The lead form, the badges on a mock window's title bar, and the clipping a
   grain overlay needs were each defined once, inside the <style> block of the
   one English page that used them. That was fine while there was one page
   using each. It stopped being fine when a second language grew its own
   copies of the same components: the Korean lead form came out as raw
   unstyled HTML, and the "예시 · 가상의 상담" badges rendered as loose text
   beside the title.

   So they live here, once, and any page that wants to differ still can - a
   page's own <style> block parses after this sheet and wins. The English
   pages keep their inline copies and look exactly as they did. */

/* the lead form, wherever it appears */
.gsform{display:grid;grid-template-columns:1fr;gap:14px;}
.two{display:grid;grid-template-columns:1fr 1fr;gap:14px;}
@media (max-width:700px){.two{grid-template-columns:1fr;}}
.fld{display:grid;gap:7px;}
.fld label{font-size:var(--fs-2xs);font-weight:800;letter-spacing:.12em;
  text-transform:uppercase;color:var(--tx3);}
.fld label .opt{color:var(--tx3);opacity:.7;letter-spacing:.02em;text-transform:none;
  font-weight:600;font-size:var(--fs-2xs);}
/* 16px 인 이유: 사파리는 입력 글씨가 16px 보다 작으면 그 칸을 누를 때마다
   화면을 확대합니다. 한 칸 칠 때마다 화면이 튀면 휴대폰으로 주문서를 끝까지
   채우기 어렵습니다. 본문 글씨와 다르더라도 여기는 16px 이어야 합니다. */
.fld input,.fld select,.fld textarea{width:100%;background:rgba(20,26,31,.058);
  border:1px solid var(--hair2);border-radius:8px;padding:13px 14px;color:#141A1F;
  font-family:inherit;font-size:16px;font-weight:500;
  transition:border-color .2s var(--ease);}
/* 테두리만 바꾸고 포커스 링은 건드리지 않습니다. 앞선 판에서 여기에
   outline:none 을 넣었다가 사이트 전체의 키보드 포커스 표시를 지웠습니다 -
   전역 :focus-visible 규칙보다 뒤에 있고 특이도도 높아서 그것을 이깁니다.
   마우스를 안 쓰는 사람은 그 순간 자기가 어디에 있는지 알 수 없게 됩니다. */
.fld input:focus,.fld select:focus,.fld textarea:focus{border-color:var(--teal);}
.fld select option{background:#141A1F;color:#141A1F;}
.fld textarea{resize:vertical;min-height:88px;line-height:1.6;}
.slots{display:flex;flex-wrap:wrap;gap:8px;}
.slotchip{position:relative;}
.slotchip input{position:absolute;opacity:0;width:0;height:0;}
.slotchip span{display:inline-block;cursor:pointer;font-size:var(--fs-xs);font-weight:700;
  border:1px solid var(--hair2);border-radius:999px;padding:9px 15px;color:var(--tx2);
  transition:all .25s var(--ease);}
.slotchip input:checked + span{background:rgba(11,120,120,.18);border-color:var(--teal);color:#141A1F;}
.slotchip input:focus-visible + span{outline:2px solid var(--teal);outline-offset:3px;}
.tzline{margin-top:10px;font-size:var(--fs-xs);color:var(--tx3);font-weight:600;line-height:1.7;}
.tzline b{color:var(--tx2);}

/* the two badges on a mock window's title bar: what it is, and when it was */
.appwin .bar .illus{margin-left:14px;font-size:var(--fs-2xs);font-weight:700;
  letter-spacing:.09em;text-transform:uppercase;color:var(--tx3);
  padding:3px 8px;border:1px solid var(--hair);border-radius:999px;white-space:nowrap;}
.appwin .bar .closed{margin-left:auto;font-size:var(--fs-2xs);font-weight:800;
  letter-spacing:.1em;text-transform:uppercase;color:var(--amber);white-space:nowrap;}
@media (max-width:700px){
  .appwin .bar .illus{margin-left:0;}
  .appwin .bar .closed{margin-left:0;}
}

/* a grain overlay is absolutely positioned; its section has to clip it */
.founding{position:relative;overflow:hidden;}

/* a list where each line is a claim with its own explanation under it */
.kolist{margin-top:26px;display:grid;gap:16px;}
.kolist li{list-style:none;padding-left:26px;position:relative;
  font-size:var(--fs-body);line-height:1.8;color:var(--tx2);}
.kolist li::before{content:"";position:absolute;left:2px;top:.72em;width:9px;height:9px;
  border-radius:50%;border:1.5px solid var(--teal);}
.kolist li b{color:#141A1F;}
.sec-light .kolist li,.bg-paper .kolist li,.sec-light2 .kolist li{color:var(--l-tx2);}
.sec-light .kolist li b,.bg-paper .kolist li b,.sec-light2 .kolist li b{color:var(--l-ink);}

/* The grain overlay is a div whose ::after paints the noise. It has to be
   taken out of flow, or it sits in the layout as an empty block and the noise
   lands against whatever happens to be positioned above it. Defined once here
   for the same reason as the parts above: it was copied into the <style> of
   every English page that used it, and the Korean pages then had none. */
.grainlayer{position:absolute;inset:0;pointer-events:none;z-index:0;}


/* [hidden] 은 display:none 을 뜻하는데, display 를 지정한 규칙이 뒤에 오면
   그 규칙이 이깁니다. .agree 와 .fld 가 grid 라서, 카드 결제가 아닐 때
   숨겨야 할 정기결제 동의와 전화 요금제가 아닐 때 숨겨야 할 통화 칸이
   그대로 보이고 있었습니다. 고른 것과 화면이 다르면 구매자는 자기가
   잘못 골랐다고 생각합니다. */
[hidden]{display:none !important;}

/* 요약 카드의 안내 문단들. 세금 처리와 창립 할인, 그리고 그 나라에서
   아직 안 되는 것을 알리는 줄입니다. 앞선 판에서 .sm-tax 만 규칙이 없어
   혼자 본문 크기로 나오고 위 상자에 붙어 있었습니다. */
.sm-note{margin-top:10px;font-size:var(--fs-xs);line-height:1.7;color:var(--tx3);font-weight:500;}
.sm-tax{margin-top:12px;padding-top:12px;border-top:1px dashed var(--hair-d);}
.sm-disc{margin-top:10px;padding:9px 11px;border-radius:8px;
  background:rgba(11,120,120,.12);color:var(--tx2);font-weight:700;}
.sm-warn{margin-top:10px;padding:9px 11px;border-radius:8px;
  background:rgba(226,168,88,.14);color:#141A1F;font-weight:600;}
.sm-row s{color:var(--tx3);font-weight:500;margin-right:6px;}

/* 칸 아래 한 줄 설명. 라벨만으로는 왜 묻는지 알 수 없는 칸이 있습니다.
   주문서와 주문 조회가 함께 씁니다 — 한쪽에만 두면 다른 쪽은 스타일 없이
   나가고, 그건 오류를 내지 않으므로 아무도 모릅니다. */
.hint{display:block;margin-top:6px;font-size:var(--fs-xs);color:var(--tx3);line-height:1.6;}

/* 계약 성립 단계. 문장은 assets/data/policy.json 이 정하고, 한국어와 영문
   약관이 그 하나에서 받아 갑니다. 두 언어에 따로 적어 두었을 때 실제로
   서로 다른 관할을 말하고 있었습니다. */
.polsum{margin-bottom:18px;}
.polsteps{margin:0;padding:0;counter-reset:pol;display:grid;gap:14px;}
.polsteps li{list-style:none;position:relative;padding-left:38px;counter-increment:pol;}
.polsteps li::before{content:counter(pol);position:absolute;left:0;top:1px;
  width:24px;height:24px;border-radius:50%;display:grid;place-items:center;
  font-size:11px;font-weight:700;font-variant-numeric:tabular-nums;
  background:rgba(11,120,120,.14);color:var(--teal);}
.polsteps li b{display:block;margin-bottom:3px;}
.polsteps li span{display:block;color:var(--tx2);}
[data-grade] .polsteps li::before,
body[data-grade="trust"] .polsteps li::before{background:rgba(11,120,120,.14);color:var(--teal);}

/* ═══════ #demo60 — the demo that drives itself ═══════
   Text in HTML, flow on canvas (d60flow), figures from the same set
   play.js publishes. One primary button; everything else is quiet. */
.d60sec{position:relative;}
.d60head{display:flex;flex-wrap:wrap;align-items:center;gap:14px;}
.d60head .btn{min-width:190px;justify-content:center;}
.d60voice{font-size:var(--fs-2xs);font-weight:700;color:var(--tx3);background:none;
  border:1px solid var(--hair-d);border-radius:999px;padding:8px 14px;cursor:pointer;}
.d60voice.on{color:var(--teal);border-color:rgba(11,120,120,.5);}
.d60prog{margin-top:18px;}
.d60bar{height:4px;border-radius:2px;background:rgba(148,163,184,.18);overflow:hidden;}
.d60bar i{display:block;height:100%;width:0;background:var(--teal);transition:width .2s linear;}
.d60ticks{display:flex;justify-content:space-between;margin-top:8px;font-size:var(--fs-2xs);
  font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--tx3);}
.d60ticks span{opacity:.45;transition:opacity .3s,color .3s;}
.d60ticks span.on{opacity:1;color:var(--teal);}
.d60stage{margin-top:26px;display:grid;grid-template-columns:1.15fr .85fr;gap:18px;align-items:start;}
.d60convo{max-height:430px;overflow-y:auto;scroll-behavior:smooth;}
.d60sys{margin:14px auto 6px;text-align:center;font-size:var(--fs-2xs);font-weight:700;
  letter-spacing:.05em;color:var(--tx3);}
.d60chan{display:inline-block;font-style:normal;font-size:var(--fs-2xs);font-weight:800;
  color:var(--chan-msg);margin-right:8px;letter-spacing:.04em;}
.d60col{display:grid;gap:12px;}
.d60card{background:rgba(20,26,31,.046);border:1px solid var(--hair-d);border-radius:14px;padding:16px 18px;}
.d60card>.lbl{font-size:var(--fs-2xs);font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--tx3);}
.d60field{display:grid;grid-template-columns:76px 1fr;gap:3px 12px;padding:8px 0;border-bottom:1px dashed var(--hair-d);
  font-size:var(--fs-xs);animation:d60in .4s ease;}
.d60field:last-child{border-bottom:0;}
.d60field b{color:var(--tx2);font-weight:700;}
.d60field span{color:var(--tx);font-weight:600;}
.d60field i{grid-column:2;font-style:normal;font-size:var(--fs-2xs);font-weight:600;}
.d60field i.ok{color:var(--green);}
.d60field i.ok::before{content:"✓ ";}
.d60field i.guess{color:var(--amber);}
.d60rec{opacity:.35;transition:opacity .5s;}
.d60rec.on{opacity:1;}
.d60rec .who{display:flex;align-items:center;gap:10px;margin-top:10px;}
.d60rec .who b{font-size:var(--fs-sm);color:var(--tx);}
.d60rec .who .d60ph,.d60rec .who .d60wa{font-style:normal;font-size:var(--fs-2xs);font-weight:800;
  padding:3px 9px;border-radius:999px;}
.d60ph{color:var(--chan-voice);background:rgba(11,120,120,.12);}
.d60wa{color:var(--chan-msg);background:rgba(47,133,90,.12);animation:d60in .5s ease;}
.d60match{margin-top:10px;font-size:var(--fs-2xs);font-weight:700;color:var(--chan-msg);}
.d60match::before{content:"⇄ ";}
.d60work{display:grid;grid-template-columns:26px 1fr;gap:2px 10px;padding:9px 0;
  border-bottom:1px dashed var(--hair-d);font-size:var(--fs-xs);animation:d60in .4s ease;}
.d60work:last-child{border-bottom:0;}
.d60work i{font-style:normal;color:var(--teal);font-weight:800;}
.d60work b{color:var(--tx);}
.d60work span{grid-column:2;color:var(--tx2);}
.d60hand{border-color:rgba(183,121,31,.45);}
.d60hand .lbl{color:var(--amber);}
.d60hand ul{margin-top:8px;display:grid;gap:6px;font-size:var(--fs-xs);color:var(--tx2);list-style:none;}
.d60hand li::before{content:"→ ";color:var(--amber);font-weight:800;}
.d60flowbox{position:relative;height:64px;margin-top:4px;}
.d60end{margin-top:22px;display:flex;flex-wrap:wrap;gap:12px;align-items:center;animation:d60in .5s ease;}
@keyframes d60in{from{opacity:0;transform:translateY(6px);}to{opacity:1;transform:none;}}
@media (max-width:900px){
  .d60stage{grid-template-columns:1fr;}
  .d60convo{max-height:320px;}
  .d60ticks span{font-size:10px;}
}
@media (prefers-reduced-motion:reduce){
  .d60field,.d60work,.d60end,.d60wa{animation:none;}
}

/* hero channel trio — what each door collects */
.herotrio{margin-top:22px;display:flex;flex-wrap:wrap;gap:10px;}
.herotrio a{display:grid;gap:2px;padding:10px 16px;border:1px solid var(--hair-d);border-radius:8px;
  background:rgba(20,26,31,.052);text-decoration:none;min-width:150px;}
.herotrio b{font-size:var(--fs-xs);font-weight:800;}
.herotrio span{font-size:var(--fs-2xs);color:var(--tx3);font-weight:600;}
.herotrio a:nth-child(1) b{color:var(--chan-voice);}
.herotrio a:nth-child(2) b{color:var(--chan-chat);}
.herotrio a:nth-child(3) b{color:var(--chan-msg);}
.herotrio a:hover{border-color:rgba(11,120,120,.45);}

/* ═══════ #quote-builder — my month, priced before I ask ═══════ */
.qbgrid{margin-top:26px;display:grid;grid-template-columns:1fr .9fr;gap:20px;align-items:start;}
.qbcard{background:rgba(20,26,31,.046);border:1px solid var(--hair-d);border-radius:14px;padding:22px 24px;}
.qbcard .lbl{font-size:var(--fs-2xs);font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--tx3);}
.qbrow{display:grid;gap:8px;padding:14px 0;border-bottom:1px dashed var(--hair-d);}
.qbrow:last-child{border-bottom:0;}
.qbrow>b,.qbrow>.qbl{font-size:var(--fs-xs);color:var(--tx);font-weight:700;}
.qbrow select,.qbrow input[type=number]{background:rgba(20,26,31,.065);border:1px solid var(--hair-d);
  border-radius:8px;color:var(--tx);padding:10px 12px;font-size:var(--fs-sm);width:100%;max-width:320px;}
.qbchan{display:flex;flex-wrap:wrap;gap:10px;}
.qbchan label{display:flex;align-items:center;gap:8px;border:1px solid var(--hair-d);border-radius:999px;
  padding:9px 16px;font-size:var(--fs-xs);font-weight:700;color:var(--tx2);cursor:pointer;}
.qbchan label:has(input:checked){border-color:rgba(11,120,120,.55);color:var(--tx);background:rgba(11,120,120,.07);}
.qbchan input{accent-color:var(--teal);}
.qbplan{margin-top:4px;font-size:var(--fs-xs);color:var(--tx2);}
.qbplan b{color:var(--teal);}
.qb-big{display:block;font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-h2);font-weight:700;color:var(--tx);letter-spacing:-.02em;}
.qb-split{display:block;margin-top:4px;font-size:var(--fs-xs);color:var(--tx2);font-weight:600;}
.qbtax{margin-top:14px;padding-top:14px;border-top:1px solid var(--hair-d);font-size:var(--fs-xs);color:var(--tx2);line-height:1.7;}
.qbinc{margin-top:12px;display:grid;gap:6px;font-size:var(--fs-xs);color:var(--tx2);list-style:none;}
.qbinc li::before{content:"✓ ";color:var(--green);font-weight:800;}
.qbnote{margin-top:14px;display:grid;gap:8px;font-size:var(--fs-xs);color:var(--tx2);line-height:1.7;}
.qbnote b{color:var(--tx);}
@media (max-width:900px){.qbgrid{grid-template-columns:1fr;}}

/* ═══════ playbook 공용 — trio·표 (업종 9쪽 + 재사용처) ═══════
   밝은 절(sec-light)과 어두운 절 양쪽에서 서도록 색은 변수로만. */
.trio{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:14px;}
.trio>div{background:rgba(127,127,127,.05);border:1px solid var(--l-hair,rgba(127,127,127,.18));
  border-radius:14px;padding:18px 20px;}
.sec-dark .trio>div{border-color:var(--hair-d);background:rgba(20,26,31,.046);}
.trio>div>b{display:block;font-size:var(--fs-sm);margin-bottom:6px;}
.trio>div>p{font-size:var(--fs-xs);line-height:1.7;margin:0;}
.dtwrap{overflow-x:auto;border:1px solid var(--l-hair,rgba(127,127,127,.18));border-radius:14px;}
.sec-dark .dtwrap{border-color:var(--hair-d);}
.dtable{border-collapse:collapse;width:100%;min-width:560px;font-size:var(--fs-xs);}
.dtable th,.dtable td{text-align:left;padding:10px 14px;border-bottom:1px solid var(--l-hair,rgba(127,127,127,.15));
  vertical-align:top;line-height:1.6;}
.sec-dark .dtable th,.sec-dark .dtable td{border-color:var(--hair-d);}
.dtable thead th{font-size:var(--fs-2xs);font-weight:800;letter-spacing:.08em;text-transform:uppercase;}
.dtable tr:last-child td,.dtable tr:last-child th{border-bottom:0;}
.h3{font-family:'Bricolage Grotesque',sans-serif;font-size:var(--fs-h3);font-weight:700;letter-spacing:-.02em;}

/* photosplit — 풀블리드 밴드의 내용 상한. 밴드 배경은 절이 칠하므로
   내용만 가운데로 모으면 초광폭에서 텍스트 반쪽이 팔을 못 벌린다. */
.photosplit{max-width:1520px;margin-left:auto;margin-right:auto;}

/* ═══════ 모바일 실사용 검증에서 잡힌 넘침 5종 (2026-09-01) ═══════ */
@media (max-width:700px){
  /* 통화 창 상단 바: 「예시·가상의 통화」「영업시간 밖」 라벨이 한 줄에서 밀려나 잘림 */
  .appwin .bar{flex-wrap:wrap;row-gap:6px;}
  .appwin .bar .closed{margin-left:0;}
  /* 요금 쪽 제목 옆 「직접 해 보세요」 알약: 제목보다 길면 다음 줄로 */
  .tryme{white-space:normal;margin-left:0;margin-top:8px;max-width:100%;}
  /* 업종 쪽 사례 탭: 화면보다 길면 가로 스크롤 (모바일 탭의 표준 동작) */
  .srjs .pstabs{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;
    padding-bottom:6px;scrollbar-width:thin;}
  .srjs .pstabs > *{flex:none;}
  /* 캡션 속 링크가 한 단어처럼 취급되어 뷰포트 밖으로 */
  .seccap .linkcta,.scenecap .linkcta{display:inline;white-space:normal;}
  /* 비교표: 감싸는 스크롤 상자가 없어도 표 스스로 가로 스크롤 */
  .cmp{display:block;overflow-x:auto;-webkit-overflow-scrolling:touch;}
}
/* 안내 링의 닫기 단추: 26px 은 손가락 표적으로 작음 — 그림은 두고 표적만 44px */
.fr-x{width:32px;height:32px;right:-16px;top:-16px;font-size:16px;}
.fr-x::before{content:"";position:absolute;inset:-6px;}

/* ═══════ 모바일 전수 스캔 잔여 (144쪽 @375, 2026-09-01) ═══════ */
@media (max-width:700px){
  /* WhatsApp 쪽: 지역 카드 6열 격자에 모바일 규칙이 없었다 */
  .reggrid{grid-template-columns:repeat(2,1fr);}
  /* 24시간 창 타임라인 SVG(viewBox 1000): 고유 폭으로 그려져 화면을 넘었다 */
  .tlpanel svg{width:100%;max-width:100%;height:auto;}
  /* 업종 쪽 문자 스레드 목업: 안쪽 요소의 최소 폭이 카드를 밀어냈다 */
  .msgthread,.msgthread *{max-width:100%;min-width:0;}
  /* 위험 되돌림 행: 두 열이 375 에서 카드 패딩까지 더하면 넘친다 */
  .riskrow{grid-template-columns:1fr;}
  /* 한국어 요금표 */
  .krate{display:block;overflow-x:auto;-webkit-overflow-scrolling:touch;}
  /* &nbsp; 로 이어 붙인 긴 구절과 단추가 몇 px 넘치는 것 — 어디서든 꺾일 수 있게 */
  .concl,.photosplit .copy,.cnp,.cnl{overflow-wrap:anywhere;}
  .btn{max-width:100%;white-space:normal;}
}

/* ═══════ 모바일 잔여 2차 — 쪽 로컬 규칙이 뒤에 실려 이겨 버리므로 여기만 !important ═══════
   측정 근거(375px): .reggrid 3열 515px>324 · .dispcols 트랙이 자식 최소폭으로 431px 팽창 ·
   .riskrow 2열 335px>324 · .tlrow 카드 403. 격자 트랙은 minmax(0,1fr) 로 팽창을 막고,
   카드 안 긴 구절은 어디서든 꺾이게 한다. */
@media (max-width:700px){
  .reggrid{grid-template-columns:1fr !important;}
  .dispcols{grid-template-columns:minmax(0,1fr) !important;}
  .dispside,.dispside *{min-width:0;overflow-wrap:anywhere;}
  .riskrow{grid-template-columns:1fr !important;}
  .tlrow{grid-template-columns:minmax(0,1fr) !important;}
  .tlrow,.tlrow>*{min-width:0;overflow-wrap:anywhere;}
}
/* WhatsApp 지역 격자의 진짜 원인: 모바일 1열에서도 4·5번째 카드의
   nth-child span 3 규칙(특이도 0,2,0)이 살아 남아 암시적 트랙 두 개를
   만들었다. 모든 카드를 한 트랙에 앉힌다. */
@media (max-width:700px){ .reggrid > *{grid-column:auto !important;} }

/* 제목에서 라벨로 내려온 것들(.hl3/.hl4/.hl5)은 UA 가 주던 굵기를 잃는다 — 돌려준다.
   h5 의 UA 크기(.83em)도. 클래스가 있는 문맥은 자기 규칙이 이긴다. */
.hl3,.hl4,.hl5{font-weight:700;}
.hl5{font-size:.83em;}
/* 시각적으로 숨긴 제목 — 문서 개요에만 존재 */
.vh{position:absolute!important;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;}

/* 금액이 든 SVG 장면은 375px 에서 4px 글자가 된다 — 가로 스크롤을 허용해 크기를 지킨다 */
@media (max-width:620px){
  .scene-frame{overflow-x:auto;-webkit-overflow-scrolling:touch;}
  .scene-frame svg{min-width:720px;}
}
/* 저대비 다섯 곳 (측정 3.79 · 2.2 · 2.1 : 1) */
.nl .t i{opacity:1;color:var(--tx2);font-size:14px;}
@media (max-width:700px){ .d60ticks span{font-size:12px;opacity:.7;} }
.cmp .lim{color:var(--amber-ink,#9A6B1F);}
/* 레일은 히어로를 지나기 전엔 보이지 않는다 — 첫 화면의 '시작' 지시는 하나 */
.stickycta.hasguide:not(.show){transform:translateY(120%);}
/* 금액 SVG 장면: 쪽 로컬 .scene-frame.x 규칙(특이도 0,2,0)이 overflow:hidden 을 이겨
   720px 로 키운 SVG 가 잘렸다 — 모바일에서만 스크롤을 강제한다 */
@media (max-width:620px){
  .scene-frame,.scene{overflow-x:auto !important;overflow-y:hidden;-webkit-overflow-scrolling:touch;}
  .scene-frame > svg,.scene > svg{min-width:720px;}
  .d60ticks{flex-wrap:wrap;gap:6px 14px;justify-content:flex-start;}
  .seccap{white-space:normal;overflow-wrap:anywhere;}
}
/* 2열 격자(.inbcols/.instcols 등)의 트랙이 720px SVG 의 최소폭으로 팽창하지 않게 —
   폰에서는 어차피 1열이다 */
@media (max-width:700px){
  main [class*="cols"]{grid-template-columns:minmax(0,1fr) !important;}
  .scene-frame,.scene{min-width:0;max-width:100%;}
}
/* 캡션 속 링크는 폰에서 제 줄을 갖는다 — 인라인 흐름이 어떤 이유로든 밖으로 밀리지 않게 */
@media (max-width:700px){
  /* 격자 항목인 캡션은 min-width:auto 라 트랙보다 넓어진다 — 0 으로 */
  main [class*="grid"] > .seccap, main [class*="grid"] > p{min-width:0;}
  .seccap .linkcta{display:inline;}
}
/* 업종 절 캡션이 2단 컬럼으로 조판되어 폰에서 둘째 단이 화면 밖에 놓였다 — 폰은 1단 */
@media (max-width:700px){
  .seccap,.igrid .seccap,.indsec .seccap{column-count:1 !important;columns:auto !important;}
}
