@charset "UTF-8";
/* ==========================================================================
   AZMILE.AI — Design System v3 · MODERN UI LAYER
   Loaded AFTER site.css. Nothing here is a rewrite: this file extends the v2
   tokens, adds the new UI surfaces, and finishes the alignment + responsive
   passes. Equal specificity + later source order is what lets the overrides
   land, so keep selectors here at the same weight as their v2 counterparts.

   Layers: tokens+ → platform upgrades → alignment → new components
           → new sections → responsive → motion/print
   ========================================================================== */

/* ================================================================ TOKENS+ = */
:root {
  /* Gutter is now a named token — .wrap, .nav, .drawer and .topbar all read
     it, so the left edge of a logo lines up with the left edge of a card
     on every page and at every width. */
  --gutter: clamp(18px, 4vw, 32px);
  --gutter-safe: max(var(--gutter), env(safe-area-inset-left, 0px));

  --maxw-narrow: 780px;
  --maxw-wide: 1360px;

  --r-2xl: 34px;

  /* Chrome heights, so fixed furniture can reserve its own space */
  --topbar-h: 40px;

  /* Minimum comfortable touch target (WCAG 2.2 AA target size is 24px; 44px
     is the Apple/Material figure and what we actually design to). */
  --tap: 44px;

  /* Glass recipe reused by every new floating surface */
  --glass: rgba(9, 12, 20, .82);
  --glass-line: rgba(255, 255, 255, .1);
  --sh-float: 0 24px 70px -24px rgba(0, 0, 0, .9), 0 2px 8px -2px rgba(0, 0, 0, .6);

  /* Lets height/grid-template-rows animate to and from `auto` in browsers
     that support it — the FAQ and the palette groups both benefit. */
  interpolate-size: allow-keywords;
}

/* ==================================================== PLATFORM UPGRADES == */

/* Cross-document view transitions. Chrome/Edge cross-fade between pages;
   everywhere else this rule is simply ignored and navigation is unchanged. */
@view-transition {
  navigation: auto;
}

/* Persistent chrome keeps its identity across the transition, so the nav and
   the brand mark don't cross-fade with themselves. */
.nav {
  view-transition-name: az-nav;
}

.footer {
  view-transition-name: az-footer;
}

::view-transition-old(root) {
  animation-duration: .22s;
}

::view-transition-new(root) {
  animation-duration: .28s;
}

/* `clip` behaves like `hidden` but without turning the element into a scroll
   container — which is what let iOS bounce a few px of horizontal slack on
   pages with an oversized orb. */
html,
body {
  overflow-x: clip;
}

/* Notch clearance lives on the footer, not on <body>: the footer paints a
   gradient down to near-black, and body padding would have shown a seam of
   flat --bg-0 underneath it. */
.footer {
  padding-bottom: calc(var(--sp-6) + env(safe-area-inset-bottom, 0px));
}

/* Consistent optical text wrapping across the whole site */
p,
li,
dd,
figcaption {
  text-wrap: pretty;
}

/* ======================================================= ALIGNMENT PASS == */

/* One gutter, one max width, safe-area aware — the single source of truth for
   the page's left and right edges. */
.wrap {
  padding-inline: var(--gutter-safe);
}

.wrap--narrow {
  max-width: var(--maxw-narrow);
}

.wrap--wide {
  max-width: var(--maxw-wide);
}

.nav {
  padding-inline: var(--gutter-safe);
}

/* Section heads: the lede sat at whatever width its own text wanted, so two
   adjacent sections could disagree about where their copy block ended.
   Pin it to the head's measure instead. */
.section-head .lede {
  max-width: 62ch;
}

.section-head.center .lede {
  margin-inline: auto;
}

/* Cards in a row are the same height (grid stretch), but their contents were
   top-aligned only — so a two-line title pushed its tag down while the
   neighbour's stayed up. Column flex + auto margin lands every tag on the
   same baseline. */
.grid>.card,
.bento>.card,
.grid>.plan {
  display: flex;
  flex-direction: column;
}

.grid>.card>.tag,
.bento>.card>.tag {
  margin-top: auto;
  align-self: flex-start;
}

/* The auto margin above collapses the gap the tag used to carry, so put it
   back on the copy — but only in cards that actually have a tag. Scoped with
   :has(), because a card whose sole child is a <p> (the contact page's
   reassurance tiles) would otherwise gain 24px of dead space at the bottom. */
.grid>.card:has(>.tag)>p,
.bento>.card:has(>.tag)>p {
  margin-bottom: var(--sp-5);
}

/* The mock screenshot is a fixed-ratio block, so it must not absorb the free
   space the auto margin is trying to hand to the text below it. */
.grid>.card>.mock {
  flex: none;
}

/* Flow cards need the same treatment one level deeper: their tag lives inside
   .flow-body, so the card's own column flex never reached it and the three
   step tags landed wherever their copy happened to end (3 lines vs 4). */
.flow-card .flow-body {
  display: flex;
  flex-direction: column;
  flex: 1;
}

.flow-card .flow-body p {
  margin-bottom: var(--sp-4);
}

.flow-card .flow-body .tag {
  margin-top: auto;
  align-self: flex-start;
}

/* Footer columns were baseline-aligned, which dropped the short lists.
   Start-align them and give the brand column a real measure. */
.footer-grid {
  align-items: start;
}

.footer h4 {
  min-height: 1lh;
}

/* Stat tiles centre their own content but the grid was stretching them to
   unequal optical weight when a label wrapped. Centre on both axes. */
.stat {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* Hero proof rail: keep the pills on one optical baseline when one of them
   carries the live dot (which is taller than the text alone). */
.hero-meta span {
  align-items: center;
}

/* ============================================================== TOPBAR === */
/* Dismissible announcement rail. Injected by ui.js as the first body child so
   the sticky nav still parks at top:0 once this scrolls away. */
/* Strictly one line at every width. The whole bar is the link, so the trailing
   call-to-action can be dropped on narrow screens without losing the target —
   and the description ellipsises rather than wrapping into the nav. */
.topbar {
  position: relative;
  z-index: 102;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: nowrap;
  gap: 10px;
  height: var(--topbar-h);
  padding-inline: calc(var(--gutter-safe) + 34px);
  font-size: 13px;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  color: var(--ink-2);
  background: linear-gradient(90deg, rgba(79, 214, 232, .1), rgba(168, 224, 74, .1) 55%, rgba(139, 124, 246, .09));
  border-bottom: 1px solid var(--line-soft);
}

.topbar-msg {
  display: inline-flex;
  align-items: baseline;
  gap: 7px;
  min-width: 0;
  color: inherit;
  transition: color var(--dur-2) var(--ease);
}

.topbar-msg b {
  flex: none;
  color: var(--lime-2);
  font-weight: 600;
}

.topbar-msg .d {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.topbar-msg .go {
  flex: none;
  margin-left: 4px;
  color: var(--ink);
  font-weight: 600;
  border-bottom: 1px solid rgba(255, 255, 255, .28);
  transition: border-color var(--dur-2) var(--ease), color var(--dur-2) var(--ease);
}

.topbar-msg:hover .go {
  color: var(--lime-2);
  border-bottom-color: var(--lime-2);
}

.topbar .x {
  position: absolute;
  top: 50%;
  right: max(8px, env(safe-area-inset-right, 0px));
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  color: var(--ink-3);
  transition: background var(--dur-2) var(--ease), color var(--dur-2) var(--ease);
}

.topbar .x:hover {
  background: var(--surface-2);
  color: var(--ink);
}

.topbar .x svg {
  width: 14px;
  height: 14px;
}

/* A one-screen hero budgets for the sticky nav, but the rail is injected here
   at runtime and pushes that budget off the bottom by exactly its own height.
   :has() rather than a body class, so dismissing the bar hands the height
   straight back with no JS on either side. */
body:has(.topbar) .hero--fit {
  min-height: calc(100vh - var(--nav-h) - var(--topbar-h));
  min-height: calc(100svh - var(--nav-h) - var(--topbar-h));
}

/* ==================================================== NAV — SEARCH KEY === */
/* The ⌘K affordance. Reads as a search field on desktop, collapses to a round
   icon button on tablet and phone. */
.nav-k {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  height: 34px;
  padding: 0 9px 0 12px;
  min-width: 172px;
  font-size: 13px;
  color: var(--ink-3);
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--surface);
  transition: border-color var(--dur-2) var(--ease), background var(--dur-2) var(--ease), color var(--dur-2) var(--ease);
}

.nav-k:hover {
  color: var(--ink-2);
  border-color: rgba(168, 224, 74, .38);
  background: var(--surface-2);
}

.nav-k svg {
  width: 15px;
  height: 15px;
  flex: none;
}

.nav-k .lbl {
  margin-right: auto;
}

/* Keycap chip — also used inside the palette footer */
.kbd {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 2px 6px;
  font-family: var(--ff-mono);
  font-size: 10.5px;
  line-height: 1.5;
  color: var(--ink-3);
  background: rgba(255, 255, 255, .06);
  border: 1px solid var(--line);
  border-bottom-width: 2px;
  border-radius: 5px;
  white-space: nowrap;
}

/* =============================================== MOBILE SHEET (DRAWER v2) */
/* v2 hung the drawer off the nav height, which stopped working the moment a
   topbar existed above it. v3 is a full-height sheet with its own header, so
   it owns the whole viewport and never has to know what's behind it. */
.drawer {
  inset: 0;
  z-index: 120;
  display: flex;
  flex-direction: column;
  gap: 0;
  padding: 0;
  background: rgba(4, 6, 12, .97);
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  border-bottom: 0;
  transform: none;
  overflow-y: auto;
  overscroll-behavior: contain;
  /* Slide the panel rather than nudge it, and fade the whole sheet */
  transition: opacity var(--dur-2) var(--ease), visibility var(--dur-2);
}

.drawer-head {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: none;
  height: var(--nav-h);
  padding-inline: var(--gutter-safe);
  padding-top: env(safe-area-inset-top, 0px);
  border-bottom: 1px solid var(--line-soft);
}

.drawer-head .brand {
  margin-right: auto;
}

.drawer-x {
  display: grid;
  place-items: center;
  width: var(--tap);
  height: var(--tap);
  margin-right: -8px;
  border-radius: var(--r-pill);
  color: var(--ink);
  border: 1px solid var(--line);
  background: var(--surface);
}

.drawer-x:hover {
  background: var(--surface-2);
}

.drawer-x svg {
  width: 18px;
  height: 18px;
}

.drawer-nav {
  display: grid;
  gap: 2px;
  padding: var(--sp-5) var(--gutter-safe) var(--sp-4);
}

/* Each row is a real target: icon rail, label, chevron. Staggered in so the
   sheet opens with a sense of direction instead of appearing all at once.
   Scoped through .drawer to match the weight of v2's `.drawer a:not(.btn)` —
   at `.drawer-nav a` alone it loses on specificity, not source order. */
.drawer .drawer-nav a {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 54px;
  padding: 10px 14px 10px 10px;
  font-family: var(--ff-display);
  font-size: 17px;
  font-weight: 500;
  letter-spacing: -.02em;
  color: var(--ink);
  border: 1px solid transparent;
  border-bottom: 1px solid var(--line-soft);
  border-radius: var(--r-md);
  opacity: 0;
  transform: translateY(10px);
  transition: opacity .38s var(--ease-out) var(--sd, 0s),
    transform .38s var(--ease-out) var(--sd, 0s),
    background var(--dur-1) var(--ease),
    border-color var(--dur-1) var(--ease);
}

.drawer.open .drawer-nav a {
  opacity: 1;
  transform: none;
}

.drawer .drawer-nav a:nth-child(2) {
  --sd: .05s;
}

.drawer .drawer-nav a:nth-child(3) {
  --sd: .1s;
}

.drawer .drawer-nav a:nth-child(4) {
  --sd: .15s;
}

.drawer .drawer-nav a:nth-child(5) {
  --sd: .2s;
}

.drawer .drawer-nav a:active {
  background: var(--surface);
}

.drawer .drawer-nav a[aria-current='page'] {
  color: var(--lime-2);
  border-color: rgba(168, 224, 74, .3);
  background: rgba(168, 224, 74, .07);
}

.drawer-ico {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  flex: none;
  border-radius: 12px;
  color: var(--lime-2);
  background: linear-gradient(150deg, rgba(168, 224, 74, .15), rgba(79, 214, 232, .06));
  border: 1px solid rgba(168, 224, 74, .2);
}

.drawer-ico svg {
  width: 18px;
  height: 18px;
}

.drawer-nav .arw {
  margin-left: auto;
  color: var(--ink-3);
  font-size: 15px;
}

/* CTA block pinned to the bottom of the sheet */
.drawer-foot {
  margin-top: auto;
  display: grid;
  gap: 10px;
  padding: var(--sp-5) var(--gutter-safe);
  padding-bottom: calc(var(--sp-6) + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--line-soft);
  background: linear-gradient(180deg, transparent, rgba(255, 255, 255, .022));
}

.drawer-foot .btn {
  --btn-py: 14px;
  margin-top: 0;
  width: 100%;
  font-size: 15px;
}

.drawer-meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px 16px;
  margin-top: 4px;
  font-family: var(--ff-mono);
  font-size: 11px;
  color: var(--ink-3);
}

.drawer .drawer-meta a {
  color: var(--ink-3);
  border: 0;
  padding: 0;
  font: inherit;
  min-height: 0;
}

.drawer-meta a:hover {
  color: var(--lime-2);
}

/* ===================================================== COMMAND PALETTE === */
/* ⌘K / Ctrl-K. Navigates the site, jumps to any section on the current page,
   and hands anything else to Azzy. */
.cmdk {
  position: fixed;
  inset: 0;
  z-index: 160;
  display: grid;
  align-items: start;
  justify-items: center;
  padding: clamp(56px, 12vh, 128px) var(--gutter-safe) var(--sp-6);
  background: rgba(2, 4, 9, .72);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur-2) var(--ease), visibility var(--dur-2);
}

.cmdk.open {
  opacity: 1;
  visibility: visible;
}

.cmdk-panel {
  position: relative;
  /* anchors the masked hairline ring below */
  width: 100%;
  max-width: 620px;
  max-height: min(72vh, 620px);
  display: flex;
  flex-direction: column;
  border-radius: var(--r-xl);
  border: 1px solid var(--glass-line);
  background: linear-gradient(180deg, rgba(20, 26, 40, .96), rgba(8, 11, 19, .97));
  box-shadow: var(--sh-float);
  overflow: hidden;
  transform: translateY(-10px) scale(.985);
  opacity: 0;
  transition: transform var(--dur-2) var(--ease-out), opacity var(--dur-2) var(--ease-out);
}

.cmdk.open .cmdk-panel {
  transform: none;
  opacity: 1;
}

/* Same travelling hairline as the hero console, so the palette reads as part
   of the same family of AI surfaces. */
.cmdk-panel::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(115deg, rgba(79, 214, 232, .5), rgba(168, 224, 74, .5) 48%, transparent 78%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
}

.cmdk-search {
  display: flex;
  align-items: center;
  gap: 11px;
  flex: none;
  padding: 15px 16px;
  border-bottom: 1px solid var(--line-soft);
}

.cmdk-search>svg {
  width: 18px;
  height: 18px;
  flex: none;
  color: var(--ink-3);
}

.cmdk-search input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: 0;
  background: none;
  font-size: 16px;
  /* 16px floor stops iOS Safari zooming the page when the field takes focus */
  color: var(--ink);
}

.cmdk-search input::placeholder {
  color: var(--ink-3);
}

.cmdk-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 8px;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, .16) transparent;
}

.cmdk-group {
  padding: 10px 10px 4px;
  font-family: var(--ff-mono);
  font-size: 10px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.cmdk-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: var(--tap);
  padding: 9px 11px;
  border-radius: var(--r-sm);
  font-size: 14px;
  color: var(--ink-2);
  text-align: left;
  transition: background var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}

.cmdk-item .ic {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  flex: none;
  border-radius: 9px;
  color: var(--lime-2);
  background: rgba(168, 224, 74, .1);
  border: 1px solid rgba(168, 224, 74, .16);
}

.cmdk-item .ic svg {
  width: 15px;
  height: 15px;
}

.cmdk-item .tx {
  min-width: 0;
  flex: 1;
}

.cmdk-item .tx b {
  display: block;
  font-weight: 500;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cmdk-item .tx span {
  display: block;
  font-size: 11.5px;
  color: var(--ink-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Matched substring, highlighted as you type */
.cmdk-item mark {
  background: rgba(168, 224, 74, .22);
  color: var(--lime-2);
  border-radius: 3px;
  padding: 0 1px;
}

.cmdk-item .go {
  flex: none;
  opacity: 0;
  color: var(--ink-3);
  font-size: 13px;
  transition: opacity var(--dur-1) var(--ease);
}

/* Active row is driven by aria-selected, so pointer and keyboard land on the
   same visual state and the two can't disagree. */
.cmdk-item[aria-selected='true'] {
  background: rgba(168, 224, 74, .1);
  color: var(--ink);
}

.cmdk-item[aria-selected='true'] .go {
  opacity: 1;
}

.cmdk-empty {
  padding: 30px 16px;
  text-align: center;
  font-size: 13.5px;
  color: var(--ink-3);
}

.cmdk-foot {
  display: flex;
  align-items: center;
  gap: 14px;
  flex: none;
  padding: 10px 14px;
  border-top: 1px solid var(--line-soft);
  font-size: 11.5px;
  color: var(--ink-3);
  background: rgba(0, 0, 0, .3);
}

.cmdk-foot .sp {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--lime-2);
}

.cmdk-foot i {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-style: normal;
}

/* ========================================================= BACK TO TOP === */
/* Circular scroll-progress ring around an arrow. The ring is a conic gradient
   driven by --p, which ui.js updates on scroll. */
.totop {
  position: fixed;
  right: max(18px, env(safe-area-inset-right, 0px));
  bottom: max(18px, env(safe-area-inset-bottom, 0px));
  z-index: 105;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  color: var(--ink);
  background: var(--glass);
  border: 1px solid var(--glass-line);
  box-shadow: var(--sh-2);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  opacity: 0;
  visibility: hidden;
  transform: translateY(12px) scale(.9);
  transition: opacity var(--dur-2) var(--ease), transform var(--dur-2) var(--ease),
    visibility var(--dur-2), border-color var(--dur-2) var(--ease);
}

.totop.show {
  opacity: 1;
  visibility: visible;
  transform: none;
}

.totop:hover {
  border-color: rgba(168, 224, 74, .5);
}

.totop::before {
  content: '';
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  padding: 2px;
  background: conic-gradient(var(--lime) calc(var(--p, 0) * 1turn), rgba(255, 255, 255, .1) 0);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
}

.totop svg {
  width: 18px;
  height: 18px;
}

/* ============================================================== TOASTS === */
.toasts {
  position: fixed;
  z-index: 170;
  right: max(16px, env(safe-area-inset-right, 0px));
  bottom: max(16px, env(safe-area-inset-bottom, 0px));
  display: grid;
  gap: 8px;
  justify-items: end;
  pointer-events: none;
}

.toast {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  max-width: min(360px, calc(100vw - 32px));
  padding: 12px 14px;
  border-radius: var(--r-md);
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--ink);
  background: var(--glass);
  border: 1px solid var(--glass-line);
  box-shadow: var(--sh-float);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  pointer-events: auto;
  animation: toastIn .34s var(--ease-out) both;
}

.toast.out {
  animation: toastOut .26s var(--ease-io) both;
}

.toast svg {
  width: 17px;
  height: 17px;
  flex: none;
  margin-top: 1px;
  color: var(--lime-2);
}

.toast.is-warn svg {
  color: var(--warn);
}

.toast.is-err svg {
  color: var(--danger);
}

@keyframes toastIn {
  from {
    opacity: 0;
    transform: translateY(14px) scale(.97);
  }
}

@keyframes toastOut {
  to {
    opacity: 0;
    transform: translateY(8px) scale(.98);
  }
}

/* ================================================ PAIN TILES / DISCLOSURE */
/* Above 680px these are the four static tiles they have always been: the
   summary renders as a plain block, the topic line and chevron are off, and
   ui.js keeps every one of them open. Below 680px they become a real
   accordion — see the responsive block at the foot of this file.            */

/* A <details> with `display:flex` keeps painting its content while closed —
   the UA's collapse behaviour assumes block layout. The alignment pass above
   makes every `.grid > .card` a flex column, which silently swallowed the
   collapse and left all four tiles open. Block by default; flex is handed
   back below 681px-up only, where the tiles are always open anyway. */
.grid>.pain-card {
  display: block;
}

@media (min-width: 681px) {
  .grid>.pain-card {
    display: flex;
    flex-direction: column;
  }
}

.pain-card>summary {
  /* Kill the native triangle in both the modern and the WebKit-legacy way */
  list-style: none;
  display: block;
}

.pain-card>summary::-webkit-details-marker {
  display: none;
}

.pain-card>summary::marker {
  content: '';
}

/* .pain-label pins .pain-fix to the bottom with `margin-bottom:auto`, which
   needs an unbroken flex column from the card down to it. <details> puts its
   content in a ::details-content box in current browsers and does not in
   older ones, so both are made flex — whichever one is the real flex item
   gets the job, and the other is a harmless no-op.

   Strictly min-width-scoped. Bottom-alignment is a grid-layout concern and
   means nothing to a stacked accordion, and giving ::details-content a
   `flex` at accordion widths stopped it collapsing at all. */
@media (min-width: 681px) {

  .pain-card::details-content,
  .pain-card>.pain-body {
    display: flex;
    flex-direction: column;
    flex: 1;
  }
}

.pain-topic,
.pain-chev {
  display: none;
}

/* =============================================== SAFE TILES / DISCLOSURE */
/* The "Built safe" guardrail tiles on ai.html get the same two-mode
   treatment as the pain tiles: four static cards from 681px up, a
   one-at-a-time accordion below. Only the chevron is mode-specific here —
   the icon and the <h3> are the card's own head either way.               */

/* Same collapse caveat as the pain tiles: a flex <details> keeps painting
   its content when closed, and the .grid > .card alignment pass makes every
   card a flex column. Block by default; flex handed back only where the
   tiles are always open anyway. */
.grid>.safe-card {
  display: block;
}

@media (min-width: 681px) {
  .grid>.safe-card {
    display: flex;
    flex-direction: column;
  }
}

.safe-card>summary {
  /* Kill the native triangle in both the modern and the WebKit-legacy way */
  list-style: none;
  display: block;
}

.safe-card>summary::-webkit-details-marker {
  display: none;
}

.safe-card>summary::marker {
  content: '';
}

/* =============================================== STEP TILES / DISCLOSURE */
/* ai.html's "Ask. Azzy reads. You confirm." steps run the same two modes as
   the two grids above: three static cards from 681px up, a one-at-a-time
   accordion below. The numbered badge and the <h3> are the card's own head
   either way — only the chevron is mode-specific.                         */

/* Same collapse caveat as the tiles above: a flex <details> keeps painting
   its content when closed, and the .grid > .card alignment pass makes every
   card a flex column. Block by default; flex handed back only where the
   cards are always open anyway. */
.grid>.step-card {
  display: block;
}

@media (min-width: 681px) {
  .grid>.step-card {
    display: flex;
    flex-direction: column;
  }
}

.step-card>summary {
  /* Kill the native triangle in both the modern and the WebKit-legacy way */
  list-style: none;
  display: block;
}

.step-card>summary::-webkit-details-marker {
  display: none;
}

.step-card>summary::marker {
  content: '';
}

/* The tag used to be a direct child of the card, so the alignment pass at the
   top of this file bottom-pinned it. Moving it inside .step-body put a box
   between the two, so the flex column has to be rebuilt one level deeper —
   exactly the treatment .flow-body gets. Min-width-scoped: bottom-alignment
   is a grid concern and means nothing to a stacked accordion. */
@media (min-width: 681px) {

  .step-card::details-content,
  .step-card>.step-body {
    display: flex;
    flex-direction: column;
    flex: 1;
  }

  .step-card>.step-body>.tag {
    margin-top: auto;
    align-self: flex-start;
  }

  .step-card>.step-body:has(>.tag)>p {
    margin-bottom: var(--sp-5);
  }
}

.safe-chev,
.step-chev,
.bento-chev {
  display: none;
}

/* ============================================== BENTO TILES / DISCLOSURE */
/* The modules bento folds like the grids above, but it could not become a
   <details> itself: the mock sits above the title in the design, and a
   <details> must open with its <summary>. So the fold is a child of the card
   and the mock stays its sibling, put back on top with `order` here and
   revealed on [open] in the accordion block below.                        */

/* The card is the flex column (the alignment pass at the top of this file),
   so the collapse caveat lands on .bento-fold instead — block by default,
   flex only where the tiles are always open. */
.bento-fold {
  display: block;
}

.bento-fold>summary {
  /* Kill the native triangle in both the modern and the WebKit-legacy way */
  list-style: none;
  display: block;
}

.bento-fold>summary::-webkit-details-marker {
  display: none;
}

.bento-fold>summary::marker {
  content: '';
}

@media (min-width: 681px) {

  /* DOM order is fold-then-mock so the accordion can reach the mock with a
     sibling combinator. Here that is undone: the mock leads, exactly as it
     did before the fold existed. The .icon cards are already in source
     order and need nothing. */
  .bento-card>.mock {
    order: -1;
  }

  /* Same one-level-deeper rebuild .step-card documents: the tag used to be a
     direct child of the card, and two boxes now sit between them. */
  .bento-card>.bento-fold,
  .bento-fold::details-content,
  .bento-fold>.bento-body {
    display: flex;
    flex-direction: column;
    flex: 1;
  }

  .bento-fold>.bento-body>.tag {
    margin-top: auto;
    align-self: flex-start;
  }

  .bento-fold>.bento-body:has(>.tag)>p {
    margin-bottom: var(--sp-5);
  }
}

/* ==================================================== NEW SECTION: RAIL == */
/* Outcome rail — a hairline-divided strip of claims with an icon each.
   Same glass recipe as .hero-meta, scaled up to a full-width section. */
.rail {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--line);
  overflow: hidden;
}

.rail-cell {
  display: flex;
  align-items: flex-start;
  gap: 13px;
  padding: var(--sp-5);
  background: var(--bg-1);
  transition: background var(--dur-2) var(--ease);
}

.rail-cell:hover {
  background: var(--bg-2);
}

.rail-cell .ic {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  flex: none;
  border-radius: 11px;
  color: var(--lime-2);
  background: linear-gradient(150deg, rgba(168, 224, 74, .15), rgba(79, 214, 232, .06));
  border: 1px solid rgba(168, 224, 74, .2);
}

.rail-cell .ic svg {
  width: 17px;
  height: 17px;
}

.rail-cell b {
  display: block;
  font-family: var(--ff-display);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.018em;
  color: var(--ink);
  margin-bottom: 3px;
}

.rail-cell p {
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-3);
}

/* ============================================== NEW SECTION: SWITCHBOARD = */
/* Before / after comparison. Two columns that share one row grid, so each
   "before" line sits exactly opposite the "after" that replaces it. */
.switchboard {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-5);
  align-items: start;
}

.sb-col {
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: linear-gradient(180deg, rgba(255, 255, 255, .035), rgba(255, 255, 255, .008));
  overflow: hidden;
}

.sb-col--now {
  border-color: rgba(168, 224, 74, .28);
  background: linear-gradient(180deg, rgba(168, 224, 74, .07), rgba(255, 255, 255, .012));
  box-shadow: 0 22px 60px -34px rgba(168, 224, 74, .55);
}

/* Above 860px these are two static panels: the summary renders as a plain
   header, the chevron is off and ui.js keeps both open. Below 860px they stack
   and become real disclosures — see the responsive block at the foot of this
   file. Both ship `open` in the markup so the side-by-side layout and the
   no-JS case get the whole comparison either way. */
.sb-col>summary {
  /* Kill the native triangle in both the modern and the WebKit-legacy way */
  list-style: none;
}

.sb-col>summary::-webkit-details-marker {
  display: none;
}

.sb-col>summary::marker {
  content: '';
}

.sb-chev {
  display: none;
}

.sb-head {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--line-soft);
  font-family: var(--ff-mono);
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.sb-col--now .sb-head {
  color: var(--lime-2);
}

.sb-head i {
  width: 7px;
  height: 7px;
  flex: none;
  border-radius: 50%;
  background: var(--ink-3);
  opacity: .6;
}

.sb-col--now .sb-head i {
  background: var(--lime);
  opacity: 1;
  box-shadow: 0 0 9px 1px rgba(168, 224, 74, .8);
}

.sb-list li {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  /* Fixed row height keeps the two columns in lockstep even when one side's
     line wraps and the other's doesn't. */
  min-height: 74px;
  padding: 15px 18px;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--ink-2);
  border-bottom: 1px solid var(--line-soft);
}

.sb-list li:last-child {
  border-bottom: 0;
}

.sb-list svg {
  width: 16px;
  height: 16px;
  flex: none;
  margin-top: 2px;
  color: var(--ink-3);
}

.sb-col--now .sb-list li {
  color: var(--ink);
}

.sb-col--now .sb-list svg {
  color: var(--lime-2);
}

/* =============================================== NEW SECTION: TIMELINE == */
/* Rollout steps on a lit spine. */
.tl {
  position: relative;
  display: grid;
  gap: var(--sp-5);
  padding-left: 34px;
}

.tl::before {
  content: '';
  position: absolute;
  left: 13px;
  top: 8px;
  bottom: 8px;
  width: 2px;
  border-radius: 2px;
  background: linear-gradient(180deg, var(--lime), rgba(79, 214, 232, .5) 55%, transparent);
}

.tl-step {
  position: relative;
}

.tl-step::before {
  content: '';
  position: absolute;
  left: -34px;
  top: 5px;
  width: 12px;
  height: 12px;
  margin-left: 8px;
  border-radius: 50%;
  background: var(--bg-0);
  border: 2px solid var(--lime);
  box-shadow: 0 0 10px 1px rgba(168, 224, 74, .55);
}

.tl-when {
  font-family: var(--ff-mono);
  font-size: 10.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--lime-2);
  margin-bottom: 5px;
}

.tl-step h3 {
  font-size: 17px;
  margin-bottom: 5px;
}

.tl-step p {
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--ink-2);
}

/* ============================================ SHOWCASE CARDS / DISCLOSURE */
/* Above 680px these are the three feature cards they have always been: mock,
   then heading, then copy, with the summary rendering as a plain block and
   ui.js keeping every one of them open. Below 680px they go full width and the
   heading becomes a real disclosure — see the responsive block at the foot.

   The heading has to come first in the DOM, because a <summary> only works as
   one when it is the first child. `display: contents` on ::details-content
   lifts the mock and the copy back out as siblings of the summary, so `order`
   can put the mock above the heading again and the card looks untouched. */
.grid>.showcase-card {
  display: block;
}

@media (min-width: 681px) {
  .grid>.showcase-card {
    display: flex;
    flex-direction: column;
  }

  .showcase-card::details-content {
    display: contents;
  }

  .showcase-card>.mock {
    order: 1;
  }

  .showcase-card>summary {
    order: 2;
  }

  .showcase-card>p {
    order: 3;
  }
}

.showcase-card>summary {
  /* Kill the native triangle in both the modern and the WebKit-legacy way */
  list-style: none;
  display: block;
}

.showcase-card>summary::-webkit-details-marker {
  display: none;
}

.showcase-card>summary::marker {
  content: '';
}

.showcase-chev {
  display: none;
}

/* =============================================== NEW SECTION: ASSURE ==== */
/* The three promises under the contact form. They were three separate cards,
   each holding one short line inside a box sized for a paragraph — so the
   section read as empty furniture, and all three lines were hardcoded lime
   while the cards underneath washed lime, cyan and violet.

   One connected rail instead. The cells share a surface, so the strip reads as
   a single statement rather than three billboards, and the hue moves off the
   text and onto the mark, where the rotation finally means something. */
.assure {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background:
    radial-gradient(90% 120% at 50% -20%, rgba(255, 255, 255, .05), transparent 62%),
    linear-gradient(180deg, rgba(255, 255, 255, .04), rgba(255, 255, 255, .008));
  box-shadow: var(--sh-2), inset 0 1px 0 rgba(255, 255, 255, .06);
  overflow: hidden;
}

/* The rail's own lit edge. A single card carries one hue along this line; a
   rail carries all three, in the order the cells run — which is what ties the
   strip together instead of leaving three unrelated lights in a row. */
.assure::after {
  content: '';
  position: absolute;
  left: 6%;
  right: 6%;
  bottom: 0;
  height: 1.5px;
  border-radius: 2px;
  pointer-events: none;
  background: linear-gradient(90deg,
      transparent,
      rgb(var(--lit-lime) / .5) 17%,
      rgb(var(--lit-cyan) / .55) 50%,
      rgb(var(--lit-violet) / .5) 83%,
      transparent);
}

.assure-cell {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: clamp(15px, 1.9vw, 22px) clamp(14px, 1.8vw, 26px);
  min-height: var(--tap);
  font-family: var(--ff-display);
  font-weight: 600;
  font-size: clamp(13.5px, 1vw, 15px);
  letter-spacing: -.012em;
  line-height: 1.35;
  color: var(--ink);
}

/* Seams as pseudo-elements, not borders: a border can't fade out at both ends,
   and two adjacent ones would double up into a 2px line at every seam. */
.assure-cell+.assure-cell::before {
  content: '';
  position: absolute;
  left: 0;
  top: 16%;
  bottom: 16%;
  width: 1px;
  background: linear-gradient(180deg, transparent, var(--line-hard), transparent);
}

/* Light gathers in the cell under the cursor only — the rail stays crisp at
   rest, which is the same bargain .card struck when its bloom moved to hover. */
.assure-cell::after {
  content: '';
  position: absolute;
  inset: 0;
  /* Explicit, because ::after is the last positioned child and would otherwise
     paint straight over the mark and the label it is meant to sit behind. */
  z-index: 0;
  opacity: 0;
  pointer-events: none;
  background: radial-gradient(120% 100% at 50% 122%, rgb(var(--lit) / .3), transparent 72%);
  transition: opacity var(--dur-3) var(--ease);
}

.assure-cell:hover::after {
  opacity: 1;
}

.assure-mark {
  position: relative;
  z-index: 1;
  flex: none;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 10px;
  color: var(--lit-ink);
  background: linear-gradient(150deg, rgb(var(--lit) / .18), rgb(var(--lit) / .06));
  border: 1px solid rgb(var(--lit) / .3);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);
  transition: transform var(--dur-3) var(--ease), box-shadow var(--dur-3) var(--ease);
}

.assure-mark svg {
  width: 17px;
  height: 17px;
}

.assure-cell:hover .assure-mark {
  transform: translateY(-2px);
  box-shadow:
    0 8px 20px -8px rgb(var(--lit) / .55),
    inset 0 1px 0 rgba(255, 255, 255, .14);
}

.assure-label {
  position: relative;
  z-index: 1;
  text-wrap: balance;
}

/* ===================================================== MISC PRIMITIVES === */

/* Glowing section rule — a softer alternative to a full .band */
.rule-glow {
  height: 1px;
  border: 0;
  background: linear-gradient(90deg, transparent, var(--line-hard), transparent);
}

/* Segmented control (billing toggles, filters) */
.seg {
  display: inline-flex;
  padding: 4px;
  gap: 2px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--surface);
}

.seg button {
  min-height: 34px;
  padding: 0 16px;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-3);
  border-radius: var(--r-pill);
  transition: color var(--dur-2) var(--ease), background var(--dur-2) var(--ease);
}

.seg button[aria-pressed='true'] {
  color: #08120a;
  background: var(--grad-ai);
}

/* Shimmer placeholder */
.skel {
  border-radius: var(--r-sm);
  background: linear-gradient(90deg, rgba(255, 255, 255, .04) 25%, rgba(255, 255, 255, .09) 37%, rgba(255, 255, 255, .04) 63%);
  background-size: 400% 100%;
  animation: skel 1.4s linear infinite;
}

@keyframes skel {
  to {
    background-position: -135% 0;
  }
}

/* Copy-to-clipboard chip. ui.js binds any [data-copy] and toasts the result. */
.copy-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: 10px;
  padding: 5px 11px;
  font-family: var(--ff-mono);
  font-size: 11px;
  color: var(--ink-3);
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--surface);
  vertical-align: middle;
  transition: color var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease), background var(--dur-2) var(--ease);
}

.copy-chip:hover {
  color: var(--lime-2);
  border-color: rgba(168, 224, 74, .4);
  background: rgba(168, 224, 74, .07);
}

.copy-chip svg {
  width: 13px;
  height: 13px;
}

/* "New" flag for nav items and headings */
.pill-new {
  display: inline-flex;
  align-items: center;
  padding: 2px 7px;
  font-family: var(--ff-mono);
  font-size: 9.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #08120a;
  background: var(--grad-ai);
  border-radius: var(--r-pill);
}

/* ========================================================== RESPONSIVE === */
/* Ladder: 1240 → 1080 → 980 → 860 → 680 → 560 → 430 → 360.
   v2 covered 1080/980/680; the rest are new, plus the touch-target and
   safe-area work that has to apply to every one of them. */

/* Any pointer that isn't a mouse gets full-size targets. Applies at all
   widths — a touchscreen laptop counts. */
@media (pointer: coarse) {

  .btn,
  .chip,
  .nav-links a,
  .faq-q,
  .link-arrow,
  .seg button,
  .footer ul a {
    min-height: var(--tap);
  }

  .footer ul a,
  .link-arrow {
    display: inline-flex;
    align-items: center;
  }

  /* Hover-only flourishes are noise on touch: they either never fire or,
     worse, stick after a tap. */
  .card:hover,
  .grid>.card:hover {
    transform: none;
  }

  .assure-cell:hover .assure-mark {
    transform: none;
  }

  /* The rail's light is a hover effect it will never get, so give the cell the
     one thing a finger can actually trigger. */
  .assure-cell:active::after {
    opacity: 1;
    transition-duration: .1s;
  }
}

@media (max-width: 1240px) {
  :root {
    --maxw: 1120px;
  }
}

@media (max-width: 1080px) {

  /* Two-up section heads were running the full 760px against a narrower
     column, which broke the eyebrow → headline → lede left edge. */
  .section-head {
    max-width: 640px;
  }

  .nav-k {
    min-width: 0;
    width: 38px;
    height: 38px;
    padding: 0;
    justify-content: center;
  }

  .nav-k .lbl,
  .nav-k .kbd {
    display: none;
  }
}

@media (max-width: 980px) {

  /* The sheet is the mobile nav from here down */
  .burger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--tap);
    min-height: var(--tap);
  }

  .topbar {
    font-size: 12.5px;
    justify-content: flex-start;
    padding-inline: var(--gutter-safe) calc(var(--gutter-safe) + 34px);
  }

  /* Gives the copy column its own rhythm once the hero stacks: the visual is
     no longer beside the text, so the text no longer needs to be short. */
  .hero-grid {
    gap: var(--sp-6);
  }

  .hero .lede {
    max-width: 58ch;
  }

  .switchboard {
    gap: var(--sp-4);
  }
}

/* Tablet portrait — the band nobody had rules for. Three-up grids were still
   three-up here and every card was ~210px wide. */
@media (max-width: 860px) {
  :root {
    --section-y: clamp(64px, 10vw, 104px);
  }

  .grid-3,
  .grid-4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* Three cards two-up leaves the third alone beside an empty cell. It is
     still a full card in this band (the accordion starts at 680), so give it
     the whole row rather than half of one. */
  .step-grid>:nth-child(3) {
    grid-column: 1 / -1;
  }

  .rail {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .section-head {
    margin-bottom: var(--sp-7);
  }

  /* No room for the trailing CTA once the message has the width */
  .topbar-msg .go {
    display: none;
  }

  /* Fixed row heights only pay for themselves while the columns are side by
     side; stacked, they leave dead space. */
  .switchboard {
    grid-template-columns: 1fr;
  }

  .sb-list li {
    min-height: 0;
  }

  /* Stacked, the "with Azmile" column leads — it's the answer, not the
     footnote. */
  .sb-col--now {
    order: -1;
  }

  /* Stacked, ten rows is a long scroll to get past. Each header becomes a real
     disclosure: "with Azzy" stays open (it leads, and it's the answer), "today"
     folds away until the reader asks for it. ui.js owns the default states —
     the markup ships both open so no-JS still gets the full comparison. */
  .sb-head {
    min-height: var(--tap);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }

  /* Closed, the header's rule sits on the panel's own bottom border and the
     two draw as one thick line. */
  .sb-col:not([open]) .sb-head {
    border-bottom-color: transparent;
  }

  /* Chevron drawn from two borders so there is no extra icon to ship */
  .sb-chev {
    display: block;
    flex: none;
    margin-left: auto;
    width: 9px;
    height: 9px;
    border-right: 2px solid var(--ink-3);
    border-bottom: 2px solid var(--ink-3);
    border-radius: 1px;
    transform: translateY(-2px) rotate(45deg);
    transition: transform var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
  }

  .sb-col[open] .sb-chev {
    transform: translateY(2px) rotate(-135deg);
  }

  .sb-col--now .sb-chev {
    border-color: var(--lime-2);
  }

  /* Animate the open/close where ::details-content is supported. Elsewhere it
     simply snaps, which is the correct fallback for a disclosure. */
  .sb-col::details-content {
    block-size: 0;
    overflow: hidden;
    content-visibility: hidden;
    transition: block-size var(--dur-2) var(--ease),
      content-visibility var(--dur-2) allow-discrete;
  }

  .sb-col[open]::details-content {
    block-size: auto;
    content-visibility: visible;
  }

  /* Three across stops working the moment "Demo on your real workflows" has to
     wrap to fit its cell. Stack into a checklist instead — marks in a column,
     text ranged left — and cap the measure, or a tablet strands half a screen
     of empty rail to the right of three short lines. */
  .assure {
    grid-template-columns: 1fr;
    max-width: 520px;
    margin-inline: auto;
  }

  .assure-cell {
    justify-content: flex-start;
    padding: 14px 18px;
    font-size: 14.5px;
  }

  /* The seam turns with the layout */
  .assure-cell+.assure-cell::before {
    left: 0;
    right: 0;
    top: 0;
    bottom: auto;
    width: auto;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--line-hard), transparent);
  }
}

@media (max-width: 680px) {

  /* FAB stays off on phones. It was originally hidden because the dock owned
     this corner, but the other half of that reasoning outlived the dock: it
     sits squarely on top of whatever full-width CTA a page ends on (the
     pricing plans are the worst case), and the toasts below go full-width
     here and would run straight underneath it. Flicking up is the gesture. */
  .totop {
    display: none;
  }

  .toasts {
    left: max(12px, env(safe-area-inset-left, 0px));
    right: max(12px, env(safe-area-inset-right, 0px));
    bottom: max(12px, env(safe-area-inset-bottom, 0px));
    justify-items: stretch;
  }

  .toast {
    max-width: none;
  }

  /* Palette becomes a near-full-height sheet — a 620px box floating in the
     middle of a 700px viewport is worse than one that owns it. */
  .cmdk {
    padding: 0;
    align-items: stretch;
  }

  .cmdk-panel {
    max-width: none;
    max-height: none;
    height: 100%;
    border-radius: 0;
    border: 0;
    padding-top: env(safe-area-inset-top, 0px);
  }

  .cmdk-panel::before {
    content: none;
  }

  .cmdk-foot {
    padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px));
  }

  /* Hide the desktop-only shortcut hints; nothing on a phone has a ⌘ key */
  .cmdk-foot i {
    display: none;
  }

  /* Non-pain 4-up grids stay two-up. They're short cards — stacking them adds
     a full extra screen of scroll for no gain in legibility. */
  .grid-4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sp-3);
  }

  /* Same call for the portals grid (platform.html, the only .grid-auto on the
     site). Its 280px auto-fit track silently drops to one column somewhere
     around 600px, which turned five short icon cards into a full screen of
     scroll. Pinned to two rather than lowering the minmax floor, so the count
     is a decision instead of a side effect of the gutter. */
  .grid-auto {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sp-3);
  }

  /* Five cards leave an orphan on the last row. Spanning it is what .stats
     and .flow-grid already do, and a half-card next to a hole reads as a
     layout bug rather than the end of a list. */
  .grid-auto>.card:last-child:nth-child(odd) {
    grid-column: 1 / -1;
  }

  /* — Pain tiles become an accordion —
     Four expanded cards ran to roughly 1,150px of scroll on a 390px phone.
     Collapsed, the same four are about 230px, and opening one costs only the
     height of that one card. */
  .pain-grid {
    grid-template-columns: 1fr;
    gap: 10px;
  }

  .pain-card {
    padding: 0;
    overflow: hidden;
  }

  .pain-card>summary {
    display: flex;
    align-items: center;
    gap: 12px;
    /* min-height, not a fixed one — the topic wraps on a 320px screen */
    min-height: 62px;
    padding: 12px 15px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }

  /* The stat stops being the card's headline and becomes its badge */
  .pain-card>summary .pain-stat {
    flex: none;
    font-size: 21px;
    margin-bottom: 0;
    line-height: 1.1;
  }

  .pain-topic {
    display: block;
    flex: 1;
    min-width: 0;
    font-family: var(--ff-display);
    font-size: 14.5px;
    font-weight: 600;
    letter-spacing: -.015em;
    line-height: 1.25;
    color: var(--ink);
  }

  /* Chevron drawn from two borders so there is no extra markup or icon file */
  .pain-chev {
    display: block;
    flex: none;
    width: 9px;
    height: 9px;
    margin-right: 4px;
    border-right: 2px solid var(--ink-3);
    border-bottom: 2px solid var(--ink-3);
    border-radius: 1px;
    transform: translateY(-2px) rotate(45deg);
    transition: transform var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
  }

  .pain-card[open] .pain-chev {
    transform: translateY(2px) rotate(-135deg);
    border-color: var(--lime-2);
  }

  .pain-card>.pain-body {
    padding: 0 15px 14px;
  }

  /* Expanded, the label no longer has to hold a card open, so drop the
     bottom-alignment padding it carries in the grid layout. */
  .pain-card>.pain-body>.pain-label {
    padding-bottom: var(--sp-4);
  }

  /* Deliberately NOT animating the height. Transitioning `block-size` on
     ::details-content between 0 and auto left the pseudo stuck on its [open]
     values at 520–680px — the tile reported closed while still painting its
     body at full height. The native snap is correct at every width, so the
     entrance is an opacity/transform pass on the body instead: it reads as
     motion without putting layout on the line. */
  .pain-card[open]>.pain-body {
    animation: painOpen .26s var(--ease-out) both;
  }

  @keyframes painOpen {
    from {
      opacity: 0;
      transform: translateY(-6px);
    }
  }

  /* — Guardrail tiles become an accordion —
     Same trade, same numbers: the four "Built safe" cards ran to roughly a
     thousand pixels of scroll on a 390px phone for four one-line claims.
     Collapsed they are about 250px, and the section reads as a checklist
     you can open rather than a wall you have to scroll past. */
  .safe-grid {
    grid-template-columns: 1fr;
    gap: 10px;
  }

  .safe-card {
    padding: 0;
    overflow: hidden;
  }

  .safe-card>summary {
    display: flex;
    align-items: center;
    gap: 12px;
    /* min-height, not a fixed one — "Full audit trail" wraps at 320px */
    min-height: 62px;
    padding: 12px 15px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }

  /* The icon chip stops being a block above the title and becomes a badge
     beside it, so it loses both its size and its bottom margin. */
  .safe-card>summary>.icon {
    flex: none;
    width: 34px;
    height: 34px;
    margin-bottom: 0;
    border-radius: 10px;
  }

  .safe-card>summary>.icon svg {
    width: 17px;
    height: 17px;
  }

  .safe-card>summary>.h3 {
    flex: 1;
    min-width: 0;
    margin-bottom: 0;
    font-size: 15px;
    line-height: 1.25;
  }

  /* Chevron drawn from two borders so there is no extra markup or icon file */
  .safe-chev,
  .step-chev {
    display: block;
    flex: none;
    width: 9px;
    height: 9px;
    margin-right: 4px;
    border-right: 2px solid var(--ink-3);
    border-bottom: 2px solid var(--ink-3);
    border-radius: 1px;
    transform: translateY(-2px) rotate(45deg);
    transition: transform var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
  }

  .safe-card[open] .safe-chev,
  .step-card[open] .step-chev {
    transform: translateY(2px) rotate(-135deg);
    border-color: var(--lime-2);
  }

  .safe-card>.safe-body {
    padding: 0 15px 14px;
  }

  /* Height is deliberately not animated, for the reason spelled out on the
     pain tiles above; the entrance is the same opacity/transform pass. */
  .safe-card[open]>.safe-body {
    animation: painOpen .26s var(--ease-out) both;
  }

  /* — Flow steps become an accordion —
     Three full cards two-up was the worst of both: ~150px columns breaking
     the copy to three words a line, and a third card stranded alone on its
     own row. One per row, collapsed, reads as the three-step list it is. */
  .step-grid {
    grid-template-columns: 1fr;
    gap: 10px;
  }

  .step-card {
    padding: 0;
    overflow: hidden;
  }

  .step-card>summary {
    display: flex;
    align-items: center;
    gap: 12px;
    /* min-height, not a fixed one — "You ask in plain language" wraps at 320px */
    min-height: 62px;
    padding: 12px 15px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }

  /* The number stops being a block above the title and becomes a badge beside
     it, so it loses both its size and its bottom margin. */
  .step-card>summary>.step-n {
    flex: none;
    width: 34px;
    height: 34px;
    margin-bottom: 0;
    border-radius: 10px;
    font-size: 13.5px;
  }

  .step-card>summary>.h3 {
    flex: 1;
    min-width: 0;
    margin-bottom: 0;
    font-size: 15px;
    line-height: 1.25;
  }

  .step-card>.step-body {
    padding: 0 15px 14px;
  }

  .step-card[open]>.step-body {
    animation: painOpen .26s var(--ease-out) both;
  }

  /* Only where a tag follows — step 1 has none, and a trailing margin there
     is just dead space above the card's bottom edge. */
  .step-card>.step-body:has(>.tag)>p {
    margin-bottom: 12px;
  }

  /* — Modules bento becomes an accordion —
     Nine cards at roughly 450px each is about four screens of scroll for
     what is really a list of module names. Collapsed the whole section is
     nine rows, and the mock is the payoff for opening one. */
  .bento {
    gap: 10px;
  }

  .bento-card {
    padding: 0;
    overflow: hidden;
  }

  /* Written as a child selector, not a bare .bento-head: the base
     `.bento-fold > summary { display: block }` above scores (0,1,1) and would
     otherwise out-rank this and leave the row stacked. */
  .bento-fold>.bento-head {
    display: flex;
    align-items: center;
    gap: 12px;
    /* min-height, not a fixed one — "COD, Finance & Reconciliation" wraps */
    min-height: 62px;
    padding: 12px 15px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }

  .bento-fold>.bento-head>.h3 {
    flex: 1;
    min-width: 0;
    margin-bottom: 0;
    font-size: 15px;
    line-height: 1.25;
  }

  /* Chevron drawn from two borders so there is no extra markup or icon file */
  .bento-chev {
    display: block;
    flex: none;
    width: 9px;
    height: 9px;
    margin-right: 4px;
    border-right: 2px solid var(--ink-3);
    border-bottom: 2px solid var(--ink-3);
    border-radius: 1px;
    transform: translateY(-2px) rotate(45deg);
    transition: transform var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
  }

  .bento-fold[open] .bento-chev {
    transform: translateY(2px) rotate(-135deg);
    border-color: var(--lime-2);
  }

  .bento-fold>.bento-body {
    padding: 0 15px 14px;
  }

  .bento-fold[open]>.bento-body {
    animation: painOpen .26s var(--ease-out) both;
  }

  .bento-fold>.bento-body:has(>.tag)>p {
    margin-bottom: 12px;
  }

  /* The chip is decorative (aria-hidden) and says nothing the title does not,
     so a collapsed row does not carry one. Dropping it outright rather than
     badging it keeps all nine rows the same shape — four cards with a chip
     and five without reads as a bug, not a distinction. */
  .bento-card>.icon {
    display: none;
  }

  /* The mock is real content with its own description, so it is revealed
     rather than dropped. It sits after the fold in the DOM precisely so this
     combinator can reach it; `order` puts it back on top above 680px. */
  .bento-card>.mock {
    display: none;
  }

  .bento-fold[open]~.mock {
    display: flex;
    margin: 0 15px 14px;
    animation: painOpen .26s var(--ease-out) both;
  }

  /* — Flow steps: 2 + 1 —
     Steps 1 and 2 pair up, step 3 takes the whole row. v2 stacked all three,
     which cost about a screen and a half of scroll for three short cards. */
  .flow-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
  }

  .flow-grid>.flow-card:nth-child(3) {
    grid-column: 1 / -1;
  }

  /* A half-column here is only ~150px, and every padding in the stack is
     charged to it twice — panel, then card. Both come down so the copy keeps
     a readable measure rather than breaking to three words a line. */
  .flow-panel {
    padding: var(--sp-4);
  }

  .flow-card {
    min-height: 0;
    padding: 14px;
  }

  /* The 106px offset exists to clear the bloom on a 400px-tall desktop card.
     At this size it would be most of the tile. */
  .flow-card .flow-body {
    margin-top: 26px;
  }

  .flow-ico {
    width: 36px;
    height: 36px;
  }

  .flow-ico svg {
    width: 17px;
    height: 17px;
  }

  .flow-n {
    font-size: 19px;
  }

  .flow-card .h3 {
    font-size: 14px;
    margin: 7px 0 6px;
  }

  .flow-card p {
    font-size: 12px;
    line-height: 1.5;
  }

  /* The base .tag is nowrap; these are phrases, not identifiers, so a second
     line beats spilling past a 120px column. */
  .flow-card .tag {
    font-size: 9.5px;
    padding: 4px 7px;
    white-space: normal;
    line-height: 1.35;
  }

  /* Full width, one per row. Two up left each card about 170px, which is
     narrower than the mock's own furniture — three KPI tiles and a status pill
     were being cut off mid-word. This grid only; the other .grid-3 sections
     hold text and icons, and they read fine two up. */
  .showcase {
    grid-template-columns: 1fr;
  }

  /* Full width means a tall section, so the heading becomes the control and
     the mock and copy fold behind it. ui.js owns the default states — the
     markup ships all three open so no-JS still gets whole cards. */
  .showcase-card {
    padding: 0;
  }

  .showcase-card>summary {
    display: flex;
    align-items: center;
    gap: 12px;
    min-height: var(--tap);
    padding: 14px var(--sp-5);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }

  .showcase-card>summary .h3 {
    flex: 1;
    min-width: 0;
    font-size: 16px;
    margin-bottom: 0;
  }

  /* Chevron drawn from two borders so there is no extra icon to ship */
  .showcase-chev {
    display: block;
    flex: none;
    width: 9px;
    height: 9px;
    border-right: 2px solid var(--ink-3);
    border-bottom: 2px solid var(--ink-3);
    border-radius: 1px;
    transform: translateY(-2px) rotate(45deg);
    transition: transform var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
  }

  .showcase-card[open] .showcase-chev {
    transform: translateY(2px) rotate(-135deg);
    border-color: var(--lime-2);
  }

  .showcase-card>.mock,
  .showcase-card>p {
    margin-inline: var(--sp-5);
  }

  .showcase-card>.mock {
    margin-bottom: var(--sp-4);
  }

  .showcase-card>p {
    margin-bottom: var(--sp-5);
  }

  /* Animate the open/close where ::details-content is supported. Elsewhere it
     simply snaps, which is the correct fallback for a disclosure. */
  .showcase-card::details-content {
    block-size: 0;
    overflow: hidden;
    content-visibility: hidden;
    transition: block-size var(--dur-2) var(--ease),
      content-visibility var(--dur-2) allow-discrete;
  }

  .showcase-card[open]::details-content {
    block-size: auto;
    content-visibility: visible;
  }

  /* Stays two up on phones. The icon can't keep its seat beside the copy at
     this width — a 36px mark plus its gap leaves the paragraph about 90px of
     measure — so each cell turns into a column and the text gets the cell's
     full width back. */
  .rail {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .rail-cell {
    flex-direction: column;
    gap: 10px;
    padding: var(--sp-4);
  }

  .rail-cell .ic {
    width: 32px;
    height: 32px;
    border-radius: 10px;
  }

  .rail-cell b {
    font-size: 14px;
  }

  .rail-cell p {
    font-size: 12.5px;
    line-height: 1.5;
  }

  .tl {
    padding-left: 28px;
  }

  .tl::before {
    left: 10px;
  }

  .tl-step::before {
    left: -28px;
    margin-left: 5px;
  }

  /* Section heads centre-align on phones only where the section already
     centres its content — otherwise ragged-left stays. */
  .section-head.center {
    margin-bottom: var(--sp-6);
  }

  /* Long identifiers and figures inside prose can't be allowed to set the
     page's minimum width. */
  .mono,
  code,
  .viz-table td {
    overflow-wrap: anywhere;
  }

  /* Heavy backdrop filters are the most expensive thing on the page and the
     least visible on a small screen. */
  .card,
  .wire-card {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }

  .footer-bottom {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
  }
}

/* Small phones */
@media (max-width: 560px) {

  /* The hero is the only place a display-size headline has to survive a
     320px column, so give it a lower floor than the global clamp. */
  .hero .h1,
  .hero--fit .h1 {
    font-size: clamp(29px, 8.4vw, 44px);
  }

  .h2 {
    font-size: clamp(25px, 6.8vw, 34px);
  }

  .hero-cta {
    gap: 10px;
  }

  .hero-cta .btn {
    width: 100%;
  }

  .eyebrow {
    font-size: 10px;
    padding: 7px 13px;
  }

  .section-head {
    margin-bottom: var(--sp-6);
  }

  .stats .stat {
    padding: var(--sp-5) var(--sp-4);
  }

  /* Below here a portals column is under ~250px and the card's own 32px
     padding is charged to it twice, leaving less than half the tile for
     text. Same compaction .bento-2 uses to hold its two-up on a phone.
     The full-width last card takes it too — matching its neighbours matters
     more than the extra room it happens to have. */
  .grid-auto>.card {
    padding: var(--sp-4);
  }

  .grid-auto>.card .icon {
    width: 36px;
    height: 36px;
    margin-bottom: var(--sp-4);
    border-radius: 11px;
  }

  .grid-auto>.card .icon svg {
    width: 18px;
    height: 18px;
  }

  .grid-auto>.card .h3 {
    font-size: 15px;
  }

  .grid-auto>.card p {
    font-size: 12.5px;
    line-height: 1.6;
  }
}

@media (max-width: 430px) {
  :root {
    --gutter: 16px;
  }

  /* Below this the two-up tiles genuinely stop working. .bento-2 is left
     alone on purpose — v2 keeps the text-only showcase two-up on phones with
     reduced type, and that decision still reads well at 390px. */
  .grid-4 {
    grid-template-columns: 1fr;
  }

  .topbar {
    font-size: 12px;
  }

  /* Just the headline claim — the rest would only ever be an ellipsis */
  .topbar-msg .d {
    display: none;
  }

  .drawer-nav a {
    min-height: 50px;
    font-size: 16px;
  }

  .drawer-ico {
    width: 34px;
    height: 34px;
  }
}

@media (max-width: 360px) {
  .nav-cta .btn-primary {
    --btn-px: 14px;
    font-size: 13px;
  }

}

/* Short landscape windows — phones on their side, and small laptop windows */
@media (max-height: 560px) and (orientation: landscape) {

  .hero--fit {
    min-height: 0;
    padding-block: var(--sp-7);
  }

  .cmdk {
    padding-top: 24px;
  }

  .cmdk-panel {
    max-height: calc(100vh - 48px);
  }
}

/* ============================================================= MOTION ==== */
@media (prefers-reduced-motion: reduce) {

  .drawer-nav a {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .cmdk-panel {
    transform: none;
  }

  .toast,
  .skel {
    animation: none;
  }

  .skel {
    background: rgba(255, 255, 255, .06);
  }

  /* Cross-document transitions are a full-page motion effect; opt out. */
  @view-transition {
    navigation: none;
  }
}

/* Nothing here should ever hide content when scripting is off */
.no-js .drawer-nav a {
  opacity: 1;
  transform: none;
}

/* ============================================================== PRINT ==== */
@media print {

  .nav,
  .topbar,
  .drawer,
  .totop,
  .toasts,
  .cmdk,
  .progress,
  .hero-scroll,
  .neural,
  .orb,
  .hero-aurora,
  .hero-mesh {
    display: none !important;
  }

  body {
    padding-bottom: 0;
    background: #fff;
    color: #000;
  }

  .card,
  .plan,
  .rail-cell,
  .sb-col {
    break-inside: avoid;
    border-color: #ccc;
    background: none;
    box-shadow: none;
  }

  a[href^='http']::after {
    content: ' (' attr(href) ')';
    font-size: 10px;
  }
}
