/* /static/site.css */
/**
 * Sporetag's stylesheet: tokens, base, layout, components, header, footer,
 * the app shell. Marketing and the app share these tokens (docs/style.md).
 *
 * Light and warm by default. `:root` holds light. Dark is written twice: once
 * for the reader who never touches the toggle (prefers-color-scheme), once
 * for the one who does (`data-theme`, stamped by public/static/theme.js).
 *
 * Area styles live in their own files, linked after this one by the layout:
 * site-marketing.css, app-analytics.css, app-links.css, app-billing.css.
 * Use the tokens here; add no new colors without a contrast note.
 */

/* ---------------- tokens ----------------
   Light and warm by default (DECISIONS.md, 2026-10-21): warm paper ground,
   raised white cards, warm neutral lines and ink, one blue accent, green only
   on the call to action, red only for "missed" numbers.

   Dark is written twice, like light used to be: once for the reader who
   never touches the toggle (prefers-color-scheme), once for the one who does
   (`data-theme`, stamped by public/static/theme.js). Ratios are WCAG 2.1. */

:root {
  --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9.5 12 15.5 18 9.5'/%3E%3C/svg%3E");
  /* Warm paper. Cards sit on it in white; tinted bands alternate with it. */
  --bg: #f8f6f1;
  /* Panels and app cards: a breath warmer than white, so they sit on paper
     without going grey. --text-faint 5.5:1, --text-dim 6.9:1 on it. */
  --bg-panel: #fbfaf7;
  /* The tint band (alternate marketing sections, inset wells): one step down
     from paper. --text-dim 6.1:1, --text-faint 4.9:1 on it. */
  --bg-tint: #f0ede6;
  --bg-raised: #ffffff;
  --bg-input: #ffffff;
  --bg-hover: #f2efe8;
  --bg-active: #e9e5dc;
  /* Hairlines: 1.20:1 on --bg, enough on a flat warm ground. */
  --line: #e4dfd5;
  /* 1.41:1 on --bg: borders that must read (inputs, selected cards). */
  --line-strong: #cdc6b8;
  --line-control: #dcd5c8;
  /* The edge of a field, a switch track or a checkbox: what tells a person a
     box is there to type in (WCAG 1.4.11). 3.6:1 on --bg-panel, 3.2:1 on --bg-tint. */
  --line-input: #8a8377;
  /* On --bg: --text 15.6:1, --text-dim 6.6:1, --text-faint 5.3:1.
     On --bg-panel: --text-dim 6.1:1, --text-faint 4.9:1. */
  --text: #1f1d1a;
  --text-dim: #5c574f;
  --text-faint: #6b665d;
  /* The current blue family, one step deeper so it holds on the tint:
     5.8:1 on --bg, 5.3:1 on --bg-panel. White ink on it 6.2:1. */
  --accent: #1559d0;
  --accent-ink: #ffffff;
  --accent-hover: #124cb3;
  --accent-soft: rgba(21, 89, 208, 0.1);
  /* The soft blue band ("pick what you run", the promise). --text 14.5:1,
     --accent 5.4:1, --text-dim 6.2:1 on it. */
  --brand-band: #e9eefb;
  --overlay: rgba(236, 232, 224, 0.8);
  --scrim: rgba(40, 34, 26, 0.38);
  /* The call to action. White on it 5.4:1. */
  --cta: #1c7a45;
  --cta-hover: #18733f;
  --cta-ink: #ffffff;
  --danger: #c4392b;
  --danger-hover: #ad3124;
  --danger-ink: #ffffff;
  /* Danger text and "lost" numbers: 6.1:1 on --bg. */
  --danger-fg: #b3261e;
  /* Loss and gain, nowhere else: missed numbers red, found numbers blue. */
  --lost: var(--danger-fg);
  --found: var(--accent);
  /* Semantic tones: -fg is text and icons, -bg the soft fill, -line its border.
     Every -fg is AA for small text on its own -bg and on --bg-panel:
     success 5.8:1, warning 6.1:1, danger 7.2:1, info 5.4:1. */
  --success: #1c7a45;
  --success-fg: #1d6b3f;
  --success-bg: #e9f5ed;
  --success-line: #b5dcc3;
  --warning: #b07d1c;
  --warning-fg: #7a5514;
  --warning-bg: #fbf3e1;
  --warning-line: #e6d3a2;
  --danger-bg: #fce9e5;
  --danger-line: #e2aca3;
  --danger-text: #8c2b26;
  --info: var(--accent);
  --info-fg: var(--accent);
  --info-bg: #e9eefb;
  --info-line: color-mix(in srgb, var(--accent) 32%, transparent);
  /* Dot texture: warm grey at low strength. */
  --site-dot: color-mix(in srgb, #bdb4a3 34%, transparent);
  --shadow-card: 0 1px 2px rgba(60, 45, 20, 0.05), 0 8px 24px rgba(60, 45, 20, 0.06);
  --shadow-menu: 0 10px 24px rgba(60, 45, 20, 0.12);
  --shadow-panel: 0 1px 2px rgba(60, 45, 20, 0.06), 0 18px 40px rgba(60, 45, 20, 0.1);
  --shadow-sheet: 0 24px 60px rgba(60, 45, 20, 0.2);
  --header-bg: rgba(248, 246, 241, 0.88);
  --select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235c574f' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9.5 12 15.5 18 9.5'/%3E%3C/svg%3E");

  --site-max: 1160px;
  --gutter: 32px;
  /* ---- the system (docs/style.md, Design system) ----
     Spacing: one 4px scale. Use these for gaps, padding and margins. */
  --space-0: 0;
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;

  /* Type: one scale. The named steps are what pages use; the numbers are
     there for the rare in-between (a chart axis, a big number). */
  --fs-11: 11px;
  --fs-12: 12px;
  --fs-13: 13px;
  --fs-14: 14px;
  --fs-15: 15px;
  --fs-16: 16px;
  --fs-18: 18px;
  --fs-20: 20px;
  --fs-24: 24px;
  --fs-28: 28px;
  --fs-32: 32px;
  --fs-40: 40px;
  --fs-48: 48px;
  --type-display: var(--fs-28);  /* the page title */
  --type-title: var(--fs-20);    /* a section or a dialog */
  --type-heading: var(--fs-16);  /* a card */
  --type-body: var(--fs-15);
  --type-ui: var(--fs-14);       /* controls, table cells */
  --type-small: var(--fs-13);    /* hints, meta lines */
  --type-caption: var(--fs-12);  /* pills, axis labels */
  --type-label: var(--fs-11);    /* mono eyebrows and table heads */
  --lh-tight: 1.2;
  --lh-snug: 1.35;
  --lh-body: 1.55;
  --weight-medium: 500;
  --weight-strong: 600;
  --weight-title: 650;
  --track-label: 0.08em;
  --track-title: -0.015em;

  /* Controls: three heights. 32 for dense rows and toolbars, 36 for most
     buttons and fields in the app, 44 for the one main action and for every
     control on a phone (a finger, below). */
  --ctl-h-sm: 32px;
  --ctl-h-md: 36px;
  --ctl-h-lg: 44px;

  /* Radii: one set. Controls md, cards lg, dialogs and sheets xl. */
  --r-xs: 4px;
  --r-sm: 6px;
  --r-md: 8px;
  --r-lg: 12px;
  --r-xl: 16px;
  --r-pill: 999px;
  --radius: var(--r-lg);
  --radius-sm: var(--r-md);
  --radius-lg: var(--r-xl);

  /* Elevation: flat cards (0), a resting lift (1), cards that float (2),
     menus and popovers (3), dialogs and sheets (4). */
  --elev-0: none;
  --elev-1: 0 1px 2px rgba(60, 45, 20, 0.06);
  --elev-2: var(--shadow-card);
  --elev-3: var(--shadow-menu);
  --elev-4: var(--shadow-sheet);

  /* Focus: one ring, the same on every control. The solid inner line (with the
     field's own accent border, 2px of accent at 5.3:1 or better) is what meets
     WCAG 1.4.11; the soft outer glow is the look. */
  --focus-ring: 0 0 0 1px var(--accent), 0 0 0 4px color-mix(in srgb, var(--accent) 22%, transparent);

  /* Motion: short and calm. All of it drops to none under reduced motion. */
  --dur-1: 90ms;   /* hover, press */
  --dur-2: 160ms;  /* menus, toggles */
  --dur-3: 240ms;  /* dialogs, toasts */
  --dur-4: 400ms;  /* count-up, page */
  --ease-out: cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);

  --header-h: 62px;
  --sans: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  /* Marketing h1 and h2 only. System serifs, no web font: New York on Apple,
     Iowan Old Style and Charter where Safari's ui-serif is missing, Georgia on
     Windows. Charter's free cut (Bitstream Charter) covers Linux. */
  --serif: ui-serif, 'New York', 'Iowan Old Style', Charter, 'Bitstream Charter', Georgia, serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Button and field sizes. Marketing keeps its roomier 40 and 48; the app
     and the sign-in pages map these to the control heights (ui.css). */
  --btn-h-sm: var(--ctl-h-sm);
  --btn-h-md: 40px;
  --btn-h-lg: 48px;
  --btn-fs-sm: var(--fs-13);
  --btn-fs-md: var(--fs-15);
  --btn-fs-lg: 15.5px;
  --btn-px-sm: 11px;
  --btn-px-md: 16px;
  --btn-px-lg: 22px;
  --btn-radius: var(--r-md);
  --field-h: 40px;
  --field-fs: var(--fs-15);
  --field-px: 10px;
  --field-radius: var(--r-md);

  /* Old names, kept so nothing breaks; new code uses the tones above. */
  --chip-ok-fg: var(--success-fg);
  --chip-ok-line: var(--success-line);
  --chip-ok-bg: var(--success-bg);
  --chip-warn-fg: var(--warning-fg);
  --chip-warn-line: var(--warning-line);
  --chip-warn-bg: var(--warning-bg);
  --error-bg: var(--danger-bg);
  --error-line: var(--danger-line);
  --error-text: var(--danger-text);
  color-scheme: light;
}

/* Dark, warm-tinted so it is the same room with the lights down. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --bg: #161513;
    --bg-panel: #1c1b18;
    /* The dark tint band: a step up from --bg. --text-faint 5.2:1 on it. */
    --bg-tint: #1f1d1a;
    --bg-raised: #23211e;
    --bg-input: #191816;
    --bg-hover: #2b2925;
    --bg-active: #33302b;
    /* 1.41:1 on --bg. */
    --line: #34312b;
    --line-strong: #45413a;
    --line-control: #3c3832;
    /* 3.3:1 on --bg-raised, 3.7:1 on --bg-input, 3.0:1 on --bg-hover. */
    --line-input: #777166;
    /* On --bg: --text 15.1:1, --text-dim 7.5:1, --text-faint 5.7:1 (5.0:1 on --bg-raised). */
    --text: #ede9e2;
    --text-dim: #aba59b;
    --text-faint: #958f85;
    /* 7.3:1 on --bg, 6.5:1 on --bg-raised. Ink on it is near black (7.6:1). */
    --accent: #57a8ff;
    --accent-ink: #08121f;
    --accent-hover: #7bbcff;
    --accent-soft: rgba(87, 168, 255, 0.16);
    /* --text-dim 6.6:1 on it. */
    --brand-band: #182133;
    --overlay: rgba(20, 19, 17, 0.74);
    --scrim: rgba(6, 5, 4, 0.66);
    /* White on it 5.5:1, and 3.2:1 against --bg-panel so the button still leads. */
    --cta: #17793f;
    --cta-hover: #1c8749;
    --cta-ink: #ffffff;
    --danger: #d94a45;
    --danger-hover: #e85d58;
    --danger-ink: #1a0605;
    /* 9.0:1 on --bg. */
    --danger-fg: #ff9a95;
    --success: #3fb06a;
    --success-fg: #8ee0a1;
    --success-bg: #16271c;
    --success-line: #2d5b3c;
    --warning: #d9a53f;
    --warning-fg: #e6c77a;
    --warning-bg: #262013;
    --warning-line: #5c4c24;
    --danger-bg: #3a1a18;
    --danger-line: #8c4340;
    --danger-text: #ffd9d6;
    --info-bg: #182133;
    --site-dot: color-mix(in srgb, #c9bca6 12%, transparent);
    --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 24px rgba(0, 0, 0, 0.25);
  --elev-1: 0 1px 2px rgba(0, 0, 0, 0.3);
    --elev-1: 0 1px 2px rgba(0, 0, 0, 0.3);
    --shadow-menu: 0 12px 28px rgba(0, 0, 0, 0.45);
    --shadow-panel: 0 1px 2px rgba(0, 0, 0, 0.35), 0 18px 40px rgba(0, 0, 0, 0.42);
    --shadow-sheet: 0 26px 64px rgba(0, 0, 0, 0.6);
    --header-bg: rgba(22, 21, 19, 0.88);
    --select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23aba59b' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9.5 12 15.5 18 9.5'/%3E%3C/svg%3E");
    color-scheme: dark;
  }
}

:root[data-theme='dark'] {
  --bg: #161513;
  --bg-panel: #1c1b18;
  --bg-tint: #1f1d1a;
  --bg-raised: #23211e;
  --bg-input: #191816;
  --bg-hover: #2b2925;
  --bg-active: #33302b;
  --line: #34312b;
  --line-strong: #45413a;
  --line-control: #3c3832;
  --line-input: #777166;
  --text: #ede9e2;
  --text-dim: #aba59b;
  --text-faint: #958f85;
  --accent: #57a8ff;
  --accent-ink: #08121f;
  --accent-hover: #7bbcff;
  --accent-soft: rgba(87, 168, 255, 0.16);
  --brand-band: #182133;
  --overlay: rgba(20, 19, 17, 0.74);
  --scrim: rgba(6, 5, 4, 0.66);
  --cta: #17793f;
  --cta-hover: #1c8749;
  --cta-ink: #ffffff;
  --danger: #d94a45;
  --danger-hover: #e85d58;
  --danger-ink: #1a0605;
  --danger-fg: #ff9a95;
  --success: #3fb06a;
  --success-fg: #8ee0a1;
  --success-bg: #16271c;
  --success-line: #2d5b3c;
  --warning: #d9a53f;
  --warning-fg: #e6c77a;
  --warning-bg: #262013;
  --warning-line: #5c4c24;
  --danger-bg: #3a1a18;
  --danger-line: #8c4340;
  --danger-text: #ffd9d6;
  --info-bg: #182133;
  --site-dot: color-mix(in srgb, #c9bca6 12%, transparent);
  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 24px rgba(0, 0, 0, 0.25);
  --shadow-menu: 0 12px 28px rgba(0, 0, 0, 0.45);
  --shadow-panel: 0 1px 2px rgba(0, 0, 0, 0.35), 0 18px 40px rgba(0, 0, 0, 0.42);
  --shadow-sheet: 0 26px 64px rgba(0, 0, 0, 0.6);
  --header-bg: rgba(22, 21, 19, 0.88);
  --select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23aba59b' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9.5 12 15.5 18 9.5'/%3E%3C/svg%3E");
  color-scheme: dark;
}

/* A finger, not a pointer: every control on a phone is at least 44 px. */
@media (max-width: 720px) {
  :root {
    --btn-h-sm: 44px;
    --btn-h-md: 46px;
    --btn-h-lg: 50px;
    --field-h: 46px;
    /* 16 px or iOS zooms the page when a field takes focus. */
    --field-fs: 16px;
    --gutter: 16px;
  }
}

@media (min-width: 721px) and (max-width: 1023px) {
  :root {
    --gutter: 24px;
  }
}

/* ---------------- base ---------------- */

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  /* The sticky header is 62px plus its 1px border. */
  scroll-padding-top: 63px;
  /* Room for the scrollbar is kept, so nothing shifts sideways as a page grows. */
  scrollbar-gutter: stable;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* A #link lands with a little room under the sticky header (scroll-padding-top
   above), not flush against it. Pages with a second sticky bar add its height. */
:target {
  scroll-margin-top: var(--space-4);
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-1: 0ms;
    --dur-2: 0ms;
    --dur-3: 0ms;
    --dur-4: 0ms;
  }
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* Sticky footer: the body is a column at least one screen tall and <main>
   takes what is left, so a short page pushes the footer to the bottom. */
body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--text);
  font: 15px/1.6 var(--sans);
  /* A word longer than its box (large text on a phone) breaks instead of
     running out of it. It changes nothing where words fit. */
  overflow-wrap: break-word;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a {
  color: var(--accent);
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

/* Links drawn as controls (pills, buttons, chips, tiles) never underline: they change color or fill instead. */
a:is(.pill, .live-now, .hl-badge, .btn, .chip, .segment, .icon-button, .card, .nav-item):hover {
  text-decoration: none;
}

/* A link in running text is told apart by more than its color. */
main p a:not([class]),
main li a:not([class]),
main .prose a:not([class]) {
  text-decoration: underline;
  text-underline-offset: 0.15em;
}

h1,
h2,
h3,
h4 {
  margin: 0;
  line-height: 1.2;
  letter-spacing: -0.01em;
}

p {
  margin: 0;
}

img,
svg {
  max-width: 100%;
}

code,
kbd,
pre {
  font-family: var(--mono);
  font-size: 0.92em;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

::selection {
  background: var(--accent-soft);
}

[hidden] {
  display: none !important;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* The first stop for a keyboard: past the header, straight to the page. */
.skip-link {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 1000;
  padding: 8px 14px;
  border-radius: 8px;
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
  transform: translateY(-200%);
}

.skip-link:focus,
.skip-link:focus-visible {
  transform: none;
  outline: 2px solid var(--text);
  outline-offset: 2px;
  text-decoration: none;
}

main[tabindex='-1']:focus {
  outline: none;
}

/* ---------------- layout ---------------- */

.container {
  width: 100%;
  max-width: var(--site-max);
  margin: 0 auto;
  padding-inline: var(--gutter);
}

.site-main {
  display: flex;
  flex-direction: column;
  flex: 1 0 auto;
  min-width: 0;
}

/* The last section takes the spare height, so its ground runs to the footer. */
.site-main > .section:last-child {
  flex: 1 0 auto;
}

.section {
  padding-block: 56px;
  border-top: 1px solid var(--line);
}

.section:first-child {
  border-top: none;
}

.section-tight {
  padding-block: 8px 72px;
  border-top: none;
}

/* A dotted panel: a 20px dot ground, faint enough that a paragraph over it
   still reads as print on paper. */
.section-alt,
.dots {
  background-color: var(--bg-panel);
  background-image: radial-gradient(var(--site-dot) 1px, transparent 1px);
  background-size: 20px 20px;
}

.band {
  background: var(--brand-band);
}

.section-head {
  max-width: 660px;
  margin-bottom: 30px;
}

.eyebrow,
.section-eyebrow {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 10px;
}

.section-title {
  font-size: 27px;
  font-weight: 700;
}

.section-sub {
  margin-top: 10px;
  color: var(--text-dim);
}

.lead {
  font-size: 17px;
  color: var(--text-dim);
  max-width: 34em;
}

.prose {
  max-width: 66ch;
}

.prose > * + * {
  margin-top: 1em;
}

.prose h2 {
  margin-top: 1.8em;
  font-size: 22px;
}

.prose h3 {
  margin-top: 1.5em;
  font-size: 17px;
}

.prose ul,
.prose ol {
  padding-left: 1.3em;
}

.muted {
  color: var(--text-dim);
}

.faint {
  color: var(--text-faint);
}

.mono {
  font-family: var(--mono);
}

.stack {
  display: grid;
  gap: var(--space-4);
}

.row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.row-between {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.grid-2,
.grid-3 {
  display: grid;
  gap: 16px;
}

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

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

@media (max-width: 960px) {
  .grid-3 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 720px) {
  .grid-2,
  .grid-3 {
    grid-template-columns: minmax(0, 1fr);
  }
  .section {
    padding-block: 44px;
  }
  .section-title {
    font-size: 23px;
  }
}

/* ---------------- hero ---------------- */

.hero {
  padding-block: 56px 64px;
}

.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
  gap: 44px;
  align-items: center;
}

.hero h1 {
  font-size: 44px;
  font-weight: 700;
  letter-spacing: -0.025em;
}

.hero h1 .accent,
.accent-word {
  color: var(--accent);
}

.hero-lead {
  margin-top: 18px;
  font-size: 17px;
  color: var(--text-dim);
  max-width: 34em;
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 26px;
}

.hero-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 22px;
  margin: 26px 0 0;
  padding: 0;
  list-style: none;
  font-size: 13px;
  color: var(--text-faint);
}

@media (max-width: 960px) {
  .hero-grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 32px;
  }
  .hero h1 {
    font-size: 36px;
  }
}

@media (max-width: 720px) {
  .hero {
    padding-block: 34px 44px;
  }
  .hero h1 {
    font-size: 30px;
  }
  .hero-lead {
    font-size: 15.5px;
  }
  .hero-actions .btn {
    flex: 1 1 160px;
  }
}


/* ---------------- wordmark ---------------- */

.wordmark {
  font-size: 17px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--text);
  user-select: none;
  text-decoration: none;
  white-space: nowrap;
}

.wordmark:hover {
  text-decoration: none;
}

/* The wordmark is the brand drawing inline (src/brand.ts), inked from the
   theme's own tokens, so light and dark need no rules of their own. Its height
   keeps the lowercase letters at the size of the CSS text they replaced:
   108 units of a 95.09 unit em (the system UI sans at the header's size):
   the big t rising above the rest, plus a few units of air above it and below
   the g. The bottom margin of 17 units lifts the box so the lowercase sits
   where the text sat. `display: block` drops the inline gap under the drawing. */
.wordmark-svg {
  display: block;
  height: 1.136em;
  width: auto;
  aspect-ratio: 450 / 108;
  margin-bottom: 0.179em;
}
.wordmark-ink {
  fill: var(--text);
}
.wordmark-accent {
  fill: var(--accent);
}

/* ---------------- header ---------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--header-bg);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}

.site-header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: var(--header-h);
  padding-block: 8px;
}

.site-header .wordmark {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
  margin-left: 2px;
  font-size: 22px;
  min-height: 44px;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: 2px;
  margin-left: 14px;
  flex: 1 1 auto;
  min-width: 0;
}

.nav-link {
  display: inline-flex;
  align-items: center;
  min-height: 38px;
  padding: 4px 11px;
  border-radius: 7px;
  color: var(--text-dim);
  font: inherit;
  font-weight: 500;
  text-decoration: none;
  background: transparent;
  border: none;
  cursor: pointer;
}

.nav-link:hover {
  color: var(--text);
  background: var(--bg-raised);
  text-decoration: none;
}

.nav-link[aria-current='page'] {
  color: var(--text);
}

/* A menu in the row: a <details> whose summary looks like the links beside
   it, with a chevron that turns over while its panel is open. */
.nav-group {
  position: relative;
}

.nav-group > summary {
  gap: 5px;
  list-style: none;
}

.nav-group > summary::-webkit-details-marker {
  display: none;
}

.nav-group[open] > summary {
  color: var(--text);
  background: var(--bg-raised);
}

.nav-chevron {
  flex: 0 0 auto;
  width: 12px;
  height: 12px;
  margin-top: 1px;
  opacity: 0.7;
  transition: transform 0.15s ease;
}

.nav-group[open] .nav-chevron {
  transform: rotate(180deg);
}

.nav-panel {
  position: absolute;
  top: calc(100% + 10px);
  left: 50%;
  z-index: 70;
  width: 340px;
  padding: 6px;
  transform: translateX(-50%);
  background: var(--bg-raised);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-panel);
}

.nav-panel-list {
  display: grid;
  gap: 2px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.nav-item {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 56px;
  padding: 8px 10px;
  border-radius: 9px;
  color: var(--text);
  text-decoration: none;
}

.nav-item:hover,
.nav-item:focus-visible {
  background: var(--bg-active);
  text-decoration: none;
}

.nav-item:focus-visible {
  outline-offset: -2px;
}

.nav-item-icon {
  display: grid;
  place-items: center;
  flex: 0 0 36px;
  width: 36px;
  height: 36px;
  border-radius: 9px;
  background: var(--accent-soft);
  color: var(--accent);
}

.nav-item-icon svg {
  width: 18px;
  height: 18px;
}

.nav-item-text {
  display: grid;
  gap: 1px;
  min-width: 0;
}

.nav-item-label {
  font-weight: 600;
  font-size: 14.5px;
  line-height: 1.3;
}

.nav-item-line {
  color: var(--text-dim);
  font-size: 13px;
  line-height: 1.35;
}

.nav-item[aria-current='page'] {
  background: var(--bg-active);
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 1 auto;
  min-width: 0;
}

/* With large text (a phone's text size, browser zoom) a button's words break
   onto two lines before the menu is pushed off the screen. At normal sizes
   the row fits, so nothing breaks. */
.header-actions .btn {
  flex-shrink: 1;
  min-width: 0;
}

.header-actions > :not(.btn) {
  flex: none;
}

/* The phone menu: a sheet under the header, behind a Menu button. Hidden on
   a desk, where the row carries the same links. */
.nav-menu {
  display: none;
  position: relative;
}

.nav-menu > summary {
  list-style: none;
}

.nav-menu > summary::-webkit-details-marker {
  display: none;
}

.menu-icon-close {
  display: none;
}

.nav-menu[open] .menu-icon-open {
  display: none;
}

.nav-menu[open] .menu-icon-close {
  display: inline;
}

.nav-sheet {
  position: absolute;
  top: calc(100% + 8px);
  right: -6px;
  z-index: 60;
  width: min(360px, calc(100vw - 24px));
  max-height: calc(100dvh - 84px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 6px 8px 8px;
  background: var(--bg-raised);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sheet);
}

.nav-sheet-group + .nav-sheet-group {
  margin-top: 6px;
  padding-top: 4px;
  border-top: 1px solid var(--line);
}

.nav-sheet-heading {
  padding: 6px 10px 0;
  color: var(--text-faint);
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  line-height: 16px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.nav-sheet-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 4px;
}

/* The call to action stays pinned to the bottom of the sheet while it scrolls. */
.nav-sheet-foot {
  position: sticky;
  bottom: -8px;
  z-index: 1;
  display: grid;
  gap: 6px;
  margin: 6px -8px -8px;
  padding: 10px 8px 12px;
  border-top: 1px solid var(--line);
  background: var(--bg-raised);
}

/* Sign in sits beside the call, always in reach at the foot of the menu. */
.nav-sheet-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
}

/* The account menu: avatar button, then a small list. */
.account-menu {
  position: relative;
}

.account-menu > summary {
  list-style: none;
}

.account-menu > summary::-webkit-details-marker {
  display: none;
}

.avatar-button {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 3px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 999px;
  cursor: pointer;
}

.avatar-button:hover,
.account-menu[open] > .avatar-button {
  border-color: var(--line-strong);
  background: var(--bg-raised);
}

.avatar {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  border: 1px solid var(--line-strong);
}

.menu-who {
  padding: 8px 10px 10px;
  margin-bottom: 5px;
  border-bottom: 1px solid var(--line);
}

.menu-who .who-email {
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.menu-who .who-plan {
  margin-top: 2px;
  font-size: 12.5px;
  color: var(--text-dim);
}

/* Degrades in a set order as width shrinks: link padding, then Sign in, then
   the whole row gives way to the phone menu at 860px. */
@media (max-width: 1100px) {
  .site-nav {
    margin-left: 8px;
  }
  .site-nav .nav-link {
    padding: 4px 8px;
  }
}

/* The setup call button leaves the header first; the menu sheet keeps it. */
@media (max-width: 1180px) {
  .header-actions .hide-call {
    display: none;
  }
}

@media (max-width: 860px) {
  .site-nav {
    display: none;
  }
  .nav-menu {
    display: block;
  }
  .header-actions .hide-narrow {
    display: none;
  }
}

@media (max-width: 720px) {
  .site-header .wordmark {
    font-size: 21px;
  }
  .header-actions {
    gap: 2px;
  }
  .header-actions .hide-phone {
    display: none;
  }
}

@media (max-width: 380px) {
  .header-actions .btn {
    --btn-px: 12px;
  }
}

/* Four 44px tools and the full wordmark do not fit under 360px (a small phone,
   or 400% zoom on a laptop), so the app header keeps just the mark. So does
   the site header when signed in (Dashboard, the account and the menu, as on
   a 404). The link keeps its name. */
@media (max-width: 359px) {
  .app-header .wordmark-plain,
  .site-header-inner:has(.account-menu) .wordmark-plain {
    display: none;
  }
  /* At 320 the 21px wordmark, Start tracking and the menu run 16px past the
     gutter; 18px keeps all three on the row. */
  .site-header .wordmark {
    font-size: 18px;
  }
}

/* ---------------- footer ---------------- */

.site-footer {
  border-top: 1px solid var(--line);
  background: var(--bg-raised);
}

.footer-inner {
  padding-block: 36px 0;
}

.footer-grid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  column-gap: 32px;
  row-gap: 28px;
  align-items: start;
}

.footer-brand {
  grid-column: span 2;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.site-footer .wordmark {
  display: inline-flex;
  align-items: center;
  /* Tall enough for the whole drawing, the t's ascender and the g's tail. */
  min-height: 24px;
  font-size: 18px;
  align-self: flex-start;
}

.footer-tagline {
  margin-top: 10px;
  max-width: 30em;
  color: var(--text-dim);
  font-size: 13px;
  line-height: 1.5;
}

.footer-group {
  min-width: 0;
}

.footer-eyebrow {
  display: flex;
  align-items: center;
  height: 20px;
  margin: 0;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-faint);
}

/* Held open wider than a phone, where the summary is only the eyebrow. */
.footer-summary {
  display: block;
  list-style: none;
  cursor: default;
  pointer-events: none;
}

.footer-summary::-webkit-details-marker {
  display: none;
}

.footer-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
}

.footer-list a,
.footer-compare a {
  display: inline-block;
  padding: 1px 0;
  color: var(--text-dim);
  font-size: 13px;
  line-height: 1.4;
}

.footer-list a:hover,
.footer-compare a:hover,
.footer-meta a:hover {
  color: var(--text);
  text-decoration: none;
}

.footer-compare {
  margin-top: 28px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
}

.footer-compare .footer-list {
  flex-direction: row;
  flex-wrap: wrap;
  gap: 6px 28px;
  margin-top: 10px;
}

.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 4px 24px;
  margin-top: 18px;
  padding-block: 10px 14px;
  border-top: 1px solid var(--line);
  font-size: 12px;
  color: var(--text-faint);
}

.footer-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 18px;
}

.footer-meta a {
  color: var(--text-faint);
  font-size: 12px;
  white-space: nowrap;
}

/* The toggle keeps its box; pulling it out by its padding keeps the glyph on the edge. */
.footer-meta .icon-button {
  margin-right: -10px;
}

@media (max-width: 900px) {
  .footer-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
  .footer-brand {
    grid-column: 1 / -1;
  }
}

/* A phone: the brand, then the groups as rows between hairlines, each a
   full-width eyebrow with a chevron, closed until tapped. */
@media (max-width: 720px) {
  .footer-inner {
    padding-block: 28px 0;
  }
  .footer-grid {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 0;
  }
  .footer-brand {
    margin-bottom: 22px;
  }
  .footer-group {
    border-top: 1px solid var(--line);
  }
  .footer-compare {
    margin-top: 0;
    padding-top: 0;
  }
  .footer-summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-height: 48px;
    cursor: pointer;
    pointer-events: auto;
    -webkit-tap-highlight-color: transparent;
  }
  .footer-summary .footer-eyebrow {
    height: auto;
    font-size: 12px;
  }
  .footer-summary::after {
    content: '';
    flex: 0 0 auto;
    width: 14px;
    height: 14px;
    margin-right: 2px;
    background: var(--text-dim);
    -webkit-mask: var(--chevron) center / contain no-repeat;
    mask: var(--chevron) center / contain no-repeat;
    transition: transform 0.15s ease;
  }
  .footer-group[open] > .footer-summary::after {
    transform: rotate(180deg);
  }
  .footer-list,
  .footer-compare .footer-list {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 16px;
    margin: 0 0 12px;
  }
  .footer-list a,
  .footer-compare a,
  .footer-meta a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    /* Large text: a long word breaks inside its column. */
    max-width: 100%;
    overflow-wrap: anywhere;
  }
  .footer-bottom {
    flex-direction: column-reverse;
    align-items: flex-start;
    margin-top: 0;
    padding-top: 6px;
  }
}

/* ---------------- auth pages ---------------- */

.auth {
  display: grid;
  /* One column no wider than the screen, whatever the card holds (large text). */
  grid-template-columns: minmax(0, 1fr);
  place-items: start center;
  padding-block: 56px 72px;
  /* The card sits in no container, so it needs the gutter itself: 16px on phones, not edge to edge. */
  padding-inline: var(--gutter);
}

.auth-card {
  width: 100%;
  max-width: 420px;
  padding: 28px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-panel);
}

.auth-card h1 {
  font-size: 24px;
  font-weight: 700;
}

.auth-card .auth-sub {
  margin-top: 6px;
  color: var(--text-dim);
}

.auth-card .form {
  margin-top: 22px;
}

.auth-actions {
  margin-top: 22px;
}

.auth-social {
  display: grid;
  gap: 10px;
  margin-top: 22px;
}

.auth-social svg {
  flex: none;
}

.auth-or {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 20px;
  font-size: 13px;
  color: var(--text-dim);
}

.auth-or::before,
.auth-or::after {
  content: '';
  flex: 1;
  border-top: 1px solid var(--line);
}

.auth-or + .form {
  margin-top: 16px;
}

.auth-alt {
  margin-top: 18px;
  font-size: 14px;
  color: var(--text-dim);
  text-align: center;
}
/* Each link wraps whole ("Forgot your password?" never splits across lines).
   Where the two do not fit on one line they stack, and the dot goes. */
.auth-alt a {
  white-space: nowrap;
}
.auth-dot {
  margin-inline: 6px;
  color: var(--text-faint);
}

@media (max-width: 480px) {
  .auth-alt:has(.auth-dot) {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    gap: var(--space-2);
  }
  /* Stacked, each link has its own line; only large text ever breaks one. */
  .auth-alt:has(.auth-dot) a {
    white-space: normal;
  }
  .auth-alt .auth-dot {
    display: none;
  }
}

@media (max-width: 480px) {
  .auth {
    padding-block: 24px 48px;
  }
  .auth-card {
    padding: 22px 18px;
  }
}

/* ---------------- app shell ---------------- */

.app-header .container {
  max-width: 1400px;
}

.app-notice {
  margin-bottom: 20px;
}

.app-notice.notice,
.app-notice > .notice {
  align-items: center;
}

.notice-action {
  margin: 0 0 0 auto;
}

@media (max-width: 480px) {
  .app-notice,
  .app-notice.notice,
  .app-notice > .notice {
    flex-direction: column;
    align-items: flex-start;
  }
  /* A notice's action drops under its words on a phone, its left edge on
     theirs (the icon keeps its own column), so the words keep the width.
     A notice with no icon (the confirm-your-email banner in src/layout.ts,
     the View as banner in src/viewAs.ts) has one column: with two, its words took the first and
     pushed the action off the right edge of the page. */
  .notice:has(> .notice-action) {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
  }
  .notice:has(> .notice-action):not(:has(> .notice-icon)) {
    grid-template-columns: minmax(0, 1fr);
  }
  .notice:has(> .notice-action) > .notice-action {
    grid-column: -2;
    justify-self: start;
    margin: 0;
  }
}

.app-frame {
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr);
  flex: 1 0 auto;
  width: 100%;
  max-width: 1400px;
  margin: 0 auto;
  /* The sidebar's rule, drawn by the frame so it runs the full page height. */
  background: linear-gradient(var(--line), var(--line)) 219px 0 / 1px 100% no-repeat;
}

.app-nav {
  position: sticky;
  top: calc(var(--header-h) + 1px);
  align-self: start;
  display: flex;
  flex-direction: column;
  gap: 2px;
  /* Only as tall as its links, never a full screen: a full-screen sidebar
     made every frame a screen tall, so the footer below it gave even a short
     page 56px to scroll, and the page and sidebar slid up under the header.
     In a window too short for its links it scrolls by itself. */
  max-height: calc(100dvh - var(--header-h) - 1px);
  overflow-y: auto;
  padding: 20px 12px 20px var(--gutter);
}

.app-nav-link {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 40px;
  padding: 6px 10px;
  border-radius: 8px;
  color: var(--text-dim);
  font-weight: 500;
}

.app-nav-link svg {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  color: var(--text-faint);
}

.app-nav-link:hover {
  color: var(--text);
  background: var(--bg-raised);
  text-decoration: none;
}

.app-nav-link[aria-current='page'] {
  color: var(--text);
  background: var(--bg-active);
}

.app-nav-link[aria-current='page'] svg {
  color: var(--accent);
}

.app-nav-sep {
  height: 1px;
  margin: 8px 10px;
  background: var(--line);
}

.app-main {
  min-width: 0;
  padding: 28px var(--gutter) 64px;
}

/* The space from a tab row (appTabs) to the page under it, as on a site's tabs. */
.app-tabbed,
.set-page {
  margin-top: 24px;
}

/* ---- Settings (src/routes/account.ts): the full frame width, like a site's
   pages. Cards sit two to a row and share the row's height; a card left
   alone on its row takes the whole width. One column under 960px. */
.set-notices {
  display: grid;
  gap: 12px;
  margin-bottom: 16px;
}

.set-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}

.set-grid > :last-child:nth-child(odd) {
  grid-column: 1 / -1;
}

/* Delete account (src/routes/accountDelete.ts): what goes, one line each. */
.del-list {
  display: grid;
  gap: 10px;
  margin: 0;
  padding-left: 20px;
  line-height: 1.5;
}

/* A stretched card keeps its own rhythm at the top instead of spreading out. */
.set-grid > .card {
  align-content: start;
}

/* Long lines stay readable on a whole-width card. */
.set-grid .muted,
.set-grid .field-hint {
  max-width: 72ch;
}

.set-line {
  gap: 12px;
}

/* ---- Settings, Partner (src/routes/partners.ts) and /partners: an uploaded
   agency logo, square and contained, the same on both. */
.pt-logo {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  object-fit: contain;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}

/* The program card sits beside the tall form: it keeps its own height. */
.set-grid > .pt-about-card {
  align-self: start;
}

.pt-stats {
  display: grid;
  /* Three across on a wide card, wrapping on a phone so "$1,234.00" never squeezes. */
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: var(--space-4);
}

.pt-checks {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2) var(--space-4);
  margin-top: var(--space-1);
}

.pt-serves-field {
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

.pt-logo-now,
.pt-mini {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-2);
}

.pt-mini {
  margin-top: 0;
}

@media (max-width: 520px) {
  .pt-checks {
    grid-template-columns: minmax(0, 1fr);
  }
}

.set-value {
  overflow-wrap: anywhere;
}

@media (max-width: 960px) {
  .set-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

.app-footer {
  padding: 18px var(--gutter);
  border-top: 1px solid var(--line);
  font-size: 12px;
  color: var(--text-faint);
}

.app-footer .footer-meta {
  justify-content: space-between;
}

/* On a phone the sidebar becomes a row of tabs under the header. */
@media (max-width: 860px) {
  .app-frame {
    grid-template-columns: minmax(0, 1fr);
    /* Rows keep their own height; spare height stays under the page. */
    align-content: start;
    background: none;
  }
  .app-nav {
    position: sticky;
    top: calc(var(--header-h) + 1px);
    z-index: 40;
    flex-direction: row;
    height: auto;
    gap: 4px;
    padding: 6px var(--gutter);
    overflow-x: auto;
    background: var(--header-bg);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--line);
    scrollbar-width: none;
  }
  .app-nav::-webkit-scrollbar {
    display: none;
  }
  .app-nav-link {
    flex: 0 0 auto;
    min-height: 44px;
  }
  .app-nav-sep {
    display: none;
  }
  .app-main {
    padding-top: 20px;
  }
}

/* As a row of tabs the sections are words only: all seven fit a tablet,
   and four fit a 390px phone, the rest a swipe away under the fade. */
@media (max-width: 860px) {
  .app-nav-link svg {
    display: none;
  }
  .app-nav-link {
    padding-inline: 12px;
  }
}

/* ---------------- sites list ---------------- */

.site-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 14px;
}

/* A site card is a .card (ui.css): the dashboard's chrome. This lays it out. */
.site-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  transition: border-color var(--dur-1) ease;
}

.site-card:hover {
  border-color: var(--line-strong);
}

.site-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-2) 10px;
  min-width: 0;
}

.site-card-name {
  font-size: var(--type-heading);
  font-weight: var(--weight-title);
  color: var(--text);
  overflow-wrap: anywhere;
}

.site-card-name:hover {
  color: var(--accent);
  text-decoration: none;
}

.site-card-domain {
  margin-top: 2px;
  font-family: var(--mono);
  font-size: var(--type-caption);
  color: var(--text-dim);
  overflow-wrap: anywhere;
}

.site-card-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-start;
  gap: var(--space-2);
  margin-top: auto;
  font-size: var(--type-small);
  color: var(--text-faint);
}

.favicon-dot {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--accent);
  background: var(--accent-soft);
}

.site-card-id {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1 1 220px;
  min-width: 0;
}

.min-w-0 {
  min-width: 0;
}

.narrow {
  max-width: 680px;
}

.site-settings {
  margin-top: 24px;
}

/* A site's Goals, Integrations, Share and Settings tabs use the whole frame,
   like its dashboard: on a wide screen the cards flow into two columns, each
   card under the one above it, so short cards leave no holes. Anything that
   is not a card (a notice, a back link) spans both. A connector's own page
   stays one column. */
@media (min-width: 1100px) {
  .stack.site-settings:not(.cn-page) {
    display: block;
    max-width: none;
    column-count: 2;
    column-gap: var(--space-4);
  }
  .stack.site-settings:not(.cn-page) > * {
    break-inside: avoid;
    margin-bottom: var(--space-4);
  }
  .stack.site-settings:not(.cn-page) > :not(.card) {
    column-span: all;
  }
}

.archived-table {
  margin-top: var(--space-3);
}

/* Cloudflare Turnstile (src/turnstile.ts): the widget sizes itself; this only
   spaces it and keeps the reserved height steady while it loads. */
.turnstile {
  margin-block: 4px 12px;
  min-height: 65px;
}

/* No lone words. Headings split their lines evenly, so "story." never drops
   to a line of its own; body copy avoids a one-word last line. Browsers
   without text-wrap simply wrap as before. Lines a heading forces itself
   (.hero-line, white-space: nowrap) are unaffected. */
h1,
h2,
h3,
h4,
.section-title,
.page-title {
  text-wrap: balance;
}

p,
li,
dd,
figcaption {
  text-wrap: pretty;
}

/* The Sporetag mark at the top of sign up, sign in and password pages. */
.auth-mark {
  display: block;
  width: 48px;
  height: 48px;
  margin-bottom: 16px;
  border-radius: 12px;
}

/* The blue t tile beside the wordmark (src/layout.ts), sized from the
   wordmark's font-size so header and footer stay in proportion. */
.wordmark {
  gap: 0.42em;
}
.wordmark-mark {
  display: block;
  flex: none;
  width: 1.3em;
  height: 1.3em;
}

/* The plain wordmark beside the tile: same letter scale and baseline as the
   accent wordmark (90 of its 108 units tall), so the lockup lines up. */
.wordmark-svg.wordmark-plain {
  height: 0.989em;
  aspect-ratio: 450 / 94;
  /* Center the letters' x-height (y 11 to 65) on the tile, not the box,
     which also holds the p and g tails: drop the old baseline margin and
     nudge the drawing down by the 7 units between the two centers. */
  margin-bottom: 0;
  transform: translateY(0.074em);
}

/* ---------------- two-step sign-in (src/routes/twoFactor.ts) ---------------- */

/* The lock after "Admin" in the menus while Admin needs two-step sign-in. */
.nav-lock {
  display: inline-flex;
  margin-left: auto;
  color: var(--text-faint);
}
.nav-lock svg,
.app-nav-link .nav-lock svg {
  width: 14px;
  height: 14px;
}

.tf-head {
  gap: 12px;
}

/* Setup: two numbered steps in one card, a hairline between them. */
.tf-setup {
  display: grid;
  gap: 0;
  padding: 0;
  overflow: hidden;
}
.tf-step {
  display: grid;
  gap: 8px;
  padding: 24px;
}
.tf-step + .tf-step {
  border-top: 1px solid var(--line);
}
.tf-step-label {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}
.tf-qr-row {
  display: flex;
  align-items: center;
  gap: 24px;
  margin-top: 10px;
}
/* The code stays dark on white in both themes: phone cameras need the contrast. */
.tf-qr {
  flex: none;
  padding: 8px;
  line-height: 0;
  background: #ffffff;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
}
.tf-qr svg {
  display: block;
  width: 168px;
  height: 168px;
}
.tf-key {
  display: grid;
  justify-items: start;
  gap: 8px;
  min-width: 0;
}
.tf-key-text {
  display: block;
  max-width: 100%;
  padding: 10px 12px;
  font-family: var(--mono);
  font-size: 14px;
  letter-spacing: 0.06em;
  line-height: 1.5;
  word-break: break-all;
  color: var(--text);
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.tf-step .field {
  max-width: 220px;
}
/* Six digits read best big, spaced and centered. */
input.field-input[autocomplete='one-time-code'][inputmode='numeric'] {
  font-family: var(--mono);
  font-size: 20px;
  letter-spacing: 0.18em;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.auth-card input.field-input[autocomplete='one-time-code'][inputmode='numeric'] {
  font-size: 22px;
}

.tf-manage .field {
  max-width: 320px;
}

/* Recovery codes: two columns of mono codes in an inset well. */
.tf-codes {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px 24px;
  margin: 0;
  padding: 18px 22px;
  list-style: none;
  counter-reset: tf;
  font-family: var(--mono);
  font-size: 15px;
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
  background: var(--bg-tint);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.tf-codes li {
  counter-increment: tf;
  white-space: nowrap;
}
.tf-codes li::before {
  content: counter(tf, decimal-leading-zero);
  display: inline-block;
  width: 2.4em;
  font-size: 11px;
  color: var(--text-faint);
}

/* The Admin gate: one centered card, one action. */
.tf-gate {
  display: grid;
  justify-items: center;
  gap: 12px;
  max-width: 520px;
  margin: 48px auto 0;
  padding: 36px 32px;
  text-align: center;
  background: var(--bg-raised);
  box-shadow: var(--shadow-panel);
}
.tf-gate-icon {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  margin-bottom: 4px;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 14px;
}
.tf-gate-icon svg {
  width: 26px;
  height: 26px;
}
.tf-gate-title {
  font-size: 22px;
  font-weight: 650;
  letter-spacing: -0.01em;
  line-height: 1.3;
}
.tf-gate .btn {
  margin-top: 8px;
}
.tf-gate-note {
  font-size: 13.5px;
  color: var(--text-faint);
}

@media (max-width: 720px) {
  .tf-qr-row {
    flex-direction: column;
    align-items: stretch;
  }
  .tf-qr {
    align-self: center;
  }
  .tf-step {
    padding: 20px 18px;
  }
  .tf-step .field {
    max-width: none;
  }
  .tf-gate {
    margin-top: 16px;
    padding: 28px 20px;
  }
}
@media (max-width: 400px) {
  .tf-codes {
    gap: 8px 12px;
    padding: 14px 14px;
    font-size: 14px;
  }
  .tf-codes li::before {
    width: 2em;
  }
}

/* ---------------- home-screen app (public/static/pwa.js, src/routes/pwa.ts) ---------------- */

/* The add-to-home-screen hint: once, on a phone, above the home indicator. */
.a2hs {
  position: fixed;
  z-index: 90;
  right: max(12px, env(safe-area-inset-right));
  bottom: max(12px, env(safe-area-inset-bottom));
  left: max(12px, env(safe-area-inset-left));
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr);
  gap: 4px 12px;
  align-items: center;
  max-width: 480px;
  margin: 0 auto;
  padding: 14px 16px;
  background: var(--bg-raised);
  color: var(--text);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sheet);
  animation: a2hs-in 0.24s ease-out;
}

/* Out of the way while the Assistant is open: its field and Send button sit at the bottom too. */
body.as-on .a2hs {
  display: none;
}

@keyframes a2hs-in {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
}

.a2hs-icon {
  border-radius: 9px;
}

.a2hs-title {
  margin: 0;
  font-weight: 600;
}

.a2hs-line {
  margin: 2px 0 0;
  color: var(--text-dim);
  font-size: 14px;
  line-height: 1.45;
}

.a2hs-actions {
  display: flex;
  grid-column: 1 / -1;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 8px;
}

@media (prefers-reduced-motion: reduce) {
  .a2hs {
    animation: none;
  }
}

/* The offline page: one calm card, centered, inside the safe area. */
.offline-body {
  min-height: 100vh;
  min-height: 100dvh;
}

.offline {
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 12px;
  min-height: 100vh;
  min-height: 100dvh;
  padding: max(24px, env(safe-area-inset-top)) max(16px, env(safe-area-inset-right)) max(24px, env(safe-area-inset-bottom)) max(16px, env(safe-area-inset-left));
  text-align: center;
}

.offline h1 {
  margin: 8px 0 0;
  font-size: 24px;
}

.offline p {
  max-width: 30ch;
  margin: 0 0 8px;
  color: var(--text-dim);
}

.offline-mark {
  border-radius: 12px;
}

/* ---------------- phone polish: the main app pages ----------------
   Sites, the dashboard in view mode, Messages and Reports on a touch screen.
   Every control is at least 44px to tap (Apple's guidelines, WCAG 2.5.5).
   Where a bigger box would change the look (pills, a tile's menu, tab chips),
   an invisible ::after grows the tap area instead. `.app` (and `.has-dash`, the
   dashboard on /demo and share pages) outranks the area
   files that load after this one. Phone width counts too: a phone is always touch. */
@media (pointer: coarse), (max-width: 720px) {
  :is(.app, .has-dash) .field-check {
    min-height: 44px;
  }
  :is(.app, .has-dash) .as-open,
  :is(.app, .has-dash) .chip,
  :is(.app, .has-dash) .dash-board-btn,
  :is(.app, .has-dash) .dash-live-btn {
    min-height: 44px;
  }
  :is(.app, .has-dash) .dash-tool:not(.dw-menu-btn) {
    width: 44px;
    height: 44px;
  }
  :is(.app, .has-dash) .dash-row {
    min-height: 44px;
  }
  :is(.app, .has-dash) .site-card-foot > a:not(.btn) {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
  :is(.app, .has-dash) .site-card-name,
  :is(.app, .has-dash) .scs-action,
  :is(.app, .has-dash) .dash-sub .pill,
  :is(.app, .has-dash) .site-card-pills a.pill,
  :is(.app, .has-dash) .dw-menu-btn,
  :is(.app, .has-dash) .dw-tabs button {
    position: relative;
  }
  :is(.app, .has-dash) .site-card-name::after,
  :is(.app, .has-dash) .scs-action::after,
  :is(.app, .has-dash) .dash-sub .pill::after,
  :is(.app, .has-dash) .site-card-pills a.pill::after,
  :is(.app, .has-dash) .dw-menu-btn::after,
  :is(.app, .has-dash) .dw-tabs button::after {
    content: '';
    position: absolute;
    inset: -12px -4px;
  }
  :is(.app, .has-dash) .dw-menu-btn::after {
    inset: -7px;
  }
  :is(.app, .has-dash) .dw-tabs button::after {
    inset: -7px -2px;
  }
  :is(.app, .has-dash) .dw-tabs button {
    min-width: 44px;
  }
}

/* Clear of the notch and the home indicator, in Safari and the Home Screen app
   (the viewport is viewport-fit=cover). The gutter grows only where an inset is wider. */
.app {
  --gutter: max(32px, env(safe-area-inset-left), env(safe-area-inset-right));
}
@media (max-width: 720px) {
  .app {
    --gutter: max(16px, env(safe-area-inset-left), env(safe-area-inset-right));
  }
}
@media (min-width: 721px) and (max-width: 1023px) {
  .app {
    --gutter: max(24px, env(safe-area-inset-left), env(safe-area-inset-right));
  }
}
.app .app-footer {
  padding-bottom: max(18px, env(safe-area-inset-bottom));
}

/* Inside an app's built-in browser the other sign-ins follow the email form (src/routes/social.ts socialAfter). */
.auth-social-after {
  margin-top: 16px;
}

.auth-social-after .field-hint {
  margin: 0;
  text-align: center;
}

/* /static/ui.css */
/**
 * Sporetag's components: one shared layer for the app, the sign-in pages and
 * the marketing site. Built only from the tokens in site.css (spacing, type,
 * control heights, radii, elevation, tones, motion). Area files (app-*.css)
 * arrange these; they do not restyle them.
 *
 *   page head and tabs     .app-page-head  .tabs-bar .tabs .tab .tab-count .tabs-more .tabs-sub
 *   cards                  .card .card-head .card-title .card-sub .card-actions .card-section
 *   buttons                .btn + .btn-sm|.btn-lg + .btn-primary|.btn-accent|.btn-secondary|.btn-quiet|.btn-danger|.btn-danger-solid  .btn-icon  .icon-button
 *   fields                 .field .field-label .field-input .field-hint .field-error .field-check .switch
 *   choices                .segmented .segment (2 or 3 options)  .chips .chip (filters)
 *   status                 .pill (+ -ok|-warn|-danger|-accent|-info, .pill-dot)  .badge  .checklist
 *   tables                 .table-wrap .table .num .table-empty
 *   feedback               .notice (+ -ok|-warn|-error)  .toast  .empty  .skeleton
 *   overlays               .dialog  .menu-list .menu-row  .cmdk  .kbd
 *   numbers                .stats (+ -2|-3|-4)  .stat .stat-wide .stat-label .stat-value .stat-word .stat-note .stat-body .spark-tile .delta
 *   sections and rows      .app-section-head .app-section-title .app-section-meta  .list .list-row .list-mark .list-main .list-title .list-sub .list-end
 *   the way in             .btn-go (actionLink)
 */

/* ---------------- app and sign-in sizes ----------------
   The app is a tool: 36px controls and 14px text in them. Sign-in pages
   use the 44px step. Every control on a phone is 44px, and fields are 16px
   so iOS does not zoom. */

body.app {
  --btn-h-sm: var(--ctl-h-sm);
  --btn-h-md: var(--ctl-h-md);
  --btn-h-lg: var(--ctl-h-lg);
  --btn-fs-sm: var(--fs-13);
  --btn-fs-md: var(--fs-14);
  --btn-fs-lg: var(--fs-15);
  --btn-px-sm: 10px;
  --btn-px-md: 14px;
  --btn-px-lg: 18px;
  --field-h: var(--ctl-h-md);
  --field-fs: var(--fs-14);
  --seg-h: var(--ctl-h-md);
}

.auth {
  --field-h: var(--ctl-h-lg);
  --btn-h-md: var(--ctl-h-lg);
  --btn-h-lg: var(--ctl-h-lg);
}

@media (max-width: 720px) {
  body.app,
  .auth {
    --btn-h-sm: var(--ctl-h-lg);
    --btn-h-md: var(--ctl-h-lg);
    --btn-h-lg: var(--ctl-h-lg);
    --field-h: var(--ctl-h-lg);
    --field-fs: var(--fs-16);
    --seg-h: var(--ctl-h-lg);
  }
}

/* iOS Safari zooms the whole page into any text field or select under 16px
   the moment it gets focus, and leaves it zoomed. On a phone or a tablet no
   field is smaller, whatever an area file sets (the board's tab select, the
   link form's mono fields). */
@media (max-width: 720px), (pointer: coarse) {
  :where(body) :is(input:not([type='checkbox'], [type='radio'], [type='range'], [type='file'], [type='color'], [type='hidden']), select, textarea) {
    font-size: max(var(--fs-16), 1em) !important;
  }
}

/* ---------------- page transitions ----------------
   Same-origin page loads cross-fade where the browser supports it
   (progressive: nothing happens elsewhere). The header and the side nav keep
   their own names, so only the page under them changes. */

@media (prefers-reduced-motion: no-preference) {
  @view-transition {
    navigation: auto;
  }
}

::view-transition-group(root) {
  animation-duration: var(--dur-2);
  animation-timing-function: var(--ease-out);
}

.app-header {
  view-transition-name: app-header;
}

.app-nav {
  view-transition-name: app-nav;
}

/* ---------------- page head ----------------
   appHead() in src/layout.ts: the title, one line under it, actions right. */

.app-page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-3) var(--space-4);
  margin-bottom: var(--space-6);
}

.app-page-head h1,
.app-page-head .app-page-name {
  font-size: var(--type-display);
  font-weight: 700;
  line-height: var(--lh-tight);
  letter-spacing: var(--track-title);
}

.app-page-head .app-page-sub {
  margin-top: var(--space-1);
  font-size: var(--type-body);
  color: var(--text-dim);
}

.app-page-head > .row {
  gap: var(--space-2);
}

/* A short trail above a title: "Links / spring-sale". */
.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-2);
  margin-bottom: var(--space-2);
  font-size: var(--type-small);
  color: var(--text-faint);
}

.crumbs a {
  color: var(--text-dim);
}

.app-section + .app-section {
  margin-top: var(--space-8);
}

/* A heading over a group of cards inside a page. */
.app-section-title,
.section-label {
  margin-bottom: var(--space-3);
  font-size: var(--type-heading);
  font-weight: var(--weight-title);
  line-height: var(--lh-snug);
}

@media (max-width: 860px) {
  .app-page-head h1 {
    font-size: var(--fs-24);
  }
}

/* ---------------- tabs ----------------
   Underlined tabs for a page's sections (appTabs). A count rides after the word.
   The bar draws the rule, so "More" (ui.js moves tabs that do not fit into it)
   sits on the same line as the tabs. */

.tabs-bar {
  display: flex;
  align-items: stretch;
  min-width: 0;
  border-bottom: 1px solid var(--line);
}

.tabs {
  display: flex;
  flex: 0 1 auto;
  gap: var(--space-1);
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}

.tab[hidden],
.tabs-more[hidden] {
  display: none;
}

.tabs-more {
  flex: 0 0 auto;
}

.tabs-more-button {
  cursor: pointer;
}

.tabs-more-button svg {
  width: 14px;
  height: 14px;
  transition: transform var(--dur-2) var(--ease-out);
}

.tabs-more[open] .tabs-more-button {
  color: var(--text);
}

.tabs-more[open] .tabs-more-button svg {
  transform: rotate(180deg);
}

.tabs-more .menu-list {
  top: calc(100% + 2px);
}

/* The pages inside one tab (appSubTabs): a segmented row under the tabs. */
.tabs-sub {
  margin-top: var(--space-4);
}

/* One step from the tab row, or the pages row under it, to the page, on
   every page: no page starts flush against the tabs. The dashboard
   (.dash and what sits over it) keeps its own spacing. */
:where(body.app) .tabs-bar + :not(.tabs-sub, .dash, .dash-setup, .dash-notice, script, style, template) {
  margin-top: var(--space-6);
}

:where(body.app) .tabs-sub + :not(script, style, template) {
  margin-top: var(--space-5);
}

.tabs::-webkit-scrollbar {
  display: none;
}

/* On a phone the section row tucks under the header while you scroll down and
   comes back the moment you scroll up (ui.js), like Safari's own bars: the
   numbers get the 57px it took. It stays while anything in it has focus. */
@media (max-width: 860px) {
  .app-nav {
    transition: transform var(--dur-3) var(--ease-out), opacity var(--dur-2) ease;
  }
  body.nav-tucked .app-nav:not(:focus-within) {
    transform: translateY(calc(-100% - 1px));
    opacity: 0;
    pointer-events: none;
  }
}

/* On a phone the row scrolls; its edges fade so a cut-off word reads as "more".
   The app's section row under the header does the same. */
@media (max-width: 860px) {
  .app-nav {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent 100%);
    mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent 100%);
  }
}

@media (max-width: 720px) {
  .tabs {
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 12px, #000 calc(100% - 20px), transparent 100%);
    mask-image: linear-gradient(to right, transparent 0, #000 12px, #000 calc(100% - 20px), transparent 100%);
  }
  /* Once ui.js has fitted the row, nothing is cut off, so nothing fades. */
  .tabs-bar.is-fitted .tabs {
    -webkit-mask-image: none;
    mask-image: none;
  }
}

.tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: var(--ctl-h-lg);
  padding: 0 var(--space-3);
  margin-bottom: -1px;
  font-size: var(--type-ui);
  font-weight: var(--weight-medium);
  color: var(--text-dim);
  white-space: nowrap;
  border-bottom: 2px solid transparent;
  transition: color var(--dur-1) ease, border-color var(--dur-2) var(--ease-out);
}

.tab:hover {
  color: var(--text);
  text-decoration: none;
}

.tab[aria-current='page'],
.tab[aria-selected='true'] {
  color: var(--text);
  border-bottom-color: var(--accent);
}

.tab:focus-visible {
  outline-offset: -4px;
}

.tab-count,
.badge {
  display: inline-grid;
  place-items: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  font-size: var(--fs-11);
  font-weight: var(--weight-strong);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--text-dim);
  /* 6.1:1 light, 6.9:1 dark: --bg-active would drop under 4.5. */
  background: var(--bg-tint);
  box-shadow: inset 0 0 0 1px var(--line);
  border-radius: var(--r-pill);
}

.tab[aria-current='page'] .tab-count,
.badge-accent {
  color: var(--accent);
  background: var(--accent-soft);
}

/* ---------------- buttons ----------------
   `.btn` plus at most one size and one look.
     size   .btn-sm   (default)   .btn-lg
     look   .btn-primary (green, the one main action)   .btn-secondary (default)
            .btn-accent (blue)   .btn-quiet   .btn-danger   .btn-danger-solid
     shape  .btn-icon (square)   .btn-block (full width)
   Every look changes only six colors. */

.btn {
  --btn-bg: var(--bg-raised);
  --btn-fg: var(--text);
  --btn-line: var(--line-control);
  --btn-bg-hover: var(--bg-hover);
  --btn-fg-hover: var(--btn-fg);
  --btn-line-hover: var(--line-strong);
  --btn-h: var(--btn-h-md);
  --btn-fs: var(--btn-fs-md);
  --btn-px: var(--btn-px-md);

  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.45em;
  min-height: var(--btn-h);
  margin: 0;
  padding: 0 var(--btn-px);
  font: inherit;
  font-size: var(--btn-fs);
  font-weight: var(--weight-strong);
  line-height: 1.2;
  color: var(--btn-fg);
  background: var(--btn-bg);
  border: 1px solid var(--btn-line);
  border-radius: var(--btn-radius);
  box-shadow: var(--btn-shadow, none);
  cursor: pointer;
  text-decoration: none;
  /* A label stays on one line wherever its button fits. A button wider than
     its whole box (large text, browser zoom, a 320px phone) breaks its words
     instead of running off the screen. It never shrinks to make room for its
     neighbors, so a row that fits today looks the same. */
  white-space: normal;
  text-align: center;
  flex-shrink: 0;
  max-width: 100%;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  transition:
    background-color var(--dur-1) ease,
    border-color var(--dur-1) ease,
    color var(--dur-1) ease,
    transform var(--dur-1) ease;
}

.btn:hover {
  color: var(--btn-fg-hover);
  background: var(--btn-bg-hover);
  border-color: var(--btn-line-hover);
  text-decoration: none;
}

.btn:active {
  transform: translateY(1px);
}

.btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.btn:disabled,
.btn[aria-disabled='true'] {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none;
}

.btn:disabled:hover,
.btn[aria-disabled='true']:hover {
  color: var(--btn-fg);
  background: var(--btn-bg);
  border-color: var(--btn-line);
}

/* Working: the words stay, a small ring turns before them. */
.btn[aria-busy='true'] {
  cursor: progress;
}

.btn[aria-busy='true']::before {
  content: '';
  width: 0.95em;
  height: 0.95em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: ui-spin 0.7s linear infinite;
}

@keyframes ui-spin {
  to {
    transform: rotate(360deg);
  }
}

.btn svg {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
}

.btn-sm {
  --btn-h: var(--btn-h-sm);
  --btn-fs: var(--btn-fs-sm);
  --btn-px: var(--btn-px-sm);
}

.btn-sm svg {
  width: 15px;
  height: 15px;
}

.btn-lg {
  --btn-h: var(--btn-h-lg);
  --btn-fs: var(--btn-fs-lg);
  --btn-px: var(--btn-px-lg);
}

.btn-primary,
.btn-cta {
  --btn-bg: var(--cta);
  --btn-fg: var(--cta-ink);
  --btn-line: transparent;
  --btn-bg-hover: var(--cta-hover);
  --btn-line-hover: transparent;
  --btn-shadow: var(--elev-1);
}

.btn-accent {
  --btn-bg: var(--accent);
  --btn-fg: var(--accent-ink);
  --btn-line: transparent;
  --btn-bg-hover: var(--accent-hover);
  --btn-line-hover: transparent;
  --btn-shadow: var(--elev-1);
}

.btn-secondary {
  --btn-bg: var(--bg-raised);
  --btn-fg: var(--text);
  --btn-line: var(--line-control);
  --btn-shadow: var(--elev-1);
}

.btn-quiet {
  --btn-bg: transparent;
  --btn-fg: var(--text-dim);
  --btn-line: transparent;
  --btn-bg-hover: var(--bg-hover);
  --btn-fg-hover: var(--text);
  --btn-line-hover: transparent;
  font-weight: var(--weight-medium);
}

.btn-danger {
  --btn-bg: transparent;
  --btn-fg: var(--danger-fg);
  --btn-line: color-mix(in srgb, var(--danger) 45%, transparent);
  --btn-bg-hover: var(--danger-bg);
  --btn-fg-hover: var(--danger-text);
  --btn-line-hover: var(--danger-line);
}

.btn-danger-solid {
  --btn-bg: var(--danger);
  --btn-fg: var(--danger-ink);
  --btn-line: transparent;
  --btn-bg-hover: var(--danger-hover);
  --btn-fg-hover: var(--danger-ink);
  --btn-line-hover: transparent;
}

.btn-icon {
  flex: 0 0 auto;
  width: var(--btn-h);
  padding: 0;
}

.btn-block {
  display: flex;
  width: 100%;
}

/* A borderless square button: the theme toggle, the menu, a close. */
.icon-button {
  display: inline-grid;
  place-items: center;
  flex: 0 0 auto;
  width: var(--ctl-h-md);
  height: var(--ctl-h-md);
  padding: 0;
  color: var(--text-dim);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-md);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color var(--dur-1) ease, color var(--dur-1) ease;
}

@media (hover: hover) {
  .icon-button:hover {
    color: var(--text);
    background: color-mix(in srgb, var(--text) 6%, transparent);
  }
}

.icon-button:active {
  color: var(--text);
  background: color-mix(in srgb, var(--text) 10%, transparent);
}

.icon-button svg {
  width: 17px;
  height: 17px;
}

@media (max-width: 720px) {
  .icon-button {
    width: var(--ctl-h-lg);
    height: var(--ctl-h-lg);
  }
}

/* The theme button shows where a click goes: the sun while dark, the moon
   while light. Chosen from <html> so the first paint is right. */
.theme-toggle .theme-icon-sun {
  display: none;
}

:root[data-theme='dark'] .theme-toggle .theme-icon-sun {
  display: inline;
}

:root[data-theme='dark'] .theme-toggle .theme-icon-moon {
  display: none;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .theme-toggle .theme-icon-sun {
    display: inline;
  }
  :root:not([data-theme]) .theme-toggle .theme-icon-moon {
    display: none;
  }
}

/* ---------------- segmented control ----------------
   For two or three choices that switch a view. A sunken track with the
   chosen one raised on it, the same everywhere (and in the dashboard).
   <div class="segmented" role="tablist"><button class="segment" role="tab" aria-selected="true">..</button></div>
   Links work too: <a class="segment" aria-current="page">. So do radios:
   <label><input type="radio" class="visually-hidden"><span class="segment">..</span></label>. */

.segmented {
  --seg-h: var(--ctl-h-md);
  display: inline-flex;
  gap: 2px;
  max-width: 100%;
  min-height: var(--seg-h);
  padding: 3px;
  background: var(--bg-tint);
  border: 1px solid var(--line);
  border-radius: calc(var(--r-md) + 2px);
}

.segment {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  flex: 0 0 auto;
  min-height: calc(var(--seg-h) - 8px);
  margin: 0;
  padding: 0 var(--space-3);
  font: inherit;
  font-size: var(--fs-13);
  font-weight: var(--weight-strong);
  line-height: 1.2;
  white-space: nowrap;
  color: var(--text-dim);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-md);
  cursor: pointer;
  text-decoration: none;
  transition: background-color var(--dur-2) var(--ease-out), color var(--dur-1) ease, box-shadow var(--dur-2) ease;
}

.segment:hover {
  color: var(--text);
  text-decoration: none;
}

.segment[aria-selected='true'],
.segment[aria-current='page'],
.segment[aria-checked='true'],
.segment[aria-pressed='true'],
input:checked + .segment,
.segment:has(input:checked) {
  color: var(--text);
  background: var(--bg-raised);
  border-color: var(--line);
  box-shadow: var(--elev-1);
}

/* A finger on a phone: the segment keeps its look and gains 8px of tap area
   above and below, so the row reads 44px to a thumb. */
@media (pointer: coarse), (max-width: 720px) {
  .segment {
    position: relative;
  }
  .segment::after {
    content: '';
    position: absolute;
    inset: -8px 0;
  }
}

input:focus-visible + .segment,
.segment:has(input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.segment .count,
.segment .pill {
  margin-left: 2px;
}

@media (max-width: 480px) {
  .segmented {
    display: flex;
    flex-wrap: wrap;
    width: 100%;
  }
  /* Equal shares of the row, never narrower than their words: with large text
     a segment that does not fit moves to a second row instead of overlapping
     its neighbor. */
  .segment {
    flex: 1 1 0;
    min-width: max-content;
    padding-inline: var(--space-2);
  }
}

/* ---------------- form fields ----------------
   field() in src/ui.ts writes:
   <div class="field">
     <label class="field-label" for="x">Email</label>
     <input class="field-input" id="x">
     <p class="field-hint">..</p>   <p class="field-error">..</p>
   </div> */

.form {
  display: grid;
  gap: var(--space-4);
}

.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  margin: 0;
}

.field-label {
  font-size: var(--type-small);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
  color: var(--text);
}

.field-optional {
  font-weight: 400;
  color: var(--text-faint);
}

.field-hint {
  font-size: var(--type-small);
  line-height: 1.45;
  color: var(--text-dim);
}

.field-input {
  width: 100%;
  min-height: var(--field-h);
  margin: 0;
  padding: 6px var(--field-px);
  font: inherit;
  font-size: var(--field-fs);
  line-height: var(--lh-snug);
  color: var(--text);
  background: var(--bg-input);
  border: 1px solid var(--line-input);
  border-radius: var(--field-radius);
  transition: border-color var(--dur-1) ease, box-shadow var(--dur-2) ease;
}

/* Safari on iPhone centers a date or time in its field; every other field
   reads from the left, so these do too (the custom range, notes, a flow wait). */
.field-input::-webkit-date-and-time-value {
  text-align: start;
}

textarea.field-input {
  min-height: calc(var(--field-h) * 2.4);
  padding-block: var(--space-2);
  resize: vertical;
}

select.field-input {
  appearance: none;
  -webkit-appearance: none;
  padding-right: calc(var(--field-px) + 22px);
  background-image: var(--select-chevron);
  background-repeat: no-repeat;
  background-position: right var(--field-px) center;
  background-size: 14px 14px;
  cursor: pointer;
}

/* Safari lays a long chosen option out past a narrow select's edge, and that
   overflow scrolls the page sideways on a phone (Settings, Currency: 6px at
   390). Clipping it keeps every one-line select inside its own box. */
select:not([multiple]):not([size]) {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* A file picker: the button looks like a secondary button, the name stays one line. */
input[type='file'].field-input {
  display: flex;
  align-items: center;
  padding: 3px;
  font-size: var(--fs-13);
  color: var(--text-dim);
  text-overflow: ellipsis;
  cursor: pointer;
}

input[type='file']::file-selector-button {
  min-height: calc(var(--field-h) - 8px);
  margin-right: var(--space-3);
  padding: 0 var(--space-3);
  font: inherit;
  font-size: var(--fs-13);
  font-weight: var(--weight-strong);
  color: var(--text);
  background: var(--bg-raised);
  border: 1px solid var(--line-control);
  border-radius: var(--r-sm);
  box-shadow: var(--elev-1);
  cursor: pointer;
}

input[type='file']::file-selector-button:hover {
  background: var(--bg-hover);
}

.field-input::placeholder {
  color: var(--text-faint);
  opacity: 1;
}

.field-input:hover:not(:disabled) {
  border-color: var(--text-dim);
}

/* A transparent outline, not none: Windows High Contrast paints it, since it drops box shadows. */
.field-input:focus {
  outline: 2px solid transparent;
  border-color: var(--accent);
  box-shadow: var(--focus-ring);
}

.field-input:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.field-input[aria-invalid='true'] {
  border-color: var(--danger);
}

.field-input[aria-invalid='true']:focus {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--danger) 25%, transparent);
}

.field-error {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  font-size: var(--type-small);
  line-height: 1.4;
  font-weight: var(--weight-medium);
  color: var(--danger-fg);
}

/* A mark before the words, so the error is not told by color alone. */
.field-error::before {
  content: '!';
  flex: 0 0 auto;
  display: inline-grid;
  place-items: center;
  width: 1.25em;
  height: 1.25em;
  margin-top: 0.05em;
  font-size: 0.85em;
  font-weight: 700;
  line-height: 1;
  color: var(--bg-raised);
  background: var(--danger-fg);
  border-radius: 50%;
}

.field-check {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  font-size: var(--type-ui);
  line-height: 1.4;
  cursor: pointer;
}

.field-check input {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  margin: 2px 0 0;
  accent-color: var(--accent);
}

.field-row {
  display: flex;
  gap: var(--space-2);
  align-items: stretch;
}

.field-row > .field-input {
  flex: 1 1 auto;
  min-width: 0;
}

.form-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-1);
}

@media (max-width: 480px) {
  .form-actions .btn {
    flex: 1 1 100%;
  }
}

/* A toggle for one setting that turns on or off at once.
   <label class="switch"><input type="checkbox" role="switch"> Words</label> */
.switch {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--ctl-h-sm);
  font-size: var(--type-ui);
  cursor: pointer;
}

.switch input {
  appearance: none;
  -webkit-appearance: none;
  position: relative;
  flex: 0 0 auto;
  width: 36px;
  height: 22px;
  margin: 0;
  /* --line-input keeps the off track at 3:1 against the card, and the knob at 3:1 on it. */
  background: var(--line-input);
  border-radius: var(--r-pill);
  cursor: pointer;
  transition: background-color var(--dur-2) ease;
}

.switch input::before {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  background: #ffffff;
  border-radius: 50%;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
  transition: transform var(--dur-2) var(--ease-out);
}

.switch input:checked {
  background: var(--accent);
}

.switch input:checked::before {
  transform: translateX(14px);
}

.switch input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.switch input:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ---------------- cards ----------------
   <section class="card">
     <div class="card-head"><div><h2 class="card-title">..</h2><p class="card-sub">..</p></div><div class="card-actions">..</div></div>
     ..
   </section> */

.card {
  min-width: 0;
  padding: var(--card-pad, var(--space-5));
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

/* In the app every surface wears the dashboard's card chrome
   (public/static/app-analytics.css, .dw): the raised surface, a hairline,
   12px corners, the resting lift and 16px in. A surface inside another
   stays flat, so a page never stacks shadows. */
body.app {
  --card-pad: var(--space-4);
}

:where(body.app) .card,
.card-raised {
  background: var(--bg-raised);
  border-radius: var(--r-lg);
  box-shadow: var(--elev-2);
}

:where(body.app) :is(.card, .list, .table-wrap, .stats) :is(.card, .list, .table-wrap, .stats) {
  box-shadow: none;
}

.card-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-2) var(--space-4);
  margin-bottom: var(--space-4);
}

.card-head > :first-child {
  min-width: 0;
}

.card-title {
  font-size: var(--type-heading);
  font-weight: var(--weight-title);
  line-height: var(--lh-snug);
}

.card-sub {
  margin-top: var(--space-1);
  font-size: var(--type-small);
  line-height: 1.45;
  color: var(--text-dim);
}

/* Older cards stack a title and its line in a .stack: keep them one unit,
   as cardHead() does, instead of a full gap apart. */
.stack > .card-title + .muted,
.stack > .card-title + .card-sub,
.stack > .card-title + p:not([class]),
.stack > .row-between:has(> .card-title) + .muted,
.stack > .row-between:has(> .card-title) + p:not([class]) {
  margin-top: calc(var(--space-1) - var(--space-4));
}

.card-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

/* Parts of one card, split by a hairline. */
.card-section + .card-section {
  margin-top: var(--space-5);
  padding-top: var(--space-5);
  border-top: 1px solid var(--line);
}

/* A card that is one big link. */
a.card-link {
  display: block;
  color: inherit;
  transition: border-color var(--dur-1) ease, box-shadow var(--dur-2) ease;
}

a.card-link:hover {
  border-color: var(--line-strong);
  box-shadow: var(--elev-1);
  text-decoration: none;
}

@media (max-width: 480px) {
  .card {
    --card-pad: var(--space-4);
  }
}

/* ---------------- section head ----------------
   sectionHead() in src/ui.ts: a heading over a group of cards, with one
   quiet link or fact on the right. */

.app-section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-1) var(--space-3);
  margin-bottom: var(--space-3);
}

.app-section-head .app-section-title {
  margin-bottom: 0;
}

.app-section-meta {
  font-size: var(--type-small);
  color: var(--text-dim);
}

/* ---------------- list rows ----------------
   <ul class="list"><li class="list-row"><span class="list-mark">icon</span>
     <div class="list-main"><p class="list-title">..</p><p class="list-sub">..</p></div>
     <div class="list-end">meta or actions</div></li></ul>
   Rows of one kind (alerts, reports, events): a mark, a title, one line under
   it, and what you can do on the right. Hairlines between, the card's chrome
   around. Inside a card the list runs edge to edge. */

.list {
  display: grid;
  margin: 0;
  padding: 0;
  list-style: none;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--elev-2);
  overflow: hidden;
}

.card > .list {
  margin-inline: calc(var(--card-pad) * -1);
  border-inline: 0;
  border-radius: 0;
}

.card > .list:last-child {
  margin-bottom: calc(var(--card-pad) * -1);
  border-bottom: 0;
}

/* Rows keep the card's own inset, so a row's mark lines up with the card's title. */
.card > .list > .list-row {
  padding-inline: var(--card-pad);
}

.list-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  min-height: 56px;
  padding: var(--space-3) var(--space-4);
}

.list-row:has(> .list-mark) {
  grid-template-columns: auto minmax(0, 1fr) auto;
}

.list-row + .list-row {
  border-top: 1px solid var(--line);
}

.list-mark {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: var(--r-md);
  color: var(--text-dim);
  background: var(--bg-tint);
}

.list-mark svg {
  width: 16px;
  height: 16px;
}

.list-mark.is-good {
  color: var(--success-fg);
  background: var(--success-bg);
}

.list-mark.is-bad {
  color: var(--warning-fg);
  background: var(--warning-bg);
}

.list-main {
  display: grid;
  gap: 2px;
  min-width: 0;
}

.list-title {
  font-size: var(--type-ui);
  font-weight: var(--weight-title);
  line-height: var(--lh-snug);
  color: var(--text);
  overflow-wrap: anywhere;
}

.list-title a {
  color: inherit;
  text-decoration: none;
}

a.list-title:hover,
.list-title a:hover {
  color: var(--accent);
  text-decoration: none;
}

.list-sub {
  font-size: var(--type-small);
  line-height: 1.45;
  color: var(--text-dim);
}

/* Where and when, after the line: the row's one bit of small print. */
.list-meta {
  font-size: var(--type-caption);
  line-height: 1.45;
  color: var(--text-faint);
}

.list-end {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2);
}

.list-end form {
  margin: 0;
}

@media (max-width: 560px) {
  .list-row,
  .list-row:has(> .list-mark) {
    grid-template-columns: minmax(0, 1fr);
  }
  .list-row:has(> .list-mark) {
    grid-template-columns: auto minmax(0, 1fr);
  }
  .list-row:has(> .list-mark) > .list-end {
    grid-column: 2;
  }
  .list-end {
    justify-content: flex-start;
  }
}

/* ---------------- the way in ----------------
   actionLink() in src/ui.ts: "Open dashboard" and the like, a secondary
   button with an arrow, so the next step reads as a step and not a link. */

.btn-go svg {
  width: 14px;
  height: 14px;
  transition: transform var(--dur-1) ease;
}

.btn-go:hover svg {
  transform: translateX(2px);
}

@media (prefers-reduced-motion: reduce) {
  .btn-go:hover svg {
    transform: none;
  }
}

/* ---------------- info tip ----------------
   <button class="info-tip" popovertarget="tip-1" title="..">(i)</button><span class="info-tip-pop" id="tip-1" popover>..</span>
   One small (i) in place of a paragraph under a card (infoTip() in src/ui.ts).
   24px target (WCAG 2.5.8) around a 15px mark. The popover sits under its
   button where anchor positioning works, and centered on screen elsewhere. */

.info-tip {
  display: inline-grid;
  place-items: center;
  width: 24px;
  height: 24px;
  margin: -4px 0;
  padding: 0;
  vertical-align: middle;
  color: var(--text-faint);
  background: none;
  border: 0;
  border-radius: var(--r-pill);
  cursor: help;
  transition: color var(--dur-1) ease;
}

.info-tip svg {
  width: 15px;
  height: 15px;
}

.info-tip:hover,
.info-tip:focus-visible {
  color: var(--text);
}

.info-tip:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.info-tip-pop {
  max-width: min(320px, calc(100vw - 32px));
  margin: auto;
  padding: var(--space-3) var(--space-4);
  font-size: var(--type-small);
  font-weight: 400;
  line-height: 1.5;
  text-align: left;
  text-transform: none;
  letter-spacing: normal;
  color: var(--text);
  background: var(--bg-raised);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  box-shadow: var(--elev-3);
}

/* Phones: a 44px target for a finger, the same 24px of room in the line. */
@media (max-width: 720px) {
  .info-tip {
    width: 44px;
    height: 44px;
    margin: -14px -10px;
  }
}

@supports (position-area: bottom) {
  .info-tip-pop {
    inset: auto;
    margin: var(--space-1) 0 0;
    position-area: bottom span-right;
    /* Near the right edge it opens to the left, then centered; near the bottom, above. Never cut by the viewport. */
    position-try-fallbacks: bottom span-left, bottom, top span-right, top span-left, top;
  }
}

/* ---------------- big numbers ----------------
   <div class="stat"><p class="stat-label">Visitors</p><p class="stat-value">1,147</p><p class="stat-note">last 7 days</p></div> */

/* A stat tile is the dashboard's number tile (public/static/app-analytics.css,
   .dw-num and .dw-stats): a mono label, a 28px number in tabular figures,
   the change beside it, and a small curve when the number has a shape.
   Tiles sit in a .stats row, split by hairlines, inside one frame.

   <div class="stats">
     <div class="stat stat-wide"><p class="stat-label">Visitors, 7 days</p>
       <div class="stat-body"><p class="stat-value">1,041 <span class="delta down">45%</span></p><svg class="spark">..</svg></div></div>
     <div class="stat"><p class="stat-label">Ad spend</p><p class="stat-value">$73.74</p></div>
   </div> */

.stat {
  display: grid;
  align-content: start;
  gap: var(--space-1);
  min-width: 0;
}

.stat-label {
  overflow-wrap: anywhere;
  font-family: var(--mono);
  font-size: var(--type-label);
  font-weight: var(--weight-medium);
  line-height: 1.4;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-faint);
}

.stat-value {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px var(--space-2);
  min-width: 0;
  font-size: var(--fs-28);
  font-weight: var(--weight-title);
  line-height: 1.1;
  letter-spacing: -0.025em;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

/* A word where a number would be ("Up", "None"): one step down, so a row of
   tiles keeps one baseline. */
.stat-word {
  font-size: var(--fs-24);
}

.stat-value .stat-of,
.stat-value .stat-meta {
  font-size: var(--type-small);
  font-weight: var(--weight-medium);
  letter-spacing: 0;
  color: var(--text-faint);
}

.stat-value .stat-of {
  color: var(--text-dim);
}

.stat-note {
  font-size: var(--type-caption);
  line-height: 1.4;
  color: var(--text-faint);
}

/* The row of tiles: one frame, hairlines between. Each tile draws its line on
   its right and bottom edge; the frame clips the outer ones, so a short last
   row never shows an empty grey cell. */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 140px), 1fr));
  min-width: 0;
  overflow: hidden;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--elev-2);
}

.stats > .stat {
  padding: var(--space-3) 14px;
  box-shadow:
    1px 0 0 var(--line),
    0 1px 0 var(--line);
}

/* A fixed count of columns, when the tiles must line up across cards. */
.stats-2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

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

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

/* The tile with a curve takes two columns: the number left, the curve right. */
.stat-wide {
  grid-column: span 2;
}

.stat-full,
.stats-2 > .stat-wide {
  grid-column: 1 / -1;
}

.stat-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: var(--space-3);
}

/* The dashboard's sparkline (.dw-spark): the line in the accent, a 10% wash under it. */
.spark-tile {
  display: block;
  width: 96px;
  height: 34px;
  overflow: visible;
  color: var(--accent);
}

.spark-tile-line {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.spark-tile-area {
  fill: currentColor;
  opacity: 0.1;
}

/* Today (or this hour) is still filling up: its stretch is dashed, as on the dashboard's charts. */
.spark-tile-tail {
  stroke-dasharray: 2 3.5;
}

/* The change against the period before, as on the dashboard (.dash-delta). */
.delta {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: var(--type-small);
  font-weight: var(--weight-title);
  letter-spacing: 0;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  color: var(--text-faint);
}

.delta.good {
  color: var(--success-fg);
}

.delta.bad {
  color: var(--danger-fg);
}

.delta svg {
  width: 8px;
  height: 8px;
}

/* Phones: two columns; the wide tile keeps the whole row. */
@media (max-width: 560px) {
  .stats,
  .stats-3,
  .stats-4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  /* A tile left alone on the last row takes the row, never half of it. */
  .stats > .stat:last-child:nth-child(odd):not(.stat-wide ~ .stat),
  .stats > .stat-wide ~ .stat:last-child:nth-child(even),
  .stat-wide {
    grid-column: 1 / -1;
  }
  .stat-value {
    font-size: var(--fs-24);
  }
  .stat-word {
    font-size: var(--fs-20);
  }
}

.num,
.tabular {
  font-variant-numeric: tabular-nums;
}

/* ---------------- chips, pills and badges ---------------- */

/* A filter chip: one choice in a row of many. Two or three choices that
   switch a view are a .segmented instead. */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: var(--ctl-h-sm);
  padding: 0 var(--space-3);
  font: inherit;
  font-size: var(--fs-13);
  font-weight: var(--weight-medium);
  color: var(--text-dim);
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--dur-1) ease, border-color var(--dur-1) ease, color var(--dur-1) ease;
}

.chip:hover {
  color: var(--text);
  border-color: var(--line-strong);
  text-decoration: none;
}

.chip[aria-pressed='true'],
.chip[aria-current='true'],
.chip[aria-current='page'] {
  color: var(--accent);
  background: var(--accent-soft);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
}

.chip .count {
  display: inline-grid;
  place-items: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  font-size: var(--fs-11);
  font-weight: var(--weight-strong);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--text-dim);
  /* 6.1:1 light, 6.9:1 dark: --bg-active would drop under 4.5. */
  background: var(--bg-tint);
  box-shadow: inset 0 0 0 1px var(--line);
  border-radius: var(--r-pill);
}

.chip[aria-pressed='true'] .count,
.chip[aria-current='page'] .count,
.chip[aria-current='true'] .count {
  /* On the raised ground the blue holds 5.9:1 light, 6.5:1 dark. */
  color: var(--accent);
  background: var(--bg-raised);
  box-shadow: none;
}

@media (max-width: 720px) {
  .chip {
    min-height: var(--ctl-h-lg);
    padding-inline: 14px;
  }
}

/* A status: small, soft, the same shape everywhere.
   Tones: (none) neutral, -ok, -warn, -danger, -accent, -info. */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-height: 22px;
  padding: 0 var(--space-2);
  font-family: var(--sans);
  font-size: var(--type-caption);
  font-weight: var(--weight-medium);
  line-height: 1.2;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text-dim);
  background: var(--bg-tint);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  white-space: nowrap;
  vertical-align: middle;
}

.live-now {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 22px;
  padding: 0 var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  font-size: var(--type-caption);
  font-weight: var(--weight-medium);
  color: var(--text-dim);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.live-now:is(a) {
  text-decoration: none;
  transition: border-color var(--dur-1) ease, background-color var(--dur-1) ease;
}
.live-now:is(a):hover {
  border-color: var(--line-strong);
  background: var(--bg-tint);
}
.live-now[hidden] {
  display: none;
}
.live-dot {
  position: relative;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--text-faint);
}
.live-now.on {
  color: var(--text);
}
.live-now.on .live-dot {
  background: var(--success-fg);
}
.live-now.on .live-dot::after {
  content: '';
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  background: var(--success-fg);
  animation: live-ping 2s cubic-bezier(0.2, 0.6, 0.4, 1) infinite;
}
@keyframes live-ping {
  from {
    transform: scale(0.4);
    opacity: 0.55;
  }
  to {
    transform: scale(1.6);
    opacity: 0;
  }
}
@media (prefers-reduced-motion: reduce) {
  .live-now.on .live-dot::after {
    animation: none;
    /* At rest the ring is a soft halo, not a second solid dot. */
    opacity: 0.25;
  }
}
.pill-ok {
  color: var(--success-fg);
  border-color: var(--success-line);
  background: var(--success-bg);
}

.pill-warn {
  color: var(--warning-fg);
  border-color: var(--warning-line);
  background: var(--warning-bg);
}

.pill-danger {
  color: var(--danger-text);
  border-color: var(--danger-line);
  background: var(--danger-bg);
}

.pill-accent,
.pill-info {
  color: var(--accent);
  border-color: var(--info-line);
  background: var(--accent-soft);
}

/* A live dot before a pill's words. */
.pill-dot::before {
  content: '';
  flex: 0 0 auto;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

/* ---------------- checklist ----------------
   Steps with a progress bar: the setup checklist on /app (src/activation.ts).
   <section class="card checklist"><div class="checklist-head">..</div><div class="checklist-bar"><span style="width: 40%"></span></div>
     <ol class="checklist-steps"><li class="checklist-step is-done|is-next"><span class="checklist-mark"></span><div><p class="checklist-label">..</p><p class="checklist-why">..</p></div>(button)</li></ol>
   </section> */

.checklist {
  display: grid;
  gap: var(--space-3);
}

.checklist-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
}

.checklist-head .muted {
  margin: 2px 0 0;
}

.checklist-bar {
  height: 6px;
  overflow: hidden;
  background: var(--bg-tint);
  border-radius: var(--r-pill);
}

.checklist-bar span {
  display: block;
  height: 100%;
  background: var(--success);
  border-radius: inherit;
  transition: width var(--dur-4) var(--ease-out);
}

.checklist-steps {
  display: grid;
  gap: 2px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.checklist-step {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--ctl-h-lg);
  padding: 6px 0;
}

.checklist-step + .checklist-step {
  border-top: 1px solid var(--line);
}

.checklist-mark {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  background: var(--bg-raised);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
}

.checklist-step.is-done .checklist-mark {
  color: var(--success-fg);
  background: var(--success-bg);
  border-color: var(--success-line);
}

.checklist-step.is-next .checklist-mark {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 4px var(--bg-raised), inset 0 0 0 11px var(--accent);
}

.checklist-step.is-done .checklist-label {
  color: var(--text-faint);
}

.checklist-step.is-next .checklist-label {
  font-weight: var(--weight-strong);
}

.checklist-why {
  margin: 2px 0 0;
  font-size: var(--type-small);
  color: var(--text-dim);
}

/* On a phone the next step's button goes under its words. */
@media (max-width: 520px) {
  .checklist-step.is-next {
    grid-template-columns: 22px minmax(0, 1fr);
  }
  .checklist-step.is-next .btn {
    grid-column: 2;
    justify-self: start;
  }
}

/* ---------------- notices ----------------
   notice() in src/ui.ts. A line that stays on the page. Things that just
   happened (saved, failed to save) are toasts instead. */

.notice {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3) 14px;
  font-size: var(--type-ui);
  line-height: 1.5;
  color: var(--text);
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.notice > .notice-icon {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  margin-top: 2px;
}

.notice > .notice-icon svg {
  width: 16px;
  height: 16px;
}

.notice-info > .notice-icon {
  color: var(--accent);
}

.notice-ok {
  color: var(--success-fg);
  background: var(--success-bg);
  border-color: var(--success-line);
}

.notice-warn {
  color: var(--warning-fg);
  background: var(--warning-bg);
  border-color: var(--warning-line);
}

.notice-error {
  color: var(--danger-text);
  background: var(--danger-bg);
  border-color: var(--danger-line);
}

.notice .btn {
  margin-left: auto;
}

/* ---------------- toasts ----------------
   window.sporetag.toast('Saved') in public/static/ui.js. One region, bottom
   right on a desk and bottom center on a phone. Polite for saves, assertive
   for errors. */

.toast-region {
  position: fixed;
  right: var(--space-6);
  bottom: var(--space-6);
  z-index: 300;
  display: grid;
  justify-items: end;
  gap: var(--space-2);
  width: min(380px, calc(100vw - 32px));
  pointer-events: none;
}

.toast {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  max-width: 100%;
  min-height: var(--ctl-h-lg);
  padding: var(--space-2) var(--space-2) var(--space-2) 14px;
  font-size: var(--type-ui);
  line-height: 1.4;
  color: var(--bg);
  background: var(--text);
  border-radius: var(--r-lg);
  box-shadow: var(--elev-3);
  pointer-events: auto;
  animation: ui-toast-in var(--dur-3) var(--ease-out);
}

.toast[data-leaving] {
  opacity: 0;
  transform: translateY(6px);
  transition: opacity var(--dur-2) ease, transform var(--dur-2) ease;
}

.toast-icon {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  color: #ffffff;
  background: var(--success);
}

.toast-error .toast-icon {
  background: var(--danger);
}

.toast-info .toast-icon {
  color: var(--accent-ink);
  background: var(--accent);
}

.toast-icon svg {
  width: 12px;
  height: 12px;
}

.toast-text {
  flex: 1 1 auto;
  min-width: 0;
}

/* Undo, inside the dark toast (a form or a button). */
.toast-action {
  flex: 0 0 auto;
  margin: 0;
}

.toast-action .btn {
  color: var(--bg);
  background: transparent;
  border-color: color-mix(in srgb, var(--bg) 40%, transparent);
}

.toast-action .btn:hover {
  background: color-mix(in srgb, var(--bg) 12%, transparent);
}

.toast .icon-button {
  width: 32px;
  height: 32px;
  color: color-mix(in srgb, var(--bg) 70%, transparent);
}

.toast .icon-button:hover {
  color: var(--bg);
  background: color-mix(in srgb, var(--bg) 14%, transparent);
}

@keyframes ui-toast-in {
  from {
    opacity: 0;
    transform: translateY(8px) scale(0.98);
  }
}

@media (max-width: 720px) {
  .toast-region {
    right: 50%;
    bottom: calc(var(--space-4) + env(safe-area-inset-bottom));
    justify-items: center;
    transform: translateX(50%);
  }
}

/* ---------------- tables ----------------
   Numbers right-aligned in tabular figures (.num). The head sticks when the
   wrap scrolls (.table-wrap-tall). Rows light up under the pointer. */

.table-wrap {
  /* Positioned, so a visually-hidden label in a wide row scrolls with the table
     instead of widening the page (admin links and billing at 390px). */
  position: relative;
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-panel);
}

/* In the app a table is a dashboard card too. */
:where(body.app) .table-wrap {
  background: var(--bg-raised);
  border-radius: var(--r-lg);
  box-shadow: var(--elev-2);
}

:where(body.app) .table th {
  background: var(--bg-raised);
}

.table-wrap-tall {
  max-height: min(70vh, 720px);
  max-height: min(70dvh, 720px);
  overflow-y: auto;
}

.table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--type-ui);
}

.table th,
.table td {
  padding: 10px 14px;
  text-align: left;
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
}

.table th {
  position: sticky;
  top: 0;
  z-index: 1;
  height: 40px;
  padding-block: 0;
  font-family: var(--mono);
  font-size: var(--type-label);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-faint);
  white-space: nowrap;
  background: var(--bg-panel);
}

/* The head styles above are for column heads. A row's name (tbody th) is a
   cell like its neighbors: the same padding, so it shares their line, and it
   never sticks to the top of a scrolling table. */
.table tbody th,
.table tfoot th {
  position: static;
  height: auto;
  padding-block: 10px;
}

/* The frame closes the table: the last row's name loses its rule too. */
.table tbody tr:last-child > :is(td, th) {
  border-bottom: none;
}

.table tbody tr {
  transition: background-color var(--dur-1) ease;
}

/* A table wider than its card (a phone, six models side by side): it scrolls
   inside the card, its first column stays put so every row keeps its name,
   and the right edge fades while there is more to see. ui.js sets .is-wide
   and .has-more from the real widths. */
.table-wrap.is-wide :is(th, td):first-child {
  position: sticky;
  /* A wrap with side padding: the column sticks at the wrap's edge, not inside
     the padding, so nothing scrolls by in a gap beside it (--wrap-pad, ui.js). */
  left: calc(-1 * var(--wrap-pad, 0px));
  z-index: 2;
  background: var(--bg-raised);
  box-shadow: inset -1px 0 0 var(--line);
}
.table-wrap.is-wide th:first-child {
  z-index: 3;
}
.table-wrap.is-wide.has-more {
  -webkit-mask-image: linear-gradient(to left, transparent 0, #000 28px);
  mask-image: linear-gradient(to left, transparent 0, #000 28px);
}

.table tbody tr:hover td {
  background: color-mix(in srgb, var(--bg-hover) 60%, transparent);
}

.table .num,
.table th.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.table-empty td {
  padding: var(--space-8) var(--space-4);
  text-align: center;
  color: var(--text-dim);
}

/* ---------------- code ---------------- */

.code {
  position: relative;
  margin: 0;
  padding: 14px var(--space-4);
  overflow-x: auto;
  font-family: var(--mono);
  font-size: var(--fs-13);
  line-height: var(--lh-body);
  color: var(--text);
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  white-space: pre;
}

.code-block {
  display: grid;
  gap: var(--space-2);
}

.code-block .row-between {
  flex-wrap: nowrap;
  font-size: var(--fs-13);
  color: var(--text-dim);
}

.code-block .row-between > .btn {
  flex: 0 0 auto;
}

/* Snippets in the app wrap instead of scrolling: one line of HTML reads whole,
   with no scroll bars at any width. Line breaks in longer code are kept. */
.code-block:not(.doc-code) .code {
  overflow: hidden;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

:not(pre) > code {
  padding: 1px 5px;
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: var(--r-xs);
}

/* A key on the keyboard. */
.kbd {
  display: inline-grid;
  place-items: center;
  min-width: 20px;
  height: 20px;
  padding: 0 5px;
  font-family: var(--sans);
  font-size: var(--fs-11);
  font-weight: var(--weight-medium);
  line-height: 1;
  color: var(--text-dim);
  background: var(--bg-raised);
  border: 1px solid var(--line-strong);
  border-bottom-width: 2px;
  border-radius: var(--r-xs);
}

/* ---------------- empty state ----------------
   emptyState() in src/ui.ts: one icon, one line, one action. */

.empty {
  display: grid;
  justify-items: center;
  gap: var(--space-2);
  padding: var(--space-10) var(--space-6);
  text-align: center;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  background-color: var(--bg-panel);
  background-image: radial-gradient(var(--site-dot) 1px, transparent 1px);
  background-size: 20px 20px;
}

/* Inside a card: no second frame. */
.card .empty,
.empty-plain {
  padding: var(--space-8) var(--space-4);
  border: 0;
  background: none;
}

.empty-mark {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin-bottom: var(--space-1);
  border-radius: var(--r-lg);
  color: var(--accent);
  background: var(--accent-soft);
}

.empty-mark svg {
  width: 20px;
  height: 20px;
}

.empty-title {
  font-size: var(--type-heading);
  font-weight: var(--weight-title);
  line-height: var(--lh-snug);
  color: var(--text);
}

.empty p:not(.empty-title) {
  max-width: 40ch;
  font-size: var(--type-ui);
  color: var(--text-dim);
}

.empty .btn {
  margin-top: var(--space-2);
}

/* ---------------- loading skeletons ----------------
   Grey shapes where slow numbers and lists will land, so the page does not
   jump. A soft sweep while waiting; still under reduced motion. */

.skeleton {
  display: block;
  min-height: 12px;
  color: transparent !important;
  background: linear-gradient(90deg, var(--bg-active) 0%, var(--bg-hover) 50%, var(--bg-active) 100%) 0 0 / 200% 100%;
  border-radius: var(--r-sm);
  animation: ui-shimmer 1.4s ease-in-out infinite;
  user-select: none;
}

.skeleton-line {
  height: 12px;
  margin-block: 6px;
}

.skeleton-num {
  width: 5ch;
  height: 28px;
}

.skeleton-row {
  height: 40px;
  margin-bottom: var(--space-2);
}

@keyframes ui-shimmer {
  to {
    background-position: -200% 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .skeleton {
    animation: none;
  }
}

/* With script off nothing will land, so no shapes wait for it: the page's
   <noscript> notice says what is needed instead. */
@media (scripting: none) {
  .skeleton,
  .dw-sk,
  .live-body,
  .live-cards,
  .live-sub {
    display: none !important;
  }
}

/* ---------------- menus ----------------
   A dropdown is a <details data-menu> (site.js closes it on a click outside
   and on Escape, and moves with the arrow keys): its <summary> is the button,
   then .menu-list holds .menu-row items. */

.dropdown {
  position: relative;
}

.dropdown > summary {
  list-style: none;
}

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

.dropdown[open] > summary.btn {
  color: var(--text);
  background: var(--bg-hover);
}

/* A small mono heading over a group of rows. */
.menu-heading {
  padding: var(--space-2) 10px var(--space-1);
  font-family: var(--mono);
  font-size: var(--type-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-faint);
}

.menu-list {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 60;
  min-width: 220px;
  max-width: calc(100vw - 24px);
  padding: var(--space-1);
  background: var(--bg-raised);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  box-shadow: var(--elev-3);
  transform-origin: top right;
  animation: ui-pop var(--dur-2) var(--ease-out);
}

.menu-list-start {
  right: auto;
  left: 0;
  transform-origin: top left;
}

@keyframes ui-pop {
  from {
    opacity: 0;
    transform: translateY(-4px) scale(0.98);
  }
}

.sheet-row,
.menu-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: var(--ctl-h-md);
  padding: 6px 10px;
  text-align: left;
  font: inherit;
  font-size: var(--type-ui);
  line-height: 1.25;
  color: var(--text);
  background: transparent;
  border: none;
  border-radius: var(--r-md);
  cursor: pointer;
  text-decoration: none;
}

.sheet-row {
  min-height: var(--ctl-h-lg);
  font-size: var(--fs-15);
}

.menu-row svg {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  color: var(--text-faint);
}

.sheet-row:hover,
.menu-row:hover,
.menu-row:focus-visible {
  background: var(--bg-hover);
  text-decoration: none;
}

.menu-row:hover svg {
  color: var(--accent);
}

.menu-row:focus-visible {
  outline: 2px solid transparent;
  box-shadow: inset 0 0 0 2px var(--accent);
}

.menu-row-danger,
.menu-row-danger svg {
  color: var(--danger-fg);
}

.sheet-row[aria-current='page'] {
  color: var(--accent);
  font-weight: var(--weight-strong);
}

.menu-sep {
  height: 1px;
  margin: var(--space-1) var(--space-1);
  background: var(--line);
}

.menu-list form {
  margin: 0;
}

@media (max-width: 720px) {
  .menu-row {
    min-height: var(--ctl-h-lg);
    font-size: var(--fs-15);
  }
}

/* ---------------- stars ----------------
   favStar() in src/favorites.ts: an outline star in the faint ink, filled
   with --warning once starred (3.4:1 on white, 7:1 on the dark card, so the
   state reads without color too: filled or not). 32px on a desk, 44px on
   a phone. */

.fav {
  display: inline-flex;
  flex: none;
  margin: 0;
}

.fav-btn {
  display: inline-grid;
  place-items: center;
  width: var(--ctl-h-sm);
  height: var(--ctl-h-sm);
  padding: 0;
  color: var(--text-faint);
  background: transparent;
  border: 0;
  border-radius: var(--r-md);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition:
    color var(--dur-1) var(--ease-out),
    background-color var(--dur-1) var(--ease-out);
}

.fav-btn svg {
  width: 18px;
  height: 18px;
  transition: transform var(--dur-2) var(--ease-out);
}

@media (hover: hover) {
  .fav-btn:hover {
    color: var(--text);
    background: var(--bg-hover);
  }
}

.fav-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.fav-btn[aria-pressed='true'] {
  color: var(--warning);
}

.fav-btn[aria-pressed='true'] svg {
  fill: currentColor;
}

.fav-btn[aria-pressed='true']:active svg {
  transform: scale(0.88);
}

@media (max-width: 720px) {
  .fav-btn {
    width: var(--ctl-h-lg);
    height: var(--ctl-h-lg);
  }
}

/* On a site card, settings and the star take the top right corner, beside the name. */
.site-card-corner {
  display: flex;
  align-items: center;
  align-self: flex-start;
  margin: -6px -6px 0 auto;
}

/* ---------------- site switcher ----------------
   siteSwitch() in src/favorites.ts, one look everywhere: a chevron right
   after the page's title, opening a menu of sites: a search box from 7
   sites, Starred, Sites, each row with its star, then Add site. */

.site-switch-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--ctl-h-sm);
  min-height: var(--ctl-h-sm);
  color: var(--text-dim);
  border-radius: var(--r-md);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.site-switch-btn svg {
  flex: none;
  width: 18px;
  height: 18px;
  transition: transform var(--dur-2) var(--ease-out);
}

.site-switch[open] > .site-switch-btn svg {
  transform: rotate(180deg);
}

.site-switch-btn:hover,
.site-switch[open] > .site-switch-btn {
  color: var(--text);
  background: var(--bg-hover);
}

.site-switch-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.site-switch-list {
  display: flex;
  flex-direction: column;
  width: 320px;
  padding: 0;
  overflow: hidden;
}

.site-switch-search {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0 var(--space-3);
  border-bottom: 1px solid var(--line);
}

.site-switch-search svg {
  flex: none;
  width: 16px;
  height: 16px;
  color: var(--text-faint);
}

.site-switch-q {
  flex: 1;
  min-width: 0;
  height: var(--ctl-h-lg);
  padding: 0;
  font: inherit;
  /* 16px keeps phones from zooming into the box. */
  font-size: var(--fs-16);
  color: var(--text);
  background: transparent;
  border: 0;
  outline: 2px solid transparent;
  -webkit-appearance: none;
  appearance: none;
}

.site-switch-q::placeholder {
  color: var(--text-faint);
}

.site-switch-q::-webkit-search-cancel-button {
  display: none;
}

.site-switch-search:focus-within {
  box-shadow: inset 0 -2px 0 var(--accent);
}

.site-switch-scroll {
  max-height: min(420px, 60vh);
  max-height: min(420px, 60dvh);
  padding: var(--space-1);
  overflow-y: auto;
  overscroll-behavior: contain;
}

.site-switch-group[hidden] {
  display: none;
}

.site-switch-group + .site-switch-group {
  margin-top: var(--space-1);
  padding-top: var(--space-1);
  border-top: 1px solid var(--line);
}

.site-switch-rows {
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-switch-row {
  display: flex;
  align-items: center;
  gap: 2px;
}

.site-switch-row[hidden] {
  display: none;
}

.site-switch-row .menu-row {
  flex: 1;
  min-width: 0;
}

.site-switch-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.site-switch-domain {
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--type-caption);
  color: var(--text-faint);
}

.site-switch-row .menu-row[aria-current='page'] {
  font-weight: var(--weight-strong);
}

.site-switch-row .menu-row[aria-current='page'] svg {
  margin-left: auto;
  color: var(--accent);
}

.site-switch-none {
  margin: 0;
  padding: var(--space-3) 10px;
  font-size: var(--type-small);
  color: var(--text-faint);
}

.site-switch-none[hidden] {
  display: none;
}

/* The title row: the name with the site switcher right after it (src/favorites.ts switchTitle). */
.app-page-title {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  min-width: 0;
}

.app-page-title .app-page-name {
  min-width: 0;
  overflow-wrap: anywhere;
}

@media (max-width: 720px) {
  .site-switch-btn {
    width: var(--ctl-h-lg);
    min-height: var(--ctl-h-lg);
  }
  /* The menu spans the page head, right under the button (top: auto keeps
     it where it falls), so it never runs off a narrow screen. */
  .site-switch {
    position: static;
  }
  .app-page-head:has(.site-switch) {
    position: relative;
  }
  .site-switch-list {
    top: auto;
    left: 0;
    right: 0;
    width: auto;
    max-width: none;
    margin-top: 6px;
  }
}

/* ---------------- dialogs and sheets ----------------
   A native <dialog class="dialog"> opened with showModal(): the browser
   traps focus and closes it on Escape; ui.js puts focus back where it was.
   On a phone it rises from the bottom as a sheet. */

.dialog {
  width: min(520px, calc(100vw - 32px));
  max-height: min(86vh, 760px);
  max-height: min(86dvh, 760px);
  padding: 0;
  color: var(--text);
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  box-shadow: var(--elev-4);
  overflow: auto;
  overscroll-behavior: contain;
}

/* A yes-or-no question: narrow, the answer bottom right. */
.dialog-confirm {
  width: min(420px, calc(100vw - 32px));
}

.dialog-confirm .dialog-body p {
  color: var(--text-dim);
}

.dialog[open] {
  animation: ui-dialog-in var(--dur-3) var(--ease-out);
}

/* Safari before 17.4 gives ::backdrop none of the page's custom properties, so
   var(--scrim) alone left the page behind a dialog undimmed on older iPhones.
   The fallback is a dim that reads in light and dark. */
.dialog::backdrop {
  background: var(--scrim, rgba(20, 17, 13, 0.5));
  animation: ui-fade var(--dur-3, 240ms) ease;
}

.dialog-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-5) var(--space-5) 0 var(--space-6);
}

.dialog-title {
  font-size: var(--type-title);
  font-weight: var(--weight-title);
  line-height: var(--lh-snug);
  letter-spacing: var(--track-title);
}

.dialog-head .icon-button {
  margin: -6px -6px 0 0;
}

.dialog-body {
  display: grid;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-6);
}

.dialog-foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-6) var(--space-5);
}

@keyframes ui-dialog-in {
  from {
    opacity: 0;
    transform: translateY(8px) scale(0.98);
  }
}

@keyframes ui-fade {
  from {
    opacity: 0;
  }
}

@media (max-width: 720px) {
  .dialog {
    width: 100%;
    max-width: 100%;
    /* Above the on-screen keyboard when one is open (--kb and --vvh, ui.js). */
    max-height: min(86dvh, 760px, calc(var(--vvh, 100dvh) - var(--space-4)));
    margin: auto 0 var(--kb, 0px);
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    padding-bottom: env(safe-area-inset-bottom);
  }
  .dialog[open] {
    animation-name: ui-sheet-in;
  }
  /* The grab handle: says the sheet can be pulled down to close (ui.js swipeToClose). */
  .dialog::before {
    content: '';
    position: absolute;
    top: 6px;
    left: 50%;
    width: 36px;
    height: 5px;
    margin-left: -18px;
    border-radius: var(--r-pill);
    background: var(--line-strong);
    pointer-events: none;
  }
  .dialog.is-dragging {
    transition: none;
    animation: none;
  }
  .dialog-foot .btn {
    flex: 1 1 0;
  }
}

/* While a dialog or sheet is open the page under it stays put: a finger on
   the dim area no longer scrolls the page behind (iOS Safari did). */
:root:has(dialog.dialog[open]:modal) {
  overflow: hidden;
}

@keyframes ui-sheet-in {
  from {
    transform: translateY(24px);
    opacity: 0;
  }
}

/* ---------------- command palette ----------------
   Cmd+K or Ctrl+K anywhere in the app (public/static/ui.js). */

.cmdk {
  width: min(620px, calc(100vw - 32px));
  max-height: min(72vh, 620px);
  max-height: min(72dvh, 620px);
  margin: 12vh auto auto;
  margin: 12dvh auto auto;
  padding: 0;
  overflow: hidden;
  color: var(--text);
  background: var(--bg-raised);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-xl);
  box-shadow: var(--elev-4);
}

.cmdk[open] {
  display: flex;
  flex-direction: column;
  animation: ui-dialog-in var(--dur-2) var(--ease-out);
}

.cmdk::backdrop {
  background: var(--scrim, rgba(20, 17, 13, 0.5));
}

.cmdk-search {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 0 var(--space-4);
  border-bottom: 1px solid var(--line);
}

.cmdk-search svg {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  color: var(--text-faint);
}

.cmdk-input {
  flex: 1 1 auto;
  min-width: 0;
  height: 52px;
  padding: 0;
  font: inherit;
  font-size: var(--fs-16);
  color: var(--text);
  background: transparent;
  border: 0;
  outline: none;
}

.cmdk-input::placeholder {
  color: var(--text-faint);
}

.cmdk-list {
  flex: 1 1 auto;
  min-height: 0;
  margin: 0;
  padding: var(--space-2);
  overflow-y: auto;
  overscroll-behavior: contain;
  list-style: none;
}

.cmdk-group {
  padding: var(--space-3) 10px var(--space-1);
  font-family: var(--mono);
  font-size: var(--type-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-faint);
}

.cmdk-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 40px;
  padding: 0 10px;
  font-size: var(--type-ui);
  color: var(--text);
  border-radius: var(--r-md);
  cursor: pointer;
}

.cmdk-item svg {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  color: var(--text-faint);
}

.cmdk-item[aria-selected='true'] {
  background: var(--bg-active);
}

.cmdk-item[aria-selected='true'] svg {
  color: var(--accent);
}

.cmdk-label {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cmdk-hint {
  flex: 0 0 auto;
  font-size: var(--type-caption);
  color: var(--text-faint);
}

.cmdk-keys {
  display: inline-flex;
  gap: 3px;
}

.cmdk-none {
  padding: var(--space-8) var(--space-4);
  text-align: center;
  font-size: var(--type-ui);
  color: var(--text-dim);
}

.cmdk-foot {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  padding: 10px var(--space-4);
  font-size: var(--type-caption);
  color: var(--text-faint);
  border-top: 1px solid var(--line);
  background: var(--bg-panel);
}

.cmdk-foot span {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

/* No keyboard on a touch screen: no key hints. */
@media (hover: none) {
  .cmdk-foot,
  .cmdk-item .cmdk-keys {
    display: none;
  }
}

/* The search hint in the app header: opens the palette. */
.cmdk-open {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 200px;
  height: var(--ctl-h-sm);
  padding: 0 6px 0 10px;
  font: inherit;
  font-size: var(--fs-13);
  color: var(--text-faint);
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  cursor: pointer;
  transition: border-color var(--dur-1) ease, color var(--dur-1) ease;
}

.cmdk-open:hover {
  color: var(--text-dim);
  border-color: var(--line-strong);
}

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

.cmdk-open .cmdk-keys {
  margin-left: auto;
}

@media (max-width: 860px) {
  .cmdk-open {
    min-width: 0;
    width: var(--ctl-h-lg);
    height: var(--ctl-h-lg);
    padding: 0;
    justify-content: center;
    background: transparent;
    border-color: transparent;
  }
  .cmdk-open .cmdk-open-text,
  .cmdk-open .cmdk-keys {
    display: none;
  }
  .cmdk {
    margin-top: var(--space-4);
    max-height: calc(100dvh - 32px);
  }
}

/* ---------------- phone tap targets ----------------
   Links that act like buttons get a finger's height on a phone. Links inside
   running text keep their line. */
@media (max-width: 720px) {
  .site-card-foot a,
  .site-card-foot .btn {
    display: inline-flex;
    align-items: center;
    min-height: var(--ctl-h-lg);
  }
  .scs-action,
  .site-card-name,
  .link-short,
  .link-head-short > a,
  .crumbs a,
  .code-block .row-between a {
    display: inline-flex;
    align-items: center;
    min-height: var(--ctl-h-sm);
  }
}

/* ---------------- Windows High Contrast ----------------
   Forced colors drop backgrounds and box shadows. Focus, switches and the
   chosen tab, segment or chip show that way here, so each gets a system-color
   line instead. */
@media (forced-colors: active) {
  :focus-visible,
  .field-input:focus,
  .as-compose:focus-within {
    outline: 2px solid Highlight;
    outline-offset: 2px;
  }
  .switch input,
  .cap-switch-track {
    forced-color-adjust: none;
    background: Canvas;
    border: 1px solid ButtonText;
  }
  .switch input::before,
  .cap-switch-track::after {
    top: 1px;
    left: 1px;
    background: ButtonText;
    box-shadow: none;
  }
  .switch input:checked,
  .cap-switch[aria-checked='true'] .cap-switch-track {
    background: Highlight;
    border-color: Highlight;
  }
  .switch input:checked::before,
  .cap-switch[aria-checked='true'] .cap-switch-track::after {
    background: HighlightText;
  }
  /* A transparent border turns to text color here, so only the chosen tab keeps one. */
  .tab {
    border-bottom-color: Canvas;
  }
  .tab[aria-current='page'],
  .tab[aria-selected='true'] {
    border-bottom-color: Highlight;
  }
  .segment[aria-selected='true'],
  .segment[aria-current='page'],
  .segment[aria-checked='true'],
  .segment[aria-pressed='true'],
  input:checked + .segment,
  .segment:has(input:checked),
  .chip[aria-pressed='true'],
  .chip[aria-current='true'],
  .chip[aria-current='page'],
  .cmdk-item[aria-selected='true'],
  .menu-row[aria-current='page'],
  .app-nav-link[aria-current='page'],
  .sheet-row[aria-current='page'] {
    border: 1px solid Highlight;
    outline: 1px solid Highlight;
  }
  .btn,
  .icon-button {
    border: 1px solid ButtonText;
  }
}

/* Phones: a short row of filter chips wraps in balanced lines, never a full
   line and one chip alone. Balancing works on inline content. A row marked
   .chips-scroll keeps one line and scrolls sideways instead, its ends fading
   so a cut chip reads as "more this way"; in a card it runs edge to edge. */
@media (max-width: 720px) {
  nav.chips:not(.chips-scroll) {
    display: block;
    text-wrap: balance;
  }
  nav.chips:not(.chips-scroll) > * {
    display: inline-flex;
    margin: 0 4px 6px 0;
    vertical-align: middle;
  }
  .chips-scroll {
    --chips-in: 0px;
    flex-wrap: nowrap;
    margin-inline: calc(-1 * var(--chips-in));
    padding-inline: var(--chips-in) var(--space-6);
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-mask-image: linear-gradient(to right, transparent, #000 var(--chips-in), #000 calc(100% - var(--space-6)), transparent);
    mask-image: linear-gradient(to right, transparent, #000 var(--chips-in), #000 calc(100% - var(--space-6)), transparent);
  }
  .card .chips-scroll {
    --chips-in: var(--card-pad, var(--space-4));
  }
  .chips-scroll::-webkit-scrollbar {
    display: none;
  }
  .chips-scroll > * {
    flex: 0 0 auto;
  }
}

/* Tracking health as a score ring (src/tracking/health.ts healthRing): the arc
   fills to the score from the top, its color says the status, the number sits
   inside. Small in badges and the overview, large on the health page. */
.hl-ring {
  position: relative;
  display: inline-grid;
  place-items: center;
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  vertical-align: middle;
}
.hl-ring svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
}
.hl-ring circle {
  fill: none;
  stroke-width: 3.5;
}
.hl-ring-track {
  stroke: var(--line);
}
.hl-ring-arc {
  stroke: var(--text-faint);
  stroke-linecap: round;
  transition: stroke-dasharray var(--dur-2) var(--ease-out);
}
.hl-ring-good .hl-ring-arc {
  stroke: var(--success-fg);
}
.hl-ring-warn .hl-ring-arc {
  stroke: var(--warning-fg);
}
.hl-ring-bad .hl-ring-arc {
  stroke: var(--danger-text);
}
.hl-ring-num {
  position: relative;
  font-size: 8.5px;
  font-weight: var(--weight-strong);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  color: var(--text);
}
.hl-ring-lg {
  width: 88px;
  height: 88px;
}
.hl-ring-lg circle {
  stroke-width: 3;
}
.hl-ring-lg .hl-ring-num {
  font-size: 28px;
  font-weight: var(--weight-title);
}
.hl-badge-ring {
  gap: 7px;
  padding: 3px 11px 3px 4px;
}
/* Inside a pill the ring sits inset, with the same space top, bottom and left. */
.hl-badge-ring .hl-ring {
  width: 22px;
  height: 22px;
}
.hl-badge-ring .hl-ring circle {
  stroke-width: 3;
}
.hl-badge-ring .hl-ring-num {
  font-size: 8px;
  letter-spacing: -0.04em;
}
@media (prefers-reduced-motion: reduce) {
  .hl-ring-arc {
    transition: none;
  }
}

/* A pill that is a link shows it by its fill, not an underline. */
a.pill {
  transition: border-color var(--dur-1) ease, background-color var(--dur-1) ease;
}
a.pill:hover {
  border-color: var(--line-strong);
  background: var(--bg-tint);
}

/* ---- shared with the app ----------------------------------------------------------------
   Plan cards (pricing, and Billing in the app) and the arrow link. They live here, not in
   site-marketing.css, because app pages do not load the marketing stylesheets. */

/* A link with an arrow that moves a little on hover. */
.text-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  font-weight: 600;
}

.text-link svg {
  width: 16px;
  height: 16px;
  transition: transform 0.15s ease;
}

.text-link:hover {
  text-decoration: none;
}

.text-link:hover svg {
  transform: translateX(3px);
}

/* Plans with a price: four across on wide screens, two by two below 1100px, one column on phones. Custom sits under them (.plan-wide). */
.plan-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
  align-items: stretch;
}

.plan-card {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 22px;
  color: inherit;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  transition: transform 0.16s ease, border-color 0.16s ease, box-shadow 0.16s ease;
}

.plan-card:hover {
  border-color: var(--line-strong);
  text-decoration: none;
}

.plan-card.highlight {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent-soft);
}

a.plan-card-link:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-menu);
}

.plan-name {
  display: block;
  font-size: 17px;
  font-weight: 700;
}

.plan-tagline {
  display: block;
  margin-top: 5px;
  color: var(--text-dim);
  font-size: 13.5px;
}

.plan-price {
  display: flex;
  align-items: baseline;
  gap: 6px;
  margin-top: 16px;
}

.plan-amount {
  font-size: 34px;
  font-weight: 700;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

.plan-period,
.plan-billing {
  color: var(--text-dim);
  font-size: 13.5px;
}

.plan-billing {
  margin-top: 2px;
  color: var(--text-faint);
}

.plan-features {
  flex: 1 1 auto;
  margin: 18px 0 22px;
  padding: 0;
  list-style: none;
  font-size: 14px;
  color: var(--text-dim);
}

.plan-features li {
  position: relative;
  padding-left: 22px;
  margin-bottom: 8px;
}

.plan-features li::before {
  content: '';
  position: absolute;
  left: 3px;
  top: 0.58em;
  width: 8px;
  height: 4px;
  border-left: 2px solid var(--chip-ok-fg);
  border-bottom: 2px solid var(--chip-ok-fg);
  transform: rotate(-45deg);
}

.plan-card .btn {
  width: 100%;
}

.plan-teaser .plan-features {
  margin-bottom: 0;
}

.plans-notice {
  justify-content: center;
  max-width: 640px;
  margin: 22px auto 0;
  font-size: 13.5px;
}

@media (max-width: 1099px) {
  .plan-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    max-width: 760px;
    margin-inline: auto;
  }
}

@media (max-width: 640px) {
  .plan-grid {
    grid-template-columns: minmax(0, 1fr);
    max-width: 480px;
  }
}

.plan-flag {
  position: absolute;
  top: -11px;
  left: 20px;
  margin: 0;
  padding: 2px 10px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent-ink);
  background: var(--accent);
  border-radius: 999px;
}

.plan-card:not(.highlight) .plan-flag {
  display: none;
}

/* A plan priced per deal (Custom): one wide card under the grid. Head,
   features and the "Talk to us" side by side; stacked below 900px. */
.plan-wide {
  display: grid;
  grid-template-columns: minmax(200px, 1fr) minmax(0, 2fr) minmax(200px, 1fr);
  gap: 16px 32px;
  align-items: center;
  margin-top: 16px;
}

.plan-wide .plan-wide-head {
  display: block;
  min-width: 0;
}

.marketing .plan-wide .plan-tagline {
  min-height: 0;
}

.plan-wide .plan-price {
  margin-top: 0;
}

/* Two flowing columns, so a long line never leaves a gap in the other one. */
.plan-wide .plan-wide-features {
  columns: 2;
  column-gap: 24px;
  margin: 0;
}

.plan-wide .plan-wide-features li {
  break-inside: avoid;
}

.plan-wide .plan-wide-action {
  display: flex;
  flex-direction: column;
  align-items: stretch;
}

.plan-wide .plan-wide-action .btn {
  margin-top: 14px;
}

.plan-wide-teaser .plan-wide-action {
  align-items: flex-end;
  text-align: right;
}

.plan-wide-teaser .plan-wide-action .text-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--accent);
  font-weight: 600;
}

.plan-teaser + .plan-wide {
  margin-top: 16px;
}

@media (max-width: 1099px) {
  .plan-wide {
    max-width: 760px;
    margin-inline: auto;
  }
}

@media (max-width: 899px) {
  .plan-wide {
    grid-template-columns: minmax(0, 1fr);
    align-items: stretch;
  }
  .plan-wide-teaser .plan-wide-action {
    flex-direction: row;
    /* With large text the link drops under the price instead of spilling. */
    flex-wrap: wrap;
    gap: 4px 12px;
    align-items: baseline;
    justify-content: space-between;
  }
}

@media (max-width: 640px) {
  .plan-wide {
    max-width: 480px;
  }
  .plan-wide .plan-wide-features {
    columns: 1;
  }
}

/* /static/site-marketing.css */
/* Styles for the marketing pages (src/content/*, src/routes/marketing.ts).
   Linked on every page by src/layout.ts, after site.css. Uses the tokens in
   site.css only; patterns follow Mokxi web/src/site/site.css (plans, FAQ,
   steps, closing band, /vs). Scoped to body.marketing where a rule would
   otherwise change the app. */

/* ---------------- shared ---------------- */

.marketing .accent {
  color: var(--accent);
}

/* The h1 of a page that is not the home hero. */
.page-title {
  font-size: 40px;
  font-weight: 700;
  letter-spacing: -0.025em;
}

/* Centered section heads, as on Mokxi. A head beside its content sits left. */
.marketing .section-head {
  max-width: 720px;
  margin-inline: auto;
  margin-bottom: 34px;
  text-align: center;
}

.marketing .section-head .section-sub {
  max-width: 60ch;
  margin-inline: auto;
}

.marketing .section-head-left,
.marketing .section-head-left .section-sub {
  margin-inline: 0;
  text-align: left;
}

.marketing .section-title {
  font-size: 30px;
  letter-spacing: -0.02em;
}

/* A planned feature: quiet, never hidden. */
.soon {
  /* Kept whole: it moves to the next line as one piece, and breaks inside
     only when one line cannot hold it (large text on a phone). */
  display: inline-block;
  max-width: 100%;
  color: var(--text-faint);
  font-size: 0.92em;
}

.section-actions {
  display: flex;
  justify-content: center;
  margin-top: 26px;
}

/* Row headers in a table read as words, not labels. */
.marketing .table tbody th {
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text);
  white-space: normal;
}

.marketing .table td {
  color: var(--text-dim);
}

/* A row reads along one line: a name and its cells meet on their first
   baseline, however many lines the longest cell wraps to. Tables of marks
   (.compare-table) keep the middle, where a tick lines up with a word. */
.marketing .table tbody :is(th, td) {
  vertical-align: baseline;
}

.marketing .compare-table tbody :is(th, td) {
  vertical-align: middle;
}

/* A list of short lines with a green tick before each. */
.checks {
  display: grid;
  gap: 10px;
  margin: 20px 0 0;
  padding: 0;
  list-style: none;
}

.checks li {
  position: relative;
  padding-left: 28px;
  color: var(--text);
}

.checks li::before {
  content: '';
  position: absolute;
  left: 3px;
  top: 0.62em;
  width: 10px;
  height: 5px;
  border-left: 2px solid var(--chip-ok-fg);
  border-bottom: 2px solid var(--chip-ok-fg);
  transform: rotate(-45deg);
}

.checks-wide {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px 32px;
  max-width: 980px;
  /* Centered under its centered section head, like every other section body. */
  margin-inline: auto;
}

/* Visible breadcrumbs over a page title. */
.crumbs ol {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: 0 0 18px;
  padding: 0;
  list-style: none;
  font-size: 13px;
  color: var(--text-faint);
}

.crumbs li + li::before {
  content: '/';
  margin-right: 4px;
  color: var(--line-strong);
}

.crumbs a {
  color: var(--text-dim);
}

/* ---------------- how it works ---------------- */

.steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg-panel);
}

.step {
  position: relative;
  padding: 24px 26px;
  border-right: 1px solid var(--line);
}

.step:last-child {
  border-right: none;
}

.step-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.step-no {
  display: block;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
}

.step-icon,
.audience-icon {
  display: inline-grid;
  place-items: center;
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 10px;
}

.step-name {
  margin-top: 14px;
  font-size: 19px;
}

.step-line {
  margin-top: 7px;
  color: var(--text-dim);
  font-size: 14.5px;
}

/* An arrow between steps on a desk: the path reads left to right. */
.steps:not(.steps-plain) .step:not(:last-child)::after {
  content: '';
  position: absolute;
  top: 50%;
  right: -7px;
  z-index: 1;
  width: 12px;
  height: 12px;
  background: var(--bg-panel);
  border-top: 1px solid var(--line);
  border-right: 1px solid var(--line);
  transform: translateY(-50%) rotate(45deg);
}

@media (max-width: 760px) {
  .steps {
    grid-template-columns: minmax(0, 1fr);
  }
  .step {
    border-right: none;
    border-bottom: 1px solid var(--line);
  }
  .step:last-child {
    border-bottom: none;
  }
  .steps:not(.steps-plain) .step:not(:last-child)::after {
    top: auto;
    right: auto;
    bottom: -7px;
    left: 32px;
    transform: rotate(135deg);
  }
}

/* ---------------- pricing ---------------- */

/* The page opens on the plans: a short head, the toggle, the cards. */
.marketing .pricing-hero {
  padding-block: 64px 96px;
}

.pricing-head {
  max-width: 720px;
  margin: 0 auto 32px;
  text-align: center;
}

/* The toggle stays its own size on a phone too: two words and a pill. */
.pricing-toggle .segmented {
  display: inline-flex;
  width: auto;
}

.marketing .pricing-head .hero-lead {
  max-width: 40em;
  margin: 16px auto 0;
}

@media (max-width: 720px) {
  .marketing .pricing-hero {
    padding-block: 32px 64px;
  }
  .pricing-head {
    margin-bottom: 24px;
  }
}

.pricing-toggle {
  display: flex;
  justify-content: center;
  margin-bottom: 26px;
}

/* With large text the Yearly segment lets its pill drop under the word
   instead of running past the screen; at normal sizes it stays on the row. */
.pricing-toggle .segment {
  flex: 0 1 auto;
  min-width: 0;
  flex-wrap: wrap;
  padding-block: 2px;
}

.pricing-save {
  font-family: var(--sans);
  font-size: 11px;
  line-height: 16px;
}

.segment[aria-selected='true'] .pricing-save,
.segment[aria-pressed='true'] .pricing-save {
  color: var(--accent);
  background: var(--bg-raised);
  border-color: transparent;
}

.compare-wrap {
  max-width: 940px;
  margin-inline: auto;
}

.compare-table th[scope='col'] {
  text-align: center;
}

.compare-table th[scope='col']:first-child {
  text-align: left;
}

.compare-table td {
  text-align: center;
}

.compare-group th {
  padding-top: 18px;
  font-family: var(--mono) !important;
  font-size: 11px !important;
  font-weight: 500 !important;
  letter-spacing: 0.08em !important;
  text-transform: uppercase !important;
  color: var(--accent) !important;
  background: var(--bg-panel);
}

.marketing .compare-table tbody tr.compare-group:hover th {
  background: var(--bg-panel);
}

.tick {
  display: inline-grid;
  place-items: center;
  color: var(--chip-ok-fg);
}

/* Not "dash": app-analytics.css styles .dash as the dashboard grid, which pushed these cells down. */
.no-mark {
  color: var(--text-faint);
}

.steps-plain .step-no {
  letter-spacing: 0.08em;
}

.compare-prices {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px;
}

.compare-title {
  margin-bottom: 12px;
  font-size: 17px;
}

/* Price tables: the name, then cells on its line. A price never breaks
   ("$49 a month" stays whole) and sits right in tabular figures; the notes
   take the slack. The Sporetag row is tinted to the frame's rounded corners. */
.price-table tr.is-ours th,
.price-table tr.is-ours td {
  color: var(--text);
  background: var(--accent-soft);
}

.marketing .price-table tbody tr.is-ours:hover td {
  background: var(--accent-soft);
}

.price-table .num {
  white-space: nowrap;
}

/* Usage prices are sentences: they wrap, still flush right. */
.usage-table th[scope='row'] {
  width: 45%;
}

/* On a phone a row stacks: name and price on the first line, the plan and
   notes under them. The column heads stay for screen readers. */
@media (max-width: 640px) {
  .price-table,
  .price-table tbody,
  .price-table tr,
  .price-table th,
  .price-table td,
  .usage-table,
  .usage-table tbody,
  .usage-table tr,
  .usage-table th,
  .usage-table td {
    display: block;
  }
  .price-table thead,
  .usage-table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .price-table tbody tr,
  .usage-table tbody tr {
    padding: 12px 16px;
    border-bottom: 1px solid var(--line);
  }
  .price-table tbody tr:last-child,
  .usage-table tbody tr:last-child {
    border-bottom: 0;
  }
  .marketing .price-table tbody :is(th, td),
  .marketing .usage-table tbody :is(th, td) {
    width: auto;
    padding: 0;
    text-align: left;
    background: none;
    border: 0;
  }
  .price-table tbody tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 16px;
    row-gap: 2px;
    align-items: baseline;
  }
  .price-table tbody th {
    grid-area: 1 / 1;
  }
  .marketing .price-table tbody td.num {
    grid-area: 1 / 2;
    text-align: right;
    color: var(--text);
  }
  .price-table tbody td:not(.num) {
    grid-column: 1 / -1;
    font-size: 13.5px;
  }
  .price-table tr.is-ours {
    background: var(--accent-soft);
  }
  .marketing .usage-table tbody td.num {
    margin-top: 2px;
    white-space: normal;
  }
}

.sources-line {
  margin-top: 18px;
  font-size: 13px;
  color: var(--text-faint);
  text-align: center;
}

.sources-line a {
  color: var(--text-dim);
}

@media (max-width: 960px) {
  .compare-prices {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ---------------- FAQ ---------------- */

.faq {
  max-width: 78ch;
  margin-inline: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

.faq-item + .faq-item {
  border-top: 1px solid var(--line);
}

.faq-q {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 52px;
  padding: 14px 18px;
  font-weight: 600;
  font-size: 15px;
  color: var(--text);
  background: var(--bg-panel);
  cursor: pointer;
  list-style: none;
}

.faq-q::-webkit-details-marker {
  display: none;
}

.faq-q:hover {
  background: var(--bg-hover);
}

.faq-q:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.faq-q > span:first-child {
  flex: 1 1 auto;
}

.faq-chevron {
  flex: 0 0 auto;
  color: var(--text-faint);
  transition: transform 0.15s ease;
}

.faq-item[open] > .faq-q {
  background: var(--bg-raised);
}

.faq-item[open] .faq-chevron {
  transform: rotate(180deg);
  color: var(--accent);
}

.faq-a {
  padding: 0 18px 18px;
  background: var(--bg-raised);
}

.faq-a p {
  max-width: 68ch;
  font-size: 14.5px;
  color: var(--text-dim);
}

/* ---------------- the closing band ---------------- */

.closing {
  background:
    radial-gradient(110% 85% at 50% 100%, var(--accent-soft), transparent 72%),
    radial-gradient(110% 85% at 50% 0%, var(--accent-soft), transparent 72%),
    var(--bg-panel);
}

.closing-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.closing-title {
  font-size: 32px;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.closing-line {
  margin-top: 12px;
  max-width: 54ch;
  color: var(--text-dim);
}

.closing-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
  margin-top: 24px;
}

@media (max-width: 720px) {
  .page-title {
    font-size: 30px;
  }
  .marketing .section-title {
    font-size: 24px;
  }
  .closing-title {
    font-size: 26px;
  }
  .closing-actions {
    width: 100%;
  }
  .closing-actions .btn {
    flex: 1 1 160px;
  }
  .checks-wide {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ---------------- /vs ---------------- */

.vs-hero {
  padding-block: 40px 56px;
}

.vs-hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  gap: 44px;
  align-items: start;
}

.vs-hero .hero-lead {
  margin-top: 16px;
}

.vs-checked {
  margin-top: 16px;
  font-size: 13px;
  color: var(--text-faint);
}

/* The direct answer, for "X alternative" searches. */
.answer {
  padding: 22px 24px;
  background: var(--brand-band);
  border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--line));
  border-left: 4px solid var(--accent);
  border-radius: var(--radius);
}

.answer-label {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}

.answer-text {
  margin-top: 10px;
  font-size: 16.5px;
  line-height: 1.55;
}

.answer-note {
  margin-top: 10px;
  font-size: 12.5px;
  color: var(--text-dim);
}

.claims {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.claims li {
  display: flex;
  gap: 12px;
  padding: 16px 18px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.claim-mark {
  flex: 0 0 auto;
  color: var(--chip-ok-fg);
}

.claim-text {
  color: var(--text);
}

.claim-source {
  display: inline-block;
  margin-top: 4px;
  font-size: 12.5px;
  color: var(--text-dim);
}

.vs-table th[scope='col']:nth-child(2) {
  color: var(--accent);
}

.vs-table td:nth-child(2) {
  color: var(--text);
}

.vs-sources {
  margin-top: 18px;
  font-size: 13px;
}

.vs-sources-title {
  font-weight: 600;
  color: var(--text-dim);
}

.vs-sources ul {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 20px;
  margin: 6px 0 0;
  padding: 0;
  list-style: none;
}

.vs-sources a {
  color: var(--text-dim);
}

.which-card {
  padding: 24px;
  background: var(--bg-raised);
}

.which-ours {
  border-color: var(--accent);
}

.which-link {
  margin-top: 18px;
}

.which-link a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  font-weight: 600;
}

.which-link svg {
  width: 15px;
  height: 15px;
}

.related {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.related .chip {
  min-height: 44px;
  padding-inline: 16px;
  font-size: 14px;
}

.vs-groups {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 32px;
}

/* Comparison headlines are two whole lines, "Sporetag vs" and the name, so
   the name never breaks. The longest name ("Google Analytics.") fits a
   358px phone column at the phone size below. */
.vs-title .hero-line {
  display: block;
  /* Each line is chosen to fit whole from 360px up, so it never breaks there.
     With large text (a phone's text size, browser zoom) it breaks evenly
     instead of running off the screen. */
  text-wrap: balance;
}

.vs-group-line {
  margin: -8px 0 14px;
  font-size: 13.5px;
  color: var(--text-dim);
}

.vs-group-title {
  margin-bottom: 14px;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}

.vs-cards {
  display: grid;
  gap: 12px;
}

.vs-card {
  position: relative;
  display: grid;
  gap: 2px;
  padding: 18px 52px 18px 20px;
}

.vs-card .card-title,
.vs-card .card-sub {
  display: block;
}

.vs-card-go {
  position: absolute;
  top: 50%;
  right: 18px;
  color: var(--accent);
  transform: translateY(-50%);
  transition: transform 0.15s ease;
}

a.vs-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-menu);
}

a.vs-card:hover .vs-card-go {
  transform: translate(3px, -50%);
}

@media (max-width: 900px) {
  .vs-hero-grid,
  .vs-groups,
  .claims {
    grid-template-columns: minmax(0, 1fr);
    gap: 24px;
  }
  .claims {
    gap: 12px;
  }
}

/* ---------------- docs ----------------
   The help center (src/content/docs.ts) and its articles (docs/help/,
   rendered by src/content/md.ts). Modeled on calm API docs: a quiet list on
   the left, the article at a reading measure, and a contents rail on the
   right that marks the section being read. Every color is a token, so light
   and dark follow the theme; ratios are noted where a pair is new. */

/* The index: the search first, then one card per section. */
.marketing .docs-head {
  margin-bottom: 28px;
}

.docs-search {
  position: relative;
  max-width: 620px;
  margin: 0 auto;
}

.docs-search-icon {
  position: absolute;
  top: 50%;
  left: 16px;
  color: var(--text-faint);
  transform: translateY(-50%);
  line-height: 0;
}

.docs-search-input {
  min-height: 52px;
  padding-left: 46px;
  font-size: 16px;
  border-radius: var(--radius);
  box-shadow: var(--shadow-menu);
}

.docs-results {
  max-width: 720px;
  margin: 22px auto 0;
}

.docs-results-count {
  margin-bottom: 10px;
  font-size: 13px;
  color: var(--text-faint);
  text-align: center;
}

.docs-result-list {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.docs-result {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 2px 12px;
  padding: 14px 16px;
  color: inherit;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.docs-result:hover {
  border-color: var(--line-strong);
  text-decoration: none;
}

.docs-result-title {
  font-weight: 650;
  color: var(--accent);
}

.docs-result-meta {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.docs-result-line {
  grid-column: 1 / -1;
  font-size: 13.5px;
  color: var(--text-dim);
}

.docs-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  align-items: start;
}

.docs-card {
  padding: 22px 22px 16px;
  background: var(--bg-raised);
}

.docs-card-head {
  display: flex;
  gap: 14px;
  align-items: flex-start;
}

.docs-card-list {
  display: grid;
  margin: 0;
  padding: 0;
  list-style: none;
}

.docs-card-head + .docs-card-list {
  margin-top: 16px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
}

/* A title list reads as a list of places, so no underline until hover. */
.docs-card-link {
  display: flex;
  align-items: center;
  min-height: 34px;
  font-size: 14.5px;
  color: var(--text);
}

.docs-card-link:hover {
  color: var(--accent);
  text-decoration: none;
}

.docs-card-more > summary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 34px;
  font-size: 14px;
  font-weight: 600;
  color: var(--accent);
  list-style: none;
  cursor: pointer;
}

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

.docs-card-more > summary .doc-chevron {
  transform: rotate(90deg);
}

.docs-card-more[open] > summary {
  display: none;
}

@media (max-width: 960px) {
  .docs-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 640px) {
  .docs-grid {
    grid-template-columns: minmax(0, 1fr);
  }
  .docs-card-link,
  .docs-card-more > summary {
    min-height: 44px;
  }
}

/* An article: the list, the page, then the contents rail. */
.doc-page,
.legal-page {
  padding-block: 40px 80px;
}

.doc-layout {
  display: grid;
  grid-template-columns: 232px minmax(0, 1fr) 184px;
  gap: 48px;
  align-items: start;
}

.doc-layout-no-toc {
  grid-template-columns: 232px minmax(0, 1fr);
}

/* One fold mark for every docs disclosure: right when closed, down when open. */
.doc-chevron {
  flex: none;
  color: var(--text-faint);
  transition: transform var(--dur-2) var(--ease-out);
}

details[open] > summary > .doc-chevron {
  transform: rotate(90deg);
}

.doc-nav summary,
.doc-toc-fold > summary {
  list-style: none;
  cursor: pointer;
}

.doc-nav summary::-webkit-details-marker,
.doc-toc-fold > summary::-webkit-details-marker {
  display: none;
}

/* ---- the article list ---- */

.doc-nav {
  position: sticky;
  top: calc(var(--header-h) + 24px);
  font-size: 14px;
}

.doc-nav-summary {
  display: none;
}

/* Its own scroll, the height of the screen. The bar shows only while the
   pointer is over the list (overlay scroll bars already hide on their own). */
.doc-nav-scroll {
  max-height: calc(100dvh - var(--header-h) - 48px);
  margin: -12px 0 0 -10px;
  padding: 12px 6px 24px 0;
  overflow-y: auto;
  /* Rows fade at either edge instead of being cut by it. The padding keeps
     the first and last rows clear of the fade when scrolled to an end. */
  mask-image: linear-gradient(to bottom, transparent, #000 12px, #000 calc(100% - 24px), transparent);
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: transparent transparent;
}

.doc-nav-scroll:hover,
.doc-nav-scroll:focus-within {
  scrollbar-color: var(--line-strong) transparent;
}

.doc-nav-section + .doc-nav-section {
  margin-top: 20px;
}

/* A group heading is a quiet label on a wide screen; on a phone it folds. */
.doc-nav-heading {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 10px 6px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
  pointer-events: none;
}

.doc-nav-heading .doc-chevron {
  display: none;
}

.doc-nav ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Nav lists are plainly links already: no underline (site.css underlines links in running text). */
.doc-nav a,
.doc-toc a,
main .doc-nav a:not([class]),
main .doc-toc a:not([class]),
main .doc-toc-fold a:not([class]) {
  text-decoration: none;
}

/* 32px rows: 20px of line and 6px above and below. */
.doc-nav a {
  display: block;
  padding: 6px 10px;
  line-height: 20px;
  color: var(--text-dim);
  border-radius: var(--r-sm);
  outline-offset: -2px;
}

.doc-nav a:hover {
  color: var(--text);
  background: var(--bg-hover);
}

/* The current article: accent words on a faint accent wash, and heavier.
   Accent on the 7% wash is 5.5:1 in light and 5.0:1 in dark (the 10 and 16%
   accent-soft fell under 4.5 in dark). */
.doc-nav a[aria-current='page'] {
  color: var(--accent);
  font-weight: 600;
  background: color-mix(in srgb, var(--accent) 7%, transparent);
}

/* ---- the article ---- */

.doc-article,
.legal-article {
  min-width: 0;
  max-width: 760px;
}

.doc-article {
  max-width: 680px;
}

.legal-layout {
  display: flex;
  justify-content: center;
}

.legal-article {
  width: 100%;
}

.doc-trail {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 12px;
  font-size: 13px;
  color: var(--text-faint);
}

.doc-trail-link {
  color: var(--text-dim);
}

.doc-trail-link:hover {
  color: var(--accent);
  text-decoration: none;
}

.doc-trail [aria-hidden] {
  color: var(--line-strong);
}

.doc-title {
  font-size: 38px;
  line-height: 1.12;
  letter-spacing: -0.022em;
  text-wrap: balance;
}

.doc-lead {
  max-width: 36em;
  margin-top: 12px;
  font-size: 17.5px;
  line-height: 1.55;
  color: var(--text-dim);
}

.legal-updated {
  margin-top: 8px;
  font-size: 13px;
  color: var(--text-faint);
}

.legal-article .notice {
  margin-top: 18px;
}

/* The words. One scale: 16px body at 1.7, 22px h2, 17px h3, 14px tables,
   13px code. One measure: 36em of running text, about 70 characters. Space
   comes from the block above: 16px between paragraphs, 24px around tables,
   code and notes, 48px before an h2, 32px before an h3, tight under each. */
.doc-body {
  margin-top: 32px;
  font-size: 16px;
  line-height: 1.7;
}

.doc-body > p,
.doc-body > ul,
.doc-body > ol,
.doc-body > h2,
.doc-body > h3 {
  max-width: 36em;
}

.doc-body > * + * {
  margin-top: 16px;
}

.doc-body > h2 {
  margin-top: 48px;
  font-size: 22px;
  line-height: 1.3;
  font-weight: 650;
  letter-spacing: -0.012em;
}

.doc-body > h3 {
  margin-top: 32px;
  font-size: 17px;
  line-height: 1.4;
  font-weight: 650;
}

.doc-body > h2:first-child {
  margin-top: 0;
}

.doc-body > h2 + * {
  margin-top: 12px;
}

.doc-body > h3 + * {
  margin-top: 8px;
}

.doc-body > .table-wrap,
.doc-body > .doc-code,
.doc-body > .doc-note,
.doc-body > * + .table-wrap,
.doc-body > * + .doc-code,
.doc-body > * + .doc-note {
  margin-block: 24px;
}

.doc-body > h2 + .table-wrap,
.doc-body > h2 + .doc-code,
.doc-body > h2 + .doc-note,
.doc-body > h3 + .table-wrap,
.doc-body > h3 + .doc-code,
.doc-body > h3 + .doc-note {
  margin-top: 12px;
}

.doc-body ul,
.doc-body ol {
  padding-left: 1.3em;
}

.doc-body li + li {
  margin-top: 6px;
}

.doc-body li::marker {
  color: var(--text-faint);
}

.doc-body strong {
  font-weight: 650;
}

.doc-body h2,
.doc-body h3 {
  scroll-margin-top: calc(var(--header-h) + 24px);
}

main .doc-body a:not([class]) {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  text-decoration-color: color-mix(in srgb, var(--accent) 45%, transparent);
}

main .doc-body a:not([class]):hover {
  text-decoration-color: currentColor;
}

/* A link to the section, shown when the pointer is on its heading (and on
   the docs and guides alike, which share the renderer). */
.doc-anchor {
  margin-left: 0.4em;
  font-weight: 500;
  color: var(--text-faint);
  text-decoration: none;
  opacity: 0;
  transition: opacity var(--dur-1) ease;
}

h2:hover > .doc-anchor {
  opacity: 1;
}

.doc-anchor:hover {
  color: var(--accent);
  text-decoration: none;
}

@media (hover: none) {
  .doc-anchor {
    display: none;
  }
}

/* Inline code: a soft pill in the text's own color, no border. The 7% wash
   of the text color keeps code at 14:1 or better in both themes. */
.doc-body :not(pre) > code,
.guide-body :not(pre) > code {
  padding: 0.12em 0.36em;
  font-size: 0.875em;
  background: color-mix(in srgb, var(--text) 7%, transparent);
  border: 0;
  border-radius: 5px;
  /* A long address in a sentence breaks rather than push the page sideways. */
  overflow-wrap: anywhere;
}

/* ---- code blocks: a slim bar (language, Copy) on the same ground as the code ---- */

.doc-code {
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

.doc-code-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 38px;
  padding: 0 6px 0 16px;
  border-bottom: 1px solid var(--line);
}

.doc-code-lang {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.doc-code-copy {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 28px;
  padding: 0 10px;
  font: inherit;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--text-dim);
  background: transparent;
  border: 0;
  border-radius: var(--r-sm);
  cursor: pointer;
  transition:
    color var(--dur-1) ease,
    background-color var(--dur-1) ease;
}

.doc-code-copy:hover {
  color: var(--text);
  background: var(--bg-hover);
}

.doc-code .code {
  padding: 14px 16px;
  font-size: 13px;
  line-height: 1.65;
  color: var(--text);
  background: transparent;
  border: 0;
  border-radius: 0;
  overflow-y: hidden;
  tab-size: 2;
}

.doc-code .code:focus-visible {
  outline-offset: -2px;
}

.doc-code-wrap .code {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.doc-code .code code {
  padding: 0;
  background: none;
  border: none;
}

/* ---- notes: one shape, two tones. Used sparingly ---- */

.doc-note {
  display: grid;
  grid-template-columns: 16px minmax(0, 1fr);
  gap: 10px;
  padding: 12px 16px;
  background: var(--info-bg);
  border: 1px solid var(--info-line);
  border-radius: var(--radius);
}

.doc-note-icon {
  margin-top: 4px;
  color: var(--accent);
}

.doc-note p {
  font-size: 15px;
  line-height: 1.6;
  color: var(--text);
}

.doc-warning {
  background: var(--warning-bg);
  border-color: var(--warning-line);
}

/* Warning ink on the warning ground: 6.1:1 light, 9.6:1 dark. */
.doc-warning .doc-note-icon {
  color: var(--warning-fg);
}

/* ---- tables: hairlines between rows, no zebra, no hover ---- */

.doc-table {
  font-size: 14px;
  line-height: 1.5;
}

/* Cells meet on their first line, so a mono type lines up with its name. */
.doc-table th,
.doc-table td {
  padding: 9px 14px;
  vertical-align: baseline;
}

.doc-table thead th {
  position: static;
  height: 36px;
  padding-block: 0;
  vertical-align: middle;
  white-space: nowrap;
  background: transparent;
}

.doc-table tbody tr:hover td {
  background: none;
}

/* The frame closes the table: the last row's name loses its rule too. */
.doc-table tbody tr:last-child > th {
  border-bottom: 0;
}

/* A field name is one word: it never breaks, and its column takes what it
   needs. A row named in plain words (a plan feature) wraps like any text. */
.doc-table th[scope='row'] code {
  padding: 0;
  font-size: 0.93em;
  font-weight: 600;
  background: none;
  overflow-wrap: normal;
  white-space: nowrap;
}

.doc-type {
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--text-faint);
}

/* Named past `.marketing .table td`, which sets cells in text-dim. Faint on
   the panel is 5.1:1 light, 5.5:1 dark. */
.marketing .doc-table td.doc-type {
  color: var(--text-faint);
  white-space: nowrap;
}

/* A table wider than the screen scrolls inside its frame. A shade at the
   edge says there is more: the panel-colored covers scroll with the table
   and hide the shade once the edge is reached. Cells stay transparent so the
   shade can show through. */
.doc-table-wrap {
  background:
    linear-gradient(to right, var(--bg-panel) 40%, transparent) left / 36px 100% no-repeat local,
    linear-gradient(to left, var(--bg-panel) 40%, transparent) right / 36px 100% no-repeat local,
    linear-gradient(to right, color-mix(in srgb, var(--text) 12%, transparent), transparent) left / 14px 100% no-repeat scroll,
    linear-gradient(to left, color-mix(in srgb, var(--text) 12%, transparent), transparent) right / 14px 100% no-repeat scroll,
    var(--bg-panel);
}

/* ---- after the words ---- */

.doc-pager {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin-top: 56px;
}

.doc-pager-link {
  display: grid;
  gap: 2px;
  padding: 14px 16px;
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  transition:
    border-color var(--dur-1) ease,
    background-color var(--dur-1) ease;
}

.doc-pager-link:hover {
  background: var(--bg-panel);
  border-color: var(--line-strong);
  text-decoration: none;
}

.doc-pager-dir {
  font-size: 12.5px;
  color: var(--text-faint);
}

.doc-pager-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--accent);
}

.doc-pager-link.next {
  text-align: right;
}

.doc-help {
  margin-top: 20px;
  font-size: 13.5px;
  color: var(--text-faint);
}

/* ---- contents: a rail on a wide screen, folded under the lead otherwise ---- */

.doc-side {
  position: sticky;
  top: calc(var(--header-h) + 24px);
  max-height: calc(100dvh - var(--header-h) - 48px);
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
}

.doc-toc-title {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.doc-side .doc-toc ul {
  margin: 10px 0 0;
  padding: 0;
  list-style: none;
  border-left: 1px solid var(--line);
}

.doc-side .doc-toc a {
  display: block;
  margin-left: -1px;
  padding: 5px 0 5px 12px;
  font-size: 13px;
  line-height: 1.45;
  color: var(--text-dim);
  border-left: 2px solid transparent;
  outline-offset: -2px;
}

.doc-side .doc-toc a:hover {
  color: var(--text);
}

.doc-side .doc-toc a[aria-current='true'] {
  color: var(--accent);
  font-weight: 600;
  border-left-color: var(--accent);
}

.doc-toc-fold {
  display: none;
  margin-top: 24px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.doc-toc-fold > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 44px;
  padding: 0 14px 0 16px;
  font-size: 14.5px;
  font-weight: 600;
}

.doc-toc-fold ul {
  margin: 0;
  padding: 0 16px 10px;
  list-style: none;
  font-size: 14.5px;
}

.doc-toc-fold a {
  display: flex;
  align-items: center;
  min-height: 36px;
  color: var(--text-dim);
}

.doc-toc-fold a:hover {
  color: var(--accent);
}

/* The legal pages keep their contents list as one box under the lead. */
.legal-article .doc-toc {
  margin-top: 24px;
  padding: 14px 18px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.legal-article .doc-toc ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0 20px;
  margin: 8px 0 0;
  padding: 0;
  list-style: none;
  font-size: 14px;
}

.legal-article .doc-toc a {
  display: inline-flex;
  align-items: center;
  min-height: 30px;
}

/* Under 1180 the rail goes; the contents fold under the lead. */
@media (max-width: 1180px) {
  .doc-layout,
  .doc-layout-no-toc {
    grid-template-columns: 232px minmax(0, 1fr);
  }
  .doc-side {
    display: none;
  }
  .doc-toc-fold {
    display: block;
  }
}

/* Under 900 the list folds into one row above the article; each group folds too. */
@media (max-width: 900px) {
  .doc-layout,
  .doc-layout-no-toc {
    grid-template-columns: minmax(0, 1fr);
    gap: 24px;
  }
  .doc-nav {
    position: static;
    font-size: 15px;
  }
  .doc-nav-fold {
    background: var(--bg-panel);
    border: 1px solid var(--line);
    border-radius: var(--radius);
  }
  .doc-nav-summary {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 48px;
    padding: 0 14px 0 16px;
    font-weight: 600;
  }
  .doc-nav-where {
    margin-left: auto;
    font-size: 13.5px;
    font-weight: 400;
    color: var(--text-faint);
  }
  .doc-nav-scroll {
    max-height: none;
    margin: 0;
    padding: 4px 8px 8px;
    overflow: visible;
    mask-image: none;
    border-top: 1px solid var(--line);
  }
  .doc-nav-section + .doc-nav-section {
    margin-top: 0;
    border-top: 1px solid var(--line);
  }
  .doc-nav-heading {
    min-height: 44px;
    padding: 0 8px;
    pointer-events: auto;
  }
  .doc-nav-heading .doc-chevron {
    display: block;
  }
  .doc-nav-section ul {
    padding-bottom: 8px;
  }
  .doc-nav a {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding-block: 10px;
  }
}

@media (max-width: 720px) {
  .doc-page {
    padding-top: 20px;
  }
  .doc-title {
    font-size: 30px;
  }
  .doc-lead {
    font-size: 16px;
  }
  .doc-body {
    margin-top: 24px;
  }
  .doc-body > h2 {
    margin-top: 40px;
    font-size: 20px;
  }
  .doc-toc-fold a {
    min-height: 44px;
  }
  /* A 44px tap target that still sits inside the slim bar. */
  .doc-code-bar {
    min-height: 44px;
    padding-right: 0;
  }
  .doc-code-copy {
    height: 44px;
    padding-inline: 14px;
    border-radius: 0;
  }
  /* Plain tables keep a readable column: the notes never shrink to a word
     a line, the frame scrolls instead. */
  .doc-table td {
    min-width: 11em;
  }
  /* A parameter table stacks: the name, its type beside it in muted mono,
     then the notes under them. One hairline between parameters. */
  .doc-table-wrap:has(.doc-params) {
    background: var(--bg-panel);
  }
  .doc-params,
  .doc-params tbody,
  .doc-params tr,
  .doc-params td {
    display: block;
  }
  /* The column names stay for screen readers; clip-path hides them. */
  .doc-params thead {
    position: absolute;
    width: 1px;
    height: 1px;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .doc-params tr {
    padding: 12px 16px;
    border-bottom: 1px solid var(--line);
  }
  .doc-params tbody tr:last-child {
    border-bottom: 0;
  }
  .doc-params th[scope='row'],
  .doc-params td {
    padding: 0;
    border: 0;
  }
  .doc-params th[scope='row'] {
    display: inline;
  }
  .doc-params td.doc-type {
    display: inline;
    margin-left: 8px;
  }
  .doc-params td:last-child {
    min-width: 0;
    margin-top: 4px;
    color: var(--text-dim);
  }
  .doc-pager {
    grid-template-columns: minmax(0, 1fr);
  }
  .doc-pager-link.next {
    text-align: left;
  }
}

/* ---------------- fixes from the layout check ---------------- */

/* Each group of rows keeps its bottom rule; only the table's last row loses it.
   td and th named so these outrank `.table tbody tr:last-child td` in site.css. */
.compare-table tbody tr:last-child > td,
.compare-table tbody tr:last-child > th {
  border-bottom: 1px solid var(--line);
}

.compare-table tbody:last-of-type tr:last-child > td,
.compare-table tbody:last-of-type tr:last-child > th {
  border-bottom: none;
}

/* Five plans do not fit a phone: the table scrolls inside its frame, and the
   feature names stay pinned on the left so each row stays readable. */
@media (max-width: 720px) {
  .compare-table {
    min-width: 640px;
  }
  .compare-table th[scope='row'],
  .compare-table thead th:first-child {
    position: sticky;
    left: 0;
    z-index: 1;
    min-width: 132px;
    background: var(--bg-panel);
  }
}

.claims .claim-text {
  display: block;
}

/* ---------------- /tools/utm-builder (src/content/tools.ts) ---------------- */

.ub-wrap {
  max-width: 760px;
}

.ub-lead {
  max-width: 34em;
  margin-top: 12px;
  font-size: 17px;
  color: var(--text-dim);
}

.ub-lead-small {
  max-width: 40em;
  margin-top: 8px;
  font-size: 14px;
  color: var(--text-faint);
}

.ub {
  display: grid;
  gap: 18px;
  margin-top: 28px;
  padding: 22px;
  background: var(--bg-raised);
  box-shadow: var(--shadow-panel);
}

.ub-field {
  display: grid;
  gap: 6px;
  min-width: 0;
}

.ub-label {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
}

.ub-optional {
  font-weight: 400;
  color: var(--text-faint);
}

.ub-key {
  margin-left: 4px;
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 400;
  color: var(--text-faint);
}

.ub-input {
  width: 100%;
  min-height: 44px;
  padding: 8px 12px;
  font: inherit;
  color: var(--text);
  background: var(--bg-input);
  /* The field edge at 3:1 on every surface (WCAG 1.4.11); line-strong is 1.7:1. */
  border: 1px solid var(--line-input);
  border-radius: var(--radius-sm);
}

.ub-input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.ub-dest {
  min-height: 50px;
  font-family: var(--mono);
  font-size: 14.5px;
}

.ub-hint,
.ub-note {
  font-size: 13px;
  color: var(--text-dim);
}

.ub-hint:empty {
  display: none;
}

.ub-group {
  display: grid;
  grid-template-columns: 76px minmax(0, 1fr);
  gap: 8px;
  align-items: start;
}

.ub-group-name {
  padding-top: 9px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.ub .chip {
  min-height: 40px;
  padding-inline: 14px;
  font: inherit;
  font-size: 14px;
  cursor: pointer;
}

/* A phone tap target is 44px, as every other chip on a phone (ui.css). */
@media (max-width: 720px) {
  .ub .chip {
    min-height: var(--ctl-h-lg);
  }
}

.ub-pair,
.ub-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.ub-advanced {
  padding: 0 14px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}

.ub-advanced summary {
  display: flex;
  align-items: center;
  min-height: 44px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text-dim);
  cursor: pointer;
}

.ub-advanced summary::-webkit-details-marker {
  display: none;
}

.ub-advanced[open] {
  display: grid;
  gap: 12px;
  padding-bottom: 14px;
}

.ub-result {
  display: grid;
  gap: 10px;
  padding: 16px;
  background: var(--bg-panel);
  border: 1px solid color-mix(in srgb, var(--accent) 40%, var(--line));
  border-radius: var(--radius);
}

.ub-code {
  display: block;
  padding: 10px 12px;
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.5;
  color: var(--text);
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  overflow-wrap: anywhere;
}

.ub-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.ub-template {
  display: grid;
  gap: 10px;
}

.ub-template-card {
  display: grid;
  gap: 8px;
  padding: 14px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}

.ub-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.ub-template-title {
  font-size: 14px;
  font-weight: 600;
}

.ub-steps {
  display: grid;
  gap: 4px;
  margin: 0;
  padding-left: 20px;
  font-size: 13.5px;
  color: var(--text-dim);
}

.ub-private {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text-dim);
}

.ub-private svg {
  flex: none;
  color: var(--accent);
}

@media (max-width: 720px) {
  .ub {
    padding: 16px;
  }
  .ub-group {
    grid-template-columns: minmax(0, 1fr);
    gap: 6px;
  }
  .ub-group-name {
    padding-top: 0;
  }
  .ub-pair,
  .ub-grid {
    grid-template-columns: minmax(0, 1fr);
  }
  .ub-actions .btn {
    flex: 1 1 100%;
  }
}

/* ---------------- /tools, the tag checker, the estimator, the checklist (src/content/freeTools.ts) ---------------- */

.tools-cards {
  margin-top: 28px;
}

.tool-card {
  padding-left: 64px;
}

.tool-icon {
  position: absolute;
  top: 50%;
  left: 20px;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 9px;
  transform: translateY(-50%);
}

.tc-row {
  display: flex;
  gap: 10px;
}

.tc-row .ub-input {
  flex: 1 1 auto;
  min-width: 0;
}

.tc-row .btn {
  flex: none;
}

#result:empty {
  display: none;
}

.tc-result {
  display: grid;
  gap: 14px;
  padding: 18px;
  background: var(--bg-panel);
  border: 1px solid color-mix(in srgb, var(--accent) 40%, var(--line));
  border-radius: var(--radius);
}

.tc-head {
  display: grid;
  gap: 4px;
}

.tc-site {
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--text-faint);
  overflow-wrap: anywhere;
}

.tc-title {
  font-family: var(--serif);
  font-size: 22px;
  line-height: 1.25;
  letter-spacing: -0.015em;
  color: var(--text);
}

.tc-line {
  color: var(--text-dim);
}

.tc-groups {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.tc-group {
  display: grid;
  gap: 8px;
  align-content: start;
  padding: 14px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}

.tc-group-name {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.tc-list {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.tc-list li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 8px;
  font-size: 14.5px;
  font-weight: 600;
}

.tc-tick {
  display: inline-flex;
  color: var(--accent);
}

.tc-id {
  padding: 2px 7px;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 400;
  color: var(--text-dim);
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: 6px;
  overflow-wrap: anywhere;
}

.tc-notes {
  display: grid;
  gap: 4px;
  margin: 0;
  padding-left: 18px;
  font-size: 13.5px;
  color: var(--text-dim);
}

.tc-steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.tc-steps li {
  display: grid;
  gap: 10px;
  padding: 20px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: var(--shadow-card);
}

.tc-steps b {
  color: var(--text);
}

.tc-steps span {
  color: var(--text-dim);
}

.tc-step-no {
  font-size: 12px;
  letter-spacing: 0.1em;
  color: var(--accent) !important;
}

.blocker {
  margin-top: 28px;
}

.blocker-source {
  margin-top: 18px;
  font-size: 13px;
  color: var(--text-dim);
}

.lead-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: 14px 32px;
  align-items: center;
  max-width: 960px;
  margin-inline: auto;
  padding: 28px;
  background: var(--bg-raised);
  box-shadow: var(--shadow-card);
}

.lead-title {
  font-family: var(--serif);
  font-size: 26px;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.015em;
}

.lead-line {
  margin-top: 6px;
  color: var(--text-dim);
}

.lead-row {
  display: flex;
  gap: 10px;
}

.lead-input {
  flex: 1 1 auto;
  min-width: 0;
}

.lead-row .btn {
  flex: none;
}

.lead-card .turnstile,
.lead-note {
  grid-column: 2;
}

.lead-note {
  font-size: 12.5px;
  color: var(--text-faint);
}

@media (max-width: 720px) {
  .tc-row,
  .lead-row {
    flex-direction: column;
  }
  .tc-groups,
  .tc-steps,
  .lead-card {
    grid-template-columns: minmax(0, 1fr);
  }
  .lead-card {
    padding: 20px;
  }
  .lead-card .turnstile,
  .lead-note {
    grid-column: auto;
  }
  .lead-title {
    font-size: 22px;
  }
}

/* ================================================================
   The warm redesign (docs/style.md, 2026-10-21). Serif headlines on
   marketing pages, mono labels, app windows, big numbers, alternating
   paper, tint and blue bands. Motion lives in marketing.js and is off
   under prefers-reduced-motion.
   ================================================================ */

/* ---------------- type ---------------- */

.marketing h1,
.marketing .section-title,
.marketing .page-title,
.marketing .closing-title,
.marketing .promise-title,
.marketing .gap-statement,
.marketing .estimator-title,
.marketing .step-card-title,
.marketing .mode-title,
.marketing .pick-title,
.marketing .faq-q,
.marketing .plan-name {
  font-family: var(--serif);
  font-weight: 500;
  letter-spacing: -0.015em;
}

.marketing .hero-title {
  font-size: 54px;
  line-height: 1.06;
  letter-spacing: -0.025em;
  font-weight: 500;
}

.marketing .page-title {
  font-size: 48px;
  line-height: 1.08;
  font-weight: 500;
}

.marketing .section-title {
  font-size: 44px;
  line-height: 1.1;
  font-weight: 500;
}

.marketing .section-sub {
  font-size: 17px;
  line-height: 1.55;
}

.marketing .section-eyebrow {
  font-size: 11.5px;
  letter-spacing: 0.12em;
  color: var(--text-faint);
}

.step-label {
  margin: 0 0 12px;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.step-label-no {
  color: var(--accent);
}

.found {
  color: var(--found);
}

.lost {
  color: var(--lost);
}

/* ---------------- sections: paper, tint, blue ---------------- */

.wsec {
  padding-block: 104px;
}

.wsec-tint {
  background: var(--bg-tint);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.wsec-tint + .section,
.section + .wsec-tint {
  border-top-color: var(--line);
}

.wsec-blue {
  border-top: none;
}

.wsec-paper + .wsec-paper {
  border-top: 1px solid var(--line);
}

.wsec-head {
  max-width: 780px;
  margin: 0 auto 52px;
  text-align: center;
}

.wsec-head .section-sub {
  max-width: 58ch;
  margin: 16px auto 0;
  color: var(--text-dim);
}

.wsec-head-left {
  margin-inline: 0;
  text-align: left;
}

.frame-icon {
  display: block;
  margin: 0 auto 22px;
  color: var(--text);
}

.wsec-head-left .frame-icon {
  margin-inline: 0;
}

/* The soft blue band: a rounded panel on paper, a white title card on it. */
.blue-panel {
  position: relative;
  padding: 40px;
  background:
    radial-gradient(70% 90% at 100% 0%, color-mix(in srgb, var(--accent) 9%, transparent), transparent 70%),
    radial-gradient(60% 80% at 0% 100%, color-mix(in srgb, var(--accent) 7%, transparent), transparent 70%),
    var(--brand-band);
  border: 1px solid color-mix(in srgb, var(--accent) 16%, var(--line));
  border-radius: 22px;
  overflow: hidden;
}

.wsec-head-card {
  max-width: 900px;
  margin-bottom: 28px;
  padding: 26px 32px 30px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: var(--shadow-card);
}

.wsec-head-card .section-title {
  font-size: 38px;
}

/* ---------------- app window ---------------- */

.st-window {
  position: relative;
  min-width: 0;
  /* A picture of our screens: with large text its words break inside it. */
  overflow-wrap: anywhere;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-panel);
  overflow: hidden;
}

.st-window-bar {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr) 64px;
  align-items: center;
  height: 38px;
  padding: 0 14px;
  border-bottom: 1px solid var(--line);
  background: var(--bg-raised);
}

.st-dots {
  display: flex;
  gap: 6px;
}

.st-dots i {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--line-strong);
  opacity: 0.8;
}

.st-url {
  overflow: hidden;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--text-faint);
}

.st-tag {
  justify-self: end;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  white-space: nowrap;
  color: var(--accent);
}

.st-window-body {
  padding: 18px;
}

.st-window-foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 6px 16px;
  padding: 12px 18px;
  font-size: 13px;
  color: var(--text-dim);
  border-top: 1px solid var(--line);
  background: color-mix(in srgb, var(--bg-tint) 55%, var(--bg-raised));
}

.window-caption {
  margin-top: 12px;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.04em;
  color: var(--text-faint);
  text-align: center;
}

/* ---------------- big numbers ---------------- */

.bignum {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.bignum-label {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.bignum-value {
  font-family: var(--serif);
  font-size: 44px;
  line-height: 1.05;
  font-weight: 500;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--text);
}

.bignum-lost .bignum-value {
  color: var(--lost);
}

.bignum-found .bignum-value {
  color: var(--found);
}

.bignum-caption {
  font-size: 13px;
  color: var(--text-dim);
}

/* ---------------- pills and chips ---------------- */

.pill-row,
.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.pill-row-center,
.chip-row.strip-chips {
  justify-content: center;
}

.pill-row-center {
  margin-top: 40px;
}

.pill-plain {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 34px;
  padding: 4px 14px 4px 11px;
  font-size: 14px;
  font-weight: 500;
  color: var(--text);
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 999px;
}

.pill-plain .tick-svg {
  color: var(--accent);
}

.chip-row li {
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  padding: 4px 14px;
  font-size: 14px;
  color: var(--text);
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 999px;
}

.chip-mini {
  display: inline-flex;
  align-items: center;
  padding: 1px 8px;
  font-size: 11.5px;
  font-weight: 500;
  color: var(--text-dim);
  background: var(--bg-tint);
  border: 1px solid var(--line);
  border-radius: 999px;
  white-space: nowrap;
}

.chip-mini.is-on {
  color: var(--accent);
  background: var(--accent-soft);
  border-color: transparent;
}

/* ---------------- hero ---------------- */

.home-hero,
.pricing-hero {
  padding-block: 72px 96px;
}

.marketing .hero-grid {
  grid-template-columns: minmax(0, 0.94fr) minmax(0, 1.06fr);
  gap: 56px;
}

.marketing .hero-lead {
  margin-top: 22px;
  font-size: 18px;
  line-height: 1.55;
  max-width: 30em;
}

/* The button tray: both calls to action in one quiet card. */
.cta-tray {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 30px;
  padding: 10px;
  background: color-mix(in srgb, var(--bg-raised) 70%, transparent);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: var(--shadow-card);
}

.hero-try {
  margin-top: 16px;
  font-size: 14px;
  color: var(--text-dim);
}

.hero-dots {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  margin: 22px 0 0;
  padding: 0;
  list-style: none;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.04em;
  color: var(--text-faint);
}

/* Each fact is its own item with its own dot, so a wrapped row stays aligned. */
.hero-dots li {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}

.hero-dots li::before {
  content: '';
  flex: 0 0 auto;
  width: 5px;
  height: 5px;
  margin-right: 8px;
  border-radius: 50%;
  background: var(--accent);
}

/* The hero headline is always two lines: "Know which platforms" and
   "drive <word>." Each line stays whole; the font size below keeps the
   first line inside the column down to a 360px phone. */
.hero-title .hero-line {
  display: block;
  /* Each line is chosen to fit whole from 360px up, so it never breaks there.
     With large text (a phone's text size, browser zoom) it breaks evenly
     instead of running off the screen. */
  text-wrap: balance;
}

/* The rotating word: every word in one grid cell, so the box is as wide as
   the widest and nothing moves when it swaps. */
.rotator {
  display: inline-grid;
  justify-items: start;
  vertical-align: baseline;
}

.rotator-word {
  grid-area: 1 / 1;
  white-space: nowrap;
}

.js-motion .rotator-word {
  opacity: 0;
  transform: translateY(0.22em);
  transition: opacity 0.28s ease, transform 0.28s ease;
}

.js-motion .rotator-word.is-on {
  opacity: 1;
  transform: none;
}

.js-motion .rotator-word.is-out {
  opacity: 0;
  transform: translateY(-0.22em);
}

/* ---------------- the hero film ---------------- */

.film {
  margin: 0;
}

.film .st-window-body {
  padding: 0;
}

.film-steps {
  /* Each step as wide as its words, spread across the bar: equal quarters cut "Sent to Meta" on phones. */
  display: grid;
  grid-template-columns: repeat(4, auto);
  justify-content: space-between;
  column-gap: 8px;
  margin: 0;
  padding: 12px 14px 10px;
  list-style: none;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.film-step {
  display: flex;
  align-items: center;
  gap: 7px;
  /* Each step fits on one line at every phone width; with large text it wraps
     inside its column instead of pushing the bar off the screen. */
  min-width: 0;
  transition: color 0.3s ease;
}

.film-step b {
  display: inline-grid;
  place-items: center;
  width: 18px;
  height: 18px;
  font-weight: 600;
  font-size: 10px;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
}

.film.is-b1 .film-step[data-step='1'],
.film.is-b2 .film-step[data-step='2'],
.film.is-b3 .film-step[data-step='3'],
.film.is-b4 .film-step[data-step='4'] {
  color: var(--accent);
}

.film.is-b1 .film-step[data-step='1'] b,
.film.is-b2 .film-step[data-step='2'] b,
.film.is-b3 .film-step[data-step='3'] b,
.film.is-b4 .film-step[data-step='4'] b {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--accent);
}

.film-bar {
  height: 2px;
  margin: 0 14px;
  background: var(--line);
  border-radius: 2px;
  overflow: hidden;
}

.film-bar i {
  display: block;
  width: 0;
  height: 100%;
  background: var(--accent);
  transition: width 0.9s ease;
}

.film.is-b1 .film-bar i { width: 25%; }
.film.is-b2 .film-bar i { width: 50%; }
.film.is-b3 .film-bar i { width: 75%; }
.film.is-b4 .film-bar i { width: 100%; }

.film-source {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 12px;
  margin: 16px 18px 6px;
  padding: 12px 14px;
  background: var(--bg-tint);
  border: 1px solid var(--line);
  border-radius: 12px;
}

.film-avatar {
  display: inline-grid;
  place-items: center;
  width: 34px;
  height: 34px;
  font-weight: 700;
  color: #ffffff;
  background: linear-gradient(135deg, #b8547a, #d4884a);
  border-radius: 50%;
}

.film-who {
  display: flex;
  flex-direction: column;
  line-height: 1.25;
  font-size: 13.5px;
}

.film-who span {
  font-size: 12px;
  color: var(--text-faint);
}

.film-link {
  position: relative;
  display: inline-flex;
  min-width: 0;
  max-width: 100%;
  overflow-wrap: anywhere;
  align-items: center;
  gap: 6px;
  margin-left: auto;
  padding: 6px 11px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--text);
  background: var(--bg-raised);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
}

.film-link svg {
  width: 14px;
  height: 14px;
  color: var(--accent);
}

.film-tap {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 34px;
  height: 34px;
  margin: -17px 0 0 -17px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--accent) 35%, transparent);
  opacity: 0;
  pointer-events: none;
}

.film.is-tap .film-tap {
  animation: film-tap 0.7s ease-out;
}

@keyframes film-tap {
  0% { opacity: 0.9; transform: scale(0.3); }
  100% { opacity: 0; transform: scale(2.2); }
}

.film-feed {
  margin: 10px 18px 0;
}

.film-row {
  display: grid;
  grid-template-columns: 62px 74px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 0 4px;
  font-size: 13px;
  border-bottom: 1px dashed var(--line);
}

/* Each row is an empty slot until its beat: the line stays, the words arrive. */
.film-row > * {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.4s ease, transform 0.4s ease;
}

.film-row:last-child {
  border-bottom: none;
}

.film.is-b1 .film-row-1 > *,
.film.is-b2 .film-row-2 > *,
.film.is-b3 .film-row-3 > * {
  opacity: 1;
  transform: none;
}

.film.is-b1 .film-row-1,
.film.is-b2 .film-row-2,
.film.is-b3 .film-row-3 {
  border-bottom-style: solid;
}

.film-time {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--text-faint);
}

.film-ev {
  justify-self: start;
  padding: 1px 8px;
  font-size: 11.5px;
  font-weight: 600;
  border-radius: 999px;
}

.ev-click {
  color: var(--accent);
  background: var(--accent-soft);
}

.ev-visit {
  color: var(--text-dim);
  background: var(--bg-active);
}

.ev-sale {
  color: var(--chip-ok-fg);
  background: var(--chip-ok-bg);
}

.film-what {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--mono);
  font-size: 12px;
}

.film-note {
  font-size: 12.5px;
  color: var(--text-faint);
  white-space: nowrap;
}

.film-credit {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-weight: 600;
  color: var(--accent);
  transition: opacity 0.4s ease 0.6s;
}

.film:not(.is-b3) .film-row-3 .film-credit {
  opacity: 0;
}

.film-foot {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  margin-top: 14px;
  border-top: 1px solid var(--line);
  background: color-mix(in srgb, var(--bg-tint) 55%, var(--bg-raised));
}

.film-foot > * {
  padding: 16px 18px 18px;
}

.film-foot > * + * {
  border-left: 1px solid var(--line);
}

.film-foot .bignum-value {
  font-size: 38px;
}

.film-meta-state {
  display: flex;
  align-items: center;
  min-height: 40px;
}

.film-wait,
.film-sent {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
}

.film-wait {
  color: var(--text-faint);
}

.film-sent {
  padding: 5px 12px;
  font-weight: 600;
  color: var(--chip-ok-fg);
  background: var(--chip-ok-bg);
  border: 1px solid var(--chip-ok-line);
  border-radius: 999px;
}

.film:not(.is-b4) .film-sent,
.film.is-b4 .film-wait {
  display: none;
}

.film.is-b4 .film-sent {
  animation: film-pop 0.45s ease;
}

@keyframes film-pop {
  0% { transform: scale(0.85); opacity: 0; }
  100% { transform: none; opacity: 1; }
}

.film.is-fading .st-window-body {
  opacity: 0.25;
  transition: opacity 0.4s ease;
}

.film-caption {
  margin-top: 12px;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.04em;
  text-align: center;
  color: var(--text-faint);
}

/* ---------------- platform strip and setup ---------------- */

.strip {
  /* It follows the revenue band now, not the hero, so it needs its own room above. */
  padding-block: 64px 72px;
}

.strip-line {
  margin-bottom: 14px;
  font-size: 14.5px;
  color: var(--text-dim);
  text-align: center;
}

.setup-band {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 24px;
  max-width: 1000px;
  margin: 36px auto 0;
  padding: 18px 22px;
  background: var(--bg-tint);
  border: 1px solid var(--line);
  border-radius: 14px;
}

.setup-band-line {
  flex: 1 1 360px;
  font-size: 14.5px;
  color: var(--text-dim);
}

.setup-band-line strong {
  color: var(--text);
}

.setup-band-link {
  font-weight: 600;
  white-space: nowrap;
}

.setup-band-list {
  gap: 6px;
}

.setup-band-list li {
  min-height: 28px;
  padding: 2px 10px;
  font-size: 12.5px;
  color: var(--text-dim);
}

/* ---------------- the gap ---------------- */

.gap-grid {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: 28px;
  align-items: center;
}

.gap-card {
  padding: 40px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 18px;
  box-shadow: var(--shadow-card);
}

.gap-statement {
  font-size: 40px;
  line-height: 1.1;
}

.gap-line {
  margin-top: 18px;
  font-size: 17px;
  color: var(--text-dim);
}

.gap-fine {
  margin-top: 18px;
  font-size: 13px;
  color: var(--text-faint);
}

.journey-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.journey-row {
  display: grid;
  grid-template-columns: 14px 58px minmax(0, 1fr);
  align-items: center;
  gap: 12px;
  min-height: 44px;
  border-bottom: 1px solid var(--line);
  font-size: 14.5px;
}

.journey-dot {
  width: 9px;
  height: 9px;
  border: 1.5px solid var(--line-strong);
  border-radius: 50%;
}

.journey-day {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--text-faint);
}

.journey-row.is-sale .journey-dot {
  background: var(--accent);
  border-color: var(--accent);
}

.journey-row.is-sale .journey-day {
  color: var(--accent);
}

.journey-row.is-sale .journey-what {
  font-weight: 600;
}

.journey-totals {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin-top: 16px;
}

.journey-totals .bignum {
  padding: 14px 16px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 12px;
}

.journey-totals .bignum-value {
  font-size: 36px;
}

/* ---------------- four steps ---------------- */

.step-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.step-card {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 30px 30px 26px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 18px;
  box-shadow: var(--shadow-card);
}

.step-card-title {
  font-size: 27px;
  line-height: 1.15;
}

.step-card-line {
  margin-top: 8px;
  color: var(--text-dim);
}

.step-card-visual {
  display: flex;
  align-items: center;
  flex: 1 1 auto;
  min-height: 132px;
  margin-top: 22px;
  padding: 18px;
  background: var(--bg-tint);
  border: 1px solid var(--line);
  border-radius: 12px;
}

.step-card-visual > * {
  width: 100%;
}

.mini-code {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 12px 12px 14px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 10px;
}

.mini-code code {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--text);
  word-break: break-all;
}

.mini-linkcard {
  padding: 14px 16px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 10px;
}

.mini-linkcard-short {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--mono);
  font-size: 14px;
}

/* With large text the short address breaks inside the card. */
.mini-linkcard-short > span {
  min-width: 0;
  overflow-wrap: anywhere;
}

.mini-linkcard-short svg {
  color: var(--accent);
}

.mini-linkcard-label {
  margin: 12px 0 8px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.mini-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.mini-chips li {
  padding: 3px 10px;
  font-size: 12.5px;
  color: var(--text-dim);
  background: var(--bg-tint);
  border: 1px solid var(--line);
  border-radius: 999px;
}

.mini-chips li.is-on {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--accent);
}

.mini-path {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 10px;
}

.mini-path li {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 14px;
}

.mini-path li + li {
  border-left: 1px solid var(--line);
}

.mini-path-label {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.mini-path-value {
  font-family: var(--serif);
  font-size: 26px;
  font-variant-numeric: tabular-nums lining-nums;
}

.mini-path li:last-child .mini-path-value {
  color: var(--found);
}

.mini-sync {
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(24px, 1fr) minmax(0, auto);
  align-items: center;
  /* With large text the words break inside the boxes, so the card keeps to the screen. */
  overflow-wrap: anywhere;
}

.sync-from {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px 14px;
  font-weight: 600;
  font-size: 14px;
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: 10px;
}

.sync-mark {
  color: var(--accent);
}

.sync-sub {
  font-weight: 400;
  font-size: 12px;
  color: var(--text-dim);
}

.sync-lines {
  width: 100%;
  height: 70px;
  overflow: visible;
}

.sync-line {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.6;
  stroke-dasharray: 3 4;
  vector-effect: non-scaling-stroke;
}

.js-motion .sync-line:not(.sync-line-off) {
  animation: sync-flow 1.2s linear infinite;
}

@keyframes sync-flow {
  to { stroke-dashoffset: -14; }
}

.sync-line-off {
  stroke: var(--line-strong);
}

.sync-to {
  display: grid;
  gap: 8px;
}

.sync-card {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: min(128px, 100%);
  padding: 9px 12px;
  font-size: 14px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 10px;
}

.sync-ok {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  font-weight: 600;
  color: var(--chip-ok-fg);
}

.sync-card.is-off strong {
  color: var(--text-dim);
}

/* ---------------- split rows ---------------- */

.split {
  display: grid;
  grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr);
  gap: 64px;
  align-items: center;
}

.split-flip {
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
}

.split-copy .section-title {
  font-size: 42px;
}

.split-lead {
  margin-top: 16px;
  font-size: 17px;
  color: var(--text-dim);
}

.checks-lg {
  margin: 22px 0 22px;
  font-size: 16px;
}

.checks-lg li {
  margin-bottom: 10px;
}

/* ---------------- ad sets table ---------------- */

.ads .st-window-body {
  padding: 4px 0 0;
}

.ads-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}

.ads-table th,
.ads-table td {
  padding: 12px 18px;
  text-align: left;
  border-bottom: 1px solid var(--line);
}

.ads-table thead th {
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.ads-table thead th.ads-ours {
  color: var(--accent);
}

.ads-table tbody th,
.ads-table tfoot th {
  font-weight: 500;
}

.ads-table tfoot th,
.ads-table tfoot td {
  border-bottom: none;
  font-weight: 600;
}

.ads-table .num {
  text-align: right;
  white-space: nowrap;
}

.ads-meta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

.ads-meta .cross-svg {
  color: var(--lost);
}

.ads-pill {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: 5px;
  min-width: 64px;
  padding: 3px 10px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 7px;
}

.ads-pill-strong {
  color: var(--accent-ink);
  background: var(--accent);
}

/* ---------------- estimator ---------------- */

.estimator {
  margin-top: 64px;
  padding: 36px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 18px;
  box-shadow: var(--shadow-card);
}

.estimator-title {
  font-size: 30px;
  line-height: 1.15;
}

.estimator-sub {
  margin-top: 8px;
  color: var(--text-dim);
  max-width: 60ch;
}

.estimator-grid {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: 32px;
  margin-top: 26px;
}

.estimator-inputs {
  display: grid;
  gap: 14px;
  align-content: start;
}

.estimator-inputs .field {
  margin: 0;
}

.estimator-out {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  align-content: start;
}

.estimator-out .bignum {
  padding: 18px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 12px;
}

.estimator-out .bignum-value {
  font-size: 48px;
}

.estimator-formula {
  grid-column: 1 / -1;
  padding: 12px 14px;
  font-size: 13px;
  color: var(--text-dim);
  background: var(--bg-tint);
  border: 1px dashed var(--line-strong);
  border-radius: 10px;
}

/* ---------------- pick what you run ---------------- */

.pick-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.pick-card {
  position: relative;
  display: grid;
  grid-template-columns: 58px minmax(0, 1fr);
  min-height: 100%;
  color: inherit;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 14px;
  overflow: hidden;
  transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}

.pick-card:hover {
  text-decoration: none;
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--accent) 40%, var(--line));
  box-shadow: var(--shadow-panel);
}

.pick-no {
  grid-row: 1 / span 2;
  padding: 18px 0 0;
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--accent);
  text-align: center;
  background: color-mix(in srgb, var(--accent) 6%, var(--bg-raised));
  border-right: 1px solid var(--line);
}

.pick-icon {
  display: none;
}

.pick-text {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 18px 120px 22px 20px;
}

.pick-title {
  font-size: 23px;
  line-height: 1.2;
}

.pick-line {
  color: var(--text-dim);
}

.pick-see {
  margin-top: 6px;
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--text-faint);
}

.pick-go {
  position: absolute;
  top: 16px;
  right: 16px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--text);
  background: var(--bg-tint);
  border: 1px solid var(--line);
  border-radius: 7px;
}

.pick-go svg {
  width: 13px;
  height: 13px;
  transition: transform 0.15s ease;
}

.pick-card:hover .pick-go svg {
  transform: translateX(2px);
}

/* ---------------- agencies: the sites window ---------------- */

.sites .st-window-body {
  padding: 0;
}

.sites-filter {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--line);
}

.sites-filter-label {
  margin-right: 4px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.sites-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.sites-row {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr) auto 76px 88px;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--line);
}

.sites-fav {
  display: inline-grid;
  place-items: center;
  width: 30px;
  height: 30px;
  font-weight: 700;
  font-size: 13px;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 8px;
}

.sites-name {
  display: flex;
  flex-direction: column;
  min-width: 0;
  line-height: 1.3;
  font-size: 14px;
}

.sites-name span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--text-faint);
}

.sites-num {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.3;
  font-size: 14px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.sites-sub {
  font-weight: 400;
  font-size: 11px;
  color: var(--text-faint);
}

.sites-share {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 12px 16px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--text-dim);
}

.sites-share .pill {
  margin-left: auto;
  font-family: var(--sans);
}

/* ---------------- private by default ---------------- */

.mode-grid,
.usecase-points {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
  max-width: 960px;
  margin-inline: auto;
}

.usecase-points {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  max-width: none;
}

.mode-card {
  padding: 30px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 18px;
  box-shadow: var(--shadow-card);
}

.mode-tag {
  display: inline-block;
  margin-bottom: 12px;
  padding: 2px 9px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-dim);
  background: var(--bg-tint);
  border: 1px solid var(--line);
  border-radius: 999px;
}

.mode-tag-accent {
  color: var(--accent);
  background: var(--accent-soft);
  border-color: transparent;
}

.mode-title {
  font-size: 26px;
  margin-bottom: 14px;
}

.usecase-line {
  color: var(--text-dim);
}

/* ---------------- plans, restyled ---------------- */

.marketing .plan-card {
  position: relative;
  background: var(--bg-raised);
  border-radius: 16px;
  box-shadow: var(--shadow-card);
}

.marketing .plan-card.highlight {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent), var(--shadow-panel);
}

.marketing .plan-name {
  font-size: 24px;
}

.marketing .plan-amount {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 44px;
}

/* Two lines held for every tagline and billing line, so prices and feature lists start level across cards side by side. */
.marketing .plan-tagline {
  line-height: 1.6;
}

@media (min-width: 641px) {
  .marketing .plan-tagline,
  .marketing .pricing-cards .plan-billing {
    line-height: 1.6;
    min-height: 3.2em;
  }
}

/* /pricing cards: name in small caps, the price, the rows that differ
   between plans (a check or a muted cross), one button. Free sits under
   them as one quiet row, Custom as the wide card. */
.marketing .pricing-cards {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  max-width: 1040px;
  margin-inline: auto;
}

.marketing .pricing-cards .plan-name {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 650;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.marketing .pricing-cards .plan-price {
  margin-top: 10px;
}

.marketing .pricing-cards .plan-amount {
  font-size: 48px;
  line-height: 1.05;
}

.marketing .pricing-cards .plan-period {
  font-size: 15px;
}

/* Every billing line here is one short line: nothing to hold level. */
@media (min-width: 641px) {
  .marketing .pricing-cards .plan-billing {
    min-height: 0;
  }
}

.plan-checks {
  flex: 1 1 auto;
  margin: 20px 0 24px;
  padding: 18px 0 0;
  list-style: none;
  font-size: 14.5px;
  border-top: 1px solid var(--line);
}

.plan-checks li {
  position: relative;
  padding-left: 26px;
  margin-bottom: 10px;
  line-height: 1.45;
}

.plan-checks li::before {
  content: '';
  position: absolute;
  left: 4px;
  top: 0.42em;
  width: 9px;
  height: 5px;
  border-left: 2px solid var(--chip-ok-fg);
  border-bottom: 2px solid var(--chip-ok-fg);
  transform: rotate(-45deg);
}

.plan-checks li.is-off {
  color: var(--text-faint);
}

.plan-checks li.is-off::before,
.plan-checks li.is-off::after {
  content: '';
  top: 0.68em;
  left: 3px;
  width: 11px;
  height: 0;
  border: 0;
  border-top: 1.5px solid currentColor;
  transform: rotate(45deg);
}

.plan-checks li.is-off::after {
  position: absolute;
  transform: rotate(-45deg);
}

.plan-checks a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--line-strong);
  text-underline-offset: 3px;
}

.plan-checks a:hover {
  color: var(--accent);
  text-decoration-color: currentColor;
}

.plan-term summary {
  display: inline;
  cursor: pointer;
  list-style: none;
  text-decoration: underline dashed;
  text-decoration-color: var(--text-faint);
  text-underline-offset: 4px;
  border-radius: 4px;
}

.plan-term summary::-webkit-details-marker {
  display: none;
}

.plan-term summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.plan-term p {
  margin: 6px 0 2px;
  padding: 8px 10px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-dim);
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: 8px;
}

.plan-checks li.is-off .plan-term p {
  color: var(--text-dim);
}

.plan-due {
  margin: 10px 0 0;
  font-size: 12.5px;
  line-height: 1.5;
  text-align: center;
  color: var(--text-faint);
}

/* Free: the same card language, quieter than the paid plans (panel, no
   shadow, a smaller price), in a row like Custom with room for its lines. */
.marketing .plan-free {
  display: grid;
  grid-template-columns: minmax(140px, 0.75fr) minmax(0, 2.5fr) minmax(200px, 0.9fr);
  align-items: center;
  gap: 16px 32px;
  max-width: 1040px;
  margin: 16px auto 0;
  padding: 22px 24px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  box-shadow: none;
}

.marketing .plan-free .plan-name {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 650;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.marketing .plan-free .plan-price {
  margin-top: 6px;
}

.marketing .plan-free .plan-amount {
  font-size: 36px;
  line-height: 1.05;
}

.marketing .plan-free .plan-period {
  font-size: 14px;
}

/* What Free has down the first column, what it lacks at the end. Two
   columns where each line fits whole; one below that. */
.plan-free-checks {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: repeat(3, auto);
  grid-auto-flow: column;
  gap: 8px 24px;
  margin: 0;
  padding: 0;
  font-size: 14px;
  border-top: 0;
}

.plan-free-checks li {
  margin: 0;
}

@media (max-width: 1099px) {
  .plan-free-checks {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
    grid-auto-flow: row;
  }
}

.plan-free-action {
  display: flex;
  flex-direction: column;
  align-items: stretch;
}

.plan-free-nudge {
  margin: 10px 0 0;
  font-size: 12.5px;
  line-height: 1.5;
  text-align: center;
  color: var(--text-faint);
}

.plan-free-nudge a {
  color: var(--text-dim);
  text-decoration: underline;
  text-decoration-color: var(--line-strong);
  text-underline-offset: 3px;
}

.plan-free-nudge a:hover {
  color: var(--accent);
  text-decoration-color: currentColor;
}

.marketing .pricing-cards ~ .plan-wide {
  max-width: 1040px;
  margin-inline: auto;
}

@media (max-width: 1099px) {
  .marketing .pricing-cards {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    max-width: 1040px;
  }
}

@media (max-width: 900px) {
  .marketing .pricing-cards {
    grid-template-columns: minmax(0, 1fr);
    max-width: 480px;
  }

  .marketing .plan-free {
    grid-template-columns: minmax(0, 1fr);
    align-items: stretch;
    gap: 0;
    max-width: 480px;
  }

  .plan-free-checks {
    margin-top: 18px;
    padding-top: 16px;
    border-top: 1px solid var(--line);
  }

  .plan-free-action {
    margin-top: 12px;
  }
}

/* ---------------- plan finder ---------------- */

.finder .st-window-body {
  padding: 6px 22px 22px;
}

.finder-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(150px, 0.8fr);
  align-items: center;
  gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid var(--line);
}

.finder-label {
  font-size: 14.5px;
}

.finder-check {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  font-size: 14.5px;
  border-bottom: 1px solid var(--line);
  cursor: pointer;
}

.finder-check input {
  width: 18px;
  height: 18px;
  accent-color: var(--accent);
}

.finder-result {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
  margin-top: 18px;
}

.finder-result > div:first-child {
  display: flex;
  flex-direction: column;
}

.finder-result-label {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.finder-result-name {
  font-family: var(--serif);
  font-size: 34px;
  line-height: 1.1;
}

.finder-result-price {
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-family: var(--serif);
  font-size: 34px;
  color: var(--accent);
}

.finder-result-per {
  font-family: var(--sans);
  font-size: 13.5px;
  color: var(--text-dim);
}

/* The finder's "See Studio above" lands with the card's flag clear of the header. */
.marketing [data-plan-card] {
  scroll-margin-top: 28px;
}

.finder-stage {
  max-width: 560px;
  margin-inline: auto;
}

.finder-see {
  display: flex;
  justify-content: center;
  margin-top: 14px;
  font-size: 14px;
}

.finder-note {
  margin: 6px 0 16px;
  font-size: 13.5px;
  color: var(--text-dim);
}

.plan-card.is-match {
  animation: plan-match 0.5s ease;
}

@keyframes plan-match {
  0% { transform: translateY(0); }
  40% { transform: translateY(-4px); }
  100% { transform: translateY(0); }
}

/* ---------------- promise band ---------------- */

.promise {
  padding-block: 96px;
}

.promise-card {
  max-width: 880px;
  margin-inline: auto;
  padding: 52px 40px 44px;
  text-align: center;
  background:
    radial-gradient(80% 60% at 50% 0%, var(--accent-soft), transparent 70%),
    var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 22px;
  box-shadow: var(--shadow-card);
}

.promise-card .frame-icon {
  margin: 0 auto 18px;
}

.promise-title {
  font-size: 46px;
  line-height: 1.1;
}

.promise-line {
  max-width: 52ch;
  margin: 16px auto 0;
  font-size: 17px;
  color: var(--text-dim);
}

.promise-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-top: 28px;
}

.promise-facts {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px 0;
  margin: 22px 0 0;
  padding: 0;
  list-style: none;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.04em;
  color: var(--text-faint);
}

.promise-facts li + li::before {
  content: '·';
  margin: 0 10px;
}

/* ---------------- FAQ, restyled ---------------- */

.marketing .faq {
  max-width: 820px;
  padding: 6px 28px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 18px;
  box-shadow: var(--shadow-card);
}

.marketing .faq-q {
  min-height: 64px;
  padding: 16px 0;
  font-size: 19px;
  background: transparent;
}

.marketing .faq-q:hover {
  background: transparent;
  color: var(--accent);
}

.marketing .faq-item[open] > .faq-q {
  background: transparent;
}

.marketing .faq-chevron {
  width: 26px;
  height: 26px;
  padding: 5px;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 50%;
}

.marketing .faq-a {
  padding: 0 0 20px;
  background: transparent;
}

.marketing .faq-a p {
  font-size: 15.5px;
}

/* ---------------- closing band ---------------- */

.marketing .closing {
  padding-block: 104px;
  background:
    radial-gradient(70% 90% at 50% 100%, color-mix(in srgb, var(--accent) 5%, transparent), transparent 72%),
    var(--bg-tint);
  border-top: 1px solid var(--line);
}

.marketing .closing-title {
  font-size: 48px;
  line-height: 1.1;
}

.marketing .closing-line {
  font-size: 17px;
}

/* ---------------- use case pages ---------------- */

.usecase-hero {
  padding-block: 88px 96px;
}

.usecase-hero-inner {
  max-width: 820px;
  text-align: center;
}

.usecase-hero .hero-lead {
  margin-inline: auto;
}

.usecase-others {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
}

/* ---------------- setup call ---------------- */

.call-hero {
  padding-block: 72px 96px;
}

.call-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 56px;
  align-items: start;
}

.call-list {
  display: grid;
  gap: 18px;
  margin: 32px 0 30px;
  padding: 0;
  list-style: none;
}

.call-list li {
  display: flex;
  align-items: center;
  gap: 16px;
  color: var(--text-dim);
}

.call-list .frame-icon {
  flex: 0 0 auto;
  margin: 0;
  width: 46px;
  height: 35px;
}

.call-list strong {
  color: var(--text);
}

.call-card {
  padding: 30px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 18px;
  box-shadow: var(--shadow-panel);
}

/* Client sites and traffic: asked only for a Custom plan. Without :has() they always show. */
.call-size {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px 14px; /* the form's own 16px rhythm when stacked */
}

@supports selector(:has(*)) {
  .form:not(:has(#f-plan option[value='custom']:checked)) .call-size {
    display: none;
  }
}

@media (max-width: 480px) {
  .call-size {
    grid-template-columns: minmax(0, 1fr);
  }
}

.call-platforms {
  margin: 0;
  padding: 0;
  border: 0;
}

.call-checks {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 18px;
}

/* The honeypot: off screen for people, there for bots. */
.hp {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.call-thanks {
  padding-block: 96px;
}

/* ---------------- reveal on scroll ---------------- */

.js-motion .reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.5s ease, transform 0.5s ease;
}

.js-motion .reveal.is-in {
  opacity: 1;
  transform: none;
}

/* ---------------- responsive ---------------- */

@media (max-width: 1100px) {
  .marketing .hero-title {
    font-size: 46px;
  }
  .split,
  .split-flip {
    gap: 40px;
  }
}

@media (max-width: 960px) {
  .marketing .hero-grid,
  .gap-grid,
  .split,
  .split-flip,
  .call-grid,
  .estimator-grid {
    grid-template-columns: minmax(0, 1fr);
  }
  .split-flip .split-visual {
    order: 2;
  }
  .split .split-copy {
    order: -1;
  }
  .wsec {
    padding-block: 80px;
  }
  .marketing .section-title {
    font-size: 38px;
  }
  .usecase-points {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 720px) {
  .home-hero,
  .pricing-hero,
  .call-hero {
    padding-block: 32px 64px;
  }
  .marketing .hero-title {
    font-size: clamp(30px, 9.4vw, 40px);
    line-height: 1.08;
  }
  .marketing .page-title {
    font-size: 36px;
  }
  .marketing .hero-lead {
    font-size: 16.5px;
  }
  .cta-tray {
    display: flex;
    flex-direction: column;
    width: 100%;
  }
  .cta-tray .btn {
    width: 100%;
  }
  .wsec {
    padding-block: 64px;
  }
  .wsec-head {
    margin-bottom: 36px;
  }
  .marketing .section-title,
  .split-copy .section-title {
    font-size: 32px;
  }
  .wsec-head-card .section-title {
    font-size: 28px;
  }
  .marketing .section-sub {
    font-size: 16px;
  }
  .blue-panel {
    margin-inline: calc(var(--gutter) * -1 + 8px);
    padding: 16px 12px;
    border-radius: 18px;
  }
  .wsec-head-card {
    padding: 20px 18px 22px;
  }
  .step-grid,
  .pick-grid,
  .mode-grid {
    grid-template-columns: minmax(0, 1fr);
  }
  .step-card,
  .mode-card {
    padding: 22px 20px;
  }
  .step-card-title {
    font-size: 24px;
  }
  .step-card-visual {
    padding: 12px;
  }
  .gap-card {
    padding: 26px 22px;
  }
  .gap-statement {
    font-size: 32px;
  }
  .st-window-body {
    padding: 14px;
  }
  .bignum-value {
    font-size: 36px;
  }
  .estimator {
    margin-top: 44px;
    padding: 22px 18px;
  }
  .estimator-title {
    font-size: 25px;
  }
  .estimator-out .bignum {
    padding: 14px;
  }
  .estimator-out .bignum-value {
    font-size: 34px;
  }
  .pick-text {
    padding: 18px 16px 12px;
  }
  .pick-card {
    grid-template-columns: 44px minmax(0, 1fr);
  }
  .pick-go {
    position: static;
    grid-column: 2;
    justify-self: start;
    margin: 0 16px 18px;
  }
  .sites-row {
    grid-template-columns: 30px minmax(0, 1fr) 80px;
  }
  .sites-row .chip-mini,
  .sites-row .sites-visitors {
    display: none;
  }
  .promise {
    padding-block: 64px;
  }
  .promise-card {
    padding: 36px 20px 30px;
  }
  .promise-title {
    font-size: 32px;
  }
  .promise-actions .btn {
    flex: 1 1 200px;
  }
  .marketing .faq {
    padding: 2px 18px;
  }
  .marketing .faq-q {
    font-size: 17px;
  }
  .marketing .closing {
    padding-block: 72px;
  }
  .marketing .closing-title {
    font-size: 34px;
  }
  .ads-table th,
  .ads-table td {
    padding: 11px 12px;
  }
  .ads-table {
    font-size: 13.5px;
  }
  .ads-pill {
    min-width: 0;
  }
  .ads-pill .tick-svg {
    display: none;
  }
  .film-row {
    grid-template-columns: 66px minmax(0, 1fr) auto;
  }
  .film-time {
    display: none;
  }
  .film-steps {
    font-size: 9.5px;
    letter-spacing: 0.04em;
    padding-inline: 10px;
  }
  .film-step {
    gap: 4px;
  }
  .film-step b {
    width: 16px;
    height: 16px;
  }
  .film-source {
    margin-inline: 12px;
  }
  .film-link {
    margin-left: 0;
  }
  .film-feed {
    margin-inline: 12px;
  }
  .film-foot > * {
    padding: 14px;
  }
  .film-foot .bignum-value {
    font-size: 32px;
  }
  .finder .st-window-body {
    padding: 4px 16px 18px;
  }
  .finder-row {
    grid-template-columns: minmax(0, 1fr);
    gap: 6px;
  }
  .call-card {
    padding: 20px 16px;
  }
  .setup-band {
    padding: 16px;
  }
  .strip {
    padding-block: 48px 56px;
  }
  .journey-row {
    grid-template-columns: 12px 50px minmax(0, 1fr);
    font-size: 14px;
  }
  .journey-totals .bignum-value {
    font-size: 30px;
  }
}

@media (max-width: 420px) {
  .film-step:nth-child(4) {
    letter-spacing: 0;
  }
  .mini-path {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .mini-path li:nth-child(3) {
    border-left: none;
  }
  .mini-path li:nth-child(n + 3) {
    border-top: 1px solid var(--line);
  }
  .mini-sync {
    grid-template-columns: auto minmax(24px, 1fr) auto;
  }
  .sync-card {
    min-width: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .js-motion .reveal,
  .js-motion .rotator-word {
    opacity: 1;
    transform: none;
  }
}

/* ---------------- footer, four columns ---------------- */

.footer-promise {
  margin-top: 12px;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.04em;
  color: var(--accent);
}


/* ================================================================
   Phase 2 pages: /how-it-works, /for/*, /platforms/*, /walkthroughs,
   /demo and the Product menu. Built from the same tokens and pieces
   as the home page; only what those pages add lives here.
   ================================================================ */

.section-actions {
  flex-wrap: wrap;
  gap: 4px 28px;
}

/* ---------------- page heroes (two lines, like home) ---------------- */

.page-hero {
  padding-block: 72px 96px;
}

.page-hero .hero-try {
  margin-top: 12px;
}

.page-hero .hero-try .text-link {
  min-height: 32px;
}

/* ---------------- card grids ---------------- */

.card-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px;
  margin: 0;
  padding: 0;
  list-style: none;
}

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

.info-card {
  display: flex;
  flex-direction: column;
}

.info-card .mode-tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  align-self: flex-start;
}

.info-card-lost .mode-tag {
  color: var(--lost);
}

.info-card-lost .cross-svg {
  color: var(--lost);
}

.info-card .mode-title {
  font-size: 23px;
  margin-bottom: 8px;
}

.info-card-visual {
  margin-top: auto;
  padding-top: 20px;
}

.mini-num {
  padding: 14px 16px;
  background: var(--bg-tint);
  border: 1px solid var(--line);
  border-radius: 12px;
}

.mini-num .bignum-value {
  font-size: 34px;
}

.problem-nums {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  max-width: 980px;
  margin-inline: auto;
}

.problem-nums .mini-num {
  padding: 22px 22px 20px;
  background: var(--bg-raised);
  box-shadow: var(--shadow-card);
}

.problem-nums .bignum-value {
  font-size: 44px;
}

.problem-nums + .window-caption a {
  color: inherit;
  text-decoration: underline;
}

/* ---------------- numbered set up steps ---------------- */

.step-rows {
  display: grid;
  gap: 28px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.step-row {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: 48px;
  align-items: center;
  padding: 32px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 18px;
  box-shadow: var(--shadow-card);
}

.step-row-flip {
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
}

.step-row-flip .step-row-copy {
  order: 2;
}

.step-row-title {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 30px;
  line-height: 1.15;
  letter-spacing: -0.015em;
  margin-bottom: 16px;
}

.step-row-visual {
  min-width: 0;
}

.step-row-visual .st-window {
  box-shadow: var(--shadow-card);
}

/* ---------------- link chips ----------------
   The one look for a chip that is a link (blocks.ts linkChip): a bordered
   pill with a small arrow that moves on hover, a lift and an accent border.
   Static words (chipRow, pillRow) have no border and no hover, so the two
   never get mixed up. */

.link-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.link-chips-center {
  justify-content: center;
}

.link-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 38px;
  padding: 5px 10px 5px 13px;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.2;
  color: var(--text);
  text-decoration: none;
  background: var(--bg-raised);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  box-shadow: 0 1px 0 color-mix(in srgb, var(--line-strong) 45%, transparent);
  transition: border-color 0.15s ease, color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}

.link-chip:hover {
  color: var(--accent);
  text-decoration: none;
  border-color: var(--accent);
  box-shadow: var(--shadow-card);
  transform: translateY(-1px);
}

.link-chip:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.link-chip-arrow {
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
  color: var(--accent);
  transition: transform 0.15s ease;
}

.link-chip:hover .link-chip-arrow {
  transform: translateX(2px);
}

@media (max-width: 720px) {
  /* A full 44px tap target on phones, for both sizes. */
  .link-chip {
    min-height: 44px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .link-chip,
  .link-chip-arrow {
    transition: none;
  }
  .link-chip:hover,
  .link-chip:hover .link-chip-arrow {
    transform: none;
  }
}

/* The install row takes the band's full width, so it stays on one line on a desk. */
.setup-band {
  max-width: none;
}

/* Static words and facts: no border, no shadow, no hover. */
.chip-row li {
  min-height: 30px;
  padding: 3px 11px;
  font-size: 13.5px;
  color: var(--text-dim);
  background: var(--bg-tint);
  border: none;
  border-radius: 8px;
}

.pill-plain {
  background: transparent;
  border: none;
  padding-inline: 4px 8px;
}

/* ---------------- replicas of our own screens ---------------- */

.rep-title {
  margin-bottom: 12px;
  font-weight: 600;
  font-size: 15px;
}

.rep-title-flat {
  margin: 0;
}

.rep-label {
  display: block;
  margin-bottom: 6px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-dim);
}

.rep-label-gap {
  margin-top: 14px;
}

.rep-field {
  margin-bottom: 12px;
}

.rep-input {
  display: block;
  overflow: hidden;
  min-height: 38px;
  padding: 8px 11px;
  font-size: 13.5px;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--text);
  background: var(--bg-input, var(--bg-raised));
  border: 1px solid var(--line-strong);
  border-radius: 8px;
}

.rep-mono,
.rep-code code,
.rep-tpl-code {
  font-family: var(--mono);
  font-size: 12px;
}

.rep-hint {
  display: block;
  margin-top: 4px;
  font-size: 12px;
  color: var(--text-faint);
}

.rep-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.rep-chips li {
  padding: 3px 10px;
  font-size: 12.5px;
  color: var(--text-dim);
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 999px;
}

.rep-chips li.is-on {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--accent);
}

.rep-groups {
  display: grid;
  gap: 8px;
}

.rep-group {
  display: grid;
  grid-template-columns: 70px minmax(0, 1fr);
  align-items: start;
  gap: 8px;
}

.rep-group-name {
  padding-top: 4px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.rep-short {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
  margin-top: 16px;
  padding-top: 14px;
  font-family: var(--mono);
  font-size: 13.5px;
  border-top: 1px solid var(--line);
}

.rep-short svg {
  color: var(--accent);
}

.rep-short .rep-btn {
  margin-left: auto;
  font-family: var(--sans, inherit);
}

.rep-short-flat {
  margin: 0;
  padding: 0;
  border: 0;
}

.rep-dest {
  margin: 4px 0 14px;
}

.rep-btn {
  display: inline-flex;
  align-items: center;
  min-height: 30px;
  padding: 4px 12px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  background: var(--bg-raised);
  border: 1px solid var(--line-strong);
  border-radius: 8px;
}

.rep-btn-primary {
  margin-top: 4px;
  color: var(--cta-ink);
  background: var(--cta);
  border-color: var(--cta);
}

.rep-btn-quiet {
  border-color: transparent;
  color: var(--text-dim);
}

.rep-row {
  display: flex;
  gap: 8px;
  margin-top: 12px;
}

.rep-code {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 14px 0 10px;
  padding: 10px 10px 10px 12px;
  background: var(--bg-tint);
  border: 1px solid var(--line);
  border-radius: 8px;
}

.rep-code code {
  flex: 1 1 auto;
  min-width: 0;
  word-break: break-all;
}

.rep-ok {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 600;
  color: var(--chip-ok-fg);
}

.rep-tpl-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 10px;
}

.rep-tpl-title {
  font-weight: 600;
  font-size: 14px;
}

.rep-tpl-code {
  display: block;
  padding: 10px 12px;
  line-height: 1.55;
  word-break: break-all;
  background: var(--bg-tint);
  border: 1px solid var(--line);
  border-radius: 8px;
}

.rep-steps {
  margin: 12px 0 0;
  padding-left: 20px;
  font-size: 13px;
  color: var(--text-dim);
}

.rep-steps li + li {
  margin-top: 4px;
}

.rep-kinds {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 12px;
}

.rep-kind {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 12px;
  font-size: 12px;
  color: var(--text-faint);
  border: 1px solid var(--line);
  border-radius: 10px;
}

.rep-kind strong {
  font-size: 13.5px;
  color: var(--text);
}

.rep-kind.is-on {
  color: var(--text-dim);
  background: var(--accent-soft);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
}

.rep-two {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

.rep-pill-ok {
  display: inline-flex;
  align-items: center;
  padding: 2px 10px;
  font-size: 12px;
  font-weight: 600;
  color: var(--chip-ok-fg);
  background: var(--chip-ok-bg);
  border: 1px solid var(--chip-ok-line);
  border-radius: 999px;
  white-space: nowrap;
}

.rep-goals {
  display: grid;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.rep-goals li {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 10px;
}

.rep-check {
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  border: 1.5px solid var(--line-strong);
  border-radius: 5px;
}

.rep-check.is-on {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--accent);
}

.rep-check .tick-svg {
  width: 12px;
  height: 12px;
}

.rep-goal-name {
  display: flex;
  flex-direction: column;
  min-width: 0;
  font-size: 13px;
  line-height: 1.3;
}

.rep-goal-name code {
  font-size: 11.5px;
  color: var(--text-faint);
}

.rep-select {
  padding: 4px 10px;
  font-size: 12.5px;
  border: 1px solid var(--line-strong);
  border-radius: 8px;
}

.rep-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: 0 0 10px;
  padding: 0;
  list-style: none;
}

.rep-tabs li {
  padding: 3px 9px;
  font-size: 12px;
  color: var(--text-dim);
  border-radius: 7px;
}

.rep-tabs li.is-on {
  color: var(--text);
  font-weight: 600;
  background: var(--bg-active);
}

.rep-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13.5px;
}

.rep-table th,
.rep-table td {
  padding: 9px 8px;
  text-align: left;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}

.rep-table thead th {
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.rep-table tbody th {
  font-weight: 500;
}

.rep-table .num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.rep-table tr:last-child th,
.rep-table tr:last-child td {
  border-bottom: none;
}

.rep-sub {
  display: block;
  font-size: 11.5px;
  color: var(--text-faint);
}

/* The bar behind each name, as in the dashboard. */
.rep-bars tbody th span {
  position: relative;
  display: block;
  padding: 2px 6px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--mono);
  font-size: 12.5px;
  border-radius: 5px;
  background: linear-gradient(90deg, var(--accent-soft) var(--w), transparent var(--w));
}

.rep-bars tr.is-hit tbody th span,
.rep-bars tr.is-hit th span {
  background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 22%, transparent) var(--w), transparent var(--w));
  font-weight: 700;
}

.rep-num-hit {
  font-weight: 700;
  color: var(--found);
}

.rep-bars tr.is-hit td {
  font-weight: 700;
}

.rep-filter {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 2px 10px;
  font-size: 12px;
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 999px;
}

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

.rep-sms-from,
.rep-mail-from {
  margin-bottom: 12px;
  font-size: 13px;
  font-weight: 600;
  text-align: center;
  color: var(--text-dim);
}

.rep-bubble {
  max-width: 88%;
  padding: 10px 14px;
  font-size: 15px;
  line-height: 1.4;
  background: var(--bg-tint);
  border: 1px solid var(--line);
  border-radius: 18px 18px 18px 6px;
}

.rep-bubble-link {
  color: var(--accent);
  text-decoration: underline;
  word-break: break-all;
}

.rep-sms-meta {
  margin-top: 6px;
  font-size: 11.5px;
  color: var(--text-faint);
}

.rep-mail-from {
  display: flex;
  flex-direction: column;
  text-align: left;
  color: var(--text);
}

.rep-mail-from span {
  font-weight: 400;
  color: var(--text-dim);
}

.rep-mail-line {
  font-size: 14px;
  color: var(--text-dim);
}

.rep-mail-btn {
  display: inline-block;
  margin-top: 14px;
  padding: 9px 16px;
  font-size: 14px;
  font-weight: 600;
  color: var(--cta-ink);
  background: var(--cta);
  border-radius: 8px;
}

.rep-mail-href {
  margin-top: 8px;
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--text-faint);
  word-break: break-all;
}

.rep-mail-brand {
  margin-bottom: 12px;
  font-weight: 700;
  font-size: 16px;
}

.rep-mail-site {
  margin-bottom: 12px;
  font-family: var(--serif);
  font-size: 22px;
}

.rep-kpis {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.rep-kpis > span {
  display: flex;
  flex-direction: column;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
}

.rep-kpis strong {
  font-size: 22px;
}

.rep-up {
  font-style: normal;
  font-size: 12px;
  font-weight: 600;
  color: var(--chip-ok-fg);
}

.rep-list {
  margin: 0 0 10px;
  padding: 0;
  list-style: none;
  font-size: 13.5px;
}

.rep-list li {
  display: flex;
  justify-content: space-between;
  padding: 6px 0;
  border-bottom: 1px solid var(--line);
}

/* ---------------- the template, plan fit, status ---------------- */

.tpl-card {
  max-width: 820px;
  margin-inline: auto;
  padding: 26px 28px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 18px;
  box-shadow: var(--shadow-card);
}

.tpl-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}

.tpl-card-label {
  font-size: 11.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.tpl-code {
  display: block;
  padding: 14px 16px;
  font-size: 13.5px;
  line-height: 1.6;
  word-break: break-all;
  background: var(--bg-tint);
  border: 1px solid var(--line);
  border-radius: 10px;
}

.tpl-steps {
  margin: 16px 0 0;
  padding-left: 22px;
  color: var(--text-dim);
}

.tpl-steps li + li {
  margin-top: 6px;
}

.tpl-note {
  margin-top: 14px;
  font-size: 14px;
  color: var(--text-dim);
}

.status-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  align-items: start;
  gap: 20px;
  max-width: 960px;
  margin-inline: auto;
}

.status-later {
  margin: 0;
  padding-left: 18px;
  color: var(--text-dim);
}

.status-later li + li {
  margin-top: 8px;
}

.fit-card {
  max-width: 900px;
  margin-inline: auto;
  padding: 28px 32px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: var(--shadow-card);
}

.fit-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px 20px;
}

.fit-head .plan-name {
  font-size: 30px;
}

.fit-head .plan-amount {
  font-family: var(--serif);
  font-size: 40px;
}

.fit-head .plan-period {
  margin-left: 6px;
  color: var(--text-dim);
}

.fit-why {
  margin-top: 6px;
  font-size: 16px;
  color: var(--text-dim);
}

.fit-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px 24px;
  margin: 18px 0 22px;
}

.fit-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.meta-sync {
  max-width: 520px;
  margin: 32px auto 0;
  padding: 20px;
  background: var(--bg-tint);
  border: 1px solid var(--line);
  border-radius: 14px;
}

.meta-sync-big {
  margin: 0 0 22px;
}

.journey-solo {
  max-width: 640px;
  margin-inline: auto;
}

.credit-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
  max-width: 900px;
  margin-inline: auto;
}

.credit-winner {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
  font-family: var(--serif);
  font-size: 26px;
  line-height: 1.2;
}

.credit-winner .tick-svg {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  color: var(--accent);
}

/* The walkthrough teaser under a /for page's steps. */
.wt-teaser {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 20px;
  max-width: 900px;
  margin: 28px auto 0;
  padding: 16px 22px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 14px;
}

.wt-teaser-label {
  font-size: 11.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.wt-teaser-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  font-family: var(--serif);
  font-size: 20px;
}

/* ---------------- walkthroughs ---------------- */

.wt-hero {
  padding-block: 40px 88px;
}

.wt-hero-inner {
  max-width: 900px;
}

.wt-head {
  margin: 18px 0 14px;
  font-size: 11.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
}

.wt-title {
  font-size: 56px;
}

.wt-kicker {
  color: var(--text-dim);
}

.stat-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 28px 0 0;
  padding: 0;
  list-style: none;
}

.stat-pills li {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 128px;
  padding: 10px 16px 12px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 14px;
}

.stat-pill-label {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.stat-pill-value {
  font-family: var(--serif);
  font-size: 28px;
  font-variant-numeric: tabular-nums lining-nums;
}

.stat-pills li:last-child .stat-pill-value {
  color: var(--found);
}

.wt-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 30px;
}

.wt-note {
  margin-top: 14px;
  font-size: 13.5px;
  color: var(--text-faint);
}

.learned {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 0.7fr);
  gap: 24px;
  max-width: 1000px;
  margin-inline: auto;
}

.learned-list {
  margin: 0;
  padding: 26px 28px 26px 52px;
  font-size: 17px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 18px;
  box-shadow: var(--shadow-card);
}

.learned-list li + li {
  margin-top: 12px;
}

.learned-list li::marker {
  font-family: var(--mono);
  color: var(--accent);
}

.learned-try {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 16px;
  padding: 26px;
  background: var(--accent-soft);
  border-radius: 18px;
}

.learned-try p {
  font-size: 15.5px;
}

.wt-cards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
}

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

.wt-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 26px;
  color: var(--text);
  text-decoration: none;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 18px;
  box-shadow: var(--shadow-card);
  transition: border-color 0.15s ease, transform 0.15s ease;
}

.wt-card:hover {
  text-decoration: none;
  border-color: var(--accent);
}

.wt-card .wt-head {
  margin: 0;
}

.wt-card-title {
  font-family: var(--serif);
  font-size: 26px;
  line-height: 1.15;
}

.wt-card-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  font-size: 14px;
  color: var(--text-dim);
}

.wt-card-pills b {
  color: var(--text);
}

.wt-card-go {
  margin-top: auto;
  color: var(--accent);
}

/* Two app windows on top of each other in a hero, the second a little in. */
.hero-stack {
  display: grid;
  gap: 16px;
}

.hero-stack > .st-window + .st-window {
  margin-left: 48px;
}

/* ---------------- /demo ---------------- */


.demo-window .demo-body {
  padding: 22px;
  background: var(--bg);
}

.demo-stories {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* ---------------- the verdict sheet (/vs/hyros) ---------------- */

.verdict-band {
  padding-block: 0 64px;
}

.verdict {
  max-width: 860px;
  margin-inline: auto;
}

.verdict-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 15px;
}

.verdict-table th,
.verdict-table td {
  padding: 13px 10px;
  text-align: left;
  border-bottom: 1px solid var(--line);
}

.verdict-table thead th {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.verdict-table tbody th {
  font-weight: 500;
}

.verdict-table td {
  width: 24%;
}

.verdict-table tr:last-child th,
.verdict-table tr:last-child td {
  border-bottom: none;
}

.verdict-yes {
  display: inline-grid;
  place-items: center;
  width: 26px;
  height: 26px;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 50%;
}

.verdict-word {
  font-size: 13.5px;
  color: var(--text-dim);
}

.verdict-jump {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px 12px;
  margin-top: 18px;
  font-size: 14px;
  color: var(--text-faint);
}

.verdict-jump a {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
}

.ads-none {
  font-size: 12px;
  color: var(--text-faint);
  white-space: nowrap;
}

/* ---------------- the Product menu ---------------- */

.nav-panel-wide {
  left: 0;
  /* Three columns: Product, By what you run, Platforms. Never wider than the screen. */
  width: min(940px, calc(100vw - 64px));
  padding: 14px;
  transform: none;
}

.nav-cols {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}

/* Each column is one list in the three-column panel, however many links it holds. */
.nav-cols .nav-panel-list-2 {
  grid-template-columns: minmax(0, 1fr);
}

.nav-cols .nav-panel-list-2 .nav-item {
  min-height: 0;
}

.nav-col-label {
  padding: 4px 10px 6px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.nav-col-label::before {
  content: '';
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: 8px;
  vertical-align: 1px;
  border-radius: 2px;
  background: var(--accent);
}

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

.nav-panel-list-2 .nav-item {
  min-height: 64px;
}

.nav-more {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 6px;
  margin: 10px 0 0;
  padding: 10px 0 0;
  list-style: none;
  border-top: 1px solid var(--line);
}

.nav-more-link {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  align-items: center;
  column-gap: 8px;
  min-height: 52px;
  padding: 8px 10px;
  color: var(--text);
  font-weight: 600;
  font-size: 14px;
  text-decoration: none;
  border-radius: 9px;
}

.nav-more-link svg {
  color: var(--accent);
}

.nav-more-link:hover,
.nav-more-link:focus-visible,
.nav-more-link[aria-current='page'] {
  background: var(--bg-active);
  text-decoration: none;
}

.nav-more-line {
  grid-column: 2;
  font-weight: 400;
  font-size: 12.5px;
  color: var(--text-dim);
}

/* ---------------- phase 2: responsive ---------------- */

@media (max-width: 1100px) {
  .step-row {
    gap: 32px;
    padding: 26px;
  }
}

@media (max-width: 960px) {
  .card-grid,
  .problem-nums,
  .wt-cards-3 {
    grid-template-columns: minmax(0, 1fr);
  }
  .step-row,
  .step-row-flip,
  .learned {
    grid-template-columns: minmax(0, 1fr);
  }
  .step-row-flip .step-row-copy {
    order: 0;
  }
}

@media (max-width: 720px) {
  .page-hero {
    padding-block: 32px 64px;
  }
  .step-row {
    padding: 20px 16px;
    gap: 22px;
  }
  .step-row-title {
    font-size: 25px;
  }
  .card-grid-4,
  .credit-grid,
  .wt-cards,
  .fit-list,
  .rep-two,
  .rep-kinds {
    grid-template-columns: minmax(0, 1fr);
  }
  .rep-group {
    grid-template-columns: minmax(0, 1fr);
    gap: 4px;
  }
  .rep-group-name {
    padding-top: 0;
  }
  .rep-hide-sm {
    display: none;
  }
  .tpl-card,
  .fit-card {
    padding: 20px 18px;
  }
  .wt-title {
    font-size: 38px;
  }
  .wt-hero {
    padding-block: 24px 64px;
  }
  .stat-pills li {
    flex: 1 1 calc(50% - 10px);
    min-width: 0;
  }
  .stat-pill-value {
    font-size: 24px;
  }
  .learned-list {
    padding: 20px 18px 20px 40px;
    font-size: 16px;
  }
  .demo-window .demo-body {
    padding: 12px;
  }
  .verdict-table th,
  .verdict-table td {
    padding: 11px 6px;
    font-size: 13.5px;
  }
  .verdict-table td {
    width: 26%;
  }
  .problem-nums .bignum-value {
    font-size: 38px;
  }
  .meta-sync {
    padding: 14px;
  }
  .hero-stack > .st-window + .st-window {
    margin-left: 0;
  }
}

/* Home hero headline: sized from its own column, not the window, so
   "Know which platforms" fits on one line with room to spare in every serif
   the system picks (Apple's New York runs wider than Charter or Georgia).
   About 9cqi keeps a 20-character line near 90% of the column. */
.marketing .home-hero .hero-grid,
.marketing .page-hero .hero-grid {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 72px;
}
.marketing .home-hero .hero-copy,
.marketing .page-hero .hero-copy {
  container-type: inline-size;
}
.marketing .home-hero .hero-title,
.marketing .page-hero .hero-title {
  font-size: clamp(30px, 9cqi, 56px);
}
/* The hero eyebrow stays on one line; the smallest phones get tighter tracking. */
.marketing .hero-eyebrow {
  white-space: nowrap;
}
@media (max-width: 360px) {
  .marketing .hero-eyebrow {
    letter-spacing: 0.06em;
  }
}
/* The facts under a hero never wrap mid-row on a phone. A short set (up to 50
   characters, marked .hero-dots-line) stays on one line, its type following the
   column; a longer set, or any set on the narrowest phones, stacks one per line. */
@media (max-width: 720px) {
  .marketing .hero-dots {
    flex-direction: column;
    gap: 8px;
  }
}
/* Its type is sized against the hero column, so the column is the container. */
.marketing .hero-copy:has(> .hero-dots-line) {
  container-type: inline-size;
}
@media (min-width: 370px) and (max-width: 720px) {
  .marketing .hero-dots-line {
    flex-direction: row;
    /* Sized to fit one line; with large text the items wrap instead of spilling. */
    flex-wrap: wrap;
    justify-content: center;
    gap: 6px 14px;
    font-size: clamp(8.5px, 2.9cqi, 11.5px);
    letter-spacing: 0;
  }
  .marketing .hero-dots-line li::before {
    margin-right: 6px;
  }
}
/* On a phone the headline fills the column: the longest line ("Prove which
   ads", "drive revenue.") still fits at 12.5cqi. */
@media (max-width: 720px) {
  .marketing .home-hero .hero-title {
    font-size: clamp(34px, 12.5cqi, 52px);
    line-height: 1.04;
  }
}
@media (max-width: 1100px) {
  .marketing .home-hero .hero-grid,
  .marketing .page-hero .hero-grid {
    gap: 48px;
  }
}
@media (max-width: 960px) {
  .marketing .home-hero .hero-grid,
  .marketing .page-hero .hero-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ================================================================
   Vertical pages, round two: the live feed hero, the gap window,
   the journey band and the payoff (src/content/vertical.ts).
   ================================================================ */

/* The hero picture sits on a soft blue panel with faint contour lines. */
.hero-panel {
  position: relative;
  padding: 36px 30px 22px;
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='400' viewBox='0 0 600 400'%3E%3Cg fill='none' stroke='%231559d0' stroke-opacity='.07' stroke-width='14'%3E%3Cpath d='M-20 80 C120 20 260 140 400 70 S620 40 640 60'/%3E%3Cpath d='M-20 210 C140 150 280 270 420 200 S620 170 640 190'/%3E%3Cpath d='M-20 340 C120 290 260 400 400 330 S620 300 640 320'/%3E%3C/g%3E%3C/svg%3E") center / cover,
    var(--brand-band);
  border: 1px solid color-mix(in srgb, var(--accent) 16%, var(--line));
  border-radius: 22px;
}

.hero-panel .film-caption {
  margin-top: 14px;
}

.ledger .st-window-body {
  padding: 0;
}

.ledger-status {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 40px;
  margin: 10px 14px 0;
  padding: 0 4px 8px;
  font-size: 12.5px;
  font-weight: 600;
}

.ledger-status i {
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-right: 8px;
  border-radius: 50%;
}

.ledger-miss {
  color: var(--lost);
}

.ledger-miss i {
  background: var(--lost);
}

.ledger-ok {
  color: var(--accent);
}

.ledger-ok i {
  background: var(--accent);
}

.ledger:not(.is-connected) .ledger-ok,
.ledger.is-connected .ledger-miss {
  display: none;
}

.ledger-bar {
  position: absolute;
  right: 4px;
  bottom: 0;
  left: 4px;
  height: 3px;
  background: var(--line);
  border-radius: 3px;
  overflow: hidden;
}

.ledger-bar b {
  display: block;
  width: 0;
  height: 100%;
  background: var(--accent);
  transition: width 1.1s ease;
}

.ledger.is-connected .ledger-bar b {
  width: 100%;
}

.ledger-table {
  width: 100%;
  margin-top: 4px;
  border-collapse: collapse;
  font-size: 13px;
}

.ledger-table th {
  padding: 8px 10px;
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-align: left;
  text-transform: uppercase;
  color: var(--text-faint);
  border-bottom: 1px solid var(--line);
}

.ledger-table th:first-child,
.ledger-table td:first-child {
  padding-left: 18px;
}

.ledger-table td {
  height: 38px;
  padding: 0 10px;
  white-space: nowrap;
  border-bottom: 1px solid var(--line);
}

.ledger-table .num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.ledger-time {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--text-faint);
}

.ledger-item {
  font-weight: 600;
}

.ledger-value {
  font-family: var(--mono);
  font-size: 12.5px;
}

.ledger-state {
  width: 52%;
  max-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ledger-lost,
.ledger-found {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  max-width: 100%;
  font-family: var(--mono);
  font-size: 11.5px;
}

.ledger-found span {
  overflow: hidden;
  text-overflow: ellipsis;
}

.ledger-lost {
  color: var(--lost);
}

.ledger-found {
  color: var(--accent);
}

.ledger-row .ledger-found,
.ledger-row.is-credited .ledger-lost {
  display: none;
}

.ledger-row.is-credited .ledger-found {
  display: inline-flex;
}

.ledger-row.is-credited {
  background: color-mix(in srgb, var(--accent) 4%, transparent);
}

.ledger-row > td {
  opacity: 0;
  transition: opacity 0.35s ease;
}

.ledger-row.is-in > td {
  opacity: 1;
}

.ledger-foot .bignum-value {
  font-size: 34px;
}

.ledger-count .bignum-value {
  color: var(--lost);
  transition: color 0.4s ease;
}

.ledger.is-connected .ledger-count .bignum-value {
  color: var(--found);
}

.ledger.is-connected .ledger-lost-label,
.ledger:not(.is-connected) .ledger-found-label {
  display: none;
}

.ledger-seen .bignum-value {
  color: var(--accent);
}

/* ---------------- the gap window ---------------- */

.gap-solo {
  max-width: 920px;
  margin-inline: auto;
}

.gap-window .st-window-body {
  padding: 0;
}

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

.gap-cell {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 28px 30px 26px;
}

.gap-cell + .gap-cell {
  border-left: 1px solid var(--line);
}

.gap-value {
  font-family: var(--serif);
  font-size: 56px;
  line-height: 1;
  font-weight: 500;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--text);
}

.gap-spark {
  width: 80px;
  height: 22px;
  color: var(--text-faint);
}

.gap-cost {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--text);
  font-weight: 600;
}

.gap-cost i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--lost);
}

.card-grid-gap {
  margin-top: 24px;
}

/* ---------------- payoff ---------------- */

.payoff {
  margin-top: 48px;
  text-align: center;
}

.payoff-pills {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px 22px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 15px;
  font-weight: 500;
}

.payoff-pills li {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.payoff-pills svg {
  color: var(--accent);
}

.payoff-line {
  margin-top: 24px;
  font-family: var(--serif);
  font-size: 34px;
  line-height: 1.2;
  letter-spacing: -0.015em;
}

.journey-band .gap-card .frame-icon {
  margin: 0 0 18px;
}

@media (max-width: 720px) {
  .hero-panel {
    margin-inline: calc(var(--gutter) * -1 + 8px);
    padding: 16px 8px 12px;
    border-radius: 18px;
  }
  .ledger-time,
  .ledger-table th:first-child {
    display: none;
  }
  .ledger-table td:nth-child(2),
  .ledger-table th:nth-child(2) {
    padding-left: 12px;
  }
  .ledger-table td {
    padding: 0 6px;
  }
  .ledger-item {
    max-width: 90px;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .ledger-foot .bignum-value {
    font-size: 28px;
  }
  .gap-cells {
    grid-template-columns: minmax(0, 1fr);
  }
  .gap-cell + .gap-cell {
    border-left: none;
    border-top: 1px solid var(--line);
  }
  .gap-cell {
    padding: 20px 18px;
  }
  .gap-value {
    font-size: 44px;
  }
  .payoff-line {
    font-size: 26px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .ledger-row > td,
  .ledger-bar b,
  .ledger-count .bignum-value {
    transition: none;
  }
}

.share-row {
  margin-top: 40px;
  text-align: center;
}

.share-row-label {
  margin-bottom: 12px;
  font-size: 14.5px;
  color: var(--text-dim);
}

/* ---------------- send to Meta, and the dashboard still ---------------- */

.send-window .st-window-body {
  padding: 0;
}

.send-cols {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  padding: 10px 18px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
  border-bottom: 1px solid var(--line);
  background: color-mix(in srgb, var(--bg-tint) 55%, var(--bg-raised));
}

.send-cols span:nth-child(2) {
  text-align: center;
}

.send-cols span:last-child {
  text-align: right;
}

.send-grid {
  display: grid;
  grid-template-columns: auto minmax(40px, 1fr) auto;
  align-items: center;
  padding: 28px 22px;
}

.send-from .frame-icon {
  width: 34px;
  height: 26px;
  margin: 0 0 6px;
}

.send-lines {
  height: 140px;
}

.send-card {
  min-width: 170px;
  padding: 12px 14px;
}

.send-sub {
  font-size: 12px;
  color: var(--accent);
}

.dash-still .st-window-body {
  padding: 0;
}

.still-wrap {
  max-width: 980px;
  margin-inline: auto;
}

.still-kpis {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  border-bottom: 1px solid var(--line);
}

.still-kpis > div {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 16px 18px;
}

.still-kpis > div + div {
  border-left: 1px solid var(--line);
}

.still-kpis > div:first-child {
  background: var(--accent-soft);
  box-shadow: inset 0 -2px 0 var(--accent);
}

.still-kpis strong {
  font-size: 26px;
  font-variant-numeric: tabular-nums;
}

.still-body {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: 24px;
  padding: 20px 18px;
}

.still-chart {
  width: 100%;
  height: 180px;
}

.still-area {
  fill: color-mix(in srgb, var(--accent) 14%, transparent);
}

.still-line {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2.2;
  vector-effect: non-scaling-stroke;
}

.still-sources {
  display: grid;
  align-content: start;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 13.5px;
}

.still-sources li {
  display: flex;
  justify-content: space-between;
  padding: 6px 10px;
  border-radius: 6px;
  background: linear-gradient(90deg, var(--accent-soft) var(--w), transparent var(--w));
}

.still-sources li span:last-child {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.payoff-band .payoff {
  margin-top: 0;
  padding: 18px 0 6px;
}

.payoff-band .share-row-label {
  color: var(--text-dim);
}

@media (max-width: 720px) {
  .send-grid {
    grid-template-columns: auto minmax(20px, 1fr) auto;
    padding: 20px 12px;
  }
  .send-card {
    min-width: 0;
  }
  .still-kpis {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .still-kpis > div:nth-child(3) {
    border-left: none;
  }
  .still-kpis > div:nth-child(n + 3) {
    border-top: 1px solid var(--line);
  }
  .still-body {
    grid-template-columns: minmax(0, 1fr);
  }
  .still-chart {
    height: 120px;
  }
}

/* The selected KPI sits on the accent tint: its label needs the dimmer ink, not the faint one (4.5:1 in dark). */
.still-kpis .bignum-label {
  color: var(--text-dim);
}

/* ---------------- product pages: real screenshots, light and dark ---------------- */

/* A screenshot fills its window edge to edge. */
.shot-window .st-window-body {
  padding: 0;
  overflow: hidden;
}

.shot {
  display: block;
  width: 100%;
  height: auto;
}

/* Light by default; the dark shot follows the same two rules as the theme tokens. Hidden lazy images never load. */
.shot-dark {
  display: none;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .shot-light {
    display: none;
  }
  :root:not([data-theme='light']) .shot-dark {
    display: block;
  }
}

:root[data-theme='dark'] .shot-light {
  display: none;
}

:root[data-theme='dark'] .shot-dark {
  display: block;
}

/* The tall report shot stays a readable width in the hero. */
.product-hero .hero-stage .shot-window {
  max-height: 620px;
}

.product-hero .hero-stage .shot-window .st-window-body {
  max-height: 582px;
}

.split-shot,
.split-flip.split-shot {
  grid-template-columns: minmax(0, 0.72fr) minmax(0, 1.28fr);
  gap: 48px;
}

@media (max-width: 960px) {
  .split-shot,
  .split-flip.split-shot {
    grid-template-columns: minmax(0, 1fr);
    gap: 28px;
  }
}

.later-list {
  display: grid;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.later-list li {
  color: var(--text-dim);
}

.product-plan-table th,
.product-plan-table td {
  text-align: center;
  white-space: nowrap;
}

/* The Assistant's hero: words, not a picture of a screen that is not live. */
.soon-card {
  display: grid;
  gap: 14px;
  padding: 28px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 18px;
  box-shadow: var(--shadow-card);
}

.soon-card-title {
  font-family: var(--serif);
  font-size: 30px;
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -0.02em;
}

.soon-card-line {
  font-size: 14px;
  color: var(--text-faint);
}

/* Prove, keep, automate: copy and a real screen per job. */
.jobs {
  display: grid;
  gap: 28px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.job {
  display: grid;
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
  gap: 48px;
  align-items: center;
  padding: 32px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 18px;
  box-shadow: var(--shadow-card);
}

.job:nth-child(even) .job-copy {
  order: 2;
}

.job-title {
  margin: 8px 0 10px;
  font-family: var(--serif);
  font-size: 34px;
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: -0.02em;
}

.job-line {
  margin: 0 0 18px;
  font-size: 16px;
  color: var(--text-dim);
}

/* The report shot is tall and narrow: show its top. */
.job-visual .shot-window {
  max-height: 440px;
}

.job-visual .shot-window .st-window-body {
  max-height: 402px;
}

.product-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 14px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.product-card {
  height: 100%;
}

/* Dashboards on home: the real board, then three points under it. On desk
   widths the shot ends just under the two charts (610px of a 1040px wide
   shot), so the points stay near it; phones show all of it. */
.board-stage {
  max-width: 1040px;
  margin-inline: auto;
}

.board-stage .shot-window .st-window-body {
  max-height: 610px;
}

.board-points {
  margin-top: 36px;
}

/* /product/dashboards: each template with its numbers and cards, as the app builds them. */
.board-label {
  margin: 14px 0 4px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.board-numbers {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
}

.board-cards {
  display: grid;
  gap: 4px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 14.5px;
  color: var(--text-dim);
}

.board-cards li {
  position: relative;
  padding-left: 14px;
}

/* A short rule, not a bullet: the list reads as the stack of cards on the board. */
.board-cards li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.8em;
  width: 7px;
  height: 1.5px;
  background: var(--line-strong);
}

@media (max-width: 720px) {
  .board-stage .shot-window .st-window-body {
    max-height: none;
  }
  .board-points {
    margin-top: 24px;
  }
}

@media (max-width: 960px) {
  .job {
    grid-template-columns: minmax(0, 1fr);
    gap: 24px;
    padding: 22px;
  }
  .job:nth-child(even) .job-copy {
    order: 0;
  }
}

@media (max-width: 720px) {
  .job {
    padding: 18px;
  }
  .job-title {
    font-size: 28px;
  }
  .soon-card {
    padding: 20px;
  }
  .soon-card-title {
    font-size: 25px;
  }
  .product-hero .hero-stage .shot-window {
    max-height: 460px;
  }
  .product-hero .hero-stage .shot-window .st-window-body {
    max-height: 422px;
  }
}

/* ---- /status (src/routes/reliability.ts) ------------------------------------
   State colours reuse the chip tokens, so light and dark both come from the
   token blocks: working is the ok green, degraded the warn amber, down the
   danger red. Days with no checks use the strong line colour: "no data" must
   never read as green. */
.status-page {
  --st-up: var(--chip-ok-fg);
  --st-degraded: var(--chip-warn-fg);
  --st-down: var(--danger);
  --st-maintenance: var(--accent);
  --st-unknown: var(--line-strong);
  padding-block: 48px 88px;
}

.status-wrap {
  max-width: 820px;
}

.status-head h1 {
  font-family: var(--serif);
  font-size: 42px;
  font-weight: 500;
  line-height: 1.12;
  letter-spacing: -0.02em;
}

.status-head .eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

/* The overall state as a dot before the eyebrow. */
.status-head .eyebrow::before {
  --dot: var(--st-unknown);
  content: '';
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--dot);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--dot) 22%, transparent);
}

.status-head.is-up .eyebrow::before {
  --dot: var(--st-up);
}

.status-head.is-degraded .eyebrow::before {
  --dot: var(--st-degraded);
}

.status-head.is-down .eyebrow::before {
  --dot: var(--st-down);
}

.status-head.is-maintenance .eyebrow::before {
  --dot: var(--st-maintenance);
}

.status-sub {
  margin-top: 12px;
  max-width: 60ch;
  font-size: 17px;
  color: var(--text-dim);
}

.status-section {
  margin-top: 44px;
}

.status-h2 {
  margin-bottom: 14px;
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.status-list {
  margin: 0;
  padding: 0;
  list-style: none;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: var(--shadow-card);
}

.status-row {
  padding: 20px 22px;
  border-bottom: 1px solid var(--line);
}

.status-row:last-child {
  border-bottom: 0;
}

.status-row-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

.status-row h3 {
  font-size: 16px;
  font-weight: 600;
}

.status-row-head p {
  margin-top: 2px;
  font-size: 14px;
  color: var(--text-dim);
}

.status-state {
  --dot: var(--st-unknown);
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 7px;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-dim);
}

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--dot);
}

.status-state.is-up {
  --dot: var(--st-up);
  color: var(--chip-ok-fg);
}

.status-state.is-degraded {
  --dot: var(--st-degraded);
  color: var(--chip-warn-fg);
}

.status-state.is-down {
  --dot: var(--st-down);
  color: var(--danger-fg);
}

.status-state.is-maintenance {
  --dot: var(--st-maintenance);
  color: var(--accent);
}

/* One bar a day, the newest on the right. */
.status-bars {
  display: grid;
  grid-auto-columns: minmax(0, 1fr);
  grid-auto-flow: column;
  gap: 2px;
  height: 30px;
  margin-top: 14px;
}

.status-bars span,
.status-key i {
  display: block;
  border-radius: 2px;
  background: var(--st-unknown);
}

.status-bars .d-up,
.status-key .d-up {
  background: var(--st-up);
}

.status-bars .d-degraded,
.status-key .d-degraded {
  background: var(--st-degraded);
}

.status-bars .d-down,
.status-key .d-down {
  background: var(--st-down);
}

.status-axis {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-top: 7px;
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  color: var(--text-faint);
}

.status-axis > span:first-child,
.status-axis > span:last-child {
  flex: 0 0 auto;
  white-space: nowrap;
}

.status-axis > span:nth-child(2) {
  text-align: center;
}

.status-key {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  margin-top: 12px;
  font-size: 12.5px;
  color: var(--text-faint);
}

.status-key span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.status-key i {
  width: 10px;
  height: 10px;
}

.status-incident {
  padding: 18px 22px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 16px;
}

.status-incident + .status-incident {
  margin-top: 12px;
}

/* An open incident carries its impact on the left edge. */
.status-incident.is-open {
  border-left: 4px solid var(--st-degraded);
}

.status-incident.is-open.impact-major {
  border-left-color: var(--st-down);
}

.status-incident.is-open.impact-maintenance {
  border-left-color: var(--st-maintenance);
}

.status-incident h3 {
  font-size: 17px;
  font-weight: 600;
}

.status-incident-meta {
  margin-top: 2px;
  font-size: 13px;
  color: var(--text-faint);
}

.status-updates {
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
}

.status-updates li {
  padding-left: 14px;
  border-left: 2px solid var(--line);
}

.status-updates li + li {
  margin-top: 12px;
}

.status-updates p {
  font-size: 15px;
}

.status-updates time {
  display: block;
  margin-top: 2px;
  font-size: 12.5px;
  color: var(--text-faint);
}

.status-empty {
  color: var(--text-dim);
}

.status-how ul {
  margin: 0 0 14px;
  padding-left: 20px;
  color: var(--text-dim);
}

.status-how li + li {
  margin-top: 6px;
}

@media (max-width: 720px) {
  .status-page {
    padding-block: 32px 64px;
  }

  .status-head h1 {
    font-size: 32px;
  }

  .status-row,
  .status-incident {
    padding: 16px;
  }

  /* All 90 days on a phone too, so the bars and the uptime cover the same days. */
  .status-bars {
    gap: 1px;
    height: 26px;
  }
}

/* ---------------- phone sweep (scripts/phone-sweep.mjs) ----------------
   At 320 to 430 wide: nothing past the edge, no word cut short, and no row of
   short items that leaves one alone on its last line. */
@media (max-width: 720px) {
  /* Clouds of chips wrap in balanced lines, not a full line and a lone chip.
     Balancing works on inline content, so the items flow inline here. */
  .link-chips,
  .rep-chips,
  .mini-chips,
  .rep-tabs,
  .sites-filter,
  .marketing .chips {
    display: block;
    text-wrap: balance;
  }
  .link-chips > *,
  .rep-chips > *,
  .mini-chips > *,
  .rep-tabs > *,
  .sites-filter > *,
  .marketing .chips > * {
    display: inline-flex;
    margin: 0 4px 6px 0;
    vertical-align: middle;
  }
  .link-chips-center {
    text-align: center;
  }
  /* Three or four short facts and pills: one per line, centered, never 2 + 1. */
  .promise-facts,
  .payoff-pills,
  .pill-row-center,
  .section-actions {
    flex-direction: column;
    align-items: center;
    gap: 8px;
  }
  .promise-facts li + li::before {
    content: none;
  }
  /* The window bar: the address may take two lines rather than end in "...". */
  .st-window-bar {
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 10px;
    height: auto;
    min-height: 38px;
    padding-block: 6px;
  }
  .st-dots {
    display: none;
  }
  .st-url {
    overflow: visible;
    white-space: normal;
    overflow-wrap: anywhere;
    text-overflow: clip;
    text-align: left;
    font-size: 11px;
    line-height: 1.35;
  }
  /* Replicas of inputs and table names wrap instead of hiding their ends. */
  .rep-input {
    overflow: visible;
    white-space: normal;
    overflow-wrap: anywhere;
    text-overflow: clip;
    font-size: 12.5px;
  }
  .rep-short > span {
    min-width: 0;
    overflow-wrap: anywhere;
  }
  .rep-bars tbody th span {
    overflow: visible;
    white-space: normal;
    overflow-wrap: anywhere;
  }
  .sites-name span,
  .sites-name strong {
    overflow: visible;
    white-space: normal;
    overflow-wrap: anywhere;
  }
  /* Column heads in the demo tables may take two lines on the narrowest phones. */
  .ads-table thead th,
  .ads-table thead th.num,
  .rep-table thead th {
    white-space: normal;
  }
}
@media (max-width: 380px) {
  .ads-table th,
  .ads-table td {
    padding-inline: 8px;
  }
  .rep-table th,
  .rep-table td {
    padding-inline: 5px;
  }  /* The verdict's columns size to their names, so "AgencyAnalytics" stays whole. */
  .verdict-table th,
  .verdict-table td {
    padding-inline: 4px;
  }
  .verdict-table td {
    width: auto;
  }
  .verdict-table thead th {
    letter-spacing: 0.02em;
  }
}

/* ---- /partners (src/content/partners.ts): approved agencies, one card each.
   A logo only when the agency uploaded one; the name carries the card otherwise. */
.pt-list {
  display: grid;
  gap: 12px;
  margin: 28px 0 0;
  padding: 0;
  list-style: none;
}

.pt-card {
  display: grid;
  gap: 10px;
  padding: 20px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-card);
}

.pt-card-head {
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
}

.pt-card-title {
  min-width: 0;
}

.pt-name {
  font-family: var(--serif);
  font-size: 22px;
  font-weight: 500;
  letter-spacing: -0.015em;
  line-height: 1.25;
}

.pt-meta {
  margin-top: 2px;
  font-size: 14px;
  color: var(--text-dim);
  overflow-wrap: anywhere;
}

.pt-line {
  color: var(--text);
}

.pt-serves {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.pt-serves li {
  padding: 2px 10px;
  font-size: 13px;
  color: var(--text-dim);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
}

.pt-empty {
  display: grid;
  gap: 8px;
  margin-top: 28px;
  padding: 24px;
}

.pt-empty-title {
  font-family: var(--serif);
  font-size: 22px;
  font-weight: 500;
}

.pt-empty-line {
  color: var(--text-dim);
}

.pt-empty-actions,
.pt-band-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 8px;
}

.pt-band-actions {
  justify-content: center;
  margin-top: 28px;
}

.pt-band-note {
  max-width: 40em;
  margin: 14px auto 0;
  font-size: 14px;
  text-align: center;
  color: var(--text-faint);
}

@media (max-width: 720px) {
  .pt-band-actions .btn {
    flex: 1 1 100%;
  }
}

/* ================================================================
   The layout system (owner, 2026-10-23: "centering and stylings...
   Mokxi got this right"). Last in the file on purpose: every frame a
   marketing section sits in is set here once, and the per-page rules above
   only lay out what goes inside a frame. The rules follow Mokxi's
   web/src/site/site.css ("One axis, on every page").

   Section types, each with one alignment rule:
   - Hero with a picture beside it (home, pricing, product, /for, /platforms,
     /how-it-works, /vs/<tool>, setup call): words on the left at desk width.
     Once the picture drops under them (960px) the words stack on the
     center line, as on Mokxi.
   - Hero with no picture (/vs, /tools, /walkthroughs): centered at every
     width, on the same column as the section heads under it.
   - Section head (eyebrow, h2, sub): centered, 760px at most, the sub at a
     60 character measure. A list under a centered head sits as one centered
     block and keeps left-aligned lines (a centered bullet reads badly).
   - A head that shares its row with a picture (split rows): left beside the
     picture, centered once the row stacks.
   - Cards: words left inside the card at every width. A card is a thing to
     read, not a title.
   - Promise and closing bands: centered.
   - Reading pages (guides, glossary, docs, legal): left, like a document.

   One container (--site-max), one vertical step (--sec-pad), one h2 size,
   one button set (--btn-h-*), one eyebrow.
   ================================================================ */

.marketing {
  /* Every band: 104, then 80 under 960, then 64 on a phone. */
  --sec-pad: 104px;
  /* Heroes start closer to the header and end on the same step. */
  --hero-pad-top: 72px;
  /* Reading pages keep a tighter step between short topic sections. */
  --read-pad: 56px;
  --head-max: 760px;
  --head-gap: 52px;
  --measure: 60ch;
  --h2: 44px;
  --page-h1: 48px;
}

@media (max-width: 960px) {
  .marketing {
    --sec-pad: 80px;
    --hero-pad-top: 56px;
    --h2: 38px;
    --page-h1: 42px;
  }
}

@media (max-width: 720px) {
  .marketing {
    --sec-pad: 64px;
    --hero-pad-top: 32px;
    --read-pad: 44px;
    --head-gap: 36px;
    --h2: 32px;
    --page-h1: 36px;
  }
}

/* ---- rhythm: one step between every section type ---- */

.marketing .wsec,
.marketing .promise,
.marketing .closing,
.marketing:not(.guides):not(.docs):not(.legal) main > .section:not(.hero):not(.strip):not(.verdict-band):not(.vs-hero):not(.wt-hero):not(.call-hero) {
  padding-block: var(--sec-pad);
}

.marketing .hero,
.marketing .call-hero,
.marketing .vs-hero,
.marketing .wt-hero {
  padding-block: var(--hero-pad-top) var(--sec-pad);
}

/* The verdict sheet continues the /vs hero and the platform strip continues
   the home hero. Each ends on the same step as any band. */
.marketing .verdict-band,
.marketing .strip {
  padding-block: 0 var(--sec-pad);
}

.marketing.guides main > .section:not(.guide-page),
.marketing.docs main > .section:not(.doc-page):not(.closing) {
  padding-block: var(--read-pad);
}

/* ---- section heads ---- */

.marketing .wsec-head,
.marketing .section-head {
  max-width: var(--head-max);
  margin: 0 auto var(--head-gap);
  text-align: center;
}

.marketing .wsec-head .section-sub,
.marketing .section-head .section-sub {
  max-width: var(--measure);
  margin: 16px auto 0;
}

/* A reading page's heads stay on its left edge. */
.marketing .section-head-left,
.marketing .section-head-left .section-sub,
.marketing .wsec-head-left,
.marketing .wsec-head-left .section-sub {
  margin-inline: 0;
  text-align: left;
}

/* One eyebrow: mono, uppercase, faint. The accent is kept for the one word
   in each headline, so nothing competes with it. */
.marketing .section-eyebrow,
.marketing .wt-head,
.marketing .answer-label,
.marketing .split-copy > .step-label,
.marketing .split-copy > .step-label .step-label-no {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 400;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
  text-wrap: balance;
}

/* ---- type: one h2 size for every section head ---- */

.marketing .section-title,
.marketing .split-copy .section-title,
.marketing .wsec-head-card .section-title,
.marketing .closing-title,
.marketing .promise-title {
  font-family: var(--serif);
  font-size: var(--h2);
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: -0.02em;
}

/* Reading pages head their topics a step smaller, as a document does. */
.marketing.guides .guides-topic .section-title {
  font-size: min(var(--h2), 30px);
}

.marketing .page-title,
.marketing .wt-title {
  font-size: var(--page-h1);
  line-height: 1.08;
  letter-spacing: -0.025em;
}

/* Every hero headline is sized from its own column, so a two-line title
   keeps both lines whole and every hero reads at the same size. */
.marketing .hero-copy,
.marketing .call-copy {
  container-type: inline-size;
}

.marketing .hero-copy .hero-title,
.marketing .call-copy .hero-title {
  font-size: clamp(30px, 9cqi, 56px);
}

/* Home's lines are the shortest, so on a phone they fill the column. */
@media (max-width: 720px) {
  .marketing .home-hero .hero-copy .hero-title {
    font-size: clamp(34px, 12.5cqi, 52px);
  }
}

/* ---- heroes ---- */

/* The calls to action sit on the page, not in a box around them. */
.cta-tray {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 32px;
  padding: 0;
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}

/* Heroes with no picture: one centered column. */
.marketing .wt-hero-inner,
.marketing.tools .ub-wrap,
.marketing.vs .vs-hero > .container > .section-head {
  max-width: var(--head-max);
  margin-inline: auto;
  text-align: center;
}

.marketing .wt-hero-inner .crumbs,
.marketing.tools .ub-wrap .crumbs,
.marketing.vs .vs-hero:not(:has(.vs-hero-grid)) .crumbs {
  justify-content: center;
}

.marketing .wt-hero-inner .hero-lead,
.marketing .wt-note,
.marketing.tools .ub-lead {
  max-width: var(--measure);
  margin-inline: auto;
}

.marketing .wt-hero-inner .stat-pills,
.marketing .wt-actions {
  justify-content: center;
}

.marketing.tools .tools-cards {
  text-align: left;
}

/* Heroes with a picture stack on the center line once the picture drops
   under the words. */
@media (max-width: 960px) {
  .marketing .hero-copy,
  .marketing .call-copy,
  .marketing .vs-hero-grid > div:first-child {
    text-align: center;
  }
  .marketing .hero-copy .hero-lead,
  .marketing .call-copy .hero-lead,
  .marketing .vs-hero-grid .hero-lead,
  .marketing .vs-hero-grid .vs-checked {
    max-width: var(--measure);
    margin-inline: auto;
  }
  .marketing .hero-copy .cta-tray,
  .marketing .hero-copy .hero-dots,
  .marketing .call-copy .pill-row {
    justify-content: center;
  }
  .marketing .hero-copy .hero-dots {
    align-items: center;
  }
  /* A list keeps left-aligned lines, as one block on the center line. */
  .marketing .hero-copy .checks,
  .marketing .call-copy .call-list {
    width: fit-content;
    max-width: 100%;
    margin-inline: auto;
    text-align: left;
  }
  .marketing.vs .vs-hero .crumbs {
    justify-content: center;
  }
}

/* ---- split rows: a head beside its picture ---- */

@media (max-width: 960px) {
  .marketing .split-copy {
    text-align: center;
  }
  .marketing .split-copy .checks {
    width: fit-content;
    max-width: 100%;
    margin-inline: auto;
    text-align: left;
  }
  .marketing .split-copy .split-lead {
    max-width: var(--measure);
    margin-inline: auto;
  }
}

/* ---- the blue band: the panel keeps the page's gutter, its head is not a card ---- */

.marketing .wsec-head-card {
  max-width: var(--head-max);
  margin: 0 auto var(--head-gap);
  padding: 0;
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}

@media (max-width: 720px) {
  .marketing .blue-panel {
    margin-inline: 0;
    padding: 32px 16px 16px;
  }
}

/* ---- buttons: one set ----
   48 for the calls to action in heroes and bands, 40 for the rest, and every
   one 44 or more on a phone (site.css). A pair of calls to action never
   shares a phone's row: each takes its own, full width, so both are the same
   size and neither label wraps. */

@media (max-width: 520px) {
  .marketing .cta-tray,
  .marketing .closing-actions,
  .marketing .promise-actions,
  .marketing .wt-actions {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
  }
  .marketing .cta-tray .btn,
  .marketing .closing-actions .btn,
  .marketing .promise-actions .btn,
  .marketing .wt-actions .btn {
    flex: 0 0 auto;
    width: 100%;
  }
}

/* "Show me how" inside a card that is itself the link: a plain text link,
   the same as "Read the walkthrough", not a box that looks like a second button. */
.marketing .pick-go {
  padding: 0;
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--accent);
  background: none;
  border: 0;
}

/* ---- rows that wrap: never one item alone on a phone ---- */

@media (max-width: 720px) {
  /* Up to six link chips become a list of full-width rows, each a 44px target. */
  .marketing .link-chips:not(:has(> li:nth-child(7))) {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    max-width: 420px;
    margin-inline: auto;
  }
  .marketing .link-chips:not(:has(> li:nth-child(7))) .link-chip {
    display: flex;
    justify-content: space-between;
    width: 100%;
    padding-inline: 16px 14px;
  }
  /* Short facts with a tick: one per line, as one block. */
  .marketing .pill-row {
    flex-direction: column;
    align-items: flex-start;
    width: fit-content;
    max-width: 100%;
  }
  .marketing .pill-row-center,
  .marketing .call-copy .pill-row {
    margin-inline: auto;
  }
  /* In-page links and source lists: one per line, no separators. */
  .marketing .verdict-jump {
    flex-direction: column;
    align-items: center;
    gap: 0;
  }
  .marketing .verdict-jump [aria-hidden='true'] {
    display: none;
  }
  .marketing .verdict-jump a {
    min-height: 44px;
  }
  .marketing .vs-sources ul {
    flex-direction: column;
    gap: 4px;
  }
  /* The promise facts: one per line, no leading dot. */
  .marketing .promise-facts {
    flex-direction: column;
    align-items: center;
    gap: 6px;
  }
  .marketing .promise-facts li + li::before {
    content: none;
  }
  /* Tabs and filters inside a picture of the app scroll sideways, as they do
     in the app, instead of dropping one onto a line of its own. */
  .marketing .rep-tabs,
  .marketing .rep-chips,
  .marketing .sites-filter {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .marketing .rep-tabs > *,
  .marketing .rep-chips > *,
  .marketing .sites-filter > * {
    flex: 0 0 auto;
  }
  /* A guide's related terms: the same full-width rows as the link chips. */
  .marketing .guide-terms {
    flex-direction: column;
    gap: 8px;
  }
  .marketing .guide-terms a {
    display: flex;
    min-height: 44px;
    padding-inline: 16px;
  }
  /* Form choices: one per line, each a full row to tap. */
  .marketing .call-checks {
    flex-direction: column;
    gap: 0;
  }
  .marketing .call-checks .field-check {
    min-height: 44px;
  }
  /* Column heads and names in a picture's table may take two lines rather
     than be cut off. */
  .marketing .st-window thead th {
    white-space: normal;
    letter-spacing: 0.04em;
  }
  .marketing .rep-bars tbody th span,
  .marketing .sites-name > span,
  .marketing .rep-input {
    white-space: normal;
    overflow-wrap: anywhere;
  }
  /* Related links under a section: one per line, on the center line. */
  .marketing .section-actions {
    flex-direction: column;
    align-items: center;
    gap: 4px;
  }
  .marketing .section-actions .text-link {
    min-height: 44px;
  }
  /* The trail above a page title stops at its parent: the title under it
     already names the page, and a long one would wrap the trail. */
  .marketing .crumbs li[aria-current],
  .marketing .crumbs li:has(> [aria-current]) {
    display: none;
  }
  /* "Home" alone is not a trail; the wordmark already goes there. */
  .marketing .crumbs:not(:has(li:nth-child(3))) {
    display: none;
  }
  /* A link taken apart in a guide figure: one part per line. */
  .marketing .fig-anatomy {
    flex-direction: column;
  }
}

/* ---- the home setup row: on the strip's center line ---- */

.marketing .setup-band {
  justify-content: center;
  text-align: center;
}

.marketing .setup-band-line {
  flex-basis: 100%;
}

.marketing .setup-band .link-chips,
.marketing .setup-band .chip-row {
  justify-content: center;
}

/* ---- details ---- */

/* The short answer on /vs: a quiet panel, no heavy rule down its side. */
.marketing .answer {
  border-left-width: 1px;
  border-radius: var(--r-lg);
}

/* A window's address bar shows the whole address on a desk. On a phone it
   shows the site only, as Safari does, so nothing is cut off mid-word. */
@media (max-width: 560px) {
  .st-url-rest {
    display: none;
  }
}

/* ---- home hero: the website field (src/content/home.ts addSiteForm) ----
   One unit on a desk: the field and its button in one raised box, and the
   box takes the focus ring while the field is typed in. On a phone the two
   stack, each full width, and the field carries the box itself. */

.marketing .hero-add {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  max-width: 520px;
  margin-top: 32px;
  padding: 6px;
  background: var(--bg-input);
  border: 1px solid var(--line-input);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-card);
  transition: border-color var(--dur-1) ease, box-shadow var(--dur-1) ease;
}

.marketing .hero-add:focus-within:not(:has(.hero-add-go:focus-visible)) {
  border-color: var(--accent);
  box-shadow: var(--focus-ring), var(--shadow-card);
}

.marketing .hero-add-field {
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  gap: 10px;
  min-width: 0;
  padding-left: 12px;
  color: var(--text-faint);
  cursor: text;
}

.marketing .hero-add-icon {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
}

.marketing .hero-add-input {
  flex: 1 1 auto;
  min-width: 0;
  height: var(--btn-h-lg);
  padding: 0;
  font: inherit;
  font-size: 17px;
  color: var(--text);
  background: transparent;
  border: 0;
  outline: none;
  -webkit-appearance: none;
  appearance: none;
}

.marketing .hero-add-input::placeholder {
  color: var(--text-faint);
  opacity: 1;
}

.marketing .hero-add-go {
  flex: 0 0 auto;
  border-radius: calc(var(--r-xl) - 6px);
  white-space: nowrap;
}

.marketing .home-hero .hero-dots {
  margin-top: 18px;
}

.marketing .home-hero .hero-try {
  margin-top: 14px;
}

@media (max-width: 960px) {
  .marketing .hero-add {
    margin-inline: auto;
  }
}

@media (max-width: 520px) {
  .marketing .hero-add {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    padding: 0;
    background: none;
    border: 0;
    box-shadow: none;
  }
  .marketing .hero-add:focus-within:not(:has(.hero-add-go:focus-visible)) {
    box-shadow: none;
  }
  .marketing .hero-add-field {
    padding: 0 14px;
    background: var(--bg-input);
    border: 1px solid var(--line-input);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-card);
    transition: border-color var(--dur-1) ease, box-shadow var(--dur-1) ease;
  }
  .marketing .hero-add-field:focus-within {
    border-color: var(--accent);
    box-shadow: var(--focus-ring), var(--shadow-card);
  }
  .marketing .hero-add-go {
    width: 100%;
    border-radius: var(--r-lg);
  }
}

/* ---- home hero: revenue by source on the demo shop (src/content/demo.ts revenueWindow) ---- */

.money {
  margin: 0;
}

.money-top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 16px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--line);
}

.money-top .bignum-value {
  font-size: clamp(30px, 4vw, 40px);
}

.money-table {
  width: 100%;
  margin-top: 6px;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}

.money-table caption {
  padding: 12px 0 4px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-align: left;
  color: var(--text-faint);
}

.money-table thead th {
  padding: 4px 0 8px;
  font-size: 12px;
  font-weight: 500;
  text-align: left;
  color: var(--text-faint);
}

.money-table .num {
  padding-left: 12px;
  text-align: right;
  white-space: nowrap;
}

.money-table tbody th,
.money-table tbody td {
  padding: 9px 0;
  border-top: 1px solid var(--line);
  vertical-align: top;
}

.money-table tbody td.num {
  padding-left: 12px;
  font-size: 14px;
  color: var(--text);
}

.money-table tbody th {
  font-weight: 400;
  text-align: left;
}

.money-name {
  display: block;
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
}

.money-kind {
  display: block;
  margin-top: 1px;
  font-size: 12px;
  color: var(--text-dim);
}

/* The bar: each source's revenue against the top one, under its name. */
.money-bar {
  display: block;
  width: var(--w);
  height: 4px;
  margin-top: 7px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--accent) 30%, transparent);
}

.money-table .is-best .money-bar {
  background: var(--accent);
}

.money-table .num:last-child {
  /* Room for the best value's pill, so it stays inside the window's edge. */
  padding-right: 7px;
}

.money-best {
  display: inline-block;
  padding: 1px 7px;
  margin: -1px -7px;
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: var(--r-pill);
}

.money-caption {
  margin-top: 12px;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.04em;
  text-align: center;
  color: var(--text-faint);
}

.money-caption .text-link {
  display: flex;
  align-items: center;
  gap: 4px;
  width: fit-content;
  margin: 4px auto 0;
  font-family: var(--sans);
  font-size: 13px;
  letter-spacing: 0;
  white-space: nowrap;
}

@media (max-width: 420px) {
  .money .st-window-body {
    padding: 14px;
  }
  .money-top {
    gap: 12px;
  }
  .money-top .bignum-value {
    font-size: 28px;
  }
}

/* ---------------- /demo, the ad landing page (src/content/demopage.ts) ----------------
   First screen on a phone: the problem, one ad that made money beside one
   that did not, then the home hero's field. On a desk the two ads sit to the
   right of the words and the field. */

.marketing.demo-page .demo-hero {
  padding-block: 40px 48px;
}

.demo-page .demo-hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr);
  grid-template-areas: 'copy ads' 'act ads';
  align-items: start;
  gap: 0 56px;
  margin: 0 auto;
}

.demo-hero-copy {
  grid-area: copy;
}

.demo-hero-act {
  grid-area: act;
}

.demo-page .demo-ads {
  grid-area: ads;
  align-self: center;
}

.marketing .demo-title {
  margin-top: 10px;
  text-wrap: balance;
}

.marketing .demo-lead {
  margin-top: 16px;
}

.demo-promise {
  margin-top: 26px;
  font-size: 17px;
  line-height: 1.5;
  color: var(--text);
  max-width: 30em;
}

.demo-hero-act .hero-add {
  margin-top: 16px;
}

.demo-hero .hero-dots {
  margin-top: 16px;
}

.demo-hero .hero-try,
.demo-close .hero-try {
  margin-top: 12px;
}

.demo-sep {
  margin: 0 8px;
  color: var(--text-faint);
}

.link-button {
  padding: 0;
  font: inherit;
  color: var(--accent);
  background: none;
  border: 0;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

.link-button:hover {
  color: var(--accent-hover);
}

/* The two ads, in the words a shop owner says out loud. */
.demo-ads {
  margin: 0;
  padding: 18px 18px 14px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-panel);
}

.demo-ads-head {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.04em;
  color: var(--text-faint);
}

.demo-ads-list {
  display: grid;
  gap: 10px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
}

.demo-ad {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: 'name back' 'nums nums';
  align-items: baseline;
  gap: 4px 12px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-left-width: 4px;
  border-radius: var(--r-lg);
}

.demo-ad-win {
  border-left-color: var(--success);
  background: color-mix(in srgb, var(--success-bg) 70%, transparent);
}

.demo-ad-lose {
  border-left-color: var(--danger);
  background: color-mix(in srgb, var(--danger-bg) 60%, transparent);
}

.demo-ad-name {
  grid-area: name;
  font-weight: 600;
  font-size: 15.5px;
}

.demo-ad-nums {
  grid-area: nums;
  display: flex;
  flex-wrap: wrap;
  gap: 2px 18px;
  font-size: 15px;
  color: var(--text-dim);
}

.demo-ad-nums strong {
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.demo-ad-back {
  grid-area: back;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
}

.demo-ad-win .demo-ad-back {
  color: var(--success-fg);
}

.demo-ad-lose .demo-ad-back {
  color: var(--danger-fg);
}

.demo-ads-cap {
  margin-top: 10px;
  font-size: 12.5px;
  color: var(--text-faint);
}

/* The line over the board: what it is, and where to look first. */
.demo-orient {
  max-width: 46em;
  margin: 0 0 16px;
  font-size: 15.5px;
  line-height: 1.55;
  color: var(--text-dim);
}

.demo-orient strong {
  color: var(--text);
  font-weight: 600;
}

/* The feature list: a name, the plan, one line. */
.demo-features {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.demo-feature {
  display: grid;
  gap: 6px;
  height: 100%;
  padding: 16px 18px;
  color: inherit;
  text-decoration: none;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-card);
  transition: border-color var(--dur-1) ease;
}

.demo-feature:hover,
.demo-feature.is-on {
  border-color: var(--accent);
}

.demo-feature-top {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px 10px;
}

.demo-feature-line {
  font-size: 14.5px;
  color: var(--text-dim);
}

.demo-plan {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  white-space: nowrap;
  color: var(--accent);
}

/* The feature pages: a row of chips, one line of what it is, the view. */
.demo-nav {
  margin: 0 0 22px;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.demo-nav::-webkit-scrollbar {
  display: none;
}

.demo-nav ul {
  display: flex;
  gap: 6px;
  width: max-content;
  margin: 0;
  padding: 2px;
  list-style: none;
}

.demo-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 36px;
  padding: 0 14px;
  font-size: 14px;
  color: var(--text-dim);
  text-decoration: none;
  white-space: nowrap;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 999px;
}

.demo-nav a[aria-current='page'] {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--accent);
}

.demo-hero-feature .hero-lead {
  max-width: 40em;
}

.demo-feature-body {
  display: grid;
  gap: 20px;
}

.demo-pair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: start;
  gap: 20px;
}

.demo-pair-report {
  grid-template-columns: minmax(0, 0.7fr) minmax(0, 1fr);
}

.demo-stack {
  display: grid;
  gap: 20px;
}

.demo-view > .st-window,
.demo-view > .hero-panel {
  max-width: 760px;
  margin-inline: auto;
}

.demo-caption {
  font-size: 13px;
  color: var(--text-faint);
  text-align: center;
}

.demo-do-inner,
.demo-close-inner {
  display: grid;
  justify-items: center;
  text-align: center;
}

.demo-do-line {
  max-width: 34em;
  font-size: 17px;
}

.demo-do-inner .hero-add,
.demo-close-inner .hero-add {
  margin: 18px auto 0;
}

.demo-do-inner .hero-dots,
.demo-close-inner .hero-dots {
  justify-content: center;
  margin-top: 16px;
}

.marketing.demo-page .demo-close {
  background:
    radial-gradient(110% 85% at 50% 100%, var(--accent-soft), transparent 72%),
    var(--bg-panel);
}

/* The slim start bar: phones only, once the hero's field is out of view. */
.demo-startbar {
  position: fixed;
  inset: auto 0 0;
  z-index: 60;
  padding: 8px 12px max(8px, env(safe-area-inset-bottom));
  background: color-mix(in srgb, var(--bg-raised) 94%, transparent);
  border-top: 1px solid var(--line);
  box-shadow: 0 -6px 20px color-mix(in srgb, #000 8%, transparent);
  -webkit-backdrop-filter: saturate(1.4) blur(12px);
  backdrop-filter: saturate(1.4) blur(12px);
}

.demo-startbar[hidden],
.tour-open .demo-startbar {
  display: none;
}

.demo-startbar-line {
  margin: 0 0 6px;
  font-size: 13px;
  font-weight: 600;
}

.marketing .hero-add.hero-add-slim {
  flex-direction: row;
  align-items: center;
  gap: 6px;
  max-width: none;
  margin: 0;
  padding: 4px;
  background: var(--bg-input);
  border: 1px solid var(--line-input);
  border-radius: var(--r-lg);
  box-shadow: none;
}

.marketing .hero-add-slim .hero-add-field {
  padding: 0 0 0 8px;
  background: none;
  border: 0;
  box-shadow: none;
}

.marketing .hero-add-slim .hero-add-field:focus-within {
  box-shadow: none;
}

.marketing .hero-add-slim .hero-add-input {
  height: 40px;
  font-size: 16px;
}

.marketing .hero-add-slim .hero-add-go {
  width: auto;
  min-height: 40px;
  height: 40px;
  padding-inline: 14px;
  font-size: 15px;
  border-radius: calc(var(--r-lg) - 4px);
}

@media (min-width: 721px) {
  .demo-startbar {
    display: none;
  }
}

@media (max-width: 720px) {
  .has-startbar body {
    padding-bottom: 104px;
  }
}

@media (max-width: 960px) {
  .demo-page .demo-hero-grid {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: 'copy' 'ads' 'act';
    gap: 0;
  }
  .demo-page .demo-ads {
    max-width: 560px;
    margin-top: 20px;
  }
  .demo-hero-act .hero-add {
    margin-inline: 0;
  }
  .demo-features {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 720px) {
  .marketing.demo-page .demo-hero {
    padding-block: 18px 32px;
  }
  .marketing .demo-title {
    font-size: 36px;
    margin-top: 6px;
  }
  .marketing .demo-lead {
    margin-top: 10px;
    font-size: 16.5px;
  }
  .demo-page .demo-ads {
    margin-top: 16px;
    padding: 14px 12px 10px;
  }
  .demo-ad {
    grid-template-areas: 'name name' 'nums back';
    padding: 10px 12px;
  }
  .demo-promise {
    margin-top: 16px;
    font-size: 16px;
  }
  .demo-hero-act .hero-add {
    margin-top: 12px;
  }
  .demo-features,
  .demo-pair,
  .demo-pair-report {
    grid-template-columns: minmax(0, 1fr);
  }
}
/* The revenue view in its own band under the hero: one window, centered, as wide as it reads well. */
.marketing .money-stage {
  max-width: 640px;
  margin-inline: auto;
}

/* /demo: Store, Lead gen, Agency client. A segmented row of plain links. */
.demo-boards {
  margin: 0 0 14px;
}

.demo-boards ul {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: 0;
  padding: 4px;
  list-style: none;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: 999px;
}

.demo-boards a {
  display: inline-flex;
  align-items: center;
  min-height: 36px;
  padding: 0 14px;
  font-size: 14px;
  color: var(--text-dim);
  text-decoration: none;
  border-radius: 999px;
}

.demo-boards a[aria-current='page'] {
  color: var(--text);
  font-weight: 600;
  background: var(--bg-raised);
  box-shadow: var(--shadow-card);
}

/* The board continues the demo hero: no rule between them, and a link to #board lands clear of the sticky header. */
.marketing .demo-stage.strip {
  padding-top: 12px;
  border-top: 0;
  scroll-margin-top: 72px;
}

/* The demo is about which ad made money: on a phone its Ad spend card comes right after the numbers,
   ahead of the charts the app's own phone order puts first (public/static/app-analytics.css). */
@media (max-width: 720px) {
  .demo-page .dw.dw-ads {
    order: 3;
  }
}

/* The home hero's film opens the live demo: the whole window is one link. */
.hero-film-link {
  display: block;
  color: inherit;
  text-decoration: none;
  border-radius: 16px;
}
.hero-film-link .st-window {
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.hero-film-link:hover .st-window {
  transform: translateY(-2px);
}
.hero-film-link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 6px;
}
.hero-film-cta {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
  font-weight: 600;
  color: var(--accent);
}
.hero-film-cta svg {
  width: 16px;
  height: 16px;
  transition: transform 0.2s ease;
}
.hero-film-link:hover .hero-film-cta svg {
  transform: translateX(2px);
}
@media (prefers-reduced-motion: reduce) {
  .hero-film-link .st-window,
  .hero-film-cta svg {
    transition: none;
  }
  .hero-film-link:hover .st-window,
  .hero-film-link:hover .hero-film-cta svg {
    transform: none;
  }
}

/* /static/app-analytics.css */
/* Styles for the analytics area: the site dashboard (public/static/app/analytics.js),
   goals and share tabs, share pages, site card stats (src/routes/analytics.ts).
   Linked on every page by src/layout.ts, after site.css. Uses the tokens there;
   the dashboard is adapted from makerhandle public/static/app-stats.css. */

.dash,
.dialog.dash-all {
  /* Bars behind breakdown rows: the accent at low strength, so row text keeps
     its full contrast (--text on the bar stays above 11:1 in both themes). */
  --dash-bar: color-mix(in srgb, var(--accent) 13%, transparent);
  --dash-bar-hover: color-mix(in srgb, var(--accent) 24%, transparent);
  --dash-good: var(--success-fg);
  --dash-bad: var(--danger-fg);
}
.dash {
  display: grid;
  gap: 16px;
  min-width: 0;
  margin-top: 20px;
  font-variant-numeric: tabular-nums;
}
.dash.is-loading > :not(.dash-bar) {
  opacity: 0.55;
  transition: opacity var(--dur-2) ease var(--dur-1);
  pointer-events: none;
}
.dash-ic {
  display: inline-grid;
  place-items: center;
  flex-shrink: 0;
}
.dash-unavailable {
  margin: 0;
}
.dash-sub {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
}
.dash-sub .mono {
  font-size: var(--type-small);
}
.dash-notice {
  margin: 16px 0 0;
}

/* ---- top bar ---- */
.dash-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px 16px;
}
.dash-live {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 32px;
  padding: 0 12px 0 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--bg-panel);
  font-size: var(--type-small);
  color: var(--text-dim);
  white-space: nowrap;
}
.dash-live b {
  color: var(--text);
  font-weight: var(--weight-title);
}
.dash-pulse {
  position: relative;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-faint);
}
.dash-live.on .dash-pulse {
  background: var(--success-fg);
}
.dash-live.on .dash-pulse::after {
  content: '';
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  background: var(--success-fg);
  opacity: 0.5;
  animation: dash-pulse 2s cubic-bezier(0.2, 0.6, 0.4, 1) infinite;
}
@keyframes dash-pulse {
  from {
    transform: scale(0.4);
    opacity: 0.55;
  }
  to {
    transform: scale(1.6);
    opacity: 0;
  }
}
.dash-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: var(--btn-h-md);
  padding: 0 12px;
  border: 1px solid var(--line-control);
  border-radius: var(--btn-radius);
  background: var(--bg-raised);
  color: var(--text);
  font: inherit;
  font-size: var(--type-ui);
  font-weight: var(--weight-strong);
  cursor: pointer;
  transition: background-color var(--dur-1) ease, border-color var(--dur-1) ease;
}
.dash-btn:hover {
  background: var(--bg-hover);
  border-color: var(--line-strong);
}
.dash-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.dash-btn[aria-expanded='true'] {
  border-color: var(--accent);
  box-shadow: var(--focus-ring);
}
.dash-btn .dash-ic {
  color: var(--text-dim);
}
.dash-range {
  min-width: 176px;
}
.dash-range-label {
  flex: 1;
  overflow: hidden;
  text-align: left;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Menus are the shared .menu-list with .menu-row items (ui.css), opened by
   the script under their button; these only lay out what is inside them. */
.dash .menu-list {
  display: grid;
}
.dash .menu-row {
  justify-content: space-between;
}
.menu-row[aria-checked='true']:not(.switch) {
  font-weight: var(--weight-title);
}
.menu-row[aria-checked='true']:not(.switch) svg {
  color: var(--accent);
}
.menu-row:disabled,
.menu-row[aria-disabled='true'] {
  color: var(--text-faint);
  cursor: default;
}
.menu-row:disabled:hover,
.menu-row[aria-disabled='true']:hover {
  background: transparent;
}
.menu-row:disabled svg,
.menu-row[aria-disabled='true'] svg {
  color: inherit;
}
.dash-menu-filter {
  min-width: 260px;
  max-height: min(70vh, 520px);
  max-height: min(70dvh, 520px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
/* The period menu, one clock for the board: periods on the left, what they
   are compared with on the right. On phones the two stack, and the periods
   sit two to a row so the whole menu fits without a long scroll. */
.dash .dash-menu-range {
  grid-template-columns: minmax(176px, auto) minmax(344px, auto);
  column-gap: var(--space-1);
}
.dash-range-col {
  display: grid;
  align-content: start;
  min-width: 0;
}
.dash-range-col + .dash-range-col {
  padding-left: var(--space-1);
  border-left: 1px solid var(--line);
}
.dash-menu-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.dash-menu-end {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}
/* Key hints only where a mouse can hover; a chosen row shows its check instead. */
.dash-menu-kbd,
.menu-row[aria-checked='true'] .dash-menu-kbd {
  display: none;
}
@media (hover: hover) and (pointer: fine) {
  .dash-menu-kbd {
    display: inline-grid;
  }
}
@media (max-width: 720px) {
  .dash .dash-menu-range {
    grid-template-columns: 1fr;
    max-height: min(78vh, 660px);
    max-height: min(78dvh, 660px);
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  .dash-range-col:first-child {
    grid-template-columns: 1fr 1fr;
    column-gap: var(--space-1);
  }
  .dash-range-col:first-child .menu-sep {
    grid-column: 1 / -1;
  }
  .dash-range-col + .dash-range-col {
    margin-top: var(--space-1);
    padding-top: var(--space-1);
    padding-left: 0;
    border-top: 1px solid var(--line);
    border-left: 0;
  }
}
.dash-menu-main {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
.dash-menu-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dash-menu-hint {
  flex-shrink: 0;
  color: var(--text-faint);
  font-size: var(--type-small);
  font-weight: var(--weight-medium);
}
.dash-menu-note {
  margin: 0;
  padding: var(--space-2) 10px;
  font-size: var(--type-small);
  color: var(--text-dim);
}
.dash-custom {
  display: grid;
  gap: var(--space-2);
  padding: 0 var(--space-1) var(--space-1);
}
.dash-custom .menu-heading {
  padding-inline: 6px;
}
.dash-custom-row {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 6px;
}
.dash-date {
  min-width: 0;
  padding-inline: 8px;
  font-variant-numeric: tabular-nums;
}
/* A whole date, calendar icon included, always fits its field. */
.dash-custom-row .dash-date {
  min-width: 150px;
}

.dash-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: -4px;
}
.dash-chip-group {
  display: inline-flex;
  flex-direction: column;
  gap: 2px;
  max-width: 100%;
  min-width: 0;
}
/* What an app's own tag means, in one quiet line under its chip. */
.dash-filter-note {
  max-width: 34ch;
  padding-left: 10px;
  overflow: hidden;
  color: var(--text-faint);
  font-size: var(--type-caption);
  line-height: 1.35;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dash-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  max-width: 100%;
  padding: 4px 4px 4px 12px;
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  font-size: var(--type-ui);
}
.dash-chip-dim {
  color: var(--text-dim);
  white-space: nowrap;
}
.dash-chip b {
  overflow: hidden;
  font-weight: var(--weight-title);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dash-chip button {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
}
.dash-chip button:hover {
  background: color-mix(in srgb, var(--accent) 25%, transparent);
  color: var(--text);
}
.dash-clear {
  border: 0;
  background: none;
  color: var(--text-dim);
  font: inherit;
  font-size: var(--type-small);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

/* ---- KPIs and chart ---- */
.dash-delta {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: var(--type-small);
  font-weight: var(--weight-title);
  white-space: nowrap;
  color: var(--text-faint);
}
.dash-delta.good {
  color: var(--dash-good);
}
.dash-delta.bad {
  color: var(--dash-bad);
}
/* Profit below zero (the Return on all ad spend panel) reads as a loss. */
.dash-neg {
  color: var(--dash-bad);
}

.dash-chart {
  position: relative;
  min-height: 232px;
  padding: 18px 18px 6px;
}
.dash-chart:focus-visible {
  outline: 2px solid transparent;
  box-shadow: inset 0 0 0 2px var(--accent);
}
.dash-svg {
  display: block;
  overflow: visible;
  touch-action: pan-y;
}
.dash-gl {
  stroke: var(--line);
  stroke-width: 1;
}
.dash-gl.base {
  stroke: var(--line-strong);
}
.dash-ytick,
.dash-xtick {
  fill: var(--text-faint);
  font-family: var(--sans);
  font-size: var(--type-caption);
}
.dash-fill-top {
  stop-color: var(--accent);
  stop-opacity: 0.26;
}
.dash-fill-bottom {
  stop-color: var(--accent);
  stop-opacity: 0;
}
.dash-line {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2.25;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.dash-tail {
  stroke-dasharray: 3 5;
}
.dash-prev {
  fill: none;
  stroke: var(--text-faint);
  stroke-width: 1.75;
  stroke-dasharray: 4 5;
  stroke-linecap: round;
  opacity: 0.85;
}
.dash-dot {
  fill: var(--accent);
}
.dash-svg.animate .dash-line:not(.dash-tail) {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: dash-draw calc(var(--dur-4) * 2) var(--ease-out) forwards;
}
.dash-svg.animate .dash-area {
  opacity: 0;
  animation: dash-fade calc(var(--dur-4) * 1.5) ease var(--dur-3) forwards;
}
@keyframes dash-draw {
  to {
    stroke-dashoffset: 0;
  }
}
@keyframes dash-fade {
  to {
    opacity: 1;
  }
}
.dash-cross {
  stroke: var(--text-dim);
  stroke-width: 1;
  stroke-dasharray: 2 3;
}
.dash-hdot {
  fill: var(--accent);
  stroke: var(--bg-panel);
  stroke-width: 2.5;
}
.dash-hdot.prev {
  fill: var(--text-faint);
}
.dash-tip {
  position: absolute;
  top: 8px;
  left: 0;
  /* Solid, over every mark and note in the chart, in both themes. */
  z-index: 40;
  isolation: isolate;
  display: grid;
  gap: 5px;
  min-width: 170px;
  padding: 10px 12px;
  background: var(--bg-raised);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  box-shadow: var(--elev-3);
  font-size: var(--type-small);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-1) ease;
}
.dash-tip.show {
  opacity: 1;
}
.sw-none {
  visibility: hidden;
}
.dash-tip-when {
  font-family: var(--mono);
  font-size: var(--type-caption);
  letter-spacing: 0.04em;
  color: var(--text-dim);
}
.dash-tip-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.dash-tip-row span {
  flex: 1;
  white-space: nowrap;
  color: var(--text-dim);
}
.dash-tip-row b {
  font-size: var(--type-body);
}
.dash-tip-row.prev b {
  font-size: var(--type-small);
  color: var(--text-dim);
}
.sw {
  display: inline-block;
  flex-shrink: 0;
  width: 10px;
  height: 3px;
  border-radius: var(--r-xs);
  background: var(--accent);
}
.sw.prev {
  background: repeating-linear-gradient(90deg, var(--text-faint) 0 3px, transparent 3px 5px);
}

/* ---- breakdown panels ---- */
.dash-panel-note {
  margin: -4px 0 10px;
  font-size: var(--type-small);
  color: var(--text-faint);
}
.dash-tabs {
  position: relative;
  display: flex;
  gap: 2px;
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
}
.dash-tabs::-webkit-scrollbar {
  display: none;
}
/* More tabs than fit: a fade on the side that scrolls (scrollFade in app/analytics.js). */
.dash-tabs.fade-end {
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 36px), transparent);
  mask-image: linear-gradient(to right, #000 calc(100% - 36px), transparent);
}
.dash-tabs.fade-start {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 36px);
  mask-image: linear-gradient(to right, transparent, #000 36px);
}
.dash-tabs.fade-start.fade-end {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 36px, #000 calc(100% - 36px), transparent);
  mask-image: linear-gradient(to right, transparent, #000 36px, #000 calc(100% - 36px), transparent);
}
.dash-tabs button {
  padding: 5px 9px;
  border: 0;
  border-radius: var(--r-sm);
  background: none;
  color: var(--text-faint);
  font: inherit;
  font-size: var(--type-small);
  font-weight: var(--weight-strong);
  white-space: nowrap;
  cursor: pointer;
}
.dash-tabs button:hover {
  background: var(--bg-hover);
  color: var(--text);
}
.dash-tabs button[aria-selected='true'] {
  background: var(--bg-active);
  color: var(--text);
}
.dash-tabs button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.dash-colhead,
.dash-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 64px 52px;
  align-items: center;
  column-gap: 8px;
}
.dash-colhead.goals,
.dash-goals .dash-row {
  grid-template-columns: minmax(0, 1fr) 80px 72px 60px;
}
.dash-colhead {
  padding: 0 10px 6px;
  font-family: var(--mono);
  font-size: var(--type-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-faint);
}
.dash-colhead > :not(:first-child) {
  text-align: right;
}
.dash-colhead .dash-pct {
  font-size: inherit;
}
.dash-rows {
  display: grid;
  gap: 3px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.dash-row {
  position: relative;
  isolation: isolate;
  width: 100%;
  min-height: 34px;
  padding: 0 10px;
  border: 0;
  border-radius: var(--r-md);
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: var(--type-ui);
  text-align: left;
  cursor: pointer;
  /* The row's own corners round the bar's start, and its end when it is full. */
  overflow: hidden;
}
.dash-row:disabled {
  cursor: default;
}
.dash-bar-fill {
  position: absolute;
  inset: 0 auto 0 0;
  z-index: -1;
  width: var(--w);
  /* Square start, a small round at the end: a short bar reads as a bar, not a pill. */
  border-radius: 0 4px 4px 0;
  background: var(--dash-bar);
  transition: background-color var(--dur-1) ease, width var(--dur-4) var(--ease-out);
}
.dash-row:not(:disabled):hover .dash-bar-fill,
.dash-row.active .dash-bar-fill {
  background: var(--dash-bar-hover);
}
.dash-row:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.dash-name {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
}
.dash-name .dash-ic {
  color: var(--text-dim);
}
.dash-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* An app's own tag (zalo, ig): who added it, one quiet line under the name.
   The full sentence is the title, and shows under the filter once tapped. */
.dash-label-wrap {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 5px 0;
  text-align: left;
}
.dash-row-note {
  overflow: hidden;
  color: var(--text-dim);
  font-size: var(--fs-11);
  font-weight: 400;
  line-height: 1.35;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dash-row:not(:disabled):hover .dash-label {
  text-decoration: underline;
  text-decoration-color: var(--text-faint);
  text-underline-offset: 3px;
}
/* The goal's name wins the room: its rule shrinks first, never past half the row, and shows
   only on a wide card, where it is not a cut-off "/gu..." beside a cut-off name. */
.dash-goals {
  container-type: inline-size;
}
@container (max-width: 559px) {
  .dash-goal-match {
    display: none;
  }
}
.dash-goal-match {
  overflow: hidden;
  flex-shrink: 100;
  min-width: 0;
  max-width: 45%;
  padding: 1px 6px;
  border-radius: var(--r-xs);
  background: var(--bg-hover);
  font-family: var(--mono);
  font-size: var(--type-caption);
  color: var(--text-dim);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dash-flag {
  flex-shrink: 0;
  width: 16px;
  font-size: var(--type-body);
  line-height: 1;
  text-align: center;
}
.dash-letter {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  border-radius: var(--r-xs);
  background: var(--accent-soft);
  color: var(--accent);
  font-family: var(--mono);
  font-size: var(--type-label);
  font-weight: var(--weight-title);
}
.dash-val {
  font-weight: var(--weight-title);
  text-align: right;
}
.dash-pct {
  font-size: var(--type-small);
  text-align: right;
  color: var(--text-faint);
}
.dash-none {
  margin: auto 0;
  padding: 18px 10px;
  font-size: var(--type-ui);
  text-align: center;
  color: var(--text-faint);
}
.dash-privacy {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 4px 0;
  font-size: var(--type-small);
  text-align: center;
  color: var(--text-faint);
}

/* ---- skeleton (server-rendered, so nothing jumps when data arrives) ----
   The shared .skeleton shapes (ui.css), placed on the widget cells. */
.dw-sk-in > .skeleton-line {
  width: 60%;
  margin-block: 0 10px;
}
.dw-sk-in > .skeleton-num {
  width: 50%;
}
.dw-sk-chart {
  height: 210px;
}

/* ---- responsive ---- */
@media (max-width: 720px) {
  .dash {
    gap: 14px;
    margin-top: 16px;
  }
  .dash-range {
    width: 100%;
    min-width: 0;
  }
  .dash-chart {
    min-height: 200px;
    padding: 14px 10px 4px 6px;
  }
  .dash-colhead {
    padding: 0 8px 6px;
  }
  .dash-row {
    min-height: 40px;
    padding: 0 8px;
  }
  .dash-colhead,
  .dash-row {
    grid-template-columns: minmax(0, 1fr) 56px 46px;
  }
  .dash-colhead.goals,
  .dash-goals .dash-row {
    grid-template-columns: minmax(0, 1fr) 70px 50px;
  }
  .dash-hide-sm,
  .dash-goal-match {
    display: none;
  }
  .dash-privacy {
    align-items: flex-start;
    font-size: var(--type-caption);
    text-align: left;
  }
}

/* ---- site cards in /app: quick stats (src/dashboard/quick.ts) ---- */
/* Client chips on the left, the quick stats period on the right. */
.scs-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.scs-range {
  margin-left: auto;
}
.app-section.scs-bar + .site-list {
  margin-top: 16px;
}
.site-card-stats {
  display: grid;
  gap: 12px;
}
.scs-visits {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
  min-height: 38px;
}
.scs-main {
  display: grid;
  gap: 2px;
  min-width: 0;
}
.scs-figure {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.scs-num {
  font-size: var(--fs-24);
  font-weight: var(--weight-title);
  line-height: 1.15;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.scs-label {
  font-size: var(--type-small);
  color: var(--text-faint);
}
.scs-delta {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: var(--type-small);
  font-weight: var(--weight-title);
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}
.scs-delta.up {
  color: var(--success-fg);
}
.scs-delta.down {
  color: var(--danger-fg);
}
.scs-action {
  font-size: var(--type-small);
  font-weight: var(--weight-strong);
  white-space: nowrap;
}
.scs-money {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 8px;
  margin: 0;
  padding: 10px 12px;
  border-radius: var(--r-md);
  background: var(--bg-tint);
}
.scs-money div {
  display: grid;
  gap: 1px;
  min-width: 0;
}
.scs-money dt {
  font-family: var(--mono);
  font-size: var(--type-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-faint);
}
.scs-money dd {
  margin: 0;
  font-size: var(--type-body);
  font-weight: var(--weight-title);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
.scs-more {
  font-size: var(--type-caption);
  font-weight: var(--weight-strong);
  color: var(--text-faint);
}
.spark {
  flex-shrink: 0;
  overflow: visible;
}
.spark-line {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.spark-area {
  fill: var(--accent-soft);
  stroke: none;
}

/* ---- goals tab ---- */
.goal-list {
  display: grid;
  margin: 0;
  padding: 0;
  list-style: none;
}
.goal-item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  border-top: 1px solid var(--line);
}
.goal-item:first-child {
  border-top: 0;
}
/* A plain .pill (sans, 12px, never mono); one width so the names line up. */
.goal-kind {
  min-width: 56px;
  justify-content: center;
}
.goal-name {
  font-weight: var(--weight-strong);
}
/* Edit and Archive side by side; the edit form takes the whole row. */
.gl-acts {
  display: flex;
  align-items: center;
  gap: 2px;
}
.goal-item.gl-editing {
  display: block;
}
.gl-edit {
  display: grid;
  gap: var(--space-3);
}
.gl-value {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 12rem);
  gap: var(--space-3);
  align-items: start;
}
.gl-worth {
  color: var(--text-dim);
}
.gl-archived {
  margin-top: var(--space-2);
  border-top: 1px solid var(--line);
  padding-top: var(--space-2);
}
.gl-archived > summary::-webkit-details-marker {
  display: none;
}

.gl-archived > summary {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  color: var(--text-dim);
  font-weight: var(--weight-strong);
  cursor: pointer;
}
.gl-archived .goal-item.is-archived .goal-name {
  color: var(--text-dim);
}
@media (max-width: 560px) {
  .gl-value {
    grid-template-columns: minmax(0, 1fr);
  }
  .goal-item:not(.gl-editing) {
    grid-template-columns: auto minmax(0, 1fr);
  }
  .goal-item .gl-acts {
    grid-column: 2;
  }
}
.goal-kinds {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  margin: 0;
  padding: 0;
  border: 0;
}
.goal-kinds legend {
  margin-bottom: 8px;
  padding: 0;
}
.goal-kind-option {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px;
  border: 1px solid var(--line-control);
  border-radius: var(--r-lg);
  background: var(--bg-input);
  cursor: pointer;
}
.goal-kind-option:has(input:checked) {
  border-color: var(--accent);
  box-shadow: var(--focus-ring);
}
.goal-kind-option input {
  margin-top: 4px;
  accent-color: var(--accent);
}
.goal-kind-option > span {
  display: grid;
  gap: 2px;
}
@media (max-width: 480px) {
  .goal-kinds {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ---- share pages ---- */
.share-section {
  padding-block: 32px 56px;
}
.share-container {
  max-width: 1240px;
}
.share-head {
  display: flex;
  align-items: center;
  gap: 16px;
}
.share-head h1 {
  font-size: var(--type-display);
  /* A long address (acme-shop.example.com) beside the agency name must wrap at 390px, not push the page sideways. */
  overflow-wrap: anywhere;
}
.share-head .eyebrow {
  margin-bottom: 4px;
}
.share-logo {
  flex-shrink: 0;
  max-width: 160px;
  height: 44px;
  object-fit: contain;
}
/* White label without a logo: the owner's name in the logo's place. */
.share-brand {
  flex-shrink: 0;
  max-width: 220px;
  padding-right: 16px;
  border-right: 1px solid var(--line);
  font-size: var(--fs-18);
  font-weight: var(--weight-title);
  color: var(--text);
  overflow-wrap: anywhere;
}
/* A long unbroken owner name wraps inside its box instead of pushing the page sideways at 390px. */
header.share-head p.share-brand {
  min-width: 0;
  overflow-wrap: anywhere;
}
@media (max-width: 480px) {
  header.share-head p.share-brand {
    flex-shrink: 1;
    max-width: 40%;
  }
}
/* White-label footer: no link columns, just the owner's name and the theme toggle.
   On the page's own paper, so it is no lighter band in light or dark. */
.wl-footer {
  background: transparent;
}
.wl-footer .footer-bottom {
  margin-top: 0;
  border-top: 0;
}
/* No brand name: the toggle alone, at the end. */
.wl-footer .footer-meta:only-child {
  margin-left: auto;
}
.share-domain {
  margin-top: 2px;
  font-size: var(--type-small);
  color: var(--text-dim);
}
@media (max-width: 720px) {
  .share-section {
    padding-block: 20px 40px;
  }
  .share-head h1 {
    font-size: var(--fs-24);
  }
}

/* ---- Share tab: client invites and connect requests (src/clientShare.ts) ---- */
.ci-form {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: 10px;
}
.ci-form .field {
  margin: 0;
}
.ci-list {
  display: grid;
  margin: 0;
  padding: 0;
  list-style: none;
}
.ci-item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 12px 0;
  border-top: 1px solid var(--line);
}
.ci-avatar {
  width: 34px;
  height: 34px;
  border: 0;
  background: var(--accent-soft);
  color: var(--accent);
}
.ci-icon {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: var(--r-pill);
  background: var(--bg-tint);
  color: var(--text-dim);
}
.ci-email {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font-weight: var(--weight-strong);
  overflow-wrap: anywhere;
}
.ci-meta {
  font-size: var(--type-small);
  color: var(--text-faint);
}
.ci-actions {
  display: flex;
  gap: 6px;
}
.ci-link {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
  min-width: 0;
}
.ci-link code {
  min-width: 0;
  padding: 4px 8px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--bg-tint);
  font-family: var(--mono);
  font-size: var(--type-caption);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ci-connect {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  align-items: end;
  gap: 10px;
}
.ci-connect .field {
  margin: 0;
}
.ci-connect .form-actions {
  margin: 0;
}
@media (max-width: 560px) {
  .ci-form {
    grid-template-columns: minmax(0, 1fr);
  }
  .ci-item {
    grid-template-columns: auto minmax(0, 1fr);
  }
  .ci-actions {
    grid-column: 2;
  }
}

/* ---- the client shell: /client, /client/s/:id, /invite, /connect (src/routes/clients.ts) ---- */
.client-bar {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--header-bg);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.client-bar-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: var(--header-h);
  padding-block: 8px;
}
.client-brand {
  display: flex;
  align-items: center;
  min-width: 0;
}
/* The Sporetag lockup, tile beside the letters, as in the site header: on its own it stacked the tile over the word. */
.client-brand .wordmark {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
  min-height: 44px;
  font-size: 21px;
}
.client-logo {
  max-width: 160px;
  height: 36px;
  object-fit: contain;
}
.client-brand-name {
  font-size: var(--fs-18);
  font-weight: var(--weight-title);
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.client-nav {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: 6px;
}
.client-nav form {
  margin: 0;
}
.client-back svg {
  width: 16px;
  height: 16px;
}
.client-section {
  padding-block: 48px 72px;
}
.client-container {
  max-width: 760px;
}
.client-head {
  margin-bottom: 24px;
}
.client-head .eyebrow {
  margin-bottom: 6px;
}
.client-head h1 {
  font-family: var(--serif);
  font-size: var(--fs-32);
  font-weight: var(--weight-medium);
  letter-spacing: -0.02em;
}
.client-sub {
  margin-top: 6px;
  color: var(--text-dim);
  overflow-wrap: anywhere;
}
.client-list {
  display: grid;
  gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.client-item {
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  background: var(--bg-raised);
  box-shadow: var(--elev-2);
  overflow: hidden;
}
.client-card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 14px;
  padding: 18px 20px;
  color: var(--text);
  text-decoration: none;
  transition: background-color var(--dur-2) ease;
}
.client-card:hover {
  background: var(--bg-hover);
}
.client-card:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.client-card-mark {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: var(--r-lg);
  background: var(--accent-soft);
  color: var(--accent);
}

/* ---- the customizable dashboard (src/dashboard/layout.ts) ---- */

/* No visit yet: one slim line with the next step, above a dashboard that
   still shows what is connected. */
.dash-setup {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 20px;
  padding: 10px 10px 10px 14px;
  background: var(--info-bg);
  border: 1px solid var(--info-line);
  border-radius: var(--r-lg);
}
.dash-setup + .dash {
  margin-top: 16px;
}
.dash-setup-mark {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: var(--r-md);
  background: var(--bg-raised);
  color: var(--accent);
}
.dash-setup-mark svg {
  width: 17px;
  height: 17px;
}
.dash-setup-text {
  flex: 1;
  min-width: 0;
  margin: 0;
  font-size: var(--type-ui);
  color: var(--text-dim);
}
.dash-setup-text strong {
  color: var(--text);
}
.dash-setup .btn {
  flex-shrink: 0;
}
.dash-faint {
  color: var(--text-faint);
  font-weight: var(--weight-medium);
}
.dash-money {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  white-space: nowrap;
}
.dash-more {
  font-size: 0.72em;
  font-weight: var(--weight-title);
  color: var(--text-faint);
}

/* Connected panels: ad spend, sales, email and texts. */
.dash-pill {
  font-size: var(--type-caption);
}
.dash-panel-tag {
  padding: 2px 8px;
  border-radius: var(--r-pill);
  background: var(--bg-hover);
  font-size: var(--type-caption);
  color: var(--text-dim);
}
.dash-rate {
  margin-left: 5px;
  font-size: var(--type-caption);
  font-weight: var(--weight-medium);
  color: var(--text-faint);
}
.dash-foot {
  margin: auto 0 0;
  padding-top: 12px;
  font-size: var(--type-small);
  color: var(--text-faint);
}
.dash-foot a {
  font-weight: var(--weight-strong);
}
.dw-heard-line {
  margin: 0 0 var(--space-2);
  font-size: var(--type-small);
  color: var(--text-dim);
  overflow-wrap: anywhere;
}
.dw-heard-line b {
  color: var(--text);
  font-weight: var(--weight-strong);
}
.client-card-text {
  display: grid;
  gap: 2px;
  min-width: 0;
}
.client-card-name {
  font-size: var(--type-heading);
  font-weight: var(--weight-title);
  overflow-wrap: anywhere;
}
.client-card-line {
  font-size: var(--type-ui);
  color: var(--text-dim);
  overflow-wrap: anywhere;
}
.client-card-line .mono {
  font-size: var(--type-small);
}
.client-card-go {
  color: var(--text-faint);
  transition: transform var(--dur-2) ease, color var(--dur-2) ease;
}
.client-card:hover .client-card-go {
  color: var(--accent);
  transform: translateX(2px);
}
.client-ask {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 11px 20px;
  border-top: 1px solid var(--line);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: var(--type-ui);
  font-weight: var(--weight-strong);
  text-decoration: none;
}
.client-ask span {
  flex: 1;
}
.client-ask svg {
  width: 16px;
  height: 16px;
}
.client-ask:hover {
  text-decoration: underline;
}
.client-asks {
  margin-bottom: 16px;
}
.client-empty p {
  max-width: 420px;
  color: var(--text-dim);
  overflow-wrap: anywhere;
}
.connect-facts {
  display: grid;
  gap: 12px;
  margin: 18px 0 22px;
  padding: 0;
  list-style: none;
  text-align: left;
}
.connect-facts li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 10px;
  font-size: var(--type-body);
  color: var(--text-dim);
}
.connect-facts svg {
  margin-top: 2px;
  color: var(--accent);
}
.connect-hint {
  margin-top: 12px;
  text-align: center;
}
.connect-off {
  margin-top: 22px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
  text-align: center;
}
.connect-pick {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  border: 0;
  text-align: left;
}
.connect-acct {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px;
  border: 1px solid var(--line-control);
  border-radius: var(--r-lg);
  background: var(--bg-input);
  cursor: pointer;
}
.connect-acct:has(input:checked) {
  border-color: var(--accent);
  box-shadow: var(--focus-ring);
}
.connect-acct input {
  margin-top: 4px;
  accent-color: var(--accent);
}
.connect-acct > span {
  display: grid;
  gap: 2px;
}
@media (max-width: 720px) {
  .client-section {
    padding-block: 28px 48px;
  }
  .client-head h1 {
    font-size: var(--fs-28);
  }
}
@media (max-width: 480px) {
  .client-back span {
    display: none;
  }
  .client-card {
    padding: 16px;
  }
}
/* Client cards keep the 16px phone gutter. */
.client-main .auth {
  padding-inline: 16px;
}

/* The key for bars: a small square in the bar color. */
.sw.sw-bar {
  height: 10px;
  border-radius: var(--r-xs);
  background: var(--accent);
}

/* ---- customizing ---- */
.dash-save-state {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-width: 4em;
  font-size: var(--type-small);
  font-weight: var(--weight-strong);
  color: var(--text-faint);
}
.dash-save-state:empty {
  display: none;
}
/* A save that did not land: the line in the danger ink (AA on paper and panels), then its one way out. */
.dash-save-state.is-problem {
  flex-wrap: wrap;
  gap: var(--space-2);
  min-width: 0;
  color: var(--danger-fg);
}

/* Earlier versions: one row each, the time and card count left, Restore right. */
.dash-versions {
  display: flex;
  flex-direction: column;
  margin: var(--space-3) 0 0;
  padding: 0;
  list-style: none;
}
.dash-version {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) 0;
  border-top: 1px solid var(--line);
}
.dash-version:first-child {
  border-top: 0;
}
.dash-version-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
  font-size: var(--type-ui);
}
.dash-version-text span {
  font-size: var(--type-small);
  color: var(--text-dim);
}

/* Arrange on a phone: the cards as a list, 44px buttons to move or remove each. */
.dash-arrange {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  list-style: none;
}
.dash-arrange-row {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) 0;
  border-top: 1px solid var(--line);
}
.dash-arrange-row:first-child {
  border-top: 0;
}
.dash-arrange-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  font-size: var(--type-ui);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dash-arrange .icon-button {
  width: var(--ctl-h-lg);
  height: var(--ctl-h-lg);
}
.dash-arrange .icon-button:disabled {
  opacity: 0.35;
}
.dash-arrange-remove {
  color: var(--danger-fg);
}

/* Small square tools: refresh, undo and redo, a widget's menu. */
.dash .icon-button:disabled {
  opacity: 0.35;
  cursor: default;
  background: transparent;
}
.dash .icon-button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.dw-dragging,
.dw-dragging * {
  cursor: grabbing !important;
  user-select: none;
}
@media (max-width: 720px) {
  .dash-setup {
    flex-wrap: wrap;
    margin-top: 16px;
  }
  .dash-setup .btn {
    justify-content: center;
    width: 100%;
    min-height: 44px;
  }
  .dash-hide-xs {
    display: none;
  }
  .dash-menu-range {
    right: auto;
    left: 0;
  }
  .scs-range {
    margin-left: 0;
  }
}

/* ==== The widget dashboard (public/static/app/analytics.js, src/dashboard/layout.ts) ====
   A 12-column board of cards, edited like Funnel's: drag by the header, resize
   from the corner, Chart settings on the right. Everything here is scoped
   under .dash, .dw (a widget) or .dash-head. */

/* Five line colors for the main chart, in fixed order, the accent first.
   Checked with the dataviz palette validator (lightness band, chroma, CVD
   and normal-vision separation, 3:1 contrast) against #ffffff, #fbfaf7 and
   #f8f6f1 in light, and #23211e and #1c1b18 in dark; all pass. The light set
   is Sporetag's accent with Mokxi's admin series hues, darkened to the band;
   the dark set is Mokxi's dark series. */
.dash {
  --s1: var(--accent);
  --s2: #0f8a78;
  --s3: #c8650f;
  --s4: #b8327f;
  --s5: #6d4fc4;
  --row-h: 124px;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .dash {
    --s1: #3d8ff0;
    --s2: #1f9e8b;
    --s3: #d9701f;
    --s4: #d4508f;
    --s5: #8a70e6;
  }
}
:root[data-theme='dark'] .dash {
  --s1: #3d8ff0;
  --s2: #1f9e8b;
  --s3: #d9701f;
  --s4: #d4508f;
  --s5: #8a70e6;
}

/* ---- header: title and actions, then the date and filters ---- */
.dash-head {
  display: grid;
  gap: 12px;
  min-width: 0;
}
.dash-head-top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px 16px;
}
.dash-head-title {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  min-width: 0;
}
.dash-title {
  margin: 0;
  font-size: var(--type-title);
  font-weight: var(--weight-title);
  letter-spacing: -0.012em;
  line-height: 1.25;
}
.dash-title-input {
  width: min(320px, 100%);
  height: 36px;
  padding: 0 10px;
  /* Dashed says "you can type here"; --line-input keeps it at 3:1. */
  border: 1px dashed var(--line-input);
  border-radius: var(--r-md);
  background: var(--bg-raised);
  color: var(--text);
  font: inherit;
  font-size: var(--fs-18);
  font-weight: var(--weight-title);
}
.dash-title-input:focus {
  border: 1px solid var(--accent);
  outline: 2px solid transparent;
  box-shadow: var(--focus-ring);
}
.dash-head-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}
.dash-head-actions .btn {
  gap: 6px;
}
.dash-refreshed {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  margin-right: 2px;
  font-size: var(--type-small);
  color: var(--text-faint);
  white-space: nowrap;
}
.dash-refresh.is-spinning svg {
  animation: dash-spin 0.8s linear infinite;
}
@keyframes dash-spin {
  to {
    transform: rotate(360deg);
  }
}
.dash-head-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.dash-head-filters .dash-filters {
  margin: 0;
}
.dash-range {
  height: auto;
  min-height: var(--btn-h-md);
  padding: 4px 12px;
}
.dash-range-text {
  display: grid;
  flex: 1;
  min-width: 0;
  line-height: 1.2;
  text-align: left;
}
.dash-range-vs {
  overflow: hidden;
  font-size: var(--type-caption);
  font-weight: var(--weight-medium);
  color: var(--text-faint);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dash-count {
  display: inline-grid;
  place-items: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--r-pill);
  background: var(--accent);
  color: var(--accent-ink);
  font-size: var(--fs-11);
  font-weight: var(--weight-title);
}

/* ---- the board ---- */
.dash-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
  gap: 16px;
  min-width: 0;
}
.dash-body.is-inspecting {
  grid-template-columns: minmax(0, 1fr) 320px;
}
.dw-grid {
  /* --board tells the script the grid is the 12-column board (drag by cell). */
  --board: 1;
  --gap: 16px;
  position: relative;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  /* Sub-rows: 14 to a row's pitch (GRID.SUB in public/static/app/analytics.js),
     so a table or panel is as tall as its content. Each card keeps the gap
     below it as a margin. */
  grid-auto-rows: calc((var(--row-h) + var(--gap)) / 14);
  column-gap: var(--gap);
  min-width: 0;
}
.dw {
  position: relative;
  margin-bottom: var(--gap);
  display: flex;
  flex-direction: column;
  grid-column: var(--x) / span var(--w);
  grid-row: var(--y) / span var(--h);
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--elev-2);
}
.dw-head {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: 8px;
  min-width: 0;
  height: 44px;
  padding: 0 6px 0 14px;
  transition: background-color var(--dur-1) ease;
}
.dw-mark {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  border-radius: var(--r-sm);
  background: var(--bg-tint);
  color: var(--text-dim);
}
.dw-mark .dw-logo svg {
  width: 14px;
  height: 14px;
}
/* A title wraps to a second line before it is cut: "Cost per signup (Meta)" keeps who counted it. */
.dw-title {
  flex: 1;
  min-width: 0;
  margin: 0;
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  font-size: var(--type-ui);
  font-weight: var(--weight-title);
  line-height: 1.3;
  overflow-wrap: anywhere;
}
.dw-head-tools {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  margin-left: auto;
}
/* Square tools sit at the dense row height in the head and on every widget. */
.dw-menu-btn,
.dash-head .icon-button {
  width: var(--ctl-h-sm);
  height: var(--ctl-h-sm);
}
/* The menu sits quiet until the card is pointed at, focused or touched. */
@media (hover: hover) {
  .dw:not(.is-editing) .dw-menu-btn {
    opacity: 0;
    transition: opacity var(--dur-1) ease;
  }
  .dw:hover .dw-menu-btn,
  .dw:focus-within .dw-menu-btn,
  .dw .dw-menu-btn[aria-expanded='true'] {
    opacity: 1;
  }
}
.dw .dropdown .menu-list {
  top: calc(100% + 2px);
}
.dw:has(.menu-list) {
  z-index: 30;
  overflow: visible;
}
.dw-body {
  display: flex;
  flex: 1;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  padding: 0 14px 12px;
  overflow: auto;
  overscroll-behavior: contain;
  container-type: inline-size;
}
.dw-loading {
  padding-top: 6px;
}
.dw-loading > .skeleton-line {
  width: 60%;
}

/* A number tile. When its line is on the main chart, a bar in the line's
   color runs along its top. */
.dw-number .dw-body {
  justify-content: flex-end;
  padding: 0;
}
.dw-num {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: 10px;
  width: 100%;
  min-height: 100%;
  padding: 0 14px 12px;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  text-align: left;
}
.dw-num-toggle {
  cursor: pointer;
  transition: background-color var(--dur-1) ease;
}
.dw-num-toggle:hover {
  background: var(--bg-hover);
}
.dw-num-toggle:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  border-radius: 0 0 var(--r-lg) var(--r-lg);
}
.dw.is-charted::before {
  content: '';
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
  background: var(--tone, var(--accent));
}
.dw.is-charted .dw-mark {
  background: color-mix(in srgb, var(--tone, var(--accent)) 14%, transparent);
  color: var(--tone, var(--accent));
}
.dw-num-text {
  display: grid;
  gap: 2px;
  min-width: 0;
}
.dw-num-main {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 8px;
}
.dw-num-value {
  font-size: var(--fs-28);
  font-weight: var(--weight-title);
  line-height: 1.1;
  letter-spacing: -0.025em;
  white-space: nowrap;
}
.dw-num-value.is-none {
  font-size: var(--fs-24);
  font-weight: var(--weight-strong);
  color: var(--text-faint);
}
.dw-num-sub {
  overflow: hidden;
  font-size: var(--type-caption);
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-faint);
}
.dw-spark {
  width: 84px;
  height: 34px;
  color: var(--tone, var(--accent));
}
.dw-spark svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.dw-spark-line {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.dw-spark-area {
  fill: currentColor;
  opacity: 0.1;
}
/* Today is still filling up: its stretch is dashed, as on the charts. */
.dw-spark-tail {
  stroke-dasharray: 2 3.5;
}
/* A taller tile: the sparkline goes under the number, full width. */
.dw-number.dw-tall .dw-num {
  grid-template-columns: minmax(0, 1fr);
  align-content: end;
}
.dw-number.dw-tall .dw-spark {
  order: -1;
  width: 100%;
  height: 56px;
  margin-bottom: 4px;
}
@container (max-width: 210px) {
  .dw-num {
    grid-template-columns: minmax(0, 1fr);
  }
  .dw-spark {
    display: none;
  }
}

/* Charts fill the card; the script draws them at the box's size. */
.dw-chart {
  flex: 1;
  min-height: 0;
  padding: 0;
}
.dw-chart:focus-visible {
  border-radius: var(--r-md);
}
.dw-panel-chart {
  flex: 0 0 150px;
  margin: 2px 0 10px;
}
.dw-bar {
  fill: var(--accent);
  transition: fill var(--dur-1) ease;
}
.dw-bar.is-hover {
  fill: var(--accent-hover);
}
/* The bar still filling up (today, this hour): a lighter fill and a dashed edge, so a short bar reads as "so far", not a drop. */
.dw-bar.is-partial {
  fill: var(--accent-soft);
  stroke: var(--accent);
  stroke-width: 1.25;
  stroke-dasharray: 3 3;
}
.dw-bar.is-partial.is-hover {
  fill: var(--accent-soft);
  stroke: var(--accent-hover);
}
.dw-line-over {
  stroke: var(--s2);
}
.dash-line.dw-tone-1 {
  stroke: var(--s1);
}
.dash-line.dw-tone-2 {
  stroke: var(--s2);
}
.dash-line.dw-tone-3 {
  stroke: var(--s3);
}
.dash-line.dw-tone-4 {
  stroke: var(--s4);
}
.dash-line.dw-tone-5 {
  stroke: var(--s5);
}
.dw .dash-hdot {
  stroke: var(--bg-raised);
}
.dash-hdot.dw-tone-1,
.dash-dot.dw-tone-1 {
  fill: var(--s1);
}
.dash-hdot.dw-tone-2,
.dash-dot.dw-tone-2 {
  fill: var(--s2);
}
.dash-hdot.dw-tone-3,
.dash-dot.dw-tone-3 {
  fill: var(--s3);
}
.dash-hdot.dw-tone-4,
.dash-dot.dw-tone-4 {
  fill: var(--s4);
}
.dash-hdot.dw-tone-5,
.dash-dot.dw-tone-5 {
  fill: var(--s5);
}
.dw-sw-1 {
  background: var(--s1);
}
.dw-sw-2 {
  background: var(--s2);
}
.dw-sw-3 {
  background: var(--s3);
}
.dw-sw-4 {
  background: var(--s4);
}
.dw-sw-5 {
  background: var(--s5);
}
.dw-dot {
  display: inline-block;
  flex-shrink: 0;
  width: 9px;
  height: 9px;
  border-radius: 50%;
}
.dw-legend {
  display: flex;
  flex-wrap: wrap;
  flex-shrink: 0;
  align-items: center;
  justify-content: flex-end;
  gap: 6px 18px;
  padding-top: 8px;
  font-size: var(--type-small);
  color: var(--text-dim);
}
.dw-legend span {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  white-space: nowrap;
}
.dw-legend.is-multi {
  justify-content: flex-start;
}
.dw-legend b {
  color: var(--text);
  font-weight: var(--weight-title);
}
.dw-legend .dw-legend-note {
  margin-left: auto;
  color: var(--text-faint);
  white-space: normal;
}
.dw .dash-none {
  margin: auto 0;
}

/* Horizontal bars, one per row. */
.dw-hbars {
  display: grid;
  gap: 4px;
  margin: 0;
  padding: 2px 0 0;
  list-style: none;
}
.dw-hbar {
  display: grid;
  grid-template-columns: minmax(0, 36%) minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  min-height: 30px;
  font-size: var(--type-ui);
}
.dw-hbar-name {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
/* One line a name, cut with an ellipsis (the full name is its title), so long campaign names never stack. */
.dw-hbar-name .dash-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow-wrap: normal;
}
.dw-hbar-track {
  height: 10px;
  overflow: hidden;
  border-radius: var(--r-pill);
  background: var(--bg-hover);
}
.dw-hbar-track i {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--accent);
}
.dw-hbar-val {
  min-width: 48px;
  font-weight: var(--weight-title);
  text-align: right;
}

/* Visit breakdown rows: the dashboard's rows, with as many columns as fit. */
.dw-rows-wrap {
  min-width: 0;
}
.dash-colhead.dw-colhead,
.dash-row.dw-row {
  grid-template-columns: minmax(0, 1fr) repeat(var(--n, 2), minmax(52px, auto));
}
.dw .dash-colhead {
  position: sticky;
  top: 0;
  z-index: 1;
  padding-top: 2px;
  background: var(--bg-raised);
}
.dw-tabs {
  flex-shrink: 0;
  margin: 0 0 10px;
}
.dw-tools-row {
  display: flex;
  flex-wrap: wrap;
  flex-shrink: 0;
  align-items: center;
  justify-content: flex-end;
  gap: 6px 8px;
  min-width: 0;
}
.dw-tools-row:empty {
  display: none;
}
.dw-tools-row .dw-tabs {
  flex: 1 1 220px;
  min-width: 0;
  margin: 0 auto 10px 0;
}
.dw-tools-row .dash-panel-tag,
.dw-tools-row .pill {
  flex-shrink: 0;
  white-space: nowrap;
}

/* Tables: a name with a muted line, then numbers on the right. */
.dw-table-wrap {
  min-width: 0;
  margin: 0 -14px;
  overflow-x: auto;
}
/* A table wider than its card fades at the edge that scrolls, so the hidden columns show they are there. */
.dw-table-wrap.fade-end {
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 40px), transparent);
  mask-image: linear-gradient(to right, #000 calc(100% - 40px), transparent);
}
.dw-table-wrap.fade-start {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 40px);
  mask-image: linear-gradient(to right, transparent, #000 40px);
}
.dw-table-wrap.fade-start.fade-end {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 40px, #000 calc(100% - 40px), transparent);
  mask-image: linear-gradient(to right, transparent, #000 40px, #000 calc(100% - 40px), transparent);
}
.dw-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--type-ui);
  font-variant-numeric: tabular-nums;
}
.dw-table th,
.dw-table td {
  padding: 8px 14px;
  text-align: left;
  vertical-align: middle;
}
.dw-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  padding-block: 6px;
  background: var(--bg-raised);
  border-bottom: 1px solid var(--line);
  font-family: var(--mono);
  font-size: var(--type-label);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-faint);
  white-space: nowrap;
}
.dw-table tbody tr + tr {
  border-top: 1px solid var(--line);
}
.dw-table tbody tr:hover {
  background: var(--bg-hover);
}
.dw-table tbody th {
  width: 100%;
  max-width: 0;
  font-weight: var(--weight-medium);
}
.dw-table .num {
  padding-left: 8px;
  text-align: right;
  white-space: nowrap;
}
.dw-table td.num {
  font-weight: var(--weight-title);
}
.dw-cell-name {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
.dw-cell-text {
  display: grid;
  min-width: 0;
}
.dw-cell-main,
.dw-cell-sub {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dw-cell-sub {
  font-size: var(--type-caption);
  color: var(--text-faint);
}
.dw-logo {
  display: inline-grid;
  place-items: center;
  flex-shrink: 0;
  color: var(--text);
}
.dw-logo svg {
  width: 16px;
  height: 16px;
}
.dw-logo .logo-letter {
  display: grid;
  place-items: center;
  width: 16px;
  height: 16px;
  border-radius: var(--r-xs);
  background: var(--accent-soft);
  color: var(--accent);
  font-family: var(--mono);
  font-size: var(--type-label);
  font-weight: var(--weight-title);
}

/* Stat tiles in the connected panels, like the number tiles: lines between. */
.dw-stats {
  display: grid;
  flex-shrink: 0;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px;
  margin-bottom: 12px;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--line);
}
/* Three numbers fill the row, with no empty cell. */
.dw-stats-3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
@container (max-width: 560px) {
  .dw-stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .dw-stats-3 > :last-child {
    grid-column: 1 / -1;
  }
}
.dw-stat {
  display: grid;
  align-content: start;
  gap: 3px;
  min-width: 0;
  padding: 11px 13px;
  background: var(--bg-raised);
}
.dw-stat-label {
  overflow-wrap: anywhere;
  font-family: var(--mono);
  font-size: var(--type-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-faint);
}
.dw-stat-value {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
  font-size: var(--fs-20);
  font-weight: var(--weight-title);
  line-height: 1.2;
  letter-spacing: -0.02em;
}
.dw-stat-sub {
  display: flex;
  align-items: center;
  gap: 6px;
  overflow: hidden;
  font-size: var(--type-caption);
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-faint);
}
.dw .dash-foot {
  flex-shrink: 0;
}
.dw .dash-panel-note {
  flex-shrink: 0;
  margin: 0 0 10px;
}
/* Widget empties are the shared .empty .empty-plain (ui.css), centered in the card. */
.dw .empty {
  flex: 1;
  align-content: center;
  padding: var(--space-3) var(--space-3) var(--space-2);
}
.dw .empty p:not(.empty-title) {
  margin: 0;
}
/* No widgets at all: the framed empty across the board, as tall as it needs. */
.dw-grid:has(> .empty) {
  grid-auto-rows: auto;
}
.dw-grid > .empty {
  grid-column: 1 / -1;
}

/* The skeleton the server draws on the same cells. */
.dw-sk {
  box-shadow: none;
}
.dw-sk-in {
  padding: 14px;
}

/* ---- editing ---- */
.dw.is-editing {
  transition: border-color var(--dur-1) ease, box-shadow var(--dur-1) ease;
}
.dw.is-editing:hover {
  border-color: var(--line-strong);
}
.dw.is-editing .dw-head {
  cursor: grab;
  touch-action: none;
  user-select: none;
}
.dw-grip {
  display: grid;
  place-items: center;
  width: 14px;
  margin-left: -6px;
  color: var(--text-faint);
}
.dw.is-editing:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.dw.is-selected {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent), var(--elev-2);
}
.dw.is-selected .dw-head {
  background: var(--accent-soft);
}
.dw.is-selected .dw-grip {
  color: var(--accent);
}
/* Hints about clicking keep their space while editing, so cards keep their height. */
.dw-hint.is-still,
.dw-notes-pop.is-still {
  visibility: hidden;
}
/* While editing, a widget is a thing to move, not to click through. */
.dw.is-editing .dw-body {
  pointer-events: none;
}
.dw.is-dragging,
.dw.is-resizing {
  z-index: 20;
  box-shadow: var(--elev-4);
}
.dw.is-dragging {
  opacity: 0.94;
  cursor: grabbing;
}
.dw-drop {
  grid-column: var(--x) / span var(--w);
  grid-row: var(--y) / span var(--h);
  margin-bottom: var(--gap);
  border: 2px dashed var(--accent);
  border-radius: var(--r-lg);
  background: var(--accent-soft);
  pointer-events: none;
}
.dw-resize {
  position: absolute;
  right: 0;
  bottom: 0;
  z-index: 2;
  width: 22px;
  height: 22px;
  cursor: nwse-resize;
  touch-action: none;
}
.dw-resize::after {
  content: '';
  position: absolute;
  right: 5px;
  bottom: 5px;
  width: 9px;
  height: 9px;
  border-right: 2px solid var(--text-faint);
  border-bottom: 2px solid var(--text-faint);
  border-bottom-right-radius: var(--r-xs);
}
.dw.is-selected .dw-resize::after,
.dw-resize:hover::after {
  border-color: var(--accent);
}
.dash.is-editing .dash-head {
  position: sticky;
  top: 62px;
  z-index: 40;
  margin: -8px -12px 0;
  padding: 8px 12px 10px;
  border-bottom: 1px solid var(--line);
  border-radius: 0 0 var(--r-lg) var(--r-lg);
  background: var(--bg);
}
.dash.is-editing .dash-save-state {
  min-width: 0;
}

/* ---- Chart settings ---- */
.dw-inspector {
  position: sticky;
  top: 160px;
  display: flex;
  flex-direction: column;
  max-height: calc(100vh - 180px);
  max-height: calc(100dvh - 180px);
  overflow: hidden;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  box-shadow: var(--elev-3);
  animation: dw-in var(--dur-2) var(--ease-out);
}
@keyframes dw-in {
  from {
    opacity: 0;
    transform: translateX(8px);
  }
}
.dw-insp-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 8px 10px 16px;
  border-bottom: 1px solid var(--line);
}
.dw-insp-head h2 {
  margin: 0;
  font-size: var(--type-body);
  font-weight: var(--weight-title);
}
.dw-insp-body {
  display: grid;
  gap: 16px;
  padding: 16px;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.dw-insp-foot {
  display: flex;
  gap: 6px;
  padding: 10px 12px;
  border-top: 1px solid var(--line);
}
.dw-insp-foot .btn {
  gap: 6px;
}
.dw-insp-foot .dw-remove {
  margin-left: auto;
  color: var(--danger-fg);
}
.dw-field {
  display: grid;
  gap: 6px;
  min-width: 0;
}
.dw-field-label {
  font-size: var(--type-small);
  font-weight: var(--weight-strong);
  color: var(--text-dim);
}
.dw-field-hint {
  font-size: var(--type-caption);
  line-height: 1.4;
  color: var(--text-faint);
}
.dw-field .field-input {
  height: 38px;
  font-size: var(--type-ui);
}
.dw-switch-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  cursor: pointer;
}
.dw-switch-row > span {
  display: grid;
  gap: 2px;
}
.dw-stepper {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  width: max-content;
  padding: 2px;
  border: 1px solid var(--line-control);
  border-radius: var(--r-md);
}
.dw-stepper-val {
  min-width: 64px;
  font-size: var(--type-ui);
  font-weight: var(--weight-strong);
  text-align: center;
}
.dw-picker {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  min-height: 38px;
  padding: 6px 10px;
  border: 1px solid var(--line-control);
  border-radius: var(--btn-radius);
  background: var(--bg-raised);
  color: var(--text);
  font: inherit;
  font-size: var(--type-ui);
  text-align: left;
  cursor: pointer;
}
.dw-picker:hover {
  border-color: var(--line-strong);
}
.dw-picker:focus-visible,
.dw-picker[aria-expanded='true'] {
  border-color: var(--accent);
  outline: 2px solid transparent;
  box-shadow: var(--focus-ring);
}
.dw-picker-main {
  display: grid;
  gap: 4px;
  min-width: 0;
}
.dw-picker-item {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  font-weight: var(--weight-strong);
}
.dw-picker-item > span:last-child {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dw-inspector .dropdown {
  display: block;
}
.dw-menu-metrics {
  left: 0;
  right: 0;
  min-width: 0;
  max-height: min(56vh, 440px);
  max-height: min(56dvh, 440px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.dw-menu-group {
  display: flex;
  align-items: center;
  gap: 7px;
}
/* The metric picker: the search box stays on top while the list scrolls under it. */
.dw-menu-metrics {
  padding-top: 0;
}
.dw-find-wrap {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: var(--space-2) var(--space-1) var(--space-1);
  background: var(--bg-raised);
}
.dw-find {
  width: 100%;
}
.dw-pick-row[hidden],
.dw-pick-group[hidden] {
  display: none;
}
/* Each metric's value now, so people pick by seeing: right-aligned, tabular, quiet. */
.dw-pick-val {
  flex-shrink: 0;
  margin-left: auto;
  padding-left: var(--space-3);
  color: var(--text-dim);
  font-size: var(--type-small);
  font-variant-numeric: tabular-nums;
}
.dw-pick-row .dash-menu-text {
  flex: 1 1 auto;
}
.dw-pick-none {
  margin: 0;
  padding: var(--space-3) 10px;
  font-size: var(--type-small);
  color: var(--text-dim);
}
.dw-menu-group .dash-ic,
.dw-menu-group .dw-logo {
  color: var(--text-dim);
}
.dw-menu-group .dw-logo svg {
  width: 13px;
  height: 13px;
}

/* ---- in between: the board flows; widgets keep their order and height ---- */
@media (max-width: 1080px) {
  .dw-grid {
    --board: 0;
    grid-auto-flow: row dense;
  }
  .dw {
    grid-column: span var(--wm);
    grid-row: span var(--h);
    order: var(--o);
  }
  .dw-drop {
    display: none;
  }
  .dash-body.is-inspecting {
    grid-template-columns: minmax(0, 1fr);
    padding-bottom: min(64vh, 560px);
  }
  /* Chart settings become a bottom sheet over the board. */
  .dw-inspector {
    position: fixed;
    right: 0;
    bottom: 0;
    left: 0;
    top: auto;
    z-index: 90;
    max-height: min(64vh, 560px);
    max-height: min(64dvh, 560px);
    border-bottom: 0;
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    box-shadow: var(--elev-4);
    animation-name: dw-up;
  }
  .dw-insp-head {
    position: relative;
    padding-top: 16px;
  }
  .dw-insp-head::before {
    content: '';
    position: absolute;
    top: 6px;
    left: 50%;
    width: 36px;
    height: 4px;
    margin-left: -18px;
    border-radius: var(--r-pill);
    background: var(--line-strong);
  }
  .dw-insp-body {
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    align-items: start;
  }
}
@keyframes dw-up {
  from {
    opacity: 0;
    transform: translateY(24px);
  }
}

/* ---- phones: numbers two a row, everything else the whole width ---- */
@media (max-width: 720px) {
  .dw-grid {
    --gap: 12px;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-rows: auto;
    row-gap: var(--gap);
  }
  .dw {
    grid-column: span var(--wp);
    grid-row: auto;
    margin-bottom: 0;
  }
  .dw-number {
    min-height: 104px;
  }
  /* A row's name takes a second line rather than ending in "...", so "Direct / None" and a page path read whole.
     Three lines at most: a 180-character product path filled a phone screen. The full name is the title. */
  .dash-label {
    display: -webkit-box;
    overflow: hidden;
    white-space: normal;
    overflow-wrap: anywhere;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
  }
  /* Two numbers a row leave no room for the plain # mark: its 30px goes to the name, so "Unique visitors" reads whole. A platform logo stays. */
  .dw-number .dw-mark:not(:has(.dw-logo)) {
    display: none;
  }
  .dw-body {
    overflow: visible;
    padding-inline: 12px;
  }
  .dw-line .dw-chart,
  .dw-bar .dw-chart {
    flex: 0 0 210px;
  }
  .dw-head {
    height: 42px;
    padding-left: 12px;
  }
  .dw-num {
    padding-inline: 12px;
  }
  .dw-num-value {
    font-size: var(--fs-24);
  }
  .dw-table-wrap {
    margin-inline: -12px;
  }
  .dw-table th,
  .dw-table td {
    padding-inline: 12px;
  }
  .dash-title {
    font-size: var(--fs-18);
  }
  .dash-refreshed-text {
    display: none;
  }
  .dash-head-actions {
    margin-left: auto;
  }
  .dash-addcard-start {
    min-width: 44px;
  }
  /* The smallest phones: Share keeps its icon (the label stays its name), so
     the five actions fit on one row. */
  @media (max-width: 359px) {
    .dash-head-actions {
      gap: 6px;
    }
    .dash-share {
      min-width: 44px;
      padding-inline: 0;
      justify-content: center;
    }
    .dash-share > span:not(.dash-ic) {
      display: none;
    }
  }
  .dash-head-filters > .dropdown:first-child {
    flex: 1 1 100%;
  }
  .dash-head-filters .dash-range {
    width: 100%;
  }
  .dash.is-editing .dash-head {
    top: 56px;
    margin-inline: -16px;
    padding-inline: 16px;
    border-radius: 0;
  }
  .dw-resize {
    width: 32px;
    height: 32px;
  }
  .dw-legend .dw-legend-note {
    margin-left: 0;
  }
  .dw-hbar {
    grid-template-columns: minmax(0, 42%) minmax(0, 1fr) auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .dw,
  .dw-inspector,
  .dw-num-toggle,
  .dw-menu-btn {
    animation: none;
    transition: none;
  }
  .dash-refresh.is-spinning svg {
    animation: none;
  }
}
@media (max-width: 720px) {
  .dw-inspector {
    max-height: 52vh;
    max-height: 52dvh;
  }
  .dash-body.is-inspecting {
    padding-bottom: 52vh;
  }
}
@media (max-width: 720px) {
  /* While editing on a phone the sticky bar keeps only the title and actions. */
  .dash.is-editing .dash-head-filters {
    display: none;
  }
}

/* ---- ad rows: sortable headers, the top-N note, and their settings ---- */
.dw-table thead th:has(.dw-sort) {
  padding-block: 2px;
}
.dw-sort {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: 3px;
  min-height: 28px;
  padding: 0 4px;
  margin-right: -4px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  cursor: pointer;
}
.dw-sort:hover:not(:disabled) {
  background: var(--bg-hover);
  color: var(--text);
}
.dw-sort:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 0;
}
.dw-sort:disabled {
  cursor: default;
}
.dw-sort.is-on {
  color: var(--text);
}
.dw-sort-dir {
  font-family: var(--sans);
  font-size: var(--type-caption);
}
.dw-table td.is-sorted {
  color: var(--text);
}
.dw-table-more {
  margin: 0;
  padding: 8px 14px 0;
  font-size: var(--type-caption);
  color: var(--text-faint);
}
.dw-check {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 32px;
  padding: 2px 6px;
  border-radius: var(--r-sm);
  font-size: var(--type-ui);
  cursor: pointer;
}
.dw-check:hover {
  background: var(--bg-hover);
}
.dw-check input {
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  margin: 0;
  accent-color: var(--accent);
}
.dw-check span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dw-rows-all {
  justify-self: start;
}

/* ---- the visitors-now tile ---- */
.dw-live .dw-body {
  justify-content: flex-end;
}
.dw-livebox {
  display: grid;
  gap: 2px;
  padding-bottom: 2px;
}
.dw-live-row {
  display: flex;
  align-items: center;
  gap: 10px;
}
.dw-live-num {
  font-size: var(--fs-28);
  font-weight: var(--weight-title);
  line-height: 1.1;
  letter-spacing: -0.025em;
}
.dw-livebox.on .dash-pulse {
  background: var(--success-fg);
}
.dw-livebox.on .dash-pulse::after {
  content: '';
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  background: var(--success-fg);
  opacity: 0.5;
  animation: dash-pulse 2s cubic-bezier(0.2, 0.6, 0.4, 1) infinite;
}

/* ---- undo and redo while editing ---- */
.dash-undo {
  display: inline-flex;
  gap: 2px;
}
@media (prefers-reduced-motion: reduce) {
  .dash-live.on .dash-pulse::after,
  .dw-livebox.on .dash-pulse::after {
    animation: none;
    /* At rest the ring is a soft halo, not a second solid dot. */
    opacity: 0.25;
  }
}
/* While editing, a widget waiting for its new numbers dims a little. */
.dash.is-refreshing .dw.is-selected .dw-body {
  opacity: 0.55;
  transition: opacity var(--dur-2) ease var(--dur-1);
}
/* In the panels the whole card scrolls, so a table never squeezes into a
   strip of its own; a table widget scrolls inside, under its sticky head. */
.dw-ads .dw-table-wrap,
.dw-sales .dw-table-wrap,
.dw-messages .dw-table-wrap {
  flex-shrink: 0;
}

/* ---- who is on the site: the live pill's list and Recent visitors ---- */
.dash-live-btn {
  font: inherit;
  font-size: var(--type-small);
  cursor: pointer;
  transition: border-color var(--dur-1) ease, background-color var(--dur-1) ease;
}
.dash-live-btn:hover {
  border-color: var(--line-strong);
  background: var(--bg-hover);
}
.dash-live-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.dash-live-btn[aria-expanded='true'] {
  border-color: var(--accent);
}
.dash-live-btn .dash-ic {
  color: var(--text-faint);
}
.menu-list.dw-live-menu {
  width: min(420px, calc(100vw - 32px));
  max-height: min(70vh, 560px);
  max-height: min(70dvh, 560px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.dw-live-head {
  display: grid;
  gap: 2px;
  padding: 8px 10px 10px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 4px;
}
.dw-live-head span {
  font-size: var(--type-small);
  color: var(--text-faint);
}
.dw-live-all {
  margin-top: 4px;
  border-top: 1px solid var(--line);
  border-radius: 0 0 var(--r-md) var(--r-md);
}
.dw-people {
  display: grid;
  gap: 2px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.dw-person {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  min-height: 48px;
  padding: 6px 8px;
  border-radius: var(--r-md);
  color: var(--text);
  text-decoration: none;
}
a.dw-person:hover,
a.dw-person:focus-visible {
  background: var(--bg-hover);
  outline: 2px solid transparent;
  text-decoration: none;
}
a.dw-person:focus-visible {
  box-shadow: inset 0 0 0 2px var(--accent);
}
.dw-person-av {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent);
  font-family: var(--mono);
  font-size: var(--type-label);
  font-weight: var(--weight-title);
}
.dw-person-text {
  display: grid;
  min-width: 0;
}
.dw-person-name {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  overflow: hidden;
  font-size: var(--type-ui);
  font-weight: var(--weight-strong);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dw-person-tag {
  padding: 0 6px;
  border-radius: var(--r-pill);
  background: var(--chip-ok-bg, var(--bg-hover));
  color: var(--chip-ok-fg, var(--text-dim));
  font-size: var(--fs-11);
  font-weight: var(--weight-strong);
}
.dw-person-sub {
  overflow: hidden;
  font-size: var(--type-caption);
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-faint);
}
.dw-person-facts {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--type-small);
  color: var(--text-dim);
  white-space: nowrap;
}
.dw-person-src {
  max-width: 110px;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dw-person-when {
  min-width: 64px;
  text-align: right;
  color: var(--text-faint);
}
.dw-visitors .dw-body {
  padding-inline: 6px;
}
@container (max-width: 420px) {
  .dw-person-src {
    display: none;
  }
}
@media (max-width: 720px) {
  .dw-person-src {
    max-width: 72px;
  }
}
.dw-person-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* A narrow card: the name takes the row's full width, and where from, the
   flag, device and time sit under it on the right, beside the visit count.
   Names and pages wrap rather than end in "...". */
@container (max-width: 420px) {
  .dw-person {
    row-gap: 2px;
  }
  .dw-person-av {
    grid-row: 1 / span 2;
  }
  .dw-person-text {
    display: contents;
  }
  .dw-person-name {
    flex-wrap: wrap;
    grid-column: 2 / -1;
    overflow: visible;
    white-space: normal;
  }
  .dw-person-label,
  .dw-person-sub {
    overflow: visible;
    overflow-wrap: anywhere;
    white-space: normal;
  }
  .dw-person-sub {
    grid-column: 2;
  }
  .dw-person-facts {
    grid-row: 2;
    grid-column: 3;
  }
}
.dw-person-tag {
  flex-shrink: 0;
}
@media (max-width: 720px) {
  .dw-live-menu .dw-person-src {
    display: none;
  }
}

/* ---- no inner scrollbars: charts fit their card, tables and panels grow
   to fit their rows (the script measures them) ---- */
.dw .dw-body {
  overflow: hidden;
}
.dw.dw-auto .dw-body {
  overflow: visible;
}
.dw.dw-auto .dw-table-wrap {
  flex-shrink: 0;
  overflow: visible;
}

/* ---- the main chart's marks for the bucket still filling up ---- */
.dw .dash-dot.dw-today {
  fill: var(--bg-raised);
  stroke: var(--accent);
  stroke-width: 2;
}
/* A line with one number so far (tracking began today): a soft halo and the number beside it. */
.dw .dash-halo {
  fill: var(--accent);
  opacity: 0.16;
}
.dw .dash-halo.dw-tone-1 { fill: var(--s1); }
.dw .dash-halo.dw-tone-2 { fill: var(--s2); }
.dw .dash-halo.dw-tone-3 { fill: var(--s3); }
.dw .dash-halo.dw-tone-4 { fill: var(--s4); }
.dw .dash-halo.dw-tone-5 { fill: var(--s5); }
.dw .dash-solo {
  fill: var(--text);
  font-family: var(--sans);
  font-size: var(--type-caption);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.dw .dash-dot.dw-today.is-real {
  fill: var(--accent);
  stroke: var(--bg-raised);
  stroke-width: 2;
}
.dw .dash-dot.dw-today.dw-tone-1 { stroke: var(--s1); }
.dw .dash-dot.dw-today.dw-tone-2 { stroke: var(--s2); }
.dw .dash-dot.dw-today.dw-tone-3 { stroke: var(--s3); }
.dw .dash-dot.dw-today.dw-tone-4 { stroke: var(--s4); }
.dw .dash-dot.dw-today.dw-tone-5 { stroke: var(--s5); }
.dw .dash-dot.dw-today.is-real.dw-tone-1 { fill: var(--s1); stroke: var(--bg-raised); }
.dw .dash-dot.dw-today.is-real.dw-tone-2 { fill: var(--s2); stroke: var(--bg-raised); }
.dw .dash-dot.dw-today.is-real.dw-tone-3 { fill: var(--s3); stroke: var(--bg-raised); }
.dw .dash-dot.dw-today.is-real.dw-tone-4 { fill: var(--s4); stroke: var(--bg-raised); }
.dw .dash-dot.dw-today.is-real.dw-tone-5 { fill: var(--s5); stroke: var(--bg-raised); }
/* Pointing at a legend item picks its line out. */
.dw-chart .is-dim {
  opacity: 0.16;
  transition: opacity var(--dur-1) ease;
}
.dw-legend-item {
  border-radius: var(--r-sm);
}
.dw-legend-item:focus-visible {
  outline: 2px solid transparent;
  box-shadow: 0 0 0 2px var(--accent);
}

/* ---- number tiles say they can be clicked ---- */
.dw-num-toggle {
  position: relative;
}
.dw-num-toggle > :not(.dw-num-hit):not(.dw-chip-row) {
  pointer-events: none;
}
.dw-num-hit {
  position: absolute;
  inset: 0;
  z-index: 1;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}
.dw-num-hit:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  border-radius: 0 0 var(--r-lg) var(--r-lg);
}
.dw-num-toggle:hover {
  background: var(--bg-hover);
}
.dw-chip-row {
  position: absolute;
  top: -36px;
  right: 40px;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 4px;
  opacity: 0;
  transition: opacity var(--dur-1) ease;
  pointer-events: none;
}
.dw-num-toggle:hover .dw-chip-row,
.dw-num-toggle:focus-within .dw-chip-row,
.dw-chip-row:has([aria-expanded='true']) {
  opacity: 1;
}
.dw-chip-row .dw-swatch-pop {
  pointer-events: auto;
}
@media (hover: none) {
  .dw-chip-row {
    opacity: 1;
  }
}
.dw-chart-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 22px;
  padding: 0 8px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--bg-raised);
  color: var(--text-dim);
  font-size: var(--type-caption);
  font-weight: var(--weight-strong);
  white-space: nowrap;
}
.dw-chart-chip.is-on {
  border-color: color-mix(in srgb, var(--tone, var(--accent)) 45%, var(--line));
  color: var(--text);
}
.dw-hint {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-right: auto;
  padding: 2px 8px;
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: var(--type-caption);
  font-weight: var(--weight-strong);
}
.dw-legend.is-multi .dw-hint {
  order: 9;
}

/* ---- colors: the dot that opens the picker, and the picker ---- */
.dw-swatch-pop {
  display: inline-flex;
}
.dw-swatch-btn {
  width: 18px;
  height: 18px;
  padding: 0;
  border: 2px solid var(--bg-raised);
  border-radius: 50%;
  background: var(--sw, var(--accent));
  box-shadow: 0 0 0 1px var(--line-strong);
  cursor: pointer;
}
.dw-legend .dw-swatch-btn {
  width: 14px;
  height: 14px;
}
.dw-swatch-btn:hover {
  box-shadow: 0 0 0 1px var(--text-dim);
}
.dw-swatch-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.menu-list.dw-color-menu {
  width: 248px;
}
.dw-swatches {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 4px 8px 8px;
}
.dw-swatch {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 2px solid var(--bg-raised);
  border-radius: 50%;
  background: var(--sw, var(--bg-tint));
  box-shadow: 0 0 0 1px var(--line-strong);
  color: var(--text-dim);
  cursor: pointer;
}
.dw-swatch[aria-checked='true'] {
  box-shadow: 0 0 0 2px var(--text);
}
.dw-swatch:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.dw-hex {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr) auto;
  align-items: center;
  gap: 6px;
  padding: 0 8px 4px;
}
.dw-hex-wheel {
  width: 34px;
  height: 34px;
  padding: 2px;
  border: 1px solid var(--line-control);
  border-radius: var(--r-md);
  background: var(--bg-raised);
  cursor: pointer;
}
.dw-hex-text {
  height: 34px;
  font-family: var(--mono);
  font-size: var(--type-small);
}

/* ---- a sparkline with one day of data is a dot ---- */
.dw-spark {
  position: relative;
}
.dw-spark-base {
  stroke: var(--line-strong);
  stroke-width: 1;
}
.dw-spark-dot {
  position: absolute;
  width: 7px;
  height: 7px;
  margin: -3.5px 0 0 -3.5px;
  border-radius: 50%;
  background: currentColor;
}
@media (prefers-reduced-motion: reduce) {
  .dw-chip-row,
  .dw-chart .is-dim {
    transition: none;
  }
}
/* The number tile's chip sits in the header row, above its body. */
.dw.dw-number .dw-body {
  overflow: visible;
}
/* The chart chip lives in the number tile's header, before its menu. */
.dw-head .dw-chip-row {
  position: static;
  margin-right: 2px;
  opacity: 1;
  pointer-events: auto;
}
.dw-head .dw-chip-row:not(.is-on) {
  opacity: 0;
}
.dw:hover .dw-head .dw-chip-row,
.dw:focus-within .dw-head .dw-chip-row {
  opacity: 1;
}
@media (hover: none) {
  .dw-head .dw-chip-row:not(.is-on) {
    opacity: 1;
  }
  .dw-head .dw-chip-row:not(.is-on) .dw-chip-text {
    display: none;
  }
}
.dw-chart-chip {
  cursor: pointer;
  font: inherit;
  font-size: var(--type-caption);
  font-weight: var(--weight-strong);
}
.dw-chart-chip:hover {
  border-color: var(--line-strong);
  color: var(--text);
}
.dw-chart-chip.is-on {
  width: 22px;
  justify-content: center;
  padding: 0;
  border-color: transparent;
  background: color-mix(in srgb, var(--tone, var(--accent)) 16%, transparent);
  color: var(--tone, var(--accent));
}
.dw-chart-chip.is-on .dw-chip-text {
  display: none;
}
/* Hidden chips take no room, so titles stay whole until a tile is pointed at. */
.dw-head .dw-chip-row:not(.is-on) {
  display: none;
}
.dw:hover .dw-head .dw-chip-row,
.dw:focus-within .dw-head .dw-chip-row {
  display: flex;
}
@media (hover: none) {
  .dw-head .dw-chip-row:not(.is-on) {
    display: flex;
  }
}
.dw-color-rows {
  display: grid;
  gap: 6px;
}
.dw-color-row {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: var(--type-ui);
}
.dw-inspector .dw-swatch-pop .menu-list {
  top: calc(100% + 6px);
}

/* ---- round four: clean tiles, the dashboard switcher, goals, headers, segments ---- */
/* Outside edit mode a tile on the chart says so with its top bar; the chip shows on hover only. */
.dw-head .dw-chip-row,
.dw-head .dw-chip-row.is-on {
  display: none;
}
.dw:hover .dw-head .dw-chip-row,
.dw:focus-within .dw-head .dw-chip-row {
  display: flex;
}
@media (hover: none) {
  .dw-head .dw-chip-row,
  .dw-head .dw-chip-row:not(.is-on) {
    display: none;
  }
}
/* In a number tile's head the chip is its plus alone ("Add to chart" is its tooltip), laid
   over the end of the name beside the menu: taking room in the row, it squeezed a
   quarter-width tile's name into "Conversi / ons" on hover. */
.dw-number .dw-head {
  position: relative;
}
.dw-number .dw-head .dw-chip-row {
  position: absolute;
  top: 50%;
  right: calc(6px + var(--ctl-h-sm));
  margin: 0;
  padding-left: var(--space-3);
  background: linear-gradient(to right, transparent, var(--bg-raised) var(--space-3));
  transform: translateY(-50%);
}
.dw-number .dw-head .dw-chip-text {
  display: none;
}
.dw-number .dw-head .dw-chart-chip {
  width: 22px;
  justify-content: center;
  padding: 0;
}
.dw-legend .dw-dot {
  display: inline-block;
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  border-radius: 50%;
}

/* The dashboard switcher: the title is the button. */
.dash-board-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  max-width: 420px;
  min-height: 36px;
  margin-left: -8px;
  padding: 2px 8px;
  border: 0;
  border-radius: var(--r-md);
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: var(--type-title);
  font-weight: var(--weight-title);
  letter-spacing: -0.012em;
  cursor: pointer;
}
.dash-board-btn:hover,
.dash-board-btn[aria-expanded='true'] {
  background: var(--bg-hover);
}
.dash-board-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.dash-board-btn svg {
  flex-shrink: 0;
  color: var(--text-dim);
}
.dash-board-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.menu-list.dash-menu-boards {
  left: -8px;
  width: min(320px, calc(100vw - 32px));
  max-height: min(560px, calc(100vh - 120px));
  max-height: min(560px, calc(100dvh - 120px));
  overflow-y: auto;
}
.dash-menu-boards .dash-menu-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dash-menu-boards .dash-menu-main {
  min-width: 0;
}
.dash-template {
  align-items: flex-start;
  padding-block: 8px;
}
.dash-template-text {
  display: grid;
  gap: 1px;
  text-align: left;
}
.dash-template-text b {
  font-weight: var(--weight-strong);
}
.dash-template-text span {
  color: var(--text-dim);
  font-size: var(--type-small);
}
/* "Show to clients": a menu row that is the shared .switch. */
.menu-row.dash-menu-switch {
  font-weight: inherit;
}
.dash-menu-switch input {
  margin-left: auto;
}

/* ---- dialogs: confirmations, rename, the share link, notes, a new goal ---- */
.dash-share-row {
  display: flex;
  gap: var(--space-2);
}
.dash-share-row .field-input {
  flex: 1 1 auto;
  min-width: 0;
}
.dialog .dw-goal-maker {
  padding: 0;
  border: 0;
  background: transparent;
}
.dialog .dw-gm-head {
  display: none;
}
.dash-goal-pick {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--text-dim);
  font-size: var(--type-small);
  font-weight: var(--weight-strong);
}
.dash-goal-pick .field-input {
  width: auto;
  max-width: 180px;
  height: 32px;
  padding-block: 0;
  font-size: var(--type-small);
}
.dw-goal-none {
  margin: 0;
}
@media (max-width: 640px) {
  .dash-board-btn {
    max-width: calc(100vw - 150px);
    font-size: var(--fs-18);
  }
}

/* Ad headers: every column named over its values, on up to two lines held to the bottom so the
   one-line names sit on the same baseline; a longer name ends in an ellipsis, the full name on hover. */
.dw.dw-auto .dw-table-wrap:has(.dw-ad-table) {
  overflow-x: auto;
  overflow-y: hidden;
}
.dw-ad-table thead th.num {
  max-width: 152px;
  vertical-align: bottom;
}
.dw-ad-table thead th:first-child {
  vertical-align: bottom;
}
.dw-ad-table th,
.dw-ad-table td {
  padding-inline: 10px;
}
.dw-ad-table tbody th {
  min-width: 150px;
}
/* A tall ad panel gives spare room to its chart, never to blank space under the rows. */
.dw.dw-auto .dw-panel-chart {
  flex: 1 0 150px;
}
.dw-ad-table .dw-sort {
  max-width: 100%;
  margin-right: 0;
  padding-inline: 0;
}
.dw-sort-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dw-ad-table .dw-sort {
  align-items: flex-end;
}
.dw-ad-table .dw-sort-text {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  /* As wide as the name up to the cap, so the column never squeezes it to one word a line. */
  width: max-content;
  max-width: 132px;
  white-space: normal;
  text-align: right;
  text-wrap: balance;
}
.dw-ad-table th.num,
.dw-ad-table td.num {
  text-align: right;
}

.dw-ad-table thead th:first-child,
.dw-ad-table tbody th {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--bg-raised);
}
.dw-ad-table thead th:first-child {
  z-index: 2;
}
.dw-ad-table tbody tr:hover th {
  background: var(--bg-hover);
}
@media (max-width: 640px) {
  .dw-ad-table tbody th {
    min-width: 128px;
    max-width: 150px;
  }
}

/* A one-row tile with nothing connected: one quiet line and a Connect link, no mark. */
.dw-number .empty {
  justify-items: start;
  align-content: end;
  gap: var(--space-1);
  padding: 0 14px 12px;
  text-align: left;
}
.dw-number .empty-mark {
  display: none;
}
.dw-number .empty p:not(.empty-title) {
  font-size: var(--type-small);
}
.dw-number .empty .btn {
  min-height: 0;
  height: auto;
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
  color: var(--accent);
  margin: 0;
  font-weight: var(--weight-strong);
}
.dw-number .empty .btn:hover {
  text-decoration: underline;
}

/* ---- Chart settings on wide screens: the board keeps its real width (the drawer is below) ---- */
@media (min-width: 1081px) {
  .dash-body.is-inspecting {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ---- a goal made in the editor ---- */
.dw-goal-maker {
  display: grid;
  gap: 12px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--bg-tint);
}
.dw-gm-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin: -4px -4px -4px 0;
  font-size: var(--type-ui);
}
.dw-gm-ideas {
  display: grid;
  gap: 6px;
}
.dw-gm-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.dw-gm-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  max-width: 100%;
  min-height: 30px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--bg-raised);
  color: var(--text);
  font: inherit;
  font-size: var(--type-small);
  font-weight: var(--weight-strong);
  cursor: pointer;
}
.dw-gm-chip span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dw-gm-chip:hover:not(:disabled) {
  border-color: var(--accent);
  color: var(--accent);
}
.dw-gm-chip:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.dw-gm-form {
  display: grid;
  gap: 12px;
}
.dw-gm-form .dw-field-hint {
  margin: 0;
}
.dw-gm-error {
  margin: 0;
  color: var(--danger-fg);
  font-size: var(--type-small);
}
.dw-gm-actions {
  display: flex;
  justify-content: flex-end;
}
.dash-goal-new {
  gap: 6px;
}

/* The edit bar keeps to one row at 1280: a shorter title field and goal picker. */
@media (min-width: 1081px) {
  .dash.is-editing .dash-title-input {
    width: min(240px, 100%);
  }
  .dash-goal-pick .field-input {
    max-width: 160px;
  }
}

/* ---- Chart settings: one calm system (sizes as Mokxi's comfortable controls) ---- */
.dw-inspector {
  --ctl-h: 36px;
  --ctl-r: 8px;
  --ctl-px: 10px;
  --ctl-fs: 14px;
}
.dw-insp-head {
  flex-shrink: 0;
  align-items: flex-start;
  padding: 14px 10px 12px 20px;
}
.dw-insp-heading {
  display: grid;
  gap: 2px;
  min-width: 0;
}
.dw-insp-kicker {
  color: var(--text-faint);
  font-size: var(--type-caption);
  font-weight: var(--weight-strong);
}
.dw-insp-head h2.dw-insp-name {
  overflow: hidden;
  margin: 0;
  font-size: var(--type-heading);
  font-weight: var(--weight-title);
  line-height: 1.3;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dw-inspector .dw-insp-body {
  display: block;
  flex: 1 1 auto;
  min-height: 0;
  padding: 0;
  overflow-x: hidden;
  overflow-y: auto;
}
.dw-sec {
  display: grid;
  gap: 14px;
  padding: 18px 20px 20px;
}
.dw-sec + .dw-sec {
  border-top: 1px solid var(--line);
}
.dw-sec-title {
  margin: 0;
  color: var(--text);
  font-size: var(--type-small);
  font-weight: var(--weight-title);
  letter-spacing: 0;
}
.dw-sec-body {
  display: grid;
  gap: 14px;
  min-width: 0;
}
.dw-inspector .dw-field {
  display: grid;
  gap: 6px;
  min-width: 0;
}
.dw-inspector .dw-field-label {
  color: var(--text-dim);
  font-size: var(--type-small);
  font-weight: var(--weight-strong);
  line-height: 1.3;
}
.dw-inspector .dw-field-hint {
  margin: 0;
  color: var(--text-faint);
  font-size: var(--type-small);
  line-height: 1.4;
}
.dw-field-pair {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 12px;
  align-items: start;
}
/* Every input, select and picker: one height, radius and padding. */
.dw-inspector .field-input,
.dw-inspector .dw-picker,
.dw-inspector .dw-static {
  box-sizing: border-box;
  width: 100%;
  min-width: 0;
  height: var(--ctl-h);
  min-height: var(--ctl-h);
  padding: 0 var(--ctl-px);
  border-radius: var(--ctl-r);
  font-size: var(--ctl-fs);
  line-height: 1.2;
}
.dw-inspector select.field-input {
  padding-right: 30px;
  text-overflow: ellipsis;
}
.dw-inspector .dw-picker {
  display: flex;
  align-items: center;
  gap: 8px;
  height: auto;
  padding-block: 6px;
}
.dw-static {
  display: flex;
  align-items: center;
  border: 1px dashed var(--line);
  color: var(--text-dim);
}
.dw-inspector .segmented {
  --seg-h: var(--ctl-h);
  display: flex;
  width: 100%;
}
.dw-inspector .segment {
  flex: 1 1 0;
  min-width: 0;
  padding-inline: var(--space-2);
  overflow: hidden;
  text-overflow: ellipsis;
}
.dw-inspector .dw-stepper {
  display: grid;
  grid-template-columns: var(--ctl-h) minmax(0, 1fr) var(--ctl-h);
  align-items: center;
  width: 100%;
  height: var(--ctl-h);
  box-sizing: border-box;
  border: 1px solid var(--line);
  border-radius: var(--ctl-r);
  background: var(--bg-raised);
}
.dw-step {
  display: grid;
  place-items: center;
  height: 100%;
  border: 0;
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
}
.dw-step:hover:not(:disabled) {
  color: var(--text);
}
.dw-step:disabled {
  opacity: 0.4;
  cursor: default;
}
.dw-step:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  border-radius: var(--ctl-r);
}
.dw-inspector .dw-stepper-val {
  text-align: center;
  font-size: var(--ctl-fs);
}
.dw-inspector .dw-switch-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.dw-switch-text {
  display: grid;
  gap: 2px;
}
.dw-link {
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent);
  font: inherit;
  font-size: var(--type-small);
  font-weight: var(--weight-strong);
  cursor: pointer;
  justify-self: start;
}
.dw-link:disabled {
  color: var(--text-faint);
  cursor: default;
}
.dw-link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}

/* Checklists: names wrap to two lines, never sideways; no box of their own to scroll. */
.dw-checklist {
  display: grid;
  min-width: 0;
  border: 1px solid var(--line);
  border-radius: var(--ctl-r);
  background: var(--bg-raised);
}
.dw-checklist-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: var(--ctl-h);
  padding: 6px 10px;
  border-bottom: 1px solid var(--line);
}
.dw-inspector .dw-checklist-find {
  flex: 1 1 auto;
  height: 28px;
  min-height: 28px;
  padding: 0 8px;
  font-size: var(--type-small);
}
.dw-checklist-count {
  margin-right: auto;
  color: var(--text-faint);
  font-size: var(--type-small);
  white-space: nowrap;
}
.dw-checklist-find + .dw-checklist-count {
  margin-right: 0;
}
.dw-checklist-items {
  display: grid;
  min-width: 0;
  padding: 4px 0;
}
.dw-inspector .dw-check {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  align-items: start;
  gap: 10px;
  min-width: 0;
  padding: 7px 10px;
  font-size: var(--ctl-fs);
  line-height: 1.3;
  cursor: pointer;
}
.dw-inspector .dw-check[hidden] {
  display: none;
}
.dw-inspector .dw-check:hover {
  background: var(--bg-hover);
}
.dw-inspector .dw-check input {
  width: 16px;
  height: 16px;
  margin: 1px 0 0;
  accent-color: var(--accent);
}
.dw-check-text {
  display: -webkit-box;
  min-width: 0;
  overflow: hidden;
  overflow-wrap: anywhere;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
}

/* The footer: Remove on the left, Done on the right. */
.dw-inspector .dw-insp-foot {
  flex-shrink: 0;
  align-items: center;
  gap: 6px;
  padding: 12px 16px;
}
.dw-inspector .dw-insp-foot .dw-done {
  min-width: 84px;
  margin-left: auto;
}
.dw-inspector .dw-goal-maker {
  gap: 14px;
  padding: 14px;
  border-radius: var(--ctl-r);
}

/* ---- the drawer itself (wide screens) ---- */
@media (min-width: 1081px) {
  .dw-inspector.is-drawer {
    position: fixed;
    right: 16px;
    bottom: 16px;
    left: auto;
    z-index: 92;
    width: 380px;
    max-width: calc(100vw - 32px);
    max-height: none;
    border-radius: var(--r-xl);
    box-shadow: var(--elev-4);
    animation: dw-drawer-in var(--dur-2) var(--ease-out);
  }
  .dw-inspector.is-drawer.is-left {
    right: auto;
    left: 16px;
    animation-name: dw-drawer-in-left;
  }
  /* Everything but the selected widget and the edit bar sits under a soft dim. */
  .dash.has-drawer::after {
    content: '';
    position: fixed;
    inset: 0;
    z-index: 88;
    background: color-mix(in srgb, var(--scrim) 58%, transparent);
    pointer-events: none;
    animation: dw-fade var(--dur-2) var(--ease-out);
  }
  .dash.has-drawer .dw.is-selected {
    z-index: 90;
    box-shadow: 0 0 0 2px var(--accent), var(--elev-3);
  }
  .dash.has-drawer.is-editing .dash-head {
    z-index: 91;
  }
}
@keyframes dw-drawer-in {
  from {
    opacity: 0;
    transform: translateX(16px);
  }
}
@keyframes dw-drawer-in-left {
  from {
    opacity: 0;
    transform: translateX(-16px);
  }
}
@keyframes dw-fade {
  from {
    opacity: 0;
  }
}
@media (prefers-reduced-motion: reduce) {
  .dw-inspector.is-drawer,
  .dash.has-drawer::after {
    animation: none;
  }
}
/* Phones: the sheet, with finger-sized controls. */
@media (max-width: 720px) {
  .dw-inspector {
    --ctl-h: 44px;
    --ctl-fs: 16px;
  }
  .dw-sec {
    padding: 16px;
  }
  .dw-field-pair {
    grid-template-columns: minmax(0, 1fr);
  }
}
.dw-inspector .dw-insp-foot {
  justify-content: flex-start;
}
.dw-field-pair.dw-pair-auto {
  grid-template-columns: minmax(0, 1fr) auto;
}
.dw-inspector .dw-pair-auto .segmented {
  width: auto;
}
.dw-inspector .dw-pair-auto .segment {
  flex: 0 0 auto;
  padding-inline: 10px;
}
.dw-inspector .dw-insp-foot .dw-remove {
  margin-left: 0;
}

/* ---- notes on the chart (src/dashboard/notes.ts) ---- */
/* A small flag on the baseline of a day with a note; the note reads in the tip. */
.dash-note line {
  stroke: var(--text-faint);
  stroke-width: 1.25;
}
.dash-note circle {
  fill: var(--accent);
  stroke: var(--bg-raised);
  stroke-width: 1.5;
}
.dash-svg.is-drillable {
  cursor: pointer;
}
.dash-tip-note {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  max-width: 240px;
  margin-top: 4px;
  padding-top: 6px;
  border-top: 1px solid var(--line);
  color: var(--text);
  white-space: normal;
}
.dash-tip-note .dash-ic {
  margin-top: 3px;
  color: var(--accent);
}
.dw-notes-pop {
  display: inline-flex;
}
.dw-notes-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-height: 32px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--text-dim);
  font: inherit;
  font-size: var(--type-small);
  cursor: pointer;
}
.dw-notes-btn:hover,
.dw-notes-btn[aria-expanded='true'] {
  border-color: var(--line-strong);
  color: var(--text);
}
/* The notes dialog: this period's notes, then a day and a line to add one. */
.dash-notes {
  display: grid;
  max-height: 220px;
  margin: 0;
  padding: 0;
  overflow-y: auto;
  list-style: none;
}
.dash-notes-item {
  display: grid;
  grid-template-columns: 52px minmax(0, 1fr) auto;
  gap: 8px;
  align-items: center;
  padding: 4px 4px 4px 6px;
  border-radius: var(--r-md);
  font-size: var(--type-ui);
}
.dash-notes-item.is-day {
  background: var(--accent-soft);
}
.dash-notes-day {
  font-family: var(--mono);
  font-size: var(--type-caption);
  color: var(--text-faint);
}
.dash-notes-text {
  overflow-wrap: anywhere;
}
.dash-notes-auto {
  display: block;
  font-size: var(--type-caption);
  color: var(--text-faint);
}
.dash-notes .icon-button {
  width: var(--ctl-h-sm);
  height: var(--ctl-h-sm);
}
.dash-notes-row {
  grid-template-columns: 132px minmax(0, 1fr);
}
@media (max-width: 720px) {
  .dw-notes-btn {
    min-height: 44px;
  }
  .dash-head .icon-button,
  .dash-notes .icon-button {
    width: var(--ctl-h-lg);
    height: var(--ctl-h-lg);
  }
  .dash-notes-row {
    grid-template-columns: 1fr;
  }
}

/* A revenue widget's takeaway: one sentence above its numbers (src/revenue/report.ts). */
.dw-take {
  margin: 0 0 var(--space-3);
  font-size: var(--type-body);
  line-height: var(--lh-snug);
  color: var(--text);
  text-wrap: pretty;
}

/* Ad spend card: a row's own result kind under its count, names that open Attribution. */
.dw-cell-link {
  color: inherit;
  text-decoration: none;
}
.dw-cell-link:hover,
.dw-cell-link:focus-visible {
  text-decoration: underline;
  text-underline-offset: 2px;
}
.dw-cell-kind {
  display: block;
  font-size: var(--type-caption);
  font-weight: 400;
  color: var(--text-faint);
  white-space: nowrap;
}

/* The one line on what keeps ads untied, with Copy parameters and How. */
.dw-ad-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  flex-shrink: 0;
  margin-top: 10px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--bg-hover);
}
.dw-ad-foot-text {
  flex: 1 1 240px;
  min-width: 0;
  margin: 0;
  font-size: var(--type-caption);
  color: var(--text-dim);
}
.dw-ad-foot-actions {
  display: flex;
  align-items: center;
  gap: 12px;
}

/* Customize: ordered picks (numbers on top, columns) and column sets. */
.dw-cols {
  display: grid;
  gap: 8px;
  min-width: 0;
}
.dw-presets {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.dw-presets .dw-gm-chip[aria-pressed='true'] {
  border-color: var(--accent);
  color: var(--accent);
}
.dw-ordered {
  display: grid;
  gap: 6px;
  min-width: 0;
}
.dw-ordered-items {
  display: grid;
  gap: 2px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.dw-ordered-item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto auto;
  align-items: center;
  gap: 2px;
  padding: 2px 2px 2px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}
.dw-ordered-name {
  overflow: hidden;
  font-size: var(--type-ui);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dw-ordered-btn {
  width: 32px;
  height: 32px;
}
.dw-ordered-btn:disabled {
  opacity: 0.35;
}
/* Ad card labels name who counted them ("Cost per signup (Meta)"): they wrap rather than lose the platform. */
.dw-stat.dw-by-platform .dw-stat-label,
.dw-stat.dw-by-sporetag .dw-stat-label {
  white-space: normal;
  overflow-wrap: anywhere;
}

/* ---- the Card editor: metric, Show as and Split by up front; the rest under More ---- */
.dw-shape {
  width: 100%;
}
.dw-shape .segment {
  flex: 1 1 0;
}
.dw-more {
  border-top: 1px solid var(--line);
}
.dw-more-sum {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--ctl-h-lg);
  padding: 0 20px;
  list-style: none;
  cursor: pointer;
  font-size: var(--type-small);
  font-weight: var(--weight-title);
  color: var(--text);
}
.dw-more-sum::-webkit-details-marker {
  display: none;
}
.dw-more-sum:hover {
  background: var(--bg-hover);
}
.dw-more-sum:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.dw-more-hint {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-faint);
  font-weight: var(--weight-medium);
}
.dw-more-sum .dash-ic {
  color: var(--text-dim);
  transition: transform var(--dur-2) var(--ease-out);
}
.dw-more[open] .dw-more-sum .dash-ic {
  transform: rotate(180deg);
}
.dw-more-body {
  display: grid;
  gap: 14px;
  padding: 4px 20px 20px;
}
.dw-filters {
  display: grid;
  gap: var(--space-2);
}
.dw-filter-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 36px;
  padding: 0 4px 0 var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--bg-panel);
}
.dw-filter-text {
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
  font-size: var(--type-small);
  color: var(--text-dim);
}
.dw-filter-text b {
  color: var(--text);
  font-weight: var(--weight-strong);
}
.dw-filter-new {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr) auto;
  gap: var(--space-2);
  align-items: center;
}
.dw-filter-add {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  justify-self: start;
  min-height: 32px;
}
@media (max-width: 520px) {
  .dw-filter-new {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }
  .dw-filter-new .dw-filter-ok {
    grid-column: 1 / -1;
  }
}

/* ---- tabs past three: More, a quiet select that reads as a tab ---- */
.dw-tab-more {
  position: relative;
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  gap: 2px;
  padding: 0 6px 0 9px;
  border-radius: var(--r-sm);
  color: var(--text-dim);
  font-size: var(--type-small);
  font-weight: var(--weight-strong);
}
.dw-tab-more:hover {
  background: var(--bg-hover);
  color: var(--text);
}
.dw-tab-more.is-on {
  background: var(--bg-hover);
  color: var(--text);
}
.dw-tab-select {
  /* As wide as the option shown ("More", or the view picked), not the longest one. */
  field-sizing: content;
  appearance: none;
  min-height: 30px;
  padding: 0 14px 0 0;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  cursor: pointer;
}
.dw-tab-select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}
.dw-tab-more .dash-ic {
  position: absolute;
  right: 6px;
  pointer-events: none;
}

/* ---- empty in one line, with its action ---- */
.dw-empty-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  padding: var(--space-2) 0;
  color: var(--text-dim);
  font-size: var(--type-ui);
}
.dw-empty-line .dash-ic {
  color: var(--text-faint);
}

/* ---- a card the dashboard's filters cannot narrow: greyed, one line says so ---- */
.dw.is-unfiltered:not(.dw-number) .dw-body,
.dw-number.is-unfiltered .dw-num-main,
.dw-number.is-unfiltered .dw-num svg {
  opacity: 0.45;
}
.dw-unfiltered {
  margin: 0;
  padding: 0 16px 12px;
  color: var(--text-dim);
  font-size: var(--type-caption);
}
/* Phones (npm run check:visual): a number tile's name may take two lines
   rather than end in "...", and the site's address sits on its own line above
   its two pills. */
@media (max-width: 720px) {
  .dw-number .dw-head {
    height: auto;
    min-height: 42px;
  }
  .dw-number .dw-title {
    /* The whole name: a clamp with visible overflow painted its third line over the number. */
    display: block;
    overflow: visible;
    -webkit-line-clamp: none;
    line-clamp: none;
    white-space: normal;
    line-height: 1.2;
  }
  .dash-sub > :first-child {
    flex-basis: 100%;
  }
}

/* ---- Add card: one sheet (openAddSheet, src/dashboard/suggest.ts) ----
   Suggested on top, then search, then templates. Each card is one row a
   finger tall: its mark, its name, one line of why, and a plus. On a phone
   the dialog is already a bottom sheet (ui.css). */
/* Wider than a plain dialog on a desk; a phone keeps ui.css's full-width sheet. */
@media (min-width: 721px) {
  .dash-add-sheet {
    width: min(560px, calc(100vw - 32px));
  }
}
.dash-add-sheet .dialog-body {
  gap: var(--space-6);
  padding-bottom: var(--space-6);
}
.dash-add-sec {
  display: grid;
  gap: var(--space-2);
  min-width: 0;
}
.dash-add-h {
  margin: 0;
  font-family: var(--mono);
  font-size: var(--type-label);
  font-weight: 400;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-faint);
}
.dash-add-list {
  display: grid;
  gap: 2px;
  min-width: 0;
}
.dash-add-list:empty {
  display: none;
}
.dash-add-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  min-width: 0;
  min-height: var(--ctl-h-lg);
  padding: var(--space-2) var(--space-3) var(--space-2) var(--space-2);
  text-align: left;
  font: inherit;
  color: var(--text);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-md);
  cursor: pointer;
  transition: background var(--dur-1) ease, border-color var(--dur-1) ease;
}
.dash-add-row:hover:not(:disabled) {
  background: var(--bg-hover);
}
.dash-add-row:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.dash-add-row:disabled {
  cursor: default;
}
.dash-add-row:disabled .dash-add-title {
  color: var(--text-dim);
}
.dash-add-mark {
  display: grid;
  flex: 0 0 auto;
  place-items: center;
  width: 32px;
  height: 32px;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: var(--r-md);
}
.dash-add-text {
  display: grid;
  flex: 1 1 auto;
  min-width: 0;
  gap: 1px;
}
/* Names and reasons wrap rather than end in "...": a cut name hides which card it is. */
.dash-add-title {
  font-size: var(--type-ui);
  font-weight: var(--weight-strong);
  line-height: var(--lh-snug);
  overflow-wrap: anywhere;
}
.dash-add-why {
  font-size: var(--type-small);
  line-height: var(--lh-snug);
  color: var(--text-dim);
}
.dash-add-plus {
  display: grid;
  flex: 0 0 auto;
  place-items: center;
  width: 28px;
  height: 28px;
  color: var(--text-faint);
  border-radius: var(--r-pill);
  transition: color var(--dur-1) ease, background var(--dur-1) ease;
}
.dash-add-row:hover:not(:disabled) .dash-add-plus,
.dash-add-row:focus-visible .dash-add-plus {
  color: var(--accent);
  background: var(--accent-soft);
}
.dash-add-skel {
  height: 48px;
  border-radius: var(--r-md);
}
.dash-add-find {
  width: 100%;
}
.dash-add-note {
  margin: 0;
  padding: var(--space-2) 0;
  font-size: var(--type-small);
  color: var(--text-dim);
}
.dash-add-tpls {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2);
}
.dash-add-tpl {
  display: grid;
  align-content: start;
  gap: 2px;
  min-width: 0;
  min-height: var(--ctl-h-lg);
  padding: var(--space-2) var(--space-3);
  text-align: left;
  font: inherit;
  color: var(--text);
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  cursor: pointer;
  transition: background var(--dur-1) ease, border-color var(--dur-1) ease;
}
.dash-add-tpl:hover {
  background: var(--bg-hover);
  border-color: var(--line-strong);
}
.dash-add-tpl:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.dash-add-tpl b {
  font-size: var(--type-ui);
  font-weight: var(--weight-strong);
}
.dash-add-tpl span {
  font-size: var(--type-small);
  line-height: var(--lh-snug);
  color: var(--text-dim);
}
/* The title holds focus on a phone (see openAddSheet); it needs no ring. */
.dash-add-sheet .dialog-title:focus:not(:focus-visible) {
  outline: 2px solid transparent;
}
/* A card just added says where it landed, then lets go. */
.dw.is-new {
  box-shadow: 0 0 0 2px var(--accent), var(--shadow-card);
  transition: box-shadow var(--dur-4) var(--ease-out);
}
@media (max-width: 520px) {
  .dash-add-tpls {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ---- card sentences, targets and unusual changes (src/dashboard/insight.ts, pace.ts) ---- */
/* The sentence is the tile's one line of small print: dimmer than the number,
   a little stronger than a plain note, since it says why. */
.dw-num-why {
  color: var(--text-dim);
}
.dw-number.dw-tall .dw-num-why {
  overflow: visible;
  white-space: normal;
  line-height: 1.35;
}
/* A one-row tile with a sentence: the text takes the whole width. */
.dw-num-text.is-wide {
  grid-column: 1 / -1;
}
.dw-num-text.is-wide .dw-num-why {
  overflow: visible;
  white-space: normal;
  line-height: 1.3;
}
/* A target spans the tile under the number: bar, where it stands, its pace. */
.dw-target {
  grid-column: 1 / -1;
  display: grid;
  gap: var(--space-1);
  min-width: 0;
  --target: var(--accent);
}
.dw-target.is-good {
  --target: var(--success);
}
.dw-target.is-warn {
  --target: var(--warning);
}
.dw-target.is-bad {
  --target: var(--danger);
}
.dw-target-bar {
  position: relative;
  display: block;
  height: 6px;
  margin-top: var(--space-1);
  border-radius: var(--r-pill);
  background: var(--bg-tint);
  box-shadow: inset 0 0 0 1px var(--line);
}
.dw-target-fill {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--target);
}
/* Where the bar should be by today on pace. */
.dw-target-mark {
  position: absolute;
  top: -3px;
  bottom: -3px;
  width: 2px;
  margin-left: -1px;
  border-radius: 1px;
  background: var(--text);
}
.dw-target-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-2);
  min-width: 0;
  font-size: var(--type-caption);
}
.dw-target-head {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--type-caption);
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.dw-target-status {
  flex: none;
  font-weight: var(--weight-strong);
  color: var(--text-dim);
}
.dw-target.is-good .dw-target-status {
  color: var(--success-fg);
}
.dw-target.is-warn .dw-target-status {
  color: var(--warning-fg);
}
.dw-target.is-bad .dw-target-status {
  color: var(--danger-fg);
}
.dw-target-line {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--type-caption);
  color: var(--text-faint);
}
/* An unusual change: a dot and its words in the header, linked to its cause. */
.dw-unusual {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  justify-content: center;
  min-width: 24px;
  min-height: 24px;
  margin-right: 2px;
  padding: 0 8px;
  border-radius: var(--r-pill);
  background: var(--warning-bg);
  color: var(--warning-fg);
  font-size: var(--type-caption);
  font-weight: var(--weight-strong);
  white-space: nowrap;
  text-decoration: none;
}
a.dw-unusual:hover {
  text-decoration: underline;
}
a.dw-unusual:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.dw-unusual:not(:has(.dw-unusual-text)) {
  padding: 0;
}
.dw-unusual-dot {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--warning);
}
@media (max-width: 720px) {
  /* Two tiles a row: the dot alone, its words in the label. */
  .dw-unusual {
    justify-content: center;
    padding: 0;
  }
  .dw-unusual-text {
    display: none;
  }
  .dw-num-why {
    overflow: visible;
    white-space: normal;
    line-height: 1.35;
  }
}
@media (forced-colors: active) {
  .dw-target-fill,
  .dw-target-mark,
  .dw-unusual-dot {
    background: CanvasText;
  }
}

/* Days before tracking began (src/tracking/start.ts): no data, not 0. A muted hatch, the line starts where data does. */
.dash-nodata-hatch {
  stroke: var(--line);
  stroke-width: 1.5;
}
.dash-nodata-text {
  fill: var(--text-faint);
  font-size: var(--type-caption);
}

/* ---- card states (src/dashboard/resolve.ts cardState) ----
   A card held by a state says one line and offers one action, centered in
   the card; on a one-row tile they sit left under the title. */
.dw-state {
  display: flex;
  flex: 1;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  min-height: 0;
  padding: var(--space-2) 0;
  text-align: center;
}
.dw-state-text {
  max-width: 34ch;
  margin: 0;
  font-size: var(--type-small);
  line-height: 1.4;
  color: var(--text-dim);
}
.dw-state .notice-action {
  margin: 0;
}
.dw-number .dw-body:has(> .dw-state) {
  padding: 0 14px 12px;
}
.dw-number:not(.dw-tall) .dw-state {
  align-items: flex-start;
  justify-content: flex-end;
  gap: var(--space-2);
  padding: 0;
  text-align: left;
}
/* One line on a one-row tile (the words are written to fit); the whole line is its title. */
.dw-number:not(.dw-tall) .dw-state-text {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* A state that keeps the numbers: the card's one line of small print, its action a link. */
.dw-state-line {
  display: flex;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
}
.dw-state-line-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dw-state-line.is-sync-broken .dw-state-line-text {
  color: var(--warning-fg);
}
.dw-state-link {
  position: relative;
  z-index: 2;
  flex: none;
  color: var(--accent);
  font-weight: var(--weight-strong);
  text-decoration: none;
  pointer-events: auto;
}
.dw-state-link:hover {
  text-decoration: underline;
}
.dw-state-link:focus-visible {
  border-radius: var(--r-xs);
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.dash-pill-state {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
}
.dash-pill-act {
  color: var(--accent);
  font-size: var(--type-small);
  font-weight: var(--weight-strong);
  text-decoration: none;
  white-space: nowrap;
}
.dash-pill-act:hover {
  text-decoration: underline;
}

/* ---- the drill-down: a number or a chart point opens what makes it up ---- */
/* The number is its own button above the tile's add-to-chart area, so the two never compete. */
.dw-num-drill {
  position: relative;
  z-index: 2;
  margin: -2px -4px;
  padding: 2px 4px;
  border: 0;
  border-radius: var(--r-sm);
  background: none;
  color: inherit;
  font-family: inherit;
  text-align: left;
  text-decoration: underline dotted transparent;
  text-decoration-thickness: 1.5px;
  text-underline-offset: 5px;
  cursor: pointer;
  pointer-events: auto;
  transition: background-color var(--dur-1) ease, text-decoration-color var(--dur-1) ease;
}
.dw-num-drill:hover {
  background: var(--bg-hover);
  text-decoration-color: var(--text-faint);
}
.dw-num-toggle:hover .dw-num-drill:hover {
  background: var(--bg-raised);
}
.dw-num-drill:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 0;
}
.dash-tip-hint {
  margin-top: 4px;
  padding-top: 6px;
  border-top: 1px solid var(--line);
  color: var(--text-faint);
  font-size: var(--type-caption);
}

/* The sheet: on the right on a desk, from the bottom on a phone (ui.css .dialog). */
.dialog.dash-drill {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.dialog.dash-drill:not([open]) {
  display: none;
}
/* Grows from its content, not from 0: Safari gave a 0% basis no height in a sheet of auto height,
   and the breakdown opened 100px tall with its rows hidden. min-height 0 still lets it scroll under max-height. */
.dash-drill .dialog-body {
  flex: 1 1 auto;
  align-content: start;
  min-height: 0;
  overflow: auto;
}
.dash-drill-head {
  display: grid;
  gap: 2px;
  min-width: 0;
}
.dash-drill-when {
  margin: 0;
  color: var(--text-faint);
  font-size: var(--type-small);
}
.dash-drill-value {
  margin: 0;
  font-size: var(--fs-32);
  font-weight: var(--weight-title);
  line-height: 1.1;
  letter-spacing: -0.025em;
}
.dash-drill-note {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  margin: 0;
  color: var(--text-dim);
  font-size: var(--type-small);
}
.dash-drill-note .dash-ic {
  margin-top: 3px;
  color: var(--accent);
}
.dash-drill-tabs {
  margin: 0 -9px;
}
.dash-drill-tabs button {
  min-height: var(--ctl-h-sm);
}
.dash-drill-panel {
  min-height: 180px;
}
.dash-drill-panel:focus-visible {
  border-radius: var(--r-sm);
  outline: 2px solid var(--accent);
  outline-offset: 4px;
}
/* Names get the room in the sheet; the bar only compares. */
.dash-drill .dw-hbar {
  grid-template-columns: minmax(0, 1fr) minmax(48px, 30%) auto;
}
.dash-drill-loading {
  display: grid;
  gap: 10px;
  padding-top: 6px;
}
.dash-drill-foot {
  justify-content: space-between;
  border-top: 1px solid var(--line);
}
.dash-drill-foot > :only-child {
  margin-left: auto;
}
@media (min-width: 721px) {
  .dialog.dash-drill {
    width: min(460px, calc(100vw - 32px));
    height: 100dvh;
    max-height: 100dvh;
    margin: 0 0 0 auto;
    border-width: 0 0 0 1px;
    border-radius: var(--r-xl) 0 0 var(--r-xl);
  }
  .dialog.dash-drill[open] {
    animation-name: dash-drill-in;
  }
}
@media (max-width: 720px) {
  /* Phones size cards to their content: a state's line and a sync line wrap rather than cut. */
  .dw-number:not(.dw-tall) .dw-state-text,
  .dw-state-line-text {
    overflow: visible;
    white-space: normal;
  }
  .dw-state-line {
    flex-wrap: wrap;
  }
  .dw-state .btn {
    max-width: 100%;
    height: auto;
    min-height: var(--ctl-h-lg);
    white-space: normal;
  }
  .dialog.dash-drill {
    max-height: 86dvh;
  }
  .dash-drill-tabs button {
    min-height: var(--ctl-h-lg);
  }
}
@keyframes dash-drill-in {
  from {
    transform: translateX(24px);
    opacity: 0;
  }
}

/* Which dashboard of how many: dots on a phone (swipe for the others) and on the TV. */
.dash-pages {
  display: none;
}

/* ---- phones: the most important numbers first, every target 44px ---- */
@media (max-width: 720px) {
  /* The fixed order (GRID.phone in app/analytics.js): numbers two a row, then charts, then tables and panels. */
  .dw {
    order: var(--op);
  }
  .dash-head .icon-button,
  .dw-menu-btn,
  .dash-btn,
  .dash-live-btn,
  .dash-tabs button,
  .dw-tab-more,
  .dw-sort {
    min-height: var(--ctl-h-lg);
  }
  /* A short heading such as ROAS left the sort button 28px wide. */
  .dw-sort {
    min-width: var(--ctl-h-lg);
  }
  .dash-head .icon-button,
  .dw-menu-btn {
    width: var(--ctl-h-lg);
  }
  .dash-addcard-start {
    min-width: var(--ctl-h-lg);
    justify-content: center;
  }
  .dw-tab-select {
    min-height: var(--ctl-h-lg);
  }
  /* The menu sits in the card's corner; its larger target reaches into the padding, not the title. */
  .dw-menu-btn {
    margin-right: calc(var(--space-2) * -1);
  }
  /* The number opens its breakdown: the target is 44px tall around it, the figure keeps its place. */
  .dw-num-drill {
    position: relative;
  }
  .dw-num-drill::after {
    content: '';
    position: absolute;
    /* 44px wide even round a one-digit "0": half the shortfall on each side, never under 6px. */
    inset: -8px min(-6px, calc(50% - 22px));
  }
  .dw-show-all {
    min-height: var(--ctl-h-lg);
    margin-top: var(--space-1);
    color: var(--text-dim);
    gap: var(--space-1);
  }
  .dash-pages {
    display: flex;
    gap: 6px;
    margin-left: calc(var(--space-2) * -1);
  }
  .dash.is-leaving-left .dash-body,
  .dash.is-leaving-right .dash-body {
    opacity: 0.4;
    transition: opacity var(--dur-2) var(--ease-out);
  }
}
.dash-pages i,
.tv-pages i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--line-strong);
}
.dash-pages i.is-on,
.tv-pages i.is-on {
  background: var(--text-dim);
}
.dw-show-all .dash-ic {
  color: var(--text-faint);
}
/* Arrange on a phone: the groups the phone draws in, so a card moves among its own kind. */
.dash-arrange-group {
  padding: var(--space-3) 0 var(--space-1);
  color: var(--text-faint);
  font-family: var(--mono);
  font-size: var(--type-label);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.dash-arrange-group + .dash-arrange-row {
  border-top: 0;
}

/* ---- the TV (/tv/:token): a glance from across the room ---- */
body.tv {
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--bg);
}
.tv-main {
  min-height: 100vh;
  min-height: 100dvh;
  padding: 0 var(--space-10) var(--space-6);
}
/* Room for a figure, its change and the line under it at TV size. */
.dash.is-tv {
  --row-h: 140px;
}
.dash.is-tv .dw-grid,
.dash.is-tv .dash-head {
  pointer-events: none;
}
.tv-head {
  /* It stays on top while a tall board moves a screenful at a time. */
  position: sticky;
  top: 0;
  /* Over the cards, whose menu layer is 30. */
  z-index: 31;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: var(--space-2) var(--space-8);
  margin-bottom: var(--space-4);
  padding: var(--space-6) 0 var(--space-4);
  background: var(--bg);
}
.tv-title-row {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  min-width: 0;
}
.tv-who,
.tv-when {
  display: grid;
  gap: var(--space-1);
  min-width: 0;
}
.tv-when {
  justify-items: end;
  text-align: right;
}
.tv-brand {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: 0;
  color: var(--text-dim);
  font-size: var(--type-heading);
  font-weight: var(--weight-strong);
}
.tv-logo {
  display: block;
  max-width: 160px;
  max-height: 28px;
  object-fit: contain;
}
.tv-brand-name {
  color: var(--text);
}
.tv-brand-name + .tv-site::before {
  content: '';
  display: inline-block;
  width: 4px;
  height: 4px;
  margin: 0 var(--space-3) 0 0;
  border-radius: 50%;
  background: var(--text-faint);
  vertical-align: middle;
}
.tv-title {
  margin: 0;
  overflow: hidden;
  font-size: var(--fs-32);
  font-weight: var(--weight-title);
  line-height: 1.15;
  letter-spacing: -0.02em;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tv-period {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: 0;
  font-size: var(--fs-20);
  font-weight: var(--weight-title);
}
.tv-meta {
  display: flex;
  gap: var(--space-4);
  margin: 0;
  color: var(--text-dim);
  font-size: var(--type-small);
}
.tv-updated {
  font-variant-numeric: tabular-nums;
}
.tv-pages {
  display: flex;
  flex-shrink: 0;
  gap: var(--space-2);
  margin: 0;
}
/* Large type: titles and figures sized for the room (the page also scales to the screen, fitTv). */
.dash.is-tv .dw-title {
  font-size: var(--type-heading);
}
.dash.is-tv .dw-num-value {
  font-size: var(--fs-40);
}
.dash.is-tv .dash-delta {
  font-size: var(--type-body);
}
/* The change sits beside its figure on every tile, so the figures line up across the row. */
.dash.is-tv .dw-num-main {
  flex-wrap: nowrap;
}
/* A long figure ("1m 55s") keeps its room: the sparkline gives way, never the reverse. */
.dash.is-tv .dw-number:not(.dw-tall) .dw-num {
  grid-template-columns: max-content minmax(0, 84px);
  justify-content: space-between;
}
.dash.is-tv .dw-number:not(.dw-tall) .dw-spark {
  width: 100%;
}
/* Nothing to press on a TV: menus, tabs, hints and buttons stay off screen. */
.dash.is-tv .dw-menu-btn,
.dash.is-tv .dw-chip-row,
.dash.is-tv .dw-hint,
.dash.is-tv .dw-notes-pop,
.dash.is-tv .dw-tabs,
.dash.is-tv .info-tip,
.dash.is-tv .dw-link,
.dash.is-tv .dash-pill-act,
.dash.is-tv .dw-state .btn,
.dash.is-tv .dw-sort-dir {
  display: none;
}
.dash.is-tv .dw-grid.is-new {
  animation: tv-in var(--dur-4) var(--ease-out);
}
.dash.is-turning .dw-grid {
  opacity: 0;
  transition: opacity var(--dur-3) var(--ease-out);
}
@keyframes tv-in {
  from {
    opacity: 0;
  }
}
.tv-main:has(.tv-gone) {
  padding-bottom: 0;
}
.tv-gone {
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  place-content: center;
  gap: var(--space-2);
  padding: var(--space-6);
  text-align: center;
}
.tv-gone h1 {
  margin: 0;
  font-size: var(--fs-32);
  font-weight: var(--weight-title);
  letter-spacing: -0.02em;
}
.tv-gone p {
  margin: 0;
  color: var(--text-dim);
  font-size: var(--fs-18);
}

/* Under a list read from sampled rows (src/dashboard/resolve.ts `estimated`). */
.dw-estimated {
  margin: 6px 0 0;
  font-size: var(--fs-12);
}

/* Editing on a phone: the goal picker drops its "Goal" word (the select still says it) and narrows,
   so Goal, Arrange and Done share one row instead of Done wrapping alone. */
@media (max-width: 720px) {
  .dash.is-editing .dash-goal-pick > span {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .dash.is-editing .dash-goal-pick .field-input {
    max-width: 128px;
  }
}

/* "See all": every row of one list, with a search that stays on top while the rows scroll. */
.dash-all-head {
  position: sticky;
  top: calc(var(--space-4) * -1);
  z-index: 2;
  display: grid;
  gap: var(--space-2);
  margin: 0 calc(var(--space-6) * -1);
  padding: var(--space-2) var(--space-6);
  background: var(--bg-raised);
}
.dash-all-find {
  width: 100%;
}
.dash-all-count {
  margin: 0;
  font-size: var(--type-small);
}
.dash-all-rows {
  margin-top: var(--space-2);
}
.dash-all-rows .skeleton-row {
  display: block;
  height: 30px;
  margin-bottom: 6px;
}
/* The Filters menu's search results replace its lists in place. */
.dash-filter-list,
.dash-filter-groups {
  display: contents;
}
/* A sheet with no number on top (a list of pages has no one total) leaves no gap for it. */
.dash-drill-value:empty {
  display: none;
}
/* "See all" keeps its height while a search narrows the rows, so the sheet does not jump under the thumb. */
.dialog.dash-all {
  min-height: min(72dvh, 640px);
}
/* A goal with a value per conversion: what its conversions are worth, quiet beside its name. */
.dash-goal-worth {
  flex-shrink: 0;
  color: var(--text-dim);
  font-size: var(--type-small);
}

/* /static/app-tour.css */
/* The product tour in /app (src/tour.ts) and on /demo: the ring and the step
   card, the one offer card on the Sites list and the app-only touches. Here,
   not in site-marketing.css, because app pages do not load the marketing
   stylesheets. Tokens only, so both themes match. */

/* ---------------- the ring and the step card ---------------- */

:root {
  --tour-dim: color-mix(in srgb, #1d1b17 12%, transparent);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --tour-dim: color-mix(in srgb, #000 38%, transparent);
  }
}

:root[data-theme='dark'] {
  --tour-dim: color-mix(in srgb, #000 38%, transparent);
}

.tour-ring {
  position: absolute;
  z-index: 80;
  border: 2px solid var(--accent);
  border-radius: 16px;
  /* A light dim around the part, never over it: what is inside looks as it does without the tour. */
  box-shadow: 0 0 0 4px var(--accent-soft), 0 0 0 9999px var(--tour-dim);
  pointer-events: none;
  transition: left 0.3s ease, top 0.3s ease, width 0.3s ease, height 0.3s ease;
}

.tour-card {
  position: absolute;
  z-index: 81;
  width: min(360px, calc(100vw - 32px));
  padding: 18px 20px 16px;
  background: var(--bg-raised);
  border: 1px solid var(--line-strong);
  border-radius: 16px;
  box-shadow: var(--shadow-sheet);
  outline: none;
  animation: tour-in 0.25s ease;
}

.tour-card:focus {
  outline: none;
}

/* /demo: a close button in the corner, clear of the title. */
.tour-card.has-close {
  padding-right: 48px;
}

.tour-close {
  position: absolute;
  top: 8px;
  right: 8px;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  padding: 0;
  font-size: 22px;
  line-height: 1;
  color: var(--text-dim);
  background: none;
  border: 0;
  border-radius: 50%;
  cursor: pointer;
}

.tour-close:hover {
  color: var(--text);
  background: var(--bg-hover);
}

.tour-close:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

.tour-card.is-center {
  position: fixed;
  width: min(460px, calc(100vw - 32px));
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.tour-card.is-sheet {
  position: fixed;
  top: auto;
  right: 12px;
  bottom: 12px;
  left: 12px;
  width: auto;
}

.tour-ring.no-motion,
.tour-card.no-motion {
  transition: none;
  animation: none;
}

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

.tour-card.is-center {
  animation: none;
}

.tour-count {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}

.tour-title {
  margin: 6px 0 6px;
  font-family: var(--serif);
  font-weight: 500;
  font-size: 22px;
  line-height: 1.2;
}

.tour-text {
  font-size: 14.5px;
  color: var(--text-dim);
}

.tour-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 14px;
}

.tour-actions .btn-quiet {
  margin-right: auto;
}


/* ---------------- the "Take the tour" card on /app ---------------- */

.tour-offer {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 12px 14px 18px;
}

.tour-offer-mark {
  display: grid;
  flex: none;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: var(--r-lg);
  color: var(--accent);
  background: var(--accent-soft);
}

.tour-offer-copy {
  flex: 1 1 auto;
  min-width: 0;
}

.tour-offer-copy .card-title {
  font-size: var(--fs-15);
}

.tour-offer-actions {
  display: flex;
  flex: none;
  align-items: center;
  gap: 4px;
}

.tour-offer-actions form {
  margin: 0;
}

@media (max-width: 720px) {
  /* The close button stays in the top corner; Start goes full width below. */
  .tour-offer {
    position: relative;
    flex-wrap: wrap;
    align-items: flex-start;
    padding: 16px;
  }
  .tour-offer-copy {
    flex-basis: calc(100% - 52px - 44px);
  }
  .tour-offer-actions {
    width: 100%;
  }
  .tour-offer-actions > .btn {
    flex: 1 1 auto;
  }
  .tour-offer-actions form {
    position: absolute;
    top: 6px;
    right: 6px;
  }
}

/* ---------------- the step card inside the app ---------------- */

/* App UI stays sans (docs/style.md): the step title matches the card titles. */
.app .tour-title {
  font-family: inherit;
  font-weight: 650;
  font-size: var(--fs-18);
  letter-spacing: -0.01em;
}

/* On a phone the card is a sheet over the bottom of the screen: clear of the
   home indicator, with full-size tap targets. */
@media (max-width: 720px) {
  .app .tour-card.is-sheet {
    bottom: max(12px, env(safe-area-inset-bottom));
  }
  .app .tour-actions .btn {
    min-height: 44px;
  }
}
