/* =========================================================
   Praxis Landing — Design System
   Purple-forward brand identity matching Praxis 3.0 app
   ========================================================= */

:root {
  /* Type scale — fluid */
  --text-xs: clamp(0.75rem, 0.7rem + 0.2vw, 0.8125rem);
  --text-sm: clamp(0.875rem, 0.83rem + 0.2vw, 0.9375rem);
  --text-base: clamp(1rem, 0.95rem + 0.25vw, 1.0625rem);
  --text-lg: clamp(1.125rem, 1rem + 0.6vw, 1.375rem);
  --text-xl: clamp(1.5rem, 1.25rem + 1.2vw, 2.125rem);
  --text-2xl: clamp(1.75rem, 1.25rem + 1.8vw, 2.75rem);   /* section headings — capped */
  --text-3xl: clamp(2.25rem, 1.4rem + 3vw, 3.75rem);
  --text-hero: clamp(2.5rem, 0.9rem + 4.8vw, 5.25rem);    /* hero — capped so 3-4 lines */

  /* Spacing */
  --space-1: 0.25rem; --space-2: 0.5rem; --space-3: 0.75rem; --space-4: 1rem;
  --space-5: 1.25rem; --space-6: 1.5rem; --space-8: 2rem; --space-10: 2.5rem;
  --space-12: 3rem; --space-16: 4rem; --space-20: 5rem; --space-24: 6rem; --space-32: 8rem;

  /* Radii */
  --r-sm: 6px; --r-md: 10px; --r-lg: 14px; --r-xl: 20px; --r-2xl: 28px; --r-full: 999px;

  /* UI typeface. The literal stack was written out in three places (html, the
     app-shell root and the Stella panel); they must not drift apart, so they
     all read it from here. */
  --font-ui: 'Brown', system-ui, 'Segoe UI', Roboto, Arial, sans-serif;

  /* Accent typeface — Newsreader Italic, paired with Brown.
     Newsreader's x-height measures ~111% of Brown's at the same font-size, so an
     inline accent swapped at 1em optically overshoots the line. --accent-scale is
     the measured correction (1 / 1.113) that brings the two x-heights level.
     Retune this single value if the accent face ever changes. */
  --font-accent: 'Newsreader', 'Iowan Old Style', Georgia, 'Times New Roman', serif;
  --accent-scale: 0.9;

  /* Praxis brand — per Praxis 3.0 Brand v3.0 (July 2026) */
  --brand: #9747FF;                    /* Praxis Purple — HSL(270 70% 61%) */
  --brand-strong: hsl(271 57% 50%);    /* Purple 700 */
  --brand-hover: hsl(271 57% 45%);
  --brand-tint: hsl(270 100% 97%);     /* Purple 50 */
  --brand-border: hsl(270 70% 88%);
  --brand-glow: hsl(270 70% 61% / 0.28);

  /* Parent brand — Emergn. Deliberately restricted: permitted ONLY on the hover/focus
     state of the Emergn parent-brand link in the nav and mobile drawer. Never on dark
     surfaces (#eb1414 on Purple-950 is ~3.4:1, fails AA — the footer parent link hovers
     white instead, on purpose). Never near data, pills or status, because --danger and
     .pill-drop already own "red means bad" in this system. */
  --emergn-red: #eb1414;        /* emergn.com --color--red / --color--brand-1 */
  --emergn-red-hover: #ab1515;  /* emergn.com --color--darkred */

  /* External-link glyph, as a mask so ::after pseudo-elements inherit currentColor. */
  --ext-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%23000' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 2H10V7'/%3E%3Cpath d='M10 2L4.5 7.5'/%3E%3Cpath d='M9 8.5V10H2V3h1.5'/%3E%3C/svg%3E");
  /* Tick, same path the app screens draw on a Fund verdict. A mask rather than a
     glyph so the mark takes its colour from the rule that draws it, and so screen
     readers do not announce a check character before every list item. */
  --check-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12l5 5L20 6'/%3E%3C/svg%3E");

  /* Neutrals — per brand spec */
  --bg: rgb(251 251 251);              /* Canvas */
  --bg-alt: hsl(0 0% 96.5%);
  --surface: #ffffff;                  /* Surface white */
  --surface-alt: rgb(251 251 251);
  --ink: hsl(0 0% 8%);                 /* Black 950 */
  --ink-2: hsl(0 0% 15.7%);            /* Ink 700 — exactly #282828, which is also
                                          Emergn's --color--darkgrey. Shared secondary
                                          ink, so the family resemblance is typeface
                                          *and* ink, not typeface alone. */
  --ink-muted: hsl(0 0% 37%);          /* Muted 400 */
  --ink-faint: hsl(0 0% 67%);          /* Subtle 300 */
  --border: hsl(0 0% 88.2%);           /* Border 200 */
  --border-strong: hsl(0 0% 82%);

  /* Semantic — per brand spec */
  --success: hsl(107 45% 43%);
  --success-tint: hsl(107 45% 94%);
  --danger: hsl(346 79% 50%);
  --danger-tint: hsl(346 79% 96%);
  --warn: hsl(34 88% 54%);
  --warn-tint: hsl(34 88% 94%);
  --info: hsl(214 74% 52%);
  --info-tint: hsl(214 74% 95%);

  /* =========================================================
     App-surface tokens — the live hero dashboard (.pd-*) and any
     landing component that renders product UI share these. Where
     the app palette coincides with the site palette they alias
     the core token (single source of truth); app-specific values
     are defined literally.
     ========================================================= */
  --pd-ink: var(--ink);
  --pd-ink-2: var(--ink-2);
  --pd-ink-3: var(--ink-muted);
  /* The app's subtle ink. 55% (#8c8c8c) held only 3.1-3.4:1 against the grounds it
     lands on, so every ID, rank, lane count and unit label set in it failed WCAG AA.
     42% is the lightest value that clears 4.5:1 on all four of them: --pd-surface
     (#fff), --pd-paper-2 (#fbfbfb), --pd-paper-3 (97%), and -- the binding one --
     the lavender corner of .pd's own wash, which composites to about #f3ebfc and
     is where .pd-scope-kind and .pd-menu-label sit. Anything lighter re-breaks that
     corner first, at 4.4:1. This does compress the muted end of the ramp
     (8% -> 15.7% -> 37% -> 42%), so ink-3 and ink-4 now read closer together than
     they were designed to; the alternative was thinning the brand wash instead. */
  --pd-ink-4: hsl(0 0% 42%);           /* #6b6b6b */
  --pd-line: hsl(0 0% 8% / 0.1);       /* app borders are alpha inks */
  --pd-line-soft: hsl(0 0% 8% / 0.06);
  --pd-surface: var(--surface);
  --pd-paper-2: var(--bg);             /* rgb(251 251 251) canvas */
  --pd-paper-3: hsl(0 0% 97%);
  --pd-avatar: hsl(0 0% 13%);
  --pd-ink-5: #c7c7d1;                 /* lightest ink: inline separators */
  /* App status colors (Kill Score semantics, distinct from site --success) */
  --pd-green: #30a66b;
  --pd-green-deep: #178260;
  --pd-green-ink: hsl(150 55% 30%);
  --pd-green-bg: hsl(150 55% 95%);
  --pd-green-bd: hsl(150 45% 80%);
  --pd-green-bg-soft: hsl(150 55% 98%); /* full-row success tint */
  --pd-amber: var(--warn);
  --pd-amber-ink: hsl(34 88% 36%);
  --pd-amber-bg: hsl(37 96% 91%);
  --pd-amber-bd: hsl(37 90% 82%);
  --pd-red: var(--danger);
  --pd-red-bg: hsl(357 100% 95%);
  --pd-red-bd: hsl(357 80% 88%);
  --pd-blue: hsl(214 80% 42%);         /* delivery "In Progress" family */
  --pd-blue-bg: hsl(214 90% 95%);
  --pd-blue-bd: hsl(214 80% 86%);
  --pd-blue-bd-strong: hsl(214 80% 68%);
  --pd-line-strong: hsl(0 0% 8% / 0.18);    /* hover borders on rows/cards */
  --pd-line-stronger: hsl(0 0% 8% / 0.25);  /* hover borders on small controls */

  /* Product identity tints — lightened steps of each logo's sampled color
     (the logos are the source of truth; inks hold >=8.5:1 on both tints). */
  --prod-fitflow-ink: hsl(0 0% 25%); --prod-fitflow-bg: hsl(0 0% 96%); --prod-fitflow-bd: hsl(0 0% 8% / 0.14); --prod-fitflow-bg-strong: hsl(0 0% 93%); --prod-fitflow-bd-strong: hsl(0 0% 8% / 0.26);
  --prod-coach-ink: hsl(266 30% 28%); --prod-coach-bg: hsl(266 45% 96%); --prod-coach-bd: hsl(266 35% 88%); --prod-coach-bg-strong: hsl(266 45% 93%); --prod-coach-bd-strong: hsl(266 35% 79%);
  --prod-wear-ink: hsl(140 45% 20%); --prod-wear-bg: hsl(120 30% 96%); --prod-wear-bd: hsl(120 25% 86%); --prod-wear-bg-strong: hsl(120 30% 92%); --prod-wear-bd-strong: hsl(120 25% 76%);
  --prod-studio-ink: hsl(28 50% 24%); --prod-studio-bg: hsl(31 55% 95%); --prod-studio-bd: hsl(31 45% 85%); --prod-studio-bg-strong: hsl(31 55% 92%); --prod-studio-bd-strong: hsl(31 45% 76%);
  /* Stella brand */
  --stella-grad: linear-gradient(135deg, #8B5CF6 0%, #6366F1 55%, #3B82F6 100%);
  --stella-ink: hsl(270 50% 45%);
  --stella-link: hsl(270 55% 40%);
  /* Glass — frosted surfaces for the interactive app screens.
     Naming follows the Praxis prototype's --glass-* family. */
  --glass-blur: saturate(180%) blur(18px);       /* panels */
  --glass-blur-mid: saturate(180%) blur(14px);   /* composer fields */
  --glass-blur-tight: blur(8px) saturate(160%);  /* small controls */
  --glass-panel: linear-gradient(180deg, hsl(0 0% 100% / 0.94) 0%, hsl(255 60% 99% / 0.88) 100%);
  --glass-panel-border: hsl(0 0% 100% / 0.85);
  --glass-surface: hsl(0 0% 100% / 0.72);        /* input surfaces */
  --glass-surface-border: hsl(0 0% 100% / 0.6);
  --glass-control: hsl(0 0% 100% / 0.55);        /* round action buttons */
  --glass-control-border: hsl(0 0% 100% / 0.7);
  --glass-strong: hsl(0 0% 100% / 0.85);         /* bubbles, hover fills */
  --glass-edge: hsl(0 0% 100% / 0.4);            /* border on saturated fills */
  --glass-sheen: hsl(0 0% 100% / 0.3);           /* inset light on saturated fills */
  --glass-highlight: hsl(0 0% 100% / 0.8);       /* inset top lights, by intensity */
  --glass-highlight-soft: hsl(0 0% 100% / 0.6);
  --glass-highlight-mid: hsl(0 0% 100% / 0.7);
  --glass-highlight-strong: hsl(0 0% 100% / 0.9);
  /* Stella glass (purple-tinted) */
  --stella-glass: linear-gradient(135deg, hsl(270 100% 98% / 0.92), hsl(270 100% 96% / 0.78));
  --stella-glass-border: hsl(270 70% 88% / 0.9);
  --stella-border-hover: hsl(265 60% 80%);
  --stella-shade: 270 60% 55%;          /* violet shadow hue triplet */
  --stella-banner: linear-gradient(135deg, hsl(252 80% 97% / 0.92) 0%, hsl(270 90% 98% / 0.8) 50%, hsl(210 90% 97% / 0.88) 100%);
  --stella-banner-border: hsl(252 60% 90%);
  /* Shadow hues as channel triplets, composed with per-use alpha */
  --pd-shade: 250 40% 14%;
  --pd-shade-2: 250 30% 20%;

  /* Dark surface — Purple 950 per brand spec */
  --dark-bg: hsl(270 45% 10%);         /* Purple 950 */
  --dark-surface: hsl(270 40% 14%);
  --dark-border: rgba(255,255,255,0.10);
  --dark-ink: #ffffff;
  --dark-muted: rgba(255,255,255,0.62);
  /* The two glows that sit over --dark-bg: top left, then a warmer one bottom
     right. Shared by the Proof section and the featured pricing card, which are
     meant to read as the same ground, so they cannot be allowed to drift apart. */
  --dark-glow:
    radial-gradient(ellipse 60% 40% at 20% 0%, hsl(270 70% 30% / 0.5), transparent 60%),
    radial-gradient(ellipse 50% 30% at 90% 100%, hsl(280 80% 40% / 0.35), transparent 65%);

  /* Shadows — neutral (no warm tint) */
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.06), 0 1px 3px rgba(0,0,0,0.04);
  --shadow-md: 0 4px 12px rgba(0,0,0,0.06), 0 1px 3px rgba(0,0,0,0.04);
  --shadow-lg: 0 20px 40px -12px rgba(0,0,0,0.12), 0 8px 16px -8px rgba(0,0,0,0.06);
  --shadow-brand: 0 20px 50px -12px hsl(270 70% 40% / 0.28), 0 4px 12px hsl(270 70% 40% / 0.10);

  /* Motion */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-io: cubic-bezier(0.65, 0, 0.35, 1);

  /* Layout */
  --container: 1200px;
  --container-wide: 1320px;
  --gutter: clamp(1.25rem, 4vw, 2.5rem);
}

/* =========================================================
   Brand typeface — Brown (BrownLLPan)
   Brown ships only three faces: Light, Regular, Bold. The weight
   ranges below fold this design's 500 -> Regular and 600 -> Bold,
   so no rule ever triggers synthetic (faux-bold) rendering.
   Served as WOFF2, converted from the OTFs in Emergn's own font
   package. 449 KB of OTF became 186 KB of WOFF2, 59% smaller, and
   the two preloaded weights are the ones that block first paint.
   No OTF fallback: WOFF2 has been supported everywhere since 2016.
   The .otf sources stay in the repo, since they are what the WOFF2
   files are regenerated from, and are held out of the deploy by
   .vercelignore.
   The accent face (Newsreader) is self-hosted for the same reason
   it is preloaded: served from Google it arrived as a stylesheet
   that blocked first paint for 750ms, and the font itself was only
   discoverable after that stylesheet parsed. Two hops, two TLS
   handshakes, 144 KB.
   The file here is Google's own `latin` italic cut, subset to the
   ranges below and limited to the 400-600 weights this design uses:
   144 KB became 74 KB. Both variable axes survive, so optical
   sizing still tracks font-size the way it did on the CDN, and the
   letterforms are unchanged.
   Coverage is ASCII, the typographic punctuation Google's `latin`
   range carried, and the accented letters English business copy
   reaches for. Anything outside that falls to the Georgia fallback
   in --font-accent, so an accent span is not the place to put a
   character this list does not name. Regenerate with:
     pyftsubset Newsreader-Italic[opsz,wght].ttf --flavor=woff2
   Note U+2192 was never in Google's `latin` range either, so the
   arrow in .proof-value renders in the fallback here exactly as it
   always has.
   ========================================================= */
@font-face {
  font-family: 'Newsreader';
  src: url('./assets/fonts/Newsreader-Italic-latin.woff2') format('woff2');
  font-weight: 400 600;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: 'Brown';
  src: url('./assets/fonts/BrownLLPan-Light.woff2') format('woff2');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Brown';
  src: url('./assets/fonts/BrownLLPan-Regular.woff2') format('woff2');
  font-weight: 400 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Brown';
  src: url('./assets/fonts/BrownLLPan-Bold.woff2') format('woff2');
  font-weight: 600 700;
  font-style: normal;
  font-display: swap;
}

html { font-family: var(--font-ui); }
body {
  background: var(--bg);
  color: var(--ink);
  font-size: var(--text-base);
  line-height: 1.55;
  font-weight: 400;
  letter-spacing: -0.005em;
}

/* Numeric alignment for tabular data */
.num, .kpi, .metric { font-variant-numeric: tabular-nums lining-nums; }

/* =========================================================
   Layout primitives
   ========================================================= */
.container { max-width: var(--container); margin: 0 auto; padding-inline: var(--gutter); }
.container-wide { max-width: var(--container-wide); margin: 0 auto; padding-inline: var(--gutter); }
section { padding-block: clamp(4rem, 8vw, 7.5rem); position: relative; }
.section-inner { max-width: var(--container); margin: 0 auto; padding-inline: var(--gutter); }
.divider { height: 1px; background: var(--border); }

/* Eyebrow / labels */
.eyebrow {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font-size: 0.75rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.14em;
  color: var(--brand-strong);
  padding: 0.4rem 0.75rem;
  background: var(--brand-tint);
  border: 1px solid var(--brand-border);
  border-radius: var(--r-full);
}
.eyebrow::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--brand); box-shadow: 0 0 0 3px var(--brand-glow);
}
/* The [hidden] attribute must beat author display rules (e.g. .btn's
   inline-flex), or hiding an element with a display class does nothing. */
[hidden] { display: none !important; }

.section-label {
  display: block; font-size: 0.72rem; font-weight: 500;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--ink-muted); margin-bottom: 1rem;
}

/* Headings */
h1, h2, h3, h4 { font-weight: 500; letter-spacing: -0.02em; line-height: 1.08; color: var(--ink); }
h2 { font-size: var(--text-2xl); line-height: 1.12; letter-spacing: -0.02em; max-width: 28ch; }
.what-header h2, .pricing-header h2 { max-width: 26ch; text-wrap: balance; }
h3 { font-size: var(--text-lg); letter-spacing: -0.015em; }
/* Inline editorial accent — single words inside a Brown headline.
   Sits at the same declared font-size as the surrounding sans, so it carries
   the x-height correction. Tracking is looser than the old condensed Didone
   needed: negative tracking closes up a cursive italic's joins. */
.italic-accent {
  font-family: var(--font-accent);
  font-style: italic; font-weight: 500;
  font-size: calc(1em * var(--accent-scale));
  letter-spacing: -0.01em;
  /* Purple by default so no section can forget it; dark sections override with the
     lighter tint below (brand-strong has no contrast on --dark-bg). */
  color: var(--brand-strong);
}

/* Same treatment for inline accent labels in body copy ("Problem:", "Rationale:"). */
.accent-label {
  font-family: var(--font-accent);
  font-style: italic; font-weight: 500;
  font-size: calc(1em * var(--accent-scale));
  color: var(--brand-strong);
}

p { color: var(--ink-2); max-width: 62ch; }
.lede { font-size: var(--text-lg); color: var(--ink-2); line-height: 1.5; max-width: 58ch; }

/* Buttons */
.btn {
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0.85rem 1.35rem;
  font-size: 0.9375rem; font-weight: 500;
  border-radius: var(--r-full);
  transition: all 0.25s var(--ease);
  white-space: nowrap;
}
.btn-primary {
  background: var(--ink); color: var(--bg);
  box-shadow: 0 1px 0 rgba(255,255,255,0.08) inset, 0 8px 20px -6px rgba(0,0,0,0.35);
}
.btn-primary:hover { background: var(--brand); transform: translateY(-1px); box-shadow: var(--shadow-brand); }
.btn-brand {
  background: var(--brand); color: white;
  box-shadow: var(--shadow-brand);
}
.btn-brand:hover { background: var(--brand-hover); transform: translateY(-1px); }
.btn-ghost {
  color: var(--ink); background: transparent; border: 1px solid var(--border-strong);
}
.btn-ghost:hover { background: var(--surface); border-color: var(--ink); }
.btn-dark { background: white; color: var(--dark-bg); }
.btn-dark:hover { background: var(--brand); color: white; }
.btn-arrow { display: inline-block; transition: transform 0.25s var(--ease); }
.btn:hover .btn-arrow { transform: translateX(3px); }

/* =========================================================
   Navigation
   ========================================================= */
.nav {
  position: sticky; top: 0; z-index: 50;
  backdrop-filter: saturate(140%) blur(14px);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
  background: rgba(251,251,251,0.78);
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s var(--ease), background 0.3s var(--ease);
}
.nav.scrolled { border-bottom-color: var(--border); background: rgba(251,251,251,0.92); }
.nav-inner {
  display: flex; align-items: center; justify-content: space-between;
  height: 68px; max-width: var(--container-wide); margin: 0 auto;
  padding-inline: var(--gutter);
}
.brand-lock { display: flex; align-items: center; flex: none; }
.brand-lock .brand-logo { height: 26px; width: auto; display: block; }
.nav-links {
  display: flex; gap: 2rem; align-items: center;
  font-size: 0.9rem; color: var(--ink-2);
  flex: none;   /* never let the labels compress and wrap — drop to the burger instead */
}
.nav-links a { transition: color 0.2s; white-space: nowrap; }
.nav-links a:hover { color: var(--brand); }
.nav-cta { display: flex; align-items: center; gap: 0.75rem; }
.nav-end { display: flex; align-items: center; gap: 0.9rem; flex: none; }

/* --- Emergn parent-brand link ---------------------------------------------
   Sits in the actions cluster behind a divider, not among .nav-links, so the
   nav links stay one mental model ("places on this page") and this reads as
   attribution rather than a peer section. */
.nav-parent {
  display: inline-flex; align-items: center; gap: 0.5rem; flex: none;
  color: var(--ink-muted);
  transition: color 0.2s var(--ease);
}
.nav-parent-pre {
  font-size: 0.625rem; font-weight: 500;
  letter-spacing: 0.14em; text-transform: uppercase;
  white-space: nowrap;
  /* --ink-faint (#ababab) is only ~2.3:1 on the canvas and this is 10px text,
     so the muted ink is the floor here, not the faint one. */
  color: var(--ink-muted);
  transition: color 0.2s var(--ease);
}
.nav-parent-mark { height: 15px; width: 79px; display: block; }
.ext-ico { width: 10px; height: 10px; flex: none; opacity: 0.55; transition: opacity 0.2s; }

/* The only place Emergn red appears on this page (plus its drawer twin). */
.nav-parent:hover, .nav-parent:focus-visible { color: var(--emergn-red); }
.nav-parent:hover .nav-parent-pre, .nav-parent:focus-visible .nav-parent-pre { color: var(--emergn-red); }
.nav-parent:hover .ext-ico { opacity: 1; }
.nav-parent:active { color: var(--emergn-red-hover); }

.nav-sep { width: 1px; height: 20px; background: var(--border); flex: none; }
.nav-burger { display: none; }

/* The right cluster gains ~150px over the original design, so the nav runs out of room
   far above the old 900px breakpoint. Things are dropped in order of least value:
   the micro-label first, then the whole parent link (it's still in the footer and the
   drawer), and only last the product links, which hand off to the burger. */
@media (max-width: 1240px) {
  .nav-links { gap: 1.25rem; font-size: 0.875rem; }
  .nav-parent-pre { display: none; }
}
@media (max-width: 1080px) {
  .nav-parent, .nav-sep { display: none; }
}
@media (max-width: 940px) {
  .nav-links { display: none; }
  .nav-burger {
    display: inline-flex; align-items: center; justify-content: center;
    flex-direction: column; gap: 5px;
    width: 40px; height: 40px; margin-right: -8px;
    border-radius: var(--r-sm);
  }
  .nav-burger span { display: block; width: 18px; height: 1.5px; background: var(--ink); border-radius: 2px; }
}
.cta-short { display: none; }
/* Below ~700px the full CTA label would collide with the lockup once the burger is
   also in the row, so it swaps to a shorter one rather than disappearing — the header
   CTA is the primary conversion path and shouldn't be sacrificed to the drawer. */
@media (max-width: 700px) {
  .cta-long { display: none; }
  .cta-short { display: inline; }
  .nav-cta .btn { padding: 0.55rem 0.9rem; font-size: 0.82rem; }
  .nav-end { gap: 0.5rem; }
  .brand-lock .brand-logo { height: 22px; }
}
@media (max-width: 400px) {
  .brand-lock .brand-logo { height: 19px; }
  .nav-cta .btn { padding: 0.5rem 0.75rem; font-size: 0.78rem; }
}

/* --- Mobile drawer -------------------------------------------------------- */
.drawer {
  width: 100%; max-width: none; max-height: none; height: 100dvh;
  margin: 0; padding: 0 var(--gutter) calc(env(safe-area-inset-bottom) + 1.5rem);
  border: 0; background: var(--bg); color: var(--ink);
  flex-direction: column;
}
.drawer[open] { display: flex; }
.drawer::backdrop { background: hsl(270 45% 10% / 0.5); backdrop-filter: blur(2px); }
.drawer-top { height: 68px; display: flex; align-items: center; justify-content: space-between; flex: none; }
.drawer-x { width: 40px; height: 40px; display: grid; place-items: center; margin-right: -10px; color: var(--ink); }
.drawer-links { display: flex; flex-direction: column; margin-top: 1.5rem; }
.drawer-links a {
  padding: 0.95rem 0; font-size: 1.375rem; font-weight: 500;
  letter-spacing: -0.02em; border-bottom: 1px solid var(--border);
  transition: color 0.2s var(--ease);
}
.drawer-links a:hover, .drawer-links a:focus-visible { color: var(--brand-strong); }
.drawer-parent {
  display: flex; align-items: center; gap: 0.5rem;
  margin-top: auto; padding: 1.5rem 0 1.25rem;
  color: var(--ink-muted); transition: color 0.2s var(--ease);
}
.drawer-parent-pre { font-size: 0.65rem; font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-muted); }
.drawer-parent:hover, .drawer-parent:focus-visible { color: var(--emergn-red); }
.drawer-cta { width: 100%; justify-content: center; padding-block: 1rem; flex: none; }
html.menu-open { overflow: hidden; }
@media (min-width: 941px) {
  .drawer[open] { display: none; }
  /* Backstop: the drawer is hidden at this width, so the scroll lock must not survive
     here even if the JS that clears it fails. Otherwise the page is unscrollable with
     no visible way out. */
  html.menu-open { overflow: visible; }
}

/* =========================================================
   HERO
   ========================================================= */
.hero {
  padding-block: clamp(4rem, 10vh, 8rem) clamp(3rem, 6vw, 5rem);
  position: relative; overflow: hidden;
}
.hero-bg {
  position: absolute; inset: 0; pointer-events: none; z-index: 0;
  background:
    radial-gradient(ellipse at 20% 0%, hsl(270 100% 92% / 0.55), transparent 55%),
    radial-gradient(ellipse at 90% 20%, hsl(270 70% 88% / 0.4), transparent 50%);
}
.hero-grid-bg {
  position: absolute; inset: 0; z-index: 0; opacity: 0.5;
  background-image:
    linear-gradient(rgba(0,0,0,0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0,0,0,0.045) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(ellipse 80% 60% at 50% 30%, black, transparent 80%);
  -webkit-mask-image: radial-gradient(ellipse 80% 60% at 50% 30%, black, transparent 80%);
}
.hero-inner { position: relative; z-index: 1; }
/* Keeps a multi-word phrase on one line so text-wrap: balance can only break
   between phrases, not inside them. */
.nowrap { white-space: nowrap; }

.hero-headline {
  font-size: var(--text-hero);
  line-height: 1.04;
  letter-spacing: -0.03em;
  max-width: 24ch;
  margin-top: 1.5rem;
  font-weight: 500;
  text-wrap: balance;
}
.hero-sub {
  margin-top: 1.75rem;
  font-size: clamp(1.0625rem, 0.9rem + 0.6vw, 1.3125rem);
  color: var(--ink-2); max-width: 58ch; line-height: 1.5;
}
.hero-ctas { margin-top: 2.25rem; display: flex; gap: 0.75rem; flex-wrap: wrap; align-items: center; }

/* Hero visual — decision flow. Linear-style breakout: the frame escapes the
   1200px text container and runs toward the viewport edges, capped just under
   the dashboard's native 1400px canvas so the live UI never upscales. The
   internal --pd-scale tracks the frame width, so every element inside grows
   with it. Centered with margins (not transform) so the .reveal animation
   keeps ownership of transform. */
.hero-visual {
  /* 100vw includes the scrollbar gutter, so the width errs a hair wide;
     equal negative margins keep the frame optically centered regardless. */
  --hv-w: min(1400px, calc(100vw - 2 * var(--gutter)));
  width: var(--hv-w);
  margin-inline: calc((100% - var(--hv-w)) / 2);
  margin-top: clamp(3rem, 6vw, 5rem);
  position: relative;
  border-radius: var(--r-2xl);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-lg), 0 40px 80px -20px hsl(270 70% 30% / 0.15);
  overflow: hidden;
}
/* The frame supplies the card chrome and takes its height from the image, so
   no asset ratio ever gets cropped. The empty placeholder state keeps a 16:9
   canvas of its own. */
.hero-visual .screen-placeholder { aspect-ratio: 16/9; height: auto; border: 0; border-radius: 0; box-shadow: none; }
.hero-visual > img { display: block; width: 100%; height: auto; }

/* Mobile — Linear-style hero: the live dashboard goes static and bleeds off
   the right edge at a readable scale instead of shrinking to fit the screen.
   Anchored at the container's left gutter; the hero section clips the bleed
   so the page never scrolls sideways. */
@media (max-width: 767px) {
  .hero { overflow-x: clip; }
  .hero-visual {
    --hv-w: min(200vw, 780px);
    margin-inline: 0 calc(100% - var(--hv-w));
  }
  .hero-visual .pd { pointer-events: none; }
}

/* Logo band — circulating client-logo strip and platform statement on the same
   dark ground as the trust-bar directly below, so hero → logos → statement →
   stats reads as one composed band. Logos are Emergn's own white carousel SVGs. */
.logo-band {
  background: var(--dark-bg);
  color: var(--dark-ink);
  padding-block: clamp(2.5rem, 5vw, 4rem) clamp(3rem, 6vw, 5rem);
  overflow: hidden;
}
.logo-marquee {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
}
.logo-track {
  display: flex;
  width: max-content;
  animation: logo-scroll 36s linear infinite;
}
.logo-marquee:hover .logo-track { animation-play-state: paused; }
.logo-set {
  display: flex; align-items: center;
  list-style: none; margin: 0; padding: 0;
}
/* Spacing lives on the items (not flex gap) so both halves of the track are
   identical in width and the -50% loop is seamless. */
.logo-set li { margin-inline: clamp(1.5rem, 3.5vw, 3.25rem); }
.logo-set img {
  display: block;
  height: clamp(3rem, 5vw, 4.25rem);
  width: auto;
  opacity: 0.72;
  transition: opacity 0.3s var(--ease);
}
.logo-set li:hover img { opacity: 1; }
@keyframes logo-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .logo-track { animation: none; width: auto; flex-wrap: wrap; justify-content: center; }
  .logo-set { flex-wrap: wrap; justify-content: center; row-gap: 1.5rem; }
  .logo-set[aria-hidden] { display: none; }
  .logo-marquee { -webkit-mask-image: none; mask-image: none; }
}

/* Statement — Linear-style two-tone: opening clause in full ink, the rest muted. */
.logo-band-statement {
  margin-top: clamp(2.75rem, 6vw, 4.5rem);
  font-size: clamp(1.625rem, 1rem + 2.4vw, 3rem);
  font-weight: 500;
  line-height: 1.18;
  letter-spacing: -0.02em;
  max-width: 30ch;
  color: var(--dark-muted);
  text-wrap: balance;
}
.logo-band-statement .lead { color: var(--dark-ink); }

/* Trust band — full-bleed statistics strip in the same visual family as the
   closing CTA: flat dark ground, content on the page container, no card chrome. */
.trust-bar {
  background: var(--dark-bg);
  color: var(--dark-ink);
  padding-block: clamp(2rem, 4vw, 3rem);
}
.trust-bar-label {
  display: block;
  font-size: 0.72rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: rgba(255,255,255,0.45);
  margin-bottom: clamp(1.25rem, 2vw, 1.5rem);
}
.trust-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.5rem 2rem;
  margin: 0;
}
/* dt before dd keeps the definition-list order valid; column-reverse puts the
   number on top visually. */
.trust-stat { display: flex; flex-direction: column-reverse; gap: 0.35rem; }
.trust-stat dd {
  margin: 0;
  font-size: clamp(1.5rem, 1rem + 1.1vw, 2rem);
  font-weight: 500; letter-spacing: -0.02em; line-height: 1;
  color: var(--dark-ink);
  font-variant-numeric: tabular-nums;
}
.trust-stat dt { font-size: 0.875rem; color: var(--dark-muted); line-height: 1.4; }

@media (max-width: 760px) {
  .trust-grid { grid-template-columns: repeat(2, 1fr); gap: 1.5rem 1.25rem; }
}

/* =========================================================
   Section: THE PROBLEM
   ========================================================= */
/* Copy left, Value Gap card right. The headline only ever used about half the
   container, so the card fills space this section already had rather than adding
   height — it is also the only outside evidence here since the stat tiles came out.
   The section's own padding-block sets the space below. */
.problem-header {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 24rem);
  column-gap: clamp(2rem, 5vw, 4.5rem); align-items: start;
}
@media (max-width: 900px) {
  .problem-header { grid-template-columns: 1fr; row-gap: 2.25rem; }
  /* Stacked, the card would otherwise stretch the full container and look padded
     out on tablets. Below ~26rem of viewport it goes full width anyway. */
  .study-card { max-width: 26rem; }
}
.problem-header .section-label { margin-bottom: 0.75rem; }
.problem-header h2 { max-width: none; margin-top: 0; }
.problem-intro, .problem-coda { margin: 1.25rem 0 0; font-size: 1rem; line-height: 1.65; max-width: 60ch; }
.problem-intro { color: var(--ink-2); }
/* The Emergn line is a claim, not more framing, so it holds full ink against the
   intro's secondary grey rather than reading as a third paragraph of context. */
.problem-coda { color: var(--ink); }

/* The whole card is one link, so the hover has to read as a single affordance:
   the diagonal tint wash and lift the stat tiles used to carry, inherited here. */
.study-card {
  display: flex; flex-direction: column; align-items: flex-start;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-xl); padding: clamp(1.5rem, 2.2vw, 1.875rem);
  position: relative; overflow: hidden;
  transition: transform 0.35s var(--ease), border-color 0.35s var(--ease), box-shadow 0.35s var(--ease);
}
.study-card::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(135deg, transparent 60%, var(--brand-tint) 100%);
  opacity: 0; transition: opacity 0.35s var(--ease);
}
.study-card > * { position: relative; z-index: 1; }
.study-card:hover, .study-card:focus-visible {
  transform: translateY(-2px); border-color: var(--brand-border); box-shadow: var(--shadow-md);
}
.study-card:hover::after, .study-card:focus-visible::after { opacity: 1; }
.study-label {
  font-size: 0.72rem; font-weight: 500; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--ink-muted);
}
/* The accent face, standing alone rather than inline: this is the name of a
   published study, and the italic is what marks it as a cited artifact. */
.study-title {
  font-family: var(--font-accent); font-style: italic; font-weight: 400;
  font-size: calc(var(--text-xl) * 1.05); line-height: 1.1; letter-spacing: -0.01em;
  color: var(--brand-strong); margin-top: 0.85rem;
}
.study-desc { font-size: 0.9375rem; line-height: 1.5; color: var(--ink-2); margin-top: 0.75rem; }
.study-cta {
  display: inline-flex; align-items: center; gap: 0.4rem; align-self: stretch;
  margin-top: 1.25rem; padding-top: 1.1rem; border-top: 1px solid var(--border);
  font-size: 0.9375rem; color: var(--brand-strong);
}
.study-cta::after {
  content: ""; width: 10px; height: 10px; flex: none; background: currentColor;
  -webkit-mask: var(--ext-mask) center / contain no-repeat;
  mask: var(--ext-mask) center / contain no-repeat;
  transition: transform 0.35s var(--ease);
}
.study-card:hover .study-cta::after, .study-card:focus-visible .study-cta::after { transform: translate(1px, -1px); }
/* The question lands on its own line — same treatment as the closing h2. */
/* The accent face runs at 0.9em (x-height correction), so as its own line its
   line box comes up 10% short of the Brown lines above. Dividing the h2's
   line-height by the same scale restores an equal absolute line box. */
.problem-header h2 .italic-accent {
  display: block;
  line-height: calc(1.12 / var(--accent-scale));
}
/* =========================================================
   WHAT PRAXIS IS — annotated screenshot
   ========================================================= */
/* Two-column header: label spans the row, headline left, intro right. */
.what-header {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  column-gap: clamp(2rem, 5vw, 4rem);
  row-gap: 0.75rem;
  /* Intro's last line sits on the headline's final baseline. */
  align-items: last baseline;
  margin: 0 0 clamp(3rem, 5vw, 4rem);
}
.what-header .section-label { grid-column: 1 / -1; margin-bottom: 0; }
/* Deck scale, deliberately clear of the tab descriptions below (0.975rem): at
   17px the two paragraphs were within 1.4px of each other in the same weight
   and colour, so they read as one tier that had drifted rather than two that
   do different jobs. This one opens the whole section; those describe whichever
   tab is selected. */
.what-intro {
  margin: 0; max-width: 46rem; color: var(--ink-2);
  font-size: clamp(1.1875rem, 1.6vw, 1.3125rem);
  line-height: 1.5;
}
@media (max-width: 900px) {
  .what-header { grid-template-columns: 1fr; }
}

/* =========================================================
   PRAXIS AND WORK OS — the parent-brand argument, made structural:
   two cards for two layers, bridged by the methodology they share.
   ========================================================= */
/* The one section where Emergn is the SUBJECT rather than a credential, so it's the one
   place the parent brand gets colour of its own. Both brands appear as glass panels on a
   neutral black field: Emergn red for the operating model, Praxis purple for the product
   layer, bridged by the methodology they share. Red and purple sit near-complementary and
   would vibrate if layered, so they're kept apart in SPACE rather than by hierarchy —
   two separated objects, never overlapping washes.

   Neutral black, not Purple-950: red over a purple-black desaturates to maroon, and
   Emergn's own dark is neutral. The field stays hueless so both cards read true. */
.workos {
  background: hsl(0 0% 5%);
  color: var(--dark-ink);
  position: relative;
  overflow: hidden;
  /* Tighter than the shared section rhythm. Scoped here rather than changed on
     `section` so every other section keeps its spacing. */
  padding-block: clamp(3.25rem, 6vw, 6rem);
}
/* A hueless lift only — enough that the loop diagram has something to sit against
   instead of dead flat black. No colour here; the arcs and stations carry all of it. */
.workos::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(ellipse 70% 55% at 20% 0%, rgba(255,255,255,0.045), transparent 62%),
    radial-gradient(ellipse 55% 45% at 92% 100%, rgba(255,255,255,0.025), transparent 66%);
}
.workos > * { position: relative; z-index: 1; }
.workos .section-label { color: rgba(255,255,255,0.58); }
.workos h2 { color: var(--dark-ink); }
/* Accent on its own line — the period travels inside the span so it can't orphan. */
.workos h2 .italic-accent { color: hsl(280 100% 84%); display: block; }
.workos-header { margin-bottom: clamp(2rem, 3vw, 2.5rem); }
.workos-copy p { color: rgba(255,255,255,0.76); text-wrap: pretty; }

/* Heading left, framing paragraph right — the pattern .problem-header uses, so
   the two sections read as siblings. The first column is floored at the lead
   line's min-content width instead of a plain fr ratio: a ratio that clears the
   lead at 1434px comes up 5px short by 940px, and the failure mode is the
   headline silently going to three lines with "the" stranded. min-content
   cannot fail that way. */
@media (min-width: 901px) {
  .workos-header {
    display: grid;
    grid-template-columns: minmax(min-content, 1.2fr) minmax(0, 1fr);
    column-gap: clamp(2rem, 5vw, 4.5rem);
    align-items: end;
  }
  .workos-h2-lead { white-space: nowrap; }
  /* Optical: sits the paragraph's last line near the headline's baseline. */
  .workos-copy { padding-bottom: 0.3rem; }
  .workos-copy p { max-width: 48ch; }
}
/* Stacked, the paragraph gets the container back and needs its own measure.
   No nowrap here: at 375px the lead needs 361px against 335px available, so
   holding it on one line would overflow the viewport. The headline runs to
   three lines at phone widths, as it did before this layout. */
@media (max-width: 900px) {
  .workos-header { max-width: 44rem; }
  .workos-copy { margin-top: 1.5rem; }
  .workos-copy p { max-width: 60ch; }
}

/* The operating loop. One circle, always running: the top arc is dotted
   red — Work OS, the model being set; the bottom arc is solid purple —
   Praxis, the model running every day. Dotted-to-solid is the temporal
   claim (an engagement ends, the software doesn't) drawn as line quality,
   so the colors only have to carry ownership.

   Above 880px the step copy sits inside the circle, which makes the section
   a header and one figure. That is also what fixes the circle's size — see
   .wos-orbit below.

   Color note: brand red and purple appear as decorative strokes and node
   fills only — no text sits on them, so the AA restriction on
   --emergn-red doesn't apply. Text tints reuse the card-label tints
   hsl(0 100% 88%) / hsl(280 100% 86%), which pass on this field. */

.wos-cycle { margin-top: clamp(0.5rem, 1.5vw, 1.25rem); }

/* 49rem is not a taste choice. The longest step copy is 280x184, so its
   half-diagonal is 167px, and the circle needs r >= 167 plus real clearance.
   With the viewBox 810 units wide, r = 210 * (width / 810), which puts the
   floor near 775px. Below that the copy leaves the circle.

   width:100% is load-bearing beside margin-inline:auto: auto inline margins
   stop a grid or flex item from stretching, so without it the svg falls back
   to its 300px CSS default and the figure renders undersized. */
.wos-orbit { max-width: 49rem; width: 100%; margin-inline: auto; position: relative; }
.wos-orbit svg { display: block; width: 100%; height: auto; }

.wos-node { cursor: pointer; outline-offset: 6px; }
.wos-node text {
  font-size: 15px; font-weight: 400; fill: rgba(255,255,255,0.6);
  transition: fill 0.3s var(--ease);
}
.wos-node-dot {
  fill: hsl(0 0% 5%); stroke: rgba(255,255,255,0.45); stroke-width: 1.5;
  transition: transform 0.35s var(--ease), fill 0.35s var(--ease), stroke 0.35s var(--ease);
  transform-box: fill-box; transform-origin: center;
}
.wos-node:hover .wos-node-dot, .wos-node:focus-visible .wos-node-dot { stroke: #fff; transform: scale(1.25); }
.wos-node:hover text { fill: var(--dark-ink); }

@keyframes wos-pulse { 0% { opacity: 0.5; transform: scale(1); } 100% { opacity: 0; transform: scale(2.6); } }
.wos-node-pulse {
  fill: var(--node-c); opacity: 0;
  transform-box: fill-box; transform-origin: center;
}
@media (prefers-reduced-motion: no-preference) {
  .wos-node.active .wos-node-pulse { animation: wos-pulse 2.4s var(--ease) infinite; }
}
.wos-node[data-phase="os"] { --node-c: var(--emergn-red); }
.wos-node[data-phase="praxis"] { --node-c: var(--brand); }
.wos-node-halo { fill: none; stroke: var(--node-c); stroke-width: 1; opacity: 0; transition: opacity 0.3s var(--ease); }
.wos-node.active .wos-node-dot { fill: var(--node-c); stroke: var(--node-c); }
.wos-node.active .wos-node-halo { opacity: 0.35; }
.wos-node.active text { fill: var(--dark-ink); }

@keyframes wos-timer { from { stroke-dashoffset: 100.5; } to { stroke-dashoffset: 0; } }
.wos-node-timer {
  fill: none; stroke: var(--node-c); stroke-width: 1.5; opacity: 0;
  stroke-dasharray: 100.5; stroke-dashoffset: 100.5;
  transform: rotate(-90deg); transform-box: fill-box; transform-origin: center;
}
.wos-node.timing .wos-node-timer { opacity: 0.9; animation: wos-timer var(--wos-step, 6000ms) linear forwards; }
.wos-node.timing .wos-node-halo { opacity: 0; }

.wos-node:focus-visible { outline: 2px solid #fff; }

/* Hint line under the stack figure. The Work OS orbit used to share this and no
   longer carries a hint, so the declarations are no longer split across sections. */
.stack-hint {
  text-align: center; font-size: 0.8rem; color: rgba(255,255,255,0.45);
  /* max-width:none matters: p is capped at 62ch globally, and text-align would
     otherwise centre the line inside that box rather than under the figure. */
  margin-top: 0.6rem; max-width: none;
}

/* Base rule first: the media query below has equal specificity, so if it came
   first this would override it and both variants would resolve to none, leaving
   the hint empty on every touch device. */
.stack-hint-touch { display: none; }
@media (hover: none) {
  .stack-hint-hover { display: none; }
  .stack-hint-touch { display: inline; }
}

.wos-step-eyebrow {
  display: block; font-size: 0.68rem; font-weight: 500;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: rgba(255,255,255,0.5); margin-bottom: 0.6rem;
}
/* Ownership lives in the eyebrow: the owner tinted, the "· Step n" left in the
   eyebrow's grey. This replaces the arc labels, and before them the legend.
   The tints are the arc colours' text-safe versions, so the active step's
   eyebrow matches the arc that step runs along — red on the dotted Work OS
   arc, purple on the solid Praxis one. Both clear 11:1 against this field, so
   they hold at the eyebrow's small uppercase size; the grey is 5.3:1. */
.wos-owner-os { color: hsl(0 100% 88%); }
.wos-owner-praxis { color: hsl(280 100% 86%); }
.wos-steps { position: relative; min-height: 8.5rem; }
.wos-step-copy {
  position: absolute; inset: 0;
  opacity: 0; transform: translateY(8px);
  transition: opacity 0.45s var(--ease), transform 0.45s var(--ease);
  pointer-events: none;
}
.wos-step-copy.active { opacity: 1; transform: none; pointer-events: auto; }
.wos-step-copy h3 {
  font-size: clamp(1.35rem, 1.1rem + 0.9vw, 1.75rem);
  letter-spacing: -0.015em; color: var(--dark-ink);
  /* All four headings fit one line at the widths above. This is the fallback if
     one ever doesn't: balanced lines rather than a single orphaned word. */
  text-wrap: balance;
}
.wos-step-copy p { margin-top: 0.6rem; font-size: 0.95rem; color: rgba(255,255,255,0.72); max-width: 46ch; }

/* Copy inside the circle, at every width. 19.5rem, not 17.5: "Decisions run
   through it" needs 303px on one line and 280px orphaned "it" onto a second.
   Widening costs less than it looks — the heading collapsing to one line takes
   31px off the tallest step, so clearance inside the stroke only goes 40px ->
   33px. 300px would be worse than 312px on both counts, since there the
   heading still wraps. */
.wos-panel {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: min(19.5rem, 58%); text-align: center;
}
.wos-steps { min-height: 11.5rem; display: grid; align-items: center; }
.wos-step-copy { display: grid; align-content: center; }
.wos-step-copy p { max-width: none; margin-inline: auto; }

/* Below 880px the station labels come off, which is what pays for the copy
   being inside the circle here too. The labels were the only reason the viewBox
   reserved side margin, so with them gone the box tightens to the circle (see
   the swap in index.html) and the radius goes from 87px to ~144px at 375px.
   The station's own name is not lost with the labels: the active step's heading
   in the centre is that name. The description is the one thing that will not
   fit at this radius, so it is dropped here rather than set at a size nobody
   would read. */
@media (max-width: 880px) {
  .wos-orbit { max-width: 26rem; }
  .wos-node text { display: none; }
  .wos-panel { width: 62%; }
  /* The description stays in the circle here, but not at its desktop 0.95rem:
     that overruns the stroke at every panel width tried. 0.75rem/1.4 is the
     setting that clears at 360px, the common Android width where 0.8rem/1.45
     left only 6px. Measured clearance: 14px at 360, 21px at 375, 36px at 880.
     Below 375px it comes off entirely - see the query after this one. */
  .wos-step-copy p { font-size: 0.75rem; line-height: 1.4; margin-top: 0.45rem; }
  .wos-steps { min-height: 10rem; }
}

/* Under 360px the circle is only 120px in radius and even 0.75rem copy breaks
   the stroke, so the description comes off and the eyebrow and heading carry the
   step on their own - the same trade the section already makes for the labels. */
@media (max-width: 359px) {
  .wos-step-copy p { display: none; }
  .wos-steps { min-height: 6.5rem; }
}

/* In-prose outbound links need a dark-surface variant: .link-out hovers to --brand-strong
   (Purple 700), which is near-invisible on this field. */
.workos .link-out { text-decoration-color: rgba(255,255,255,0.45); }
.workos .link-out:hover, .workos .link-out:focus-visible {
  color: hsl(280 100% 86%); text-decoration-color: currentColor;
}
.workos :focus-visible { outline-color: #fff; }

/* =========================================================
   WHO IT'S FOR — one statement, no cards. Two audiences with one
   clause each never filled a three-card grid, and this stretch of page
   already runs stat tiles into price cards, so a third grid read as
   filler. The statement carries the section as its own heading; there
   is no separate headline above it to restate.
   ========================================================= */
.fit-statement {
  /* A <p>, not an h2 — two sentences made a bad heading, so #fit's eyebrow carries
     the tag instead. These four declarations are the h2 rule's typography, restated
     here so the statement renders identically to when it was one. */
  font-size: var(--text-2xl); font-weight: 500;
  letter-spacing: -0.02em; color: var(--ink);
  /* Long for a heading, so it runs wider than the 28ch h2 default and
     opens the leading a touch to stay readable across three lines. */
  max-width: 46ch; line-height: 1.2;
  /* Without this the second sentence drops "goes." onto a line of its own. */
  text-wrap: balance;
}
/* The audiences are the subject of this section, so they carry the colour.
   Solid rather than .italic-accent: the italic is for rhetorical phrases,
   and two serif runs mid-sentence break the reading rhythm here. */
.fit-statement .fit-role { color: var(--brand-strong); }

/* Showcase: a horizontal tab row, its crossfading lede, then the full-width
   live screen. Stacked so the screen gets the whole container. */
.what-showcase {
  display: flex; flex-direction: column;
  gap: clamp(1rem, 2vw, 1.5rem);
}

/* Labels only, sized to their text — a segmented control, not three cards
   competing with the screen below for attention. */
.callout-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

/* A rule picking up where the last tab ends and running to the container's
   content edge, on the tabs' own centre line. It stops flush with the right
   edge of the intro paragraph above it, so the two share a margin. Drawing the
   remaining space as a flex item is what lets it start after the last pill
   whatever the labels are. */
.callout-row::after {
  content: "";
  flex: 1 1 1.5rem;
  align-self: center;
  height: 1px;
  background: var(--border);
  margin-left: 0.5rem;
}

/* The active tab's description: an italic display line over its supporting
   sentence. All three are stacked in one grid cell so the block holds the
   height of the tallest and the screen below never shifts. */
.callout-ledes { display: grid; }
.callout-lede {
  grid-area: 1 / 1;
  max-width: 62ch;
  opacity: 0; visibility: hidden;
  transition: opacity 0.45s var(--ease), visibility 0.45s var(--ease);
}
.callout-lede.active { opacity: 1; visibility: visible; }
.callout-lede-head {
  margin: 0 0 0.4rem;
  font-family: var(--font-accent); font-style: italic; font-weight: 500;
  color: var(--brand-strong);
  /* Display scale, not a bolder body line: --accent-scale is 0.9, so this needs
     to be set well above the body to read as the tier above it. */
  font-size: calc(clamp(1.6rem, 1.9vw, 2rem) * var(--accent-scale));
  line-height: 1.2;
  letter-spacing: -0.01em;
}
.callout-lede-body {
  margin: 0;
  max-width: none;
  /* The page's default body size. It sits under the header intro's deck scale,
     but the role difference between the two is carried by the rule above and by
     the italic head, not by shaving pixels off this one. */
  font-size: 1.0625rem; color: var(--ink-2); line-height: 1.55;
}

.screenshot-wrap { position: relative; }
/* Layout only — no chrome of its own. The designed assets are full compositions
   (transparent background, own shadows), so they stand bare; the card look lives on
   .screen-placeholder and disappears slot by slot as real images replace them. */
.screenshot {
  position: relative;
  /* Fixed ratio so every screen targets one full-width canvas and the frame
     never resizes between tabs. Matches the hero's 1400×849 app canvas —
     every screen here is a live shell on those dimensions. */
  aspect-ratio: 1400 / 849;
  height: auto;
  /* Break out of the text container to the hero frame's exact width formula
     (.hero-visual), so these shells render at the hero's scale and their type
     sizes match it 1:1 on wide screens. */
  --ws-w: min(1400px, calc(100vw - 2 * var(--gutter)));
  width: var(--ws-w);
  margin-inline: calc((100% - var(--ws-w)) / 2);
}

/* Screens are stacked in the same box so the frame never resizes between them. */
.what-screen {
  position: absolute; inset: 0;
  opacity: 0; visibility: hidden;
  transition: opacity 0.45s var(--ease), visibility 0.45s var(--ease);
}
.what-screen.active { opacity: 1; visibility: visible; }

/* Every screen is a live pd shell (the hero's component set). The frame chrome
   the designed images used to carry moves onto the viewport itself; the hero's
   own .pd-viewport stays bare because .hero-visual frames it. */
.what-screen .pd-viewport {
  width: 100%; height: 100%;
  border-radius: var(--r-2xl);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-lg), 0 60px 120px -30px hsl(270 70% 25% / 0.18);
}

/* Mobile — the same treatment as the hero (see .hero-visual): the live shells
   go static and bleed off the right edge at a readable scale instead of
   shrinking to fit the screen. Anchored at the container's left gutter, with
   the section clipping the bleed so the page never scrolls sideways. The tabs
   above stay live so the visitor can still switch screens; only the shells
   themselves stop responding to touch. */
@media (max-width: 767px) {
  #product { overflow-x: clip; }
  .screenshot {
    --ws-w: min(200vw, 780px);
    margin-inline: 0 calc(100% - var(--ws-w));
  }
  .what-screen .pd { pointer-events: none; }
}

.callout {
  position: relative;
  font: inherit;
  font-size: 1rem; font-weight: 500; letter-spacing: -0.01em; line-height: 1.2;
  padding: 0.55rem 1.15rem;
  border-radius: 999px;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--ink-2);
  cursor: pointer;
  transition: border-color 0.3s var(--ease), background 0.3s var(--ease), color 0.3s var(--ease);
}
.callout:hover { border-color: var(--brand); color: var(--ink); }
/* Solid fill, not a tinted outline: this row sits a few hundred pixels above the
   app shell's own filter chips, which are the same shape and size, so selection
   has to be unmistakable at a glance. Filled with --brand-strong rather than
   --brand because white on --brand lands at 4.5:1, right on the AA line, while
   --brand-strong clears it at 6.3:1. Border matches the fill so the pill's
   footprint stays identical between states and the row never reflows. */
.callout.active {
  background: var(--brand-strong);
  border-color: var(--brand-strong);
  color: #fff;
}
.callout.active:hover { border-color: var(--brand-strong); color: #fff; }
.callout:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }

/* =========================================================
   STELLA AI section
   ========================================================= */
.stella-wrap { display: grid; grid-template-columns: 1.05fr 0.95fr; gap: clamp(2rem, 5vw, 4rem); align-items: center; }
@media (max-width: 900px) { .stella-wrap { grid-template-columns: 1fr; } }
.stella-copy h2 { margin-top: 1rem; }
.stella-copy p { margin-top: 1.25rem; font-size: 1rem; line-height: 1.65; }
/* Designed-image slot: the frame supplies the card chrome and a fixed 4:3
   canvas; the placeholder inside stays flat so borders don't double up. */
.stella-visual {
  position: relative;
  aspect-ratio: 4/3;
  border-radius: var(--r-xl);
  background: var(--surface);
  border: 1px solid var(--border);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
}
.stella-visual .screen-placeholder { border: 0; border-radius: 0; box-shadow: none; }
.stella-visual > img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* ---- Stella chat panel -------------------------------------------------
   The chat window on its own, without the app shell around it. Every part
   inside is the rail's own component set (.pd-rail-head / -body / -greeting
   / -shortcuts / -composer, .pd-msg, .pd-typing, .pd-idea-card), which all
   use bare class selectors and :root-level --pd-* tokens, so they work
   outside a .pd shell unchanged. What .pd used to provide and this has to
   supply itself: border-box, the app's type ramp, and the panel chrome that
   lived on .pd-rail's absolutely-positioned box.
   Unlike the other embeds this one is a real control rather than a facade,
   so the prompts are buttons and the chrome around them is aria-hidden. */
.sc {
  display: flex; flex-direction: column;
  height: clamp(34rem, 62vh, 40rem);
  /* justify-self rather than an auto margin: an auto inline margin on a grid
     item overrides stretch, which collapses the panel to its content width. */
  width: 100%; max-width: 33rem; justify-self: end;
  /* Page-level panel, not part of the fixed .pd canvas, so it takes the page
     radius scale rather than the prototype's raw pixel radii. */
  border-radius: var(--r-xl);
  overflow: hidden;
  font-family: var(--font-ui);
  font-size: 14px; line-height: 1.5;
  color: var(--pd-ink);
  -webkit-font-smoothing: antialiased;
  background: var(--glass-panel);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-panel-border);
  box-shadow:
    0 0 0 1px var(--pd-line-soft),
    0 2px 6px hsl(var(--pd-shade) / 0.06),
    -16px 12px 48px hsl(var(--pd-shade) / 0.16);
}
.sc *, .sc *::before, .sc *::after { box-sizing: border-box; }

/* Stacked, the panel has to be allowed to grow. Its height is a fixed clamp so
   that .pd-rail-thread has something bounded to scroll inside, but the clamp's
   34rem floor is smaller than the greeting + shortcuts + composer once text
   starts wrapping: 12px short at 375px, 132px short at 320px. With .sc set to
   overflow:hidden that shortfall is not slack being absorbed, it is the bottom
   of the composer being cut off - at 320px the tool row and send button
   disappear completely, and the visible symptom higher up is the composer's
   16px bottom padding rendering as 5px while its sides keep 16px.

   min-height keeps the designed proportions wherever the content does fit, so
   this only ever adds height where the alternative was clipping. Chat mode gets
   the fixed height back: the greeting and shortcuts are hidden by then, so the
   clamp is comfortable, and the thread needs a bounded parent to scroll in. */
@media (max-width: 900px) {
  .sc { height: auto; min-height: clamp(34rem, 62vh, 40rem); }
  .sc.pd-chat-active { height: clamp(34rem, 62vh, 40rem); }
}
/* The shortcuts here are inert <span>s, like every other shortcut list on the
   page, so they need nothing beyond the shared .pd-shortcut rule: the flex
   column already stretches them and the base sets size, weight and colour. */
.sc .sc-reset { padding: 0; font: inherit; }
.sc .sc-reset:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* Composer with a prompt already in it. .pd-rail-placeholder is the greyed
   empty state; .is-draft is the same line reading as typed text waiting to be
   sent, which is what makes the send button the obvious next move. */
.sc .sc-draft.is-draft { color: var(--pd-ink); }

/* .pd-typing's display: inline-flex is declared after .pd-step's display: none
   at equal specificity, so an unrevealed typing step keeps its 21px box and is
   merely transparent. The shared rails get away with it because every step is
   revealed by the end of the script; here the second exchange sits unsent until
   the visitor sends it, which would park 63px of dead space under the first
   reply. Scoped to this panel rather than fixed on .pd-typing so the other
   embeds keep the spacing they were built against. */
.sc .pd-typing:not(.is-vis) { display: none; }
.sc .sc-send {
  padding: 0; border: 0; font: inherit; cursor: pointer;
  transition: background 160ms ease, color 160ms ease, transform 120ms ease;
}
.sc .sc-send.is-ready {
  background: var(--brand-strong); color: #fff;
  animation: sc-pulse 2s ease-in-out infinite;
}
.sc .sc-send.is-ready:hover { transform: translateY(-1px); animation: none; }
/* Purple halo off --brand, so the cue tracks the brand token rather than a
   second copy of the colour. box-shadow only: it never affects layout, so the
   loop stays on the compositor. */
@keyframes sc-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--brand) 55%, transparent); }
  50%      { box-shadow: 0 0 0 6px transparent; }
}
.sc .sc-send:disabled { cursor: default; }
.sc .sc-send:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* Stella's suggestion pills are inert display affordances everywhere else on
   the page. Here two of them are the actual controls that carry the flow, so
   they are buttons and need the type and focus ring a button does not inherit. */
.sc button.pd-msg-action { font: inherit; }
/* A used offer stays legible as part of the transcript but stops inviting a
   second press, which would replay a reply that has already been given. */
.sc button.pd-msg-action:disabled { opacity: 0.45; cursor: default; }
.sc button.pd-msg-action:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* The drafted message to the CPO, on the shared .pd-card surface. Only the
   padding changes: 18px is right for a page card and too loose nested inside
   a chat bubble. */
.sc .sc-note { padding: 12px 14px; }
/* base.css strips list-style globally, so the evidence bullets have to ask for
   discs back. Tighter than the 8px block rhythm on purpose: the bullets read as
   part of the sentence that introduces them, not as separate blocks. */
.sc .sc-note-list { margin: 6px 0; padding-left: 18px; list-style: disc; }
.sc .sc-note-list li + li { margin-top: 4px; }

/* Every gap between blocks inside one of Stella's messages is 8px, but
   .pd-msg.stella .pd-msg-p + .pd-msg-p only matches paragraph pairs, so prose
   resuming after a card was landing flush against it at 0. These restore the
   8px for the two cases this panel introduces: a paragraph after an idea card,
   and the drafted-message card and the paragraph that follows it. */
.sc .pd-msg.stella .pd-idea-card + .pd-msg-p,
.sc .pd-msg.stella .sc-note,
.sc .pd-msg.stella .sc-note + .pd-msg-p,
/* The draft's own controls hug the card they act on ... */
.sc .pd-msg.stella .sc-note + .pd-msg-actions { margin-top: 8px; }
/* ... and the advice that follows them starts a new thought. General sibling,
   not adjacent: the copy button's role="status" announcement is a real element
   between the two, so `+` silently matched nothing and the closing line sat
   flush against the button. */
.sc .pd-msg.stella .pd-msg-actions ~ .pd-msg-p { margin-top: 12px; }

/* Copy swaps its own icon and label in place on success. Two SVGs toggled by a
   class rather than an innerHTML rewrite, which would drop the click listener. */
.sc .sc-copy .sc-ico-done { display: none; }
.sc .sc-copy.is-done .sc-ico-copy { display: none; }
.sc .sc-copy.is-done .sc-ico-done { display: block; }

@media (max-width: 900px) {
  .sc { max-width: none; justify-self: stretch; margin-top: 2.5rem; }
}

/* =========================================================
   PRAXIS IN YOUR STACK
   =========================================================
   One wide integration figure, and all of the words above it: portfolio
   tools feed in on the left, delivery tools are fed on the right, Praxis
   between them, so the drawing carries the loop and the header carries the
   argument. (It replaced three captioned cards, and then the figure's own
   caption moved up into the header beside the headline.) The
   drawing is inline SVG: theme tokens for every color, site font
   inherited, flow lines animated by dashoffset only, and only when
   motion is welcome. Brand purple, never red: red is coded to
   Emergn / Work OS elsewhere on this page.

   The section runs on the same near-black field as .workos and .proof.
   The SVGs are re-themed by scoping their tokens on .stack-visual:
   node roundels and list rows keep WHITE fills — brand marks read like
   app icons on the dark field — so two extra tokens exist for text:
   --stack-accent for accent text sitting on dark fills. */
#stack {
  /* Tighter than the page default: this section is one wide figure plus a short
     header, so the standard 7.5rem block padding left it floating. */
  padding-block: clamp(2.5rem, 5vw, 4.5rem);
  /* The field colour is read by the station fills, the label halos and the
     overlay's ground, all of which have to sit on exactly this value. It was a
     literal in fourteen places, so changing the background silently left them
     stale; they now all resolve from here. */
  --stack-bg: hsl(0 0% 5%);
  background: var(--stack-bg);
  --stack-accent: hsl(280 100% 84%);
}
/* Same hueless lift as .workos, so the two dark slabs read as siblings. */
#stack::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(ellipse 70% 55% at 80% 0%, rgba(255,255,255,0.045), transparent 62%),
    radial-gradient(ellipse 55% 45% at 8% 100%, rgba(255,255,255,0.025), transparent 66%);
}
#stack > * { position: relative; z-index: 1; }
#stack .section-label { color: rgba(255,255,255,0.58); }
#stack h2 { color: var(--dark-ink); }
#stack h2 .italic-accent { color: hsl(280 100% 84%); }
/* Two-column header on the .what-header pattern: label across the row,
   headline left, the copy that used to sit under the figure on the right,
   its last line landing on the headline's final baseline. That alignment only
   holds while the two columns stay close in height — the headline runs two
   lines, so keep this copy to roughly four. */
.stack-header {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  column-gap: clamp(2rem, 5vw, 4rem); row-gap: 0.75rem; align-items: last baseline;
  margin-bottom: clamp(2.5rem, 4vw, 3.5rem);
}
.stack-header .section-label { grid-column: 1 / -1; margin-bottom: 0; }
/* Same body treatment as .workos-copy, so the two dark slabs read as siblings. */
.stack-intro p { color: rgba(255,255,255,0.76); text-wrap: pretty; }
@media (max-width: 900px) {
  .stack-header { grid-template-columns: 1fr; row-gap: 1.25rem; align-items: start; }
}
.stack-feature { max-width: 56rem; margin-inline: auto; }
.stack-visual {
  /* No padding of its own: the section's rhythm comes from the shared
     section padding and the standard header margin, like every other
     section. */
  /* One line language with the Work OS loop: no containers — station
     dots, hairline curves, ringed glowing hubs, and the loop's own
     lavender-to-purple gradient on every accent. Monochrome glyphs
     (the -mono logo variants in assets/logos/); purple is the only
     color in the frame. */
  --stack-line: rgba(255,255,255,0.16);
  --stack-muted: rgba(255,255,255,0.45);
}
.stack-visual svg { display: block; width: 100%; height: auto; }
/* Accent lines carry traveling dots — the round-cap dotted texture of
   the Work OS arc, in motion. Offset is a multiple of the 7.5-unit
   dash period so the loop is seamless; the dots move only for
   visitors who welcome motion, and the still frame keeps its texture. */
@media (prefers-reduced-motion: no-preference) {
  .stack-anim-f { animation: stack-dash-f 1.6s linear infinite; }
  /* The delivery channels run out, hold, then run back, so one line carries both
     funded work leaving and outcomes returning. Each leg runs a long way before it
     turns: the point is to read as a sustained direction, not as an oscillation,
     and the pause at each end is what makes the turn legible rather than jittery. */
  .stack-anim-cycle { animation: stack-dash-cycle 10s ease-in-out infinite; }
}
@keyframes stack-dash-f { to { stroke-dashoffset: -15; } }
/* Expanding ring on the mark: the affordance for "hover me", using the ring the
   mark already has rather than adding a cue of its own. Stops once open, since
   the invitation has been taken. */
.stack-hub-pulse {
  fill: none; stroke: var(--brand); stroke-width: 1.5; opacity: 0;
  transform-box: view-box; transform-origin: 240px 93px;
}
@media (prefers-reduced-motion: no-preference) {
  .stack-hub-pulse { animation: stack-hub-pulse 3.4s ease-out infinite; }
}
.stack-feature.is-open .stack-hub-pulse { animation: none; }
@keyframes stack-hub-pulse {
  0%   { transform: scale(1);    opacity: 0.55; }
  65%  { transform: scale(1.42); opacity: 0; }
  100% { transform: scale(1.42); opacity: 0; }
}
/* -45 is six whole dash periods, so both ends of the cycle land on a seam and the
   dots never appear to jump. At 10s that is ~10 units/sec, close to the one-way
   flows' 9.4, so the two kinds of line travel at about the same pace. */
@keyframes stack-dash-cycle {
  0%   { stroke-dashoffset: 0; }
  46%  { stroke-dashoffset: -45; }
  54%  { stroke-dashoffset: -45; }
  94%  { stroke-dashoffset: 0; }
  100% { stroke-dashoffset: 0; }
}

/* The two channels of the base figure. Shape is shared; only hue differs, which is
   the whole rule: grey is your stack's context arriving, purple is Praxis's own
   work leaving and its outcomes coming back. */
/* The tool stations: eight identical circles that differed only in position and,
   on the delivery side, in ring colour. */
.stack-station { fill: var(--stack-bg); stroke: rgba(255,255,255,0.7); stroke-width: 1.25; }
.stack-station.is-out { stroke: rgba(176,124,255,0.7); }

/* One primitive for every travelling line in this section, in both states: same
   weight, cap and dash period, so only the stroke distinguishes them. The four
   used to repeat these four properties between them. */
.stack-in, .stack-out, .stack-flow-in, .stack-flow-live {
  fill: none; stroke-width: 1.5; stroke-linecap: round; stroke-dasharray: 0.5 7;
}
.stack-in { stroke: url(#stkA-in); }
.stack-out { stroke: url(#stkA-out); }
/* Now that all three channels leave from one point, the outer curves sweep through
   the band these labels sit in. Same halo the workflow labels use: paint the field
   colour under the words so a line passing behind them stays behind them. */
.stack-chan-label {
  /* A point down from the tool names: these sit in the band the outer channels
     sweep through, and the smaller they are the less of that band they occupy. */
  font-size: 6.5px; fill: var(--stack-muted);
  paint-order: stroke fill; stroke: var(--stack-bg); stroke-width: 2.6; stroke-linejoin: round;
}

/* ---- Hover/tap/focus the mark to open the workflow inside it ----
   Three layers cross-fade around one shared origin, the hub's centre: the tool
   columns recede, the mark contracts away, and the workflow scales up in its
   place. Nothing moves in the layout, so the figure never changes height and the
   page cannot shift under the pointer. */
.stack-tools, .stack-hub, .stack-flow {
  transform-box: view-box; transform-origin: 240px 93px;
  transition: opacity 0.4s var(--ease), transform 0.45s var(--ease);
}
.stack-tools { opacity: 1; }
.stack-hub { opacity: 1; }
/* Collapsed: inert as well as invisible, so it never intercepts the pointer. */
.stack-flow { opacity: 0; transform: scale(0.42); pointer-events: none; }

/* Opaque ground, so the figure underneath is covered rather than shown through.
   It sits outside .stack-flow and only fades, because inheriting that group's
   scale-up would leave the canvas edges uncovered mid-transition. */
.stack-flow-bg {
  fill: var(--stack-bg); opacity: 0; pointer-events: none;
  transition: opacity 0.4s var(--ease);
}
.stack-feature.is-open .stack-flow-bg { opacity: 1; }
.stack-feature.is-open .stack-hub { opacity: 0; transform: scale(0.85); }
.stack-feature.is-open .stack-flow { opacity: 1; transform: none; }

.stack-hub-btn { cursor: pointer; outline-offset: 4px; }
#stack :focus-visible { outline: 2px solid #fff; }

/* The revealed workflow, in the same language as the rest of this figure: hairlines
   for the paths that stop, the accent plus traveling dots for the one that continues,
   small letter-spaced caps for every label. No cards and no grid — those belong to
   the app, and this is a diagram. */
.stack-flow-line { fill: none; stroke: var(--stack-line); stroke-width: 1; }
.stack-flow-live { stroke: var(--brand); }
/* The run out to delivery fades, exactly as the figure's own outbound flow does. */
.stack-flow-live.is-out { stroke: url(#stkA-fund-out); }
/* Context arriving: travelling, but grey, because it is not Praxis's value yet. */
.stack-flow-in { stroke: url(#stkA-flow-in); }
/* Portfolio layer: a line, not a container. A box would be the only box in a
   figure built entirely from lines. */
.stack-flow-plane { fill: none; stroke: rgba(151,71,255,0.55); stroke-width: 1; }
.stack-flow-plane-label {
  font-size: 6.5px; font-weight: 500; letter-spacing: 0.9px; fill: var(--stack-accent);
}
/* Aggregation rather than flow, so this is dotted and never arrowed. Kill and Park
   merge into the riser, so a single line reaches the portfolio. */
/* Grey, not purple: purple is this figure's colour for value moving through the
   system, and a roll-up is reporting rather than flowing. */
.stack-flow-roll {
  fill: none; stroke: rgba(255,255,255,0.3); stroke-width: 1;
  stroke-linecap: round; stroke-dasharray: 0.5 4;
}
.stack-flow-port { fill: var(--brand); }

.stack-flow-dot { fill: var(--stack-bg); stroke: rgba(255,255,255,0.45); stroke-width: 1; }
.stack-flow-dot.is-sm { stroke-width: 0.8; }
.stack-flow-dot.is-on { fill: var(--brand); stroke: var(--brand); }
.stack-flow-ring { fill: none; stroke: rgba(151,71,255,0.7); stroke-width: 1; }
/* Outcome states straight off the app's tokens. The dots take --pd-red / --pd-amber /
   --pd-green as-is; the labels take those hues lifted, because at this size the app's
   own mid-lightness values do not hold as text on a near-black field. */
.stack-flow-dot.is-kill { fill: var(--pd-red);   stroke: var(--pd-red); }
.stack-flow-dot.is-park { fill: var(--pd-amber); stroke: var(--pd-amber); }
.stack-flow-dot.is-fund { fill: var(--pd-green); stroke: var(--pd-green); }
.stack-flow-label.is-kill { fill: hsl(346 80% 70%); }
.stack-flow-label.is-park { fill: hsl(34 90% 66%); }
.stack-flow-label.is-fund { fill: hsl(150 55% 62%); }

/* One label treatment for the whole figure: small, letter-spaced, uppercase. */
.stack-flow-label {
  font-size: 6.5px; font-weight: 500; letter-spacing: 0.75px;
  fill: var(--stack-muted); text-transform: uppercase;
}
.stack-flow-label.is-strong { fill: var(--dark-ink); }

/* The hint line itself is defined with the Work OS orbit's, since both figures
   use the same component. */
@media (max-width: 900px) {
  /* The wide figure keeps its drawn size and pans sideways instead of
     shrinking its labels below legibility; it opens centered on the
     Praxis hub. */
  .stack-feature .stack-visual { overflow-x: auto; scrollbar-width: thin; scrollbar-color: rgba(255,255,255,0.25) transparent; }
  .stack-feature .stack-visual svg { min-width: 36rem; }
}

/* =========================================================
   PROOF section (dark)
   ========================================================= */
.proof {
  background: var(--dark-bg);
  color: var(--dark-ink);
  position: relative;
  overflow: hidden;
}
.proof::before {
  content: ""; position: absolute; inset: 0;
  background: var(--dark-glow);
  pointer-events: none;
}
.proof > * { position: relative; z-index: 1; }
.proof .section-label { color: rgba(255,255,255,0.55); }
.proof h2 { color: var(--dark-ink); max-width: 28ch; }
/* Accent on its own line, matching the problem and closing headers. */
.proof h2 .italic-accent { color: hsl(280 100% 84%); display: block; }
.proof-intro { color: var(--dark-muted); margin-top: 1rem; max-width: 42rem; }
.proof-grid {
  margin-top: clamp(3rem, 5vw, 4rem);
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem;
}
@media (max-width: 900px) { .proof-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .proof-grid { grid-template-columns: 1fr; } }
.proof-tile {
  padding: 2rem 1.75rem;
  background: var(--dark-surface);
  border: 1px solid var(--dark-border);
  border-radius: var(--r-lg);
  transition: all 0.35s var(--ease);
  position: relative;
  overflow: hidden;
}
.proof-tile::before {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(135deg, transparent 55%, hsl(270 70% 55% / 0.15));
  opacity: 0; transition: opacity 0.35s;
}
.proof-tile:hover { transform: translateY(-2px); border-color: hsl(270 70% 55% / 0.5); }
.proof-tile:hover::before { opacity: 1; }
.proof-tile > * { position: relative; z-index: 1; }
.proof-value {
  font-size: clamp(2rem, 1.4rem + 2vw, 3rem);
  font-weight: 500;
  letter-spacing: -0.035em;
  color: white;
  line-height: 1.05;
}
.proof-value .arrow { color: hsl(280 100% 84%); font-family: var(--font-accent); font-style: italic; font-weight: 500; font-size: calc(1em * var(--accent-scale)); }
.proof-label {
  margin-top: 0.85rem;
  font-size: 0.925rem;
  color: var(--dark-muted);
  line-height: 1.5;
}
.proof-cta { margin-top: 3rem; text-align: center; }
.proof-cta a {
  color: hsl(280 100% 84%); font-size: 0.95rem;
  border-bottom: 1px solid currentColor; padding-bottom: 2px;
  transition: color 0.2s;
}
.proof-cta a:hover { color: white; }

/* =========================================================
   Pricing
   ========================================================= */
.pricing-header { text-align: center; max-width: 44rem; margin: 0 auto clamp(3rem, 5vw, 4rem); }
/* The base h2 is width-capped for line length, so the capped box needs centring
   inside the centred header. This lived on the element as an inline style. */
.pricing-header h2 { margin-inline: auto; }

/* Three tiers, not four: the two self-serve tiers are merged into one card
   because neither is buyable yet, and two waitlist cards spent half the row on
   nothing anyone can buy. Three columns also give each card enough width that
   nothing has to be squeezed or truncated. */
.pricing-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.25rem; }
@media (max-width: 900px) { .pricing-grid { grid-template-columns: 1fr; max-width: 30rem; margin-inline: auto; } }

.price-card {
  padding: clamp(1.5rem, 2.2vw, 2rem);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  /* Enough lift to read as a card sitting on the section rather than a drawn box,
     and little enough that the row still reads as three peers. Hover deepens it. */
  box-shadow: var(--shadow-sm);
  display: flex; flex-direction: column;
  transition: border-color 0.25s var(--ease), box-shadow 0.25s var(--ease);
}
.price-card:hover { border-color: var(--brand-border); box-shadow: var(--shadow-md); }

/* Side by side, the cards share the parent's rows instead of each stacking its own,
   so the price, the bullet list, and the CTA sit on one baseline across the row
   however many lines a name or description takes. That alignment used to be bought
   by reserving a second line on every tier name and a bigger top margin on the
   bullets that follow no "Everything in" label, both of which showed up as dead
   space. Below the breakpoint the cards stack and go back to the flex layout, where
   there is no row to align to. Row 4 is the "Everything in …, plus" label: the
   first card has none, and its empty row is what keeps that card's bullets level
   with the other two. */
@media (min-width: 901px) {
  .pricing-grid { grid-template-rows: repeat(6, auto); row-gap: 0; }
  .price-card { display: grid; grid-template-rows: subgrid; grid-row: span 6; }
  .price-tier-name { grid-row: 1; }
  .price-desc { grid-row: 2; }
  .price-amount { grid-row: 3; }
  .price-inherit { grid-row: 4; }
  .price-features { grid-row: 5; }
  .price-card .btn { grid-row: 6; align-self: end; }
}
/* The same ground as the Proof section, from the same token, layered here as
   backgrounds rather than an overlay because the card has no ::before to spare
   (its rows are a subgrid). Percentages resolve against the card, so the two glows
   land in the same corners at every card size. */
.price-card.featured {
  border-color: var(--dark-bg);
  background: var(--dark-glow), var(--dark-bg);
  color: var(--bg);
}

.price-tier-name {
  font-weight: 600;
  font-size: clamp(1.25rem, 1.1rem + 0.5vw, 1.5rem);
  letter-spacing: -0.02em; line-height: 1.2;
  color: var(--ink);
}
/* No height reserved here. A second line used to be held open on every name so the
   prices stayed level when the longest one wrapped, which showed up as dead space
   above each description. The subgrid above keeps the row level instead, and it
   does so whether a name takes one line or two. */

/* One sentence answering "is this me?", set in the Newsreader accent italic like
   the other editorial asides on the page. It replaces the pair of seats/products
   chips, which read as spec and made the reader translate numbers into a fit.
   --accent-scale corrects the serif's optical overshoot against the sans. */
.price-desc {
  margin-top: 0.6rem;
  font-family: var(--font-accent); font-style: italic; font-weight: 500;
  font-size: calc(1.0625rem * var(--accent-scale));
  color: var(--ink-muted); line-height: 1.45;
}

.price-amount { margin-top: 1.5rem; font-size: 1.875rem; font-weight: 500; letter-spacing: -0.03em; color: var(--ink); line-height: 1; }
.price-amount .per { font-size: 0.875rem; color: var(--ink-muted); font-weight: 400; letter-spacing: 0; margin-left: 0.3rem; }
.price-amount.is-custom { font-size: 1.5rem; }

/* "Everything in the tier before, plus" as a quiet label rather than a bullet, so
   inheritance does not consume a feature slot. It also names the list that follows
   it for assistive tech, via aria-labelledby in the markup. */
.price-inherit {
  margin-top: 2rem;
  font-size: 0.75rem; color: var(--ink-muted);
}
/* Grouped by whitespace rather than a rule: a divider would need the same offset
   in all three cards, and the card with no inheritance label has nothing to line
   one up against. */
.price-features {
  margin-top: 0.85rem; margin-bottom: 2rem;
  font-size: var(--text-sm); color: var(--ink-2); line-height: 1.5;
}
/* Stacked, there is no row to inherit spacing from, so the card with no
   "Everything in …, plus" label opens its list with the space that label would
   have taken. Side by side the subgrid handles it and this would double up. */
@media (max-width: 900px) {
  .price-features.no-inherit { margin-top: 2rem; }
}
.price-features li { padding-left: 1.5rem; position: relative; margin-bottom: 0.6rem; }
.price-features li:last-child { margin-bottom: 0; }
/* Ticks rather than dots: every line is something the tier includes, and a dot
   only says "list item". Sized and offset to sit on the first line's optical
   centre, and drawn with background through the mask so the featured card's
   lighter accent below still recolours it. */
.price-features li::before {
  content: ""; position: absolute; left: 0; top: 0.28em;
  width: 0.875rem; height: 0.875rem; background: var(--brand);
  -webkit-mask: var(--check-mask) center / contain no-repeat;
  mask: var(--check-mask) center / contain no-repeat;
}

/* margin-top: auto pins the CTA to the bottom of the card in the stacked layout.
   Side by side the subgrid puts every CTA in the same row, so it is the fallback
   rather than the mechanism. */
.price-card .btn { margin-top: auto; padding-block: 0.8rem; width: 100%; justify-content: center; }

.price-card.featured .price-tier-name { color: var(--bg); }
.price-card.featured .price-desc { color: rgba(255,255,255,0.72); }
.price-card.featured .price-amount { color: white; }
.price-card.featured .price-inherit { color: rgba(255,255,255,0.6); }
.price-card.featured .price-features { color: rgba(255,255,255,0.85); }
.price-card.featured .price-features li::before { background: hsl(280 100% 84%); }
/* Transparent border matches the 1px on .btn-ghost, so all three CTAs are the
   same height rather than the borderless one sitting 2px shorter. */
.price-card .btn-brand { border: 1px solid transparent; }

/* Not on sale yet, so the card sits back rather than competing with the two that
   can actually be bought: canvas ground instead of a raised white surface, and a
   muted name and price. It keeps the row's shadow, so all three read as cards.

   Deliberately a visual recession and not a disabled state. Body copy keeps full
   contrast and the CTA stays completely active, because joining the waitlist is a
   real action — dimming it would suppress the one thing this card is here to do. */
.price-card.coming {
  background: transparent;
}
.price-card.coming:hover { border-color: var(--border-strong); }
.price-card.coming .price-tier-name { color: var(--ink-muted); }
.price-card.coming .price-amount { color: var(--ink-muted); }
/* The CTA is left to .btn-ghost, identical to the Product Portfolio button down to
   the hover fill. This card used to restate those properties at a higher
   specificity, which beat .btn-ghost:hover and left the waitlist button the only
   CTA in the row that did not fill on hover. Recession is the card's job, not the
   button's. */

/* =========================================================
   CLOSING CTA (dark)
   ========================================================= */
.closing {
  background: var(--dark-bg);
  color: var(--dark-ink);
  padding-block: clamp(5rem, 9vw, 8rem);
  text-align: center;
  position: relative;
  overflow: hidden;
}
.closing::before {
  content: ""; position: absolute; inset: 0;
  background:
    radial-gradient(ellipse 60% 50% at 50% 100%, hsl(270 80% 40% / 0.5), transparent 60%),
    radial-gradient(ellipse 40% 30% at 50% 0%, hsl(280 80% 40% / 0.3), transparent 60%);
  pointer-events: none;
}
.closing-inner { position: relative; z-index: 1; max-width: 46rem; margin: 0 auto; padding-inline: var(--gutter); }
.closing h2 {
  color: white; max-width: 20ch; margin-inline: auto;
  font-size: clamp(2rem, 1.2rem + 3vw, 3.5rem);
  line-height: 1.06;
}
.closing h2 .italic-accent { color: hsl(280 100% 84%); display: block; }

/* ---------------------------------------------------------------
   Accent lines on narrow screens.

   Four section headings give .italic-accent its own line, which reads well
   when there is width to spend. On a phone there is not: the forced line costs
   a whole line of the heading, taking these to three and four. Letting the
   accent flow inline lets the heading wrap as the one sentence it is.

   Scoped to 640px because that is where it starts paying. At 600px and 768px
   every one of these is already two lines either way, so applying it wider
   would change the editorial look for nothing.

   Measured at 375px, accent inline:
     #workos   3 -> 2 lines
     #proof    3 -> 2 lines
     #problem  4 -> 3 lines - two would need the type at 22.8px, since its
               789px of text has only 670px of two-line capacity. Not worth
               breaking the shared heading scale for, so three it is.
     #closing  stays blocked: inline leaves it at three lines and makes it
               taller, so it gains nothing.

   These selectors match the blocking rules' specificity exactly, so this has
   to stay below all of them - order is what makes it win. */
@media (max-width: 640px) {
  .workos h2 .italic-accent,
  .problem-header h2 .italic-accent,
  .proof h2 .italic-accent { display: inline; }
  /* The x-height compensation on this one exists only to even up an accent
     line box against the Brown lines above it. Inline, there is no such line. */
  .problem-header h2 .italic-accent { line-height: inherit; }
  /* Two lines from a wrap can still rag badly; balance evens them. */
  .workos h2, .problem-header h2, .proof h2 { text-wrap: balance; }
}
.closing p { margin: 1.75rem auto 0; color: var(--dark-muted); max-width: 42rem; font-size: 1.0625rem; line-height: 1.55; }
.closing .btn { margin-top: 2.5rem; padding: 1rem 1.75rem; font-size: 1rem; }

/* =========================================================
   CONTACT PAGE (contact/) AND ITS THANK-YOU PAGE (contact/thank-you/)
   ========================================================= */
.contact {
  /* min-height rather than height: the form outgrows short viewports. 68px is the
     sticky nav; keeping the footer at the fold edge makes the page feel composed. */
  min-height: calc(100vh - 68px);
  display: flex; align-items: center;
  background:
    radial-gradient(ellipse 50% 40% at 85% 0%, hsl(270 100% 97%), transparent 65%),
    var(--bg);
}
.contact-grid {
  width: 100%;
  display: grid; grid-template-columns: 1fr 1.1fr;
  gap: clamp(2.5rem, 6vw, 5.5rem);
  align-items: start;
}
.contact-intro h1 {
  font-size: var(--text-3xl);
  line-height: 1.06;
  max-width: 14ch;
}
.contact-intro .lede { margin-top: 1.25rem; }
.contact-points { margin-top: 2rem; display: flex; flex-direction: column; gap: 0.75rem; }
/* The generic demo page leaves this list empty, and an empty flex item would still
   spend its top margin. */
.contact-points:empty { display: none; }
.contact-points li {
  position: relative; padding-left: 1.5rem;
  color: var(--ink-2); font-size: var(--text-sm); line-height: 1.5;
}
/* Same tick, size, and offset as the pricing card lists: a visitor arriving from a
   card is reading the same list again, so it should not change shape on the way.
   The dot's glow ring goes with it, because a box-shadow is drawn from the box
   rather than the mask and would ghost a square behind the mark. */
.contact-points li::before {
  content: ""; position: absolute; left: 0; top: 0.28em;
  width: 0.875rem; height: 0.875rem; background: var(--brand);
  -webkit-mask: var(--check-mask) center / contain no-repeat;
  mask: var(--check-mask) center / contain no-repeat;
}
.contact-alt { margin-top: 2.25rem; font-size: var(--text-sm); color: var(--ink-muted); }

/* The 404's single way out. Only the offset is new: .btn-primary carries the rest. */
.nf-home { margin-top: 2rem; }

.contact-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  padding: clamp(1.5rem, 3.5vw, 2.5rem);
  box-shadow: var(--shadow-lg);
}
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.field { margin-bottom: 1.15rem; }
.field label {
  display: block; margin-bottom: 0.4rem;
  font-size: 0.8125rem; font-weight: 500; color: var(--ink);
  letter-spacing: 0.01em;
}
.field .req { color: var(--brand-strong); }
.field .opt { color: var(--ink-muted); font-weight: 400; }
.field input, .field textarea {
  width: 100%;
  padding: 0.7rem 0.9rem;
  background: var(--bg);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  font-size: var(--text-sm);
  color: var(--ink);
  transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease), background 0.2s var(--ease);
}
.field input::placeholder, .field textarea::placeholder { color: var(--ink-faint); }
.field textarea { resize: vertical; min-height: 6rem; }
.field input:hover, .field textarea:hover { border-color: var(--ink-faint); }
/* Focus is carried by the border + ring, so the global outline would double up. */
.field input:focus-visible, .field textarea:focus-visible {
  outline: none;
  background: var(--surface);
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-glow);
}
.field input.invalid, .field textarea.invalid { border-color: var(--danger); }
.field input.invalid:focus-visible, .field textarea.invalid:focus-visible {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px hsl(346 79% 50% / 0.18);
}
.field-error { margin-top: 0.4rem; font-size: 0.8125rem; color: var(--danger); }

/* Honeypot. Moved out of view rather than display:none, because some bots skip
   undisplayed fields and would never take the bait. aria-hidden + tabindex="-1"
   in the markup keep it away from screen readers and the tab order. */
.field-decoy {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Send failures, as opposed to .field-error's per-field validation messages. */
.form-error {
  margin-top: 1rem;
  padding: 0.7rem 0.9rem;
  background: var(--danger-tint);
  border: 1px solid color-mix(in srgb, var(--danger) 30%, transparent);
  border-radius: var(--r-md);
  font-size: 0.8125rem;
  color: var(--danger);
  max-width: none;
}

.contact-submit { width: 100%; justify-content: center; padding: 0.95rem 1.5rem; font-size: 1rem; margin-top: 0.5rem; }
/* No hover lift while sending: the button is inert until the request settles. */
.contact-submit:disabled { opacity: 0.45; cursor: default; }
.contact-submit:disabled:hover { background: var(--brand); transform: none; }
.contact-privacy { margin-top: 1rem; font-size: 0.75rem; color: var(--ink-muted); text-align: center; max-width: none; }
/* The Privacy Policy link inside the disclosure. base.css strips every underline and
   sets a { color: inherit }, which left this one rendering in exactly the paragraph's
   own grey with no underline and no weight change — invisible as a link, and a 1.4.1
   Use of Color failure with nothing at all to fall back on. Same treatment as
   .link-out so in-prose links speak one language across the site. */
.contact-privacy a {
  text-decoration: underline;
  text-underline-offset: 0.2em;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, currentColor 45%, transparent);
  transition: color 0.2s var(--ease), text-decoration-color 0.2s var(--ease);
}
.contact-privacy a:hover, .contact-privacy a:focus-visible {
  color: var(--brand-strong);
  text-decoration-color: currentColor;
}

.contact-confirm { text-align: center; padding-block: clamp(1.5rem, 4vw, 3rem); }
.confirm-mark {
  width: 56px; height: 56px; margin: 0 auto 1.25rem;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--success-tint); color: var(--success);
  border: 1px solid color-mix(in srgb, var(--success) 30%, transparent);
}
/* h1 on the thank-you page, where the confirmation is the whole page; the rule
   covers h2 as well so the block travels if it is ever nested under one again. */
.contact-confirm :is(h1, h2) { max-width: 18ch; margin-inline: auto; font-size: var(--text-xl); }
.contact-confirm p { margin: 1rem auto 0; max-width: 38ch; color: var(--ink-2); font-size: var(--text-sm); }

/* The thank-you page has no intro column beside the card: the confirmation is the
   page. One centred column rather than the form page's two, capped so the lines
   inside it keep their measure on a wide viewport. */
.contact-grid.is-confirm { grid-template-columns: minmax(0, 33rem); justify-content: center; }

@media (max-width: 860px) {
  .contact { min-height: 0; display: block; }
  .contact-grid { grid-template-columns: 1fr; }
  .contact-intro h1 { max-width: none; }
}
@media (max-width: 480px) {
  .field-row { grid-template-columns: 1fr; gap: 0; }
}

/* =========================================================
   FOOTER
   ========================================================= */
footer {
  background: var(--dark-bg);
  color: var(--dark-muted);
  border-top: 1px solid var(--dark-border);
  padding: clamp(3rem, 6vw, 4.5rem) 0 0;
  font-size: 0.875rem;
}
.footer-inner {
  max-width: var(--container-wide); margin: 0 auto;
  padding-inline: var(--gutter);
  display: grid; gap: 2.5rem clamp(1.5rem, 4vw, 3.5rem);
  grid-template-columns: 1.6fr repeat(3, 1fr);
}
.footer-brand-col { display: flex; flex-direction: column; align-items: flex-start; gap: 1rem; }
.footer-logo { height: 24px; width: auto; display: block; }
.footer-tagline { color: var(--dark-muted); max-width: 30ch; font-size: 0.875rem; line-height: 1.55; }

.footer-parent {
  display: inline-flex; align-items: center; gap: 0.5rem;
  color: rgba(255,255,255,0.72); transition: color 0.2s var(--ease);
}
.footer-parent-pre {
  /* 0.55 rather than a dimmer value: at 10px this needs 4.5:1 on Purple-950, and
     0.45 measured 4.49. Quiet enough to stay subordinate to the wordmark. */
  font-size: 0.625rem; font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(255,255,255,0.55); transition: color 0.2s var(--ease);
}
.footer-parent-mark { height: 15px; width: 79px; display: block; }
/* Deliberately NOT --emergn-red here: #eb1414 on Purple-950 is ~3.4:1 and fails AA.
   The wordmark hovers white on dark; only the nav version goes red. Don't "fix" this. */
.footer-parent:hover, .footer-parent:focus-visible { color: #fff; }
.footer-parent:hover .footer-parent-pre, .footer-parent:focus-visible .footer-parent-pre { color: rgba(255,255,255,0.7); }

.footer-h {
  /* 0.55, not 0.42 — 0.42 measured 4.06:1 on Purple-950 and these are real headings. */
  font-size: 0.6875rem; font-weight: 500; letter-spacing: 0.16em; text-transform: uppercase;
  color: rgba(255,255,255,0.55); margin-bottom: 1rem; line-height: 1.2;
}
.footer-col ul { display: flex; flex-direction: column; gap: 0.6rem; }
.footer-col a { color: rgba(255,255,255,0.72); transition: color 0.2s var(--ease); }
.footer-col a:hover, .footer-col a:focus-visible { color: #fff; }
.footer-out a { display: inline-flex; align-items: center; gap: 0.35rem; }
.footer-out a::after {
  content: ""; width: 9px; height: 9px; flex: none; opacity: 0.5;
  background: currentColor;
  -webkit-mask: var(--ext-mask) center / contain no-repeat;
  mask: var(--ext-mask) center / contain no-repeat;
}
.footer-out a:hover::after { opacity: 0.9; }
.footer-out a[href^="#"]::after, .footer-out a[href^="mailto"]::after,
/* Internal, so no ↗. Matches /contact and every instance of the form below it. */
.footer-out a[href^="/contact"]::after { display: none; }

.footer-bar {
  max-width: var(--container-wide); margin: clamp(2.5rem, 5vw, 3.5rem) auto 0;
  padding: 1.25rem var(--gutter) 1.5rem;
  border-top: 1px solid var(--dark-border);
  display: flex; flex-wrap: wrap; gap: 0.75rem 2rem;
  align-items: center; justify-content: space-between;
  font-size: 0.8125rem;
}
.footer-copy { color: rgba(255,255,255,0.5); max-width: none; }
.footer-legal { display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; }
.footer-legal a { color: rgba(255,255,255,0.5); transition: color 0.2s var(--ease); }
.footer-legal a:hover, .footer-legal a:focus-visible {
  color: rgba(255,255,255,0.85); text-decoration: underline; text-underline-offset: 0.2em;
}

@media (max-width: 900px) {
  .footer-inner { grid-template-columns: 1fr 1fr; }
  .footer-brand-col { grid-column: 1 / -1; }
}
@media (max-width: 520px) {
  .footer-inner { grid-template-columns: 1fr; }
  .footer-bar { flex-direction: column; align-items: flex-start; }
}

/* --brand on Purple-950 is only ~3.9:1, so the focus ring needs to be white on dark bands. */
footer :focus-visible, .proof :focus-visible, .closing :focus-visible {
  outline-color: #fff;
}

/* In-prose outbound links. base.css strips all underlines; emergn.com underlines links by
   default, so restoring it here for body copy is a shared-DNA borrow that also fixes a real
   discoverability gap. Hover is Praxis purple, not Emergn red: colour signals "this page's
   interactive language", the ↗ glyph signals "this leaves". */
.link-out {
  text-decoration: underline;
  text-underline-offset: 0.2em;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, currentColor 38%, transparent);
  transition: color 0.2s var(--ease), text-decoration-color 0.2s var(--ease);
}
.link-out:hover, .link-out:focus-visible {
  color: var(--brand-strong);
  text-decoration-color: currentColor;
}

/* =========================================================
   Reveal-on-scroll
   ========================================================= */
.reveal { opacity: 0; transform: translateY(16px); transition: opacity 0.7s var(--ease), transform 0.7s var(--ease); }
.reveal.in { opacity: 1; transform: none; }
.reveal.d1 { transition-delay: 0.05s; }
.reveal.d2 { transition-delay: 0.10s; }
.reveal.d3 { transition-delay: 0.15s; }
.reveal.d4 { transition-delay: 0.20s; }

/* =========================================================
   UI MOCK COMPONENTS (Praxis app screenshot placeholders)
   ========================================================= */
.mock {
  background: white;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 1rem;
  box-shadow: var(--shadow-sm);
  font-size: 0.85rem;
  overflow: hidden;
}
.mock-title { font-size: 0.7rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-muted); margin-bottom: 0.75rem; }
.mock-row { display: flex; align-items: center; justify-content: space-between; padding: 0.55rem 0; border-bottom: 1px dashed var(--border); font-size: 0.8rem; }
.mock-row:last-child { border-bottom: 0; }
.mock-row .name { color: var(--ink); font-weight: 500; flex: 1; }
.mock-pill {
  font-size: 0.68rem; font-weight: 500; padding: 0.2rem 0.5rem;
  border-radius: var(--r-full); letter-spacing: 0.02em;
}
.pill-fund { background: var(--success-tint); color: var(--success); }
.pill-park { background: var(--warn-tint); color: var(--warn); }
.pill-drop { background: var(--danger-tint); color: var(--danger); }
.pill-brand { background: var(--brand-tint); color: var(--brand-strong); }
.mock-val { font-variant-numeric: tabular-nums; color: var(--ink-muted); font-size: 0.75rem; }

/* App chrome mock */
.app-chrome {
  position: absolute; inset: 0;
  background: var(--surface);
  display: grid;
  grid-template-columns: 220px 1fr;
  grid-template-rows: 48px 1fr;
}
.app-topbar {
  grid-column: 1 / -1;
  border-bottom: 1px solid var(--border);
  background: white;
  display: flex; align-items: center; padding: 0 1rem;
  gap: 0.75rem;
}
.dot { width: 10px; height: 10px; border-radius: 50%; background: #e6e2da; }
.dot.dot-red { background: #ff6c65; }
.dot.dot-y { background: #ffbf3d; }
.dot.dot-g { background: #26cd6a; }
.app-tab {
  font-size: 0.72rem; color: var(--ink-muted); padding: 0.25rem 0.5rem;
  border-radius: var(--r-sm);
}
.app-tab.on { background: var(--brand-tint); color: var(--brand-strong); font-weight: 500; }
.app-tabs { margin-left: auto; display: flex; gap: 0.4rem; flex-shrink: 0; }
.app-sidebar {
  border-right: 1px solid var(--border);
  padding: 1rem 0.75rem;
  background: var(--bg);
}
.side-item {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.45rem 0.5rem; border-radius: var(--r-sm);
  font-size: 0.78rem; color: var(--ink-2);
  margin-bottom: 0.15rem;
}
.side-item.on { background: white; color: var(--ink); border: 1px solid var(--border); font-weight: 500; }
.side-item .dot-brand { width: 6px; height: 6px; border-radius: 50%; background: var(--brand); }
.app-main { padding: 1.25rem; overflow: hidden; }

/* KPI strip inside app */
.kpi-strip { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.6rem; margin-bottom: 0.85rem; }
.kpi {
  padding: 0.65rem 0.8rem;
  background: white;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}
.kpi-label { font-size: 0.65rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-muted); }
.kpi-value { font-size: 1.05rem; font-weight: 500; letter-spacing: -0.015em; color: var(--ink); margin-top: 0.15rem; font-variant-numeric: tabular-nums; }
.kpi-delta { font-size: 0.68rem; margin-top: 0.15rem; }
.kpi-delta.up { color: var(--success); }
.kpi-delta.down { color: var(--danger); }

/* Portfolio table mock */
.p-table { border: 1px solid var(--border); border-radius: var(--r-md); background: white; overflow: hidden; }
.p-table .p-head {
  display: grid;
  grid-template-columns: 2fr 0.9fr 1fr 0.9fr;
  gap: 0.5rem;
  padding: 0.55rem 0.85rem;
  background: var(--bg);
  font-size: 0.63rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-muted);
  border-bottom: 1px solid var(--border);
}
.p-row {
  display: grid;
  grid-template-columns: 2fr 0.9fr 1fr 0.9fr;
  gap: 0.5rem; align-items: center;
  padding: 0.5rem 0.85rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.78rem;
}
.p-row:last-child { border-bottom: 0; }
.p-row .p-name { color: var(--ink); font-weight: 500; }
.p-row .p-name .sub { display: block; color: var(--ink-muted); font-size: 0.68rem; font-weight: 400; margin-top: 1px; }
.p-row .p-val { text-align: right; font-variant-numeric: tabular-nums; color: var(--ink); }
.bar { height: 5px; background: var(--bg-alt); border-radius: var(--r-full); overflow: hidden; }
.bar > i { display: block; height: 100%; background: var(--brand); border-radius: inherit; }

/* Decision card mock */
.card-idea {
  background: white; border: 1px solid var(--border); border-radius: var(--r-md); padding: 0.9rem;
}
.card-idea h4 { font-size: 0.85rem; font-weight: 500; letter-spacing: -0.005em; }
.card-idea .id { font-size: 0.7rem; color: var(--ink-muted); letter-spacing: 0.05em; margin-bottom: 0.35rem; }
.evidence-bar {
  margin-top: 0.75rem; display: flex; align-items: center; gap: 0.4rem;
  font-size: 0.68rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-muted);
}
.evidence-track { flex: 1; height: 4px; background: var(--bg-alt); border-radius: 999px; overflow: hidden; }
.evidence-track > i { display: block; height: 100%; background: linear-gradient(90deg, var(--warn), var(--success)); }

/* Stella message bubble */
.stella-msg {
  background: white; border: 1px solid var(--brand-border);
  border-radius: var(--r-lg);
  padding: 0.85rem 1rem;
  box-shadow: 0 6px 20px -8px hsl(270 70% 30% / 0.18);
  position: relative;
}
.stella-msg::before {
  content: ""; position: absolute; left: -6px; top: 12px;
  width: 12px; height: 12px; background: white; border-left: 1px solid var(--brand-border); border-bottom: 1px solid var(--brand-border);
  transform: rotate(45deg);
}
.stella-head {
  display: flex; align-items: center; gap: 0.5rem;
  font-size: 0.78rem; margin-bottom: 0.35rem;
}
.stella-avatar {
  width: 22px; height: 22px; border-radius: 50%;
  background: linear-gradient(135deg, hsl(270 70% 55%), hsl(280 80% 68%));
  color: white; font-size: 0.62rem; display: grid; place-items: center;
  font-weight: 600; letter-spacing: 0.05em;
}
.stella-msg .who { font-weight: 600; color: var(--ink); }
.stella-msg .badge {
  font-size: 0.6rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--warn); font-weight: 600;
  padding: 0.15rem 0.4rem; border-radius: var(--r-full); background: var(--warn-tint);
}
.stella-msg .body { font-size: 0.85rem; color: var(--ink-2); line-height: 1.5; }
.stella-msg .body em { font-family: var(--font-accent); font-style: italic; font-weight: 500; color: var(--brand-strong); font-size: calc(0.9rem * var(--accent-scale)); }
.stella-msg .cite {
  margin-top: 0.55rem;
  font-size: 0.68rem; color: var(--ink-muted); letter-spacing: 0.05em;
  padding-top: 0.5rem; border-top: 1px dashed var(--border);
}

/* Chart mock (mini sparkline / bar) */
.mini-chart {
  height: 50px; display: flex; align-items: flex-end; gap: 3px;
}
.mini-chart .b { flex: 1; background: var(--brand); border-radius: 2px 2px 0 0; opacity: 0.85; }

/* Data-flow animated background lines */
.flow-lines {
  position: absolute; inset: 0; pointer-events: none; opacity: 0.6;
}
.flow-lines path {
  fill: none; stroke: var(--brand); stroke-width: 1;
  stroke-dasharray: 6 8; opacity: 0.35;
}
/* stroke-dashoffset cannot be composited, so every frame of this repaints a
   viewport-sized SVG on the main thread. Sitting above the fold and starting at
   first paint, it competed with the load it was decorating: on a throttled Moto
   G Power that showed up in Speed Index and in the hero headline's render delay.
   index.html adds .is-drawing on the load event instead. The lines sit at 0.35
   opacity behind the hero, so starting them a beat late is not perceptible, and
   nothing about the finished state changes. */
.flow-lines.is-drawing path {
  animation: dash 8s linear infinite;
}
@keyframes dash { to { stroke-dashoffset: -140; } }

/* Showcase tabs: tighten the pills once the row gets cramped. */
@media (max-width: 640px) {
  .callout-row { gap: 0.4rem; }
  .callout { padding: 0.5rem 0.9rem; font-size: 0.9375rem; }
}

/* Sub-nav breadcrumb mock */
.crumb {
  display: inline-flex; gap: 0.35rem; align-items: center;
  font-size: 0.68rem; color: var(--ink-muted);
  letter-spacing: 0.04em;
}
.crumb .sep { opacity: 0.4; }
.crumb .cur { color: var(--ink); font-weight: 500; }

/* Utility */
.mt-0 { margin-top: 0; } .mt-1 { margin-top: 0.25rem; }
/* Screen-reader-only text: the description a live facade carries in place of
   an image's alt. */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* Skip link. The first focusable element on every page, parked off-screen until
   it takes focus rather than hidden with .sr-only — a skip link has to be able to
   show itself. Offset rather than transformed so there is no motion to suppress,
   and above the nav's z-index: 50 so it is never covered when it appears. */
.skip-link {
  position: absolute; top: 0; left: -100vw; z-index: 60;
  padding: 0.7rem 1.1rem;
  background: var(--ink); color: var(--bg);
  font-size: 0.875rem; line-height: 1;
  border-radius: 0 0 8px 0;
}
.skip-link:focus { left: 0; }

/* =========================================================
   Live hero — Portfolio dashboard
   A Linear-style live-HTML recreation of the Praxis Portfolio
   dashboard (content from the Figma "Main Frame" export,
   interaction patterns from the Praxis 3.0 prototype).
   The component is laid out on a fixed 1400×849 canvas and
   scaled to the hero width via --pd-scale (set by JS; the
   fallback below approximates a 1120px-wide hero). It is
   decorative: aria-hidden, no focusable elements — hover
   styling only.
   ========================================================= */
.pd-viewport {
  position: relative;
  aspect-ratio: 1400 / 849;
  overflow: hidden;
  --pd-scale: 0.8;
}
.pd {
  position: absolute; top: 0; left: 0;
  width: 1400px; height: 849px;
  transform: scale(var(--pd-scale));
  transform-origin: 0 0;
  display: grid;
  grid-template-columns: 267px 1fr;
  font-family: var(--font-ui);
  font-size: 14px; line-height: 1.5;
  color: var(--pd-ink);
  background:
    radial-gradient(900px 600px at 0% 0%, hsl(270 90% 90% / 0.35), transparent 60%),
    radial-gradient(900px 600px at 100% 0%, hsl(213 100% 90% / 0.28), transparent 55%),
    var(--pd-paper-2);
  -webkit-font-smoothing: antialiased;
  cursor: default;
  user-select: none;
  transition: grid-template-columns 280ms cubic-bezier(.22, .61, .36, 1);
}
/* One-frame guard so the mobile default-collapsed state doesn't animate in on
   load. JS adds this, sets .pd-collapsed, then drops it on the next frame. */
.pd.pd-no-anim, .pd.pd-no-anim * { transition: none !important; }
.pd *, .pd *::before, .pd *::after { box-sizing: border-box; }

/* Collapsed sidebar — icon-only nav, compact logo, flipped toggle */
.pd.pd-collapsed { grid-template-columns: 76px 1fr; }
.pd-collapsed .pd-side { padding-left: 12px; padding-right: 12px; }
.pd-collapsed .pd-logo { flex-direction: column-reverse; align-items: center; gap: 12px; padding: 2px 0 20px; }
.pd-collapsed .pd-logo-full { display: none; }
.pd-collapsed .pd-logo .pd-logo-sm { display: block; }
.pd-collapsed .pd-collapse { margin-left: 0; }
.pd-collapsed .pd-collapse svg { transform: scaleX(-1); }
.pd-collapsed .pd-scope { justify-content: center; padding: 8px 0; width: 46px; margin-left: auto; margin-right: auto; }
.pd-collapsed .pd-scope > span,
.pd-collapsed .pd-scope > svg { display: none; }
.pd-collapsed .pd-nav { align-items: center; }
.pd-collapsed .pd-navitem { justify-content: center; padding: 0; width: 42px; height: 42px; border-radius: 12px; }
.pd-collapsed .pd-navitem > span { display: none; }
.pd-collapsed .pd-side-foot { justify-content: center; }
.pd-collapsed .pd-side-foot > span:nth-of-type(2),
.pd-collapsed .pd-side-foot > svg { display: none; }

/* ---------- Sidebar ---------- */
.pd-side {
  display: flex; flex-direction: column;
  padding: 22px 14px 16px;
  min-height: 0;
}
.pd-logo { display: flex; align-items: center; gap: 8px; padding: 2px 6px 28px 14px; }
.pd-logo img { height: 20px; width: auto; display: block; }
.pd-logo .pd-logo-sm { display: none; height: 24px; }
.pd-collapse {
  margin-left: auto;
  width: 26px; height: 26px; border-radius: 8px;
  display: grid; place-items: center;
  color: var(--pd-ink-3); border: 1px solid transparent;
  cursor: pointer;
  transition: background 140ms ease, border-color 140ms ease, color 140ms ease;
}
.pd-collapse:hover { background: var(--pd-surface); border-color: var(--pd-line); color: var(--pd-ink); }
.pd-collapse svg { transition: transform 280ms cubic-bezier(.22, .61, .36, 1); }

.pd-scope {
  display: flex; align-items: center; gap: 10px;
  background: var(--pd-surface);
  border: 1px solid var(--pd-line);
  border-radius: 12px;
  padding: 8px 12px 8px 8px;
  cursor: pointer;
  transition: border-color 150ms ease, box-shadow 150ms ease;
}
.pd-scope:hover { border-color: hsl(0 0% 8% / 0.22); box-shadow: 0 2px 8px hsl(var(--pd-shade-2) / 0.06); }
.pd-scope-wrap { position: relative; margin-bottom: 13px; }
.pd-scope-chev { transition: transform 160ms ease; }
.pd-scope-open .pd-scope-chev { transform: rotate(180deg); }

/* Scope dropdown — mirrors the prototype's switcher menu */
.pd-scope-menu {
  position: absolute; top: calc(100% + 5px); left: 0; right: 0;
  min-width: 208px; z-index: 12;
  background: var(--pd-surface);
  border: 1px solid var(--pd-line);
  border-radius: 12px;
  box-shadow: 0 8px 24px -6px hsl(var(--pd-shade) / 0.18), 0 2px 4px hsl(var(--pd-shade) / 0.06);
  padding: 4px;
  opacity: 0; transform: translateY(-4px) scale(0.98);
  pointer-events: none;
  transition: opacity 160ms ease, transform 160ms cubic-bezier(.22, .61, .36, 1);
}
.pd-scope-open .pd-scope-menu { opacity: 1; transform: none; pointer-events: auto; }
.pd-menu-label {
  padding: 9px 10px 5px;
  font-size: 10px; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--pd-ink-4);
}
.pd-menu-div { height: 1px; background: var(--pd-line-soft); margin: 4px 0; }
.pd-menu-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 9px; border-radius: 10px;
  font-size: 14px; font-weight: 500; color: var(--pd-ink);
  cursor: pointer;
  transition: background 120ms ease;
}
.pd-menu-item:hover { background: var(--pd-paper-3); }
.pd-menu-item.is-selected { font-weight: 700; }
.pd-menu-item.is-selected > svg { margin-left: auto; color: var(--brand); flex-shrink: 0; }
.pd-menu-item > span:not(.pd-prod-av) { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Product logo tiles — image tiles for real assets, tinted letter tiles for the rest */
.pd-prod-av {
  width: 24px; height: 24px; border-radius: 7px; flex-shrink: 0;
  display: grid; place-items: center; object-fit: cover;
  font-size: 10px; font-weight: 700; color: var(--pd-surface);
  box-shadow: 0 1px 2px hsl(var(--pd-shade) / 0.18);
}
.pd-scope-av {
  width: 28px; height: 28px; border-radius: 8px; flex-shrink: 0;
  display: block; object-fit: cover;
  box-shadow: 0 1px 3px hsl(var(--pd-shade) / 0.25);
}
.pd-scope-name { display: block; font-size: 13.5px; font-weight: 700; line-height: 1.1; }
/* Small uppercase label, shared by the scope switcher, the sidebar user role
   and the Idea screen's sub-labels. */
.pd-eyebrow-sm, .pd-scope-kind, .pd-user-role {
  font-size: 9.5px; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--pd-ink-4);
}
.pd-scope-kind, .pd-user-role { line-height: 1.2; margin-top: 2px; }
.pd-scope > svg:last-child { margin-left: auto; color: var(--pd-ink-3); flex-shrink: 0; }

.pd-nav { display: flex; flex-direction: column; gap: 8px; }
.pd-navitem {
  display: flex; align-items: center; gap: 12px;
  padding: 7px 14px; border-radius: 10px;
  font-size: 13.5px; font-weight: 500; color: var(--pd-ink-2);
  transition: background 150ms ease;
}
.pd-navitem svg { color: var(--pd-ink-2); flex-shrink: 0; }
.pd-navitem:hover { background: hsl(0 0% 8% / 0.045); }
.pd-navitem.active {
  background: var(--pd-surface); color: var(--pd-ink); font-weight: 700;
  box-shadow: 0 1px 2px hsl(var(--pd-shade-2) / 0.05), 0 4px 14px hsl(var(--pd-shade-2) / 0.06);
}

.pd-side-foot {
  margin-top: auto;
  display: flex; align-items: center; gap: 11px;
  padding: 10px 8px 2px;
  border-top: 1px solid var(--pd-line-soft);
  transition: opacity 150ms ease;
}
.pd-side-foot:hover .pd-user-name { color: var(--brand-strong); }
.pd-user-av {
  width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0;
  background: var(--pd-avatar); color: var(--pd-surface);
  display: grid; place-items: center;
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.02em;
}
.pd-user-name { font-size: 13px; font-weight: 700; line-height: 1.25; transition: color 150ms ease; }
.pd-side-foot > svg:last-child { margin-left: auto; color: var(--pd-ink-3); }

/* ---------- Main pane ---------- */
.pd-main {
  margin: 12px 12px 12px 0;
  background: var(--pd-surface);
  border-radius: 24px;
  border: 1px solid var(--pd-line-soft);
  box-shadow: -2px 0 24px hsl(var(--pd-shade-2) / 0.04);
  overflow: hidden;
  min-width: 0;
  padding: 22px 24px 0 21px;
}

/* Vision strip */
.pd-vision {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) 1px minmax(0, 1fr);
  gap: 36px;
  padding-bottom: 26px;
}
.pd-vision-div {
  background: linear-gradient(180deg, transparent 0%, var(--pd-line) 18%, var(--pd-line) 82%, transparent 100%);
}
.pd-eyebrow {
  font-size: 11px; font-weight: 700; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--pd-ink-3);
}
.pd-vision-text {
  margin: 6px 0 0;
  font-size: 20px; line-height: 1.38; letter-spacing: -0.015em;
  font-weight: 400; color: var(--pd-ink);
  max-width: 640px;
  text-wrap: pretty;
}
.pd-vision-cta {
  display: inline-flex; align-items: center; gap: 7px;
  margin-top: 16px;
  font-size: 13.5px; font-weight: 700; color: var(--pd-ink-2);
  transition: color 120ms ease;
}
.pd-vision-cta svg { transition: transform 120ms ease; }
.pd-vision-cta:hover { color: var(--brand); cursor: pointer; }
.pd-vision-cta:hover svg { transform: translateX(3px); }

.pd-goals { display: flex; flex-direction: column; gap: 10px; padding-top: 1px; }
.pd-goal {
  display: flex; align-items: center; gap: 16px;
  font-size: 13.5px; line-height: 1.3; color: var(--pd-ink); min-height: 24px;
}
.pd-goal.upcoming { color: var(--pd-ink-3); }
.pd-goal-label { flex: 1; line-height: 1.35; }
.pd-goal-pill {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 9.5px; font-weight: 700; letter-spacing: 0.09em;
  text-transform: uppercase;
  padding: 5px 10px; border-radius: 999px; white-space: nowrap;
  border: 1px solid;
}
.pd-goal-pill .pd-dot { width: 6px; height: 6px; border-radius: 50%; }
.pd-goal-pill.progress { color: hsl(270 50% 42%); background: var(--brand-tint); border-color: var(--brand-border); }
.pd-goal-pill.progress .pd-dot { background: hsl(270 70% 58%); }
.pd-goal-pill.upcoming { color: var(--pd-ink-3); background: var(--pd-surface); border-color: var(--pd-line); }

/* Cards */
.pd-card {
  background: var(--pd-surface);
  border: 1px solid var(--pd-line);
  border-radius: 16px;
  box-shadow: 0 1px 2px hsl(var(--pd-shade-2) / 0.03);
  padding: 18px;
}
.pd-card + .pd-card { margin-top: 10px; }

/* Kill score distribution */
.pd-killbar {
  display: flex; height: 22px; border-radius: 8px; overflow: hidden;
  margin-top: 5px;
  clip-path: inset(0 0 0 0 round 8px);
}
.pd-killbar .pd-seg {
  display: grid; place-items: center;
  font-size: 11px; font-weight: 600; color: var(--pd-surface);
  transition: width 900ms var(--ease) 500ms;
}
/* Pre-reveal state: segments meet at equal thirds, labels hidden */
.pd:not(.pd-live) .pd-seg { width: 33.34% !important; }
.pd .pd-seg > span { opacity: 1; transition: opacity 400ms ease 1150ms; }
.pd:not(.pd-live) .pd-seg > span { opacity: 0; transition: none; }
.pd-kill-legend {
  display: flex; gap: 20px; margin-top: 8px;
  font-size: 12.5px; color: var(--pd-ink-3);
}
.pd-kill-legend .pd-key { display: inline-flex; align-items: center; gap: 7px; }
.pd-kill-legend .pd-dot { width: 8px; height: 8px; border-radius: 50%; }

/* Stella insight banner */
.pd-stella {
  margin-top: 12px;
  display: flex; align-items: flex-start; gap: 12px;
  padding: 10px 14px 10px 16px;
  border-radius: 12px;
  border: 1px solid var(--stella-banner-border);
  background: var(--stella-banner);
  box-shadow: inset 0 1px 0 var(--glass-highlight-soft);
}
.pd-stella-body { flex: 1; font-size: 13px; line-height: 1.6; color: var(--pd-ink-2); text-wrap: pretty; }
.pd-stella-body strong { color: var(--pd-ink); font-weight: 700; }
.pd-ask-stella {
  flex-shrink: 0; align-self: center;
  display: inline-flex; align-items: center; gap: 7px;
  height: 34px; padding: 0 16px; border-radius: 999px;
  font-size: 13px; font-weight: 700; color: var(--pd-surface);
  background: var(--stella-grad);
  border: 1px solid var(--glass-edge);
  box-shadow:
    0 1px 0 var(--glass-sheen) inset,
    0 8px 22px -8px hsl(258 80% 55% / 0.45),
    0 2px 6px hsl(258 80% 55% / 0.18);
  transition: transform 120ms ease, box-shadow 150ms ease;
  cursor: pointer;
}
.pd-ask-stella:hover {
  transform: translateY(-1px);
  box-shadow:
    0 1px 0 var(--glass-sheen) inset,
    0 12px 28px -8px hsl(258 80% 55% / 0.55),
    0 3px 10px hsl(258 80% 55% / 0.22);
}
/* The primary invitation on each shell pulses until it is used, the same cue
   the canvas screen's Stella note already carries. The ring lives on ::after
   rather than as a fourth layer on the button's own box-shadow: that stack is
   three layers deep and hover rewrites all of it, so animating it here would
   mean restating every layer inside the keyframes and fighting hover for it. */
.pd-ask-stella.pd-pulse { position: relative; }
.pd-ask-stella.pd-pulse::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  pointer-events: none;
  animation: pd-ask-pulse 2.4s ease-in-out infinite;
}
@keyframes pd-ask-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--brand) 50%, transparent); }
  50%      { box-shadow: 0 0 0 8px transparent; }
}
/* Hover replaces the invitation with a definite state, as .pd-bmc-note does. */
.pd-ask-stella.pd-pulse:hover::after { animation: none; }

/* Funded ideas */
.pd-funded-head { display: flex; align-items: flex-start; gap: 16px; margin-bottom: 8px; }
.pd-h3 { font-size: 20px; font-weight: 700; letter-spacing: -0.01em; line-height: 1.25; }
.pd-funded-sub { font-size: 13.5px; color: var(--pd-ink-3); margin-top: 5px; }
/* The app's pill button, shared by every embed. Variants: .sm .ink .ghost
   .sq (icon square). Alignment belongs to the layout, not to the button. */
.pd-btn {
  display: inline-flex; align-items: center; gap: 8px;
  height: 32px; padding: 0 14px; border-radius: 999px;
  font-size: 13px; font-weight: 500; white-space: nowrap;
  background: var(--pd-surface); border: 1px solid var(--pd-line); color: var(--pd-ink);
  transition: border-color 150ms ease, box-shadow 150ms ease, background 150ms ease;
  cursor: pointer;
}
.pd-btn:hover { border-color: var(--pd-line-stronger); box-shadow: 0 2px 8px hsl(var(--pd-shade-2) / 0.06); }
.pd-btn.sm { height: 28px; padding: 0 12px; font-size: 12.5px; }
.pd-btn.ink { background: var(--pd-ink); border-color: var(--pd-ink); color: var(--pd-surface); }
.pd-btn.ink:hover { background: #000; box-shadow: 0 8px 24px -8px hsl(var(--pd-shade) / 0.35); }
.pd-btn.ghost { background: transparent; border-color: transparent; color: var(--pd-ink-2); }
.pd-btn.ghost:hover { background: var(--pd-paper-3); border-color: transparent; }
.pd-btn.sq { width: 28px; height: 28px; padding: 0; justify-content: center; flex-shrink: 0; color: var(--pd-ink-3); }
/* The hero's Funded Ideas header pushes its button to the right edge. */
.pd-funded-head .pd-btn { margin-left: auto; flex-shrink: 0; }

/* Lane header: label + meta left, column captions right (aligned over chips) */
.pd-lane {
  display: grid;
  grid-template-columns: 1fr 78px 78px 78px 81px;
  align-items: baseline; column-gap: 6px;
  padding: 3px 12px 7px;
}
.pd-lane-label { font-size: 12.5px; font-weight: 700; letter-spacing: 0.06em; color: var(--pd-ink); }
.pd-lane-label span { font-weight: 400; letter-spacing: 0; color: var(--pd-ink-4); margin-left: 10px; font-size: 12.5px; }
.pd-lane-col {
  font-size: 10px; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--pd-ink-4);
  text-align: center;
}

/* Idea rows */
.pd-row {
  display: grid;
  grid-template-columns: 20px 24px 58px 1fr 78px 78px 78px 81px;
  grid-column-gap: 6px;
  align-items: center;
  background: var(--pd-surface);
  border: 1px solid var(--pd-line);
  border-radius: 12px;
  padding: 7px 12px;
  margin-bottom: 4px;
  transition: border-color 140ms ease, box-shadow 140ms ease, transform 140ms ease;
  cursor: pointer;
}
.pd-row:last-child { margin-bottom: 0; }
.pd-row:hover {
  border-color: var(--pd-line-strong);
  box-shadow: 0 8px 24px -12px hsl(var(--pd-shade-2) / 0.18), 0 2px 4px hsl(var(--pd-shade-2) / 0.04);
  transform: translateY(-1px);
}
.pd-row-rank { font-size: 13px; color: var(--pd-ink-4); text-align: center; }
.pd-row-av {
  width: 20px; height: 20px; border-radius: 6px;
  display: grid; place-items: center; object-fit: cover;
  font-size: 10px; font-weight: 700; color: var(--pd-surface);
  justify-self: center;
  box-shadow: 0 1px 2px hsl(var(--pd-shade) / 0.18);
}
.pd-row-code { font-size: 11.5px; color: var(--pd-ink-4); letter-spacing: 0.02em; margin-left: 4px; }
.pd-row-title { font-size: 14px; font-weight: 400; color: var(--pd-ink); margin-left: 8px; }
.pd-chip {
  display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  height: 26px; padding: 0 4px; border-radius: 999px;
  background: linear-gradient(180deg, var(--pd-paper-2), var(--pd-surface));
  border: 1px solid hsl(0 0% 8% / 0.06);
  font-size: 11.5px; font-weight: 600;
  color: var(--pd-ink-2); white-space: nowrap;
  justify-self: stretch;
}
.pd-chip .muted { color: var(--pd-ink-4); font-weight: 400; }
.pd-chip.cd3 { color: var(--pd-green-deep); font-weight: 700; }
.pd-row-chev { color: var(--pd-ink-4); justify-self: center; transition: transform 140ms ease, color 140ms ease; }
.pd-row:hover .pd-row-chev { transform: translateX(2px); color: var(--pd-ink-2); }

/* Load-in: elements float up into place once the dashboard enters the viewport */
.pd .pd-anim { opacity: 0; transform: translateY(18px); }
.pd.pd-live .pd-anim {
  opacity: 1; transform: none;
  transition:
    opacity 650ms var(--ease) var(--pd-d, 0s),
    transform 650ms var(--ease) var(--pd-d, 0s);
}

/* Stella bubble — floating trigger, bottom right of the frame */
.pd-stella-bubble {
  position: absolute; bottom: 26px; right: 26px;
  width: 56px; height: 56px; border-radius: 50%;
  cursor: pointer; z-index: 5;
  box-shadow: 0 1px 2px hsl(var(--pd-shade) / 0.18), 0 8px 20px hsl(253 54% 51% / 0.30);
  transition: transform 220ms cubic-bezier(.22, .61, .36, 1), opacity 180ms ease, box-shadow 180ms ease;
}
.pd.pd-live .pd-stella-bubble.pd-anim { transition:
  transform 220ms cubic-bezier(.22, .61, .36, 1),
  box-shadow 180ms ease,
  opacity 650ms var(--ease) var(--pd-d, 0s);
}
.pd-stella-bubble img { width: 100%; height: 100%; border-radius: 50%; display: block; }
.pd-stella-bubble:hover {
  transform: translateY(-2px);
  box-shadow: 0 1px 2px hsl(var(--pd-shade) / 0.20), 0 12px 28px hsl(253 54% 51% / 0.38);
}
.pd.pd-stella-open .pd-stella-bubble { opacity: 0 !important; transform: translateY(8px) scale(0.85); pointer-events: none; }

/* Stella rail — slide-in chat panel */
.pd-rail {
  position: absolute; top: 24px; right: 24px; z-index: 6;
  width: 340px; height: calc(100% - 48px);
  display: flex; flex-direction: column;
  border-radius: 20px;
  overflow: hidden;
  background: var(--glass-panel);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-panel-border);
  box-shadow:
    0 0 0 1px var(--pd-line-soft),
    0 2px 6px hsl(var(--pd-shade) / 0.06),
    -16px 12px 48px hsl(var(--pd-shade) / 0.16);
  transform: translateX(calc(100% + 44px));
  transition: transform 280ms cubic-bezier(.22, .61, .36, 1);
}
.pd.pd-stella-open .pd-rail { transform: translateX(0); }
.pd-rail-head {
  display: flex; align-items: center; gap: 9px;
  padding: 12px;
  border-bottom: 1px solid var(--pd-line-soft);
}
.pd-rail-head > img { border-radius: 50%; }
.pd-rail-titles { display: flex; flex-direction: column; min-width: 0; line-height: 1.2; }
.pd-rail-name { font-size: 14px; font-weight: 700; }
.pd-rail-sub {
  font-size: 11.5px; font-weight: 500; color: var(--pd-ink-3);
  margin-top: 1px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pd-rail-actions { margin-left: auto; display: flex; align-items: center; gap: 5px; flex-shrink: 0; }
.pd-rail-act {
  width: 28px; height: 28px; border-radius: 50%;
  display: grid; place-items: center;
  color: var(--pd-ink-2);
  background: var(--glass-control);
  -webkit-backdrop-filter: var(--glass-blur-tight);
  backdrop-filter: var(--glass-blur-tight);
  border: 1px solid var(--glass-control-border);
  box-shadow:
    0 1px 0 var(--glass-highlight) inset,
    0 0 0 1px var(--pd-line-soft),
    0 2px 6px hsl(var(--pd-shade) / 0.08);
  cursor: pointer;
  transition: transform 120ms ease, box-shadow 150ms ease, background 150ms ease, color 150ms ease;
}
.pd-rail-act:hover {
  transform: translateY(-1px);
  background: var(--pd-surface);
  color: var(--pd-ink);
  box-shadow:
    0 1px 0 var(--glass-highlight-strong) inset,
    0 0 0 1px var(--pd-line),
    0 5px 14px hsl(var(--pd-shade) / 0.14);
}
.pd-rail-act:active { transform: translateY(0); }
.pd-rail-body { flex: 1; display: flex; flex-direction: column; padding: 16px; min-height: 0; }
.pd-rail-greeting { margin-top: auto; display: flex; align-items: center; gap: 14px; padding: 0 2px 18px; }
.pd-rail-gav {
  width: 44px; height: 44px; border-radius: 50%; flex-shrink: 0;
  box-shadow: 0 4px 10px hsl(270 60% 45% / 0.22), 0 12px 28px hsl(270 70% 50% / 0.18);
}
.pd-rail-gav img { width: 100%; height: 100%; border-radius: 50%; display: block; }
.pd-rail-hi { display: block; font-size: 13.5px; color: var(--pd-ink-3); line-height: 1.3; }
.pd-rail-q { display: block; font-size: 19px; font-weight: 700; letter-spacing: -0.015em; margin-top: 2px; }
.pd-rail-shortcuts { display: flex; flex-direction: column; gap: 2px; padding-bottom: 14px; }
.pd-shortcut {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 10px; border-radius: 13px;
  border: 1px solid transparent;
  font-size: 13.5px; font-weight: 500; color: var(--pd-ink);
  cursor: pointer;
  transition: background 180ms ease, border-color 180ms ease, box-shadow 180ms ease;
}
.pd-shortcut:hover {
  background: var(--stella-glass);
  border-color: var(--stella-glass-border);
  box-shadow: 0 1px 0 var(--glass-highlight) inset, 0 6px 18px hsl(var(--stella-shade) / 0.12);
}
.pd-shortcut-ico {
  width: 27px; height: 27px; border-radius: 11px; flex-shrink: 0;
  display: grid; place-items: center;
  color: var(--brand); border: 1px solid var(--brand-border);
  transition: background 180ms ease, box-shadow 180ms ease;
}
.pd-shortcut:hover .pd-shortcut-ico { background: var(--glass-strong); box-shadow: 0 2px 6px hsl(var(--stella-shade) / 0.18); }
.pd-shortcut-arrow { margin-left: auto; color: var(--brand); opacity: 0; transform: translateX(-4px); transition: opacity 180ms ease, transform 180ms ease; }
.pd-shortcut:hover .pd-shortcut-arrow { opacity: 1; transform: translateX(0); }
/* Anchors the scroll cue, which floats just above the composer. */
.pd-rail-composer {
  position: relative;
  border: 1px solid var(--glass-surface-border);
  border-radius: 18px;
  background: var(--glass-surface);
  -webkit-backdrop-filter: var(--glass-blur-mid);
  backdrop-filter: var(--glass-blur-mid);
  box-shadow:
    0 1px 0 var(--glass-highlight-mid) inset,
    0 1px 2px hsl(var(--pd-shade) / 0.04),
    0 8px 24px hsl(var(--pd-shade) / 0.10);
  padding: 13px 13px 10px;
  display: flex; flex-direction: column; gap: 16px;
  transition: border-color 150ms ease, box-shadow 150ms ease;
}
.pd-rail-composer:hover { border-color: var(--stella-border-hover); }
/* "There is more of this reply below." Injected by JS into every rail's
   composer so all five Stella surfaces share one implementation, and shown only
   while the thread actually has content past the fold. Sits above the composer
   rather than inside the thread so it never scrolls away from the reader. */
.pd-scroll-cue {
  position: absolute; left: 50%; bottom: calc(100% + 10px);
  width: 30px; height: 30px; padding: 0;
  border-radius: 50%;
  display: grid; place-items: center;
  color: var(--pd-ink-2);
  background: var(--pd-surface);
  border: 1px solid var(--pd-line);
  box-shadow: 0 2px 8px hsl(var(--pd-shade) / 0.16), 0 0 0 3px var(--pd-paper-2);
  cursor: pointer;
  opacity: 0; pointer-events: none;
  transform: translate(-50%, 5px);
  transition: opacity 180ms var(--ease), transform 180ms var(--ease),
              border-color 140ms ease, color 140ms ease;
  z-index: 4;
}
.pd-scroll-cue.is-on { opacity: 1; pointer-events: auto; transform: translate(-50%, 0); }
.pd-scroll-cue:hover { border-color: var(--pd-line-stronger); color: var(--pd-ink); }
.pd-scroll-cue:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.pd-rail-placeholder { font-size: 13.5px; color: var(--pd-ink-4); }
.pd-rail-tools { display: flex; align-items: center; gap: 6px; }
.pd-rail-tool {
  width: 28px; height: 28px; border-radius: 50%;
  border: 1px solid var(--pd-line); background: var(--pd-surface);
  display: grid; place-items: center;
  color: var(--pd-ink-2); cursor: pointer;
  transition: border-color 120ms ease, background 120ms ease;
}
.pd-rail-tool:hover { border-color: var(--pd-line-stronger); background: var(--pd-paper-3); }
.pd-rail-at { font-size: 13.5px; font-weight: 500; line-height: 1; padding-bottom: 1px; }
.pd-rail-send {
  margin-left: auto;
  width: 28px; height: 28px; border-radius: 50%;
  background: #f1f1f4; color: #8a8a93;
  display: grid; place-items: center;
}

/* Stella chat thread — scripted conversation triggered by "Ask Stella" */
.pd-rail-thread {
  display: none;
  flex: 1; min-height: 0;
  flex-direction: column;
  gap: 10px;
  overflow-y: auto;
  padding: 4px 2px 14px;
}
/* Bottom-anchor the conversation without justify-content: flex-end, which
   would make overflowing messages at the top unreachable by scroll. */
.pd-rail-thread > .pd-step:first-child { margin-top: auto; }
.pd-chat-active .pd-rail-thread.is-on { display: flex; }
.pd-chat-active .pd-rail-greeting,
.pd-chat-active .pd-rail-shortcuts { display: none; }
.pd-step { display: none; opacity: 0; transform: translateY(8px); transition: opacity 350ms ease, transform 350ms cubic-bezier(.22, .61, .36, 1); }
.pd-step.is-vis { display: block; }
.pd-typing.is-vis { display: inline-flex; }
.pd-step.is-in { opacity: 1; transform: none; }
.pd-msg { border-radius: 14px; padding: 10px 12px; font-size: 12.5px; line-height: 1.5; color: var(--pd-ink-2); }
.pd-msg.user {
  align-self: flex-end; max-width: 86%;
  background: var(--glass-strong);
  border: 1px solid hsl(0 0% 8% / 0.07);
  border-bottom-right-radius: 5px;
  box-shadow: 0 1px 2px hsl(var(--pd-shade) / 0.04);
  color: var(--pd-ink);
}
.pd-msg.stella {
  align-self: stretch;
  background: none;
  border: 0;
  box-shadow: none;
  border-radius: 0;
  padding: 2px 2px;
}


/* Inline idea cards — product badge + kill score, id + state, title, note, chips */
.pd-idea-card {
  margin-top: 8px;
  padding: 11px 12px;
  background: var(--pd-surface);
  border: 1px solid var(--pd-line);
  border-radius: 12px;
  box-shadow: 0 1px 2px hsl(var(--pd-shade) / 0.04);
  cursor: pointer;
  transition: border-color 140ms ease, box-shadow 140ms ease, transform 140ms ease;
}
.pd-idea-card:hover {
  border-color: hsl(0 0% 8% / 0.2);
  transform: translateY(-1px);
  box-shadow: 0 8px 20px -10px hsl(var(--pd-shade) / 0.2), 0 2px 4px hsl(var(--pd-shade) / 0.05);
}
.pd-idea-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.pd-prod-badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px 3px 4px;
  background: var(--pd-paper-3);
  border: 1px solid var(--pd-line);
  border-radius: 999px;
  font-size: 11px; font-weight: 500; color: var(--pd-ink-2);
  line-height: 1.4;
}
.pd-prod-badge img { width: 16px; height: 16px; border-radius: 50%; display: block; }
.pd-prod-badge.sm { padding: 2px 8px 2px 3px; font-size: 10.5px; gap: 5px; }
.pd-prod-badge.sm img { width: 14px; height: 14px; }
.pd-idea-sub { display: flex; align-items: center; gap: 5px; margin-top: 7px; font-size: 11px; }
.pd-idea-code { font-weight: 500; color: var(--pd-ink-4); letter-spacing: 0.02em; }
.pd-sub-sep { color: var(--pd-ink-4); }
.pd-state { font-weight: 500; color: var(--pd-ink-4); }
.pd-idea-title { font-size: 12.5px; font-weight: 700; color: var(--pd-ink); line-height: 1.35; margin-top: 4px; }
.pd-idea-note { font-size: 11.5px; color: var(--pd-ink-3); line-height: 1.5; margin-top: 4px; }
.pd-idea-chips { display: flex; gap: 6px; margin-top: 9px; }
.pd-idea-chips .pd-chip { justify-self: auto; padding: 0 10px; height: 24px; font-size: 10.5px; }
.pd-person-main { flex: 1; min-width: 0; }
.pd-person-top { display: flex; align-items: center; gap: 7px; margin-bottom: 2px; }
.pd-id-link {
  color: var(--stella-link); font-weight: 600;
  border-bottom: 1px solid hsl(270 60% 82%);
  cursor: pointer;
  transition: color 120ms ease, border-color 120ms ease;
}
.pd-id-link:hover { color: hsl(270 60% 32%); border-bottom-color: hsl(270 55% 60%); }
.pd-msg.stella p { margin: 0; }
/* Beats `.pd-msg.stella p { margin: 0 }` above, which is more specific. */
.pd-msg.stella .pd-msg-p + .pd-msg-p { margin-top: 8px; }
.pd-msg.stella strong { color: var(--pd-ink); font-weight: 700; }
.pd-msg-label {
  margin-top: 12px; margin-bottom: 2px;
  font-size: 9.5px; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--stella-ink);
}
.pd-killpill {
  flex-shrink: 0; margin-top: 1px;
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 30px; height: 19px; padding: 0 7px; border-radius: 999px;
  font-size: 11px; font-weight: 700;
  border: 1px solid transparent;
}
.pd-killpill.green { background: var(--pd-green-bg); color: var(--pd-green-ink); border-color: var(--pd-green-bd); }
.pd-killpill.amber { background: var(--pd-amber-bg); color: var(--pd-amber-ink); border-color: var(--pd-amber-bd); }
.pd-killpill.red { background: var(--pd-red-bg); color: var(--pd-red); border-color: var(--pd-red-bd); }
.pd-person { display: flex; align-items: flex-start; gap: 8px; margin-top: 8px; font-size: 12px; line-height: 1.45; }
.pd-person-av {
  flex-shrink: 0; margin-top: 1px;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--pd-avatar); color: var(--pd-surface);
  display: grid; place-items: center;
  font-size: 8.5px; font-weight: 700; letter-spacing: 0.02em;
}
.pd-typing {
  align-self: flex-start;
  display: inline-flex; gap: 4px; align-items: center;
  padding: 8px 4px;
}
.pd-typing.is-done { display: none; }
.pd-typing span {
  width: 5px; height: 5px; border-radius: 50%;
  background: hsl(270 55% 62%);
  animation: pd-typing-blink 1.1s ease-in-out infinite;
}
.pd-typing span:nth-child(2) { animation-delay: 0.18s; }
.pd-typing span:nth-child(3) { animation-delay: 0.36s; }
@keyframes pd-typing-blink {
  0%, 60%, 100% { opacity: 0.35; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-2px); }
}

/* Decisions Needed — deliberately clipped by the frame bottom, implying scroll */
.pd-card.clipped { border-bottom: 0; border-radius: 16px 16px 0 0; padding-bottom: 40px; }

@media (prefers-reduced-motion: reduce) {
  .pd-bmc-note { animation: none; }
  .pd .pd-seg, .pd .pd-seg > span { transition: none; }
  .pd:not(.pd-live) .pd-seg { width: auto; }
  .pd:not(.pd-live) .pd-seg > span { opacity: 1; }
  .pd .pd-anim { opacity: 1; transform: none; transition: none; }
  .pd, .pd-rail, .pd-collapse svg { transition: none; }
  .pd-step { transition: none; }
  .pd-typing span { animation: none; }
}

/* =========================================================
   Roadmap board — What-Praxis-Is Portfolio screen
   Mirrors the prototype's PortfolioRoadmapPage: a product
   filter over three lane columns (Now / Next / Later) of
   funded-idea cards. All colors ride on the pd token set;
   the one blue (Jira "In Progress") matches the prototype.
   ========================================================= */
.pd-rm { display: flex; flex-direction: column; }
.pd-rm .pd-h3 { margin-bottom: 12px; }
/* The board's Stella strip sits above the filter, so its stock top margin
   flips to a bottom one. */
.pd-rm .pd-stella { margin: 0 0 14px; }

.pd-rm-filter { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.pd-rm-seg {
  display: inline-flex;
  border: 1px solid var(--pd-line);
  border-radius: var(--r-md);
  background: var(--pd-surface);
  overflow: hidden;
}
.pd-rm-opt {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px;
  font-size: 12.5px; font-weight: 500; color: var(--pd-ink-3);
  border-left: 1px solid var(--pd-line);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.pd-rm-opt:first-child { border-left: none; }
.pd-rm-opt:hover { color: var(--pd-ink); }
.pd-rm-opt.active { background: var(--pd-paper-3); color: var(--pd-ink); font-weight: 600; }
/* Product marks are the hero's Funded Ideas avatars (.pd-row-av), full tile. */
.pd-rm-opt { padding-block: 5px; }

.pd-rm-lanes { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.pd-rm-lane {
  /* Faint grey ground — the white cards read as sitting on the lane. */
  background: var(--pd-paper-3);
  border: 1px solid var(--pd-line-soft);
  /* Column-level surface: --r-xl, sitting inside .pd-main's 24px. */
  border-radius: var(--r-xl);
  padding: 12px;
  display: flex; flex-direction: column;
}
.pd-rm-lane-h { display: flex; align-items: baseline; margin-bottom: 2px; }
.pd-rm-lane-h > span:first-child { font-size: 13px; font-weight: 600; color: var(--pd-ink); }
.pd-rm-count {
  margin-left: auto;
  font-size: 11px; color: var(--pd-ink-4);
}
.pd-rm-lane-sub {
  font-size: 10px; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--pd-ink-4);
  margin-bottom: 10px;
}
.pd-rm-stack { display: flex; flex-direction: column; gap: 8px; flex: 1; }
.pd-rm-empty {
  display: none;
  font-size: 12px; color: var(--pd-ink-4); text-align: center;
  padding: 24px 8px;
  border: 1px dashed var(--pd-line);
  border-radius: var(--r-lg);
}
.pd-rm-lane-empty .pd-rm-empty { display: block; }
/* Doubled class so it outranks .pd-rm-card's own display, declared below. */
.pd-rm-card.pd-rm-out { display: none; }

.pd-rm-card {
  display: flex; flex-direction: column; gap: 8px;
  background: var(--pd-surface);
  border: 1px solid var(--pd-line);
  /* Card-level surface: --r-lg. (Was 12px to match the rail's .pd-idea-card,
     but that radius belongs to the compact chat rail — at the hero-scale
     render it reads too sharp.) Resting shadow still mirrors .pd-idea-card. */
  border-radius: var(--r-lg);
  box-shadow: 0 1px 2px hsl(var(--pd-shade) / 0.04);
  padding: 12px;
  cursor: pointer;
  transition: border-color 150ms ease, box-shadow 150ms ease;
}
/* Hover matches the hero's Funded Ideas rows (.pd-row:hover) exactly. */
.pd-rm-card:hover {
  border-color: var(--pd-line-strong);
  box-shadow: 0 8px 24px -12px hsl(var(--pd-shade-2) / 0.18), 0 2px 4px hsl(var(--pd-shade-2) / 0.04);
}
.pd-rm-toprow { display: flex; align-items: center; gap: 6px; }
/* Plain brand-font ID, no badge — mirrors .pd-row-code in the hero. */
.pd-rm-ide {
  font-size: 11.5px; color: var(--pd-ink-4);
  letter-spacing: 0.02em;
  white-space: nowrap;
}
/* Product badge — clickable route to the product's scope. Each tint is a
   lightened version of its logo's sampled color (no tokens exist for these;
   the logos are the source of truth). Text inks are darkened same-hue steps
   holding ≥8.5:1 contrast on both resting and hover tints — the canvas scale
   renders this text near 8px, so AA's 4.5:1 is not enough. Hover deepens the tint and reveals an
   in-app arrow, mirroring the Jira tag's external-link reveal. */
.pd-rm-prod {
  display: inline-flex; align-items: center; gap: 5px;
  /* Same 24px height as the Jira tag (.pd-rm-jtag) sharing the row. */
  height: 24px; padding: 0 8px 0 4px; border-radius: 999px;
  font-size: 10.5px; font-weight: 500; color: var(--pd-ink-2);
  background: var(--pd-paper-3);
  border: 1px solid var(--pd-line);
  white-space: nowrap;
  cursor: pointer;
  transition: background 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
}
.pd-rm-prod:hover { box-shadow: 0 2px 8px hsl(var(--pd-shade-2) / 0.08); }
.pd-rm-prod img { width: 14px; height: 14px; border-radius: 999px; display: block; }
.pd-rm-prod.fitflow { background: var(--prod-fitflow-bg); border-color: var(--prod-fitflow-bd); color: var(--prod-fitflow-ink); }
.pd-rm-prod.fitflow:hover { background: var(--prod-fitflow-bg-strong); border-color: var(--prod-fitflow-bd-strong); }
.pd-rm-prod.coach { background: var(--prod-coach-bg); border-color: var(--prod-coach-bd); color: var(--prod-coach-ink); }
.pd-rm-prod.coach:hover { background: var(--prod-coach-bg-strong); border-color: var(--prod-coach-bd-strong); }
.pd-rm-prod.wear { background: var(--prod-wear-bg); border-color: var(--prod-wear-bd); color: var(--prod-wear-ink); }
.pd-rm-prod.wear:hover { background: var(--prod-wear-bg-strong); border-color: var(--prod-wear-bd-strong); }
.pd-rm-prod.studio { background: var(--prod-studio-bg); border-color: var(--prod-studio-bd); color: var(--prod-studio-ink); }
.pd-rm-prod.studio:hover { background: var(--prod-studio-bg-strong); border-color: var(--prod-studio-bd-strong); }
.pd-rm-go {
  width: 0; opacity: 0; margin-left: -5px;
  transition: width 140ms ease, opacity 140ms ease, margin-left 140ms ease;
}
.pd-rm-prod:hover .pd-rm-go { width: 10px; opacity: 1; margin-left: 0; }
.pd-rm-title { font-size: 13.5px; font-weight: 500; color: var(--pd-ink); line-height: 1.35; text-wrap: pretty; }
/* The decision rationale that funded the idea — the evidence trail (or its
   absence) in one sentence, right under the bet it justifies. */
.pd-rm-why { font-size: 11.5px; color: var(--pd-ink-3); line-height: 1.5; text-wrap: pretty; }
/* CoD / CD3 ride the hero rail's .pd-idea-chips badges; the card's own flex
   gap already spaces the row, so the rail's top margin is dropped. */
.pd-rm-card .pd-idea-chips { margin-top: 0; }
/* Bottom row: the hero's Jira chip (colored by delivery status) left, owner
   right. On hover the chip grows an external-link glyph — the tag opens the
   epic in a new tab. */
.pd-rm-links { display: flex; align-items: center; margin-top: 2px; }
.pd-rm-links .pd-rm-jtag { margin-left: auto; }
/* Owner sits top-right, on the ID's baseline row. */
.pd-rm-toprow .pd-rm-av { margin-left: auto; }
.pd-rm-jtag {
  justify-self: auto;
  height: 24px; padding: 0 9px; gap: 5px;
  font-size: 10.5px;
  transition: border-color 140ms ease, box-shadow 140ms ease;
}
.pd-rm-jtag:hover { border-color: var(--pd-line-stronger); box-shadow: 0 2px 8px hsl(var(--pd-shade-2) / 0.08); }
.pd-rm-jtag.prog { color: var(--pd-blue); background: var(--pd-blue-bg); border-color: var(--pd-blue-bd); }
.pd-rm-jtag.prog:hover { border-color: var(--pd-blue-bd-strong); }
.pd-rm-jtag.todo { color: var(--pd-ink-2); background: var(--pd-paper-3); border-color: var(--pd-line); }
.pd-rm-jtag.backlog { color: var(--pd-ink-4); background: var(--pd-paper-2); border-color: var(--pd-line-soft); }
.pd-rm-ext {
  width: 0; opacity: 0; margin-left: -5px;
  transition: width 140ms ease, opacity 140ms ease, margin-left 140ms ease;
}
.pd-rm-jtag:hover .pd-rm-ext { width: 10px; opacity: 1; margin-left: 0; }
.pd-rm-av {
  width: 20px; height: 20px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 8.5px; font-weight: 700; letter-spacing: 0.02em;
  color: var(--pd-surface);
  background: var(--pd-avatar);
  box-shadow: 0 1px 2px hsl(var(--pd-shade) / 0.18);
}

/* Roadmap rail — Stella's lane-by-lane value rows. Expected value = each
   card's CoD weighted by its funding evidence; weak-evidence bets show the
   claimed figure struck through beside the discounted one. */
.pd-rmv-list { margin: 8px 0 10px; }
.pd-rmv {
  padding: 6px 0;
  border-bottom: 1px solid var(--pd-line-soft);
  font-size: 12px;
}
.pd-rmv:last-child { border-bottom: 0; }
.pd-rmv-top { display: flex; align-items: baseline; gap: 8px; }
/* The FBA note: the problem solved and the annual unlock behind the CoD. */
.pd-rmv-note { margin-top: 2px; padding-left: 22px; font-size: 11.5px; line-height: 1.45; color: var(--pd-ink-3); text-wrap: pretty; }
.pd-rmv-note strong { color: var(--pd-ink); font-weight: 700; }
.pd-rmv-wk { font-weight: 400; color: var(--pd-ink-4); }
.pd-rmv-code { flex: none; font-size: 11px; color: var(--pd-ink-4); letter-spacing: 0.02em; }
/* Basis text stays neutral — the classes keep the semantics, the copy and the
   struck-through discounts carry the judgement. */
.pd-rmv-basis { flex: 1; min-width: 0; color: var(--pd-ink-3); }
.pd-rmv-logo { flex: none; align-self: center; width: 14px; height: 14px; border-radius: 4px; display: block; }
.pd-rmv-val { flex: none; font-weight: 700; color: var(--pd-ink); white-space: nowrap; }
/* Next-step suggestions inside Stella's messages: compact pill chips, visually
   distinct from the greeting's full-row contextual shortcuts. Display
   affordances only: nothing is wired to them. */
.pd-msg-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.pd-msg-action {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px;
  border-radius: 999px;
  font-size: 12px; font-weight: 500; color: var(--stella-ink);
  background: var(--pd-surface);
  border: 1px solid var(--stella-banner-border);
  cursor: pointer;
  transition: background 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
}
.pd-msg-action svg { flex: none; color: var(--brand); }
.pd-msg-action:hover {
  background: var(--stella-glass);
  border-color: var(--stella-border-hover);
  box-shadow: 0 2px 8px hsl(var(--stella-shade) / 0.12);
}

/* Stella's glass surface. Every note she writes into a screen sits on it:
   the Idea screen's recommendation hero, its sizing note and its verdict
   pushback, and the canvas screen's cell flags. */
.pd-idp-rechero, .pd-idp-recnote, .pd-idp-counter {
  background: var(--stella-glass);
  border: 1px solid var(--stella-glass-border);
}

/* =========================================================
   Live screen — Idea detail (What-Praxis-Is, Product tab)
   IDE-018 in the Coach product. A faithful port of the
   Praxis 3.0 prototype's IdeaDetailPage components (values
   lifted from the rendered prototype): cards, state pills,
   code chips, kill banner, page tabs, FBA rows, sizing rows,
   and the Decision composer. Tabs, the verdict tiles, and
   the cross-tab buttons are wired in index.html's script.
   ========================================================= */
/* Audited 2026-08-13: this screen declares NO tokens of its own. Every value
   rides the shared pd-* / stella-* families (the prototype's --funded IS
   --pd-green, its --bad IS --pd-red, its lavender banner IS --stella-banner,
   its --ink-5 IS --pd-ink-5). */

/* The site's editorial `p { max-width: 62ch }` must not clamp app copy */
.pd-idp p { max-width: none; }

/* --- Shared primitives (ported 1:1) ----------------------------------- */
.pd-idp-sub { font-size: 12px; color: var(--pd-ink-4); }
/* Variant of the shared .pd-card: the prototype's tighter radius and roomier
   padding. Markup carries both classes, so the surface itself stays shared.
   (The prototype's inset white highlight is a no-op on a var(--pd-surface) card.) */
.pd-idp-card { border-radius: 14px; padding: 20px; }
/* Panels and the canvas meta row space their cards with grid/flex gap, so the
   shared adjacent-card margin would double it (and stop a grid item
   stretching to its row height). */
.pd-idp-panel .pd-card + .pd-card,
.pd-bmc-meta .pd-card + .pd-card { margin-top: 0; }
.pd-idp-card.p0 { padding: 0; overflow: hidden; }
.pd-idp-click { transition: border-color .14s ease, box-shadow .14s ease, transform .14s ease; cursor: pointer; }
.pd-idp-click:hover { border-color: var(--pd-line-strong); box-shadow: 0 8px 24px -12px hsl(var(--pd-shade-2) / 0.18), 0 2px 4px hsl(var(--pd-shade-2) / 0.04); transform: translateY(-1px); }
.pd-idp-stella-av {
  width: 16px; height: 16px; border-radius: 50%; flex-shrink: 0; display: inline-block;
  box-shadow: 0 2px 6px hsl(var(--stella-shade) / 0.35);
}
.pd-idp-stella-av img { width: 100%; height: 100%; border-radius: 50%; display: block; }
/* Optical alignment of Stella's avatar against the first line of her text */
.pd-idp-counter .pd-idp-stella-av { margin-top: 2px; }
.pd-idp-nudge .pd-idp-stella-av, .pd-idp-recnote .pd-idp-stella-av { margin-top: 1px; }
/* Reference-code chip (HYP-058, EXP-207 …) — the prototype's .mono.eyebrow */
.pd-idp-code {
  display: inline-flex; align-items: center; height: 20px; padding: 0 9px;
  border-radius: 999px; background: var(--pd-paper-3); border: 1px solid var(--pd-line);
  color: var(--pd-ink-3); font-size: 10.5px; line-height: 1; white-space: nowrap;
  font-variant-numeric: tabular-nums;
  text-transform: uppercase; letter-spacing: 0.06em; font-weight: 700;
}
/* Square code chip used inside candidate bars */
.pd-idp-codechip {
  font-size: 11.5px; font-weight: 600; color: var(--pd-ink-2); font-variant-numeric: tabular-nums;
  background: var(--pd-surface); border: 1px solid var(--pd-line); padding: 2px 7px; border-radius: 6px; flex: 0 0 auto;
  white-space: nowrap;
}
/* State pill — the prototype's .state */
.pd-idp-pill {
  display: inline-flex; align-items: center; height: 20px; padding: 0 9px;
  border-radius: 999px; font-size: 10.5px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; border: 1px solid transparent; white-space: nowrap;
}
.pd-idp-pill.deciding { background: var(--pd-amber-bg); color: var(--pd-amber-ink); border-color: var(--pd-amber-bd); }
.pd-idp-pill.ok { background: var(--pd-green-bg); color: var(--pd-green-ink); border-color: var(--pd-green-bd); }
.pd-idp-pill.bad { background: var(--pd-red-bg); color: var(--pd-red); border-color: var(--pd-red-bd); }
.pd-idp-pill.neutral { background: var(--pd-paper-3); color: var(--pd-ink-2); border-color: var(--pd-line); }
.pd-idp-dd {
  display: inline-flex; align-items: center; gap: 5px; padding: 3px 6px 3px 3px;
  border-radius: 8px; cursor: pointer; transition: background .12s ease;
}
.pd-idp-dd:hover { background: var(--pd-paper-3); }
.pd-idp-dd > svg { color: var(--pd-ink-4); margin-top: 1px; flex-shrink: 0; }
/* Count chip (footer of hyp cards, row cells) */
.pd-idp-count {
  display: inline-flex; align-items: center; gap: 4px; height: 22px; box-sizing: border-box;
  font-size: 11.5px; font-weight: 600; border-radius: 999px; padding: 0 8px 0 6px;
  border: 1px solid var(--pd-line); background: var(--pd-paper-3); color: var(--pd-ink-3);
  font-variant-numeric: tabular-nums;
}
.pd-idp-count svg { color: var(--pd-ink-4); }
/* 24px round icon button (kebabs on cards/rows) */
.pd-idp-iconbtn {
  width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 999px; border: 1px solid transparent; background: transparent; color: var(--pd-ink-3);
  cursor: pointer; transition: background .12s ease, border-color .12s ease;
}
.pd-idp-iconbtn:hover { background: var(--pd-paper-3); color: var(--pd-ink); border-color: var(--pd-line); }
/* 28px icon tile (goal / customer / artifact chips) */
.pd-idp-tile { width: 28px; height: 28px; border-radius: 8px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.pd-idp-tile.amber { background: var(--pd-amber-bg); color: var(--pd-amber-ink); }
.pd-idp-tile.green { background: var(--pd-green-bg); color: var(--pd-green-ink); }
.pd-idp-tile.blue { background: var(--pd-blue-bg); color: var(--pd-blue); }

/* --- Document header, shared by the Idea and Artifact screens ---------- */
.pd-crumb { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; font-size: 12px; }
.pd-crumb-link { color: var(--pd-ink-3); cursor: pointer; }
.pd-crumb-link:hover { color: var(--pd-ink); }
.pd-crumb-sep { color: var(--pd-ink-5); user-select: none; }
.pd-crumb-cur { color: var(--pd-ink); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 480px; }
.pd-crumb-cur span { margin-right: 2px; }
.pd-idp-staterow { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; }
.pd-idp-staterow > .pd-idp-pill { cursor: help; }
.pd-idp-owner {
  display: inline-flex; align-items: center; gap: 8px; padding: 4px 10px 4px 4px;
  border-radius: 999px; border: 1px solid var(--pd-line); background: var(--pd-surface); color: var(--pd-ink);
  font-size: 12.5px; line-height: 1.2; cursor: pointer;
}
.pd-idp-owner:hover { border-color: var(--pd-line-stronger); }
.pd-idp-owner .name { font-weight: 500; }
.pd-idp-owner .caret { color: var(--pd-ink-4); font-size: 10px; margin-left: -2px; }
.pd-kebab {
  background: transparent; border: 1px solid var(--pd-line); border-radius: 8px;
  width: 28px; height: 28px; cursor: pointer; display: flex; align-items: center; justify-content: center;
  color: var(--pd-ink-3); transition: background .12s, border-color .12s;
}
.pd-kebab:hover { background: var(--pd-paper-3); border-color: var(--pd-ink-3); }
.pd-doc-title { margin: 0 0 6px; font-size: 22px; font-weight: 700; letter-spacing: -0.01em; }
.pd-byline { font-size: 12.5px; color: var(--pd-ink-3); margin-bottom: 20px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.pd-byline strong { color: var(--pd-ink-2); font-weight: 600; }
.pd-byline .dot { font-size: 0; width: 3px; height: 3px; border-radius: 50%; background: var(--pd-ink-5); flex-shrink: 0; }

/* --- Kill banner --------------------------------------------------------- */
.pd-idp-kill {
  margin-bottom: 20px; border-color: var(--stella-banner-border);
  background: var(--stella-banner);
  box-shadow: 0 1px 0 var(--glass-highlight-soft) inset;
}
.pd-idp-kill-inner { display: flex; align-items: center; gap: 18px; }
.pd-idp-kill-score { display: flex; flex-direction: column; align-items: center; gap: 6px; flex-shrink: 0; }
.pd-idp-kill-score .pd-eyebrow { color: var(--pd-ink-4); }
/* Size variant of the hero's .pd-killpill (colors come from the shared class) */
.pd-idp .pd-killpill.lg {
  margin-top: 0; min-width: 68px; height: 32px; padding: 0 14px;
  font-size: 16px; font-variant-numeric: tabular-nums;
}
.pd-idp-kill-div { width: 1px; align-self: stretch; background: var(--stella-banner-border); }
.pd-idp-kill-note { flex: 1; min-width: 0; font-size: 13px; color: var(--pd-ink-2); line-height: 1.55; text-wrap: pretty; }
.pd-idp-kill-note strong { color: var(--pd-ink); font-weight: 700; }

/* --- Tabs ----------------------------------------------------------------- */
.pd-idp-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--pd-line); margin-bottom: 20px; }
.pd-idp-tab {
  padding: 10px 14px; font-size: 13px; font-weight: 500; color: var(--pd-ink-3);
  cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px;
  transition: all 150ms; white-space: nowrap;
}
.pd-idp-tab:hover { color: var(--pd-ink); }
.pd-idp-tab.active { color: var(--pd-ink); border-bottom-color: var(--pd-ink); font-weight: 600; }
.pd-idp-panel { display: none; flex-direction: column; gap: 16px; }
.pd-idp-panel.active { display: flex; }
.pd-idp-panel.gap12 { gap: 12px; }
/* Decision: header and tiles sit tighter so a Kill/Park pick keeps Stella's
   reaction inside the canvas fold rather than below it. */
.pd-idp-dec-head { margin-bottom: 12px; }
.pd-idp-verdicts { margin-bottom: 12px; }
.pd-idp-actions { display: flex; gap: 8px; align-items: center; }
.pd-idp-flex1 { flex: 1; }

/* --- Brief ------------------------------------------------------------------ */
.pd-idp-cardhead { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 12px; }
.pd-idp-cardhead .main { flex: 1; min-width: 0; }
/* Label that sits above the block it names (replaces repeated inline styles) */
.pd-idp-lbl { display: block; margin-bottom: 4px; }
.pd-eyebrow-sm.pd-idp-lbl { margin-bottom: 6px; }
.pd-idp-cardhead .pd-eyebrow { display: block; margin-bottom: 4px; }
.pd-idp-desc { color: var(--pd-ink-2); font-size: 13.5px; line-height: 1.6; }
.pd-idp-desc p { margin: 0; }
.pd-idp-brief-block { margin-bottom: 28px; }
.pd-idp-goalwrap { border: 1px solid var(--pd-line); border-radius: 10px; background: var(--pd-surface); padding: 0 12px; }
.pd-idp-goalrow { display: flex; align-items: center; gap: 12px; padding: 10px 12px; margin: 0 -12px; border-radius: 10px; transition: background .12s; }
.pd-idp-goalrow:hover { background: var(--pd-paper-2); }
.pd-idp-goalrow .t { font-size: 13px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pd-idp-goalrow .s { font-size: 11.5px; color: var(--pd-ink-4); }
.pd-idp-goalrow .main { flex: 1; min-width: 0; }
.pd-idp-chiprow { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.pd-idp-linkchip {
  display: inline-flex; align-items: center; gap: 10px; padding: 7px 8px 7px 10px;
  border-radius: 10px; border: 1px solid var(--pd-line); background: var(--pd-surface); max-width: 100%;
  transition: background .12s; cursor: pointer;
}
.pd-idp-linkchip:hover { background: var(--pd-paper-2); }
.pd-idp-linkchip .name { font-size: 13px; font-weight: 500; color: var(--pd-ink); max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pd-idp-addbtn {
  display: inline-flex; align-items: center; gap: 5px; height: 44px; padding: 0 12px;
  border-radius: 10px; border: 1px dashed var(--pd-line); background: transparent;
  color: var(--pd-ink-3); font-size: 12.5px; cursor: pointer;
}
.pd-idp-addbtn:hover { border-color: var(--pd-line-stronger); color: var(--pd-ink-2); }
.pd-idp-filechip {
  display: inline-flex; align-items: center; gap: 8px; height: 44px; padding: 0 14px;
  border-radius: 10px; border: 1px dashed var(--pd-line); background: var(--pd-paper-3);
  color: var(--pd-ink-4); font-size: 12.5px;
}
.pd-idp-filechip .pd-idp-tile { background: var(--pd-surface); border: 1px solid var(--pd-line); color: var(--pd-ink-4); }
.pd-idp-sechead { display: flex; align-items: center; gap: 10px; padding: 2px 0 6px; }

/* Value Assessment */
.pd-idp-va-head { padding: 16px 18px 12px; display: flex; align-items: flex-start; gap: 12px; flex-wrap: wrap; }
.pd-idp-va-head .main { flex: 1 1 260px; min-width: 0; }
.pd-idp-va-head .pd-eyebrow { display: block; margin-bottom: 4px; }
.pd-idp-va-sub { font-size: 12.5px; color: var(--pd-ink-3); line-height: 1.5; }
.pd-idp-va-body { padding: 0 18px 16px; }
.pd-idp-cod { background: var(--pd-paper-3); border: 1px solid var(--pd-line-soft); border-radius: 12px; padding: 14px 16px; }
.pd-idp-cod-top { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.pd-idp-cod-line { display: flex; align-items: baseline; gap: 6px; }
.pd-idp-cod-num {
  font-size: 32px; font-weight: 700; color: var(--pd-ink);
  letter-spacing: -0.02em; line-height: 1; cursor: pointer; border-radius: 8px;
  padding: 2px 4px; margin: -2px -4px; transition: background .12s; font-variant-numeric: tabular-nums;
}
.pd-idp-cod-num:hover { background: var(--brand-tint); }
.pd-idp-cod-per { font-size: 13px; color: var(--pd-ink-3); }
.pd-idp-cod-annual { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--pd-line-soft); display: flex; align-items: baseline; gap: 6px; font-size: 12px; color: var(--pd-ink-4); }
.pd-idp-cod-annual .v { color: var(--pd-ink-2); font-weight: 500; font-variant-numeric: tabular-nums; }
.pd-idp-nudge {
  margin-top: 12px; background: var(--pd-green-bg-soft); border: 1px solid var(--pd-green-bd);
  border-radius: 10px; padding: 12px; display: flex; align-items: flex-start; gap: 10px;
}
.pd-idp-nudge .body { flex: 1; font-size: 12.5px; color: var(--pd-ink-2); line-height: 1.5; min-width: 0; }
.pd-idp-nudge .body a { color: var(--pd-green-ink); text-decoration: underline; text-decoration-style: dotted; cursor: pointer; }
.pd-idp-fba { border-top: 1px solid var(--pd-line-soft); }
.pd-idp-fba-row { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-bottom: 1px solid var(--pd-line-soft); cursor: pointer; transition: background .12s; }
.pd-idp-fba-row:last-child { border-bottom: 0; }
.pd-idp-fba-row:hover { background: var(--pd-paper-2); }
.pd-idp-fba-row .main { flex: 1; min-width: 0; }
.pd-idp-fba-row .t { font-size: 13px; font-weight: 500; }
.pd-idp-fba-row .s { font-size: 11.5px; color: var(--pd-ink-4); }
.pd-idp-fba-val { font-size: 13.5px; font-weight: 600; color: var(--pd-green-deep); white-space: nowrap; font-variant-numeric: tabular-nums; }
.pd-idp-fba-val .per { color: var(--pd-ink-4); font-weight: 400; }
.pd-idp-fba-row .pd-btn { padding-inline: 8px; }

/* --- Hypothesis cards ------------------------------------------------------ */
.pd-idp-hyp { display: flex; flex-direction: column; gap: 10px; position: relative; }
.pd-idp-hyp-top { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.pd-idp-hyp-top .when { margin-left: auto; font-size: 11.5px; color: var(--pd-ink-4); }
.pd-idp-hyp-title { font-size: 15px; font-weight: 600; color: var(--pd-ink); letter-spacing: -0.005em; line-height: 1.35; }
.pd-idp-hyp-body { font-size: 13px; line-height: 1.55; color: var(--pd-ink-3); }
.pd-idp-hyp-by { font-size: 12px; color: var(--pd-ink-4); margin-top: -2px; }
.pd-idp-hyp-foot { display: flex; align-items: center; gap: 12px; padding-top: 10px; border-top: 1px solid var(--pd-line-soft); flex-wrap: wrap; min-height: 22px; }

/* --- List rows (experiments / insights) ------------------------------------ */
.pd-idp-row { display: flex; align-items: center; gap: 12px; padding: 10px 14px; min-height: 52px; }
.pd-idp-row .lead { display: flex; align-items: center; gap: 12px; flex: 1 1 auto; min-width: 0; }
.pd-idp-rowcode {
  width: 56px; flex-shrink: 0; font-size: 12px; color: var(--pd-ink-4); white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.pd-idp-rowtitle { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 500; color: var(--pd-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pd-idp-cell { flex-shrink: 0; }
.pd-idp-cell.w116 { width: 116px; }
.pd-idp-cell.w100 { width: 116px; }
.pd-idp-cell.w150 { width: 150px; min-width: 0; display: flex; }
.pd-idp-cell.w56 { width: 56px; }
.pd-idp-cell.w46 { width: 46px; }
.pd-idp-when { width: 60px; flex-shrink: 0; text-align: right; color: var(--pd-ink-4); font-size: 12px; }
.pd-idp-instag {
  display: inline-block; max-width: 100%; font-size: 10.5px; font-weight: 700; padding: 2px 9px;
  border-radius: 999px; text-transform: uppercase; letter-spacing: 0.06em; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
  background: var(--pd-blue-bg); color: var(--pd-blue); border: 1px solid var(--pd-blue-bd);
}
.pd-idp-instag.src { background: var(--pd-paper-3); color: var(--pd-ink-2); border-color: var(--pd-line); font-weight: 600; }

/* --- Sizing ------------------------------------------------------------------ */
.pd-idp-codpanel {
  display: flex; align-items: center; gap: 16px; margin-top: 16px; padding: 14px 16px;
  border: 1px solid var(--stella-glass-border); border-radius: 12px;
  background: linear-gradient(var(--brand-tint), var(--pd-surface) 80%);
}
.pd-idp-codpanel .main { flex: 1; min-width: 0; }
.pd-idp-codpanel .pd-eyebrow { color: var(--stella-ink); margin-bottom: 4px; display: block; }
.pd-idp-codpanel .why { font-size: 12.5px; line-height: 1.5; color: var(--pd-ink-3); text-wrap: pretty; }
.pd-idp-codpanel .num { font-size: 24px; font-weight: 600; color: var(--pd-ink); line-height: 1; font-variant-numeric: tabular-nums; }
.pd-idp-codpanel .num .per { font-size: 13px; color: var(--pd-ink-4); font-weight: 400; font-family: inherit; }
.pd-idp-codpanel .right { text-align: right; flex-shrink: 0; }
.pd-idp-valink { font-size: 11px; color: var(--pd-ink-4); margin-top: 3px; }
.pd-idp-valink span { color: var(--stella-ink); font-weight: 500; cursor: pointer; }
.pd-idp-valink span:hover { color: var(--stella-link); }
.pd-idp-sols { display: flex; flex-direction: column; gap: 10px; }
.pd-idp-sol {
  display: flex; align-items: center; gap: 14px; padding: 12px 14px;
  border: 1px solid var(--pd-line); border-radius: 14px; background: var(--pd-surface);
  box-shadow: 0 1px 2px hsl(var(--pd-shade-2) / 0.03), 0 1px 0 var(--glass-highlight) inset;
}
.pd-idp-sol.sel { border-color: var(--pd-green); background: var(--pd-green-bg-soft); }
.pd-idp-sol .lead { flex: 1; min-width: 0; display: flex; align-items: center; gap: 12px; }
/* Solution titles link to their experiment record in the app */
.pd-idp-sol .t {
  font-size: 13.5px; font-weight: 600; color: var(--pd-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
  border-bottom: 1px solid transparent; cursor: pointer;
  transition: color .12s ease, border-color .12s ease;
}
.pd-idp-sol .t:hover { color: var(--stella-link); border-bottom-color: var(--stella-border-hover); }
.pd-idp-rank {
  flex-shrink: 0; width: 34px; text-align: center; font-size: 10px; font-weight: 700;
  letter-spacing: 0.3px; text-transform: uppercase; border-radius: 6px; padding: 1px 0;
  color: var(--pd-ink-3); background: var(--pd-paper-3); border: 1px solid var(--pd-line);
}
.pd-idp-rank.ok { color: var(--pd-green-ink); background: var(--pd-green-bg); border-color: var(--pd-green-bd); }
.pd-idp-stepper {
  display: inline-flex; align-items: center; height: 32px; border-radius: 8px; overflow: hidden;
  border: 1px solid var(--pd-line); background: var(--pd-surface); opacity: 0.55; flex-shrink: 0;
}
.pd-idp-stepper .pm { width: 28px; height: 100%; color: var(--pd-ink-3); font-size: 16px; line-height: 1; display: inline-flex; align-items: center; justify-content: center; }
.pd-idp-stepper .val { display: inline-flex; align-items: center; height: 100%; border-left: 1px solid var(--pd-line); border-right: 1px solid var(--pd-line); padding: 0 8px; font-size: 14px; font-variant-numeric: tabular-nums; }
.pd-idp-soldiv { width: 1px; height: 32px; background: var(--pd-line-soft); flex-shrink: 0; }
.pd-idp-cd3 { display: flex; align-items: baseline; justify-content: flex-end; gap: 8px; flex-shrink: 0; }
.pd-idp-cd3 .l { font-size: 10px; color: var(--pd-ink-4); }
.pd-idp-cd3 .v { font-variant-numeric: tabular-nums; font-size: 14.5px; font-weight: 600; color: var(--pd-ink-3); border: 1px solid var(--pd-line); border-radius: 6px; padding: 1px 6px; }
.pd-idp-cd3 .v.ok { color: var(--pd-green-deep); }
.pd-idp-recnote {
  display: flex; gap: 12px; align-items: flex-start; padding: 14px 16px; border-radius: 12px;
  box-shadow: 0 2px 8px hsl(var(--stella-shade) / 0.08);
}
.pd-idp-recnote .pd-eyebrow { color: var(--stella-ink); margin-bottom: 6px; display: block; }
.pd-idp-recnote .body { font-size: 13px; line-height: 1.55; color: var(--pd-ink-2); text-wrap: pretty; min-width: 0; flex: 1; }
.pd-idp-recnote .body strong { font-weight: 700; color: var(--pd-ink); }
.pd-idp-purlink { color: var(--stella-link); font-weight: 700; border-bottom: 1px solid var(--stella-border-hover); cursor: pointer; }
.pd-idp-sizefoot { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--pd-line-soft); }
.pd-idp-selbar {
  margin-top: 12px; border: 1px solid var(--pd-line); border-radius: 12px; padding: 12px 16px;
  background: var(--pd-paper-2); display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
}
.pd-idp-selbar .ok-label { color: var(--pd-green-ink); flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px; }
.pd-idp-selbar .div { width: 1px; height: 16px; background: var(--pd-line); flex: 0 0 auto; }
.pd-idp-selbar .lead { display: flex; align-items: center; gap: 10px; flex: 1 1 240px; min-width: 0; }
.pd-idp-selbar .t { font-size: 13px; color: var(--pd-ink); font-weight: 500; line-height: 1.4; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pd-idp-selbar .stats { display: flex; align-items: center; gap: 14px; flex: 0 0 auto; }
.pd-idp-selbar .m { font-size: 13px; font-weight: 600; color: var(--pd-ink); font-variant-numeric: tabular-nums; }
.pd-idp-selbar .sdiv { width: 1px; height: 14px; background: var(--pd-line); }

/* --- Decision ------------------------------------------------------------------ */
.pd-idp-rechero {
  box-shadow: 0 2px 8px hsl(var(--stella-shade) / 0.08);
  border-radius: 12px; padding: 16px 24px; margin: 0 0 12px;
  display: flex; align-items: center; gap: 24px; flex-wrap: wrap;
}
.pd-idp-scorebox {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  flex: 0 0 auto; padding: 16px 22px; border-radius: 12px; align-self: flex-start;
  background: var(--pd-green-bg); border: 1px solid var(--pd-green-bd);
}
.pd-idp-scorebox .num {
  font-size: 52px; font-weight: 700; line-height: 1;
  letter-spacing: -0.01em; color: var(--pd-green-ink); font-variant-numeric: tabular-nums;
}
.pd-idp-scorebox .pd-eyebrow-sm { color: var(--pd-green-ink); opacity: 0.75; }
.pd-idp-rec-main { flex: 1 1 300px; min-width: 0; }
.pd-idp-rec-title { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; font-size: 15px; font-weight: 700; color: var(--pd-ink); letter-spacing: -0.01em; }
.pd-idp-rec-title .fund { color: var(--pd-green-ink); }
.pd-idp-rec-body { font-size: 13px; color: var(--pd-ink-2); line-height: 1.6; margin: 0 0 12px; text-wrap: pretty; }
.pd-idp-rec-body em { font-style: italic; }
.pd-idp-candbar {
  background: var(--glass-surface); border: 1px solid var(--stella-glass-border); border-radius: 10px;
  padding: 10px 14px; margin-bottom: 12px; display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
}
.pd-idp-candbar .lead { display: flex; align-items: center; gap: 10px; flex: 1 1 220px; min-width: 0; }
.pd-idp-candbar .t {
  font-size: 12.5px; color: var(--pd-ink); font-weight: 500; line-height: 1.4; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  border-bottom: 1px dotted var(--pd-ink-4); cursor: pointer;
}
.pd-idp-candbar .t:hover { border-bottom-style: solid; }
.pd-idp-candbar .stats { display: flex; align-items: center; gap: 12px; flex: 0 0 auto; }
.pd-idp-candbar .m { font-size: 12.5px; font-weight: 600; color: var(--pd-ink); font-variant-numeric: tabular-nums; }
.pd-idp-candbar .div { width: 1px; height: 13px; background: var(--stella-glass-border); }
/* The candbar is now the last child of rec-main (the Stella pill moved up to
   the Kill Score banner), so its trailing margin is dead space in the hero. */
.pd-idp-rec-main .pd-idp-candbar:last-child { margin-bottom: 0; }
.pd-idp-verdicts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 18px; }
.pd-idp-verdict {
  position: relative; text-align: left; padding: 18px 18px 16px;
  border: 1px solid var(--pd-line); background: var(--pd-surface); border-radius: 12px;
  cursor: pointer; transition: all 120ms ease; margin: 1px;
}
.pd-idp-verdict .head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 6px; }
.pd-idp-verdict .label { font-size: 22px; font-weight: 700; color: var(--pd-ink); line-height: 1; letter-spacing: -0.01em; }
.pd-idp-verdict .sub { font-size: 12.5px; color: var(--pd-ink-3); line-height: 1.5; text-wrap: pretty; }
.pd-idp-verdict .check { display: none; }
.pd-idp-verdict .stella-tag { margin-top: 10px; font-size: 9.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--pd-ink-4); }
.pd-idp-verdict:hover { border-color: var(--pd-line-stronger); }
.pd-idp-verdict.active { margin: 0; }
.pd-idp-verdict.active .check { display: inline; }
.pd-idp-verdict.kill.active { border: 2px solid var(--pd-red); background: var(--pd-red-bg); }
.pd-idp-verdict.kill.active .label, .pd-idp-verdict.kill.active .sub { color: var(--pd-red); }
.pd-idp-verdict.park.active { border: 2px solid var(--pd-amber-ink); background: var(--pd-amber-bg); }
.pd-idp-verdict.park.active .label, .pd-idp-verdict.park.active .sub { color: var(--pd-amber-ink); }
.pd-idp-verdict.fund.active { border: 2px solid var(--pd-green-ink); background: var(--pd-green-bg); }
.pd-idp-verdict.fund.active .label, .pd-idp-verdict.fund.active .sub { color: var(--pd-green-ink); }
.pd-idp-verdict.active .sub { opacity: 0.9; }
.pd-idp-counter {
  display: none; gap: 10px; align-items: flex-start; margin-bottom: 18px;
  border-radius: 12px; padding: 12px 14px;
  box-shadow: 0 1px 0 var(--glass-highlight-soft) inset, 0 2px 8px hsl(var(--stella-shade) / 0.08);
}
.pd-idp-counter.is-on { display: flex; }
/* Thinking state: the bubble arrives with typing dots (the rail's .pd-typing
   component) and holds its final height, so the note replaces the dots without
   the block resizing under the cursor. */
.pd-idp-counter .body { min-height: 40px; }
.pd-idp-counter .pd-idp-dots { display: none; padding: 0; height: 19px; }
.pd-idp-counter.is-thinking .pd-idp-dots { display: inline-flex; }
.pd-idp-counter.is-thinking .pd-idp-ctext { display: none; }
.pd-idp-ctext { animation: pd-idp-fade 260ms ease both; }
@keyframes pd-idp-fade { from { opacity: 0; } to { opacity: 1; } }
.pd-idp-counter .body { flex: 1; font-size: 12.5px; color: var(--pd-ink); line-height: 1.55; text-wrap: pretty; }
.pd-idp-rationale { border: 1px solid var(--pd-line); border-radius: 12px; padding: 14px 16px 12px; margin-bottom: 14px; background: var(--pd-surface); cursor: text; }
.pd-idp-rationale .label { font-size: 12.5px; font-weight: 600; color: var(--pd-ink); margin-bottom: 8px; }
.pd-idp-rationale .ph { font-size: 13px; line-height: 1.55; color: var(--pd-ink-4); min-height: 40px; }
.pd-idp-confirm { margin-top: 22px; display: flex; justify-content: flex-end; align-items: center; gap: 10px; }

/* Kill Score dimension blocks in Stella's rail (Idea screen). Reuses the
   hero rail's .pd-idea-card, .pd-idea-title, .pd-idea-note and .pd-chip;
   only the title's card-anatomy margin needs neutralizing here. */
.pd-ksd .pd-idea-title { margin-top: 0; }
.pd-ksd-why { display: block; }
.pd-ksd-why + .pd-ksd-why { margin-top: 9px; }
/* Dive-deeper link per dimension: the hero vision strip's CTA, card-sized */
.pd-ksd-cta { margin-top: 10px; font-size: 12px; }
.pd-ksd .pd-idea-head { align-items: baseline; }
.pd-ksd .pd-chip { flex-shrink: 0; height: 22px; font-size: 10.5px; }

/* =========================================================
   Live screen — Business Model Canvas (What-Praxis-Is, People tab)
   Coach's canvas with Stella's review attached: a strip at the
   top, flags inside the two cells that are still assertions, and
   the conversation in her rail. A faithful port of the
   prototype's BmcEditor (bmc-canvas / bmc-grid / bmc-cell,
   bmc-meta-row, alink chips), with every value on the shared
   pd-* / stella-* tokens. Row height is a variable because the
   whole 3-row canvas has to clear the 849px fold.
   ========================================================= */
.pd-bmc { --pd-bmc-row: 178px; --pd-bmc-row-b: 125px; }
.pd-bmc .pd-doc-title { margin-bottom: 6px; }
.pd-bmc .pd-byline { margin-bottom: 12px; }

/* Title row: info button, title, Draft with Stella, kebab */
.pd-bmc-headrow { display: flex; align-items: center; gap: 10px; margin-bottom: 2px; }
.pd-bmc-info {
  width: 26px; height: 26px; border-radius: 50%; flex-shrink: 0;
  display: grid; place-items: center; cursor: pointer;
  color: var(--pd-ink-3); border: 1px solid transparent;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.pd-bmc-info:hover { background: var(--pd-paper-3); border-color: var(--pd-line); color: var(--pd-ink); }
.pd-bmc-headrow .pd-doc-title { flex: 1; min-width: 0; margin-bottom: 0; }
.pd-bmc-headacts { display: inline-flex; align-items: center; gap: 8px; flex-shrink: 0; }


/* Meta row: linked Ideas + linked Artifacts, then version notes */
.pd-bmc-meta { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: 12px; margin-bottom: 14px; }
.pd-bmc-metacard { padding: 13px 16px; display: flex; flex-direction: column; }
.pd-bmc-metahead { display: flex; align-items: center; margin-bottom: 9px; }
.pd-bmc-metalabel { display: inline-flex; align-items: center; gap: 6px; }
.pd-bmc-metalabel svg { color: var(--pd-ink-4); }
.pd-bmc-metadiv { height: 1px; background: var(--pd-line-soft); margin: 11px -16px; }
.pd-bmc-chiprow { display: flex; align-items: center; gap: 6px; flex-wrap: nowrap; overflow: hidden; }
/* One line, app-style: chips give up width (titles ellipsis) before the
   overflow count and the add button, which must always stay reachable. */
.pd-bmc-more, .pd-bmc-add { flex-shrink: 0; }
.pd-bmc-notes { font-size: 12.5px; line-height: 1.55; color: var(--pd-ink-2); text-wrap: pretty; }

/* Linked-record chip. Two variants: an Idea (code + title) and a typed
   Artifact link (verb + target). */
.pd-bmc-chip {
  display: inline-flex; align-items: center; height: 30px; min-width: 0; cursor: pointer;
  background: var(--pd-surface); border: 1px solid var(--pd-line); border-radius: 12px;
  transition: border-color 120ms ease, box-shadow 120ms ease;
}
.pd-bmc-chip:hover { border-color: var(--pd-line-strong); box-shadow: 0 1px 2px hsl(var(--pd-shade-2) / 0.04); }
.pd-bmc-idea { gap: 7px; padding: 4px 4px 4px 10px; max-width: 320px; }
.pd-bmc-code { font-size: 10.5px; color: var(--pd-ink-4); letter-spacing: 0.02em; font-weight: 500; flex-shrink: 0; white-space: nowrap; }
.pd-bmc-chiptitle { font-size: 12.5px; color: var(--pd-ink-2); min-width: 0; max-width: 168px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pd-bmc-x {
  width: 20px; height: 20px; border-radius: 10px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--pd-ink-4); transition: background 120ms ease, color 120ms ease;
}
.pd-bmc-x:hover { background: var(--pd-paper-3); color: var(--pd-ink); }
.pd-bmc-add, .pd-bmc-more {
  height: 30px; border-radius: 12px; cursor: pointer;
  background: var(--pd-paper-3); border: 1px solid var(--pd-line); color: var(--pd-ink-3);
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
  font-size: 12px; font-weight: 500; white-space: nowrap;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.pd-bmc-add { width: 30px; }
.pd-bmc-more { padding: 0 10px; }
.pd-bmc-add:hover, .pd-bmc-more:hover { background: var(--pd-surface); border-color: var(--pd-line-strong); color: var(--pd-ink); }

.pd-bmc-alink { max-width: 100%; padding: 3px; box-sizing: border-box; }
.pd-bmc-verb {
  display: inline-flex; align-items: center; gap: 4px; flex-shrink: 0;
  padding: 2px 7px; border-radius: 8px;
  font-size: 10.5px; font-weight: 600; letter-spacing: 0.02em; line-height: 1.2;
  color: var(--pd-ink-3); background: var(--pd-paper-3); border: 1px solid var(--pd-line-soft);
}
.pd-bmc-arrow { font-size: 10px; opacity: 0.85; }
.pd-bmc-target { display: inline-flex; align-items: center; gap: 6px; padding: 0 6px 0 8px; min-width: 0; overflow: hidden; }
.pd-bmc-alink:hover .pd-bmc-chiptitle { color: var(--pd-ink); }

/* The canvas itself */
.pd-bmc-canvas {
  background: var(--pd-paper-2); border: 1px solid var(--pd-line);
  border-radius: 20px; padding: 14px;
}
.pd-bmc-grid {
  display: grid; grid-template-columns: repeat(10, 1fr);
  grid-template-rows: var(--pd-bmc-row) var(--pd-bmc-row) var(--pd-bmc-row-b); gap: 10px;
}
.pd-bmc-slot { display: flex; min-height: 0; }
.pd-bmc-slot > * { width: 100%; }
.pd-bmc-partners      { grid-area: 1 / 1 / span 2 / span 2; }
.pd-bmc-activities    { grid-area: 1 / 3 / span 1 / span 2; }
.pd-bmc-resources     { grid-area: 2 / 3 / span 1 / span 2; }
.pd-bmc-value         { grid-area: 1 / 5 / span 2 / span 2; }
.pd-bmc-relationships { grid-area: 1 / 7 / span 1 / span 2; }
.pd-bmc-channels      { grid-area: 2 / 7 / span 1 / span 2; }
.pd-bmc-segments      { grid-area: 1 / 9 / span 2 / span 2; }
.pd-bmc-costs         { grid-area: 3 / 1 / span 1 / span 5; }
.pd-bmc-revenue       { grid-area: 3 / 6 / span 1 / span 5; }
.pd-bmc-cell {
  background: var(--pd-surface); border: 1px solid var(--pd-line); border-radius: 14px;
  padding: 12px 14px 11px; display: flex; flex-direction: column; gap: 7px;
  width: 100%; height: 100%;
  transition: border-color 140ms ease, box-shadow 140ms ease;
}
.pd-bmc-cell:hover { border-color: var(--pd-line-strong); box-shadow: 0 2px 10px hsl(var(--pd-shade-2) / 0.05); }
.pd-bmc-cellhead { display: flex; align-items: center; gap: 8px; }
.pd-bmc-celltitle { flex: 1; font-size: 13.5px; font-weight: 700; letter-spacing: -0.005em; color: var(--pd-ink); text-wrap: balance; }
.pd-bmc-celltext { font-size: 12.5px; line-height: 1.5; color: var(--pd-ink); text-wrap: pretty; }
/* Inline @-mention of another artifact inside a cell */
.pd-bmc-mention {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 6px; border-radius: 6px; white-space: nowrap;
  background: var(--pd-green-bg); border: 1px solid var(--pd-green-bd); color: var(--pd-green-ink);
  font-size: 11px; font-weight: 600; cursor: pointer;
}
.pd-bmc-mention:hover { border-color: var(--pd-green); }

/* Stella's nudge on a cell that is still an assertion. The cell itself says
   nothing: the indicator sits in the cell's existing action slot and opens her
   note in the rail, so the canvas stays readable. */
.pd-bmc-cell.flagged { border-color: var(--stella-glass-border); }
.pd-bmc-note {
  width: 18px; height: 18px; border-radius: 50%; flex-shrink: 0; cursor: pointer;
  box-shadow: 0 0 0 3px var(--stella-glass-border);
  transition: box-shadow 140ms ease, transform 140ms ease;
}
.pd-bmc-note img { width: 100%; height: 100%; border-radius: 50%; display: block; }
.pd-bmc-note {
  animation: pd-bmc-pulse 2.4s ease-in-out infinite;
}
@keyframes pd-bmc-pulse {
  0%, 100% { box-shadow: 0 0 0 3px var(--stella-glass-border); }
  50%      { box-shadow: 0 0 0 7px hsl(var(--stella-shade) / 0.16); }
}
/* Hover replaces the invitation with a definite state. */
.pd-bmc-note:hover { animation: none; transform: scale(1.08); box-shadow: 0 0 0 4px var(--stella-border-hover); }
