/* ===================================================================
   JAPHONE — design tokens
=================================================================== */
:root {
  --ink: #050506;
  --panel: #0B0E14;
  --panel-2: #12161F;
  --line: rgba(255,255,255,0.10);
  --line-soft: rgba(255,255,255,0.06);
  /* Shades of white, not shades of blue. The old pair sat at 92.7% and 95.1%
     lightness with ~30% saturation, and at that darkness the blue cast became
     visible — the section change read as "white to light blue" rather than as
     one surface stepping to another. These are the same relationship (a ~2
     point step) moved up near white, so the step reads as tone, not hue.
     --paper is the sunken/alternating section; --paper-2 is the canvas. */
  --paper: #F3F4F8;
  --paper-2: #FAFBFC;
  /* A third, deeper step so sections have more than two tones to work with.
     The rule that keeps it grey instead of blue: saturation drops as
     lightness drops. The old blue --paper held ~30% saturation at 92.7%
     lightness; this is DARKER at 93.5% but only 15% saturation, so it reads
     as a deeper white rather than a blue tint. */
  --paper-3: #ECEDF1;
  /* The two shadow colours every raised and recessed surface is built from. */
  --soft-dark: rgba(163,177,198,0.55);
  --soft-light: rgba(255,255,255,0.95);
  --text-hi: #F5F6F8;
  --text-lo: #8B93A7;
  --text-dark: #0B0E14;
  /* Darkened with the ground. #5B6472 cleared 4.5:1 against white; against
     the softer #EEF1F7 it fell to 3.84 and stopped being readable body text. */
  --text-dark-lo: #4E5766;
  /* Ink as raw channels, so themed surfaces can invert every hairline border,
     hover tint and divider that was authored as "ink at N% alpha". */
  --ink-rgb: 11,14,20;

  /* The ticker is a normal-flow bar at the very top; the nav is fixed. Both
     numbers live here so the nav can be parked clear of the bar instead of
     under it, and js/main.js does not have to hard-code the offset. */
  --ticker-h: 32px;
  --nav-top: calc(var(--ticker-h) + 14px);
  --blue: #2F6FFF;
  /* White on --blue measures 4.34:1, just under the 4.5:1 AA floor, and button
     labels here are 13.6px/600 so the normal-text threshold applies. This is
     the same blue a shade down (4.93:1) and is used ONLY where white text sits
     on a blue fill. Borders, links, focus rings and accents keep --blue. */
  --blue-cta: #2A66F0;
  --blue-bright: #6E9BFF;
  --blue-soft: rgba(47,111,255,0.14);
  /* --blue is 3.8:1 on the soft ground, which is under the 4.5 small text
     needs. Fills keep --blue; anything you have to READ takes this. */
  --blue-ink: #1D4FD8;
  --amber: #FFD166;
  /* Yellow is light; use this for accent TEXT on light surfaces.
     Darkened from #9A7500, which measured 3.77:1 on the light card and failed
     WCAG AA for the small labels and notes using it. This is 4.53:1 there and
     5.12:1 on white. The hero's big accent word passed either way at its size. */
  --amber-deep: #7E5F00;
  --amber-soft: rgba(255,209,102,0.14);
  --green: #34D399;
  /* #34D399 is a light mint — fine on the dark sections, but only 1.9:1 on a
     white card, which is unreadable at small sizes. Use this for green TEXT on
     light surfaces, the same way --amber-deep exists for yellow. */
  --green-deep: #047857;

  --font-display: 'Space Grotesk', sans-serif;
  --font-body: 'Plus Jakarta Sans', sans-serif;

  --container: 1240px;
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);

  /* The ambient card elevation. Same glass anatomy as --lift-*, one step
     softer, since this is what most panels and cards sit on. */
  --shadow-soft:
    0 1px 2px rgba(19,22,30,0.04),
    0 8px 24px -10px rgba(31,38,135,0.12);
  --shadow-glass: 0 30px 80px -20px rgba(0,0,0,0.55), inset 0 1px 0 rgba(255,255,255,0.06);

  /* ---------------------------------------------------------------- soft UI
     One scale of radii and one of elevations, so a button, a card, an input
     and a panel are all obviously the same family. Everything below is
     expressed against these rather than hand-rolled per component, which is
     how the site drifted into five different shadows in the first place.

     The elevations are two-part: a cool shadow below and a white highlight
     above, which is what makes a surface look lifted off the page rather
     than stuck on with a drop shadow. */
  --r-xs: 10px;
  --r-sm: 14px;
  --r-md: 18px;
  --r-lg: 24px;
  --r-xl: 32px;
  --r-pill: 999px;

  /* ---- spacing scale ----
     Seeded from this file's own most-common gap/padding/margin values —
     the real rhythm here runs in ~2px steps, not an imported 8px grid. */
  --space-1: 2px;   --space-2: 4px;   --space-3: 6px;   --space-4: 8px;
  --space-5: 10px;  --space-6: 12px;  --space-7: 14px;  --space-8: 16px;
  --space-9: 18px;  --space-10: 20px; --space-11: 22px; --space-12: 24px;
  --space-13: 26px; --space-14: 28px; --space-15: 32px; --space-16: 40px;

  /* ---- type scale ----
     Named from this file's own most-common font-size values. Numbered
     rather than xs/sm/md/lg — too many close, real steps for t-shirt
     sizes to stay meaningful. */
  --fs-1: 0.66rem;  --fs-2: 0.68rem;  --fs-3: 0.7rem;   --fs-4: 0.72rem;
  --fs-5: 0.78rem;  --fs-6: 0.8rem;   --fs-7: 0.82rem;  --fs-8: 0.85rem;
  --fs-9: 0.86rem;  --fs-10: 0.88rem; --fs-11: 0.9rem;  --fs-12: 0.92rem;
  --fs-13: 0.95rem; --fs-14: 1.02rem;

  /* ---------------------------------------------------------------- glass
     Liquid Glass, replacing the soft-UI elevations. Neumorphism made depth
     out of a light and a dark shadow on an opaque surface; glass makes it
     out of a translucent pane with light caught on its edges. Four parts,
     the same four the wizard's glass already uses:

       1. a frosted, translucent fill, so the section tone shows through
       2. a specular line along the top edge, where the light lands
       3. a chromatic split at the rim, cool on one side and warm on the
          other, standing in for what a real refraction shader would do
       4. a soft cast shadow, so it still sits ABOVE the page

     The lift/press names are kept deliberately: 57 selectors already
     reference them, so redefining them here converts the whole site at
     once instead of touching every rule. */
  /* Glassmorphism, not Liquid Glass. The difference that matters: Liquid
     Glass is thin and very see-through, which is fine for a control
     floating over a photo but goofy over a page of text — content behind
     stays legible and collides with the content in front. Glassmorphism
     leans on the BLUR instead, at an opacity high enough that whatever is
     behind becomes an unreadable wash. So: heavier fill, heavier blur, one
     soft border, one soft shadow, and none of the specular / chromatic-rim
     / gloss ornamentation. */
  /* Two things make this read as glass rather than a tinted box:
       1. a heavy blur — heavy enough that text behind becomes an
          unreadable wash. This, not opacity, is what stops bleed-through,
          which means the pane can stay genuinely translucent.
       2. a bright rim, crisp all the way around. It is the single most
          recognisable part of the look; without it a translucent panel
          just reads as a lighter rectangle.
     A hairline ring is paired with the rim on light surfaces, because a
     white border on a near-white card is invisible on its own. */
  /* Tinted rather than pure white, and a touch more solid. The sections
     underneath are near-neutral, so a whisper of the brand hue in the
     pane is what makes it read as coloured glass instead of frosted
     plastic. Kept faint on purpose — much past this and it stops being
     glass and starts being a blue card. */
  /* Near-clear, and that is the whole point. At 0.74 this was a white sheet
     with a stroke on it — a card, not glass. Glass is only visible by what
     it does to what is behind it, so the paint gets out of the way and the
     blur carries legibility instead. Two layers: a broad diagonal specular
     sweep, and a faint body tint under it. */
  --glass-sheen: linear-gradient(118deg,
    transparent 26%, rgba(255,255,255,0.08) 38%,
    rgba(255,255,255,0.02) 47%, transparent 60%);
  --glass-body:  linear-gradient(160deg,
    rgba(255,255,255,0.07), rgba(255,255,255,0.01));
  /* The thickness. A pane of real glass shows its near surface catching
     light along the top, its far surface as a caustic along the bottom,
     and a slight densening of the body just inside the rim. */
  --glass-bevel:
    inset 0 1px 0 0 rgba(255,255,255,0.48),
    inset 0 -1.5px 2px -1px rgba(255,255,255,0.30),
    inset 0 0 16px -10px rgba(19,22,30,0.20);
  --glass-fill-2: rgba(246,249,255,0.90);   /* menus and overlays stay opaque */
  --glass-border: rgba(255,255,255,0.9);
  /* The rim, as a sweep rather than a value. 0deg is the top of the pane
     and the angle runs clockwise: white across the top from a light in the
     upper left, thinning through the right side, tipping into a faint dark
     along the lower right — which is what holds the pane's boundary there
     now that no hairline does — then back up through the left. First and
     last stops match, so the sweep closes without a seam. */
  --glass-lens: conic-gradient(from 0deg at 50% 50%,
    rgba(255,255,255,0.40)   0deg,
    rgba(255,209,102,0.12)  42deg,   /* amber fringe */
    rgba(255,255,255,0.07)  92deg,
    rgba(19,22,30,0.07)    150deg,
    rgba(19,22,30,0.09)    200deg,
    rgba(47,111,255,0.09)  248deg,   /* blue fringe */
    rgba(255,255,255,0.22) 300deg,
    rgba(255,255,255,0.40) 360deg);
  /* Was 0 0 0 1px — a hard hairline all the way round, which is a drawn
     outline, not an edge. The rim sweep above does that job now; this is
     just what seats the pane on the page. */
  --glass-ring:   0 1px 3px rgba(19,22,30,0.07);
  /* Saturation well above 100% so colour passing under the pane comes
     through vivid rather than washed — the single thing that separates
     glass from frosted plastic. */
  --glass-blur:   blur(16px) saturate(185%);
  /* The rim band's own filter. Saturation pushed hard so the edge takes
     its colour from whatever is behind it, the way a real lens edge goes
     pink over red and teal over teal. Over a neutral ground it resolves
     to neutral and the conic carries the edge alone. A token because dark
     grounds need it far lower: 420% of a navy page is a vivid blue ring
     that reads as a focus state. */
  --glass-rim-filter: blur(2px) brightness(1.22) saturate(420%);

  --lift-1:
    0 1px 2px rgba(19,22,30,0.04),
    0 4px 14px -6px rgba(31,38,135,0.10);
  --lift-2:
    0 2px 4px rgba(19,22,30,0.04),
    0 10px 28px -10px rgba(31,38,135,0.14);
  --lift-3:
    0 4px 8px rgba(19,22,30,0.05),
    0 22px 52px -16px rgba(31,38,135,0.20);
  /* Recessed glass: the pane sits BELOW the surface, so the specular moves
     to the inside of the top edge and the tint darkens rather than lifts. */
  --press-1:
    inset 0 1px 3px rgba(19,22,30,0.10),
    inset 0 -1px 0 rgba(255,255,255,0.7);
  --press-2:
    inset 0 2px 6px rgba(19,22,30,0.14),
    inset 0 -1px 0 rgba(255,255,255,0.6);
  /* Soft UI carries no outlines; edges come from the light. Kept as a token so
     the few places that genuinely need a line still have one to reach for. */
  --hairline: 1px solid rgba(163,177,198,0.22);
  --focus-ring: 0 0 0 3px rgba(47,111,255,0.22);
  /* Universal icons rather than typographic characters or emoji: these render
     identically on every platform and inherit currentColor through a mask. */
  --icon-arrow-ne: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 17L17 7M9 7h8v8'/%3E%3C/svg%3E");
  --icon-arrow-right: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E");
  --icon-arrow-left: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 12H5M11 18l-6-6 6-6'/%3E%3C/svg%3E");
  --icon-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E");
}

* { box-sizing: border-box; margin: 0; padding: 0; }
body {
  background: var(--paper-2);
  color: var(--text-dark);
  font-family: var(--font-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  position: relative;
}
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 999;
  pointer-events: none;
  opacity: 0.025;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; background: none; border: none; cursor: pointer; color: inherit; }
ul { list-style: none; }
input, textarea, select { font: inherit; }

.section-eyebrow {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-display);
  font-size: var(--fs-2);
  font-weight: 600;
  letter-spacing: 0.16em;
  color: var(--blue);
  padding: 7px var(--space-8);
  border-radius: var(--r-pill);
  border: 1px solid rgba(47,111,255,0.22);
  background: rgba(47,111,255,0.07);
  margin-bottom: var(--space-9);
}
.section-eyebrow--center { margin-left: auto; margin-right: auto; }

/* ===================================================================
   BUTTONS
=================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  padding: 15px var(--space-12);
  border-radius: var(--r-pill);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-8);
  letter-spacing: 0.02em;
  transition:
    transform 0.28s var(--ease-spring),
    background 0.28s var(--ease),
    color 0.28s var(--ease),
    border-color 0.28s var(--ease),
    box-shadow 0.28s var(--ease);
  white-space: nowrap;
  position: relative;
  -webkit-tap-highlight-color: transparent;
}
.btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.btn--solid, .btn--outline { padding-right: 54px; }
/* The arrow was the character U+2197, which every platform draws differently
   and some draw as a colour emoji. A masked SVG is the same glyph everywhere
   and takes currentColor, so it tracks the button's own text. */
.btn--solid::after, .btn--outline::after {
  content: '';
  position: absolute;
  right: 6px;
  top: 50%;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  transform: translateY(-50%);
  background-color: currentColor;
  transition: transform 0.28s var(--ease-spring), opacity 0.28s var(--ease);
}
/* Two layers on one pseudo-element: the disc is a background-color, the arrow
   is punched out of it by a mask, so this needs a separate element for the
   glyph. ::before carries the arrow, ::after the disc behind it. */
.btn--solid::before, .btn--outline::before {
  content: '';
  position: absolute;
  right: 6px;
  top: 50%;
  width: 32px;
  height: 32px;
  transform: translateY(-50%);
  z-index: 1;
  background-color: currentColor;
  -webkit-mask: var(--icon-arrow-ne) center / 13px 13px no-repeat;
  mask: var(--icon-arrow-ne) center / 13px 13px no-repeat;
  transition: transform 0.28s var(--ease-spring);
}

.btn--solid {
  background: var(--blue-cta);
  color: #fff;
  box-shadow:
    0 1px 2px rgba(47,111,255,0.24),
    0 10px 24px -10px rgba(47,111,255,0.55),
    inset 0 1px 0 rgba(255,255,255,0.25);
}
.btn--solid::after { background-color: rgba(255,255,255,0.20); }
.btn--solid:hover {
  transform: translateY(-2px);
  background: var(--blue-bright);
  box-shadow:
    0 2px 4px rgba(47,111,255,0.24),
    0 16px 32px -12px rgba(47,111,255,0.6),
    inset 0 1px 0 rgba(255,255,255,0.3);
}
.btn--solid:hover::before { transform: translateY(-50%) translate(2px,-2px); }
.btn--solid:active {
  transform: translateY(0) scale(0.985);
  box-shadow: inset 0 2px 6px rgba(12,40,110,0.35);
}

.btn--outline {
  border: 1px solid rgba(255,255,255,0.22);
  color: inherit;
}
.btn--outline::after { background-color: rgba(255,255,255,0.08); }
.btn--outline:hover { transform: translateY(-2px); border-color: var(--blue); color: var(--blue-bright); }
.btn--outline:hover::before { transform: translateY(-50%) translate(2px,-2px); }
.btn--outline:active { transform: translateY(0) scale(0.985); }

.btn--ghost-invert { border: 1px solid var(--line); color: var(--text-hi); font-size: var(--fs-5); padding: 11px var(--space-11); }
.btn--ghost-invert:hover { background: var(--text-hi); color: var(--ink); }
.btn--full { width: 100%; padding: var(--space-8) 54px var(--space-8) var(--space-12); margin-top: var(--space-4); }

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-4);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-8);
  color: var(--text-dark);
  border-bottom: 1px solid currentColor;
  padding-bottom: var(--space-1);
  width: fit-content;
}
.link-arrow::after { content: '→'; transition: transform 0.4s var(--ease-spring); }
.link-arrow:hover::after { transform: translateX(4px); }
/* A back link points the other way. Without this the shared ::after arrow is
   appended to a label that already leads with one, and it reads
   "← Back to plans →". */
.link-arrow--back::after { content: none; }
.link-arrow--back::before { content: '←'; transition: transform 0.4s var(--ease-spring); }
.link-arrow--back:hover::before { transform: translateX(-4px); }

/* ===================================================================
   TICKER
=================================================================== */
.ticker {
  background: var(--ink);
  color: var(--text-lo);
  overflow: hidden;
  white-space: nowrap;
  font-family: var(--font-display);
  font-size: var(--fs-2);
  letter-spacing: 0.08em;
  border-bottom: 1px solid var(--line-soft);
  position: relative;
  z-index: 200;
}
.ticker__track {
  display: inline-flex;
  gap: var(--space-7);
  padding: 7px 0;
  animation: ticker-scroll 32s linear infinite;
}
.ticker__track span { padding: 0 6px; }
/* Fade the text into the bar at both edges — a marquee that hard-cuts at the
   viewport looks like clipped text rather than a moving line. */
.ticker::before, .ticker::after {
  content: '';
  position: absolute;
  top: 0; bottom: 0;
  width: 72px;
  z-index: 1;
  pointer-events: none;
}
.ticker::before { left: 0; background: linear-gradient(90deg, var(--ink), rgba(5,5,6,0)); }
.ticker::after { right: 0; background: linear-gradient(270deg, var(--ink), rgba(5,5,6,0)); }
.ticker__stat { color: #FFDA7A; font-weight: 700; }
@keyframes ticker-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

/* ===================================================================
   SKIP LINK — invisible until a keyboard user tabs to it
=================================================================== */
.skip-link {
  position: absolute;
  top: -100px;
  left: 16px;
  z-index: 999;
  background: var(--ink);
  color: #fff;
  padding: var(--space-6) var(--space-10);
  border-radius: var(--r-xs);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-11);
  text-decoration: none;
  transition: top 0.2s var(--ease);
}
.skip-link:focus { top: 16px; outline: 2px solid var(--blue-bright); outline-offset: 2px; }

/* ===================================================================
   NAV — floating glass island
=================================================================== */
.nav {
  position: fixed;
  top: var(--nav-top);
  /* .is-docked: the ticker has scrolled away, so close the gap it was holding.
     .is-hidden must come after it — same specificity, and hiding wins. */
  left: 50%;
  transform: translateX(-50%);
  z-index: 190;
  color: var(--text-hi);
  width: max-content;
  max-width: calc(100vw - 32px);
  transition: top 0.3s var(--ease);
}
.nav.is-docked { top: 12px; }
/* After .is-docked on purpose — same specificity, and hidden has to win. */
.nav.is-hidden { top: -90px; }
.nav__inner {
  display: flex;
  align-items: center;
  gap: 30px;
  padding: 9px var(--space-5) 9px var(--space-10);
  background: rgba(8,10,18,0.72);
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
  border: 1px solid rgba(255,255,255,0.09);
  border-radius: var(--r-pill);
  box-shadow: 0 12px 30px -14px rgba(0,0,0,0.55), inset 0 1px 0 rgba(255,255,255,0.05);
}
.brand { display: flex; align-items: center; gap: var(--space-4); font-family: var(--font-display); font-weight: 700; font-size: var(--fs-13); letter-spacing: 0.02em; flex-shrink: 0; }
.brand__mark { flex-shrink: 0; }
.nav__links { display: flex; gap: var(--space-12); font-size: var(--fs-7); font-weight: 500; }
.nav__links a { opacity: 0.85; transition: opacity 0.25s; }
.nav__links a:hover { opacity: 1; }
.nav__cta { flex-shrink: 0; }
.nav__cta.btn--ghost-invert { font-size: 0.74rem; padding: var(--space-4) var(--space-8); }

.nav__toggle {
  display: none;
  position: relative;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: var(--space-2);
  width: 30px;
  height: 30px;
  padding: 0;
  background: none;
  border: none;
  flex-shrink: 0;
  cursor: pointer;
}
/* This is the only way into the menu on a phone, so the glyph stays 30px but
   the tappable area reaches the 44px minimum. */
.nav__toggle::before {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 44px; height: 44px; transform: translate(-50%, -50%);
}
.nav__toggle span {
  display: block;
  width: 16px;
  height: 2px;
  border-radius: 2px;
  background: var(--text-hi);
  transition: transform 0.3s var(--ease), opacity 0.3s var(--ease);
}
.nav__toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav__toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav__toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

@media (max-width: 860px) {
  .nav__toggle { display: flex; }
  .nav__links {
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-1);
    position: absolute;
    top: calc(100% + 10px);
    left: 0;
    right: 0;
    min-width: 220px;
    background: rgba(8,10,18,0.94);
    backdrop-filter: blur(20px) saturate(160%);
    -webkit-backdrop-filter: blur(20px) saturate(160%);
    border: 1px solid rgba(255,255,255,0.09);
    border-radius: 20px;
    padding: var(--space-5);
    box-shadow: 0 20px 40px -14px rgba(0,0,0,0.6);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-8px);
    transition: opacity 0.25s var(--ease), transform 0.25s var(--ease), visibility 0s linear 0.25s;
  }
  .nav__links.is-open {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    transition: opacity 0.25s var(--ease), transform 0.25s var(--ease);
  }
  .nav__links a { padding: 11px var(--space-7); border-radius: 12px; }
  .nav__links a:hover { background: rgba(255,255,255,0.07); }
}

/* ===================================================================
   HERO (liquid cursor-reveal)
=================================================================== */
/* Hero sits on white now, with the same soft blue/amber wash the .decay and
   .integrations sections use — a little glow, not a gradient feature. The
   WebGL starfield is gone (its init is skipped in index.html too); the giant
   JAPHONE watermark stays, restated in ink instead of bone. */
.hero {
  position: relative;
  min-height: 100vh;
  background: var(--paper-2);
  color: var(--text-dark);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  isolation: isolate;
}
.hero__starfield { display: none; }
.hero__fallback { display: none; }
/* The blue and amber glows that used to drift across this section are gone.
   On the near-white surface they read as coloured haze rather than depth,
   and they fought the section tones for attention. Sections are now
   differentiated by tone alone. */
@keyframes hero-drift {
  0% { transform: translate(0, 0) scale(1); }
  100% { transform: translate(-3%, 2%) scale(1.06); }
}
/* Soft fade into the section below, so the watermark doesn't butt against the
   next block's edge. */
.hero__vignette {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: linear-gradient(180deg, transparent 72%, rgba(255,255,255,0.75) 100%);
  pointer-events: none;
}
.hero__watermark {
  position: absolute;
  z-index: 1;
  left: 50%;
  bottom: -4vw;
  transform: translateX(-50%);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(4rem, 22vw, 20rem);
  letter-spacing: 0.02em;
  color: rgba(var(--ink-rgb),0.055);
  white-space: nowrap;
  pointer-events: none;
  line-height: 1;
}
.hero__grid {
  position: relative;
  z-index: 3;
  flex: 1;
  display: grid;
  grid-template-columns: 1.25fr 0.85fr;
  gap: var(--space-16);
  align-items: center;
  max-width: 1220px;
  width: 100%;
  margin: 0 auto;
  padding: 150px var(--space-15) var(--space-16);
  pointer-events: none;
}
.hero__main { text-align: left; }
.hero__eyebrow {
  display: inline-flex;
  font-family: var(--font-display);
  font-size: var(--fs-4);
  font-weight: 600;
  letter-spacing: 0.18em;
  color: var(--amber-deep);
  padding: 7px var(--space-8);
  border-radius: var(--r-pill);
  border: 1px solid rgba(154,117,0,0.22);
  background: rgba(255,209,102,0.16);
  margin-bottom: var(--space-12);
}
.hero__title {
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
  line-height: 1.08;
  letter-spacing: -0.01em;
  font-size: clamp(2.4rem, 5.6vw, 4.6rem);
  color: var(--text-dark);
  margin-bottom: var(--space-11);
}
.hero__title .line { display: block; overflow: hidden; padding: 0 2px; }
.hero__title .word { display: inline-block; }
.hero__title .word--accent { color: var(--amber-deep); }
.hero__trust {
  display: flex;
  align-items: center;
  gap: 9px;
  font-family: var(--font-display);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  color: var(--text-dark-lo);
  margin-bottom: var(--space-9);
}
.hero__trust-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: #34D399;
  box-shadow: 0 0 0 4px rgba(52,211,153,0.18);
  flex-shrink: 0;
}
.hero__sub {
  font-size: clamp(1rem, 1.4vw, 1.15rem);
  color: var(--text-dark-lo);
  max-width: 520px;
  margin: 0 0 34px;
}
.hero__ctas { display: flex; gap: var(--space-8); justify-content: flex-start; flex-wrap: wrap; pointer-events: auto; }
/* The shared .btn--outline is drawn for dark surfaces (white borders); on the
   white hero it needs ink instead. */
.hero .btn--outline { border-color: rgba(var(--ink-rgb),0.16); color: var(--text-dark); }
.hero .btn--outline::after { background: rgba(var(--ink-rgb),0.05); border-color: rgba(var(--ink-rgb),0.1); }
.hero .btn--outline:hover { border-color: var(--blue); color: var(--blue); }

/* Aside stacks the logo orb above the rotating proof card. */
.hero__aside {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 30px;
  pointer-events: auto;
}
.orb.hero__orb { width: 150px; height: 150px; flex-shrink: 0; }
.orb.hero__orb .orb__core { width: 132px; height: 132px; }

.hero-card {
  width: 100%;
  max-width: 340px;
  background: var(--paper-2);
  border: 1px solid rgba(var(--ink-rgb),0.08);
  border-radius: 20px;
  padding: var(--space-11);
  box-shadow: var(--shadow-soft);
}
.hero-card__row { display: flex; gap: var(--space-7); align-items: flex-start; }
.hero-card__mark {
  width: 44px; height: 44px; border-radius: 12px; flex-shrink: 0;
  background: rgba(47,111,255,0.08);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.hero-card__mark img { width: 26px; height: 26px; object-fit: contain; }
.hero-card__panel { flex: 1; min-width: 0; }
.hero-card__slot { min-height: 58px; }
.hero-card__caption {
  font-family: var(--font-display); font-size: var(--fs-1); letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--amber-deep); margin-bottom: var(--space-3);
}
.hero-card__text { font-size: var(--fs-12); color: var(--text-dark); line-height: 1.45; }
.hero-card__foot {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: var(--space-8); padding-top: var(--space-7); border-top: 1px solid rgba(var(--ink-rgb),0.08);
}
.hero-card__dots { display: flex; gap: var(--space-3); }
.hero-card__dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: rgba(var(--ink-rgb),0.18);
  transition: background 0.3s, transform 0.3s;
}
.hero-card__dot.is-active { background: var(--blue); transform: scale(1.3); }
.hero-card__nav { display: flex; gap: var(--space-3); }
.hero-card__btn {
  position: relative;
  width: 26px; height: 26px; border-radius: 50%;
  border: 1px solid rgba(var(--ink-rgb),0.14);
  background: transparent; color: var(--text-dark-lo);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; transition: background 0.2s, border-color 0.2s, color 0.2s;
}
/* The visible dot stays small so the carousel controls don't overpower the
   card, but the tappable area still meets the 44px touch-target minimum. */
.hero-card__btn::before {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 44px; height: 44px; transform: translate(-50%, -50%);
}
.hero-card__btn:hover { background: rgba(var(--ink-rgb),0.05); border-color: rgba(var(--ink-rgb),0.28); color: var(--text-dark); }
.hero__status {
  position: relative;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: space-between;
  max-width: 1220px;
  width: 100%;
  margin: 0 auto;
  padding: 0 32px 30px;
  font-family: var(--font-display);
  font-size: var(--fs-1);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-dark-lo);
  pointer-events: none;
}
.hero__status-center { display: none; }
.hero__status-scroll span { display: inline-block; animation: hero-bob 1.6s ease-in-out infinite; margin-left: var(--space-2); }
@keyframes hero-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(4px); }
}
@media (min-width: 720px) {
  .hero__status-center { display: block; }
}
@media (max-width: 900px) {
  .hero__grid { grid-template-columns: 1fr; text-align: center; padding-top: 130px; }
  .hero__main { text-align: center; }
  .hero__trust { justify-content: center; }
  .hero__sub { margin-left: auto; margin-right: auto; }
  .hero__ctas { justify-content: center; }
  /* Keep the orb on small screens — only the proof card drops out. */
  .hero__aside { gap: 0; }
  .hero__aside .hero-card { display: none; }
  .orb.hero__orb { width: 120px; height: 120px; }
  .orb.hero__orb .orb__core { width: 104px; height: 104px; }
}
@media (max-width: 620px) {
  /* On a phone the headline and the paragraph under it were close enough in
     weight that the eye landed on the paragraph first. The headline is the
     message, so it grows and the paragraph gives a little back. The vw term
     drives the middle of the range; the floor protects small phones and the
     ceiling stops it colliding with the 620px breakpoint. */
  .hero__title { font-size: clamp(2.6rem, 12.6vw, 3.2rem); }
  .hero__sub { font-size: var(--fs-13); }
}
.reveal-up { opacity: 0; transform: translateY(24px); filter: blur(8px); }

/* ===================================================================
   PROBLEM / DECAY (stat scrub section)
=================================================================== */
.decay {
  position: relative;
  background: var(--paper-2);
  padding: 140px 0 0;
}
.decay::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 780px;
  pointer-events: none;
  z-index: 0;
}
.decay__gradient { display: none; }
.decay__grid {
  position: relative;
  z-index: 1;
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 32px 64px;
  display: grid;
  grid-template-columns: 0.5fr 1.5fr;
  gap: var(--space-12) 48px;
}
.decay__image-wrap { grid-column: 1; }
.decay__image {
  width: 100%;
  aspect-ratio: 1;
  border-radius: 26px;
  /* The photo shows through clean — no tint layered over it. */
  background: url("../assets/decay-photo.jpg") center/cover no-repeat, #0E1420;
  border: 1px solid rgba(var(--ink-rgb),0.08);
  box-shadow: var(--shadow-soft);
}
.decay__statement {
  grid-column: 2;
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: clamp(2rem, 4.4vw, 3.6rem);
  line-height: 1.02;
  color: var(--text-dark);
}
.decay__line { display: block; }
.decay__line--dim { color: rgba(var(--ink-rgb),0.22); transition: color 0.5s var(--ease); }
.decay__line--dim.is-lit { color: var(--text-dark); }

.decay__copy {
  grid-column: 2;
  max-width: 560px;
  margin-top: var(--space-14);
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
}
.decay__copy p { color: var(--text-dark-lo); font-size: var(--fs-14); }
.decay__copy-fade { opacity: 0.45; transition: opacity 0.5s var(--ease); }
.decay__copy-fade.is-lit { opacity: 1; }
.decay__copy .link-arrow { color: var(--text-dark); margin-top: var(--space-3); }

.decay__stats {
  grid-column: 1 / -1;
  margin-top: 90px;
  background: var(--paper);
  border-radius: var(--r-xl);
  padding: 76px 52px 64px;
  color: var(--text-dark);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-16);
  box-shadow: var(--shadow-soft);
}
.decay__stats-label {
  grid-column: 1 / -1;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-13);
  color: var(--text-dark-lo);
  border-bottom: 1px solid rgba(var(--ink-rgb),0.10);
  padding-bottom: var(--space-14);
  margin-bottom: var(--space-5);
}
.stat-block__number {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2.6rem, 5vw, 4.2rem);
  line-height: 1;
  letter-spacing: -0.02em;
}
.stat-block__label { color: var(--text-dark-lo); margin-top: var(--space-5); max-width: 260px; font-size: var(--fs-13); }

@media (max-width: 860px) {
  .decay__grid { grid-template-columns: 1fr; }
  .decay__image-wrap, .decay__statement, .decay__copy { grid-column: 1; }
  .decay__stats { grid-template-columns: 1fr; padding: 48px var(--space-12) 64px; }
}

/* ===================================================================
   PIPELINE (pinned scrollytelling)
=================================================================== */
.pipeline {
  position: relative;
  background: var(--paper);
}
.pipeline::before { display: none; }
.pipeline__pin {
  height: 100vh;
  will-change: transform;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 100px var(--space-15);
  max-width: var(--container);
  margin: 0 auto;
}
.pipeline__eyebrow {
  display: inline-flex;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-2);
  letter-spacing: 0.16em;
  color: var(--blue);
  padding: 7px var(--space-8);
  border-radius: var(--r-pill);
  border: 1px solid rgba(47,111,255,0.22);
  background: rgba(47,111,255,0.07);
  margin-bottom: var(--space-9);
}
.pipeline__header h2 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.7rem, 3.6vw, 2.6rem);
  max-width: 700px;
  letter-spacing: -0.01em;
}
.pipeline__clock {
  position: absolute;
  top: 100px;
  right: 32px;
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--text-dark-lo);
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  padding: var(--space-5) var(--space-9);
  border-radius: var(--r-pill);
  background: var(--paper-2);
  box-shadow: var(--shadow-soft);
}
.pipeline__clock #pipeline-seconds { font-size: 2.2rem; color: var(--blue); }
.pipeline__clock-unit { font-size: 0.75rem; letter-spacing: 0.1em; }

.pipeline__track { margin-top: 90px; position: relative; }
.pipeline__line {
  position: absolute;
  top: 27px;
  left: 0;
  right: 0;
  height: 2px;
  background: rgba(var(--ink-rgb),0.08);
}
.pipeline__line-fill {
  height: 100%;
  width: 0%;
  background: var(--blue);
}
.pipeline__traveler {
  position: absolute;
  top: 27px;
  left: 0;
  width: 34px;
  height: 34px;
  margin-top: -16px;
  border-radius: 50%;
  background: var(--blue);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 10px 26px -6px rgba(47,111,255,0.55), 0 0 0 6px rgba(47,111,255,0.10);
  will-change: transform;
  z-index: 2;
}
.pipeline__traveler svg { width: 16px; height: 16px; }
.pipeline__stages {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--space-12);
  position: relative;
}
.stage { display: flex; flex-direction: column; align-items: flex-start; opacity: 0.32; transition: opacity 0.5s var(--ease); }
.stage.is-active { opacity: 1; }
.stage__dot {
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--paper);
  border: 2px solid rgba(var(--ink-rgb),0.16);
  margin-bottom: var(--space-13);
  transition: background 0.4s var(--ease), border-color 0.4s var(--ease), transform 0.5s var(--ease-spring);
}
.stage.is-active .stage__dot { background: var(--blue); border-color: var(--blue); transform: scale(1.15); }
.stage__icon {
  width: 44px; height: 44px;
  border-radius: var(--r-sm);
  background: var(--paper-2);
  box-shadow: var(--shadow-soft);
  display: flex; align-items: center; justify-content: center;
  color: var(--text-dark-lo);
  margin-bottom: var(--space-9);
  transition: color 0.4s var(--ease), background 0.4s var(--ease), transform 0.5s var(--ease-spring), box-shadow 0.4s var(--ease);
}
.stage.is-active .stage__icon { color: var(--blue); background: var(--blue-soft); transform: translateY(-3px) scale(1.05); box-shadow: 0 16px 30px -12px rgba(47,111,255,0.35); }
.stage__icon svg { width: 20px; height: 20px; }
.stage__title { font-family: var(--font-display); font-weight: 600; font-size: 0.98rem; margin-bottom: var(--space-4); }
.stage__desc { font-size: var(--fs-8); color: var(--text-dark-lo); }

@media (max-width: 900px) {
  .pipeline { height: auto; }
  .pipeline__pin { position: relative; height: auto; padding: 90px var(--space-12); }
  /* relative, not static: identical in flow, but it still has to be a
     containing block for its own lens ring.
     inset:auto is not optional here — the desktop rule's top:100px/right:32px
     are inherited into this breakpoint, and static ignored them where
     relative applies them as a shift. Without this the clock lands 100px low
     and 32px left of where it belongs. */
  .pipeline__clock {
    position: relative;
    inset: auto;
    margin: 20px 0 0;
    width: fit-content;
  }
  .pipeline__stages { grid-template-columns: 1fr; gap: 36px; }
  .pipeline__line, .pipeline__traveler { display: none; }
  .stage { opacity: 1; }
  .stage.is-active .stage__dot, .stage .stage__dot { background: var(--blue); border-color: var(--blue); }
  .stage__icon { color: var(--blue); background: var(--blue-soft); }
}

/* ===================================================================
   SHOWCASE / FEATURES (pinned cycling cards)
=================================================================== */
.showcase {
  position: relative;
  background: var(--paper-2);
  color: var(--text-dark);
}
.showcase__pin {
  height: 100vh;
  overflow: hidden;
  will-change: transform;
}
.showcase__bg-text {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(3rem, 12vw, 9rem);
  color: rgba(var(--ink-rgb),0.035);
  text-transform: uppercase;
  white-space: nowrap;
  pointer-events: none;
}
.showcase__grid {
  position: relative;
  z-index: 1;
  height: 100%;
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 32px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  gap: 60px;
}
.showcase__eyebrow {
  display: inline-flex;
  font-family: var(--font-display); font-weight: 600; font-size: var(--fs-2); letter-spacing: 0.16em; color: var(--blue);
  padding: 7px var(--space-8); border-radius: var(--r-pill); border: 1px solid rgba(47,111,255,0.28); background: rgba(47,111,255,0.09);
  margin-bottom: var(--space-10);
}
.showcase__lede { font-size: clamp(1.3rem, 2.4vw, 1.8rem); font-weight: 500; max-width: 420px; line-height: 1.3; }
.showcase__dots { display: flex; gap: var(--space-4); margin-top: var(--space-16); }
.showcase__dots span {
  width: 8px; height: 8px; border-radius: 50%;
  background: rgba(var(--ink-rgb),0.14);
  transition: background 0.4s var(--ease), transform 0.4s var(--ease-spring);
}
.showcase__dots span.is-active { background: var(--blue-bright); transform: scale(1.3); }

.showcase__card {
  padding: var(--space-16) var(--space-16) 44px;
  background: var(--paper-2);
  border: 1px solid rgba(var(--ink-rgb),0.08);
  border-radius: 28px;
  box-shadow: var(--shadow-soft);
}
.showcase__card-icon {
  width: 54px; height: 54px;
  border-radius: 16px;
  background: var(--blue-soft);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.12);
  color: var(--blue-bright);
  display: flex; align-items: center; justify-content: center;
  margin-bottom: var(--space-13);
}
.showcase__card-icon svg { width: 26px; height: 26px; }
.showcase__card-title { font-family: var(--font-display); font-weight: 700; font-size: clamp(1.6rem, 2.6vw, 2.1rem); margin-bottom: var(--space-7); }
.showcase__card-desc { color: var(--text-dark-lo); font-size: var(--fs-14); max-width: 420px; }

@media (max-width: 900px) {
  /* Unpinned, like the pipeline and the pillars. A pinned section costs the
     reader two and a half screens of scrolling to pass, and on a phone there
     is no cursor to make the cycling feel like a reward for it. Every feature
     is simply shown at once instead — js/main.js renders them all rather than
     one, since without the scrub nothing would advance the card. */
  .showcase__pin { height: auto; overflow: visible; padding: 90px 0; }
  .showcase__grid { grid-template-columns: 1fr; height: auto; gap: var(--space-15); }
  .showcase__bg-text { display: none; }
  /* The dots track a card that no longer changes. */
  .showcase__dots { display: none; }
  .showcase__card { margin-top: 0; padding: var(--space-14); }
  /* The container carries .showcase__card too, so it has to give up its own
     panel styling once it is holding a stack of them. */
  .showcase__card.showcase__cards {
    display: flex; flex-direction: column; gap: var(--space-8);
    padding: 0; background: none; border: none; box-shadow: none;
  }
  .showcase__card-title { font-size: 1.25rem; margin-bottom: var(--space-4); }
  .showcase__card-desc { font-size: var(--fs-13); max-width: none; }
  .showcase__card-icon { width: 44px; height: 44px; }
  .showcase__card-icon svg { width: 22px; height: 22px; }
}

/* ===================================================================
   ALWAYS ON (visual break)
=================================================================== */
.alwayson {
  position: relative;
  background: var(--paper);
  color: var(--text-dark);
  padding: 160px 0;
  overflow: hidden;
}
.alwayson__bg { position: absolute; inset: 0; }
.alwayson__content {
  position: relative;
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 32px;
  display: grid;
  grid-template-columns: 0.8fr 1.2fr;
  gap: 80px;
  align-items: center;
}
.alwayson__phone {
  position: relative;
  width: 280px;
  min-height: 480px;
  /* Solid dark device on the section’s light background — the old
     rgba(13,17,25,0.6) + blur(20px) was frosted glass tuned for sitting
     over a dark section backdrop; on the light background it let the
     page show through and read as a flat gray blob instead of a phone. */
  background: linear-gradient(160deg, #1A1F29, #10131A);
  border: 1px solid var(--line);
  border-radius: 38px;
  padding: 44px var(--space-9) var(--space-12);
  box-shadow: var(--shadow-glass), 0 40px 90px rgba(0,0,0,0.35);
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}
.alwayson__phone-notch {
  position: absolute; top: 16px; left: 50%; transform: translateX(-50%);
  width: 90px; height: 18px; border-radius: var(--r-xs); background: #060709;
}
.alwayson__bubble {
  max-width: 82%;
  padding: 11px var(--space-7);
  border-radius: 16px;
  font-size: var(--fs-7);
  line-height: 1.4;
  opacity: 0;
  transform: translateY(10px);
}
.alwayson__bubble--in { align-self: flex-start; background: #1B212D; color: var(--text-hi); border-bottom-left-radius: 4px; }
.alwayson__bubble--out { align-self: flex-end; background: var(--blue-cta); color: #fff; border-bottom-right-radius: 4px; box-shadow: 0 10px 24px -8px rgba(47,111,255,0.5); }
.alwayson__typing { display: flex; gap: var(--space-2); align-self: flex-start; padding: var(--space-4) var(--space-6); opacity: 0; }
.alwayson__typing span { width: 6px; height: 6px; border-radius: 50%; background: var(--text-lo); animation: typing-dot 1.2s infinite; }
.alwayson__typing span:nth-child(2) { animation-delay: 0.2s; }
.alwayson__typing span:nth-child(3) { animation-delay: 0.4s; }
@keyframes typing-dot { 0%, 60%, 100% { opacity: 0.3; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-3px); } }

/* Qualified to outrank `.alwayson__text p`, which previously won on both
   specificity and source order and stripped this pill of its accent colour
   and its 0.68rem size. */
.alwayson__text p.alwayson__eyebrow {
  display: inline-flex;
  font-family: var(--font-display); font-weight: 600; font-size: var(--fs-2); letter-spacing: 0.16em; color: var(--amber-deep);
  padding: 7px var(--space-8); border-radius: var(--r-pill); border: 1px solid rgba(255,209,102,0.3); background: rgba(255,209,102,0.09);
  margin-bottom: var(--space-10);
}
.alwayson__text h2 { font-family: var(--font-display); font-weight: 700; font-size: clamp(1.8rem, 3.4vw, 2.6rem); line-height: 1.15; margin-bottom: var(--space-10); max-width: 560px; color: var(--text-dark); }
.alwayson__text p { color: var(--text-dark-lo); font-size: var(--fs-14); max-width: 480px; }

@media (max-width: 860px) {
  .alwayson__content { grid-template-columns: 1fr; }
  .alwayson__phone { margin: 0 auto; }
}

/* ===================================================================
   PILLARS (zoom-out reveal)
=================================================================== */
.pillars {
  position: relative;
  background: var(--paper);
}
.pillars::before { display: none; }
.pillars__pin {
  height: 100vh;
  will-change: transform;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  max-width: 1100px;
  margin: 0 auto;
  padding: 0 32px;
}
.pillars__center {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%) scale(1);
  text-align: center;
}
.orb { width: 120px; height: 120px; display: flex; align-items: center; justify-content: center; position: relative; }
/* The orb is the Japhone logo mark rendered as a solid sphere: the same 135deg
   blue gradient as assets/logo-mark.png (sampled off the file itself —
   #729EFF -> #3D79FF -> #1A40A8), minus the white JP glyph. Filled all the way
   through: no transparent centre, no cut-out ring. The motion lives in the
   breathing scale, the outer glow, and a sheen that drifts across the surface
   like a light source moving over a ball. */
.orb__core {
  width: 92px; height: 92px;
  flex-shrink: 0;
  border-radius: 50%;
  background: linear-gradient(135deg, #729EFF 0%, #3D79FF 52%, #1A40A8 100%);
  border: 1px solid rgba(140,180,255,0.28);
  box-shadow: 0 0 46px rgba(47,111,255,0.32), inset 0 0 26px rgba(4,11,32,0.45);
  position: relative;
  overflow: hidden;
  animation: orb-breathe 4.2s ease-in-out infinite;
}
/* Drifting specular sheen. Blue-tinted rather than white, so the mark still
   reads as the logo ball and not a glossy button. */
.orb__core::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  pointer-events: none;
  background: radial-gradient(circle at 33% 27%, rgba(104,148,226,0.5), rgba(104,148,226,0.14) 40%, transparent 64%);
  animation: orb-sheen 7s ease-in-out infinite;
}
/* Shading at the lower right — what turns the logo's flat diagonal gradient
   into a sphere rather than a disc. */
.orb__core::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: radial-gradient(circle at 72% 78%, rgba(2,7,22,0.42), transparent 62%);
  pointer-events: none;
}
@keyframes orb-breathe {
  0%, 100% { transform: scale(1); box-shadow: 0 0 46px rgba(47,111,255,0.32), inset 0 0 26px rgba(4,11,32,0.45); }
  50% { transform: scale(1.035); box-shadow: 0 0 64px rgba(47,111,255,0.44), inset 0 0 32px rgba(4,11,32,0.5); }
}
@keyframes orb-sheen {
  0%, 100% { transform: translate(0, 0) scale(1); opacity: 0.85; }
  50%      { transform: translate(5%, 4%) scale(1.07); opacity: 1; }
}
.pillars__center-label { font-family: var(--font-display); font-weight: 700; letter-spacing: 0.1em; margin-top: var(--space-5); color: var(--text-dark-lo); font-size: var(--fs-8); }

.pillar {
  align-self: center;
  opacity: 0;
  max-width: 300px;
  padding: var(--space-12);
  border-radius: 22px;
  background: var(--paper-2);
  box-shadow: var(--shadow-soft);
}
.pillar--tl { justify-self: start; align-self: start; margin-top: var(--space-16); }
.pillar--tr { justify-self: end; align-self: start; margin-top: var(--space-16); text-align: right; }
.pillar--bl { justify-self: start; align-self: end; margin-bottom: var(--space-16); }
.pillar--br { justify-self: end; align-self: end; margin-bottom: var(--space-16); text-align: right; }
.pillar__title { font-family: var(--font-display); font-weight: 700; font-size: 1.15rem; margin-bottom: var(--space-5); }
.pillar__desc { color: var(--text-dark-lo); font-size: var(--fs-12); }

@media (max-width: 900px) {
  .pillars { height: auto; }
  .pillars__pin { position: relative; height: auto; display: flex; flex-direction: column; gap: var(--space-10); padding: 100px var(--space-12); }
  .pillars__center { position: static; transform: none; margin-bottom: var(--space-6); }
  /* .orb is a fixed-width flex box, so in the stacked column it hugs the left
     edge even though its label is centred. Centre the orb itself. */
  .pillars__center .orb { margin-left: auto; margin-right: auto; }
  .pillar {
    /* No opacity override here (there used to be one, forcing opacity: 1
       !important) — js/main.js's initPillars now gives each one its own
       scroll-triggered reveal on mobile, same as the pipeline and showcase
       sections. !important would have out-ranked that reveal's inline
       opacity, leaving every pillar stuck fully visible with no animation. */
    max-width: 100%;
    text-align: left !important;
    margin: 0 !important;
    /* --bl and --br carry align-self: end from the desktop grid, which in a
       column flex container means "right edge" rather than "bottom". */
    align-self: stretch !important;
  }
}

/* ===================================================================
   TESTIMONIALS
=================================================================== */
.testimonials { background: var(--paper-3); padding: 170px var(--space-15); }
.testimonials__head { max-width: 700px; margin: 0 auto 70px; text-align: center; display: flex; flex-direction: column; align-items: center; }
.testimonials__head h2 { font-family: var(--font-display); font-weight: 700; font-size: clamp(1.6rem, 3vw, 2.3rem); line-height: 1.15; letter-spacing: -0.02em; }
.testimonials__list { max-width: var(--container); margin: 0 auto; display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-15); }
.testimonial { padding: 34px; border-radius: var(--r-lg); background: var(--paper-2); box-shadow: var(--shadow-soft); transition: transform 0.5s var(--ease), box-shadow 0.5s var(--ease); }
.testimonial:hover { transform: translateY(-4px); box-shadow: 0 40px 80px -30px rgba(var(--ink-rgb),0.22), 0 10px 24px -14px rgba(var(--ink-rgb),0.12); }
.testimonial__avatar { width: 44px; height: 44px; margin-bottom: var(--space-10); }
.testimonial__quote { font-size: 1rem; line-height: 1.55; margin-bottom: var(--space-10); }
.testimonial__attr { font-family: var(--font-display); font-weight: 600; font-size: var(--fs-8); color: var(--text-dark-lo); }
.testimonial__stars { display: flex; gap: 3px; margin-bottom: var(--space-8); }
.testimonial__star { width: 16px; height: 16px; fill: #E4E6EB; stroke: #B8BCC6; stroke-width: 1px; }
.testimonial__star.is-filled { fill: #FFB020; stroke: #FFB020; }

.testimonials__cta { display: flex; justify-content: center; margin-top: 56px; }

/* The verified mark is a factual claim — the review was left from a signed-in
   Japhone account — so it is styled to be read, not to decorate. Green reads
   as "checked" without competing with the amber stars above it. */
.testimonial__meta { display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap; margin-top: var(--space-6); }
.testimonial__verified { display: inline-flex; align-items: center; gap: var(--space-2); font-family: var(--font-display); font-weight: 600; font-size: var(--fs-2); letter-spacing: 0.01em; color: #0F7B4F; background: rgba(16, 150, 95, 0.10); border-radius: var(--r-pill); padding: 3px 9px 3px 7px; }
.testimonial__verified svg { width: 12px; height: 12px; flex: none; }
/* Inline inside a sentence in the trust strip, where a pill background would
   break the line rhythm. */
.testimonial__verified--inline { background: none; padding: 0; color: #0F7B4F; }
.testimonial__date { font-size: var(--fs-2); color: var(--text-dark-lo); }

/* States plainly how reviews get here. It sits under the list rather than
   above it so it reads as a footnote to the evidence, not a preamble. */
.testimonials__trust { max-width: 640px; margin: var(--space-12) auto 0; text-align: center; font-size: var(--fs-5); line-height: 1.6; color: var(--text-dark-lo); }

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

/* Opting out of being named. Sits on one line rather than using the stacked
   label rows the rest of the form uses, and the hint sits under the label so
   the trade-off is visible at the moment of the decision rather than only in
   the consent paragraph below the button. */
.review-anon { display: flex; align-items: flex-start; gap: var(--space-5); margin: var(--space-8) 0 var(--space-4); }
.review-anon input { margin: 3px 0 0; width: 16px; height: 16px; flex: none; accent-color: var(--blue); cursor: pointer; }
.review-anon label { display: block; font-size: var(--fs-8); font-weight: 600; cursor: pointer; }
.review-anon__hint { display: block; font-weight: 400; font-size: var(--fs-5); color: var(--text-dark-lo); margin-top: 2px; }

/* ===================================================================
   LEAVE A REVIEW — modal
=================================================================== */
/* .review-modal sets display:flex unconditionally below, which — as an
   author-stylesheet rule — otherwise beats the UA stylesheet's [hidden]
   { display:none } regardless of specificity. Restore it explicitly. */
[hidden] { display: none !important; }
.review-modal { position: fixed; inset: 0; z-index: 500; display: flex; align-items: center; justify-content: center; padding: var(--space-12); }
.review-modal__backdrop {
  position: absolute; inset: 0;
  background: rgba(5,6,9,0.6);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  animation: review-fade-in 0.35s var(--ease);
}
.review-modal__panel {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 480px;
  max-height: calc(100vh - 48px);
  overflow-y: auto;
  background: var(--paper-2);
  border-radius: 28px;
  box-shadow: var(--shadow-glass), 0 60px 120px -30px rgba(0,0,0,0.5);
  padding: 44px var(--space-16) var(--space-16);
  color: var(--text-dark);
  animation: review-panel-in 0.4s var(--ease);
}
@keyframes review-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes review-panel-in {
  from { opacity: 0; transform: translateY(18px) scale(0.97); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
.review-modal__close {
  position: absolute; top: 20px; right: 20px;
  width: 36px; height: 36px; border-radius: 50%;
  border: none; background: rgba(var(--ink-rgb),0.05);
  color: var(--text-dark-lo);
  font-size: 1.3rem; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.25s var(--ease), color 0.25s var(--ease), transform 0.25s var(--ease);
}
.review-modal__close:hover { background: rgba(var(--ink-rgb),0.1); color: var(--text-dark); transform: rotate(90deg); }
.review-modal__title { font-family: var(--font-display); font-weight: 700; font-size: 1.5rem; margin: 10px 0 10px; line-height: 1.2; }
.review-modal__sub { font-size: var(--fs-12); color: var(--text-dark-lo); line-height: 1.55; margin-bottom: var(--space-13); }
.review-modal__account-note {
  font-size: var(--fs-7); color: var(--text-dark-lo);
  background: var(--blue-soft); border-radius: var(--r-xs);
  padding: var(--space-5) var(--space-7); margin: -6px 0 18px;
}
.review-modal__account-note strong { color: var(--blue); }
.review-modal__note { font-size: var(--fs-8); color: var(--amber-deep); min-height: 18px; margin-top: var(--space-1); }
/* .contact__form's input styling (light text on a near-transparent dark-ish
   background) assumes the dark contact section it was built for. This modal
   has a white panel, so that combination was unreadable — same class of bug
   as the star fill. Scoped override, not a global change, since the same
   .contact__form class is still correctly used on dark surfaces elsewhere
   (the sign-in form, account.html's setup form). */
.review-modal__panel .contact__form input,
.review-modal__panel .contact__form textarea {
  color: var(--text-dark);
  background: rgba(var(--ink-rgb),0.035);
  border-color: rgba(var(--ink-rgb),0.14);
}
.review-modal__panel .contact__form input:focus,
.review-modal__panel .contact__form textarea:focus {
  border-color: var(--blue);
  background: rgba(47,111,255,0.05);
}
.review-modal__panel .contact__form label { color: var(--text-dark-lo); }

.review-stars {
  display: flex; gap: var(--space-4); margin-bottom: var(--space-11);
}
.review-star {
  position: relative;
  width: 34px; height: 34px; padding: 0; border: none; background: none; cursor: pointer;
  transition: transform 0.2s var(--ease-spring);
}
/* The stars stay 34px so a five-star row still reads as one control, but the
   tappable area is padded out to the 44px minimum. Horizontally the row's own
   8px gap absorbs most of it; vertically there is nothing to collide with. */
.review-star::before {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 42px; height: 44px; transform: translate(-50%, -50%);
}
.review-star:hover { transform: scale(1.15); }
/* var(--line) (near-transparent white) was the bug here — that token is
   meant for borders on DARK backgrounds, but this modal has a white panel,
   so unselected stars were nearly invisible. Visible light-gray fill +
   a real stroke so the star shape always reads, selected or not. */
.review-star svg {
  width: 100%; height: 100%;
  fill: #E4E6EB; stroke: #B8BCC6; stroke-width: 1.2px;
  transition: fill 0.2s var(--ease), stroke 0.2s var(--ease);
}
.review-star.is-filled svg { fill: #FFB020; stroke: #FFB020; }

.review-modal__success-view { text-align: center; padding: 20px 0 10px; }
.review-modal__success-icon {
  width: 64px; height: 64px; margin: 0 auto 22px;
  border-radius: 50%; background: var(--blue-soft); color: var(--blue);
  display: flex; align-items: center; justify-content: center;
  animation: review-panel-in 0.5s var(--ease-spring);
}
.review-modal__success-icon svg { width: 28px; height: 28px; }
.review-modal__success-view .review-modal__title { margin-top: 0; }
.review-modal__success-view .review-modal__sub { margin-bottom: var(--space-14); }

@media (max-width: 560px) {
  .review-modal__panel { padding: 36px var(--space-12) var(--space-15); border-radius: 22px; }
}

/* ===================================================================
   INTEGRATIONS MARQUEE
=================================================================== */
.integrations { background: var(--paper); padding: 110px var(--space-15) 140px; text-align: center; }
.integrations__lede { font-size: 1.05rem; color: var(--text-dark-lo); max-width: 460px; margin: 0 auto 50px; }
.integrations__marquee { overflow: hidden; border-top: 1px solid rgba(var(--ink-rgb),0.08); border-bottom: 1px solid rgba(var(--ink-rgb),0.08); padding: 28px 0; }
.integrations__track {
  display: inline-flex;
  gap: var(--space-10);
  white-space: nowrap;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.1rem;
  color: var(--text-dark-lo);
  animation: ticker-scroll 26s linear infinite;
}
.integrations__track span:nth-child(odd):not(:first-child) { color: var(--blue); }

/* ===================================================================
   FAQ
=================================================================== */
.faq { background: var(--paper-2); padding: 170px var(--space-15); }
.faq__head { max-width: var(--container); margin: 0 auto 50px; display: flex; justify-content: space-between; align-items: flex-end; gap: var(--space-12); flex-wrap: wrap; }
.faq__head h2 { font-family: var(--font-display); font-weight: 700; font-size: clamp(2.2rem, 4vw, 3.2rem); line-height: 1.08; letter-spacing: -0.02em; }
.faq__head p { color: var(--text-dark-lo); max-width: 280px; }
.faq__list { max-width: var(--container); margin: 0 auto; border-top: 1px solid rgba(var(--ink-rgb),0.10); }
.faq__item { border-bottom: 1px solid rgba(var(--ink-rgb),0.10); transition: background 0.3s var(--ease); border-radius: var(--r-md); }
.faq__item:hover { background: rgba(var(--ink-rgb),0.02); }
.faq__q {
  width: 100%;
  display: flex;
  align-items: center;
  gap: var(--space-12);
  padding: var(--space-13) var(--space-6);
  text-align: left;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.05rem;
}
.faq__num { color: var(--text-dark-lo); font-size: var(--fs-8); width: 24px; flex-shrink: 0; }
.faq__q span:nth-child(2) { flex: 1; }
.faq__toggle {
  font-size: 1.1rem; color: var(--blue); flex-shrink: 0;
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--blue-soft);
  display: flex; align-items: center; justify-content: center;
  transition: transform 0.5s var(--ease-spring), background 0.3s var(--ease);
}
.faq__item.is-open .faq__toggle { transform: rotate(45deg); background: var(--blue); color: #fff; }
.faq__a { max-height: 0; overflow: hidden; transition: max-height 0.5s var(--ease); }
.faq__a p { padding: 0 12px 26px 60px; color: var(--text-dark-lo); max-width: 640px; }

/* ===================================================================
   CONTACT
=================================================================== */
.pricing-section, .contact { background: var(--paper-2); color: var(--text-dark); padding: 170px var(--space-15) 110px; position: relative; overflow: hidden; }
.contact__inner { position: relative; max-width: var(--container); margin: 0 auto; display: grid; grid-template-columns: 1fr 1fr; gap: 80px; align-items: center; }
.contact__intro h2 { font-family: var(--font-display); font-weight: 700; font-size: clamp(2.2rem, 4.6vw, 3.4rem); margin-bottom: var(--space-10); }
.contact__sub { color: var(--text-dark-lo); font-size: var(--fs-14); max-width: 440px; margin-bottom: var(--space-15); }
.contact__points { display: flex; flex-direction: column; gap: var(--space-6); }
.contact__points li { display: flex; align-items: center; gap: var(--space-5); color: var(--text-dark-lo); font-size: var(--fs-12); }
.contact__points li::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--blue); flex-shrink: 0; }

.contact__form {
  display: flex; flex-direction: column; gap: var(--space-10);
  background: var(--paper-2);
  border: 1px solid rgba(var(--ink-rgb),0.08);
  border-radius: 28px;
  padding: 36px;
  box-shadow: var(--shadow-soft);
}
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-10); }
.contact__form label { display: flex; flex-direction: column; gap: var(--space-4); font-size: var(--fs-7); color: var(--text-dark-lo); }
.contact__form input, .contact__form textarea, .contact__form select {
  background: rgba(var(--ink-rgb),0.03);
  border: 1px solid rgba(var(--ink-rgb),0.14);
  border-radius: 12px;
  padding: 13px var(--space-7);
  color: var(--text-dark);
  transition: border-color 0.3s var(--ease), background 0.3s var(--ease);
  resize: vertical;
}
.contact__form input:focus, .contact__form textarea:focus, .contact__form select:focus { outline: none; border-color: var(--blue); background: rgba(47,111,255,0.05); }
/* color-scheme is a hint some browsers ignore for the dropdown popup itself
   (confirmed: Chrome/Windows rendered the option list with a white
   background and near-white text — unreadable). Styling <option> directly
   with solid colors (no rgba — option backgrounds don't reliably support
   transparency) is what actually controls the popup's appearance. */
.contact__form select { color-scheme: light; cursor: pointer; }
.contact__form select option { background: var(--paper-2); color: var(--text-dark); }
/* --- Password field with a reveal toggle ----------------------------------
   The button overlays the right end of the input rather than sitting beside
   it, so the field keeps its full width and nothing shifts when it appears. */
.pw { position: relative; display: flex; }
.pw input { flex: 1; min-width: 0; padding-right: 46px; }
.pw__toggle {
  position: absolute;
  top: 50%; right: 4px;
  transform: translateY(-50%);
  width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 9px;
  color: var(--text-dark-lo);
  transition: color 0.2s var(--ease), background 0.2s var(--ease);
  -webkit-tap-highlight-color: transparent;
}
.pw__toggle:hover { color: var(--text-dark); background: rgba(var(--ink-rgb),0.05); }
.pw__toggle:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }
.pw__toggle svg { width: 19px; height: 19px; }

.contact__note { font-size: var(--fs-8); color: var(--green-deep); min-height: 18px; }
.contact__note.is-error { color: #A64A08; }
.contact__consent { font-size: var(--fs-5); color: var(--text-dark-lo); margin: -6px 0 14px; line-height: 1.4; }
.contact__tos { display: flex; align-items: flex-start; gap: var(--space-4); font-size: var(--fs-8); color: var(--text-dark-lo); margin: 0 0 14px; line-height: 1.4; cursor: pointer; }
.contact__tos input[type="checkbox"] { margin-top: 3px; flex-shrink: 0; width: 16px; height: 16px; accent-color: var(--blue); cursor: pointer; }
.contact__tos a { color: var(--blue-bright); }

.contact__authtabs { display: flex; gap: var(--space-4); margin-bottom: var(--space-9); }
.contact__authtab {
  flex: 1;
  background: rgba(var(--ink-rgb),0.03);
  border: 1px solid rgba(var(--ink-rgb),0.12);
  border-radius: var(--r-pill);
  padding: var(--space-5) var(--space-8);
  color: var(--text-dark-lo);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-7);
  cursor: pointer;
  transition: color 0.25s var(--ease), background 0.25s var(--ease), border-color 0.25s var(--ease);
}
.contact__authtab:hover { color: var(--text-dark); }
.contact__authtab.is-active { color: var(--blue); background: var(--blue-soft); border-color: rgba(47,111,255,0.35); }
.contact__google-btn { display: flex; align-items: center; justify-content: center; gap: var(--space-5); margin-bottom: var(--space-9); }
.contact__google-btn svg { flex-shrink: 0; }

.contact__account {
  font-size: var(--fs-8);
  color: var(--text-dark-lo);
  margin-bottom: var(--space-9);
}
.contact__account strong { color: var(--text-dark); font-weight: 600; }
.contact__account .link-arrow { font-size: var(--fs-8); color: var(--text-dark); }
#contact-auth-view .link-arrow { color: var(--text-dark); }

/* ---- Pricing cards ---- */
.pricing__eyebrow {
  font-family: var(--font-display);
  font-size: var(--fs-4);
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--text-dark-lo);
  margin-bottom: var(--space-9);
}
.pricing__compare {
  font-size: var(--fs-12);
  color: var(--text-dark-lo);
  max-width: 480px;
  margin: -8px 0 22px;
  line-height: 1.5;
}
.pricing__cards { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-10); }
/* Pricing: the homepage's planet-home restyle caps .contact__inner at 560px
   (right for the sign-in form, but it squeezed the two plan cards to ~250px
   each — the "tall and skinny" block). Give the pricing block more room so the
   cards breathe (~410px each). The .planet-home prefix out-specifies that cap;
   below 861px the cards already stack, so a wider cap changes nothing there. */
.planet-home .pricing-section .contact__inner { max-width: 900px; }
.pricing__card {
  display: flex;
  flex-direction: column;
  gap: var(--space-7);
  background: var(--paper-2);
  border: 1px solid rgba(var(--ink-rgb),0.08);
  border-radius: var(--r-lg);
  padding: var(--space-14) var(--space-13);
  box-shadow: var(--shadow-soft);
  position: relative;
}
.pricing__card--featured { border-color: rgba(255,209,102,0.4); background: rgba(255,209,102,0.05); }
.pricing__badge {
  position: absolute; top: -12px; left: 26px;
  background: #FFD166; color: #3D2E00;
  font-family: var(--font-display); font-weight: 700; font-size: var(--fs-2);
  letter-spacing: 0.04em; text-transform: uppercase;
  padding: 5px var(--space-6); border-radius: var(--r-pill);
}
.pricing__name { font-family: var(--font-display); font-weight: 700; font-size: 1.1rem; color: var(--text-dark); }
.pricing__price { font-family: var(--font-display); font-weight: 700; font-size: 2.2rem; color: var(--text-dark); }
.pricing__price span { font-size: var(--fs-13); font-weight: 500; color: var(--text-dark-lo); }
.pricing__price .pricing__price-strike {
  font-size: 1.2rem;
  font-weight: 500;
  color: var(--text-dark-lo);
  text-decoration: line-through;
  text-decoration-color: rgba(154,117,0,0.7);
  margin-right: var(--space-4);
}
.pricing__price-note { font-size: var(--fs-5); color: var(--text-dark-lo); margin-top: -10px; }
.pricing__cap { font-size: var(--fs-8); color: var(--blue-ink); font-weight: 600; margin-top: -10px; }
.pricing__roi {
  font-size: var(--fs-6);
  color: var(--green-deep);
  margin-top: -6px;
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
.pricing__roi::before { content: '✓'; font-weight: 700; }
.pricing__features { display: flex; flex-direction: column; gap: 9px; margin-bottom: var(--space-2); }
.pricing__features li { display: flex; align-items: flex-start; gap: 9px; color: var(--text-dark-lo); font-size: var(--fs-8); line-height: 1.4; }
.pricing__features li::before { content: '✓'; color: var(--green-deep); font-weight: 700; flex-shrink: 0; }

/* ---- Auth gate extras ---- */
#back-to-pricing { display: block; margin-top: var(--space-8); font-size: var(--fs-8); }
.contact__redirect { color: var(--text-dark-lo); font-size: var(--fs-13); padding: 40px 0; text-align: center; }

/* ---- Setup view ---- */
.contact__plan-badge {
  display: inline-block;
  background: var(--blue-soft); color: var(--blue-bright);
  font-family: var(--font-display); font-weight: 600; font-size: var(--fs-4);
  letter-spacing: 0.04em; text-transform: uppercase;
  padding: 3px var(--space-5); border-radius: var(--r-pill);
  margin-right: var(--space-4);
}
// All of .setup__label / .setup__number* / .setup__gate* below still used
// the pre-redesign dark-dashboard tokens (light text, near-white tints)
// and were missed when account.html moved to a light theme — same bug
// class as the alwayson phone mockup and admin login title.
.setup__label {
  font-family: var(--font-display); font-weight: 600; font-size: var(--fs-8);
  color: var(--text-dark); margin-bottom: var(--space-6);
}
.setup__number {
  background: var(--blue-soft);
  border: 1px solid rgba(47,111,255,0.35);
  border-radius: 16px;
  padding: var(--space-9) var(--space-10);
  margin-bottom: var(--space-12);
}
.setup__number-label { font-size: var(--fs-5); color: var(--text-dark-lo); margin-bottom: var(--space-2); }
.setup__number-value { font-family: var(--font-display); font-weight: 700; font-size: 1.5rem; color: var(--text-dark); margin-bottom: var(--space-4); }
.setup__number-instructions { font-size: var(--fs-8); color: var(--text-dark-lo); line-height: 1.5; }
.setup__number-instructions code { background: rgba(var(--ink-rgb),0.06); padding: var(--space-1) var(--space-3); border-radius: 4px; color: var(--blue); }
.setup__number--pending { background: rgba(var(--ink-rgb),0.03); border-color: rgba(var(--ink-rgb),0.08); color: var(--text-dark-lo); font-size: var(--fs-8); }
.setup__number--failed { background: rgba(255,107,107,0.08); border-color: rgba(255,107,107,0.35); font-size: var(--fs-8); }
.setup__number--failed p { margin-bottom: var(--space-2); color: var(--text-dark-lo); }
.setup__number--failed #setup-number-error { color: #d1373f; font-weight: 600; }

.setup__gate {
  background: rgba(var(--ink-rgb),0.03);
  border: 1px solid rgba(var(--ink-rgb),0.08);
  border-radius: 20px;
  padding: var(--space-14) var(--space-13);
  margin-bottom: var(--space-14);
}
.setup__gate .setup__label { font-size: var(--fs-14); margin-bottom: var(--space-4); }
.setup__gate-sub { font-size: var(--fs-10); color: var(--text-dark-lo); line-height: 1.5; margin-bottom: var(--space-11); max-width: 46ch; }
.setup__gate-choices { display: flex; gap: var(--space-7); flex-wrap: wrap; }
.setup__gate-url { margin-top: var(--space-11); padding-top: var(--space-11); border-top: 1px solid rgba(var(--ink-rgb),0.08); }
.setup__gate-url label { display: flex; flex-direction: column; gap: var(--space-4); font-size: var(--fs-7); color: var(--text-dark-lo); margin-bottom: var(--space-8); }
.setup__gate-url input {
  background: var(--paper-2);
  border: 1px solid rgba(var(--ink-rgb),0.14);
  border-radius: var(--r-xs);
  padding: var(--space-6) var(--space-7);
  color: var(--text-dark);
  font-family: var(--font-body);
  font-size: var(--fs-11);
  transition: border-color 0.25s var(--ease), background 0.25s var(--ease);
}
.setup__gate-url input::placeholder { color: var(--text-dark-lo); opacity: 0.6; }
.setup__gate-url input:focus { outline: none; border-color: var(--blue); background: rgba(47,111,255,0.05); box-shadow: var(--focus-ring); }
.setup__gate-note { font-size: var(--fs-8); color: var(--amber-deep); min-height: 18px; margin-top: var(--space-5); }
.setup__gate-note.is-success { color: var(--green-deep); }

.setup__prefill-note {
  font-size: var(--fs-8); color: var(--green-deep);
  background: rgba(52,211,153,0.1); border: 1px solid rgba(52,211,153,0.3);
  border-radius: var(--r-xs); padding: var(--space-5) var(--space-7); margin-bottom: var(--space-12);
}

/* Required "connect your calendar" step. Deliberately a full-width child of
   .contact__form's flex column rather than a .form-row cell: the two connect
   buttons are wider than a 1fr grid column, and grid's default
   min-width: auto would let that intrinsic width push the column past its
   share and blow the two-column row out. */
.setup__number-warning {
  font-size: var(--fs-8); color: var(--amber-deep); background: rgba(255,209,102,0.1);
  border: 1px solid rgba(255,209,102,0.32); border-radius: var(--r-xs); padding: var(--space-5) var(--space-6); margin-top: var(--space-5);
}
.setup__number-warning code { background: rgba(var(--ink-rgb),0.08); padding: 1px 5px; border-radius: 4px; }
.setup__verify { margin-top: var(--space-8); padding-top: var(--space-8); border-top: 1px solid rgba(var(--ink-rgb),0.1); }
.setup__verify-title { font-family: var(--font-display); font-weight: 600; font-size: var(--fs-12); color: var(--text-dark); margin-bottom: var(--space-2); }
.setup__verify-sub { font-size: var(--fs-8); color: var(--text-dark-lo); margin-bottom: var(--space-6); }
.setup__verify .btn { color: var(--text-dark); }
.setup__verify-status { font-size: var(--fs-8); margin-top: var(--space-5); min-height: 1.1em; color: var(--text-dark-lo); }
.setup__transfer {
  background: var(--paper-2); border: 1px solid rgba(var(--ink-rgb),0.08);
  border-radius: 16px; padding: var(--space-10) var(--space-11); margin-bottom: var(--space-9);
}
.setup__transfer-sub { font-size: var(--fs-8); color: var(--text-dark-lo); margin: 8px 0 14px; }
.setup__transfer-field { display: block; margin-bottom: var(--space-6); }
.setup__transfer-field span { display: block; font-size: var(--fs-8); font-weight: 600; color: var(--text-dark); margin-bottom: var(--space-3); }
.setup__transfer-field input {
  width: 100%; padding: 11px var(--space-7); border-radius: var(--r-xs);
  border: 1px solid rgba(var(--ink-rgb),0.14); background: var(--paper-2); color: var(--text-dark); font-size: var(--fs-13);
}
.setup__transfer-warning {
  font-size: var(--fs-7); color: var(--amber-deep); background: rgba(255,209,102,0.1);
  border: 1px solid rgba(255,209,102,0.32); border-radius: var(--r-xs); padding: var(--space-5) var(--space-6); margin-bottom: var(--space-7);
}
.setup__transfer-status { font-size: var(--fs-8); margin-top: var(--space-5); min-height: 1.1em; color: var(--text-dark-lo); }

.setup__calendar {
  display: flex; flex-direction: column; gap: var(--space-6);
  background: rgba(var(--ink-rgb),0.03);
  border: 1px solid rgba(var(--ink-rgb),0.08);
  border-radius: var(--r-sm);
  padding: var(--space-8) var(--space-9);
}
.setup__calendar > span { font-size: var(--fs-7); color: var(--text-dark-lo); }
.setup__calendar > span em { font-style: normal; opacity: 0.75; }
.setup__calendar-buttons { display: flex; gap: var(--space-6); flex-wrap: wrap; }
/* .btn--outline is `color: inherit`; pin it to a dark tone so the buttons
   read as actions on this light card rather than picking up a dim inherited
   label colour. Padding is left alone deliberately — .btn--outline's
   padding-right: 54px reserves space for its ::after arrow badge. */
.setup__calendar-buttons .btn { color: var(--text-dark); }
.setup__calendar-connected {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-5);
  font-size: var(--fs-8); color: var(--text-dark-lo);
}
.setup__calendar-connected strong { color: var(--text-dark); font-weight: 600; }
.setup__calendar-badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 2px 10px; border-radius: var(--r-pill);
  background: rgba(46,160,90,0.14); color: #1f8a4c;
  font-size: var(--fs-4); font-weight: 700; letter-spacing: 0.02em;
}
.setup__calendar-badge::before {
  content: ''; width: 7px; height: 7px; border-radius: 50%;
  background: #2ea05a; box-shadow: 0 0 0 3px rgba(46,160,90,0.2);
}
#setup-calendar-connected .link-arrow { font-size: var(--fs-8); color: var(--text-dark); }

/* Cal.com's inline connect form — the other three providers are plain OAuth
   links, but Cal.com is a bare API key + event type ID pasted in directly,
   so it needs actual inputs rather than a redirect. */
.setup__calendar-calcom { display: flex; flex-direction: column; gap: var(--space-5); max-width: 360px; }
.setup__calendar-calcom input { color: var(--text-dark); }
.setup__calcom-status { font-size: var(--fs-7); min-height: 1.1em; }

/* Live calendar preview — reads as a nested card within .setup__calendar's
   own card, one step visually "inside" the connection state it reports on.
   A real month grid: dates the events actually fall on, not a flat list. */
.cal-preview { margin-top: var(--space-2); }
.cal-preview__head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--space-5); margin-bottom: var(--space-5); }
.cal-preview__nav { display: flex; align-items: center; gap: var(--space-4); }
.cal-preview__nav-btn {
  width: 26px; height: 26px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(var(--ink-rgb),0.12); background: var(--paper-2);
  color: var(--text-dark); font-size: var(--fs-8); line-height: 1;
}
.cal-preview__nav-btn:hover { border-color: rgba(47,111,255,0.4); color: var(--blue); }
.cal-preview__month { font-family: var(--font-display); font-weight: 600; font-size: var(--fs-8); color: var(--text-dark); min-width: 118px; text-align: center; }
.cal-preview__today {
  font-family: var(--font-display); font-weight: 600; font-size: var(--fs-4);
  padding: 5px 11px; border-radius: var(--r-pill);
  border: 1px solid rgba(var(--ink-rgb),0.12); background: var(--paper-2); color: var(--text-dark);
}
.cal-preview__today:hover { border-color: rgba(47,111,255,0.4); color: var(--blue); }

.cal-preview__weekdays {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: var(--space-2);
  font-family: var(--font-display); font-weight: 600; font-size: var(--fs-2);
  letter-spacing: 0.04em; color: var(--text-dark-lo); text-align: center;
  padding: 0 1px; margin-bottom: var(--space-2);
}
.cal-preview__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: var(--space-2); }
.cal-day {
  min-height: 66px; padding: 5px 5px var(--space-2);
  border-radius: 8px; background: var(--paper-2); border: 1px solid rgba(var(--ink-rgb),0.06);
  display: flex; flex-direction: column; gap: 3px; overflow: hidden;
}
.cal-day.is-other-month { opacity: 0.4; }
.cal-day.is-today { border-color: rgba(47,111,255,0.5); box-shadow: inset 0 0 0 1px rgba(47,111,255,0.25); }
.cal-day__num { font-family: var(--font-display); font-weight: 600; font-size: var(--fs-4); color: var(--text-dark); }
.cal-day.is-today .cal-day__num { color: var(--blue); }
.cal-day__events { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.cal-day__event {
  font-size: var(--fs-1); line-height: 1.3; color: var(--text-dark);
  background: rgba(47,111,255,0.1); border-radius: 4px; padding: 1px var(--space-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cal-day__more { font-size: 0.64rem; color: var(--text-dark-lo); padding: 0 4px; }
/* The chips are buttons now, so the grid is keyboard-reachable. Only the
   button chrome is reset here — no font shorthand, which would wipe the
   per-chip font-size above. */
.cal-day__event,
.cal-day__more { display: block; width: 100%; font-family: inherit; text-align: left; border: 0; cursor: pointer; }
.cal-day__more { background: none; }
.cal-day__event:hover { background: rgba(47,111,255,0.2); }
.cal-day__more:hover { color: var(--text-dark); }
.cal-day__event:focus-visible,
.cal-day__more:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }
.cal-day.has-events { cursor: pointer; }

.cal-preview__loading,
.cal-preview__note { font-size: var(--fs-7); color: var(--text-dark-lo); margin-top: var(--space-4); }

@media (max-width: 560px) {
  .cal-day { min-height: 48px; position: relative; }
  .cal-day__event { font-size: 0; padding: 0; height: 4px; border-radius: 2px; margin-top: 1px; }
  /* Too small to read at this width, but it is the only way to a day's third
     appointment for a keyboard or screen reader: hidden from sight, not from
     the tab order, and shown while it has focus. */
  .cal-day__more:not(:focus-visible) { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
}

@media (max-width: 560px) {
  .setup__gate { padding: var(--space-11) var(--space-9); }
  /* .btn is white-space: nowrap, and "Connect Google Calendar" is wider than a
     phone-width form column — stack them full-width, same as .setup__gate-choices. */
  .setup__calendar-buttons { flex-direction: column; }
  .setup__calendar-buttons .btn { width: 100%; }
  .setup__gate-choices { flex-direction: column; }
  .setup__gate-choices .btn { width: 100%; }
}
.voice-picker {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-5);
  margin-bottom: var(--space-12);
}
.voice-card {
  display: flex; align-items: center; gap: var(--space-5);
  background: rgba(var(--ink-rgb),0.03);
  border: 1px solid rgba(var(--ink-rgb),0.08);
  border-radius: var(--r-sm);
  padding: var(--space-5) var(--space-6);
  cursor: pointer;
  transition: border-color 0.25s var(--ease), background 0.25s var(--ease);
}
.voice-card:hover { border-color: rgba(47,111,255,0.35); }
.voice-card.is-selected { border-color: var(--blue); background: var(--blue-soft); }
.voice-card__play {
  flex-shrink: 0;
  width: 30px; height: 30px;
  border-radius: 50%;
  background: var(--paper-2);
  border: 1px solid rgba(var(--ink-rgb),0.14);
  color: var(--text-dark);
  display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-3);
}
.voice-card__play:hover { background: var(--blue); border-color: var(--blue); color: #fff; }
.voice-card__body { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.voice-card__name { font-family: var(--font-display); font-weight: 600; font-size: var(--fs-8); color: var(--text-dark); }
.voice-card__style { font-size: 0.74rem; color: var(--text-dark-lo); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.voice-card--custom { grid-column: 1 / -1; display: block; cursor: default; }
.voice-card--custom.is-locked { opacity: 0.6; cursor: not-allowed; }
.voice-card--custom .voice-card__style { white-space: normal; overflow: visible; text-overflow: clip; margin-bottom: var(--space-2); }
.voice-card__body--custom { gap: var(--space-4); }
.voice-card__body--custom input[type="file"] { font-size: var(--fs-6); color: var(--text-dark-lo); }
.voice-card__consent { display: flex; align-items: flex-start; gap: var(--space-4); font-size: var(--fs-5); color: var(--text-dark-lo); line-height: 1.4; cursor: pointer; }
.voice-card__consent input[type="checkbox"] { margin-top: var(--space-1); flex-shrink: 0; accent-color: var(--blue); cursor: pointer; }
.voice-card__note { font-size: var(--fs-6); color: var(--blue-bright); min-height: 1.1em; margin: 0; }
.voice-card--custom button { align-self: flex-start; }

@media (max-width: 860px) {
  .contact__inner { grid-template-columns: 1fr; gap: 50px; }
  .form-row { grid-template-columns: 1fr; }
  .contact__form { padding: var(--space-12); }
  .pricing__cards { grid-template-columns: 1fr; }
  .voice-picker { grid-template-columns: 1fr; }
}

/* ===================================================================
   AURORA — a slow-drifting blurred gradient backdrop with a soft "bubble"
   warp that follows the cursor. Shared by the homepage's closing section
   and setup.html's background (js/aurora.js drives both the same way).

   Two identical gradient layers stacked: .aurora__base plays the ambient
   drift on its own forever, .aurora__warp is the same gradient pushed
   through an SVG feDisplacementMap filter (see the inline <svg> markup
   each page includes once) and revealed only inside a soft circular mask
   centered on the pointer — so the distortion reads as a lens/bubble
   sitting under the cursor rather than a warp of the whole scene.
   Replaces the old WebGL starfield: same two spots, no Three.js, no
   multi-pass render pipeline.
=================================================================== */
.aurora { position: absolute; inset: 0; overflow: hidden; }
/* Film grain — the trait every "premium flowing gradient" reference shares
   and the one thing a purely smooth CSS gradient can never fake. A static
   tiled noise texture (no per-frame cost, unlike animating it would be),
   blended with overlay so it reads as texture in the gradient rather than
   a layer sitting on top of it. */
.aurora::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 140px 140px;
  opacity: 0.07;
  mix-blend-mode: overlay;
  pointer-events: none;
}
/* __base is a wrapper holding four static layers (the streak + three
   colour accents below) rather than one background — kept as separate
   children even though none of them animate anymore, since that's what
   lets each one have its own size/position/opacity tuned independently
   to match a reference image's composition, the same way it let each one
   move independently in an earlier animated version of this. */
.aurora__base {
  position: absolute;
  inset: -20%;
  overflow: hidden;
  filter: blur(40px);
}
.aurora__streak, .aurora__glow { position: absolute; inset: 0; }
/* Static now, matching a specific reference image directly rather than
   animating toward one — the composition: a deep blue diagonal band
   (this layer) between a bright white/pale-blue field (__glow--a, right
   side) and a lavender field (__glow--b, bottom-left), plus amber
   (__glow--c) added back in for the brand's own second colour, which the
   reference itself doesn't use but was an explicit ask independent of it.
   Stop percentages are in THIS box's own space (the __base wrapper is
   140% the section's size, inset -20% on every side) — the actual
   .cosmos viewport only ever shows the middle ~71% of it (14%-86%). */
.aurora__streak {
  background: linear-gradient(135deg,
    #060B18 0%, #060B18 20%,
    #0e1a4a 28%,
    #1c2f8a 36%,
    #2a4fd0 44%,
    #4f7dff 52%,
    #8fc8ff 58%,
    #060B18 72%, #060B18 100%);
}
/* Bright white/pale-blue field — the right side of the reference image. */
.aurora__glow--a {
  background: radial-gradient(ellipse 46% 60% at 86% 40%, rgba(255,255,255,0.75), rgba(215,238,255,0.35) 50%, transparent 74%);
}
/* Lavender field — the bottom-left of the reference image. */
.aurora__glow--b {
  background: radial-gradient(ellipse 44% 48% at 20% 76%, rgba(201,168,224,0.55), transparent 70%);
}
/* Amber — genuinely visible, not a token trace, per the explicit ask to
   keep the brand's second colour in even though the reference doesn't
   have it. Tucked into a corner the reference's own palette doesn't
   occupy so it reads as an added accent rather than fighting it. */
.aurora__glow--c {
  background: radial-gradient(ellipse 20% 26% at 90% 85%, rgba(255,176,90,0.3), transparent 60%);
}
/* The cursor bubble: the same gradient pulled toward the pointer by
   scaling it down around that exact point (transform-origin), then
   showing only a tight circle of the result — content that was further
   out gets compressed inward into that small window, reading as a
   black-hole/indent pull rather than a noisy turbulent warp. An earlier
   version used an SVG feDisplacementMap (noise-driven, no defined centre)
   here; this is simpler, has no cross-browser filter quirks, and is a much
   closer match to "pulled toward one point" than turbulence ever was.
   Deliberately NOT drifting like __base — it only shows in a small masked
   circle, so matching the ambient layer's exact position doesn't matter;
   what has to read is the pull, not pixel alignment with what's under it.

   inset: 0 here (not -20% like __base) is load-bearing, not cosmetic:
   --mx/--my are computed by aurora.js relative to .aurora's own box. A
   percentage used in mask-image/transform-origin resolves against THIS
   element's own box — if this box were the overscanned 140%-sized one
   __base uses, "64%" here would land at a completely different point than
   64% actually is on .aurora, and the bubble would visibly drift away from
   the real cursor position the further from centre it moved. Matching
   .aurora's own size exactly keeps the two coordinate spaces identical. */
.aurora__warp {
  position: absolute;
  inset: 0;
  /* One combined copy of __base's now-static children (streak + three
     glows) — kept as its own composite rather than importing that whole
     structure for a layer that's masked down to a 130px circle anyway. */
  background:
    radial-gradient(ellipse 46% 60% at 86% 40%, rgba(255,255,255,0.75), rgba(215,238,255,0.35) 50%, transparent 74%),
    radial-gradient(ellipse 44% 48% at 20% 76%, rgba(201,168,224,0.55), transparent 70%),
    radial-gradient(ellipse 20% 26% at 90% 85%, rgba(255,176,90,0.3), transparent 60%),
    linear-gradient(135deg,
      #060B18 0%, #060B18 20%,
      #0e1a4a 28%,
      #1c2f8a 36%,
      #2a4fd0 44%,
      #4f7dff 52%,
      #8fc8ff 58%,
      #060B18 72%, #060B18 100%),
    #060B18;
  filter: blur(16px);
  transform-origin: var(--mx, 50%) var(--my, 50%);
  transform: scale(0.76);
  -webkit-mask-image: radial-gradient(circle 130px at var(--mx, 50%) var(--my, 50%), black 55%, transparent 80%);
          mask-image: radial-gradient(circle 130px at var(--mx, 50%) var(--my, 50%), black 55%, transparent 80%);
  opacity: 0;
  transition: opacity 0.3s ease;
}
/* The event-horizon rim — brighter and tighter than the old glass-rim
   version, since "black hole" reads through a sharper edge than a soft
   glass catch-light would. inset: 0 for the same reason as __warp itself —
   this positions relative to __warp's own (now unoffset) box. */
.aurora__warp::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(circle 130px at var(--mx, 50%) var(--my, 50%), transparent 40%, rgba(255,255,255,0.3) 56%, transparent 76%);
}
.aurora.is-hovering .aurora__warp { opacity: 1; }
/* The ambient background (.aurora__streak/.aurora__glow--*) is a static
   match of a specific reference image now, not animated — only the
   cursor bubble (.aurora__warp) still moves, so reduced-motion just needs
   to turn that off rather than stopping a background animation. */
@media (prefers-reduced-motion: reduce) {
  .aurora__warp { display: none; }
}

/* ===================================================================
   COSMOS — closing statement, the aurora backdrop above sits behind it
=================================================================== */
.cosmos {
  position: relative;
  min-height: 70vh;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: #060B18;
}
/* Blends the aurora into the footer's own starting tone rather than
   cutting to it — the aurora's animated diagonal streak can land bright
   right at this edge on any given frame, and a hard cut would show it. A
   partial-opacity fade (not a solid mask) so the aurora stays visible
   through it, just tinted toward #10275C — the footer's own first
   gradient stop (css/style.css's .footer rule) — as it approaches the
   edge. Straight edge on purpose, per the brief: it doesn't need to be a
   blurred/soft boundary, just colour-continuous with what's below it. */
.cosmos__footer-fade {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  /* Taller than before (380px, was 200px) — the aurora's white/pale-blue
     field (.aurora__glow--a) can sit fairly bright right up near this
     edge, and fading a bright area down to near-black in a short span
     still reads as a line even when the two ends are the "right" colors.
     More room to work with fixes that regardless of exactly how bright
     the aurora is at this specific edge on a given viewport. */
  height: 380px;
  /* The footer already has its OWN top-of-page fade for exactly this seam
     (.footer's second background layer, "cosmos (#060B18) into the
     footer's navy" — search that comment) — it blends FROM #060B18 TO
     transparent over its own first 180px, so this fades TO #060B18 too
     (the color that fade already expects), not a different target of its
     own — two fades disagreeing on the color at the seam is what didn't
     connect earlier.
     Held fully transparent for the first 20% on purpose: starting the
     darken immediately at the top of this band is what made a plain
     2-stop transparent->solid fade still read as a hard-ish edge against
     bright content — more of the transition happens in the back half,
     which reads as smoother than a straight linear ramp the same height. */
  background: linear-gradient(180deg,
    transparent 0%, transparent 20%,
    rgba(6,11,24,0.4) 55%,
    rgba(6,11,24,0.8) 80%,
    #060B18 100%);
  pointer-events: none;
}
.cosmos__content {
  position: relative;
  z-index: 2;
  text-align: center;
  max-width: 700px;
  padding: 120px var(--space-12);
  pointer-events: none;
}
.cosmos__content .btn { pointer-events: auto; }
.cosmos__eyebrow {
  display: inline-flex;
  font-family: var(--font-display);
  font-size: var(--fs-4);
  font-weight: 600;
  letter-spacing: 0.18em;
  color: #8FB4FF;
  padding: 7px var(--space-8);
  border-radius: var(--r-pill);
  border: 1px solid rgba(143,180,255,0.3);
  background: rgba(143,180,255,0.08);
  margin-bottom: var(--space-13);
}
.cosmos__title {
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
  line-height: 1.08;
  letter-spacing: -0.01em;
  font-size: clamp(1.8rem, 4vw, 3rem);
  color: #fff;
  margin-bottom: var(--space-10);
}
.cosmos__sub {
  font-size: clamp(1rem, 1.4vw, 1.1rem);
  color: rgba(245,241,234,0.68);
  max-width: 480px;
  margin: 0 auto 34px;
}

/* ===================================================================
   FOOTER
=================================================================== */
/* Flat deep navy rather than the old gradient, whose lighter #10275C end
   made the top of the footer read as a separate blue band. One solid tone
   sits under the page as a single dark mass. */
.footer { background: #0A1020; color: var(--text-hi); padding: 100px var(--space-15) var(--space-16); position: relative; overflow: hidden; }
.footer::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.footer__top {
  position: relative;
  max-width: var(--container);
  margin: 0 auto 70px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-bottom: 50px;
  border-bottom: 1px solid var(--line-soft);
  flex-wrap: wrap;
  gap: var(--space-12);
}
.footer__statement { font-family: var(--font-display); font-weight: 700; font-size: clamp(1.8rem, 3.6vw, 2.6rem); line-height: 1.1; }
.footer__grid {
  position: relative;
  max-width: var(--container);
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: var(--space-16);
}
.footer__col { display: flex; flex-direction: column; gap: var(--space-6); }
.footer__col-title { font-family: var(--font-display); font-weight: 700; font-size: 0.75rem; letter-spacing: 0.1em; color: var(--text-lo); margin-bottom: var(--space-3); }
.footer__col a { color: var(--text-hi); opacity: 0.85; font-size: var(--fs-12); transition: opacity 0.3s var(--ease); }
.footer__col a:hover { opacity: 1; color: #FFD166; }
.footer__blurb { color: var(--text-lo); font-size: var(--fs-11); max-width: 260px; }
.footer__muted { color: var(--text-lo); font-size: var(--fs-8); }
.footer__bottom {
  position: relative;
  max-width: var(--container);
  margin: 70px auto 0;
  padding-top: 30px;
  border-top: 1px solid var(--line-soft);
  display: flex;
  justify-content: space-between;
  color: var(--text-lo);
  font-size: var(--fs-7);
  flex-wrap: wrap;
  gap: var(--space-5);
}

@media (max-width: 760px) {
  .footer__grid { grid-template-columns: 1fr 1fr; }
}

/* ===================================================================
   TALK-TO-JAPHONE ORB WIDGET
=================================================================== */
.chat-widget {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 400;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-8);
  /* The closed panel is invisible but still LAID OUT, so this container keeps
     a ~360x380 box. With pointer-events left at auto it swallowed every tap
     landing inside that box — on a 375px phone that is most of the lower
     screen, which made the sign-in fields underneath untappable. The
     container must never catch anything itself; only the real controls do,
     re-enabled individually below. */
  pointer-events: none;
}
.chat-widget__launcher,
.chat-nudge { pointer-events: auto; }

.orb--launcher { width: 62px; height: 62px; }
.orb--launcher .orb__core {
  width: 50px; height: 50px;
  box-shadow: 0 0 30px rgba(47,111,255,0.45), inset 0 0 16px rgba(4,11,32,0.5);
}
/* ---- the orb as organic matter ------------------------------------
   The canvas carries the identity; .orb__core stays underneath as the
   no-JS fallback, so a visitor without scripts still sees the mark
   rather than an empty circle. Once the canvas mounts, the glossy ball
   gets out of its way entirely — a gradient sphere behind drifting
   matter reads as two competing objects.

   --orb-rgb tracks the primary button colour rather than being its own
   brand decision. That is the actual rule behind the reference's
   indigo/lime split: the orb matches the CTA. Ours is blue in both
   themes, so the orb is blue in both — a separate dark-mode hue would
   look like it followed the rule while breaking it. */
.orb {
  /* The logo mark's own three stops — lit shoulder, body, shaded base.
     Taking them from the mark rather than picking new blues is what makes
     the rendered sphere read as the same object as the favicon. */
  --orb-rgb:      61,121,255;
  --orb-rgb-lit: 114,158,255;
  --orb-rgb-deep: 26,64,168;
}
.orb__canvas {
  position: absolute;
  inset: 0;
  margin: auto;
  pointer-events: none;
  z-index: 1;
}
.orb.has-canvas .orb__core {
  background: none;
  border-color: transparent;
  box-shadow: none;
  animation: none;
}
.orb.has-canvas .orb__core::before,
.orb.has-canvas .orb__core::after { display: none; }

.orb--xs { width: 34px; height: 34px; flex-shrink: 0; }
.orb--xs .orb__core {
  width: 28px; height: 28px;
  border-width: 1px;
  box-shadow: 0 0 16px rgba(47,111,255,0.4), inset 0 0 9px rgba(4,11,32,0.45);
}

/* Hero-orb-to-chat-orb morph — a fixed-position clone of the hero orb that
   js/main.js's initHeroOrbMorph() drives along a curved path as the page
   scrolls, landing on the real chat launcher. Sized to match .orb.hero__orb
   exactly so the handoff at the top of the page is seamless. Desktop only —
   see the matchMedia branches in that function; on mobile this just sits
   inert, invisible and unused. */
.hero-orb-traveler {
  position: fixed;
  top: 0;
  left: 0;
  width: 150px;
  height: 150px;
  pointer-events: none;
  z-index: 402;
  opacity: 0;
  will-change: transform, opacity;
}
.hero-orb-traveler .orb { width: 150px; height: 150px; }
.hero-orb-traveler .orb__core { width: 132px; height: 132px; }

/* Open animation: a clone of the corner launcher orb floats up and lands as the
   panel's header avatar. Built and driven by js/orb-chat.js (animateOrbOpen) —
   it sits above the panel for the short flight, while the real header orb is
   held hidden until the clone arrives on top of it. */
.chat-orb-flyer {
  position: fixed;
  z-index: 500;
  pointer-events: none;
  transform-origin: top left;
  will-change: transform;
}
.chat-orb-flyer .orb { width: 100%; height: 100%; }

.chat-widget__launcher {
  position: relative;
  width: 62px; height: 62px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: transform 0.4s var(--ease-spring);
}
.chat-widget__launcher:hover { transform: scale(1.06); }
.chat-widget__launcher:active { transform: scale(0.96); }
.chat-widget__launcher-pulse {
  position: absolute; inset: -4px;
  border-radius: 50%;
  border: 1.5px solid rgba(255,209,102,0.8);
  animation: launcher-pulse 2.6s ease-out infinite;
  pointer-events: none;
}
@keyframes launcher-pulse {
  0% { transform: scale(0.9); opacity: 0.8; }
  100% { transform: scale(1.5); opacity: 0; }
}
.chat-widget.is-open .chat-widget__launcher { opacity: 0; pointer-events: none; transform: scale(0.7); }

.chat-nudge {
  position: relative;
  max-width: 210px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: var(--space-6) 30px var(--space-6) var(--space-8);
  color: var(--text-hi);
  font-family: var(--font-body);
  font-weight: 500;
  font-size: var(--fs-8);
  line-height: 1.35;
  box-shadow: var(--shadow-glass);
  cursor: pointer;
  animation: chat-nudge-in 0.5s var(--ease) both;
}
.chat-nudge::after {
  content: '';
  position: absolute;
  bottom: -7px;
  right: 26px;
  width: 14px; height: 14px;
  background: var(--panel-2);
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  transform: rotate(45deg);
}
.chat-nudge__close {
  position: absolute;
  top: 6px; right: 6px;
  width: 20px; height: 20px;
  border: none;
  background: none;
  color: var(--text-lo);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  transition: color 0.2s var(--ease);
}
.chat-nudge__close:hover { color: var(--text-hi); }
@keyframes chat-nudge-in {
  from { opacity: 0; transform: translateY(10px) scale(0.94); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
.chat-widget.is-open .chat-nudge { display: none; }

.chat-widget__panel {
  width: min(360px, calc(100vw - 48px));
  max-height: min(560px, 70vh);
  display: flex;
  flex-direction: column;
  background: rgba(8,10,15,0.92);
  backdrop-filter: blur(24px) saturate(160%);
  -webkit-backdrop-filter: blur(24px) saturate(160%);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-glass);
  color: var(--text-hi);
  opacity: 0;
  transform: translateY(16px) scale(0.97);
  pointer-events: none;
  transition: opacity 0.4s var(--ease), transform 0.4s var(--ease-spring);
  transform-origin: bottom right;
}
.chat-widget.is-open .chat-widget__panel {
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}

.chat-widget__header {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  padding: var(--space-8) var(--space-8) var(--space-7);
  border-bottom: 1px solid var(--line-soft);
  flex-shrink: 0;
}
.chat-widget__heading { flex: 1; min-width: 0; }
.chat-widget__title { font-family: var(--font-display); font-weight: 700; font-size: var(--fs-13); }
.chat-widget__status { font-size: 0.75rem; color: var(--text-lo); }
.chat-widget__close {
  position: relative;
  width: 28px; height: 28px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.2rem; color: var(--text-lo);
  transition: background 0.25s, color 0.25s;
}
.chat-widget__close:hover { background: rgba(255,255,255,0.08); color: var(--text-hi); }
.chat-widget__close::before {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 44px; height: 44px; transform: translate(-50%, -50%);
}

.chat-widget__messages {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-8);
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  min-height: 160px;
}
.chat-widget__messages::-webkit-scrollbar { width: 5px; }
.chat-widget__messages::-webkit-scrollbar-thumb { background: var(--line); border-radius: 3px; }

.chat-msg {
  max-width: 86%;
  padding: var(--space-5) var(--space-7);
  border-radius: 16px;
  font-size: 0.87rem;
  line-height: 1.45;
  opacity: 0;
  transform: translateY(8px);
  animation: chat-msg-in 0.4s var(--ease) forwards;
}
@keyframes chat-msg-in { to { opacity: 1; transform: translateY(0); } }
.chat-msg--user { align-self: flex-end; background: var(--blue); color: #fff; border-bottom-right-radius: 4px; }
.chat-msg--japhone { align-self: flex-start; background: rgba(255,255,255,0.06); border: 1px solid var(--line-soft); border-bottom-left-radius: 4px; }
.chat-msg--japhone .chat-cta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-5);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-5);
  color: var(--blue-bright);
  border-bottom: 1px solid rgba(47,111,255,0.4);
  padding-bottom: 1px;
  width: fit-content;
}
.chat-msg--japhone .chat-cta:hover { color: #fff; border-color: #fff; }

/* The empty state for reviews. Hidden by js/main.js as soon as a real
   approved review renders, so it never sits above actual testimonials. */
.testimonials__empty {
  text-align: center;
  max-width: 46ch;
  margin: 0 auto var(--space-10);
  font-size: var(--fs-11);
  line-height: 1.6;
  /* --text-dark-lo, not --text-lo. The -lo/-hi pair is for dark sections;
     these sit on the pale ground, where they measured 2.63:1. */
  color: var(--text-dark-lo);
}

/* Consent and terms notices under a form's submit button. Quiet, but it
   has to clear 4.5:1 — this is the text that tells someone what happens
   to their data, so it is the last thing that should be hard to read. */
.contact__consent {
  margin-top: var(--space-5);
  font-size: var(--fs-5);
  line-height: 1.5;
  /* These sit on the pale contact panel, so they take the dark-surface
     tokens. Using --text-lo/--text-hi here put the body at 2.97:1 and the
     policy links at 1.04:1 — white on near-white, invisible. */
  color: var(--text-dark-lo);
  text-align: center;
}
.contact__consent a {
  color: var(--text-dark);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Opening prompts. Deliberately quieter than the CTA above — they are a way
   in for someone who does not know what to ask, not a call to action, and
   they only ever appear once at the top of a conversation. */
.chat-suggest {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-self: flex-start;
  margin-top: var(--space-2);
}
.chat-suggest__chip {
  font: inherit;
  font-size: var(--fs-5);
  line-height: 1.3;
  text-align: left;
  color: var(--text-hi);
  background: rgba(255,255,255,0.07);
  border: 1px solid rgba(255,255,255,0.16);
  border-radius: var(--r-pill);
  padding: var(--space-4) var(--space-7);
  cursor: pointer;
  transition: background 0.2s, border-color 0.2s;
  -webkit-tap-highlight-color: transparent;
}
.chat-suggest__chip:hover {
  background: rgba(255,255,255,0.13);
  border-color: rgba(255,255,255,0.3);
}

.chat-typing { display: flex; gap: var(--space-2); align-self: flex-start; padding: var(--space-5) var(--space-7); }
.chat-typing span { width: 6px; height: 6px; border-radius: 50%; background: var(--text-lo); animation: typing-dot 1.2s infinite; }
.chat-typing span:nth-child(2) { animation-delay: 0.2s; }
.chat-typing span:nth-child(3) { animation-delay: 0.4s; }

.chat-widget__input-row {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-6);
  border-top: 1px solid var(--line-soft);
  flex-shrink: 0;
}
.chat-widget__mic, .chat-widget__send {
  position: relative;
  width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--text-lo);
  background: rgba(255,255,255,0.05);
  transition: background 0.25s, color 0.25s;
}
.chat-widget__mic::before, .chat-widget__send::before {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 44px; height: 44px; transform: translate(-50%, -50%);
}
.chat-widget__mic svg, .chat-widget__send svg { width: 16px; height: 16px; }
.chat-widget__mic:hover, .chat-widget__send:hover { background: var(--blue); color: #fff; }
.chat-widget__mic.is-listening { background: var(--amber); color: #3D2E00; animation: mic-pulse 1s ease-in-out infinite; }
@keyframes mic-pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.12); } }
.chat-widget__input-row input {
  flex: 1;
  min-width: 0;
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  padding: 9px var(--space-7);
  color: var(--text-hi);
  font-size: var(--fs-8);
}
.chat-widget__input-row input:focus { outline: none; border-color: var(--blue); box-shadow: var(--focus-ring); }

@media (max-width: 500px) {
  .chat-widget { right: 16px; bottom: 16px; }
}

/* Chat states tint the rim and the outer glow only — the ball itself stays the
   solid logo blue, so the mark never stops looking like the logo. */
.orb__core.is-listening {
  border-color: var(--blue-bright);
  animation: orb-listen 1s ease-in-out infinite;
}
.orb__core.is-thinking {
  border-color: var(--amber);
  animation: orb-think 1.2s ease-in-out infinite;
}
.orb__core.is-speaking {
  border-color: var(--green);
  animation: orb-speak 0.55s ease-in-out infinite;
}
@keyframes orb-listen {
  0%, 100% { transform: scale(1); box-shadow: 0 0 30px rgba(47,111,255,0.5), inset 0 0 18px rgba(4,11,32,0.5); }
  50% { transform: scale(1.1); box-shadow: 0 0 46px rgba(47,111,255,0.7), inset 0 0 24px rgba(4,11,32,0.55); }
}
@keyframes orb-think {
  0%, 100% { transform: scale(1) rotate(0deg); box-shadow: 0 0 30px rgba(255,209,102,0.42), inset 0 0 18px rgba(4,11,32,0.5); }
  50% { transform: scale(1.05) rotate(4deg); box-shadow: 0 0 46px rgba(255,209,102,0.6), inset 0 0 24px rgba(4,11,32,0.55); }
}
@keyframes orb-speak {
  0%, 100% { transform: scale(1); box-shadow: 0 0 30px rgba(52,211,153,0.5), inset 0 0 18px rgba(4,11,32,0.5); }
  50% { transform: scale(1.08); box-shadow: 0 0 46px rgba(52,211,153,0.72), inset 0 0 24px rgba(4,11,32,0.55); }
}

/* ===================================================================
   DASHBOARD SHELL (account.html) — sidebar + topbar + tabbed panels,
   light theme, ElevenLabs-style app layout.
=================================================================== */
/* iOS paints the status-bar strip and the overscroll bounce from the ROOT
   element's background, not the body's — so this is the only way to stop the
   page showing through up there. It has to repeat the light/dark values
   because it sits outside .dash-body, where the theme tokens live. data-theme
   sits on <html> too, so these are one element — the attribute attaches to the
   class rather than nesting. */
.dash-html { background: #FFFFFF; }
.dash-html[data-theme="dark"] { background: #141A26; }

.dash-body {
  background: var(--paper);
  /* The mobile bottom pill. Charcoal on the light theme, matching the rest of
     the brand's dark furniture; on the dark theme it lifts to a lighter
     surface instead, since a dark pill on a dark page reads as a hole. */
  /* Deliberately the same glass as .nav__inner on the marketing page — same
     tint, blur, rim and sheen — so the dashboard's floating bar reads as the
     site's own header, just docked at the bottom. */
  /* Same glass system as every other pane: tinted fill, bright rim. */
  /* 0.40 was too sheer to carry its own icons. Where the pill floats over a
     white stretch of page the charcoal washed out to mid-grey and the icons
     landed at 2.6:1 — under the 3:1 a control needs, and pure-white ink only
     reached 2.78:1, so tint was the only lever. 0.52 holds ~3.4:1 in that
     worst case and still reads as glass over everything else. */
  --navpill: rgba(16,22,40,0.52);
  --navpill-solid: #12161F;
  /* The rim, as a sweep rather than a value. 0deg is the top of the pill and
     the angle runs clockwise, so: brightest across the top, falling through
     the right cap, all but gone along the bottom right, a little bounce
     returning on the lower left, and back up. First and last stops match so
     there is no seam where the sweep closes. */
  --navpill-lens: conic-gradient(from 0deg at 50% 50%,
    rgba(255,255,255,0.34)   0deg,
    rgba(255,255,255,0.17)  52deg,
    rgba(255,255,255,0.05)  98deg,
    rgba(255,255,255,0.01) 152deg,
    rgba(255,255,255,0.02) 206deg,
    rgba(255,255,255,0.08) 254deg,
    rgba(255,255,255,0.16) 296deg,
    rgba(255,255,255,0.34) 360deg);
  --navpill-sheen: rgba(255,255,255,0.20);
  --navpill-active: rgba(255,255,255,0.15);
  /* Full white, not 0.72 — every point of it is needed against the tint. */
  --navpill-ink: #FFFFFF;
}
.dash { display: flex; min-height: 100vh; }

.dash__sidebar {
  /* Read from a variable so narrowing the sidebar is a value change rather
     than an override that has to out-specify this rule. */
  width: var(--dash-sidebar-w, 240px);
  flex-shrink: 0;
  background: var(--paper-2);
  border-right: 1px solid rgba(var(--ink-rgb),0.08);
  display: flex;
  flex-direction: column;
  padding: var(--space-12) var(--space-8);
  position: fixed;
  top: 0; left: 0; bottom: 0;
  z-index: 100;
  transition: transform 0.3s var(--ease);
}
/* Matches .pl-brand on the marketing page and .wiz__brand in setup — same
   face, same weight, same tracking, always uppercase. */
.dash__brand {
  display: flex; align-items: center; gap: var(--space-5);
  font-family: 'Quicksand', var(--font-display); font-weight: 700; font-size: 1rem;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-dark);
  padding: var(--space-2) var(--space-4) var(--space-12);
}
/* The JAPHONE wordmark. Every letter uses the logo P's monoline stroke,
   circular bowls, and softened joins. Generated by scripts/wordmark.js and
   inlined, and sized in em so it scales with every lockup. The viewBox
   carries the cap-height, baseline, and balanced visible-letter spacing. */
.brand-word {
  display: inline-block;
  height: 0.7031em;
  width: auto;
  aspect-ratio: 5170 / 703;
  vertical-align: baseline;
  overflow: visible;
}
.dash__nav { display: flex; flex-direction: column; gap: var(--space-2); flex: 1; }
/* Only the mobile pill uses this; on the desktop sidebar it has no job. */
.dash__nav-chip { display: none; }
.dash__nav-item {
  display: flex; align-items: center; gap: var(--space-6);
  padding: 11px var(--space-6);
  border-radius: var(--r-xs);
  font-family: var(--font-body); font-weight: 500; font-size: var(--fs-11);
  color: var(--text-dark-lo);
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
  text-align: left;
  width: 100%;
}
.dash__nav-item svg { width: 19px; height: 19px; flex-shrink: 0; }
.dash__nav-item:hover { background: rgba(var(--ink-rgb),0.04); color: var(--text-dark); }
.dash__nav-item.is-active { background: rgba(var(--ink-rgb),0.10); color: var(--text-dark); font-weight: 600; }

/* Square-style sidebar, desktop only. Small uppercase section headings, and
   the selected row marked by an accent bar on the sidebar's edge instead of
   a filled pill. The phone keeps its travelling-pill layout below 900px. */
.dash__nav-group {
  font-family: var(--font-display);
  font-size: 0.64rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-dark-lo); opacity: 0.6;
  padding: 0 var(--space-7); margin: var(--space-9) 0 var(--space-4);
}
.dash__nav-group:first-of-type { margin-top: 0; }
@media (min-width: 901px) {
  .dash__nav-item { border-radius: 0 var(--r-md) var(--r-md) 0; }
  .dash__nav-item.is-active {
    background: rgba(var(--ink-rgb),0.06);
    color: var(--text-dark);
    font-weight: 600;
    box-shadow: inset 3px 0 0 var(--blue);
  }
  .dash__nav-item.is-active svg { color: var(--blue); }
}
/* No room for headings in the bottom pill, or in the icons-only column. */
@media (max-width: 900px) { .dash__nav-group { display: none; } }
.dash-narrow .dash__nav-group { display: none; }
.dash__back {
  display: block;
  padding: 14px 8px 0;
  font-size: var(--fs-7);
  color: var(--text-dark-lo);
  border-top: 1px solid rgba(var(--ink-rgb),0.08);
  margin-top: var(--space-6);
}
.dash__back:hover { color: var(--blue); }

.dash__scrim {
  position: fixed; inset: 0;
  background: rgba(4,7,14,0.45);
  z-index: 99;
}

/* The sidebar is position:fixed, so it is out of flow and this margin is
   what actually holds the content clear of it. It has to track the same
   variable — narrowing the sidebar while this stayed at 240px would move
   nothing on screen. */
.dash__main { flex: 1; margin-left: var(--dash-sidebar-w, 240px); min-height: 100vh; display: flex; flex-direction: column; }
.dash__topbar {
  display: flex; align-items: center; gap: var(--space-8);
  padding: var(--space-9) var(--space-15);
  border-bottom: 1px solid rgba(var(--ink-rgb),0.08);
  background: var(--paper-2);
  position: sticky; top: 0; z-index: 50;
}
.dash__menu-toggle {
  display: none;
  width: 34px; height: 34px;
  align-items: center; justify-content: center;
  color: var(--text-dark);
  flex-shrink: 0;
}
.dash__title { font-family: var(--font-display); font-weight: 700; font-size: 1.2rem; color: var(--text-dark); flex: 1; }
.dash__profile { position: relative; flex-shrink: 0; }
/* Hue derived from the account's email (js/account.js sets --avhue), the same
   technique the voice picker uses — same person, same color, every reload,
   without needing a photo. --avhue's fallback matches --blue for the instant
   before JS runs. */
.dash__avatar {
  width: 36px; height: 36px; border-radius: 50%;
  background: linear-gradient(150deg,
    hsl(var(--avhue, 221) 62% 58%), hsl(calc(var(--avhue, 221) + 26) 55% 40%));
  color: #fff;
  font-family: var(--font-display); font-weight: 700; font-size: var(--fs-11);
  display: flex; align-items: center; justify-content: center;
  text-transform: uppercase;
}
/* Avatar, name and plan in one control, like the reference's account block.
   The name and caret drop away on narrower screens, leaving just the avatar. */
.dash__profile-btn {
  display: inline-flex; align-items: center; gap: var(--space-5);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--r-pill);
  transition: background 0.2s var(--ease);
}
.dash__profile-btn:hover { background: rgba(var(--ink-rgb),0.06); }
.dash__profile-who { display: none; flex-direction: column; align-items: flex-start; line-height: 1.25; }
.dash__profile-name { font-family: var(--font-display); font-weight: 600; font-size: var(--fs-9); color: var(--text-dark); white-space: nowrap; }
.dash__profile-role { font-size: 0.7rem; color: var(--text-dark-lo); white-space: nowrap; }
.dash__profile-caret { width: 15px; height: 15px; color: var(--text-dark-lo); flex-shrink: 0; display: none; }
@media (min-width: 1100px) {
  .dash__profile-who, .dash__profile-caret { display: flex; }
  .dash__profile-btn { padding-right: var(--space-5); }
}

/* The search control reads as a field rather than a bare icon button. */
.dash__search { width: auto; justify-content: flex-start; gap: var(--space-4); }
.dash__search-label { display: none; font-size: var(--fs-7); color: var(--text-dark-lo); white-space: nowrap; }
@media (min-width: 1100px) {
  .dash__search {
    min-width: 210px; padding: 0 var(--space-7);
    border-radius: var(--r-pill);
    background: rgba(var(--ink-rgb),0.05);
  }
  .dash__search-label { display: inline; }
  .dash__search:hover { background: rgba(var(--ink-rgb),0.09); }
}

.dash__profile-menu {
  position: absolute; top: calc(100% + 8px); right: 0;
  background: var(--paper-2);
  border: 1px solid rgba(var(--ink-rgb),0.08);
  border-radius: var(--r-sm);
  box-shadow: var(--shadow-soft);
  padding: var(--space-7);
  min-width: 220px;
  display: flex; flex-direction: column; gap: var(--space-2);
  z-index: 60;
}
.dash__profile-meta {
  padding: 0 8px 10px;
  border-bottom: 1px solid rgba(var(--ink-rgb),0.08);
  margin-bottom: var(--space-3);
}
.dash__profile-email { font-size: var(--fs-7); color: var(--text-dark-lo); word-break: break-all; }
.dash__profile-signin { font-size: 0.74rem; color: var(--text-dark-lo); opacity: 0.75; margin-top: var(--space-1); }
.dash__profile-menu button, .dash__profile-menu a { text-align: left; padding: 9px var(--space-4); border-radius: 8px; font-size: var(--fs-10); color: var(--text-dark); text-decoration: none; display: block; }
.dash__profile-menu button:hover, .dash__profile-menu a:hover { background: rgba(var(--ink-rgb),0.05); }
/* Initials-color picker in the profile menu. Each swatch previews the same
   hsl() gradient the avatar uses, keyed on its own --avhue; the "A" swatch is
   the automatic email-derived color. */
.dash__profile-color { padding: 2px 8px 10px; border-bottom: 1px solid rgba(var(--ink-rgb),0.08); margin-bottom: var(--space-3); }
.dash__profile-color-label { font-size: var(--fs-7); color: var(--text-dark-lo); margin-bottom: 8px; }
.dash__profile-swatches { display: flex; flex-wrap: wrap; gap: 8px; }
.dash__swatch {
  width: 20px; height: 20px; border-radius: 50%; padding: 0; cursor: pointer;
  background: linear-gradient(150deg, hsl(var(--avhue,221) 62% 58%), hsl(calc(var(--avhue,221) + 26) 55% 40%));
  border: 0;
  box-shadow: 0 0 0 1px rgba(var(--ink-rgb),0.12);
  transition: transform .15s ease, box-shadow .15s ease;
}
.dash__swatch:hover { transform: scale(1.14); background: linear-gradient(150deg, hsl(var(--avhue,221) 62% 58%), hsl(calc(var(--avhue,221) + 26) 55% 40%)); }
.dash__swatch.is-active { box-shadow: 0 0 0 2px var(--paper-2), 0 0 0 4px hsl(var(--avhue,221) 62% 52%); }

/* ===================================================================
   ACCOUNT SETTINGS PAGE (settings.html)
   =================================================================== */
.settings { max-width: 640px; margin: 0 auto; padding: clamp(28px, 6vw, 56px) 20px 80px; }
.settings__back { display: inline-block; color: var(--blue); text-decoration: none; font-size: var(--fs-8); margin-bottom: 18px; }
.settings__back:hover { text-decoration: underline; }
.settings__title { font-family: var(--font-display); font-weight: 700; font-size: clamp(1.7rem, 3.6vw, 2.2rem); color: var(--text-dark); margin: 0 0 28px; }
.settings__loading { color: var(--text-dark-lo); font-size: var(--fs-11); }
.settings__body { display: flex; flex-direction: column; gap: 18px; }
.settings-card { background: var(--paper-2); border: 1px solid rgba(var(--ink-rgb),0.08); border-radius: var(--r-lg); box-shadow: var(--shadow-soft); padding: var(--space-13); }
.settings-card__title { font-family: var(--font-display); font-weight: 600; font-size: var(--fs-14); color: var(--text-dark); margin: 0 0 16px; }
.settings-profile { display: flex; align-items: center; gap: 14px; margin-bottom: 20px; }
.settings-avatar { width: 48px; height: 48px; font-size: 1rem; flex-shrink: 0; }
.settings-profile__meta { min-width: 0; }
.settings-profile__email { font-size: var(--fs-12); color: var(--text-dark); font-weight: 600; word-break: break-all; }
.settings-profile__signin { font-size: var(--fs-7); color: var(--text-dark-lo); margin-top: 2px; }
.settings-field__label { font-size: var(--fs-8); color: var(--text-dark-lo); margin-bottom: 10px; }
.settings-field__hint { font-size: var(--fs-7); color: var(--text-dark-lo); margin-top: 10px; }
.settings .dash__profile-swatches { gap: 10px; }
.settings .dash__swatch { width: 26px; height: 26px; }
.settings-toggle { display: flex; align-items: center; gap: 12px; cursor: pointer; }
.settings-toggle__input { position: absolute; opacity: 0; width: 0; height: 0; }
.settings-toggle__track { position: relative; width: 44px; height: 26px; border-radius: 999px; background: rgba(var(--ink-rgb),0.18); flex-shrink: 0; transition: background .2s ease; }
.settings-toggle__knob { position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.3); transition: transform .2s ease; }
.settings-toggle__input:checked + .settings-toggle__track { background: var(--blue); }
.settings-toggle__input:checked + .settings-toggle__track .settings-toggle__knob { transform: translateX(18px); }
.settings-toggle__input:focus-visible + .settings-toggle__track { box-shadow: 0 0 0 3px rgba(47,111,255,.35); }
.settings-toggle__label { font-size: var(--fs-11); color: var(--text-dark); }
.settings-card--danger { border-color: rgba(220,53,69,0.35); }
.settings-danger__text { font-size: var(--fs-10); color: var(--text-dark-lo); line-height: 1.55; margin-bottom: 16px; }
.settings-danger__btn { background: #dc3545; color: #fff; border: 1px solid transparent; box-shadow: none; }
.settings-danger__btn:hover:not(:disabled) { background: #c42d3c; }
.settings-danger__btn:disabled { opacity: 0.5; cursor: not-allowed; }
.settings-danger__confirm { margin-top: 4px; }
.settings-danger__prompt { font-size: var(--fs-9); color: var(--text-dark); margin-bottom: 10px; }
.settings-danger__input { width: 100%; max-width: 260px; padding: 11px 14px; border-radius: 10px; border: 1px solid rgba(var(--ink-rgb),0.2); background: var(--paper); color: var(--text-dark); font-size: var(--fs-11); box-shadow: none; }
.settings-danger__input:focus { border-color: #dc3545; outline: none; box-shadow: 0 0 0 3px rgba(220,53,69,.2); }
.settings-danger__actions { display: flex; gap: 10px; margin-top: 14px; flex-wrap: wrap; }
.settings__signout { align-self: center; margin-top: 8px; background: none; border: 0; color: var(--text-dark-lo); font-size: var(--fs-9); cursor: pointer; padding: 8px; }
.settings__signout:hover { color: var(--text-dark); text-decoration: underline; }
.dash__swatch--auto { position: relative; }
.dash__swatch--auto::after {
  content: "A"; position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 10px; font-weight: 700; color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,.45); pointer-events: none;
}

.dash__content { flex: 1; padding: var(--space-15); max-width: 760px; width: 100%; }
/* 760px reads well as a form's line length, but on a real desktop viewport
   it leaves most of the window empty next to the 240px sidebar. Widen it
   once there's room, mobile and tablet keep the narrower, more readable
   column below the 900px sidebar-collapse breakpoint. */
@media (min-width: 901px) {
  .dash__content { max-width: 1200px; }
}
/* On a genuinely wide monitor 1200px strands hundreds of pixels beside the
   sidebar. This panel is a dashboard now, not a form, so let it use the room.
   (The matching one-row KPI grid lives with the results rules further down —
   it has to come after .results__stats sets its own columns.) */
@media (min-width: 1400px) {
  .dash__content { max-width: 1560px; }
}
.dash__loading { color: var(--text-dark-lo); text-align: center; padding: 80px 0; }

/* Outstanding payment. Amber rather than red: the service is still running,
   so this is a warning, not a failure. */
.dash__banner {
  display: flex; align-items: center; gap: var(--space-8); flex-wrap: wrap;
  padding: var(--space-8) var(--space-9);
  margin-bottom: var(--space-10);
  border-radius: var(--r-sm);
  background: rgba(255,209,102,0.12);
  border: 1px solid rgba(255,209,102,0.4);
}
.dash__banner-text { flex: 1; min-width: 200px; }
.dash__banner-title { font-family: var(--font-display); font-weight: 700; font-size: var(--fs-13); color: var(--text-dark); }
.dash__banner-sub { font-size: 0.84rem; color: var(--text-dark-lo); margin-top: var(--space-1); }
.dash__banner-btn { flex-shrink: 0; }

.dash__panel { display: none; }
.dash__panel.is-active { display: block; }

.dash__card { background: var(--paper-2); border: 1px solid rgba(var(--ink-rgb),0.08); border-radius: 16px; padding: var(--space-11) var(--space-12); margin-bottom: var(--space-8); }
.dash__card-label { font-size: var(--fs-5); color: var(--text-dark-lo); margin-bottom: var(--space-3); }
.dash__card-value { font-family: var(--font-display); font-weight: 600; font-size: 1.05rem; color: var(--text-dark); }
.dash__card-actions { display: flex; gap: var(--space-6); margin-top: var(--space-2); flex-wrap: wrap; }

/* --- Mobile: the sidebar becomes a floating pill at the bottom -------------
   A drawer put every panel two taps away and parked the trigger in the top-
   left corner, which is the hardest place on a phone to reach one-handed.
   The same <aside> is restyled into a docked pill instead, so the panel
   wiring in js/account.js is untouched — it still just looks for
   .dash__nav-item. Settings and the account menu stay in the top right. */
@media (max-width: 900px) {
  .dash__sidebar {
    position: fixed;
    top: auto;
    /* Centred and only as wide as its contents, the same way the marketing
       header floats — not a bar stretched to both edges. */
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    width: max-content;
    max-width: calc(100vw - 24px);
    /* Clear of the home indicator. The 12px stands on its own where the inset
       resolves to zero (Android, and Safari when its toolbar already covers
       the indicator), and the inset adds to it where it does not. */
    bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    padding: var(--space-3);
    border-radius: var(--r-pill);
    /* The marketing header's glass, value for value: same tint, blur,
       saturation, rim and inset sheen. -webkit- prefix included, since iOS
       Safari still requires it. */
    /* The charcoal identity stays — this is brand furniture, and a clear
       pill would need the icons to flip dark. What it takes from the panes
       is the material: the diagonal specular sweep over the tint, and the
       thickness below. */
    /* Its own sweep, at well under the panes' strength. The panes are pale
       and can absorb a 20% white band; this one is charcoal, and at that
       strength it washed to mid-grey and took the icons down to 2.56:1,
       under the 3:1 a UI control needs. */
    background:
      linear-gradient(118deg, transparent 26%, rgba(255,255,255,0.035) 38%,
        rgba(255,255,255,0.01) 47%, transparent 60%),
      linear-gradient(var(--navpill), var(--navpill));
    -webkit-backdrop-filter: blur(30px) saturate(160%);
    backdrop-filter: blur(30px) saturate(160%);
    /* Transparent, not absent: the 1px still shapes the box, but nothing
       draws it. Every lit edge — the top sheen and the two side lines
       included — moves into ::before, where it can vary around the
       perimeter instead of being stamped on at one flat value. */
    border: 1px solid transparent;
    /* No 0 0 0 1px ring either. A hard hairline is a drawn outline; what
       seats the pill is the shadow under it. */
    box-shadow:
      0 12px 30px -14px rgba(0,0,0,0.55),
      0 2px 8px -3px rgba(0,0,0,0.28),
      /* the near surface catching light, the far one as a caustic below,
         and the body densening just inside the rim */
      inset 0 1px 0 0 rgba(255,255,255,0.30),
      inset 0 -1.5px 2px -1px rgba(255,255,255,0.15),
      inset 0 0 16px -10px rgba(0,0,0,0.45);
    /* Was a slide-in drawer; the only transform now is the centring one. */
    transition: none;
    z-index: 90;
  }
  .dash__sidebar.is-open { transform: translateX(-50%); }

  /* The rim, and the reason it is a gradient instead of a border. A stroke
     is one value all the way round; a glass edge is bright where the light
     reaches it and gone where it doesn't. This ring carries a conic
     gradient, so the light runs strongest across the top, dies away down
     the lower right, and comes back as bounce on the lower left — and it
     carries its own backdrop-filter, so the same band bends what scrolls
     under it. That is the fade and the warp, in one pass over one band. */
  .dash__sidebar::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    z-index: 0;
    padding: 1.5px;
    background: var(--navpill-lens);
    -webkit-backdrop-filter: blur(5px) brightness(1.16) saturate(130%);
    backdrop-filter: blur(5px) brightness(1.16) saturate(130%);
    -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;
  }
  /* Where the lensing dissolves. The rim above stops at 4px, and a stop is
     its own hard line if nothing follows it — so a second, wider ring picks
     up exactly where the first ends, carrying the same sweep at a fraction
     of the strength plus a gentler bend. The edge steps down instead of
     ending, which is what gives it depth rather than a boundary.

     Two rings and not a smooth ramp because masking is applied after
     filtering, so a blur on the ring cannot soften its own mask cut, and a
     radial mask cannot follow a rounded rectangle. Two steps is what CSS
     actually affords here, and at these widths it reads as a falloff. */
  .dash__sidebar::after {
    content: '';
    position: absolute;
    inset: 1.5px;
    border-radius: inherit;
    pointer-events: none;
    z-index: 0;
    padding: 5px;
    opacity: 0.28;
    background: var(--navpill-lens);
    -webkit-backdrop-filter: blur(2px) brightness(1.05);
    backdrop-filter: blur(2px) brightness(1.05);
    -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;
  }
  .dash__nav, .dash__nav-item { position: relative; z-index: 1; }

  /* Where the backdrop cannot be blurred, the same pill still has to be
     opaque enough to read against whatever scrolls under it. */
  @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .dash__sidebar { background: var(--navpill-solid); }
  }
  /* The drawer's furniture has nowhere to go in a pill, and its trigger and
     backdrop no longer have anything to open. */
  .dash__brand,
  .dash__back,
  .dash__menu-toggle,
  .dash__scrim { display: none; }

  .dash__nav { flex-direction: row; gap: 0; position: relative; }
  .dash__nav-item {
    position: relative;
    z-index: 1;
    /* An explicit width, not just a flex-basis: the bar is sized to its
       contents, and max-content sizing measures the icon, not the basis.
       Shrink stays on so seven cells still fit a 320px screen — and they
       shrink together, which is what keeps the chip's 1/7 arithmetic true. */
    width: 46px;
    flex: 0 1 46px;
    min-width: 0;
    justify-content: center;
    gap: 0;
    padding: 10px 0;
    border-radius: var(--r-pill);
    color: var(--navpill-ink);
    /* iOS paints a grey box over the glass on tap without this. */
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
  }
  .dash__nav-item svg { width: 22px; height: 22px; }
  /* Icon-only by sight, still labelled for screen readers and voice control. */
  .dash__nav-item span {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .dash__nav-item:hover { background: none; color: var(--navpill-ink); }
  .dash__nav-item.is-active {
    background: var(--navpill-active);
    color: #fff;
  }

  /* --- The active chip, as one piece of glass that travels -----------------
     Every browser gets the highlight above. Where :has() is available the
     per-item background is handed off to a single element that slides between
     positions instead, so the chip reads as one blob of liquid moving under
     the icons rather than one lamp switching off as another lights up.
     :has() is Safari 15.4+ / Chrome 105+; anything older keeps the cross-fade,
     which looks fine, just less alive. */
  @supports selector(:has(*)) {
    .dash__nav-item.is-active { background: none; }
    .dash__nav-chip {
      display: block;
      position: absolute;
      z-index: 0;
      top: 0; bottom: 0; left: 0;
      /* The row runs gapless, so five equal cells divide the track exactly
         and one cell is exactly one step. */
      width: calc(100% / 5);
      /* translate rather than left: this is the one property here that moves
         on the compositor, which is what keeps the slide smooth on a phone
         instead of relaying out the bar every frame. Percentages resolve
         against the chip's own width, so N cells across is N * 100%. */
      translate: calc(var(--nav-i, 0) * 100%);
      border-radius: var(--r-pill);
      background: var(--navpill-active);
      box-shadow:
        inset 0 1px 0 var(--navpill-sheen),
        0 2px 8px -2px rgba(0,0,0,0.28);
      /* Slight overshoot on settle — the "liquid" part. */
      transition: translate 0.44s cubic-bezier(0.34, 1.32, 0.64, 1);
      pointer-events: none;
    }
    /* :nth-of-type counts buttons only, so the chip sitting first in the
       DOM does not shift these indices. */
    .dash__nav:has(.dash__nav-item:nth-of-type(1).is-active) { --nav-i: 0; }
    .dash__nav:has(.dash__nav-item:nth-of-type(2).is-active) { --nav-i: 1; }
    .dash__nav:has(.dash__nav-item:nth-of-type(3).is-active) { --nav-i: 2; }
    .dash__nav:has(.dash__nav-item:nth-of-type(4).is-active) { --nav-i: 3; }
    .dash__nav:has(.dash__nav-item:nth-of-type(5).is-active) { --nav-i: 4; }
    /* Nothing selected yet — no chip to show. */
    .dash__nav:not(:has(.dash__nav-item.is-active)) .dash__nav-chip { opacity: 0; }
  }
  @media (prefers-reduced-motion: reduce) {
    .dash__nav-chip { transition: none; }
  }

  .dash__main { margin-left: 0; }
  /* Room for the pill, so the last card is never trapped underneath it. */
  .dash__content {
    padding:
      20px
      max(20px, env(safe-area-inset-right, 0px))
      calc(96px + env(safe-area-inset-bottom, 0px))
      max(20px, env(safe-area-inset-left, 0px));
  }
  /* viewport-fit=cover lets content run under the notch in landscape, so the
     topbar has to hold itself off the edges. */
  .dash__topbar {
    padding-top: calc(14px + env(safe-area-inset-top, 0px));
    padding-bottom: var(--space-7);
    padding-left: max(16px, env(safe-area-inset-left, 0px));
    padding-right: max(16px, env(safe-area-inset-right, 0px));
    gap: var(--space-6);
  }
  /* Everything above the bar, painted by the bar. viewport-fit=cover lets the
     page run up under the status bar, and padding-top alone does not close
     that gap — env(safe-area-inset-top) reports 0 in Safari's normal portrait
     chrome, so there is nothing for the padding to add. This slab is anchored
     to the bar's own top edge and extends past the top of the screen, so
     whatever strip is up there is solid rather than showing the page scrolling
     behind the clock and battery. */
  .dash__topbar::before {
    content: '';
    position: absolute;
    left: 0; right: 0;
    bottom: 100%;
    height: 100vh;
    background: var(--paper-2);
  }
  .dash__title { font-size: 1.05rem; }


  /* The chat orb is parked in the same corner the nav pill now occupies.
     Lift it clear of the bar rather than hiding it — but only on the
     dashboard, which is the only page with a bar down there. Unscoped, this
     pushed the orb up the marketing page too. */
  .dash-body .chat-widget {
    bottom: calc(84px + env(safe-area-inset-bottom, 0px));
    right: max(16px, env(safe-area-inset-right, 0px));
  }
}

/* ===================================================================
   DASHBOARD THEMING (account.html) — light / dark / auto.
   The choice is stored in localStorage and resolved to a concrete
   data-theme on <html> before first paint (see the inline script in
   account.html), so there's no flash of the wrong theme on load.
   Scoped to .dash-body on purpose: the marketing site is art-directed
   section by section and is not meant to invert.
=================================================================== */
[data-theme="dark"] .dash-body {
  /* Ink flips to bone, so every rgba(var(--ink-rgb), N) border, divider and
     hover tint in the dashboard inverts with it. */
  --ink-rgb: 226,232,244;
  --paper: #0B0F17;
  --paper-2: #141A26;
  --text-dark: #E8EDF6;
  --text-dark-lo: #97A3BA;
  --blue-soft: rgba(47,111,255,0.22);
  /* --amber-deep is a dark gold meant for light surfaces; on a dark panel the
     bright amber is the readable one. */
  --amber-deep: #FFD166;
  --shadow-soft: 0 30px 70px -30px rgba(0,0,0,0.65), 0 8px 20px -12px rgba(0,0,0,0.5);
  /* Lighter than --paper-2 so the pill still reads as floating above the page.
     A dark page gives the blur less to work with, so this leans on the tint
     and the rim more than the light theme does. */
  --navpill: rgba(38,47,64,0.40);
  --navpill-solid: #232B3A;
  /* Same sweep, pulled down. A dark page has less light to throw at the
     rim, and a bright edge here would read as a drawn outline again. */
  --navpill-lens: conic-gradient(from 0deg at 50% 50%,
    rgba(255,255,255,0.24)   0deg,
    rgba(255,255,255,0.12)  52deg,
    rgba(255,255,255,0.04)  98deg,
    rgba(255,255,255,0.01) 152deg,
    rgba(255,255,255,0.02) 206deg,
    rgba(255,255,255,0.06) 254deg,
    rgba(255,255,255,0.11) 296deg,
    rgba(255,255,255,0.24) 360deg);
  --navpill-sheen: rgba(255,255,255,0.20);
  --navpill-active: rgba(255,255,255,0.19);
  --navpill-ink: rgba(232,237,246,0.70);
}
[data-theme="dark"] .dash-body,
[data-theme="dark"] .dash-body input,
[data-theme="dark"] .dash-body select,
[data-theme="dark"] .dash-body textarea {
  color-scheme: dark;
}

/* --- Settings control in the topbar, beside the profile avatar --- */
/* --- Setup checklist, in the topbar beside settings ------------------------
   A short list of what is still outstanding. It never stores a "done" flag of
   its own — every row reads live account state — so it cannot drift out of
   step with reality, and a row un-ticks itself if the thing behind it is
   later undone. */
.dash__todo { position: relative; flex-shrink: 0; }
.dash__todo-btn {
  position: relative;
  width: 36px; height: 36px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: var(--text-dark-lo);
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.dash__todo-btn svg { width: 18px; height: 18px; }
.dash__todo-btn:hover,
.dash__todo-btn[aria-expanded="true"] {
  background: rgba(var(--ink-rgb),0.06);
  color: var(--text-dark);
}
.dash__todo-badge {
  position: absolute; top: -1px; right: -1px;
  min-width: 17px; height: 17px; padding: 0 4px;
  border-radius: var(--r-pill);
  background: var(--blue); color: #fff;
  font-family: var(--font-display); font-weight: 700; font-size: 0.62rem;
  display: flex; align-items: center; justify-content: center;
  border: 2px solid var(--paper-2);
}
.dash__todo.is-clear .dash__todo-btn { color: #34D399; }

.dash__todo-menu {
  position: absolute; top: calc(100% + 8px); right: 0;
  background: var(--paper-2);
  border: 1px solid rgba(var(--ink-rgb),0.08);
  border-radius: var(--r-sm);
  box-shadow: var(--shadow-soft);
  padding: var(--space-8);
  width: 320px;
  max-width: calc(100vw - 32px);
  z-index: 60;
}
.dash__todo-title { font-family: var(--font-display); font-weight: 700; font-size: var(--fs-13); color: var(--text-dark); }
.dash__todo-sub { font-size: var(--fs-5); color: var(--text-dark-lo); margin-top: var(--space-1); }
.dash__todo-bar {
  height: 4px; border-radius: var(--r-pill);
  background: rgba(var(--ink-rgb),0.08);
  margin: 10px 0 6px;
  overflow: hidden;
}
.dash__todo-bar span {
  display: block; height: 100%; width: 0;
  border-radius: var(--r-pill);
  background: var(--blue);
  transition: width 0.4s var(--ease);
}
.dash__todo-list { display: flex; flex-direction: column; gap: var(--space-1); }
.dash__todo-row {
  display: flex; align-items: flex-start; gap: var(--space-5);
  width: 100%;
  padding: 9px var(--space-4);
  border-radius: var(--r-xs);
  text-align: left;
  transition: background 0.2s var(--ease);
  -webkit-tap-highlight-color: transparent;
}
.dash__todo-row:hover { background: rgba(var(--ink-rgb),0.05); }
.dash__todo-check {
  flex-shrink: 0;
  width: 19px; height: 19px; margin-top: 1px;
  border-radius: 50%;
  border: 1.6px solid rgba(var(--ink-rgb),0.22);
  display: flex; align-items: center; justify-content: center;
  color: transparent;
  transition: background 0.25s var(--ease), border-color 0.25s var(--ease), color 0.25s var(--ease);
}
.dash__todo-check svg { width: 11px; height: 11px; }
.is-done .dash__todo-check {
  background: #34D399;
  border-color: #34D399;
  color: #fff;
}
.dash__todo-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.dash__todo-label { font-size: var(--fs-9); font-weight: 600; color: var(--text-dark); }
.dash__todo-hint { font-size: 0.75rem; color: var(--text-dark-lo); line-height: 1.4; }
.is-done .dash__todo-label { color: var(--text-dark-lo); text-decoration: line-through; }
.is-done .dash__todo-hint { display: none; }
.dash__todo-go { margin-left: auto; color: var(--text-dark-lo); font-size: 1.1rem; line-height: 1; align-self: center; }
.is-done .dash__todo-go { opacity: 0.35; }

/* Anchored to a button near the right edge, a 320px panel hangs off the left
   of a phone screen — and six rows of it hang off the bottom. Dropping the
   wrapper out of the positioning chain hands the panel to the topbar, which
   spans the full width: left/right then pin it to the screen while top still
   means "below the bar", with no hard-coded bar height anywhere.
   This block has to sit after the rules above, not in the earlier mobile
   section — same specificity, and later wins. */
@media (max-width: 900px) {
  .dash__todo { position: static; }
  .dash__todo-menu {
    top: calc(100% + 8px);
    left: max(12px, env(safe-area-inset-left, 0px));
    right: max(12px, env(safe-area-inset-right, 0px));
    width: auto;
    max-width: none;
    max-height: calc(100vh - 160px);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }
}

.dash__settings { position: relative; flex-shrink: 0; }
.dash__settings-btn {
  width: 36px; height: 36px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: var(--text-dark-lo);
  border: 1px solid rgba(var(--ink-rgb),0.12);
  background: transparent;
  cursor: pointer;
  transition: background 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.dash__settings-btn svg { width: 18px; height: 18px; }
.dash__settings-btn:hover,
.dash__settings-btn[aria-expanded="true"] {
  background: rgba(var(--ink-rgb),0.05);
  border-color: rgba(var(--ink-rgb),0.22);
  color: var(--text-dark);
}
.dash__settings-menu {
  position: absolute; top: calc(100% + 8px); right: 0;
  background: var(--paper-2);
  border: 1px solid rgba(var(--ink-rgb),0.08);
  border-radius: var(--r-sm);
  box-shadow: var(--shadow-soft);
  padding: var(--space-7);
  min-width: 232px;
  z-index: 60;
}
.dash__settings-label {
  font-family: var(--font-display);
  font-size: var(--fs-1); letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--text-dark-lo);
  padding: 0 4px 10px;
}
.dash__theme-options { display: flex; flex-direction: column; gap: var(--space-1); }
.dash__theme-option {
  display: flex; align-items: center; gap: var(--space-5);
  width: 100%;
  padding: var(--space-5) var(--space-5);
  border-radius: var(--r-xs);
  font-family: var(--font-body); font-size: var(--fs-10); font-weight: 500;
  color: var(--text-dark);
  text-align: left;
  cursor: pointer;
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.dash__theme-option svg { width: 17px; height: 17px; flex-shrink: 0; }
.dash__theme-option:hover { background: rgba(var(--ink-rgb),0.05); }
.dash__theme-option.is-active { background: var(--blue-soft); color: var(--blue); }
.dash__theme-check { margin-left: auto; opacity: 0; flex-shrink: 0; }
.dash__theme-option.is-active .dash__theme-check { opacity: 1; }
.dash__theme-note {
  font-size: 0.76rem; color: var(--text-dark-lo);
  padding: 10px 4px 0; margin-top: var(--space-4);
  border-top: 1px solid rgba(var(--ink-rgb),0.08);
}

/* ===================================================================
   SECTION SEAMS — sections melt into each other instead of meeting at
   a hard line. Page order and fill:
     decay(white) → pipeline(tint) → showcase(white) → alwayson(tint)
     → pillars(tint) → testimonials(white) → integrations(tint)
     → faq(white) → pricing(white) → contact(white) → cosmos(dark)
     → footer(dark)
   A tinted section resolves to --paper-2 at any edge that touches a
   white section, so that seam becomes white-on-white and disappears.
   Edges where two tinted sections meet (alwayson → pillars) stay flat,
   so the pair reads as one continuous field rather than two bands.
=================================================================== */
.pipeline {
  background: linear-gradient(180deg,
    var(--paper-2) 0%, var(--paper) 15%,
    var(--paper) 85%, var(--paper-2) 100%);
}
.alwayson {
  /* pillars follows and is also tinted — hold the tint at the bottom */
  background: linear-gradient(180deg, var(--paper-2) 0%, var(--paper) 18%, var(--paper) 100%);
}
.pillars {
  /* alwayson precedes and is also tinted — hold the tint at the top */
  background: linear-gradient(180deg, var(--paper) 0%, var(--paper) 82%, var(--paper-2) 100%);
}
.integrations {
  background: linear-gradient(180deg,
    var(--paper-2) 0%, var(--paper) 15%,
    var(--paper) 85%, var(--paper-2) 100%);
}

/* contact (white) into cosmos (dark) is left as a clean hard edge on
   purpose — the starfield reads better meeting the light head-on than
   fading up out of it. */

/* cosmos (#060B18) into the footer's navy — close, but still a seam.
   Done as a background layer rather than an ::after overlay: the footer's
   children are position:relative with no z-index, so a trailing pseudo-element
   would paint over them. A background can't. */
.footer {
  background:
    /* Keeps the seam blender: fades from the cosmos section's #060B18 into
       the footer over the first 180px, so that boundary stays smooth. Ends
       at a transparent version of the footer's OWN colour, so the fade does
       not drift through a third hue on the way. */
    linear-gradient(180deg, #060B18 0%, rgba(10,16,32,0) 180px),
    /* Flat deep navy, replacing the old 165deg gradient whose lighter
       #10275C end made the top of the footer read as its own blue band. */
    linear-gradient(#0A1020, #0A1020);
}

/* ===================================================================
   COST OF MISSED CALLS (#roi) — interactive, and the last thing a
   visitor sees before the price. Tinted section, so it carries the
   same edge fades as the other --paper sections above.
=================================================================== */
.roi {
  position: relative;
  padding: 150px var(--space-15);
  background: linear-gradient(180deg,
    var(--paper-2) 0%, var(--paper) 14%,
    var(--paper) 86%, var(--paper-2) 100%);
}
.roi__inner { position: relative; max-width: 1080px; margin: 0 auto; }
.roi__head { text-align: center; max-width: 660px; margin: 0 auto 56px; }
.roi__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2rem, 4.2vw, 3.1rem);
  line-height: 1.08;
  letter-spacing: -0.02em;
  color: var(--text-dark);
  margin: 0 0 18px;
}
.roi__lede { color: var(--text-dark-lo); font-size: var(--fs-14); line-height: 1.6; }

.roi__panel {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  background: var(--paper-2);
  border: 1px solid rgba(var(--ink-rgb),0.08);
  border-radius: 26px;
  box-shadow: var(--shadow-soft);
  overflow: hidden;
}
.roi__controls { padding: 42px var(--space-16); display: flex; flex-direction: column; gap: 34px; justify-content: center; }
.roi__control-top {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-8);
  margin-bottom: var(--space-7);
}
.roi__control-top label { font-size: var(--fs-11); color: var(--text-dark-lo); }
.roi__control-val {
  font-family: var(--font-display); font-weight: 700;
  font-size: 1.15rem; color: var(--text-dark);
  font-variant-numeric: tabular-nums;
}
.roi__scale {
  display: flex; justify-content: space-between;
  font-size: var(--fs-3); color: var(--text-dark-lo); opacity: 0.7; margin-top: var(--space-4);
  font-family: var(--font-display); letter-spacing: 0.04em;
}

/* Range inputs are styled per-engine; the track is painted with a
   gradient driven by --pct so the filled portion tracks the thumb. */
.roi__control input[type="range"] {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 6px; border-radius: var(--r-pill); outline: none; cursor: pointer;
  background: linear-gradient(90deg, var(--blue) 0%, var(--blue) var(--pct, 20%),
              rgba(var(--ink-rgb),0.10) var(--pct, 20%), rgba(var(--ink-rgb),0.10) 100%);
}
.roi__control input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--paper-2);
  border: 2px solid var(--blue);
  box-shadow: 0 4px 12px -2px rgba(47,111,255,0.45);
  cursor: grab;
  transition: transform 0.18s var(--ease-spring), box-shadow 0.25s var(--ease);
}
.roi__control input[type="range"]::-webkit-slider-thumb:hover { transform: scale(1.14); }
.roi__control input[type="range"]:active::-webkit-slider-thumb { transform: scale(1.05); cursor: grabbing; }
.roi__control input[type="range"]::-moz-range-thumb {
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--paper-2); border: 2px solid var(--blue);
  box-shadow: 0 4px 12px -2px rgba(47,111,255,0.45); cursor: grab;
}
.roi__control input[type="range"]:focus-visible { outline: 2px solid var(--blue); outline-offset: 6px; }

.roi__result {
  padding: 42px var(--space-16);
  background: linear-gradient(165deg, #10275C, #060E24);
  color: var(--text-hi);
  display: flex; flex-direction: column; justify-content: center;
}
.roi__result-label {
  font-family: var(--font-display); font-size: var(--fs-2); font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--amber);
  margin-bottom: var(--space-6);
}
.roi__result-figure {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(2.6rem, 6vw, 3.9rem); line-height: 1;
  color: #fff; font-variant-numeric: tabular-nums;
  margin-bottom: var(--space-5);
}
.roi__result-sub { font-size: var(--fs-11); color: rgba(245,241,234,0.62); margin-bottom: var(--space-14); }

.roi__bars { display: flex; flex-direction: column; gap: var(--space-7); margin-bottom: var(--space-13); }
.roi__bar-row { display: grid; grid-template-columns: 118px 1fr 72px; align-items: center; gap: var(--space-6); }
.roi__bar-name { font-size: 0.76rem; color: rgba(245,241,234,0.6); }
.roi__bar-track { height: 9px; border-radius: var(--r-pill); background: rgba(255,255,255,0.09); overflow: hidden; }
.roi__bar-fill {
  height: 100%; border-radius: var(--r-pill); width: 0%;
  transition: width 0.75s var(--ease);
}
.roi__bar-fill--loss { background: linear-gradient(90deg, #FFD166, #FF8A5B); }
.roi__bar-fill--cost { background: linear-gradient(90deg, var(--blue), var(--blue-bright)); }
.roi__bar-fig {
  font-family: var(--font-display); font-size: var(--fs-6); font-weight: 700;
  text-align: right; color: rgba(245,241,234,0.9); font-variant-numeric: tabular-nums;
}
.roi__verdict {
  font-size: var(--fs-12); line-height: 1.55; color: var(--amber);
  min-height: 2.9em; margin-bottom: var(--space-12);
}
.roi__cta { align-self: flex-start; }
.roi__disclaimer {
  text-align: center; font-size: var(--fs-5); color: var(--text-dark-lo);
  opacity: 0.75; max-width: 620px; margin: 26px auto 0; line-height: 1.5;
}
@media (max-width: 860px) {
  .roi { padding: 110px var(--space-10); }
  .roi__panel { grid-template-columns: 1fr; }
  .roi__controls, .roi__result { padding: 34px var(--space-13); }
  .roi__bar-row { grid-template-columns: 96px 1fr 64px; }
}

/* ===================================================================
   ASSURANCE STRIP — the four things that make it safe to try. Every
   line here restates a commitment already made in the pricing block
   or the FAQ; nothing new is promised.
=================================================================== */
.assurance { background: var(--paper-3); padding: 30px var(--space-15) 120px; }
.assurance__inner {
  max-width: var(--container); margin: 0 auto;
  display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-14);
}
.assurance__item {
  padding: var(--space-14) var(--space-12);
  border: 1px solid rgba(var(--ink-rgb),0.08);
  border-radius: var(--r-md);
  background: var(--paper-2);
  transition: transform 0.45s var(--ease), box-shadow 0.45s var(--ease), border-color 0.45s var(--ease);
}
.assurance__item:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-soft);
  border-color: rgba(47,111,255,0.28);
}
.assurance__item svg { width: 26px; height: 26px; color: var(--blue); margin-bottom: var(--space-8); }
.assurance__title {
  font-family: var(--font-display); font-weight: 700; font-size: 0.98rem;
  color: var(--text-dark); margin-bottom: var(--space-4);
}
.assurance__copy { font-size: var(--fs-10); line-height: 1.55; color: var(--text-dark-lo); }
@media (max-width: 900px) {
  .assurance__inner { grid-template-columns: repeat(2, 1fr); gap: var(--space-9); }
}
@media (max-width: 540px) {
  .assurance { padding: var(--space-10) var(--space-10) 90px; }
  .assurance__inner { grid-template-columns: 1fr; }
}

/* ===================================================================
   SMS COMPOSER (Messages panel) — themed with the dashboard tokens, so
   it inverts with the light/dark switcher like everything else.
=================================================================== */
/* --- Conversations -------------------------------------------------------
   The thread list and the open conversation sit side by side on a desktop and
   stack on a phone, where opening a thread takes over the screen. */
.sms__tabs { display: flex; gap: var(--space-4); margin-bottom: var(--space-10); }
.sms__tab {
  padding: 9px var(--space-8);
  border-radius: var(--r-pill);
  border: 1px solid rgba(var(--ink-rgb),0.12);
  background: rgba(var(--ink-rgb),0.03);
  font-family: var(--font-body); font-size: var(--fs-8); font-weight: 600;
  color: var(--text-dark-lo);
  display: flex; align-items: center; gap: 7px;
  transition: background 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.sms__tab.is-active { background: var(--blue-soft); border-color: transparent; color: var(--blue); }
.sms__tab-badge {
  min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: var(--r-pill);
  background: var(--blue); color: #fff;
  font-size: var(--fs-1); font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}

.sms-threads { display: grid; grid-template-columns: minmax(0,340px) minmax(0,1fr); gap: var(--space-10); align-items: start; }
.sms-threads__list { display: flex; flex-direction: column; gap: var(--space-3); max-height: 620px; overflow-y: auto; }
.sms-thread {
  display: flex; flex-direction: column; gap: var(--space-2);
  width: 100%;
  padding: var(--space-6) var(--space-7);
  border-radius: 12px;
  border: 1px solid rgba(var(--ink-rgb),0.08);
  background: var(--paper-2);
  text-align: left;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease);
}
.sms-thread:hover { border-color: rgba(var(--ink-rgb),0.2); }
/* A thread the agent has handed over is the only one with someone waiting. */
.sms-thread.needs-owner { border-color: rgba(255,209,102,0.55); background: rgba(255,209,102,0.07); }
.sms-thread__top { display: flex; justify-content: space-between; gap: var(--space-5); align-items: baseline; }
.sms-thread__who { font-weight: 600; font-size: var(--fs-10); color: var(--text-dark); }
.sms-thread__when { font-size: var(--fs-4); color: var(--text-dark-lo); flex-shrink: 0; }
.sms-thread__preview {
  font-size: var(--fs-6); color: var(--text-dark-lo);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

.sms-threads__convo {
  border: 1px solid rgba(var(--ink-rgb),0.08);
  border-radius: 16px;
  background: var(--paper-2);
  padding: var(--space-8) var(--space-9);
  display: flex; flex-direction: column; gap: var(--space-6);
}
.sms-convo__head { display: flex; align-items: center; gap: var(--space-6); flex-wrap: wrap; }
.sms-convo__back { display: none; font-size: var(--fs-6); color: var(--blue); }
.sms-convo__who { font-family: var(--font-display); font-weight: 700; font-size: 1rem; color: var(--text-dark); }
.sms-convo__flag {
  font-size: var(--fs-3); font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--amber-deep);
  padding: var(--space-2) var(--space-5); border-radius: var(--r-pill);
  background: rgba(255,209,102,0.16);
}
.sms-convo__log { display: flex; flex-direction: column; gap: var(--space-5); max-height: 420px; overflow-y: auto; padding-right: var(--space-2); }
.sms-msg { display: flex; flex-direction: column; gap: var(--space-1); max-width: 82%; }
/* Them on the left, us on the right — the arrangement every texting app uses,
   so nobody has to read a label to know who said what. */
.sms-msg--contact { align-self: flex-start; }
.sms-msg--agent, .sms-msg--owner { align-self: flex-end; text-align: right; }
.sms-msg__who { font-size: var(--fs-2); font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-dark-lo); }
.sms-msg__body {
  font-size: var(--fs-9); line-height: 1.45; color: var(--text-dark);
  padding: 9px var(--space-6); border-radius: 12px;
  background: rgba(var(--ink-rgb),0.05);
}
.sms-msg--agent .sms-msg__body { background: var(--blue-soft); color: var(--text-dark); }
.sms-msg--owner .sms-msg__body { background: rgba(52,211,153,0.16); }
.sms-msg__when { font-size: var(--fs-2); color: var(--text-dark-lo); }
.sms-convo__reply { display: flex; gap: var(--space-5); align-items: flex-end; }
.sms-convo__reply textarea { flex: 1; min-width: 0; }
.sms-convo__note { font-size: var(--fs-5); color: var(--text-dark-lo); min-height: 16px; }
.sms-convo__resume { font-size: var(--fs-6); color: var(--blue); align-self: flex-start; }

@media (max-width: 860px) {
  /* One at a time on a phone: the list, or the conversation. */
  .sms-threads { grid-template-columns: 1fr; }
  .sms-threads__list.is-secondary { display: none; }
  .sms-convo__back { display: block; }
}

.sms { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-12); align-items: start; }
.sms__compose, .sms__people {
  background: var(--paper-2);
  border: 1px solid rgba(var(--ink-rgb),0.08);
  border-radius: 16px;
  padding: var(--space-11);
}
.sms__hint { font-size: var(--fs-8); color: var(--text-dark-lo); margin: 4px 0 14px; line-height: 1.5; }
.sms textarea {
  width: 100%;
  border: 1px solid rgba(var(--ink-rgb),0.14);
  border-radius: 12px;
  background: var(--paper-2);
  color: var(--text-dark);
  font-family: var(--font-body);
  font-size: var(--fs-13);
  line-height: 1.5;
  padding: var(--space-7);
  resize: vertical;
}
.sms textarea:focus { outline: none; border-color: var(--blue); box-shadow: var(--focus-ring); }
.sms__meter {
  display: flex; justify-content: space-between;
  font-size: 0.76rem; color: var(--text-dark-lo);
  margin-top: var(--space-4); font-variant-numeric: tabular-nums;
}
.sms__optout {
  font-size: var(--fs-5); color: var(--text-dark-lo);
  margin-top: var(--space-6); padding-top: var(--space-6);
  border-top: 1px solid rgba(var(--ink-rgb),0.08);
  line-height: 1.5;
}
.sms__people-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-6); margin-bottom: var(--space-6); }
.sms__selectall { display: flex; align-items: center; gap: var(--space-4); font-size: var(--fs-7); color: var(--text-dark-lo); cursor: pointer; }
.sms__search {
  width: 100%;
  border: 1px solid rgba(var(--ink-rgb),0.14);
  border-radius: var(--r-xs);
  background: var(--paper-2);
  color: var(--text-dark);
  padding: var(--space-5) var(--space-6);
  font-size: var(--fs-10);
  margin-bottom: var(--space-6);
}
.sms__search:focus { outline: none; border-color: var(--blue); box-shadow: var(--focus-ring); }
.sms__list { max-height: 320px; overflow-y: auto; display: flex; flex-direction: column; gap: var(--space-1); }
.sms__row {
  display: flex; align-items: center; gap: var(--space-6);
  padding: var(--space-5) var(--space-5);
  border-radius: var(--r-xs);
  cursor: pointer;
  transition: background 0.2s var(--ease);
}
.sms__row:hover { background: rgba(var(--ink-rgb),0.04); }
.sms__row-info { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.sms__row-name { font-size: var(--fs-11); color: var(--text-dark); }
.sms__row-phone { font-size: var(--fs-5); color: var(--text-dark-lo); font-variant-numeric: tabular-nums; }
.sms__empty { font-size: var(--fs-9); color: var(--text-dark-lo); padding: var(--space-9) var(--space-2); line-height: 1.55; }
.sms__send { grid-column: 1 / -1; display: flex; align-items: center; gap: var(--space-8); flex-wrap: wrap; }
.sms__summary { font-size: var(--fs-10); color: var(--text-dark-lo); }
.sms__status { font-size: var(--fs-9); color: var(--blue); }
/* The confirm step is a colour change as well as a label change — the button
   changing meaning under the cursor should be impossible to miss. */
#sms-send-btn.is-confirming { background: var(--amber-deep); color: #fff; }
.sms__results { grid-column: 1 / -1; display: flex; flex-direction: column; gap: var(--space-2); }
.sms__result { font-size: var(--fs-6); }
.sms__result--failed { color: #C2410C; }
@media (max-width: 860px) {
  .sms { grid-template-columns: 1fr; }
}

/* ===================================================================
   VOICE PICKER — avatars, gender split, Business-tier locks
=================================================================== */
.voice-filter { display: flex; flex-wrap: wrap; gap: var(--space-4); margin-bottom: var(--space-9); }
.voice-filter__btn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: var(--space-4) var(--space-7); border-radius: var(--r-pill);
  border: 1px solid rgba(var(--ink-rgb),0.12);
  background: transparent; color: var(--text-dark-lo);
  font-family: var(--font-body); font-size: 0.84rem; font-weight: 500;
  cursor: pointer; transition: background 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.voice-filter__btn span {
  font-size: var(--fs-4); padding: 1px 7px; border-radius: var(--r-pill);
  background: rgba(var(--ink-rgb),0.07); font-variant-numeric: tabular-nums;
}
.voice-filter__btn:hover { border-color: rgba(var(--ink-rgb),0.26); color: var(--text-dark); }
.voice-filter__btn.is-active { background: var(--blue); border-color: var(--blue); color: #fff; }
.voice-filter__btn.is-active span { background: rgba(255,255,255,0.22); }
.voice-filter__btn--biz.is-active { background: var(--amber-deep); border-color: var(--amber-deep); }

.voice-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(255px, 1fr));
  gap: var(--space-6);
  max-height: 520px;
  overflow-y: auto;
  padding-right: var(--space-2);
}
.voice-card {
  display: flex; align-items: center; gap: 13px;
  padding: 13px var(--space-7);
  border: 1px solid rgba(var(--ink-rgb),0.10);
  border-radius: var(--r-sm);
  background: var(--paper-2);
  cursor: pointer;
  transition: border-color 0.2s var(--ease), box-shadow 0.25s var(--ease), transform 0.25s var(--ease);
}
.voice-card:hover { border-color: rgba(47,111,255,0.4); transform: translateY(-2px); box-shadow: var(--shadow-soft); }
.voice-card.is-selected { border-color: var(--blue); box-shadow: 0 0 0 2px rgba(47,111,255,0.18); }
.voice-card__body { flex: 1; min-width: 0; }
.voice-card__name {
  font-family: var(--font-display); font-weight: 700; font-size: 0.94rem;
  color: var(--text-dark); display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
}
.voice-card__rec {
  font-family: var(--font-body); font-weight: 600; font-size: 0.6rem;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--blue); background: var(--blue-soft);
  padding: var(--space-1) 7px; border-radius: var(--r-pill);
}
.voice-card__tags { display: flex; gap: var(--space-3); margin-top: 7px; flex-wrap: wrap; }
.voice-tag {
  font-size: var(--fs-1); font-weight: 600; letter-spacing: 0.04em;
  padding: var(--space-1) var(--space-4); border-radius: var(--r-pill);
  border: 1px solid rgba(var(--ink-rgb),0.12);
  color: var(--text-dark-lo);
}
.voice-tag--female { color: #B0468A; border-color: rgba(176,70,138,0.28); background: rgba(176,70,138,0.07); }
.voice-tag--male { color: #2F6FFF; border-color: rgba(47,111,255,0.28); background: rgba(47,111,255,0.07); }
.voice-tag--biz { color: var(--amber-deep); border-color: rgba(154,117,0,0.3); background: rgba(255,209,102,0.15); }

/* Avatar: one fixed color per gender (not a photograph of a person who does
   not exist), so the male/female split reads instantly across dozens of
   cards instead of every voice getting its own arbitrary hue. HSL, not
   fixed hex stops, so a Business-tier voice's locked/unlocked state is
   just a lightness shift of that SAME hue — darker while this viewer can't
   use it yet (.is-business), lighter with a glow once they can
   (.is-business.is-unlocked) — rather than switching to a different color
   or (the old .is-locked behavior) desaturating to gray, which would have
   fought the "same color, different finish" point of this entirely. */
.voice-av {
  width: 46px; height: 46px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: flex-end; justify-content: center;
  overflow: hidden;
  --av-h: 220; --av-s: 12%; --av-hi: 62%; --av-lo: 38%; /* neutral default, for gender: 'other' */
  background: linear-gradient(150deg, hsl(var(--av-h) var(--av-s) var(--av-hi)), hsl(var(--av-h) var(--av-s) var(--av-lo)));
  color: rgba(255,255,255,0.94);
}
.voice-av svg { width: 100%; height: 78%; display: block; }
.voice-av--male { --av-h: 221; --av-s: 100%; --av-hi: 68%; --av-lo: 46%; }
.voice-av--female { --av-h: 321; --av-s: 50%; --av-hi: 64%; --av-lo: 43%; }
.voice-av.is-business { --av-hi: 46%; --av-lo: 28%; }
.voice-av.is-business.is-unlocked {
  --av-hi: 76%; --av-lo: 56%;
  box-shadow: 0 0 12px 2px hsl(var(--av-h) var(--av-s) 60% / 0.6);
}

/* Locked = visibly out of reach, but still previewable. The avatar itself
   signals locked/unlocked via color+glow (above), so it's exempted from
   the rest of the card's dimming rather than doubling up on it. */
.voice-card.is-locked { opacity: 0.62; }
.voice-card.is-locked:hover { border-color: rgba(154,117,0,0.45); transform: none; box-shadow: none; }
.voice-card.is-locked .voice-av { opacity: 1; }
.voice-card.is-shaking { animation: voice-shake 0.45s ease; }
@keyframes voice-shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-5px); }
  40% { transform: translateX(5px); }
  60% { transform: translateX(-3px); }
  80% { transform: translateX(3px); }
}
.voice-card__play {
  position: relative;
  width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0;
  border: 1px solid rgba(var(--ink-rgb),0.16);
  background: transparent; color: var(--text-dark-lo);
  font-size: var(--fs-3); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.voice-card__play:hover:not(:disabled) { background: var(--blue); border-color: var(--blue); color: #fff; }
.voice-card__play.is-playing { background: var(--blue); border-color: var(--blue); color: #fff; }
.voice-card__play:disabled { opacity: 0.35; cursor: default; }
.voice-card__play::before {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 44px; height: 44px; transform: translate(-50%, -50%);
}
.voice-upgrade-note {
  margin-top: var(--space-7); font-size: var(--fs-9); color: var(--amber-deep);
  background: rgba(255,209,102,0.12);
  border: 1px solid rgba(154,117,0,0.22);
  border-radius: var(--r-xs); padding: var(--space-5) var(--space-7);
}

/* ===================================================================
   BRIDGE — forwarding walkthrough in the Setup panel
=================================================================== */
.setup__number-copy {
  margin-top: var(--space-3);
  padding: 7px var(--space-7); border-radius: var(--r-pill);
  border: 1px solid rgba(var(--ink-rgb),0.16);
  background: transparent; color: var(--text-dark-lo);
  font-family: var(--font-body); font-size: var(--fs-5); cursor: pointer;
  transition: background 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.setup__number-copy:hover { background: var(--blue); border-color: var(--blue); color: #fff; }

.bridge {
  margin-top: var(--space-11); padding-top: var(--space-11);
  border-top: 1px solid rgba(var(--ink-rgb),0.08);
}
.bridge__open { margin-top: var(--space-8); }

/* Overlay that holds the forwarding how-to steps + the works-check. */
.bridge-modal {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center;
  padding: var(--space-8);
}
.bridge-modal__backdrop { position: absolute; inset: 0; background: rgba(10,14,22,0.55); backdrop-filter: blur(2px); }
.bridge-modal__panel {
  position: relative; z-index: 1;
  width: min(520px, 100%); max-height: 90vh; overflow-y: auto;
  background: var(--paper); color: var(--text-dark);
  border: 1px solid rgba(var(--ink-rgb),0.10); border-radius: var(--r-lg);
  box-shadow: 0 30px 80px rgba(10,14,22,0.35);
  padding: var(--space-13);
  animation: bridge-modal-in 0.24s var(--ease) both;
}
@keyframes bridge-modal-in { from { opacity: 0; transform: translateY(12px) scale(0.98); } to { opacity: 1; transform: none; } }
.bridge-modal__close {
  position: absolute; top: var(--space-7); right: var(--space-7);
  width: 32px; height: 32px; border-radius: 50%; border: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.3rem; line-height: 1; color: var(--text-dark-lo);
  background: rgba(var(--ink-rgb),0.06);
}
.bridge-modal__close:hover { background: rgba(var(--ink-rgb),0.12); color: var(--text-dark); }
.bridge-modal__panel .bridge__steps { margin-top: var(--space-10); }
.bridge-modal__panel .setup__verify { margin-top: var(--space-11); }

/* ---- calendar: what sits behind an appointment ---- */
.cal-detail__back { background: none; border: 0; padding: 0; font-family: inherit; font-size: var(--fs-7); font-weight: 600; color: var(--blue); cursor: pointer; margin-bottom: var(--space-8); }
.cal-detail__source { font-size: var(--fs-2); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--dash-booked); margin-bottom: var(--space-3); }
.cal-detail__source--own { color: var(--text-dark-lo); }
/* Right padding keeps a long name clear of the close button. */
.cal-detail__title { font-family: var(--font-display); font-weight: 700; font-size: 1.25rem; line-height: 1.25; color: var(--text-dark); padding-right: 40px; overflow-wrap: anywhere; }
.cal-detail__flag { display: inline-block; vertical-align: middle; font-family: var(--font-body); font-size: var(--fs-2); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: #B42318; background: rgba(217,45,32,0.10); border: 1px solid rgba(217,45,32,0.30); border-radius: var(--r-pill); padding: 2px 8px; }
.cal-detail__when { font-size: var(--fs-10); color: var(--text-dark-lo); margin-top: var(--space-3); }
.cal-detail__rows { margin: var(--space-11) 0 0; display: grid; gap: var(--space-5); }
.cal-detail__row { display: grid; grid-template-columns: 88px 1fr; gap: var(--space-6); font-size: var(--fs-10); }
.cal-detail__row dt { color: var(--text-dark-lo); }
.cal-detail__row dd { margin: 0; color: var(--text-dark); overflow-wrap: anywhere; }
.cal-detail__row a { color: var(--blue); font-weight: 600; text-decoration: none; }
.cal-detail__row a:hover { text-decoration: underline; }
.cal-detail__notes { margin-top: var(--space-11); padding: var(--space-8); border-radius: var(--r-md); background: var(--paper-2); }
.cal-detail__label { font-size: var(--fs-2); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-dark-lo); margin-bottom: var(--space-3); }
/* pre-wrap: the caller's reason keeps whatever line breaks it arrived with. */
.cal-detail__notes-text { font-size: var(--fs-10); line-height: 1.55; color: var(--text-dark); white-space: pre-wrap; overflow-wrap: anywhere; }
.cal-detail__open { display: inline-block; margin-top: var(--space-11); font-size: var(--fs-8); font-weight: 600; color: var(--blue); text-decoration: none; }
.cal-detail__open:hover { text-decoration: underline; }
.cal-detail__list { list-style: none; margin: var(--space-10) 0 0; padding: 0; display: grid; gap: var(--space-3); }
.cal-detail__item { width: 100%; display: flex; align-items: center; gap: var(--space-6); text-align: left; font-family: inherit; font-size: var(--fs-10); color: var(--text-dark); background: var(--paper-2); border: 1px solid rgba(var(--ink-rgb),0.08); border-radius: var(--r-md); padding: var(--space-6) var(--space-8); cursor: pointer; }
.cal-detail__item:hover { border-color: rgba(47,111,255,0.4); }
.cal-detail__item:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }
.cal-detail__item-time { flex: none; min-width: 64px; color: var(--text-dark-lo); font-variant-numeric: tabular-nums; }
.cal-detail__item-name { flex: 1; min-width: 0; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-detail__item-tag { flex: none; font-size: var(--fs-2); font-weight: 700; color: #0F7B4F; background: rgba(16,150,95,0.12); border-radius: var(--r-pill); padding: 2px 8px; }

.bridge__title { font-family: var(--font-display); font-weight: 700; font-size: 1rem; color: var(--text-dark); margin-bottom: var(--space-3); }
.bridge__lede { font-size: var(--fs-10); color: var(--text-dark-lo); line-height: 1.55; margin-bottom: var(--space-8); }
.bridge__choice { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-5); margin-bottom: var(--space-10); }
.bridge__opt {
  text-align: left; padding: 13px 15px; border-radius: 12px;
  border: 1px solid rgba(var(--ink-rgb),0.12);
  background: transparent; cursor: pointer;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease);
}
.bridge__opt:hover { border-color: rgba(47,111,255,0.4); }
.bridge__opt.is-active { border-color: var(--blue); background: var(--blue-soft); }
.bridge__opt-name { display: block; font-weight: 600; font-size: var(--fs-10); color: var(--text-dark); margin-bottom: 3px; }
.bridge__opt-sub { display: block; font-size: var(--fs-5); color: var(--text-dark-lo); line-height: 1.45; }
.bridge__steps { list-style: none; display: flex; flex-direction: column; gap: var(--space-7); margin: 0 0 16px; padding: 0; }
.bridge__steps li { display: flex; gap: 13px; align-items: flex-start; }
.bridge__step-n {
  width: 25px; height: 25px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--blue-soft); color: var(--blue);
  font-family: var(--font-display); font-weight: 700; font-size: 0.76rem;
}
.bridge__step-title { font-size: var(--fs-11); color: var(--text-dark); margin-bottom: var(--space-1); }
.bridge__step-title code {
  background: rgba(var(--ink-rgb),0.07); padding: 1px var(--space-3); border-radius: 5px;
  font-size: 0.92em; color: var(--blue);
}
.bridge__step-sub { font-size: var(--fs-6); color: var(--text-dark-lo); line-height: 1.5; }
.bridge__carrier-pick { display: flex; flex-direction: column; gap: 6px; margin: 2px 0 18px; }
.bridge__carrier-pick > span { font-size: var(--fs-7); color: var(--text-dark-lo); font-weight: 600; }
.bridge__carrier-pick select {
  padding: 10px 12px; border-radius: 10px; border: 1px solid rgba(var(--ink-rgb),0.2);
  background: var(--paper); color: var(--text-dark); font-size: var(--fs-11); cursor: pointer;
}
.bridge__carrier-pick select:focus { outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px rgba(47,111,255,0.18); }
.bridge__dial { margin: 4px 0 6px; }
.bridge__dial code {
  font-size: 1.15rem; font-weight: 700; letter-spacing: 0.02em; color: var(--blue);
  background: var(--blue-soft); padding: 7px 13px; border-radius: 8px; display: inline-block;
  font-family: var(--font-mono, monospace); word-break: break-all;
}
.bridge__note {
  font-size: 0.83rem; line-height: 1.55; color: var(--amber-deep);
  background: rgba(255,209,102,0.12);
  border: 1px solid rgba(154,117,0,0.2);
  border-radius: var(--r-xs); padding: 11px var(--space-7); margin-bottom: var(--space-6);
}
.bridge__off, .bridge__carrier { font-size: var(--fs-6); color: var(--text-dark-lo); line-height: 1.55; margin-bottom: var(--space-3); }
.bridge__off code, .bridge__carrier code {
  background: rgba(var(--ink-rgb),0.07); padding: 1px 5px; border-radius: 4px; font-size: 0.92em;
}
@media (max-width: 620px) { .bridge__choice { grid-template-columns: 1fr; } }

/* ===================================================================
   NUMBER LIFECYCLE — swap, bring-your-own, SIP, release.
   The backends for these are not built yet; each option explains what
   it does and routes to us, rather than presenting a dead control.
=================================================================== */
.numline { margin-top: var(--space-11); margin-bottom: var(--space-11); padding-top: var(--space-11); border-top: 1px solid rgba(var(--ink-rgb),0.08); }
.numline__title { font-family: var(--font-display); font-weight: 700; font-size: 1rem; color: var(--text-dark); margin-bottom: var(--space-3); }
.numline__lede { font-size: var(--fs-10); color: var(--text-dark-lo); line-height: 1.55; margin-bottom: var(--space-8); }
.numline__actions { display: flex; flex-wrap: wrap; gap: var(--space-5); }
.numline__btn { font-size: var(--fs-7); padding: var(--space-5) var(--space-8); }
.numline__btn.is-active { border-color: var(--blue); color: var(--blue); }
.numline__btn--danger { border-color: rgba(194,65,12,0.3); color: #C2410C; }
.numline__btn--danger:hover { border-color: #C2410C; color: #C2410C; }
.numline__detail {
  margin-top: var(--space-7); padding: 15px 17px;
  border: 1px solid rgba(var(--ink-rgb),0.10);
  border-radius: 12px;
  background: rgba(var(--ink-rgb),0.03);
}
.numline__detail-title { font-weight: 600; font-size: var(--fs-11); color: var(--text-dark); margin-bottom: var(--space-3); }
.numline__detail-body { font-size: var(--fs-8); color: var(--text-dark-lo); line-height: 1.6; margin-bottom: var(--space-6); }
.numline__detail-soon {
  display: inline-block; font-size: var(--fs-2); font-weight: 600;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--amber-deep); background: rgba(255,209,102,0.16);
  border: 1px solid rgba(154,117,0,0.22);
  padding: 3px 9px; border-radius: var(--r-pill); margin-bottom: var(--space-5);
}

/* ===================================================================
   MOBILE FORM CONTROLS
   iOS Safari zooms the entire page whenever a focused input renders
   below 16px. The layout jumps, the field you tapped slides out from
   under your thumb, and the keyboard covers what is left — which reads
   as "the text boxes don't work" rather than as a zoom.

   Every control is therefore pinned to 16px at the widths where that
   behaviour applies. Desktop keeps its finer sizing. 16px is the exact
   threshold, so this cannot be nudged down to 15px.
=================================================================== */
@media (max-width: 900px) {
  input,
  textarea,
  select,
  .contact__form input,
  .contact__form textarea,
  .contact__form select,
  .review-modal input,
  .review-modal textarea,
  .sms textarea,
  .sms__search,
  .chat-widget__input-row input {
    font-size: 16px;
  }
}

/* ===================================================================
   YOUR AGENT panel — live status, config at a glance, repair.
=================================================================== */
.agent { display: flex; flex-direction: column; gap: var(--space-11); }
.agent__status {
  display: flex; align-items: center; gap: var(--space-7);
  padding: var(--space-9) var(--space-10);
  border: 1px solid rgba(var(--ink-rgb),0.10);
  border-radius: var(--r-sm);
  background: var(--paper-2);
}
.agent__dot { width: 11px; height: 11px; border-radius: 50%; flex-shrink: 0; }
.agent__dot--good { background: var(--green); box-shadow: 0 0 0 4px rgba(52,211,153,0.18); }
.agent__dot--bad { background: #DC2626; box-shadow: 0 0 0 4px rgba(220,38,38,0.16); }
.agent__dot--unknown { background: var(--amber); box-shadow: 0 0 0 4px rgba(255,209,102,0.2); }
.agent__dot--idle { background: rgba(var(--ink-rgb),0.25); }
.agent__state { font-family: var(--font-display); font-weight: 700; font-size: 0.98rem; color: var(--text-dark); }
.agent__state-sub { font-size: var(--fs-8); color: var(--text-dark-lo); line-height: 1.5; margin-top: 3px; }
.agent__repair { margin-left: auto; flex-shrink: 0; font-size: var(--fs-7); }
.agent__repair-note {
  font-size: var(--fs-8); line-height: 1.55; color: var(--amber-deep);
  background: rgba(255,209,102,0.12);
  border: 1px solid rgba(154,117,0,0.2);
  border-radius: var(--r-xs); padding: 11px var(--space-7);
}
.agent__grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-7); }
.dash__info-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-6); margin-bottom: var(--space-7);
}
.dash__info-head .btn { flex-shrink: 0; font-size: var(--fs-7); }
.agent__hint { font-size: var(--fs-5); color: var(--text-dark-lo); margin-top: var(--space-3); }
.agent__hint a { color: var(--blue); text-decoration: underline; text-underline-offset: 2px; }
.agent__script {
  padding: var(--space-10);
  border: 1px solid rgba(var(--ink-rgb),0.10);
  border-radius: var(--r-sm);
  background: var(--paper-2);
}
.agent__script-row {
  display: grid; grid-template-columns: 92px 1fr; gap: var(--space-7);
  padding: 11px 0;
  border-bottom: 1px solid rgba(var(--ink-rgb),0.06);
}
.agent__script-row:last-of-type { border-bottom: none; }
.agent__script-key {
  font-family: var(--font-display); font-size: var(--fs-4); font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-dark-lo);
  padding-top: var(--space-1);
}
.agent__script-val { font-size: var(--fs-11); color: var(--text-dark); line-height: 1.55; }
@media (max-width: 720px) {
  .agent__grid { grid-template-columns: 1fr; }
  .agent__status { flex-wrap: wrap; }
  .agent__repair { margin-left: 0; width: 100%; }
  .agent__script-row { grid-template-columns: 1fr; gap: var(--space-2); }
}

/* ===================================================================
   SIGNED-IN VIEW — replaces the sign-in form on the home page once
   there is a session. Two actions only: go manage, or sign out.
=================================================================== */
.signedin { text-align: center; }
.signedin__label {
  font-family: var(--font-display);
  font-size: var(--fs-2); font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--text-dark-lo);
  margin-bottom: var(--space-4);
}
.signedin__email {
  font-family: var(--font-display); font-weight: 700;
  font-size: 1.15rem; color: var(--text-dark);
  word-break: break-all;
  margin-bottom: var(--space-3);
}
.signedin__sub {
  font-size: var(--fs-10); color: var(--text-dark-lo);
  line-height: 1.55; margin-bottom: var(--space-12);
}
/* Sign out is deliberately the quieter of the two — it is the action you
   want available, not the one you want to hit by accident. */
.signedin__signout { margin-top: var(--space-5); }

/* Secondary escape from the website-first setup path. Deliberately quiet:
   the crawl produces a better agent than a hand-filled form, so typing it
   in yourself is the fallback rather than an equal choice. */
.setup__gate-alt { margin-top: var(--space-9); text-align: center; }
.setup__gate-alt .link-arrow { font-size: var(--fs-8); color: var(--text-dark-lo); }
.setup__gate-alt .link-arrow:hover { color: var(--blue); }

/* ===================================================================
   SETUP WIZARD (setup.html) — full screen, one question per view, over
   the same aurora backdrop as the closing section of the marketing page.

   None of the dashboard chrome: setup is a single job to finish, and a
   sidebar full of other places to go is what stops people finishing it.
   The content sits on a raised card so it stays readable over a moving
   background — the card does that work, not text-shadow on the copy.
=================================================================== */
.wiz-body { background: #060B18; min-height: 100vh; }
/* The wrapper is what the aurora measures, so it must be pinned to the
   viewport; .aurora inside it simply fills it. */
.wiz__skywrap { position: fixed; inset: 0; z-index: 0; pointer-events: none; }

.wiz { position: relative; z-index: 1; min-height: 100vh; display: flex; flex-direction: column; }
.wiz__loading { position: relative; z-index: 1; padding: 60px var(--space-12); text-align: center; color: rgba(245,241,234,0.6); }

.wiz__bar {
  display: flex; align-items: center; gap: var(--space-10);
  padding: var(--space-9) var(--space-14);
  border-bottom: 1px solid rgba(255,255,255,0.08);
  background: rgba(6,11,24,0.55);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
.wiz__brand {
  display: flex; align-items: center; gap: 9px; flex-shrink: 0;
  font-family: 'Quicksand', var(--font-display); font-weight: 700; font-size: var(--fs-12);
  color: var(--text-hi); letter-spacing: 0.14em; text-transform: uppercase;
}
.wiz__progress { flex: 1; height: 4px; border-radius: var(--r-pill); background: rgba(255,255,255,0.12); overflow: hidden; }
.wiz__progress-fill {
  height: 100%; width: 0%; border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--blue), var(--blue-bright));
  transition: width 0.45s var(--ease);
}
.wiz__count {
  flex-shrink: 0; font-family: var(--font-display);
  font-size: 0.74rem; letter-spacing: 0.08em; color: rgba(245,241,234,0.5);
  font-variant-numeric: tabular-nums;
}

.wiz__stage { flex: 1; display: flex; align-items: center; justify-content: center; padding: 48px var(--space-12) 80px; }

/* A heavy shadow plus a translucent dark surface is what keeps the copy
   legible over a moving starfield. */
.wiz__card {
  position: relative;
  width: 100%; max-width: 580px;
  padding: var(--space-16) var(--space-16) 34px;
  border-radius: var(--r-lg);
  background: rgba(10,15,28,0.82);
  border: 1px solid rgba(255,255,255,0.12);
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  box-shadow:
    0 40px 90px -20px rgba(0,0,0,0.75),
    0 10px 30px -10px rgba(0,0,0,0.6),
    inset 0 1px 0 rgba(255,255,255,0.07);
  animation: wiz-in 0.45s var(--ease) both;
}
@keyframes wiz-in {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: translateY(0); }
}

.wiz__eyebrow {
  font-family: var(--font-display); font-size: var(--fs-2); font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--amber); margin-bottom: var(--space-7);
}
.wiz__question {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(1.55rem, 3.2vw, 2.05rem); line-height: 1.15;
  color: #fff; margin-bottom: var(--space-6);
}
.wiz__help { font-size: 0.94rem; line-height: 1.6; color: rgba(245,241,234,0.7); margin-bottom: var(--space-13); }

.wiz__input {
  width: 100%;
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: var(--r-sm);
  background: rgba(255,255,255,0.06);
  color: #fff;
  font-family: var(--font-body);
  font-size: var(--fs-14);
  padding: var(--space-8) var(--space-9);
}
.wiz__input::placeholder { color: rgba(245,241,234,0.35); }
.wiz__input:focus { outline: none; border-color: var(--blue-bright); background: rgba(255,255,255,0.09); box-shadow: 0 0 0 3px rgba(90,150,255,0.28); }
.wiz__input--area { resize: vertical; line-height: 1.55; }

.wiz__multi { display: flex; flex-direction: column; gap: var(--space-10); }
.wiz__multi-field { display: block; }
.wiz__multi-label {
  display: block; font-family: var(--font-display); font-size: var(--fs-3); font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: rgba(245,241,234,0.5);
  margin-bottom: var(--space-4);
}

/* Day-by-day open hours (manual route, no website to read them from). */
.wiz__hours { display: flex; flex-direction: column; gap: var(--space-3); }
.wiz__hours-row {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-4) var(--space-6);
  padding: var(--space-4) var(--space-6);
  border: 1px solid rgba(255,255,255,0.14); border-radius: var(--r-sm);
  background: rgba(255,255,255,0.04);
}
.wiz__hours-day {
  flex: 0 0 5.5rem; font-family: var(--font-body); font-size: var(--fs-12);
  font-weight: 600; color: rgba(245,241,234,0.92);
}
.wiz__hours-times { display: flex; align-items: center; gap: var(--space-4); flex: 1 1 auto; }
.wiz__hours-time {
  border: 1px solid rgba(255,255,255,0.18); border-radius: var(--r-sm);
  background: rgba(255,255,255,0.06); color: #fff;
  font-family: var(--font-body); font-size: var(--fs-12);
  padding: var(--space-3) var(--space-5); color-scheme: dark;
}
.wiz__hours-time:focus {
  outline: none; border-color: var(--blue-bright); background: rgba(255,255,255,0.09);
  box-shadow: 0 0 0 3px rgba(90,150,255,0.28);
}
.wiz__hours-dash { font-size: var(--fs-11); color: rgba(245,241,234,0.55); }
.wiz__hours-closed {
  display: inline-flex; align-items: center; gap: var(--space-3); margin-left: auto;
  font-family: var(--font-body); font-size: var(--fs-11); color: rgba(245,241,234,0.7);
  cursor: pointer; user-select: none;
}
.wiz__hours-closed input { width: 1rem; height: 1rem; accent-color: var(--blue); cursor: pointer; }

.wiz__choices { display: flex; flex-wrap: wrap; gap: var(--space-5); }
.wiz__choice {
  padding: var(--space-6) var(--space-9); border-radius: var(--r-pill);
  border: 1px solid rgba(255,255,255,0.18);
  background: rgba(255,255,255,0.05); color: rgba(245,241,234,0.9);
  font-family: var(--font-body); font-size: var(--fs-12); cursor: pointer;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease), color 0.2s var(--ease);
}
.wiz__choice:hover { border-color: var(--blue-bright); background: rgba(255,255,255,0.09); }
.wiz__choice.is-active { background: var(--blue); border-color: var(--blue); color: #fff; }

.wiz__choices--route { flex-direction: column; }
.wiz__route {
  display: flex; flex-direction: column; gap: var(--space-2);
  width: 100%; text-align: left;
  padding: var(--space-10) var(--space-11); border-radius: 16px;
  border: 1px solid rgba(255,255,255,0.16);
  background: rgba(255,255,255,0.05); cursor: pointer;
  transition: border-color 0.2s var(--ease), transform 0.25s var(--ease), background 0.25s var(--ease);
}
.wiz__route:hover { border-color: var(--blue-bright); background: rgba(255,255,255,0.09); transform: translateY(-2px); }
.wiz__route-title { font-family: var(--font-display); font-weight: 700; font-size: 1rem; color: #fff; }
.wiz__route-sub { font-size: var(--fs-9); color: rgba(245,241,234,0.6); }
.wiz__calbtn { margin-bottom: var(--space-4); border-color: rgba(255,255,255,0.22); color: #fff; }
.wiz__calbtn:hover { border-color: var(--blue-bright); color: #fff; }

.wiz__connected {
  padding: var(--space-9) var(--space-10); border-radius: var(--r-sm);
  border: 1px solid rgba(52,211,153,0.4); background: rgba(52,211,153,0.12);
}
.wiz__connected-title { font-family: var(--font-display); font-weight: 700; color: var(--green); margin-bottom: 3px; }
.wiz__connected-sub { font-size: var(--fs-10); color: rgba(245,241,234,0.7); }

/* The cost-of-missed-calls reveal (js/setup.js's renderCostReveal) — a big
   headline figure in the same amber used for the hero's "call" accent, so
   it reads as the number worth stopping on, then the .wiz__summary rows
   below it show the math it came from. */
.wiz__reveal-figure {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(2.4rem, 6vw, 3.4rem); line-height: 1;
  color: var(--amber); margin-bottom: var(--space-5);
}
.wiz__reveal-sub { font-size: 0.94rem; line-height: 1.55; color: rgba(245,241,234,0.75); margin-bottom: var(--space-11); }

.wiz__summary { display: flex; flex-direction: column; gap: var(--space-1); margin-bottom: var(--space-11); }
.wiz__summary-row {
  display: grid; grid-template-columns: 120px 1fr; gap: var(--space-7);
  padding: 11px 0; border-bottom: 1px solid rgba(255,255,255,0.08);
}
.wiz__summary-key {
  font-family: var(--font-display); font-size: var(--fs-3); font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: rgba(245,241,234,0.5);
}
.wiz__summary-val { font-size: var(--fs-12); color: rgba(245,241,234,0.92); line-height: 1.5; }
.wiz__terms { display: flex; gap: var(--space-5); align-items: flex-start; font-size: var(--fs-10); color: rgba(245,241,234,0.72); line-height: 1.55; }
.wiz__terms a { color: var(--blue-bright); text-decoration: underline; }

.wiz__note { min-height: 1.3em; margin-top: var(--space-7); font-size: var(--fs-10); color: rgba(245,241,234,0.6); }
.wiz__note.is-error { color: #FF8A5B; }
.wiz__actions { display: flex; align-items: center; gap: var(--space-7); margin-top: var(--space-13); flex-wrap: wrap; }
.wiz__next { min-width: 180px; }
.wiz__skip, .wiz__back {
  background: none; border: none; cursor: pointer;
  font-family: var(--font-body); font-size: var(--fs-9); color: rgba(245,241,234,0.55);
  text-decoration: underline; text-underline-offset: 3px;
}
.wiz__skip:hover, .wiz__back:hover { color: var(--blue-bright); }
.wiz__back { margin-top: var(--space-13); display: inline-block; }

/* The way out, parked in the corner. Deliberately the quietest thing on the
   screen — it should be findable by anyone who wants it and invisible to
   everyone else, so it is not underlined and sits well below the card. */
.wiz__bail {
  position: fixed;
  right: max(22px, env(safe-area-inset-right, 0px));
  bottom: calc(20px + env(safe-area-inset-bottom, 0px));
  z-index: 2;
  padding: var(--space-4) var(--space-6);
  border-radius: var(--r-pill);
  font-family: var(--font-body); font-size: var(--fs-6);
  color: rgba(245,241,234,0.36);
  transition: color 0.25s var(--ease), background 0.25s var(--ease);
  -webkit-tap-highlight-color: transparent;
}
.wiz__bail:hover { color: rgba(245,241,234,0.78); background: rgba(255,255,255,0.06); }
.wiz__bail:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
@media (max-width: 560px) {
  /* On a phone the card is taller than the screen, so a pinned corner button
     would float over whatever happens to be there — including the line that
     reports errors. Below the card instead, still bottom-right. */
  .wiz__bail {
    position: static;
    align-self: flex-end;
    margin: var(--space-1) var(--space-8) var(--space-14);
  }
}

@media (max-width: 560px) {
  .wiz__bar { padding: var(--space-7) var(--space-9); gap: var(--space-7); }
  .wiz__count { display: none; }
  .wiz__stage { padding: var(--space-14) var(--space-8) 56px; }
  .wiz__card { padding: var(--space-14) var(--space-12) var(--space-12); border-radius: 20px; }
  .wiz__summary-row { grid-template-columns: 1fr; gap: 3px; }
  .wiz__next { width: 100%; }
}

/* ===================================================================
   SOFT SURFACES — one pass over every panel, card, input and control

   These follow the button rules above rather than restating them: same
   radius scale, same two-part elevation, same pressed state. Written as one
   block at the end so it lands after the per-section rules it refines,
   without having to unpick each of them.

   Nothing here moves anything. Only radius, elevation, border and the
   transitions between them — the layout each section already had is
   untouched by design.
=================================================================== */

/* --- Panels and cards ---------------------------------------------------- */
.dash__card,
.pricing__card,
.showcase__card,
.testimonial,
.hero-card,
.roi__panel,
.sms-threads__convo,
.dash__todo-menu,
.dash__profile-menu,
.dash__settings-menu {
  border-radius: var(--r-lg);
}
.dash__card,
.showcase__card,
.testimonial,
.sms-threads__convo {
  border: var(--hairline);
  box-shadow: var(--lift-1);
  transition: box-shadow 0.3s var(--ease), border-color 0.3s var(--ease), transform 0.3s var(--ease);
}
.testimonial:hover,
.showcase__card:hover { box-shadow: var(--lift-2); }

.pricing__card { border-radius: var(--r-xl); box-shadow: var(--lift-2); }
.pricing__card--featured { box-shadow: var(--lift-3); }

.dash__todo-menu,
.dash__profile-menu,
.dash__settings-menu { box-shadow: var(--lift-3); border: var(--hairline); }

/* --- Inputs -------------------------------------------------------------- */
/* Recessed rather than outlined: the reference set reads as controls pressed
   into the surface, which is also a clearer affordance than a hairline box. */
.contact__form input,
.contact__form textarea,
.contact__form select,
.setup__field input,
.setup__field textarea,
.setup__field select,
.sms__compose textarea,
.sms-convo__reply textarea,
.dash__card input,
.dash__card textarea,
.dash__card select {
  border-radius: var(--r-sm);
  border: 1px solid rgba(17,24,39,0.08);
  background: rgba(17,24,39,0.035);
  box-shadow: var(--press-1);
  transition: box-shadow 0.25s var(--ease), border-color 0.25s var(--ease), background 0.25s var(--ease);
}
.contact__form input:focus,
.contact__form textarea:focus,
.contact__form select:focus,
.setup__field input:focus,
.setup__field textarea:focus,
.setup__field select:focus,
.sms__compose textarea:focus,
.sms-convo__reply textarea:focus,
.dash__card input:focus,
.dash__card textarea:focus,
.dash__card select:focus {
  outline: none;
  border-color: rgba(47,111,255,0.5);
  background: rgba(47,111,255,0.04);
  box-shadow: var(--press-1), var(--focus-ring);
}

/* --- Small controls ------------------------------------------------------ */
.contact__authtab,
.wiz__choice,
.bridge__opt,
.voice-card,
.dash__nav-item,
.sms__tab {
  border-radius: var(--r-sm);
  transition: box-shadow 0.25s var(--ease), background 0.25s var(--ease),
              border-color 0.25s var(--ease), transform 0.25s var(--ease-spring);
}
.contact__authtab { border-radius: var(--r-pill); }
.contact__authtab.is-active { box-shadow: var(--lift-1); }
.wiz__choice:active,
.bridge__opt:active,
.contact__authtab:active { transform: scale(0.985); }

/* --- Focus, everywhere --------------------------------------------------- */
/* One visible focus style rather than the browser default in some places and
   nothing at all in others. :focus-visible so it only appears for keyboards. */
a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--r-xs);
}

/* The dark dashboard's elevations are set once, with the rest of the soft-UI
   pass at the end of this file. An earlier version restated --lift-* here with
   inset shadows, which resolved every raised card on the dark theme into a
   recessed one. */

/* ===================================================================
   CHAT PULL TAB — slide the orb out of the way

   A small handle at the screen edge. Tapping it slides the whole widget
   off to the right and leaves the tab behind; tapping again brings it
   back. The tab is a sibling of the widget, never a child, because a
   control that leaves with the thing it is meant to recall is no use.
   The choice is remembered, so it stays out of the way across pages.
=================================================================== */
.chat-tuck {
  position: fixed;
  right: 0;
  /* Vertically centred on the launcher: it sits 24px up and is 62px tall, so
     its middle is 55px, and this tab is 52px tall. */
  bottom: 29px;
  z-index: 401;
  width: 18px;
  height: 52px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--r-xs) 0 0 var(--r-xs);
  background: rgba(255,255,255,0.82);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  backdrop-filter: blur(14px) saturate(160%);
  border: 1px solid rgba(17,24,39,0.08);
  border-right: none;
  box-shadow: -2px 0 10px -4px rgba(17,24,39,0.18);
  transition: width 0.28s var(--ease), background 0.28s var(--ease), box-shadow 0.28s var(--ease);
  -webkit-tap-highlight-color: transparent;
}
.chat-tuck:hover { width: 22px; background: rgba(255,255,255,0.95); }
/* The grip itself: a short bar that rotates into a chevron-ish lean when the
   widget is tucked, so the tab says which way it will move. */
.chat-tuck__grip {
  width: 3px;
  height: 22px;
  border-radius: var(--r-pill);
  background: rgba(17,24,39,0.35);
  transition: transform 0.32s var(--ease-spring), background 0.28s var(--ease);
}
.chat-tuck:hover .chat-tuck__grip { background: rgba(17,24,39,0.6); }

.chat-widget {
  transition:
    transform 0.42s var(--ease-spring),
    opacity 0.28s var(--ease),
    right 0.42s var(--ease-spring),
    bottom 0.42s var(--ease-spring);
}
/* Tucked: the widget travels its own width plus the gap, so nothing of it is
   left peeking, and stops taking pointer events so it cannot be tapped blind. */
body.chat-tucked .chat-widget {
  transform: translateX(calc(100% + 40px));
  opacity: 0;
  pointer-events: none;
}
body.chat-tucked .chat-tuck__grip { transform: rotate(180deg) translateY(1px); }
body.chat-tucked .chat-tuck { background: rgba(255,255,255,0.92); }

/* The dashboard's dark theme needs its own tab, for the same reason its
   panels do. */
[data-theme="dark"] .dash-body .chat-tuck {
  background: rgba(20,26,38,0.85);
  border-color: rgba(226,232,244,0.12);
  box-shadow: -2px 0 10px -4px rgba(0,0,0,0.5);
}
[data-theme="dark"] .dash-body .chat-tuck:hover { background: rgba(20,26,38,0.96); }
[data-theme="dark"] .dash-body .chat-tuck__grip { background: rgba(226,232,244,0.45); }
[data-theme="dark"] .dash-body .chat-tuck:hover .chat-tuck__grip { background: rgba(226,232,244,0.75); }

@media (max-width: 500px) {
  /* The marketing orb drops to 16px here, so the tab follows it down. */
  .chat-tuck { bottom: 21px; }
}
@media (max-width: 900px) {
  /* The dashboard's orb is lifted clear of the bottom nav pill; the tab has
     to go with it or the two stop being one control. */
  .dash-body .chat-tuck { bottom: calc(89px + env(safe-area-inset-bottom, 0px)); }
}
@media (prefers-reduced-motion: reduce) {
  .chat-widget, .chat-tuck, .chat-tuck__grip { transition: none; }
}

/* Icon sizing for the controls whose glyphs became drawn icons. */
.voice-card__play svg { width: 12px; height: 12px; display: block; }
.admin__rating { display: flex; gap: var(--space-1); align-items: center; }
.admin__star { width: 14px; height: 14px; color: rgba(17,24,39,0.28); flex-shrink: 0; }
.admin__star.is-on { color: var(--amber-deep); }

/* ===================================================================
   RESULTS — the numbers the agent has actually produced

   Charts drawn as plain elements rather than pulled from a library: the
   whole thing is a bar per day and a progress ring, and a charting
   dependency would cost more to load than the section is worth.
=================================================================== */
/* No longer one big panel — a transparent wrapper that lets the stat cards
   and the chart each sit in their own rounded card (squircle), the way the
   reference dashboard lays its blocks out. */
.results {
  margin-bottom: var(--space-9);
}
/* The graph gets its own raised squircle, separate from the stat cards. */
.results__chart {
  background: var(--paper-2);
  border-radius: var(--r-lg);
  box-shadow: var(--lift-1);
  padding: var(--space-10) var(--space-11) var(--space-11);
}
.results__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-8); flex-wrap: wrap; margin-bottom: var(--space-10); }
.results__label { font-family: var(--font-display); font-weight: 700; font-size: 1.05rem; color: var(--text-dark); }
.results__sub { font-size: var(--fs-5); color: var(--text-dark-lo); margin-top: var(--space-1); }

.results__range { display: flex; gap: var(--space-2); padding: 3px; border-radius: var(--r-pill); background: rgba(17,24,39,0.05); }
.results__range-btn {
  padding: var(--space-3) 13px;
  border-radius: var(--r-pill);
  font-family: var(--font-display); font-weight: 600; font-size: 0.76rem;
  color: var(--text-dark-lo);
  transition: background 0.22s var(--ease), color 0.22s var(--ease), box-shadow 0.22s var(--ease);
}
.results__range-btn.is-active { background: var(--paper-2); color: var(--text-dark); box-shadow: var(--lift-1); }

/* The dashboard's own accent runs on a neutral ink scale (charcoal → grey),
   not the site's brand blue — the numbers should read like a quiet control
   panel, not a marketing page. Themed so the ink flips light on dark. */
/* Two-tone series, the way the reference separates its two lines: blue for
   the calls that came in, green for the ones that turned into a booking.
   The grid and axis labels stay neutral so the scaffolding never competes
   with the data drawn on top of it. Named for what they mean, not for how
   dark they are. */
/* Texts is the site's amber (--amber, the same #FFD166 the marketing page
   uses) rather than a purple that appeared nowhere else on Japhone. Blue,
   amber, green: three flat colours, one per series, no other treatment. The
   dark row lifts each one for contrast on the dark dashboard, amber included —
   #FFD166 is already bright enough there, so it carries over unchanged. */
.dash-body { --dash-answered: #2F6FFF; --dash-texts: #E0A400; --dash-booked: #0EA06B; --dash-grid: #9AA1AD; }
[data-theme="dark"] .dash-body { --dash-answered: #6E9BFF; --dash-texts: #FFD166; --dash-booked: #34D399; --dash-grid: #79808C; }

.results__stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-8); margin-bottom: var(--space-8); }
/* The wide chart and the three cards stacked beside it. minmax(0,…) so the
   SVG cannot push the chart column wider than its share. */
/* The chart row reuses the SAME four tracks as the cards above it, with the
   chart spanning three of them. A 3fr/1fr split looks equivalent but is not:
   four columns put the last one at 0.75W + 0.75gap, while a two-track split
   puts it at 0.75W + 0.25gap, so the rail sat half a gap (8px) left of the
   card above it. Sharing the track definition is what makes them line up,
   rather than matching numbers by eye. Both rows must keep the same gap. */
.results__main { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-8); align-items: stretch; }
.results__chart { grid-column: span 3; min-width: 0; }
.results__rail { grid-column: span 1; display: grid; grid-template-rows: repeat(3, 1fr); gap: var(--space-8); min-width: 0; }
/* The rail sets the row height, and the chart matches it. Tighter than the
   cards along the top, because three of them stacked otherwise drive the plot
   tall enough that a one-day spike renders as a needle. */
.results__rail .results__stat {
  display: flex; flex-direction: column; justify-content: center;
  padding: var(--space-6) var(--space-9);
}
.results__stat {
  position: relative;
  padding: var(--space-8) var(--space-9);
  border-radius: var(--r-md);
  background: rgba(17,24,39,0.03);
  border: 1px solid rgba(17,24,39,0.05);
}
/* The metric NAME reads as the card's heading, the comparison line under the
   value stays muted — the hierarchy the reference dashboard uses. */
.results__stat-label { font-family: var(--font-display); font-weight: 600; font-size: 0.82rem; color: var(--text-dark); letter-spacing: 0.01em; }
.results__stat-row { display: flex; align-items: baseline; gap: var(--space-4); flex-wrap: wrap; margin-top: var(--space-3); }
.results__stat-value { font-family: var(--font-display); font-weight: 700; font-size: 1.75rem; color: var(--text-dark); line-height: 1.1; }
.results__stat-delta { font-family: var(--font-display); font-weight: 600; font-size: 0.76rem; white-space: nowrap; color: var(--text-dark-lo); }
.results__stat-trend { font-size: 0.74rem; color: var(--text-dark-lo); margin-top: var(--space-2); min-height: 16px; }

/* Small in-card visuals, drawn from the same numbers the card already states.
   Absolutely placed so they can never push the figures around, with the card
   reserving room for them rather than letting the text run underneath. */
.results__viz { position: absolute; right: var(--space-9); top: 50%; transform: translateY(-50%); pointer-events: none; }
.results__viz svg { display: block; }
.results__stat:has(.results__viz) { padding-right: 82px; }
/* Two-up cards on a phone have no room for a chart beside the number. */
@media (max-width: 700px) {
  .results__viz { display: none; }
  .results__stat:has(.results__viz) { padding-right: var(--space-9); }
}
.results__stat-trend.is-up,
.results__stat-delta.is-up { color: var(--green-deep); }
.results__stat-trend.is-down,
.results__stat-delta.is-down { color: #A64A08; }
/* Those two read as mud on the dark dashboard; these clear AA on it. */
[data-theme="dark"] .dash-body .results__stat-trend.is-up,
[data-theme="dark"] .dash-body .results__stat-delta.is-up { color: #4ADE80; }
[data-theme="dark"] .dash-body .results__stat-trend.is-down,
[data-theme="dark"] .dash-body .results__stat-delta.is-down { color: #F87171; }

/* The booking rate reads as a proportion, so it gets drawn as one. */
.results__ring { position: absolute; top: 14px; right: 14px; width: 44px; height: 44px; }
.results__ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.results__ring circle { fill: none; stroke-width: 3.4; stroke-linecap: round; }
.results__ring-track { stroke: rgba(17,24,39,0.09); }
.results__ring-fill {
  stroke: var(--dash-answered);
  stroke-dasharray: 97.4;          /* 2πr at r=15.5 */
  stroke-dashoffset: 97.4;
  transition: stroke-dashoffset 0.7s var(--ease);
}

.results__chart-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-6); margin-bottom: var(--space-6); }
.results__chart-title { font-family: var(--font-display); font-weight: 600; font-size: var(--fs-10); color: var(--text-dark); }
.results__legend { display: flex; gap: var(--space-7); }
.results__key { font-size: var(--fs-4); color: var(--text-dark-lo); display: inline-flex; align-items: center; gap: var(--space-3); }
.results__key::before { content: ''; width: 8px; height: 8px; border-radius: 50%; }
.results__key--calls::before { background: var(--dash-answered); }
.results__key--texts::before { background: var(--dash-texts); }
.results__key--booked::before { background: var(--dash-booked); }

/* The chart column is as tall as the rail beside it, so the plot grows to
   fill whatever is left under the title rather than leaving dead space. */
.results__chart { display: flex; flex-direction: column; }
.results__plot {
  display: block;
  position: relative;          /* anchors the hover readout */
  flex: 1 1 auto;
  min-height: 150px;
  /* A wide, shallow plot. Past this the box gets tall enough that a single
     busy day draws as a narrow spike rather than a readable curve. */
  max-height: 230px;
  padding-top: var(--space-4);
}
.results__svg { display: block; width: 100%; height: 100%; overflow: visible; }

/* The hover readout. pointer-events:none matters — the card sits over the
   plot, and without it the cursor would leave the chart the moment the card
   caught up with it, flickering the whole thing off and on. */
.results__tip {
  position: absolute;
  z-index: 3;
  pointer-events: none;
  transform: translate(-50%, -100%);
  padding: var(--space-4) var(--space-7);
  border-radius: var(--r-md);
  background: var(--paper);
  border: 1px solid rgba(var(--ink-rgb),0.1);
  box-shadow: var(--lift-2);
  white-space: nowrap;
  opacity: 0;
  transition: opacity 0.12s var(--ease);
}
.results__tip.is-on { opacity: 1; }
.results__tip-val { font-family: var(--font-display); font-weight: 700; font-size: var(--fs-10); color: var(--text-dark); }
.results__tip-day { font-size: 0.7rem; color: var(--text-dark-lo); margin-top: 1px; }
.results__bar {
  flex: 1 1 0;
  min-width: 0;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  height: 100%;
  border-radius: var(--r-xs);
  transition: background 0.2s var(--ease);
}
.results__bar:hover { background: rgba(17,24,39,0.04); }
/* Two stacked segments: booked sits inside answered, so the eye reads the
   filled portion as the share that converted rather than as an extra total. */
.results__bar-calls {
  width: 100%;
  border-radius: 5px 5px 3px 3px;
  background: var(--blue-soft);
  box-shadow: inset 0 0 0 1px rgba(47,111,255,0.28);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  transition: height 0.5s var(--ease);
}
.results__bar-booked { width: 100%; background: var(--blue); border-radius: 3px 3px 0 0; transition: height 0.5s var(--ease); }
.results__bar-tip {
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  padding: var(--space-3) 9px;
  border-radius: var(--r-xs);
  background: var(--text-dark);
  color: var(--paper-2);
  font-size: var(--fs-3);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s var(--ease), transform 0.2s var(--ease);
  z-index: 2;
}
.results__bar:hover .results__bar-tip { opacity: 1; transform: translateX(-50%) translateY(0); }
.results__empty { font-size: var(--fs-8); color: var(--text-dark-lo); text-align: center; padding: 18px 0 4px; }

@media (max-width: 620px) {
  .results { padding: var(--space-9) var(--space-8) var(--space-10); }
  /* Six stats in a row stop being readable well before the panel does; two
     columns keep them dense without crushing the numbers. */
  .results__stats { grid-template-columns: repeat(2, 1fr); }
  .results__stat-value { font-size: 1.4rem; }
  .results__plot { min-height: 124px; gap: var(--space-1); }
  /* Touch has no hover, so the tooltips never appear — the totals above carry
     the meaning on a phone. */
  .results__bar-tip { display: none; }
}

/* Below a true desktop there is no room for a chart and a rail side by side:
   the chart takes the full width and the three cards run under it as a row.
   Declared after the base rules above, since a media query adds no
   specificity of its own. */
@media (max-width: 1100px) {
  .results__main { grid-template-columns: 1fr; }
  /* Must clear the spans. A "span 3" left in a single-column grid does not
     shrink to fit — it generates two implicit columns and the chart hangs off
     the side. */
  .results__chart, .results__rail { grid-column: auto; }
  .results__rail { grid-template-rows: none; grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 860px) {
  .results__stats { grid-template-columns: repeat(2, 1fr); }
  .results__rail { grid-template-columns: 1fr; }
}

/* Wells take --paper on both themes; see the soft-UI pass. */
[data-theme="dark"] .dash-body .results__ring-track { stroke: rgba(226,232,244,0.12); }
[data-theme="dark"] .dash-body .results__bar:hover { background: rgba(255,255,255,0.04); }
[data-theme="dark"] .dash-body .results__bar-tip { background: var(--paper); color: var(--text-dark); }

/* ===================================================================
   SOFT UI — the full pass

   Everything below follows one rule taken from the reference: a control is
   the same tone as the surface behind it, and depth comes from a shadow on
   one side and a highlight on the other. Raised for anything you press,
   recessed for anything you type into or that holds a value. Borders come
   off rather than getting softer — an outline and a shadow describing the
   same edge is what makes soft UI look muddy.

   Layout is untouched. Only surface, radius, shadow and the transitions.
=================================================================== */

/* --- Raised: things you press --------------------------------------------- */
.btn--outline,
.contact__authtab,
.wiz__choice,
.bridge__opt,
.results__range-btn,
.sms__tab,
.voice-card__play,
.dash__settings-btn,
.dash__todo-btn,
.hero-card__btn {
  background: var(--paper-2);
  border: none;
  box-shadow: var(--lift-1);
}
.btn--outline:hover,
.contact__authtab:hover,
.wiz__choice:hover,
.bridge__opt:hover,
.results__range-btn:hover,
.sms__tab:hover,
.voice-card__play:hover,
.dash__settings-btn:hover,
.dash__todo-btn:hover,
.hero-card__btn:hover {
  box-shadow: var(--lift-2);
  color: var(--text-dark);
}
/* Pressed means pressed: the same two shadows, seen from the inside. */
.btn--outline:active,
.contact__authtab:active,
.wiz__choice:active,
.bridge__opt:active,
.results__range-btn:active,
.sms__tab:active,
.voice-card__play:active,
.dash__settings-btn:active,
.dash__todo-btn:active,
.hero-card__btn:active {
  box-shadow: var(--press-1);
  transform: none;
}

/* A selected thing stays pressed in. That is how the reference separates a
   chosen option from a merely raised one, without needing a colour. */
.contact__authtab.is-active,
.wiz__choice.is-active,
.bridge__opt.is-active,
.results__range-btn.is-active,
.sms__tab.is-active,
.voice-card.is-selected {
  box-shadow: var(--press-1);
  background: var(--paper-2);
  color: var(--blue-ink);
}
.dash__settings-btn[aria-expanded="true"],
.dash__todo-btn[aria-expanded="true"] { box-shadow: var(--press-1); }

/* Inside the dashboard the selected tab's accent is neutral ink, not brand
   blue — the pressed-in shadow already marks it as chosen. Scoped to
   .dash-body so the marketing and setup tabs keep their blue. */
.dash-body .results__range-btn.is-active,
.dash-body .sms__tab.is-active,
.dash-body .voice-card.is-selected { color: var(--blue); }

/* The one exception: the primary action keeps its fill, because a page where
   nothing is coloured gives the eye nowhere to land. Its shadow is tinted to
   its own colour rather than the neutral one. */
.btn--solid {
  box-shadow:
    /* specular along the top edge, the same one every glass surface gets */
    inset 0 1px 0 rgba(255,255,255,0.34),
    inset 0 -1px 0 rgba(12,40,110,0.28),
    0 1px 2px rgba(20,53,140,0.20),
    0 10px 24px -10px rgba(47,111,255,0.50);
}
.btn--solid:hover {
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.40),
    inset 0 -1px 0 rgba(12,40,110,0.28),
    0 2px 4px rgba(20,53,140,0.22),
    0 16px 34px -12px rgba(47,111,255,0.58);
}
.btn--solid:active {
  box-shadow:
    inset 4px 4px 10px rgba(12,40,110,0.45),
    inset -3px -3px 8px rgba(120,160,255,0.40);
}

/* --- Recessed: things you type into --------------------------------------- */
.contact__form input,
.contact__form textarea,
.contact__form select,
.setup__field input,
.setup__field textarea,
.setup__field select,
.sms__compose textarea,
.sms-convo__reply textarea,
.sms__search,
.dash__card input,
.dash__card textarea,
.dash__card select {
  background: var(--paper);
  border: none;
  box-shadow: var(--press-1);
  color: var(--text-dark);
}
.contact__form input:focus,
.contact__form textarea:focus,
.contact__form select:focus,
.setup__field input:focus,
.setup__field textarea:focus,
.setup__field select:focus,
.sms__compose textarea:focus,
.sms-convo__reply textarea:focus,
.sms__search:focus,
.dash__card input:focus,
.dash__card textarea:focus,
.dash__card select:focus {
  outline: none;
  background: var(--paper);
  box-shadow: var(--press-2), 0 0 0 2px rgba(47,111,255,0.35);
}

/* --- Cards and panels ----------------------------------------------------- */
.dash__card,
.pricing__card,
.showcase__card,
.testimonial,
.hero-card,
.results,
.sms-threads__convo,
.sms-thread,
.dash__todo-menu,
.dash__profile-menu,
.dash__settings-menu,
.contact__form {
  background: var(--paper-2);
  border: none;
}
.dash__card,
.showcase__card,
.testimonial,
.results,
.sms-threads__convo,
.sms-thread { box-shadow: var(--lift-1); }
.pricing__card,
.hero-card,
.dash__todo-menu,
.dash__profile-menu,
.dash__settings-menu,
.contact__form { box-shadow: var(--lift-2); }
.pricing__card--featured { box-shadow: var(--lift-3); }
.testimonial:hover,
.showcase__card:hover,
.sms-thread:hover { box-shadow: var(--lift-2); }

/* The range toggle stays a recessed well; the stat cards are now raised
   squircles that stand on the page on their own, matching the reference —
   each with a hairline edge so the card reads as its own object rather than
   dissolving into the background. */
.results__range { background: var(--paper); box-shadow: var(--press-1); border: none; }
.results__stat,
.results__chart {
  background: var(--paper-2);
  box-shadow: var(--lift-1);
  border: 1px solid rgba(var(--ink-rgb),0.07);
  border-radius: var(--r-lg);
}
.sms-thread.needs-owner { box-shadow: var(--lift-1), inset 3px 0 0 var(--amber-deep); }

/* --- Graphs ---------------------------------------------------------------- */
/* Recessed track with the value sitting inside it, the way the reference
   draws its bars. */
.results__plot { gap: 5px; }
.results__bar-calls {
  border-radius: var(--r-pill);
  background: var(--paper);
  box-shadow: var(--press-1);
  padding: 3px;
}
.results__bar-booked {
  border-radius: var(--r-pill);
  background: linear-gradient(180deg, var(--blue-bright), var(--blue));
  box-shadow: 0 2px 6px -1px rgba(47,111,255,0.5);
}
.results__ring-track { stroke: rgba(163,177,198,0.4); }
.results__bar-tip { box-shadow: var(--lift-2); }
.results__bar:hover { background: none; }
.results__bar:hover .results__bar-calls { box-shadow: var(--press-2); }

/* --- Sliders --------------------------------------------------------------- */
/* Recessed track, blue-to-cyan fill, raised knob — the progress control from
   the reference, which the ROI calculator already had the shape of. */
.roi__control input[type="range"] {
  height: 12px;
  background: var(--paper);
  box-shadow: var(--press-1);
  background-image: linear-gradient(90deg, var(--blue) 0%, #35D0E0 var(--pct, 20%),
                    transparent var(--pct, 20%), transparent 100%);
}
.roi__control input[type="range"]::-webkit-slider-thumb {
  width: 24px; height: 24px;
  background: var(--paper-2);
  border: none;
  box-shadow: var(--lift-2);
}
.roi__control input[type="range"]::-webkit-slider-thumb:hover { box-shadow: var(--lift-3); transform: scale(1.06); }
.roi__control input[type="range"]::-moz-range-thumb {
  width: 22px; height: 22px; background: var(--paper-2); border: none; box-shadow: var(--lift-2);
}
/* The value bubble the reference floats above its slider. */
.roi__control-val {
  background: var(--paper-2);
  box-shadow: var(--lift-1);
  border-radius: var(--r-xs);
  padding: var(--space-2) var(--space-5);
}

/* --- Toggles and checkboxes ------------------------------------------------ */
.contact__tos input[type="checkbox"],
.sms__selectall input[type="checkbox"],
.wiz__terms input[type="checkbox"],
.dash__card input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 20px; height: 20px;
  border-radius: 6px;
  background: var(--paper);
  box-shadow: var(--press-1);
  cursor: pointer;
  position: relative;
  flex-shrink: 0;
  transition: background 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
.contact__tos input[type="checkbox"]:checked,
.sms__selectall input[type="checkbox"]:checked,
.wiz__terms input[type="checkbox"]:checked,
.dash__card input[type="checkbox"]:checked {
  background: var(--blue);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.35), 0 4px 10px -4px rgba(47,111,255,0.45);
}
.contact__tos input[type="checkbox"]:checked::after,
.sms__selectall input[type="checkbox"]:checked::after,
.wiz__terms input[type="checkbox"]:checked::after,
.dash__card input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  inset: 0;
  background-color: #fff;
  -webkit-mask: var(--icon-check) center / 12px 12px no-repeat;
  mask: var(--icon-check) center / 12px 12px no-repeat;
}

/* --- Icon wells ------------------------------------------------------------ */
/* Icons set into soft squares rather than sitting flat beside the text. */
.stage__icon,
.showcase__card-icon {
  background: var(--paper-2);
  box-shadow: var(--lift-1);
  border: none;
}
.stage.is-active .stage__icon { box-shadow: var(--press-1); color: var(--blue); }

/* --- Links ----------------------------------------------------------------- */
.link-arrow { border-bottom: none; padding-bottom: 3px; }
.link-arrow:hover { color: var(--blue); }

/* --- What must NOT go soft -------------------------------------------------- */
/* The dark bands and the nav pill are art-directed on dark grounds, where a
   white highlight reads as a scuff. Killing the light half of the pair inside
   them leaves the shadow alone to do the work. */
.nav__inner,
.alwayson,
.cosmos,
.footer,
.roi__result { --soft-light: transparent; }

/* .btn--outline lives on both the light sections and the dark ones. The light
   theme's soft fill is near-white, which on a dark ground is a white pill with
   white text on it — exactly what the footer's Get Started became. So these
   get the same construction, built for their own ground: the dark geometry,
   where the highlight is a tight catch on the edge rather than the wide bloom
   that only works on pale surfaces.

   The fill is left transparent rather than given a tone. These sit on
   gradients — the footer runs #10275C to #060E24 under a seam fade — so any
   flat colour matches at exactly one point on it and bands everywhere else.
   Transparent means the button IS its background, which is the rule the whole
   language is built on, and the two shadows do all the lifting. */
.footer .btn--outline,
.cosmos .btn--outline,
.alwayson .btn--outline,
.roi__result .btn--outline {
  background: transparent;
  border: none;
  color: var(--text-hi);
  box-shadow:
    6px 6px 14px rgba(0,0,0,0.55),
    -3px -3px 8px rgba(255,255,255,0.07),
    /* A hairline of light along the top edge, which is what stops a fully
       transparent control disappearing where the ground is already dark. */
    inset 0 1px 0 rgba(255,255,255,0.09);
}
.footer .btn--outline::after,
.cosmos .btn--outline::after,
.alwayson .btn--outline::after,
.roi__result .btn--outline::after { background-color: rgba(255,255,255,0.10); }
.footer .btn--outline:hover,
.cosmos .btn--outline:hover,
.alwayson .btn--outline:hover,
.roi__result .btn--outline:hover {
  background: rgba(255,255,255,0.045);
  color: var(--text-hi);
  box-shadow:
    9px 9px 20px rgba(0,0,0,0.62),
    -4px -4px 10px rgba(255,255,255,0.09),
    inset 0 1px 0 rgba(255,255,255,0.12);
}
/* Pressed turns both shadows inward, the same way it does everywhere else. */
.footer .btn--outline:active,
.cosmos .btn--outline:active,
.alwayson .btn--outline:active,
.roi__result .btn--outline:active {
  transform: none;
  background: transparent;
  box-shadow:
    inset 5px 5px 11px rgba(0,0,0,0.65),
    inset -3px -3px 7px rgba(255,255,255,0.07);
}
.roi__result .btn--solid,
.cosmos .btn--solid,
.footer .btn--solid { box-shadow: 0 12px 30px -10px rgba(47,111,255,0.55); }

/* --- FAQ ------------------------------------------------------------------- */
/* Was a bordered accordion — hairlines between rows. In this language a row is
   a card that lifts on hover and presses in once it is open, so the rules that
   drew those lines come off rather than sitting under the shadows. */
.faq__list { border-top: none; display: flex; flex-direction: column; gap: var(--space-5); }
.faq__item {
  border-bottom: none;
  border-radius: var(--r-md);
  background: var(--paper-2);
  box-shadow: var(--lift-1);
  transition: box-shadow 0.3s var(--ease), background 0.3s var(--ease);
}
.faq__item:hover { background: var(--paper-2); box-shadow: var(--lift-2); }
.faq__item.is-open { box-shadow: var(--press-1); }
.faq__q { padding: var(--space-11) var(--space-11); }
.faq__a p { padding: 0 22px 22px 70px; }
/* The plus sits in its own well, and fills once the row is open. */
.faq__toggle { background: var(--paper-2); box-shadow: var(--lift-1); color: var(--blue); }
.faq__item.is-open .faq__toggle {
  background: var(--blue);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.35), 0 5px 12px -4px rgba(47,111,255,0.45);
}

/* --- Remaining flat surfaces ----------------------------------------------- */
/* Anything still drawing itself with a hairline on a light ground. */
.assurance__item,
.numline__card,
.setup__gate,
.dash__banner,
.voice-card {
  border: none;
  background: var(--paper-2);
  box-shadow: var(--lift-1);
  border-radius: var(--r-md);
}
.voice-card:hover { box-shadow: var(--lift-2); }
.voice-card.is-selected { box-shadow: var(--press-1); }
.dash__banner { background: var(--paper-2); box-shadow: var(--lift-1), inset 3px 0 0 var(--amber-deep); }

/* Dividers that were hairlines become a soft groove: a dark line and a light
   one, which is how a seam reads in this language. */
.dash__topbar,
.dash__sidebar {
  border-bottom-color: transparent;
  border-right-color: transparent;
}
.dash__topbar { box-shadow: 0 1px 0 rgba(19,22,30,0.06); backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur); }

/* --- Progress and meters ---------------------------------------------------- */
.dash__todo-bar,
.wiz__progress {
  background: var(--paper);
  box-shadow: var(--press-1);
  border-radius: var(--r-pill);
  overflow: hidden;
}
.dash__todo-bar span,
.wiz__progress-fill {
  background: linear-gradient(90deg, var(--blue), #35D0E0);
  border-radius: var(--r-pill);
}

/* --- The setup wizard ------------------------------------------------------- */
/* Its own dark ground, over the starfield. Same two-sided construction, with
   the highlight dropped to a hint so it does not scuff the glass. */
.wiz-body {
  --soft-dark: rgba(0,0,0,0.6);
  --soft-light: rgba(255,255,255,0.06);
  --paper: #0B1220;
  --paper-2: rgba(255,255,255,0.05);

  /* The same correction the dark dashboard needed. Only the shadow COLOURS
     were being overridden here; the geometry still came from :root, which is
     built for a pale ground — 4px out with 9px of blur. A white blur that wide
     disappears into pale grey but stands off a starfield as a halo, and every
     choice chip was ringed with one. Tight catch of light on the edge, and the
     dark half widened to carry the depth. */
  --lift-1: 5px 5px 12px var(--soft-dark), -2px -2px 4px var(--soft-light);
  --lift-2: 8px 8px 18px var(--soft-dark), -3px -3px 6px var(--soft-light);
  --lift-3: 14px 14px 30px var(--soft-dark), -4px -4px 8px var(--soft-light);
  --press-1: inset 4px 4px 9px var(--soft-dark), inset -2px -2px 5px var(--soft-light);
  --press-2: inset 6px 6px 13px var(--soft-dark), inset -3px -3px 6px var(--soft-light);
  --shadow-soft: 12px 12px 26px var(--soft-dark), -4px -4px 10px var(--soft-light);
  /* The shared control rules reach for --text-dark on hover and select. On a
     dark ground that is near-black on near-black, so the token points at the
     readable colour here rather than every one of those rules needing to know
     which page it is on. */
  --text-dark: #F5F1EA;
  --text-dark-lo: rgba(245,241,234,0.65);
  --blue-ink: #8AB0FF;
}
.wiz__progress { background: rgba(255,255,255,0.08); box-shadow: none; }

/* --- Dark dashboard --------------------------------------------------------- */
/* Neumorphism twice over, not once with the colours swapped.

   The light half of the pair cannot keep the light theme's geometry here. A
   wide white blur disappears into a pale ground but stands off a dark one as a
   halo, which is what ringed every card. On dark it becomes a tight catch of
   light along the top-left edge — small offset, small blur — and the dark half
   is widened to carry the depth on its own.

   Surfaces also stop being lighter than the ground. A lifted fill AND a glow
   is the same effect applied twice; the shadow alone should say which way is
   up, exactly as it does on the light theme. */
[data-theme="dark"] .dash-body {
  --soft-dark: rgba(0,0,0,0.62);
  --soft-light: rgba(255,255,255,0.055);
  --paper: #171D29;
  --paper-2: #1B2230;
  /* Same reason as the wizard: the readable blue on a pale ground is the
     unreadable one here. */
  --blue-ink: #8AB0FF;

  --lift-1: 5px 5px 12px var(--soft-dark), -2px -2px 4px var(--soft-light);
  --lift-2: 8px 8px 18px var(--soft-dark), -3px -3px 6px var(--soft-light);
  --lift-3: 14px 14px 30px var(--soft-dark), -4px -4px 8px var(--soft-light);
  --press-1: inset 4px 4px 9px var(--soft-dark), inset -2px -2px 5px var(--soft-light);
  --press-2: inset 6px 6px 13px var(--soft-dark), inset -3px -3px 6px var(--soft-light);
  --shadow-soft: 12px 12px 26px var(--soft-dark), -4px -4px 10px var(--soft-light);
}
/* Structural seams. Setting these transparent for the light theme left the
   sidebar and topbar floating with nothing to divide them from the content. */
[data-theme="dark"] .dash-body .dash__sidebar { border-right: 1px solid rgba(255,255,255,0.06); }
[data-theme="dark"] .dash-body .dash__topbar { box-shadow: 0 1px 0 rgba(255,255,255,0.05), 0 6px 16px -10px rgba(0,0,0,0.7); }
[data-theme="dark"] .dash-body .results__ring-track { stroke: rgba(226,232,244,0.14); }
[data-theme="dark"] .dash-body input,
[data-theme="dark"] .dash-body textarea,
[data-theme="dark"] .dash-body select { background: var(--paper); color: var(--text-dark); }

/* --- Section eyebrows ------------------------------------------------------ */
/* The little pills over each section heading — 24/7 AI PHONE RECEPTIONIST,
   HOW IT WORKS, and their siblings. They were tinted chips with a matching
   hairline, which is the one combination this language does not use: an
   outline and a shadow describing the same edge. They keep their tint, since
   that is what separates the blue sections from the amber ones, but the edge
   now comes from the light instead. */
.section-eyebrow,
.hero__eyebrow,
.pipeline__eyebrow,
.showcase__eyebrow,
.roi__eyebrow {
  border: none;
  box-shadow: var(--lift-1);
}
/* Each keeps its own tint, laid over the ground rather than replacing it, so
   the pill still reads as the same material as everything around it. */
.section-eyebrow,
.pipeline__eyebrow,
.showcase__eyebrow,
.roi__eyebrow { background: linear-gradient(var(--paper-2), var(--paper-2)) padding-box, rgba(47,111,255,0.10); }
.hero__eyebrow { background: linear-gradient(var(--paper-2), var(--paper-2)) padding-box, rgba(255,209,102,0.18); }

/* On dark grounds the same pills take the dark geometry — a tight catch of
   light rather than the wide bloom that only works on pale surfaces. */
.alwayson__text p.alwayson__eyebrow,
.cosmos__eyebrow,
.footer .section-eyebrow {
  border: none;
  background: rgba(255,255,255,0.05);
  box-shadow:
    4px 4px 10px rgba(0,0,0,0.45),
    -2px -2px 5px rgba(255,255,255,0.06),
    inset 0 1px 0 rgba(255,255,255,0.08);
}

/* --- The primary blue button ----------------------------------------------- */
/* Neumorphism in its own colour rather than a neutral shadow under a coloured
   fill: the shadow is a darker blue, the highlight a lighter one, so the
   button looks pressed out of a blue surface the way the reference's toggle
   does. A grey shadow under a blue button is the giveaway that the colour was
   painted on afterwards. */
/* Gradient stops sit a shade below the brand blue on purpose: white button
   labels are 13.6px/600, so the 4.5:1 normal-text floor applies, and the old
   light stop (#3C7BFF) measured 3.84:1 against white. Both stops now pass.
   Hover no longer brightens the fill, because every blue light enough to read
   as "brighter" fails the same check; the bigger shadow and the lift already
   carry that feedback. */
.btn--solid {
  background: linear-gradient(145deg, #2E6DEE, #2354CC);
  box-shadow:
    6px 6px 14px rgba(20,53,140,0.42),
    -4px -4px 10px rgba(126,168,255,0.45),
    inset 0 1px 0 rgba(255,255,255,0.28);
}
.btn--solid:hover {
  background: linear-gradient(145deg, #2E6DEE, #2A63E8);
  box-shadow:
    9px 9px 20px rgba(20,53,140,0.48),
    -5px -5px 13px rgba(126,168,255,0.5),
    inset 0 1px 0 rgba(255,255,255,0.34);
}
/* Pressed pushes the same two shadows inward — the button sinks into its own
   colour rather than dimming. */
.btn--solid:active {
  transform: none;
  background: linear-gradient(145deg, #2354CC, #2E6DEE);
  box-shadow:
    inset 5px 5px 12px rgba(16,44,120,0.55),
    inset -4px -4px 10px rgba(126,168,255,0.35);
}

/* On the dark bands the lighter half would glow, so it tightens the same way
   every other dark-ground control does. */
.footer .btn--solid,
.cosmos .btn--solid,
.alwayson .btn--solid,
.roi__result .btn--solid {
  box-shadow:
    6px 6px 16px rgba(0,0,0,0.5),
    -3px -3px 8px rgba(126,168,255,0.28),
    inset 0 1px 0 rgba(255,255,255,0.22);
}
.footer .btn--solid:hover,
.cosmos .btn--solid:hover,
.alwayson .btn--solid:hover,
.roi__result .btn--solid:hover {
  box-shadow:
    9px 9px 22px rgba(0,0,0,0.55),
    -4px -4px 10px rgba(126,168,255,0.34),
    inset 0 1px 0 rgba(255,255,255,0.28);
}

/* ===================================================================
   PLAN CARDS IN BILLING

   Deliberately the same shape as the marketing page's pricing cards, so
   the thing you chose when you signed up is recognisable when you come
   back to change it. Built on the shared soft-UI tokens like everything
   else, rather than a second set of values that would drift.
=================================================================== */
.plans {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-8);
  margin-bottom: var(--space-9);
}
.plans__card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: var(--space-13) var(--space-12);
  border-radius: var(--r-lg);
  background: var(--paper-2);
  box-shadow: var(--lift-1);
  transition: box-shadow 0.3s var(--ease);
}
.plans__card--featured { box-shadow: var(--lift-2); }
.plans__card:hover { box-shadow: var(--lift-2); }
/* The plan you are on is pressed into the surface rather than raised off it —
   the same way every other selected thing on the site reads. */
.plans__card.is-current {
  box-shadow: var(--press-1);
  background: var(--paper);
}
.plans__flag {
  position: absolute;
  top: 14px; right: 16px;
  font-family: var(--font-display);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blue-ink);
  padding: var(--space-2) var(--space-5);
  border-radius: var(--r-pill);
  background: var(--blue-soft);
}
.plans__badge {
  font-family: var(--font-display);
  font-size: var(--fs-1); font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--blue-ink);
  margin-bottom: var(--space-4);
}
/* Once this card is the current one its badge has nothing left to sell. */
.plans__card.is-current .plans__badge { visibility: hidden; }
.plans__name { font-family: var(--font-display); font-weight: 700; font-size: 1.15rem; color: var(--text-dark); }
.plans__price {
  font-family: var(--font-display); font-weight: 700; font-size: 2rem;
  color: var(--text-dark); line-height: 1.1; margin-top: var(--space-2);
}
.plans__price span { font-size: var(--fs-11); font-weight: 600; color: var(--text-dark-lo); margin-left: var(--space-1); }
.plans__cap { font-size: var(--fs-7); font-weight: 600; color: var(--blue-ink); margin-top: var(--space-3); }
.plans__features { display: flex; flex-direction: column; gap: var(--space-4); margin: 16px 0 20px; }
.plans__features li {
  position: relative;
  padding-left: var(--space-12);
  font-size: var(--fs-8);
  color: var(--text-dark-lo);
  line-height: 1.4;
}
/* A drawn tick rather than a bullet character, for the same reason as
   everywhere else on the site. */
.plans__features li::before {
  content: '';
  position: absolute;
  left: 0; top: 2px;
  width: 15px; height: 15px;
  background-color: var(--blue-ink);
  -webkit-mask: var(--icon-check) center / 12px 12px no-repeat;
  mask: var(--icon-check) center / 12px 12px no-repeat;
}
.plans__cta { margin-top: auto; }
/* Disabled because it is already yours, not because something is wrong — so
   it dims rather than looking broken, and stops inviting a click. */
.plans__cta:disabled {
  opacity: 0.55;
  cursor: default;
  box-shadow: var(--press-1);
  background: var(--paper);
  color: var(--text-dark-lo);
}
.plans__cta:disabled::before,
.plans__cta:disabled::after { opacity: 0.4; }
.plans__note { font-size: var(--fs-7); color: var(--text-dark-lo); min-height: 18px; margin-bottom: var(--space-9); }
.plans__note.is-error { color: #A64A08; }

@media (max-width: 720px) {
  /* Two plans side by side stop being readable well before the panel does. */
  .plans { grid-template-columns: 1fr; }
}

/* ===================================================================
   BREATHING ROOM

   Soft UI needs more space than the bordered version it replaced. A
   border occupies one pixel; these shadows bleed about nine in every
   direction, so a 20px gap between two fields now reads as roughly
   eleven of actual clear space and everything looks packed. The gaps
   below are the old ones plus enough to clear the shadows.
=================================================================== */

/* --- Forms ----------------------------------------------------------------- */
.contact__form { gap: var(--space-13); padding: 34px; }
.contact__form label { gap: 11px; }
.form-row { gap: var(--space-11); }
.contact__form input,
.contact__form textarea,
.contact__form select { padding: 15px var(--space-8); }
.contact__form textarea { min-height: 108px; line-height: 1.5; }

/* Checkbox rows: the box and its text were close enough to read as one
   smudge at a glance, and the rows sat right on top of each other. */
.contact__tos,
.wiz__terms,
.sms__selectall {
  display: flex;
  align-items: flex-start;
  gap: var(--space-7);
  line-height: 1.55;
  margin: 4px 0;
}
.contact__tos input[type="checkbox"],
.wiz__terms input[type="checkbox"],
.sms__selectall input[type="checkbox"] { margin-top: var(--space-1); }
.contact__consent { margin: 2px 0 6px; line-height: 1.55; }

/* The submit button was flush against the last checkbox. */
.btn--full { margin-top: var(--space-7); }

/* --- Dashboard panels ------------------------------------------------------ */
.dash__card { padding: var(--space-12) var(--space-13); margin-bottom: var(--space-10); }
.dash__card-label { margin-bottom: var(--space-4); }
.dash__card-actions { gap: var(--space-7); margin-top: var(--space-8); }
.setup__label { margin-bottom: var(--space-7); }
.setup__field { display: flex; flex-direction: column; gap: 11px; margin-bottom: var(--space-11); }

/* --- Groups of buttons ----------------------------------------------------- */
/* Soft buttons sitting shoulder to shoulder merge into one bar; their
   shadows overlap and the gap between them disappears. */
.numline__actions { gap: var(--space-7); }
.wiz__choices { gap: var(--space-7); }
.wiz__actions { gap: var(--space-9); margin-top: 30px; }
.bridge__choice { gap: var(--space-8); }
.contact__authtabs { gap: var(--space-6); margin-bottom: var(--space-11); }
.sms__tabs { gap: var(--space-6); margin-bottom: var(--space-12); }
.results__range { gap: var(--space-3); padding: var(--space-2); }
.hero__ctas { gap: var(--space-10); }
.dash__nav { gap: var(--space-4); }

/* --- Lists and rows -------------------------------------------------------- */
.plans__features { gap: 11px; }
.dash__todo-list { gap: var(--space-3); }
.dash__todo-row { padding: 11px var(--space-5); gap: var(--space-6); }
.faq__list { gap: var(--space-6); }
.sms-threads__list { gap: var(--space-5); }
.sms-thread { padding: var(--space-7) var(--space-8); }
.results__stats { gap: var(--space-8); }
.results__stat { padding: var(--space-9) var(--space-10); }

/* --- The setup wizard ------------------------------------------------------ */
.wiz__card { padding: var(--space-16) var(--space-16) 34px; }
.wiz__field { margin-top: var(--space-13); }
.wiz__help { margin-top: var(--space-5); line-height: 1.55; }

@media (max-width: 620px) {
  /* Tighter on a phone, but still clear of the shadows. */
  .contact__form { gap: var(--space-11); padding: var(--space-12); }
  .dash__card { padding: var(--space-10); margin-bottom: var(--space-8); }
  .wiz__card { padding: var(--space-14) var(--space-11) var(--space-13); }
  .hero__ctas { gap: var(--space-7); }
}

/* The setup form's own gap only reaches the panels it contains, not the fields
   inside them — those sat in a plain block with nothing between them at all,
   which is why the form read as one solid stack however much the form gap was
   raised. Scoped to this form so the panels outside it keep their own layout. */
.contact__form .dash__panel.is-active {
  display: flex;
  flex-direction: column;
  gap: var(--space-12);
}
/* Cards carry their own bottom margin for the block layout they were built
   for; inside a gapped column that would double up. */
.contact__form .dash__panel .dash__card { margin-bottom: 0; }
/* Same double-up as above: .results, .setup__number and .numline each carry
   their own margin from when they sat outside the gapped panel. */
.contact__form .dash__panel .results,
.contact__form .dash__panel .setup__number,
.contact__form .dash__panel .numline,
.contact__form .dash__panel .setup__transfer { margin-top: 0; margin-bottom: 0; }

/* ===================================================================
   LIQUID GLASS — the wizard's controls

   Glass only works where there is something behind it to bend. On the
   flat light pages it would be an expensive way to draw nothing; over
   the starfield it is the right material, so it lives here and the rest
   of the site stays matte. That split is also how iOS 26 works —
   content opaque, controls glass — rather than two languages fighting.

   Four things make it read as glass rather than a tinted box:
     the blur behind it, a specular line where the light hits the top
     edge, a cool/warm split at the rim standing in for the chromatic
     aberration a real shader would do, and a gloss falling down the
     upper half.
=================================================================== */
.wiz-body .wiz__choice,
.wiz-body .wiz__route,
.wiz-body .wiz__calbtn,
.wiz-body .btn--solid {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border: 1px solid rgba(255,255,255,0.16);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  backdrop-filter: blur(16px) saturate(180%);
  transition:
    background 0.3s var(--ease),
    box-shadow 0.3s var(--ease),
    border-color 0.3s var(--ease),
    transform 0.3s var(--ease-spring);
}

/* Unselected: barely there, letting the stars through. */
.wiz-body .wiz__choice,
.wiz-body .wiz__route,
.wiz-body .wiz__calbtn {
  background: rgba(255,255,255,0.06);
  box-shadow:
    /* specular — the light along the top edge */
    inset 0 1px 0 rgba(255,255,255,0.4),
    inset 0 -1px 0 rgba(255,255,255,0.05),
    /* the RGB split, one colour to each side of the rim */
    -1px 0 0 rgba(120,190,255,0.16),
    1px 0 0 rgba(255,150,220,0.12),
    /* the shadow it casts on what is behind it */
    0 10px 24px -10px rgba(0,0,0,0.7);
}

/* The gloss: a highlight falling down the upper half, brightest at the
   top-left where the specular line starts. */
.wiz-body .wiz__choice::before,
.wiz-body .wiz__route::before,
.wiz-body .wiz__calbtn::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    160deg,
    rgba(255,255,255,0.22) 0%,
    rgba(255,255,255,0.06) 42%,
    rgba(255,255,255,0) 60%
  );
  pointer-events: none;
}

.wiz-body .wiz__choice:hover,
.wiz-body .wiz__route:hover,
.wiz-body .wiz__calbtn:hover {
  background: rgba(255,255,255,0.11);
  border-color: rgba(255,255,255,0.26);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.55),
    inset 0 -1px 0 rgba(255,255,255,0.07),
    -1px 0 0 rgba(120,190,255,0.26),
    1px 0 0 rgba(255,150,220,0.2),
    0 14px 30px -10px rgba(0,0,0,0.75);
}

/* Chosen: the glass takes the accent and thickens, rather than going
   flat. The rim brightens on the blue side, which is what a real shader
   does when the surface tints. */
.wiz-body .wiz__choice.is-active {
  background: rgba(47,111,255,0.30);
  border-color: rgba(150,190,255,0.5);
  color: #fff;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.6),
    inset 0 -8px 18px -8px rgba(10,40,120,0.6),
    -1px 0 0 rgba(150,215,255,0.4),
    1px 0 0 rgba(190,150,255,0.3),
    0 12px 28px -10px rgba(20,60,180,0.6);
}

/* Pressed: the gloss compresses and the shadow pulls in, so it reads as
   the glass being pushed rather than merely darkening. */
.wiz-body .wiz__choice:active,
.wiz-body .wiz__route:active,
.wiz-body .wiz__calbtn:active {
  transform: scale(0.98);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.25),
    inset 0 6px 14px -6px rgba(0,0,0,0.6),
    0 4px 10px -6px rgba(0,0,0,0.7);
}

/* The Continue button: the same material, carrying the accent. */
/* Same contrast constraint as the light-page CTA: composited over the wizard's
   dark ground, the old light stop landed at 4.07:1 against the white label.
   These stops composite to 4.74:1 and better while keeping the glass look. */
/* Its gloss is the first background layer rather than a ::before like the
   other glass controls: ::before is the arrow in the button's badge, and
   using it for the gloss left Continue with an empty circle where the arrow
   belongs. */
.wiz-body .btn--solid {
  background:
    linear-gradient(160deg, rgba(255,255,255,0.22) 0%, rgba(255,255,255,0.06) 42%, rgba(255,255,255,0) 60%),
    linear-gradient(160deg, rgba(70,120,235,0.9), rgba(38,88,220,0.92));
  border-color: rgba(160,195,255,0.45);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.5),
    inset 0 -10px 22px -10px rgba(10,35,110,0.7),
    -1px 0 0 rgba(150,215,255,0.35),
    1px 0 0 rgba(200,150,255,0.28),
    0 16px 34px -14px rgba(20,60,180,0.75);
}
.wiz-body .btn--solid:hover {
  background:
    linear-gradient(160deg, rgba(255,255,255,0.22) 0%, rgba(255,255,255,0.06) 42%, rgba(255,255,255,0) 60%),
    linear-gradient(160deg, rgba(70,120,235,0.9), rgba(48,100,235,0.94));
  border-color: rgba(180,210,255,0.6);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.62),
    inset 0 -10px 22px -10px rgba(10,35,110,0.7),
    -1px 0 0 rgba(150,215,255,0.45),
    1px 0 0 rgba(200,150,255,0.35),
    0 20px 42px -14px rgba(20,60,180,0.8);
}
.wiz-body .btn--solid:active {
  transform: scale(0.985);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.3),
    inset 0 8px 20px -8px rgba(8,28,90,0.75),
    0 6px 14px -8px rgba(20,60,180,0.6);
}

/* The card the controls sit on is glass too, one step calmer so the
   controls still read as sitting on top of it. */
.wiz-body .wiz__card {
  -webkit-backdrop-filter: blur(26px) saturate(150%);
  backdrop-filter: blur(26px) saturate(150%);
  border: 1px solid rgba(255,255,255,0.10);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.16),
    0 40px 90px -30px rgba(0,0,0,0.8);
}

/* Where the backdrop cannot be blurred, the fills have to stand on their
   own or the controls disappear into the starfield. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .wiz-body .wiz__choice,
  .wiz-body .wiz__route,
  .wiz-body .wiz__calbtn { background: rgba(24,34,58,0.9); }
  .wiz-body .wiz__card { background: rgba(10,15,28,0.96); }
}

@media (prefers-reduced-motion: reduce) {
  .wiz-body .wiz__choice,
  .wiz-body .wiz__route,
  .wiz-body .wiz__calbtn,
  .wiz-body .btn--solid { transition: none; }
}

/* ===================================================================
   FIXES — voice picker, and buttons whose text ran under their arrow
=================================================================== */

/* The filter bar and the voice list are both children of .voice-picker, which
   was a two-column grid — so the bar sat BESIDE the list, stretched to its
   520px height, and its buttons stretched with it into the tall ovals. The bar
   belongs above the list, which is what its own bottom margin always assumed. */
.voice-picker {
  display: block;
  grid-template-columns: none;
}
/* And regardless of what contains it, the chips size to their own content. A
   flex line stretches its children by default, which is what made them tall
   the moment the container was. */
.voice-filter {
  align-items: flex-start;
  align-content: flex-start;
  gap: var(--space-5);
  margin-bottom: var(--space-10);
}
.voice-filter__btn { flex: 0 0 auto; align-self: flex-start; }

/* The list has to fit a phone. minmax(255px, 1fr) is wider than the column it
   gets at 390px once the panel padding is taken off, which is why this section
   ran wider than every other one. */
@media (max-width: 620px) {
  .voice-grid { grid-template-columns: 1fr; max-height: 420px; }
  .voice-card { padding: var(--space-6); }
}

/* .btn--solid and .btn--outline reserve 54px on the right for the arrow disc,
   which is absolutely positioned. Any button that overrides the padding puts
   its own text underneath that disc — which is what these were doing. They are
   compact utility buttons in a row, so they lose the arrow rather than the
   space. */
.numline__btn::before,
.numline__btn::after { content: none; }
.numline__btn { padding: 11px var(--space-9); }

/* The setup form wraps only three of the panels. On any of the others every
   one of its children is hidden, but the form itself still painted its card —
   34px of padding top and bottom and nothing between them, which is the empty
   slab that appeared above Your Agent. It now stands down when it has no
   panel to show. */
.dash-body .contact__form:not(:has(.dash__panel.is-active)) { display: none; }

/* Every panel the same width. The setup form is a card on the marketing page
   and in the review modal, where it should be — but in the dashboard it wraps
   three of the panels, so those three sat inside a second card, inset by its
   padding, while the other four ran full width. Three different section widths
   on one screen. Here the form is just a container; the cards inside it
   already provide the surface. */
.dash-body .contact__form {
  background: none;
  box-shadow: none;
  border: none;
  padding: 0;
}
/* A flex item will not shrink below its content unless told to, which is why
   the voice list — the widest content in any panel — pushed its panel wider
   than the screen instead of letting the cards wrap. */
.dash-body .contact__form .dash__panel.is-active,
.voice-picker,
.voice-grid,
.voice-card { min-width: 0; }
.voice-card__body { min-width: 0; }
.voice-card__name { overflow: hidden; text-overflow: ellipsis; }

/* The dashboard's main column is a flex item, and a flex item will not shrink
   below its own content unless told to. The voice list is the widest content
   on the site, so it was pushing the whole column past the width of the
   screen — which is why that one section measured wider than every other. */
.dash__main { min-width: 0; }

/* ===================================================================
   BUSINESS PLAN UNLOCK CELEBRATION — see js/account.js,
   playBusinessUnlockAnimation(), fired once on the reload right after a
   successful upgrade. Dark backdrop rather than the site's own paper tone,
   deliberately: this is a moment, not another panel.
=================================================================== */
.unlock-fx {
  position: fixed; inset: 0; z-index: 300;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--space-7); padding: var(--space-10); text-align: center;
  background: radial-gradient(circle at 50% 44%, rgba(28,19,0,0.94), rgba(6,5,2,0.98));
  cursor: pointer;
  animation: unlock-fx-in 0.35s ease both;
}
.unlock-fx.is-leaving { animation: unlock-fx-out 0.45s ease both; }
@keyframes unlock-fx-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes unlock-fx-out { to { opacity: 0; } }

.unlock-fx__burst { position: relative; width: 140px; height: 140px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.unlock-fx__ring {
  position: absolute; inset: 0; border-radius: 50%;
  border: 5px solid rgba(255,209,102,0.55);
  animation: unlock-ring 1.3s cubic-bezier(0.2,0.75,0.25,1) both;
}
@keyframes unlock-ring {
  0% { transform: scale(0.3); opacity: 0; border-width: 7px; }
  35% { opacity: 1; }
  100% { transform: scale(2.7); opacity: 0; border-width: 0.5px; }
}
.unlock-fx__badge {
  position: relative; width: 84px; height: 84px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(circle at 32% 26%, #FFEFC4, #FFD166 46%, #C99A1E 100%);
  color: #4A3400;
  box-shadow: 0 0 44px 10px rgba(255,209,102,0.55), inset 0 1px 3px rgba(255,255,255,0.65);
  transform: scale(0);
  animation: unlock-badge-in 0.65s cubic-bezier(0.34,1.6,0.5,1) both 0.15s;
}
@keyframes unlock-badge-in { to { transform: scale(1); } }

/* One span per spark; --a (angle) and --d (travel distance) are set inline
   per span in the markup so the burst reads as a ring, not a single line. */
.unlock-fx__spark {
  position: absolute; top: 50%; left: 50%; width: 6px; height: 6px; border-radius: 50%;
  background: #FFD166; transform: translate(-50%,-50%);
  opacity: 0;
  animation: unlock-spark 0.9s ease-out both;
}
@keyframes unlock-spark {
  0% { transform: translate(-50%,-50%) rotate(var(--a)) translateX(0) scale(1); opacity: 1; }
  100% { transform: translate(-50%,-50%) rotate(var(--a)) translateX(var(--d)) scale(0.2); opacity: 0; }
}

.unlock-fx__title {
  font-family: var(--font-display); font-weight: 700; font-size: clamp(1.6rem, 4.5vw, 2.4rem);
  color: #FFEFC4; letter-spacing: 0.01em;
  opacity: 0; animation: unlock-text-in 0.55s ease both 0.35s;
}
.unlock-fx__sub {
  font-size: var(--fs-13); color: rgba(255,239,196,0.72);
  opacity: 0; animation: unlock-text-in 0.55s ease both 0.52s;
}
@keyframes unlock-text-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }

@media (prefers-reduced-motion: reduce) {
  .unlock-fx, .unlock-fx__ring, .unlock-fx__badge, .unlock-fx__spark, .unlock-fx__title, .unlock-fx__sub {
    animation: none !important; opacity: 1; transform: none;
  }
}
.dash__content { min-width: 0; }

/* ===================================================================
   GLASSMORPHISM — site surfaces

   The elevation tokens give every raised thing its shadow. This block
   gives them the material: a frosted fill plus a backdrop blur.

   The rule that keeps it legible: the blur does the work, and the fill is
   opaque enough that text behind a pane turns into a wash instead of
   staying readable. Overlays that sit ON TOP of content (menus, popovers)
   go higher still, because a dropdown you can read the page through is
   the single worst version of this effect.

   Kept opaque on purpose: anything carrying a photo (.decay__image), and
   text inputs, which need maximum legibility.
=================================================================== */
.hero-card,
.decay__stats,
.pipeline__clock,
.showcase__card,
.pillar,
.testimonial,
.contact__form,
.pricing__card,
.roi__panel,
.results,
.assurance__item,
.dash__card,
.voice-card,
.sms-thread,
.sms-threads__convo {
  background: var(--glass-sheen), var(--glass-body);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  /* Transparent, not absent: the 1px still shapes the box, but the rim is
     painted in ::before instead, where it can vary around the perimeter. */
  border: 1px solid transparent;
  box-shadow: var(--glass-ring), var(--shadow-soft), var(--glass-bevel);
}

/* ---- the refracting edge ------------------------------------------
   Real glass is thickest at its rim, so the background bends there. CSS
   cannot refract, but it can get most of the way: a ring at the perimeter
   with its OWN backdrop-filter, brighter and blurred differently from the
   middle of the pane. The two-layer mask with composite:exclude is what
   limits the ring to the outer band instead of filling the whole shape.

   The ring also carries the rim itself, as a conic gradient rather than a
   border. That is the part a stroke cannot do: a border is one value the
   whole way round, and a real edge is bright where the light reaches it,
   dark where it turns away, and continuous in between. Light from the
   upper left, so the sweep runs white across the top, tips over into a
   faint dark on the lower right — which is also what keeps the pane's
   boundary readable there without a hairline — and returns as bounce.
   Two rings, not one: this narrow one for the rim, a wider fainter one in
   ::after to carry the bend inward, because a lens band that simply stops
   becomes its own hard line. */
/* The three dashboard popovers are deliberately NOT in this list. They are
   already position:absolute at their own definitions, which establishes a
   containing block for the rings just as well — and this rule sits later in
   the file at equal specificity, so naming them here silently overrode that
   absolute and dropped all three back into normal flow. On a phone the
   checklist then widened the topbar to 720px inside a 390px viewport and
   the whole page zoomed out to fit. */
/* .pipeline__clock is deliberately NOT in this list, for the same reason the
   dashboard popovers are not: it declares its own position (absolute on
   desktop, in-flow on mobile) and this rule sits later at equal specificity,
   so naming it here silently overrode that. The "12 SEC" readout is meant to
   shrink-wrap its text in the section's top right; forced into normal flow it
   became a full-width block laid across the progress track and the stages. */
.hero-card, .decay__stats, .showcase__card, .pillar,
.testimonial, .contact__form, .pricing__card, .roi__panel, .results,
.assurance__item, .dash__card, .voice-card, .sms-thread,
.sms-threads__convo { position: relative; }

.hero-card::before, .decay__stats::before, .pipeline__clock::before,
.showcase__card::before, .pillar::before, .testimonial::before,
.contact__form::before, .pricing__card::before, .roi__panel::before,
.results::before, .assurance__item::before, .dash__card::before,
.voice-card::before, .sms-thread::before, .sms-threads__convo::before,
.dash__settings-menu::before, .dash__todo-menu::before,
.dash__profile-menu::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: -1;
  padding: 1.5px;                /* how wide the rim band is */
  background: var(--glass-lens);
  -webkit-backdrop-filter: var(--glass-rim-filter);
  backdrop-filter: var(--glass-rim-filter);
  -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;
}

/* The falloff. Picks up exactly where the rim ends and carries the same
   sweep at a fraction of its strength, plus a gentler bend, so the edge
   steps down instead of stopping. A band that simply ends is its own hard
   line — which is the whole problem the sweep is here to solve, just moved
   a few pixels inward. Two rings rather than one smooth ramp because
   masking is applied after filtering (so a blur cannot soften a ring's own
   mask cut) and a radial mask cannot follow a rounded rectangle. */
.hero-card::after, .decay__stats::after, .pipeline__clock::after,
.showcase__card::after, .pillar::after, .testimonial::after,
.contact__form::after, .pricing__card::after, .roi__panel::after,
.results::after, .assurance__item::after, .dash__card::after,
.voice-card::after, .sms-thread::after, .sms-threads__convo::after,
.dash__settings-menu::after, .dash__todo-menu::after,
.dash__profile-menu::after {
  content: '';
  position: absolute;
  inset: 1.5px;
  border-radius: inherit;
  pointer-events: none;
  z-index: -1;
  padding: 5px;
  opacity: 0.28;
  background: var(--glass-lens);
  -webkit-backdrop-filter: blur(2px) brightness(1.02);
  backdrop-filter: blur(2px) brightness(1.02);
  -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;
}
/* Content sits above the lens ring — but NOT by positioning every child.
   This used to be `<container> > * { position: relative; z-index: 1 }`, which
   is 0-1-0 and sits late in the file, so it silently outranked any child that
   declared its own position. .pricing__badge is absolute at top:-12px so the
   ribbon hangs off the card's edge; that rule put it back in normal flow and
   applied the -12px as a nudge instead.

   The rings carry z-index:-1 instead. Every one of these surfaces declares a
   backdrop-filter, which makes it a stacking context, so a negative-z child
   paints above the surface's own background but below its in-flow content —
   the exact order the old rule was faking, with nothing to clobber. */

/* Anything that floats OVER content has to occlude it. Near-opaque fill,
   stronger blur, and a real shadow so it reads as a separate layer. */
.dash__settings-menu,
.dash__todo-menu,
.dash__profile-menu {
  background: var(--glass-fill-2);
  -webkit-backdrop-filter: blur(40px) saturate(150%);
  backdrop-filter: blur(40px) saturate(150%);
  border: 1px solid transparent;
  box-shadow: var(--glass-ring), var(--lift-3);
}

/* Inputs: near-opaque, so typed text never competes with whatever is
   behind the field. */
.contact__form input,
.contact__form textarea,
.contact__form select,
.dash__card input,
.dash__card textarea,
.dash__card select {
  background: rgba(255,255,255,0.86);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}

/* ---- dark contexts -------------------------------------------------
   Same idea inverted: a light sheer over a dark ground, and the same
   near-clear body — a dark page needs the pane to lift slightly, which the
   sweep does without turning it back into a painted card. */
[data-theme="dark"] .dash-body,
.wiz-body,
.admin-login {
  --glass-sheen: linear-gradient(118deg,
    transparent 26%, rgba(255,255,255,0.05) 38%,
    rgba(255,255,255,0.01) 47%, transparent 60%);
  /* Held a little higher than the light theme's body. A pane this sheer on
     a dark page stops separating from it altogether, and the dashboard
     needs its panels to still read as panels. */
  --glass-body:  linear-gradient(160deg,
    rgba(150,180,255,0.08), rgba(150,180,255,0.03));
  --glass-bevel:
    inset 0 1px 0 0 rgba(255,255,255,0.20),
    inset 0 -1.5px 2px -1px rgba(255,255,255,0.09),
    inset 0 0 16px -10px rgba(0,0,0,0.40);
  --glass-fill-2: rgba(28,36,58,0.90);
  --glass-border: rgba(255,255,255,0.22);
  /* Far gentler than the light default — see the note there. */
  --glass-rim-filter: blur(4px) brightness(1.14) saturate(135%);
  /* Same sweep, pulled down and with no dark half — a dark rim on a dark
     page separates nothing, so the shadow side simply fades out. */
  --glass-lens: conic-gradient(from 0deg at 50% 50%,
    rgba(255,255,255,0.24)   0deg,
    rgba(255,209,102,0.11)  42deg,   /* amber fringe */
    rgba(255,255,255,0.05)  92deg,
    rgba(255,255,255,0.01) 150deg,
    rgba(255,255,255,0.02) 206deg,
    rgba(120,160,255,0.13) 248deg,   /* blue fringe */
    rgba(255,255,255,0.15) 300deg,
    rgba(255,255,255,0.24) 360deg);
  --glass-ring:   0 1px 4px rgba(0,0,0,0.38);

  --lift-1: 0 4px 14px -6px rgba(0,0,0,0.55);
  --lift-2: 0 10px 28px -10px rgba(0,0,0,0.62);
  --lift-3: 0 22px 52px -16px rgba(0,0,0,0.72);
  --press-1: inset 0 1px 4px rgba(0,0,0,0.5);
  --press-2: inset 0 2px 7px rgba(0,0,0,0.6);
  --shadow-soft: 0 8px 24px -10px rgba(0,0,0,0.55);
}

[data-theme="dark"] .dash-body .dash__card,
[data-theme="dark"] .dash-body .voice-card,
[data-theme="dark"] .dash-body .sms-thread,
[data-theme="dark"] .dash-body .results,
/* NOT .dash-body .contact__form — on the dashboard that is a full-height
   wrapper around every panel, not a card. See the note at the end of the
   file; the .dash__card panes inside it carry the glass instead. */
.admin-login .contact__form {
  background: var(--glass-sheen), var(--glass-body);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid transparent;
}
/* Dark overlays get a solid-ish panel colour rather than a white sheer —
   a white sheer over dark stays see-through no matter how much blur is
   behind it. */
[data-theme="dark"] .dash-body .dash__settings-menu,
[data-theme="dark"] .dash-body .dash__todo-menu,
[data-theme="dark"] .dash-body .dash__profile-menu {
  background: var(--glass-fill-2);
}
/* The dark rim filter now rides on --glass-rim-filter, set once in the
   dark-context block above, so every glass surface picks it up — including
   the ones the hand-maintained ::before list here used to miss (the profile
   menu among them, which is why it wore a blue focus ring). */
[data-theme="dark"] .dash-body .dash__card input,
[data-theme="dark"] .dash-body .dash__card textarea,
[data-theme="dark"] .dash-body .dash__card select,
.admin-login .contact__form input {
  background: rgba(255,255,255,0.08);
}

/* Glass depends on backdrop-filter. Where it is unsupported, fall back to
   an opaque surface so nothing turns into unreadable haze. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .hero-card, .decay__stats, .pipeline__clock, .showcase__card, .pillar,
  .testimonial, .contact__form, .pricing__card, .roi__panel, .results,
  .assurance__item, .dash__card, .voice-card, .sms-thread,
  .sms-threads__convo { background: var(--paper-2); }
  .dash__settings-menu, .dash__todo-menu, .dash__profile-menu { background: #fff; }
}

/* ---- the dashboard's form wrapper is not a card ---------------------
   .contact__form is a real pane on the marketing page and in the admin
   login, but on the dashboard it wraps every panel at full height. Giving
   it the glass material drew a 1,773px border down each side of the
   column. The .dash__card panes inside it are the actual objects, so the
   wrapper goes back to being invisible here. */
.dash-body .contact__form {
  background: transparent;
  border: 0;
  box-shadow: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.dash-body .contact__form::before,
.dash-body .contact__form::after { display: none; }

/* ===================================================================
   NO GLASS ON THE DASHBOARD
   The marketing page keeps it — that is where the material is doing
   persuasive work. The dashboard is a tool someone uses between jobs,
   often one-handed on a phone, and translucency there costs legibility
   for decoration: every panel picks up whatever is scrolling behind it.
   Panels here are solid surfaces with a hairline and a shadow.

   Scoped to .dash-body so nothing on the marketing page is touched.
=================================================================== */
.dash-body .dash__card,
.dash-body .voice-card,
.dash-body .sms-thread,
.dash-body .sms-threads__convo,
.dash-body .results,
.dash-body .assurance__item,
.dash-body .dash__settings-menu,
.dash-body .dash__todo-menu,
.dash-body .dash__profile-menu {
  background: var(--paper-2);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  border: 1px solid rgba(var(--ink-rgb), 0.10);
  box-shadow: 0 1px 2px rgba(19,22,30,0.05), 0 8px 24px -14px rgba(19,22,30,0.18);
}
/* The lens rings and their falloff are the glass. Both go. */
.dash-body .dash__card::before,   .dash-body .dash__card::after,
.dash-body .voice-card::before,   .dash-body .voice-card::after,
.dash-body .sms-thread::before,   .dash-body .sms-thread::after,
.dash-body .sms-threads__convo::before, .dash-body .sms-threads__convo::after,
.dash-body .results::before,      .dash-body .results::after,
.dash-body .assurance__item::before, .dash-body .assurance__item::after,
.dash-body .dash__settings-menu::before, .dash-body .dash__settings-menu::after,
.dash-body .dash__todo-menu::before,     .dash-body .dash__todo-menu::after,
.dash-body .dash__profile-menu::before,  .dash-body .dash__profile-menu::after {
  display: none;
}
/* Menus float over content, so they get a heavier shadow rather than the
   blur that used to separate them. */
.dash-body .dash__settings-menu,
.dash-body .dash__todo-menu,
.dash-body .dash__profile-menu {
  box-shadow: 0 18px 44px -18px rgba(19,22,30,0.42);
}
/* The topbar was frosted over the scrolling column. Solid now, or the
   content reads through it. */
.dash-body .dash__topbar {
  background: var(--paper-2);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

[data-theme="dark"] .dash-body .dash__card,
[data-theme="dark"] .dash-body .voice-card,
[data-theme="dark"] .dash-body .sms-thread,
[data-theme="dark"] .dash-body .sms-threads__convo,
[data-theme="dark"] .dash-body .results,
[data-theme="dark"] .dash-body .assurance__item,
[data-theme="dark"] .dash-body .dash__settings-menu,
[data-theme="dark"] .dash-body .dash__todo-menu,
[data-theme="dark"] .dash-body .dash__profile-menu {
  background: var(--paper-2);
  border-color: rgba(255,255,255,0.09);
  box-shadow: 0 1px 2px rgba(0,0,0,0.4), 0 10px 28px -16px rgba(0,0,0,0.6);
  /* Repeated at this specificity on purpose. The dark glass rule is
     [data-theme] .dash-body .dash__card — 0-3-0 — so the none set in the
     0-2-0 block above loses to it, and the cards kept blurring the page
     behind a background that is now opaque anyway: invisible, and still
     paying for a GPU pass on every scroll. */
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
[data-theme="dark"] .dash-body .dash__settings-menu,
[data-theme="dark"] .dash-body .dash__todo-menu,
[data-theme="dark"] .dash-body .dash__profile-menu {
  box-shadow: 0 20px 48px -18px rgba(0,0,0,0.75);
}

/* The mobile nav pill is the marketing header's pill, value for value —
   same tint, blur, saturation, rim, radius and shadow. Not "similar to":
   copied from .nav__inner, so the two cannot drift apart. It is the one
   place on the dashboard that keeps translucency, because it is the one
   element that is meant to read as floating above the page rather than
   being part of it.

   The old lens rings still go. Those were the liquid-glass treatment, and
   they are what made the edge look wet rather than like a thin rim. */
@media (max-width: 900px) {
  .dash-body .dash__sidebar {
    background: rgba(8,10,18,0.72);
    -webkit-backdrop-filter: blur(20px) saturate(160%);
    backdrop-filter: blur(20px) saturate(160%);
    border: 1px solid rgba(255,255,255,0.09);
    border-radius: var(--r-pill);
    box-shadow:
      0 12px 30px -14px rgba(0,0,0,0.55),
      inset 0 1px 0 rgba(255,255,255,0.05);
  }
  .dash-body .dash__sidebar::before,
  .dash-body .dash__sidebar::after { display: none; }

  /* Where the backdrop cannot be blurred the pill still has to occlude,
     or the column scrolls straight through it. */
  @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .dash-body .dash__sidebar { background: var(--navpill-solid); }
  }

  /* Nested corners read as wrong unless they are concentric: the inner
     radius has to be the outer radius minus the gap between them. A fixed
     16px against a ~28px stadium was neither, so the marker's corners cut
     across the pill's curve instead of following it — and being full
     height put them right against the pill's tightest bend, which is
     where that mismatch shows most.

     The reference is not concentric either, though — measured off it, the
     marker's corners sit at roughly 70% of half its height, so it is a
     true squircle against a stadium. What makes that work there is the
     clearance: it has about a third of the bar's height free above and
     below, so its corners never come near the pill's bend. Ours was full
     height and had none, which is the actual defect. Inset first, then a
     radius that reads as a squircle at the height that leaves. */
  .dash-body .dash__nav-chip {
    /* No vertical inset. The bar is 6px of padding plus a 1px border, so a
       cell already sits 7px in from the left and right edges; any inset on
       top of that made the marker further from the top and bottom than
       from the sides. Full height gives an even 7px all round.

       Safe now only because the marker is a stadium: a stadium inset
       evenly inside a stadium is concentric, so at full height its curve
       follows the pill instead of cutting across it, which is exactly what
       the earlier 12px version did. */
    top: 0;
    bottom: 0;
    border-radius: var(--r-pill);
    background: rgba(255,255,255,0.16);
    box-shadow: none;
  }
  /* The fallback path, where :has() is missing and the active item paints
     its own background. Same shape, or those browsers keep the old one.
     Inset comes from margin here — the item is a flex child, not
     absolutely positioned like the chip. */
  .dash-body .dash__nav-item.is-active {
    background: rgba(255,255,255,0.16);
    border-radius: var(--r-pill);
  }
  @supports selector(:has(*)) {
    .dash-body .dash__nav-item.is-active { background: none; }
  }
}

/* The nudge bubble floats over the dashboard column too, and its panel
   tint is translucent — it was sitting on top of the "no calls yet" copy
   and both were readable through each other. Solid here. */
.dash-body .chat-nudge {
  background: var(--paper-2);
  border-color: rgba(var(--ink-rgb), 0.12);
  color: var(--text-dark);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: 0 14px 34px -16px rgba(19,22,30,0.45);
}
[data-theme="dark"] .dash-body .chat-nudge {
  border-color: rgba(255,255,255,0.10);
  box-shadow: 0 16px 40px -16px rgba(0,0,0,0.7);
}

/* ---- the nav marker has to know about the gap ----------------------
   The chip's geometry assumed a gapless row: width 100%/5, and a step of
   100% per cell. That was true when it was written, but
   `.dash__nav { gap: var(--space-4) }` sits later in this file at equal
   specificity and quietly reinstated an 8px gap. The chip then measured
   52.4px against 46px cells and stepped 52.4px instead of 54px, so the
   error compounded along the row — dead centre in the middle, visibly
   off at both ends.

   Deriving both numbers from the gap instead of a fixed 100% means the
   marker stays centred whatever the gap becomes. Percentages in
   `translate` resolve against the element's own width, so one step is
   exactly one cell plus one gap. */
@media (max-width: 900px) {
  .dash-body .dash__nav {
    --nav-gap: var(--space-4);
    --nav-count: 5;
    gap: var(--nav-gap);
  }
  .dash-body .dash__nav-chip {
    width: calc((100% - (var(--nav-count) - 1) * var(--nav-gap)) / var(--nav-count));
    translate: calc(var(--nav-i, 0) * (100% + var(--nav-gap)));
  }
}

/* ===================================================================
   DASHBOARD TOOLBAR
   Jump to a section, narrow the sidebar, and ask the assistant.
=================================================================== */
.dash__tools {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin-right: var(--space-4);
}
.dash__tool {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: 0;
  border-radius: 9px;
  background: none;
  color: var(--text-dark-lo);
  cursor: pointer;
  transition: background 0.18s, color 0.18s;
  -webkit-tap-highlight-color: transparent;
}
.dash__tool svg { width: 18px; height: 18px; }
.dash__tool:hover:not(:disabled) {
  background: rgba(var(--ink-rgb), 0.07);
  color: var(--text-dark);
}
.dash__tool[aria-pressed="true"] {
  background: rgba(var(--ink-rgb), 0.09);
  color: var(--text-dark);
}
/* .dash__tool:disabled and .dash__tool-sep lived here for the back/forward
   arrows and their divider. Both are gone — the sidebar already shows every
   destination, so a history of which panel came before was a browser idiom in
   a place that never needed one. */

.dash__tool-menu {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 60;
  min-width: 210px;
  display: flex;
  flex-direction: column;
  padding: var(--space-2);
  background: var(--paper-2);
  border: 1px solid rgba(var(--ink-rgb), 0.10);
  border-radius: var(--r-sm);
  box-shadow: 0 18px 44px -18px rgba(19,22,30,0.42);
}
.dash__tool-menu-item {
  text-align: left;
  border: 0;
  background: none;
  border-radius: 8px;
  padding: 9px var(--space-5);
  font: inherit;
  font-size: var(--fs-7);
  color: var(--text-dark);
  cursor: pointer;
}
.dash__tool-menu-item:hover { background: rgba(var(--ink-rgb), 0.06); }


@media (prefers-reduced-motion: reduce) {
  .dash__sidebar { transition: none; }
}

/* The toolbar is desktop furniture. On mobile the pill already navigates
   and there is no sidebar left to narrow, so the whole thing is off and the
   rail variable is cleared — otherwise a rail set on desktop would follow
   the account down to a phone and squeeze the nav pill. */
@media (max-width: 900px) {
  .dash__tools { display: none; }
}

/* ---- resizable sidebar ---------------------------------------------
   The grab strip sits on the sidebar's right edge. Only 6px wide but it
   takes the full height, which is what makes it easy to hit without
   putting a visible bar in the layout. */
.dash__resizer {
  position: absolute;
  top: 0;
  right: -3px;
  bottom: 0;
  width: 6px;
  cursor: col-resize;
  z-index: 5;
  background: transparent;
  transition: background 0.15s;
}
.dash__resizer:hover,
.dash__resizer:focus-visible,
.is-resizing .dash__resizer { background: var(--blue); }
.dash__resizer:focus-visible { outline: none; }
/* While dragging, nothing else should react to the pointer — text
   selecting mid-drag is the usual way a resize handle feels broken. */
.is-resizing { user-select: none; cursor: col-resize; }
.is-resizing .dash__main { transition: none; }
.is-resizing .dash__sidebar { transition: none; }

/* Past the point where labels fit, the column becomes icons rather than
   clipping words in half. */
.dash-narrow .dash__sidebar .dash__brand span,
.dash-narrow .dash__sidebar .dash__nav-item span,
.dash-narrow .dash__sidebar .dash__back { display: none; }
.dash-narrow .dash__sidebar .dash__brand { justify-content: center; }
.dash-narrow .dash__nav-item { justify-content: center; padding-inline: 0; }

/* Desktop only: on mobile the sidebar is the floating pill. */
@media (max-width: 900px) {
  .dash__resizer { display: none; }
}

/* The mark must never be squeezed narrower than it is tall. The resizer's
   minimum already keeps it clear, but this makes the guarantee structural
   rather than a number someone could lower later. */
.dash__brand img { flex-shrink: 0; }

/* ===================================================================
   ADMIN SECTION  (dashboard panel, owner account only)
   Self-contained on the dashboard tokens, which .dash-body redefines
   per theme — so this reads correctly in light and dark without its
   own theme blocks.
=================================================================== */
.dash__panel-title { font-family: var(--font-display); font-weight: 600; font-size: 1.3rem; color: var(--text-dark); margin: 0; }
.dash__panel-sub { font-size: var(--fs-8); color: var(--text-dark-lo); margin: var(--space-3) 0 0; max-width: 60ch; line-height: 1.5; }
.btn--sm { padding: var(--space-4) var(--space-8); font-size: var(--fs-6); }
/* A compact button has no room for the arrow badge: .btn--solid/.btn--outline
   reserve 54px on the right for it, and the padding above takes that back, so
   the 32px disc landed on top of the label ("Refres(h)"). Same fix
   .numline__btn already uses. Anything else that shrinks a badged button's
   right padding has to drop the badge with it. */
.btn--sm::before,
.btn--sm::after { content: none; }

.admin-sec__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-8); flex-wrap: wrap; margin-bottom: var(--space-11); }
.admin-sec__head-actions { display: flex; align-items: center; gap: var(--space-6); flex-shrink: 0; }
.admin-sec__range { font-size: var(--fs-6); color: var(--text-dark-lo); display: inline-flex; align-items: center; gap: var(--space-4); }
.admin-sec__range select { font: inherit; color: var(--text-dark); background: var(--paper-2); border: 1px solid rgba(var(--ink-rgb),0.14); border-radius: var(--r-md); padding: var(--space-3) var(--space-6); }

.admin-sec__summary { font-size: var(--fs-10); color: var(--text-dark); line-height: 1.55; margin: 0 0 var(--space-11); padding: var(--space-8) var(--space-10); background: var(--paper-2); border: 1px solid rgba(var(--ink-rgb),0.08); border-left: 3px solid var(--blue); border-radius: var(--r-md); }

.admin-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-6); margin-bottom: var(--space-12); }
.admin-stat { text-align: center; padding: var(--space-9) var(--space-6); background: var(--paper-2); border: 1px solid rgba(var(--ink-rgb),0.08); border-radius: var(--r-md); }
.admin-stat__value { font-family: var(--font-display); font-weight: 700; font-size: 1.7rem; color: var(--text-dark); line-height: 1; font-variant-numeric: tabular-nums; }
.admin-stat__value.is-hot { color: var(--blue); }
.admin-stat__label { font-size: var(--fs-4); color: var(--text-dark-lo); margin-top: var(--space-4); }

.admin-search { position: relative; margin-bottom: var(--space-12); }
.admin-search__icon {
  position: absolute; left: var(--space-8); top: 50%; transform: translateY(-50%);
  width: 16px; height: 16px; color: var(--text-dark-lo); pointer-events: none;
}
.admin-search input {
  width: 100%; font: inherit; font-size: var(--fs-8); color: var(--text-dark);
  background: var(--paper-2); border: 1px solid rgba(var(--ink-rgb),0.14);
  border-radius: var(--r-md); padding: var(--space-6) var(--space-8) var(--space-6) 40px;
}
.admin-search input::placeholder { color: var(--text-dark-lo); }
.admin-search input:focus { outline: none; border-color: var(--blue); box-shadow: var(--focus-ring); }

/* Client-facing "Recent calls" list in the phone panel (reuses .admin-row). */
.calls-log { margin-bottom: var(--space-12); }
.calls-log__list { display: flex; flex-direction: column; }
.calls-log__badge {
  display: inline-block; padding: 1px 8px; border-radius: var(--r-pill);
  font-size: var(--fs-2); font-weight: 700; vertical-align: middle;
  background: rgba(var(--ink-rgb),0.08); color: var(--text-dark-lo);
}
.calls-log__badge.is-booked { background: rgba(46,160,90,0.15); color: #1f8a4c; }
.calls-log__call {
  flex-shrink: 0; margin-left: var(--space-5);
  padding: var(--space-3) var(--space-7); border-radius: var(--r-pill);
  border: 1px solid var(--blue); background: transparent; color: var(--blue);
  font: inherit; font-size: var(--fs-4); font-weight: 700; cursor: pointer;
}
.calls-log__call:hover { background: var(--blue); color: #fff; }
.calls-log__call:disabled { opacity: 0.6; cursor: default; }
.calls-log__status { margin-top: var(--space-6); font-size: var(--fs-8); min-height: 1.2em; }

.admin-sec__group { margin-bottom: var(--space-12); }
.admin-sec__group-head { display: flex; align-items: baseline; gap: var(--space-5); margin-bottom: var(--space-7); padding-bottom: var(--space-4); border-bottom: 1px solid rgba(var(--ink-rgb),0.10); }
.admin-sec__group-head h3 { font-family: var(--font-display); font-weight: 600; font-size: 1.02rem; color: var(--text-dark); margin: 0; }
.admin-sec__count { font-size: var(--fs-4); color: var(--text-dark-lo); font-variant-numeric: tabular-nums; }

.admin-list { display: flex; flex-direction: column; gap: var(--space-3); }
.admin-row { display: flex; align-items: center; gap: var(--space-8); padding: var(--space-7) var(--space-9); background: var(--paper-2); border: 1px solid rgba(var(--ink-rgb),0.08); border-radius: var(--r-md); }
.admin-row__main { flex: 1; min-width: 0; }
.admin-row__title { font-size: var(--fs-8); font-weight: 600; color: var(--text-dark); }
.admin-row__meta { font-size: var(--fs-5); color: var(--text-dark-lo); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; }
.admin-row__flag { display: inline-block; font-size: var(--fs-2); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: #A85A08; background: rgba(255,209,102,0.16); border: 1px solid rgba(255,209,102,0.45); border-radius: var(--r-pill); padding: 2px 8px; margin-left: var(--space-4); }
/* A review has to be read in full before it is published, so its row opts out
   of the single-line treatment the other admin rows use — .admin-row__meta
   clips with an ellipsis, which is right for a phone number and wrong for a
   paragraph. Top-aligned so the buttons stay put as the quote grows. */
/* Separates the two review lists in one pane: waiting for approval, then
   already on the site. */
.admin-subhead { font-family: var(--font-display); font-weight: 700; font-size: var(--fs-11); color: var(--text-dark); margin: var(--space-15) 0 var(--space-3); }
.admin-row--review { align-items: flex-start; }

/* ---- Admin call list (Find Businesses) ---- */
.prospect-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-6); margin: var(--space-4) 0 var(--space-3); }
.prospect-area { display: flex; align-items: center; gap: var(--space-4); }
.prospect-area label { font-size: var(--fs-6); color: var(--text-dark-lo); }
.prospect-area input { font-family: inherit; font-size: var(--fs-6); color: var(--text-dark); background: var(--paper-2); border: 1px solid rgba(var(--ink-rgb),0.14); border-radius: var(--r-pill); padding: var(--space-3) var(--space-7); width: 200px; }
.prospect-area input:focus { outline: none; border-color: var(--blue); }
.prospect-count { font-weight: 500; color: var(--text-dark-lo); }
/* A row carries up to six controls, so they drop under the name on a
   narrow screen instead of squeezing it to nothing. */
.prospect-row { flex-wrap: wrap; row-gap: var(--space-5); }
.prospect-row .admin-row__main { min-width: 220px; }
.prospect-row .admin-row__meta { white-space: normal; }
.prospect-row .admin-row__meta a { color: var(--blue); text-decoration: none; }
.prospect-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
.prospect-actions .admin-row__cb { text-decoration: none; }
.prospect-cat { display: inline-block; vertical-align: 1px; font-size: var(--fs-2); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-dark-lo); background: rgba(var(--ink-rgb),0.07); border-radius: var(--r-pill); padding: 2px 8px; margin-right: var(--space-4); }
.prospect-status { display: inline-block; vertical-align: 1px; font-size: var(--fs-2); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; border-radius: var(--r-pill); padding: 2px 8px; margin-right: var(--space-3); }
.prospect-status--accepted { color: var(--dash-booked); background: rgba(16,150,95,0.12); border: 1px solid rgba(16,150,95,0.35); }
.prospect-status--rejected { color: #E5484D; background: rgba(229,72,77,0.10); border: 1px solid rgba(229,72,77,0.35); }
.prospect-status--called { color: var(--text-dark-lo); background: rgba(var(--ink-rgb),0.06); border: 1px solid rgba(var(--ink-rgb),0.18); }
.prospect-btn { font-family: inherit; font-size: var(--fs-5); font-weight: 600; background: transparent; border-radius: var(--r-pill); padding: var(--space-3) var(--space-7); cursor: pointer; white-space: nowrap; }
.prospect-btn:disabled { opacity: 0.5; cursor: default; }
.prospect-btn--yes { color: var(--dash-booked); border: 1px solid rgba(16,150,95,0.45); }
.prospect-btn--yes:hover { background: rgba(16,150,95,0.10); }
.prospect-btn--no { color: #E5484D; border: 1px solid rgba(229,72,77,0.45); }
.prospect-btn--no:hover { background: rgba(229,72,77,0.08); }
.prospect-btn--undo { color: var(--text-dark-lo); border: 1px solid rgba(var(--ink-rgb),0.18); }
.prospect-btn--undo:hover { color: var(--text-dark); }
.prospect-filter { display: flex; gap: var(--space-3); margin-bottom: var(--space-6); }
.prospect-filter__btn { font-family: inherit; font-size: var(--fs-5); font-weight: 600; color: var(--text-dark-lo); background: transparent; border: 1px solid rgba(var(--ink-rgb),0.14); border-radius: var(--r-pill); padding: var(--space-2) var(--space-7); cursor: pointer; }
.prospect-filter__btn.is-active { color: var(--blue); border-color: var(--blue); }
.prospect-credit { font-size: var(--fs-3); color: var(--text-dark-lo); margin-top: var(--space-11); }
.prospect-credit a { color: inherit; }
.prospect-maps { margin-top: var(--space-8); }
.prospect-maps summary { cursor: pointer; font-size: var(--fs-6); font-weight: 600; color: var(--text-dark-lo); margin-bottom: var(--space-6); }
.admin-row__review-text { margin-top: var(--space-4); font-size: var(--fs-8); line-height: 1.55; color: var(--text-dark); white-space: pre-wrap; overflow-wrap: anywhere; }
.admin-row__review-text--empty { color: var(--text-dark-lo); font-style: italic; }
.admin-row__badge { display: inline-block; font-size: var(--fs-2); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: #0F7B4F; background: rgba(16,150,95,0.12); border: 1px solid rgba(16,150,95,0.35); border-radius: var(--r-pill); padding: 2px 8px; margin-left: var(--space-4); }
.admin-row__when { font-size: var(--fs-3); color: var(--text-dark-lo); white-space: nowrap; font-variant-numeric: tabular-nums; }
.admin-row__cb { flex-shrink: 0; white-space: nowrap; padding: var(--space-3) var(--space-7); font-size: var(--fs-5); border-radius: var(--r-pill); border: 1px solid var(--blue); color: var(--blue); background: transparent; cursor: pointer; transition: background .15s ease, color .15s ease; }
.admin-row__cb:hover { background: var(--blue); color: #fff; }
.admin-row__cb:disabled { opacity: .5; cursor: default; }
.admin-list__empty { font-size: var(--fs-6); color: var(--text-dark-lo); padding: var(--space-8); text-align: center; }

.admin-sec__callout { padding: var(--space-11) var(--space-12); background: var(--paper-2); border: 1px solid rgba(var(--ink-rgb),0.08); border-radius: var(--r-lg); }
.admin-sec__callout h3 { font-family: var(--font-display); font-weight: 600; font-size: 1.02rem; color: var(--text-dark); margin: 0 0 var(--space-3); }
.admin-sec__callout > p { font-size: var(--fs-6); color: var(--text-dark-lo); margin: 0 0 var(--space-9); line-height: 1.5; max-width: 56ch; }
.admin-sec__callform { display: grid; grid-template-columns: 1fr 1fr 1.4fr auto; gap: var(--space-5); }
.admin-sec__callform input { font: inherit; font-size: var(--fs-6); color: var(--text-dark); background: var(--paper); border: 1px solid rgba(var(--ink-rgb),0.14); border-radius: var(--r-md); padding: var(--space-6) var(--space-7); min-width: 0; }
.admin-sec__callform input:focus { outline: none; border-color: var(--blue); }
.admin-sec__note { font-size: var(--fs-5); color: var(--text-dark-lo); margin: var(--space-6) 0 0; min-height: 1em; }
.admin-sec__note.is-ok { color: var(--green-deep); }

@media (max-width: 720px) {
  .admin-stats { grid-template-columns: repeat(2, 1fr); }
  .admin-sec__callform { grid-template-columns: 1fr; }
  .admin-row { flex-wrap: wrap; }
}

/* ---- admin: header actions (the Refresh button read as a stray dark blob;
        make it and the range select one cohesive control cluster) ---- */
.admin-sec__head-actions { align-items: stretch; }
.admin-sec__head-actions .btn--sm { display: inline-flex; align-items: center; }
.admin-sec__head .btn--outline {
  background: var(--paper-2);
  border: 1px solid rgba(var(--ink-rgb),0.14);
  color: var(--text-dark);
}
.admin-sec__head .btn--outline:hover { border-color: var(--blue); color: var(--blue); }

/* ---- admin: inline conversation ---- */
.admin-convo { margin-top: var(--space-8); border: 1px solid rgba(var(--ink-rgb),0.10); border-radius: var(--r-lg); overflow: hidden; background: var(--paper-2); }
.admin-convo__head { display: flex; align-items: center; gap: var(--space-6); padding: var(--space-7) var(--space-9); border-bottom: 1px solid rgba(var(--ink-rgb),0.08); }
.admin-convo__back { border: none; background: none; font-size: 1.1rem; color: var(--text-dark-lo); cursor: pointer; line-height: 1; padding: var(--space-2); }
.admin-convo__back:hover { color: var(--text-dark); }
.admin-convo__who { font-family: var(--font-display); font-weight: 600; font-size: 0.98rem; color: var(--text-dark); }
.admin-convo__log { display: flex; flex-direction: column; gap: var(--space-4); padding: var(--space-9); max-height: 340px; overflow-y: auto; }
.admin-msg { max-width: 78%; padding: var(--space-5) var(--space-8); border-radius: var(--r-md); font-size: var(--fs-6); line-height: 1.4; }
.admin-msg--contact { align-self: flex-start; background: var(--paper); border: 1px solid rgba(var(--ink-rgb),0.10); color: var(--text-dark); border-bottom-left-radius: var(--space-2); }
.admin-msg--agent, .admin-msg--owner { align-self: flex-end; background: var(--blue); color: #fff; border-bottom-right-radius: var(--space-2); }
.admin-msg--owner { background: var(--green-deep); }
.admin-msg__who { display: block; font-size: var(--fs-2); opacity: .7; margin-bottom: 2px; text-transform: uppercase; letter-spacing: .05em; }
.admin-convo__reply { display: flex; gap: var(--space-5); padding: var(--space-7) var(--space-9); border-top: 1px solid rgba(var(--ink-rgb),0.08); }
.admin-convo__reply input { flex: 1; font: inherit; font-size: var(--fs-6); color: var(--text-dark); background: var(--paper); border: 1px solid rgba(var(--ink-rgb),0.14); border-radius: var(--r-pill); padding: var(--space-5) var(--space-8); min-width: 0; }
.admin-convo__reply input:focus { outline: none; border-color: var(--blue); }
.admin-row--text { cursor: pointer; transition: border-color .15s ease; }
.admin-row--text:hover { border-color: var(--blue); }

/* ---- admin: sub-tabs + panes ---- */
/* The rule under the tabs is an inset shadow rather than a border, so the
   active tab's underline can cover it without hanging 1px out of the strip.
   That 1px overhang (margin-bottom: -1px on the tab) made the scrolling strip
   one pixel too tall, and Windows drew a full up/down scrollbar, arrows and
   all, beside the tabs. The strip still scrolls sideways on a narrow phone. */
.admin-tabs { display: flex; gap: var(--space-2); box-shadow: inset 0 -1px 0 rgba(var(--ink-rgb),0.12); margin-bottom: var(--space-11); overflow-x: auto; overflow-y: hidden; scrollbar-width: none; }
.admin-tabs::-webkit-scrollbar { display: none; }
.admin-tab { flex-shrink: 0; font: inherit; font-size: var(--fs-7); font-weight: 600; color: var(--text-dark-lo); background: none; border: none; border-bottom: 2px solid transparent; padding: var(--space-6) var(--space-7); cursor: pointer; white-space: nowrap; }
.admin-tab:hover { color: var(--text-dark); }
.admin-tab.is-active { color: var(--blue); border-bottom-color: var(--blue); }
/* Phone & Messages reuses the Admin strip verbatim — .admin-tabs/.admin-tab
   are on the markup — so there is one tab style in the dashboard rather than
   two that drift. These two rules are all the section adds. */
.phone-tabs { margin-bottom: var(--space-10); }
.phone-tabpane[hidden] { display: none; }
.admin-stats--5 { grid-template-columns: repeat(5, 1fr); }
.admin-lead-search { width: 100%; font: inherit; font-size: var(--fs-6); color: var(--text-dark); background: var(--paper-2); border: 1px solid rgba(var(--ink-rgb),0.14); border-radius: var(--r-md); padding: var(--space-7) var(--space-9); margin-bottom: var(--space-9); }
.admin-lead-search:focus { outline: none; border-color: var(--blue); }
.admin-prospect-form { grid-template-columns: 1fr 1fr auto; }
/* a row's inline delete / action buttons */
.admin-row__del { flex-shrink: 0; border: none; background: none; color: var(--text-dark-lo); font-size: 1.05rem; line-height: 1; padding: var(--space-3) var(--space-5); border-radius: var(--r-md); cursor: pointer; }
.admin-row__del:hover { color: #C0392B; background: rgba(192,57,43,0.10); }
.admin-row__status { flex-shrink: 0; font: inherit; font-size: var(--fs-5); color: var(--text-dark); background: var(--paper); border: 1px solid rgba(var(--ink-rgb),0.14); border-radius: var(--r-pill); padding: var(--space-3) var(--space-6); }
.admin-row__stars { color: #E2A200; letter-spacing: 1px; font-size: var(--fs-8); }
.admin-row__approve { flex-shrink: 0; white-space: nowrap; padding: var(--space-3) var(--space-7); font-size: var(--fs-5); border-radius: var(--r-pill); border: 1px solid var(--green-deep); color: var(--green-deep); background: transparent; cursor: pointer; }
.admin-row__approve:hover { background: var(--green-deep); color: #fff; }

/* ---- admin: multi-select + bulk delete ---- */
.admin-row__check { flex-shrink: 0; width: 16px; height: 16px; margin: 0; accent-color: var(--blue); cursor: pointer; }
.admin-bulk { display: flex; align-items: center; justify-content: space-between; gap: var(--space-6); margin-bottom: var(--space-5); padding: var(--space-4) var(--space-7); background: var(--paper-2); border: 1px solid rgba(var(--ink-rgb),0.08); border-radius: var(--r-md); }
.admin-bulk__all { display: inline-flex; align-items: center; gap: var(--space-4); font-size: var(--fs-5); color: var(--text-dark-lo); cursor: pointer; user-select: none; }
.admin-bulk__all input { width: 16px; height: 16px; margin: 0; accent-color: var(--blue); cursor: pointer; }
.admin-bulk__del { flex-shrink: 0; white-space: nowrap; font: inherit; font-size: var(--fs-5); font-weight: 600; padding: var(--space-3) var(--space-7); border-radius: var(--r-pill); border: 1px solid #C0392B; color: #C0392B; background: transparent; cursor: pointer; }
.admin-bulk__del:hover { background: #C0392B; color: #fff; }
.admin-bulk__del:disabled { opacity: .5; cursor: default; }

@media (max-width: 720px) {
  .admin-stats--5 { grid-template-columns: repeat(2, 1fr); }
  .admin-prospect-form { grid-template-columns: 1fr; }
}

/* --- Results: a wrapper, not a card ---------------------------------------
   The results block used to be one panel; its stat cards and its chart are
   the cards now, and .results is only the thing that stacks them. Several
   earlier card groupings (the glass pass, the dashboard surface pass) still
   list .results, which put a background, a border and a shadow back on it —
   and with the card radius gone that painted a hard-cornered box around the
   whole section. Neutralised here, at the end, so those groupings can keep
   styling the real cards they were written for. */
.results,
.dash-body .results,
[data-theme="dark"] .dash-body .results {
  background: none;
  border: none;
  box-shadow: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  padding: 0;
}
.results::before,
.results::after,
.dash-body .results::before,
.dash-body .results::after { content: none; }
