
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("/app/assets/fonts/instrument-sans-upright-b4cf60bf4e3b.woff2") format("woff2");
}

@font-face {
  font-family: "Instrument Sans";
  font-style: italic;
  font-weight: 400 600;
  font-display: swap;
  src: url("/app/assets/fonts/instrument-sans-italic-acabf784a5e7.woff2") format("woff2");
}

:root {
  /* Redesign foundation (#2953, #2955). Public documents and signed-in
     routes share one dark slate frame. Semantic aliases stay separate even
     when the approved palette gives them the same value: interaction,
     success, P&L, and navigation must not silently become one meaning. */
  --bg: #0e161b;
  --surface: #172229;
  --surface-2: #24343d;
  --border: #344750;
  --border-strong: #78909b;
  --text: #edf3f1;
  --text-dim: #a5b7bb;
  --accent: #93d8c4;
  --on-accent: #0e161b;
  --nav-active: #edf3f1;
  --data-neutral: #91a8ba;
  --success: #b5cf9a;
  --warn: #e6c27a;
  --danger: #f1a4a8;
  --info: #9cc9e0;
  --pnl-up: #b5cf9a;
  --pnl-down: #e8a3ab;
  /* Legal print-only paper adaptation; never a browser theme. */
  --print-paper: #ffffff;
  --print-ink: #000000;

  /* Accent washes are reserved for interactive emphasis on the canvas or
     working surface. Semantic fills use the same reviewed 12% recipe but
     retain their own hue and meaning. */
  --accent-wash: rgba(147, 216, 196, 0.10);
  --accent-wash-strong: rgba(147, 216, 196, 0.16);
  --accent-bg: var(--accent-wash-strong);
  --success-bg: rgba(181, 207, 154, 0.12);
  --warn-bg: rgba(230, 194, 122, 0.12);
  --danger-border: var(--danger);
  --danger-bg: rgba(241, 164, 168, 0.12);
  --info-bg: rgba(156, 201, 224, 0.12);

  /* Geometry has three jobs: chips, controls, and bounded task surfaces.
     Ordinary rows and sections remain flat; elevation tokens below are only
     for overlays, menus, dialogs, tooltips, and the mobile drawer. */
  --radius-sm: 4px;
  --radius: 8px;
  --radius-lg: 12px;
  --font-sans: "Instrument Sans", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
               Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas,
               "Liberation Mono", monospace;
  --fs-micro: 0.75rem;
  /* #986 removed the 0.8125rem (13px) --fs-sm step: it packed a third
     size into the 12-14px band and was used interchangeably with its
     neighbors, earning no distinct role. Every consumer was repointed
     up to --fs-base-sm (14px), a uniform +1px move that shrinks
     nothing. */
  --fs-base-sm: 0.875rem;
  --fs-base: 1rem;
  --fs-md: 1.125rem;
  --fs-lg: 1.25rem;
  --fs-xl: 1.5rem;
  --fs-2xl: 2rem;
  /* Mobile rescales for the page/ticker display size. Kept as
     explicit tokens (rather than rolling clamp() into --fs-xl /
     --fs-2xl) because the codebase isn't using clamp() anywhere
     else yet; the token surface stays consistent across breakpoints. */
  --fs-h1-mobile: 1.625rem;
  --fs-hero-mobile: 1.625rem;
  /* Marketing display step. The public marketing pages set
     ``body.layout-marketing`` and consume the approved 56/36px pair. */
  --fs-3xl: 3.5rem;
  --fs-3xl-mobile: 2.25rem;
  /* Guide title step (#4224). Above 640px the guides and the /guides
     index set their title between the 32px page heading and the 56px
     marketing display; phones keep --fs-h1-mobile. */
  --fs-guide-title: 2.5rem;
  /* Spacing scale — 4px-based, used by every gap/margin/padding
     declaration in the branded web surface. Twenty-six off-scale
     rem values had been intuited per-component before issue #523;
     this token series snaps them to a single rhythm so cards,
     rows, and tiles share consistent breathing room. Steps follow
     a 4px progression (--space-1 = 4px, --space-2 = 8px, …), with
     gaps in the numbering (skipping 7, 9-11) reserved for future
     additions. */
  --space-1: 0.25rem;  /*  4px */
  --space-2: 0.5rem;   /*  8px */
  --space-3: 0.75rem;  /* 12px */
  --space-4: 1rem;     /* 16px */
  --space-5: 1.25rem;  /* 20px */
  --space-6: 1.5rem;   /* 24px */
  --space-8: 2rem;     /* 32px */
  --space-12: 3rem;    /* 48px */
  /* Font weights — three steps cover the surface. Five distinct
     weights had been used inconsistently before issue #527 (400 /
     500 / 600 / 700 / inherited). Headings sit at --fw-bold so the
     UA default 700 doesn't slam light-on-dark display type; --fw-
     medium picks out labels and tile values that want a small step
     up from body without going semi-bold. The bare literal ``700``
     survives only on the tier-features ✓ icon, a deliberate
     typographic exception documented at that site rather than a fourth
     token. */
  --fw-regular: 400;
  --fw-medium: 500;
  --fw-bold: 600;
  /* Elevation is reserved for true overlays: the tooltip and mobile drawer.
     Ordinary cards and highlighted rows remain flat. */
  --shadow-md: 0 6px 18px rgba(0, 0, 0, 0.45);
  --shadow-lg: 2px 0 16px rgba(0, 0, 0, 0.4);
  /* Layout measures (#2573 D02, the design system's foundation slice).
     The --space-* scale above covers every gap/margin/padding
     relationship, and Stylelint enforces it. It does not cover
     ``width``, ``max-width``, ``min-height`` or ``line-height``, which
     sit outside the literal ban in both frontend/stylelint.config.mjs
     and scripts/check_spacing_tokens.py. Those four properties had
     therefore drifted uncaught: 65ch appeared 8 times, 2.75rem 10
     times, and 40rem twice, with no declared authority anywhere.
     docs/frontend-design-system.md is the design decision; these
     tokens make it executable. SPA stylesheets cannot declare a custom
     property at all, so a shared token is the only available home. */

  /* Comfortable reading measure for prose, ledes, help and supporting
     notes. A genuinely tabular comparison is not prose and is not
     capped here. */
  --measure-prose: 65ch;
  --measure-support: 72ch;

  /* Slatemark's minimum interaction target for single-line controls,
     buttons and inline actions. This is a product choice, not an
     accessibility floor: WCAG 2.2 AA's target-size minimum is 24 CSS
     px with specified exceptions. Do not describe this token as the
     AA minimum. */
  --control-target: 2.75rem;

  /* Purposeful control widths. Every one is a maximum applied as
     min(100%, maximum), so a control still fits a narrow column; none
     of them is a value constraint. A 10rem quantity field does not
     imply a numeric limit. --control-long doubles as the fallback cap
     for a control that has not been classified yet. */
  --control-numeric: 10rem;
  --control-symbol: 12rem;
  --control-compact: 20rem;
  --control-text: 32rem;
  --control-long: 40rem;

  /* Line heights. Body and controls read at --lh-body, long prose at
     --lh-prose, and headings at --lh-heading, which is the loose end
     of the 1.2 to 1.35 heading band. */
  --lh-body: 1.5;
  --lh-prose: 1.65;
  --lh-heading: 1.35;

  /* Public frame (#4218). Every public header, the Home, Features and
     Pricing workspace and the /guides index (#4224) share one pair of
     edges: at most --public-frame of content between two --public-gutter
     margins. Phones keep 16px margins. Wider windows keep 24px until the
     content reaches 73rem, the former maximum, hold it there until 4vw is
     wider, then follow 4vw up to 5rem, so no window gets less content than
     before. The gutter's 100% is the page width only on an element whose
     containing block spans the page, so use these two tokens on the public
     header, the workspace and the /guides index alone. */
  --public-frame: 92rem;
  --public-gutter: var(--space-4);
}

@media (min-width: 641px) {
  :root { --public-gutter: clamp(var(--space-6), (100% - 73rem) / 2, min(4vw, 5rem)); }
}
* { box-sizing: border-box; }
/* Native choice controls share the interaction accent (#1562 D19).
   The browser keeps its platform-native shape and forced-colors behavior. */
input[type="checkbox"],
input[type="radio"] { accent-color: var(--accent); }
/* Themed scrollbars (design pass). The OS default scrollbar renders as
   a chunky light bar that clashes with the dark theme — most visible on
   the fixed sidebar's overflow-y track at viewport heights where the
   nav + footer exceed the fold (1080p and below), and on any long
   dashboard. Thin + dark across Firefox (scrollbar-*) and WebKit/Blink
   (::-webkit-scrollbar) so every scroll container (sidebar, main, code
   blocks, tooltips) recedes into the surface instead of punching a
   bright rectangle through the page. Track stays transparent; the thumb
   is the hairline --border at rest and lifts to --text-dim on hover so
   it reads as grabbable without ever shouting. */
html { scrollbar-width: thin; scrollbar-color: var(--border) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 999px;
  /* Transparent border + padding-box clip insets the thumb so it reads
     as a slim pill with breathing room, not a full-width slab. */
  border: 2px solid transparent;
  background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--text-dim); }
/* WCAG 2.1 SC 2.4.7 — keyboard focus indicator. Chrome's default
   focus ring dims to near-invisible against the dark theme, so we
   draw our own. Scoped to :focus-visible so a mouse click into an
   input or button doesn't paint a ring. Elements that need a
   different offset (overflow-clipped containers, dense nav rows)
   override per-class below. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius);
}
.btn:focus-visible { outline-offset: 3px; }
.nav-item:focus-visible { outline-offset: -2px; }
html {
  /* Lock the rem base to 16px regardless of UA quirks. Every rem
     value below is sized against this. */
  font-size: 16px;
  min-height: 100%;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}
body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  line-height: 1.5;
  /* Antialiasing for the unified dark public and signed-in surface, where
     subpixel rendering thickens light-on-dark text. */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-feature-settings: "kern", "liga";
  /* Sticky footer. Body is a column flex container that fills the
     viewport, main grows to absorb any leftover space, footer stays
     non-shrinking at the bottom. Works for both the public topbar
     layout and the signed-in sidebar layout — the sidebar is
     position:fixed and the hidden nav-toggle checkbox is
     position:absolute, so neither participates in the flex flow. */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  color-scheme: dark;
}
main { flex: 1 0 auto; }
.footer { flex-shrink: 0; }
/* Semantic emphasis follows the same three-step weight system as the
   headings and components instead of falling back to UA-specific boldness.
   Keep italic explicit too, so prose emphasis has one shared primitive even
   though the current platform stacks already provide a native italic face. */
strong, b { font-weight: var(--fw-bold); }
em, i { font-style: italic; }
/* Authored underlines use the same font-relative geometry as prose links.
   ``skip-ink`` keeps descenders legible instead of drawing through them. */
u, ins {
  text-decoration: underline;
  text-decoration-thickness: 0.08em;
  text-underline-offset: 0.16em;
  text-decoration-skip-ink: auto;
}
/* Inline links need a non-color resting affordance (#1570 / WCAG
   1.4.1). Accent green is intentionally close to the surrounding
   light body text, so color alone cannot identify a prose link.
   Navigation and whole-component links opt out at their component
   rules below; ordinary prose, help, and legal links stay underlined. */
a {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-thickness: 0.08em;
  text-underline-offset: 0.16em;
  text-decoration-skip-ink: auto;
}
a:hover { text-decoration-thickness: 0.12em; }
/* Long support addresses must reflow without changing their destination. */
a[href^="mailto:"] { overflow-wrap: anywhere; }
/* Honor the ``hidden`` attribute even on elements whose own rule
   sets a ``display`` (e.g. ``.tile`` is flex, ``.hero-card-link``
   is block) — the UA ``[hidden]`` rule loses to any author display.
   Used by the client-side tool filter (#766) to show/hide cards. */
[hidden] { display: none !important; }
/* Screen-reader-only label: removed from view but kept in the
   accessibility tree (e.g. the tool-search input's label, #766). */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
code, .mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum", "zero";
}
/* Skip-to-content link (#1300 P2, WCAG 2.4.1). First focusable
   element in the public topbar shell; parked offscreen until a
   keyboard user tabs onto it, then pinned over the header so Tab ->
   Enter jumps past the nav to <main id="main">. */
.skip-link {
  position: absolute;
  left: -9999px;
  z-index: 100;
}
.skip-link:focus {
  left: var(--space-4);
  top: var(--space-4);
  background: var(--surface-2);
  color: var(--text);
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  text-decoration: none;
}
.shell { max-width: 56rem; margin: 0 auto; padding: 0 var(--space-6); }

/* Sidebar layout — opt-in via <body class="layout-sidebar"> on the
   frontend-owned signed-in document shell. Public pages keep the topbar.

   Mobile drawer trick: a hidden checkbox sibling of the sidebar +
   scrim drives the slide-in via :checked, so the whole thing is
   CSS-only. Order matters: the checkbox must appear in the DOM
   before .sidebar and .scrim for the `~` sibling selectors below
   to fire. */
.nav-toggle { position: absolute; left: -9999px; }
.sidebar {
  container: navigation-rail / inline-size;
  position: fixed;
  left: 0;
  top: 0;
  bottom: 0;
  width: 13rem;
  background: var(--bg);
  border-right: 1px solid var(--border);
  /* env(safe-area-inset-*) keeps the brand off the iOS notch /
     status bar and the Sign out button clear of the home
     indicator. The viewport meta carries ``viewport-fit=cover``
     so the env values resolve to actual insets on iPhone; on
     Android / desktop they're 0 and the fallback padding wins. */
  padding:
    max(var(--space-4), calc(var(--space-3) + env(safe-area-inset-top)))
    var(--space-3)
    max(var(--space-4), calc(var(--space-2) + env(safe-area-inset-bottom)));
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  overflow-y: auto;
  z-index: 20;
}
.sidebar .brand {
  display: inline-flex;
  align-items: center;
  gap: 0;
  padding: var(--space-2);
  font-size: var(--fs-lg);
}
/* Keep the wordmark and its dot together. At large text the decorative
   mark yields first, so the native drawer keeps the same readable name
   as the text-only SPA rail. */
.sidebar .brand-mark { margin-inline-end: var(--space-2); }
@container navigation-rail (max-width: 12rem) {
  .sidebar .brand-mark { display: none; }
}
.brand-mark {
  display: block;
  width: var(--space-6);
  height: var(--space-6);
  flex: 0 0 auto;
}
.side-nav { display: flex; flex-direction: column; gap: var(--space-4); flex: 1; }
.nav-group { display: flex; flex-direction: column; gap: var(--space-1); }
.job-context {
  margin-bottom: var(--space-4);
}
.context-nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  width: fit-content;
  max-width: 100%;
  min-height: 2.75rem;
  border-bottom: 1px solid var(--border);
}
.context-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: var(--space-2) var(--space-3);
  border-bottom: 2px solid transparent;
  color: var(--text-dim);
  font-size: var(--fs-base-sm);
  text-decoration: none;
}
.context-nav a:hover {
  background: var(--surface-2);
  color: var(--text);
  text-decoration: none;
}
.context-nav a[aria-current] { color: var(--text); }
/* Exact pages carry the stronger fill plus underline treatment; a containing
   location keeps only its underline. Weight and shape preserve page versus
   section without depending on color alone (#1659). */
.context-nav a[aria-current="page"] {
  border-bottom-color: var(--nav-active);
  background: var(--surface-2);
  font-weight: var(--fw-medium);
}
.context-nav a[aria-current="location"] {
  border-bottom-color: var(--border-strong);
}
.nav-item {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: var(--space-2);
  /* 44px min touch target (issue #626 a11y) — the rows were
     tightly stacked at space-2 padding. min-height + centered
     flex keeps the visual rhythm while meeting the target. */
  min-height: 2.75rem;
  padding: var(--space-2);
  border-radius: var(--radius);
  color: var(--text-dim);
  font-size: var(--fs-base-sm);
  text-decoration: none;
  line-height: 1.3;
  position: relative;
  transition: background-color 160ms ease, color 160ms ease;
}
.nav-icon {
  display: block;
  width: 1.125rem;
  height: 1.125rem;
  flex: 0 0 auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.nav-label { flex: 1 1 auto; }
.nav-item:hover {
  background: var(--surface-2);
  color: var(--text);
  text-decoration: none;
}
.nav-item.active {
  background: var(--surface-2);
  color: var(--text);
  font-weight: var(--fw-medium);
}
/* The current destination's marker (#4322): a straight 2px bar in the
   navigation marker's role on the plate's leading edge. It stops a corner
   radius short of the plate's top and bottom, so it never bends around them.
   The rail is otherwise flat, with no glow, gradient or motion. */
.nav-item.active::after {
  background: var(--nav-active);
  border-radius: var(--radius-sm);
  content: "";
  inline-size: 2px;
  inset-block: var(--radius);
  inset-inline-start: 0;
  pointer-events: none;
  position: absolute;
}
.sidebar-foot {
  border-top: 1px solid var(--border);
  padding-top: var(--space-3);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.account-disclosure > summary {
  min-height: 2.75rem;
  padding: var(--space-2);
  border-radius: var(--radius);
  color: var(--text-dim);
  cursor: pointer;
}
.account-disclosure > summary:hover,
.account-disclosure[open] > summary {
  background: var(--surface-2);
  color: var(--text);
}
.account-disclosure > summary::marker { color: var(--accent); }
.sidebar-foot .who {
  display: inline-block;
  color: var(--text-dim);
  font-size: var(--fs-base-sm);
  font-family: var(--font-mono);
  max-width: calc(100% - var(--space-4));
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: middle;
  white-space: nowrap;
}
.sidebar-foot form { padding: var(--space-2) var(--space-1) 0; }
.sidebar-foot .btn { width: 100%; text-align: center; padding: var(--space-2) var(--space-3); font-size: var(--fs-base-sm); }

/* Mobile top strip on sidebar pages — slim bar with hamburger +
   brand. Hidden on desktop; the sidebar carries everything there. */
.topbar.mobile-only { display: none; }
/* The drawer toggle is a `span.hamburger` wrapped in a role-free
   `label[for="nav-toggle"]`: the label is the no-JavaScript activation
   path, the span is where `role="button"` is actually valid (#2604).
   `display: contents` drops the wrapper's box so the span stays the
   topbar flex item and every `.hamburger` rule below still applies. */
.hamburger-slot { display: contents; }
.hamburger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  color: var(--text);
  background: transparent;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  cursor: pointer;
  /* Reset font metrics so the SVG icon below isn't shifted by
     an inherited line-height (system fonts vary on Mac vs.
     iOS Safari and the old &#9776; glyph centered differently
     on each). */
  line-height: 1;
}
.hamburger:hover { background: var(--surface-2); }
.hamburger svg {
  width: 1.25rem;
  height: 1.25rem;
  display: block;
  stroke: currentColor;
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
}
.scrim { display: none; }

/* 13rem on the main + foot margin-left is the wide sidebar offset
   (matches the .sidebar width above) — a layout constraint, not a
   spacing-rhythm value, so it stays a literal rather than riding on
   the --space-* scale. */
body.layout-sidebar main { margin-left: 13rem; padding: var(--space-12) 0 4rem; /* 4rem bottom = generous page-bottom breathing; --space-12 (3rem) would crowd the foot on long dashboards */ }
body.layout-sidebar .shell { max-width: 78rem; margin: 0 auto; padding: 0 var(--space-8); }
body.layout-sidebar > .topbar:not(.mobile-only) { display: none; }
body.layout-sidebar .footer {
  margin-left: 13rem; /* sidebar offset, see above */
  background: var(--surface);
}

/* The immutable SPA document reaches first paint before the authenticated
   React chrome can exist. Keep its footer out of that pending frame so it
   cannot flash at the top of an otherwise empty workspace. Limit the rule to
   the empty mount and sole session-loading status so complete, error and
   reviewed synthetic shell content reveal the footer normally. */
body.layout-sidebar:has(#slatemark-spa-root:empty) > .footer,
body.layout-sidebar:has(#slatemark-spa-root > p[role="status"]:only-child) > .footer {
  visibility: hidden;
}
@media (scripting: none) {
  body.layout-sidebar:has(#slatemark-spa-root:empty) > .footer {
    visibility: visible;
  }
}

/* Intermediate desktop keeps the same jobs in a compact 184px rail with the
   contract's 24px task gutter. */
@media (min-width: 900px) and (max-width: 1199px) {
  body.layout-sidebar .sidebar { width: 11.5rem; }
  body.layout-sidebar main,
  body.layout-sidebar .footer { margin-left: 11.5rem; }
  body.layout-sidebar .shell { padding: 0 var(--space-6); }
}

/* Below 900px the task column takes the viewport and the existing rail becomes
   the accessible overlay drawer (#2741, #2956). */
@media (max-width: 899px) {
  body.layout-sidebar > .topbar.mobile-only,
  body.layout-sidebar > #slatemark-browser-document-root > .topbar.mobile-only {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: max(var(--space-3), calc(var(--space-1) + env(safe-area-inset-top))) var(--space-5) var(--space-3);
    flex-direction: row;
    flex-wrap: wrap;
    container: mobile-topbar / inline-size;
  }
  /* Large text on a narrow phone (#2744). The menu control, the mark and
     the wordmark need about 12.5rem in one row, and 200% text on a 320px
     phone leaves 8rem inside the topbar's padding. The control keeps its
     full target instead of shrinking, the row wraps so the wordmark takes
     a line of its own, and the decorative mark drops first, once that
     row is 13.5rem or narrower (the 12.5rem plus a rem of slack), so the
     wordmark stays whole. The query is in rem, which follows the text
     size. A break inside the wordmark is the last resort, for text larger
     still. The SPA shell and the signed-in browser documents both render
     this topbar. */
  .topbar.mobile-only .hamburger { flex: none; }
  .topbar.mobile-only .brand { min-width: 0; overflow-wrap: anywhere; }
  @container mobile-topbar (max-width: 13.5rem) {
    .topbar.mobile-only .brand-mark { display: none; }
  }
  body.layout-sidebar main { margin-left: 0; padding: var(--space-6) 0 var(--space-12); }
  body.layout-sidebar .shell { padding: 0 var(--space-5); }
  body.layout-sidebar .footer { margin-left: 0; }
  body.layout-sidebar .sidebar {
    transform: translateX(-100%);
    /* The closed drawer is removed from pointer AND keyboard/AT reach
       (WCAG 2.4.3 / #1395 WS7) — an off-screen transform alone leaves
       ~30 nav links in the tab order behind the page. The transform is
       intentionally instant; the redesign motion contract permits only
       brief colour or opacity feedback. */
    visibility: hidden;
    width: min(16rem, 100%);
    box-shadow: var(--shadow-lg);
  }
  body.layout-sidebar .nav-toggle:checked ~ .sidebar {
    transform: translateX(0);
    visibility: visible;
  }
  body.layout-sidebar .scrim {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
    z-index: 15;
    opacity: 0;
    pointer-events: none;
    transition: opacity 160ms ease;
  }
  body.layout-sidebar .nav-toggle:checked ~ .scrim {
    opacity: 1;
    pointer-events: auto;
  }
}

@media (max-width: 375px) {
  body.layout-sidebar > .topbar.mobile-only,
  body.layout-sidebar > #slatemark-browser-document-root > .topbar.mobile-only {
    padding-inline: var(--space-4);
  }
  body.layout-sidebar .shell { padding-inline: var(--space-4); }
}

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4) var(--space-6);
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}
.brand {
  font-family: var(--font-mono);
  font-weight: var(--fw-bold);
  font-size: var(--fs-md);
  letter-spacing: 0.02em;
  color: var(--text);
  text-decoration: none;
}
/* Keep the wordmark and its dot together, as the rail does: the decorative
   mark carries the space after it, not a flex gap (#2744). min-width and
   overflow-wrap let the wordmark wrap rather than overflow, as a last
   resort; each header drops its mark before that point at up to 200%
   text. */
.topbar .brand {
  display: inline-flex;
  align-items: center;
  gap: 0;
  min-width: 0;
  max-width: 100%;
  overflow-wrap: anywhere;
}
.topbar .brand-mark { margin-inline-end: var(--space-2); }
.brand .dot { color: var(--accent); }
.topbar-right { display: flex; align-items: center; gap: var(--space-4); }
.topbar nav a:not(.btn) {
  margin-left: var(--space-5);
  color: var(--text-dim);
  text-decoration: none;
}
.topbar nav a:first-child { margin-left: 0; }
.topbar nav a:not(.btn):hover { color: var(--text); text-decoration: none; }
/* Active-page state on the public nav (#1300 P0). The shell marks the
   current page's nav link with ``aria-current="page"`` (derived from
   the request's canonical path), and the style keys off that
   attribute so the semantic and visual state can't drift apart. Kept
   deliberately neutral — full text color plus a quiet underline; the
   accent green stays reserved for the CTA (#627 "one green, one
   meaning"). */
.topbar nav a[aria-current="page"] {
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: var(--text-dim);
  text-underline-offset: 0.45em;
}
/* Compact header CTA (#1300 P0), sized down from the body .btn so it
   sits inside the header type, not on top of it. "Sign in" stays a text
   link; one filled control per header. It is the public nav's last
   item, so a narrow header folds it into the menu with the links rather
   than crowding the brand row above a hero that repeats it. */
.btn.nav-cta {
  padding: var(--space-1) var(--space-3);
  font-size: var(--fs-base-sm);
  white-space: nowrap;
}
.public-menu > summary { list-style: none; }
.public-menu > summary::-webkit-details-marker { display: none; }
main { padding: var(--space-8) 0 4rem; /* 4rem bottom = generous page-bottom breathing on the public layout; --space-12 (3rem) would crowd the foot under long pages */ }
/* Headings: explicit 600 so we don't inherit the UA's 700 — too
   heavy for light-on-dark display text. Slight negative tracking
   on h1 tightens the larger size optically. */
h1 {
  font-size: var(--fs-2xl);
  font-weight: var(--fw-bold);
  letter-spacing: -0.01em;
  line-height: 1.2;
  margin: 0 0 0.5rem;
}
body.layout-sidebar main h1 {
  font-size: var(--fs-2xl);
  line-height: 1.2;
  letter-spacing: -0.015em;
}
@media (max-width: 640px) {
  body.layout-sidebar main h1 { font-size: var(--fs-hero-mobile); }
}
/* Hero size step — opt-in via ``.card.hero`` on a landing-style card.
   Product and account pages share the approved 32/26px page-title pair. */
.card.hero h1 {
  font-size: var(--fs-2xl);
  line-height: 1.2;
  letter-spacing: -0.015em;
}
@media (max-width: 640px) {
  .card.hero h1 { font-size: var(--fs-hero-mobile); }
}
/* Marketing pages opt into the approved 56/36px hero pair; the public Home's
   two-column hero scales between the two (see the Home experience below).
   Section headings stay at the shared 20/18px scale, except Home's, which
   take a step up (#4601). Element-level selectors
   are intentional: copy pins assert the literal heading markup. */
body.layout-marketing .card.hero h1 {
  font-size: var(--fs-3xl);
  font-weight: var(--fw-medium);
  line-height: 1.1;
}
body.layout-marketing h2 { font-size: var(--fs-lg); }
@media (max-width: 640px) {
  body.layout-marketing .card.hero h1 { font-size: var(--fs-3xl-mobile); }
  body.layout-marketing h2 { font-size: var(--fs-md); }
}
h2 {
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  line-height: var(--lh-heading);
  margin: 0 0 0.75rem;
  color: var(--text);
}
p.kicker {
  /* Dim, not accent (design-critique pass): the eyebrow kicker used to
     paint --accent green, putting a second green attention magnet right
     above the hero's green CTA so first fixation split between the two.
     This completes the "one green, one meaning" accent discipline the
     rest of the marketing surface already follows: green is reserved for
     the CTA button and the proof column (#627), and for the analyst turn
     label + CTA on /examples (#817). The kicker now shares the signed-in
     sentence-case eyebrow role, letting the <h1> and the CTA own the hero.
     --text-dim on the dark surface is ~7:1, well past AA at this size. */
  color: var(--text-dim);
  font-size: var(--fs-base-sm);
  font-weight: var(--fw-medium);
  margin: 0 0 0.5rem;
}
p.lede {
  color: var(--text-dim);
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  margin: 0 0 var(--space-8);
}
/* Opt-in measure cap (issue #760) — a dashboard ``.lede`` runs the full
   60rem shell width by default, which is too wide for comfortable
   reading. Pages where the lede is body copy (not a hero line) add
   ``measure`` to cap it near the ~65ch readable line length, matching
   the ``.dim-blurb`` (60ch) treatment. Opt-in for dashboard surfaces;
   the marketing pages carry a blanket ~70ch cap below (#1300 P2 —
   uncapped ledes ran 85-90ch across the 56rem shell). */
p.lede.measure { max-width: var(--measure-prose); }
/* Marketing prose measure (#1300 P2). Scoped to the public marketing
   shell: ledes cap near 70ch so
   paragraphs stop running the full 56rem card width. Ledes that opt
   into the tighter 65ch .measure are excluded here (the :not()) so
   the opt-in keeps winning — without it this later, higher-specificity
   rule would silently widen them to 70ch. */
body.layout-marketing p.lede:not(.measure) { max-width: var(--measure-support); }
/* "How this works" expander — demotes pipeline/drift mechanics under
   a plain-English lede (e.g. /dashboard/rules) so the value promise
   reads first and the internals are one click away. Tighten the gap
   to the lede above it so the two read as one unit. */
p.lede:has(+ details.how-it-works) { margin-bottom: var(--space-3); }
details.how-it-works {
  margin: 0 0 var(--space-8);
  font-size: var(--fs-base-sm);
  color: var(--text-dim);
}
details.how-it-works > summary {
  cursor: pointer;
  list-style: none;
  color: var(--text-dim);
  font-weight: var(--fw-medium);
}
details.how-it-works > summary::-webkit-details-marker { display: none; }
details.how-it-works > summary::before {
  /* The plain arrow first: Firefox before 128 and Safari before 17.4 drop
     a content value with alt text, and would draw no marker. */
  content: "▸";
  content: "▸" / "";
  display: inline-block;
  flex: 0 0 auto;
  margin-right: var(--space-2);
}
details.how-it-works[open] > summary::before { transform: rotate(90deg); }
details.how-it-works > summary:hover { color: var(--accent); }
details.how-it-works > p {
  margin: var(--space-2) 0 0;
  line-height: 1.55;
}
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--space-5) var(--space-6);
  margin-bottom: var(--space-4);
}
.card.hero { border-radius: var(--radius-lg); }
body.layout-sidebar .card { padding: var(--space-6) var(--space-8); }
@media (max-width: 640px) {
  body.layout-sidebar .card { padding: var(--space-5); }
}
.card.danger { border-color: var(--danger-border); }
/* Section-rhythm floor (#1308). Top-level page sections self-space
   via a bottom margin on their own class (.card above;
   .feature-pillar, .tier-grid below), but a
   section class that never joined the system rendered flush against
   its neighbor: /demo's bare `section.tile-grid` sat 0px above the
   setup-help card. This floor guarantees the standard gap between
   adjacent top-level sections. :where() keeps it at zero
   specificity, so any class that declares its own margin-top
   (.mt-*) still wins outright, and sibling margin
   collapsing makes the floor a no-op wherever the preceding section
   already carries a bottom margin of --space-4 or more (every
   existing page). Pinned by tests/web/test_section_rhythm.py; a new
   top-level section class must also join RHYTHM_AUDITED_CLASSES
   there. */
:where(.shell > section + section) { margin-top: var(--space-4); }
.tile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
  gap: var(--space-4);
}
/* /features capability grid (issue #816). The shared auto-fit
   .tile-grid uses a smaller content floor here to keep reading measures
   useful at intermediate widths. The floor is bounded by available width
   so enlarged text still gets one complete column. */
.tile-grid.feature-grid {
  grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
}
.tile {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--space-5) var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
/* Flex gap owns generic tile rhythm. Zero specificity lets a component
   with an intentional paragraph margin override this without a fight. */
:where(.tile > p) { margin: 0; }
.tile .row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-4);
  /* Wrap so a long pill drops below its label rather than
     squeezing the label into a two-line stub when the row
     can't hold both on one line. */
  flex-wrap: wrap;
}
/* Long unbreakable code tokens (SLATEMARK_* env names, row ids) are
   the classic 320px page-overflow source (#1395 WS7): let them break
   anywhere rather than widen the page. */
code { overflow-wrap: anywhere; }
/* Focal accent-left rule, the single point of truth for the
   "this is the focal one" framing on tile-grid heroes
   (``.tile.hero``, issue #422).
   ``.tier.featured`` intentionally uses a different treatment
   (full accent border + ``--accent-wash`` bg, see below) —
   it sits in a grid of peers on /pricing and carries heavier
   emphasis than a single focal card. */
.tile.hero {
  border-left: 3px solid var(--accent);
}
/* A faint accent wash and complete accent edge make the promoted next step
   distinct without elevation. */
.tile.hero {
  background: var(--accent-wash);
  border-color: var(--accent);
  border-left-color: var(--accent);
}
/* Features pairs a short promise with its evidence in each of six anchored
   pillars. Headings remain in the document's reading order, and the layout
   below gives the same lead/detail relationship at every width. */
.feature-lead > h2 { margin-bottom: var(--space-2); }
/* The short promise reads at the detail's size and strength, so the
   promise never reads quieter than the evidence beside it. */
.feature-lead > .pillar-lede {
  color: var(--text);
  font-size: var(--fs-base);
  line-height: 1.55;
  margin: 0;
  max-width: var(--measure-prose);
}
/* Marketing-tile heading — the scannable title on a /features tile.
   Deliberately NOT .tile-title (that's a mono identifier for the
   tools catalog): full --text color, sentence case, and a step above
   the 16px body so the title is the most prominent element on the
   tile, not the dimmest (issue #816 inverted-hierarchy fix). Promoted
   from a dim <span class="label"> to a real <h3> so heading
   navigation and SEO get one stop per feature. */
.tile > h3.tile-heading {
  font-size: var(--fs-base);
  font-weight: var(--fw-bold);
  line-height: var(--lh-heading);
  color: var(--text);
  margin: 0;
}
/* Linked tile titles (#1298): a heading is no place to spend the
   accent (one green, one meaning). Keep the title in --text and carry
   the link affordance as a quiet underline that sharpens on hover. */
.tile > h3.tile-heading a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--border);
  text-underline-offset: 3px;
}
.tile > h3.tile-heading a:hover { text-decoration-color: var(--text-dim); }
.tile .value {
  font-size: var(--fs-md);
  font-weight: var(--fw-medium);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum", "zero";
}
.tile .actions { margin-top: auto; padding-top: var(--space-2); display: flex; gap: var(--space-2); flex-wrap: wrap; align-items: center; }
.muted-note {
  color: var(--text-dim);
  /* Roman, not italic (issue #626): long italic runs hurt
     readability and these are the lowest-contrast text on the
     tile face. Contrast of --text-dim on --surface is ~7:1, well
     past the 4.5:1 AA floor. */
  font-size: var(--fs-base-sm);
}
.tile .muted-note { padding: var(--space-3) 0; }
/* Setup-stepper "skill install" sub-card. Groups the per-AI-client
   download picker, the install-path hint, and the attestation
   checkbox into one visually-cohesive block on step 2's done state.
   Without the frame the three pieces read as three competing
   affordances on a flat surface; with it they read as one
   "install your skill" workflow. */
.card > .muted-note:first-of-type {
  margin-top: 0;
  margin-bottom: var(--space-4);
  max-width: 48rem;
}
.section-stack > * + * { margin-top: var(--space-6); }
/* Returning-user recent-record panel on Home / the dashboard (#1578).
   Rides .card for its section rhythm; these rules only shape the
   inner list and rows. ``Open <symbol>`` is an explicit compact action,
   not prose, so it uses weight + hover feedback instead of carrying the
   global resting underline into every ticker row. */
.activity-recent {
  list-style: none;
  margin: 0 0 var(--space-3);
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.activity-recent-link {
  display: inline-block;
  font-weight: var(--fw-medium);
  text-decoration: none;
}
.activity-recent-link:hover {
  text-decoration: underline;
  text-decoration-thickness: 0.1em;
}
.activity-attention {
  margin: 0 0 var(--space-2);
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.activity-scorecard { margin: 0; }
.connection-row { margin: 0; }
/* The card's vertical rhythm rides the .tile flex `gap` (--space-2), not
   the UA <p> margins (which never collapse in a flex column and stacked
   on the gap) nor the shared `.tile .muted-note` padding — both zeroed
   here so related content stays tight. Group boundaries add an explicit
   token margin on top of the base gap so unrelated groups breathe, and
   the biggest void inside the card no longer exceeds the page's own
   section rhythm (#1375). */
.connection-row p { margin: 0; }
.connection-row .muted-note { padding: 0; }
.connection-row .account-list-head {
  margin-top: var(--space-2);  /* + the .tile gap ~= a group boundary */
  padding: 0;
}
.connection-row .account-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--border);
}
/* Account rows read as a border-separated table, name + institution
   inline ("Roth IRA · Fidelity") rather than
   flung to opposite card edges with no separator (#1375). */
.connection-row .account-row {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  flex-wrap: wrap;
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--border);
}
.connection-row .account-row:last-child { border-bottom: none; }
.connection-row .account-broker { color: var(--text-dim); }
.connection-row .account-broker::before {
  content: "·";
  padding-right: var(--space-2);
}
/* Rename: a real disclosure affordance, not inert dim text. The prior
   `display: inline-block` suppressed the UA marker, leaving "Rename"
   looking static; draw our own caret and
   underline on hover, grouped just under the action row (#1375). */
.connection-row .rename { margin-top: 0; }
.connection-row .rename > summary {
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  width: max-content;
  padding: var(--space-1) 0;
  list-style: none;
}
.connection-row .rename > summary::-webkit-details-marker { display: none; }
.connection-row .rename > summary::before {
  content: "";
  width: 0.4rem;
  height: 0.4rem;
  border-right: 2px solid var(--text-dim);
  border-bottom: 2px solid var(--text-dim);
  transform: rotate(-45deg);
}
.connection-row .rename[open] > summary::before {
  transform: rotate(45deg);
}
.connection-row .rename > summary:hover {
  color: var(--text);
  text-decoration: underline;
}
.connection-row .rename > summary:hover::before { border-color: var(--accent); }
.coming-soon { margin-top: var(--space-4); }
.credentials {
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--border);
  margin-top: var(--space-1);
}
p.callout {
  margin: 0 0 var(--space-4) 0;
  padding: var(--space-3) var(--space-4);
  background: var(--surface-2);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
  font-size: var(--fs-base-sm);
  color: var(--text);
}
p.callout code {
  font-family: var(--font-mono);
  /* em-relative shrink (not a token): monospace inline <code> renders
     visually larger than the surrounding sans, so it scales relative to
     its parent rather than to a rem-based size. */
  font-size: 0.88em;
  color: var(--text-dim);
}
.tool-list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1);
  margin: var(--space-3) 0 var(--space-1) 0;
}
/* Shared input skin (#985, extended #1206). One base, the .input class,
   owns the surface + border + radius + padding + text color + accent
   focus-border that each form system used to redeclare identically.
   Per-system deltas (width / max-width / font-family / font-size / flex
   / resize) stay on the individual rules below. The selector list folds
   in each system's existing matched set (descendant
   input/select/textarea) alongside .input, so no element needs
   class="input" added and specificity is unchanged, while a future form
   can just use class="input". The keyboard :focus-visible ring lives at
   the top of this file and is untouched; the focus selectors below only
   restate the accent border + non-keyboard outline-reset. A single
   ::placeholder treatment (dim + italic) is hoisted alongside the skin
   (#1206) so placeholder tone no longer varies page to page; a system's
   own font-family on the placeholder stays local. The systems whose
   last consumer retired were removed from these lists (#2591 D20).
   color-scheme: dark
   is part of the skin (#1207): it themes the native control chrome (the
   <select> arrow, the date-picker glyph) that the UA otherwise draws
   dark-on-dark against these controls' dark background. */
.input,
.form-stack input[type="text"],
.form-stack input[type="datetime-local"],
.form-stack input[type="number"],
.form-stack input[type="email"],
.form-stack input[type="password"],
.form-stack input[type="url"],
.form-stack select,
.form-stack textarea,
.chat-form textarea {
  background: var(--bg);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  padding: var(--space-2) var(--space-3);
  color: var(--text);
  color-scheme: dark;
}
/* The shared skin keeps native arrows and picker glyphs on the same dark
   chrome across public, auth, and signed-in surfaces. */
.input:focus,
.form-stack input:focus,
.form-stack select:focus,
.form-stack textarea:focus,
.chat-form textarea:focus { border-color: var(--accent); }
.input:focus:not(:focus-visible),
.form-stack input:focus:not(:focus-visible),
.form-stack select:focus:not(:focus-visible),
.form-stack textarea:focus:not(:focus-visible),
.chat-form textarea:focus:not(:focus-visible) { outline: none; }
/* Shared placeholder treatment (#1206). One dim, italic tone for every
   skinned control, so placeholder text reads the same on every form
   (.form-stack and .chat-form fell back to the browser default). Only
   color + slant are shared:
   font-family stays per system, so the mono controls keep a mono
   placeholder. Selects carry no placeholder and are absent from the
   list. */
.input::placeholder,
.form-stack input::placeholder,
.form-stack textarea::placeholder,
.chat-form textarea::placeholder {
  color: var(--text-dim);
  font-style: italic;
}
/* Keep Chromium's saved-value paint inside the same dark control contract.
   Native picker glyphs and select arrows inherit the body/control dark
   color-scheme; the text/caret declarations prevent a bright autofill state
   from erasing the value against that ground. */
.input:-webkit-autofill,
.form-stack input:-webkit-autofill {
  -webkit-text-fill-color: var(--text);
  caret-color: var(--text);
}
.input:disabled,
.form-stack :is(input, select, textarea):disabled,
.chat-form textarea:disabled {
  background: var(--surface-2);
  color: var(--text-dim);
  cursor: not-allowed;
}
.input[readonly],
.form-stack :is(input, textarea)[readonly],
.chat-form textarea[readonly] {
  background: var(--surface-2);
  border-style: dashed;
}
/* Inline validation error state (#977, #2744). A control is invalid only
   when its projection names that control: the message is the field's
   .field-error line, joined to the control's aria-describedby. A
   form-level error is a role="alert" banner and marks no control. Every
   .field-row sits in a form.form-stack. These element-qualified
   selectors tie the skin's focus rule and sit later in source, so the
   danger edge survives focus. The keyboard ring takes the danger tone too
   (#4636): every refusal focuses its field, and the 2px accent ring would
   otherwise cover the 1px danger edge, so a refused field read as accepted. */
.form-stack input[aria-invalid="true"],
.form-stack select[aria-invalid="true"],
.form-stack textarea[aria-invalid="true"] { border-color: var(--danger); }
.form-stack :is(input, select, textarea)[aria-invalid="true"]:focus-visible {
  outline-color: var(--danger);
}
.btn {
  display: inline-block;
  /* Grid items stretch across their track by default even when their
     display is inline-block. Buttons should hug their label unless a
     component deliberately owns a full-width CTA (for example the
     sidebar and narrow-screen action stacks), so make that default
     shared across every grid-backed action row. */
  justify-self: start;
  max-width: 100%;
  padding: var(--space-2) var(--space-4);
  background: var(--accent);
  color: var(--on-accent);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  font-weight: var(--fw-bold);
  font-size: var(--fs-base);
  cursor: pointer;
  text-decoration: none;
  font-family: inherit;
  /* Background and text switch together so disabled-to-enabled changes never
     pass through an unreadable interpolated pair. The edge keeps the brief
     interaction feedback allowed by the motion contract. */
  transition: border-color 160ms ease;
}
.btn:hover { background: var(--accent); color: var(--on-accent); border-color: var(--text); text-decoration: none; }
.btn.small {
  padding: var(--space-1) var(--space-3);
  font-size: var(--fs-base-sm);
}
.hero-cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3) var(--space-4);
  margin: 0 0 var(--space-4) 0;
}
.btn.secondary {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border-strong);
}
.btn.secondary:hover { background: var(--surface-2); border-color: var(--text-dim); color: var(--text); }
.btn.danger {
  background: transparent;
  color: var(--danger);
  border: 1px solid var(--border-strong);
}
.btn.danger:hover { background: var(--danger-bg); border-color: var(--danger); }
.btn:disabled,
.btn:disabled:hover,
.btn[aria-disabled="true"],
.btn[aria-disabled="true"]:hover {
  background: var(--surface-2);
  color: var(--text-dim);
  border-color: var(--border-strong);
  cursor: not-allowed;
  /* Belt + suspenders (issue #426). The anchor-as-button render
     pattern uses ``<a class="btn" aria-disabled="true" tabindex="-1">``
     with no ``href`` so it can't be clicked or focused. ``pointer-
     events: none`` is a final guard: if a future caller adds an
     ``href`` to "fix" linting, the disabled visual still doesn't
     navigate. */
  pointer-events: none;
}
.pill {
  display: inline-block;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--fs-base-sm);
  font-weight: var(--fw-bold);
  font-family: var(--font-sans);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  /* Long pill text (e.g. "1 active · 1 revoked", "Swing /
     individual-stock trader") used to wrap inside the pill on
     narrow viewports, which made the pill look like a two-line
     bubble and pushed the sibling label onto two lines too.
     Keep pill content atomic; the surrounding ``.tile .row``
     flex-wraps it onto its own line when the row can't fit
     both items. */
  white-space: nowrap;
}
.pill.ok { background: var(--success-bg); color: var(--success); }
.pill.warn { background: var(--warn-bg); color: var(--warn); }
.pill.dim { background: var(--surface-2); color: var(--text-dim); }
/* Meaning-specific, non-status pills (#1569). Trade side, plan identity,
   and a product recommendation are labels, not success or warning
   states, so they deliberately carry no ok/warn glyph. */
.pill.side {
  background: var(--surface-2);
  color: var(--text);
  border: 1px solid var(--border-strong);
  padding: calc(var(--space-1) - 1px) calc(var(--space-2) - 1px);
}
.pill.plan { background: var(--surface-2); color: var(--text-dim); }
.pill.recommended { background: var(--info-bg); color: var(--info); }
/* ``.pill.danger`` (issue #635) — muted-danger status tone so a
   terminal/revoked state reads as *status*, distinct from the
   neutral grey ``.pill.dim`` used for provenance tags (e.g.
   "Auto-connected") that sit beside it. Same 0.12-alpha-fill +
   token-color recipe as ``.ok`` / ``.warn``, which clears WCAG AA on
   both frames: the tokens resolve to --danger over --surface on the
   public pages and the same dark signed-in canvas (#2955). */
.pill.danger { background: var(--danger-bg); color: var(--danger); }
/* ``.pill.info`` (issue #419) — half-state tone for "started, not
   done" rows. Distinct from ``.pill.warn`` ("needs your attention")
   and ``.pill.ok`` ("done"), so a user scanning the setup stepper
   can tell PINNED apart from PENDING at a glance. Cool blue keeps
   the system at three colors plus dim and clears WCAG AA on both
   frames, resolving to --info over --surface on the public pages and
   to --info over the unified signed-in canvas (#2955). */
.pill.info { background: var(--info-bg); color: var(--info); }
/* ``.pill.outline`` (issue #432) — credential row "Not set" status,
   distinct from ``.pill.dim`` ("Disabled" — stored but paused). The
   solid border + no fill reads as "no key here" so a user scanning
   the credentials page can tell stored-paused from nothing-stored
   apart without reading the masked value. */
.pill.outline {
  background: transparent;
  color: var(--text-dim);
  border: 1px solid var(--border-strong);
  /* solid border eats ~2px vs filled background; trim padding to
     keep pill height visually consistent with .ok/.warn/.dim. */
  padding: calc(var(--space-1) - 1px) calc(var(--space-2) - 1px);
}
/* The check-email resend form (#981). Sign-in and sign-up compose a
   form.form-stack field since #2744. */
form.signin { display: flex; flex-direction: column; gap: var(--space-3); max-width: 22rem; }
/* Share the first-paint and resolved form footprint. Longer signup details
   and validation messages remain free to grow without clipping at zoom. */
.auth-card { min-block-size: 20rem; }
/* The edge's sign-in first paint reserves the resolved form's height
   (#4636). At 20rem the footer dropped about 185px when the projection
   arrived, and CLS misses it because the runtime replaces the tree. The
   form is 464-483px from 375px up and 521-536px at 320px, where the notice
   wraps to more lines; each value sits within 12px of its range. The
   root's document id is static shell markup, so no pinned pending markup
   changes. */
[data-browser-document-id="sign-in"] .auth-card:has(> .auth-pending) {
  min-block-size: 29.5rem;
}
@media (max-width: 359px) {
  [data-browser-document-id="sign-in"] .auth-card:has(> .auth-pending) {
    min-block-size: 33rem;
  }
}
/* An auth card's heading and lede read as one unit (#4636): 12px between
   them, inside the card's 24px rhythm between groups. */
.card.auth-card > h1 + .lede {
  margin-block-start: calc(var(--space-3) - var(--space-6));
}
/* The offer of the other form is secondary to this one (#4242): it reads in
   the lede's dim text, and its link keeps the accent. */
.auth-switch { color: var(--text-dim); }
.auth-pending {
  min-block-size: 10rem;
  display: grid;
  align-content: center;
  color: var(--text-dim);
}
.auth-pending p {
  align-items: center;
  display: grid;
  gap: var(--space-4);
  grid-template-columns: var(--space-12) minmax(0, 1fr);
  margin: 0;
}
/* The decorative ledger mark resolves like a compact journal coming into
   focus without implying measurable progress. Its bars grow only inside the
   mark's reserved footprint; status text and surrounding layout stay fixed.
   The shared auth and React loading states remain still when the user requests
   reduced motion. */
.loading-mark {
  border-inline-start: 1px solid var(--border-strong);
  display: grid;
  gap: var(--space-2);
  inline-size: var(--space-12);
  padding-inline-start: var(--space-3);
}
.loading-mark > span {
  background: var(--info);
  block-size: calc(var(--space-1) / 2);
  border-radius: var(--radius-sm);
  display: block;
  transform-origin: left center;
}
.loading-mark-long { inline-size: 100%; }
.loading-mark-medium { inline-size: 75%; }
.loading-mark-short { inline-size: 50%; }
@media (prefers-reduced-motion: no-preference) {
  .loading-mark > span {
    animation: loading-mark-resolve 1.4s ease-in-out infinite;
  }
  /* These selectors deliberately outrank the animation shorthand above. */
  .loading-mark > .loading-mark-medium { animation-delay: -0.35s; }
  .loading-mark > .loading-mark-short { animation-delay: -0.7s; }
}
@keyframes loading-mark-resolve {
  0%, 100% {
    opacity: 0.35;
    transform: scaleX(0.55);
  }
  50% {
    opacity: 1;
    transform: scaleX(1);
  }
}
.signup-assurance {
  max-width: 34rem;
  margin: var(--space-5) 0 0;
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text-dim);
  font-size: var(--fs-base-sm);
  line-height: 1.5;
}
.signup-assurance li + li { margin-top: var(--space-2); }
.signup-assurance strong {
  color: var(--text);
  font-weight: var(--fw-medium);
}
/* Resend affordance on the check-your-email page (#981). The button
   group lays the inbox deep-link and the resend button in one wrapping
   row. The resend button carries its own cooldown countdown (#4636), in
   tabular figures so the label keeps its width from second to second. */
form.signin.resend { gap: var(--space-2); }
.resend-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
}
.resend-actions button { font-variant-numeric: tabular-nums; }
.banner {
  border-left: 3px solid var(--accent);
  background: var(--accent-wash);
  padding: var(--space-3) var(--space-4);
  border-radius: 0 var(--radius) var(--radius) 0;
  margin-bottom: var(--space-6);
  color: var(--text-dim);
}
.banner.warn { background: var(--warn-bg); border-left-color: var(--warn); }
/* A refusal reads at full text strength (#4636): in the shared dim it was
   the quietest line on the card it was refusing. */
.banner.danger { background: var(--danger-bg); border-left-color: var(--danger); color: var(--text); }
/* A form directly inside a banner (the past-due "Update payment"
   button, #177) sits under the message with a small gap. Inline-block
   rather than inline: a vertical margin needs a block-level box to take
   effect. Its button carries the 44px target itself (#4040): the
   dashboard chrome's banner sits outside every route's floor, and
   browser documents load only this stylesheet. */
.banner > form {
  display: inline-block;
  margin-top: var(--space-2);
}
.banner > form > .btn { min-height: var(--control-target); }
.banner-progress {
  display: block;
  margin-top: var(--space-2);
  height: 0.35rem;
  background: var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.banner-progress > span {
  display: block;
  height: 100%;
  background: var(--warn);
  border-radius: inherit;
}
.banner.warn .banner-progress > span { background: var(--warn); }
.footer {
  border-top: 1px solid var(--border);
  margin-top: 4rem; /* 4rem footer top margin = clear separation from page content; --space-12 (3rem) would crowd the disclaimer band */
  padding: var(--space-5) 0;
  color: var(--text-dim);
  font-size: var(--fs-base-sm);
}
.footer-row { display: flex; justify-content: space-between; align-items: center; gap: var(--space-4); }
.footer-nav { display: flex; flex-wrap: wrap; gap: var(--space-4); }
.footer-nav a { color: var(--text-dim); text-decoration: none; }
.footer-nav a:hover { color: var(--text); text-decoration: none; }
/* The fineprint is a plain child of the footer's ``.shell``, below
   ``.footer-row``, so its rule and its text take the column's edges in
   every layout and at every breakpoint (#4321). It has no width or inline
   padding of its own: a separate box drifted off the column the tagline
   sits on. It must not carry the ``.shell`` class itself, because
   ``body.layout-sidebar .shell`` would replace its top margin and padding. */
.footer-fineprint {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
  font-size: var(--fs-base-sm);
  line-height: 1.5;
  color: var(--text-dim);
}
.disclosure-list { margin: var(--space-6) 0; padding: var(--space-4) var(--space-4) var(--space-4) var(--space-8); background: var(--surface-2); border-left: 3px solid var(--border); border-radius: var(--radius); font-size: var(--fs-base-sm); line-height: 1.55; color: var(--text-dim); }
.disclosure-list li { margin: var(--space-1) 0; }
.disclosure-list strong { color: var(--text); font-weight: var(--fw-bold); }
.hero-disclaimer {
  margin: 0;
  font-size: var(--fs-base-sm);
  line-height: 1.5;
  color: var(--text-dim);
}
.hero-disclaimer a { color: var(--text-dim); text-decoration: underline; }
.hero-disclaimer a:hover { color: var(--text); }
/* Tertiary text-link CTA (e.g. paused-signup "Sign in") sitting in the
   .hero-cta flex row beside the .btn pair (#627). Reads as a link, not
   a button, so the single primary stays unambiguous. Padded so the tap
   target clears 44px on touch even though it isn't a .btn. */
.hero-cta-text {
  color: var(--text-dim);
  font-weight: var(--fw-medium);
  text-decoration: underline;
  padding: var(--space-2) 0;
}
.hero-cta-text:hover { color: var(--text); }
/* Hero proof teaser (#818 P1) — lifts one cite chip above the fold so a
   product whose pitch is "sourced, timestamped numbers" shows a sourced
   number in the hero, not only in the third card down the page. Reuses
   the .cite typographic mark from the after-vignette; line-height runs
   loose so the inline chips don't crowd. */
.hero-proof {
  margin: 0 0 var(--space-5);
  font-size: var(--fs-base);
  line-height: 1.7;
  color: var(--text-dim);
}
/* Launch-wedge audience line (#855). It names the swing trader as the
   first audience right under the lede, so a cold visitor knows who the
   product is built for before the proof chip: secondary color, with the
   audience noun promoted to --text. */
.hero-audience {
  margin: 0 0 var(--space-4);
  font-size: var(--fs-base-sm);
  line-height: 1.5;
  color: var(--text-dim);
}
.hero-audience strong { color: var(--text); font-weight: var(--fw-medium); }
/* "Works with" line (#3755). Beside an AI-client action on Home, Pricing
   and sign-up, it names the clients the Named client contract allows, so a
   visitor knows which AI clients work before signing up. The full list sits
   one click away in a how-it-works disclosure, which drops its section
   margin here because the line lives inside a hero, a plan card or the
   sign-up list. */
.ai-clients {
  font-size: var(--fs-base-sm);
  line-height: 1.5;
  color: var(--text-dim);
}
.ai-clients > p { margin: 0; }
.ai-clients > details.how-it-works { margin: var(--space-1) 0 0; }
/* The list's summary reads as a control at rest, in the link accent
   (#4242). Home and sign-up nest the list in .ai-clients; Pricing's Free
   card sets it after the plan action. Other disclosures keep the dim
   summary. */
:is(.ai-clients > details.how-it-works, .tier-cta + details.how-it-works) > summary {
  color: var(--accent);
}
.kv {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--space-2) var(--space-4);
  font-size: var(--fs-base-sm);
  font-variant-numeric: tabular-nums;
}
.kv dt { color: var(--text-dim); }
.kv dd { margin: 0; }
/* FAQ list — question/answer pairs. Desktop: two columns with a
   fixed-width question gutter so the answers wrap on a consistent
   left edge. Mobile: questions stack above answers (see the 640px
   breakpoint) since long questions otherwise crush the answer
   column on a phone. */
.faq { display: grid; grid-template-columns: minmax(0, 16rem) minmax(0, 1fr); gap: var(--space-4) var(--space-6); font-size: var(--fs-base); align-items: baseline; }
.faq dt { color: var(--text); font-weight: var(--fw-bold); line-height: 1.4; }
.faq dd { margin: 0; color: var(--text-dim); line-height: 1.6; }
/* Pricing keeps lower-frequency FAQ answers in one native disclosure.
   .disclosure-summary uses flex layout, which can hide the browser marker,
   so restore an explicit chevron and rotate it with the native open state. */
.pricing-faq-more > summary { list-style: none; }
.pricing-faq-more > summary::-webkit-details-marker { display: none; }
.pricing-faq-more > summary::before {
  content: "▸";
  display: inline-block;
  margin-right: var(--space-2);
}
.pricing-faq-more[open] > summary::before { transform: rotate(90deg); }
.center { text-align: center; }

/* L4 — design-system audit cleanup. The utilities and three
   component classes below replace the bulk of the inline
   ``style=""`` declarations that had accumulated across the
   branded web modules before the H1/H2/M4 token series landed
   (issues #522 / #523 / #527). Per the class-naming guidance at
   the top of this file, a utility earns its keep when it's used
   in two+ unrelated components AND is purely presentational. */
.mt-2 { margin-top: var(--space-2); }
.mt-3 { margin-top: var(--space-3); }
.mt-4 { margin-top: var(--space-4); }
.mt-5 { margin-top: var(--space-5); }
.mt-6 { margin-top: var(--space-6); }
.ml-2 { margin-left: var(--space-2); }

/* Document forms (#1211, #2744): the browser documents' statement of the
   field anatomy in docs/frontend-design-system.md ("Field", "Field
   widths"). One order, always: the label, the control, then an optional
   .field-notes block holding the help and then the field error. The label
   names the control through <label for>, and the help and error join its
   aria-describedby, so its accessible name is the label alone. The
   signed-in .sm-field in frontend/src/spa.css is the same anatomy in the
   route bundle; site.css declares no .sm-field rule and spa.css no
   .field-row rule, so the two never meet.

   Each gap has one owner, and no child adds a margin in the same axis. A
   form.form-stack spaces its fields from its action row (24px),
   .field-group spaces fields (16px), .field-row spaces the label, control
   and notes (8px), and .field-notes spaces the help from the error (4px).
   A bare div.form-stack, the reviewed first-workflow copy box, keeps its
   20px step. */
.form-stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}
form.form-stack { gap: var(--space-6); }
.form-stack > .btn { align-self: flex-start; }
.field-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
/* The single minmax(0, 1fr) track and min-width: 0 let a control shrink
   below its intrinsic width on the 320px floor at 200% text. */
.field-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  gap: var(--space-2);
  min-width: 0;
}
.field-row > .field-label {
  color: var(--text);
  font-size: var(--fs-base-sm);
  font-weight: var(--fw-bold);
  line-height: var(--lh-body);
}
.field-notes {
  display: grid;
  gap: var(--space-1);
}
/* The notes block owns both of its steps, so its lines keep no user-agent
   paragraph margin. */
.field-notes > * { margin: 0; }
.field-help {
  color: var(--text-dim);
  font-size: var(--fs-base-sm);
  line-height: var(--lh-body);
}
.field-error {
  color: var(--danger);
  font-size: var(--fs-base-sm);
  font-weight: var(--fw-medium);
  line-height: var(--lh-body);
}
.form-stack input[type="text"],
.form-stack input[type="datetime-local"],
.form-stack input[type="number"],
.form-stack input[type="email"],
.form-stack input[type="password"],
.form-stack input[type="url"],
.form-stack select {
  width: 100%;
  /* The unclassified fallback, the route bundle's cap. */
  max-width: var(--control-long);
  min-block-size: var(--control-target);
  margin: 0;
  font-family: inherit;
  font-size: var(--fs-base);
  line-height: var(--lh-body);
}
.form-stack textarea {
  width: 100%;
  font-family: var(--font-mono);
  font-size: var(--fs-base-sm);
  line-height: 1.5;
  resize: vertical;
}
/* A classified control width. Only the control takes the maximum; the
   label and notes keep the field's column. This ties the control rule
   above at (0,2,1) and wins on source order alone, so it stays after it. */
.field-row.field-text > :is(input, select, textarea) {
  max-width: var(--control-text);
}
/* A read-only input reads as neither editable nor disabled, as in the
   route bundle: the subdued ground and a dashed edge, with the skin's live
   text color. It ties the skin at (0,2,1) and wins on source order. */
.field-row > input[readonly] {
  background: var(--surface-2);
  border-style: dashed;
}

/* Broker link + Account-Data consent interstitials (#1208). The
   SnapTrade link, consent, and result pages use the clean neutral React
   shell, with no distracting nav on a trust-sensitive consent step. They
   inherit ``.card`` / ``.btn`` /
   ``.form-stack`` / ``.banner`` / ``.muted-note``; these two rules are
   the only markup unique to them: the consent bullet list and the
   affirmative-consent checkbox row. */
.consent-points { margin: 0 0 var(--space-4); padding-left: var(--space-5); }
.consent-points li { margin: var(--space-1) 0; line-height: 1.5; }
.consent-agree {
  display: flex;
  gap: var(--space-2);
  align-items: flex-start;
  margin: var(--space-4) 0;
  line-height: 1.5;
}
.consent-agree input[type="checkbox"] { flex: none; margin: var(--space-1) 0 0; }

/* Data table. Only signed-in route bodies render one today (Scorecard,
   the symbol page, a record's booked reductions and Settings' starter
   packs). Cells stay left-aligned unless numeric. Wrap a table that must
   scroll on a narrow viewport in a labeled, focusable ``.scroll-x``
   region. */
.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-base);
}
.data-table thead tr {
  text-align: left;
  color: var(--text-dim);
  /* Headings sit at --fs-base-sm (14px), below the 16px body they head
     (#986), in sentence case with normal tracking like every other label
     (#2744). */
  font-size: var(--fs-base-sm);
  border-bottom: 1px solid var(--border);
}
.data-table th { padding: var(--space-2); font-weight: var(--fw-medium); }
.data-table td { padding: var(--space-3) var(--space-2); vertical-align: top; }
.data-table th:first-child,
.data-table td:first-child { padding-left: 0; }
.data-table tbody tr { border-bottom: 1px solid var(--border); }
.data-table tbody tr:last-child { border-bottom: none; }

/* Strategy Scorecard (/dashboard/scorecard) — page-specific styling
   for the date/account filter row, the sortable + numeric ``.data-table``
   modifiers, the sample-size badges (P0-7), the "Favorite vs Best"
   insight card (P0-6), and the free-tier teaser (P0-9). These extend
   the shared ``.data-table`` base above; they live here rather than
   inline in ``web/scorecard.py`` so all page CSS stays in this one
   string (see module docstring). */
.data-table th.sortable a {
  color: inherit;
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  text-decoration: none;
}
.data-table th.sortable a:hover { color: var(--accent); text-decoration: none; }
.data-table td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.data-table th.num { text-align: right; }
/* P&L cells read from the semantic --pnl-* tokens, not the brand
   --accent / --danger, so gain/loss *meaning* is decoupled from CTA
   and destructive intent (#982). */
.data-table td .pnl-pos { color: var(--pnl-up); }
.data-table td .pnl-neg { color: var(--pnl-down); }
.win-ci { display: block; color: var(--text-dim); font-size: var(--fs-micro); }
/* Facet rollup (#828): the default scorecard view, one expandable
   disclosure per PRIMARY facet. The summary carries the facet name and
   its distribution headline; expanding reveals the per-leaf table. */
.facet-rollup {
  border-top: 1px solid var(--border);
  padding: var(--space-2) 0;
}
.facet-rollup:first-of-type { border-top: none; }
.facet-rollup > summary {
  cursor: pointer;
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  list-style: none;
}
.facet-rollup > summary::-webkit-details-marker { display: none; }
.facet-rollup > summary::before {
  content: "▸";
  color: var(--text-dim);
}
.facet-rollup[open] > summary::before { content: "▾"; }
.facet-rollup .facet-name { font-weight: 600; }
.facet-rollup .facet-dist { color: var(--text-dim); font-size: 0.9em; }
.facet-rollup .data-table { margin-top: var(--space-2); }
/* The reconcile inbox is a progressive review queue: every trade is a
   compact disclosure row and only the first unresolved item opens on
   render. Its field and action composition lives with the route in the
   SPA stylesheet (#2585 D14). */
.reconcile-task-list {
  border-top: 1px solid var(--border);
  margin-top: var(--space-4);
}
.reconcile-task {
  border-bottom: 1px solid var(--border);
}
.reconcile-task:last-child { border-bottom: none; }
.reconcile-task-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 3rem;
  padding: var(--space-3) var(--space-6) var(--space-3) 0;
  cursor: pointer;
  list-style: none;
  position: relative;
}
.reconcile-task-head::-webkit-details-marker { display: none; }
.reconcile-task-head::after {
  content: "";
  position: absolute;
  right: var(--space-1);
  top: 50%;
  width: var(--space-2);
  height: var(--space-2);
  margin-top: calc(-1 * var(--space-2));
  border-right: 2px solid var(--text-dim);
  border-bottom: 2px solid var(--text-dim);
  transform: rotate(-45deg);
}
.reconcile-task[open] > .reconcile-task-head::after {
  margin-top: calc(-1 * var(--space-1));
  transform: rotate(45deg);
}
.reconcile-task-head:hover::after { border-color: var(--accent); }
.reconcile-task-trade { min-width: 0; }
.reconcile-task-needs {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2);
  flex-wrap: wrap;
  margin-left: auto;
}
.reconcile-task-needs-label {
  color: var(--text-dim);
  font-size: var(--fs-base-sm);
}
@media (max-width: 640px) {
  .reconcile-task-head {
    align-items: flex-start;
    flex-direction: column;
  }
  .reconcile-task-needs {
    justify-content: flex-start;
    margin-left: 0;
  }
  .reconcile-dismiss {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
}
.helper-prompt-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: var(--space-3);
}
@media (max-width: 640px) {
  .helper-prompt-actions .btn { width: 100%; }
}
/* "No read on this one" (#1410). A quiet text-link affordance, not a
   button: dismissing is the secondary path out of the row and must not
   compete with Save. Matches .reconcile-note-toggle > summary. */
.reconcile-dismiss {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font-family: inherit;
  font-size: var(--fs-base-sm);
  color: var(--text-dim);
}
.reconcile-dismiss:hover { color: var(--accent); }
/* Close-note disclosure inside each untagged row (#731): the optional
   close note is hidden behind a quiet text-link summary so the default
   row reads as one tidy line; the field reveals on demand. */
.reconcile-note-toggle > summary {
  cursor: pointer;
  list-style: none;
  font-size: var(--fs-base-sm);
  color: var(--text-dim);
}
.reconcile-note-toggle > summary::-webkit-details-marker { display: none; }
.reconcile-note-toggle > summary:hover { color: var(--accent); }
.reconcile-note-toggle[open] > summary { margin-bottom: var(--space-2); }
.reconcile-note-toggle > *:not(summary) { margin-top: var(--space-2); }
/* Linked-trades history disclosure (#600): the whole "Linked trades"
   section collapses by default so the inbox leads with the actionable
   worklists. The summary carries the section heading and reads like the
   card's other <h2> headings, with a disclosure affordance. Sits in a
   .card. The unlinked-closes disclosure (#1406) shares the shape: an
   informational section that must not compete with the action queues. */
.reconcile-linked-disclosure > summary,
.reconcile-unlinked-disclosure > summary {
  cursor: pointer;
  list-style: none;
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  line-height: var(--lh-heading);
  color: var(--text);
  padding-right: var(--space-5);
  position: relative;
}
.reconcile-linked-disclosure > summary::-webkit-details-marker,
.reconcile-unlinked-disclosure > summary::-webkit-details-marker { display: none; }
.reconcile-linked-disclosure > summary::after,
.reconcile-unlinked-disclosure > summary::after {
  content: "";
  position: absolute;
  right: 0.25rem;
  top: 50%;
  width: 0.5rem;
  height: 0.5rem;
  margin-top: -0.35rem;
  border-right: 2px solid var(--text-dim);
  border-bottom: 2px solid var(--text-dim);
  transform: rotate(-45deg);
}
.reconcile-linked-disclosure[open] > summary::after,
.reconcile-unlinked-disclosure[open] > summary::after {
  margin-top: -0.15rem;
  transform: rotate(45deg);
}
.reconcile-linked-disclosure > summary:hover::after,
.reconcile-unlinked-disclosure > summary:hover::after { border-color: var(--accent); }
.reconcile-linked-disclosure[open] > summary,
.reconcile-unlinked-disclosure[open] > summary { margin-bottom: var(--space-4); }
/* Shared Journal page identity and symbol links, also used by the React
   route bodies. Keep these base styles alongside the shared shell. */
.journal-page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4) var(--space-6);
  margin-bottom: var(--space-4);
}
.journal-page-header .lede { margin-bottom: 0; }
.journal-symbol-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  text-decoration: none;
}
@media (max-width: 640px) {
  .journal-page-header {
    flex-direction: column;
    align-items: stretch;
  }
  .journal-symbol-link { min-height: 2.75rem; }
}
/* Filter disclosure (#625): filters sit below the headline numbers and
   stay collapsed until reached for. Open by default when a non-default
   filter is active so the applied scope stays visible. */
.scorecard-filters-disclosure { margin-bottom: var(--space-4); }
.insight-card {
  border: 1px solid var(--accent);
  /* Inset/recessed callout: the insight card uses the canvas inside a
     working panel and an accent edge instead of elevation. */
  border-radius: var(--radius);
  background: var(--bg);
  padding: var(--space-5) var(--space-5);
}
/* Page-level scorecard disclaimer (#388 / #840): a muted past-performance
   + not-advice note under the real card, free or Pro. */
.scorecard-disclaimer {
  margin-top: var(--space-4);
  font-size: var(--fs-micro);
}

/* Read-only code / JSON snapshot block. Pre + monospace +
   scrollable surface for verbatim text the analyst recorded
   (notes appended to a journal entry; intent-params / rule_refs
   captured at fill time; rendered skill Markdown). The
   ``.snapshot-note`` helper renders the explanatory caption
   above a ``.code-block`` (e.g. "Snapshot at record time"). */
.code-block {
  background: var(--surface-2);
  padding: var(--space-3);
  border-radius: var(--radius);
  max-height: 24rem;
  overflow: auto;
  white-space: pre-wrap;
  font-size: var(--fs-base-sm);
  font-family: var(--font-mono);
  line-height: 1.5;
  margin: 0;
}
.snapshot-note {
  color: var(--text-dim);
  font-size: var(--fs-base-sm);
  margin: 0 0 0.5rem 0;
}
.record-snapshot {
  margin-top: var(--space-3);
}
.record-snapshot > summary {
  cursor: pointer;
  list-style: none;
  font-weight: var(--fw-medium);
  color: var(--text-dim);
}
.record-snapshot > summary::-webkit-details-marker { display: none; }
.record-snapshot > summary::before {
  content: "▸";
  display: inline-block;
  margin-right: var(--space-2);
}
.record-snapshot[open] > summary::before { transform: rotate(90deg); }
.record-snapshot > summary:hover { color: var(--accent); }
.record-snapshot > *:not(summary) { margin-top: var(--space-2); }
/* Disclosure-summary styling for the recurring "open the
   advanced editor" pattern used by connected-apps, credentials,
   setup, and onboarding. ``-aside`` is the parenthetical hint
   after the summary text. */
.disclosure-summary {
  display: flex;
  align-items: center;
  min-height: 44px;
  cursor: pointer;
  font-size: var(--fs-base);
  font-weight: var(--fw-bold);
  color: var(--text);
}
.disclosure-summary-aside {
  font-weight: var(--fw-regular);
  margin-left: var(--space-2);
  font-size: var(--fs-base-sm);
}
/* "Label + copyable value + copy button" row pattern used by the
   credentials-shown-once success page in connected-apps. The
   value span flexes to 18rem so the copy button sits beside it
   on desktop and wraps below it on phones. */
.copy-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  word-break: break-all;
}
.copy-row > .value { flex: 1 1 18rem; }
/* Last-resort copy target. The shared handler reveals this read-only
   textarea only after both clipboard writes fail and a copy button has
   no visible .copy-row value to select. It spans its container so long
   commands and multi-line snippets remain readable and selectable. */
.copy-fallback-value {
  flex: 1 1 100%;
  width: 100%;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-base);
  line-height: 1.5;
  resize: vertical;
}
/* A copy-row carrying a sentence rather than an identifier (#1462:
   the first question the setup funnel and the connect walkthroughs
   hand over). ``break-all`` above is right for a URL or a CLI command
   and wrong for prose, which it snaps mid-word ("how does the chart
   read int / o it today?"). */
.copy-row.prose { word-break: normal; overflow-wrap: break-word; }
.copy-row.tinted {
  background: var(--surface-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius);
}
/* Unstyled list inside a ``<dl><dd>`` — kills the default
   margin / list-style so a short bullet list of redirect URLs
   sits flush against the term. */
.flush-list { margin: 0; padding-left: var(--space-4); }

/* Sit a paragraph or heading flush — the wrapping ``.copy-row``
   already supplies its own spacing, so the inner element should
   not add a default block margin. */
.flush { margin: 0; }
/* Tinted code snippet pre — onboarding's "paste this into your
   AI client's config" block. Same surface tint as
   ``.endpoint-display`` but pre-wraps preserved verbatim
   (whitespace:pre) and a horizontal scrollbar for long lines. */
.snippet-block {
  background: var(--surface-2);
  padding: var(--space-3);
  border-radius: var(--radius);
  overflow-x: auto;
  margin: var(--space-3) 0 0;
  white-space: pre;
}
.install-hint { font-size: var(--fs-base); }
/* The waitlist form on the landing-notify document and the reviewed
   campaign home variants (#2744): a form.form-stack, like the sign-in and
   reviewer forms, with one text-width email field. Only its distance from
   the lede above it is local. */
.notify-me-form { margin-top: var(--space-4); }

.disclosure-summary.plain {
  cursor: pointer;
  font-size: inherit;
  color: inherit;
  font-weight: var(--fw-bold);
}
/* The paid first-workflow renderer is scoped under .setup-page. The Free
   first-value journey reuses the generic setup-stepper classes and keeps its
   separate compact milestone treatment. */
.setup-page { min-width: 0; }

/* Detail-page reference key: the raw kebab-case slug shown mono
   directly under the humanized <h1>, mirroring the catalog row so a
   power user can still cite the id (#1349). */
.rule-slug {
  margin: var(--space-1) 0 var(--space-3) 0;
  font-size: var(--fs-base-sm);
  color: var(--text-dim);
}

/* ===========================================================
   Landing-interstitial (per-AI-client "not wired up yet" page)
   =========================================================== */
.interstitial-aside-base {
  margin-top: var(--space-2);
  font-size: var(--fs-base);
}

/* ===========================================================
   OAuth consent screen (/oauth/authorize)
   =========================================================== */
.oauth-client-logo {
  width: 48px;
  height: 48px;
  border-radius: 8px;
  background: var(--surface-2);
  object-fit: contain;
}
.oauth-client-header {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}
.oauth-client-header > div { min-width: 0; overflow-wrap: anywhere; }
.oauth-client-subhead { font-size: var(--fs-base-sm); }
.oauth-scopes-heading {
  font-size: var(--fs-base);
  margin-top: var(--space-6);
}
.oauth-scopes-list {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--space-6);
}
.oauth-scopes-note { font-size: var(--fs-base-sm); }
.oauth-decision-form {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-4);
}
.oauth-scope-desc { font-size: var(--fs-base-sm); }
.oauth-scope-row {
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--border);
}

/* PS6: one bounded task per first-party form, decision, or result. These
   widths are reading columns, not additional themes or route capabilities. */
.card.document-task {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  gap: var(--space-6);
  max-width: 36rem;
  margin-inline: auto;
  padding: var(--space-8);
  border: 0;
  border-radius: var(--radius-lg);
  overflow-wrap: anywhere;
}
.card.document-task > *,
.card.document-task > .muted-note { margin-block: 0; }
.card.document-task > :is(p, ul) { line-height: var(--lh-prose); }
/* Controls read at --lh-body. A native button otherwise keeps the UA's
   `normal`, so on a phone a link button stood 50px beside a 46px button
   in one row (#4636). */
.document-task .btn {
  min-block-size: var(--control-target);
  line-height: var(--lh-body);
}
.card.auth-card,
.card.notify-card { max-width: 28rem; }
.card.oauth-card { max-width: 42rem; }
.card.consent-card { max-width: 46rem; }
/* Free sign-up's Next line is its button's caption (#4242), so it sits 8px
   below the form instead of the card's 24px gap. */
.card.document-task > .signup-next {
  margin-block-start: calc(var(--space-2) - var(--space-6));
}
/* An auth card's lede wraps without a lone last word, which the short Free
   sign-up lede left at phone widths (#4635). */
.card.auth-card > .lede { text-wrap: pretty; }
/* Counsel's sign-in wrap (#4319) sits directly above the button it names,
   12px from it instead of the form's 24px gap, in body text. It sits in
   the form, out of reach of the card's prose rule, so it takes the lede's
   leading here (#4635). */
form.form-stack > .signin-terms-notice {
  margin-block: 0 calc(var(--space-3) - var(--space-6));
  line-height: var(--lh-prose);
}
body.layout-sidebar .document-task { margin-inline: 0; }
/* A pending or refused OAuth projection has no verified sidebar. Its neutral
   frame must not reserve the rail gutter from the static document body. */
body.layout-sidebar .document-frame main,
body.layout-sidebar .document-frame .footer { margin-left: 0; }
body.layout-sidebar .document-frame .shell { max-width: 56rem; }
body.layout-sidebar .document-frame .document-task { margin-inline: auto; }
.document-task .signup-assurance {
  background: transparent;
  border: 0;
  border-top: 1px solid var(--border);
  border-radius: 0;
  padding: var(--space-4) 0 0 var(--space-5);
}
.document-task .oauth-scopes-list { margin-top: calc(-1 * var(--space-3)); }
.document-task .oauth-client-header { align-items: flex-start; }
.document-task .oauth-client-logo { flex: none; }
.document-task .oauth-scope-row {
  display: grid;
  gap: var(--space-1);
  padding-block: var(--space-3);
}
.document-task .consent-points {
  display: grid;
  gap: var(--space-4);
  padding-left: var(--space-6);
  border-left: 1px solid var(--border);
}
.document-task .consent-points li {
  margin: 0;
  line-height: var(--lh-prose);
}
.document-consent-form {
  display: grid;
  gap: var(--space-4);
  justify-items: start;
}
.document-consent-form .consent-agree {
  margin: 0;
  min-height: var(--control-target);
  line-height: var(--lh-prose);
}
.document-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}
.document-status-code {
  color: var(--text-dim);
  font-size: var(--fs-base-sm);
  font-variant-numeric: tabular-nums;
}
@media (max-width: 640px) {
  .card.document-task,
  body.layout-sidebar .card.document-task { padding: var(--space-6); }
  .document-task h1 { font-size: var(--fs-h1-mobile); }
}

/* Sign-up's assurance list marks each line with the accent check the
   Pricing plan card uses for the same claims (#4635), silent to assistive
   technology. The two auth documents' decorative scene, lit card rim and
   arrival retired under #4330 (#4344), so their card is the flat
   .card.document-task the other browser documents use. */
.document-task .signup-assurance {
  list-style: none;
  padding-inline-start: 0;
}
.document-task .signup-assurance li {
  position: relative;
  padding-inline-start: var(--space-6);
}
.document-task .signup-assurance li::before {
  /* The plain check first: Firefox before 128 and Safari before 17.4 drop
     a content value with alt text, and would draw no marker. */
  content: "✓";
  content: "✓" / "";
  position: absolute;
  inset-inline-start: var(--space-1);
  color: var(--accent);
  font-weight: var(--fw-bold);
}
/* The named-client bullet keeps the list's leading, not the shared
   .ai-clients line's (#4635), and its disclosure summary is a full 24px
   target. Home and Pricing keep theirs. */
.document-task .signup-assurance > li.ai-clients { line-height: inherit; }
.document-task .signup-assurance .ai-clients > details.how-it-works > summary {
  display: flex;
  align-items: center;
  min-block-size: var(--space-6);
}

/* Status banner used by dashboard POST-redirect-GET surfaces (e.g. the
   reconcile inbox) — a bordered card-ish strip reporting the result of
   the last POST. The ``.flash-ok`` color above tints the success
   variant; the error variant borrows the danger accent. */
.flash {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--space-2) var(--space-3);
  margin: 0 0 var(--space-4);
  font-size: var(--fs-base-sm);
}
.flash.flash-error { color: var(--danger); border-color: var(--danger); }
.data-table em.col-empty { opacity: 0.7; }

/* Account-profile editor — full-width section under the tile grid.
   The briefing and per-account forms are stacks of labelled inputs /
   textareas, mirroring the credentials row styling but with multiline
   support. Each per-account form sits in its own native disclosure so the
   account list stays scannable without hiding controls from no-JS users. */
.profile { display: flex; flex-direction: column; gap: var(--space-5); }
.profile .blurb {
  margin: 0;
  color: var(--text-dim);
  font-size: var(--fs-base-sm);
}

/* Before/after vignette — the contrast block on the landing page.
   Two side-by-side panels (vanilla AI vs. AI + Slatemark) with the
   "after" panel accent-tinted so the reader's eye lands there. The
   `.vignette-question` row above the grid carries the prompt being
   compared. Falls back to a single column under the .tile-grid
   breakpoint so phones stack cleanly. */
.vignette-question {
  font-family: var(--font-mono);
  font-size: var(--fs-base);
  color: var(--text);
  padding: var(--space-3) var(--space-4);
  background: var(--surface-2);
  border-left: 3px solid var(--text-dim);
  border-radius: 0 var(--radius) var(--radius) 0;
  margin: 0 0 var(--space-4);
}
.vignette-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
  gap: var(--space-4);
}
/* Retained vignette component. PS4 and PS5 own their public compositions;
   examples use a flat reading sequence rather than this panel. */
.vignette {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
/* Before panel: neutral left border + dim label (intentionally
   NOT --danger). Coloring vanilla AI as "danger" framed it as a
   competitor failure rather than a typical baseline; neutral
   reads as "this is what an AI without Slatemark says" without the
   comparative loaded coding. Also dodges the red/green a11y
   trap — deuteranopia / protanopia compress red/green contrast,
   so the text labels carry the meaning instead. */
.vignette.before {
  border-left: 3px solid var(--border);
}
.vignette.after {
  border-left: 3px solid var(--accent);
  background: var(--accent-wash);
}
.vignette-label {
  font-size: var(--fs-base-sm);
  font-weight: var(--fw-bold);
  color: var(--text-dim);
}
.vignette.after .vignette-label { color: var(--accent); }
.vignette-quote {
  margin: 0;
  font-size: var(--fs-base);
  line-height: 1.55;
  color: var(--text);
}
.vignette-meta {
  margin: 0;
  font-size: var(--fs-base-sm);
  color: var(--text-dim);
  border-top: 1px solid var(--border);
  padding-top: var(--space-3);
}
/* Citation chips inside the after-vignette quote. Each chip pairs a
   value (tabular-nums monospace, accent left bar) with a small
   source label so the analyst output reads as sourced, not
   invented. That contrast is the visual punchline opposite the
   prose-only "before" panel. No background fill: the chip is a
   *typographic* mark, not a pill, so the surrounding prose still
   reads as prose. Value and source may wrap inside a narrow column; keeping
   them in one element preserves their association at enlarged text sizes. */
.cite {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-1);
  padding-left: var(--space-1);
  border-left: 2px solid var(--accent);
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--text);
  white-space: normal;
  overflow-wrap: anywhere;
  max-width: 100%;
  flex-wrap: wrap;
}
.cite .cite-src { white-space: normal; }
.cite-src {
  font-family: var(--font-sans);
  font-size: var(--fs-micro);
  color: var(--text-dim);
  font-weight: var(--fw-medium);
  letter-spacing: 0;
}
/* In the segmented after-vignette the chip value carries the punchline
   ("every number is sourced"), so bold the value while the source label
   stays medium (#818 P2). Scoped to .vignette.after so the inline chips
   elsewhere keep their lighter typographic-mark weight. */
.vignette.after .cite { font-weight: var(--fw-bold); }
.vignette.after .cite-src { font-weight: var(--fw-medium); }

/* Compact numbered paths shared by the homepage's record loop and the
   setup value preview. The accent is reserved for the step index only,
   keeping the single-green discipline intact. */
.step-strip {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-4);
  align-items: stretch;
}
.step {
  flex: 1 1 14rem;
  min-width: 0;
  max-width: 100%;
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-5);
}
.step-num {
  flex: none;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: var(--fw-bold);
  font-size: var(--fs-md);
  line-height: 1.2;
  color: var(--accent);
}
.step-body { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; overflow-wrap: anywhere; }
.step-title { font-weight: var(--fw-bold); color: var(--text); }
.step-detail {
  margin: 0;
  font-size: var(--fs-base-sm);
  line-height: 1.5;
  color: var(--text-dim);
}
/* Four setup beats read as a deliberate 2 × 2 sequence. The generic
   flex strip lets a fourth item stretch across the whole second row,
   which overstates that beat and makes the sequence look accidental. */

/* A one-sentence deployment caveat should not consume a full card
   (#1562 D15). Keep the canonical Availability copy in its established
   pre-close position, but render it as a compact labelled note. */
.availability-note {
  margin: 0 0 var(--space-4);
  padding-left: var(--space-3);
  border-left: 2px solid var(--border-strong);
  color: var(--text-dim);
  font-size: var(--fs-base-sm);
}
.availability-note strong { color: var(--text); }

.hero-proof .cite,
.vignette-quote .cite { margin: 0 0.15em; }

/* Pricing tiers — same shape as .tile but with a price line and a
   feature list inside. The "featured" tier (Plus) is the page's focal
   point: it carries a multi-signal treatment (a "Recommended" badge,
   accent border, raised wash, and a soft shadow lift) so the eye lands
   there first. Color alone never carries the featured state — issue
   #819 found the old hue-only differentiation was invisible on the
   dark surface and undetectable to low-vision / colorblind users; the
   text badge fixes the design and the a11y gap at once. Tier cards
   stack on mobile. */
.tier-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
  gap: var(--space-4);
  margin-bottom: var(--space-6);
  /* Vertical room for the badge that overhangs the featured card's
     top edge (it's translated up by half its own height). */
  padding-top: var(--space-3);
}
/* Shared-baseline tier rows (#1300 P0). The two asks must sit on one
   eyeline, so each card is a row subgrid over the parent grid: six
   rows — name / price / tagline / CTA / risk reversal / features — each
   sized to the tallest card, which pins the Free and Plus CTAs to the
   exact same y. Free's fifth row holds only the one-line "See all AI
   clients" disclosure (#3755), shorter than the Plus cancellation and
   retention note, so both feature lists begin below that note.
   The card order puts the CTA *above* the feature list (price ->
   ask -> evidence), so the ~250px void that #819 hit (bottom-anchored
   CTA under Free's much shorter bullet list, via stretch +
   margin-top:auto) can't reopen: the only slack row is the trailing
   feature list, where extra space reads as list whitespace, not a
   detached button. Browsers without subgrid drop the
   grid-template-rows declaration and fall back to a per-card grid —
   same visual order, CTAs a few px apart at worst. The codebase
   already leans on subgrid (.catalog-row). */
.tier {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--space-6) var(--space-6) var(--space-5);
  display: grid;
  grid-template-rows: subgrid;
  grid-row: span 6;
  align-content: start;
  gap: var(--space-3);
}
.tier.featured {
  position: relative;
  border: 1px solid var(--accent);
  background: var(--accent-wash-strong);
}
/* Featured-tier "Recommended" pill — solid accent with the same dark
   --on-accent text the filled .btn uses (AA-passing on accent green).
   Overhangs the card's top edge so it reads as a ribbon, not a list
   item. */
.tier-badge {
  position: absolute;
  top: 0;
  right: var(--space-5);
  transform: translateY(-50%);
  background: var(--accent);
  color: var(--on-accent);
  font-size: var(--fs-micro);
  font-weight: var(--fw-bold);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-sm);
  white-space: nowrap;
}
.tier-name {
  /* Plan names keep their authored title case and use the marketing
     subheading step instead of the compact label role. */
  font-size: var(--fs-base);
  font-weight: var(--fw-bold);
  color: var(--text);
}
.tier.featured .tier-name { color: var(--accent); }
.tier-price {
  font-family: var(--font-mono);
  font-size: var(--fs-2xl);
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum", "zero";
  color: var(--text);
  line-height: 1.1;
  letter-spacing: -0.01em;
  margin: 0;
}
.tier-price .per { font-size: var(--fs-base-sm); color: var(--text-dim); font-weight: var(--fw-regular); }
.tier-tagline {
  font-size: var(--fs-base);
  color: var(--text-dim);
  margin: 0;
}
.tier > .muted-note {
  grid-row: 5;
  margin: 0;
}
.tier-features {
  grid-row: 6;
  list-style: none;
  padding: 0;
  margin: var(--space-2) 0 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  font-size: var(--fs-base-sm);
}
.tier-features li {
  display: flex;
  gap: var(--space-2);
  color: var(--text);
}
.tier-features li::before {
  content: "✓";
  color: var(--accent);
  font-weight: 700;
  flex-shrink: 0;
}
.tier-features li.muted { color: var(--text-dim); }
.tier-features li.muted::before { color: var(--text-dim); content: "·"; }
/* The CTA is row 4 of the tier subgrid (see .tier above), directly
   under the tagline — no bottom-anchoring auto margin, which is what
   opened the #819 void when the rows were a flex column. */
.tier-cta { padding-top: var(--space-2); }
/* The pricing CTA is the page's primary conversion target, so give it
   a roomier touch target than the default .btn (#819): taller vertical
   padding and full card width so it's an easy tap on mobile. */
.tier-cta .btn {
  display: block;
  text-align: center;
  padding-top: var(--space-3);
  padding-bottom: var(--space-3);
}

/* Horizontal-scroll wrapper for wide tables that can't shrink to a
   phone viewport without losing meaning (catalogs of credentials,
   skills, etc.). Pair with a `min-width` on the inner table so the
   columns keep usable width when the wrapper scrolls. */
.scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.scroll-x > table { min-width: 32rem; }

/* A documentary excerpt, using the journal's label/value grammar. The
   example carries no live data, interactive controls or model conclusion. */
.journal-preview-title { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.journal-preview-facts { display: grid; grid-template-columns: minmax(0, 9rem) minmax(0, 1fr); gap: var(--space-3) var(--space-4); }
.journal-preview-facts dt { color: var(--text-dim); }
.journal-preview-facts dd { margin: 0; overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }
.journal-preview { container: journal-preview / inline-size; }
@container journal-preview (max-width: 28rem) {
  .journal-preview-facts { grid-template-columns: minmax(0, 1fr); gap: var(--space-1); }
  .journal-preview-facts dt { margin-top: var(--space-3); }
}

/* Mobile breakpoint. Phones land here (~iPhone 13/14 logical width
   is 390px; the small Plus/Mini sizes are 320–375). The desktop
   layout assumes ~700px+ before the public topbar fits its brand,
   navigation, and account action on one row, so anything narrower
   needs to stack. */
@media (max-width: 640px) {
  .topbar {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
  }
  .topbar-right {
    width: 100%;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-3);
    justify-content: flex-start;
  }
  .topbar nav { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-3); }
  /* Touch-target bump (#627, WCAG 2.5.5 / Apple HIG ≥44px): the public
     top-nav links (Features / Pricing / Sign in)
     are bare text on desktop; on phones they need vertical padding so
     the tap target clears 44px. 14px text × 1.5 line-height + 12px × 2
     padding ≈ 45px. */
  .topbar nav a:not(.btn) { margin-left: 0; font-size: var(--fs-base-sm); display: inline-block; padding: var(--space-3) 0; }
  .shell { padding: 0 var(--space-4); }
  main { padding: var(--space-6) 0 var(--space-12); }
  /* Mobile rescales: h1 stays distinctly larger than body, h2 stays
     larger than body, lede stays heavier than body via line-height
     even when sizes converge. Don't drop h2 to 1rem — collapses
     against body and the hierarchy disappears. */
  h1 { font-size: var(--fs-h1-mobile); }
  h2 { font-size: var(--fs-md); }
  p.lede { font-size: var(--fs-base); margin-bottom: var(--space-5); }
  .card { padding: var(--space-4); }
  .tile { padding: var(--space-4); }
  .tile-grid { gap: var(--space-3); }
  /* Touch-target bumps (issue #426). Apple HIG / WCAG 2.5.5 both
     ask for ≥44px on touchable targets. Desktop padding is fine
     for pointer; on phones the same controls need to be thumb-sized.
     ``.nav-item`` and ``.btn`` are the two surfaces the dashboard
     leans on most heavily. A rail row takes its bump on the block axis
     only, so each outline stays level with the wordmark (#4322). */
  .nav-item { padding-block: var(--space-3); }
  .btn { padding: var(--space-3) var(--space-4); }
  .btn.secondary { padding: var(--space-3) var(--space-4); }
  /* ``.btn.small`` (e.g. the reconcile inbox tag/link/unlink actions,
     #731/#600) stays compact on desktop but needs the same ≥44px tap
     target on touch — bump min-height + padding inside the media query
     only so desktop is untouched. */
  .btn.small {
    min-height: 44px;
    padding: var(--space-2) var(--space-4);
  }
  /* Hamburger nudge: 2rem (32px) on desktop is fine for pointer
     but undersized for touch — bump to 2.75rem (44px) on mobile. */
  .hamburger { width: 2.75rem; height: 2.75rem; }
  .footer-row { flex-wrap: wrap; }
  /* The footer links run beyond one phone-width row — the lone
     horizontal-overflow source at phone widths (pre-existing;
     spotted during the #1300 mobile pass). Let the row wrap. */
  .faq { grid-template-columns: 1fr; gap: var(--space-1) 0; }
  .faq dt { font-size: var(--fs-base); margin-top: var(--space-3); }
  .faq dt:first-of-type { margin-top: 0; }
  .faq dd { padding-bottom: var(--space-1); border-bottom: 1px solid var(--border); }
  .faq dd:last-of-type { border-bottom: 0; padding-bottom: 0; }
}

/* A signed-in marketing page loses 14rem to the sidebar and 2rem more to shell/card
   padding. Stack its FAQs until they have the same room as the public 640px
   breakpoint; otherwise the fixed question gutter crushes the answer column. */
@media (min-width: 641px) and (max-width: 896px) {
  body.layout-sidebar.layout-marketing .faq { grid-template-columns: 1fr; gap: var(--space-1) 0; }
  body.layout-sidebar.layout-marketing .faq dt { font-size: var(--fs-base); margin-top: var(--space-3); }
  body.layout-sidebar.layout-marketing .faq dt:first-of-type { margin-top: 0; }
  body.layout-sidebar.layout-marketing .faq dd { padding-bottom: var(--space-1); border-bottom: 1px solid var(--border); }
  body.layout-sidebar.layout-marketing .faq dd:last-of-type { border-bottom: 0; padding-bottom: 0; }
}

/* The header itself supplies the available inline size. Container-query rem
   units follow enlarged text, unlike viewport media-query rem units. The same
   native disclosure becomes an inline navigation row only when its text fits.
   Its padding puts the brand and the last action on the public frame's edges
   on every public page (#4218); the 100% is the page width, which, unlike
   100vw, leaves out a classic scrollbar. */
.topbar.collapsible {
  container: public-header / inline-size;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-start;
  gap: var(--space-2) var(--space-3);
  padding-inline: max(var(--public-gutter), (100% - var(--public-frame)) / 2);
}
.topbar.collapsible .brand { margin-right: auto; }
.topbar.collapsible .topbar-right,
.topbar.collapsible .public-menu,
.topbar.collapsible .public-menu::details-content { display: contents; }
.topbar.collapsible .hamburger {
  display: inline-flex;
  order: 2;
  width: 2.75rem;
  height: 2.75rem;
  flex: none;
}
.topbar.collapsible nav { display: none; }
.topbar.collapsible .public-menu[open] > nav {
  display: flex;
  flex-direction: column;
  gap: 0;
  order: 10;
  flex-basis: 100%;
}
.topbar.collapsible nav a:not(.btn) {
  margin-left: 0;
  padding: var(--space-3) 0;
}
/* The open menu ends on the CTA at the body button's touch size. */
.topbar.collapsible nav .nav-cta {
  align-self: flex-start;
  margin-block: var(--space-2);
  padding: var(--space-3) var(--space-4);
  font-size: var(--fs-base);
  white-space: normal;
}
/* Large text on a narrow phone (#2744). The mark and the wordmark need
   about 9rem in one line, and 200% text on a 320px phone leaves 8rem
   inside the header's padding. The decorative mark drops once that row is
   9.5rem or narrower (the 9rem plus slack), so the wordmark stays whole;
   the mark is alt="" and aria-hidden, so no accessible name changes. The
   neutral header is a query container for this alone. The signed-in
   mobile topbar keeps its own threshold above, because its row also holds
   the menu control. */
.topbar:not(.collapsible):not(.mobile-only) { container: neutral-header / inline-size; }
@container neutral-header (max-width: 9.5rem) {
  .topbar:not(.collapsible):not(.mobile-only) .brand-mark { display: none; }
}
@container public-header (max-width: 9.5rem) {
  .topbar.collapsible .brand-mark { display: none; }
}
@container public-header (min-width: 43.75rem) {
  @supports selector(::details-content) {
    .topbar.collapsible .hamburger { display: none; }
    .topbar.collapsible .public-menu::details-content {
      content-visibility: visible;
    }
    .topbar.collapsible .public-menu > nav,
    .topbar.collapsible .public-menu[open] > nav {
      display: flex;
      flex-direction: row;
      flex-basis: auto;
      align-items: center;
      gap: var(--space-4);
      order: 0;
    }
    .topbar.collapsible nav a:not(.btn) { padding: 0; }
    .topbar.collapsible nav .nav-cta {
      margin-block: 0;
      padding: var(--space-1) var(--space-3);
      font-size: var(--fs-base-sm);
      white-space: nowrap;
    }
  }
}

.card .actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-3);
}
fieldset {
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
  margin: 0 0 var(--space-4);
  min-width: 0;
}
/* Radio-card pickers use fieldset for semantics, not panel chrome. */
legend {
  padding: 0 var(--space-2);
  font-weight: var(--fw-bold);
  font-size: var(--fs-base-sm);
  color: var(--text);
}
input[readonly], textarea[readonly] {
  background: var(--surface);
  color: var(--text-dim);
  cursor: text;
}

/* Base h3/h4 scale (#1395 WS7). Only h1/h2 had element rules; bare
   <h3>/<h4> outside .tile fell to the UA's 700-weight defaults the
   h1/h2 comments explicitly avoid. */
h3 {
  font-size: var(--fs-base);
  font-weight: var(--fw-bold);
  line-height: var(--lh-heading);
  margin: 0 0 var(--space-2);
}
h4 {
  font-size: var(--fs-base);
  font-weight: var(--fw-bold);
  line-height: var(--lh-heading);
  margin: 0 0 var(--space-2);
}

/* Filled pills stay text-first: their visible status label (or signed P&L
   value) carries meaning without a generated symbol prefix. Semantic color
   supports scanning, while forced-colors mode below restores a boundary when
   alpha fills disappear. */

/* Labelled horizontal-scroll regions (#1395 WS7). Call sites add
   tabindex="0" + role="region" + a name so keyboard users can scroll
   and AT users know what the region holds; the focus ring marks the
   scrollable surface. */
.scroll-x:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Forced-colors (Windows High Contrast) baseline (#1395 WS7). The
   alpha-fill pills, checkbox-driven drawer, and accent focus ring
   otherwise lose their boundaries when the UA strips backgrounds. */
@media (forced-colors: active) {
  .pill { border: 1px solid CanvasText; }
  .btn { border: 1px solid ButtonText; }
  .banner { border: 1px solid CanvasText; }
  .nav-item[aria-current],
  .context-nav a[aria-current],
  .topbar nav a[aria-current="page"] { outline: 2px solid Highlight; }
  .banner-progress > span { background: Highlight; }
}

/* Reduced-motion escape hatch (WCAG 2.3.3, issue #533). The brief scrim
   opacity and control border-colour feedback stop for users who set the
   OS-level preference; the loading resolve runs only with no-preference. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto !important; }
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
}

/* Embedded chat surface (epic #638, Phase 1). Kept deliberately
   plain: the demo's job is to show the analyst frame, not to be a
   polished product chat. Radii are tokens (#1206), not literals, even
   though this gated-off surface is not a full skin member. */
.chat { max-width: 760px; margin: 0 auto; }
.chat-banner {
  background: var(--accent-bg);
  border: 1px solid var(--accent);
  color: var(--text);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius);
  font-size: var(--fs-base-sm);
  margin-bottom: var(--space-2);
}
.chat-transcript {
  min-height: 220px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  padding: var(--space-2);
  margin-bottom: var(--space-2);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  overflow-y: auto;
  max-height: 60vh;
}
.chat-empty { color: var(--text-dim); }
.chat-msg { padding: var(--space-1) var(--space-2); border-radius: var(--radius); }
.chat-msg p { margin: 0 0 0.4rem; white-space: pre-wrap; }
.chat-msg p:last-child { margin-bottom: 0; }
.chat-msg-footer { color: var(--text-dim); font-size: var(--fs-base-sm); }
.chat-msg-error p { color: var(--danger); }
.chat-form { display: flex; flex-direction: column; gap: var(--space-1); }
.chat-form textarea {
  width: 100%;
  font: inherit;
  resize: vertical;
}
.chat-form button { align-self: flex-end; }
.chat-tos { max-width: 640px; margin: 0 auto; }
.chat-tos-points { color: var(--text-dim); line-height: 1.6; }
.chat-tos-points li { margin-bottom: var(--space-1); }
.chat-tos-fine { font-size: var(--fs-base-sm); color: var(--text-dim); }

/* Long words remain readable when enlarged text leaves narrow prose tracks. */
body:not(.layout-sidebar) main { overflow-wrap: anywhere; }
.journal-preview .pill { white-space: normal; font-family: var(--font-sans); }

/* PS4: the public record uses the same working surface and factual rows as
   the journal. Scope composition to these pages; the shared frame, public
   navigation, and subsequent reading-page slices retain their own owners.
   The workspace is the public frame: its content box shares its edges with
   the public header's (#4218). */
.marketing-workspace {
  container: marketing-workspace / inline-size;
  max-width: calc(var(--public-frame) + 2 * var(--public-gutter));
  padding-inline: var(--public-gutter);
}
.marketing-workspace .btn,
.marketing-workspace summary { min-height: var(--control-target); align-content: center; }
/* No line of reading text gets longer on the wider frame (#4218): copy
   keeps the width its column had at the former 73rem content maximum,
   5/11 of a hero or Home section row and 2/5 and 3/5 of a Features
   pillar, each after its gap. Home's headline, the cards and the space
   beside the copy take the extra width; Features' headline keeps its
   breaks between sentences. Stacked rows keep the full column, as
   before. */
@container marketing-workspace (min-width: 50.01rem) {
  body.layout-marketing .marketing-intro > .hero > :not(h1),
  .marketing-features .marketing-intro > .hero > h1,
  .marketing-home :is(.home-flow-copy, .home-context-copy, .home-trust-copy) {
    max-width: calc((73rem - var(--space-12)) * 5 / 11);
  }
  .marketing-features .feature-lead { max-width: calc((73rem - var(--space-8)) * 2 / 5); }
  .marketing-features .feature-detail { max-width: calc((73rem - var(--space-8)) * 3 / 5); }
}
.marketing-workspace > p { max-width: 73rem; }
.marketing-intro {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  align-items: start;
  gap: var(--space-12);
  padding-block: var(--space-8);
  margin-bottom: var(--space-8);
}
.marketing-intro > .hero {
  padding: 0;
  margin: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  min-width: 0;
}
.marketing-intro > .hero h1 { max-width: 16ch; }
.marketing-intro > .hero .lede { margin-bottom: var(--space-6); }
.marketing-intro .hero-cta { margin-block: var(--space-6) var(--space-3); }
.marketing-intro .hero-audience { margin-top: var(--space-6); }
.marketing-intro .hero-disclaimer { margin-top: var(--space-6); }
.marketing-intro > .journal-preview {
  min-width: 0;
  margin: 0;
  padding: var(--space-6);
  border: 0;
  border-radius: var(--radius-lg);
}
.marketing-intro .journal-preview-title { margin-block: var(--space-6); }
.record-symbol {
  font-size: var(--fs-2xl);
  font-weight: var(--fw-bold);
  line-height: 1.2;
  margin-right: var(--space-2);
}
.marketing-intro .journal-preview-facts {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0;
  margin-block: var(--space-4);
}
.marketing-home .marketing-intro { margin-bottom: 0; }
.marketing-home .home-context,
.marketing-home .home-trust {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  align-items: start;
  gap: var(--space-12);
  margin-bottom: 0;
}
.home-context h2,
.home-trust h2 { margin-top: 0; }
/* Home's section headings sit a step above the example card's title, at
   the size the guides use for theirs (#4601). */
.marketing-home .marketing-section h2 { font-size: var(--fs-xl); }
@media (max-width: 640px) {
  .marketing-home .marketing-section h2 { font-size: var(--fs-lg); }
}
/* "Start on Free" reads as the call to action's caption: it sits close
   under the button, and the AI-client line keeps its distance. The two
   gaps add up to what they were, so the hero keeps its height. */
.marketing-home .marketing-intro .hero-cta { margin-bottom: var(--space-2); }
.marketing-home .marketing-intro .hero-cta + .muted-note { margin-block: 0 var(--space-5); }
.home-context-copy > p,
.home-trust > div > p { max-width: var(--measure-prose); }
.home-context-note h3 { margin: 0 0 var(--space-4); font-size: var(--fs-md); }
.home-context-note dl {
  display: grid;
  grid-template-columns: 4rem minmax(0, 1fr);
  gap: var(--space-3) var(--space-4);
  margin-block: 0 var(--space-4);
}
.home-context-note dt { color: var(--text-dim); }
.home-context-note dd,
.home-context-note .muted-note { margin: 0; }
.home-trust > div > p:first-child { margin-top: 0; }
.record-event {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 3fr);
  gap: var(--space-3) var(--space-4);
  padding-block: var(--space-3);
  border-top: 1px solid var(--border);
  min-height: 3.25rem;
}
.record-event dt { margin: 0; font-size: var(--fs-base-sm); }
.record-event dd { font-size: var(--fs-base); line-height: var(--lh-body); }
.marketing-section {
  margin-block: 0 var(--space-8);
  padding-block: var(--space-8);
  border-top: 1px solid var(--border);
  min-width: 0;
}
.marketing-section > p { max-width: var(--measure-prose); }
.marketing-section .lede { margin-bottom: var(--space-6); }
.marketing-section .vignette-grid { gap: var(--space-6); }
.marketing-section .vignette {
  border: 0;
  border-radius: 0;
  background: transparent;
  padding: 0;
}
.marketing-section .vignette.after {
  padding-left: var(--space-6);
  border-left: 1px solid var(--border);
}
.marketing-section .vignette-question {
  max-width: var(--measure-prose);
  margin-block: var(--space-6);
}
.marketing-section .vignette-question,
.marketing-section .cite,
.marketing-section .step-num { font-family: var(--font-sans); font-variant-numeric: tabular-nums; }
.marketing-section .cite-src { font-size: var(--fs-base-sm); }
.marketing-section .tile-grid,
.feature-evidence { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-6); }
.marketing-section .tile {
  border: 0;
  border-radius: 0;
  background: transparent;
  padding: 0;
  max-width: var(--measure-prose);
}
.workflow-index { display: grid; gap: 0; }
.workflow-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  gap: var(--space-4) var(--space-6);
  padding-block: var(--space-4);
  border-top: 1px solid var(--border);
}
.workflow-row h3,
.workflow-row p,
.workflow-row ul { margin: 0; }
.workflow-row h3 { font-size: var(--fs-base); font-weight: var(--fw-bold); }
.workflow-row p { color: var(--text-dim); max-width: var(--measure-prose); }
.workflow-row h3 a { display: inline-flex; align-items: center; min-height: var(--control-target); }
.marketing-section .step-strip { padding: 0; margin: var(--space-6) 0 0; list-style: none; }
.marketing-section .step-strip { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.marketing-section .step { background: transparent; border: 0; border-radius: 0; padding: var(--space-4) 0; }
.marketing-disclosure {
  padding-block: var(--space-4);
  margin-bottom: var(--space-8);
  border-block: 1px solid var(--border);
  font-size: var(--fs-base-sm);
  color: var(--text-dim);
  max-width: var(--measure-support);
}
.marketing-disclosure > summary { min-height: var(--control-target); align-content: center; cursor: pointer; color: var(--text); }
/* One disclosure marker on a public page: the how-it-works arrow. */
.marketing-disclosure > summary { list-style: none; }
.marketing-disclosure > summary::-webkit-details-marker { display: none; }
.marketing-disclosure > summary::before {
  content: "▸";
  content: "▸" / "";
  display: inline-block;
  margin-right: var(--space-2);
}
.marketing-disclosure[open] > summary::before { transform: rotate(90deg); }
.marketing-disclosure > p { margin-block: var(--space-3) 0; }
.marketing-disclosure + .marketing-section { border-top: 0; }
.feature-outcome { border-left: 2px solid var(--data-neutral); padding-left: var(--space-6); margin-top: var(--space-6); max-width: var(--measure-prose); }
.feature-outcome h3 { font-size: var(--fs-base); font-weight: var(--fw-bold); }
.marketing-features .feature-pillar {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
  align-items: start;
  gap: var(--space-8);
  padding-block: var(--space-6);
  margin-block: 0;
}
.marketing-features .feature-lead,
.marketing-features .feature-detail { min-width: 0; }
.marketing-features .feature-detail > :first-child { margin-top: 0; }
.marketing-features .feature-outcome { padding-left: 0; border-left: 0; }
.marketing-heading { margin-bottom: var(--space-8); padding-block: var(--space-6); max-width: var(--measure-support); }
.marketing-pricing .pricing-heading { margin-bottom: var(--space-4); padding-bottom: 0; }
.marketing-pricing .pricing-heading h1 { font-size: var(--fs-2xl); line-height: 1.2; font-weight: var(--fw-bold); }
.marketing-pricing .pricing-plans { grid-template-columns: repeat(2, minmax(0, 1fr)); margin-bottom: var(--space-8); }
.marketing-pricing .tier { border-color: var(--border); border-radius: var(--radius-lg); }
.marketing-pricing .tier.featured { background: var(--surface); border-color: var(--border-strong); }
.marketing-pricing .tier-name { color: var(--text); font-size: var(--fs-lg); margin: 0; }
.marketing-pricing .tier.featured .tier-name { color: var(--text); }
.marketing-pricing .tier-badge { background: var(--surface-2); color: var(--text); font-size: var(--fs-base-sm); }
.marketing-pricing .tier-price { font-family: var(--font-sans); font-weight: var(--fw-medium); line-height: 1.2; }
.marketing-pricing .pricing-closing { background: transparent; }
.marketing-pricing .faq dd { max-width: var(--measure-prose); line-height: var(--lh-prose); }
.marketing-campaign .campaign-task { max-width: 48rem; margin-inline: auto; border: 0; padding: var(--space-8) 0; background: transparent; }
.marketing-campaign .campaign-task .hero-cta { margin-top: var(--space-6); }
@container marketing-workspace (max-width: 50rem) {
  .marketing-intro { grid-template-columns: minmax(0, 1fr); gap: var(--space-8); }
  .marketing-intro > .hero h1 { max-width: 100%; }
  .marketing-home .home-context,
  .marketing-home .home-trust { grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
  .marketing-features .feature-pillar { grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
  .marketing-section .vignette-grid { grid-template-columns: minmax(0, 1fr); }
  .marketing-section .vignette.after { border-left: 0; border-top: 1px solid var(--border); padding: var(--space-6) 0 0; }
  .workflow-row { grid-template-columns: minmax(0, 1fr); gap: var(--space-2); }
  .marketing-section .step-strip { grid-template-columns: minmax(0, 1fr); }
}
@container journal-preview (max-width: 28rem) {
  .record-event { grid-template-columns: minmax(0, 1fr); gap: var(--space-1); }
  .record-event dt { margin: 0; }
}
@media (max-width: 899px) {
  .marketing-pricing .pricing-plans { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 640px) {
  .marketing-intro { padding-block: var(--space-4); }
  .marketing-intro > .journal-preview { padding: var(--space-5); }
  .record-symbol { font-size: var(--fs-h1-mobile); }
  .marketing-pricing .pricing-heading h1 { font-size: var(--fs-h1-mobile); }
  .marketing-pricing .tier-name { font-size: var(--fs-md); }
}
/* Laptop-height windows. The two-column plans end about 786px down the
   page, and laptop browser windows run about 590 to 830px tall. Shorter
   windows tighten the space above the heading, the gap before the plans and
   the cards' rhythm so both whole cards share the first screen. The plan
   buttons keep their size, and the subgrid keeps both buttons and both
   feature lists on one line. */
@media (min-width: 900px) and (max-height: 840px) {
  .marketing-pricing .pricing-heading { padding-top: 0; }
  .marketing-pricing .pricing-heading .lede { margin-bottom: 0; }
  .marketing-pricing .pricing-plans { margin-top: 0; }
  .marketing-pricing .tier { padding: var(--space-5) var(--space-6) var(--space-4); gap: var(--space-2); }
  .marketing-pricing .tier-cta { padding-top: var(--space-1); }
  .marketing-pricing .tier-features { margin-top: var(--space-1); }
}
@media (min-width: 900px) and (max-height: 720px) {
  .marketing-pricing main { padding-top: var(--space-4); }
  .marketing-pricing .pricing-heading { margin-bottom: var(--space-2); }
  .marketing-pricing .tier-features { gap: var(--space-1); }
}

/* Home experience. The public Home is the one reviewed exception to the
   flat marketing grammar: a rotating set of fictional AI-client
   conversations beside the hero. Everything here is CSS on script-free
   bytes. The static composition below is complete; motion lives only under
   `prefers-reduced-motion: no-preference`, animates opacity, transform or a
   motion-path offset alone so no layout moves, and the "Pause motion"
   control stops the conversation rotation and the source loop. The
   illustrative 3D price history that stood under the hero text was removed
   when the risk-first hero took its height (#3603).
   docs/frontend-design-system.md records the exception and its limits. */
.marketing-home .marketing-intro {
  position: relative;
  isolation: isolate;
  grid-template-areas: "hero record" "stage record";
  grid-template-rows: auto 1fr;
  row-gap: 0;
}
.marketing-home .marketing-intro::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -6rem 0 -4rem;
  background:
    radial-gradient(30% 38% at 30% 76%, color-mix(in srgb, var(--accent) 9%, transparent), transparent 70%),
    radial-gradient(34% 42% at 72% 28%, color-mix(in srgb, var(--info) 7%, transparent), transparent 72%);
  pointer-events: none;
}
.marketing-home .marketing-intro > .hero { grid-area: hero; }
.marketing-home .marketing-intro > .home-chat {
  grid-area: record;
  position: relative;
  z-index: 2;
  border: 1px solid var(--border);
  background: var(--surface);
}
/* The stage cell fills the rows beside the card below the hero text, so its
   pause row sits at the foot of the hero column, level with the card's
   lower edge, rather than among the call to action's captions (#4601). It
   adds no height: where the text runs past the card, the cell is the row's
   own height. */
.marketing-home .market-stage-wrap {
  grid-area: stage;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-self: stretch;
  min-width: 0;
}

/* The fictional AI-client window. Each stage holds one trade idea checked
   four ways, and its four conversations share one stage cell, so the card
   keeps the tallest one's height and nothing moves when the examples
   change. The first stage is the default; the others are hidden, and the
   public session module may show one of them instead before the first
   paint. Each conversation runs question, Slatemark tool calls, then the
   source- and time-labelled facts, above an input that keeps its prompt.
   Statically the first example shows complete; a
   visually hidden radio group behind the chips below the stages picks
   another and stops the rotation. */
.marketing-home .home-chat-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border);
}
.marketing-home .home-chat-dots { display: flex; gap: var(--space-2); }
.marketing-home .home-chat-dots > span {
  width: 0.625rem;
  height: 0.625rem;
  border-radius: 50%;
  background: var(--surface-2);
}
.marketing-home .home-chat-client { color: var(--text-dim); font-size: var(--fs-base-sm); font-weight: var(--fw-medium); }
/* The connection chip: the pulse is decorative; the label carries it. */
.marketing-home .home-chat-conn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
  padding: var(--space-1) var(--space-3);
  border-radius: 999px;
  background: var(--accent-wash);
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-weight: var(--fw-medium);
}
.marketing-home .home-chat-pulse {
  position: relative;
  flex: none;
  width: 0.4375rem;
  height: 0.4375rem;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 8px color-mix(in srgb, var(--accent) 50%, transparent);
}
.marketing-home .home-chat-pulse::after {
  content: "";
  position: absolute;
  inset: -0.25rem;
  border: 1px solid var(--accent);
  border-radius: 50%;
  opacity: 0;
}
.marketing-home .home-chat > h2 { margin-bottom: var(--space-4); }
.marketing-home .home-chat-stage { display: grid; margin: 0; padding: 0; list-style: none; }
.marketing-home .home-chat-example {
  grid-area: 1 / 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  min-width: 0;
}
.marketing-home .home-chat-example + .home-chat-example { visibility: hidden; }
.marketing-home .home-chat-choice:checked ~ .home-chat-stage > .home-chat-example { visibility: hidden; }
.marketing-home #home-example-1:checked ~ .home-chat-stage > .home-chat-example:nth-child(1),
.marketing-home #home-example-2:checked ~ .home-chat-stage > .home-chat-example:nth-child(2),
.marketing-home #home-example-3:checked ~ .home-chat-stage > .home-chat-example:nth-child(3),
.marketing-home #home-example-4:checked ~ .home-chat-stage > .home-chat-example:nth-child(4) { visibility: visible; }
.marketing-home .home-chat-meta {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  color: var(--text-dim);
  font-size: var(--fs-base-sm);
}
/* The question reads left to right with the rest of the transcript, its
   speaker named inline so it takes no line of its own. */
.marketing-home .home-chat-ask {
  margin: 0;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-lg);
  background: var(--surface-2);
  color: var(--text);
}
.marketing-home .home-chat-ask::before,
.marketing-home .home-chat-reply::before {
  color: var(--text-dim);
  font-size: var(--fs-base-sm);
  font-weight: var(--fw-medium);
}
.marketing-home .home-chat-ask::before { content: "You"; display: inline-block; margin-right: var(--space-2); }
.marketing-home .home-chat-reply::before { content: "Your AI"; display: block; padding-bottom: var(--space-1); }
.marketing-home .home-chat-tools { display: grid; gap: var(--space-1); margin: 0; padding: 0; list-style: none; }
.marketing-home .home-chat-tools > li {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 var(--space-2);
  min-height: 1.75rem;
  padding-left: var(--space-6);
  color: var(--text-dim);
  font-size: var(--fs-base-sm);
}
.marketing-home .home-chat-tools code { color: var(--text); overflow-wrap: anywhere; }
.marketing-home .home-chat-tools > li::before,
.marketing-home .home-chat-tools > li::after { content: ""; position: absolute; top: calc(50% - 0.4375rem); }
/* The pending ring shows only while a tool call runs. */
.marketing-home .home-chat-tools > li::before {
  left: 0;
  width: 0.875rem;
  height: 0.875rem;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  opacity: 0;
}
.marketing-home .home-chat-tools > li::after {
  left: 0.25rem;
  width: 0.375rem;
  height: 0.6875rem;
  border: solid var(--accent);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.marketing-home .marketing-intro .home-chat .journal-preview-facts { margin: 0; }
/* With room, the two facts sit side by side as tiles, which keeps the card
   short; a narrow card keeps them as rows. */
@container journal-preview (min-width: 30rem) {
  .marketing-home .home-chat-reply { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); }
  .marketing-home .home-chat-reply::before { grid-column: 1 / -1; padding-bottom: 0; }
  .marketing-home .home-chat-reply > .record-event {
    grid-template-columns: minmax(0, 1fr);
    align-content: start;
    gap: var(--space-1);
    min-height: 0;
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
  }
  .marketing-home .home-chat-reply .record-symbol { font-size: var(--fs-xl); }
}
/* A tile in a card just past that width is too narrow for the longest
   values, such as "12.0% of holdings", at that size; a step down keeps
   them on one line. */
@container journal-preview (min-width: 30rem) and (max-width: 34rem) {
  .marketing-home .home-chat-reply .record-symbol { font-size: var(--fs-lg); }
}
/* The input sits at the bottom of every example, as in an AI client. It is
   a picture of an input, hidden from assistive technology, that keeps its
   prompt while the sent question shows above it (#4601). */
.marketing-home .home-chat-input {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-3);
  margin: auto 0 0;
  padding: var(--space-2) var(--space-2) var(--space-2) var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg);
  color: var(--text);
  font-size: var(--fs-base-sm);
  cursor: default;
}
.marketing-home .home-chat-placeholder { color: var(--text-dim); }
.marketing-home .home-chat-send {
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  border-radius: var(--radius);
  background: var(--surface-2);
}
.marketing-home .home-chat-send::after {
  content: "";
  width: 0.5rem;
  height: 0.5rem;
  border: solid var(--text);
  border-width: 2px 0 0 2px;
  transform: translateY(0.125rem) rotate(45deg);
}
/* Chips below the stage name each example, like suggested questions. The
   radios they label carry the names for assistive technology. */
.marketing-home .home-chat-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-4);
}
.marketing-home .home-chat-tabs > label {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 2rem;
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--text);
  font-size: var(--fs-base-sm);
  font-weight: var(--fw-medium);
  cursor: pointer;
}
.marketing-home .home-chat-tabs > label:hover { border-color: var(--border-strong); }
/* A plan tag reads as a quiet second word behind a hairline rather than a
   box nested in the chip, so all four chips still fit one row in a
   full-width card. */
.marketing-home .home-chat-tabs .pill {
  margin-inline-start: calc(var(--space-1) * -0.5);
  padding: 0 0 0 0.3125rem;
  border-left: 1px solid var(--border-strong);
  border-radius: 0;
  background: none;
  color: var(--text-dim);
  font-weight: var(--fw-medium);
  line-height: 1;
}
/* The current example: a lit layer, plus a progress rule while the
   examples rotate. */
.marketing-home .home-chat-tabs > label::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--accent-wash-strong);
  box-shadow: inset 0 0 0 1px var(--accent);
  opacity: 0;
}
.marketing-home .home-chat-tabs > label::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--accent);
  transform-origin: left center;
  transform: scaleX(0);
}
.marketing-home .home-chat-tabs > label:first-child::before { opacity: 1; }
.marketing-home .home-chat-choice:checked ~ .home-chat-tabs > label::before { opacity: 0; }
.marketing-home #home-example-1:checked ~ .home-chat-tabs > label:nth-child(1)::before,
.marketing-home #home-example-2:checked ~ .home-chat-tabs > label:nth-child(2)::before,
.marketing-home #home-example-3:checked ~ .home-chat-tabs > label:nth-child(3)::before,
.marketing-home #home-example-4:checked ~ .home-chat-tabs > label:nth-child(4)::before { opacity: 1; }
.marketing-home #home-example-1:focus-visible ~ .home-chat-tabs > label:nth-child(1),
.marketing-home #home-example-2:focus-visible ~ .home-chat-tabs > label:nth-child(2),
.marketing-home #home-example-3:focus-visible ~ .home-chat-tabs > label:nth-child(3),
.marketing-home #home-example-4:focus-visible ~ .home-chat-tabs > label:nth-child(4) {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.marketing-home .home-chat > .muted-note { margin-block: var(--space-4) 0; }

.marketing-home .market-foot {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-4);
  min-height: var(--control-target);
}
.marketing-home .market-motion { display: none; margin: 0; }
.marketing-home .market-motion label { color: var(--text-dim); font-size: var(--fs-base-sm); cursor: pointer; }

/* Optional context: the illustrative private note as a stack of slates. */
.marketing-home .home-context { padding-bottom: var(--space-12); perspective: 70rem; }
.marketing-home .home-context-note {
  position: relative;
  padding: var(--space-6);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: 0 28px 56px var(--bg);
  transform-style: preserve-3d;
  transform-origin: 100% 50%;
  transform: rotateX(8deg) rotateY(-14deg);
}
.marketing-home .home-context-note::before,
.marketing-home .home-context-note::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  pointer-events: none;
}
.marketing-home .home-context-note::before {
  background: color-mix(in srgb, var(--surface) 72%, var(--bg));
  transform: translate3d(0, var(--space-4), -2.5rem);
}
.marketing-home .home-context-note::after {
  background: color-mix(in srgb, var(--surface) 44%, var(--bg));
  transform: translate3d(0, var(--space-8), -5rem);
}

/* Trust: what Slatemark does and does not do, beside a fictional tool
   receipt. The receipt is readable content: paper is the text role, ink the
   background role, and every mid tone mixes the two. It repeats only the
   reviewed fictional AAPL facts from the first example. */
.marketing-home .home-trust { align-items: center; }
.marketing-home .home-trust-copy > p { max-width: var(--measure-prose); }
.marketing-home .home-trust-copy > p:first-of-type { margin-top: 0; }
.marketing-home .home-ledger {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-4);
  margin-block: var(--space-6);
}
.marketing-home .home-ledger > div {
  padding: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}
.marketing-home .home-ledger h3 {
  margin: 0 0 var(--space-3);
  color: var(--text-dim);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-weight: var(--fw-medium);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.marketing-home .home-ledger ul,
.marketing-home .home-plan ul { display: grid; gap: var(--space-3); margin: 0; padding: 0; list-style: none; }
.marketing-home .home-ledger li,
.marketing-home .home-plan li { position: relative; padding-left: var(--space-6); line-height: var(--lh-body); }
.marketing-home .home-ledger li::before,
.marketing-home .home-plan li::before { content: ""; position: absolute; }
.marketing-home .home-ledger-does li::before,
.marketing-home .home-plan li::before {
  left: 0.3125rem;
  top: 0.25rem;
  width: 0.375rem;
  height: 0.6875rem;
  border: solid var(--success);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.marketing-home .home-ledger-not li::before {
  left: 0.125rem;
  top: 0.375rem;
  width: 0.75rem;
  height: 0.75rem;
  background:
    linear-gradient(45deg, transparent calc(50% - 1px), var(--text-dim) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)),
    linear-gradient(-45deg, transparent calc(50% - 1px), var(--text-dim) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px));
}
.marketing-home .home-receipt-stage {
  position: relative;
  display: grid;
  place-items: center;
  min-width: 0;
  padding-block: var(--space-8);
  perspective: 120rem;
  filter: drop-shadow(1.5rem 2rem 1.75rem var(--bg));
}
.marketing-home .home-receipt-stage::before {
  content: "";
  position: absolute;
  inset: 5% 0;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--accent) 9%, transparent), transparent);
  pointer-events: none;
}
.marketing-home .home-receipt {
  position: relative;
  width: 100%;
  max-width: 25rem;
  padding: var(--space-6) var(--space-6) var(--space-12);
  background: var(--text);
  color: var(--bg);
  font-family: var(--font-mono);
  font-size: var(--fs-base-sm);
  line-height: 1.55;
  transform-style: preserve-3d;
  transform: rotateX(4deg) rotateY(-7deg);
  /* A torn, zig-zag lower edge. */
  -webkit-mask: conic-gradient(from -45deg at bottom, transparent, var(--bg) 1deg 89deg, transparent 90deg) 50% / 0.875rem 100%;
  mask: conic-gradient(from -45deg at bottom, transparent, var(--bg) 1deg 89deg, transparent 90deg) 50% / 0.875rem 100%;
}
.marketing-home .home-receipt > p { margin: 0; }
.marketing-home .home-receipt-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  color: color-mix(in srgb, var(--bg) 62%, var(--text));
  font-size: var(--fs-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.marketing-home .home-receipt-brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--bg);
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  font-weight: var(--fw-bold);
  letter-spacing: 0;
  text-transform: none;
}
/* The brand mark: a jade candle crossing a slate level line. */
.marketing-home .home-receipt-brand::before {
  content: "";
  width: 1.25rem;
  height: 1.25rem;
  background:
    linear-gradient(color-mix(in srgb, var(--accent) 34%, var(--bg)), color-mix(in srgb, var(--accent) 34%, var(--bg))) center 20% / 0.5rem 0.75rem no-repeat,
    linear-gradient(color-mix(in srgb, var(--accent) 34%, var(--bg)), color-mix(in srgb, var(--accent) 34%, var(--bg))) center / 2px 100% no-repeat,
    linear-gradient(var(--border), var(--border)) center 48% / 100% 2px no-repeat;
}
.marketing-home .home-receipt-sub {
  margin-top: var(--space-1);
  color: color-mix(in srgb, var(--bg) 62%, var(--text));
  font-size: var(--fs-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.marketing-home .home-receipt-rows,
.marketing-home .home-receipt-note {
  margin: var(--space-4) 0 0;
  padding-top: var(--space-4);
  border-top: 1.5px dashed color-mix(in srgb, var(--bg) 32%, var(--text));
}
.marketing-home .home-receipt-rows { display: grid; gap: var(--space-1); }
/* A row that cannot hold its field name and value side by side wraps, and
   the value takes its own line on the right, so a narrow phone never breaks
   a name mid-word (#4601). Only enlarged text, where a name alone outgrows
   the receipt, breaks it. */
.marketing-home .home-receipt-rows > div { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 0 var(--space-4); }
.marketing-home .home-receipt-rows > .home-receipt-value { align-items: center; }
.marketing-home .home-receipt-rows dt { color: color-mix(in srgb, var(--bg) 62%, var(--text)); }
.marketing-home .home-receipt-rows dd { margin: 0 0 0 auto; font-weight: var(--fw-medium); text-align: right; text-wrap: balance; }
.marketing-home .home-receipt-tool dd { color: color-mix(in srgb, var(--accent) 40%, var(--bg)); }
.marketing-home .home-receipt-value dd {
  font-family: var(--font-sans);
  font-size: var(--fs-2xl);
  font-weight: var(--fw-bold);
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}
.marketing-home .home-receipt-note {
  color: color-mix(in srgb, var(--bg) 62%, var(--text));
  font-size: var(--fs-micro);
  text-align: center;
}
.marketing-home .home-receipt-code {
  display: block;
  height: 2.375rem;
  margin-top: var(--space-4);
  background: repeating-linear-gradient(90deg, var(--bg) 0 2px, transparent 2px 4px, var(--bg) 4px 5px, transparent 5px 8px, var(--bg) 8px 11px, transparent 11px 12px, var(--bg) 12px 13px, transparent 13px 17px);
  opacity: 0.85;
}
.marketing-home .home-receipt-stamp {
  position: absolute;
  right: var(--space-6);
  bottom: 3.25rem;
  padding: var(--space-2);
  background: color-mix(in srgb, var(--text) 88%, transparent);
  border: 2px solid color-mix(in srgb, var(--accent) 28%, var(--bg));
  border-radius: var(--radius);
  color: color-mix(in srgb, var(--accent) 40%, var(--bg));
  font-size: var(--fs-micro);
  font-weight: var(--fw-bold);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  transform: rotate(-12deg) translateZ(1.875rem);
  opacity: 0.85;
}

/* Plans: the two public self-serve plans, in the Pricing page's words. */
.marketing-home .home-plans { margin-bottom: 0; }
.marketing-home .home-plans h2 { margin-top: 0; }
.marketing-home .home-plan-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-6);
  margin-block: var(--space-6);
}
/* The closing note ends the page; the section's own padding follows it. */
.marketing-home .home-plans .home-plan-grid + .muted-note { margin-bottom: 0; }
.marketing-home .home-plan {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  min-width: 0;
  padding: var(--space-8);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}
.marketing-home .home-plan-plus {
  border-color: color-mix(in srgb, var(--accent) 31%, var(--border));
  background: linear-gradient(160deg, var(--accent-wash), var(--surface) 45%);
}
.marketing-home .home-plan h3 {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  margin: 0;
  font-size: var(--fs-lg);
}
.marketing-home .home-plan h3 .pill { background: var(--surface-2); color: var(--text); font-weight: var(--fw-medium); white-space: normal; }
.marketing-home .home-plan-price {
  margin: 0;
  font-size: var(--fs-3xl-mobile);
  font-weight: var(--fw-bold);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.marketing-home .home-plan-price > span { color: var(--text-dim); font-size: var(--fs-base); font-weight: var(--fw-regular); }
.marketing-home .home-plan > .btn { align-self: flex-start; margin-top: auto; }

/* One connection: each source feeds Slatemark, which feeds your AI. The
   diagram restates the supporting line above it and stays aria-hidden. */
.marketing-home .home-flow {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  align-items: center;
  gap: var(--space-12);
  margin-bottom: 0;
}
.marketing-home .home-flow h2 { margin-top: 0; }
.marketing-home .home-flow-copy > p { max-width: var(--measure-prose); }
.marketing-home .flow { position: relative; min-width: 0; height: 21rem; perspective: 60rem; }
.marketing-home .flow-canvas {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 640px;
  height: 320px;
  transform-style: preserve-3d;
  transform: translate(-50%, -50%) rotateX(14deg) rotateY(-9deg) scale(0.9);
}
.marketing-home .flow-lines { position: absolute; left: 0; top: 0; width: 640px; height: 320px; overflow: visible; }
.marketing-home .flow-lines-narrow { display: none; }
.marketing-home .flow-line { stroke: var(--border-strong); stroke-width: 1.5; stroke-opacity: 0.5; }
.marketing-home .flow-source,
.marketing-home .flow-hub,
.marketing-home .flow-client {
  position: absolute;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0 var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  font-size: var(--fs-base-sm);
  font-weight: var(--fw-medium);
  transform: translateZ(18px);
  box-shadow: 0 14px 24px var(--bg);
}
.marketing-home .flow-source { left: 0; width: 176px; height: 40px; }
.marketing-home .flow-source::before {
  content: "";
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--data-neutral);
}
/* A lit layer so the loop can light a source with opacity alone. */
.marketing-home .flow-source::after,
.marketing-home .flow-hub::after,
.marketing-home .flow-client::before {
  content: "";
  position: absolute;
  inset: -1px;
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  box-shadow: 0 0 24px color-mix(in srgb, var(--accent) 8%, transparent);
  opacity: 0;
  pointer-events: none;
}
.marketing-home .flow-source-market { top: 20px; }
.marketing-home .flow-source-calc { top: 80px; }
.marketing-home .flow-source-sec { top: 140px; }
.marketing-home .flow-source-macro { top: 200px; }
.marketing-home .flow-source-context { top: 260px; }
.marketing-home .flow-hub {
  left: 300px;
  top: 100px;
  width: 120px;
  height: 120px;
  flex-direction: column;
  justify-content: center;
  padding: 0;
  border-color: var(--border-strong);
  background: var(--surface-2);
  transform: translateZ(34px);
}
/* The brand mark: a jade candle crossing a slate level line. */
.marketing-home .flow-hub-mark {
  position: relative;
  width: 50px;
  height: 46px;
  margin-bottom: var(--space-2);
  background: linear-gradient(var(--accent), var(--accent)) center 11px / 18px 22px no-repeat;
}
.marketing-home .flow-hub-mark::before,
.marketing-home .flow-hub-mark::after { content: ""; position: absolute; border-radius: 2px; }
.marketing-home .flow-hub-mark::before { left: 0; right: 0; top: 20px; height: 4px; background: var(--border-strong); }
.marketing-home .flow-hub-mark::after { left: 23px; top: 0; width: 4px; height: 46px; background: var(--accent); }
.marketing-home .flow-client {
  left: 500px;
  top: 116px;
  width: 140px;
  height: 88px;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-color: var(--border-strong);
}
.marketing-home .flow-client-bar {
  width: 33px;
  height: 6px;
  background: radial-gradient(circle at 3px 3px, var(--border-strong) 2.5px, transparent 3px) 0 0 / 11px 6px repeat-x;
}
.marketing-home .flow-client::after {
  content: "";
  height: 22px;
  background:
    linear-gradient(var(--surface-2), var(--surface-2)) 0 0 / 70% 8px no-repeat,
    linear-gradient(var(--accent-wash-strong), var(--accent-wash-strong)) 100% 100% / 55% 8px no-repeat;
}
.marketing-home .flow-pulse {
  position: absolute;
  left: 0;
  top: 0;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 12px color-mix(in srgb, var(--accent) 50%, transparent);
  offset-rotate: 0deg;
  opacity: 0;
}
.marketing-home .flow-pulse-market { offset-path: path("M 176 40 L 300 160"); }
.marketing-home .flow-pulse-calc { offset-path: path("M 176 100 L 300 160"); }
.marketing-home .flow-pulse-sec { offset-path: path("M 176 160 L 300 160"); }
.marketing-home .flow-pulse-macro { offset-path: path("M 176 220 L 300 160"); }
.marketing-home .flow-pulse-context { offset-path: path("M 176 280 L 300 160"); }
.marketing-home .flow-pulse-client { offset-path: path("M 420 160 L 500 160"); }

/* The reviewed Home motion. Durations, delays and keyframes are
   inventoried by the design-system gallery motion contract.
   - The source loop runs indefinitely inside its hidden illustration.
   - The conversation card rotates its four examples on one 48-second
     loop, 12 seconds each. Inside every example the same 12-second
     conversation runs in lockstep, so each shows from its start whenever
     its slot opens. Delayed parts fill backwards, so nothing shows early.
   - Each example opens on its question, already sent, so the card is
     never an empty transcript; the tool calls follow and the facts land
     2.4 seconds in (#4601). The input below keeps its prompt.
   - Every delay in the rotation carries the same -6s, so the loop starts
     6 seconds in (#4218): the card opens on the first example's finished
     answer, and the second example opens 6 seconds after load. Negative
     delays start a part partway through its keyframes, so all parts stay
     in lockstep.
   - Focusing the card, the "Pause motion" control, or picking an example
     stops the rotation (WCAG 2.2.2). A resting pointer does not: one that
     happened to sit where the card loads froze it before its first
     example appeared, leaving an empty card until the pointer moved.
   - "Pause motion" needs `:has()`, so every loop and the control run only
     where it is supported (#4618). Firefox before 121, inside the build
     floor, keeps the still card that reduced motion shows. */
@media (prefers-reduced-motion: no-preference) {
  /* Every loop, and the control that pauses them. */
  @supports selector(:has(*)) {
    .marketing-home .market-motion { display: flex; align-items: center; gap: var(--space-2); min-height: var(--control-target); }
    /* The connection chip pulses. */
    .marketing-home .home-chat-pulse::after { animation: home-ping 1.8s ease-out infinite; }
    /* One slot per example, and the chip that names it. */
    .marketing-home .home-chat-stage > .home-chat-example { visibility: visible; animation: home-slot 48s linear -6s infinite both; }
    .marketing-home .home-chat-tabs > label::before { animation: home-slot 48s linear -6s infinite both; }
    .marketing-home .home-chat-tabs > label::after { animation: home-progress 48s linear -6s infinite both; }
    .marketing-home .home-chat-stage > .home-chat-example:nth-child(2),
    .marketing-home .home-chat-tabs > label:nth-child(2)::before,
    .marketing-home .home-chat-tabs > label:nth-child(2)::after { animation-delay: 6s; }
    .marketing-home .home-chat-stage > .home-chat-example:nth-child(3),
    .marketing-home .home-chat-tabs > label:nth-child(3)::before,
    .marketing-home .home-chat-tabs > label:nth-child(3)::after { animation-delay: 18s; }
    .marketing-home .home-chat-stage > .home-chat-example:nth-child(4),
    .marketing-home .home-chat-tabs > label:nth-child(4)::before,
    .marketing-home .home-chat-tabs > label:nth-child(4)::after { animation-delay: 30s; }
    /* The question, each tool call in turn, then the facts. */
    .marketing-home .home-chat-ask { animation: home-ask 12s linear -6s infinite; }
    .marketing-home .home-chat-tools { animation: home-tools 12s linear -6s infinite; }
    .marketing-home .home-chat-tools > li { animation: home-row 12s linear -6s infinite backwards; }
    .marketing-home .home-chat-tools > li::before { animation: home-spin 12s linear -6s infinite backwards; }
    .marketing-home .home-chat-tools > li::after { animation: home-done 12s linear -6s infinite backwards; }
    .marketing-home .home-chat-tools > li:nth-child(2),
    .marketing-home .home-chat-tools > li:nth-child(2)::before,
    .marketing-home .home-chat-tools > li:nth-child(2)::after { animation-delay: -5.3s; }
    .marketing-home .home-chat-tools > li:nth-child(3),
    .marketing-home .home-chat-tools > li:nth-child(3)::before,
    .marketing-home .home-chat-tools > li:nth-child(3)::after { animation-delay: -4.6s; }
    .marketing-home .home-chat-reply { animation: home-answer 12s linear -6s infinite; }
    .marketing-home .home-chat-reply > .record-event { animation: home-fact 12s linear -6s infinite backwards; }
    .marketing-home .home-chat-reply > .record-event:nth-child(2) { animation-delay: -5.75s; }
    /* A picked example shows complete and still. */
    .marketing-home .home-chat-choice:checked ~ .home-chat-stage *,
    .marketing-home .home-chat-choice:checked ~ .home-chat-stage *::before,
    .marketing-home .home-chat-choice:checked ~ .home-chat-stage *::after,
    .marketing-home .home-chat-choice:checked ~ .home-chat-tabs > label::before,
    .marketing-home .home-chat-choice:checked ~ .home-chat-tabs > label::after { animation-name: none; }
    .marketing-home .home-chat:focus-within *,
    .marketing-home .home-chat:focus-within *::before,
    .marketing-home .home-chat:focus-within *::after { animation-play-state: paused; }
    /* One source at a time feeds Slatemark, then your AI, on a 10s loop. */
    .marketing-home .flow-pulse { animation: home-lane 10s linear infinite; }
    .marketing-home .flow-source::after { animation: home-lit 10s linear infinite; }
    .marketing-home .flow-pulse-calc,
    .marketing-home .flow-source-calc::after { animation-delay: 2s; }
    .marketing-home .flow-pulse-sec,
    .marketing-home .flow-source-sec::after { animation-delay: 4s; }
    .marketing-home .flow-pulse-macro,
    .marketing-home .flow-source-macro::after { animation-delay: 6s; }
    .marketing-home .flow-pulse-context,
    .marketing-home .flow-source-context::after { animation-delay: 8s; }
    .marketing-home .flow-pulse-client { animation: home-out 2s linear infinite; }
    .marketing-home .flow-hub::after { animation: home-hub 2s linear infinite; }
    .marketing-home .flow-client::before { animation: home-reply 2s linear infinite; }
    .marketing-home:has(#market-motion-pause:checked) .flow *,
    .marketing-home:has(#market-motion-pause:checked) .flow *::before,
    .marketing-home:has(#market-motion-pause:checked) .flow *::after,
    .marketing-home:has(#market-motion-pause:checked) .home-chat *,
    .marketing-home:has(#market-motion-pause:checked) .home-chat *::before,
    .marketing-home:has(#market-motion-pause:checked) .home-chat *::after { animation-play-state: paused; }
  }
  /* Below the hero, motion follows the reader's own scrolling. */
  @supports (animation-timeline: view()) {
    .marketing-home .home-context-note {
      animation: home-stack linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 55%;
    }
    .marketing-home .home-receipt {
      animation: home-receipt linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 50%;
    }
  }
}
@keyframes home-ping {
  from { opacity: 0.9; transform: scale(0.6); }
  to { opacity: 0; transform: scale(1.8); }
}
/* 48-second rotation: each example owns the first quarter of its offset
   loop. */
@keyframes home-slot {
  from { opacity: 0; }
  0.625%, 23.75% { opacity: 1; }
  25%, to { opacity: 0; }
}
/* A view's objects rise from the floor as its slot opens and lower into it
   as the slot closes, easing out through the middle stop. */
@keyframes home-progress {
  from { transform: scaleX(0); }
  25% { transform: scaleX(1); }
  25.01%, to { transform: scaleX(0); }
}
/* 12-second conversation, as percentages of 12s (1% is 0.12s): the
   question shows at full opacity from the slot's start and only settles
   into place while the slot fades in over 0.3s; tools from 0.36s; the
   facts land from 2.4s, 0.25s apart, both shown by 2.9s (#4601). */
@keyframes home-ask {
  from { transform: translateY(var(--space-2)); }
  2.5%, to { transform: none; }
}
@keyframes home-tools {
  from, 3% { opacity: 0; }
  3.1%, to { opacity: 1; }
}
@keyframes home-row {
  from, 3.3% { opacity: 0; }
  4.5%, to { opacity: 1; }
}
@keyframes home-spin {
  from, 3.3% { opacity: 0; transform: rotate(0deg); }
  3.4% { opacity: 1; transform: rotate(0deg); }
  8.3% { opacity: 1; transform: rotate(540deg); }
  8.4%, to { opacity: 0; transform: rotate(540deg); }
}
@keyframes home-done {
  from, 8.3% { opacity: 0; transform: rotate(45deg) scale(0.4); }
  9.5%, to { opacity: 1; transform: rotate(45deg); }
}
@keyframes home-answer {
  from, 20% { opacity: 0; }
  21%, to { opacity: 1; }
}
@keyframes home-fact {
  from, 20% { opacity: 0; transform: translateY(var(--space-1)); }
  22%, to { opacity: 1; transform: none; }
}
@keyframes home-lane {
  from { offset-distance: 0%; opacity: 0; }
  2% { opacity: 1; }
  8% { opacity: 1; }
  10%, to { offset-distance: 100%; opacity: 0; }
}
@keyframes home-lit {
  from, 16%, to { opacity: 0; }
  2%, 12% { opacity: 1; }
}
@keyframes home-out {
  from, 45% { offset-distance: 0%; opacity: 0; }
  50% { opacity: 1; }
  72% { opacity: 1; }
  75%, to { offset-distance: 100%; opacity: 0; }
}
@keyframes home-hub {
  from, 36%, 82%, to { opacity: 0; }
  46%, 66% { opacity: 1; }
}
@keyframes home-reply {
  from, 66%, to { opacity: 0; }
  76%, 92% { opacity: 1; }
}
@keyframes home-stack { from { transform: rotateX(18deg) rotateY(-26deg) translateZ(-3rem); } }
@keyframes home-receipt { from { transform: rotateX(18deg) rotateY(-28deg) translateZ(-2rem); } }
@container marketing-workspace (max-width: 50rem) {
  .marketing-home .marketing-intro {
    grid-template-areas: "hero" "record" "stage";
    grid-template-rows: auto;
    row-gap: var(--space-8);
  }
  .marketing-home .home-context-note { transform: none; animation-name: none; }
  .marketing-home .home-flow { grid-template-columns: minmax(0, 1fr); gap: var(--space-6); }
  .marketing-home .flow { height: 19rem; }
  .marketing-home .home-plan-grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
  .marketing-home .home-receipt-stage { padding-block: var(--space-4) var(--space-8); }
}
@container marketing-workspace (min-width: 50.01rem) and (max-width: 72rem) {
  .marketing-home .flow-canvas { transform: translate(-50%, -50%) rotateX(14deg) rotateY(-9deg) scale(0.72); }
}
@container marketing-workspace (max-width: 36rem) {
  .marketing-home .home-ledger { grid-template-columns: minmax(0, 1fr); }
  .marketing-home .home-plan { padding: var(--space-6); }
  /* A narrow column has no room for the receipt's tilt; it lies flat. */
  .marketing-home .home-receipt { padding-inline: var(--space-5); transform: none; animation-name: none; }
  .marketing-home .home-receipt-stamp { transform: rotate(-12deg); }
}
@container marketing-workspace (max-width: 36rem) {
  .marketing-home .flow { height: 25rem; }
  .marketing-home .flow-canvas {
    width: 360px;
    height: 400px;
    transform: translate(-50%, -50%) rotateX(12deg) rotateY(-6deg);
  }
  .marketing-home .flow-lines-wide { display: none; }
  .marketing-home .flow-lines-narrow { display: block; width: 360px; height: 400px; }
  .marketing-home .flow-hub { left: 224px; top: 80px; }
  .marketing-home .flow-client { left: 214px; top: 300px; }
  .marketing-home .flow-pulse-market { offset-path: path("M 176 40 L 224 140"); }
  .marketing-home .flow-pulse-calc { offset-path: path("M 176 100 L 224 140"); }
  .marketing-home .flow-pulse-sec { offset-path: path("M 176 160 L 224 140"); }
  .marketing-home .flow-pulse-macro { offset-path: path("M 176 220 L 224 140"); }
  .marketing-home .flow-pulse-context { offset-path: path("M 176 280 L 224 140"); }
  .marketing-home .flow-pulse-client { offset-path: path("M 284 200 L 284 300"); }
}
@container marketing-workspace (max-width: 22rem) {
  /* Scaled down, the tilted drawing paints about 300px of its 400px canvas,
     so the box fits the drawing with a little room rather than the whole
     canvas (#4601). */
  .marketing-home .flow { height: 21rem; }
  .marketing-home .flow-canvas { transform: translate(-50%, -50%) rotateX(12deg) rotateY(-6deg) scale(0.82); }
}
/* Phones keep the first sourced value inside the first 812px screen. */
@media (max-width: 640px) {
  .marketing-home .marketing-intro > .home-chat { padding: var(--space-4); }
  .marketing-home .marketing-intro { row-gap: var(--space-6); }
  .marketing-home .home-chat-bar { margin-bottom: var(--space-2); padding-bottom: 0; border-bottom: 0; }
  .marketing-home .home-chat-dots { display: none; }
  .marketing-home .home-chat > h2 { margin-bottom: var(--space-2); }
  .marketing-home .home-chat-example { gap: var(--space-2); }
  .marketing-home .home-chat-meta .pill { padding: 0 var(--space-1); }
  .marketing-home .home-chat-ask { padding: var(--space-2) var(--space-3); font-size: var(--fs-base-sm); }
  .marketing-home .home-chat-reply > .record-event { padding-block: var(--space-2); }
  .marketing-home .home-chat-reply::before { display: none; }
  .marketing-home .home-chat-tools { gap: 0; }
  .marketing-home .home-chat-tools > li { min-height: 1.5rem; }
  .marketing-home .marketing-intro > .hero .lede { margin-bottom: var(--space-4); }
  .marketing-home .marketing-intro .hero-cta { margin-block: var(--space-4) var(--space-2); }
}
/* Laptop and tablet windows. In two columns the headline scales between the
   approved 36px and 56px, and the "Pause motion" row sits at the foot of
   the hero column, level with the card's lower edge. */
@container marketing-workspace (min-width: 50.01rem) {
  .marketing-home .marketing-intro > .card.hero h1 {
    font-size: clamp(var(--fs-3xl-mobile), 5cqi - 0.15rem, var(--fs-3xl));
    text-wrap: balance;
  }
}
/* Laptop browser windows run about 590 to 830px tall. Shorter windows step
   the rhythm and the card's chrome down so the hero and the whole card share
   the first screen. */
@media (max-height: 840px) {
  @container marketing-workspace (min-width: 50.01rem) {
    .marketing-home .marketing-intro { padding-block: var(--space-2) var(--space-4); }
    .marketing-home .marketing-intro > .home-chat { padding: var(--space-5); }
    .marketing-home .home-chat-bar { margin-bottom: var(--space-3); padding-bottom: var(--space-2); }
    .marketing-home .home-chat > h2 { margin-bottom: var(--space-2); }
    .marketing-home .home-chat-example { gap: var(--space-2); }
    .marketing-home .home-chat-ask { padding: var(--space-2) var(--space-3); }
    .marketing-home .home-chat-tools { gap: 0; }
    .marketing-home .home-chat-tools > li { min-height: 1.5rem; }
    .marketing-home .home-chat-reply > .record-event { padding-block: var(--space-2); }
    .marketing-home .home-chat-tabs { margin-top: var(--space-3); }
    .marketing-home .home-chat > .muted-note { margin-top: var(--space-3); }
  }
}
@media (max-height: 720px) {
  @container marketing-workspace (min-width: 50.01rem) {
    .marketing-home .marketing-intro { margin-top: calc(var(--space-4) * -1); padding-top: 0; }
    .marketing-home .marketing-intro > .hero .lede { margin-bottom: var(--space-4); }
    .marketing-home .marketing-intro .hero-cta { margin-block: var(--space-4) var(--space-2); }
    .marketing-home .marketing-intro > .home-chat { padding: var(--space-4); }
    .marketing-home .home-chat-bar { margin-bottom: var(--space-2); padding-bottom: 0; border-bottom: 0; }
    .marketing-home .home-chat-meta .pill { padding: 0 var(--space-1); }
    .marketing-home .home-chat-ask { font-size: var(--fs-base-sm); }
    .marketing-home .home-chat-reply::before { display: none; }
    .marketing-home .home-chat-reply .record-symbol { font-size: var(--fs-lg); }
    .marketing-home .home-chat-tabs { margin-top: var(--space-2); }
    .marketing-home .home-chat > .muted-note { margin-top: var(--space-2); }
  }
}
@media (forced-colors: active) {
  .marketing-home .flow,
  .marketing-home .home-receipt-code,
  .marketing-home .home-receipt-stamp { display: none; }
  .marketing-home .home-chat-ask,
  .marketing-home .home-chat-input,
  .marketing-home .home-receipt { border: 1px solid CanvasText; }
  .marketing-home .home-chat-tabs > label::before { box-shadow: none; border: 2px solid Highlight; }
}
@media print {
  .marketing-home .market-stage-wrap,
  .marketing-home .flow,
  .marketing-home .home-chat-tabs,
  .marketing-home .home-chat-input { display: none; }
}

/* Features experience. The public Features page is the second reviewed
   exception to the flat marketing grammar: an illustrated tour of what
   Slatemark supplies. Every illustration is aria-hidden decoration that
   restates the copy beside it. None shows a market value, a live quote,
   a chart Slatemark renders or an outcome. The static composition below
   is complete; motion lives only under `prefers-reduced-motion:
   no-preference`, animates opacity, transform or a motion-path offset so
   no layout moves, and the "Pause motion" control beside the question
   rows stops both loops. docs/frontend-design-system.md records the
   exception and its limits. */
.marketing-features .marketing-intro {
  position: relative;
  isolation: isolate;
}
.marketing-features .marketing-intro::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -6rem 0 -4rem;
  background:
    radial-gradient(32% 44% at 74% 46%, color-mix(in srgb, var(--accent) 9%, transparent), transparent 70%),
    radial-gradient(30% 36% at 24% 22%, color-mix(in srgb, var(--info) 7%, transparent), transparent 72%);
  pointer-events: none;
}
/* The connection details close the hero column, under its disclaimer, as
   that column's footnote. */
.marketing-features .marketing-intro > .hero > .marketing-disclosure {
  margin: var(--space-6) 0 0;
  padding-block: var(--space-2) 0;
  border-bottom: 0;
}

/* The record reads as the path one question takes: you ask, Slatemark
   supplies sourced results, your AI explains. A rail joins the three
   steps, and Slatemark's step carries the brand mark. */
.marketing-features .marketing-intro > .features-trace {
  position: relative;
  border: 1px solid var(--border);
  background: var(--surface);
}
.marketing-features .features-trace::before {
  content: "";
  position: absolute;
  top: -1px;
  left: var(--space-8);
  right: var(--space-8);
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
}
.marketing-features .features-trace .journal-preview-facts { margin-block: var(--space-2); }
/* The two results the question asks for read as labels, the chip the
   lens below uses for the same results. */
.marketing-features .features-trace .journal-preview-title .pill {
  background: var(--surface-2);
  color: var(--text);
  font-weight: var(--fw-medium);
}
.marketing-features .features-trace .record-event {
  position: relative;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-1);
  min-height: 0;
  padding: var(--space-3) 0 var(--space-3) 3.25rem;
  border-top: 0;
}
.marketing-features .features-trace .record-event::before,
.marketing-features .features-trace .record-event::after { content: ""; position: absolute; }
.marketing-features .features-trace .record-event::before {
  left: 0;
  top: var(--space-3);
  width: 2.25rem;
  height: 2.25rem;
  box-sizing: border-box;
  border: 1px solid var(--border-strong);
  border-radius: 50%;
  background: radial-gradient(circle, var(--text-dim) 0 0.1875rem, transparent 0.25rem), var(--bg);
}
.marketing-features .features-trace .record-event::after {
  left: calc(1.125rem - 1px);
  top: calc(var(--space-3) + 2.25rem);
  bottom: calc(var(--space-3) * -1);
  width: 2px;
  background: linear-gradient(var(--border-strong), var(--accent));
  transform-origin: center top;
}
.marketing-features .features-trace .record-event:last-child::after { content: none; }
.marketing-features .features-trace .record-event:nth-child(2)::before {
  border-color: var(--accent);
  background:
    linear-gradient(var(--accent), var(--accent)) center / 2px 1.25rem no-repeat,
    linear-gradient(var(--border-strong), var(--border-strong)) center 46% / 1.25rem 2px no-repeat,
    linear-gradient(var(--accent), var(--accent)) center 38% / 0.5rem 0.625rem no-repeat,
    var(--bg);
  box-shadow: 0 0 0 4px var(--accent-wash-strong), 0 0 24px color-mix(in srgb, var(--accent) 8%, transparent);
}
.marketing-features .features-trace .record-event:nth-child(3)::before {
  border-color: var(--accent);
  background: radial-gradient(circle, var(--accent) 0 0.25rem, color-mix(in srgb, var(--accent) 9%, transparent) 0.3125rem 0.625rem, transparent 0.6875rem), var(--bg);
}

/* Labels on an illustration: the orbit's sources face the reader. */
.marketing-features .features-tag > span {
  position: absolute;
  padding: 0 var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text);
  font-size: var(--fs-base-sm);
  font-weight: var(--fw-medium);
  line-height: var(--lh-body);
  white-space: nowrap;
}
/* "Pause motion" sits beside the questions, the first loop, with a 44px
   target; the orbit in the next section is the only other loop. */
.marketing-features .features-motion { display: none; margin: 0; }
.marketing-features .features-motion input {
  width: 1.125rem;
  height: 1.125rem;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}
.marketing-features .features-motion label {
  display: inline-flex;
  align-items: center;
  min-height: var(--control-target);
  padding-inline-start: var(--space-2);
  color: var(--text-dim);
  font-size: var(--fs-base-sm);
  cursor: pointer;
}

/* Each section's illustration sits under its heading, where the lead
   column otherwise ends early. Shared pieces: a label chip, skeleton
   bars that stand in for values, and the brand mark. */
.marketing-features .features-visual {
  position: relative;
  min-width: 0;
  margin-top: var(--space-8);
  pointer-events: none;
}
.marketing-features .features-visual p { margin: 0; }
.marketing-features .features-chip {
  display: inline-flex;
  align-items: center;
  padding: 0 var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text);
  font-size: var(--fs-base-sm);
  font-weight: var(--fw-medium);
  line-height: var(--lh-body);
  white-space: nowrap;
}
.marketing-features .features-bar {
  display: block;
  flex: 1 1 auto;
  height: 0.5rem;
  border-radius: 999px;
  background: var(--surface-2);
}
.marketing-features .features-bar-value {
  flex: 0 1 6rem;
  height: 1rem;
  background: color-mix(in srgb, var(--data-neutral) 45%, var(--surface-2));
}
.marketing-features .features-bar-short { flex: 0 1 4rem; }
.marketing-features .features-mark {
  display: inline-block;
  flex: none;
  width: 1.5rem;
  height: 1.5rem;
  background:
    linear-gradient(var(--accent), var(--accent)) center / 12% 100% no-repeat,
    linear-gradient(var(--border-strong), var(--border-strong)) center 46% / 100% 10% no-repeat,
    linear-gradient(var(--accent), var(--accent)) center 36% / 38% 46% no-repeat;
}

/* Grounding: a lens passes over a result and shows the source and time
   fields each value carries. The cards share one width in container
   units so the lens's view lines up with the card under it. */
.marketing-features .features-lens {
  container-type: inline-size;
  max-width: 24rem;
  height: 12.5rem;
}
.marketing-features .features-lens-card {
  position: absolute;
  left: 0;
  top: 0;
  display: grid;
  align-content: center;
  gap: var(--space-2);
  box-sizing: border-box;
  width: 100cqi;
  height: 12.5rem;
  overflow: hidden;
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}
.marketing-features .features-lens-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 1.75rem;
}
.marketing-features .features-lens-row > .features-chip,
.marketing-features .features-lens-row > code { flex: none; }
.marketing-features .features-lens-row:nth-child(3) { margin-top: var(--space-2); padding-top: var(--space-3); border-top: 1px solid var(--border); }
/* At rest the lens centres one whole field, the quote's fetched_at, and
   lets its rim cut the rows above and below. Its place is in rem, like
   the text it frames, and never past the card's right edge, so enlarged
   text cannot push it off the card. */
.marketing-features .features-lens-glass {
  position: absolute;
  left: min(3.25rem, 100cqi - 8rem - 2px);
  top: 0.75rem;
  width: 8rem;
  height: 8rem;
  box-sizing: border-box;
  overflow: hidden;
  border: 2px solid var(--accent);
  border-radius: 50%;
  box-shadow: 0 0 0 6px var(--accent-wash), 0 0 36px color-mix(in srgb, var(--accent) 8%, transparent), 0 18px 36px var(--bg);
}
.marketing-features .features-lens-xray {
  left: calc(min(3.25rem, 100cqi - 8rem - 2px) * -1 - 2px);
  top: calc(-0.75rem - 2px);
  border-color: transparent;
  background:
    linear-gradient(var(--accent-wash) 1px, transparent 1px) 0 0 / 100% 0.75rem,
    linear-gradient(90deg, var(--accent-wash) 1px, transparent 1px) 0 0 / 0.75rem 100%,
    var(--bg);
}
.marketing-features .features-lens-xray code {
  color: var(--accent);
  font-size: var(--fs-base-sm);
  font-weight: var(--fw-medium);
  line-height: var(--lh-body);
}
.marketing-features .features-lens-xray .features-chip { background: var(--accent-wash-strong); }

/* Journal: a private entry keeps the rule version it used, and the
   Strategy Scorecard waits for five scored trades before it shows
   figures. The dots are a count, not a result, so they stay neutral. */
.marketing-features .features-journal { max-width: 24rem; perspective: 60rem; }
.marketing-features .features-note {
  position: relative;
  display: grid;
  gap: var(--space-3);
  margin-inline-end: var(--space-8);
  padding: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: 0 24px 48px var(--bg);
  transform-style: preserve-3d;
  transform-origin: 0 50%;
  transform: rotateX(4deg) rotateY(10deg);
}
.marketing-features .features-note::before,
.marketing-features .features-note::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}
.marketing-features .features-note::before {
  background: color-mix(in srgb, var(--surface) 70%, var(--bg));
  transform: translate3d(var(--space-4), calc(var(--space-3) * -1), -2rem);
}
.marketing-features .features-note::after {
  background: color-mix(in srgb, var(--surface) 42%, var(--bg));
  transform: translate3d(var(--space-8), calc(var(--space-6) * -1), -4rem);
}
.marketing-features .features-note-head,
.marketing-features .features-note-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--text-dim);
  font-size: var(--fs-base-sm);
}
.marketing-features .features-note-head { flex-wrap: wrap; justify-content: space-between; color: var(--text); font-weight: var(--fw-medium); }
.marketing-features .features-note-head .features-chip { background: var(--accent-wash-strong); color: var(--accent); }
.marketing-features .features-note-row > span:first-child { flex: 0 1 7rem; min-width: 0; }
.marketing-features .features-journal > .features-gate {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  margin-top: var(--space-8);
  color: var(--text-dim);
  font-size: var(--fs-base-sm);
}
.marketing-features .features-gate-dots { display: flex; gap: var(--space-2); }
.marketing-features .features-gate-dots > span {
  position: relative;
  width: 1rem;
  height: 1rem;
  box-sizing: border-box;
  border: 1px solid var(--border-strong);
  border-radius: 50%;
}
.marketing-features .features-gate-dots > span::after {
  content: "";
  position: absolute;
  inset: 2px;
  border-radius: 50%;
  background: var(--data-neutral);
}

/* Ready-made questions drift past as suggestions. They are Home's
   fictional example questions from all three sets, word for word, each
   with its plan: the Free checks on one row and the Plus checks on the
   other. Each row is a list a screen reader reads once; its second half
   repeats the first so the drift can join, and stays hidden. With motion
   reduced, in forced colors, in print and without `:has()`, a row rests
   on its first question, whole, and the others stay in the reading
   order. */
.marketing-features .features-marquee {
  display: grid;
  gap: var(--space-3);
  margin: 0 0 var(--space-6);
  pointer-events: auto;
}
.marketing-features .features-marquee-track {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}
.marketing-features .features-question {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-4) var(--space-2) var(--space-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text);
  font-size: var(--fs-base-sm);
}
.marketing-features .features-question > .pill { flex: none; }
@media print, (forced-colors: active), (prefers-reduced-motion: reduce) {
  .marketing-features .features-question:nth-child(n+2) {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .marketing-features .features-question[aria-hidden="true"] { display: none; }
}
/* The rows only move where `:has()` lets "Pause motion" stop them, so a
   browser without it keeps the same resting pose (#4618). The two copies
   are pinned equal by the design-system gallery motion contract. */
@supports not selector(:has(*)) {
  .marketing-features .features-question:nth-child(n+2) {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .marketing-features .features-question[aria-hidden="true"] { display: none; }
}
.marketing-features .features-marquee-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-4);
}

/* Research breadth: Free's public sources orbit Slatemark. Labels turn
   against the ring so they always face the reader. A 40-degree tilt and a
   32cqi ring leave the eight labels clear of each other and of the faded
   edges in the resting pose. */
.marketing-features .features-orbit {
  container-type: inline-size;
  height: 19rem;
  max-width: 28rem;
  overflow: hidden;
  perspective: 50rem;
  perspective-origin: 50% 10%;
  -webkit-mask-image: linear-gradient(90deg, transparent, var(--bg) 4%, var(--bg) 96%, transparent);
  mask-image: linear-gradient(90deg, transparent, var(--bg) 4%, var(--bg) 96%, transparent);
}
.marketing-features .features-orbit-plane {
  position: absolute;
  left: 50%;
  top: 52%;
  width: 0;
  height: 0;
  transform-style: preserve-3d;
  transform: rotateX(40deg);
}
.marketing-features .features-orbit-plane > span,
.marketing-features .features-orbit-ring > span { position: absolute; transform-style: preserve-3d; }
.marketing-features .features-orbit-track {
  left: -32cqi;
  top: -32cqi;
  width: 64cqi;
  height: 64cqi;
  box-sizing: border-box;
  border: 1px solid var(--border-strong);
  border-radius: 50%;
  box-shadow: 0 0 40px color-mix(in srgb, var(--accent) 5%, transparent), inset 0 0 40px color-mix(in srgb, var(--accent) 6%, transparent);
}
.marketing-features .features-orbit-track-inner {
  left: -18cqi;
  top: -18cqi;
  width: 36cqi;
  height: 36cqi;
  border-style: dashed;
  border-color: var(--border);
  box-shadow: none;
}
.marketing-features .features-orbit-ring { left: 0; top: 0; width: 0; height: 0; }
.marketing-features .features-orbit-node { left: 0; top: 0; width: 0; height: 0; }
.marketing-features .features-orbit-node:nth-child(1) { transform: rotateZ(0deg) translateX(32cqi) rotateZ(0deg); }
.marketing-features .features-orbit-node:nth-child(2) { transform: rotateZ(45deg) translateX(32cqi) rotateZ(-45deg); }
.marketing-features .features-orbit-node:nth-child(3) { transform: rotateZ(90deg) translateX(32cqi) rotateZ(-90deg); }
.marketing-features .features-orbit-node:nth-child(4) { transform: rotateZ(135deg) translateX(32cqi) rotateZ(-135deg); }
.marketing-features .features-orbit-node:nth-child(5) { transform: rotateZ(180deg) translateX(32cqi) rotateZ(-180deg); }
.marketing-features .features-orbit-node:nth-child(6) { transform: rotateZ(225deg) translateX(32cqi) rotateZ(-225deg); }
.marketing-features .features-orbit-node:nth-child(7) { transform: rotateZ(270deg) translateX(32cqi) rotateZ(-270deg); }
.marketing-features .features-orbit-node:nth-child(8) { transform: rotateZ(315deg) translateX(32cqi) rotateZ(-315deg); }
.marketing-features .features-orbit-node::before {
  content: "";
  position: absolute;
  left: -0.3125rem;
  top: -0.3125rem;
  width: 0.625rem;
  height: 0.625rem;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 10px color-mix(in srgb, var(--accent) 50%, transparent);
}
.marketing-features .features-orbit .features-tag {
  position: absolute;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  transform-style: preserve-3d;
  transform: rotateX(-40deg);
}
.marketing-features .features-orbit .features-tag > span { left: 0; bottom: var(--space-2); translate: -50% 0; }
.marketing-features .features-orbit-core {
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  transform: rotateX(-40deg) translateY(-1.5rem);
}
.marketing-features .features-orbit-core::before {
  content: "";
  position: absolute;
  left: -3.5rem;
  top: -3.5rem;
  width: 7rem;
  height: 7rem;
  border-radius: 50%;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--accent) 9%, transparent), transparent);
}
.marketing-features .features-orbit-core > .features-mark {
  position: absolute;
  left: -1.75rem;
  top: -1.75rem;
  width: 3.5rem;
  height: 3.5rem;
  box-sizing: border-box;
  padding: var(--space-2);
  border: 1px solid var(--accent);
  border-radius: var(--radius-lg);
  background-color: var(--surface-2);
  background-origin: content-box;
  box-shadow: 0 0 28px color-mix(in srgb, var(--accent) 8%, transparent);
}

/* Catalyst calendar: market dates land in your own calendar, with an
   optional reminder. The grid has no numbers, so it names no date. */
.marketing-features .features-calendar { max-width: 22rem; perspective: 60rem; }
.marketing-features .features-calendar-card {
  position: relative;
  padding: var(--space-4) var(--space-4) var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: 0 24px 48px var(--bg);
  transform-origin: 0 50%;
  transform: rotateX(4deg) rotateY(10deg);
}
.marketing-features .features-calendar-card > .features-calendar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
  color: var(--text);
  font-size: var(--fs-base-sm);
  font-weight: var(--fw-medium);
}
.marketing-features .features-calendar-head .features-chip { background: var(--accent-wash-strong); color: var(--accent); }
.marketing-features .features-calendar-card > .features-calendar-days {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  margin-bottom: var(--space-1);
  color: var(--text-dim);
  font-size: var(--fs-base-sm);
  text-align: center;
}
.marketing-features .features-calendar-grid {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding-top: 8.25rem;
}
.marketing-features .features-calendar-grid::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 7.5rem;
  box-sizing: border-box;
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  background:
    linear-gradient(var(--border) 1px, transparent 1px) 0 0 / 100% 20%,
    linear-gradient(90deg, var(--border) 1px, transparent 1px) 0 0 / calc(100% / 7) 100%;
}
.marketing-features .features-event {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--text);
  font-size: var(--fs-base-sm);
}
/* Rows are 1.5rem tall: expiration sits in the third week's Friday and
   the Fed meeting across the fifth week's Tuesday and Wednesday. */
.marketing-features .features-event::before {
  content: "";
  position: absolute;
  top: calc(3rem + 1px);
  left: calc(500% / 7 + 1px);
  width: calc(100% / 7 - 1px);
  height: calc(1.5rem - 1px);
  background: var(--accent-wash-strong);
  box-shadow: inset 0 0 0 1px var(--accent);
}
.marketing-features .features-event-fed::before {
  top: calc(6rem + 1px);
  left: calc(200% / 7 + 1px);
  width: calc(200% / 7 - 1px);
  background: var(--info-bg);
  box-shadow: inset 0 0 0 1px var(--info);
}
.marketing-features .features-event::after {
  content: "";
  width: 0.625rem;
  height: 0.625rem;
  order: -1;
  border-radius: 2px;
  background: var(--accent);
}
.marketing-features .features-event-fed::after { background: var(--info); }
.marketing-features .features-reminder {
  position: absolute;
  right: 6rem;
  top: calc(var(--space-4) * -1);
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text);
  font-size: var(--fs-base-sm);
  box-shadow: 0 12px 24px var(--bg);
}
.marketing-features .features-reminder::before {
  content: "";
  width: 0.625rem;
  height: 0.75rem;
  border-radius: 50% 50% 2px 2px / 60% 60% 2px 2px;
  background: var(--accent);
  box-shadow: 0 0.1875rem 0 -0.0625rem var(--accent);
}

/* Brokerage: account facts flow one way, into Slatemark. The way back,
   to place orders or move funds, does not exist, so its lane is locked. */
.marketing-features .features-boundary {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-rows: auto auto;
  align-items: center;
  gap: var(--space-6) var(--space-3);
  max-width: 28rem;
}
.marketing-features .features-node {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  grid-row: 1 / 3;
  min-height: 7.5rem;
  padding: var(--space-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  background: var(--surface);
  color: var(--text);
  font-size: var(--fs-base-sm);
  font-weight: var(--fw-medium);
  text-align: center;
}
.marketing-features .features-node-broker { grid-column: 1; max-width: 6rem; }
.marketing-features .features-node-broker::before {
  content: "";
  width: 1.5rem;
  height: 1.25rem;
  background:
    linear-gradient(var(--data-neutral), var(--data-neutral)) 0 0 / 100% 3px no-repeat,
    linear-gradient(90deg, var(--data-neutral) 3px, transparent 3px) 2px 5px / 0.4375rem 0.625rem repeat-x,
    linear-gradient(var(--data-neutral), var(--data-neutral)) 0 100% / 100% 3px no-repeat;
}
.marketing-features .features-node-slatemark {
  grid-column: 3;
  border-color: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-wash), 0 0 28px color-mix(in srgb, var(--accent) 8%, transparent);
}
.marketing-features .features-lane {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  grid-column: 2;
  min-height: 3rem;
  padding-top: var(--space-6);
}
.marketing-features .features-lane::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: var(--space-3);
  height: 2px;
  background: linear-gradient(90deg, var(--data-neutral), var(--accent));
}
.marketing-features .features-lane::after {
  content: "";
  position: absolute;
  right: 0;
  top: calc(var(--space-3) - 0.3125rem);
  width: 0.5rem;
  height: 0.5rem;
  border: solid var(--accent);
  border-width: 2px 2px 0 0;
  transform: rotate(45deg);
}
.marketing-features .features-lane-label {
  position: absolute;
  left: 50%;
  top: calc(var(--space-3) - 0.75rem);
  padding: 0 var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--accent);
  font-size: var(--fs-base-sm);
  font-weight: var(--fw-medium);
  line-height: var(--lh-body);
  translate: -50% 0;
}
.marketing-features .features-lane-track {
  display: flex;
  flex: 1 1 100%;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
}
.marketing-features .features-packet {
  padding: 0 var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text);
  font-size: var(--fs-base-sm);
  line-height: var(--lh-body);
  white-space: nowrap;
}
.marketing-features .features-lane-blocked { grid-row: 2; }
.marketing-features .features-lane-blocked::before {
  background: repeating-linear-gradient(90deg, var(--border-strong) 0 0.375rem, transparent 0.375rem 0.75rem);
}
.marketing-features .features-lane-blocked::after {
  left: 0;
  right: auto;
  border-color: var(--border-strong);
  border-width: 0 0 2px 2px;
}
.marketing-features .features-lock {
  position: absolute;
  left: 50%;
  top: calc(var(--space-3) - 0.375rem);
  width: 1.125rem;
  height: 0.875rem;
  border-radius: 3px;
  background: var(--text-dim);
  box-shadow: 0 0 0 0.25rem var(--bg);
  translate: -50% 0;
}
.marketing-features .features-lock::before {
  content: "";
  position: absolute;
  left: 0.1875rem;
  bottom: 100%;
  width: 0.75rem;
  height: 0.5rem;
  box-sizing: border-box;
  border: 2px solid var(--text-dim);
  border-bottom: 0;
  border-radius: 0.375rem 0.375rem 0 0;
}
.marketing-features .features-blocked {
  color: var(--text-dim);
  font-size: var(--fs-base-sm);
  text-decoration: line-through;
  white-space: nowrap;
}

/* Closing: one lit panel with the brand mark on its level line. */
.marketing-features .marketing-closing {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  margin-top: var(--space-8);
  padding: var(--space-12) var(--space-8);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background:
    radial-gradient(50% 90% at 86% 50%, color-mix(in srgb, var(--accent) 9%, transparent), transparent 72%),
    linear-gradient(160deg, var(--surface), var(--bg) 72%);
}
.marketing-features .marketing-closing > h2,
.marketing-features .marketing-closing > .lede,
.marketing-features .marketing-closing > .hero-cta { position: relative; max-width: 36rem; }
.marketing-features .features-closing-art {
  position: absolute;
  z-index: -1;
  top: 0;
  right: 0;
  bottom: 0;
  width: 42%;
  pointer-events: none;
}
.marketing-features .features-closing-level {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--border-strong) 30%, var(--border-strong));
}
.marketing-features .features-closing-sweep {
  position: absolute;
  left: 0;
  top: calc(50% - 1px);
  width: 30%;
  height: 4px;
  border-radius: 999px;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
  box-shadow: 0 0 16px color-mix(in srgb, var(--accent) 50%, transparent);
  opacity: 0;
}
.marketing-features .features-closing-art > .features-mark {
  position: absolute;
  right: 20%;
  top: calc(50% - 3.5rem);
  width: 7rem;
  height: 7rem;
  background:
    linear-gradient(var(--accent), var(--accent)) center / 3px 100% no-repeat,
    linear-gradient(var(--accent), var(--accent)) center 40% / 1.75rem 3.25rem no-repeat;
  filter: drop-shadow(0 0 18px color-mix(in srgb, var(--accent) 8%, transparent)) drop-shadow(0 0 36px color-mix(in srgb, var(--accent) 8%, transparent));
}

/* The reviewed Features motion. Durations, delays and keyframes are
   inventoried by the design-system gallery motion contract.
   - The record traces its three steps once, ending within five seconds.
   - The question drift and the orbit, in back-to-back sections, run
     indefinitely. "Pause motion", under the questions, stops them both
     (WCAG 2.2.2). That control needs `:has()`, so the loops and the
     control run only where it is supported (#4618). Firefox before 121,
     inside the build floor, keeps the resting pose instead.
   - The lens, the journal entry, the Scorecard count, the calendar, the
     brokerage lane and the closing sweep move only with the reader's own
     scrolling, where scroll timelines are supported. */
@media (prefers-reduced-motion: no-preference) {
  .marketing-features .features-trace .record-event { animation: features-rise 0.6s cubic-bezier(0.2, 0.8, 0.2, 1) 0.2s both; }
  .marketing-features .features-trace .record-event::before { animation: features-node 0.5s cubic-bezier(0.2, 0.8, 0.2, 1) 0.2s both; }
  .marketing-features .features-trace .record-event::after { animation: features-draw 0.45s ease-out 0.6s both; }
  .marketing-features .features-trace .record-event:nth-child(2),
  .marketing-features .features-trace .record-event:nth-child(2)::before { animation-delay: 0.65s; }
  .marketing-features .features-trace .record-event:nth-child(2)::after { animation-delay: 1.05s; }
  .marketing-features .features-trace .record-event:nth-child(3),
  .marketing-features .features-trace .record-event:nth-child(3)::before { animation-delay: 1.1s; }
  /* Loops and their pause control. */
  @supports selector(:has(*)) {
    .marketing-features .features-motion { display: flex; align-items: center; gap: var(--space-2); min-height: var(--control-target); }
    .marketing-features .features-orbit-ring { animation: features-spin 64s linear infinite; }
    .marketing-features .features-orbit .features-tag { animation: features-spin-face 64s linear infinite; }
    /* Moving rows show every question in a single line, and their faded
       ends hide where the questions enter and leave. Each row carries six
       questions, one per check from each of Home's three sets, so a loop
       lasts three times the two-question drift and the chips keep their
       reading speed. */
    .marketing-features .features-marquee {
      overflow: hidden;
      -webkit-mask-image: linear-gradient(90deg, transparent, var(--bg) 10%, var(--bg) 90%, transparent);
      mask-image: linear-gradient(90deg, transparent, var(--bg) 10%, var(--bg) 90%, transparent);
    }
    .marketing-features .features-marquee-track { flex-wrap: nowrap; width: max-content; padding-inline-end: var(--space-3); }
    .marketing-features .features-question { white-space: nowrap; }
    .marketing-features .features-marquee-row:nth-child(1) .features-marquee-track { animation: features-drift 210s linear infinite; }
    .marketing-features .features-marquee-row:nth-child(2) .features-marquee-track { animation: features-drift-back 240s linear infinite; }
    .marketing-features:has(#features-motion-pause:checked) .features-visual *,
    .marketing-features:has(#features-motion-pause:checked) .features-visual *::before,
    .marketing-features:has(#features-motion-pause:checked) .features-visual *::after,
    .marketing-features:has(#features-motion-pause:checked) .features-closing-art * { animation-play-state: paused; }
  }
  /* Below the hero, these move only with the reader's own scrolling. */
  @supports (animation-timeline: view()) {
    .marketing-features .features-lens { view-timeline: --features-lens block; }
    .marketing-features .features-lens-glass {
      animation: features-lens linear both;
      animation-timeline: --features-lens;
      animation-range: cover 15% cover 85%;
    }
    .marketing-features .features-lens-xray {
      animation: features-lens-view linear both;
      animation-timeline: --features-lens;
      animation-range: cover 15% cover 85%;
    }
    .marketing-features .features-note,
    .marketing-features .features-calendar-card {
      animation: features-settle linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 45%;
    }
    .marketing-features .features-journal { view-timeline: --features-journal block; }
    .marketing-features .features-gate-dots > span::after {
      animation: features-count linear both;
      animation-timeline: --features-journal;
      animation-range: cover 30% cover 38%;
    }
    .marketing-features .features-gate-dots > span:nth-child(2)::after { animation-range: cover 36% cover 44%; }
    .marketing-features .features-gate-dots > span:nth-child(3)::after { animation-range: cover 42% cover 50%; }
    .marketing-features .features-gate-dots > span:nth-child(4)::after { animation-range: cover 48% cover 56%; }
    .marketing-features .features-gate-dots > span:nth-child(5)::after { animation-range: cover 54% cover 62%; }
    /* Packets cross the read lane at full strength as the section passes;
       the track's clipped, faded ends hide where they enter and leave. */
    .marketing-features .features-boundary { view-timeline: --features-boundary block; }
    .marketing-features .features-lane-track {
      position: relative;
      display: block;
      height: 1.5rem;
      overflow: hidden;
      container-type: inline-size;
      -webkit-mask-image: linear-gradient(90deg, transparent, var(--bg) 14%, var(--bg) 86%, transparent);
      mask-image: linear-gradient(90deg, transparent, var(--bg) 14%, var(--bg) 86%, transparent);
    }
    .marketing-features .features-lane-track > .features-packet {
      position: absolute;
      left: 0;
      top: 0;
      animation: features-lane linear both;
      animation-timeline: --features-boundary;
      animation-range: cover 10% cover 60%;
    }
    .marketing-features .features-lane-track > .features-packet:nth-child(2) { animation-range: cover 22% cover 72%; }
    .marketing-features .features-lane-track > .features-packet:nth-child(3) { animation-range: cover 34% cover 84%; }
    /* The closing panel sits near the end of the page, so its sweep
       finishes before the panel can scroll past the middle. */
    .marketing-features .features-closing-art { view-timeline: --features-closing block; }
    .marketing-features .features-closing-sweep {
      animation: features-sweep linear both;
      animation-timeline: --features-closing;
      animation-range: entry 0% cover 50%;
    }
  }
}
@keyframes features-rise { from { opacity: 0; transform: translateY(var(--space-2)); } }
@keyframes features-node { from { opacity: 0; transform: scale(0.4); } }
@keyframes features-draw { from { transform: scaleY(0); } }
@keyframes features-spin { to { transform: rotateZ(360deg); } }
@keyframes features-spin-face {
  from { transform: rotateZ(0deg) rotateX(-40deg); }
  to { transform: rotateZ(-360deg) rotateX(-40deg); }
}
@keyframes features-drift { to { transform: translateX(-50%); } }
@keyframes features-drift-back {
  from { transform: translateX(-50%); }
  to { transform: translateX(0); }
}
@keyframes features-lane {
  from { transform: translateX(-100%); }
  to { transform: translateX(100cqi); }
}
@keyframes features-sweep {
  from { opacity: 0; transform: translateX(0); }
  15% { opacity: 1; }
  70% { opacity: 1; }
  85%, to { opacity: 0; transform: translateX(240%); }
}
/* The lens never travels past the card's edges, even with enlarged text:
   it is 8rem wide and rests at most 3.25rem from the left, so it travels
   back no further than its resting gap and forward no further than the
   room left on its right. */
@keyframes features-lens {
  from { transform: translate(calc(max(0px, min(20cqi, min(3.25rem, 100cqi - 8rem - 2px) - 2px)) * -1), -0.75rem); }
  to { transform: translate(max(0px, min(36cqi, 100cqi - 8rem - 2px - min(3.25rem, 100cqi - 8rem - 2px))), 0.75rem); }
}
@keyframes features-lens-view {
  from { transform: translate(max(0px, min(20cqi, min(3.25rem, 100cqi - 8rem - 2px) - 2px)), 0.75rem); }
  to { transform: translate(calc(max(0px, min(36cqi, 100cqi - 8rem - 2px - min(3.25rem, 100cqi - 8rem - 2px))) * -1), -0.75rem); }
}
@keyframes features-settle { from { transform: rotateX(22deg) rotateY(34deg) translateZ(-3rem); } }
@keyframes features-count { from { opacity: 0; transform: scale(0.2); } }
@container marketing-workspace (max-width: 50rem) {
  .marketing-features .features-visual { margin-top: var(--space-6); }
}
/* A column narrower than the ring has no room for eight labels around it,
   so the sources sit flat in a three-by-three grid around Slatemark and
   nothing turns. The two shortest labels take the middle column, so every
   word fits its column at 320px. */
@container marketing-workspace (max-width: 29rem) {
  .marketing-features .features-orbit {
    height: auto;
    perspective: none;
    -webkit-mask-image: none;
    mask-image: none;
  }
  .marketing-features .features-orbit-plane {
    position: static;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    align-items: center;
    justify-items: center;
    gap: var(--space-4) var(--space-2);
    width: auto;
    height: auto;
    transform: none;
  }
  .marketing-features .features-orbit-track { display: none; }
  .marketing-features .features-orbit-ring,
  .marketing-features .features-orbit-node { display: contents; animation-name: none; }
  .marketing-features .features-orbit-node::before { content: none; }
  .marketing-features .features-orbit .features-tag {
    position: static;
    width: auto;
    height: auto;
    transform: none;
    animation-name: none;
  }
  .marketing-features .features-orbit .features-tag > span {
    position: static;
    display: block;
    translate: none;
    white-space: normal;
    overflow-wrap: normal;
    text-align: center;
  }
  .marketing-features .features-orbit-plane > .features-orbit-core {
    position: relative;
    grid-area: 2 / 2;
    width: 3.5rem;
    height: 3.5rem;
    transform: none;
  }
  .marketing-features .features-orbit-core::before { left: 0; top: 0; width: 100%; height: 100%; }
  .marketing-features .features-orbit-core > .features-mark { position: static; }
  .marketing-features .features-orbit-node:nth-child(1) > .features-tag { grid-area: 2 / 3; }
  .marketing-features .features-orbit-node:nth-child(2) > .features-tag { grid-area: 3 / 3; }
  .marketing-features .features-orbit-node:nth-child(3) > .features-tag { grid-area: 3 / 2; }
  .marketing-features .features-orbit-node:nth-child(4) > .features-tag { grid-area: 1 / 2; }
  .marketing-features .features-orbit-node:nth-child(5) > .features-tag { grid-area: 2 / 1; }
  .marketing-features .features-orbit-node:nth-child(6) > .features-tag { grid-area: 1 / 1; }
  .marketing-features .features-orbit-node:nth-child(7) > .features-tag { grid-area: 3 / 1; }
  .marketing-features .features-orbit-node:nth-child(8) > .features-tag { grid-area: 1 / 3; }
}
@container marketing-workspace (max-width: 36rem) {
  .marketing-features .features-note { transform: none; animation-name: none; }
  .marketing-features .features-calendar-card { transform: none; animation-name: none; }
  .marketing-features .features-boundary { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .marketing-features .features-node { grid-row: 1; min-height: 0; max-width: none; flex-direction: row; }
  .marketing-features .features-node-broker { grid-column: 1; }
  .marketing-features .features-node-slatemark { grid-column: 2; }
  .marketing-features .features-lane-read { grid-column: 1 / -1; grid-row: 2; }
  .marketing-features .features-lane-blocked { grid-column: 1 / -1; grid-row: 3; }
  .marketing-features .marketing-closing { padding: var(--space-8) var(--space-5); }
  /* A narrow panel has no room beside its copy: the level line and its
     sweep run along the bottom edge, and the candle steps aside. */
  .marketing-features .features-closing-art { top: auto; left: 0; width: auto; height: var(--space-8); }
  .marketing-features .features-closing-art > .features-mark { display: none; }
}
/* Forced colors and print omit the hidden illustrations. The questions are
   content, so they stay, in their resting pose: whole, on wrapping rows,
   without their loop's repeats. With nothing left to move, the pause
   control goes too. */
@media (forced-colors: active), print {
  .marketing-features .features-visual:not(.features-marquee),
  .marketing-features .features-closing-art,
  .marketing-features .features-motion { display: none; }
  .marketing-features .features-marquee { overflow: visible; -webkit-mask-image: none; mask-image: none; }
  .marketing-features .features-marquee-track { flex-wrap: wrap; width: auto; }
  /* As specific as the drift rules, which name each row. */
  .marketing-features .features-marquee .features-marquee-row .features-marquee-track { animation-name: none; }
  .marketing-features .features-question { white-space: normal; }
}

/* PS5 public reading pages share the dark shell. Legal classes live on body
   so the immutable legal-body extraction delimiters and content stay exact. */
.shell.reading-page,
.reading-legal main > .shell { max-width: 46rem; }
.reading-heading { margin-bottom: var(--space-8); padding-block: var(--space-6); }
.reading-section,
.reading-legal main .card {
  border: 0;
  border-top: 1px solid var(--border);
  border-radius: 0;
  background: transparent;
  padding: var(--space-8) 0 0;
  margin: 0 0 var(--space-8);
  min-width: 0;
}
.reading-legal main .card:first-child { border: 0; padding-top: var(--space-6); }
body.layout-marketing .reading-page h1,
body.reading-legal h1 { font-size: var(--fs-2xl); line-height: 1.2; font-weight: var(--fw-bold); }
.reading-page p,
.reading-page li,
.reading-page dd { line-height: var(--lh-prose); }
.reading-page p,
.reading-page ul,
.reading-page ol { max-width: var(--measure-prose); }
.reading-page p.lede { font-size: var(--fs-base); line-height: var(--lh-prose); margin-bottom: var(--space-6); }
.reading-page .reading-section p,
.reading-legal main p { margin-block: 0 var(--space-4); }
.reading-page h2 { margin-bottom: var(--space-4); }
.reading-page h3 { margin-block: var(--space-6) var(--space-3); }
.reading-page h2,
.reading-page h3,
.reading-page [id] { scroll-margin-top: var(--space-6); }
.reading-page li + li { margin-top: var(--space-3); }
.reading-page a { overflow-wrap: anywhere; }
.reading-page .hero-disclaimer { padding-block: var(--space-4); border-block: 1px solid var(--border); color: var(--text); font-size: var(--fs-base-sm); }
.reading-legal main p,
.reading-legal main li,
.reading-legal main .kicker { color: var(--text); font-weight: var(--fw-regular); }
.reading-page .cite { font-family: var(--font-sans); }
.reading-page .cite-src { font-size: var(--fs-base-sm); }
.reading-workflow .reading-heading { padding-block: 0; margin-bottom: 0; }
.reading-workflow .reading-heading .lede { margin-bottom: var(--space-4); }
.reading-workflow .reading-heading .hero-cta { margin-bottom: var(--space-3); }
.reading-workflow .hero-disclaimer { border-bottom: 0; padding-block: var(--space-3) 0; color: var(--text-dim); }
.reading-workflow > .reading-heading + .reading-section { border-top: 0; padding-top: var(--space-4); }
.reading-workflow .workflow-browse { margin: var(--space-3) 0 0; }
.reading-copy-help { font-size: var(--fs-base-sm); color: var(--text-dim); margin-bottom: var(--space-8); }
.reading-disclosure > summary { min-height: var(--control-target); cursor: pointer; align-content: center; }
.reading-disclosure > summary::-webkit-details-marker { display: none; }
.reading-disclosure > summary::before { content: "▸"; margin-right: var(--space-2); }
.reading-disclosure[open] > summary::before { transform: rotate(90deg); }
.reading-disclosure[open] > section { margin-top: var(--space-6); }
.reading-disclosure[open] > p { margin-top: var(--space-6); }
.reading-link { display: inline-flex; align-items: center; min-height: var(--control-target); }
.workflow-steps { padding-left: var(--space-6); margin: 0; }
.workflow-step { padding: var(--space-4) 0 var(--space-6) var(--space-3); border-bottom: 1px solid var(--border); }
.workflow-step::marker { color: var(--accent); font-weight: var(--fw-medium); font-variant-numeric: tabular-nums; }
.workflow-step:last-child { border-bottom: 0; padding-bottom: 0; }
.workflow-step .step-body { display: block; }
.workflow-step .step-title { font-size: var(--fs-base); margin: 0 0 var(--space-3); }
.workflow-step .step-detail { color: var(--text); font-size: var(--fs-base); line-height: var(--lh-prose); }
.workflow-setup,
.workflow-question { margin-top: var(--space-6); }
.workflow-question { padding: var(--space-4); background: var(--surface); border-radius: var(--radius-lg); }
.workflow-subheading { font-size: var(--fs-base); margin: 0 0 var(--space-3); font-weight: var(--fw-bold); }
.workflow-question .input { font-family: var(--font-sans); }
.reading-guide .faq { grid-template-columns: minmax(0, 1fr); gap: var(--space-3); }
.reading-guide .faq dt { margin: var(--space-3) 0 0; line-height: var(--lh-heading); }
.reading-guide .faq dd { padding-bottom: var(--space-6); border-bottom: 1px solid var(--border); color: var(--text); line-height: var(--lh-prose); }
.reading-guide .faq dd:last-child { border-bottom: 0; padding-bottom: 0; }
/* A guide reads as one article (#4224). Its sections part on space, and
   only the FAQ separators keep a rule, because they pair each answer with
   its question. The hero disclaimer is one filled panel as wide as the
   column; on the Claude guide the Anthropic line joins it from the next
   sibling, so the counsel-reviewed markup is unchanged. Wording, order,
   placement, the --text color and the 14px size stay as counsel saw them.
   The risk line that ends the product section keeps its place, unruled. */
.reading-guide .reading-heading { padding-bottom: 0; margin-bottom: var(--space-12); }
.reading-guide .reading-heading .hero-disclaimer { max-width: none; padding: var(--space-4); border-block: 0; border-radius: var(--radius-lg); background: var(--surface); }
.reading-guide .reading-heading .hero-disclaimer:has(+ .muted-note) { padding-bottom: 0; border-radius: var(--radius-lg) var(--radius-lg) 0 0; }
.reading-guide .reading-heading .hero-disclaimer + .muted-note { max-width: none; margin: 0; padding: var(--space-3) var(--space-4) var(--space-4); border-radius: 0 0 var(--radius-lg) var(--radius-lg); background: var(--surface); }
.reading-guide .reading-section { border-top: 0; padding-top: 0; margin-bottom: var(--space-12); }
.reading-guide .reading-section .hero-disclaimer { padding-block: 0; border-block: 0; }
/* Forced colors flatten the panel's fill to Canvas, so the panel keeps a
   CanvasText edge there (the #1395 WS7 baseline) and stays as conspicuous
   as the rules it replaced. */
@media (forced-colors: active) {
  .reading-guide .reading-heading .hero-disclaimer { border: 1px solid CanvasText; }
  .reading-guide .reading-heading .hero-disclaimer:has(+ .muted-note) { border-bottom: 0; }
  .reading-guide .reading-heading .hero-disclaimer + .muted-note { border: 1px solid CanvasText; border-top: 0; }
}
/* The intro is never dimmer than the legal panel below it, and the title
   never leaves one word on its last line. */
.reading-guide .reading-heading p.lede,
.reading-index .reading-heading p.lede { color: var(--text); }
body.layout-marketing :is(.reading-guide, .reading-index) h1 { text-wrap: balance; }
/* Above 640px the guides read on a larger scale in the same 46rem column:
   body paragraphs average 75 to 88 characters a line instead of 85 to 96,
   and the intro outranks the legal panel by size. Phones keep the shared
   sizes. */
@media (min-width: 641px) {
  .reading-guide p:not(.kicker, .hero-disclaimer, .muted-note),
  .reading-guide li,
  .reading-guide .faq dd { font-size: var(--fs-md); }
  .reading-guide .reading-heading p.lede,
  .reading-index .reading-heading p.lede { font-size: var(--fs-lg); line-height: 1.55; }
  .reading-guide .reading-heading p.lede { margin-bottom: var(--space-8); }
  body.layout-marketing :is(.reading-guide, .reading-index) h1 { font-size: var(--fs-guide-title); line-height: 1.15; }
  body.layout-marketing .reading-guide h2 { font-size: var(--fs-xl); }
  body.layout-marketing .reading-guide h3,
  .reading-guide .faq dt { font-size: var(--fs-md); }
}
/* /guides is a card index on the public frame (#4224): its edges meet the
   header's brand and last action, and its heading keeps the 46rem reading
   width. Guides sit in two columns once the frame holds 50rem of content
   and stack below that; the container query measures that content and
   follows enlarged text. Each card is one link. The title keeps --text and
   the tile's quiet underline (one green, one meaning), its hit area covers
   the card, and its focus ring outlines the whole card. */
.shell.reading-index {
  container: guides-index / inline-size;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-6);
  max-width: calc(var(--public-frame) + 2 * var(--public-gutter));
  padding-inline: var(--public-gutter);
}
.reading-index > .reading-heading { grid-column: 1 / -1; max-width: 46rem; padding-bottom: 0; margin-bottom: 0; }
.reading-index > .guide-feature { grid-column: 1 / -1; position: relative; margin: 0; padding: var(--space-6); border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--surface); }
.reading-index > .guide-feature > :last-child { margin-bottom: 0; }
.reading-index > .guide-feature:hover { border-color: var(--border-strong); }
.reading-index .guide-feature h2 a { color: inherit; text-decoration-color: var(--border); text-underline-offset: 3px; }
.reading-index .guide-feature h2 a:hover { text-decoration-color: var(--text-dim); }
.reading-index .guide-feature h2 a::after { content: ""; position: absolute; inset: 0; border-radius: var(--radius-lg); }
.reading-index .guide-feature h2 a:focus-visible { outline: 0; }
.reading-index .guide-feature h2 a:focus-visible::after { outline: 2px solid var(--accent); outline-offset: 2px; }
@container guides-index (min-width: 50rem) {
  .reading-index > .guide-feature { grid-column: auto; }
}
@media (max-width: 640px) {
  body.layout-marketing .reading-page h1,
  body.reading-legal h1 { font-size: var(--fs-h1-mobile); }
  .reading-heading { padding-block: var(--space-4); }
  .workflow-step { padding-left: var(--space-1); }
  .reading-index > .guide-feature { padding: var(--space-4); }
}
/* Print is a paper adaptation only. Browser screen colors remain dark;
   every operative legal paragraph and link stays present and selectable. */
@media print {
  body.reading-legal { background: var(--print-paper); color: var(--print-ink); color-scheme: light; }
  body.reading-legal main,
  body.reading-legal main *,
  body.reading-legal main .kicker { background: transparent; color: var(--print-ink); border-color: var(--print-ink); box-shadow: none; }
  body.reading-legal .topbar,
  body.reading-legal .skip-link,
  body.reading-legal .footer { display: none; }
  .reading-legal main { padding: 0; }
  .reading-legal main > .shell { max-width: 46rem; padding: 0; }
  .reading-legal main h1,
  .reading-legal main h2,
  .reading-legal main h3 { break-after: avoid; }
  .reading-legal main p,
  .reading-legal main li { orphans: 3; widows: 3; }
  .reading-legal main a { text-decoration: underline; }
}
