/* ============================================================================
   CloudCall v5 design system
   Style: Bento Box Grid (UI/UX Pro Max) · Type: Plus Jakarta Sans
   Canvas: off-white page, white cards, deep navy feature sections
   Chrome: full-bleed nav + 10px-radius buttons (--btn-r)
   ========================================================================== */
:root{
  --ink:#0B1020; --ink-2:#131A2E;
  --brand:#1D4ED8; --brand-2:#3B82F6; --brand-3:#60A5FA; --brand-deep:#1739A8;
  --accent:#06B6D4;
  --page:#F4F6FA; --card:#FFFFFF; --line:#E4E9F2; --line-2:#EEF2F8;
  --text:#48566E; --muted:#7C8AA5;
  --ok:#16A34A;
  --grad:linear-gradient(115deg,#1D4ED8,#06B6D4);
  --sh-1:0 1px 2px rgba(11,16,32,.04);
  --sh-2:0 8px 24px -10px rgba(11,16,32,.14);
  --sh-3:0 28px 64px -24px rgba(11,16,32,.30);
  --r:20px; --r-lg:26px;
  --nav-h:66px;
  /* Contact strip REMOVED from mobile and desktop (client, 2026-08-17). 0 here is the
     single switch: the nav's `top` and --chrome-h both read it, and page() no longer
     renders the markup either. `.topbar` CSS below is dead but kept -- see topbar()
     in build.py for why. Restore = 38px here + the markup back in page(). */
  --tb-h:0px;
  /* FULL-BLEED CHROME (client, 2026-08-10). The nav bar and the hero are edge-to-edge
     BACKGROUNDS again -- the inset capsule/panel of 2026-08-07 is gone. What stayed from
     that pass is that the CONTENT is still capped and centred, so "not full width" still
     holds for the copy; it is only the paint that now runs to the viewport edge.
     `--shell` / `--shell-pad` therefore size the nav's inner CONTENT, not the bar. The hero
     caps its own content with the `.wrap` inside it (1200px, or 1400px on `.dial-hero`).
     `--nav-pad` is kept at 0 and NOT deleted: --chrome-h, .dial-hero's min-height and
     main.js's availPx() all read it, and it is the one knob that would float the bar again.
     `--chrome-h` is the real height of everything above the page: --nav-h is only the bar
     itself, so anything offsetting below the bar must use --chrome-h, never --nav-h.
     main.js measures the bar's rect instead of re-adding these, so the two cannot drift. */
  --nav-pad:0px; --shell:1560px; --shell-pad:24px;
  --chrome-h:calc(var(--tb-h) + var(--nav-h) + var(--nav-pad)*2);
}
*{margin:0;padding:0;box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
html.lenis,html.lenis body{height:auto}
.lenis.lenis-smooth{scroll-behavior:auto!important}
body{font-family:'Plus Jakarta Sans',system-ui,-apple-system,sans-serif;background:var(--page);
  color:var(--text);font-size:16px;line-height:1.65;-webkit-font-smoothing:antialiased;overflow-x:hidden}
h1,h2,h3,h4,b,strong{color:var(--ink);letter-spacing:-.025em;font-weight:700}
h1{font-weight:800}
a{color:inherit;text-decoration:none}
img,svg{max-width:100%;display:block}
button{font:inherit;cursor:pointer;border:0;background:none;color:inherit}
.wrap{max-width:1200px;margin:0 auto;padding:0 24px}
.wrap.narrow{max-width:820px}
.sec{padding:104px 0}
.sec.pt0{padding-top:0}
.sec.light{background:var(--card)}
.sec.dark{background:var(--ink);color:#9DAAC4}
.sec.dark h2,.sec.dark h3,.sec.dark b{color:#fff}
/* ---------------------------------------------------------------- icons
   Inline SVG from icons.py replaces every emoji. Sized in em so each icon inherits the
   font-size its container already sets, and coloured by currentColor. */
.ic-svg{width:1.15em;height:1.15em;flex:none;display:block}
.ic,.uc-ic,.csc-ic,.sic,.psi,.pint .ic{color:var(--brand)}
.bt .ic,.fcard .ic,.pc .ic,.mm .ic,.citem .ic,.faq-help .ic{color:var(--brand)}
.sec.dark .bt .ic,.plat-sec .bt .ic{color:#93C5FD}
.uc:hover .uc-ic,.step .sic{color:#fff}
.cs-dark .csc-ic{color:#7DD3FC}
/* inline icons that sit next to text rather than in a tile */
.cta-trust .ic-svg,.fn .ic-svg,.pfn .ic-svg,.ind-chip .ic-svg,.psearch .ic-svg,
.psearchbox .ic-svg,.pbell .ic-svg,.plock .ic-svg{display:inline-block;vertical-align:-.18em}
.cta-trust span{display:inline-flex;align-items:center;gap:7px}
.fn,.pfn{display:inline-flex;align-items:center;gap:8px;justify-content:center}
.pcall,.pcctrl button,.pacts button,.pplay{display:inline-flex;align-items:center;
  justify-content:center;gap:7px}
.pplay .ic-svg{width:11px;height:11px}
.pcctrl button .ic-svg{width:16px;height:16px}
.av .ic-svg{width:15px;height:15px}
.psi .ic-svg{width:15px;height:15px}
.pdir .ic-svg{width:12px;height:12px}

/* Solid, high contrast highlight. A gradient that faded to cyan was unreadable
   against the white hero, so the accent word is now a single deep brand blue. */
.hl{color:var(--brand)}
.hl-l{background:linear-gradient(115deg,#93C5FD,#22D3EE);-webkit-background-clip:text;background-clip:text;color:transparent}

/* ---------------------------------------------------------------- buttons
   SQUARED OFF (client, 2026-08-10): every button is a 10px radius, not the 999px pill it
   was. `--btn-r` is the single knob -- variants and the console never restate the number,
   so retuning it is one edit here. Deliberately scoped to `.btn`: the pill radius on
   `.mp-tag`, `.ind-chip` and `.subnav a` stays, because those are tags, chips and tabs,
   not buttons, and squaring them turns them into buttons visually. */
:root{--btn-r:10px}
.btn{display:inline-flex;align-items:center;justify-content:center;gap:7px;font-weight:600;font-size:15px;
  padding:12px 22px;border-radius:var(--btn-r);line-height:1.2;white-space:nowrap;position:relative;
  transition:transform .18s cubic-bezier(.2,.8,.3,1),box-shadow .18s,background .18s,border-color .18s,color .18s}
.btn.sm{padding:9px 16px;font-size:13.5px}
.btn.lg{padding:14px 28px;font-size:15.5px}
.btn .ba{width:15px;height:15px;flex:none;transition:transform .2s cubic-bezier(.2,.8,.3,1)}
.btn.arw:hover .ba{transform:translateX(3px)}

.btn.solid{color:#fff;background:var(--ink);box-shadow:0 1px 2px rgba(11,16,32,.28),
  inset 0 1px 0 rgba(255,255,255,.12)}
.btn.solid:hover{background:var(--brand);transform:translateY(-1px);
  box-shadow:0 10px 24px -10px rgba(29,78,216,.75),inset 0 1px 0 rgba(255,255,255,.18)}
.btn.solid:active{transform:translateY(0)}

.btn.ghost{color:var(--ink);background:var(--card);border:1px solid var(--line);box-shadow:var(--sh-1)}
.btn.ghost:hover{border-color:#C3D4F5;background:#F7F9FE;transform:translateY(-1px);box-shadow:var(--sh-2)}
.btn.ghost:active{transform:translateY(0)}

.btn.white{color:var(--ink);background:#fff;box-shadow:0 10px 26px -12px rgba(0,0,0,.6)}
.btn.white:hover{transform:translateY(-1px);box-shadow:0 16px 34px -14px rgba(0,0,0,.7)}

.btn.outline-light{color:#fff;border:1px solid rgba(255,255,255,.28);background:rgba(255,255,255,.06)}
.btn.outline-light:hover{background:rgba(255,255,255,.13);border-color:rgba(255,255,255,.55);transform:translateY(-1px)}

.cta-row{display:flex;gap:11px;flex-wrap:wrap;align-items:center}
.cta-row.center{justify-content:center}

/* ---------------------------------------------------------------- nav (floating dark bar)
   A single deep-navy bar with softly rounded corners, not a light capsule. It reads as a
   piece of product chrome rather than page furniture, and holds up over both the light
   hero and the dark bands it floats above. Dropdown panels stay light for legibility. */
/* ---------------------------------------------------------------- contact ticker
   Blue strip above the nav. It slides away on scroll and the nav takes the top edge, so
   the fixed chrome costs 66px rather than 104px once you are reading. `main` keeps a
   constant offset for both, so nothing jumps. */
/* CONTACT MARQUEE (client, 2026-08-10). Full-bleed blue strip pinned above the nav, running
   as a marquee at every width -- it used to be static and centred on desktop and only
   scrolled on mobile. Height is --tb-h, which the nav's `top` and --chrome-h both read, so
   setting --tb-h:0 is all it takes to remove the strip again without unwiring anything. */
.topbar{position:fixed;top:0;left:0;right:0;z-index:199;height:var(--tb-h);overflow:hidden;
  display:flex;align-items:center;color:#fff;
  background:linear-gradient(90deg,#1739A8,#1D4ED8 45%,#0891B2);
  transition:transform .35s cubic-bezier(.2,.8,.3,1)}
/* it slides away on scroll and the nav takes top:0 -- both on the same duration and curve,
   or the bar visibly races the strip it is following */
body.scrolled .topbar{transform:translateY(-100%)}
/* STATIC AND CENTRED (client, 2026-08-10). It ran as a marquee earlier the same day and the
   client asked for it to stop, so there is no animation, no transform and no duplicate set
   here -- nothing to keep in sync. The strip only ever has to fit ONE row of items, which is
   why the narrow-screen rules below drop items rather than scroll them. */
.tb-track{display:flex;align-items:center;justify-content:center;gap:30px;
  width:100%;padding:0 32px;min-width:0}
.tb-set{display:flex;align-items:center;gap:30px;white-space:nowrap;min-width:0}
.tb-set a,.tb-set span.tb-hrs{display:inline-flex;align-items:center;gap:7px;font-size:12.8px;
  font-weight:600;color:#fff;letter-spacing:.01em;transition:opacity .16s}
.tb-set a span{opacity:.72;font-weight:600}
.tb-set a:hover{opacity:.78}
.topbar .ic-svg{width:14px;height:14px;opacity:.9}
.tb-hrs{opacity:.82}
/* WHAT DROPS, AND WHEN. `.topbar` is overflow:hidden, so anything that does not fit is cut
   mid-word rather than wrapped -- the strip is a fixed 34-38px single row. So items are
   removed on the way down instead, least useful first. Thresholds are measured (see
   NOTES.md), not guessed, and each one is the width at which the NEXT item down would start
   to clip. Support and WhatsApp are last out: they are what a visitor on a phone taps.
   Measured item widths: Support 178, Sales 148, WhatsApp 180, email 142, hours 194. Gaps are
   30/32 padding above 860px and 22/16 below it, which is where each threshold comes from.
   NOTE THE SELECTOR SHAPE. `.tb-set a` and `.tb-set span.tb-hrs` above both carry a type
   selector, so a bare `.tb-em{display:none}` (0,1,0) silently loses and nothing drops. These
   have to match that shape to win on source order -- and this text has to stay inside the
   comment, because stray prose before an @media swallows the whole rule. */
@media(max-width:1060px){.tb-set span.tb-hrs{display:none}}
@media(max-width:800px){.tb-set a.tb-em{display:none}}
@media(max-width:620px){.tb-set a.tb-sal{display:none}}
/* Last resort before clipping: the word goes, the number stays. Two items with labels need
   412px and the smallest phones are 360-390. The icon already says which is which. */
@media(max-width:440px){.tb-set a span{display:none}}
/* The strip is dropped entirely on short viewports so it cannot break the one-screen hero.
   That rule is NOT here: it sets --tb-h and so must come after every width-based override
   of it, which means after the max-width:860px block. Search "STRIP YIELDS". */

/* FULL-BLEED BAR (client, 2026-08-10). The bar's paint lives on `.nav` so it runs the whole
   viewport width; `.nav-inner` is now only the content track. The two used to be one element
   and every bit of chrome below (background, blur, border, shadow, the .scrolled state) was
   on `.nav-inner` -- moving it up here is the whole change. `.nav` must therefore take
   `pointer-events:auto`: it is the bar now, not an invisible positioning frame. */
.nav{position:fixed;top:var(--tb-h);left:0;right:0;z-index:200;padding:var(--nav-pad) 0;
  pointer-events:auto;
  background:rgba(6,9,20,.92);backdrop-filter:saturate(170%) blur(22px);
  -webkit-backdrop-filter:saturate(170%) blur(22px);
  border-bottom:1px solid rgba(255,255,255,.11);
  box-shadow:0 18px 44px -32px rgba(11,16,32,.75),inset 0 -1px 0 rgba(255,255,255,.04);
  transition:top .35s cubic-bezier(.2,.8,.3,1),background .3s,box-shadow .3s,border-color .3s}
body.scrolled .nav{top:0}
.nav.scrolled{background:rgba(5,7,16,.97);border-bottom-color:rgba(255,255,255,.16);
  box-shadow:0 24px 54px -32px rgba(11,16,32,.9),0 1px 6px -3px rgba(11,16,32,.4),
             inset 0 -1px 0 rgba(255,255,255,.05)}
/* Content track only -- no paint of its own. `width:min()` rather than max-width plus
   margins, because the content has to be both centred and never closer to the edge than the
   gutter: `max-width` alone gives no gutter below the cap, and a margin alone gives no cap.
   `--nav-pad` is deliberately NOT animated on scroll: it feeds --chrome-h, so changing it
   would move `main`'s padding and jump the whole page. */
.nav-inner{width:min(var(--shell),100% - var(--shell-pad)*2);margin:0 auto;
  height:var(--nav-h);display:flex;align-items:center;gap:10px;
  padding:0 12px 0 24px;
  /* The backdrop-filter that used to sit here is what made this the containing block for
     the fixed .mm dropdowns, which is why they are bar-content-width and not viewport-wide
     sheets. The blur moved to `.nav`, so the containing block has to be re-established by
     other means or every dropdown snaps to full bleed. Any of transform/filter/contain
     does it; translateZ(0) is the cheapest and the element was already composited. */
  transform:translateZ(0)}
/* the three groups are plain flex wrappers now, not separate capsules */
.nav-pill{display:flex;align-items:center;background:none;border:0;box-shadow:none;
  backdrop-filter:none;-webkit-backdrop-filter:none;height:auto;border-radius:0}
.nav-brand{flex:none}
.nav-nav{flex:none;margin-left:30px;margin-right:auto}
.nav-cta{flex:none;gap:18px}
.logo{display:inline-flex;align-items:center;flex:none}
.logo-img{display:block;width:auto;max-width:100%}

.menu{display:flex;align-items:center;gap:1px;position:relative}
/* pill that slides between menu items on hover, driven by main.js */
.menu-ind{position:absolute;top:auto;bottom:-9px;left:0;width:0;height:2.5px;transform:none;
  border-radius:2px;background:linear-gradient(90deg,var(--brand-2),var(--accent));border:0;
  opacity:0;pointer-events:none;z-index:0;
  transition:left .34s cubic-bezier(.4,1.3,.5,1),width .34s cubic-bezier(.4,1.3,.5,1),opacity .22s}
.menu.lit .menu-ind{opacity:1}
.mi{position:relative;z-index:1}
.mt{position:relative;z-index:1;display:inline-flex;align-items:center;gap:6px;padding:9px 15px;
  font-weight:600;font-size:14.5px;color:#B9C6E0;border-radius:12px;transition:color .22s}
.menu.lit .mt.hot,.menu.lit .mi.hot>.mt,.mi:hover>.mt{color:#fff}
.cx{display:none;width:5.5px;height:5.5px;border-right:1.8px solid currentColor;border-bottom:1.8px solid currentColor;
  transform:rotate(45deg) translate(-1px,-1px);transition:transform .22s;opacity:.65}
.mi:hover .cx{transform:rotate(225deg) translate(-2px,-2px)}

/* Rounded sheet matching the nav's CONTENT width, floating just below the bar. It kept this
   shape when the bar went back to full bleed (2026-08-10) -- a viewport-wide sheet is what
   it used to be and what the client moved away from. `--band` is plain padding, not the old
   viewport calculation that lined the columns up with the 1200px page band. */
.mm{--band:26px;
  /* fixed, not absolute: .nav-inner is a containing block for fixed descendants (see the
     translateZ there), so left/right 0 is the content track's width and top:100% is its
     bottom edge. Absolute would centre on the menu item. */
  position:fixed;top:calc(100% + 12px);left:0;right:0;
  /* Capped and centred in the nav track (client, 2026-08-10: mega menu off full width).
     left:0/right:0 alone stretched it to the whole track -- 1560px on a 1920 screen. With a
     width set as well the box is over-constrained, so margin-inline:auto resolves the
     remainder and centres it. --mm-w is the only number to change to retune this. */
  --mm-w:1100px;
  width:min(var(--mm-w),100%);margin-inline:auto;
  /* White sheet (client, 2026-08-17: "dark is not appealing my text and things"). Was a
     navy gradient -- every colour below this point used to be tuned for white-on-dark and
     had to flip to ink-on-white at the same time, or the menu goes back to unreadable. */
  background:var(--card);
  /* Square corners (client, 2026-08-10). `overflow:hidden` below was what clipped the
     .mm-bar to the old 24px curve; with the radius at 0 it now only matters for the
     stagger transforms, so do not delete it on the assumption it was only for the curve. */
  border:1px solid var(--line);border-radius:0;
  box-shadow:0 34px 64px -34px rgba(11,16,32,.28);
  padding:0;overflow:hidden;opacity:0;visibility:hidden;transform:translateY(-10px);
  transition:opacity .24s cubic-bezier(.2,.8,.3,1),transform .24s cubic-bezier(.2,.8,.3,1),visibility .24s;
  z-index:210}
.mi:hover .mm{opacity:1;visibility:visible;transform:translateY(0)}
.mi::after{content:'';position:absolute;top:100%;left:0;right:0;height:20px}
.mm-body{padding:30px var(--band) 34px}
/* .one-col went with the Resources dropdown (client, 2026-08-10). .two-col stays -- the
   Features menu still uses it with an .mm-promo rail. */
.mm.two-col{display:grid;grid-template-columns:1fr 320px;
  padding:0 var(--band);column-gap:44px}
.mm.two-col .mm-body{padding:30px 0 34px}
.mm-grid{display:grid;grid-template-columns:1fr 1fr;gap:2px}

/* items stagger in behind the panel */
.mm a,.mm .mh{opacity:0;transform:translateY(6px)}
.mi:hover .mm a,.mi:hover .mm .mh{opacity:1;transform:none;
  transition:opacity .3s ease,transform .3s cubic-bezier(.2,.8,.3,1),background .16s}
.mi:hover .mm a:nth-child(2){transition-delay:.03s}
.mi:hover .mm a:nth-child(3){transition-delay:.06s}
.mi:hover .mm a:nth-child(4){transition-delay:.09s}
.mi:hover .mm a:nth-child(5){transition-delay:.12s}
.mi:hover .mm a:nth-child(6){transition-delay:.15s}
.mi:hover .mm a:nth-child(7){transition-delay:.18s}

.mm a{display:flex;gap:12px;align-items:center;padding:10px 11px;border-radius:14px;position:relative}
.mm a:hover{background:var(--line-2)}
.mm a::after{content:'→';position:absolute;right:12px;font-size:13px;color:var(--brand);
  opacity:0;transform:translateX(-4px);transition:opacity .2s,transform .2s}
.mm a:hover::after{opacity:1;transform:none}
.mm .ic{width:38px;height:38px;border-radius:12px;background:#EEF3FD;
  border:1px solid #DCE6FA;display:grid;place-items:center;
  font-size:17px;flex-shrink:0;transition:background .2s,transform .2s;color:var(--brand)}
/* icons go white on hover: the tile fills with the brand gradient */
.mm a:hover .ic{background:var(--grad);border-color:transparent;color:#fff;transform:scale(1.06) rotate(-4deg)}
/* `.ic.sm` used to shrink the Use Cases icons to 31px. Every dropdown icon is now the
   same 38px tile as the Features menu; the class is kept only as a markup hook. */
.mm .ic.sm{width:38px;height:38px;border-radius:12px}
/* the glyph is sized explicitly, not in em: `.mm.mega .mcol span` sets font-size 11.5px
   at a higher specificity and would otherwise shrink the mega-menu icons to 13px */
.mm .ic .ic-svg{width:19px;height:19px}
.mm b{display:block;font-size:14px;color:var(--ink);font-weight:600;letter-spacing:-.01em}
.mm span{display:block;font-size:12.5px;color:var(--muted);line-height:1.45}

/* promo panel on the right of the sheet -- a soft brand tint on the now-white sheet. */
.mm-promo{align-self:center;margin:30px 0 34px;border-radius:18px;
  background:linear-gradient(165deg,#EEF3FD,#F2FBFD);
  border:1px solid var(--line);color:var(--text);padding:22px 20px;display:flex;
  flex-direction:column;justify-content:center;gap:9px}
.mp-tag{display:inline-block;align-self:flex-start;font-size:10px;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:var(--brand);background:#fff;
  border:1px solid #DCE6FA;border-radius:999px;padding:4px 10px}
.mm-promo b{font-size:16px;color:var(--ink);letter-spacing:-.02em}
.mm-promo p{font-size:12.5px;line-height:1.6;margin-bottom:6px;color:var(--muted)}
.mm-promo .btn{align-self:flex-start}

/* footer bar on the Use Cases mega menu */
.mm-bar{display:flex;align-items:center;gap:14px;padding:16px var(--band);
  background:#F8FAFD;border-top:1px solid var(--line)}
.mb-dot{width:9px;height:9px;border-radius:50%;background:var(--ok);flex:none;
  box-shadow:0 0 0 4px rgba(22,163,74,.16);animation:blink 2s infinite}
.mm-bar b{display:block;font-size:13.5px;color:var(--ink)}
.mm-bar span{display:block;font-size:12px;color:var(--muted);line-height:1.45}
.mm-bar .btn{flex:none;margin-left:auto}

/* Both dropdown CTAs are ink filled and go brand blue on hover -- they were WHITE for the
   navy sheet (client, 2026-08-10); the sheet is white now, so a white button would vanish
   and these flipped to a solid fill instead. Listed by variant rather than as a bare
   `.mm .btn` because `.btn.solid:hover` is (0,3,0) and would otherwise win the background
   back on the Use Cases one; naming the variant here makes these (0,4,0). */
.mm .btn.white,.mm .btn.solid{color:#fff;background:var(--ink);border:0;
  box-shadow:0 10px 26px -12px rgba(11,16,32,.5)}
.mm .btn.white:hover,.mm .btn.solid:hover{background:var(--brand);color:#fff;
  transform:translateY(-1px);box-shadow:0 16px 32px -14px rgba(29,78,216,.55)}

.mm.mega .mm-body{display:grid;grid-template-columns:1fr 1fr 2.05fr;gap:6px;
  padding:30px var(--band) 30px}
/* Features menu: three EQUAL columns. `.mm.mega`'s default 1/1/2.05 is shaped for the Use
   Cases menu, whose third column is a 12-item industry grid; the Features columns are all
   plain lists, so equal thirds is the right split. */
.mm.mega.feat .mm-body{grid-template-columns:repeat(3,1fr);column-gap:26px}
.mm.mega.feat .mcol+.mcol{border-left:1px solid var(--line);padding-left:22px}
.mm.mega .mcol{padding:4px}
.mm.mega .mcol.wide{border-left:1px solid var(--line);padding-left:22px}
.mm.mega .mcol span{font-size:11.5px}
.mh{display:block;font-size:10.5px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);padding:6px 11px 10px}
/* three across keeps the 12 industries to four rows, so the menu is not far taller
   than the three-item columns beside it */
.mind{display:grid;grid-template-columns:repeat(3,1fr);gap:1px}
.mind a{padding:8px 9px;gap:9px}
.mind a::after{display:none}
.mind b{font-size:13px;line-height:1.3}

.nav-login{font-size:14px;font-weight:600;color:#93A3C4;padding:8px 6px;transition:color .16s}
.nav-login:hover{color:#fff}
/* the ink-black solid button would vanish on the dark bar, so the nav CTA is white */
.nav-cta .btn.solid{background:#fff;color:var(--ink);
  box-shadow:0 6px 18px -8px rgba(0,0,0,.7),inset 0 -1px 0 rgba(11,16,32,.08)}
.nav-cta .btn.solid:hover{background:var(--brand-3);color:var(--ink);
  box-shadow:0 10px 26px -10px rgba(96,165,250,.8)}
.menu-foot{display:none}
.burger{display:none;width:40px;height:40px;position:relative;flex:none}
.burger i,.burger i::before,.burger i::after{content:'';position:absolute;left:8px;width:24px;height:2.2px;
  background:#fff;border-radius:2px;transition:.25s}
.burger i{top:19px}.burger i::before{top:-7px;left:0}.burger i::after{top:7px;left:0}
body.nav-open .burger i{background:transparent}
body.nav-open .burger i::before{transform:rotate(45deg);top:0}
body.nav-open .burger i::after{transform:rotate(-45deg);top:0}

/* ---------------------------------------------------------------- hero */
main{padding-top:var(--chrome-h)}
/* FULL-BLEED BAND (client, 2026-08-10). The hero background runs the whole viewport width
   again -- no width cap, no radius, no border, no drop shadow, because none of those read
   as anything once the element touches all four edges. The CONTENT is still capped: every
   hero puts a `.wrap` inside (1200px, 1400px on `.dial-hero`), so nothing here needs to
   constrain it and the copy never goes edge to edge.
   The background is three layers: two soft brand washes in the top corners over a light
   vertical gradient. Keep the washes low-alpha -- `.hero-glow` and `.horbs` paint on top
   of them and the sum is what the eye reads, not any one layer. The washes are placed in
   PERCENTAGES, so they follow the viewport now instead of a 1560px panel.
   `overflow:hidden` still matters: it is what clips the orbs.
   Horizontal padding is a clamp, not a fixed value: `.wrap` already carries 24px, and at
   the narrow end this gutter has to disappear or the copy column starves. */
.hero{position:relative;
  padding:84px clamp(0px,1.4vw,26px) 92px;overflow:hidden;
  background:
    radial-gradient(820px 460px at 8% -12%,rgba(59,130,246,.14),transparent 62%),
    radial-gradient(760px 440px at 96% 4%,rgba(6,182,212,.11),transparent 60%),
    linear-gradient(168deg,#FFFFFF 0%,#F5F8FF 52%,#EDF2FC 100%)}
.hero.short{padding:76px clamp(0px,1.4vw,26px) 60px;text-align:center}
.hero-glow{position:absolute;top:-320px;left:50%;transform:translateX(-50%);width:1100px;height:640px;
  background:radial-gradient(circle at 50% 50%,rgba(59,130,246,.20),rgba(6,182,212,.10) 42%,transparent 70%);
  filter:blur(20px);pointer-events:none}
.hero-grid{position:relative;display:grid;grid-template-columns:1.05fr .95fr;gap:60px;align-items:center}
.center-hero{position:relative;max-width:780px;margin:0 auto}
.center-hero .lede{margin-left:auto;margin-right:auto}
.eyebrow{display:inline-flex;align-items:center;gap:8px;font-size:12.5px;font-weight:700;letter-spacing:.11em;
  text-transform:uppercase;color:var(--brand);margin-bottom:16px}
.eyebrow::before{content:'';width:20px;height:2px;border-radius:2px;background:var(--grad)}
.eyebrow.light{color:#7DD3FC}
.center-hero .eyebrow,.sh.center .eyebrow{justify-content:center}
h1{font-size:clamp(36px,5.2vw,62px);line-height:1.06;margin-bottom:20px;color:var(--ink)}
h1.art{font-size:clamp(30px,4vw,46px)}
.lede{font-size:clamp(16px,1.5vw,18.5px);color:var(--muted);max-width:600px;margin-bottom:30px;line-height:1.7}
.kick{margin-top:18px;font-size:13.5px;color:var(--muted)}
.hero-vis{position:relative}
.crumbs{display:flex;gap:8px;font-size:12.5px;color:var(--muted);margin-bottom:14px;flex-wrap:wrap}
.crumbs a{color:var(--brand)}
.hero.short .crumbs{justify-content:flex-start}

/* ---------------------------------------------------------------- strip */
.strip{background:#fff;border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  padding:14px 0;overflow:hidden}
.strip-track{display:flex;gap:0;width:max-content;animation:strip 40s linear infinite}
.strip span{display:inline-flex;align-items:center;gap:34px;padding:0 17px;color:var(--muted);
  font-size:13.5px;font-weight:600;white-space:nowrap}
.strip span::after{content:'';width:5px;height:5px;border-radius:50%;background:var(--brand-2)}
@keyframes strip{to{transform:translateX(-50%)}}

/* ---------------------------------------------------------------- section heads */
.sh{margin-bottom:54px;max-width:700px}
.sh.center{margin-left:auto;margin-right:auto;text-align:center}
.sh h2{font-size:clamp(28px,3.5vw,44px);line-height:1.12;margin-bottom:14px}
.sh p{color:var(--muted);font-size:17px}
.sec.dark .sh p{color:#8FA0BF}

/* ---------------------------------------------------------------- BENTO */
/* Homepage platform band: a ruled index instead of a bento of cards. Hairlines and
   numbers, no boxes, so it reads as a spec sheet rather than the stock bento grid.
   Inner /platform/ pages keep `.bento` below. */
/* Re-coloured for the LIGHT platform band (client, 2026-08-10). It was white-on-navy;
   every colour here is now an ink/line token. `.sxs` is homepage-only, so there is no
   dark copy of this list left anywhere and the old values did not need keeping. */
.sxs{display:grid;grid-template-columns:1fr 1fr;column-gap:60px}
.sx{display:grid;grid-template-columns:auto auto 1fr;gap:18px;align-items:start;
  padding:22px 4px 22px 0;border-top:1px solid var(--line)}
.sx-n{font-size:11px;font-weight:800;letter-spacing:.16em;color:#A3B0C9;padding-top:9px;
  font-variant-numeric:tabular-nums}
.sx-ic{width:36px;height:36px;border-radius:11px;display:grid;place-items:center;color:var(--brand);
  background:#EEF3FD;border:1px solid #DCE6FA;margin-top:2px;
  transition:background .25s,color .25s,border-color .25s}
.sx:hover .sx-ic{background:var(--grad);border-color:transparent;color:#fff}
.sx h3{font-size:16.5px;color:var(--ink);margin-bottom:5px;letter-spacing:-.02em}
.sx p{font-size:13.5px;line-height:1.62;color:var(--muted)}
@media(max-width:860px){.sxs{grid-template-columns:1fr;column-gap:0}}

.bento{display:grid;grid-template-columns:repeat(4,1fr);grid-auto-rows:minmax(196px,auto);gap:16px}
.bt{background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:26px;
  display:flex;flex-direction:column;box-shadow:var(--sh-1);
  transition:transform .25s cubic-bezier(.2,.8,.3,1),box-shadow .25s,border-color .25s;position:relative;overflow:hidden}
.bt::after{content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  background:radial-gradient(280px circle at var(--mx,50%) var(--my,0%),rgba(59,130,246,.10),transparent 70%);
  opacity:0;transition:opacity .3s}
.bt:hover{transform:translateY(-4px);box-shadow:var(--sh-2);border-color:#C7D8F7}
.bt:hover::after{opacity:1}
.bt.wide{grid-column:span 2}
.bt.tall{grid-row:span 2}
.bt .ic{width:50px;height:50px;border-radius:14px;background:#EEF3FD;display:grid;place-items:center;
  font-size:22px;margin-bottom:auto}
.bt h3{font-size:19px;margin:20px 0 8px;line-height:1.25}
.bt p{font-size:14.5px;color:var(--muted);line-height:1.6}
.bt.wide h3{font-size:21px}
.bt.tall .ic{margin-bottom:0}
.bt.tall h3{margin-top:22px}

/* dark bento variant */
.sec.dark .bt{background:var(--ink-2);border-color:#232C46}
.sec.dark .bt p{color:#8FA0BF}
.sec.dark .bt .ic{background:#1C2540}

/* ---------------------------------------------------------------- feature cards */
.fcards{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.fcard{background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:26px;box-shadow:var(--sh-1);
  transition:transform .25s,box-shadow .25s,border-color .25s}
.fcard:hover{transform:translateY(-4px);box-shadow:var(--sh-2);border-color:#C7D8F7}
.fcard .ic{width:46px;height:46px;border-radius:13px;background:#EEF3FD;display:grid;place-items:center;
  font-size:20px;margin-bottom:16px;color:var(--brand);font-weight:700}
.fcard h3{font-size:16.5px;margin-bottom:7px;line-height:1.3}
.fcard p{font-size:14px;color:var(--muted)}

/* ---------------------------------------------------------------- products */
.prods{display:grid;grid-template-columns:repeat(2,1fr);gap:18px}
.prod{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);padding:32px;
  box-shadow:var(--sh-1);transition:transform .25s,box-shadow .25s,border-color .25s;
  display:flex;flex-direction:column;gap:16px;position:relative;overflow:hidden}
.prod::before{content:'';position:absolute;top:0;left:0;right:0;height:3px;background:var(--grad);
  transform:scaleX(0);transform-origin:left;transition:transform .35s}
.prod:hover{transform:translateY(-5px);box-shadow:var(--sh-2);border-color:#C7D8F7}
.prod:hover::before{transform:scaleX(1)}
.prod .ic{width:54px;height:54px;border-radius:15px;background:var(--grad);color:#fff;display:grid;
  place-items:center;font-size:23px;box-shadow:0 8px 20px -8px rgba(29,78,216,.6)}
.prod h3{font-size:22px;margin-bottom:6px}
.prod p{color:var(--muted);font-size:15px}
.more{display:inline-flex;align-items:center;gap:7px;font-size:14px;font-weight:600;color:var(--brand);margin-top:auto}
.more::after{content:'→';transition:transform .2s}
.prod:hover .more::after,.pc:hover .more::after,.post:hover .more::after{transform:translateX(4px)}
.pcs{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
.pc{background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:26px;box-shadow:var(--sh-1);
  display:flex;flex-direction:column;transition:transform .25s,box-shadow .25s,border-color .25s}
.pc:hover{transform:translateY(-4px);box-shadow:var(--sh-2);border-color:#C7D8F7}
.pc .ic{width:46px;height:46px;border-radius:13px;background:#EEF3FD;display:grid;place-items:center;
  font-size:20px;margin-bottom:16px}
.pc h3{font-size:17.5px;margin-bottom:6px}
.pc p{font-size:14px;color:var(--muted);margin-bottom:16px}

/* ---------------------------------------------------------------- how it works (static grid)
   The pinned horizontal scroller was removed: it hijacked the page scroll. */
/* A timeline, not four cards. The numbered nodes sit on a single rule that runs the width
   of the band, so the four steps read as one sequence instead of four separate boxes. */
.steps{display:grid;grid-template-columns:repeat(4,1fr);gap:30px;position:relative}
.steps::before{content:'';position:absolute;top:18px;left:18px;right:18px;height:1.5px;
  background:linear-gradient(90deg,rgba(125,211,252,.55),rgba(125,211,252,.14));z-index:0}
.step{position:relative;z-index:1;background:none;border:0;border-radius:0;padding:0 18px 0 0}
.step .sn{display:grid;place-items:center;width:37px;height:37px;border-radius:50%;padding:0;
  font-size:12.5px;font-weight:800;letter-spacing:.02em;color:#08121F;
  background:linear-gradient(150deg,#7DD3FC,#38BDF8);border:0;margin-bottom:20px;
  box-shadow:0 0 0 5px rgba(11,16,32,1),0 8px 20px -10px rgba(56,189,248,.9)}
.step .sic{display:inline-grid;place-items:center;width:30px;height:30px;border-radius:9px;
  font-size:15px;color:#93C5FD;background:rgba(255,255,255,.06);
  border:1px solid rgba(255,255,255,.09);box-shadow:none;margin-bottom:13px}
.step h3{font-size:18px;margin-bottom:8px;color:#fff;letter-spacing:-.02em}
.step p{color:#8FA0BF;font-size:14px;line-height:1.62}

.hs-cta{text-align:center;margin-top:44px}

/* ---------------------------------------------------------------- split deep sections */
.split{display:grid;grid-template-columns:1fr 1fr;gap:56px;align-items:center;margin-bottom:80px}
.split:last-child{margin-bottom:0}
.split.rev .sp-copy{order:2}
.sp-copy h3{font-size:clamp(23px,2.5vw,33px);line-height:1.18;margin-bottom:14px}
.sp-copy>p{color:var(--muted);font-size:16.5px;margin-bottom:24px}
.ticks{list-style:none}
.ticks li{position:relative;padding-left:30px;margin-bottom:11px;font-size:15px;color:var(--text)}
.ticks li::before{content:'✓';position:absolute;left:0;top:0;width:20px;height:20px;border-radius:6px;
  background:#DFE9FC;color:var(--brand);font-size:11px;font-weight:800;display:grid;place-items:center}

/* ---------------------------------------------------------------- pains */
.pains{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.pain{background:var(--card);border:1px solid var(--line);border-left:3px solid var(--brand-2);
  border-radius:0 var(--r) var(--r) 0;padding:26px;box-shadow:var(--sh-1)}
.pain b{display:block;font-size:16.5px;margin-bottom:9px;line-height:1.3}
.pain p{font-size:14.5px;color:var(--muted)}

/* ---------------------------------------------------------------- use cases */
.ucs{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-bottom:22px}
.uc{background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:24px;
  box-shadow:var(--sh-1);display:flex;align-items:center;gap:16px;position:relative;overflow:hidden;
  transition:transform .26s cubic-bezier(.2,.8,.3,1),box-shadow .26s,border-color .26s}
.uc::before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--grad);
  transform:scaleY(0);transform-origin:top;transition:transform .3s}
.uc:hover{transform:translateY(-4px);box-shadow:var(--sh-2);border-color:#C7D8F7}
.uc:hover::before{transform:scaleY(1)}
.uc-ic{width:50px;height:50px;border-radius:15px;background:#EEF3FD;display:grid;place-items:center;
  font-size:22px;flex:none;transition:background .26s}
.uc:hover .uc-ic{background:var(--grad)}
.uc-t{flex:1;min-width:0}
.uc-t h3{font-size:17px;margin-bottom:3px;line-height:1.3}
.uc-t p{font-size:13.5px;color:var(--muted);line-height:1.5}
.uc-go{width:32px;height:32px;border-radius:50%;border:1px solid var(--line);display:grid;place-items:center;
  color:var(--muted);flex:none;transition:all .26s}
.uc-go svg{width:14px;height:14px}
.uc:hover .uc-go{background:var(--ink);border-color:var(--ink);color:#fff;transform:translateX(2px)}

.ind-band{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);padding:28px;
  box-shadow:var(--sh-1);display:grid;grid-template-columns:270px 1fr;gap:28px;align-items:center}
.ind-head .mh{padding:0 0 6px}
.ind-head p{font-size:14px;color:var(--muted);line-height:1.6}
.ind-chips{display:flex;flex-wrap:wrap;gap:8px}
.ind-chip{display:inline-flex;align-items:center;gap:8px;padding:9px 16px;border-radius:999px;
  background:var(--page);border:1px solid var(--line);font-size:13.5px;font-weight:600;color:var(--ink);
  transition:all .2s}
.ind-chip span{font-size:15px}
.ind-chip:hover{background:#fff;border-color:var(--brand-3);color:var(--brand);transform:translateY(-2px);
  box-shadow:var(--sh-1)}

/* ---------------------------------------------------------------- stats */
.stats-sec{padding:0 0 104px}
/* One ruled row, not a floating card of four tiles. */
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:0;background:none;
  border-radius:0;padding:0;position:relative;overflow:visible;box-shadow:none;
  border-top:1px solid rgba(255,255,255,.14)}
.stats::before{content:'';position:absolute;top:-60%;left:-10%;width:60%;height:220%;
  background:radial-gradient(circle,rgba(59,130,246,.22),transparent 62%)}
.stats.three{grid-template-columns:repeat(3,1fr);padding:28px 18px;border-radius:var(--r)}
.stats.light{background:#fff;border:1px solid var(--line);box-shadow:var(--sh-2)}
.stats.light::before{display:none}
.stats.light .st b{color:var(--brand)}
.stats.light .st span{color:var(--muted)}
.st{text-align:left;position:relative;padding:32px 30px 4px;
  border-left:1px solid rgba(255,255,255,.10)}
.st:first-child{border-left:0;padding-left:0}
@media(max-width:760px){
  .stats{grid-template-columns:1fr 1fr}
  .st{padding:24px 18px 4px}
  .st:nth-child(3){border-left:0;padding-left:0}
}
.st b{display:block;font-size:clamp(32px,3.8vw,52px);color:#fff;line-height:1.05;letter-spacing:-.045em}
.st span{font-size:13px;color:#8FA0BF;font-weight:500}

/* ---------------------------------------------------------------- testimonials */
.tsts{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.tst{background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:30px;box-shadow:var(--sh-1);
  display:flex;flex-direction:column;gap:16px;transition:transform .25s,box-shadow .25s}
.tst:hover{transform:translateY(-4px);box-shadow:var(--sh-2)}
.tst .ic{width:44px;height:44px;border-radius:13px;background:#EEF3FD;display:grid;place-items:center;font-size:19px}
.tst blockquote{font-size:16px;color:var(--ink);line-height:1.6;font-weight:500}
.tst figcaption{margin-top:auto}
.tst figcaption b{display:block;font-size:14.5px}
.tst figcaption span{font-size:13px;color:var(--muted)}

/* ---------------------------------------------------------------- FAQ */
.fqs{display:flex;flex-direction:column;gap:10px}
.fq{background:var(--page);border:1px solid var(--line);border-radius:14px;overflow:hidden;transition:border-color .2s}
.sec.light .fq{background:var(--page)}
.fq[open]{border-color:#C7D8F7;background:#fff;box-shadow:var(--sh-1)}
.fq summary{list-style:none;cursor:pointer;padding:20px 24px;font-weight:600;font-size:16px;color:var(--ink);
  display:flex;align-items:center;justify-content:space-between;gap:16px}
.fq summary::-webkit-details-marker{display:none}
.fq summary i{width:11px;height:11px;flex:none;position:relative}
.fq summary i::before,.fq summary i::after{content:'';position:absolute;background:var(--brand);border-radius:2px;
  transition:transform .25s}
.fq summary i::before{top:4px;left:0;width:11px;height:2px}
.fq summary i::after{left:4.5px;top:0;width:2px;height:11px}
.fq[open] summary i::after{transform:scaleY(0)}
.fa{padding:0 24px 20px}
.fa p{color:var(--muted);font-size:15px;line-height:1.7}


/* ---------------------------------------------------------------- CTA (dark) */
.cta-sec{padding-bottom:104px}
.cta-card{position:relative;background:radial-gradient(900px 460px at 50% -20%,#1B2A5E,transparent 62%),
  linear-gradient(160deg,#0D1428,#080D1C 60%,#0B1224);
  border:1px solid #222E52;border-radius:34px;padding:76px 56px;text-align:center;overflow:hidden;
  box-shadow:0 44px 100px -34px rgba(0,0,0,.75)}
.cta-inner{position:relative;z-index:2}
.cta-card h2{color:#fff;font-size:clamp(28px,3.6vw,46px);line-height:1.12;margin-bottom:15px;
  letter-spacing:-.035em}
.cta-card p{color:#93A3C4;max-width:600px;margin:0 auto 32px;font-size:16px;line-height:1.7}
.cta-card .eyebrow{justify-content:center;display:inline-flex}
.cta-grid-bg{position:absolute;inset:0;z-index:0;opacity:.5;
  background-image:linear-gradient(rgba(255,255,255,.05) 1px,transparent 1px),
    linear-gradient(90deg,rgba(255,255,255,.05) 1px,transparent 1px);
  background-size:56px 56px;
  -webkit-mask-image:radial-gradient(ellipse 70% 65% at 50% 45%,#000 30%,transparent 78%);
  mask-image:radial-gradient(ellipse 70% 65% at 50% 45%,#000 30%,transparent 78%)}
.cta-orbs i{position:absolute;border-radius:50%;z-index:1;filter:blur(50px)}
.cta-orbs i:first-child{width:420px;height:420px;top:-190px;right:-80px;
  background:rgba(37,99,235,.42);animation:drift 14s ease-in-out infinite}
.cta-orbs i:last-child{width:340px;height:340px;bottom:-170px;left:-60px;
  background:rgba(6,182,212,.30);animation:drift 18s ease-in-out infinite reverse}
@keyframes drift{50%{transform:translate(28px,22px) scale(1.1)}}
.cta-trust{display:flex;flex-wrap:wrap;justify-content:center;gap:10px 26px;margin-top:34px;
  padding-top:26px;border-top:1px solid rgba(255,255,255,.08)}
.cta-trust span{font-size:13px;color:#8394B8;font-weight:500}

/* ---------------------------------------------------------------- panels (product UI mocks) */
.panel{background:#fff;border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;
  box-shadow:var(--sh-3);transition:transform .4s cubic-bezier(.2,.8,.3,1)}
/* A product bar with one live dot and a label, not a fake browser title bar */
.panel-bar{display:flex;align-items:center;gap:9px;padding:13px 17px;background:#F8FAFD;
  border-bottom:1px solid var(--line-2)}
.panel-bar i{width:7px;height:7px;border-radius:50%;background:#22C55E;flex:none;
  box-shadow:0 0 0 3px rgba(34,197,94,.15)}
.panel-bar span{font-size:11px;color:var(--muted);font-weight:700;letter-spacing:.12em;
  text-transform:uppercase}

/* ---- the caption strip (client, 2026-08-10: make the feature panels explain themselves
   the way the hero console does). Sits under the app, and its text is rewritten by the
   panel's animator on every beat, so it always names what is on screen right now.
   Only panels WITH an animator carry one -- see _frame(). */
.panel-cap{display:flex;align-items:center;gap:11px;padding:13px 17px;
  background:#F8FAFD;border-top:1px solid var(--line-2)}
.pc-d{width:8px;height:8px;flex:none;border-radius:50%;background:var(--brand);
  box-shadow:0 0 0 3px rgba(29,78,216,.14);animation:blink 1.9s infinite}
.pc-t{min-width:0}
/* the value is re-stated rather than inherited: on the dark panels below, `.sec.dark b`
   and the global ink rule both reach in here, and this is the one place both are wrong */
.pc-t b{display:block;font-size:13px;color:var(--ink);letter-spacing:-.01em;line-height:1.3}
.pc-t span{display:block;font-size:11.5px;color:var(--muted);line-height:1.4;margin-top:1px}
/* dark panels: the strip follows the panel, not the page */
.panel.dark .panel-cap{background:rgba(255,255,255,.04);border-top-color:rgba(255,255,255,.08)}
.panel.dark .pc-t b{color:#fff}
.panel.dark .pc-t span{color:#8FA0BF}
.panel.dark .pc-d{background:var(--brand-3);box-shadow:0 0 0 3px rgba(96,165,250,.18)}
.panel-body{padding:20px}
.panel-body.pt0{padding-top:0}
.prow{display:flex;justify-content:space-between;align-items:center;margin-bottom:14px}
.prow b{font-size:14.5px}
.tag{font-size:11px;font-weight:700;padding:4px 10px;border-radius:100px;background:#EEF3FD;color:var(--brand)}
.tag.live{background:#DCFCE7;color:#15803D}
.tag.live::before{content:'●';margin-right:5px;font-size:7px;vertical-align:middle;animation:blink 1.6s infinite}
@keyframes blink{50%{opacity:.3}}
.bars{display:flex;align-items:flex-end;gap:5px;height:72px;margin-bottom:16px}
.bars i{flex:1;background:linear-gradient(180deg,#60A5FA,#1D4ED8);border-radius:4px 4px 0 0;
  transform-origin:bottom;animation:grow 1s cubic-bezier(.2,.8,.3,1) both}
@keyframes grow{from{transform:scaleY(0)}}
.pmet{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:16px}
.pmet div{background:#F8FAFD;border:1px solid var(--line-2);border-radius:12px;padding:12px;text-align:center}
.pmet b{display:block;font-size:18px;color:var(--ink);letter-spacing:-.03em}
.pmet span{font-size:11px;color:var(--muted)}
.pmet.four{grid-template-columns:repeat(4,1fr);gap:8px}
.pmet.four div{padding:10px 5px}
.pmet.four b{font-size:16px}
.pmet.four span{font-size:9.5px}

/* live monitor: Listen / Whisper / Barge as real icon buttons beside a call, not a single
   tag standing in for all three (client, 2026-08-17, from their own product screenshot). */
.lm-acts{display:flex;gap:5px;flex:none}
.lm-act{width:25px;height:25px;border-radius:8px;display:grid;place-items:center;
  background:var(--line-2);color:var(--muted);transition:background .3s,color .3s,transform .3s,box-shadow .3s}
.lm-act .ic-svg{width:12px;height:12px}
.lm-act.is-on{background:var(--brand);color:#fff;transform:scale(1.14);
  box-shadow:0 0 0 4px rgba(29,78,216,.18)}
.panel.dark .lm-act{background:#1B2646;color:#8093B8}
.panel.dark .lm-act.is-on{background:var(--brand-2);box-shadow:0 0 0 4px rgba(59,130,246,.22)}
.prow2{display:flex;align-items:center;gap:12px;padding:11px;border:1px solid var(--line-2);border-radius:13px;margin-bottom:9px}
.prow2:last-child{margin-bottom:0}
.prow2 b{display:block;font-size:13.5px}
.prow2 small{font-size:11.5px;color:var(--muted)}
.prow2>div:nth-child(2){flex:1;min-width:0}
.av{width:36px;height:36px;border-radius:11px;background:var(--brand);color:#fff;font-size:11.5px;font-weight:700;
  display:grid;place-items:center;flex:none}
.av.g{background:var(--grad)}
.wave{display:flex;gap:3px;align-items:center}
.wave i{width:3px;border-radius:3px;background:var(--brand-2);animation:wv 1s ease-in-out infinite}
.wave i:nth-child(1){height:8px}.wave i:nth-child(2){height:16px;animation-delay:.1s}
.wave i:nth-child(3){height:22px;animation-delay:.2s}.wave i:nth-child(4){height:13px;animation-delay:.3s}
.wave i:nth-child(5){height:18px;animation-delay:.4s}
.wave.w i{background:#fff}
@keyframes wv{50%{transform:scaleY(.4)}}
.prog{height:8px;background:#EEF2F8;border-radius:100px;overflow:hidden;margin-bottom:16px}
.prog i{display:block;height:100%;background:var(--grad);border-radius:100px}
@keyframes float{50%{transform:translateY(-7px)}}
.flow{padding:26px 20px;display:flex;flex-direction:column;align-items:center}
.fn{background:#F8FAFD;border:1px solid var(--line);padding:11px 18px;border-radius:12px;font-size:13px;
  font-weight:600;color:var(--ink);transition:border-color .2s,transform .2s}
.fn:hover{border-color:var(--brand-2);transform:translateY(-2px)}
.fn.blue{background:#EEF3FD;border-color:#C7D8F7;color:var(--brand)}
.fn.green{background:#F0FDF4;border-color:#BBF7D0;color:#15803D}
.fn.amber{background:#FFFBEB;border-color:#FDE68A;color:#B45309}
.fl{width:2px;height:20px;background:linear-gradient(180deg,var(--brand-2),#C7D8F7);position:relative;overflow:hidden}
.fl::after{content:'';position:absolute;left:-1px;width:4px;height:8px;border-radius:3px;background:var(--brand);
  animation:drop 1.8s linear infinite}
@keyframes drop{from{top:-8px}to{top:20px}}
.fbr{display:flex;gap:9px;flex-wrap:wrap;justify-content:center;margin-top:4px}
.fdots{display:flex;gap:5px;margin-top:16px}
.fdots i{width:6px;height:6px;border-radius:50%;background:#C7D8F7;animation:blink 1.6s infinite}
.fdots i:nth-child(2){animation-delay:.25s}.fdots i:nth-child(3){animation-delay:.5s}

/* heatmap + equaliser visuals */
.heat{display:flex;flex-direction:column;gap:4px;margin-bottom:8px}
.hrow{display:grid;grid-template-columns:repeat(12,1fr);gap:4px}
.hrow i{aspect-ratio:1;border-radius:4px;background:#EEF2F8;transition:transform .18s}
.hrow i:hover{transform:scale(1.25)}
.heat-ax{display:flex;justify-content:space-between;font-size:10.5px;color:var(--muted);margin-bottom:16px}
.eq{display:flex;align-items:flex-end;gap:3px;height:74px;margin-bottom:16px}
.eq i{flex:1;border-radius:3px;background:linear-gradient(180deg,#60A5FA,#1D4ED8);height:30%;
  transform-origin:bottom;animation:eqb 1.4s ease-in-out infinite}
@keyframes eqb{0%,100%{transform:scaleY(.35)}50%{transform:scaleY(1)}}

/* pbx: the hero console's own "incoming call" card (`.cin` in the hero section below),
   replayed at panel scale. `.pbx-cin` mirrors `.cin`'s concrete styling rather than
   sharing its `--cl/--ct/--cm` variables, because those are scoped to `.cine-body` and
   this card sits inside `.panel`/`.panel.dark` instead. Deliberately styled the SAME
   (a white card) whether the outer `.panel` is light or dark: on the light panel it gets
   depth from its own shadow, on the dark panel it pops the way the hero's card does
   against `.cine`'s dark shell. Two acts cross-fade in a fixed-height stage, exactly like
   the hero's acts do, instead of the panel ever changing height. */
.pbx-stage{position:relative;height:210px}
.pbx-cin{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;
  justify-content:center;text-align:center;gap:5px;padding:20px;border-radius:20px;
  background:linear-gradient(170deg,#FFFFFF,#F4F8FE);border:1px solid var(--line-2);
  box-shadow:0 2px 3px rgba(14,26,51,.04),0 18px 34px -16px rgba(14,26,51,.22);
  opacity:0;transform:translateY(10px) scale(.98);
  transition:opacity .45s ease,transform .45s cubic-bezier(.2,.8,.3,1);pointer-events:none}
.pbx-cin.is-active{opacity:1;transform:none;pointer-events:auto}
.pbx-cin-eb{display:inline-flex;align-items:center;gap:6px;padding:5px 12px;border-radius:999px;
  font-size:10.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--brand);background:#E8F0FE;border:1px solid #CFE0FB;margin-bottom:4px}
.pbx-cin-eb .ic-svg{width:11px;height:11px}
.pbx-cin-eb.ok{color:#0E9C6C;background:#E7FAF1;border-color:#BEEBD3}
.pbx-cin-av{position:relative;display:grid;place-items:center;width:58px;height:58px;
  border-radius:50%;color:#fff;font-size:22px;margin-bottom:2px;
  background:linear-gradient(150deg,var(--brand-2),var(--brand-deep));
  box-shadow:0 8px 22px -7px rgba(29,78,216,.7)}
.pbx-cin-av .ic-svg{width:24px;height:24px}
.pbx-cin-av.is-live{background:linear-gradient(150deg,#22C55E,#15803D);
  box-shadow:0 8px 22px -7px rgba(34,197,94,.65)}
.pbx-cin-pulse{position:absolute;inset:0;border-radius:50%;border:2px solid var(--brand-2);
  animation:pbxcring 1.6s ease-out infinite}
@keyframes pbxcring{0%{transform:scale(1);opacity:.85}100%{transform:scale(1.75);opacity:0}}
.pbx-cin-num{font-size:19px;font-weight:700;letter-spacing:.01em;color:var(--ink);
  font-variant-numeric:tabular-nums}
.pbx-cin b{font-size:18px;letter-spacing:-.01em;color:var(--ink)}
.pbx-cin small{font-size:12.5px;color:var(--muted)}
.pbx-dots{display:flex;justify-content:center;gap:6px;margin-top:14px}
.pbx-dot{width:6px;height:6px;border-radius:50%;background:var(--line-2);transition:background .3s,transform .3s}
.pbx-dot.is-on{background:var(--brand);transform:scale(1.2)}
.panel.dark .pbx-dot{background:#263258}

/* ---------------------------------------------------------------- dark panel variant
   Same markup, inverted surface. Used so the site mixes dark and light product
   imagery instead of every screenshot being white. */
.panel.dark{background:#0F1730;border-color:#263258;
  box-shadow:0 34px 70px -28px rgba(0,0,0,.62),0 0 0 1px rgba(255,255,255,.04)}
.panel.dark .panel-bar{background:#141D3A;border-bottom-color:#263258}
.panel.dark .panel-bar i{background:#22C55E;box-shadow:0 0 0 3px rgba(34,197,94,.18)}
.panel.dark .panel-bar span{color:#8FA0BF}
.panel.dark .prow b,.panel.dark .prow2 b,.panel.dark .pmet b{color:#fff}
.panel.dark .prow2{border-color:#263258;background:rgba(255,255,255,.03)}
.panel.dark .prow2 small{color:#8093B8}
.panel.dark .pmet div{background:rgba(255,255,255,.04);border-color:#263258}
.panel.dark .pmet span{color:#8093B8}
.panel.dark .tag{background:#1B2646;color:#93C5FD}
.panel.dark .tag.live{background:rgba(34,197,94,.14);color:#4ADE80}
.panel.dark .av{background:#1D4ED8}
.panel.dark .prog{background:#1B2646}
.panel.dark .hrow i{background:#18224A}
.panel.dark .heat-ax{color:#8093B8}
.panel.dark .fn{background:#141D3A;border-color:#263258;color:#DCE4F5}
.panel.dark .fn.blue{background:rgba(37,99,235,.18);border-color:#3B5488;color:#93C5FD}
.panel.dark .fn.green{background:rgba(34,197,94,.14);border-color:#2F6B48;color:#4ADE80}
.panel.dark .fn.amber{background:rgba(245,158,11,.14);border-color:#7A5A22;color:#FCD34D}
.panel.dark i.h0{background:#151F42}.panel.dark i.h1{background:#1B2A55}
.panel.dark i.h2{background:#20356B}.panel.dark i.h3{background:#254080}
.panel.dark i.h4{background:#2A4B96}.panel.dark i.h5{background:#2F56AB}
.panel.dark i.h6{background:#3462C1}.panel.dark i.h7{background:#3B72D6}
.panel.dark i.h8{background:#4A85E4}.panel.dark i.h9{background:#5E97EE}
.panel.dark i.h10{background:#7DB0F7}

/* ---------------------------------------------------------------- pricing */
.plans{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;align-items:stretch;margin-top:8px}
.plan{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);padding:36px 30px;
  box-shadow:var(--sh-1);display:flex;flex-direction:column;position:relative;transition:transform .25s,box-shadow .25s}
.plan:hover{transform:translateY(-5px);box-shadow:var(--sh-2)}
.plan.feat{border:2px solid var(--brand-2);box-shadow:0 26px 60px -24px rgba(29,78,216,.4)}
.pop{position:absolute;top:-13px;left:50%;transform:translateX(-50%);background:var(--grad);color:#fff;
  font-size:11.5px;font-weight:700;padding:6px 16px;border-radius:100px;box-shadow:0 8px 18px -7px rgba(29,78,216,.6)}
.tier{font-size:13px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--brand);margin-bottom:10px}
.amt{font-size:34px;font-weight:800;color:var(--ink);letter-spacing:-.04em;margin-bottom:12px}
.amt small{font-size:14px;color:var(--muted);font-weight:500;margin-left:5px}
.plan>p{font-size:14px;color:var(--muted);margin-bottom:22px}
.plan .ticks{flex:1;margin-bottom:24px}
.tbl-wrap{overflow-x:auto;border:1px solid var(--line);border-radius:var(--r);background:#fff}
.cmp{width:100%;border-collapse:collapse;min-width:640px}
.cmp th,.cmp td{padding:15px 18px;text-align:left;font-size:14.5px;border-bottom:1px solid var(--line-2)}
.cmp th{background:#F8FAFD;font-size:13px;font-weight:700;color:var(--ink)}
.cmp th.hi,.cmp td.hi{background:#F2F6FE}
.cmp tbody tr:last-child td{border-bottom:0}
.cmp td:not(:first-child){text-align:center;color:var(--muted);font-weight:600}
.cmp td:first-child{color:var(--text)}
.note{font-size:13.5px;color:var(--muted);margin-top:22px}
.note.center{text-align:center}

/* ---------------------------------------------------------------- case studies */
.cs{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);padding:36px;
  box-shadow:var(--sh-1);margin-bottom:20px}
.cs-head{display:flex;align-items:center;gap:14px;margin-bottom:22px}
.cs-head .ic{width:52px;height:52px;border-radius:15px;background:#EEF3FD;display:grid;place-items:center;font-size:22px}
.cs-head h3{font-size:20px;margin-top:7px}
.cs-body{display:grid;grid-template-columns:1fr 1fr;gap:28px;margin-bottom:26px}
.cs-body p{font-size:14.5px;color:var(--muted)}
/* index cards are LINKS into the per-story page now (client, 2026-08-10). `.cs` is still
   the same card; `.csx` only adds the affordances a link needs. */
.csx{display:block;transition:transform .25s,box-shadow .25s,border-color .25s}
.csx:hover{transform:translateY(-3px);box-shadow:var(--sh-2);border-color:#C7D8F7}
.csx-go{display:inline-flex;align-items:center;gap:7px;margin-top:22px;font-size:13.5px;
  font-weight:700;color:var(--brand)}
.csx-go .ba{width:14px;height:14px;transition:transform .2s}
.csx:hover .csx-go .ba{transform:translateX(3px)}

/* ------------------------------------------------------- a single case study's own page
   case-studies/<slug>.html (client, 2026-08-10). Two columns: the written story on the
   left, a sticky sidebar carrying what they switched on and the customer's quote. */
/* `.hero.short` is text-align:center for every other inner page; this hero is a two-column
   split, so the copy column has to opt back out or the heading and lede centre inside it
   while the crumbs (which have their own override) stay left. */
.csh{text-align:left}
.csh-grid{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:38px;align-items:center}
.csh-copy .eyebrow{display:inline-flex;align-items:center;gap:7px}
.csh-copy .eyebrow .ic-svg{width:15px;height:15px}
.csh-copy h1{font-size:clamp(28px,3.6vw,46px);line-height:1.1;margin:10px 0 0}
.csh-big{flex:none;text-align:center;padding:26px 34px;border-radius:var(--r-lg);
  background:linear-gradient(160deg,#fff,#F1F6FF);border:1px solid var(--line);
  box-shadow:var(--sh-2)}
.csh-big b{display:block;font-size:clamp(38px,4.4vw,56px);line-height:1;font-weight:800;
  letter-spacing:-.05em;color:var(--brand)}
.csh-big span{display:block;margin-top:8px;font-size:12.5px;font-weight:600;color:var(--muted);
  max-width:16ch}
.csd{display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:44px;margin-top:44px;
  align-items:start}
.csd-main .eyebrow{display:block;margin:32px 0 10px}
.csd-main .eyebrow:first-child{margin-top:0}
.csd-lead{font-size:16.5px;line-height:1.7;color:var(--ink);font-weight:500}
.csd-main>p{font-size:15.5px;line-height:1.78;color:var(--text);margin-bottom:16px}
.csd-main>p:last-child{margin-bottom:0}
/* sticky, so the quote and the feature list stay with the reader down a long story. `top`
   is --chrome-h, not --nav-h: --nav-h is only the bar, and the contact strip sits above it. */
.csd-side{position:sticky;top:calc(var(--chrome-h) + 20px);display:flex;flex-direction:column;gap:18px}
.csd-card{background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  padding:24px;box-shadow:var(--sh-1)}
.csd-card b{display:block;font-size:15px;margin-bottom:14px}
.csd-stack{list-style:none;display:flex;flex-direction:column;gap:10px}
.csd-stack li{display:flex;align-items:center;gap:10px;font-size:13.5px;color:var(--text)}
/* border-box is site-wide, so the padded tick's WIDTH is the whole disc -- sizing it the
   other way round collapses the content box and the glyph vanishes */
.csd-stack .ic-svg{width:20px;height:20px;padding:4px;border-radius:50%;flex:none;
  background:#E9F9F2;color:var(--ok)}
.csd-q{padding:24px;border-radius:var(--r);color:#fff;
  background:linear-gradient(160deg,var(--brand),var(--brand-deep));
  box-shadow:0 20px 44px -22px rgba(29,78,216,.6)}
.csd-q blockquote{font-size:14.5px;line-height:1.65;font-weight:500;margin-bottom:18px}
/* same `>div>` scoping as the reviews caption, and for the same reason -- see there */
.csd-q figcaption{display:flex;align-items:center;gap:11px}
.csd-q figcaption>div>b{display:block;font-size:13.5px;color:#fff}
.csd-q figcaption>div>span{display:block;font-size:12px;color:#C7DAFB;line-height:1.4}
.csd-q .pav{background:rgba(255,255,255,.18);color:#fff}
/* the other three at the foot of the page */
.csms{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
/* flex column so the "Read it" links sit on one line across all three cards -- the teasers
   are different lengths and in flow the link lands wherever the copy ends */
.csm{display:flex;flex-direction:column;background:var(--card);border:1px solid var(--line);
  border-radius:var(--r);padding:26px;
  box-shadow:var(--sh-1);transition:transform .25s,box-shadow .25s,border-color .25s}
.csm:hover{transform:translateY(-4px);box-shadow:var(--sh-2);border-color:#C7D8F7}
.csm-ic{width:44px;height:44px;border-radius:13px;background:#EEF3FD;color:var(--brand);
  display:grid;place-items:center;margin-bottom:16px}
.csm-ic .ic-svg{width:21px;height:21px}
.csm-tag{display:block;font-size:10.5px;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:var(--brand);margin-bottom:6px}
.csm h3{font-size:16.5px;margin-bottom:7px;letter-spacing:-.02em}
.csm p{font-size:13.5px;line-height:1.6;color:var(--muted)}
.csm-go{display:inline-flex;align-items:center;align-self:flex-start;gap:7px;
  margin-top:auto;padding-top:16px;font-size:13px;font-weight:700;color:var(--brand)}
.csm-go .ba{width:14px;height:14px;transition:transform .2s}
.csm:hover .csm-go .ba{transform:translateX(3px)}
@media(max-width:900px){
  .csh-grid{grid-template-columns:minmax(0,1fr);gap:24px}
  .csh-big{align-self:start;padding:20px 26px}
  /* the sidebar un-sticks when it stacks: sticky on a full-width block below the story
     pins it to the viewport for the rest of the page */
  .csd{grid-template-columns:minmax(0,1fr);gap:32px;margin-top:32px}
  .csd-side{position:static}
  .csms{grid-template-columns:1fr}
}

/* ---------------------------------------------------------------- contact */
.cgrid{display:grid;grid-template-columns:.9fr 1.1fr;gap:52px;align-items:start}
.citem{display:flex;gap:15px;align-items:center;padding:18px 0;border-bottom:1px solid var(--line)}
.citem.last{border-bottom:0}
.citem .ic{width:44px;height:44px;border-radius:13px;background:#EEF3FD;display:grid;place-items:center;font-size:18px;flex:none}
.citem b{display:block;font-size:14.5px;margin-bottom:2px}
.citem a{color:var(--brand);font-weight:600;font-size:15px}
.citem a:hover{text-decoration:underline}
.citem .pl{font-size:14px;color:var(--muted)}
.form{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);padding:36px;box-shadow:var(--sh-2)}
.form h3{font-size:23px;margin-bottom:24px}
.frow{display:grid;grid-template-columns:1fr 1fr;gap:15px;margin-bottom:15px}
.form label{display:block;font-size:12.5px;font-weight:600;color:var(--ink);margin-bottom:7px}
.form input,.form select,.form textarea{width:100%;padding:12px 15px;border:1.5px solid var(--line);
  border-radius:11px;font:inherit;font-size:14.5px;color:var(--ink);background:#F8FAFD;outline:none;
  transition:border-color .15s,box-shadow .15s,background .15s}
.form input:focus,.form select:focus,.form textarea:focus{border-color:var(--brand-2);background:#fff;
  box-shadow:0 0 0 4px rgba(29,78,216,.1)}
.form textarea{min-height:108px;resize:vertical;margin-bottom:20px}
.form .btn{width:100%}

/* ---------------------------------------------------------------- blog */
.posts{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.post{background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:28px;box-shadow:var(--sh-1);
  display:flex;flex-direction:column;gap:12px;transition:transform .25s,box-shadow .25s,border-color .25s}
.post:hover{transform:translateY(-4px);box-shadow:var(--sh-2);border-color:#C7D8F7}
.post .tag{align-self:flex-start}
.post h3{font-size:18.5px;line-height:1.3}
.post p{font-size:14px;color:var(--muted)}
.article p{font-size:17px;line-height:1.85;color:var(--text);margin-bottom:22px}
.hero.short .tag{display:inline-block;margin-bottom:16px}

/* ---------------------------------------------------------------- footer */
footer{background:var(--ink);color:#8FA0BF;padding:72px 0 32px}
.f-top{display:grid;grid-template-columns:1.4fr 3fr;gap:48px;margin-bottom:46px}
.f-brand .logo{margin-bottom:16px}
.f-brand p{font-size:13.5px;line-height:1.7;margin-bottom:20px;max-width:330px}
.socials{display:flex;gap:9px}
.socials a{width:36px;height:36px;border-radius:11px;background:#1A2440;display:grid;place-items:center;
  font-weight:700;font-size:14px;color:#B4C1D8;transition:background .2s,transform .2s,color .2s}
.socials a:hover{background:var(--brand);color:#fff;transform:translateY(-3px)}
.f-cols{display:grid;grid-template-columns:repeat(5,1fr);gap:26px}
.f-col b{display:block;color:#fff;font-size:14px;margin-bottom:14px}
.f-col a{display:block;font-size:13px;padding:4px 0;transition:color .15s}
.f-col a:hover{color:#fff}
.f-bottom{border-top:1px solid #1A2440;padding-top:24px;display:flex;justify-content:space-between;
  gap:14px;flex-wrap:wrap;font-size:12.5px}
.f-bottom a{color:#B4C1D8}
.f-bottom a:hover{color:#fff}
.wa-float{position:fixed;right:20px;bottom:20px;width:54px;height:54px;border-radius:50%;background:#25D366;
  display:grid;place-items:center;z-index:150;box-shadow:0 5px 0 rgba(18,140,75,.35),0 14px 30px -8px rgba(37,211,102,.6);
  transition:transform .2s}
.wa-float:hover{transform:translateY(-4px) scale(1.05)}
.wa-float:active{transform:translateY(2px)}
.wa-float svg{width:29px;height:29px;fill:#fff}

/* ---------------------------------------------------------------- case studies (homepage)
   ONE FEATURED STORY beside a stack of the other three, and every card links to that
   story's own page (client, 2026-08-10). This replaced four equal "the number leads"
   columns, which gave the eye nowhere to land and read as the same block as the reviews
   band directly below. That band is now a light even wall, so the two are asymmetric-dark
   and even-light and cannot be confused. Keep them different if either is retouched. */
.csgrid{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,1fr);gap:22px}

/* the featured story */
.csf{display:flex;flex-direction:column;padding:32px;border-radius:var(--r-lg);
  background:linear-gradient(160deg,rgba(59,130,246,.16),rgba(6,182,212,.05));
  border:1px solid #2B3A66;transition:border-color .25s,transform .25s,box-shadow .25s}
.csf:hover{border-color:#3F5488;transform:translateY(-3px);
  box-shadow:0 26px 54px -30px rgba(0,0,0,.9)}
.csf-tag{display:inline-flex;align-items:center;gap:7px;font-size:10.5px;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:#7DD3FC}
.csf-tag .ic-svg{width:14px;height:14px}
.csf-big{margin:20px 0 4px}
.csf-big b{display:block;font-size:clamp(46px,5vw,68px);line-height:1;font-weight:800;
  letter-spacing:-.05em;background:linear-gradient(120deg,#fff 40%,#7DD3FC);
  -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
.csf-big span{display:block;margin-top:6px;font-size:13px;font-weight:600;color:#8FA0BF}
.csf h3{font-size:20px;color:#fff;margin:16px 0 8px;letter-spacing:-.02em}
.csf p{font-size:14px;line-height:1.62;color:#9DB0D0}
.csf-mets{display:flex;flex-wrap:wrap;gap:22px;margin:20px 0 0;padding-top:18px;
  border-top:1px solid rgba(255,255,255,.11)}
.csf-m b{display:block;font-size:19px;color:#fff;letter-spacing:-.02em}
.csf-m span{display:block;font-size:11.5px;color:#8093B8;margin-top:2px}
.csf-go{display:inline-flex;align-items:center;gap:7px;margin-top:22px;font-size:13.5px;
  font-weight:700;color:#7DD3FC}
.csf-go .ba{width:14px;height:14px;transition:transform .2s}
.csf:hover .csf-go .ba{transform:translateX(3px)}

/* the three that follow it */
.csrows{display:flex;flex-direction:column;gap:12px}
.csr{flex:1;display:grid;grid-template-columns:auto minmax(0,1fr) auto auto;gap:16px;
  align-items:center;padding:20px 22px;border-radius:var(--r);
  background:rgba(255,255,255,.035);border:1px solid #26315A;
  transition:background .25s,border-color .25s,transform .25s}
.csr:hover{background:rgba(59,130,246,.09);border-color:#3B5488;transform:translateX(3px)}
.csr-ic{width:42px;height:42px;flex:none;border-radius:12px;display:grid;place-items:center;
  background:#18224A;color:#7DD3FC}
.csr-ic .ic-svg{width:20px;height:20px}
.csr-tag{display:block;font-size:10.5px;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:#7DD3FC;margin-bottom:4px}
.csr-t h3{font-size:15.5px;color:#fff;letter-spacing:-.02em;margin-bottom:3px}
.csr-t p{font-size:12.5px;line-height:1.5;color:#8FA0BF}
.csr-n{text-align:right;flex:none}
.csr-n b{display:block;font-size:22px;color:#fff;letter-spacing:-.03em;line-height:1.1}
/* 14ch, not 11: at 11 the longest label ("Missed appointment calls") broke to three lines
   and the row went visibly taller than its two neighbours. */
.csr-n span{display:block;font-size:10.5px;color:#8093B8;margin-top:3px;max-width:14ch}
.csr-go{flex:none;color:#7DD3FC}
.csr-go .ba{width:15px;height:15px;transition:transform .2s}
.csr:hover .csr-go .ba{transform:translateX(3px)}
@media(max-width:980px){
  .csgrid{grid-template-columns:minmax(0,1fr)}
  /* the number column is the first thing to go: the story and its headline metric still
     read, and at this width four columns squeeze the title to two words a line */
  .csr{grid-template-columns:auto minmax(0,1fr) auto}
  .csr-n{display:none}
}
@media(max-width:560px){
  .csf{padding:24px}
  .csr{padding:16px 17px;gap:13px}
  .csr-ic{width:36px;height:36px}
}

/* ---------------------------------------------------------------- reviews (the wall)
   Every quote on screen at once, with the rating summary as the first card in the flow
   (client, 2026-08-10). It was ONE quote at a time cross-fading in a fixed-height stage,
   which read as thin beside a case studies band showing four stories -- and both were
   centred card blocks, so the page had two sections that looked alike. This one is light,
   dense and even; the case studies band above is dark and asymmetric.

   MULTI-COLUMN, NOT GRID. The quotes are different lengths: columns flow them into a
   masonry with no gaps, where a row-based grid leaves every row as tall as its longest
   card. The price is that reading order runs DOWN each column rather than across, which is
   correct for an unordered wall of quotes and would not be for anything sequential.
   `break-inside:avoid` is what stops a quote being split across a column boundary --
   without it a card can start in one column and finish in the next. */
.rvwall{columns:3;column-gap:20px}
.rvwall>*{break-inside:avoid;-webkit-column-break-inside:avoid;margin:0 0 20px}
/* the summary card. It is the first item in the flow rather than a header above the wall,
   so column 1 starts with the rating and the wall stays one object. */
.rvsum{padding:26px 24px;border-radius:var(--r);color:#fff;
  background:linear-gradient(160deg,var(--brand),var(--brand-deep));
  box-shadow:0 20px 44px -22px rgba(29,78,216,.65)}
.rvsum-n{display:block;font-size:52px;line-height:1;font-weight:800;letter-spacing:-.04em;color:#fff}
.rvsum-s{display:flex;gap:3px;margin:10px 0 8px}
.rvsum-s i{font-style:normal;font-size:15px;line-height:1;color:#FFD27A}
.rvsum-l{display:block;font-size:13px;color:#C7DAFB;line-height:1.5}
.rvsum-m{display:flex;gap:26px;margin-top:18px;padding-top:16px;
  border-top:1px solid rgba(255,255,255,.22)}
.rvsum-m b{display:block;font-size:20px;color:#fff;letter-spacing:-.02em}
.rvsum-m span{display:block;font-size:11.5px;color:#C7DAFB;margin-top:1px}
/* the quote cards */
.rvc{padding:24px 22px;border-radius:var(--r);background:var(--card);
  border:1px solid var(--line);box-shadow:var(--sh-1);
  transition:transform .25s,box-shadow .25s,border-color .25s}
.rvc:hover{transform:translateY(-3px);box-shadow:var(--sh-2);border-color:#C7D8F7}
.rvc-s{display:flex;gap:3px;margin-bottom:12px}
.rvc-s i{font-style:normal;font-size:14px;line-height:1;color:#D8E0EE}
.rvc-s i.on{color:#F5A524}
.rvc blockquote{font-size:14.5px;line-height:1.62;color:var(--ink);font-weight:500;
  letter-spacing:-.01em;margin-bottom:18px}
/* `>div>span`, NOT `figcaption span`. `.pav` is a span and a DIRECT child of figcaption,
   so a bare descendant selector here is (0,1,2) and beats `.pav` (0,1,0) -- it was
   overriding display:grid with display:block, which killed place-items:center and left
   the initials sitting at the top-left corner, half outside their own rounded square. */
.rvc figcaption{display:flex;align-items:center;gap:11px}
.rvc figcaption>div>b{display:block;font-size:13.5px;color:var(--ink)}
.rvc figcaption>div>span{display:block;font-size:12px;color:var(--muted);line-height:1.4}
@media(max-width:980px){.rvwall{columns:2}}
@media(max-width:640px){
  .rvwall{columns:1}
  .rvsum-n{font-size:44px}
}

/* ---------------------------------------------------------------- portal: live modules
   States the portal animators toggle so every module behaves like a live screen. */
.pfn{transition:background .3s,border-color .3s,color .3s,box-shadow .3s}
.pfn.lit{background:rgba(59,130,246,.22);border-color:rgba(96,165,250,.55);color:#fff;
  box-shadow:0 0 0 3px rgba(59,130,246,.12)}
.pfn.start.lit,.pfn.ivr.lit{background:linear-gradient(150deg,rgba(59,130,246,.34),rgba(6,182,212,.2))}
.ptable tr{transition:background .3s}
.ptable tr.lit{background:rgba(59,130,246,.10)}
.ptable tr.lit td:first-child b{color:var(--brand)}
.phcells i{transition:transform .22s,filter .22s}
.phcells i.lit{transform:scaleY(1.3);filter:brightness(1.7)}
.pbar i,.ot i{transition:width .8s cubic-bezier(.2,.8,.3,1)}
[data-pm-q],[data-pm-w],[data-pm-v],[data-pm-ov],[data-pm-bal],[data-pm-today],
[data-pm-spent],[data-pm-mins],[data-pm-done],[data-pm-conn],[data-pm-succ],[data-pm-rem]{
  font-variant-numeric:tabular-nums}
.pdot{transition:background .3s,box-shadow .3s}

/* ---------------------------------------------------------------- how it works console
   Fourth version. DARK FRAME, LIGHT APP, caption strip -- the hero console's idiom, adopted
   here because the third version was a dark panel on a dark band and the client could not
   see it ("image is not showing properly cause image is also dark", 2026-08-10). Making the
   app light fixes that by construction rather than by nudging opacities on a dark surface.

   Two columns inside: the steps tick off on the left, and the right-hand pane RENDERS what
   each step produced -- the numbers, the flow, the team, the dashboard. That pane is the
   whole point of the rebuild; a checklist can only name the steps.

   States are set by the `setup` animator in main.js, which drives the steps, the preview,
   the bar and the caption off ONE index. */
.hw{position:relative;border-radius:var(--r-lg);padding:1.05em;overflow:hidden;
  background:linear-gradient(168deg,#111A33 0%,#0B1020 52%,#0D1428 100%);
  border:1px solid rgba(255,255,255,.09);
  box-shadow:0 40px 90px -40px rgba(11,16,32,.55),0 2px 0 rgba(255,255,255,.05) inset}
/* the light app. Same trick as .cine-body: re-point a small token set here and the parts
   below inherit the right side, instead of every rule carrying two colours. */
.hw-body{--hl1:#E3EAF6; --hs:#F8FAFF; --ht:#16213D; --hm:#64748B;
  border-radius:20px;padding:20px 22px 22px;
  background:linear-gradient(180deg,#F8FAFF,#EAF0FA);border:1px solid #DCE5F4}
/* EVERY <b> IN THE LIGHT APP NEEDS THIS. The band is `sec dark`, which carries
   `.sec.dark b{color:#fff}` at (0,2,1) -- so a bold number on one of these white cards is
   white on white and simply disappears. It cost the KPI row, the phone numbers and the
   extension names before it was spotted, and it is invisible in the markup: the values are
   all there in the HTML. Anything with a class + element selector (`.hwk b` is (0,1,1))
   loses. This umbrella is (0,3,1) and covers the whole app in one place.
   Mirror image of the hero console's trap, where <b> on a DARK card inherited the global
   near-black ink and needed an explicit white. Check both directions when adding a card. */
.sec.dark .hw-body b{color:var(--ht)}
.hw-head{display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding-bottom:14px;margin-bottom:16px;border-bottom:1px solid var(--hl1)}
.su-live{display:inline-flex;align-items:center;gap:8px;font-size:11px;font-weight:700;
  letter-spacing:.13em;text-transform:uppercase;color:var(--brand)}
.su-live i{width:7px;height:7px;border-radius:50%;background:#22C55E;
  box-shadow:0 0 0 4px rgba(34,197,94,.18);animation:blink 1.6s infinite}
.su-eta{font-size:12.5px;font-weight:600;color:var(--hm);font-variant-numeric:tabular-nums}
.hw-grid{display:grid;grid-template-columns:minmax(0,1.02fr) minmax(0,1fr);gap:22px;
  align-items:start}

/* ---- left: the steps */
.su-item{display:grid;grid-template-columns:36px 1fr auto;gap:13px;align-items:center;
  padding:13px 0;border-bottom:1px solid var(--hl1)}
.su-item:last-child{border-bottom:0}
.su-ic{width:36px;height:36px;border-radius:11px;display:grid;place-items:center;color:#93A3BE;
  background:#fff;border:1px solid var(--hl1);transition:all .4s}
.su-ic .ic-svg{width:17px;height:17px}
.su-t{min-width:0}
.su-t b{display:block;font-size:14px;color:var(--ht);letter-spacing:-.01em}
.su-t small{font-size:11.5px;color:var(--hm)}
/* the minutes column was dropped at this width -- the status pill and the time together
   pushed the step titles to two lines in a half-width column */
.su-time{display:none}
.su-st{min-width:74px;text-align:center;font-size:10.5px;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;padding:5px 9px;border-radius:100px;color:#94A3B8;
  background:#fff;border:1px solid var(--hl1);transition:all .4s}
.su-item.doing .su-ic{color:#fff;background:var(--grad);border-color:transparent}
.su-item.doing .su-st{color:var(--brand);background:#E8F0FE;border-color:#CFE0FB}
.su-item.done .su-ic{color:#fff;background:linear-gradient(150deg,#22C55E,#0EA5E9);border-color:transparent}
.su-item.done .su-st{color:#15803D;background:#E9F9F2;border-color:#A9E3CC}
.su-item.done .su-t b,.su-item.doing .su-t b{color:var(--ht)}

/* ---- right: what the step produced. Absolutely stacked in a FIXED box, same rule as the
   hero stage: the four panes are different heights and anything else resizes the band.
   320px is sized off the MEASURED tallest pane, not guessed. Natural heights are
   numbers 311 / flow 283 / team 307 (at three rows) / dashboard 261, so 320 clears them
   all. Guessing cost two rounds here: 250 clipped the flow's last two departments and
   286 still clipped the team list. If a pane gains a row, measure every pane again --
   render them `position:static` with the box at `height:auto` and read the rects. */
.hw-prev{position:relative;height:320px}
.hwp{position:absolute;inset:0;padding:15px 16px;border-radius:15px;overflow:hidden;
  background:var(--hs);border:1px solid var(--hl1);box-shadow:0 8px 22px -14px rgba(14,26,51,.3);
  opacity:0;visibility:hidden;transform:translateY(8px);
  transition:opacity .45s,transform .45s cubic-bezier(.2,.8,.3,1),visibility .45s}
.hw[data-step="0"] .hwp[data-p="0"],.hw[data-step="1"] .hwp[data-p="1"],
.hw[data-step="2"] .hwp[data-p="2"],.hw[data-step="3"] .hwp[data-p="3"]{
  opacity:1;visibility:visible;transform:none}
.hwp-h{display:flex;align-items:center;gap:8px;font-size:12px;font-weight:700;
  color:var(--ht);margin-bottom:12px}
.hwp-h .ic-svg{width:15px;height:15px;color:var(--brand)}
.hwp-c{margin-left:auto;font-size:10.5px;font-weight:700;color:var(--hm);
  background:#fff;border:1px solid var(--hl1);border-radius:100px;padding:3px 9px}
.hwp-c.live{color:#15803D;background:#E9F9F2;border-color:#A9E3CC}
.hwp-n{margin-top:12px;font-size:11.5px;line-height:1.5;color:var(--hm)}

/* numbers */
.hwn-list{display:flex;flex-direction:column;gap:8px}
.hwn{display:flex;align-items:center;gap:10px;padding:9px 11px;border-radius:11px;
  background:#fff;border:1px solid var(--hl1);opacity:0;transform:translateX(-6px);
  transition:opacity .4s,transform .4s}
.hw[data-step="0"] .hwn{opacity:1;transform:none}
.hw[data-step="0"] .hwn[data-d="1"]{transition-delay:.14s}
.hw[data-step="0"] .hwn[data-d="2"]{transition-delay:.28s}
/* border-box is site-wide: size the disc, not the glyph, or the content box computes to 0 */
.hwn-k{width:26px;height:26px;flex:none;border-radius:8px;display:grid;place-items:center;
  background:#EEF3FD;color:var(--brand)}
.hwn-k .ic-svg{width:13px;height:13px}
.hwn b{display:block;font-size:12.5px;color:var(--ht);font-variant-numeric:tabular-nums}
.hwn small{font-size:10.5px;color:var(--hm)}
.hwn-s{margin-left:auto;font-size:10px;font-weight:700;color:#15803D;background:#E9F9F2;
  border:1px solid #A9E3CC;border-radius:100px;padding:3px 8px}

/* call flow */
.hwf{display:flex;flex-direction:column;align-items:center;gap:0}
.hwf-n{display:inline-flex;align-items:center;gap:7px;padding:6px 12px;border-radius:10px;
  font-size:11.5px;font-weight:600;color:var(--ht);background:#fff;border:1px solid var(--hl1)}
.hwf-n .ic-svg{width:13px;height:13px;color:var(--brand)}
.hwf-l{width:2px;height:13px;background:#CBD8EE}
.hwf-ds{display:grid;grid-template-columns:1fr 1fr;gap:7px;margin-top:13px;width:100%}
.hwf-d{padding:7px 10px;border-radius:9px;font-size:11px;font-weight:600;text-align:center;
  color:var(--brand);background:#E8F0FE;border:1px solid #CFE0FB;
  opacity:0;transform:scale(.94);transition:opacity .38s,transform .38s}
.hw[data-step="1"] .hwf-d{opacity:1;transform:none}
.hw[data-step="1"] .hwf-d[data-d="1"]{transition-delay:.1s}
.hw[data-step="1"] .hwf-d[data-d="2"]{transition-delay:.2s}
.hw[data-step="1"] .hwf-d[data-d="3"]{transition-delay:.3s}

/* team */
.hwt-list{display:flex;flex-direction:column;gap:7px}
.hwt{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:11px;
  background:#fff;border:1px solid var(--hl1);opacity:0;transform:translateY(6px);
  transition:opacity .38s,transform .38s}
.hw[data-step="2"] .hwt{opacity:1;transform:none}
.hw[data-step="2"] .hwt[data-d="1"]{transition-delay:.12s}
.hw[data-step="2"] .hwt[data-d="2"]{transition-delay:.24s}
.hw[data-step="2"] .hwt[data-d="3"]{transition-delay:.36s}
.hwt-a{width:26px;height:26px;flex:none;border-radius:8px;display:grid;place-items:center;
  font-size:10px;font-weight:700;color:#fff;background:var(--grad)}
.hwt b{display:block;font-size:12.5px;color:var(--ht)}
.hwt small{font-size:10.5px;color:var(--hm)}
.hwt-s{margin-left:auto;color:#16A34A}
.hwt-s .ic-svg{width:15px;height:15px}

/* dashboard */
.hwb{display:flex;align-items:flex-end;gap:5px;height:86px;padding:0 2px}
.hwb i{flex:1;border-radius:4px 4px 0 0;height:6px;
  background:linear-gradient(180deg,var(--brand-2),var(--brand));
  transition:height .5s cubic-bezier(.2,.8,.3,1)}
.hw[data-step="3"] .hwb i{height:var(--h)}
.hwb i[data-d="1"]{transition-delay:.04s}  .hwb i[data-d="2"]{transition-delay:.08s}
.hwb i[data-d="3"]{transition-delay:.12s}  .hwb i[data-d="4"]{transition-delay:.16s}
.hwb i[data-d="5"]{transition-delay:.2s}   .hwb i[data-d="6"]{transition-delay:.24s}
.hwb i[data-d="7"]{transition-delay:.28s}  .hwb i[data-d="8"]{transition-delay:.32s}
.hwb i[data-d="9"]{transition-delay:.36s}  .hwb i[data-d="10"]{transition-delay:.4s}
.hwb i[data-d="11"]{transition-delay:.44s}
.hwk{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-top:14px}
.hwk div{padding:9px 8px;border-radius:10px;text-align:center;background:#fff;
  border:1px solid var(--hl1)}
.hwk b{display:block;font-size:15px;color:var(--ht);letter-spacing:-.02em}
.hwk span{display:block;font-size:9.5px;color:var(--hm);margin-top:2px}

/* ---- progress + caption */
.su-bar{height:4px;margin-top:18px;border-radius:4px;background:var(--hl1);overflow:hidden}
.su-bar i{display:block;height:100%;width:0;border-radius:4px;
  background:linear-gradient(90deg,var(--brand),var(--accent));transition:width .55s cubic-bezier(.2,.8,.3,1)}
/* the caption strip is DARK, so the light app is framed top and bottom -- same reason the
   hero console's caption is dark */
.hw-cap{display:flex;align-items:center;gap:14px;margin-top:12px;padding:0 16px;height:60px;
  border-radius:14px;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.1)}
.hw-n{display:grid;place-items:center;width:34px;height:34px;flex:none;border-radius:11px;
  font-size:13px;font-weight:800;color:#fff;font-variant-numeric:tabular-nums;
  background:linear-gradient(150deg,var(--brand-2),var(--brand-deep))}
.hw-tx{min-width:0}
.hw-tx b{display:block;font-size:14px;color:#fff;line-height:1.25}
.hw-tx span{display:block;margin-top:1px;font-size:12px;color:#8FA0BF;line-height:1.35}
.hw-pct{margin-left:auto;flex:none;font-size:12px;color:#8FA0BF;white-space:nowrap}
.hw-pct b{color:#fff;font-variant-numeric:tabular-nums}
@media(max-width:860px){
  .hw-grid{grid-template-columns:minmax(0,1fr);gap:16px}
  /* the preview goes FIRST when stacked: it is the part that shows something, and burying
     it under four checklist rows on a phone hides the whole point of the rebuild */
  .hw-prev{order:-1;height:auto}
  /* AND it sizes to content here, instead of the fixed box the two-column layout uses.
     Every label wraps to two lines in a 390px column, so a pane that measured 311px on
     desktop runs well past it and clips -- the numbers pane lost its third row. A fixed
     box is only worth it beside the steps column, where it stops the two columns
     disagreeing about height; stacked there is nothing to keep it level with.
     Static + display toggling, not absolute + opacity: absolutely positioned panes cannot
     give the container a height to grow to. */
  .hwp{position:static;display:none;transform:none}
  .hw[data-step="0"] .hwp[data-p="0"],.hw[data-step="1"] .hwp[data-p="1"],
  .hw[data-step="2"] .hwp[data-p="2"],.hw[data-step="3"] .hwp[data-p="3"]{display:block}
  .su-st{min-width:0;padding:5px 8px}
  .hw-cap{height:auto;padding:12px 13px}
  .hw-pct{display:none}
}
@media(max-width:720px){
  .su-item{grid-template-columns:34px 1fr;gap:12px;row-gap:8px}
  .su-ic{width:34px;height:34px}
  .su-time{display:none}
  .su-st{grid-column:2;justify-self:start;min-width:0}
  .su-head{flex-wrap:wrap;gap:8px}
  .su-foot{flex-wrap:wrap}
  .su-foot span{margin-left:0;width:100%}
}

/* ---------------------------------------------------------------- live feature panels
   States the panel JS toggles while each core-feature demo runs. */
.prow2{transition:background .3s,border-color .3s}
.prow2.is-ring{background:rgba(251,191,36,.14);border-color:rgba(251,191,36,.4)}
.prow2.is-live{background:rgba(34,197,94,.13);border-color:rgba(34,197,94,.38)}
.panel.dark .prow2.is-ring{background:rgba(251,191,36,.13);border-color:rgba(251,191,36,.34)}
.panel.dark .prow2.is-live{background:rgba(34,197,94,.14);border-color:rgba(34,197,94,.36)}
.prow2.is-ring .tag{background:rgba(251,191,36,.2);border-color:rgba(251,191,36,.45);color:#B45309;
  animation:blink 1s infinite}
.panel.dark .prow2.is-ring .tag{color:#FCD34D}
.prow2.is-live .tag{background:rgba(34,197,94,.2);border-color:rgba(34,197,94,.45);color:#15803D}
.panel.dark .prow2.is-live .tag{color:#6EE7A8}
.prow2 [data-fp-tag]{font-variant-numeric:tabular-nums;min-width:74px;text-align:center}
[data-fp-t],[data-fp-dialed],[data-fp-int],[data-fp-conv],[data-fp-at],[data-fp-calls]{
  font-variant-numeric:tabular-nums}
.prog i{transition:width .9s cubic-bezier(.2,.8,.3,1)}
/* the scanning column in the heatmap */
.heat i{transition:transform .25s,filter .25s,box-shadow .25s}
.heat i.lit{transform:scaleY(1.32);filter:brightness(1.75);
  box-shadow:0 0 10px -1px rgba(96,165,250,.75)}

/* ---------------------------------------------------------------- numbered section head
   The homepage rhythm: a rule, a chapter number, the heading on the left and the intro
   pulled out to the right. Replaces the centred eyebrow + centred h2 + centred paragraph
   that every other SaaS template uses. Inner pages keep the centred `.sh`. */
.shx{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,400px);gap:14px 48px;
  align-items:start;padding-top:24px;border-top:1px solid var(--line);margin-bottom:46px}
.shx h2{font-size:clamp(26px,3.1vw,42px);line-height:1.12;letter-spacing:-.03em}
.shx-p{font-size:15.5px;line-height:1.7;color:var(--muted);padding-top:5px}
/* Section eyebrow (client, 2026-08-10). `.shx` is a two-column grid, so this MUST span the
   whole row -- as a plain first child it takes the heading's column and shunts the h2 into
   the intro's slot. Matches the .eyebrow used on the FAQ and CTA blocks so the page reads as
   one system; not reusing .eyebrow itself because that carries a 16px bottom margin sized
   for a stacked block, which is too much inside this grid's own row gap. */
.shx-eb{grid-column:1/-1;display:inline-flex;align-items:center;gap:8px;font-size:12.5px;
  font-weight:700;letter-spacing:.11em;text-transform:uppercase;color:var(--brand)}
.shx-eb::before{content:'';width:20px;height:2px;border-radius:2px;background:var(--grad)}
.sec.dark .shx-eb,.cs-dark .shx-eb,.stats-dark .shx-eb,.portal-sec .shx-eb,.clients-sec .shx-eb{color:#7DD3FC}
/* on the dark bands the rule and the copy have to flip */
.sec.dark .shx,.cs-dark .shx,.stats-dark .shx,.portal-sec .shx,.clients-sec .shx{border-top-color:rgba(255,255,255,.14)}
.sec.dark .shx-p,.cs-dark .shx-p,.stats-dark .shx-p,.portal-sec .shx-p,.clients-sec .shx-p{color:#8FA0BF}
@media(max-width:900px){
  .shx{grid-template-columns:1fr;gap:10px;margin-bottom:34px}
  .shx-p{padding-top:0}
}

/* ---------------------------------------------------------------- reveal */
.r{opacity:1}
html.js .r{opacity:0;transform:translateY(20px)}
html.js .r.in{opacity:1;transform:none;transition:opacity .55s cubic-bezier(.2,.8,.3,1),transform .55s cubic-bezier(.2,.8,.3,1)}
html.js .r.d1.in{transition-delay:.07s}
html.js .r.d2.in{transition-delay:.14s}
html.js .r.d3.in{transition-delay:.21s}

/* ---------------------------------------------------------------- responsive */
@media(max-width:1100px){
  .bento{grid-template-columns:repeat(2,1fr)}
  .bt.wide{grid-column:span 2}
  .bt.tall{grid-row:span 1}
  .fcards{grid-template-columns:repeat(2,1fr)}
  .ucs{grid-template-columns:repeat(2,1fr)}
  .ind-band{grid-template-columns:1fr;gap:20px}
  /* below this the four-across timeline does not fit, so the rule turns vertical and the
     numbered nodes run down the left instead of across the top */
  .steps{grid-template-columns:1fr;gap:0}
  .steps::before{top:18px;bottom:22px;left:18px;right:auto;width:1.5px;height:auto;
    background:linear-gradient(180deg,rgba(125,211,252,.55),rgba(125,211,252,.14))}
  .step{padding:0 0 28px 58px}
  .step .sn{position:absolute;left:0;top:0;margin:0}
  .step .sic{margin-bottom:10px}
  .f-cols{grid-template-columns:repeat(3,1fr)}
  .f-top{grid-template-columns:1fr}
}
@media(max-width:980px){
  .hero-grid{grid-template-columns:1fr;gap:44px}
  .hero{padding:60px 0 72px}
  .lede{max-width:none}
  .pcs,.tsts,.posts,.pains,.cscs{grid-template-columns:1fr}
  .plans{grid-template-columns:1fr;max-width:520px;margin:8px auto 0}
  .cgrid{grid-template-columns:1fr;gap:36px}
  .cs-body{grid-template-columns:1fr;gap:20px}
  .split{grid-template-columns:1fr;gap:32px;margin-bottom:56px}
  .split.rev .sp-copy{order:0}
  .stats{grid-template-columns:repeat(2,1fr);padding:34px 20px}
  .sec{padding:76px 0}
  .cta-card{padding:52px 26px;border-radius:28px}
}
/* five top-level items plus the CTA outgrow the bar just above the mobile breakpoint,
   so tighten the spacing and drop the Log in text link through that band */
@media(min-width:861px) and (max-width:1010px){
  .nav-inner{padding-left:18px}
  .mt{padding:9px 11px;font-size:14px}
  .nav-login{display:none}
  .nav-cta{gap:0}
}
@media(max-width:860px){
  /* The chrome is full bleed at every width now, so this block no longer has to undo an
     inset -- it only drops the content gutter, which the five items and the burger cannot
     spare. */
  /* --tb-h stays 0 here too: the contact strip is gone site-wide (2026-08-17) and this
     override, which used to shrink it to 34px on mobile, otherwise reserves a blank
     34px band above the nav. Only the gutter drop is still wanted. */
  :root{--shell-pad:0px}
  /* .nav-inner must NOT be a containing block here. The off-canvas .menu is position:fixed
     and pinned to the whole viewport; contained, it only slides by the bar's content width
     and peeks in at the right edge. This is the mobile counterpart of the translateZ in the
     base rule -- that one exists to CONTAIN the dropdowns, this one to release the menu. */
  .nav-inner{transform:none}
  /* tighter spacing buys back roughly one item's worth of width before anything has to drop */
  .tb-track{gap:22px;padding:0 16px}
  .tb-set{gap:22px}
  /* Opaque, no blur: the bar sits over the white off-canvas sheet on mobile and a
     translucent one lets the menu show through it. The paint is on `.nav` like everywhere
     else -- these used to target `.nav-inner` back when it was the bar. */
  .nav{background:rgba(5,7,16,.98);backdrop-filter:none;-webkit-backdrop-filter:none;
    border-bottom-color:rgba(255,255,255,.06);box-shadow:0 1px 0 rgba(255,255,255,.04)}
  .nav.scrolled{background:#050710;box-shadow:0 18px 40px -26px rgba(0,0,0,.9)}
  .nav-inner{gap:8px;padding:0 14px}
  /* the sheet is a plain in-flow block on mobile; drop the desktop panel chrome */
  .mm{border:0;border-radius:0;top:100%}
  .nav-cta{gap:0;margin-left:auto}
  /* the menu wrapper is not a group on mobile: it just hosts the off-canvas panel */
  .nav-nav{display:contents}
  .menu-ind{display:none}
  .menu{position:fixed;top:var(--chrome-h);left:0;right:0;bottom:0;background:#fff;display:block;
    padding:18px 20px 40px;overflow-y:auto;transform:translateX(100%);
    transition:transform .3s cubic-bezier(.2,.8,.3,1);margin:0;border-top:1px solid var(--line-2)}
  body.nav-open{overflow:hidden}
  body.nav-open .menu{transform:translateX(0)}
  .mi{border-bottom:1px solid var(--line-2)}
  .mi::after{display:none}
  /* the off-canvas panel is white, so the bar's light-on-dark text must flip back */
  .mt{width:100%;justify-content:space-between;padding:16px 4px;font-size:16px;border-radius:0;
    color:var(--ink)}
  .mt:hover,.mi:hover>.mt{background:none;color:var(--ink)}
  .mt.plain{display:block;border-bottom:1px solid var(--line-2)}
  .mm{position:static;opacity:1;visibility:visible;transform:none;box-shadow:none;border:0;width:auto!important;
    display:none;padding:0 0 12px;background:none}
  .mi:hover .mm{transform:none}
  /* .mm.mega and .two-col both carry display:grid at higher specificity than the .mm reset
     above, so each must be collapsed explicitly or it hangs open on mobile. (.one-col was
     the Resources menu's; it went with that dropdown on 2026-08-10.) */
  .mm.mega,.mm.two-col{display:none;grid-template-columns:1fr;gap:0;padding:0 0 12px}
  .mi.open .mm,.mi.open .mm.mega,.mi.open .mm.two-col{display:block}
  .mm-body,.mm.mega .mm-body,.mm.two-col .mm-body{display:block;padding:0}
  .mm a,.mm .mh{opacity:1;transform:none}
  .mm a::after{display:none}
  .mm-grid{grid-template-columns:1fr}
  .mm-promo,.mm-bar{display:none}
  /* Both column dividers have to be reset for the stacked mobile sheet, or the 2nd and 3rd
     groups keep a vertical rule and a 22px indent that only made sense side by side.
     `.mcol.wide` is the Use Cases menu's, `.mcol+.mcol` is the Features menu's. */
  .mm.mega .mcol.wide,.mm.mega.feat .mcol+.mcol{border-left:0;padding-left:0}
  .mind{grid-template-columns:1fr 1fr}
  /* Side by side, not stacked (client, 2026-08-17). flex:1 with min-width:0 so the two
     share the row evenly and long labels shrink instead of forcing a wrap. */
  .menu-foot{display:flex;flex-direction:row;gap:10px;margin-top:24px}
  .menu-foot .btn{flex:1;min-width:0;justify-content:center;padding-inline:12px}
  /* Burger sits hard right (client, 2026-08-17: it was "beside the logo"). `.nav-cta`
     carries margin-left:auto on tablet, but it is display:none at <=560px, so the auto
     margin has to live on the burger itself to survive both cases. */
  .burger{display:block;margin-left:auto}
  /* Chevrons are hidden on desktop by design (2026-08-04, "the chevrons are gone"), but on
     mobile the accordion rows give no other hint that they open, so they come back here
     only. Rotates to point up when its section is open. */
  .mt .cx{display:block;margin-left:auto;width:7px;height:7px;opacity:.85;
    transform:rotate(45deg) translate(-2px,-2px)}
  .mi.open > .mt .cx{transform:rotate(225deg) translate(-1px,-1px)}
  .nav-login{display:none}
  .f-cols{grid-template-columns:repeat(2,1fr)}
  .ucs{grid-template-columns:1fr}
  /* the blurred hero orbs get clipped by the hero's overflow on narrow screens,
     which leaves a hard white rectangle in the corner. Not worth it on mobile. */
  .horbs{display:none}
}
@media(max-width:560px){
  .bento{grid-template-columns:1fr}
  .bt.wide{grid-column:span 1}
  .fcards,.steps{grid-template-columns:1fr}
  .stats{grid-template-columns:1fr}
  .stats.three{grid-template-columns:1fr}
  .frow{grid-template-columns:1fr}
  .f-cols{grid-template-columns:1fr}
  .mind{grid-template-columns:1fr}
  /* Side by side, not stacked full width (client, 2026-08-17). The row already wraps, so
     flex:1 + min-width:0 shares it evenly and lets long labels shrink rather than wrap. */
  .cta-row{flex-wrap:nowrap}
  .cta-row .btn{flex:1;min-width:0;width:auto;justify-content:center;padding-inline:14px}
  .cs{padding:26px}
  .csc{padding:24px}
  .csc-mets{grid-template-columns:1fr}
}
@media(max-width:460px){
  .nav-cta{display:none}
}
/* THE STRIP YIELDS TO THE ONE-SCREEN RULE. Its 34-38px comes straight off the hero and the
   console cannot give it back: fitCine() is already pinned at FIT_MIN (5.6px) on a short
   phone, so there is nothing left to shrink and the hero runs past the fold. Measured on the
   homepage at 390 wide: 700px tall clears by 1px, 680 misses by 17, 667 by 29. Gated at 720
   to keep the ~17px margin the taller viewports already run at.
   Deliberately height-only, not width: a short desktop window has the identical problem.
   Same trade as `@media(max-height:780px)` on .hero-badge -- when height runs out the
   decoration goes, and the contact details are still in the footer and on /contact.
   MUST STAY BELOW the max-width:860px block: that one also sets --tb-h, at equal
   specificity, so whichever comes last wins. */
@media(max-height:720px){:root{--tb-h:0px}}
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important}
  html.js .r{opacity:1;transform:none}
}

/* ============================================================================
   HOMEPAGE v6: centered hero, portal replica, dark bands, marquees, animations
   ========================================================================== */

/* ---------------------------------------------------------------- scroll progress */
.sprog{position:fixed;top:0;left:0;height:3px;width:100%;transform:scaleX(0);transform-origin:left;
  background:var(--grad);z-index:400;pointer-events:none}

/* ============================================================================
   HOMEPAGE HERO: copy left, working web phone right.

   The card is dark on the light hero band deliberately. It reads as a real device,
   gives the banner one clear focal point, and it is the only dark element above the
   fold so the eye lands on it. The pad is live: main.js dials a demo number on its
   own and hands control to the visitor the moment they touch a key.

   Replaced the old centered hero (heading + Three.js particle globe + mouse
   scroll-hint). The globe read as generic AI-startup decoration and said nothing
   about calling; it is now scoped out of this hero in main.js and still runs on the
   inner-page heroes. Do not reintroduce the scroll hint.
   ========================================================================== */
.dial-hero{
  /* ONE SCREEN (client, 2026-08-06). Heading, buttons and the whole console have to be
     visible without scrolling on every viewport, so the hero is exactly the space under
     the fixed chrome and everything inside it is sized off viewport height, not off a
     fixed px value. `svh` not `vh`: on phones `vh` is the tall-viewport height, which is
     bigger than what you can actually see with the browser UI showing, and the console
     would hang off the bottom on first paint. Never put a px height on this section. */
  /* --nav-pad is 0 while the chrome is full bleed, so this is simply the space under the
     bar. It stays in the expression because it is the exact term that has to come back if
     the bar is ever floated again: the band would then end the same distance above the fold
     as it starts below the bar. main.js subtracts the same gap in availPx() -- change one
     and change the other. */
  min-height:calc(100svh - var(--chrome-h) - var(--nav-pad));
  display:flex;flex-direction:column;justify-content:center;align-items:stretch;
  padding:clamp(12px,2.1vh,40px) clamp(0px,1.4vw,26px) clamp(14px,2.5vh,52px);overflow:hidden}
  /* NO width cap, radius, border or shadow here (client, 2026-08-10, second pass: the
     banner background must reach both edges with no radius and no side gap). This briefly
     carried a capped panel earlier the same day; it was reverted because the client wanted
     the background full bleed. The content is still capped by .dial-hero>.wrap at 1400px --
     that is what keeps the copy off the edges, not the section. */
/* The hero's inner track is the site default 1200px (client, 2026-08-10) -- it used to be
   widened to 1400. Narrowing it shrinks the copy column, which is what forced the h1 cap
   down; see the h1 rule. */
.dial-hero>.wrap{width:100%}
/* Fine grid, faded out from the top so it never reads as a table. Purely texture: it is
   the first child in paint order, so .hero-glow and .horbs still sit over it. */
.dial-hero::before{content:'';position:absolute;inset:0;pointer-events:none;
  background-image:linear-gradient(rgba(11,16,32,.045) 1px,transparent 1px),
                   linear-gradient(90deg,rgba(11,16,32,.045) 1px,transparent 1px);
  background-size:48px 48px;
  -webkit-mask-image:radial-gradient(120% 88% at 50% 0%,#000 0%,transparent 72%);
  mask-image:radial-gradient(120% 88% at 50% 0%,#000 0%,transparent 72%)}
/* Copy left, console right (client, 2026-08-07). minmax(0,..) on both tracks or the
   console's nowrap innards give the right column a min-content floor and it refuses to
   shrink, pushing the grid wider than the wrap. */
/* Console WIDENED again, 1.4fr -> 1.62fr (client, 2026-08-10, seventh pass: "make the image
   animation screen width more bigger"). It was 1.05fr before that pass.
   THIS SPLIT IS A SEESAW, NOT A FREE KNOB: every px given to the console comes off the copy
   column, and the copy column is what caps the two-line h1, because `.dh-l1` is nowrap.
   Each widening has cost heading size -- 46px -> 38px -> 35px. See the note on `.dh-copy h1`
   for the arithmetic; never move this number without re-measuring that one.
   The light SCREEN inside the frame gained twice over in this pass: the split, plus the
   ~11.4em the deleted step rail column was taking out of the stage. */
.dh-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.62fr);
  align-items:center;gap:clamp(24px,3.4vw,60px)}
.dh-visual{min-width:0}
@media(max-width:1000px){
  .dh-grid{grid-template-columns:minmax(0,1fr);gap:clamp(14px,2.2vh,26px)}
}
/* Just above the stacking breakpoint is where the two-column hero is tightest -- the
   console still has to fit its widest cards in a half-width column. Through that band the
   hero gives its side padding back to the grid; that padding is decoration and the console
   is not. Must sit after `.dial-hero`'s own padding, which is a single class and would
   otherwise win on source order. (It used to narrow --shell-pad too, back when that var set
   the hero panel's width; the hero is full bleed again and --shell-pad only reaches the nav.) */
@media(min-width:1001px) and (max-width:1240px){
  .hero,.dial-hero{padding-left:0;padding-right:0}
  /* This band used to widen the console to 1.25fr, because the 1.05fr base spilled the
     cards at 1024. The base is far wider than that now, so the override was NARROWING the
     console and re-introducing the exact spill it was written to prevent -- it is gone.
     The band also used to drop the step rail here; the rail itself is gone now.
     Kept as a comment because the padding rule above is the whole point of this block and
     reads as a stray one-liner without it. */
}
.dial-hero .hero-badge{margin-bottom:clamp(8px,1.7vh,24px)}
/* The badge used to be dropped under 780px of viewport HEIGHT as a space saving. That is
   what made the hero read differently on a short laptop window than on a tall phone, which
   the client reported as mobile and desktop not matching (2026-08-17). The banner is now
   the same everywhere; if height pressure comes back, shrink the badge rather than hiding
   it, so the two never diverge again. */
/* Left column of the hero grid (client, 2026-08-07): badge, heading, lede, buttons, all
   ranged left against the console on the right. */
.dh-copy{position:relative;z-index:1;min-width:0;text-align:left}
/* max-width in `ch`, not px, so the line count holds at every font size (client, 2026-08-10:
   the lede reads as three lines). Chars per line is ~1.46x the ch value and is INDEPENDENT of
   font-size, because ch and the average glyph both scale with it -- a px cap gave 3 lines at
   1920 and 2 at 1280 purely because the smaller font fits more characters in the same width.
   The copy is ~140 chars, so ~47 per line lands on 3. Re-measure if the copy is reworded. */
.dh-lede{color:var(--muted);font-size:clamp(14px,1.05vw,16.5px);line-height:1.55;
  margin:clamp(10px,1.5vh,18px) 0 clamp(16px,2.2vh,26px);max-width:33ch}
.hero-badge{display:inline-flex;align-items:center;gap:9px;padding:8px 17px;border-radius:100px;
  background:#fff;border:1px solid #DBEAFE;color:var(--brand);font-weight:600;font-size:13px;
  box-shadow:var(--sh-1);margin-bottom:24px}
.hero-badge .dot{width:7px;height:7px;border-radius:50%;background:var(--ok);
  box-shadow:0 0 0 4px rgba(22,163,74,.16);animation:blink 2s infinite}
/* The rotating word changes the width of line 1. If line 1 is ever allowed to wrap, a long
   word ("Move your support desk" wants 632px) pushes the heading from two lines to three
   and every section below it jumps down ~60px, twice per rotation. So line 1 is one
   unbreakable line and the type is sized to guarantee it fits the column at every width;
   min-height then pins the heading box even while the reveal runs. Centring bought the
   heading ~240px of width over the old column, which is what pays for the larger cap. */
/* Back to a FIXED TWO LINES in the narrow left column (client, 2026-08-07). The whole
   heading on one line only worked while it had the full 1152px; at half that it would
   force ~28px type. So line 1 is "Move your <word>", nowrap, and "to the cloud" always
   falls to line 2 -- which is what keeps the rotating word from ever changing the line
   count. Line 1 measures 10.7px of width per 1px of font at its longest ("support desk"),
   and the column is ~576px at the 1400px wrap, giving a 53px ceiling; 46px sits under it
   with room for the shorter viewports. min-height pins the box while the reveal runs. */
/* TWO lines again (client, 2026-08-10, fifth pass): line 1 is "Move your <rotating word>",
   nowrap, and "to the cloud" always falls to line 2 -- so the rotator can never change the
   line count. Line 1 inks 11.29px of width per 1px of font, which is what caps the size:
   it has to fit the copy column, and the column is what the .dh-grid split decides. The
   console was narrowed in the same pass specifically to pay for this (see .dh-grid).
   min-height is 2 lines x 1.08 = 2.16em; it pins the box while the GSAP reveal runs. */
/* CAP 46 -> 38 -> 35px, vw term 3.3 -> 3.0 -> 2.9. Both are MEASURED CEILINGS, not
   preferences, and both fell because the client widened the console twice on 2026-08-10.
   `.dh-l1` is nowrap, so line 1 must fit the copy column with the widest rotator word
   ("support desk") substituted in, and it inks **11.28px per 1px of font**:
     - The 1.62fr split leaves the copy column 417px at 1920, so the ceiling is
       417/11.28 = 36.9px. 35 leaves 22px of slack. (At the previous 38px cap the column
       measured -12px, i.e. line 1 was overflowing its column at every width from 1280 up.)
     - The vw term binds below ~1240px. At 1100 the column is 387px, ceiling 34.3px, and
       3.0vw asked for 33 -- a 1.3px margin, inside font-rendering variance. 2.9vw asks for
       31.9 and clears by 2.4px.
   THE HEADING AND THE CONSOLE ARE A SEESAW: every px given to one comes off the other.
   To get heading size back, narrow `.dh-grid` -- that is the only lever that does not
   overturn a client decision. The other two sources of width are the hero's 1200px track
   and the rotator's nowrap two-line rule, and both are the client's calls. */
.dh-copy h1{font-size:clamp(24px,min(2.9vw,5.4vh),35px);line-height:1.08;
  min-height:2.16em;margin-bottom:0}
.dh-l1{display:block;white-space:nowrap}
.split-h .w{display:inline-block;will-change:transform,opacity}

.horbs i{position:absolute;border-radius:50%;pointer-events:none;filter:blur(50px)}
.horbs i:nth-child(1){width:340px;height:340px;top:-60px;left:6%;background:rgba(59,130,246,.28);animation:orb 16s ease-in-out infinite}
.horbs i:nth-child(2){width:300px;height:300px;top:40px;right:4%;background:rgba(6,182,212,.24);animation:orb 20s ease-in-out infinite reverse}
.horbs i:nth-child(3){width:260px;height:260px;bottom:-90px;left:42%;background:rgba(99,102,241,.20);animation:orb 24s ease-in-out infinite}
@keyframes orb{50%{transform:translate(40px,32px) scale(1.14)}}

/* ---------------------------------------------------------------- rotating headline word
   The rotator is the last thing on line 1 and "to the cloud" is forced onto line 2, so a
   longer word never reflows the rest of the heading. `.rot b` is width:max-content so JS
   can measure the intrinsic text width; if the words were plain blocks they would inherit
   the container width and every measurement would return the same number. */
/* THE SLOT MUST BE AS TALL AS THE STEP, OR THE NEIGHBOURING WORD BLEEDS IN.
   Bug found 2026-08-10: with a 1.1em slot, the two `p` descenders of "support desk" hung
   below their own box and painted inside the window while "whole office" -- the next word
   in the stack -- was at rest, reading as two stray blue marks above the heading. Only that
   pair showed it, because "support desk" is the only word with descenders sitting directly
   above another word.

   The rule: glyph ink runs from (baseline - ascent) to (baseline + descent), which is taller
   than the 1.1em line box. If the step between words equals the line box, a neighbour's ink
   is always inside the window. So the slot (and the step, and the window, which are all the
   same number) is 1.5em -- big enough to hold the whole glyph box, so each word's ink stays
   in its own slot.

   The negative margins are what keep that off the layout. .rot is an inline-block, so its
   MARGIN box is what sizes line 1 of the h1: 1.5em - .2 - .2 = 1.1em, exactly what it
   contributed before. Without them line 1 grows .4em, "to the cloud" drops with it, and the
   hero gets taller -- which 360x640 cannot afford (it is already 2px over). Verified: h1 box
   and line 2 position unchanged to the pixel.
   If the type ever changes, re-check 1.5em against the new font's ascent+descent. */
.rot{display:inline-block;position:relative;height:1.5em;overflow:hidden;vertical-align:bottom;
  margin-top:-.2em;margin-bottom:-.2em;
  transition:width .5s cubic-bezier(.65,0,.25,1)}
.rot-in{display:block}
.rot b{display:block;width:max-content;height:1.5em;line-height:1.5;white-space:nowrap;
  font-weight:inherit;color:var(--brand)}

/* ==========================================================================
   THE HERO CONSOLE (.cine)
   --------------------------------------------------------------------------
   Replaced the side-by-side dial card (2026-08-06, client). The heading is now
   centred and the visual runs full width underneath it as one landscape
   console that plays a whole call in six acts:

     1 dial  2 department (IVR)  3 right person  4 live monitoring
     5 listen / whisper / merge  6 recording + quality + transcript

   Three rules hold this together and none of them are optional.

   1. EVERYTHING SCALES OFF ONE KNOB. `.cine` sets a font-size with clamp() and
      every size inside is in `em`. That is the only way six panels this dense
      stay proportional from 1440px down to 900px without six sets of
      breakpoints. Do not put px sizes in here.
      Because em compounds, font-size is set on TEXT LEAVES ONLY. Containers
      keep the base size, so their em padding and heights all mean the same
      thing. Set font-size on a container and every child measurement under it
      silently changes.

   2. THE STAGE IS A FIXED BOX. `.cine-stage` has a fixed em height and every
      act is `position:absolute;inset:0` inside it. The six acts are wildly
      different heights, so anything else would resize the hero and shove the
      whole page up and down twice a minute. Same rule the old dial card had.

   3. IT IS A DEMO, NOT A CONTROL. Every control inside is a span, `.cine` is
      pointer-events:none and the console is aria-hidden. Nothing in here may
      use :hover, :active or :disabled, because none of them can fire. If it is
      ever made interactive the spans have to become buttons first, or it turns
      into a keyboard trap of unlabelled controls.
   ========================================================================== */
.cine{
  --cl:rgba(255,255,255,.10);        /* hairline */
  --cl2:rgba(255,255,255,.16);       /* hairline, lit */
  --cs:rgba(255,255,255,.045);       /* card surface */
  --ct:#E9EFFB;                      /* bright text */
  --cm:#8E9DBD;                      /* muted text */
  --cg:#34D399;                      /* good / connected */
  --cw:#FBBF24;                      /* waiting */
  --cr:#F87171;                      /* ended / poor */
  position:relative;z-index:1;margin-top:clamp(12px,2.3vh,52px);pointer-events:none;
  font-size:clamp(8.6px,.86vw,11px);
  border-radius:2.2em;padding:1.1em;overflow:hidden;
  background:linear-gradient(168deg,#111A33 0%,#0B1020 52%,#0D1428 100%);
  border:1px solid rgba(255,255,255,.08);
  box-shadow:0 40px 90px -40px rgba(11,16,32,.55),0 2px 0 rgba(255,255,255,.05) inset;
}
/* a slow brand wash across the console so it does not read as a flat black slab */
.cine::before{content:'';position:absolute;inset:-40% -10% auto;height:80%;pointer-events:none;
  background:radial-gradient(60% 60% at 50% 50%,rgba(59,130,246,.22),transparent 70%);
  animation:cwash 14s ease-in-out infinite}
@keyframes cwash{50%{transform:translate(6%,10%) scale(1.15)}}

/* The console window chrome (.cine-top / .cdots / .ctop-t / .ctop-l -- three dots, the
   "CloudCall console" title and the Live pill) was removed on 2026-08-10 at the client's
   request, markup and CSS. It was 2.9em tall with 1em of margin, so the console is that much
   shorter now. `.cine.tight .cine-top` went with it. */

/* ------------------------------------------------------------ journey strip
   The spine of the story: the same five nodes light up left to right across the
   first three acts, so the viewer can see how far the call has actually got.
   Acts 4-6 mark every node done, because they are the same call after it
   landed. The strip never changes height, so it never moves the stage. */
.cine-body{position:relative;
  /* THE STAGE IS LIGHT, THE SHELL IS DARK (client, 2026-08-06). The console now reads
     like a real product screenshot: dark chrome around a white app. Every token is
     re-pointed here for light surfaces, which is why almost nothing underneath needed
     a per-rule edit -- only the rules that hardcoded a white background or white text
     did, because those are the ones the tokens could not reach. If you add a component
     to an act, use var(--cs)/--ct/--cm/--cl and it inherits the right side automatically. */
  --cl:rgba(16,28,54,.10);          /* hairline */
  --cl2:rgba(16,28,54,.20);         /* hairline, lit */
  --cs:#fff;                        /* card surface */
  --ct:#0E1A33;                     /* strong text */
  --cm:#5C6E92;                     /* muted text */
  --cg2:#0E9C6C;                    /* green that still reads on white */
  --cw2:#B45309;                    /* amber that still reads on white */
  --cf:#F5F8FD;                     /* the inset fill: rows, keys, chips */
  padding:1.35em 1.2em 1.5em;border-radius:1.7em;
  background:linear-gradient(180deg,#F8FAFF 0%,#EAF0FA 100%);
  box-shadow:0 1.4em 3.4em -1.4em rgba(5,10,24,.55),0 0 0 1px rgba(10,18,38,.07) inset}
/* a faint dot grid: what stops a large flat light panel reading as blank paper */
.cine-body::before{content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  background-image:radial-gradient(rgba(29,78,216,.09) 1px,transparent 1px);background-size:22px 22px;
  -webkit-mask-image:linear-gradient(175deg,#000,transparent 62%);
  mask-image:linear-gradient(175deg,#000,transparent 62%)}
.cflow{position:relative;display:flex;align-items:flex-start;gap:.4em;height:5.6em;
  padding:0 .8em;margin-bottom:.7em}
.cfn{position:relative;flex:1;display:flex;flex-direction:column;align-items:center;gap:.55em;
  color:var(--cm);transition:color .35s}
/* box-sizing is border-box site-wide, so a padded icon's width is the WHOLE circle, not
   the glyph. Sized the other way round these collapsed to nothing and the strip rendered
   as five bare dots. Same trap in .csl and .cmode below. */
.cfn .ic-svg{position:relative;z-index:1;width:2.9em;height:2.9em;padding:.78em;border-radius:50%;
  background:#fff;border:1px solid var(--cl);box-shadow:0 .2em .5em -.2em rgba(12,22,45,.2);
  transition:all .35s}
.cfn b{font-size:1.02em;font-weight:600;color:inherit;letter-spacing:.01em;white-space:nowrap}
/* the connector runs from the previous node's dot to this one, behind both */
.cfn::before{content:'';position:absolute;top:1.55em;right:calc(50% + 1.7em);width:calc(100% - 3.4em);
  height:2px;border-radius:2px;background:var(--cl);transition:background .35s}
.cfn:first-child::before{display:none}
.cfn.done{color:#31456B}
.cfn.done .ic-svg{color:#fff;background:var(--brand);border-color:var(--brand)}
.cfn.done::before{background:var(--brand)}
.cfn.on{color:#12276B}
.cfn.on .ic-svg{color:#fff;background:var(--brand);border-color:var(--brand-3);
  box-shadow:0 0 0 .35em rgba(59,130,246,.22);animation:cpulse 1.6s ease-out infinite}
.cfn.on::before{background:var(--brand)}
@keyframes cpulse{from{box-shadow:0 0 0 .2em rgba(59,130,246,.35)}to{box-shadow:0 0 0 1.5em rgba(59,130,246,0)}}
/* acts 4-6 are past the routing, so the strip steps back and stops competing */
.cine[data-act="wall"] .cflow,.cine[data-act="super"] .cflow,.cine[data-act="after"] .cflow{opacity:.55}

/* ------------------------------------------------------------ the stage
   Fixed height, absolutely positioned acts. See rule 2 at the top. */
.cine-stage{position:relative;z-index:1;height:30em}
.cact{position:absolute;inset:0;display:grid;gap:1em;opacity:0;visibility:hidden;
  transform:translateY(1.1em) scale(.99);transition:opacity .5s,transform .5s,visibility .5s}
.cine[data-act="call"]  .cact[data-a="call"],
.cine[data-act="ivr"]   .cact[data-a="ivr"],
.cine[data-act="agent"] .cact[data-a="agent"],
.cine[data-act="wall"]  .cact[data-a="wall"],
.cine[data-act="super"] .cact[data-a="super"],
.cine[data-act="after"] .cact[data-a="after"]{opacity:1;visibility:visible;transform:none}
.cact[data-a="call"]{grid-template-columns:21em 1fr}
.cact[data-a="ivr"]{grid-template-columns:1fr 1fr}
.cact[data-a="agent"]{grid-template-columns:1.3fr 1fr}
.cact[data-a="wall"]{grid-template-columns:1fr}
.cact[data-a="super"]{grid-template-columns:1.2fr 1fr}
.cact[data-a="after"]{grid-template-columns:1.05fr 1fr}

/* ------------------------------------------------------------ shared panel parts */
.ccard{position:relative;display:flex;flex-direction:column;min-height:0;padding:1.3em 1.4em;
  border-radius:1.4em;background:var(--cs);border:1px solid var(--cl);
  box-shadow:0 .1em .2em rgba(14,26,51,.04),0 .9em 2em -.9em rgba(14,26,51,.18)}
.ccard.mid{align-items:center;justify-content:center;text-align:center}
.ccol{display:grid;grid-template-rows:auto 1fr;gap:1em;min-height:0}
.cwrapfull{display:flex;flex-direction:column;gap:1em;min-height:0}
.cch{display:flex;align-items:center;gap:.6em;margin-bottom:1em;font-size:1.12em;font-weight:700;
  color:var(--ct);letter-spacing:.01em}
.cch .ic-svg{width:1.25em;height:1.25em;color:var(--brand)}
.cfoot{display:flex;align-items:center;gap:.9em;margin-top:auto;padding-top:1em}
.cfoot small{font-size:.98em;line-height:1.45;color:var(--cm)}
.cmini{display:block;margin-top:.9em;font-size:.98em;color:var(--cm)}
.cpill{display:inline-flex;align-items:center;gap:.45em;flex:none;padding:.45em .95em;border-radius:100px;
  font-size:.95em;font-weight:700;color:#41547B;background:var(--cf);
  border:1px solid var(--cl);white-space:nowrap;transition:all .3s}
.cpill .ic-svg{width:1.15em;height:1.15em}
.cpill.ok{color:#0A7A55;background:#E3F7EF;border-color:#A3E3CA}
.cpill.rec{color:#C2352F;background:#FDECEB;border-color:#F5C3C0}
.cpill.live{color:var(--brand-deep);background:#E7F0FE;border-color:#AFCFF9}
.cpill.auto{margin-left:auto;font-size:.85em;text-transform:uppercase;letter-spacing:.1em;
  color:var(--brand-deep);background:#E7F0FE;border-color:#AFCFF9}
/* the avatar is the one shape that repeats in every act, so the acts read as one system */
.cav{display:grid;place-items:center;width:2.6em;height:2.6em;border-radius:50%;flex:none;
  font-size:1em;font-weight:700;color:#fff;letter-spacing:.02em;
  background:linear-gradient(150deg,var(--brand-2),var(--brand-deep));
  box-shadow:0 .3em .9em -.3em rgba(29,78,216,.7)}
.cav.big{width:4.6em;height:4.6em;font-size:1.5em}
.cav.ag{background:linear-gradient(150deg,#22C55E,#0EA5E9)}
.cav.me{background:linear-gradient(150deg,#F59E0B,#DC2626)}
.cav.me .ic-svg{width:1.3em;height:1.3em}
.cag-i{min-width:0}
.cag-i b{display:block;font-size:1.05em;font-weight:700;color:var(--ct);line-height:1.25;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cag-i small{font-size:.92em;color:var(--cm)}
/* the talking waveform, shared by acts 3 and 5 */
.cwave{display:flex;align-items:center;justify-content:center;gap:.28em;height:3.6em;margin:1.2em 0}
.cwave.sm{height:2.6em;margin:1em 0 .8em}
.cwave i{width:.28em;height:.4em;border-radius:.2em;background:#D5E3F8}
.cine[data-act="agent"] .cact[data-a="agent"] .cwave i,
.cine[data-act="super"] .cwave i{background:linear-gradient(180deg,var(--brand-3),var(--accent));
  animation:cwv .9s ease-in-out infinite}
.cwave i:nth-child(2n){animation-duration:.7s;animation-delay:-.2s}
.cwave i:nth-child(3n){animation-duration:1.1s;animation-delay:-.45s}
.cwave i:nth-child(5n){animation-duration:.82s;animation-delay:-.65s}
.cwave i:nth-child(7n){animation-duration:1.25s;animation-delay:-.15s}
@keyframes cwv{0%,100%{height:.4em}50%{height:2.9em}}

/* ------------------------------------------------------------ act 1: the call comes in
   Client, 2026-08-10: this act was a softphone DIALPAD typing a number out, which told the
   wrong story -- everything after it is one inbound call being routed, so the opening frame
   has to be the call ARRIVING. `.cpad`, `.cpad-scr`, `.cpad-keys`, `.ck`, `.cpad-go` and
   the `cur` caret keyframe are deleted, not repurposed; the JS that drove them went too.
   (Written without the at-rule spelling on purpose: it would show up in every grep for a
   keyframe definition and read as one.)

   It is still a display-only demo: `.cin-b` are spans, nothing here uses :hover, and the
   whole console is pointer-events:none and aria-hidden. */
.cin{display:flex;flex-direction:column;align-items:center;text-align:center;
  padding:1.4em 1.2em;border-radius:1.4em;
  background:linear-gradient(170deg,#FFFFFF,#F4F8FE);border:1px solid var(--cl);
  box-shadow:0 .1em .2em rgba(14,26,51,.04),0 .9em 2em -.9em rgba(14,26,51,.18)}
.cin-eb{display:inline-flex;align-items:center;gap:.45em;padding:.35em .8em;border-radius:999px;
  font-size:.92em;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--brand);background:#E8F0FE;border:1px solid #CFE0FB}
.cin-eb .ic-svg{width:1.1em;height:1.1em}
/* the ringing avatar. box-sizing is border-box site-wide, so the padded glyph's width is
   the whole disc -- sizing this the other way round collapses the content box to zero and
   the icon disappears. Same trap as .cfn/.csl/.cmode. */
.cin-av{position:relative;display:grid;place-items:center;width:4.6em;height:4.6em;margin:1em 0 .8em;
  border-radius:50%;color:#fff;background:linear-gradient(150deg,var(--brand-2),var(--brand-deep));
  box-shadow:0 .6em 1.6em -.5em rgba(29,78,216,.7)}
.cin-av .ic-svg{width:2.1em;height:2.1em}
/* the ring itself is a pseudo-free element so it can scale past the avatar without
   affecting layout; it stops the moment the call is answered */
.cin-pulse{position:absolute;inset:0;border-radius:50%;border:2px solid var(--brand-2);
  animation:cring 1.6s ease-out infinite}
@keyframes cring{0%{transform:scale(1);opacity:.85}100%{transform:scale(1.75);opacity:0}}
.cin.answered .cin-pulse{animation:none;opacity:0}
.cin.answered .cin-av{background:linear-gradient(150deg,#22C55E,#15803D);
  box-shadow:0 .6em 1.6em -.5em rgba(34,197,94,.65)}
.cin-num{font-size:1.8em;font-weight:700;line-height:1.2;color:var(--ct);letter-spacing:.02em;
  font-variant-numeric:tabular-nums}
.cin-loc{display:block;margin-top:.25em;font-size:1em;color:var(--cm)}
.cin-on{display:flex;align-items:center;gap:.5em;margin-top:.9em;padding:.5em .85em;border-radius:.8em;
  font-size:.95em;color:var(--cm);background:var(--cf);border:1px solid var(--cl)}
.cin-on .ic-svg{width:1.15em;height:1.15em;flex:none;color:var(--brand)}
/* b inherits the global near-black ink, which is right on this white card -- but state it
   so a later palette move cannot silently take it somewhere else */
.cin-on b{color:var(--ct);font-weight:700}
.cin-btns{display:flex;gap:.7em;margin-top:auto;padding-top:1.1em}
.cin-b{display:inline-flex;align-items:center;justify-content:center;gap:.5em;height:2.8em;
  border-radius:.85em;font-size:1.02em;font-weight:700;color:#fff;transition:transform .2s}
.cin-b .ic-svg{width:1.15em;height:1.15em}
.cin-b.dec{width:2.8em;background:linear-gradient(150deg,#F87171,#DC2626)}
.cin-b.acc{padding:0 1.3em;background:linear-gradient(150deg,#22C55E,#15803D);
  box-shadow:0 .5em 1.4em -.5em rgba(34,197,94,.8)}
.cin-b.acc.hit{transform:scale(.95)}
.cin.answered .cin-b.dec{opacity:.35}
.cin-st{margin-top:.8em;font-size:.95em;font-weight:600;color:var(--cm)}
.cin.answered .cin-st{color:var(--cg2)}
/* flex:1 with space-between, or the four rows huddle at the top of a tall card */
.cset{flex:1;display:flex;flex-direction:column;justify-content:space-between;gap:.7em;list-style:none}
.csl{display:flex;align-items:center;gap:.75em;padding:.9em 1em;border-radius:.9em;
  background:var(--cf);border:1px solid transparent;opacity:.45;
  transition:opacity .4s,background .4s,border-color .4s}
.csl .ic-svg{width:1.8em;height:1.8em;padding:.4em;border-radius:50%;color:#8496B7;
  background:#E5ECF7;transition:all .4s}
.csl span{font-size:1.05em;font-weight:600;color:var(--ct)}
.csl small{margin-left:auto;font-size:.95em;color:var(--cm)}
.csl.on{opacity:1;background:#E9F9F2;border-color:#A9E3CC}
.csl.on .ic-svg{color:#fff;background:var(--cg2)}

/* ------------------------------------------------------------ act 2: the IVR */
.civ-say{padding:.95em 1.1em;margin-bottom:1em;border-radius:.9em;font-size:1.05em;line-height:1.55;
  color:#33456B;background:#EEF5FF;border:1px solid #CFE1FC;
  border-left:.25em solid var(--brand-2)}
.civ-say b{color:var(--brand-deep)}
.civ-list{display:flex;flex-direction:column;gap:.7em}
.civ{display:flex;align-items:center;gap:.85em;padding:.8em 1em;border-radius:1em;
  background:var(--cf);border:1px solid var(--cl);transition:all .35s}
.civ-k{display:grid;place-items:center;width:2.2em;height:2.2em;flex:none;border-radius:.65em;
  font-size:1.05em;font-weight:700;color:var(--ct);background:#fff;
  border:1px solid var(--cl2);transition:all .35s}
.civ div{min-width:0}
.civ b{display:block;font-size:1.08em;font-weight:700;color:var(--ct);line-height:1.25}
.civ small{font-size:.92em;color:var(--cm)}
.civ .ic-svg{margin-left:auto;width:1.2em;height:1.2em;color:#9AA9C4;transition:color .35s}
.civ.hit .civ-k{transform:scale(.9);background:var(--brand);border-color:var(--brand-3);color:#fff}
.civ.pick{background:#E8F1FE;border-color:#9DC2F7}
.civ.pick .civ-k{color:#fff;background:var(--brand);border-color:var(--brand-3)}
.civ.pick .ic-svg{color:var(--brand)}
.civ.dim{opacity:.28}
.cdept{display:flex;align-items:center;gap:.9em;padding:1.1em 1.2em;margin-bottom:1em;border-radius:1.1em;
  background:linear-gradient(140deg,var(--brand-2),var(--brand-deep));border:1px solid transparent;
  box-shadow:0 .8em 1.8em -.8em rgba(23,57,168,.75)}
.cdept-ic{display:grid;place-items:center;width:2.8em;height:2.8em;flex:none;border-radius:.9em;
  color:#fff;background:rgba(255,255,255,.18);border:1px solid rgba(255,255,255,.25)}
.cdept-ic .ic-svg{width:1.4em;height:1.4em}
.cdept b{display:block;font-size:1.5em;font-weight:700;color:#fff;line-height:1.15}
.cdept small{font-size:.95em;color:#C7DBFA}
.crule{display:flex;align-items:center;gap:.55em;flex-wrap:wrap}
.crule i{color:#9AA9C4;display:inline-flex}
.crule i .ic-svg{width:1.1em;height:1.1em}
/* shared stat strip: sits under the rule in act 2 and under the meter in act 6 */
.cstats,.cq-stats{display:flex;gap:1.2em;margin-top:auto;padding-top:1em;font-size:.95em;color:var(--cm)}
.cstats b,.cq-stats b{color:var(--ct);font-weight:700}
.cstats{margin-top:1.1em}
.cru{padding:.5em .9em;border-radius:.7em;font-size:.98em;font-weight:600;color:var(--cm);
  background:var(--cf);border:1px solid var(--cl)}
.cru.on{color:#fff;background:var(--brand);border-color:var(--brand)}

/* ------------------------------------------------------------ act 3: the right person */
.cag-list{display:flex;flex-direction:column;gap:.7em}
.cag{display:flex;align-items:center;gap:.85em;padding:.85em 1em;border-radius:1em;
  background:var(--cf);border:1px solid var(--cl);transition:all .35s}
.cag-s{margin-left:auto;flex:none;padding:.4em .85em;border-radius:100px;font-size:.9em;font-weight:700;
  color:var(--cm);background:#E9EFF8;transition:all .35s}
.cag.ringing{background:#E9F1FE;border-color:#A9CBF9}
.cag.ringing .cag-s{color:var(--brand-deep);background:#CFE2FD;animation:blink .8s infinite}
.cag.answered{background:#E5F8F0;border-color:#96DFC1}
.cag.answered .cag-s{color:#fff;background:var(--cg2);animation:none}
.cag.dropped{opacity:.3}
.clive-n{display:block;margin-top:.9em;font-size:1.45em;font-weight:700;color:var(--ct)}
.clive-s{display:block;margin-top:.3em;font-size:1em;font-weight:600;color:var(--cm);transition:color .3s}
.clive-s.up{color:var(--cg2)}
.clive-t{font-size:1.5em;font-weight:700;color:var(--ct);font-variant-numeric:tabular-nums}
.cbadges{display:flex;gap:.6em;margin-top:1.1em}

/* ------------------------------------------------------------ act 4: the wallboard */
.ckpis{display:grid;grid-template-columns:repeat(4,1fr);gap:.9em;flex:none}
.ckpi{padding:.85em 1.1em;border-radius:1em;background:var(--cs);border:1px solid var(--cl);
  box-shadow:0 .1em .2em rgba(14,26,51,.04),0 .7em 1.6em -.8em rgba(14,26,51,.18)}
.ckpi small{display:block;font-size:.95em;color:var(--cm)}
.ckpi b{display:block;margin-top:.15em;font-size:1.9em;font-weight:700;color:var(--ct);
  font-variant-numeric:tabular-nums;line-height:1.1}
.cwall{flex:1;min-height:0;display:grid;grid-template-columns:repeat(4,1fr);grid-auto-rows:1fr;gap:.8em}
.wag{position:relative;display:flex;align-items:center;gap:.7em;padding:.8em .9em;border-radius:1em;
  overflow:hidden;background:var(--cs);border:1px solid var(--cl);transition:all .4s;
  box-shadow:0 .1em .2em rgba(14,26,51,.04),0 .7em 1.6em -.8em rgba(14,26,51,.16)}
.wag-s{margin-left:auto;flex:none;padding:.35em .75em;border-radius:100px;font-size:.85em;font-weight:700;
  color:var(--cm);background:#EDF1F8;transition:all .35s;white-space:nowrap}
/* the bar along the bottom of a tile is how long that agent has been on the call */
.wag-t{position:absolute;left:0;bottom:0;height:.2em;width:0;background:var(--cg2);transition:width 1.1s linear}
.wag.ring{background:#E9F1FE;border-color:#A9CBF9}
.wag.ring .wag-s{color:var(--brand-deep);background:#CFE2FD;animation:blink .8s infinite}
.wag.call{background:#E5F8F0;border-color:#96DFC1}
.wag.call .wag-s{color:#fff;background:var(--cg2);animation:none}
/* `.wag.wrap` (the amber wrap-up tile) is deleted -- CloudCall has no wrap-up feature
   and the console may only show what the portal does (client, 2026-08-10). */
.wag.idle .cav{filter:grayscale(.55);opacity:.75}
/* the tile the supervisor is about to open gets picked out before act 5 takes over */
.wag.sel{border-color:var(--brand-2);box-shadow:0 0 0 .22em rgba(59,130,246,.25)}

/* ------------------------------------------------------------ act 5: listen / merge */
/* margin-auto top and bottom centres the block between the card heading and the
   bottom edge, instead of letting it pile up under the heading */
.cparty{display:flex;align-items:center;justify-content:center;gap:1.6em;margin-top:auto}
.cpt{display:flex;flex-direction:column;align-items:center;gap:.6em}
.cpt small{font-size:.95em;font-weight:600;color:var(--cm)}
.cpt .cav{width:3.6em;height:3.6em;font-size:1.15em}
/* the supervisor only appears once the call is actually merged */
.cpt.add{opacity:0;transform:scale(.7) translateY(.6em);transition:opacity .45s,transform .45s}
.cpt.add.in{opacity:1;transform:none}
.cnote{margin-bottom:auto;min-height:2.9em;font-size:1.02em;line-height:1.45;text-align:center;color:#4C5E82}
.cnote b{color:var(--ct)}
.cmodes{flex:1;display:flex;flex-direction:column;justify-content:center;gap:.75em}
.cmode{display:flex;align-items:center;gap:.8em;padding:.85em 1em;border-radius:1em;
  background:var(--cf);border:1px solid var(--cl);opacity:.5;transition:all .4s}
.cmode .ic-svg{width:2.4em;height:2.4em;padding:.55em;border-radius:.7em;color:#8496B7;
  background:#E5ECF7;transition:all .4s}
.cmode b{font-size:1.08em;font-weight:700;color:var(--ct)}
.cmode small{margin-left:auto;font-size:.92em;color:var(--cm);text-align:right}
.cmode.on{opacity:1;background:#E9F1FE;border-color:#A9CBF9}
.cmode.on .ic-svg{color:#fff;background:var(--brand)}
.cmode.done{opacity:.7}
.cmode.done .ic-svg{color:#fff;background:var(--cg2)}

/* ------------------------------------------------------------ act 6: after the call */
.cplay{display:flex;align-items:center;gap:.9em}
.cpb{display:grid;place-items:center;width:2.8em;height:2.8em;flex:none;border-radius:50%;color:#fff;
  background:var(--brand);box-shadow:0 .4em 1.2em -.4em rgba(29,78,216,.9)}
.cpb .ic-svg{width:1.2em;height:1.2em;margin-left:.1em}
.cbars{position:relative;flex:1;display:flex;align-items:center;gap:.22em;height:3em;overflow:hidden}
.cbars i{flex:1;height:var(--h);min-height:.25em;border-radius:.15em;
  background:linear-gradient(180deg,var(--brand-3),var(--accent))}
/* the scrim covers what has NOT played yet and shrinks to the right, so the bright bars
   are the played part and the scrim's left edge is the playhead */
.cbar-p{position:absolute;inset:0 0 0 auto;width:100%;pointer-events:none;
  background:linear-gradient(90deg,rgba(255,255,255,.88),rgba(255,255,255,.78));
  border-left:2px solid var(--brand);transition:width .25s linear}
.cdur{flex:none;font-size:1.05em;font-weight:700;color:var(--ct);font-variant-numeric:tabular-nums}
.cq{flex:1;display:flex;align-items:center;gap:1.2em}
.cq-score{display:flex;flex-direction:column;align-items:center;flex:none;padding:.6em 1em;
  border-radius:1em;background:#E5F8F0;border:1px solid #9FE2C7}
.cq-score b{font-size:2.2em;font-weight:700;color:var(--cg2);line-height:1}
.cq-score small{font-size:.85em;letter-spacing:.12em;text-transform:uppercase;color:#3E9B7B}
.cq-bar{position:relative;flex:1;padding-bottom:1.5em}
.cqbands{display:grid;grid-template-columns:1fr 1fr 1fr;gap:.3em}
.cqb{position:relative;height:.85em;border-radius:.45em}
.cqb b{position:absolute;top:1.25em;left:0;font-size:.92em;font-weight:600;color:var(--cm)}
.cqb.bad{background:#F7A7A4}
.cqb.mid{background:#FBCF6A}
.cqb.good{background:#63D8AB}
/* the marker slides to the score; JS sets --p, so the band it lands on is the verdict */
.cq-mark{position:absolute;top:-.35em;left:var(--p,4%);width:.5em;height:1.55em;border-radius:.3em;
  background:#0E1A33;box-shadow:0 0 0 .2em rgba(14,26,51,.13);transform:translateX(-50%);
  transition:left 1.2s cubic-bezier(.65,0,.25,1)}
.ctrs{flex:1;display:flex;flex-direction:column;justify-content:safe center;gap:.7em;min-height:0;overflow:hidden}
.ctr{display:flex;gap:.8em;opacity:0;transform:translateY(.7em);transition:opacity .45s,transform .45s}
.ctr.on{opacity:1;transform:none}
.ctr-w{flex:none;width:5.2em;padding:.35em 0;font-size:.92em;font-weight:700;color:var(--brand)}
.ctr-w.a{color:var(--cg2)}
.ctr-w.b{color:var(--cw2)}
.ctr p{font-size:1.02em;line-height:1.5;color:#32456A}

/* ------------------------------------------------------------ the caption
   The client asked for wording inside the picture saying which step this is.
   Fixed height, because the six captions are different lengths and this sits in
   the console's flow: let it grow and the whole hero grows with it. */
.cine-cap{display:flex;align-items:center;gap:1.1em;height:5em;margin-top:1em;padding:0 1.4em;
  border-radius:1.2em;background:rgba(255,255,255,.05);border:1px solid var(--cl)}
.cc-n{display:grid;place-items:center;width:2.9em;height:2.9em;flex:none;border-radius:.9em;
  font-size:1.15em;font-weight:800;color:#fff;font-variant-numeric:tabular-nums;
  background:linear-gradient(150deg,var(--brand-2),var(--brand-deep))}
.cc-tx{min-width:0}
.cc-tx b{display:block;font-size:1.25em;font-weight:700;color:#fff;line-height:1.25}
.cc-tx span{display:block;margin-top:.15em;font-size:1.02em;line-height:1.4;color:var(--cm)}

/* The STEP RAIL is gone (client, 2026-08-10, seventh pass: "remove the right side
   pointers ... 1234"). `.cine-rail`, `.cst*` and the `--rail-w` column with them, and
   `.cine` went back to a plain block -- the `.cine-main` wrapper only existed to stack
   the body and caption beside that column. The rail had two lives in one day (a strip
   under the stage, then a right-hand column) and neither survived; do not add a third
   without asking. The CAPTION is what names the act now, and it numbers them itself. */

/* ------------------------------------------------------------ the compact console
   When the leftover height would push the fitted font-size below ~8.6px, `fitCine()` in
   main.js adds `.tight` and re-fits. Shrinking the type alone turns the console into
   unreadable mush, so instead the things that cost height and carry the least meaning are
   dropped or compressed first, which buys the type back.

   Order of sacrifice, and why:
     1. the step rail        - it duplicates the caption strip word for word. NOTE it is a
                               right-hand COLUMN now, so dropping it buys width, not the
                               height it used to; the rungs below are what buy the height
     2. console chrome       - padding, the title bar, the journey strip
     3. the stage            - 30em -> 25em, which the acts absorb because their cards are
                               flex; the incoming-call card is the exception and is trimmed
                               by hand below, since its avatar and buttons are fixed em
   The caption never goes: it is the wording the client asked to have inside the picture. */
.cine.tight{padding:.85em;border-radius:1.7em}
.cine.tight .cine-body{padding:1em .9em 1.1em;border-radius:1.4em}
.cine.tight .cflow{height:4.3em;margin-bottom:.35em}
.cine.tight .cfn .ic-svg{width:2.4em;height:2.4em;padding:.62em}
.cine.tight .cfn::before{top:1.3em;right:calc(50% + 1.45em);width:calc(100% - 2.9em)}
.cine.tight .cine-stage{height:25em}
.cine.tight .cine-cap{height:4.2em;margin-top:.7em}
/* the acts give up padding before they give up rows */
.cine.tight .ccard{padding:1.05em 1.15em}
.cine.tight .cch{margin-bottom:.75em}
.cine.tight .cwave{height:2.8em;margin:.85em 0}
.cine.tight .cwave.sm{height:2.2em;margin:.7em 0 .6em}
.cine.tight .cav.big{width:4em;height:4em;font-size:1.32em}
.cine.tight .cfoot{padding-top:.75em}
.cine.tight .csl{padding:.72em .9em}
.cine.tight .civ{padding:.65em .9em}
.cine.tight .cag{padding:.68em .9em}
.cine.tight .cmode{padding:.68em .9em}
.cine.tight .cdept{padding:.9em 1.05em;margin-bottom:.8em}
.cine.tight .civ-say{padding:.65em .9em;margin-bottom:.55em;line-height:1.4}
.cine.tight .civ{padding:.5em .85em}
.cine.tight .civ-list{gap:.55em}
.cine.tight .cine-cap{height:4.2em;margin-top:.7em}
/* the dial pad is the one act built out of fixed-height parts, so it needs its own trim */
/* the incoming-call card is fixed em all the way down (avatar, buttons), so unlike the
   flex act cards it does not absorb the shorter stage on its own and is trimmed by hand */
.cine.tight .cin{padding:1.1em 1em}
.cine.tight .cin-av{width:3.9em;height:3.9em;margin:.75em 0 .6em}
.cine.tight .cin-num{font-size:1.55em}
.cine.tight .cin-btns{padding-top:.85em}
.cine.tight .cin-b{height:2.5em}

/* ------------------------------------------------------------ narrow screens
   A 2:1 landscape console cannot stay landscape on a phone and stay readable,
   so below 900px the acts stack into one column. The stage stays a FIXED box
   (taller one) and the acts stay absolute: that is still what keeps the hero
   from resizing, and every act is sized to fit inside it. If you add anything
   to an act, check it still fits here. */
@media(max-width:900px){
  .cine{font-size:10.4px;border-radius:1.6em}
  .cflow{height:5em;padding:0;gap:.2em}
  .cfn b{font-size:.92em}
  .cfn::before{top:1.45em;right:calc(50% + 1.5em);width:calc(100% - 3em)}
  .cine-stage{height:46em}
  .cact{grid-template-columns:1fr !important;align-content:start}
  .cact[data-a="call"]{grid-template-rows:auto 1fr}
  .ccol{display:contents}
  .cwall{grid-template-columns:repeat(2,1fr)}
  .ckpis{grid-template-columns:repeat(2,1fr)}
  .cav.big{width:3.8em;height:3.8em;font-size:1.3em}
  .cq-stats{gap:.8em;flex-wrap:wrap}
  .cine-cap{height:5.6em}
}
@media(max-width:620px){
  .cine{font-size:9.6px}
  /* the journey strip loses its labels before it loses its shape */
  .cfn b{display:none}
  .cflow{height:3.4em}
  .cine-stage{height:48em}
  /* the wallboard stays two across: at one column the idle pair falls off the
     bottom, and the whole point of the act is that you can see them */
  .cwall{gap:.6em}
  .wag{padding:.7em}
  .wag-s{font-size:.8em;padding:.3em .6em}
  .cin-av{width:4.2em;height:4.2em}
  .cmode small{display:none}
  .csl small{display:none}
  .ctr-w{width:4.4em}
}

/* --------------------------------------------------------- the minimal console
   `.mini` is the second rung below `.tight`: main.js adds it when even the compact
   console would have to render below ~8.8px. It keys off HOW SMALL THE CONSOLE ACTUALLY
   GOT, not off screen width, because a 1280x630 laptop is in exactly the same bind as a
   phone -- it just gets there by a different route.

   What goes is the EXPLANATORY furniture; what stays is everything that moves. The
   caption strip under the stage already says what each act means, which is precisely
   what the panel footers, the spoken IVR line and the secondary stat strips were
   repeating. Losing them costs nothing a viewer was reading at that size anyway. */
.cine.mini .ccard{padding:.85em .95em;overflow:hidden}
.cine.mini .cch{margin-bottom:.6em}
.cine.mini .cfoot{display:none}
.cine.mini .civ-say{display:none}
.cine.mini .cstats{display:none}
.cine.mini .cbadges{display:none}
.cine.mini .cnote{display:none}
.cine.mini .cq-stats,.cine.mini .cmini{display:none}
.cine.mini .csl:nth-child(3),.cine.mini .csl:nth-child(4){display:none}
.cine.mini .csl{padding:.45em .7em}
.cine.mini .csl .ic-svg{width:1.5em;height:1.5em;padding:.32em}
/* act 3's queue rows are sized by their two lines of text, not by the avatar, so the
   second line is what has to go. The wallboard in act 4 keeps its extensions: it fits. */
.cine.mini .cag{padding:.5em .8em}
.cine.mini .cag .cag-i small{display:none}
.cine.mini .cag-list{gap:.5em}
.cine.mini .cav.big{width:3.1em;height:3.1em;font-size:1.05em}
.cine.mini .cwave{height:2em;margin:.55em 0}
.cine.mini .clive-n{margin-top:.6em;font-size:1.2em}
.cine.mini .clive-s{font-size:.9em}
.cine.mini .clive-t{font-size:1.15em}
.cine.mini .ctr{gap:.6em}
/* act 1 is the tallest act anywhere, because the pad is built from fixed-height parts */
.cine.mini .cin{padding:.85em .8em}
.cine.mini .cin-av{width:3.2em;height:3.2em;margin:.55em 0 .45em}
.cine.mini .cin-av .ic-svg{width:1.5em;height:1.5em}
.cine.mini .cin-num{font-size:1.35em}
/* the two lines the card can lose without losing the point: it still says who is
   calling, on what number it landed and that it is ringing */
.cine.mini .cin-on{display:none}
.cine.mini .cin-btns{padding-top:.7em}
.cine.mini .cin-b{height:2.2em;font-size:.95em}

/* ------------------------------------------------------------ compact, narrow
   These are the rules that really are about WIDTH: stacked acts are roughly twice the
   height of the landscape ones, so the stage box itself has to be a different size. The
   wallboard drops two tiles here, chosen so the story survives - act 4 keeps BOTH idle
   agents, because "two are free and ready" is the whole point of that act. */
@media(max-width:900px){
  .cine.tight .cine-stage{height:33em}
  .cine.tight .cine-cap{height:4.6em}
  .cine.tight .cflow{height:3.9em}
  .cine.mini .wag:nth-child(5),.cine.mini .wag:nth-child(6){display:none}
}
@media(max-width:620px){
  .cine.tight .cine-stage{height:34em}
  .cine.tight .cflow{height:3.2em}
}
/* The last thing there is to give: on a small AND short phone (a 320x568 class device)
   the journey strip goes. It is five unlabelled dots at that size, and dropping it is
   what gets the console inside the screen instead of 15px past it. Both conditions are
   required: a 1152x600 desktop is short too, and there the strip still reads. */
@media(max-width:620px) and (max-height:600px){
  .cine.mini .cflow{display:none}
}
}

/* A `@media(max-width:460px){.dh-l1 .rot{display:block}}` override used to sit here, to give
   the rotator its own line on small phones where "Move your support desk" would not fit.
   It is gone and is NOT needed: measured at 360 and 390, line 1 at the 24px clamp floor inks
   271px against a 287px / 316px column, so it fits on one line with room. If the rotator ever
   gains a longer word, re-measure here first -- this is the tightest point on the site. */
@keyframes flo{50%{transform:translateY(-11px)}}

/* ---------------------------------------------------------------- LIGHT platform band
   Client, 2026-08-10: this was `sec dark` sitting directly under the equally dark clients
   band and the two read as one block. It is light now, and deliberately a TINTED light --
   a soft blue wash rather than plain --page. The feature rows immediately below it are
   `sec light` (flat white), so an untinted band here would have swapped one same-background
   pair for another. The rhythm through the page is: dark clients / tinted platform /
   white features / dark how-it-works.
   `.sxs` was re-coloured for this at its own rule; there is no dark spec index left. */
.plat-sec{background:
  radial-gradient(900px 460px at 50% -12%,rgba(29,78,216,.10),transparent 64%),
  linear-gradient(180deg,#EDF2FC 0%,#F7F9FE 62%,var(--page) 100%)}

/* --------------------------------------------------------- clients (dark scrolling logos)
   Fourth version. Marquee rows -> ten separate dark cards -> one bordered hairline panel ->
   SCROLLING again (client, 2026-08-10: "make them scroll"). The static wall lasted hours.
   The band itself stays dark: with the platform band below it now light, this is the only
   dark section between the hero and the feature rows.

   The marks are drawn LIGHT because they sit on navy. **If the real client logos arrive as
   dark ink on transparent, this whole band has to go light or they will vanish** -- the
   same warning that has stood since the first dark version. */
.clients-sec{position:relative;overflow:hidden;padding:78px 0 70px;
  background:radial-gradient(1000px 520px at 50% -10%,#17224A,transparent 62%),var(--ink);
  color:#9DAAC4}
.clients-sec h2{color:#fff}
.clients-sec .sh p,.clients-sec .shx-p{color:#8FA0BF}
/* one soft brand bloom behind the row, so the navy is not a flat slab */
.cl-glow{position:absolute;left:50%;top:38%;width:900px;height:520px;transform:translateX(-50%);
  background:radial-gradient(closest-side,rgba(29,78,216,.20),transparent 72%);
  pointer-events:none;filter:blur(10px)}
.clients-sec .wrap{position:relative;z-index:1}
/* THE LOGOS SCROLL (client, 2026-08-10). This replaced the static hairline wall from
   earlier the same day. Two identical sets, translated -50% = exactly one set, so the loop
   is seamless. See the note in client_logos() for why the count is 2 and why the seam gap
   is the SET's padding-right rather than a gap on the track.

   `.lgmq` sits OUTSIDE `.wrap` so the row runs the full width of the band and the marks
   scroll out of the viewport edges rather than stopping short at a 1200px column; the
   heading and the note above and below it stay in `.wrap`. The mask is what makes them
   fade at the edges instead of being chopped off. */
.lgmq{position:relative;overflow:hidden;margin:10px 0 14px;
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 7%,#000 93%,transparent 100%);
  mask-image:linear-gradient(90deg,transparent 0,#000 7%,#000 93%,transparent 100%)}
/* TWO ROWS, opposite directions (client, 2026-08-10). They carry different halves of the
   logo list, not the same marks twice.

   TWO sets per row, and -50% per cycle = exactly one set. The count is arithmetic: the
   real logo pack is 36 marks (41 supplied, 5 pulled as too soft -- see client_logos()), so
   a row is 18 of them and one set is 18 x 210 + 18 x 14 = 4032px -- already past any
   viewport, where the old five-mark row needed three sets to clear 2560px. Change the item width, the gap or the logo count and
   re-derive BOTH the set count and the keyframe percentage; they are the same number and
   must move together.

   The DURATION is not taste either: it is set so the marks keep moving at the speed they
   did before, ~24px/s. One set is 4032px against the old 1120px, so the cycle is 166s where
   it was 46s for the same apparent pace. Shorten it and the row visibly races. */
.lgtrack{display:flex;gap:0;width:max-content;animation:lgm 166s linear infinite}
.lgtrack+.lgtrack{margin-top:14px}
/* reverse is the same keyframe played backwards -- one keyframe, no second @keyframes block
   to keep in step with the first */
.lgtrack.rev{animation-direction:reverse;animation-duration:195s}
/* the seam: each set carries the item gap as trailing padding, so the distance between the
   last mark of one set and the first of the next equals the gap inside a set */
.lgset{display:flex;gap:14px;padding-right:14px}
.lgitem{flex:none;width:210px;display:grid;place-items:center;padding:24px 18px;
  border-radius:16px;background:var(--ink-2);border:1px solid #252F4E;color:#8496B8;
  transition:color .25s,background .25s,border-color .25s}
/* Every logo file is the SAME pixel box with the mark already centred and optically sized
   inside it (see mklogos.py / LOGOS), so the box is fixed here and nothing is left to
   object-fit: one file cannot render taller or wider than its neighbour. The files are 3x
   this box, so the CSS size is what downsamples them and keeps the edges clean.

   FULL white, not dimmed (client, 2026-08-17). They were briefly at .82 so 41 marks would
   not out-shout the heading above them; the client asked for plain white, so the restraint
   now lives in the tile behind them instead. Do not reintroduce a base opacity here. */
.lgitem img{width:170px;height:54px;display:block}
.lgitem:hover{background:#18213D;border-color:#33406A}
@keyframes lgm{to{transform:translateX(-50%)}}
/* motion is decoration here: the marks are all still reachable, they just stop moving */
@media(prefers-reduced-motion:reduce){.lgtrack{animation:none}}
@media(max-width:560px){
  .lgitem{width:172px;padding:20px 16px}
  .lgitem img{width:140px;height:44px}
}

/* ---------------------------------------------------------------- case studies (dark result cards)
   Deliberately dark: on a light background it read as the same section as the reviews
   marquee directly below it. */
.cs-dark{position:relative;background:radial-gradient(1100px 560px at 50% -10%,#18234C,transparent 64%),
  var(--ink);color:#9DAAC4;overflow:hidden}
.cs-dark h2{color:#fff}
.cs-dark .sh p{color:#8FA0BF}
.csglow{position:absolute;top:120px;right:-160px;width:620px;height:620px;border-radius:50%;
  background:radial-gradient(circle,rgba(6,182,212,.16),transparent 66%);pointer-events:none}
.cs-dark .csc{background:rgba(255,255,255,.035);border-color:#26315A;box-shadow:none}
.cs-dark .csc:hover{background:rgba(59,130,246,.08);border-color:#3B5488;
  box-shadow:0 30px 60px -30px rgba(0,0,0,.8)}
.cs-dark .csc-ic{background:#18224A}
.cs-dark .csc-tag{color:#7DD3FC}
.cs-dark .csc-top h3{color:#fff}
.cs-dark .csc-big{background:linear-gradient(150deg,rgba(37,99,235,.20),rgba(6,182,212,.06));
  border-color:#33477F}
.cs-dark .csc-big b{background:linear-gradient(115deg,#93C5FD,#22D3EE);-webkit-background-clip:text;
  background-clip:text;color:transparent}
.cs-dark .csc-big span{color:#93A3C4}
.cs-dark .csc-story p{color:#93A3C4}
.cs-dark .csc-story em{color:#E4EAF7}
.cs-dark .csc-mets{border-top-color:#26315A}
.cs-dark .csc-mets b{color:#fff}
.cs-dark .csc-mets span{color:#8093B8}

.cscs{display:grid;grid-template-columns:repeat(2,1fr);gap:18px}
.csc{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);padding:30px;
  box-shadow:var(--sh-1);display:flex;flex-direction:column;position:relative;overflow:hidden;
  transition:transform .28s cubic-bezier(.2,.8,.3,1),box-shadow .28s,border-color .28s}
.csc::before{content:'';position:absolute;top:0;left:0;right:0;height:3px;background:var(--grad);
  transform:scaleX(0);transform-origin:left;transition:transform .38s}
.csc:hover{transform:translateY(-5px);box-shadow:var(--sh-2);border-color:#C7D8F7}
.csc:hover::before{transform:scaleX(1)}
.csc-top{display:flex;align-items:center;gap:14px;margin-bottom:22px}
.csc-ic{width:48px;height:48px;border-radius:14px;background:#EEF3FD;display:grid;place-items:center;
  font-size:21px;flex:none}
.csc-tag{display:inline-block;font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--brand);margin-bottom:4px}
.csc-top h3{font-size:17px;line-height:1.3}
.csc-big{background:linear-gradient(150deg,#EEF3FD,#F7FAFF);border:1px solid #DCE7FA;border-radius:18px;
  padding:22px 24px;margin-bottom:22px}
.csc-big b{display:block;font-size:clamp(34px,4vw,46px);color:var(--brand);letter-spacing:-.05em;line-height:1}
.csc-big span{font-size:13px;color:var(--muted);font-weight:600}
.csc-story{margin-bottom:22px}
.csc-story p{font-size:14.5px;color:var(--muted);line-height:1.7;margin-bottom:12px}
.csc-story p:last-child{margin-bottom:0}
.csc-story em{font-style:normal;font-weight:700;color:var(--ink)}
.csc-mets{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:auto;
  padding-top:20px;border-top:1px solid var(--line-2)}
.csc-mets b{display:block;font-size:20px;color:var(--ink);letter-spacing:-.03em;line-height:1.2}
.csc-mets span{font-size:12px;color:var(--muted)}
.cscta{text-align:center;margin-top:38px}

/* ---------------------------------------------------------------- reviews (marquee) */
.rv-sec{padding:104px 0;overflow:hidden}
.rv-avg{display:inline-flex;align-items:center;gap:12px;background:#fff;border:1px solid var(--line);
  border-radius:100px;padding:9px 20px;margin-top:6px;box-shadow:var(--sh-1)}
.rv-avg span{font-size:13.5px;color:var(--muted)}
.rv-avg b{color:var(--ink)}
.rv-s{display:flex;gap:2px;color:#E2E8F0;font-size:15px;letter-spacing:1px}
.rv-s i{font-style:normal}
.rv-s i.on{color:#F59E0B}
.rv-s.big{color:#F59E0B;font-size:17px}
.rvmq{overflow:hidden;padding:9px 0;position:relative}
.rvmq::before,.rvmq::after{content:'';position:absolute;top:0;bottom:0;width:120px;z-index:2;pointer-events:none}
.rvmq::before{left:0;background:linear-gradient(90deg,var(--card),transparent)}
.rvmq::after{right:0;background:linear-gradient(270deg,var(--card),transparent)}
.rv-sec .rv{background:var(--page)}
.rvtrack{display:flex;gap:18px;width:max-content;animation:rvm 52s linear infinite}
.rvtrack.rev{animation-direction:reverse;animation-duration:62s}
@keyframes rvm{to{transform:translateX(-50%)}}
.rvmq:hover .rvtrack{animation-play-state:paused}
.rv{flex:none;width:min(400px,84vw);background:var(--card);border:1px solid var(--line);border-radius:var(--r);
  padding:26px;box-shadow:var(--sh-1);display:flex;flex-direction:column;gap:14px;transition:transform .25s,box-shadow .25s}
.rv:hover{transform:translateY(-4px);box-shadow:var(--sh-2)}
.rv blockquote{font-size:15px;line-height:1.65;color:var(--ink);font-weight:500}
.rv figcaption{display:flex;align-items:center;gap:12px;margin-top:auto}
.rv figcaption b{display:block;font-size:14px}
.rv figcaption span{font-size:12.5px;color:var(--muted)}

/* ---------------------------------------------------------------- dark stats band */
.stats-dark{background:radial-gradient(900px 420px at 50% 0%,#17224A,transparent 60%),var(--ink);
  color:#9DAAC4;padding:96px 0}
.stats-dark h2{color:#fff}
.stats-dark .stats{background:transparent;box-shadow:none;padding:0;gap:0;
  grid-template-columns:repeat(4,1fr);border-top:1px solid rgba(255,255,255,.14)}
.stats-dark .stats::before{display:none}
/* one ruled row, not four tiles: this used to re-add the card the base rule dropped */
.stats-dark .st{background:none;border:0;border-left:1px solid rgba(255,255,255,.10);
  border-radius:0;padding:32px 30px 4px}
.stats-dark .st:first-child{border-left:0;padding-left:0}
.stats-dark .st b{color:#fff}
.stats-dark .st span{color:#8FA0BF}

/* ---------------------------------------------------------------- FAQ two-column */
.faq-2{display:grid;grid-template-columns:.85fr 1.15fr;gap:56px;align-items:start}
.faq-l{position:sticky;top:110px}
.faq-l h2{font-size:clamp(26px,3.2vw,40px);line-height:1.14;margin-bottom:14px}
.faq-l>p{color:var(--muted);font-size:16px;margin-bottom:26px}
.faq-help{display:flex;align-items:center;gap:14px;background:var(--page);border:1px solid var(--line);
  border-radius:16px;padding:18px}
.faq-help .ic{width:42px;height:42px;border-radius:12px;background:#fff;border:1px solid var(--line);
  display:grid;place-items:center;font-size:18px;flex:none}
.faq-help b{display:block;font-size:14.5px}
.faq-help span{font-size:12.5px;color:var(--muted)}
.faq-help .btn{margin-left:auto;flex:none}
.fq summary span{flex:1}

/* ============================================================================
   PORTAL REPLICA — 14 working modules
   ========================================================================== */
.portal-sec{position:relative;background:radial-gradient(1000px 560px at 50% -8%,#16224A,transparent 62%),var(--ink);
  color:#9DAAC4;overflow:hidden;padding:52px 0 70px}
.portal-sec .sh{margin-bottom:30px}
.portal-sec h2{color:#fff}
.portal-sec .sh p{color:#8FA0BF}
.pglow{position:absolute;top:-160px;left:50%;transform:translateX(-50%);width:1200px;height:520px;
  background:radial-gradient(circle,rgba(59,130,246,.24),rgba(6,182,212,.08) 45%,transparent 70%);
  filter:blur(28px);pointer-events:none}
.portal{position:relative;background:#0F1730;border:1px solid #263258;border-radius:20px;overflow:hidden;
  box-shadow:0 50px 110px -40px rgba(0,0,0,.75),0 0 0 1px rgba(255,255,255,.03)}
/* Not a fake browser. The traffic-light dots and the centred URL pill are the single most
   copied SaaS device going, so this is a plain product bar: a live dot, the path as text,
   and the demo-data flag. */
.pchrome{display:flex;align-items:center;gap:14px;padding:11px 18px;background:#141D3A;
  border-bottom:1px solid #263258}
.pc-live{display:inline-flex;align-items:center;gap:7px;font-size:11px;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:#6EE7A8}
.pc-live i{width:7px;height:7px;border-radius:50%;background:#22C55E;
  box-shadow:0 0 0 3px rgba(34,197,94,.18);animation:blink 2s infinite}
.pc-path{margin-left:auto;font-size:12.5px;color:#8FA0BF;letter-spacing:.01em}
.ppath{color:#5C6C92}
.pdemo{font-size:11px;font-weight:700;color:#7DD3FC;background:rgba(125,211,252,.12);
  border:1px solid rgba(125,211,252,.28);border-radius:100px;padding:4px 11px;white-space:nowrap}
/* One fixed height for the whole app, so switching modules never resizes the section.
   Both columns must fit inside it without scrolling: the sidebar is compacted below and
   every module in portal.py is trimmed to fit .pbody. */
.papp{display:grid;grid-template-columns:206px 1fr;height:580px;background:#F4F6FA}

/* sidebar */
/* No scrollbar here either: 13 links plus the brand and the user card have to fit .papp */
.pside{background:#0F1730;border-right:1px solid #263258;padding:12px 10px;display:flex;flex-direction:column;
  overflow:hidden}
.pbrand{display:flex;align-items:center;gap:8px;font-weight:800;font-size:15px;color:#fff;padding:2px 10px 8px;
  letter-spacing:-.03em}
.pbrand em{font-style:normal;color:#60A5FA}
.pmark{width:24px;height:24px;border-radius:7px;background:var(--grad);flex:none;
  box-shadow:0 4px 10px -3px rgba(29,78,216,.7)}
.psg{margin-bottom:4px}
.psh{display:block;font-size:8.5px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:#4E5D82;padding:3px 10px;line-height:1.4}
.pside a{display:flex;align-items:center;gap:9px;padding:5px 9px;border-radius:9px;font-size:12px;line-height:1.35;
  font-weight:500;color:#94A3C4;cursor:pointer;transition:background .15s,color .15s,transform .15s}
.pside a:hover{background:#18224A;color:#fff;transform:translateX(2px)}
.pside a.on{background:linear-gradient(90deg,rgba(37,99,235,.30),rgba(37,99,235,.05));color:#fff;
  box-shadow:inset 2px 0 0 #60A5FA}
.psi{width:16px;text-align:center;font-size:13px;opacity:.9}
.pme{margin-top:auto;display:flex;align-items:center;gap:10px;border-top:1px solid #263258;padding:8px 10px 2px}
.pme b{display:block;font-size:12.5px;color:#fff}
.pme small{font-size:10.5px;color:#6C7E9E}

/* main + chrome */
.pmain{display:flex;flex-direction:column;background:#F4F6FA;min-width:0;min-height:0}
.ptop{display:flex;align-items:center;gap:16px;padding:0 18px;background:#fff;border-bottom:1px solid var(--line);
  min-height:52px}
.pcrumb{font-size:14px;font-weight:700;color:var(--ink)}
.ptop-r{margin-left:auto;display:flex;align-items:center;gap:11px}
.psearchbox{font-size:11.5px;color:var(--muted);background:#F4F6FA;border:1px solid var(--line);
  border-radius:8px;padding:5px 14px}
.pbell{font-size:13px;opacity:.6}
.pmobnav{display:none;gap:6px;padding:10px 12px;background:#fff;border-bottom:1px solid var(--line);
  overflow-x:auto;scrollbar-width:none}
.pmobnav::-webkit-scrollbar{display:none}
.pmc{font-size:11.5px;font-weight:600;color:var(--muted);background:#F4F6FA;border:1px solid var(--line);
  border-radius:8px;padding:6px 12px;white-space:nowrap}
.pmc.on{background:var(--brand);border-color:var(--brand);color:#fff}
/* No internal scrollbar (client, 2026-08-04): every module is trimmed to fit this box on
   one screen. min-height:0 on both this and .pmain is load bearing. Without it .pmain
   keeps its automatic minimum size, grows past .papp's fixed height, and .portal's
   overflow:hidden silently cuts the bottom off every long module. The old
   `flex:1;height:588px` never worked at all: flex:1 sets flex-basis:0, which overrides
   height on the main axis, so .pbody just grew to its content and never scrolled. */
/* Nothing inside a module is clickable (client, 2026-08-04): the sidebar is the only
   control. Every in-module button is a span in portal.py, and this stops the mouse as
   well. `.pside` and `.pmobnav` sit outside .pbody, so they still work. */
.pbody{padding:16px;flex:1;min-height:0;overflow:hidden;pointer-events:none}
.pview{display:none}
.pview.on{display:block;animation:pfade .38s cubic-bezier(.2,.8,.3,1)}
@keyframes pfade{from{opacity:0;transform:translateY(10px)}}
.pvh{display:flex;align-items:flex-start;gap:16px;margin-bottom:16px;flex-wrap:wrap}
.pvh h4{font-size:17px;margin-bottom:2px}
.pvh p{font-size:12.5px;color:var(--muted)}
.pvh-r{margin-left:auto;display:flex;gap:7px}
.pchip{font-size:11.5px;font-weight:600;color:var(--muted);background:#fff;border:1px solid var(--line);
  border-radius:8px;padding:5px 11px;white-space:nowrap;cursor:pointer;transition:all .15s}
.pchip:hover{border-color:var(--brand-3);color:var(--brand)}
.pchip.on{background:var(--brand);border-color:var(--brand);color:#fff}
.pchip.on:hover{color:#fff}
.pchip.live{background:#DCFCE7;border-color:#BBF7D0;color:#15803D}

/* stat cards */
.pstats{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:12px}
.pstat{background:#fff;border:1px solid var(--line);border-radius:14px;padding:15px 16px;
  transition:transform .2s,box-shadow .2s}
.pstat:hover{transform:translateY(-2px);box-shadow:var(--sh-2)}
.psl{display:block;font-size:11.5px;color:var(--muted);font-weight:600;margin-bottom:5px}
.pstat b{display:block;font-size:23px;letter-spacing:-.04em;line-height:1.15;font-variant-numeric:tabular-nums}
.pstat i{font-style:normal;font-size:11px;color:var(--muted)}
.pstat i.up{color:var(--ok)}
.pstat b.ok{color:var(--ok)}.pstat b.warn{color:#D97706}.pstat b.bad{color:#DC2626}
.pstat.sm b{font-size:20px}

/* cards */
.pgrid{display:grid;grid-template-columns:1.6fr 1fr;gap:12px;margin-bottom:12px}
.pgrid:last-child{margin-bottom:0}
.pgrid.phone{grid-template-columns:1fr 1fr}
.pgrid.flows{grid-template-columns:1.5fr 1fr}
.pcard{background:#fff;border:1px solid var(--line);border-radius:14px;padding:16px;min-width:0}
.pcard.flush{padding:0;overflow:hidden}
.pch{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:14px}
.pch.mt{margin-top:18px}
.pch b{font-size:13.5px}
.plink{font-size:11.5px;color:var(--brand);font-weight:600;cursor:pointer}
.plink:hover{text-decoration:underline}
.pleg{display:flex;gap:12px}
.pleg span{display:flex;align-items:center;gap:5px;font-size:10.5px;color:var(--muted);font-weight:600}
.pleg i{width:8px;height:8px;border-radius:3px}
.d-in{background:#60A5FA}.d-out{background:#1D4ED8}

/* charts */
.hbars{display:flex;align-items:flex-end;gap:3px;height:120px}
.hbars.sm{height:90px}
.hb{flex:1;display:flex;align-items:flex-end;gap:1.5px;height:100%}
.hb i{flex:1;border-radius:2px 2px 0 0;min-height:2px;transform-origin:bottom;
  animation:pgrow .8s cubic-bezier(.2,.8,.3,1) both}
.hb i.in{background:#60A5FA}
.hb i.out{background:#1D4ED8}
.hb:hover i{filter:brightness(1.15)}
@keyframes pgrow{from{transform:scaleY(0)}}
.haxis{display:flex;justify-content:space-between;margin-top:8px;font-size:10px;color:var(--muted)}
.ocs{display:flex;flex-direction:column;gap:10px}
.oc{display:grid;grid-template-columns:70px 1fr 36px;align-items:center;gap:9px}
.ol{font-size:11.5px;color:var(--muted);font-weight:600}
.ot{height:7px;background:#EEF2F8;border-radius:100px;overflow:hidden}
.ot i{display:block;height:100%;border-radius:100px;background:var(--brand-2);
  animation:pwide 1s cubic-bezier(.2,.8,.3,1) both;transform-origin:left}
.ot i.ok{background:var(--ok)}.ot i.warn{background:#F59E0B}.ot i.bad{background:#EF4444}
@keyframes pwide{from{transform:scaleX(0)}}
.ov{font-size:11.5px;font-weight:700;color:var(--ink);text-align:right}

/* tables */
.ptable{width:100%;border-collapse:collapse}
.ptable th{font-size:10.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--muted);
  text-align:left;padding:9px 10px;border-bottom:1px solid var(--line-2)}
.ptable td{padding:10px;font-size:12.5px;border-bottom:1px solid var(--line-2);vertical-align:middle}
.ptable tbody tr:last-child td{border-bottom:0}
.ptable tbody tr{transition:background .15s}
.ptable tbody tr:hover{background:#F8FAFD}
.ptable td:first-child{display:flex;align-items:center;gap:9px}
.ptable.cdr td:first-child,.ptable td.plain{display:table-cell}
.ptable .num{text-align:right;font-variant-numeric:tabular-nums;font-weight:600;color:var(--ink)}
.ptable b{display:block;font-size:12.5px}
.ptable small{font-size:10.5px;color:var(--muted)}
.pav{width:30px;height:30px;border-radius:9px;background:#EEF3FD;color:var(--brand);font-size:10.5px;
  font-weight:700;display:grid;place-items:center;flex:none}
.pav.g{background:var(--grad);color:#fff}
.pav.big{width:54px;height:54px;border-radius:16px;font-size:16px}
.ptw{overflow-x:auto}
.ptable.cdr{min-width:660px}
.mono{font-variant-numeric:tabular-nums;color:var(--text)}
.pdir{width:22px;height:22px;border-radius:7px;display:grid;place-items:center;font-size:11px;font-weight:700;flex:none}
.pdir.out{background:#DBEAFE;color:#1D4ED8}
.pdir.in{background:#DCFCE7;color:#15803D}
.pdir.int{background:#F1F5F9;color:#64748B}
.pdir.ai{background:#EDE9FE;color:#6D28D9}
.pdisp{font-size:10.5px;font-weight:700;padding:3px 9px;border-radius:100px;text-transform:capitalize}
.pdisp.ok{background:#DCFCE7;color:#15803D}
.pdisp.warn{background:#FEF3C7;color:#B45309}
.pdisp.bad{background:#FEE2E2;color:#B91C1C}
.ptag{font-size:10.5px;font-weight:600;background:#EEF3FD;color:var(--brand);padding:3px 9px;border-radius:6px}
.pdash{color:#CBD5E1}
.pplay{width:24px;height:24px;border-radius:7px;background:#EEF3FD;color:var(--brand);font-size:9px;
  display:grid;place-items:center;transition:all .15s}
.pfilters{display:flex;align-items:center;gap:7px;margin-bottom:12px;flex-wrap:wrap}
.pf{font-size:11.5px;font-weight:600;color:var(--muted);background:#fff;border:1px solid var(--line);
  border-radius:8px;padding:6px 12px;transition:all .15s}
.pf.on{background:var(--brand);border-color:var(--brand);color:#fff}
.psearch{margin-left:auto;font-size:11.5px;color:var(--muted);background:#fff;border:1px solid var(--line);
  border-radius:8px;padding:6px 14px;min-width:210px}
.ppag{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-top:1px solid var(--line-2);
  font-size:11.5px;color:var(--muted)}
.ppag div{display:flex;gap:5px}
.ppag button{width:26px;height:26px;border-radius:7px;border:1px solid var(--line);font-size:11.5px;
  color:var(--muted);background:#fff;transition:all .15s}
.ppag button.on,.ppag button:hover{background:var(--brand);border-color:var(--brand);color:#fff}

/* spend / lists */
.pspend{display:flex;flex-direction:column;gap:11px}
.pspend>div{display:flex;align-items:center;justify-content:space-between;gap:10px}
.pspend span{font-size:11.5px;color:var(--muted);font-weight:600}
.pspend b{font-size:14px;letter-spacing:-.02em}
.pspend b.ok{color:var(--ok)}
.pbal{flex-direction:column!important;align-items:stretch!important;gap:7px!important;
  background:#F8FAFD;border:1px solid var(--line-2);border-radius:11px;padding:12px;margin-top:2px}
.pbal b{font-size:18px}
.pbar{height:7px;background:#E4E9F2;border-radius:100px;overflow:hidden}
.pbar i{display:block;height:100%;background:var(--grad);border-radius:100px;
  animation:pwide 1.2s cubic-bezier(.2,.8,.3,1) both;transform-origin:left}

/* live monitor */
.plcs{display:flex;flex-direction:column;gap:8px}
.plc{display:flex;align-items:center;gap:11px;padding:11px 12px;border:1px solid var(--line-2);
  border-radius:12px;background:#fff;transition:border-color .2s}
.plc:hover{border-color:#C7D8F7}
.plc.queued{background:#FFFBEB;border-color:#FDE68A}
.pagi{flex:1;min-width:0}
.pagi b{display:block;font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pagi small{font-size:10.5px;color:var(--muted)}
.pwave{display:flex;gap:2.5px;align-items:center}
.pwave i{width:2.5px;border-radius:3px;background:var(--brand-2);animation:wv 1s ease-in-out infinite}
.pwave i:nth-child(1){height:7px}.pwave i:nth-child(2){height:14px;animation-delay:.1s}
.pwave i:nth-child(3){height:19px;animation-delay:.2s}.pwave i:nth-child(4){height:11px;animation-delay:.3s}
.pwave i:nth-child(5){height:16px;animation-delay:.4s}
.pwave i:nth-child(6){height:12px;animation-delay:.5s}.pwave i:nth-child(7){height:18px;animation-delay:.6s}
.pwave.big i{width:4px;margin:0 1px}
.pwave.big i:nth-child(odd){height:26px}.pwave.big i:nth-child(even){height:16px}
.ptime{font-size:11.5px;font-weight:700;font-variant-numeric:tabular-nums;color:var(--ink)}
.ptime.warn{color:#B45309}
.ptime.live{font-size:20px;letter-spacing:-.02em}
.pacts{display:flex;gap:4px}
.pacts button{width:26px;height:26px;border-radius:7px;background:#EEF3FD;color:var(--brand);font-size:11px;
  display:grid;place-items:center;transition:all .15s}
.pags{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.pag{display:flex;align-items:center;gap:10px;padding:10px;border:1px solid var(--line-2);border-radius:11px}
.pag.oncall{background:#F0FDF4;border-color:#BBF7D0}
.pag.dnd{background:#FEF2F2;border-color:#FECACA}
.pag.offline{opacity:.62}
.pdot{width:8px;height:8px;border-radius:50%;flex:none;display:inline-block}
.pdot.oncall{background:var(--ok);box-shadow:0 0 0 3px rgba(22,163,74,.16);animation:blink 1.8s infinite}
.pdot.idle{background:#94A3B8}
.pdot.dnd{background:#EF4444}
.pdot.offline{background:#CBD5E1}
.pst{font-size:10.5px;color:var(--muted);font-weight:600;white-space:nowrap;min-width:62px;text-align:right}
.pacts-list{display:flex;flex-direction:column;gap:2px;max-height:290px;overflow:hidden}
.pact{display:flex;align-items:flex-start;gap:9px;padding:9px 6px;border-bottom:1px solid var(--line-2)}
.pact:last-child{border-bottom:0}
.pact.new{animation:pfade .5s cubic-bezier(.2,.8,.3,1)}
.pact span{width:20px;height:20px;border-radius:6px;display:grid;place-items:center;font-size:9.5px;flex:none;
  background:#F1F5F9;color:#64748B}
.pact.answer span{background:#DCFCE7;color:#15803D}
.pact.ai span{background:#EDE9FE;color:#6D28D9}
.pact.miss span{background:#FEE2E2;color:#B91C1C}
.pact.start span{background:#DBEAFE;color:#1D4ED8}
.pact p{flex:1;font-size:11.5px;color:var(--text);line-height:1.45}
.pact time{font-size:10px;color:var(--muted);white-space:nowrap}

/* web phone */
.dialer{display:flex;flex-direction:column}
.pdisplay{background:#0F1730;border-radius:14px;padding:14px;margin-bottom:10px;text-align:center}
.pdlabel{display:block;font-size:10.5px;color:#7183A8;margin-bottom:7px;font-weight:600}
.pdnum{width:100%;min-height:30px;text-align:center;font-size:24px;font-weight:700;
  color:#fff;letter-spacing:.04em;font-variant-numeric:tabular-nums}
.pdnum:empty::before{content:attr(data-ph);color:#3E4E75;font-size:16px;font-weight:500}
.pkeys{display:grid;grid-template-columns:repeat(3,1fr);gap:7px;margin-bottom:10px}
.pk{background:#fff;border:1px solid var(--line);border-radius:12px;padding:8px 0;
  transition:all .12s;display:grid;place-items:center;gap:1px}
.pk.hit{border-color:var(--brand-3);background:#E4EDFD;transform:scale(.95)}
.pk b{font-size:17px;line-height:1}
.pk small{font-size:8.5px;color:var(--muted);letter-spacing:.08em}
.pk:active{transform:scale(.94);background:#DBEAFE}
.pdacts{display:flex;gap:8px}
.pcall{flex:1;background:linear-gradient(180deg,#22C55E,#16A34A);color:#fff;font-weight:700;font-size:14px;
  border-radius:12px;padding:13px;box-shadow:0 4px 0 #12833C;transition:all .15s}
.pdel{width:52px;background:#F1F5F9;border-radius:12px;font-size:15px;color:var(--muted);transition:all .15s}
.pincall{display:none;flex-direction:column;align-items:center;gap:11px;padding:20px 0 6px;
  border-top:1px solid var(--line-2);margin-top:14px}
.pincall.on{display:flex;animation:pfade .35s}
/* In call the pad is replaced, not pushed down. .pbody has no scrollbar any more, so a
   panel appended under the keys would just be clipped. */
.dialer.on-call .pkeys,.dialer.on-call .pdacts{display:none}
.dialer.on-call .pincall{border-top:0;margin-top:0;padding-top:6px}
.pincall b{font-size:16px;font-variant-numeric:tabular-nums}
.pcctrl{display:flex;gap:7px;margin-top:4px}
.pcctrl button{width:38px;height:38px;border-radius:12px;background:#F1F5F9;font-size:14px;transition:all .15s}
.pcctrl button:hover{background:#E2E8F0;transform:translateY(-2px)}
.pcctrl button.hang{background:#FEE2E2;color:#B91C1C}
.pcctrl button.hang:hover{background:#EF4444;color:#fff}
.precents{display:flex;flex-direction:column;gap:6px}
.prc{display:flex;align-items:center;gap:10px;padding:9px 10px;border:1px solid var(--line-2);
  border-radius:11px;cursor:pointer;transition:all .15s}
.prc:hover{border-color:#C7D8F7;background:#F8FAFD;transform:translateX(2px)}
.pspeed{display:grid;grid-template-columns:1fr 1fr;gap:7px}
.pspeed button{background:#F8FAFD;border:1px solid var(--line);border-radius:10px;padding:10px;
  font-size:12px;font-weight:600;color:var(--ink);transition:all .15s}
.pspeed button:hover{border-color:var(--brand-3);color:var(--brand);background:#F2F6FE}

/* campaigns */
.pcamps{display:flex;flex-direction:column;gap:12px}
.pcamp{border:1px solid var(--line-2);border-radius:13px;padding:15px;transition:border-color .2s}
.pcamp:hover{border-color:#C7D8F7}
.pcamp-t{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:11px}
.pcamp-t b{display:block;font-size:13.5px}
.pcamp-t small{font-size:11px;color:var(--muted)}
.pcamp-m{display:flex;gap:20px;margin-top:10px;flex-wrap:wrap}
.pcamp-m.mt{margin-top:14px}
.pcamp-m span{font-size:11px;color:var(--muted)}
.pcamp-m b{color:var(--ink);font-size:13px}

/* call flows */
.pflow{display:flex;flex-direction:column;align-items:center;padding:10px 0}
.pfn{background:#F8FAFD;border:1px solid var(--line);padding:10px 18px;border-radius:11px;font-size:12.5px;
  font-weight:600;color:var(--ink);transition:all .18s;cursor:pointer;text-align:center}
.pfn:hover{border-color:var(--brand-2);box-shadow:0 4px 12px -4px rgba(29,78,216,.28);transform:translateY(-2px)}
.pfn.start{background:#EEF3FD;border-color:#C7D8F7;color:var(--brand)}
.pfn.ivr{background:#fff;border-color:var(--brand-2);box-shadow:0 0 0 3px rgba(59,130,246,.12)}
.pfn.q{background:#F0FDF4;border-color:#BBF7D0;color:#15803D}
.pfn.ai{background:#F5F3FF;border-color:#DDD6FE;color:#6D28D9}
.pfn.vm{background:#FFFBEB;border-color:#FDE68A;color:#B45309}
.pfl{width:2px;height:20px;background:linear-gradient(180deg,var(--brand-2),#C7D8F7)}
.pfbr{display:grid;grid-template-columns:repeat(4,1fr);gap:9px;width:100%;margin-top:4px}
.pfcol{display:flex;flex-direction:column;align-items:center;gap:6px}
.pfcol::before{content:'';width:2px;height:14px;background:#C7D8F7}
.pfk{font-size:9.5px;font-weight:700;color:var(--muted);letter-spacing:.06em;text-transform:uppercase}
.pform{display:grid;grid-template-columns:auto 1fr;gap:9px 12px;align-items:center}
.pform label{font-size:11px;color:var(--muted);font-weight:600}
.pinput{background:#F8FAFD;border:1px solid var(--line-2);border-radius:9px;padding:8px 11px;font-size:12px;
  color:var(--ink);display:flex;align-items:center;justify-content:space-between;gap:8px}

/* reports heatmap */
.pheat{padding:4px 0}
.phrow{display:flex;align-items:center;gap:9px;margin-bottom:4px}
.phrow>span{font-size:10px;color:var(--muted);width:26px;font-weight:600}
.phcells{display:grid;grid-template-columns:repeat(24,1fr);gap:3px;flex:1}
.phcells i{aspect-ratio:1;border-radius:3px;background:#EEF2F8;transition:transform .15s}
.phcells i:hover{transform:scale(1.35);z-index:2;position:relative}
i.h1{background:#DBEAFE}i.h2{background:#C7DDFB}i.h3{background:#AFCFF9}i.h4{background:#93C0F7}
i.h5{background:#77B0F4}i.h6{background:#5B9FF1}i.h7{background:#3F8EEE}i.h8{background:#2A7CE4}
i.h9{background:#1D6BD1}i.h10{background:#1D4ED8}
.phaxis{display:flex;justify-content:space-between;margin:8px 0 0 35px;font-size:9.5px;color:var(--muted)}
.phleg{display:flex;align-items:center;gap:5px;justify-content:flex-end;margin-top:10px;font-size:10px;color:var(--muted)}
.phleg i{width:12px;height:12px;border-radius:3px}

/* integrations */
.pints{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:12px}
.pint{background:#fff;border:1px solid var(--line);border-radius:13px;padding:14px;display:flex;
  align-items:center;gap:10px;transition:all .2s}
.pint:hover{border-color:#C7D8F7;transform:translateY(-2px);box-shadow:var(--sh-2)}
.pint .ic{width:34px;height:34px;border-radius:10px;background:#F4F6FA;display:grid;place-items:center;
  font-size:16px;flex:none}
.pint b{display:block;font-size:12.5px}
.pint small{font-size:10.5px;color:var(--muted);line-height:1.35;display:block}
.pint>div{flex:1;min-width:0}
.ptoggle{width:34px;height:19px;border-radius:100px;background:#E2E8F0;position:relative;flex:none;
  transition:background .2s}
.ptoggle i{position:absolute;top:2.5px;left:2.5px;width:14px;height:14px;border-radius:50%;background:#fff;
  box-shadow:0 1px 3px rgba(0,0,0,.2);transition:transform .2s}
.ptoggle.on{background:var(--brand)}
.ptoggle.on i{transform:translateX(15px)}
.ptoggles{display:flex;flex-direction:column;gap:2px}
.ptr{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 0;
  border-bottom:1px solid var(--line-2)}
.ptr:last-child{border-bottom:0}
.ptr b{display:block;font-size:12.5px}
.ptr small{font-size:10.5px;color:var(--muted)}

/* note */
.pnote{display:flex;align-items:center;justify-content:center;gap:18px;margin-top:32px;flex-wrap:wrap}
.pnote span{color:#8FA0BF;font-size:15px}

/* ---------------------------------------------------------------- responsive */
@media(max-width:1100px){
  .pgrid,.pgrid.phone,.pgrid.flows{grid-template-columns:1fr}
  .pstats{grid-template-columns:repeat(2,1fr)}
  .pints{grid-template-columns:repeat(2,1fr)}
  .faq-2{grid-template-columns:1fr;gap:34px}
  .faq-l{position:static}
}
@media(max-width:980px){
  .papp{grid-template-columns:1fr;height:auto}
  .pside{display:none}
  .pmobnav{display:flex}
  /* .papp is auto height here, so .pbody must go back to sizing from its own content.
     Leaving flex:1 + min-height:0 in an auto-height column flex parent collapses it to 0. */
  .pbody{flex:none;height:auto;min-height:auto}
  .stats-dark .stats{grid-template-columns:repeat(2,1fr)}
  .stats-dark .st:nth-child(3){border-left:0;padding-left:0}
  .clients-sec,.rv-sec,.stats-dark{padding:76px 0}
  .portal-sec{padding:44px 0 60px}
}
@media(max-width:640px){
  .pstats,.pstats.four{grid-template-columns:1fr 1fr}
  .pags,.pints,.pfbr{grid-template-columns:1fr}
  .pbody{padding:13px}
  .pc-path{display:none}
  .stats-dark .stats{grid-template-columns:1fr}
  .stats-dark .st{border-left:0;padding-left:0}
  .faq-help{flex-wrap:wrap}
  .faq-help .btn{margin-left:0;width:100%}
  /* Side by side, not stacked full width (client, 2026-08-17). The row already wraps, so
     flex:1 + min-width:0 shares it evenly and lets long labels shrink rather than wrap. */
  .cta-row{flex-wrap:nowrap}
  .cta-row .btn{flex:1;min-width:0;width:auto;justify-content:center;padding-inline:14px}
}

/* csat: the five-star row in vis_csat. Filled stars, brand amber, nothing interactive --
   this is a picture of a survey, not a rating widget. */
.csat-stars{display:flex;justify-content:center;gap:8px;margin:6px 0 16px}
.csat-stars .ic-svg{width:26px;height:26px;color:#F59E0B;fill:#F59E0B}
.panel.dark .csat-stars .ic-svg{color:#FBBF24;fill:#FBBF24}
